diff options
| author | Mahircan Gul <mahircg@mpi-sws.org> | 2016-07-18 10:05:20 -0400 |
|---|---|---|
| committer | Bjoern Brandenburg <bbb@mpi-sws.org> | 2016-07-18 10:46:23 -0400 |
| commit | cf1d1f6e4b1138a5a841a47a2cba4aacdcaf0d72 (patch) | |
| tree | 0f78c6a6a131700800c2f9dc7bf4768a775857e9 | |
| parent | 11a2acc387b274d2323104272e585a7059b96f4f (diff) | |
Add unit-test for CPU mapping parsing
- Decompose read_mapping into two functions: *read_mapping* which reads
CPU mapping data as string from file, and *set_mapping* that actually sets
the cpu_set_t according to the mapping
- Add unit test for setting cpu_set_t to various CPU indexes
| -rw-r--r-- | include/migration.h | 15 | ||||
| -rw-r--r-- | src/migration.c | 67 | ||||
| -rw-r--r-- | tests/core_api.c | 38 |
3 files changed, 90 insertions, 30 deletions
diff --git a/include/migration.h b/include/migration.h index f60dfe9..bd52dd4 100644 --- a/include/migration.h +++ b/include/migration.h | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | * Functions to migrate tasks to different CPUs, partitions, clusters... | 3 | * Functions to migrate tasks to different CPUs, partitions, clusters... |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <sched.h> | ||
| 6 | typedef int pid_t; | 7 | typedef int pid_t; |
| 7 | 8 | ||
| 8 | /** | 9 | /** |
| @@ -58,6 +59,20 @@ int be_migrate_to_cluster(int cluster, int cluster_sz); | |||
| 58 | int be_migrate_to_domain(int domain); | 59 | int be_migrate_to_domain(int domain); |
| 59 | 60 | ||
| 60 | /** | 61 | /** |
| 62 | * Parse CPU set given as string, and return corresponding cpu_set_t variable | ||
| 63 | * and its size as parameters. | ||
| 64 | * @param buf CPU mapping as string. Specific format is explained in | ||
| 65 | * src/migration.c:82 | ||
| 66 | * @param len Length of input string in bytes | ||
| 67 | * @param set cpu_set_t type variable with bits set as according to input | ||
| 68 | * @param sz Size of CPU set in bytes | ||
| 69 | * @return void | ||
| 70 | */ | ||
| 71 | |||
| 72 | void set_mapping(char* buf, int len, cpu_set_t** set, size_t *sz); | ||
| 73 | |||
| 74 | |||
| 75 | /** | ||
| 61 | * Return the number of CPUs currently online | 76 | * Return the number of CPUs currently online |
| 62 | * @return The number of online CPUs | 77 | * @return The number of online CPUs |
| 63 | */ | 78 | */ |
diff --git a/src/migration.c b/src/migration.c index c1e5a80..efd8d81 100644 --- a/src/migration.c +++ b/src/migration.c | |||
| @@ -27,43 +27,17 @@ int num_online_cpus() | |||
| 27 | return sysconf(_SC_NPROCESSORS_ONLN); | 27 | return sysconf(_SC_NPROCESSORS_ONLN); |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | static int read_mapping(int idx, const char* which, cpu_set_t** set, size_t *sz) | 30 | void set_mapping(char* buf, int len, cpu_set_t** set, size_t *sz) |
| 31 | { | 31 | { |
| 32 | /* Max CPUs = 4096 */ | 32 | int nbits; |
| 33 | 33 | char *chunk_str; | |
| 34 | int ret = -1; | ||
| 35 | char buf[4096/4 /* enough chars for hex data (4 CPUs per char) */ | ||
| 36 | + 4096/(4*8) /* for commas (separate groups of 8 chars) */ | ||
| 37 | + 1] = {0}; /* for \0 */ | ||
| 38 | char fname[80] = {0}; | ||
| 39 | |||
| 40 | char* chunk_str; | ||
| 41 | int len, nbits; | ||
| 42 | int i; | 34 | int i; |
| 43 | 35 | ||
| 44 | /* init vals returned to callee */ | 36 | /* init vals returned to callee */ |
| 45 | *set = NULL; | 37 | *set = NULL; |
| 46 | *sz = 0; | 38 | *sz = 0; |
| 47 | 39 | ||
| 48 | if (num_online_cpus() > 4096) | ||
| 49 | goto out; | ||
| 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. */ | ||
| 54 | snprintf(fname, sizeof(fname), "/proc/litmus/%s/%d", which, idx); | ||
| 55 | ret = read_file(fname, &buf, sizeof(buf)-1); | ||
| 56 | if (ret <= 0) | ||
| 57 | goto out; | ||
| 58 | |||
| 59 | len = strnlen(buf, sizeof(buf)); | ||
| 60 | /* if there is, omit newline at the end of string */ | ||
| 61 | if (buf[len-1] == '\n') { | ||
| 62 | buf[len-1] = '\0'; | ||
| 63 | len -= 1; | ||
| 64 | } | ||
| 65 | nbits = 32*(len/9) + 4*(len%9); /* compute bits, accounting for commas */ | 40 | nbits = 32*(len/9) + 4*(len%9); /* compute bits, accounting for commas */ |
| 66 | |||
| 67 | *set = CPU_ALLOC(nbits); | 41 | *set = CPU_ALLOC(nbits); |
| 68 | *sz = CPU_ALLOC_SIZE(nbits); | 42 | *sz = CPU_ALLOC_SIZE(nbits); |
| 69 | CPU_ZERO_S(*sz, *set); | 43 | CPU_ZERO_S(*sz, *set); |
| @@ -74,7 +48,7 @@ static int read_mapping(int idx, const char* which, cpu_set_t** set, size_t *sz) | |||
| 74 | do { | 48 | do { |
| 75 | unsigned long chunk; | 49 | unsigned long chunk; |
| 76 | /* since strtoul stops processing the string with occurrence of | 50 | /* since strtoul stops processing the string with occurrence of |
| 77 | first non-digit character, it is necessary to read 8-bytes | 51 | first non-digit character, it is necessary to read 8-bytes |
| 78 | on first iteration for ignoring the leading comma*/ | 52 | on first iteration for ignoring the leading comma*/ |
| 79 | chunk_str -= (9 + ((i == 0) ? -1 : 0)); | 53 | chunk_str -= (9 + ((i == 0) ? -1 : 0)); |
| 80 | if (chunk_str < buf) | 54 | if (chunk_str < buf) |
| @@ -88,6 +62,39 @@ static int read_mapping(int idx, const char* which, cpu_set_t** set, size_t *sz) | |||
| 88 | } | 62 | } |
| 89 | i += 1; | 63 | i += 1; |
| 90 | } while (chunk_str > buf); | 64 | } while (chunk_str > buf); |
| 65 | } | ||
| 66 | |||
| 67 | static int read_mapping(int idx, const char* which, cpu_set_t** set, size_t *sz) | ||
| 68 | { | ||
| 69 | /* Max CPUs = 4096 */ | ||
| 70 | |||
| 71 | int ret = -1; | ||
| 72 | char buf[4096/4 /* enough chars for hex data (4 CPUs per char) */ | ||
| 73 | + 4096/(4*8) /* for commas (separate groups of 8 chars) */ | ||
| 74 | + 1] = {0}; /* for \0 */ | ||
| 75 | char fname[80] = {0}; | ||
| 76 | |||
| 77 | int len; | ||
| 78 | |||
| 79 | if (num_online_cpus() > 4096) | ||
| 80 | goto out; | ||
| 81 | |||
| 82 | /* Read string is in the format of <mask>[,<mask>]*. All <mask>s following | ||
| 83 | a comma are 8 chars (representing a 32-bit mask). The first <mask> may | ||
| 84 | have fewer chars. Bits are MSB to LSB, left to right. */ | ||
| 85 | snprintf(fname, sizeof(fname), "/proc/litmus/%s/%d", which, idx); | ||
| 86 | ret = read_file(fname, &buf, sizeof(buf)-1); | ||
| 87 | if (ret <= 0) | ||
| 88 | goto out; | ||
| 89 | |||
| 90 | len = strnlen(buf, sizeof(buf)); | ||
| 91 | /* if there is, omit newline at the end of string */ | ||
| 92 | if (buf[len-1] == '\n') { | ||
| 93 | buf[len-1] = '\0'; | ||
| 94 | len -= 1; | ||
| 95 | } | ||
| 96 | |||
| 97 | set_mapping(buf, len, set, sz); | ||
| 91 | 98 | ||
| 92 | ret = 0; | 99 | ret = 0; |
| 93 | 100 | ||
diff --git a/tests/core_api.c b/tests/core_api.c index feb60c5..065c1fc 100644 --- a/tests/core_api.c +++ b/tests/core_api.c | |||
| @@ -193,6 +193,44 @@ TESTCASE(ctrl_page_writable, ALL, | |||
| 193 | ctrl_page[32] = 0x12345678; | 193 | ctrl_page[32] = 0x12345678; |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | TESTCASE(set_cpu_mapping, LITMUS, | ||
| 197 | "task's CPU affinity is set to CPU set that is read from file") | ||
| 198 | { | ||
| 199 | char buf[4096/4 /* enough chars for hex data (4 CPUs per char) */ | ||
| 200 | + 4096/(4*8) /* for commas (separate groups of 8 chars) */ | ||
| 201 | + 1] = {0}; /* for \0 */ | ||
| 202 | int len; | ||
| 203 | cpu_set_t *set; | ||
| 204 | size_t sz; | ||
| 205 | |||
| 206 | /*set affinity to CPU 0 */ | ||
| 207 | strcpy(buf, "20"); | ||
| 208 | len = strnlen(buf, sizeof(buf)); | ||
| 209 | set_mapping(buf, len, &set, &sz); | ||
| 210 | ASSERT( CPU_ISSET_S(5, sz, set) ); | ||
| 211 | |||
| 212 | /*set affinity to CPU 29 */ | ||
| 213 | strcpy(buf, "20000000"); | ||
| 214 | len = strnlen(buf, sizeof(buf)); | ||
| 215 | set_mapping(buf, len, &set, &sz); | ||
| 216 | ASSERT( CPU_ISSET_S(29, sz, set) ); | ||
| 217 | |||
| 218 | /*set affinity to CPUS 27 and 39 */ | ||
| 219 | strcpy(buf, "80,08000000"); | ||
| 220 | len = strnlen(buf, sizeof(buf)); | ||
| 221 | set_mapping(buf, len, &set, &sz); | ||
| 222 | ASSERT( CPU_ISSET_S(27, sz, set) ); | ||
| 223 | ASSERT( CPU_ISSET_S(39, sz, set) ); | ||
| 224 | |||
| 225 | /*set affinity to CPUS 96 */ | ||
| 226 | strcpy(buf, "1,00000000,00000000,00000000"); | ||
| 227 | len = strnlen(buf, sizeof(buf)); | ||
| 228 | set_mapping(buf, len, &set, &sz); | ||
| 229 | ASSERT( CPU_ISSET_S(96, sz, set) ); | ||
| 230 | |||
| 231 | } | ||
| 232 | |||
| 233 | |||
| 196 | 234 | ||
| 197 | TESTCASE(suspended_admission, LITMUS, | 235 | TESTCASE(suspended_admission, LITMUS, |
| 198 | "admission control handles suspended tasks correctly") | 236 | "admission control handles suspended tasks correctly") |
