OpenMPI  0.1.1
misc.h
1 /*
2  * Copyright © 2009 CNRS
3  * Copyright © 2009-2010 inria. All rights reserved.
4  * Copyright © 2009-2011 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 __hwloc_attribute_const
93 hwloc_ffsl(unsigned long x)
94 {
95  int i;
96 
97  if (!x)
98  return 0;
99 
100  i = 1;
101 #if HWLOC_BITS_PER_LONG >= 64
102  if (!(x & 0xfffffffful)) {
103  x >>= 32;
104  i += 32;
105  }
106 #endif
107  if (!(x & 0xffffu)) {
108  x >>= 16;
109  i += 16;
110  }
111  if (!(x & 0xff)) {
112  x >>= 8;
113  i += 8;
114  }
115  if (!(x & 0xf)) {
116  x >>= 4;
117  i += 4;
118  }
119  if (!(x & 0x3)) {
120  x >>= 2;
121  i += 2;
122  }
123  if (!(x & 0x1)) {
124  x >>= 1;
125  i += 1;
126  }
127 
128  return i;
129 }
130 
131 #elif defined(HWLOC_NEED_FFSL)
132 
133 /* We only have an int ffs(int) implementation, build a long one. */
134 
135 /* First make it 32 bits if it was only 16. */
136 static __hwloc_inline int __hwloc_attribute_const
137 hwloc_ffs32(unsigned long x)
138 {
139 #if HWLOC_BITS_PER_INT == 16
140  int low_ffs, hi_ffs;
141 
142  low_ffs = hwloc_ffs(x & 0xfffful);
143  if (low_ffs)
144  return low_ffs;
145 
146  hi_ffs = hwloc_ffs(x >> 16);
147  if (hi_ffs)
148  return hi_ffs + 16;
149 
150  return 0;
151 #else
152  return hwloc_ffs(x);
153 #endif
154 }
155 
156 /* Then make it 64 bit if longs are. */
157 static __hwloc_inline int __hwloc_attribute_const
158 hwloc_ffsl(unsigned long x)
159 {
160 #if HWLOC_BITS_PER_LONG == 64
161  int low_ffs, hi_ffs;
162 
163  low_ffs = hwloc_ffs32(x & 0xfffffffful);
164  if (low_ffs)
165  return low_ffs;
166 
167  hi_ffs = hwloc_ffs32(x >> 32);
168  if (hi_ffs)
169  return hi_ffs + 32;
170 
171  return 0;
172 #else
173  return hwloc_ffs32(x);
174 #endif
175 }
176 #endif
177 
178 /**
179  * flsl helpers.
180  */
181 #ifdef __GNUC_____
182 
183 # if (__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))
184 # define hwloc_flsl(x) (x ? 8*sizeof(long) - __builtin_clzl(x) : 0)
185 # else
186 # define hwloc_fls(x) (x ? 8*sizeof(int) - __builtin_clz(x) : 0)
187 # define HWLOC_NEED_FLSL
188 # endif
189 
190 #elif defined(HWLOC_HAVE_FLSL)
191 
192 # ifndef HWLOC_HAVE_DECL_FLSL
193 extern int flsl(long) __hwloc_attribute_const;
194 # endif
195 
196 # define hwloc_flsl(x) flsl(x)
197 
198 #elif defined(HWLOC_HAVE_CLZL)
199 
200 # ifndef HWLOC_HAVE_DECL_CLZL
201 extern int clzl(long) __hwloc_attribute_const;
202 # endif
203 
204 # define hwloc_flsl(x) (x ? 8*sizeof(long) - clzl(x) : 0)
205 
206 #elif defined(HWLOC_HAVE_FLS)
207 
208 # ifndef HWLOC_HAVE_DECL_FLS
209 extern int fls(int) __hwloc_attribute_const;
210 # endif
211 
212 # define hwloc_fls(x) fls(x)
213 # define HWLOC_NEED_FLSL
214 
215 #elif defined(HWLOC_HAVE_CLZ)
216 
217 # ifndef HWLOC_HAVE_DECL_CLZ
218 extern int clz(int) __hwloc_attribute_const;
219 # endif
220 
221 # define hwloc_fls(x) (x ? 8*sizeof(int) - clz(x) : 0)
222 # define HWLOC_NEED_FLSL
223 
224 #else /* no fls implementation */
225 
226 static __hwloc_inline int __hwloc_attribute_const
227 hwloc_flsl(unsigned long x)
228 {
229  int i = 0;
230 
231  if (!x)
232  return 0;
233 
234  i = 1;
235 #if HWLOC_BITS_PER_LONG >= 64
236  if ((x & 0xffffffff00000000ul)) {
237  x >>= 32;
238  i += 32;
239  }
240 #endif
241  if ((x & 0xffff0000u)) {
242  x >>= 16;
243  i += 16;
244  }
245  if ((x & 0xff00)) {
246  x >>= 8;
247  i += 8;
248  }
249  if ((x & 0xf0)) {
250  x >>= 4;
251  i += 4;
252  }
253  if ((x & 0xc)) {
254  x >>= 2;
255  i += 2;
256  }
257  if ((x & 0x2)) {
258  x >>= 1;
259  i += 1;
260  }
261 
262  return i;
263 }
264 
265 #endif
266 
267 #ifdef HWLOC_NEED_FLSL
268 
269 /* We only have an int fls(int) implementation, build a long one. */
270 
271 /* First make it 32 bits if it was only 16. */
272 static __hwloc_inline int __hwloc_attribute_const
273 hwloc_fls32(unsigned long x)
274 {
275 #if HWLOC_BITS_PER_INT == 16
276  int low_fls, hi_fls;
277 
278  hi_fls = hwloc_fls(x >> 16);
279  if (hi_fls)
280  return hi_fls + 16;
281 
282  low_fls = hwloc_fls(x & 0xfffful);
283  if (low_fls)
284  return low_fls;
285 
286  return 0;
287 #else
288  return hwloc_fls(x);
289 #endif
290 }
291 
292 /* Then make it 64 bit if longs are. */
293 static __hwloc_inline int __hwloc_attribute_const
294 hwloc_flsl(unsigned long x)
295 {
296 #if HWLOC_BITS_PER_LONG == 64
297  int low_fls, hi_fls;
298 
299  hi_fls = hwloc_fls32(x >> 32);
300  if (hi_fls)
301  return hi_fls + 32;
302 
303  low_fls = hwloc_fls32(x & 0xfffffffful);
304  if (low_fls)
305  return low_fls;
306 
307  return 0;
308 #else
309  return hwloc_fls32(x);
310 #endif
311 }
312 #endif
313 
314 static __hwloc_inline int __hwloc_attribute_const
315 hwloc_weight_long(unsigned long w)
316 {
317 #if HWLOC_BITS_PER_LONG == 32
318 #if (__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__) >= 4)
319  return __builtin_popcount(w);
320 #else
321  unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
322  res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
323  res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
324  res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
325  return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
326 #endif
327 #else /* HWLOC_BITS_PER_LONG == 32 */
328 #if (__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__) >= 4)
329  return __builtin_popcountll(w);
330 #else
331  unsigned long res;
332  res = (w & 0x5555555555555555ul) + ((w >> 1) & 0x5555555555555555ul);
333  res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul);
334  res = (res & 0x0F0F0F0F0F0F0F0Ful) + ((res >> 4) & 0x0F0F0F0F0F0F0F0Ful);
335  res = (res & 0x00FF00FF00FF00FFul) + ((res >> 8) & 0x00FF00FF00FF00FFul);
336  res = (res & 0x0000FFFF0000FFFFul) + ((res >> 16) & 0x0000FFFF0000FFFFul);
337  return (res & 0x00000000FFFFFFFFul) + ((res >> 32) & 0x00000000FFFFFFFFul);
338 #endif
339 #endif /* HWLOC_BITS_PER_LONG == 64 */
340 }
341 
342 
343 #endif /* HWLOC_PRIVATE_MISC_H */