Module: xenomai-forge
Branch: next
Commit: fd12b0b63593fe471b3688f4f80237171c24cf89
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=fd12b0b63593fe471b3688f4f80237171c24cf89

Author: Philippe Gerum <r...@xenomai.org>
Date:   Sun May  5 12:32:58 2013 +0200

alchemy/task: introduce rt_task_set_affinity(), remove T_CPU() macro

The former T_CPU() macro would only allow for CPUs #0-7 to be present
in the affinity mask, which is too restrictive, particularly over the
Mercury core.

We introduce rt_task_set_affinity() for the purpose of setting the CPU
affinity of a task, which takes a cpu_set_t argument as required for
high end hardware configurations.

---

 include/alchemy/task.h      |    9 +++--
 lib/alchemy/task.c          |   75 +++++++++++++++++++++++++++++++-----------
 testsuite/latency/latency.c |   22 +++++++++++--
 3 files changed, 79 insertions(+), 27 deletions(-)

diff --git a/include/alchemy/task.h b/include/alchemy/task.h
index b8c8e76..95bc32b 100644
--- a/include/alchemy/task.h
+++ b/include/alchemy/task.h
@@ -36,12 +36,10 @@
 /* Cobalt only, nop over Mercury. */
 #define T_WARNSW       __THREAD_M_WARNSW
 #define T_CONFORMING   __THREAD_M_CONFORMING
+#define T_JOINABLE     __THREAD_M_SPARE0
 /* Deprecated, compat only. */
 #define T_FPU          0x0
-/* CPU mask, up to 8 cpus [0-7] */
-#define T_CPU(cpu)     (1 << (__THREAD_M_SPARESTART + (cpu & 7)))
-#define T_CPUMASK      ((-1 >> (32 - __THREAD_M_SPARESTART - 8)) & \
-                        ~(__THREAD_M_SPARESTART ? (-1 >> (32 - 
__THREAD_M_SPARESTART)) : 0))
+
 struct RT_TASK {
        uintptr_t handle;
 };
@@ -95,6 +93,9 @@ int rt_task_create(RT_TASK *task,
 
 int rt_task_delete(RT_TASK *task);
 
+int rt_task_set_affinity(RT_TASK *task,
+                        const cpu_set_t *cpus);
+
 int rt_task_start(RT_TASK *task,
                  void (*entry)(void *arg),
                  void *arg);
diff --git a/lib/alchemy/task.c b/lib/alchemy/task.c
index 8329f67..bb37ef0 100644
--- a/lib/alchemy/task.c
+++ b/lib/alchemy/task.c
@@ -159,14 +159,6 @@ static int task_prologue(struct alchemy_task *tcb)
        struct service svc;
        int ret;
 
-       if (CPU_COUNT(&tcb->affinity) > 0) {
-               ret = sched_setaffinity(0, sizeof(tcb->affinity),
-                                       &tcb->affinity);
-               if (ret)
-                       warning("cannot set CPU affinity for task %s",
-                               tcb->name);
-       }
-
        ret = __bt(threadobj_prologue(&tcb->thobj, tcb->name));
        if (ret)
                return ret;
@@ -213,13 +205,13 @@ static int create_tcb(struct alchemy_task **tcbp, RT_TASK 
*task,
 {
        struct threadobj_init_data idata;
        struct alchemy_task *tcb;
-       int cpu, ret;
+       int ret;
 
        ret = check_task_priority(prio);
        if (ret)
                return ret;
 
-       if (mode & ~(T_CPUMASK|T_LOCK))
+       if (mode & ~T_LOCK)
                return -EINVAL;
 
        tcb = threadobj_alloc(struct alchemy_task, thobj,
@@ -234,10 +226,6 @@ static int create_tcb(struct alchemy_task **tcbp, RT_TASK 
*task,
        tcb->arg = NULL;
 
        CPU_ZERO(&tcb->affinity);
-       for (cpu = 0; cpu < 8; cpu++) {
-               if (mode & T_CPU(cpu))
-                       CPU_SET(cpu, &tcb->affinity);
-       }
 
        tcb->safecount = 0;
        syncobj_init(&tcb->sobj_safe, 0, fnref_null);
@@ -317,9 +305,6 @@ static void delete_tcb(struct alchemy_task *tcb)
  * - T_SUSP causes the task to start in suspended mode; a call to
  * rt_task_resume() is required to actually start its execution.
  *
- * - T_CPU(cpuid) makes the new task affine to CPU # @b cpuid. CPU
- * identifiers range from 0 to 7 (inclusive).
- *
  * - T_JOINABLE allows another task to wait on the termination of the
  * new task. rt_task_join() shall be called for this task to clean up
  * any resources after its termination.
@@ -474,6 +459,59 @@ out:
 }
 
 /**
+ * @fn int rt_task_set_affinity(RT_TASK *task, const cpu_set_t *cpus)
+ * @brief Set CPU affinity of real-time task.
+ *
+ * This calls makes @a task affine to the set of CPUs defined by @a
+ * cpus.
+ *
+ * @param task The descriptor address of the task.  If @a task is
+ * NULL, the CPU affinity of the current task is changed.
+ *
+ * @param cpus The set of CPUs @a task should be affine to.
+ *
+ * @return 0 is returned upon success. Otherwise:
+ *
+ * - -EINVAL is returned if @a task is NULL but the caller is not a
+ * Xenomai task, or if @a task is non-NULL but not a valid task
+ * descriptor.
+ *
+ * - -EINVAL is returned if @a cpus contains no processors that are
+ * currently physically on the system and permitted to the process
+ * according to any restrictions that may be imposed by the "cpuset"
+ * mechanism described in cpuset(7).
+ *
+ * Valid calling context:
+ *
+ * - Xenomai threads if @a task is NULL, or any otherwise.
+ */
+int rt_task_set_affinity(RT_TASK *task, const cpu_set_t *cpus)
+{
+       struct alchemy_task *tcb;
+       struct service svc;
+       int ret;
+
+       COPPERPLATE_PROTECT(svc);
+
+       tcb = get_alchemy_task_or_self(task, &ret);
+       if (tcb == NULL)
+               goto out;
+
+       tcb->affinity = *cpus;
+
+       ret = sched_setaffinity(threadobj_get_pid(&tcb->thobj),
+                               sizeof(tcb->affinity), &tcb->affinity);
+       if (ret)
+               ret = -errno;
+
+       put_alchemy_task(tcb);
+out:
+       COPPERPLATE_UNPROTECT(svc);
+
+       return ret;
+}
+
+/**
  * @fn int rt_task_start(RT_TASK *task, void (*entry)(void *arg), void *arg)
  * @brief Start a real-time task.
  *
@@ -559,9 +597,6 @@ out:
  * service; a call to rt_task_resume() is required to resume
  * execution.
  *
- * - T_CPU(cpuid) makes the new task affine to CPU # @b cpuid. CPU
- * identifiers range from 0 to 7 (inclusive).
- *
  * @return 0 is returned upon success. Otherwise:
  *
  * - -EINVAL is returned if either @a prio or @a mode are invalid.
diff --git a/testsuite/latency/latency.c b/testsuite/latency/latency.c
index 29759da..566ccd5 100644
--- a/testsuite/latency/latency.c
+++ b/testsuite/latency/latency.c
@@ -4,6 +4,7 @@
 #include <string.h>
 #include <errno.h>
 #include <signal.h>
+#include <sched.h>
 #include <time.h>
 #include <sys/mman.h>
 #include <sys/time.h>
@@ -519,8 +520,9 @@ static void sigdebug(int sig, siginfo_t *si, void *context)
 int main(int argc, char *const *argv)
 {
        struct sigaction sa __attribute__((unused));
-       int cpu = 0, c, err, sig;
+       int c, err, sig, cpu = 0;
        char task_name[16];
+       cpu_set_t cpus;
        sigset_t mask;
 
        copperplate_init(&argc, &argv);
@@ -588,7 +590,11 @@ int main(int argc, char *const *argv)
                        break;
 
                case 'c':
-                       cpu = T_CPU(atoi(optarg));
+                       cpu = atoi(optarg);
+                       if (cpu < 0 || cpu >= CPU_SETSIZE) {
+                               fprintf(stderr, "latency: invalid CPU #%d\n", 
cpu);
+                               return 1;
+                       }
                        break;
 
                case 'P':
@@ -715,10 +721,12 @@ int main(int argc, char *const *argv)
        }
 
        if (test_mode == USER_TASK) {
+               CPU_ZERO(&cpus);
+               CPU_SET(cpu, &cpus);
                snprintf(task_name, sizeof(task_name), "sampling-%d", getpid());
                err =
                    rt_task_create(&latency_task, task_name, 0, priority,
-                                  T_FPU | cpu | T_WARNSW);
+                                  T_FPU | T_WARNSW);
 
                if (err) {
                        fprintf(stderr,
@@ -727,6 +735,14 @@ int main(int argc, char *const *argv)
                        return 0;
                }
 
+               err = rt_task_set_affinity(&latency_task, &cpus);
+               if (err) {
+                       fprintf(stderr,
+                               "latency: failed to set CPU affinity, code 
%d\n",
+                               err);
+                       return 0;
+               }
+
                err = rt_task_start(&latency_task, &latency, NULL);
 
                if (err) {


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to