aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMahircan Gul <mahircg@mpi-sws.org>2016-07-18 10:05:20 -0400
committerBjoern Brandenburg <bbb@mpi-sws.org>2016-07-18 10:46:23 -0400
commitcf1d1f6e4b1138a5a841a47a2cba4aacdcaf0d72 (patch)
tree0f78c6a6a131700800c2f9dc7bf4768a775857e9
parent11a2acc387b274d2323104272e585a7059b96f4f (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.h15
-rw-r--r--src/migration.c67
-rw-r--r--tests/core_api.c38
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>
6typedef int pid_t; 7typedef int pid_t;
7 8
8/** 9/**
@@ -58,6 +59,20 @@ int be_migrate_to_cluster(int cluster, int cluster_sz);
58int be_migrate_to_domain(int domain); 59int 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
72void 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
30static int read_mapping(int idx, const char* which, cpu_set_t** set, size_t *sz) 30void 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
67static 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
196TESTCASE(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
197TESTCASE(suspended_admission, LITMUS, 235TESTCASE(suspended_admission, LITMUS,
198 "admission control handles suspended tasks correctly") 236 "admission control handles suspended tasks correctly")