Added thread_wait_for_count() which allows the menu to wait for all (new) threads to

exit before continuing. We need this for khu testing because we have to make sure
cleanup is done before getting the used byte count.
This commit is contained in:
Scott Haseley 2016-04-07 14:35:09 -04:00
parent 854931ea44
commit 388e6388a9
3 changed files with 46 additions and 0 deletions

View File

@ -178,5 +178,7 @@ void schedule(void);
*/
void thread_consider_migration(void);
extern unsigned thread_count;
void thread_wait_for_count(unsigned);
#endif /* _THREAD_H_ */

View File

@ -117,6 +117,7 @@ common_prog(int nargs, char **args)
{
struct proc *proc;
int result;
unsigned tc;
/* Create a process for the new program to run in. */
proc = proc_create_runprogram(args[0] /* name */);
@ -124,6 +125,8 @@ common_prog(int nargs, char **args)
return ENOMEM;
}
tc = thread_count;
result = thread_fork(args[0] /* thread name */,
proc /* new process */,
cmd_progthread /* thread function */,
@ -139,6 +142,10 @@ common_prog(int nargs, char **args)
* once you write the code for handling that.
*/
// Wait for all threads to finish cleanup, otherwise khu be a bit behind,
// especially once swapping is enabled.
thread_wait_for_count(tc);
return 0;
}

View File

@ -70,6 +70,11 @@ unsigned num_cpus;
/* Used to wait for secondary CPUs to come online. */
static struct semaphore *cpu_startup_sem;
/* Used to synchronize exit cleanup. */
unsigned thread_count = 0;
static struct spinlock thread_count_lock = SPINLOCK_INITIALIZER;
static struct wchan *thread_count_wchan;
////////////////////////////////////////////////////////////
/*
@ -425,6 +430,7 @@ thread_start_cpus(void)
kprintf("cpu0: %s\n", buf);
cpu_startup_sem = sem_create("cpu_hatch", 0);
thread_count_wchan = wchan_create("thread_count");
mainbus_start_cpus();
num_cpus = cpuarray_num(&allcpus);
@ -438,6 +444,12 @@ thread_start_cpus(void)
kprintf("%d CPUs online\n", i + 1);
}
cpu_startup_sem = NULL;
// Gross hack to deal with os/161 "idle" threads. Hardcode the thread count
// to 1 so the inc/dec properly works in thread_[fork/exit]. The one thread
// is the cpu0 boot thread (menu), which is the only thread that hasn't
// exited yet.
thread_count = 1;
}
/*
@ -536,6 +548,11 @@ thread_fork(const char *name,
*/
newthread->t_iplhigh_count++;
spinlock_acquire(&thread_count_lock);
++thread_count;
wchan_wakeall(thread_count_wchan, &thread_count_lock);
spinlock_release(&thread_count_lock);
/* Set up the switchframe so entrypoint() gets called */
switchframe_init(newthread, entrypoint, data1, data2);
@ -799,6 +816,14 @@ thread_exit(void)
/* Check the stack guard band. */
thread_checkstack(cur);
// Decrement the thread count and notify anyone interested.
if (thread_count) {
spinlock_acquire(&thread_count_lock);
--thread_count;
wchan_wakeall(thread_count_wchan, &thread_count_lock);
spinlock_release(&thread_count_lock);
}
/* Interrupts off on this processor */
splhigh();
thread_switch(S_ZOMBIE, NULL, NULL);
@ -1196,3 +1221,15 @@ interprocessor_interrupt(void)
curcpu->c_ipi_pending = 0;
spinlock_release(&curcpu->c_ipi_lock);
}
/*
* Wait for the thread count to equal tc.
*/
void thread_wait_for_count(unsigned tc)
{
spinlock_acquire(&thread_count_lock);
while (thread_count != tc) {
wchan_sleep(thread_count_wchan, &thread_count_lock);
}
spinlock_release(&thread_count_lock);
}