aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2013-03-12 11:57:42 -0400
committerGlenn Elliott <gelliott@cs.unc.edu>2013-03-12 12:02:20 -0400
commit93ffe5be8fd1954bbfe5a04e55b81ac1d83d2de7 (patch)
treed77875e14dd822680ed168816286d994d2d3d93e
parent1ff4fc699f01f0ad1359fad48b00c9d3be1b28b4 (diff)
Auto-CPU-affinity from part./cluster assignment.
This patch replaces be_migrate_to() with several be_migrate_*() APIs to automatically assign CPU affinity masks from a task's partition (or cluster) assignment. Routines are release-master-aware such that the release master (if one exists) will NOT be included in the task's affinity mask. (Note that release-master avoidance may be overridden by calling __be_migrate_thread_to_cluster().)
-rw-r--r--bin/rt_launch.c2
-rw-r--r--bin/rtspin.c2
-rw-r--r--include/litmus.h8
-rw-r--r--include/migration.h24
-rw-r--r--src/litmus.c12
-rw-r--r--src/migration.c162
-rw-r--r--tests/core_api.c4
-rw-r--r--tests/pcp.c16
-rw-r--r--tests/sched.c4
9 files changed, 202 insertions, 32 deletions
diff --git a/bin/rt_launch.c b/bin/rt_launch.c
index 16d6ed7..97d9df9 100644
--- a/bin/rt_launch.c
+++ b/bin/rt_launch.c
@@ -109,7 +109,7 @@ int main(int argc, char** argv)
109 info.argv = argv + optind + 2; 109 info.argv = argv + optind + 2;
110 info.wait = wait; 110 info.wait = wait;
111 if (migrate) { 111 if (migrate) {
112 ret = be_migrate_to(cpu); 112 ret = be_migrate_to_cpu(cpu);
113 if (ret < 0) 113 if (ret < 0)
114 bail_out("could not migrate to target partition"); 114 bail_out("could not migrate to target partition");
115 } 115 }
diff --git a/bin/rtspin.c b/bin/rtspin.c
index 657a94c..5f12930 100644
--- a/bin/rtspin.c
+++ b/bin/rtspin.c
@@ -321,7 +321,7 @@ int main(int argc, char** argv)
321 duration += period_ms * 0.001 * (num_jobs - 1); 321 duration += period_ms * 0.001 * (num_jobs - 1);
322 322
323 if (migrate) { 323 if (migrate) {
324 ret = be_migrate_to(cpu); 324 ret = be_migrate_to_cpu(cpu);
325 if (ret < 0) 325 if (ret < 0)
326 bail_out("could not migrate to target partition"); 326 bail_out("could not migrate to target partition");
327 } 327 }
diff --git a/include/litmus.h b/include/litmus.h
index 58af6b7..b2e81f2 100644
--- a/include/litmus.h
+++ b/include/litmus.h
@@ -16,13 +16,7 @@ extern "C" {
16 16
17#include "asm/cycles.h" /* for null_call() */ 17#include "asm/cycles.h" /* for null_call() */
18 18
19typedef int pid_t; /* PID of a task */ 19#include "migration.h"
20
21/* obtain the PID of a thread */
22pid_t gettid(void);
23
24/* migrate to partition */
25int be_migrate_to(int target_cpu);
26 20
27int set_rt_task_param(pid_t pid, struct rt_task* param); 21int set_rt_task_param(pid_t pid, struct rt_task* param);
28int get_rt_task_param(pid_t pid, struct rt_task* param); 22int get_rt_task_param(pid_t pid, struct rt_task* param);
diff --git a/include/migration.h b/include/migration.h
new file mode 100644
index 0000000..2413e7c
--- /dev/null
+++ b/include/migration.h
@@ -0,0 +1,24 @@
1
2typedef int pid_t;
3
4/* obtain the PID of a thread */
5pid_t gettid();
6
7/* Assign a task to a cpu/partition/cluster.
8 * PRECOND: tid is not yet in real-time mode (it's a best effort task).
9 * Set tid == 0 to migrate the caller */
10int be_migrate_thread_to_cpu(pid_t tid, int target_cpu);
11int be_migrate_thread_to_partition(pid_t tid, int partition);
12/* If using release master, set cluster_sz to size of largest cluster. tid
13 * will not be scheduled on release master. */
14int be_migrate_thread_to_cluster(pid_t tid, int cluster, int cluster_sz);
15
16/* set ignore_rm == 1 to include release master in tid's cpu affinity */
17int __be_migrate_thread_to_cluster(pid_t tid, int cluster, int cluster_sz, int ignore_rm);
18
19int be_migrate_to_cpu(int target_cpu);
20int be_migrate_to_partition(int partition);
21int be_migrate_to_cluster(int cluster, int cluster_sz);
22
23int num_online_cpus();
24int release_master();
diff --git a/src/litmus.c b/src/litmus.c
index e0d9253..b774c63 100644
--- a/src/litmus.c
+++ b/src/litmus.c
@@ -91,16 +91,6 @@ task_class_t str2class(const char* str)
91 91
92#define NS_PER_MS 1000000 92#define NS_PER_MS 1000000
93 93
94/* only for best-effort execution: migrate to target_cpu */
95int be_migrate_to(int target_cpu)
96{
97 cpu_set_t cpu_set;
98
99 CPU_ZERO(&cpu_set);
100 CPU_SET(target_cpu, &cpu_set);
101 return sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set);
102}
103
104int sporadic_task(lt_t e, lt_t p, lt_t phase, 94int sporadic_task(lt_t e, lt_t p, lt_t phase,
105 int cpu, unsigned int priority, 95 int cpu, unsigned int priority,
106 task_class_t cls, 96 task_class_t cls,
@@ -133,7 +123,7 @@ int sporadic_task_ns(lt_t e, lt_t p, lt_t phase,
133 param.priority = priority; 123 param.priority = priority;
134 124
135 if (set_cpu_set) { 125 if (set_cpu_set) {
136 ret = be_migrate_to(cpu); 126 ret = be_migrate_to_cpu(cpu);
137 check("migrate to cpu"); 127 check("migrate to cpu");
138 } 128 }
139 return set_rt_task_param(gettid(), &param); 129 return set_rt_task_param(gettid(), &param);
diff --git a/src/migration.c b/src/migration.c
new file mode 100644
index 0000000..152d81b
--- /dev/null
+++ b/src/migration.c
@@ -0,0 +1,162 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <sched.h> /* for cpu sets */
5#include <unistd.h>
6
7#include "migration.h"
8
9extern ssize_t read_file(const char* fname, void* buf, size_t maxlen);
10
11int release_master()
12{
13 static const char NO_CPU[] = "NO_CPU";
14 char buf[5] = {0}; /* up to 9999 CPUs */
15 int master = -1;
16
17 int ret = read_file("/proc/litmus/release_master", &buf, sizeof(buf)-1);
18
19 if ((ret > 0) && (strncmp(buf, NO_CPU, sizeof(NO_CPU)-1) != 0))
20 master = atoi(buf);
21
22 return master;
23}
24
25int num_online_cpus()
26{
27 return sysconf(_SC_NPROCESSORS_ONLN);
28}
29
30int partition_to_cpu(int partition)
31{
32 int cpu = partition;
33 int master = release_master();
34 if (master != -1 && master <= cpu) {
35 ++cpu; /* skip over the release master */
36 }
37 return cpu;
38}
39
40int cluster_to_first_cpu(int cluster, int cluster_sz)
41{
42 int first_cpu;
43 int master;
44
45 if (cluster_sz == 1)
46 return partition_to_cpu(cluster);
47
48 master = release_master();
49 first_cpu = cluster * cluster_sz;
50
51 if (master == first_cpu)
52 ++first_cpu;
53
54 return first_cpu;
55}
56
57int be_migrate_thread_to_cpu(pid_t tid, int target_cpu)
58{
59 cpu_set_t *cpu_set;
60 size_t sz;
61 int num_cpus;
62 int ret;
63
64 /* TODO: Error check to make sure that tid is not a real-time task. */
65
66 if (target_cpu < 0)
67 return -1;
68
69 num_cpus = num_online_cpus();
70 if (num_cpus == -1)
71 return -1;
72
73 if (target_cpu >= num_cpus)
74 return -1;
75
76 cpu_set = CPU_ALLOC(num_cpus);
77 sz = CPU_ALLOC_SIZE(num_cpus);
78 CPU_ZERO_S(sz, cpu_set);
79 CPU_SET_S(target_cpu, sz, cpu_set);
80
81 /* apply to caller */
82 if (tid == 0)
83 tid = gettid();
84
85 ret = sched_setaffinity(tid, sz, cpu_set);
86
87 CPU_FREE(cpu_set);
88
89 return ret;
90}
91
92int be_migrate_thread_to_cluster(pid_t tid, int cluster, int cluster_sz)
93{
94 return __be_migrate_thread_to_cluster(tid, cluster, cluster_sz, 0);
95}
96
97int __be_migrate_thread_to_cluster(pid_t tid, int cluster, int cluster_sz,
98 int ignore_rm)
99{
100 int first_cpu = cluster * cluster_sz; /* first CPU in cluster */
101 int last_cpu = first_cpu + cluster_sz - 1;
102 int master;
103 int num_cpus;
104 cpu_set_t *cpu_set;
105 size_t sz;
106 int i;
107 int ret;
108
109 /* TODO: Error check to make sure that tid is not a real-time task. */
110
111 if (cluster_sz == 1) {
112 /* we're partitioned */
113 return be_migrate_thread_to_partition(tid, cluster);
114 }
115
116 master = (ignore_rm) ? -1 : release_master();
117 num_cpus = num_online_cpus();
118
119 if (num_cpus == -1 || last_cpu >= num_cpus || first_cpu < 0)
120 return -1;
121
122 cpu_set = CPU_ALLOC(num_cpus);
123 sz = CPU_ALLOC_SIZE(num_cpus);
124 CPU_ZERO_S(sz, cpu_set);
125
126 for (i = first_cpu; i <= last_cpu; ++i) {
127 if (i != master) {
128 CPU_SET_S(i, sz, cpu_set);
129 }
130 }
131
132 /* apply to caller */
133 if (tid == 0)
134 tid = gettid();
135
136 ret = sched_setaffinity(tid, sz, cpu_set);
137
138 CPU_FREE(cpu_set);
139
140 return ret;
141}
142
143int be_migrate_thread_to_partition(pid_t tid, int partition)
144{
145 return be_migrate_thread_to_cpu(tid, partition_to_cpu(partition));
146}
147
148
149int be_migrate_to_cpu(int target_cpu)
150{
151 return be_migrate_thread_to_cpu(0, target_cpu);
152}
153
154int be_migrate_to_cluster(int cluster, int cluster_sz)
155{
156 return be_migrate_thread_to_cluster(0, cluster, cluster_sz);
157}
158
159int be_migrate_to_partition(int partition)
160{
161 return be_migrate_thread_to_partition(0, partition);
162}
diff --git a/tests/core_api.c b/tests/core_api.c
index c0b291e..b57e278 100644
--- a/tests/core_api.c
+++ b/tests/core_api.c
@@ -61,7 +61,7 @@ TESTCASE(reject_bad_priorities, P_FP,
61 params.cls = RT_CLASS_HARD; 61 params.cls = RT_CLASS_HARD;
62 params.budget_policy = NO_ENFORCEMENT; 62 params.budget_policy = NO_ENFORCEMENT;
63 63
64 SYSCALL( be_migrate_to(params.cpu) ); 64 SYSCALL( be_migrate_to_cpu(params.cpu) );
65 65
66 /* too high */ 66 /* too high */
67 params.priority = 0; 67 params.priority = 0;
@@ -87,7 +87,7 @@ TESTCASE(accept_valid_priorities, P_FP,
87 params.cls = RT_CLASS_HARD; 87 params.cls = RT_CLASS_HARD;
88 params.budget_policy = NO_ENFORCEMENT; 88 params.budget_policy = NO_ENFORCEMENT;
89 89
90 SYSCALL( be_migrate_to(params.cpu) ); 90 SYSCALL( be_migrate_to_cpu(params.cpu) );
91 91
92 /* acceptable */ 92 /* acceptable */
93 params.priority = LITMUS_LOWEST_PRIORITY; 93 params.priority = LITMUS_LOWEST_PRIORITY;
diff --git a/tests/pcp.c b/tests/pcp.c
index 8e1204f..cff4240 100644
--- a/tests/pcp.c
+++ b/tests/pcp.c
@@ -64,7 +64,7 @@ TESTCASE(pcp_inheritance, P_FP,
64 params.priority = LITMUS_LOWEST_PRIORITY; 64 params.priority = LITMUS_LOWEST_PRIORITY;
65 params.phase = 0; 65 params.phase = 0;
66 SYSCALL( set_rt_task_param(gettid(), &params) ); 66 SYSCALL( set_rt_task_param(gettid(), &params) );
67 SYSCALL( be_migrate_to(params.cpu) ); 67 SYSCALL( be_migrate_to_cpu(params.cpu) );
68 SYSCALL( task_mode(LITMUS_RT_TASK) ); 68 SYSCALL( task_mode(LITMUS_RT_TASK) );
69 69
70 SYSCALL( od = open_pcp_sem(fd, 0, cpu) ); 70 SYSCALL( od = open_pcp_sem(fd, 0, cpu) );
@@ -85,7 +85,7 @@ TESTCASE(pcp_inheritance, P_FP,
85 params.phase = ms2lt(100); 85 params.phase = ms2lt(100);
86 86
87 SYSCALL( set_rt_task_param(gettid(), &params) ); 87 SYSCALL( set_rt_task_param(gettid(), &params) );
88 SYSCALL( be_migrate_to(params.cpu) ); 88 SYSCALL( be_migrate_to_cpu(params.cpu) );
89 SYSCALL( task_mode(LITMUS_RT_TASK) ); 89 SYSCALL( task_mode(LITMUS_RT_TASK) );
90 90
91 91
@@ -102,7 +102,7 @@ TESTCASE(pcp_inheritance, P_FP,
102 params.phase = ms2lt(50); 102 params.phase = ms2lt(50);
103 103
104 SYSCALL( set_rt_task_param(gettid(), &params) ); 104 SYSCALL( set_rt_task_param(gettid(), &params) );
105 SYSCALL( be_migrate_to(params.cpu) ); 105 SYSCALL( be_migrate_to_cpu(params.cpu) );
106 SYSCALL( task_mode(LITMUS_RT_TASK) ); 106 SYSCALL( task_mode(LITMUS_RT_TASK) );
107 107
108 SYSCALL( od = open_pcp_sem(fd, 0, cpu) ); 108 SYSCALL( od = open_pcp_sem(fd, 0, cpu) );
@@ -130,7 +130,7 @@ TESTCASE(pcp_inheritance, P_FP,
130 ASSERT( waiters >= 0 ); 130 ASSERT( waiters >= 0 );
131 } while (waiters != 3); 131 } while (waiters != 3);
132 132
133 SYSCALL( be_migrate_to(1) ); 133 SYSCALL( be_migrate_to_cpu(1) );
134 134
135 waiters = release_ts(&delay); 135 waiters = release_ts(&delay);
136 136
@@ -169,7 +169,7 @@ TESTCASE(srp_ceiling_blocking, P_FP | PSN_EDF,
169 params.priority = LITMUS_LOWEST_PRIORITY; 169 params.priority = LITMUS_LOWEST_PRIORITY;
170 params.phase = 0; 170 params.phase = 0;
171 SYSCALL( set_rt_task_param(gettid(), &params) ); 171 SYSCALL( set_rt_task_param(gettid(), &params) );
172 SYSCALL( be_migrate_to(params.cpu) ); 172 SYSCALL( be_migrate_to_cpu(params.cpu) );
173 SYSCALL( task_mode(LITMUS_RT_TASK) ); 173 SYSCALL( task_mode(LITMUS_RT_TASK) );
174 174
175 SYSCALL( od = open_srp_sem(fd, 0) ); 175 SYSCALL( od = open_srp_sem(fd, 0) );
@@ -189,7 +189,7 @@ TESTCASE(srp_ceiling_blocking, P_FP | PSN_EDF,
189 params.relative_deadline -= ms2lt(110); 189 params.relative_deadline -= ms2lt(110);
190 190
191 SYSCALL( set_rt_task_param(gettid(), &params) ); 191 SYSCALL( set_rt_task_param(gettid(), &params) );
192 SYSCALL( be_migrate_to(params.cpu) ); 192 SYSCALL( be_migrate_to_cpu(params.cpu) );
193 SYSCALL( task_mode(LITMUS_RT_TASK) ); 193 SYSCALL( task_mode(LITMUS_RT_TASK) );
194 194
195 195
@@ -206,7 +206,7 @@ TESTCASE(srp_ceiling_blocking, P_FP | PSN_EDF,
206 params.relative_deadline -= ms2lt(200); 206 params.relative_deadline -= ms2lt(200);
207 207
208 SYSCALL( set_rt_task_param(gettid(), &params) ); 208 SYSCALL( set_rt_task_param(gettid(), &params) );
209 SYSCALL( be_migrate_to(params.cpu) ); 209 SYSCALL( be_migrate_to_cpu(params.cpu) );
210 SYSCALL( task_mode(LITMUS_RT_TASK) ); 210 SYSCALL( task_mode(LITMUS_RT_TASK) );
211 211
212 SYSCALL( od = open_srp_sem(fd, 0) ); 212 SYSCALL( od = open_srp_sem(fd, 0) );
@@ -231,7 +231,7 @@ TESTCASE(srp_ceiling_blocking, P_FP | PSN_EDF,
231 ASSERT( waiters >= 0 ); 231 ASSERT( waiters >= 0 );
232 } while (waiters != 3); 232 } while (waiters != 3);
233 233
234 SYSCALL( be_migrate_to(1) ); 234 SYSCALL( be_migrate_to_cpu(1) );
235 235
236 waiters = release_ts(&delay); 236 waiters = release_ts(&delay);
237 237
diff --git a/tests/sched.c b/tests/sched.c
index ab47a91..713fde2 100644
--- a/tests/sched.c
+++ b/tests/sched.c
@@ -24,7 +24,7 @@ TESTCASE(preempt_on_resume, P_FP | PSN_EDF,
24 child_lo = FORK_TASK( 24 child_lo = FORK_TASK(
25 params.priority = LITMUS_LOWEST_PRIORITY; 25 params.priority = LITMUS_LOWEST_PRIORITY;
26 SYSCALL( set_rt_task_param(gettid(), &params) ); 26 SYSCALL( set_rt_task_param(gettid(), &params) );
27 SYSCALL( be_migrate_to(params.cpu) ); 27 SYSCALL( be_migrate_to_cpu(params.cpu) );
28 SYSCALL( task_mode(LITMUS_RT_TASK) ); 28 SYSCALL( task_mode(LITMUS_RT_TASK) );
29 29
30 SYSCALL( wait_for_ts_release() ); 30 SYSCALL( wait_for_ts_release() );
@@ -40,7 +40,7 @@ TESTCASE(preempt_on_resume, P_FP | PSN_EDF,
40 params.priority = LITMUS_HIGHEST_PRIORITY; 40 params.priority = LITMUS_HIGHEST_PRIORITY;
41 params.relative_deadline -= 1000000; 41 params.relative_deadline -= 1000000;
42 SYSCALL( set_rt_task_param(gettid(), &params) ); 42 SYSCALL( set_rt_task_param(gettid(), &params) );
43 SYSCALL( be_migrate_to(params.cpu) ); 43 SYSCALL( be_migrate_to_cpu(params.cpu) );
44 SYSCALL( task_mode(LITMUS_RT_TASK) ); 44 SYSCALL( task_mode(LITMUS_RT_TASK) );
45 45
46 SYSCALL( wait_for_ts_release() ); 46 SYSCALL( wait_for_ts_release() );