Split uthread code into its own source file
[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(), while vcore0 gets restarted and barriers.  You
7  * really want to restart vcore0's context so it releases the lock in
8  * vcore_request().
9  *
10  * This will measure both the hot and cold times, with the hot times not needing
11  * to have stacks mmaped and other things. */
12
13
14 #include <parlib.h>
15 #include <ros/mman.h>
16 #include <ros/resource.h>
17 #include <ros/procdata.h>
18 #include <ros/bcq.h>
19 #include <arch/arch.h>
20 #include <rstdio.h>
21 #include <vcore.h>
22 #include <mcs.h>
23 #include <timing.h>
24 #include <rassert.h>
25 #include <uthread.h>
26
27 #ifdef __sparc_v8__
28 # define udelay(x) udelay((x)/2000)
29 #endif
30
31 mcs_barrier_t b;
32
33 void *core0_tls = 0;
34 uint64_t begin = 0, end = 0;
35
36 void ghetto_vcore_entry(void);
37 struct schedule_ops ghetto_sched_ops = {
38         0, /* init, */
39         ghetto_vcore_entry,
40         0, /* thread_create, */
41         0, /* thread_runnable, */
42         0, /* thread_yield, */
43         0, /* thread_exit, */
44         0, /* preempt_pending, */
45         0, /* spawn_thread, */
46 };
47 struct schedule_ops *sched_ops = &ghetto_sched_ops;
48
49 int main(int argc, char** argv)
50 {
51         uint32_t vcoreid = vcore_id();
52         int retval = 0;
53
54         mcs_barrier_init(&b, max_vcores());
55
56 /* begin: stuff userspace needs to do before switching to multi-mode */
57         if (vcore_init())
58                 printf("vcore_init() failed, we're fucked!\n");
59         #if 0
60         /* tell the kernel where and how we want to receive notifications */
61         struct notif_method *nm;
62         for (int i = 0; i < MAX_NR_NOTIF; i++) {
63                 nm = &__procdata.notif_methods[i];
64                 nm->flags |= NOTIF_WANTED | NOTIF_MSG | NOTIF_IPI;
65                 nm->vcoreid = i % 2; // vcore0 or 1, keepin' it fresh.
66         }
67         #endif
68         /* Need to save this somewhere that you can find it again when restarting
69          * core0 */
70         core0_tls = get_tls_desc(0);
71         /* Need to save our floating point state somewhere (like in the
72          * user_thread_tcb so it can be restarted too */
73         /* don't forget to enable notifs on vcore0 at some point */
74         struct preempt_data *vcpd;
75         vcpd = &__procdata.vcore_preempt_data[0];
76         vcpd->notif_enabled = TRUE;
77 /* end: stuff userspace needs to do before switching to multi-mode */
78
79         begin = read_tsc();
80         retval = vcore_request(max_vcores());
81         if (retval)
82                 printf("Fucked!\n");
83         mcs_barrier_wait(&b, vcoreid);
84         end = read_tsc();
85
86         printf("Took %llu usec (%llu nsec) to receive %d cores (cold).\n",
87                udiff(begin, end), ndiff(begin, end), max_vcores());
88         printf("[T]:001:%llu:%llu:%d:C.\n",
89                udiff(begin, end), ndiff(begin, end), max_vcores());
90         udelay(5000000);
91         begin = read_tsc();
92         retval = vcore_request(max_vcores() - 1);
93         if (retval)
94                 printf("Fucked!\n");
95         mcs_barrier_wait(&b, vcoreid);
96         end = read_tsc();
97         printf("Took %llu usec (%llu nsec) to receive %d cores (warm).\n",
98                udiff(begin, end), ndiff(begin, end), max_vcores());
99         printf("[T]:001:%llu:%llu:%d:W.\n",
100                udiff(begin, end), ndiff(begin, end), max_vcores());
101
102         return 0;
103 }
104
105 void ghetto_vcore_entry(void)
106 {
107         uint32_t vcoreid = vcore_id();
108
109 /* begin: stuff userspace needs to do to handle notifications */
110         struct vcore *vc = &__procinfo.vcoremap[vcoreid];
111         struct preempt_data *vcpd;
112         vcpd = &__procdata.vcore_preempt_data[vcoreid];
113         
114         /* Lets try to restart vcore0's context.  Note this doesn't do anything to
115          * set the appropriate TLS.  On x86, this will involve changing the LDT
116          * entry for this vcore to point to the TCB of the new user-thread. */
117         if (vcoreid == 0) {
118                 clear_notif_pending(vcoreid);
119                 set_tls_desc(core0_tls, 0);
120                 /* Load silly state (Floating point) too */
121                 pop_ros_tf(&vcpd->notif_tf, vcoreid);
122                 panic("should never see me!");
123         }       
124 /* end: stuff userspace needs to do to handle notifications */
125
126         /* all other vcores are down here */
127         mcs_barrier_wait(&b, vcoreid);
128
129         udelay(1000000);
130         if (vcoreid == 1)
131                 printf("Proc %d's vcores are yielding\n", getpid());
132         sys_yield(0);
133
134         while(1);
135 }
136