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:
parent
854931ea44
commit
388e6388a9
@ -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_ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user