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