diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2014-02-05 00:31:08 -0500 |
---|---|---|
committer | Bjoern Brandenburg <bbb@mpi-sws.org> | 2014-02-24 14:01:11 -0500 |
commit | 1f323b00f95c4704cdeea7918853f1e9e8d26c2e (patch) | |
tree | 76a6856b2465ba7d114009f231c0dae9c9e5ef2c | |
parent | 871eef081ff9db7289a6947d0160cd984232c34c (diff) |
Use /proc/litmus/domains to set up affinity masks
This patch replaces the algorithm used to compute CPU affinity masks.
The old algorithm was fragile and would break on systems with multiple
levels of shared caches. (As found on some older Intel chips, and as
one would probably find on a system with hyper-threading enabled.) The
bug stems from fact that Linux enumerates consecutive CPUs in a way
that distributes them across the physical system, thereby reducing
contention resources (e.g., cache).
Cluster size no longer needs to be provided now that cluster/CPU
mappings are explicit in /proc/litmus/domains/.
This keeps the following migration functions, but marks them as
deprecated:
- be_migrate_to_cluster()
- cluster_to_first_cpu()
- partition_to_cpu()
Although the deprecated interfaces are supported, the implementations
for these functions call the new be_migrate_to_domain() and
domain_to_first_cpu() functions.
[bbb: resolved several merge conflicts]
-rw-r--r-- | bin/rt_launch.c | 10 | ||||
-rw-r--r-- | bin/rtspin.c | 10 | ||||
-rw-r--r-- | include/litmus.h | 35 | ||||
-rw-r--r-- | include/migration.h | 53 | ||||
-rw-r--r-- | src/litmus.c | 10 | ||||
-rw-r--r-- | src/migration.c | 113 | ||||
-rw-r--r-- | src/task.c | 8 |
7 files changed, 119 insertions, 120 deletions
diff --git a/bin/rt_launch.c b/bin/rt_launch.c index 93f10d5..5e29893 100644 --- a/bin/rt_launch.c +++ b/bin/rt_launch.c | |||
@@ -42,7 +42,7 @@ void usage(char *error) { | |||
42 | } | 42 | } |
43 | 43 | ||
44 | 44 | ||
45 | #define OPTSTR "p:z:c:vwq:" | 45 | #define OPTSTR "p:c:vwq:" |
46 | 46 | ||
47 | int main(int argc, char** argv) | 47 | int main(int argc, char** argv) |
48 | { | 48 | { |
@@ -51,7 +51,6 @@ int main(int argc, char** argv) | |||
51 | lt_t period; | 51 | lt_t period; |
52 | int migrate = 0; | 52 | int migrate = 0; |
53 | int cluster = 0; | 53 | int cluster = 0; |
54 | int cluster_size = 1; | ||
55 | int opt; | 54 | int opt; |
56 | int verbose = 0; | 55 | int verbose = 0; |
57 | int wait = 0; | 56 | int wait = 0; |
@@ -71,9 +70,6 @@ int main(int argc, char** argv) | |||
71 | cluster = atoi(optarg); | 70 | cluster = atoi(optarg); |
72 | migrate = 1; | 71 | migrate = 1; |
73 | break; | 72 | break; |
74 | case 'z': | ||
75 | cluster_size = atoi(optarg); | ||
76 | break; | ||
77 | case 'q': | 73 | case 'q': |
78 | priority = atoi(optarg); | 74 | priority = atoi(optarg); |
79 | if (!litmus_is_valid_fixed_prio(priority)) | 75 | if (!litmus_is_valid_fixed_prio(priority)) |
@@ -114,11 +110,11 @@ int main(int argc, char** argv) | |||
114 | info.argv = argv + optind + 2; | 110 | info.argv = argv + optind + 2; |
115 | info.wait = wait; | 111 | info.wait = wait; |
116 | if (migrate) { | 112 | if (migrate) { |
117 | ret = be_migrate_to_cluster(cluster, cluster_size); | 113 | ret = be_migrate_to_domain(cluster); |
118 | if (ret < 0) | 114 | if (ret < 0) |
119 | bail_out("could not migrate to target partition or cluster"); | 115 | bail_out("could not migrate to target partition or cluster"); |
120 | } | 116 | } |
121 | ret = __create_rt_task(launch, &info, cluster, cluster_size, wcet, period, | 117 | ret = __create_rt_task(launch, &info, cluster, wcet, period, |
122 | priority, class); | 118 | priority, class); |
123 | 119 | ||
124 | 120 | ||
diff --git a/bin/rtspin.c b/bin/rtspin.c index 167741d..b4156cc 100644 --- a/bin/rtspin.c +++ b/bin/rtspin.c | |||
@@ -184,7 +184,7 @@ static int job(double exec_time, double program_end, int lock_od, double cs_leng | |||
184 | } | 184 | } |
185 | } | 185 | } |
186 | 186 | ||
187 | #define OPTSTR "p:z:c:wlveo:f:s:q:X:L:Q:" | 187 | #define OPTSTR "p:c:wlveo:f:s:q:X:L:Q:" |
188 | int main(int argc, char** argv) | 188 | int main(int argc, char** argv) |
189 | { | 189 | { |
190 | int ret; | 190 | int ret; |
@@ -194,7 +194,6 @@ int main(int argc, char** argv) | |||
194 | unsigned int priority = LITMUS_LOWEST_PRIORITY; | 194 | unsigned int priority = LITMUS_LOWEST_PRIORITY; |
195 | int migrate = 0; | 195 | int migrate = 0; |
196 | int cluster = 0; | 196 | int cluster = 0; |
197 | int cluster_size = 1; | ||
198 | int opt; | 197 | int opt; |
199 | int wait = 0; | 198 | int wait = 0; |
200 | int test_loop = 0; | 199 | int test_loop = 0; |
@@ -226,9 +225,6 @@ int main(int argc, char** argv) | |||
226 | cluster = atoi(optarg); | 225 | cluster = atoi(optarg); |
227 | migrate = 1; | 226 | migrate = 1; |
228 | break; | 227 | break; |
229 | case 'z': | ||
230 | cluster_size = atoi(optarg); | ||
231 | break; | ||
232 | case 'q': | 228 | case 'q': |
233 | priority = atoi(optarg); | 229 | priority = atoi(optarg); |
234 | if (!litmus_is_valid_fixed_prio(priority)) | 230 | if (!litmus_is_valid_fixed_prio(priority)) |
@@ -326,7 +322,7 @@ int main(int argc, char** argv) | |||
326 | duration += period_ms * 0.001 * (num_jobs - 1); | 322 | duration += period_ms * 0.001 * (num_jobs - 1); |
327 | 323 | ||
328 | if (migrate) { | 324 | if (migrate) { |
329 | ret = be_migrate_to_cluster(cluster, cluster_size); | 325 | ret = be_migrate_to_domain(cluster); |
330 | if (ret < 0) | 326 | if (ret < 0) |
331 | bail_out("could not migrate to target partition or cluster."); | 327 | bail_out("could not migrate to target partition or cluster."); |
332 | } | 328 | } |
@@ -339,7 +335,7 @@ int main(int argc, char** argv) | |||
339 | param.budget_policy = (want_enforcement) ? | 335 | param.budget_policy = (want_enforcement) ? |
340 | PRECISE_ENFORCEMENT : NO_ENFORCEMENT; | 336 | PRECISE_ENFORCEMENT : NO_ENFORCEMENT; |
341 | if (migrate) | 337 | if (migrate) |
342 | param.cpu = cluster_to_first_cpu(cluster, cluster_size); | 338 | param.cpu = domain_to_first_cpu(cluster); |
343 | ret = set_rt_task_param(gettid(), ¶m); | 339 | ret = set_rt_task_param(gettid(), ¶m); |
344 | if (ret < 0) | 340 | if (ret < 0) |
345 | bail_out("could not setup rt task params"); | 341 | bail_out("could not setup rt task params"); |
diff --git a/include/litmus.h b/include/litmus.h index 5a79b7d..5a5461f 100644 --- a/include/litmus.h +++ b/include/litmus.h | |||
@@ -51,6 +51,7 @@ extern "C" { | |||
51 | * @param param Pointer to the struct to initialise | 51 | * @param param Pointer to the struct to initialise |
52 | */ | 52 | */ |
53 | void init_rt_task_param(struct rt_task* param); | 53 | void init_rt_task_param(struct rt_task* param); |
54 | |||
54 | /** | 55 | /** |
55 | * Set real-time task parameters for given process | 56 | * Set real-time task parameters for given process |
56 | * @param pid PID of process | 57 | * @param pid PID of process |
@@ -58,6 +59,7 @@ void init_rt_task_param(struct rt_task* param); | |||
58 | * @return 0 on success | 59 | * @return 0 on success |
59 | */ | 60 | */ |
60 | int set_rt_task_param(pid_t pid, struct rt_task* param); | 61 | int set_rt_task_param(pid_t pid, struct rt_task* param); |
62 | |||
61 | /** | 63 | /** |
62 | * Get real-time task parameters for given process | 64 | * Get real-time task parameters for given process |
63 | * @param pid PID of process | 65 | * @param pid PID of process |
@@ -74,20 +76,26 @@ int get_rt_task_param(pid_t pid, struct rt_task* param); | |||
74 | * Release-master-aware functions for getting the first | 76 | * Release-master-aware functions for getting the first |
75 | * CPU in a particular cluster or partition. Use these | 77 | * CPU in a particular cluster or partition. Use these |
76 | * to set rt_task::cpu for cluster/partitioned scheduling. | 78 | * to set rt_task::cpu for cluster/partitioned scheduling. |
79 | * | ||
80 | * \deprecated{Use domain_to_first_cpu() in new code.} | ||
77 | */ | 81 | */ |
78 | int partition_to_cpu(int partition); | 82 | int partition_to_cpu(int partition); |
83 | |||
79 | /** | 84 | /** |
80 | * For given cluster, return the identifier for the first associated CPU | 85 | * For given cluster, return the identifier for the first associated CPU |
81 | * @param cluster Identifier of the cluster | 86 | * @param cluster Identifier of the cluster |
82 | * @param cluster_size Size for this cluster | 87 | * @param cluster_size Size for this cluster |
83 | * @return Identifier for the first associated CPU | 88 | * @return Identifier for the first associated CPU |
89 | * | ||
90 | * \deprecated{Use domain_to_first_cpu() in new code.} | ||
84 | */ | 91 | */ |
85 | int cluster_to_first_cpu(int cluster, int cluster_size); | 92 | int cluster_to_first_cpu(int cluster, int cluster_size); |
86 | 93 | ||
87 | /* Convenience functions for setting up real-time tasks. | 94 | |
88 | * Default behaviors set by init_rt_task_params() used. | 95 | /* The following three functions are convenience functions for setting up |
89 | * Also sets affinity masks for clustered/partitions | 96 | * real-time tasks. Default behaviors set by init_rt_task_params() are used. |
90 | * functions. Time units in nanoseconds. */ | 97 | * Also sets affinity masks for clustered/partitions functions. Time units in |
98 | * nanoseconds. */ | ||
91 | /** | 99 | /** |
92 | * Set up a sporadic task with global scheduling | 100 | * Set up a sporadic task with global scheduling |
93 | * @param e_ns Execution time in nanoseconds | 101 | * @param e_ns Execution time in nanoseconds |
@@ -95,6 +103,7 @@ int cluster_to_first_cpu(int cluster, int cluster_size); | |||
95 | * @return 0 on success | 103 | * @return 0 on success |
96 | */ | 104 | */ |
97 | int sporadic_global(lt_t e_ns, lt_t p_ns); | 105 | int sporadic_global(lt_t e_ns, lt_t p_ns); |
106 | |||
98 | /** | 107 | /** |
99 | * Set up a sporadic task with partitioned scheduling | 108 | * Set up a sporadic task with partitioned scheduling |
100 | * @param e_ns Execution time in nanoseconds | 109 | * @param e_ns Execution time in nanoseconds |
@@ -103,15 +112,15 @@ int sporadic_global(lt_t e_ns, lt_t p_ns); | |||
103 | * @return 0 on success | 112 | * @return 0 on success |
104 | */ | 113 | */ |
105 | int sporadic_partitioned(lt_t e_ns, lt_t p_ns, int partition); | 114 | int sporadic_partitioned(lt_t e_ns, lt_t p_ns, int partition); |
115 | |||
106 | /** | 116 | /** |
107 | * Set up a sporadic task with clustered scheduling | 117 | * Set up a sporadic task with clustered scheduling |
108 | * @param e_ns Execution time in nanoseconds | 118 | * @param e_ns Execution time in nanoseconds |
109 | * @param p_ns Period in nanoseconds | 119 | * @param p_ns Period in nanoseconds |
110 | * @param cluster Cluster to add this task to | 120 | * @param cluster Cluster to add this task to |
111 | * @param cluster_size Size of the cluster | ||
112 | * @return 0 on success | 121 | * @return 0 on success |
113 | */ | 122 | */ |
114 | int sporadic_clustered(lt_t e_ns, lt_t p_ns, int cluster, int cluster_size); | 123 | int sporadic_clustered(lt_t e_ns, lt_t p_ns, int cluster); |
115 | 124 | ||
116 | /* simple time unit conversion macros */ | 125 | /* simple time unit conversion macros */ |
117 | /** Convert seconds to nanoseconds | 126 | /** Convert seconds to nanoseconds |
@@ -250,29 +259,25 @@ typedef int (*rt_fn_t)(void*); | |||
250 | * @param arg Pointer to arguments to pass to the pointer in rt_prog | 259 | * @param arg Pointer to arguments to pass to the pointer in rt_prog |
251 | * @param cluster Cluster to schedule this task on. For partitioned scheduling, | 260 | * @param cluster Cluster to schedule this task on. For partitioned scheduling, |
252 | * set to the desired partition. For global scheduling, set to 0 | 261 | * set to the desired partition. For global scheduling, set to 0 |
253 | * @param cluster_size Size of the cluster. For partitioned scheduling, set to | ||
254 | * 1, for global scheduling set to 0. | ||
255 | * @param wcet Worst-Case execution time for this task | 262 | * @param wcet Worst-Case execution time for this task |
256 | * @param period Period at which this task should be launched | 263 | * @param period Period at which this task should be launched |
257 | * @param prio Priority for this task | 264 | * @param prio Priority for this task |
258 | */ | 265 | */ |
259 | int create_rt_task(rt_fn_t rt_prog, void *arg, int cluster, int cluster_size, | 266 | int create_rt_task(rt_fn_t rt_prog, void *arg, int cluster, |
260 | lt_t wcet, lt_t period, unsigned int prio); | 267 | lt_t wcet, lt_t period, unsigned int prio); |
261 | /** | 268 | /** |
262 | * Create a real-time task | 269 | * Create a real-time task |
263 | * @param rt_prog Function pointer to real-time task body | 270 | * @param rt_prog Function pointer to real-time task body |
264 | * @param arg Pointer to arguments to pass to the pointer in rt_prog | 271 | * @param arg Pointer to arguments to pass to the pointer in rt_prog |
265 | * @param cluster Cluster to schedule this task on. For partitioned scheduling, | 272 | * @param cluster Cluster to schedule this task on. For partitioned scheduling, |
266 | * set to the desired partition. For global scheduling, set to 0 | 273 | * set to the desired partition. For global scheduling, set to 0 |
267 | * @param cluster_size Size of the cluster. For partitioned scheduling, set to | ||
268 | * 1, for global scheduling set to 0. | ||
269 | * @param wcet Worst-Case execution time for this task | 274 | * @param wcet Worst-Case execution time for this task |
270 | * @param period Period at which this task should be launched | 275 | * @param period Period at which this task should be launched |
271 | * @param prio Priority for this task | 276 | * @param prio Priority for this task |
272 | * @param cls Task class (???) | 277 | * @param cls Task class (unused) |
273 | */ | 278 | */ |
274 | int __create_rt_task(rt_fn_t rt_prog, void *arg, int cluster, int cluster_size, | 279 | int __create_rt_task(rt_fn_t rt_prog, void *arg, int cluster, |
275 | lt_t wcet, lt_t period, unsigned int prio, task_class_t cls); | 280 | lt_t wcet, lt_t period, unsigned int prio, task_class_t cls); |
276 | 281 | ||
277 | /* per-task modes */ | 282 | /* per-task modes */ |
278 | enum rt_task_mode_t { | 283 | enum rt_task_mode_t { |
diff --git a/include/migration.h b/include/migration.h index 32d933b..f60dfe9 100644 --- a/include/migration.h +++ b/include/migration.h | |||
@@ -19,62 +19,55 @@ pid_t gettid(); | |||
19 | * @return 0 if successful | 19 | * @return 0 if successful |
20 | */ | 20 | */ |
21 | int be_migrate_thread_to_cpu(pid_t tid, int target_cpu); | 21 | int be_migrate_thread_to_cpu(pid_t tid, int target_cpu); |
22 | /** | 22 | |
23 | * Migrate and assign a task to a given partition | ||
24 | * @param tid Process ID for migrated task, 0 for current task | ||
25 | * @param partition Partition ID to migrate the task to | ||
26 | * @pre tid is not yet in real-time mode (it's a best effort task) | ||
27 | * @return 0 if successful | ||
28 | */ | ||
29 | int be_migrate_thread_to_partition(pid_t tid, int partition); | ||
30 | /** | 23 | /** |
31 | * Migrate current task to a given cluster | 24 | * Migrate current task to a given cluster |
32 | * @param tid Process ID for migrated task, 0 for current task | 25 | * @param tid Process ID for migrated task, 0 for current task |
33 | * @param cluster Cluster ID to migrate the task to | 26 | * @param domain Cluster ID to migrate the task to |
34 | * @param cluster_sz Size of the cluster to migrate to | ||
35 | * @pre tid is not yet in real-time mode (it's a best effort task) | 27 | * @pre tid is not yet in real-time mode (it's a best effort task) |
36 | * @return 0 if successful | 28 | * @return 0 if successful |
37 | * | ||
38 | * If using release master, set cluster_sz to size of largest cluster. tid | ||
39 | * will not be scheduled on release master | ||
40 | */ | ||
41 | int be_migrate_thread_to_cluster(pid_t tid, int cluster, int cluster_sz); | ||
42 | |||
43 | /** | ||
44 | * @private | ||
45 | * set ignore_rm == 1 to include release master in tid's cpu affinity | ||
46 | */ | 29 | */ |
47 | int __be_migrate_thread_to_cluster(pid_t tid, int cluster, int cluster_sz, int ignore_rm); | 30 | int be_migrate_thread_to_cluster(pid_t tid, int domain); |
48 | 31 | ||
49 | /** | 32 | /** |
50 | * Migrate current task to a given CPU | 33 | * Migrate current task to a given CPU |
51 | * @param target_cpu ID for CPU to migrate to | 34 | * @param target_cpu ID for CPU to migrate to |
52 | * @pre tid is not yet in real-time mode (it's a best effort task) | 35 | * @pre The current task is not yet in real-time mode (it's a best-effort task) |
53 | * @return 0 if successful | 36 | * @return 0 if successful |
54 | */ | 37 | */ |
55 | int be_migrate_to_cpu(int target_cpu); | 38 | int be_migrate_to_cpu(int target_cpu); |
56 | /** | 39 | |
57 | * Migrate current task to a given partition | ||
58 | * @param partition Partition ID to migrate the task to | ||
59 | * @pre tid is not yet in real-time mode (it's a best effort task) | ||
60 | * @return 0 if successful | ||
61 | */ | ||
62 | int be_migrate_to_partition(int partition); | ||
63 | /** | 40 | /** |
64 | * Migrate current task to a given cluster | 41 | * Migrate current task to a given cluster |
65 | * @param cluster Cluster ID to migrate the task to | 42 | * @param cluster Cluster ID to migrate the task to |
66 | * @param cluster_sz Size of the cluster to migrate to | 43 | * @param cluster_sz Size of the cluster to migrate to (unused) |
67 | * @pre tid is not yet in real-time mode (it's a best effort task) | 44 | * @pre The current task is not yet in real-time mode (it's a best-effort task) |
68 | * @return 0 if successful | 45 | * @return 0 if successful |
46 | * | ||
47 | * \deprecated{Use be_migrate_to_domain() instead in new code.} | ||
69 | */ | 48 | */ |
70 | int be_migrate_to_cluster(int cluster, int cluster_sz); | 49 | int be_migrate_to_cluster(int cluster, int cluster_sz); |
71 | 50 | ||
72 | /** | 51 | /** |
52 | * Migrate current task to a given scheduling domain (i.e., cluster or | ||
53 | * partition). | ||
54 | * @param domain The cluster/partition to migrate to. | ||
55 | * @pre The current task is not yet in real-time mode (it's a best-effort task). | ||
56 | * @return 0 if successful | ||
57 | */ | ||
58 | int be_migrate_to_domain(int domain); | ||
59 | |||
60 | /** | ||
73 | * Return the number of CPUs currently online | 61 | * Return the number of CPUs currently online |
74 | * @return The number of online CPUs | 62 | * @return The number of online CPUs |
75 | */ | 63 | */ |
76 | int num_online_cpus(); | 64 | int num_online_cpus(); |
65 | |||
77 | /** | 66 | /** |
78 | * @todo Document! | 67 | * @todo Document! |
79 | */ | 68 | */ |
80 | int release_master(); | 69 | int release_master(); |
70 | int domain_to_cpus(int domain, unsigned long long int* mask); | ||
71 | int cpu_to_domains(int cpu, unsigned long long int* mask); | ||
72 | |||
73 | int domain_to_first_cpu(int domain); | ||
diff --git a/src/litmus.c b/src/litmus.c index dce8e1b..4631eea 100644 --- a/src/litmus.c +++ b/src/litmus.c | |||
@@ -135,7 +135,7 @@ int sporadic_partitioned(lt_t e_ns, lt_t p_ns, int partition) | |||
135 | int ret; | 135 | int ret; |
136 | struct rt_task param; | 136 | struct rt_task param; |
137 | 137 | ||
138 | ret = be_migrate_to_partition(partition); | 138 | ret = be_migrate_to_domain(partition); |
139 | check("be_migrate_to_partition()"); | 139 | check("be_migrate_to_partition()"); |
140 | if (ret != 0) | 140 | if (ret != 0) |
141 | return ret; | 141 | return ret; |
@@ -143,17 +143,17 @@ int sporadic_partitioned(lt_t e_ns, lt_t p_ns, int partition) | |||
143 | init_rt_task_param(¶m); | 143 | init_rt_task_param(¶m); |
144 | param.exec_cost = e_ns; | 144 | param.exec_cost = e_ns; |
145 | param.period = p_ns; | 145 | param.period = p_ns; |
146 | param.cpu = partition_to_cpu(partition); | 146 | param.cpu = domain_to_first_cpu(partition); |
147 | 147 | ||
148 | return set_rt_task_param(gettid(), ¶m); | 148 | return set_rt_task_param(gettid(), ¶m); |
149 | } | 149 | } |
150 | 150 | ||
151 | int sporadic_clustered(lt_t e_ns, lt_t p_ns, int cluster, int cluster_size) | 151 | int sporadic_clustered(lt_t e_ns, lt_t p_ns, int cluster) |
152 | { | 152 | { |
153 | int ret; | 153 | int ret; |
154 | struct rt_task param; | 154 | struct rt_task param; |
155 | 155 | ||
156 | ret = be_migrate_to_cluster(cluster, cluster_size); | 156 | ret = be_migrate_to_domain(cluster); |
157 | check("be_migrate_to_cluster()"); | 157 | check("be_migrate_to_cluster()"); |
158 | if (ret != 0) | 158 | if (ret != 0) |
159 | return ret; | 159 | return ret; |
@@ -161,7 +161,7 @@ int sporadic_clustered(lt_t e_ns, lt_t p_ns, int cluster, int cluster_size) | |||
161 | init_rt_task_param(¶m); | 161 | init_rt_task_param(¶m); |
162 | param.exec_cost = e_ns; | 162 | param.exec_cost = e_ns; |
163 | param.period = p_ns; | 163 | param.period = p_ns; |
164 | param.cpu = cluster_to_first_cpu(cluster, cluster_size); | 164 | param.cpu = domain_to_first_cpu(cluster); |
165 | 165 | ||
166 | return set_rt_task_param(gettid(), ¶m); | 166 | return set_rt_task_param(gettid(), ¶m); |
167 | } | 167 | } |
diff --git a/src/migration.c b/src/migration.c index 5de81d5..3bd6d0a 100644 --- a/src/migration.c +++ b/src/migration.c | |||
@@ -27,31 +27,48 @@ int num_online_cpus() | |||
27 | return sysconf(_SC_NPROCESSORS_ONLN); | 27 | return sysconf(_SC_NPROCESSORS_ONLN); |
28 | } | 28 | } |
29 | 29 | ||
30 | int partition_to_cpu(int partition) | 30 | static int read_mapping(int idx, const char* which, unsigned long long int* mask) |
31 | { | 31 | { |
32 | int cpu = partition; | 32 | int ret = -1; |
33 | int master = release_master(); | 33 | char buf[129] = {0}; |
34 | if (master != -1 && master <= cpu) { | 34 | char fname[80] = {0}; |
35 | ++cpu; /* skip over the release master */ | 35 | |
36 | if (num_online_cpus() > 64) { | ||
37 | /* XXX: Support more than 64 CPUs. | ||
38 | * User can still set appropriate values directly. */ | ||
39 | goto out; | ||
36 | } | 40 | } |
37 | return cpu; | ||
38 | } | ||
39 | 41 | ||
40 | int cluster_to_first_cpu(int cluster, int cluster_sz) | 42 | snprintf(fname, sizeof(fname), "/proc/litmus/%s/%d", which, idx); |
41 | { | 43 | |
42 | int first_cpu; | 44 | ret = read_file(fname, &buf, sizeof(buf)-1); |
43 | int master; | 45 | if (ret <= 0) |
46 | goto out; | ||
44 | 47 | ||
45 | if (cluster_sz == 1) | 48 | *mask = strtoull(buf, NULL, 16); |
46 | return partition_to_cpu(cluster); | 49 | ret = 0; |
47 | 50 | ||
48 | master = release_master(); | 51 | out: |
49 | first_cpu = cluster * cluster_sz; | 52 | return ret; |
53 | } | ||
54 | |||
55 | int domain_to_cpus(int domain, unsigned long long int* mask) | ||
56 | { | ||
57 | return read_mapping(domain, "domains", mask); | ||
58 | } | ||
50 | 59 | ||
51 | if (master == first_cpu) | 60 | int cpu_to_domains(int cpu, unsigned long long int* mask) |
52 | ++first_cpu; | 61 | { |
62 | return read_mapping(cpu, "cpus", mask); | ||
63 | } | ||
53 | 64 | ||
54 | return first_cpu; | 65 | int domain_to_first_cpu(int domain) |
66 | { | ||
67 | unsigned long long int mask; | ||
68 | int ret = domain_to_cpus(domain, &mask); | ||
69 | if(ret == 0) | ||
70 | return (ffsll(mask)-1); | ||
71 | return ret; | ||
55 | } | 72 | } |
56 | 73 | ||
57 | int be_migrate_thread_to_cpu(pid_t tid, int target_cpu) | 74 | int be_migrate_thread_to_cpu(pid_t tid, int target_cpu) |
@@ -89,44 +106,29 @@ int be_migrate_thread_to_cpu(pid_t tid, int target_cpu) | |||
89 | return ret; | 106 | return ret; |
90 | } | 107 | } |
91 | 108 | ||
92 | int be_migrate_thread_to_cluster(pid_t tid, int cluster, int cluster_sz) | 109 | int be_migrate_thread_to_domain(pid_t tid, int domain) |
93 | { | ||
94 | return __be_migrate_thread_to_cluster(tid, cluster, cluster_sz, 0); | ||
95 | } | ||
96 | |||
97 | int __be_migrate_thread_to_cluster(pid_t tid, int cluster, int cluster_sz, | ||
98 | int ignore_rm) | ||
99 | { | 110 | { |
100 | int first_cpu = cluster * cluster_sz; /* first CPU in cluster */ | 111 | int ret, num_cpus; |
101 | int last_cpu = first_cpu + cluster_sz - 1; | ||
102 | int master; | ||
103 | int num_cpus; | ||
104 | cpu_set_t *cpu_set; | 112 | cpu_set_t *cpu_set; |
105 | size_t sz; | 113 | size_t sz; |
106 | int i; | 114 | unsigned long long int mask; |
107 | int ret; | ||
108 | |||
109 | /* TODO: Error check to make sure that tid is not a real-time task. */ | ||
110 | 115 | ||
111 | if (cluster_sz == 1) { | 116 | ret = domain_to_cpus(domain, &mask); |
112 | /* we're partitioned */ | 117 | if (ret != 0) |
113 | return be_migrate_thread_to_partition(tid, cluster); | 118 | return ret; |
114 | } | ||
115 | 119 | ||
116 | master = (ignore_rm) ? -1 : release_master(); | ||
117 | num_cpus = num_online_cpus(); | 120 | num_cpus = num_online_cpus(); |
118 | 121 | if (num_cpus == -1) | |
119 | if (num_cpus == -1 || last_cpu >= num_cpus || first_cpu < 0) | ||
120 | return -1; | 122 | return -1; |
121 | 123 | ||
122 | cpu_set = CPU_ALLOC(num_cpus); | 124 | cpu_set = CPU_ALLOC(num_cpus); |
123 | sz = CPU_ALLOC_SIZE(num_cpus); | 125 | sz = CPU_ALLOC_SIZE(num_cpus); |
124 | CPU_ZERO_S(sz, cpu_set); | 126 | CPU_ZERO_S(sz, cpu_set); |
125 | 127 | ||
126 | for (i = first_cpu; i <= last_cpu; ++i) { | 128 | while(mask) { |
127 | if (i != master) { | 129 | int idx = ffsll(mask) - 1; |
128 | CPU_SET_S(i, sz, cpu_set); | 130 | CPU_SET_S(idx, sz, cpu_set); |
129 | } | 131 | mask &= ~(1ull<<idx); |
130 | } | 132 | } |
131 | 133 | ||
132 | /* apply to caller */ | 134 | /* apply to caller */ |
@@ -140,23 +142,30 @@ int __be_migrate_thread_to_cluster(pid_t tid, int cluster, int cluster_sz, | |||
140 | return ret; | 142 | return ret; |
141 | } | 143 | } |
142 | 144 | ||
143 | int be_migrate_thread_to_partition(pid_t tid, int partition) | 145 | int be_migrate_to_cpu(int target_cpu) |
146 | { | ||
147 | return be_migrate_thread_to_cpu(0, target_cpu); | ||
148 | } | ||
149 | |||
150 | int be_migrate_to_domain(int domain) | ||
144 | { | 151 | { |
145 | return be_migrate_thread_to_cpu(tid, partition_to_cpu(partition)); | 152 | return be_migrate_thread_to_domain(0, domain); |
146 | } | 153 | } |
147 | 154 | ||
148 | 155 | ||
149 | int be_migrate_to_cpu(int target_cpu) | 156 | /* deprecated functions. */ |
157 | |||
158 | int be_migrate_to_cluster(int cluster, int cluster_size) | ||
150 | { | 159 | { |
151 | return be_migrate_thread_to_cpu(0, target_cpu); | 160 | return be_migrate_to_domain(cluster); |
152 | } | 161 | } |
153 | 162 | ||
154 | int be_migrate_to_cluster(int cluster, int cluster_sz) | 163 | int cluster_to_first_cpu(int cluster, int cluster_size) |
155 | { | 164 | { |
156 | return be_migrate_thread_to_cluster(0, cluster, cluster_sz); | 165 | return domain_to_first_cpu(cluster); |
157 | } | 166 | } |
158 | 167 | ||
159 | int be_migrate_to_partition(int partition) | 168 | int partition_to_cpu(int partition) |
160 | { | 169 | { |
161 | return be_migrate_thread_to_partition(0, partition); | 170 | return domain_to_first_cpu(partition); |
162 | } | 171 | } |
@@ -40,11 +40,11 @@ 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 | ||
43 | int __create_rt_task(rt_fn_t rt_prog, void *arg, int cluster, int cluster_size, | 43 | int __create_rt_task(rt_fn_t rt_prog, void *arg, int cluster, |
44 | lt_t wcet, lt_t period, unsigned int priority, task_class_t class) | 44 | lt_t wcet, lt_t period, unsigned int priority, task_class_t class) |
45 | { | 45 | { |
46 | struct rt_task params; | 46 | struct rt_task params; |
47 | params.cpu = cluster_to_first_cpu(cluster, cluster_size); | 47 | params.cpu = domain_to_first_cpu(cluster); |
48 | params.period = period; | 48 | params.period = period; |
49 | params.exec_cost = wcet; | 49 | params.exec_cost = wcet; |
50 | params.cls = class; | 50 | params.cls = class; |
@@ -57,10 +57,10 @@ int __create_rt_task(rt_fn_t rt_prog, void *arg, int cluster, int cluster_size, | |||
57 | (rt_setup_fn_t) set_rt_task_param, ¶ms); | 57 | (rt_setup_fn_t) set_rt_task_param, ¶ms); |
58 | } | 58 | } |
59 | 59 | ||
60 | int create_rt_task(rt_fn_t rt_prog, void *arg, int cluster, int cluster_size, | 60 | int create_rt_task(rt_fn_t rt_prog, void *arg, int cluster, |
61 | lt_t wcet, lt_t period, unsigned int prio) | 61 | lt_t wcet, lt_t period, unsigned int prio) |
62 | { | 62 | { |
63 | return __create_rt_task(rt_prog, arg, cluster, cluster_size, wcet, period, | 63 | return __create_rt_task(rt_prog, arg, cluster, wcet, period, |
64 | prio, RT_CLASS_HARD); | 64 | prio, RT_CLASS_HARD); |
65 | } | 65 | } |
66 | 66 | ||