Add new thread sys call

This commit is contained in:
Mathieu Maret 2024-02-13 00:19:39 +01:00 committed by Mathieu Maret
parent 758017a8e7
commit 1c2cd75c72
6 changed files with 83 additions and 5 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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;
}