diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2014-06-06 13:23:37 -0400 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2014-06-06 13:23:37 -0400 |
commit | aabfa10d86f2be6416eabedd03f52b548379f2d6 (patch) | |
tree | 34e7263a5e4dbb8f76549adc8f3ab01b0700052b | |
parent | cb9e8e3a4e12150ae0d746dffff5ce0aa4a2daab (diff) |
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).
-rw-r--r-- | src/migration.c | 20 |
1 files changed, 13 insertions, 7 deletions
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) | |||
48 | if (num_online_cpus() > 4096) | 48 | if (num_online_cpus() > 4096) |
49 | goto out; | 49 | goto out; |
50 | 50 | ||
51 | /* Read string is in the format of <mask>[,<mask>]*. All <mask>s following | ||
52 | a comma are 8 chars (representing a 32-bit mask). The first <mask> may | ||
53 | have fewer chars. Bits are MSB to LSB, left to right. */ | ||
51 | snprintf(fname, sizeof(fname), "/proc/litmus/%s/%d", which, idx); | 54 | snprintf(fname, sizeof(fname), "/proc/litmus/%s/%d", which, idx); |
52 | |||
53 | ret = read_file(fname, &buf, sizeof(buf)-1); | 55 | ret = read_file(fname, &buf, sizeof(buf)-1); |
54 | if (ret <= 0) | 56 | if (ret <= 0) |
55 | goto out; | 57 | goto out; |
56 | 58 | ||
57 | len = strnlen(buf, sizeof(buf)); | 59 | len = strnlen(buf, sizeof(buf)); |
58 | nbits = 32*(len/9 + 1); /* buf is a series of comma + 32-bits as hex */ | 60 | nbits = 32*(len/9) + 4*(len%9); /* compute bits, accounting for commas */ |
59 | 61 | ||
60 | *set = CPU_ALLOC(nbits); | 62 | *set = CPU_ALLOC(nbits); |
61 | *sz = CPU_ALLOC_SIZE(nbits); | 63 | *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) | |||
64 | /* process LSB chunks first (at the end of the str) and move backward */ | 66 | /* process LSB chunks first (at the end of the str) and move backward */ |
65 | chunk_str = buf + len - 8; | 67 | chunk_str = buf + len - 8; |
66 | i = 0; | 68 | i = 0; |
67 | while (chunk_str >= buf) { | 69 | do |
68 | unsigned long chunk = strtoul(chunk_str, NULL, 16); | 70 | { |
71 | unsigned long chunk; | ||
72 | if(chunk_str < buf) | ||
73 | chunk_str = buf; /* when MSB mask is less than 8 chars */ | ||
74 | chunk = strtoul(chunk_str, NULL, 16); | ||
69 | while (chunk) { | 75 | while (chunk) { |
70 | int j = ffsl(chunk) - 1; | 76 | int j = ffsl(chunk) - 1; |
71 | CPU_SET_S(i*32 + j, *sz, *set); | 77 | int x = i*32 + j; |
78 | CPU_SET_S(x, *sz, *set); | ||
72 | chunk &= ~(1ul << j); | 79 | chunk &= ~(1ul << j); |
73 | } | 80 | } |
74 | |||
75 | chunk_str -= 9; | 81 | chunk_str -= 9; |
76 | i += 1; | 82 | i += 1; |
77 | } | 83 | } while(chunk_str >= buf - 8); |
78 | 84 | ||
79 | ret = 0; | 85 | ret = 0; |
80 | 86 | ||