Test app to measure vcore_request()
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 27 Apr 2010 05:04:29 +0000 (22:04 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:45 +0000 (17:35 -0700)
See the comment at the top of msr_get_cores.c for details.

kern/src/Makefrag
kern/src/kfs.c
tests/msr_get_cores.c [new file with mode: 0644]
user/include/timing.h
user/parlib/timing.c

index 123f1b9..ddf751d 100644 (file)
@@ -53,18 +53,14 @@ $(OBJDIR)/$(KERN_DIR)/kernel: tests
 
 KERN_APPFILES += \
                  $(TESTS_DIR)/tlstest \
-                 $(TESTS_DIR)/proctests \
                  $(TESTS_DIR)/fp_test \
-                 $(TESTS_DIR)/null \
-                 $(TESTS_DIR)/spawn \
                  $(TESTS_DIR)/mproctests \
-                 $(TESTS_DIR)/draw_nanwan \
                  $(TESTS_DIR)/hello \
                  $(TESTS_DIR)/mhello \
-                 $(TESTS_DIR)/manycore_test \
                  $(TESTS_DIR)/pthread_test \
                  $(TESTS_DIR)/idle \
-                 $(TESTS_DIR)/fillmeup
+                 $(TESTS_DIR)/fillmeup \
+                 $(TESTS_DIR)/msr_get_cores
 endif
 
 KERN_LDFLAGS   := $(KERN_LDFLAGS) -L$(OBJDIR)/$(KERN_DIR) \
index b11c3d5..8fbe66a 100644 (file)
  */
 #ifdef __CONFIG_KFS__
 DECL_PROG(tlstest);
-DECL_PROG(proctests);
 DECL_PROG(fp_test);
-DECL_PROG(null);
-DECL_PROG(spawn);
 DECL_PROG(mproctests);
-DECL_PROG(draw_nanwan);
 DECL_PROG(hello);
 DECL_PROG(mhello);
-DECL_PROG(manycore_test);
 DECL_PROG(pthread_test);
 DECL_PROG(idle);
 DECL_PROG(fillmeup);
+DECL_PROG(msr_get_cores);
 DECL_FILE(kfs_test_txt);
 DECL_FILE(hello_txt);
 #endif
@@ -59,18 +55,14 @@ DECL_FILE(hello_txt);
 struct kfs_entry kfs[MAX_KFS_FILES] = {
 #ifdef __CONFIG_KFS__
        KFS_PENTRY(tlstest)
-       KFS_PENTRY(proctests)
        KFS_PENTRY(fp_test)
-       KFS_PENTRY(null)
-       KFS_PENTRY(spawn)
        KFS_PENTRY(mproctests)
-       KFS_PENTRY(draw_nanwan)
        KFS_PENTRY(hello)
        KFS_PENTRY(mhello)
-       KFS_PENTRY(manycore_test)
        KFS_PENTRY(pthread_test)
        KFS_PENTRY(idle)
        KFS_PENTRY(fillmeup)
+       KFS_PENTRY(msr_get_cores)
        KFS_FENTRY(kfs_test_txt)
        KFS_FENTRY(hello_txt)
 #endif
diff --git a/tests/msr_get_cores.c b/tests/msr_get_cores.c
new file mode 100644 (file)
index 0000000..569d650
--- /dev/null
@@ -0,0 +1,108 @@
+/* tests/msr_get_cores.c
+ *
+ * This measures the time it takes to request and receive the max_vcores() in
+ * the system.  The clock starts before vcore_request(), which includes the time
+ * it takes to allocate transition stacks and TLS.  The clock stops after
+ * barriering in vcore_entry().  Alternatively, you can make vcore0 pop back out
+ * and measure there (comment some things out in vcore entry()). */
+
+#include <parlib.h>
+#include <ros/mman.h>
+#include <ros/resource.h>
+#include <ros/procdata.h>
+#include <ros/notification.h>
+#include <ros/bcq.h>
+#include <arch/arch.h>
+#include <rstdio.h>
+#include <vcore.h>
+#include <mcs.h>
+#include <timing.h>
+#include <rassert.h>
+
+mcs_barrier_t b;
+
+void *core0_tls = 0;
+uint64_t begin = 0, end = 0;
+
+int main(int argc, char** argv)
+{
+       uint32_t vcoreid = vcore_id();
+
+       mcs_barrier_init(&b, max_vcores());
+
+/* begin: stuff userspace needs to do before switching to multi-mode */
+       if (vcore_init())
+               printf("vcore_init() failed, we're fucked!\n");
+       /* tell the kernel where and how we want to receive notifications */
+       struct notif_method *nm;
+       for (int i = 0; i < MAX_NR_NOTIF; i++) {
+               nm = &__procdata.notif_methods[i];
+               nm->flags |= NOTIF_WANTED | NOTIF_MSG | NOTIF_IPI;
+               nm->vcoreid = i % 2; // vcore0 or 1, keepin' it fresh.
+       }
+       /* Need to save this somewhere that you can find it again when restarting
+        * core0 */
+       core0_tls = get_tls_desc(0);
+       /* Need to save our floating point state somewhere (like in the
+        * user_thread_tcb so it can be restarted too */
+       /* don't forget to enable notifs on vcore0 at some point */
+       struct preempt_data *vcpd;
+       vcpd = &__procdata.vcore_preempt_data[0];
+       vcpd->notif_enabled = TRUE;
+/* end: stuff userspace needs to do before switching to multi-mode */
+
+       /* should do this in the vcore entry */
+       begin = read_tsc();
+       vcore_request(max_vcores());
+       mcs_barrier_wait(&b, vcoreid);
+       end = read_tsc();
+
+       printf("Took %llu usec (%llu nsec) to receive %d cores (restarting).\n",
+              udiff(begin, end), ndiff(begin, end), max_vcores());
+
+       return 0;
+}
+
+void vcore_entry(void)
+{
+       uint32_t vcoreid = vcore_id(); // this will still be slow
+
+       /* try testing immediately.  remove from here to the while(1) if you want to
+        * count vcore0 restarting. */
+       mcs_barrier_wait(&b, vcoreid);
+       if (vcoreid == 0) {
+               end = read_tsc();
+               printf("Took %llu usec (%llu nsec) to receive %d cores (no restart).\n",
+                      udiff(begin, end), ndiff(begin, end), max_vcores());
+               exit(0);
+       }
+       while(1);
+
+/* begin: stuff userspace needs to do to handle notifications */
+
+       struct vcore *vc = &__procinfo.vcoremap[vcoreid];
+       struct preempt_data *vcpd;
+       vcpd = &__procdata.vcore_preempt_data[vcoreid];
+       
+       /* Lets try to restart vcore0's context.  Note this doesn't do anything to
+        * set the appropriate TLS.  On x86, this will involve changing the LDT
+        * entry for this vcore to point to the TCB of the new user-thread. */
+       if (vcoreid == 0) {
+               vcpd->notif_pending = 0;
+               set_tls_desc(core0_tls, 0);
+               /* Load silly state (Floating point) too */
+               pop_ros_tf(&vcpd->notif_tf, vcoreid);
+               panic("should never see me!");
+       }       
+       /* unmask notifications once you can let go of the notif_tf and it is okay
+        * to clobber the transition stack.
+        * Check Documentation/processes.txt: 4.2.4.  In real code, you should be
+        * popping the tf of whatever user process you want (get off the x-stack) */
+       vcpd->notif_enabled = TRUE;
+       
+/* end: stuff userspace needs to do to handle notifications */
+       mcs_barrier_wait(&b, vcoreid);
+       while(1);
+
+}
+
index 52f0f6d..99bfb55 100644 (file)
@@ -2,5 +2,7 @@
 #define __PARLIB_TIMING_H__
 
 void udelay(uint64_t usec);
+uint64_t udiff(uint64_t begin, uint64_t end);
+uint64_t ndiff(uint64_t begin, uint64_t end);
 
 #endif /* __PARLIB_TIMING_H__ */
index b0a84bc..0efc5f7 100644 (file)
@@ -16,3 +16,15 @@ void udelay(uint64_t usec)
        } while (now < end || (now > start && end < start));
        return;
 }
+
+/* Difference between the ticks in microseconds */
+uint64_t udiff(uint64_t begin, uint64_t end)
+{
+       return (end - begin) * 1000000 /  __procinfo.tsc_freq;
+}
+
+/* Difference between the ticks in nanoseconds */
+uint64_t ndiff(uint64_t begin, uint64_t end)
+{
+       return (end - begin) * 1000000000 /  __procinfo.tsc_freq;
+}