Module: xenomai-3
Branch: wip/dovetail
Commit: f6f82cb5a7ae024cb874f72b0167bad748c74d27
URL:    
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=f6f82cb5a7ae024cb874f72b0167bad748c74d27

Author: Philippe Gerum <r...@xenomai.org>
Date:   Fri Feb 26 11:44:16 2016 +0100

testsuite/smokey: add test checking Cobalt's cpu affinity control

---

 configure.ac                                 |    1 +
 testsuite/smokey/Makefile.am                 |    3 +-
 testsuite/smokey/cpu-affinity/Makefile.am    |    9 +
 testsuite/smokey/cpu-affinity/cpu-affinity.c |  252 ++++++++++++++++++++++++++
 4 files changed, 264 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index f450673..d71aa38 100644
--- a/configure.ac
+++ b/configure.ac
@@ -909,6 +909,7 @@ AC_CONFIG_FILES([ \
        testsuite/smokey/net_packet_dgram/Makefile \
        testsuite/smokey/net_packet_raw/Makefile \
        testsuite/smokey/net_common/Makefile \
+       testsuite/smokey/cpu-affinity/Makefile \
        testsuite/clocktest/Makefile \
        testsuite/xeno-test/Makefile \
        utils/Makefile \
diff --git a/testsuite/smokey/Makefile.am b/testsuite/smokey/Makefile.am
index 174b393..51292f1 100644
--- a/testsuite/smokey/Makefile.am
+++ b/testsuite/smokey/Makefile.am
@@ -8,6 +8,7 @@ smokey_SOURCES = main.c
 COBALT_SUBDIRS =       \
        arith           \
        bufp            \
+       cpu-affinity    \
        fpu-stress      \
        iddp            \
        leaks           \
@@ -32,7 +33,7 @@ COBALT_SUBDIRS =      \
 MERCURY_SUBDIRS =
 
 DIST_SUBDIRS = $(COBALT_SUBDIRS) $(MERCURY_SUBDIRS)
-       
+
 if XENO_COBALT
 wrappers = $(XENO_POSIX_WRAPPERS)
 SUBDIRS = $(COBALT_SUBDIRS)
diff --git a/testsuite/smokey/cpu-affinity/Makefile.am 
b/testsuite/smokey/cpu-affinity/Makefile.am
new file mode 100644
index 0000000..0d2e4e6
--- /dev/null
+++ b/testsuite/smokey/cpu-affinity/Makefile.am
@@ -0,0 +1,9 @@
+
+noinst_LIBRARIES = libcpu-affinity.a
+
+libcpu_affinity_a_SOURCES = cpu-affinity.c
+
+libcpu_affinity_a_CPPFLAGS =   \
+       @XENO_USER_CFLAGS@      \
+       -I$(top_srcdir)         \
+       -I$(top_srcdir)/include
diff --git a/testsuite/smokey/cpu-affinity/cpu-affinity.c 
b/testsuite/smokey/cpu-affinity/cpu-affinity.c
new file mode 100644
index 0000000..2674f76
--- /dev/null
+++ b/testsuite/smokey/cpu-affinity/cpu-affinity.c
@@ -0,0 +1,252 @@
+/*
+ * Test CPU affinity control mechanisms.
+ *
+ * Copyright (C) Philippe Gerum <r...@xenomai.org>
+ *
+ * Released under the terms of GPLv2.
+ */
+#include <pthread.h>
+#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <semaphore.h>
+#include <rtdm/testing.h>
+#include <smokey/smokey.h>
+
+smokey_test_plugin(cpu_affinity,
+                  SMOKEY_NOARGS,
+                  "Check CPU affinity control."
+);
+
+static cpu_set_t cpu_realtime_set, cpu_online_set;
+
+struct test_context {
+       sem_t done;
+       int status;
+       int kfd;
+       int nrt_cpu;
+};
+
+static void *test_thread(void *arg)
+{
+       int cpu, cpu_in_rt_set, status = 0, ncpu, ret;
+       struct test_context *p = arg;
+       cpu_set_t set;
+
+       cpu = get_current_cpu();
+       if (!__Fassert(cpu < 0)) {
+               status = cpu;
+               goto out;
+       }
+
+       /*
+        * When emerging, we should be running on a member of the
+        * real-time CPU set.
+        */
+       cpu_in_rt_set = CPU_ISSET(cpu, &cpu_realtime_set);
+       if (!__Tassert(cpu_in_rt_set)) {
+               status = -EINVAL;
+               goto out;
+       }
+
+       smokey_trace(".... user thread starts on CPU%d, ok", cpu);
+
+       for (ncpu = 0; ncpu < CPU_SETSIZE; ncpu++) {
+               if (ncpu == cpu || !CPU_ISSET(ncpu, &cpu_realtime_set))
+                       continue;
+               CPU_ZERO(&set);
+               CPU_SET(ncpu, &set);
+               if (!__Terrno(ret, sched_setaffinity(0, sizeof(set), &set))) {
+                       status = ret;
+                       goto out;
+               }
+               smokey_trace(".... user thread moved to CPU%d, good", ncpu);
+       }
+out:
+       p->status = status;
+       __STD(sem_post(&p->done));
+       
+       return NULL;
+}
+
+static int load_test_module(void)
+{
+       int fd, status;
+       
+       status = system("modprobe -q xeno_rtdmtest");
+       if (status < 0 || WEXITSTATUS(status))
+               return -ENOSYS;
+
+       /* Open the RTDM actor device. */
+       fd = open("/dev/rtdm/rtdmx", O_RDWR);
+       if (fd < 0)
+               return -errno;
+
+       return fd;
+}
+
+static void unload_test_module(int fd)
+{
+       close(fd);
+       system("rmmod xeno_rtdmtest");
+}
+
+static void *__run_cpu_affinity(void *arg)
+{
+       struct test_context *context = arg;
+       struct sched_param param;
+       struct timespec ts, now;
+       pthread_attr_t thattr;
+       cpu_set_t set;
+       pthread_t tid;
+       int ret;
+
+       smokey_trace(".. control thread binding to non-RT CPU%d",
+                    context->nrt_cpu);
+
+       __STD(sem_init(&context->done, 0, 0));
+
+       /*
+        * Make the child thread inherit a CPU affinity outside of the
+        * valid RT set from us. Cobalt should migrate the spawned
+        * threads (kernel and user) to a CPU from the RT set
+        * automatically.
+        */
+       CPU_ZERO(&set);
+       CPU_SET(context->nrt_cpu, &set);
+       if (!__Terrno(ret, sched_setaffinity(0, sizeof(set), &set))) {
+               context->status = ret;
+               goto out;
+       }
+
+       /* Check CPU affinity handling for user-space threads. */
+
+       smokey_trace(".. starting user thread");
+
+       pthread_attr_init(&thattr);
+       param.sched_priority = 1;
+       pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_DETACHED);
+       pthread_attr_setschedpolicy(&thattr, SCHED_FIFO);
+       pthread_attr_setschedparam(&thattr, &param);
+       pthread_attr_setinheritsched(&thattr, PTHREAD_EXPLICIT_SCHED);
+
+       if (!__T(ret, pthread_create(&tid, &thattr, test_thread, context))) {
+               context->status = ret;
+               goto out;
+       }
+
+       __STD(clock_gettime(CLOCK_REALTIME, &now));
+       timespec_adds(&ts, &now, 100000000); /* 100ms from now */
+       
+       if (!__Terrno(ret, __STD(sem_timedwait(&context->done, &ts)))) {
+               context->status = ret;
+               goto out;
+       }
+
+       /*
+        *  Prepare for testing CPU affinity handling for RTDM driver
+        *  tasks. We don't actually run the test just yet, since we
+        *  have no real-time context and the RTDM actor wants one,
+        *  but we still load the module, creating the actor task over
+        *  a non-RT CPU, which is the premise of our kernel-based
+        *  test.
+        */
+
+       context->kfd = load_test_module();
+out:
+       __STD(sem_destroy(&context->done));
+       
+       return NULL;
+}
+
+static int run_cpu_affinity(struct smokey_test *t,
+                           int argc, char *const argv[])
+{
+       struct test_context context;
+       int cpu, ret, cpu_in_rt_set;
+       struct sched_param param;
+       pthread_attr_t thattr;
+       pthread_t tid;
+       __u32 kcpu;
+
+       if (sysconf(_SC_NPROCESSORS_CONF) == 1) {
+               smokey_trace("uniprocessor system, skipped");
+               return 0;
+       }
+
+       ret = get_realtime_cpu_set(&cpu_realtime_set);
+       if (ret)
+               return -ENOSYS;
+
+       ret = get_online_cpu_set(&cpu_online_set);
+       if (ret)
+               return -ENOSYS;
+
+       for (cpu = 0; cpu < CPU_SETSIZE; cpu++) {
+               if (CPU_ISSET(cpu, &cpu_online_set))
+                       smokey_trace(".. CPU%d is %s", cpu,
+                            CPU_ISSET(cpu, &cpu_realtime_set) ?
+                            "available" : "online, non-RT");
+       }
+                       
+       /* Find a non-RT CPU in the online set. */
+       for (cpu = CPU_SETSIZE - 1; cpu >= 0; cpu--) {
+               if (CPU_ISSET(cpu, &cpu_online_set) &&
+                   !CPU_ISSET(cpu, &cpu_realtime_set))
+                       break;
+       }
+
+       /*
+        * If there is no CPU restriction on the bootargs
+        * (i.e. xenomai.supported_cpus is absent or does not exclude
+        * any online CPU), pretend that we have no kernel support for
+        * running this test.
+        */
+       if (cpu < 0) {
+               smokey_trace("no CPU restriction with xenomai.supported_cpus");
+               return -ENOSYS;
+       }
+
+       pthread_attr_init(&thattr);
+       param.sched_priority = 0;
+       pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE);
+       pthread_attr_setschedpolicy(&thattr, SCHED_OTHER);
+       pthread_attr_setschedparam(&thattr, &param);
+       pthread_attr_setinheritsched(&thattr, PTHREAD_EXPLICIT_SCHED);
+
+       context.kfd = -1;
+       context.status = 0;
+       context.nrt_cpu = cpu;
+       /*
+        * Start a regular pthread for running the tests, to bypass
+        * sanity checks Cobalt does on CPU affinity. We actually want
+        * to start testing from a non-RT CPU.
+        */
+       if (!__T(ret, __STD(pthread_create(&tid, &thattr,
+                                          __run_cpu_affinity, &context))))
+               return ret;
+
+       if (!__T(ret, pthread_join(tid, NULL)))
+               return ret;
+
+       if (context.kfd < 0)
+               smokey_trace(".. RTDM test module not available, skipping");
+       else {
+               smokey_trace(".. testing kthread affinity handling");
+               if (!__Terrno(ret, ioctl(context.kfd,
+                                RTTST_RTIOC_RTDM_ACTOR_GET_CPU, &kcpu)))
+                       context.status = ret;
+               else {
+                       cpu_in_rt_set = CPU_ISSET(kcpu, &cpu_realtime_set);
+                       if (!__Tassert(cpu_in_rt_set))
+                               context.status = -EINVAL;
+                       else
+                               smokey_trace(".... kernel thread pinned to 
CPU%d, fine",
+                                            kcpu);
+               }
+               unload_test_module(context.kfd);
+       }
+
+       return context.status;
+}


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

Reply via email to