1 /*
2 * Copyright © 2009 CNRS
3 * Copyright © 2009-2010 inria. All rights reserved.
4 * Copyright © 2009-2012 Université Bordeaux 1
5 * Copyright © 2011 Cisco Systems, Inc. All rights reserved.
6 * See COPYING in top-level directory.
7 */
8
9 /* Misc internals routines. */
10
11 #ifndef HWLOC_PRIVATE_MISC_H
12 #define HWLOC_PRIVATE_MISC_H
13
14 #include <hwloc/autogen/config.h>
15 #include <private/autogen/config.h>
16 #include <private/private.h>
17
18
19 /* On some systems, snprintf returns the size of written data, not the actually
20 * required size. hwloc_snprintf always report the actually required size. */
21 int hwloc_snprintf(char *str, size_t size, const char *format, ...) __hwloc_attribute_format(printf, 3, 4);
22
23 /* Check whether needle matches the beginning of haystack, at least n, and up
24 * to a colon or \0 */
25 HWLOC_DECLSPEC
26 int hwloc_namecoloncmp(const char *haystack, const char *needle, size_t n);
27
28 /* Compile-time assertion */
29 #define HWLOC_BUILD_ASSERT(condition) ((void)sizeof(char[1 - 2*!(condition)]))
30
31
32
33 #define HWLOC_BITS_PER_LONG (HWLOC_SIZEOF_UNSIGNED_LONG * 8)
34 #define HWLOC_BITS_PER_INT (HWLOC_SIZEOF_UNSIGNED_INT * 8)
35
36 #if (HWLOC_BITS_PER_LONG != 32) && (HWLOC_BITS_PER_LONG != 64)
37 #error "unknown size for unsigned long."
38 #endif
39
40 #if (HWLOC_BITS_PER_INT != 16) && (HWLOC_BITS_PER_INT != 32) && (HWLOC_BITS_PER_INT != 64)
41 #error "unknown size for unsigned int."
42 #endif
43
44
45 /**
46 * ffsl helpers.
47 */
48
49 #if defined(HWLOC_HAVE_BROKEN_FFS)
50
51 /* System has a broken ffs().
52 * We must check the before __GNUC__ or HWLOC_HAVE_FFSL
53 */
54 # define HWLOC_NO_FFS
55
56 #elif defined(__GNUC__)
57
58 # if (__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))
59 /* Starting from 3.4, gcc has a long variant. */
60 # define hwloc_ffsl(x) __builtin_ffsl(x)
61 # else
62 # define hwloc_ffs(x) __builtin_ffs(x)
63 # define HWLOC_NEED_FFSL
64 # endif
65
66 #elif defined(HWLOC_HAVE_FFSL)
67
68 # ifndef HWLOC_HAVE_DECL_FFSL
69 extern int ffsl(long) __hwloc_attribute_const;
70 # endif
71
72 # define hwloc_ffsl(x) ffsl(x)
73
74 #elif defined(HWLOC_HAVE_FFS)
75
76 # ifndef HWLOC_HAVE_DECL_FFS
77 extern int ffs(int) __hwloc_attribute_const;
78 # endif
79
80 # define hwloc_ffs(x) ffs(x)
81 # define HWLOC_NEED_FFSL
82
83 #else /* no ffs implementation */
84
85 # define HWLOC_NO_FFS
86
87 #endif
88
89 #ifdef HWLOC_NO_FFS
90
91 /* no ffs or it is known to be broken */
92 static __hwloc_inline int
93 hwloc_ffsl(unsigned long x) __hwloc_attribute_const;
94 static __hwloc_inline int
hwloc_ffsl(unsigned long x)95 hwloc_ffsl(unsigned long x)
96 {
97 int i;
98
99 if (!x)
100 return 0;
101
102 i = 1;
103 #if HWLOC_BITS_PER_LONG >= 64
104 if (!(x & 0xfffffffful)) {
105 x >>= 32;
106 i += 32;
107 }
108 #endif
109 if (!(x & 0xffffu)) {
110 x >>= 16;
111 i += 16;
112 }
113 if (!(x & 0xff)) {
114 x >>= 8;
115 i += 8;
116 }
117 if (!(x & 0xf)) {
118 x >>= 4;
119 i += 4;
120 }
121 if (!(x & 0x3)) {
122 x >>= 2;
123 i += 2;
124 }
125 if (!(x & 0x1)) {
126 x >>= 1;
127 i += 1;
128 }
129
130 return i;
131 }
132
133 #elif defined(HWLOC_NEED_FFSL)
134
135 /* We only have an int ffs(int) implementation, build a long one. */
136
137 /* First make it 32 bits if it was only 16. */
138 static __hwloc_inline int
139 hwloc_ffs32(unsigned long x) __hwloc_attribute_const;
140 static __hwloc_inline int
hwloc_ffs32(unsigned long x)141 hwloc_ffs32(unsigned long x)
142 {
143 #if HWLOC_BITS_PER_INT == 16
144 int low_ffs, hi_ffs;
145
146 low_ffs = hwloc_ffs(x & 0xfffful);
147 if (low_ffs)
148 return low_ffs;
149
150 hi_ffs = hwloc_ffs(x >> 16);
151 if (hi_ffs)
152 return hi_ffs + 16;
153
154 return 0;
155 #else
156 return hwloc_ffs(x);
157 #endif
158 }
159
160 /* Then make it 64 bit if longs are. */
161 static __hwloc_inline int
162 hwloc_ffsl(unsigned long x) __hwloc_attribute_const;
163 static __hwloc_inline int
hwloc_ffsl(unsigned long x)164 hwloc_ffsl(unsigned long x)
165 {
166 #if HWLOC_BITS_PER_LONG == 64
167 int low_ffs, hi_ffs;
168
169 low_ffs = hwloc_ffs32(x & 0xfffffffful);
170 if (low_ffs)
171 return low_ffs;
172
173 hi_ffs = hwloc_ffs32(x >> 32);
174 if (hi_ffs)
175 return hi_ffs + 32;
176
177 return 0;
178 #else
179 return hwloc_ffs32(x);
180 #endif
181 }
182 #endif
183
184 /**
185 * flsl helpers.
186 */
187 #ifdef __GNUC_____
188
189 # if (__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))
190 # define hwloc_flsl(x) (x ? 8*sizeof(long) - __builtin_clzl(x) : 0)
191 # else
192 # define hwloc_fls(x) (x ? 8*sizeof(int) - __builtin_clz(x) : 0)
193 # define HWLOC_NEED_FLSL
194 # endif
195
196 #elif defined(HWLOC_HAVE_FLSL)
197
198 # ifndef HWLOC_HAVE_DECL_FLSL
199 extern int flsl(long) __hwloc_attribute_const;
200 # endif
201
202 # define hwloc_flsl(x) flsl(x)
203
204 #elif defined(HWLOC_HAVE_CLZL)
205
206 # ifndef HWLOC_HAVE_DECL_CLZL
207 extern int clzl(long) __hwloc_attribute_const;
208 # endif
209
210 # define hwloc_flsl(x) (x ? 8*sizeof(long) - clzl(x) : 0)
211
212 #elif defined(HWLOC_HAVE_FLS)
213
214 # ifndef HWLOC_HAVE_DECL_FLS
215 extern int fls(int) __hwloc_attribute_const;
216 # endif
217
218 # define hwloc_fls(x) fls(x)
219 # define HWLOC_NEED_FLSL
220
221 #elif defined(HWLOC_HAVE_CLZ)
222
223 # ifndef HWLOC_HAVE_DECL_CLZ
224 extern int clz(int) __hwloc_attribute_const;
225 # endif
226
227 # define hwloc_fls(x) (x ? 8*sizeof(int) - clz(x) : 0)
228 # define HWLOC_NEED_FLSL
229
230 #else /* no fls implementation */
231
232 static __hwloc_inline int
233 hwloc_flsl(unsigned long x) __hwloc_attribute_const;
234 static __hwloc_inline int
hwloc_flsl(unsigned long x)235 hwloc_flsl(unsigned long x)
236 {
237 int i = 0;
238
239 if (!x)
240 return 0;
241
242 i = 1;
243 #if HWLOC_BITS_PER_LONG >= 64
244 if ((x & 0xffffffff00000000ul)) {
245 x >>= 32;
246 i += 32;
247 }
248 #endif
249 if ((x & 0xffff0000u)) {
250 x >>= 16;
251 i += 16;
252 }
253 if ((x & 0xff00)) {
254 x >>= 8;
255 i += 8;
256 }
257 if ((x & 0xf0)) {
258 x >>= 4;
259 i += 4;
260 }
261 if ((x & 0xc)) {
262 x >>= 2;
263 i += 2;
264 }
265 if ((x & 0x2)) {
266 x >>= 1;
267 i += 1;
268 }
269
270 return i;
271 }
272
273 #endif
274
275 #ifdef HWLOC_NEED_FLSL
276
277 /* We only have an int fls(int) implementation, build a long one. */
278
279 /* First make it 32 bits if it was only 16. */
280 static __hwloc_inline int
281 hwloc_fls32(unsigned long x) __hwloc_attribute_const;
282 static __hwloc_inline int
hwloc_fls32(unsigned long x)283 hwloc_fls32(unsigned long x)
284 {
285 #if HWLOC_BITS_PER_INT == 16
286 int low_fls, hi_fls;
287
288 hi_fls = hwloc_fls(x >> 16);
289 if (hi_fls)
290 return hi_fls + 16;
291
292 low_fls = hwloc_fls(x & 0xfffful);
293 if (low_fls)
294 return low_fls;
295
296 return 0;
297 #else
298 return hwloc_fls(x);
299 #endif
300 }
301
302 /* Then make it 64 bit if longs are. */
303 static __hwloc_inline int
304 hwloc_flsl(unsigned long x) __hwloc_attribute_const;
305 static __hwloc_inline int
hwloc_flsl(unsigned long x)306 hwloc_flsl(unsigned long x)
307 {
308 #if HWLOC_BITS_PER_LONG == 64
309 int low_fls, hi_fls;
310
311 hi_fls = hwloc_fls32(x >> 32);
312 if (hi_fls)
313 return hi_fls + 32;
314
315 low_fls = hwloc_fls32(x & 0xfffffffful);
316 if (low_fls)
317 return low_fls;
318
319 return 0;
320 #else
321 return hwloc_fls32(x);
322 #endif
323 }
324 #endif
325
326 static __hwloc_inline int
327 hwloc_weight_long(unsigned long w) __hwloc_attribute_const;
328 static __hwloc_inline int
hwloc_weight_long(unsigned long w)329 hwloc_weight_long(unsigned long w)
330 {
331 #if HWLOC_BITS_PER_LONG == 32
332 #if (__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__) >= 4)
333 return __builtin_popcount(w);
334 #else
335 unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
336 res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
337 res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
338 res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
339 return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
340 #endif
341 #else /* HWLOC_BITS_PER_LONG == 32 */
342 #if (__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__) >= 4)
343 return __builtin_popcountll(w);
344 #else
345 unsigned long res;
346 res = (w & 0x5555555555555555ul) + ((w >> 1) & 0x5555555555555555ul);
347 res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul);
348 res = (res & 0x0F0F0F0F0F0F0F0Ful) + ((res >> 4) & 0x0F0F0F0F0F0F0F0Ful);
349 res = (res & 0x00FF00FF00FF00FFul) + ((res >> 8) & 0x00FF00FF00FF00FFul);
350 res = (res & 0x0000FFFF0000FFFFul) + ((res >> 16) & 0x0000FFFF0000FFFFul);
351 return (res & 0x00000000FFFFFFFFul) + ((res >> 32) & 0x00000000FFFFFFFFul);
352 #endif
353 #endif /* HWLOC_BITS_PER_LONG == 64 */
354 }
355
356
357 #endif /* HWLOC_PRIVATE_MISC_H */
358