/* Thread0 scheduler ops (for processes that haven't linked in a full 2LS) */ static void thread0_sched_entry(void) { if (current_uthread) run_current_uthread(); else run_uthread(thread0_uth); }
void ghetto_vcore_entry(void) { uint32_t vcoreid = vcore_id(); static bool first_time = TRUE; temp = 0xcafebabe; /* vcore_context test (don't need to do this anywhere) */ assert(in_vcore_context()); /* old logic was moved to parlib code */ if (current_uthread) { assert(vcoreid == 0); run_current_uthread(); } /* 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) */ enable_notifs(vcoreid); /* end: stuff userspace needs to do to handle notifications */ printf("Hello from vcore_entry in vcore %d with temp addr %p and temp %p\n", vcoreid, &temp, temp); vcore_request(1); //mcs_barrier_wait(&b,vcore_id()); udelay(vcoreid * 10000000); //exit(0); while(1); }
void ghetto_vcore_entry(void) { if (vcore_id() == 0) run_current_uthread(); while (1) sys_halt_core(0); }
/* Called from vcore entry. Options usually include restarting whoever was * running there before or running a new thread. Events are handled out of * event.c (table of function pointers, stuff like that). */ static void __attribute__((noreturn)) pth_sched_entry(void) { uint32_t vcoreid = vcore_id(); if (current_uthread) { /* Prep the pthread to run any pending posix signal handlers registered * via pthread_kill once it is restored. */ __pthread_prep_for_pending_posix_signals((pthread_t)current_uthread); /* Run the thread itself */ run_current_uthread(); assert(0); } /* no one currently running, so lets get someone from the ready queue */ struct pthread_tcb *new_thread = NULL; /* Try to get a thread. If we get one, we'll break out and run it. If not, * we'll try to yield. vcore_yield() might return, if we lost a race and * had a new event come in, one that may make us able to get a new_thread */ do { handle_events(vcoreid); __check_preempt_pending(vcoreid); mcs_pdr_lock(&queue_lock); new_thread = TAILQ_FIRST(&ready_queue); if (new_thread) { TAILQ_REMOVE(&ready_queue, new_thread, tq_next); TAILQ_INSERT_TAIL(&active_queue, new_thread, tq_next); threads_active++; threads_ready--; mcs_pdr_unlock(&queue_lock); /* If you see what looks like the same uthread running in multiple * places, your list might be jacked up. Turn this on. */ printd("[P] got uthread %08p on vc %d state %08p flags %08p\n", new_thread, vcoreid, ((struct uthread*)new_thread)->state, ((struct uthread*)new_thread)->flags); break; } mcs_pdr_unlock(&queue_lock); /* no new thread, try to yield */ printd("[P] No threads, vcore %d is yielding\n", vcore_id()); /* TODO: you can imagine having something smarter here, like spin for a * bit before yielding (or not at all if you want to be greedy). */ if (can_adjust_vcores) vcore_yield(FALSE); if (!parlib_wants_to_be_mcp) sys_yield(FALSE); } while (1); assert(new_thread->state == PTH_RUNNABLE); /* Prep the pthread to run any pending posix signal handlers registered * via pthread_kill once it is restored. */ __pthread_prep_for_pending_posix_signals(new_thread); /* Run the thread itself */ run_uthread((struct uthread*)new_thread); assert(0); }
void ghetto_vcore_entry(void) { uint32_t vcoreid = vcore_id(); static bool first_time = TRUE; temp = 0xcafebabe; /* vcore_context test (don't need to do this anywhere) */ assert(in_vcore_context()); /* old logic was moved to parlib code */ if (current_uthread) { assert(vcoreid == 0); run_current_uthread(); } /* unmask notifications once you can let go of the uthread_ctx 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) */ enable_notifs(vcoreid); /* end: stuff userspace needs to do to handle notifications */ printf("Hello from vcore_entry in vcore %d with temp addr %p and temp %p\n", vcoreid, &temp, temp); #if 0 /* Test sys change vcore. Need to manually preempt the pcore vcore4 is * mapped to from the monitor */ udelay(20000000); if (vcoreid == 1) { disable_notifs(vcoreid); printf("VC1 changing to VC4\n"); sys_change_vcore(4, TRUE); /* try both of these manually */ //sys_change_vcore(4, FALSE); /* try both of these manually */ printf("VC1 returned\n"); } udelay(10000000); #endif vcore_request(1); //mcs_barrier_wait(&b,vcore_id()); udelay(vcoreid * 10000000); //exit(0); while(1); }
/* Thread0 scheduler ops (for processes that haven't linked in a full 2LS) */ static void thread0_sched_entry(void) { /* TODO: support signal handling whenever we run a uthread */ if (current_uthread) { uthread_prep_pending_signals(current_uthread); run_current_uthread(); assert(0); } while (1) { if (!thread0_info.is_blocked) { uthread_prep_pending_signals(thread0_uth); run_uthread(thread0_uth); assert(0); } sys_yield(FALSE); handle_events(0); } }
/* Called from vcore entry. Options usually include restarting whoever was * running there before or running a new thread. Events are handled out of * event.c (table of function pointers, stuff like that). */ void __attribute__((noreturn)) pth_sched_entry(void) { uint32_t vcoreid = vcore_id(); if (current_uthread) { run_current_uthread(); assert(0); } /* no one currently running, so lets get someone from the ready queue */ struct pthread_tcb *new_thread = NULL; struct mcs_lock_qnode local_qn = {0}; /* For now, let's spin and handle events til we get a thread to run. This * will help catch races, instead of only having one core ever run a thread * (if there is just one, etc). Also, we don't need the EVENT_IPIs for this * to work (since we poll handle_events() */ while (!new_thread) { handle_events(vcoreid); mcs_lock_notifsafe(&queue_lock, &local_qn); new_thread = TAILQ_FIRST(&ready_queue); if (new_thread) { TAILQ_REMOVE(&ready_queue, new_thread, next); TAILQ_INSERT_TAIL(&active_queue, new_thread, next); threads_active++; threads_ready--; } mcs_unlock_notifsafe(&queue_lock, &local_qn); } /* Instead of yielding, you could spin, turn off the core, set an alarm, * whatever. You want some logic to decide this. Uthread code wil have * helpers for this (like how we provide run_uthread()) */ if (!new_thread) { /* Note, we currently don't get here (due to the while loop) */ printd("[P] No threads, vcore %d is yielding\n", vcore_id()); /* Not actually yielding - just spin for now, so we can get syscall * unblocking events */ vcore_idle(); //sys_yield(0); assert(0); } assert(((struct uthread*)new_thread)->state != UT_RUNNING); run_uthread((struct uthread*)new_thread); assert(0); }
void ghetto_vcore_entry(void) { uint32_t vcoreid = vcore_id(); static bool first_time = TRUE; /* begin: stuff userspace needs to do to handle notifications */ /* Restart vcore0's context. */ if (vcoreid == 0) { run_current_uthread(); panic("should never see me!"); } /* unmask notifications once you can let go of the uthread_ctx 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) */ struct preempt_data *vcpd; vcpd = &__procdata.vcore_preempt_data[vcoreid]; vcpd->notif_disabled = FALSE; /* end: stuff userspace needs to do to handle notifications */ /* if you have other vcores, they'll just chill here */ while(1); }