From 9d9f301bdd75664486352249e70b3c72494b2436 Mon Sep 17 00:00:00 2001 From: Ali Mashtizadeh Date: Wed, 14 Jan 2015 14:28:43 -0800 Subject: [PATCH] Begin refactoring to support both threads and processes --- sys/include/handle.h | 2 +- sys/include/loader.h | 8 +++ sys/include/thread.h | 39 ++++++++++---- sys/kern/handle.c | 30 +++++------ sys/kern/loader.c | 7 +-- sys/kern/syscall.c | 60 ++++++++++++++++----- sys/kern/thread.c | 124 ++++++++++++++++++++++++++++++++++++++----- 7 files changed, 216 insertions(+), 54 deletions(-) create mode 100644 sys/include/loader.h diff --git a/sys/include/handle.h b/sys/include/handle.h index 392e2d0..47a1358 100644 --- a/sys/include/handle.h +++ b/sys/include/handle.h @@ -15,7 +15,7 @@ typedef struct Handle Handle; typedef struct Handle { uint64_t fd; // FD Number uint64_t type; // Type - uint64_t threadId; // Thread ID + uint64_t processId; // Process ID VNode *vnode; // File VNode TAILQ_ENTRY(Handle) handleList; // Hash table int (*read)(Handle *, void *, uint64_t, uint64_t); // Read diff --git a/sys/include/loader.h b/sys/include/loader.h new file mode 100644 index 0000000..761deb3 --- /dev/null +++ b/sys/include/loader.h @@ -0,0 +1,8 @@ + +#ifndef __SYS_LOADER_H__ +#define __SYS_LOADER_H__ + +bool Loader_Load(Thread *thr, VNode *vn, void *buf, uint64_t len); + +#endif /* __SYS_LOADER_H__ */ + diff --git a/sys/include/thread.h b/sys/include/thread.h index 9c476a5..fa4da7b 100644 --- a/sys/include/thread.h +++ b/sys/include/thread.h @@ -17,13 +17,14 @@ typedef struct Thread Thread; #define SCHED_STATE_WAITING 3 #define SCHED_STATE_ZOMBIE 4 -#define THREAD_HANDLE_SLOTS 128 - typedef struct Thread { ThreadArch arch; AS *space; uintptr_t kstack; uint64_t tid; + // Process + struct Process *proc; + // XXX: process list // Scheduler int schedState; TAILQ_ENTRY(Thread) schedQueue; @@ -32,20 +33,38 @@ typedef struct Thread { uint64_t userTime; uint64_t kernTime; uint64_t waitTime; - // Handles - uint64_t nextFD; - TAILQ_HEAD(HandleQHead, Handle) handles[THREAD_HANDLE_SLOTS]; } Thread; +#define PROCESS_HANDLE_SLOTS 128 + +typedef struct Process { + uint64_t pid; + AS *space; + // Threads + uint64_t threads; + // Handles + uint64_t nextFD; + TAILQ_HEAD(HandleQHead, Handle) handles[PROCESS_HANDLE_SLOTS]; +} Process; + +// Thread functions void Thread_Init(); Thread *Thread_Current(); -Thread *Thread_Create(); +Process *Thread_CreateProcess(); +Thread *Thread_Create(Process *proc); Thread *Thread_KThreadCreate(void (*f)(void*), void *arg); +Thread *Thread_UThreadCreate(Thread *oldThr, uint64_t rip); void Thread_SetRunnable(Thread *thr); void Thread_SetZombie(Thread *thr); void Thread_Destroy(Thread *thr); void Thread_Switch(Thread *oldthr, Thread *newthr); void Thread_Scheduler(); +void Thread_ProcDump(Process *proc); +void Thread_Dump(Thread *thr); + +// Process functions +Process *Process_Create(); +void Process_Destroy(Process *proc); // Platform functions void Thread_InitArch(Thread *thr); @@ -54,10 +73,10 @@ void Thread_SetupUThread(Thread *thr, uint64_t rip); void Thread_SwitchArch(Thread *oldthr, Thread *newthr); // Handle Functions -void Handle_Init(Thread *thr); -uint64_t Handle_Add(Thread *thr, Handle *handle); -void Handle_Remove(Thread *thr, Handle *handle); -Handle *Handle_Lookup(Thread *thr, uint64_t fd); +void Handle_Init(Process *proc); +uint64_t Handle_Add(Process *proc, Handle *handle); +void Handle_Remove(Process *proc, Handle *handle); +Handle *Handle_Lookup(Process *proc, uint64_t fd); // CopyIn/CopyOut Functions int CopyIn(uintptr_t fromuser, void *tokernel, uintptr_t len); diff --git a/sys/kern/handle.c b/sys/kern/handle.c index 019631c..243fcfc 100644 --- a/sys/kern/handle.c +++ b/sys/kern/handle.c @@ -20,46 +20,46 @@ Handle_GlobalInit() DEFINE_SLAB(Handle, &handleSlab); void -Handle_Init(Thread *thr) +Handle_Init(Process *proc) { int i; - for (i = 0; i < THREAD_HANDLE_SLOTS; i++) { - TAILQ_INIT(&thr->handles[i]); + for (i = 0; i < PROCESS_HANDLE_SLOTS; i++) { + TAILQ_INIT(&proc->handles[i]); } } uint64_t -Handle_Add(Thread *thr, Handle *handle) +Handle_Add(Process *proc, Handle *handle) { int slot; - handle->fd = thr->nextFD; - thr->nextFD++; - handle->threadId = thr->tid; + handle->fd = proc->nextFD; + proc->nextFD++; + handle->processId = proc->pid; - slot = handle->fd % THREAD_HANDLE_SLOTS; + slot = handle->fd % PROCESS_HANDLE_SLOTS; - TAILQ_INSERT_HEAD(&thr->handles[slot], handle, handleList); + TAILQ_INSERT_HEAD(&proc->handles[slot], handle, handleList); return handle->fd; } void -Handle_Remove(Thread *thr, Handle *handle) +Handle_Remove(Process *proc, Handle *handle) { - int slot = handle->fd % THREAD_HANDLE_SLOTS; + int slot = handle->fd % PROCESS_HANDLE_SLOTS; - TAILQ_REMOVE(&thr->handles[slot], handle, handleList); + TAILQ_REMOVE(&proc->handles[slot], handle, handleList); } Handle * -Handle_Lookup(Thread *thr, uint64_t fd) +Handle_Lookup(Process *proc, uint64_t fd) { - int slot = fd % THREAD_HANDLE_SLOTS; + int slot = fd % PROCESS_HANDLE_SLOTS; Handle *handle; - TAILQ_FOREACH(handle, &thr->handles[slot], handleList) { + TAILQ_FOREACH(handle, &proc->handles[slot], handleList) { if (handle->fd == fd) return handle; } diff --git a/sys/kern/loader.c b/sys/kern/loader.c index ab76476..11a6077 100644 --- a/sys/kern/loader.c +++ b/sys/kern/loader.c @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -133,11 +134,11 @@ Loader_LoadInit() // Open stdin/out/err Handle *handle = Console_OpenHandle(); - Handle_Add(thr, handle); + Handle_Add(thr->proc, handle); handle = Console_OpenHandle(); - Handle_Add(thr, handle); + Handle_Add(thr->proc, handle); handle = Console_OpenHandle(); - Handle_Add(thr, handle); + Handle_Add(thr->proc, handle); Loader_LoadFirst(thr, init, pg, 1024); diff --git a/sys/kern/syscall.c b/sys/kern/syscall.c index 6b875fe..e87b5b2 100644 --- a/sys/kern/syscall.c +++ b/sys/kern/syscall.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,7 @@ Syscall_Spawn(uint64_t user_path) char path[512]; void *pg; VNode *file; + Process *proc; Thread *thr; // XXX: Use CopyInStr @@ -77,15 +79,16 @@ Syscall_Spawn(uint64_t user_path) return status; } - thr = Thread_Create(); + proc = Thread_CreateProcess(); + thr = Thread_Create(proc); Log(syscall, "SPAWN %lx\n", thr); Handle *handle = Console_OpenHandle(); - Handle_Add(thr, handle); + Handle_Add(proc, handle); handle = Console_OpenHandle(); - Handle_Add(thr, handle); + Handle_Add(proc, handle); handle = Console_OpenHandle(); - Handle_Add(thr, handle); + Handle_Add(proc, handle); Loader_Load(thr, file, pg, 1024); @@ -147,7 +150,7 @@ uint64_t Syscall_Read(uint64_t fd, uint64_t addr, uint64_t off, uint64_t length) { Thread *cur = Thread_Current(); - Handle *handle = Handle_Lookup(cur, fd); + Handle *handle = Handle_Lookup(cur->proc, fd); if (handle == NULL) return -EBADF; @@ -159,7 +162,7 @@ uint64_t Syscall_Write(uint64_t fd, uint64_t addr, uint64_t off, uint64_t length) { Thread *cur = Thread_Current(); - Handle *handle = Handle_Lookup(cur, fd); + Handle *handle = Handle_Lookup(cur->proc, fd); if (handle == NULL) return -EBADF; @@ -171,7 +174,7 @@ uint64_t Syscall_Flush(uint64_t fd) { Thread *cur = Thread_Current(); - Handle *handle = Handle_Lookup(cur, fd); + Handle *handle = Handle_Lookup(cur->proc, fd); if (handle == NULL) return -EBADF; @@ -197,7 +200,7 @@ Syscall_Open(uint64_t user_path, uint64_t flags) if (strncmp("/dev/", path, 5) == 0) { if (strcmp("/dev/console", path) == 0) { Handle *handle = Console_OpenHandle(); - return Handle_Add(cur, handle); + return Handle_Add(cur->proc, handle); } return -ENOENT; @@ -208,14 +211,14 @@ Syscall_Open(uint64_t user_path, uint64_t flags) if (status != 0) return status; - return Handle_Add(cur, handle); + return Handle_Add(cur->proc, handle); } uint64_t Syscall_Close(uint64_t fd) { Thread *cur = Thread_Current(); - Handle *handle = Handle_Lookup(cur, fd); + Handle *handle = Handle_Lookup(cur->proc, fd); if (handle == NULL) return -EBADF; @@ -256,7 +259,7 @@ Syscall_ReadDir(uint64_t fd, char *user_buf, size_t len, uintptr_t user_off) { int status, rstatus; Thread *cur = Thread_Current(); - Handle *handle = Handle_Lookup(cur, fd); + Handle *handle = Handle_Lookup(cur->proc, fd); uint64_t offset; if (handle == NULL) @@ -280,6 +283,34 @@ Syscall_ReadDir(uint64_t fd, char *user_buf, size_t len, uintptr_t user_off) return rstatus; } +uint64_t +Syscall_ThreadCreate(uint64_t rip) +{ + uint64_t threadId; + Thread *curThread = Thread_Current(); + Thread *newThread = Thread_UThreadCreate(curThread, rip); + if (newThread == NULL) { + return -1; + } + + threadId = newThread->tid; + Thread_SetRunnable(newThread); + + return threadId; +} + +void +Syscall_ThreadExit(uint64_t status) +{ + Thread *cur = Thread_Current(); + + Thread_SetZombie(cur); + Thread_Scheduler(); + + // Should not return + Panic("Returned to exited thread!\n"); +} + uint64_t Syscall_ThreadSleep(uint64_t time) { @@ -325,7 +356,12 @@ Syscall_Entry(uint64_t syscall, uint64_t a1, uint64_t a2, case SYSCALL_STAT: return Syscall_Stat(a1, a2); case SYSCALL_READDIR: - return Syscall_ReadDir(a1, a2, a3, a4); + return Syscall_ReadDir(a1, (char *)a2, a3, a4); + case SYSCALL_THREADCREATE: + return Syscall_ThreadCreate(a1); + case SYSCALL_THREADEXIT: + Syscall_ThreadExit(a1); + return 0; case SYSCALL_THREADSLEEP: return Syscall_ThreadSleep(a1); default: diff --git a/sys/kern/thread.c b/sys/kern/thread.c index 47411f5..8ab1369 100644 --- a/sys/kern/thread.c +++ b/sys/kern/thread.c @@ -15,10 +15,13 @@ #include Spinlock threadLock; +uint64_t nextProcessID; uint64_t nextThreadID; Thread *curProc; +// Runnable Queue TAILQ_HEAD(ThreadQueueHead, Thread) threadQueue; +Slab processSlab; Slab threadSlab; void Handle_GlobalInit(); @@ -26,12 +29,15 @@ void Handle_GlobalInit(); void Thread_Init() { + nextProcessID = 1; nextThreadID = 1; + Slab_Init(&processSlab, "Process Objects", sizeof(Process), 16); Slab_Init(&threadSlab, "Thread Objects", sizeof(Thread), 16); // Create an thread object for current context - curProc = Thread_Create(); + Process *proc = Thread_CreateProcess(); + curProc = Thread_Create(proc); curProc->schedState = SCHED_STATE_RUNNING; Spinlock_Init(&threadLock, "Thread Lock"); @@ -48,7 +54,7 @@ Thread_Current() } Thread * -Thread_Create() +Thread_Create(Process *proc) { Thread *thr = (Thread *)Slab_Alloc(&threadSlab); @@ -64,17 +70,26 @@ Thread_Create() return NULL; } - thr->space = PMap_NewAS(); - if (thr->space == NULL) { - PAlloc_Release((void *)thr->kstack); - Slab_Free(&threadSlab, thr); - return NULL; + thr->proc = proc; + + if (proc != NULL) { + // XXX: Add to thread list + proc->threads++; + } + + if ((proc != NULL) && (proc->space != NULL)) { + thr->space = proc->space; + } else { + // XXX: for kernel threads + thr->space = PMap_NewAS(); + if (thr->space == NULL) { + PAlloc_Release((void *)thr->kstack); + Slab_Free(&threadSlab, thr); + return NULL; + } } thr->schedState = SCHED_STATE_NULL; - thr->nextFD = 0; - - Handle_Init(thr); Thread_InitArch(thr); // Initialize queue @@ -82,10 +97,34 @@ Thread_Create() return thr; } +Process * +Thread_CreateProcess() +{ + Process *proc = (Process *)Slab_Alloc(&processSlab); + + if (!proc) + return NULL; + + memset(proc, 0, sizeof(*proc)); + + proc->pid = nextProcessID++; + proc->threads = 0; + + proc->space = PMap_NewAS(); + if (proc->space == NULL) { + Slab_Free(&processSlab, proc); + return NULL; + } + + Handle_Init(proc); + + return proc; +} + Thread * Thread_KThreadCreate(void (*f)(void *), void *arg) { - Thread *thr = Thread_Create(); + Thread *thr = Thread_Create(NULL); if (!thr) return NULL; @@ -94,6 +133,39 @@ Thread_KThreadCreate(void (*f)(void *), void *arg) return thr; } +Thread * +Thread_UThreadCreate(Thread *oldThr, uint64_t rip) +{ + Process *proc = oldThr->proc; + Thread *thr = (Thread *)Slab_Alloc(&threadSlab); + + if (!thr) + return NULL; + + memset(thr, 0, sizeof(*thr)); + + thr->tid = nextThreadID++; + thr->kstack = (uintptr_t)PAlloc_AllocPage(); + if (thr->kstack == 0) { + Slab_Free(&threadSlab, thr); + return NULL; + } + + thr->space = oldThr->space; + thr->schedState = SCHED_STATE_NULL; + + Thread_InitArch(thr); + // Initialize queue + + Thread_SetupUThread(thr, rip); + + thr->proc = proc; + proc->threads++; + // XXX: Add to proc thread list + + return thr; +} + void Thread_SetRunnable(Thread *thr) { @@ -174,6 +246,32 @@ ThreadKThreadEntry(TrapFrame *tf) Trap_Pop(tf); } +void +Thread_ProcDump(Process *proc) +{ + kprintf("pid %llu\n", proc->pid); + kprintf("space %016llx\n", proc->space); + kprintf("threads %llu\n", proc->threads); + kprintf("nextFD %llu\n", proc->nextFD); +} + +void +Thread_Dump(Thread *thr) +{ + // Thread_DumpArch(thr) + kprintf("space %016llx\n", thr->space); + kprintf("kstack %016llx\n", thr->kstack); + kprintf("tid %llu\n", thr->tid); + kprintf("state %d\n", thr->schedState); + kprintf("ctxswtch %llu\n", thr->ctxSwitches); + kprintf("utime %llu\n", thr->userTime); + kprintf("ktime %llu\n", thr->kernTime); + kprintf("wtime %llu\n", thr->waitTime); + if (thr->proc) { + Thread_ProcDump(thr->proc); + } +} + void Debug_Threads(int argc, const char *argv[]) { @@ -181,10 +279,10 @@ Debug_Threads(int argc, const char *argv[]) //Spinlock_Lock(&threadLock); - kprintf("Current: %016llx %d\n", curProc, curProc->ctxSwitches); + kprintf("Current: %d(%016llx) %d\n", curProc->tid, curProc, curProc->ctxSwitches); TAILQ_FOREACH(thr, &threadQueue, schedQueue) { - kprintf("Thread: %016llx %d\n", thr, thr->ctxSwitches); + kprintf("Thread: %d(%016llx) %d\n", curProc->tid, thr, thr->ctxSwitches); } //Spinlock_Unlock(&threadLock);