From 1f323b00f95c4704cdeea7918853f1e9e8d26c2e Mon Sep 17 00:00:00 2001 From: Glenn Elliott Date: Wed, 5 Feb 2014 00:31:08 -0500 Subject: 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] --- include/litmus.h | 35 ++++++++++++++++++++--------------- include/migration.h | 53 +++++++++++++++++++++++------------------------------ 2 files changed, 43 insertions(+), 45 deletions(-) (limited to 'include') 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" { * @param param Pointer to the struct to initialise */ void init_rt_task_param(struct rt_task* param); + /** * Set real-time task parameters for given process * @param pid PID of process @@ -58,6 +59,7 @@ void init_rt_task_param(struct rt_task* param); * @return 0 on success */ int set_rt_task_param(pid_t pid, struct rt_task* param); + /** * Get real-time task parameters for given process * @param pid PID of process @@ -74,20 +76,26 @@ int get_rt_task_param(pid_t pid, struct rt_task* param); * Release-master-aware functions for getting the first * CPU in a particular cluster or partition. Use these * to set rt_task::cpu for cluster/partitioned scheduling. + * + * \deprecated{Use domain_to_first_cpu() in new code.} */ int partition_to_cpu(int partition); + /** * For given cluster, return the identifier for the first associated CPU * @param cluster Identifier of the cluster * @param cluster_size Size for this cluster * @return Identifier for the first associated CPU + * + * \deprecated{Use domain_to_first_cpu() in new code.} */ int cluster_to_first_cpu(int cluster, int cluster_size); -/* Convenience functions for setting up real-time tasks. - * Default behaviors set by init_rt_task_params() used. - * Also sets affinity masks for clustered/partitions - * functions. Time units in nanoseconds. */ + +/* The following three functions are convenience functions for setting up + * real-time tasks. Default behaviors set by init_rt_task_params() are used. + * Also sets affinity masks for clustered/partitions functions. Time units in + * nanoseconds. */ /** * Set up a sporadic task with global scheduling * @param e_ns Execution time in nanoseconds @@ -95,6 +103,7 @@ int cluster_to_first_cpu(int cluster, int cluster_size); * @return 0 on success */ int sporadic_global(lt_t e_ns, lt_t p_ns); + /** * Set up a sporadic task with partitioned scheduling * @param e_ns Execution time in nanoseconds @@ -103,15 +112,15 @@ int sporadic_global(lt_t e_ns, lt_t p_ns); * @return 0 on success */ int sporadic_partitioned(lt_t e_ns, lt_t p_ns, int partition); + /** * Set up a sporadic task with clustered scheduling * @param e_ns Execution time in nanoseconds * @param p_ns Period in nanoseconds * @param cluster Cluster to add this task to - * @param cluster_size Size of the cluster * @return 0 on success */ -int sporadic_clustered(lt_t e_ns, lt_t p_ns, int cluster, int cluster_size); +int sporadic_clustered(lt_t e_ns, lt_t p_ns, int cluster); /* simple time unit conversion macros */ /** Convert seconds to nanoseconds @@ -250,29 +259,25 @@ typedef int (*rt_fn_t)(void*); * @param arg Pointer to arguments to pass to the pointer in rt_prog * @param cluster Cluster to schedule this task on. For partitioned scheduling, * set to the desired partition. For global scheduling, set to 0 - * @param cluster_size Size of the cluster. For partitioned scheduling, set to - * 1, for global scheduling set to 0. * @param wcet Worst-Case execution time for this task * @param period Period at which this task should be launched * @param prio Priority for this task */ -int create_rt_task(rt_fn_t rt_prog, void *arg, int cluster, int cluster_size, - lt_t wcet, lt_t period, unsigned int prio); +int create_rt_task(rt_fn_t rt_prog, void *arg, int cluster, + lt_t wcet, lt_t period, unsigned int prio); /** * Create a real-time task * @param rt_prog Function pointer to real-time task body * @param arg Pointer to arguments to pass to the pointer in rt_prog * @param cluster Cluster to schedule this task on. For partitioned scheduling, * set to the desired partition. For global scheduling, set to 0 - * @param cluster_size Size of the cluster. For partitioned scheduling, set to - * 1, for global scheduling set to 0. * @param wcet Worst-Case execution time for this task * @param period Period at which this task should be launched * @param prio Priority for this task - * @param cls Task class (???) + * @param cls Task class (unused) */ -int __create_rt_task(rt_fn_t rt_prog, void *arg, int cluster, int cluster_size, - lt_t wcet, lt_t period, unsigned int prio, task_class_t cls); +int __create_rt_task(rt_fn_t rt_prog, void *arg, int cluster, + lt_t wcet, lt_t period, unsigned int prio, task_class_t cls); /* per-task modes */ 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(); * @return 0 if successful */ int be_migrate_thread_to_cpu(pid_t tid, int target_cpu); -/** - * Migrate and assign a task to a given partition - * @param tid Process ID for migrated task, 0 for current task - * @param partition Partition ID to migrate the task to - * @pre tid is not yet in real-time mode (it's a best effort task) - * @return 0 if successful - */ -int be_migrate_thread_to_partition(pid_t tid, int partition); + /** * Migrate current task to a given cluster * @param tid Process ID for migrated task, 0 for current task - * @param cluster Cluster ID to migrate the task to - * @param cluster_sz Size of the cluster to migrate to + * @param domain Cluster ID to migrate the task to * @pre tid is not yet in real-time mode (it's a best effort task) * @return 0 if successful - * - * If using release master, set cluster_sz to size of largest cluster. tid - * will not be scheduled on release master - */ -int be_migrate_thread_to_cluster(pid_t tid, int cluster, int cluster_sz); - -/** - * @private - * set ignore_rm == 1 to include release master in tid's cpu affinity */ -int __be_migrate_thread_to_cluster(pid_t tid, int cluster, int cluster_sz, int ignore_rm); +int be_migrate_thread_to_cluster(pid_t tid, int domain); /** * Migrate current task to a given CPU * @param target_cpu ID for CPU to migrate to - * @pre tid is not yet in real-time mode (it's a best effort task) + * @pre The current task is not yet in real-time mode (it's a best-effort task) * @return 0 if successful */ int be_migrate_to_cpu(int target_cpu); -/** - * Migrate current task to a given partition - * @param partition Partition ID to migrate the task to - * @pre tid is not yet in real-time mode (it's a best effort task) - * @return 0 if successful - */ -int be_migrate_to_partition(int partition); + /** * Migrate current task to a given cluster * @param cluster Cluster ID to migrate the task to - * @param cluster_sz Size of the cluster to migrate to - * @pre tid is not yet in real-time mode (it's a best effort task) + * @param cluster_sz Size of the cluster to migrate to (unused) + * @pre The current task is not yet in real-time mode (it's a best-effort task) * @return 0 if successful + * + * \deprecated{Use be_migrate_to_domain() instead in new code.} */ int be_migrate_to_cluster(int cluster, int cluster_sz); +/** + * Migrate current task to a given scheduling domain (i.e., cluster or + * partition). + * @param domain The cluster/partition to migrate to. + * @pre The current task is not yet in real-time mode (it's a best-effort task). + * @return 0 if successful + */ +int be_migrate_to_domain(int domain); + /** * Return the number of CPUs currently online * @return The number of online CPUs */ int num_online_cpus(); + /** * @todo Document! */ int release_master(); +int domain_to_cpus(int domain, unsigned long long int* mask); +int cpu_to_domains(int cpu, unsigned long long int* mask); + +int domain_to_first_cpu(int domain); -- cgit v1.2.2