aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2013-03-13 17:24:27 -0400
committerGlenn Elliott <gelliott@cs.unc.edu>2013-03-13 17:24:27 -0400
commit020dc974933f4e9459f699625a138c33811eadf6 (patch)
treed45dbe70b7fc3ce0655baeda609ad452a2840ac2 /src
parent944a78c21028da69fb53c0aec3e9dfdb048d47e4 (diff)
parent0e71f86251307a37161cf3de2704a59882e25258 (diff)
Merge branch 'prop/rt_task-init-final' into temp
Conflicts: bin/base_mt_task.c bin/rt_launch.c bin/rtspin.c include/litmus.h src/litmus.c src/task.c
Diffstat (limited to 'src')
-rw-r--r--src/litmus.c103
-rw-r--r--src/migration.c162
-rw-r--r--src/task.c15
3 files changed, 233 insertions, 47 deletions
diff --git a/src/litmus.c b/src/litmus.c
index 7cdffcc..213ac3f 100644
--- a/src/litmus.c
+++ b/src/litmus.c
@@ -88,6 +88,34 @@ void show_rt_param(struct rt_task* tp)
88 tp->exec_cost, tp->period, tp->cpu); 88 tp->exec_cost, tp->period, tp->cpu);
89} 89}
90 90
91void init_rt_task_param(struct rt_task* tp)
92{
93 /* Defaults:
94 * - implicit deadline (t->relative_deadline == 0)
95 * - phase = 0
96 * - class = RT_CLASS_SOFT
97 * - budget policy = NO_ENFORCEMENT
98 * - fixed priority = LITMUS_LOWEST_PRIORITY
99 * - release policy = SPORADIC
100 * - cpu assignment = 0
101 *
102 * User must still set the following fields to non-zero values:
103 * - tp->exec_cost
104 * - tp->period
105 *
106 * User must set tp->cpu to the appropriate value for non-global
107 * schedulers. For clusters, set tp->cpu to the first CPU in the
108 * assigned cluster.
109 */
110
111 memset(tp, 0, sizeof(*tp));
112
113 tp->cls = RT_CLASS_SOFT;
114 tp->priority = LITMUS_LOWEST_PRIORITY;
115 tp->budget_policy = NO_ENFORCEMENT;
116 tp->release_policy = SPORADIC;
117}
118
91task_class_t str2class(const char* str) 119task_class_t str2class(const char* str)
92{ 120{
93 if (!strcmp(str, "hrt")) 121 if (!strcmp(str, "hrt"))
@@ -102,57 +130,50 @@ task_class_t str2class(const char* str)
102 130
103#define NS_PER_MS 1000000 131#define NS_PER_MS 1000000
104 132
105/* only for best-effort execution: migrate to target_cpu */ 133int sporadic_global(lt_t e_ns, lt_t p_ns)
106int be_migrate_to(int target_cpu)
107{ 134{
108 cpu_set_t cpu_set; 135 struct rt_task param;
136
137 init_rt_task_param(&param);
138 param.exec_cost = e_ns;
139 param.period = p_ns;
109 140
110 CPU_ZERO(&cpu_set); 141 return set_rt_task_param(gettid(), &param);
111 CPU_SET(target_cpu, &cpu_set);
112 return sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set);
113} 142}
114 143
115int sporadic_task(lt_t e, lt_t p, lt_t phase, 144int sporadic_partitioned(lt_t e_ns, lt_t p_ns, int partition)
116 int cpu, unsigned int priority,
117 task_class_t cls,
118 budget_policy_t budget_policy,
119 budget_signal_policy_t budget_signal_policy,
120 int set_cpu_set)
121{ 145{
122 return sporadic_task_ns(e * NS_PER_MS, p * NS_PER_MS, phase * NS_PER_MS, 146 int ret;
123 cpu, priority, cls, budget_policy, budget_signal_policy, 147 struct rt_task param;
124 set_cpu_set); 148
149 ret = be_migrate_to_partition(partition);
150 check("be_migrate_to_partition()");
151 if (ret != 0)
152 return ret;
153
154 init_rt_task_param(&param);
155 param.exec_cost = e_ns;
156 param.period = p_ns;
157 param.cpu = partition_to_cpu(partition);
158
159 return set_rt_task_param(gettid(), &param);
125} 160}
126 161
127int sporadic_task_ns(lt_t e, lt_t p, lt_t phase, 162int sporadic_clustered(lt_t e_ns, lt_t p_ns, int cluster, int cluster_size)
128 int cpu, unsigned int priority,
129 task_class_t cls,
130 budget_policy_t budget_policy,
131 budget_signal_policy_t budget_signal_policy,
132 int set_cpu_set)
133{ 163{
134 struct rt_task param;
135 int ret; 164 int ret;
165 struct rt_task param;
166
167 ret = be_migrate_to_cluster(cluster, cluster_size);
168 check("be_migrate_to_cluster()");
169 if (ret != 0)
170 return ret;
171
172 init_rt_task_param(&param);
173 param.exec_cost = e_ns;
174 param.period = p_ns;
175 param.cpu = cluster_to_first_cpu(cluster, cluster_size);
136 176
137 /* Zero out first --- this is helpful when we add plugin-specific
138 * parameters during development.
139 */
140 memset(&param, 0, sizeof(param));
141
142 param.exec_cost = e;
143 param.period = p;
144 param.relative_deadline = p; /* implicit deadline */
145 param.cpu = cpu;
146 param.cls = cls;
147 param.phase = phase;
148 param.budget_policy = budget_policy;
149 param.budget_signal_policy = budget_signal_policy;
150 param.priority = priority;
151
152 if (set_cpu_set) {
153 ret = be_migrate_to(cpu);
154 check("migrate to cpu");
155 }
156 return set_rt_task_param(gettid(), &param); 177 return set_rt_task_param(gettid(), &param);
157} 178}
158 179
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/src/task.c b/src/task.c
index 9317cc7..ef4bf79 100644
--- a/src/task.c
+++ b/src/task.c
@@ -40,11 +40,12 @@ int __launch_rt_task(rt_fn_t rt_prog, void *rt_arg, rt_setup_fn_t setup,
40 return rt_task; 40 return rt_task;
41} 41}
42 42
43int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, lt_t wcet, lt_t period, 43int __create_rt_task(rt_fn_t rt_prog, void *arg, int cluster, int cluster_size,
44 unsigned int priority, task_class_t cls) 44 lt_t wcet, lt_t period, unsigned int priority, task_class_t cls)
45{ 45{
46 struct rt_task params; 46 struct rt_task params;
47 params.cpu = cpu; 47 init_rt_task_param(&params);
48 params.cpu = cluster_to_first_cpu(cluster, cluster_size);
48 params.period = period; 49 params.period = period;
49 params.exec_cost = wcet; 50 params.exec_cost = wcet;
50 params.cls = cls; 51 params.cls = cls;
@@ -57,9 +58,11 @@ int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, lt_t wcet, lt_t period
57 (rt_setup_fn_t) set_rt_task_param, &params); 58 (rt_setup_fn_t) set_rt_task_param, &params);
58} 59}
59 60
60int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, lt_t wcet, lt_t period, 61int create_rt_task(rt_fn_t rt_prog, void *arg, int cluster, int cluster_size,
61 unsigned int priority) { 62 lt_t wcet, lt_t period, unsigned int prio)
62 return __create_rt_task(rt_prog, arg, cpu, wcet, period, priority, RT_CLASS_HARD); 63{
64 return __create_rt_task(rt_prog, arg, cluster, cluster_size, wcet, period,
65 prio, RT_CLASS_HARD);
63} 66}
64 67
65 68