Add SIGPROF based pvcalarms to pthreads
authorKevin Klues <klueska@cs.berkeley.edu>
Wed, 4 Jun 2014 19:44:49 +0000 (12:44 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Wed, 4 Jun 2014 19:45:49 +0000 (12:45 -0700)
Also added a utest to test this stuff.

user/pthread/profalarm.c [new file with mode: 0644]
user/pthread/profalarm.h [new file with mode: 0644]
user/utest/pvcalarm.c

diff --git a/user/pthread/profalarm.c b/user/pthread/profalarm.c
new file mode 100644 (file)
index 0000000..9052079
--- /dev/null
@@ -0,0 +1,22 @@
+/* Copyright (c) 2014 The Regents of the University of California
+ * Kevin Klues <klueska@cs.berkeley.edu>
+ * See LICENSE for details. */
+
+#include <pthread.h>
+#include <pvcalarm.h>
+
+void pvcalarm_callback()
+{
+       if (current_uthread)
+               pthread_kill((pthread_t)current_uthread, SIGPROF);
+}
+
+void enable_profalarm(uint64_t usecs)
+{
+       enable_pvcalarms(PVCALARM_PROF, usecs, pvcalarm_callback);
+}
+
+void disable_profalarm()
+{
+       disable_pvcalarms();
+}
diff --git a/user/pthread/profalarm.h b/user/pthread/profalarm.h
new file mode 100644 (file)
index 0000000..d095fd5
--- /dev/null
@@ -0,0 +1,12 @@
+/* Copyright (c) 2014 The Regents of the University of California
+ * Kevin Klues <klueska@cs.berkeley.edu>
+ * See LICENSE for details. */
+
+#ifndef _PROFALARM_H
+#define _PROFALARM_H
+
+void enable_profalarm(int hz);
+void disable_profalarm();
+
+#endif /* _PROFALARM_H */
+
index 2a5ce89..c76324b 100644 (file)
@@ -1,6 +1,7 @@
 #include <utest.h>
 #include <pthread.h>
 #include <pvcalarm.h>
 #include <utest.h>
 #include <pthread.h>
 #include <pvcalarm.h>
+#include <profalarm.h>
 
 TEST_SUITE("PVCALARMS");
 
 
 TEST_SUITE("PVCALARMS");
 
@@ -34,10 +35,65 @@ bool test_pvcalarms(void) {
        return true;
 }
 
        return true;
 }
 
+bool test_sigperf(void)
+{
+       const int INTERVAL = 10000;
+       const int ITERATIONS = 100;
+       const int NUM_PTHREADS = 10;
+       int count[NUM_PTHREADS];
+       pthread_t threads[NUM_PTHREADS];
+       static __thread int *__count;
+
+       void *thread_handler(void *arg)
+       {
+               __count = (int*)arg;
+               sigset_t s;
+               sigemptyset(&s);
+               sigaddset(&s, SIGPROF);
+               pthread_sigmask(SIG_UNBLOCK, &s, NULL);
+               int old_count = 0, new_count = 0;
+               while(1) {
+                       while((new_count = atomic_read((atomic_t)__count)) <= old_count);
+                       if (new_count >= ITERATIONS) break;
+                       old_count = new_count;
+                       pthread_yield();
+               }
+       }
+       void signal_handler(int signo)
+       {
+               assert(signo == SIGPROF);
+               __sync_fetch_and_add(__count, 1);
+       }
+
+       pthread_lib_init();
+       pthread_can_vcore_request(TRUE);
+
+       sigset_t s;
+       sigemptyset(&s);
+       sigaddset(&s, SIGPROF);
+       pthread_sigmask(SIG_BLOCK, &s, NULL);
+       struct sigaction sigact = {.sa_handler = signal_handler, 0};
+       sigaction(SIGPROF, &sigact, 0);
+       for (int i=0; i<NUM_PTHREADS; i++)
+               count[i] = 0;
+
+       enable_profalarm(INTERVAL);
+       for (int i=0; i<NUM_PTHREADS; i++)
+               pthread_create(&threads[i], NULL, thread_handler, &count[i]);
+
+       for (int i=0; i<NUM_PTHREADS; i++)
+               while(count[i] < ITERATIONS)
+                       cpu_relax();
+
+       disable_pvcalarms();
+       return true;
+}
+
 /* <--- End definition of test cases ---> */
 
 struct utest utests[] = {
        UTEST_REG(pvcalarms),
 /* <--- End definition of test cases ---> */
 
 struct utest utests[] = {
        UTEST_REG(pvcalarms),
+       UTEST_REG(sigperf),
 };
 int num_utests = sizeof(utests) / sizeof(struct utest);
 
 };
 int num_utests = sizeof(utests) / sizeof(struct utest);