From patchwork Fri Dec 5 17:44:44 2008 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cliff Wickman X-Patchwork-Id: 12522 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from ozlabs.org (localhost [127.0.0.1]) by ozlabs.org (Postfix) with ESMTP id 0F2B5474F3 for ; Sat, 6 Dec 2008 09:40:38 +1100 (EST) X-Original-To: linuxppc-dev@ozlabs.org Delivered-To: linuxppc-dev@ozlabs.org X-Greylist: delayed 358 seconds by postgrey-1.31 at ozlabs; Sat, 06 Dec 2008 04:51:05 EST Received: from relay.sgi.com (relay2.sgi.com [192.48.179.30]) by ozlabs.org (Postfix) with ESMTP id C3DD5DDDEE for ; Sat, 6 Dec 2008 04:51:05 +1100 (EST) Received: from estes.americas.sgi.com (estes.americas.sgi.com [128.162.236.10]) by relay2.corp.sgi.com (Postfix) with ESMTP id 8EE12304075; Fri, 5 Dec 2008 09:45:00 -0800 (PST) Received: from eag09.americas.sgi.com (eag09.americas.sgi.com [128.162.232.15]) by estes.americas.sgi.com (Postfix) with ESMTP id 76A7270001D3; Fri, 5 Dec 2008 11:45:00 -0600 (CST) Received: from cpw by eag09.americas.sgi.com with local (Exim 4.69) (envelope-from ) id 1L8ejM-0003Ln-VN; Fri, 05 Dec 2008 11:44:44 -0600 To: arnd@arndb.de Subject: [Re: PATCH] numactl: fix libnuma on big-endian 64-bit systems Message-Id: From: Cliff Wickman Date: Fri, 05 Dec 2008 11:44:44 -0600 X-Mailman-Approved-At: Sat, 06 Dec 2008 09:40:22 +1100 Cc: Lee.Schermerhorn@hp.com, safradin@de.ibm.com, linuxppc-dev@ozlabs.org X-BeenThere: linuxppc-dev@ozlabs.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@ozlabs.org Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@ozlabs.org linux-numa@vger.kernel.org Arnd Bergmann and Mijo Safradin called my attention to problems with libnuma's read_mask() on a big-endian 64-bit machine. In testing that function I found it to be buggy on little-endian and 32-bit systems as well. I propose a function that looks like the below. The patch is farther below. (Arnd, I did not switch to longs, as that proved problematic. The ascii hex strings being scanned are 32-bit values.) I tested on a 64-bit MIPS system. Could you test on your platform? /* * Read a mask consisting of a sequence of hexadecimal longs separated by * commas. Order them correctly and return the number of the last bit * set. */ static int read_mask(char *s, struct bitmask *bmp) { char *end = s; unsigned int *start = (unsigned int *)bmp->maskp; unsigned int *p = start; unsigned int *q; unsigned int i; unsigned int n = 0; i = strtoul(s, &end, 16); /* Skip leading zeros */ while (!i && *end++ == ',') { i = strtoul(end, &end, 16); } end++; /* past the , */ if (!i) /* End of string. No mask */ return -1; start[n++] = i; /* Read sequence of ints */ do { i = strtoul(end, &end, 16); if (i) start[n++] = i; } while (*end++ == ','); n--; /* * Invert sequence of ints if necessary since the first int * 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; *q = *p; *p = x; } /* Poor mans fls() */ for(i = 31; i >= 0; i--) if (test_bit(i, start + n)) break; /* * Return the last bit set */ return ((sizeof(unsigned int)*8) * n) + i; } Signed-off-by: Cliff Wickman --- libnuma.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) Index: numactl-dev/libnuma.c =================================================================== --- numactl-dev.orig/libnuma.c +++ numactl-dev/libnuma.c @@ -371,7 +371,6 @@ static int 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; @@ -380,22 +379,22 @@ read_mask(char *s, struct bitmask *bmp) i = strtoul(s, &end, 16); - prevend = end; /* Skip leading zeros */ while (!i && *end++ == ',') { - prevend = end; i = strtoul(end, &end, 16); } - end = prevend; + end++; /* past the , */ if (!i) /* End of string. No mask */ return -1; + start[n++] = i; /* Read sequence of ints */ do { - start[n++] = i; i = strtoul(end, &end, 16); + if (i) + start[n++] = i; } while (*end++ == ','); n--;