diff --git a/core/syscall.c b/core/syscall.c index a760424..288d5a7 100644 --- a/core/syscall.c +++ b/core/syscall.c @@ -1,6 +1,8 @@ #include "syscall.h" +#include "kernel.h" #include "keyboard.h" #include "klibc.h" +#include "paging.h" #include "process.h" #include "stdarg.h" #include "thread.h" @@ -43,17 +45,17 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx) printf("Got 5args from userspace %d %d %d %d %d\n", arg1, arg2, arg3, arg4, arg5); break; } - case SYSCALL_ID_BRK:{ + case SYSCALL_ID_BRK: { struct uAddrSpace *as; uaddr_t newHeapTop; - as = processGetAddrSpace(getCurrentThread()->process); + as = processGetAddrSpace(getCurrentThread()->process); ret = syscallGet1arg(userCtx, (unsigned int *)&newHeapTop); if (ret != 0) break; threadChangeCurrentContext(uAddrSpaceGetMMUContext(as)); - //TODO : what if *newHeapTop raise page fault? + // TODO : what if *newHeapTop raise page fault? ret = sysBrk(as, newHeapTop); threadChangeCurrentContext(NULL); break; @@ -110,6 +112,40 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx) ret = uAddrSpaceUnmap(as, uaddr, size); break; } + case SYSCALL_ID_NEW_THREAD: { + struct uAddrSpace *as; + uaddr_t funcAddr; + uint32_t arg1, arg2; + size_t stackSize; + + ret = syscallGet4args(userCtx, (unsigned int *)&funcAddr, (unsigned int *)&arg1, + (unsigned int *)&arg2, (unsigned int *)&stackSize); + if (ret) + break; + if (stackSize <= 0) { + ret = -EINVAL; + break; + } + + as = processGetAddrSpace(getCurrentThread()->process); + stackSize = ALIGN(stackSize, PAGE_SIZE); + + uaddr_t stackAddr = 0; + ret = zeroMmap(as, &stackAddr, stackSize, PAGING_MEM_READ | PAGING_MEM_WRITE, 0); + + if (ret) + break; + + struct thread *th = threadCreateUser(NULL, getCurrentThread()->process, funcAddr, + arg1, arg2, stackAddr + stackSize); + + if (th == NULL) { + ret = -ENOMEM; + uAddrSpaceUnmap(as, stackAddr, stackSize); + } + + break; + } default: printf("Unknon syscall id %d\n", syscallId); ret = -ENOENT; diff --git a/core/syscall.h b/core/syscall.h index 444789b..72ccf9e 100644 --- a/core/syscall.h +++ b/core/syscall.h @@ -11,6 +11,7 @@ #define SYSCALL_ID_BRK 6 #define SYSCALL_ID_MMAP 7 #define SYSCALL_ID_MUNMAP 8 +#define SYSCALL_ID_NEW_THREAD 9 #ifdef __KERNEL__ int syscallExecute(int syscallId, const struct cpu_state *user_ctx); diff --git a/userspace/kernel/syscall.h b/userspace/kernel/syscall.h index 444789b..72ccf9e 100644 --- a/userspace/kernel/syscall.h +++ b/userspace/kernel/syscall.h @@ -11,6 +11,7 @@ #define SYSCALL_ID_BRK 6 #define SYSCALL_ID_MMAP 7 #define SYSCALL_ID_MUNMAP 8 +#define SYSCALL_ID_NEW_THREAD 9 #ifdef __KERNEL__ int syscallExecute(int syscallId, const struct cpu_state *user_ctx); diff --git a/userspace/libc.c b/userspace/libc.c index eec4ccc..ff91b25 100644 --- a/userspace/libc.c +++ b/userspace/libc.c @@ -745,3 +745,23 @@ int munmap(void *addr, size_t len) return syscall2(SYSCALL_ID_MUNMAP, (unsigned int)addr, len); } + +/* As when a new thread is run, the params are passed by register (See cpu_ustate_init), use + * this function to simplify new thread usage*/ +static void thread_runner() +{ + register unsigned long int reg_arg1 asm("%eax"); + register unsigned long int reg_arg2 asm("%ebx"); + + start_routine *func = (start_routine *)reg_arg1; + void *arg = (void *)reg_arg2; + + func(arg); + _exit(0); +} + +int new_thread(start_routine *func, void *arg, size_t stackSize) +{ + return syscall4(SYSCALL_ID_NEW_THREAD, (unsigned int)thread_runner, (unsigned int)func, + (unsigned int)arg, stackSize); +} diff --git a/userspace/libc.h b/userspace/libc.h index 378d023..12bcf9d 100644 --- a/userspace/libc.h +++ b/userspace/libc.h @@ -63,3 +63,6 @@ void *malloc(size_t size); void *calloc(size_t nmemb, size_t size); void *realloc(void *ptr, size_t size); void free(void *ptr); + +typedef void *(start_routine)(void *); +int new_thread(start_routine *func, void *arg, size_t stackSize); diff --git a/userspace/main_user.c b/userspace/main_user.c index 65ce7c7..7354fdc 100644 --- a/userspace/main_user.c +++ b/userspace/main_user.c @@ -15,6 +15,7 @@ int func_help() printf(" tiny: a tiny C-like interpreter\n"); printf(" mmap: test mmap \n"); printf(" munmap: test munmap \n"); + printf(" thread: run a user thread\n"); return 0; } @@ -118,8 +119,20 @@ int func_munmap() return ret; } -int main(int argc, char *argv[]) -{ +static void *print_hello(void *arg) { + (void)arg; + printf("Hello World from thread\n"); + + return NULL; +} + +int func_thread() { + new_thread(print_hello, NULL, 4096); + + return 0; +} + +int main(int argc, char *argv[]) { (void)argc; (void)argv; char buf[64]; @@ -156,6 +169,10 @@ int main(int argc, char *argv[]) func_munmap(); continue; } + if (strcmp(buf, "thread") == 0) { + func_thread(); + continue; + } } return 0; }