Fix thread reference counting

This commit is contained in:
Ali Mashtizadeh 2015-01-22 09:46:48 -08:00
parent 63c04f37df
commit fa1b3c9ed2
3 changed files with 115 additions and 26 deletions

View File

@ -31,6 +31,7 @@ typedef struct Thread {
uintptr_t kstack; uintptr_t kstack;
uintptr_t ustack; uintptr_t ustack;
uint64_t tid; uint64_t tid;
uint64_t refCount;
// Process // Process
struct Process *proc; struct Process *proc;
TAILQ_ENTRY(Thread) threadList; TAILQ_ENTRY(Thread) threadList;
@ -55,6 +56,7 @@ typedef struct Process {
AS *space; AS *space;
uintptr_t ustackNext; // Next user stack uintptr_t ustackNext; // Next user stack
TAILQ_ENTRY(Process) processList; TAILQ_ENTRY(Process) processList;
uint64_t refCount;
// Process // Process
Process *parent; Process *parent;
TAILQ_ENTRY(Process) siblingList; TAILQ_ENTRY(Process) siblingList;

View File

@ -28,7 +28,11 @@ uint64_t
Syscall_GetPID() Syscall_GetPID()
{ {
Thread *cur = Sched_Current(); Thread *cur = Sched_Current();
return cur->tid; uint64_t pid = cur->proc->pid;
Thread_Release(cur);
return pid;
} }
void void
@ -37,6 +41,7 @@ Syscall_Exit(uint64_t status)
Thread *cur = Sched_Current(); Thread *cur = Sched_Current();
Sched_SetZombie(cur); Sched_SetZombie(cur);
Thread_Release(cur);
Sched_Scheduler(); Sched_Scheduler();
// Should not return // Should not return
@ -121,6 +126,7 @@ Syscall_MMap(uint64_t addr, uint64_t len, uint64_t prot)
bool status; bool status;
status = PMap_AllocMap(cur->space, addr, pgs, PTE_W); status = PMap_AllocMap(cur->space, addr, pgs, PTE_W);
Thread_Release(cur);
if (!status) { if (!status) {
// XXX: Need to unmap PMap_Unmap(cur->space, addr, pgs); // XXX: Need to unmap PMap_Unmap(cur->space, addr, pgs);
return 0; return 0;
@ -141,6 +147,7 @@ Syscall_MUnmap(uint64_t addr, uint64_t len)
} }
PMap_Unmap(cur->space, addr, len /= PGSIZE); PMap_Unmap(cur->space, addr, len /= PGSIZE);
Thread_Release(cur);
return 0; return 0;
} }
@ -156,37 +163,55 @@ Syscall_MProtect(uint64_t addr, uint64_t len, uint64_t prot)
uint64_t uint64_t
Syscall_Read(uint64_t fd, uint64_t addr, uint64_t off, uint64_t length) Syscall_Read(uint64_t fd, uint64_t addr, uint64_t off, uint64_t length)
{ {
uint64_t status;
Thread *cur = Sched_Current(); Thread *cur = Sched_Current();
Handle *handle = Handle_Lookup(cur->proc, fd); Handle *handle = Handle_Lookup(cur->proc, fd);
if (handle == NULL) if (handle == NULL) {
return -EBADF; status = -EBADF;
} else {
status = (handle->read)(handle, (void *)addr, off, length);
}
return (handle->read)(handle, (void *)addr, off, length); Thread_Release(cur);
return status;
} }
uint64_t uint64_t
Syscall_Write(uint64_t fd, uint64_t addr, uint64_t off, uint64_t length) Syscall_Write(uint64_t fd, uint64_t addr, uint64_t off, uint64_t length)
{ {
uint64_t status;
Thread *cur = Sched_Current(); Thread *cur = Sched_Current();
Handle *handle = Handle_Lookup(cur->proc, fd); Handle *handle = Handle_Lookup(cur->proc, fd);
if (handle == NULL) if (handle == NULL) {
return -EBADF; status = -EBADF;
} else {
status = (handle->write)(handle, (void *)addr, off, length);
}
return (handle->write)(handle, (void *)addr, off, length);; Thread_Release(cur);
return status;
} }
uint64_t uint64_t
Syscall_Flush(uint64_t fd) Syscall_Flush(uint64_t fd)
{ {
uint64_t status;
Thread *cur = Sched_Current(); Thread *cur = Sched_Current();
Handle *handle = Handle_Lookup(cur->proc, fd); Handle *handle = Handle_Lookup(cur->proc, fd);
if (handle == NULL) if (handle == NULL) {
return -EBADF; status = -EBADF;
} else {
status = (handle->flush)(handle);
}
return (handle->flush)(handle); Thread_Release(cur);
return status;
} }
// XXX: Cleanup // XXX: Cleanup
@ -195,41 +220,57 @@ Handle *Console_OpenHandle();
uint64_t uint64_t
Syscall_Open(uint64_t user_path, uint64_t flags) Syscall_Open(uint64_t user_path, uint64_t flags)
{ {
uint64_t handleNo;
Thread *cur = Sched_Current(); Thread *cur = Sched_Current();
int status; int status;
char path[256]; char path[256];
status = CopyStrIn(user_path, &path, sizeof(path)); status = CopyStrIn(user_path, &path, sizeof(path));
if (status != 0) if (status != 0) {
Thread_Release(cur);
return status; return status;
}
if (strncmp("/dev/", path, 5) == 0) { if (strncmp("/dev/", path, 5) == 0) {
if (strcmp("/dev/console", path) == 0) { if (strcmp("/dev/console", path) == 0) {
Handle *handle = Console_OpenHandle(); Handle *handle = Console_OpenHandle();
return Handle_Add(cur->proc, handle); handleNo = Handle_Add(cur->proc, handle);
Thread_Release(cur);
return handleNo;
} }
Thread_Release(cur);
return -ENOENT; return -ENOENT;
} }
Handle *handle; Handle *handle;
status = VFSUIO_Open(path, &handle); status = VFSUIO_Open(path, &handle);
if (status != 0) if (status != 0) {
Thread_Release(cur);
return status; return status;
}
return Handle_Add(cur->proc, handle); handleNo = Handle_Add(cur->proc, handle);
Thread_Release(cur);
return handleNo;
} }
uint64_t uint64_t
Syscall_Close(uint64_t fd) Syscall_Close(uint64_t fd)
{ {
uint64_t status;
Thread *cur = Sched_Current(); Thread *cur = Sched_Current();
Handle *handle = Handle_Lookup(cur->proc, fd); Handle *handle = Handle_Lookup(cur->proc, fd);
if (handle == NULL) if (handle == NULL) {
return -EBADF; status = -EBADF;
} else {
status = (handle->close)(handle);
}
return (handle->close)(handle); Thread_Release(cur);
return status;
} }
uint64_t uint64_t
@ -267,23 +308,35 @@ Syscall_ReadDir(uint64_t fd, char *user_buf, size_t len, uintptr_t user_off)
Handle *handle = Handle_Lookup(cur->proc, fd); Handle *handle = Handle_Lookup(cur->proc, fd);
uint64_t offset; uint64_t offset;
if (handle == NULL) if (handle == NULL) {
Thread_Release(cur);
return -EBADF; return -EBADF;
}
status = CopyIn(user_off, &offset, sizeof(offset)); status = CopyIn(user_off, &offset, sizeof(offset));
if (status != 0) if (status != 0) {
Thread_Release(cur);
return status; return status;
}
if (handle->type != HANDLE_TYPE_FILE) if (handle->type != HANDLE_TYPE_FILE) {
Thread_Release(cur);
return -ENOTDIR; return -ENOTDIR;
}
rstatus = VFS_ReadDir(handle->vnode, user_buf, len, &offset); rstatus = VFS_ReadDir(handle->vnode, user_buf, len, &offset);
if (rstatus < 0) if (rstatus < 0) {
Thread_Release(cur);
return rstatus; return rstatus;
}
status = CopyOut(&offset, user_off, sizeof(offset)); status = CopyOut(&offset, user_off, sizeof(offset));
if (status != 0) if (status != 0) {
Thread_Release(cur);
return status; return status;
}
Thread_Release(cur);
return rstatus; return rstatus;
} }
@ -294,6 +347,8 @@ Syscall_ThreadCreate(uint64_t rip, uint64_t arg)
uint64_t threadId; uint64_t threadId;
Thread *curThread = Sched_Current(); Thread *curThread = Sched_Current();
Thread *newThread = Thread_UThreadCreate(curThread, rip, arg); Thread *newThread = Thread_UThreadCreate(curThread, rip, arg);
Thread_Release(curThread);
if (newThread == NULL) { if (newThread == NULL) {
return -1; return -1;
} }
@ -314,6 +369,7 @@ Syscall_ThreadExit(uint64_t status)
Sched_SetZombie(cur); Sched_SetZombie(cur);
Semaphore_Release(&cur->proc->zombieSemaphore); Semaphore_Release(&cur->proc->zombieSemaphore);
Thread_Release(cur);
Sched_Scheduler(); Sched_Scheduler();
// Should not return // Should not return
@ -328,6 +384,7 @@ ThreadWakeupHelper(void *arg)
Sched_SetRunnable(thr); Sched_SetRunnable(thr);
KTimer_Release(thr->timerEvt); KTimer_Release(thr->timerEvt);
thr->timerEvt = NULL; thr->timerEvt = NULL;
Thread_Release(thr);
} }
uint64_t uint64_t
@ -345,6 +402,8 @@ Syscall_ThreadSleep(uint64_t time)
} }
Sched_Scheduler(); Sched_Scheduler();
Thread_Release(cur);
return 0; return 0;
} }
@ -366,8 +425,10 @@ Syscall_ThreadWait(uint64_t tid)
while (1) { while (1) {
Semaphore_Acquire(&cur->proc->zombieSemaphore); Semaphore_Acquire(&cur->proc->zombieSemaphore);
status = Thread_Wait(cur, tid); status = Thread_Wait(cur, tid);
if (status != 0) if (status != 0) {
Thread_Release(cur);
return status; return status;
}
Semaphore_Release(&cur->proc->zombieSemaphore); Semaphore_Release(&cur->proc->zombieSemaphore);
Sched_Scheduler(); Sched_Scheduler();
} }

View File

@ -73,6 +73,7 @@ Process_Create()
proc->pid = nextProcessID++; proc->pid = nextProcessID++;
proc->threads = 0; proc->threads = 0;
proc->refCount = 1;
TAILQ_INIT(&proc->threadList); TAILQ_INIT(&proc->threadList);
proc->space = PMap_NewAS(); proc->space = PMap_NewAS();
@ -105,11 +106,17 @@ Process_Lookup(uint64_t pid)
void void
Process_Retain(Process *proc) Process_Retain(Process *proc)
{ {
ASSERT(proc->refCount != 0);
__sync_fetch_and_add(&proc->refCount, 1);
} }
void void
Process_Release(Process *proc) Process_Release(Process *proc)
{ {
ASSERT(proc->refCount != 0);
if (__sync_fetch_and_sub(&proc->refCount, 1) == 1) {
Process_Destroy(proc);
}
} }
uint64_t uint64_t
@ -147,6 +154,7 @@ Thread_Create(Process *proc)
thr->ustack = proc->ustackNext; thr->ustack = proc->ustackNext;
proc->ustackNext += MEM_USERSPACE_STKLEN; proc->ustackNext += MEM_USERSPACE_STKLEN;
Process_Retain(proc);
} }
if ((proc != NULL) && (proc->space != NULL)) { if ((proc != NULL) && (proc->space != NULL)) {
@ -163,6 +171,7 @@ Thread_Create(Process *proc)
thr->schedState = SCHED_STATE_NULL; thr->schedState = SCHED_STATE_NULL;
thr->timerEvt = NULL; thr->timerEvt = NULL;
thr->refCount = 1;
Thread_InitArch(thr); Thread_InitArch(thr);
// Initialize queue // Initialize queue
@ -202,6 +211,7 @@ Thread_UThreadCreate(Thread *oldThr, uint64_t rip, uint64_t arg)
thr->space = oldThr->space; thr->space = oldThr->space;
thr->schedState = SCHED_STATE_NULL; thr->schedState = SCHED_STATE_NULL;
thr->refCount = 1;
thr->ustack = proc->ustackNext; thr->ustack = proc->ustackNext;
proc->ustackNext += MEM_USERSPACE_STKLEN; proc->ustackNext += MEM_USERSPACE_STKLEN;
@ -242,11 +252,17 @@ Thread_Lookup(Process *proc, uint64_t tid)
void void
Thread_Retain(Thread *thr) Thread_Retain(Thread *thr)
{ {
ASSERT(thr->refCount != 0);
__sync_fetch_and_add(&thr->refCount, 1);
} }
void void
Thread_Release(Thread *thr) Thread_Release(Thread *thr)
{ {
ASSERT(thr->refCount != 0);
if (__sync_fetch_and_sub(&thr->refCount, 1) == 1) {
Thread_Destroy(thr);
}
} }
uint64_t uint64_t
@ -265,7 +281,7 @@ Thread_Wait(Thread *thr, uint64_t tid)
TAILQ_REMOVE(&thr->proc->zombieQueue, t, schedQueue); TAILQ_REMOVE(&thr->proc->zombieQueue, t, schedQueue);
status = t->exitValue; status = t->exitValue;
Thread_Destroy(t); Thread_Release(t);
return status; return status;
} }
@ -273,7 +289,7 @@ Thread_Wait(Thread *thr, uint64_t tid)
if (t->tid == tid) { if (t->tid == tid) {
TAILQ_REMOVE(&thr->proc->zombieQueue, t, schedQueue); TAILQ_REMOVE(&thr->proc->zombieQueue, t, schedQueue);
status = t->exitValue; status = t->exitValue;
Thread_Destroy(t); Thread_Release(t);
return status; return status;
} }
} }
@ -288,7 +304,14 @@ Thread_Wait(Thread *thr, uint64_t tid)
Thread * Thread *
Sched_Current() Sched_Current()
{ {
return curProc; Spinlock_Lock(&schedLock);
Thread *thr = curProc;
Thread_Retain(thr);
Spinlock_Unlock(&schedLock);
return thr;
} }
void void
@ -404,6 +427,7 @@ Process_Dump(Process *proc)
kprintf("pid %llu\n", proc->pid); kprintf("pid %llu\n", proc->pid);
kprintf("space %016llx\n", proc->space); kprintf("space %016llx\n", proc->space);
kprintf("threads %llu\n", proc->threads); kprintf("threads %llu\n", proc->threads);
kprintf("refCount %d\n", proc->refCount);
kprintf("nextFD %llu\n", proc->nextFD); kprintf("nextFD %llu\n", proc->nextFD);
} }
@ -414,6 +438,7 @@ Thread_Dump(Thread *thr)
kprintf("space %016llx\n", thr->space); kprintf("space %016llx\n", thr->space);
kprintf("kstack %016llx\n", thr->kstack); kprintf("kstack %016llx\n", thr->kstack);
kprintf("tid %llu\n", thr->tid); kprintf("tid %llu\n", thr->tid);
kprintf("refCount %d\n", thr->refCount);
kprintf("state %d\n", thr->schedState); kprintf("state %d\n", thr->schedState);
kprintf("ctxswtch %llu\n", thr->ctxSwitches); kprintf("ctxswtch %llu\n", thr->ctxSwitches);
kprintf("utime %llu\n", thr->userTime); kprintf("utime %llu\n", thr->userTime);
@ -459,6 +484,7 @@ Debug_Processes(int argc, const char *argv[])
TAILQ_FOREACH(proc, &processList, processList) TAILQ_FOREACH(proc, &processList, processList)
{ {
kprintf("Process: %d(%016llx)\n", proc->pid, proc); kprintf("Process: %d(%016llx)\n", proc->pid, proc);
Process_Dump(proc);
} }
//Spinlock_Unlock(&threadLock); //Spinlock_Unlock(&threadLock);