1 /*
2  * Copyright © 2009 CNRS
3  * Copyright © 2009-2015 Inria.  All rights reserved.
4  * Copyright © 2009-2011 Université Bordeaux
5  * Copyright © 2011 Cisco Systems, Inc.  All rights reserved.
6  * See COPYING in top-level directory.
7  */
8 
9 #include <stdio.h>
10 #include <string.h>
11 #include <errno.h>
12 
13 #include "private/autogen/config.h" /* for HWLOC_WIN_SYS */
14 #include "hwloc.h"
15 
16 /* check the binding functions */
17 hwloc_topology_t topology;
18 const struct hwloc_topology_support *support;
19 
result_set(const char * msg,int err,int supported)20 static void result_set(const char *msg, int err, int supported)
21 {
22   const char *errmsg = strerror(errno);
23   if (err)
24     printf("%-40s: %sFAILED (%d, %s)\n", msg, supported?"":"X", errno, errmsg);
25   else
26     printf("%-40s: OK\n", msg);
27 }
28 
result_get(const char * msg,hwloc_const_bitmap_t expected,hwloc_const_bitmap_t result,int err,int supported)29 static void result_get(const char *msg, hwloc_const_bitmap_t expected, hwloc_const_bitmap_t result, int err, int supported)
30 {
31   const char *errmsg = strerror(errno);
32   if (err)
33     printf("%-40s: %sFAILED (%d, %s)\n", msg, supported?"":"X", errno, errmsg);
34   else if (!expected || hwloc_bitmap_isequal(expected, result))
35     printf("%-40s: OK\n", msg);
36   else {
37     char *expected_s, *result_s;
38     hwloc_bitmap_asprintf(&expected_s, expected);
39     hwloc_bitmap_asprintf(&result_s, result);
40     printf("%-40s: expected %s, got %s\n", msg, expected_s, result_s);
41     free(expected_s);
42     free(result_s);
43   }
44 }
45 
test(hwloc_const_bitmap_t cpuset,int flags)46 static void test(hwloc_const_bitmap_t cpuset, int flags)
47 {
48   hwloc_bitmap_t new_cpuset = hwloc_bitmap_alloc();
49   result_set("Bind this singlethreaded process", hwloc_set_cpubind(topology, cpuset, flags), support->cpubind->set_thisproc_cpubind || support->cpubind->set_thisthread_cpubind);
50   result_get("Get  this singlethreaded process", cpuset, new_cpuset, hwloc_get_cpubind(topology, new_cpuset, flags), support->cpubind->get_thisproc_cpubind || support->cpubind->get_thisthread_cpubind);
51   result_set("Bind this thread", hwloc_set_cpubind(topology, cpuset, flags | HWLOC_CPUBIND_THREAD), support->cpubind->set_thisthread_cpubind);
52   result_get("Get  this thread", cpuset, new_cpuset, hwloc_get_cpubind(topology, new_cpuset, flags | HWLOC_CPUBIND_THREAD), support->cpubind->get_thisthread_cpubind);
53   result_set("Bind this whole process", hwloc_set_cpubind(topology, cpuset, flags | HWLOC_CPUBIND_PROCESS), support->cpubind->set_thisproc_cpubind);
54   result_get("Get  this whole process", cpuset, new_cpuset, hwloc_get_cpubind(topology, new_cpuset, flags | HWLOC_CPUBIND_PROCESS), support->cpubind->get_thisproc_cpubind);
55 
56 #ifdef HWLOC_WIN_SYS
57   result_set("Bind process", hwloc_set_proc_cpubind(topology, GetCurrentProcess(), cpuset, flags | HWLOC_CPUBIND_PROCESS), support->cpubind->set_proc_cpubind);
58   result_get("Get  process", cpuset, new_cpuset, hwloc_get_proc_cpubind(topology, GetCurrentProcess(), new_cpuset, flags | HWLOC_CPUBIND_PROCESS), support->cpubind->get_proc_cpubind);
59   result_set("Bind thread", hwloc_set_thread_cpubind(topology, GetCurrentThread(), cpuset, flags | HWLOC_CPUBIND_THREAD), support->cpubind->set_thread_cpubind);
60   result_get("Get  thread", cpuset, new_cpuset, hwloc_get_thread_cpubind(topology, GetCurrentThread(), new_cpuset, flags | HWLOC_CPUBIND_THREAD), support->cpubind->get_thread_cpubind);
61 #else /* !HWLOC_WIN_SYS */
62   result_set("Bind whole process", hwloc_set_proc_cpubind(topology, getpid(), cpuset, flags | HWLOC_CPUBIND_PROCESS), support->cpubind->set_proc_cpubind);
63   result_get("Get  whole process", cpuset, new_cpuset, hwloc_get_proc_cpubind(topology, getpid(), new_cpuset, flags | HWLOC_CPUBIND_PROCESS), support->cpubind->get_proc_cpubind);
64   result_set("Bind process", hwloc_set_proc_cpubind(topology, getpid(), cpuset, flags), support->cpubind->set_proc_cpubind);
65   result_get("Get  process", cpuset, new_cpuset, hwloc_get_proc_cpubind(topology, getpid(), new_cpuset, flags), support->cpubind->get_proc_cpubind);
66 #ifdef hwloc_thread_t
67   result_set("Bind thread", hwloc_set_thread_cpubind(topology, pthread_self(), cpuset, flags), support->cpubind->set_thread_cpubind);
68   result_get("Get  thread", cpuset, new_cpuset, hwloc_get_thread_cpubind(topology, pthread_self(), new_cpuset, flags), support->cpubind->get_thread_cpubind);
69 #endif
70 #endif /* !HWLOC_WIN_SYS */
71   printf("\n");
72   hwloc_bitmap_free(new_cpuset);
73 }
74 
testmem(hwloc_const_bitmap_t nodeset,hwloc_membind_policy_t policy,int flags,int expected)75 static void testmem(hwloc_const_bitmap_t nodeset, hwloc_membind_policy_t policy, int flags, int expected)
76 {
77   hwloc_bitmap_t new_nodeset = hwloc_bitmap_alloc();
78   hwloc_membind_policy_t newpolicy;
79   void *area;
80   size_t area_size = 1024;
81 
82   result_set("Bind this singlethreaded process memory", hwloc_set_membind(topology, nodeset, policy, flags), (support->membind->set_thisproc_membind || support->membind->set_thisthread_membind) && expected);
83   result_get("Get  this singlethreaded process memory", nodeset, new_nodeset, hwloc_get_membind(topology, new_nodeset, &newpolicy, flags), (support->membind->get_thisproc_membind || support->membind->get_thisthread_membind) && expected);
84 
85   result_set("Bind this thread memory", hwloc_set_membind(topology, nodeset, policy, flags | HWLOC_MEMBIND_THREAD), support->membind->set_thisproc_membind && expected);
86   result_get("Get  this thread memory", nodeset, new_nodeset, hwloc_get_membind(topology, new_nodeset, &newpolicy, flags | HWLOC_MEMBIND_THREAD), support->membind->get_thisproc_membind && expected);
87 
88   result_set("Bind this whole process memory", hwloc_set_membind(topology, nodeset, policy, flags | HWLOC_MEMBIND_PROCESS), support->membind->set_thisproc_membind && expected);
89   result_get("Get  this whole process memory", nodeset, new_nodeset, hwloc_get_membind(topology, new_nodeset, &newpolicy, flags | HWLOC_MEMBIND_PROCESS), support->membind->get_thisproc_membind && expected);
90 
91 #ifdef HWLOC_WIN_SYS
92   result_set("Bind process memory", hwloc_set_proc_membind(topology, GetCurrentProcess(), nodeset, policy, flags), support->membind->set_proc_membind && expected);
93   result_get("Get  process memory", nodeset, new_nodeset, hwloc_get_proc_membind(topology, GetCurrentProcess(), new_nodeset, &newpolicy, flags), support->membind->get_proc_membind && expected);
94 #else /* !HWLOC_WIN_SYS */
95   result_set("Bind process memory", hwloc_set_proc_membind(topology, getpid(), nodeset, policy, flags), support->membind->set_proc_membind && expected);
96   result_get("Get  process memory", nodeset, new_nodeset, hwloc_get_proc_membind(topology, getpid(), new_nodeset, &newpolicy, flags), support->membind->get_proc_membind && expected);
97 #endif /* !HWLOC_WIN_SYS */
98 
99   result_set("Bind area", hwloc_set_area_membind(topology, &new_nodeset, sizeof(new_nodeset), nodeset, policy, flags), support->membind->set_area_membind && expected);
100   result_get("Get  area", nodeset, new_nodeset, hwloc_get_area_membind(topology, &new_nodeset, sizeof(new_nodeset), new_nodeset, &newpolicy, flags), support->membind->get_area_membind && expected);
101 
102   if (!(flags & HWLOC_MEMBIND_MIGRATE)) {
103     result_set("Alloc bound area", (area = hwloc_alloc_membind(topology, area_size, nodeset, policy, flags)) == NULL, (support->membind->alloc_membind && expected) || !(flags & HWLOC_MEMBIND_STRICT));
104     if (area) {
105       memset(area, 0, area_size);
106       result_get("Get   bound area", nodeset, new_nodeset, hwloc_get_area_membind(topology, area, area_size, new_nodeset, &newpolicy, flags), support->membind->get_area_membind && expected);
107       result_get("Free  bound area", NULL, NULL, hwloc_free(topology, area, area_size), support->membind->alloc_membind && expected);
108     }
109 
110     result_set("Alloc bound area through policy", (area = hwloc_alloc_membind_policy(topology, area_size, nodeset, policy, flags)) == NULL, (support->membind->set_thisproc_membind && expected) || !(flags & HWLOC_MEMBIND_STRICT));
111     if (area) {
112       memset(area, 0, area_size);
113       result_get("Get   bound area", nodeset, new_nodeset, hwloc_get_area_membind(topology, area, area_size, new_nodeset, &newpolicy, flags), support->membind->get_area_membind && expected);
114       result_get("Free  bound area", NULL, NULL, hwloc_free(topology, area, area_size), support->membind->alloc_membind && expected);
115     }
116   }
117   printf("\n");
118   hwloc_bitmap_free(new_nodeset);
119 }
120 
testmem2(hwloc_const_bitmap_t set,int flags)121 static void testmem2(hwloc_const_bitmap_t set, int flags)
122 {
123   printf("  default\n");
124   testmem(set, HWLOC_MEMBIND_DEFAULT, flags, 1);
125   printf("  firsttouch\n");
126   testmem(set, HWLOC_MEMBIND_FIRSTTOUCH, flags, support->membind->firsttouch_membind);
127   printf("  bound\n");
128   testmem(set, HWLOC_MEMBIND_BIND, flags, support->membind->bind_membind);
129   printf("  interleave\n");
130   testmem(set, HWLOC_MEMBIND_INTERLEAVE, flags, support->membind->interleave_membind);
131   printf("  nexttouch\n");
132   testmem(set, HWLOC_MEMBIND_NEXTTOUCH, flags, support->membind->nexttouch_membind);
133 }
134 
testmem3(hwloc_const_bitmap_t set)135 static void testmem3(hwloc_const_bitmap_t set)
136 {
137   testmem2(set, 0);
138   printf("now strict\n\n");
139   testmem2(set, HWLOC_MEMBIND_STRICT);
140   printf("now migrate\n\n");
141   testmem2(set, HWLOC_MEMBIND_MIGRATE);
142   printf("now strictly migrate\n\n");
143   testmem2(set, HWLOC_MEMBIND_STRICT | HWLOC_MEMBIND_MIGRATE);
144 }
145 
main(void)146 int main(void)
147 {
148   hwloc_bitmap_t set;
149   hwloc_obj_t obj;
150   char *str = NULL;
151 
152   hwloc_topology_init(&topology);
153   hwloc_topology_load(topology);
154 
155   support = hwloc_topology_get_support(topology);
156 
157   obj = hwloc_get_root_obj(topology);
158   set = hwloc_bitmap_dup(obj->cpuset);
159 
160   while (hwloc_bitmap_isequal(obj->cpuset, set)) {
161     if (!obj->arity)
162       break;
163     obj = obj->children[0];
164   }
165 
166   hwloc_bitmap_asprintf(&str, set);
167   printf("system set is %s\n", str);
168   free(str);
169 
170   test(set, 0);
171   printf("now strict\n");
172   test(set, HWLOC_CPUBIND_STRICT);
173 
174   hwloc_bitmap_free(set);
175   set = hwloc_bitmap_dup(obj->cpuset);
176   hwloc_bitmap_asprintf(&str, set);
177   printf("obj set is %s\n", str);
178   free(str);
179 
180   test(set, 0);
181   printf("now strict\n");
182   test(set, HWLOC_CPUBIND_STRICT);
183 
184   hwloc_bitmap_singlify(set);
185   hwloc_bitmap_asprintf(&str, set);
186   printf("singlified to %s\n", str);
187   free(str);
188 
189   test(set, 0);
190   printf("now strict\n");
191   test(set, HWLOC_CPUBIND_STRICT);
192   hwloc_bitmap_free(set);
193 
194   printf("\n\nmemory tests\n\n");
195   printf("complete node set\n");
196   set = hwloc_bitmap_dup(hwloc_get_root_obj(topology)->cpuset);
197   hwloc_bitmap_asprintf(&str, set);
198   printf("i.e. cpuset %s\n", str);
199   free(str);
200   testmem3(set);
201   hwloc_bitmap_free(set);
202 
203   obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0);
204   assert(obj);
205   set = hwloc_bitmap_dup(obj->cpuset);
206   hwloc_bitmap_asprintf(&str, set);
207   printf("cpuset set is %s\n", str);
208   free(str);
209 
210   testmem3(set);
211 
212   obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 1);
213   if (obj) {
214     hwloc_bitmap_or(set, set, obj->cpuset);
215     hwloc_bitmap_asprintf(&str, set);
216     printf("cpuset set is %s\n", str);
217     free(str);
218 
219     testmem3(set);
220   }
221   hwloc_bitmap_free(set);
222 
223   hwloc_topology_destroy(topology);
224   return 0;
225 }
226