Test app to measure vcore_request()
[akaros.git] / tests / msr_get_cores.c
1 /* tests/msr_get_cores.c
2  *
3  * This measures the time it takes to request and receive the max_vcores() in
4  * the system.  The clock starts before vcore_request(), which includes the time
5  * it takes to allocate transition stacks and TLS.  The clock stops after
6  * barriering in vcore_entry().  Alternatively, you can make vcore0 pop back out
7  * and measure there (comment some things out in vcore entry()). */
8
9 #include <parlib.h>
10 #include <ros/mman.h>
11 #include <ros/resource.h>
12 #include <ros/procdata.h>
13 #include <ros/notification.h>
14 #include <ros/bcq.h>
15 #include <arch/arch.h>
16 #include <rstdio.h>
17 #include <vcore.h>
18 #include <mcs.h>
19 #include <timing.h>
20 #include <rassert.h>
21
22 mcs_barrier_t b;
23
24 void *core0_tls = 0;
25 uint64_t begin = 0, end = 0;
26
27 int main(int argc, char** argv)
28 {
29         uint32_t vcoreid = vcore_id();
30
31         mcs_barrier_init(&b, max_vcores());
32
33 /* begin: stuff userspace needs to do before switching to multi-mode */
34         if (vcore_init())
35                 printf("vcore_init() failed, we're fucked!\n");
36         /* tell the kernel where and how we want to receive notifications */
37         struct notif_method *nm;
38         for (int i = 0; i < MAX_NR_NOTIF; i++) {
39                 nm = &__procdata.notif_methods[i];
40                 nm->flags |= NOTIF_WANTED | NOTIF_MSG | NOTIF_IPI;
41                 nm->vcoreid = i % 2; // vcore0 or 1, keepin' it fresh.
42         }
43         /* Need to save this somewhere that you can find it again when restarting
44          * core0 */
45         core0_tls = get_tls_desc(0);
46         /* Need to save our floating point state somewhere (like in the
47          * user_thread_tcb so it can be restarted too */
48         /* don't forget to enable notifs on vcore0 at some point */
49         struct preempt_data *vcpd;
50         vcpd = &__procdata.vcore_preempt_data[0];
51         vcpd->notif_enabled = TRUE;
52 /* end: stuff userspace needs to do before switching to multi-mode */
53
54         /* should do this in the vcore entry */
55         begin = read_tsc();
56         vcore_request(max_vcores());
57         mcs_barrier_wait(&b, vcoreid);
58         end = read_tsc();
59
60         printf("Took %llu usec (%llu nsec) to receive %d cores (restarting).\n",
61                udiff(begin, end), ndiff(begin, end), max_vcores());
62
63         return 0;
64 }
65
66 void vcore_entry(void)
67 {
68         uint32_t vcoreid = vcore_id(); // this will still be slow
69
70         /* try testing immediately.  remove from here to the while(1) if you want to
71          * count vcore0 restarting. */
72         mcs_barrier_wait(&b, vcoreid);
73         if (vcoreid == 0) {
74                 end = read_tsc();
75                 printf("Took %llu usec (%llu nsec) to receive %d cores (no restart).\n",
76                        udiff(begin, end), ndiff(begin, end), max_vcores());
77                 exit(0);
78         }
79         while(1);
80
81 /* begin: stuff userspace needs to do to handle notifications */
82
83         struct vcore *vc = &__procinfo.vcoremap[vcoreid];
84         struct preempt_data *vcpd;
85         vcpd = &__procdata.vcore_preempt_data[vcoreid];
86         
87         /* Lets try to restart vcore0's context.  Note this doesn't do anything to
88          * set the appropriate TLS.  On x86, this will involve changing the LDT
89          * entry for this vcore to point to the TCB of the new user-thread. */
90         if (vcoreid == 0) {
91                 vcpd->notif_pending = 0;
92                 set_tls_desc(core0_tls, 0);
93                 /* Load silly state (Floating point) too */
94                 pop_ros_tf(&vcpd->notif_tf, vcoreid);
95                 panic("should never see me!");
96         }       
97         /* unmask notifications once you can let go of the notif_tf and it is okay
98          * to clobber the transition stack.
99          * Check Documentation/processes.txt: 4.2.4.  In real code, you should be
100          * popping the tf of whatever user process you want (get off the x-stack) */
101         vcpd->notif_enabled = TRUE;
102         
103 /* end: stuff userspace needs to do to handle notifications */
104         mcs_barrier_wait(&b, vcoreid);
105         while(1);
106
107 }
108