From: Bernhard Walle Subject: [PATCH] Fix "memset fails with 'mbind: Invalid argument'" on PPC64 References: bnc #455977 Backport of https://bugzilla.novell.com/attachment.cgi?id=264645 Signed-off-by: Bernhard Walle --- libnuma.c | 56 +++++++++++++++++++++++++++++++++++++++++++++----------- numaint.h | 1 + 2 files changed, 46 insertions(+), 11 deletions(-) --- a/libnuma.c +++ b/libnuma.c @@ -69,12 +69,37 @@ static int maxprocnode = -1; static int maxproccpu = -1; static int nodemask_sz = 0; static int cpumask_sz = 0; +static int is_bigendian_64; int numa_exit_on_error = 0; int numa_exit_on_warn = 0; static void set_sizes(void); /* + * return 1 if this machine is big-endian 64-bit + */ +int +big_endian64() +{ + union { + struct { + int a; + int b; + } ints; + struct { + long a; + } lng; + } ua; + if (sizeof(long) != 8) + return 0; + ua.ints.a = 0; + ua.ints.b = 3; + if (ua.lng.a == 3) + return 1; + return 0; +} + +/* * There are two special functions, _init(void) and _fini(void), which * are called automatically by the dynamic loader whenever a library is loaded. * @@ -91,6 +116,7 @@ numa_init(void) for (i = 0; i < max; i++) nodemask_set_compat((nodemask_t *)&numa_all_nodes, i); memset(&numa_no_nodes, 0, sizeof(numa_no_nodes)); + is_bigendian_64 = big_endian64(); } /* @@ -103,10 +129,18 @@ numa_init(void) static unsigned int _getbit(const struct bitmask *bmp, unsigned int n) { - if (n < bmp->size) - return (bmp->maskp[n/bitsperlong] >> (n % bitsperlong)) & 1; - else - return 0; + unsigned long *ip; + + if (n < bmp->size) { + if (is_bigendian_64) { + ip = bmp->maskp; + return (ip[n/bitsperlong] >> + (n % bitsperlong)) & 1; + } else + return (bmp->maskp[n/bitsperlong] >> + (n % bitsperlong)) & 1; + } else + return 0; } static void @@ -372,10 +406,10 @@ read_mask(char *s, struct bitmask *bmp) { char *end = s; char *prevend; - unsigned int *start = (unsigned int *)bmp->maskp; - unsigned int *p = start; - unsigned int *q; - unsigned int i; + unsigned long *start = (unsigned long *)bmp->maskp; + unsigned long *p = start; + unsigned long *q; + unsigned long i; unsigned int n = 0; i = strtoul(s, &end, 16); @@ -404,21 +438,21 @@ read_mask(char *s, struct bitmask *bmp) * is the highest and we put it first because we read it first. */ for (q = start + n, p = start; p < q; q--, p++) { - unsigned int x = *q; + unsigned long x = *q; *q = *p; *p = x; } /* Poor mans fls() */ - for(i = 31; i >= 0; i--) + for(i = sizeof(unsigned long)*8 - 1; i >= 0; i--) if (test_bit(i, start + n)) break; /* * Return the last bit set */ - return ((sizeof(unsigned int)*8) * n) + i; + return ((sizeof(unsigned long)*8) * n) + i; } /* --- a/numaint.h +++ b/numaint.h @@ -32,6 +32,7 @@ enum numa_warn { }; #define howmany(x,y) (((x)+((y)-1))/(y)) +#define bitsperint (8 * sizeof(unsigned int)) #define bitsperlong (8 * sizeof(unsigned long)) #define longsperbits(n) howmany(n, bitsperlong) #define bytesperbits(x) ((x+7)/8)