| /* |
| * Copyright © 2009 CNRS |
| * Copyright © 2009-2010 INRIA. All rights reserved. |
| * Copyright © 2009-2011 Université Bordeaux 1 |
| * Copyright © 2011 Cisco Systems, Inc. All rights reserved. |
| * See COPYING in top-level directory. |
| */ |
| |
| /* Misc internals routines. */ |
| |
| #ifndef HWLOC_PRIVATE_MISC_H |
| #define HWLOC_PRIVATE_MISC_H |
| |
| #include <hwloc/autogen/config.h> |
| #include <private/autogen/config.h> |
| #include <private/private.h> |
| |
| |
| /* On some systems, snprintf returns the size of written data, not the actually |
| * required size. hwloc_snprintf always report the actually required size. */ |
| int hwloc_snprintf(char *str, size_t size, const char *format, ...) __hwloc_attribute_format(printf, 3, 4); |
| |
| /* Check whether needle matches the beginning of haystack, at least n, and up |
| * to a colon or \0 */ |
| HWLOC_DECLSPEC |
| int hwloc_namecoloncmp(const char *haystack, const char *needle, size_t n); |
| |
| /* Compile-time assertion */ |
| #define HWLOC_BUILD_ASSERT(condition) ((void)sizeof(char[1 - 2*!(condition)])) |
| |
| |
| |
| #define HWLOC_BITS_PER_LONG (HWLOC_SIZEOF_UNSIGNED_LONG * 8) |
| #define HWLOC_BITS_PER_INT (HWLOC_SIZEOF_UNSIGNED_INT * 8) |
| |
| #if (HWLOC_BITS_PER_LONG != 32) && (HWLOC_BITS_PER_LONG != 64) |
| #error "unknown size for unsigned long." |
| #endif |
| |
| #if (HWLOC_BITS_PER_INT != 16) && (HWLOC_BITS_PER_INT != 32) && (HWLOC_BITS_PER_INT != 64) |
| #error "unknown size for unsigned int." |
| #endif |
| |
| |
| /** |
| * ffsl helpers. |
| */ |
| |
| #ifdef __GNUC__ |
| |
| # if (__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4)) |
| /* Starting from 3.4, gcc has a long variant. */ |
| # define hwloc_ffsl(x) __builtin_ffsl(x) |
| # else |
| # define hwloc_ffs(x) __builtin_ffs(x) |
| # define HWLOC_NEED_FFSL |
| # endif |
| |
| #elif defined(HWLOC_HAVE_FFSL) |
| |
| # ifndef HWLOC_HAVE_DECL_FFSL |
| extern int ffsl(long) __hwloc_attribute_const; |
| # endif |
| |
| # define hwloc_ffsl(x) ffsl(x) |
| |
| #elif defined(HWLOC_HAVE_FFS) |
| |
| # ifndef HWLOC_HAVE_DECL_FFS |
| extern int ffs(int) __hwloc_attribute_const; |
| # endif |
| |
| # define hwloc_ffs(x) ffs(x) |
| # define HWLOC_NEED_FFSL |
| |
| #else /* no ffs implementation */ |
| |
| static __hwloc_inline int __hwloc_attribute_const |
| hwloc_ffsl(unsigned long x) |
| { |
| int i; |
| |
| if (!x) |
| return 0; |
| |
| i = 1; |
| #if HWLOC_BITS_PER_LONG >= 64 |
| if (!(x & 0xfffffffful)) { |
| x >>= 32; |
| i += 32; |
| } |
| #endif |
| if (!(x & 0xffffu)) { |
| x >>= 16; |
| i += 16; |
| } |
| if (!(x & 0xff)) { |
| x >>= 8; |
| i += 8; |
| } |
| if (!(x & 0xf)) { |
| x >>= 4; |
| i += 4; |
| } |
| if (!(x & 0x3)) { |
| x >>= 2; |
| i += 2; |
| } |
| if (!(x & 0x1)) { |
| x >>= 1; |
| i += 1; |
| } |
| |
| return i; |
| } |
| |
| #endif |
| |
| #ifdef HWLOC_NEED_FFSL |
| |
| /* We only have an int ffs(int) implementation, build a long one. */ |
| |
| /* First make it 32 bits if it was only 16. */ |
| static __hwloc_inline int __hwloc_attribute_const |
| hwloc_ffs32(unsigned long x) |
| { |
| #if HWLOC_BITS_PER_INT == 16 |
| int low_ffs, hi_ffs; |
| |
| low_ffs = hwloc_ffs(x & 0xfffful); |
| if (low_ffs) |
| return low_ffs; |
| |
| hi_ffs = hwloc_ffs(x >> 16); |
| if (hi_ffs) |
| return hi_ffs + 16; |
| |
| return 0; |
| #else |
| return hwloc_ffs(x); |
| #endif |
| } |
| |
| /* Then make it 64 bit if longs are. */ |
| static __hwloc_inline int __hwloc_attribute_const |
| hwloc_ffsl(unsigned long x) |
| { |
| #if HWLOC_BITS_PER_LONG == 64 |
| int low_ffs, hi_ffs; |
| |
| low_ffs = hwloc_ffs32(x & 0xfffffffful); |
| if (low_ffs) |
| return low_ffs; |
| |
| hi_ffs = hwloc_ffs32(x >> 32); |
| if (hi_ffs) |
| return hi_ffs + 32; |
| |
| return 0; |
| #else |
| return hwloc_ffs32(x); |
| #endif |
| } |
| #endif |
| |
| /** |
| * flsl helpers. |
| */ |
| #ifdef __GNUC_____ |
| |
| # if (__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4)) |
| # define hwloc_flsl(x) (x ? 8*sizeof(long) - __builtin_clzl(x) : 0) |
| # else |
| # define hwloc_fls(x) (x ? 8*sizeof(int) - __builtin_clz(x) : 0) |
| # define HWLOC_NEED_FLSL |
| # endif |
| |
| #elif defined(HWLOC_HAVE_FLSL) |
| |
| # ifndef HWLOC_HAVE_DECL_FLSL |
| extern int flsl(long) __hwloc_attribute_const; |
| # endif |
| |
| # define hwloc_flsl(x) flsl(x) |
| |
| #elif defined(HWLOC_HAVE_CLZL) |
| |
| # ifndef HWLOC_HAVE_DECL_CLZL |
| extern int clzl(long) __hwloc_attribute_const; |
| # endif |
| |
| # define hwloc_flsl(x) (x ? 8*sizeof(long) - clzl(x) : 0) |
| |
| #elif defined(HWLOC_HAVE_FLS) |
| |
| # ifndef HWLOC_HAVE_DECL_FLS |
| extern int fls(int) __hwloc_attribute_const; |
| # endif |
| |
| # define hwloc_fls(x) fls(x) |
| # define HWLOC_NEED_FLSL |
| |
| #elif defined(HWLOC_HAVE_CLZ) |
| |
| # ifndef HWLOC_HAVE_DECL_CLZ |
| extern int clz(int) __hwloc_attribute_const; |
| # endif |
| |
| # define hwloc_fls(x) (x ? 8*sizeof(int) - clz(x) : 0) |
| # define HWLOC_NEED_FLSL |
| |
| #else /* no fls implementation */ |
| |
| static __hwloc_inline int __hwloc_attribute_const |
| hwloc_flsl(unsigned long x) |
| { |
| int i = 0; |
| |
| if (!x) |
| return 0; |
| |
| i = 1; |
| #if HWLOC_BITS_PER_LONG >= 64 |
| if ((x & 0xffffffff00000000ul)) { |
| x >>= 32; |
| i += 32; |
| } |
| #endif |
| if ((x & 0xffff0000u)) { |
| x >>= 16; |
| i += 16; |
| } |
| if ((x & 0xff00)) { |
| x >>= 8; |
| i += 8; |
| } |
| if ((x & 0xf0)) { |
| x >>= 4; |
| i += 4; |
| } |
| if ((x & 0xc)) { |
| x >>= 2; |
| i += 2; |
| } |
| if ((x & 0x2)) { |
| x >>= 1; |
| i += 1; |
| } |
| |
| return i; |
| } |
| |
| #endif |
| |
| #ifdef HWLOC_NEED_FLSL |
| |
| /* We only have an int fls(int) implementation, build a long one. */ |
| |
| /* First make it 32 bits if it was only 16. */ |
| static __hwloc_inline int __hwloc_attribute_const |
| hwloc_fls32(unsigned long x) |
| { |
| #if HWLOC_BITS_PER_INT == 16 |
| int low_fls, hi_fls; |
| |
| hi_fls = hwloc_fls(x >> 16); |
| if (hi_fls) |
| return hi_fls + 16; |
| |
| low_fls = hwloc_fls(x & 0xfffful); |
| if (low_fls) |
| return low_fls; |
| |
| return 0; |
| #else |
| return hwloc_fls(x); |
| #endif |
| } |
| |
| /* Then make it 64 bit if longs are. */ |
| static __hwloc_inline int __hwloc_attribute_const |
| hwloc_flsl(unsigned long x) |
| { |
| #if HWLOC_BITS_PER_LONG == 64 |
| int low_fls, hi_fls; |
| |
| hi_fls = hwloc_fls32(x >> 32); |
| if (hi_fls) |
| return hi_fls + 32; |
| |
| low_fls = hwloc_fls32(x & 0xfffffffful); |
| if (low_fls) |
| return low_fls; |
| |
| return 0; |
| #else |
| return hwloc_fls32(x); |
| #endif |
| } |
| #endif |
| |
| static __hwloc_inline int __hwloc_attribute_const |
| hwloc_weight_long(unsigned long w) |
| { |
| #if HWLOC_BITS_PER_LONG == 32 |
| #if (__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__) >= 4) |
| return __builtin_popcount(w); |
| #else |
| unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555); |
| res = (res & 0x33333333) + ((res >> 2) & 0x33333333); |
| res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); |
| res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); |
| return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); |
| #endif |
| #else /* HWLOC_BITS_PER_LONG == 32 */ |
| #if (__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__) >= 4) |
| return __builtin_popcountll(w); |
| #else |
| unsigned long res; |
| res = (w & 0x5555555555555555ul) + ((w >> 1) & 0x5555555555555555ul); |
| res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul); |
| res = (res & 0x0F0F0F0F0F0F0F0Ful) + ((res >> 4) & 0x0F0F0F0F0F0F0F0Ful); |
| res = (res & 0x00FF00FF00FF00FFul) + ((res >> 8) & 0x00FF00FF00FF00FFul); |
| res = (res & 0x0000FFFF0000FFFFul) + ((res >> 16) & 0x0000FFFF0000FFFFul); |
| return (res & 0x00000000FFFFFFFFul) + ((res >> 32) & 0x00000000FFFFFFFFul); |
| #endif |
| #endif /* HWLOC_BITS_PER_LONG == 64 */ |
| } |
| |
| |
| #endif /* HWLOC_PRIVATE_MISC_H */ |