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 | ||
