From aabfa10d86f2be6416eabedd03f52b548379f2d6 Mon Sep 17 00:00:00 2001 From: Glenn Elliott Date: Fri, 6 Jun 2014 13:23:37 -0400 Subject: read_mapping() breaks on NR_CPUS not div by 32 This patch fixes a bug in read_mapping(), which is used for reading CPU and cluster (domain) mappings. read_mapping() did not account for the case when NR_CPUS is not evenly divisible by 32 (quite common when NR_CPUS < 32). --- src/migration.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/migration.c b/src/migration.c index ae7761b..1316d4c 100644 --- a/src/migration.c +++ b/src/migration.c @@ -48,14 +48,16 @@ static int read_mapping(int idx, const char* which, cpu_set_t** set, size_t *sz) if (num_online_cpus() > 4096) goto out; + /* Read string is in the format of [,]*. All s following + a comma are 8 chars (representing a 32-bit mask). The first may + have fewer chars. Bits are MSB to LSB, left to right. */ snprintf(fname, sizeof(fname), "/proc/litmus/%s/%d", which, idx); - ret = read_file(fname, &buf, sizeof(buf)-1); if (ret <= 0) goto out; len = strnlen(buf, sizeof(buf)); - nbits = 32*(len/9 + 1); /* buf is a series of comma + 32-bits as hex */ + nbits = 32*(len/9) + 4*(len%9); /* compute bits, accounting for commas */ *set = CPU_ALLOC(nbits); *sz = CPU_ALLOC_SIZE(nbits); @@ -64,17 +66,21 @@ static int read_mapping(int idx, const char* which, cpu_set_t** set, size_t *sz) /* process LSB chunks first (at the end of the str) and move backward */ chunk_str = buf + len - 8; i = 0; - while (chunk_str >= buf) { - unsigned long chunk = strtoul(chunk_str, NULL, 16); + do + { + unsigned long chunk; + if(chunk_str < buf) + chunk_str = buf; /* when MSB mask is less than 8 chars */ + chunk = strtoul(chunk_str, NULL, 16); while (chunk) { int j = ffsl(chunk) - 1; - CPU_SET_S(i*32 + j, *sz, *set); + int x = i*32 + j; + CPU_SET_S(x, *sz, *set); chunk &= ~(1ul << j); } - chunk_str -= 9; i += 1; - } + } while(chunk_str >= buf - 8); ret = 0; -- cgit v1.2.2