1 /*
2 * Copyright © 2012 Aleksej Saushev, The NetBSD Foundation
3 * Copyright © 2009-2014 Inria. All rights reserved.
4 * Copyright © 2009-2010 Université Bordeaux
5 * Copyright © 2011 Cisco Systems, Inc. All rights reserved.
6 * See COPYING in top-level directory.
7 */
8
9 #define _NETBSD_SOURCE /* request "_np" functions */
10
11 #include <private/autogen/config.h>
12
13 #include <sys/types.h>
14 #include <stdlib.h>
15 #include <inttypes.h>
16 #include <sys/param.h>
17 #include <pthread.h>
18 #include <sched.h>
19 #ifdef HAVE_SYS_SYSCTL_H
20 #include <sys/sysctl.h>
21 #endif
22
23 #include <hwloc.h>
24 #include <private/private.h>
25 #include <private/debug.h>
26
27 static void
hwloc_netbsd_bsd2hwloc(hwloc_bitmap_t hwloc_cpuset,const cpuset_t * cpuset)28 hwloc_netbsd_bsd2hwloc(hwloc_bitmap_t hwloc_cpuset, const cpuset_t *cpuset)
29 {
30 unsigned cpu, cpulimit;
31 int found = 0;
32 hwloc_bitmap_zero(hwloc_cpuset);
33 cpulimit = cpuset_size(cpuset) * CHAR_BIT;
34 for (cpu = 0; cpu < cpulimit; cpu++)
35 if (cpuset_isset(cpu, cpuset)) {
36 hwloc_bitmap_set(hwloc_cpuset, cpu);
37 found++;
38 }
39 /* when never bound, it returns an empty set, fill it instead */
40 if (!found)
41 hwloc_bitmap_fill(hwloc_cpuset);
42 }
43
44 static void
hwloc_netbsd_hwloc2bsd(hwloc_const_bitmap_t hwloc_cpuset,cpuset_t * cpuset)45 hwloc_netbsd_hwloc2bsd(hwloc_const_bitmap_t hwloc_cpuset, cpuset_t *cpuset)
46 {
47 unsigned cpu, cpulimit;
48 cpuset_zero(cpuset);
49 cpulimit = cpuset_size(cpuset) * CHAR_BIT;
50 for (cpu = 0; cpu < cpulimit; cpu++)
51 if (hwloc_bitmap_isset(hwloc_cpuset, cpu))
52 cpuset_set(cpu, cpuset);
53 }
54
55 static int
hwloc_netbsd_set_proc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused,hwloc_pid_t pid,hwloc_const_bitmap_t hwloc_cpuset,int flags __hwloc_attribute_unused)56 hwloc_netbsd_set_proc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t pid, hwloc_const_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused)
57 {
58 int status;
59 cpuset_t *cpuset = cpuset_create();
60 hwloc_netbsd_hwloc2bsd(hwloc_cpuset, cpuset);
61 status = sched_setaffinity_np(pid, cpuset_size(cpuset), cpuset);
62 cpuset_destroy(cpuset);
63 return status;
64 }
65
66 static int
hwloc_netbsd_get_proc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused,hwloc_pid_t pid,hwloc_bitmap_t hwloc_cpuset,int flags __hwloc_attribute_unused)67 hwloc_netbsd_get_proc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t pid, hwloc_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused)
68 {
69 int status;
70 cpuset_t *cpuset = cpuset_create();
71 status = sched_getaffinity_np(pid, cpuset_size(cpuset), cpuset);
72 hwloc_netbsd_bsd2hwloc(hwloc_cpuset, cpuset);
73 cpuset_destroy(cpuset);
74 return status;
75 }
76
77
78 static int
hwloc_netbsd_set_thisproc_cpubind(hwloc_topology_t topology,hwloc_const_bitmap_t hwloc_cpuset,int flags)79 hwloc_netbsd_set_thisproc_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_cpuset, int flags)
80 {
81 return hwloc_netbsd_set_proc_cpubind(topology, 0, hwloc_cpuset, flags);
82 }
83
84 static int
hwloc_netbsd_get_thisproc_cpubind(hwloc_topology_t topology,hwloc_bitmap_t hwloc_cpuset,int flags)85 hwloc_netbsd_get_thisproc_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_cpuset, int flags)
86 {
87 return hwloc_netbsd_get_proc_cpubind(topology, 0, hwloc_cpuset, flags);
88 }
89
90
91 static int
hwloc_netbsd_set_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused,hwloc_thread_t tid,hwloc_const_bitmap_t hwloc_cpuset,int flags __hwloc_attribute_unused)92 hwloc_netbsd_set_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t tid, hwloc_const_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused)
93 {
94 int status;
95 cpuset_t *cpuset = cpuset_create();
96 hwloc_netbsd_hwloc2bsd(hwloc_cpuset, cpuset);
97 status = pthread_setaffinity_np(tid, cpuset_size(cpuset), cpuset);
98 cpuset_destroy(cpuset);
99
100 if (status) {
101 errno = status;
102 return -1;
103 }
104 return 0;
105 }
106
107 static int
hwloc_netbsd_get_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused,hwloc_thread_t tid,hwloc_bitmap_t hwloc_cpuset,int flags __hwloc_attribute_unused)108 hwloc_netbsd_get_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t tid, hwloc_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused)
109 {
110 int status;
111 cpuset_t *cpuset = cpuset_create();
112 status = pthread_getaffinity_np(tid, cpuset_size(cpuset), cpuset);
113 hwloc_netbsd_bsd2hwloc(hwloc_cpuset, cpuset);
114 cpuset_destroy(cpuset);
115
116 if (status) {
117 errno = status;
118 return -1;
119 }
120 return 0;
121 }
122
123
124 static int
hwloc_netbsd_set_thisthread_cpubind(hwloc_topology_t topology,hwloc_const_bitmap_t hwloc_cpuset,int flags)125 hwloc_netbsd_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_cpuset, int flags)
126 {
127 return hwloc_netbsd_set_thread_cpubind(topology, pthread_self(), hwloc_cpuset, flags);
128 }
129
130 static int
hwloc_netbsd_get_thisthread_cpubind(hwloc_topology_t topology,hwloc_bitmap_t hwloc_cpuset,int flags)131 hwloc_netbsd_get_thisthread_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_cpuset, int flags)
132 {
133 return hwloc_netbsd_get_thread_cpubind(topology, pthread_self(), hwloc_cpuset, flags);
134 }
135
136 #if (defined HAVE_SYSCTL) && (defined HAVE_SYS_SYSCTL_H)
137 static void
hwloc_netbsd_node_meminfo_info(struct hwloc_topology * topology)138 hwloc_netbsd_node_meminfo_info(struct hwloc_topology *topology)
139 {
140 int mib[2] = { CTL_HW, HW_PHYSMEM64 };
141 unsigned long physmem;
142 size_t len = sizeof(physmem);
143 sysctl(mib, 2, &physmem, &len, NULL, 0);
144 topology->levels[0][0]->memory.local_memory = physmem;
145 }
146 #endif
147
148 static int
hwloc_look_netbsd(struct hwloc_backend * backend)149 hwloc_look_netbsd(struct hwloc_backend *backend)
150 {
151 struct hwloc_topology *topology = backend->topology;
152 unsigned nbprocs = hwloc_fallback_nbprocessors(topology);
153
154 if (!topology->levels[0][0]->cpuset) {
155 /* Nobody (even the x86 backend) created objects yet, setup basic objects */
156 hwloc_alloc_obj_cpusets(topology->levels[0][0]);
157 hwloc_setup_pu_level(topology, nbprocs);
158 }
159
160 /* Add NetBSD specific information */
161 #if (defined HAVE_SYSCTL) && (defined HAVE_SYS_SYSCTL_H)
162 hwloc_netbsd_node_meminfo_info(topology);
163 #endif
164 hwloc_obj_add_info(topology->levels[0][0], "Backend", "NetBSD");
165 if (topology->is_thissystem)
166 hwloc_add_uname_info(topology, NULL);
167 return 1;
168 }
169
170 void
hwloc_set_netbsd_hooks(struct hwloc_binding_hooks * hooks __hwloc_attribute_unused,struct hwloc_topology_support * support __hwloc_attribute_unused)171 hwloc_set_netbsd_hooks(struct hwloc_binding_hooks *hooks __hwloc_attribute_unused,
172 struct hwloc_topology_support *support __hwloc_attribute_unused)
173 {
174 hooks->set_proc_cpubind = hwloc_netbsd_set_proc_cpubind;
175 hooks->get_proc_cpubind = hwloc_netbsd_get_proc_cpubind;
176 hooks->set_thisproc_cpubind = hwloc_netbsd_set_thisproc_cpubind;
177 hooks->get_thisproc_cpubind = hwloc_netbsd_get_thisproc_cpubind;
178
179 hooks->set_thread_cpubind = hwloc_netbsd_set_thread_cpubind;
180 hooks->get_thread_cpubind = hwloc_netbsd_get_thread_cpubind;
181 hooks->set_thisthread_cpubind = hwloc_netbsd_set_thisthread_cpubind;
182 hooks->get_thisthread_cpubind = hwloc_netbsd_get_thisthread_cpubind;
183 }
184
185 static struct hwloc_backend *
hwloc_netbsd_component_instantiate(struct hwloc_disc_component * component,const void * _data1 __hwloc_attribute_unused,const void * _data2 __hwloc_attribute_unused,const void * _data3 __hwloc_attribute_unused)186 hwloc_netbsd_component_instantiate(struct hwloc_disc_component *component,
187 const void *_data1 __hwloc_attribute_unused,
188 const void *_data2 __hwloc_attribute_unused,
189 const void *_data3 __hwloc_attribute_unused)
190 {
191 struct hwloc_backend *backend;
192 backend = hwloc_backend_alloc(component);
193 if (!backend)
194 return NULL;
195 backend->discover = hwloc_look_netbsd;
196 return backend;
197 }
198
199 static struct hwloc_disc_component hwloc_netbsd_disc_component = {
200 HWLOC_DISC_COMPONENT_TYPE_CPU,
201 "netbsd",
202 HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
203 hwloc_netbsd_component_instantiate,
204 50,
205 NULL
206 };
207
208 const struct hwloc_component hwloc_netbsd_component = {
209 HWLOC_COMPONENT_ABI,
210 NULL, NULL,
211 HWLOC_COMPONENT_TYPE_DISC,
212 0,
213 &hwloc_netbsd_disc_component
214 };
215