blob: 6784dd20c75e8a982b2d5730cd9d38572d45995c [file] [log] [blame] [edit]
/* 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(), while vcore0 gets restarted and barriers. You
* really want to restart vcore0's context so it releases the lock in
* vcore_request().
*
* This will measure both the hot and cold times, with the hot times not needing
* to have stacks mmaped and other things. */
#include <parlib.h>
#include <ros/mman.h>
#include <ros/resource.h>
#include <ros/procdata.h>
#include <ros/bcq.h>
#include <arch/arch.h>
#include <stdio.h>
#include <vcore.h>
#include <mcs.h>
#include <timing.h>
#include <rassert.h>
#include <uthread.h>
#include <event.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();
int retval = 0;
mcs_barrier_init(&b, max_vcores());
/* begin: stuff userspace needs to do before switching to multi-mode */
vcore_init();
#if 0
/* 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.
}
#endif
/* 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 */
/* end: stuff userspace needs to do before switching to multi-mode */
begin = read_tsc();
retval = vcore_request(max_vcores());
if (retval)
printf("Fucked!\n");
mcs_barrier_wait(&b, vcoreid);
end = read_tsc();
printf("Took %llu usec (%llu nsec) to receive %d cores (cold).\n",
udiff(begin, end), ndiff(begin, end), max_vcores());
printf("[T]:001:%llu:%llu:%d:C.\n",
udiff(begin, end), ndiff(begin, end), max_vcores());
udelay(5000000);
begin = read_tsc();
retval = vcore_request(max_vcores() - 1);
if (retval)
printf("Fucked!\n");
mcs_barrier_wait(&b, vcoreid);
end = read_tsc();
printf("Took %llu usec (%llu nsec) to receive %d cores (warm).\n",
udiff(begin, end), ndiff(begin, end), max_vcores());
printf("[T]:001:%llu:%llu:%d:W.\n",
udiff(begin, end), ndiff(begin, end), max_vcores());
return 0;
}
void vcore_entry(void)
{
uint32_t vcoreid = vcore_id();
/* 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) {
handle_events(vcoreid);
set_tls_desc(core0_tls, 0);
assert(__vcoreid == 0); /* in case anyone uses this */
/* Load silly state (Floating point) too */
pop_user_ctx(&vcpd->uthread_ctx, vcoreid);
panic("should never see me!");
}
/* end: stuff userspace needs to do to handle notifications */
/* all other vcores are down here */
mcs_barrier_wait(&b, vcoreid);
udelay(1000000);
if (vcoreid == 1)
printf("Proc %d's vcores are yielding\n", getpid());
sys_yield(0);
while(1);
}