Date: Tue, 14 Apr 2015 20:05:29 +0000 (UTC) From: John Baldwin <jhb@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r281538 - in stable: 10/sys/sys 9/sys/sys Message-ID: <201504142005.t3EK5TYR073983@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jhb Date: Tue Apr 14 20:05:26 2015 New Revision: 281538 URL: https://svnweb.freebsd.org/changeset/base/281538 Log: MFC 278474,278476,280279: Expand the bitcount*() API and use it to implement CPU_COUNT for cpusets. 278474: Use __builtin_popcnt() to implement a BIT_COUNT() operation for bitsets and use this to implement CPU_COUNT() to count the number of CPUs in a cpuset. 278476: Use __builtin_popcountl() instead of __builtin_popcount(). 280279: Expand the bitcount* API to support 64-bit integers, plain ints and longs and create a "hidden" API that can be used in other system headers without adding namespace pollution. - If the POPCNT instruction is enabled at compile time, use __builtin_popcount*() to implement __bitcount*(), otherwise fall back to software implementations. - Use the existing bitcount16() and bitcount32() from <sys/systm.h> to implement the non-POPCNT __bitcount16() and __bitcount32() in <sys/types.h>. - For the non-POPCNT __bitcount64(), use a similar SWAR method on 64-bit systems. For 32-bit systems, use two __bitcount32() operations on the two halves. - Use __bitcount32() to provide a __bitcount() that operates on plain ints. - Use either __bitcount32() or __bitcount64() to provide a __bitcountl() that operates on longs. - Add public bitcount*() wrappers for __bitcount*() for use in the kernel in <sys/libkern.h>. - Use __bitcountl() instead of __builtin_popcountl() in BIT_COUNT(). Modified: stable/9/sys/sys/bitset.h stable/9/sys/sys/cpuset.h stable/9/sys/sys/libkern.h stable/9/sys/sys/systm.h stable/9/sys/sys/types.h Directory Properties: stable/9/sys/ (props changed) stable/9/sys/sys/ (props changed) Changes in other areas also in this revision: Modified: stable/10/sys/sys/bitset.h stable/10/sys/sys/cpuset.h stable/10/sys/sys/libkern.h stable/10/sys/sys/systm.h stable/10/sys/sys/types.h Directory Properties: stable/10/ (props changed) Modified: stable/9/sys/sys/bitset.h ============================================================================== --- stable/9/sys/sys/bitset.h Tue Apr 14 19:18:34 2015 (r281537) +++ stable/9/sys/sys/bitset.h Tue Apr 14 20:05:26 2015 (r281538) @@ -165,4 +165,14 @@ __bit; \ }) +#define BIT_COUNT(_s, p) __extension__ ({ \ + __size_t __i; \ + int __count; \ + \ + __count = 0; \ + for (__i = 0; __i < __bitset_words((_s)); __i++) \ + __count += __bitcountl((p)->__bits[__i]); \ + __count; \ +}) + #endif /* !_SYS_BITSET_H_ */ Modified: stable/9/sys/sys/cpuset.h ============================================================================== --- stable/9/sys/sys/cpuset.h Tue Apr 14 19:18:34 2015 (r281537) +++ stable/9/sys/sys/cpuset.h Tue Apr 14 20:05:26 2015 (r281538) @@ -58,6 +58,7 @@ #define CPU_OR_ATOMIC(d, s) BIT_OR_ATOMIC(CPU_SETSIZE, d, s) #define CPU_COPY_STORE_REL(f, t) BIT_COPY_STORE_REL(CPU_SETSIZE, f, t) #define CPU_FFS(p) BIT_FFS(CPU_SETSIZE, p) +#define CPU_COUNT(p) BIT_COUNT(CPU_SETSIZE, p) /* * Valid cpulevel_t values. Modified: stable/9/sys/sys/libkern.h ============================================================================== --- stable/9/sys/sys/libkern.h Tue Apr 14 19:18:34 2015 (r281537) +++ stable/9/sys/sys/libkern.h Tue Apr 14 20:05:26 2015 (r281538) @@ -94,6 +94,12 @@ int fls(int); #ifndef HAVE_INLINE_FLSL int flsl(long); #endif +#define bitcount64(x) __bitcount64((uint64_t)(x)) +#define bitcount32(x) __bitcount32((uint32_t)(x)) +#define bitcount16(x) __bitcount16((uint16_t)(x)) +#define bitcountl(x) __bitcountl((u_long)(x)) +#define bitcount(x) __bitcount((u_int)(x)) + int fnmatch(const char *, const char *, int); int locc(int, char *, u_int); void *memchr(const void *s, int c, size_t n); Modified: stable/9/sys/sys/systm.h ============================================================================== --- stable/9/sys/sys/systm.h Tue Apr 14 19:18:34 2015 (r281537) +++ stable/9/sys/sys/systm.h Tue Apr 14 20:05:26 2015 (r281538) @@ -392,31 +392,4 @@ int alloc_unr_specific(struct unrhdr *uh int alloc_unrl(struct unrhdr *uh); void free_unr(struct unrhdr *uh, u_int item); -/* - * Population count algorithm using SWAR approach - * - "SIMD Within A Register". - */ -static __inline uint32_t -bitcount32(uint32_t x) -{ - - x = (x & 0x55555555) + ((x & 0xaaaaaaaa) >> 1); - x = (x & 0x33333333) + ((x & 0xcccccccc) >> 2); - x = (x + (x >> 4)) & 0x0f0f0f0f; - x = (x + (x >> 8)); - x = (x + (x >> 16)) & 0x000000ff; - return (x); -} - -static __inline uint16_t -bitcount16(uint32_t x) -{ - - x = (x & 0x5555) + ((x & 0xaaaa) >> 1); - x = (x & 0x3333) + ((x & 0xcccc) >> 2); - x = (x + (x >> 4)) & 0x0f0f; - x = (x + (x >> 8)) & 0x00ff; - return (x); -} - #endif /* !_SYS_SYSTM_H_ */ Modified: stable/9/sys/sys/types.h ============================================================================== --- stable/9/sys/sys/types.h Tue Apr 14 19:18:34 2015 (r281537) +++ stable/9/sys/sys/types.h Tue Apr 14 20:05:26 2015 (r281538) @@ -283,6 +283,68 @@ typedef _Bool bool; #include <sys/select.h> +#ifdef __POPCNT__ +#define __bitcount64(x) __builtin_popcountll((__uint64_t)(x)) +#define __bitcount32(x) __builtin_popcount((__uint32_t)(x)) +#define __bitcount16(x) __builtin_popcount((__uint16_t)(x)) +#define __bitcountl(x) __builtin_popcountl((unsigned long)(x)) +#define __bitcount(x) __builtin_popcount((unsigned int)(x)) +#else +/* + * Population count algorithm using SWAR approach + * - "SIMD Within A Register". + */ +static __inline __uint16_t +__bitcount16(__uint16_t _x) +{ + + _x = (_x & 0x5555) + ((_x & 0xaaaa) >> 1); + _x = (_x & 0x3333) + ((_x & 0xcccc) >> 2); + _x = (_x + (_x >> 4)) & 0x0f0f; + _x = (_x + (_x >> 8)) & 0x00ff; + return (_x); +} + +static __inline __uint32_t +__bitcount32(__uint32_t _x) +{ + + _x = (_x & 0x55555555) + ((_x & 0xaaaaaaaa) >> 1); + _x = (_x & 0x33333333) + ((_x & 0xcccccccc) >> 2); + _x = (_x + (_x >> 4)) & 0x0f0f0f0f; + _x = (_x + (_x >> 8)); + _x = (_x + (_x >> 16)) & 0x000000ff; + return (_x); +} + +#ifdef __LP64__ +static __inline __uint64_t +__bitcount64(__uint64_t _x) +{ + + _x = (_x & 0x5555555555555555) + ((_x & 0xaaaaaaaaaaaaaaaa) >> 1); + _x = (_x & 0x3333333333333333) + ((_x & 0xcccccccccccccccc) >> 2); + _x = (_x + (_x >> 4)) & 0x0f0f0f0f0f0f0f0f; + _x = (_x + (_x >> 8)); + _x = (_x + (_x >> 16)); + _x = (_x + (_x >> 32)) & 0x000000ff; + return (_x); +} + +#define __bitcountl(x) __bitcount64((unsigned long)(x)) +#else +static __inline __uint64_t +__bitcount64(__uint64_t _x) +{ + + return (__bitcount32(_x >> 32) + __bitcount32(_x)); +} + +#define __bitcountl(x) __bitcount32((unsigned long)(x)) +#endif +#define __bitcount(x) __bitcount32((unsigned int)(x)) +#endif + /* * minor() gives a cookie instead of an index since we don't want to * change the meanings of bits 0-15 or waste time and space shifting
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201504142005.t3EK5TYR073983>