Implemented OSThreadExit and a nonblocking OSThreadWait

This commit is contained in:
Ali Mashtizadeh 2015-01-16 19:41:27 -08:00
parent db7bb93d56
commit 1160570250
3 changed files with 61 additions and 4 deletions

View File

@ -31,6 +31,7 @@ typedef struct Thread {
int schedState;
TAILQ_ENTRY(Thread) schedQueue;
TimerEvent *timerEvt; // Timer event for wakeups
uintptr_t exitValue;
// Statistics
uint64_t ctxSwitches;
uint64_t userTime;
@ -48,6 +49,7 @@ typedef struct Process {
TAILQ_ENTRY(Process) processList;
// Threads
uint64_t threads;
TAILQ_HEAD(ZombieQueueHead, Thread) zombieQueue;
// Handles
uint64_t nextFD;
TAILQ_HEAD(HandleQHead, Handle) handles[PROCESS_HANDLE_SLOTS];
@ -64,6 +66,7 @@ void Thread_SetRunnable(Thread *thr);
void Thread_SetWaiting(Thread *thr);
void Thread_SetZombie(Thread *thr);
void Thread_Destroy(Thread *thr);
uint64_t Thread_Wait(Thread *thr, uint64_t tid);
void Thread_Switch(Thread *oldthr, Thread *newthr);
void Thread_Scheduler();
void Thread_ProcDump(Process *proc);

View File

@ -305,6 +305,9 @@ Syscall_ThreadExit(uint64_t status)
{
Thread *cur = Thread_Current();
// Encode this like POSIX
cur->exitValue = status;
Thread_SetZombie(cur);
Thread_Scheduler();
@ -343,9 +346,9 @@ Syscall_ThreadSleep(uint64_t time)
uint64_t
Syscall_ThreadWait(uint64_t tid)
{
// XXX: Support waiting
Thread *cur = Thread_Current();
return 0;
return Thread_Wait(cur, tid);
}
uint64_t

View File

@ -121,6 +121,7 @@ Thread_CreateProcess()
proc->pid = nextProcessID++;
proc->threads = 0;
TAILQ_INIT(&proc->zombieQueue);
proc->space = PMap_NewAS();
if (proc->space == NULL) {
@ -219,7 +220,12 @@ Thread_SetZombie(Thread *thr)
Spinlock_Lock(&threadLock);
thr->schedState = SCHED_STATE_ZOMBIE;
// XXX: Add to wait queue
if (thr->proc) {
TAILQ_INSERT_TAIL(&thr->proc->zombieQueue, thr, schedQueue);
kprintf("ZOMBIEQUEUE\n");
} else {
kprintf("ERROR: Thread not associated with process and no zombie queue!\n");
}
Spinlock_Unlock(&threadLock);
}
@ -229,11 +235,52 @@ Thread_Destroy(Thread *thr)
{
// Remove from queue
// Free userspace stack
if (thr->proc) {
thr->proc->threads--;
}
// Free AS
PAlloc_Release((void *)thr->kstack);
Slab_Free(&threadSlab, thr);
}
uint64_t
Thread_Wait(Thread *thr, uint64_t tid)
{
Thread *t;
uint64_t status;
ASSERT(thr->proc != NULL);
Thread_Dump(thr);
if (tid == 0) {
t = TAILQ_FIRST(&thr->proc->zombieQueue);
if (!t) {
kprintf("EMPTY %llx\n", t);
return 0;
}
TAILQ_REMOVE(&thr->proc->zombieQueue, t, schedQueue);
status = t->exitValue;
Thread_Destroy(t);
return status;
}
TAILQ_FOREACH(t, &thr->proc->zombieQueue, schedQueue) {
if (t->tid == tid) {
TAILQ_REMOVE(&thr->proc->zombieQueue, t, schedQueue);
status = t->exitValue;
Thread_Destroy(t);
return status;
}
}
return 0;
}
void
Thread_Switch(Thread *oldthr, Thread *newthr)
{
@ -256,8 +303,12 @@ Thread_Scheduler()
if (!next) {
/*
* There may be no other runnable processes on this core. This is a
* good opportunity to migrate threads.
* good opportunity to migrate threads. We should never hit this case
* once the OS is up and running because of the idle threads, but just
* in case we should assert that we never return to a zombie or waiting
* thread.
*/
ASSERT(curProc->schedState == SCHED_STATE_RUNNING);
Spinlock_Unlock(&threadLock);
return;
}