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

Author: Philippe Gerum <r...@xenomai.org>
Date:   Thu Dec 19 15:57:07 2013 +0100

testsuite/unit: introduce SCHED_QUOTA policy test

---

 config/libtool.m4            |   12 +-
 configure                    |   12 +-
 testsuite/unit/Makefile.am   |   15 ++
 testsuite/unit/Makefile.in   |   50 ++++++-
 testsuite/unit/sched-quota.c |  312 ++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 392 insertions(+), 9 deletions(-)

diff --git a/config/libtool.m4 b/config/libtool.m4
index 56666f0..126202f 100644
--- a/config/libtool.m4
+++ b/config/libtool.m4
@@ -1312,7 +1312,7 @@ ia64-*-hpux*)
   rm -rf conftest*
   ;;
 
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
 s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
   # Find out which ABI we are using.
   echo 'int i;' > conftest.$ac_ext
@@ -1326,7 +1326,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
          x86_64-*linux*)
            LD="${LD-ld} -m elf_i386"
            ;;
-         ppc64-*linux*|powerpc64-*linux*)
+         powerpcle-*linux*)
+           LD="${LD-ld} -m elf32lppclinux"
+           ;;
+         powerpc-*linux*)
            LD="${LD-ld} -m elf32ppclinux"
            ;;
          s390x-*linux*)
@@ -1345,7 +1348,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
          x86_64-*linux*)
            LD="${LD-ld} -m elf_x86_64"
            ;;
-         ppc*-*linux*|powerpc*-*linux*)
+         powerpcle-*linux*)
+           LD="${LD-ld} -m elf64lppc"
+           ;;
+         powerpc-*linux*)
            LD="${LD-ld} -m elf64ppc"
            ;;
          s390*-*linux*|s390*-*tpf*)
diff --git a/configure b/configure
index 50133f3..304e833 100755
--- a/configure
+++ b/configure
@@ -7736,7 +7736,7 @@ ia64-*-hpux*)
   rm -rf conftest*
   ;;
 
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
 s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
   # Find out which ABI we are using.
   echo 'int i;' > conftest.$ac_ext
@@ -7754,7 +7754,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
          x86_64-*linux*)
            LD="${LD-ld} -m elf_i386"
            ;;
-         ppc64-*linux*|powerpc64-*linux*)
+         powerpcle-*linux*)
+           LD="${LD-ld} -m elf32lppclinux"
+           ;;
+         powerpc-*linux*)
            LD="${LD-ld} -m elf32ppclinux"
            ;;
          s390x-*linux*)
@@ -7773,7 +7776,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
          x86_64-*linux*)
            LD="${LD-ld} -m elf_x86_64"
            ;;
-         ppc*-*linux*|powerpc*-*linux*)
+         powerpcle-*linux*)
+           LD="${LD-ld} -m elf64lppc"
+           ;;
+         powerpc-*linux*)
            LD="${LD-ld} -m elf64ppc"
            ;;
          s390*-*linux*|s390*-*tpf*)
diff --git a/testsuite/unit/Makefile.am b/testsuite/unit/Makefile.am
index f292d48..a933d99 100644
--- a/testsuite/unit/Makefile.am
+++ b/testsuite/unit/Makefile.am
@@ -14,6 +14,7 @@ test_PROGRAMS += arith        \
        mutex-torture   \
        cond-torture    \
        sched-tp        \
+       sched-quota     \
        check-vdso
 
 arith_SOURCES = arith.c arith-noinline.c arith-noinline.h
@@ -76,6 +77,20 @@ sched_tp_LDADD =                             \
        @XENO_USER_LDADD@                       \
        -lpthread -lrt -lm
 
+sched_quota_SOURCES = sched-quota.c
+
+sched_quota_CPPFLAGS =                         \
+       @XENO_USER_CFLAGS@                      \
+       -I$(top_srcdir)/include
+
+sched_quota_LDFLAGS = $(XENO_POSIX_WRAPPERS)
+
+sched_quota_LDADD =                            \
+       ../../lib/copperplate/libcopperplate.la \
+       $(coredep_lib)                          \
+       @XENO_USER_LDADD@                       \
+       -lpthread -lrt -lm
+
 check_vdso_SOURCES = check-vdso.c
 
 check_vdso_CPPFLAGS =                                  \
diff --git a/testsuite/unit/Makefile.in b/testsuite/unit/Makefile.in
index 30868d9..80a9bab 100644
--- a/testsuite/unit/Makefile.in
+++ b/testsuite/unit/Makefile.in
@@ -84,6 +84,7 @@ test_PROGRAMS = wakeup-time$(EXEEXT) rtdm$(EXEEXT) 
$(am__EXEEXT_1)
 @XENO_COBALT_TRUE@     mutex-torture   \
 @XENO_COBALT_TRUE@     cond-torture    \
 @XENO_COBALT_TRUE@     sched-tp        \
+@XENO_COBALT_TRUE@     sched-quota     \
 @XENO_COBALT_TRUE@     check-vdso
 
 subdir = testsuite/unit
@@ -106,7 +107,7 @@ CONFIG_CLEAN_FILES =
 CONFIG_CLEAN_VPATH_FILES =
 @XENO_COBALT_TRUE@am__EXEEXT_1 = arith$(EXEEXT) mutex-torture$(EXEEXT) \
 @XENO_COBALT_TRUE@     cond-torture$(EXEEXT) sched-tp$(EXEEXT) \
-@XENO_COBALT_TRUE@     check-vdso$(EXEEXT)
+@XENO_COBALT_TRUE@     sched-quota$(EXEEXT) check-vdso$(EXEEXT)
 am__installdirs = "$(DESTDIR)$(testdir)"
 PROGRAMS = $(test_PROGRAMS)
 am__arith_SOURCES_DIST = arith.c arith-noinline.c arith-noinline.h
@@ -162,6 +163,16 @@ rtdm_DEPENDENCIES = ../../lib/alchemy/libalchemy.la \
 rtdm_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
        $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
        $(rtdm_LDFLAGS) $(LDFLAGS) -o $@
+am__sched_quota_SOURCES_DIST = sched-quota.c
+@XENO_COBALT_TRUE@am_sched_quota_OBJECTS =  \
+@XENO_COBALT_TRUE@     sched_quota-sched-quota.$(OBJEXT)
+sched_quota_OBJECTS = $(am_sched_quota_OBJECTS)
+@XENO_COBALT_TRUE@sched_quota_DEPENDENCIES =  \
+@XENO_COBALT_TRUE@     ../../lib/copperplate/libcopperplate.la \
+@XENO_COBALT_TRUE@     $(am__DEPENDENCIES_1)
+sched_quota_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(sched_quota_LDFLAGS) $(LDFLAGS) -o $@
 am__sched_tp_SOURCES_DIST = sched-tp.c
 @XENO_COBALT_TRUE@am_sched_tp_OBJECTS = sched_tp-sched-tp.$(OBJEXT)
 sched_tp_OBJECTS = $(am_sched_tp_OBJECTS)
@@ -213,12 +224,14 @@ am__v_CCLD_0 = @echo "  CCLD    " $@;
 am__v_CCLD_1 = 
 SOURCES = $(arith_SOURCES) $(check_vdso_SOURCES) \
        $(cond_torture_SOURCES) $(mutex_torture_SOURCES) \
-       $(rtdm_SOURCES) $(sched_tp_SOURCES) $(wakeup_time_SOURCES)
+       $(rtdm_SOURCES) $(sched_quota_SOURCES) $(sched_tp_SOURCES) \
+       $(wakeup_time_SOURCES)
 DIST_SOURCES = $(am__arith_SOURCES_DIST) \
        $(am__check_vdso_SOURCES_DIST) \
        $(am__cond_torture_SOURCES_DIST) \
        $(am__mutex_torture_SOURCES_DIST) $(rtdm_SOURCES) \
-       $(am__sched_tp_SOURCES_DIST) $(wakeup_time_SOURCES)
+       $(am__sched_quota_SOURCES_DIST) $(am__sched_tp_SOURCES_DIST) \
+       $(wakeup_time_SOURCES)
 am__can_run_installinfo = \
   case $$AM_UPDATE_INFO_DIR in \
     n|no|NO) false;; \
@@ -466,6 +479,18 @@ CCLD = $(top_srcdir)/scripts/wrap-link.sh $(CC)
 @XENO_COBALT_TRUE@     @XENO_USER_LDADD@                       \
 @XENO_COBALT_TRUE@     -lpthread -lrt -lm
 
+@XENO_COBALT_TRUE@sched_quota_SOURCES = sched-quota.c
+@XENO_COBALT_TRUE@sched_quota_CPPFLAGS = \
+@XENO_COBALT_TRUE@     @XENO_USER_CFLAGS@                      \
+@XENO_COBALT_TRUE@     -I$(top_srcdir)/include
+
+@XENO_COBALT_TRUE@sched_quota_LDFLAGS = $(XENO_POSIX_WRAPPERS)
+@XENO_COBALT_TRUE@sched_quota_LDADD = \
+@XENO_COBALT_TRUE@     ../../lib/copperplate/libcopperplate.la \
+@XENO_COBALT_TRUE@     $(coredep_lib)                          \
+@XENO_COBALT_TRUE@     @XENO_USER_LDADD@                       \
+@XENO_COBALT_TRUE@     -lpthread -lrt -lm
+
 @XENO_COBALT_TRUE@check_vdso_SOURCES = check-vdso.c
 @XENO_COBALT_TRUE@check_vdso_CPPFLAGS = \
 @XENO_COBALT_TRUE@     @XENO_USER_CFLAGS@                              \
@@ -607,6 +632,10 @@ rtdm$(EXEEXT): $(rtdm_OBJECTS) $(rtdm_DEPENDENCIES) 
$(EXTRA_rtdm_DEPENDENCIES)
        @rm -f rtdm$(EXEEXT)
        $(AM_V_CCLD)$(rtdm_LINK) $(rtdm_OBJECTS) $(rtdm_LDADD) $(LIBS)
 
+sched-quota$(EXEEXT): $(sched_quota_OBJECTS) $(sched_quota_DEPENDENCIES) 
$(EXTRA_sched_quota_DEPENDENCIES) 
+       @rm -f sched-quota$(EXEEXT)
+       $(AM_V_CCLD)$(sched_quota_LINK) $(sched_quota_OBJECTS) 
$(sched_quota_LDADD) $(LIBS)
+
 sched-tp$(EXEEXT): $(sched_tp_OBJECTS) $(sched_tp_DEPENDENCIES) 
$(EXTRA_sched_tp_DEPENDENCIES) 
        @rm -f sched-tp$(EXEEXT)
        $(AM_V_CCLD)$(sched_tp_LINK) $(sched_tp_OBJECTS) $(sched_tp_LDADD) 
$(LIBS)
@@ -627,6 +656,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/cond_torture-cond-torture.Po@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/mutex_torture-mutex-torture.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rtdm-rtdm.Po@am__quote@
+@AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/sched_quota-sched-quota.Po@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/sched_tp-sched-tp.Po@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/wakeup_time-wakeup-time.Po@am__quote@
 
@@ -735,6 +765,20 @@ rtdm-rtdm.obj: rtdm.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) 
$(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) 
$(INCLUDES) $(rtdm_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o 
rtdm-rtdm.obj `if test -f 'rtdm.c'; then $(CYGPATH_W) 'rtdm.c'; else 
$(CYGPATH_W) '$(srcdir)/rtdm.c'; fi`
 
+sched_quota-sched-quota.o: sched-quota.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) 
$(sched_quota_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT 
sched_quota-sched-quota.o -MD -MP -MF $(DEPDIR)/sched_quota-sched-quota.Tpo -c 
-o sched_quota-sched-quota.o `test -f 'sched-quota.c' || echo 
'$(srcdir)/'`sched-quota.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) 
$(DEPDIR)/sched_quota-sched-quota.Tpo $(DEPDIR)/sched_quota-sched-quota.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='sched-quota.c' 
object='sched_quota-sched-quota.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) 
$(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) 
$(INCLUDES) $(sched_quota_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o 
sched_quota-sched-quota.o `test -f 'sched-quota.c' || echo 
'$(srcdir)/'`sched-quota.c
+
+sched_quota-sched-quota.obj: sched-quota.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) 
$(sched_quota_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT 
sched_quota-sched-quota.obj -MD -MP -MF $(DEPDIR)/sched_quota-sched-quota.Tpo 
-c -o sched_quota-sched-quota.obj `if test -f 'sched-quota.c'; then 
$(CYGPATH_W) 'sched-quota.c'; else $(CYGPATH_W) '$(srcdir)/sched-quota.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) 
$(DEPDIR)/sched_quota-sched-quota.Tpo $(DEPDIR)/sched_quota-sched-quota.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='sched-quota.c' 
object='sched_quota-sched-quota.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) 
$(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) 
$(INCLUDES) $(sched_quota_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o 
sched_quota-sched-quota.obj `if test -f 'sched-quota.c'; then $(CYGPATH_W) 
'sched-quota.c'; else $(CYGPATH_W) '$(srcdir)/sched-quota.c'; fi`
+
 sched_tp-sched-tp.o: sched-tp.c
 @am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) 
$(sched_tp_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sched_tp-sched-tp.o 
-MD -MP -MF $(DEPDIR)/sched_tp-sched-tp.Tpo -c -o sched_tp-sched-tp.o `test -f 
'sched-tp.c' || echo '$(srcdir)/'`sched-tp.c
 @am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/sched_tp-sched-tp.Tpo 
$(DEPDIR)/sched_tp-sched-tp.Po
diff --git a/testsuite/unit/sched-quota.c b/testsuite/unit/sched-quota.c
new file mode 100644
index 0000000..1347bf7
--- /dev/null
+++ b/testsuite/unit/sched-quota.c
@@ -0,0 +1,312 @@
+/*
+ * SCHED_QUOTA test.
+ *
+ * Copyright (C) Philippe Gerum <r...@xenomai.org>
+ *
+ * Released under the terms of GPLv2.
+ *
+ * --
+ *
+ * This test exercizes the SCHED_QUOTA scheduling policy. Using a pool
+ * of SCHED_FIFO threads, the code first calibrates, by estimating how
+ * much work the system under test can perform when running
+ * uninterrupted over a second.
+ *
+ * The same thread pool is re-started afterwards, as a SCHED_QUOTA
+ * group this time, which is allotted a user-definable percentage of
+ * the global quota interval
+ * (CONFIG_XENO_OPT_SCHED_QUOTA_PERIOD). Using the reference
+ * calibration value obtained by running the SCHED_FIFO pool, the
+ * percentage of runtime consumed by the SCHED_QUOTA group over a
+ * second is calculated.
+ *
+ * A successful test shows that the effective percentage of runtime
+ * observed with the SCHED_QUOTA group closely matches the allotted
+ * quota (barring rounding errors and system latency).
+ */
+#include <sys/mman.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <sched.h>
+#include <errno.h>
+#include <error.h>
+#include <boilerplate/time.h>
+
+#define MAX_THREADS 8
+#define TEST_SECS   1
+#define ONE_BILLION 1000000000UL
+
+static unsigned long long crunch_per_sec, loops_per_sec;
+
+static pthread_t threads[MAX_THREADS];
+
+static unsigned long counts[MAX_THREADS];
+
+static int nrthreads;
+
+static pthread_cond_t barrier;
+
+static pthread_mutex_t lock;
+
+static int started;
+
+static sem_t ready;
+
+static unsigned long __attribute__(( noinline ))
+__do_work(unsigned long count)
+{
+       return count + 1;
+}
+
+static void __attribute__(( noinline ))
+do_work(unsigned long loops, unsigned long *count_r)
+{
+       unsigned long n;
+
+       for (n = 0; n < loops; n++)
+               *count_r = __do_work(*count_r);
+}
+
+static void *thread_body(void *arg)
+{
+       unsigned long *count_r = arg, loops;
+       int oldstate, oldtype;
+
+       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
+       pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
+       loops = crunch_per_sec / 100; /* yield each 10 ms runtime */
+       *count_r = 0;
+       sem_post(&ready);
+
+       pthread_mutex_lock(&lock);
+       for (;;) {
+               if (started)
+                       break;
+               pthread_cond_wait(&barrier, &lock);
+       }
+       pthread_mutex_unlock(&lock);
+
+       for (;;) {
+               do_work(loops, count_r);
+               if (nrthreads > 1)
+                       sched_yield();
+       }
+
+       return NULL;
+}
+
+static void __create_quota_thread(pthread_t *tid, const char *name,
+                                 int tgid, unsigned long *count_r)
+{
+       struct sched_param_ex param_ex;
+       pthread_attr_ex_t attr_ex;
+       int ret;
+
+       pthread_attr_init_ex(&attr_ex);
+       pthread_attr_setdetachstate_ex(&attr_ex, PTHREAD_CREATE_JOINABLE);
+       pthread_attr_setinheritsched_ex(&attr_ex, PTHREAD_EXPLICIT_SCHED);
+       pthread_attr_setschedpolicy_ex(&attr_ex, SCHED_QUOTA);
+       param_ex.sched_priority = 1;
+       param_ex.sched_quota_group = tgid;
+       pthread_attr_setschedparam_ex(&attr_ex, &param_ex);
+       pthread_attr_setstacksize_ex(&attr_ex, PTHREAD_STACK_MIN * 2);
+       ret = pthread_create_ex(tid, &attr_ex, thread_body, count_r);
+       if (ret)
+               error(1, ret, "pthread_create_ex(SCHED_QUOTA)");
+
+       pthread_attr_destroy_ex(&attr_ex);
+       pthread_set_name_np(*tid, name);
+}
+
+#define create_quota_thread(__tid, __label, __tgid, __count)   \
+       __create_quota_thread(&(__tid), __label, __tgid, &(__count))
+
+static void __create_fifo_thread(pthread_t *tid, const char *name,
+                                unsigned long *count_r)
+{
+       struct sched_param param;
+       pthread_attr_t attr;
+       int ret;
+
+       pthread_attr_init(&attr);
+       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+       pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
+       pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
+       param.sched_priority = 1;
+       pthread_attr_setschedparam(&attr, &param);
+       pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN * 2);
+       ret = pthread_create(tid, &attr, thread_body, count_r);
+       if (ret)
+               error(1, ret, "pthread_create(SCHED_FIFO)");
+
+       pthread_attr_destroy(&attr);
+       pthread_set_name_np(*tid, name);
+}
+
+#define create_fifo_thread(__tid, __label, __count)    \
+       __create_fifo_thread(&(__tid), __label, &(__count))
+
+static double run_quota(int quota)
+{
+       size_t len = sched_quota_confsz();
+       unsigned long long count;
+       union sched_config cf;
+       struct timespec req;
+       int ret, tgid, n;
+       double percent;
+       char label[8];
+
+       cf.quota.op = sched_quota_add;
+       cf.quota.add.tgid_r = &tgid;
+       ret = sched_setconfig_np(0, SCHED_QUOTA, &cf, len);
+       if (ret)
+               error(1, ret, "sched_setconfig_np(add-quota-group)");
+
+       cf.quota.op = sched_quota_set;
+       cf.quota.set.quota = quota;
+       cf.quota.set.quota_peak = quota;
+       cf.quota.set.tgid = tgid;
+       ret = sched_setconfig_np(0, SCHED_QUOTA, &cf, len);
+       if (ret)
+               error(1, ret, "sched_setconfig_np(set-quota, tgid=%d)", tgid);
+
+       printf("new thread group #%d on CPU0\n", tgid);
+
+       for (n = 0; n < nrthreads; n++) {
+               sprintf(label, "t%d", n);
+               create_quota_thread(threads[n], label, tgid, counts[n]);
+               sem_wait(&ready);
+       }
+
+       pthread_mutex_lock(&lock);
+       started = 1;
+       pthread_cond_broadcast(&barrier);
+       pthread_mutex_unlock(&lock);
+
+       req.tv_sec = TEST_SECS;
+       req.tv_nsec = 0;
+       clock_nanosleep(CLOCK_MONOTONIC, 0, &req, NULL);
+
+       for (n = 0, count = 0; n < nrthreads; n++) {
+               count += counts[n];
+               pthread_kill(threads[n], SIGDEMT);
+       }
+
+       percent = ((double)count / TEST_SECS) * 100.0 / loops_per_sec;
+
+       for (n = 0; n < nrthreads; n++) {
+               __real_printf("done quota_thread[%d], count=%lu\n", n, 
counts[n]);
+               pthread_cancel(threads[n]);
+               pthread_join(threads[n], NULL);
+       }
+
+       cf.quota.op = sched_quota_remove;
+       cf.quota.remove.tgid = tgid;
+       ret = sched_setconfig_np(0, SCHED_QUOTA, &cf, len);
+       if (ret)
+               error(1, ret, "sched_setconfig_np(remove-quota-group)");
+
+       return percent;
+}
+
+static unsigned long long calibrate(void)
+{
+       struct timespec start, end, delta;
+       const int crunch_loops = 10000;
+       unsigned long long ns, lps;
+       unsigned long count;
+       struct timespec req;
+       char label[8];
+       int n;
+
+       count = 0;
+       clock_gettime(CLOCK_MONOTONIC, &start);
+       do_work(crunch_loops, &count);
+       clock_gettime(CLOCK_MONOTONIC, &end);
+       
+       timespec_sub(&delta, &end, &start);
+       ns = delta.tv_sec * ONE_BILLION + delta.tv_nsec;
+       crunch_per_sec = (unsigned long long)((double)ONE_BILLION / (double)ns 
* crunch_loops);
+
+       for (n = 0; n < nrthreads; n++) {
+               sprintf(label, "t%d", n);
+               create_fifo_thread(threads[n], label, counts[n]);
+               sem_wait(&ready);
+       }
+
+       pthread_mutex_lock(&lock);
+       started = 1;
+       pthread_cond_broadcast(&barrier);
+       pthread_mutex_unlock(&lock);
+
+       req.tv_sec = 1;
+       req.tv_nsec = 0;
+       clock_nanosleep(CLOCK_MONOTONIC, 0, &req, NULL);
+
+       for (n = 0, lps = 0; n < nrthreads; n++) {
+               lps += counts[n];
+               pthread_kill(threads[n], SIGDEMT);
+       }
+
+       for (n = 0; n < nrthreads; n++) {
+               pthread_cancel(threads[n]);
+               pthread_join(threads[n], NULL);
+       }
+
+       started = 0;
+
+       return lps;
+}
+
+int main(int argc, char **argv)
+{
+       pthread_t me = pthread_self();
+       struct sched_param param;
+       sigset_t mask, oldmask;
+       int ret, quota = 0;
+       double effective;
+
+       mlockall(MCL_CURRENT | MCL_FUTURE);
+
+       sigemptyset(&mask);
+       sigaddset(&mask, SIGINT);
+       sigaddset(&mask, SIGTERM);
+       sigaddset(&mask, SIGHUP);
+       pthread_sigmask(SIG_BLOCK, &mask, &oldmask);
+       pthread_mutex_init(&lock, NULL);
+       pthread_cond_init(&barrier, NULL);
+       sem_init(&ready, 0, 0);
+
+       param.sched_priority = 50;
+       ret = pthread_setschedparam(me, SCHED_FIFO, &param);
+       if (ret)
+               error(1, ret, "pthread_setschedparam");
+
+       if (argc > 1)
+               quota = atoi(argv[1]);
+       if (quota <= 0)
+               quota = 10;
+
+       if (argc > 2)
+               nrthreads = atoi(argv[2]);
+       if (nrthreads <= 0)
+               nrthreads = 3;
+       if (nrthreads > MAX_THREADS)
+               error(1, EINVAL, "max %d threads", MAX_THREADS);
+
+       calibrate();    /* Warming up, ignore result. */
+       loops_per_sec = calibrate();
+
+       printf("calibrating: %Lu loops/sec\n", loops_per_sec);
+
+       effective = run_quota(quota);
+       __real_printf("%d thread%s: cap=%d%%, effective=%.1f%%\n",
+                     nrthreads, nrthreads > 1 ? "s": "", quota, effective);
+
+       return 0;
+}


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

Reply via email to