Implemented OSThreadCreate system call
This commit is contained in:
parent
114b35bbbc
commit
5a3d86aa7b
@ -26,7 +26,7 @@ int OSStat(const char *path, struct stat *sb);
|
|||||||
int OSReadDir(uint64_t fd, char *buf, size_t length, uint64_t *offset);
|
int OSReadDir(uint64_t fd, char *buf, size_t length, uint64_t *offset);
|
||||||
|
|
||||||
// Threads
|
// Threads
|
||||||
int OSThreadCreate(uint64_t rip);
|
int OSThreadCreate(uint64_t rip, uint64_t arg);
|
||||||
int OSThreadExit(uint64_t status);
|
int OSThreadExit(uint64_t status);
|
||||||
int OSThreadSleep(uint64_t time);
|
int OSThreadSleep(uint64_t time);
|
||||||
int OSThreadWait(uint64_t tid);
|
int OSThreadWait(uint64_t tid);
|
||||||
|
@ -92,9 +92,9 @@ OSReadDir(uint64_t fd, char *buf, size_t length, uint64_t *offset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
OSThreadCreate(uint64_t rip)
|
OSThreadCreate(uint64_t rip, uint64_t arg)
|
||||||
{
|
{
|
||||||
return syscall(SYSCALL_THREADCREATE, rip);
|
return syscall(SYSCALL_THREADCREATE, rip, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -33,6 +33,9 @@
|
|||||||
#define MEM_USERSPACE_LEN 0x0000800000000000ULL
|
#define MEM_USERSPACE_LEN 0x0000800000000000ULL
|
||||||
#define MEM_USERSPACE_TOP (MEM_USERSPACE_BASE + MEM_USERSPACE_LEN)
|
#define MEM_USERSPACE_TOP (MEM_USERSPACE_BASE + MEM_USERSPACE_LEN)
|
||||||
|
|
||||||
|
#define MEM_USERSPACE_STKBASE 0x0000000070000000ULL
|
||||||
|
#define MEM_USERSPACE_STKLEN 0x0000000000010000ULL
|
||||||
|
|
||||||
#define MEM_DIRECTMAP_BASE 0xFFFF800000000000ULL
|
#define MEM_DIRECTMAP_BASE 0xFFFF800000000000ULL
|
||||||
#define MEM_DIRECTMAP_LEN 0x0000010000000000ULL
|
#define MEM_DIRECTMAP_LEN 0x0000010000000000ULL
|
||||||
#define MEM_XMAP_BASE 0xFFFF810000000000ULL
|
#define MEM_XMAP_BASE 0xFFFF810000000000ULL
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <machine/amd64.h>
|
#include <machine/amd64.h>
|
||||||
#include <machine/amd64op.h>
|
#include <machine/amd64op.h>
|
||||||
#include <machine/trap.h>
|
#include <machine/trap.h>
|
||||||
|
#include <machine/pmap.h>
|
||||||
|
|
||||||
extern void ThreadKThreadEntry(TrapFrame *tf);
|
extern void ThreadKThreadEntry(TrapFrame *tf);
|
||||||
extern void switchstack(uint64_t *oldrsp, uint64_t rsp);
|
extern void switchstack(uint64_t *oldrsp, uint64_t rsp);
|
||||||
@ -22,7 +23,8 @@ Thread_InitArch(Thread *thr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Thread_SetupKThread(Thread *thr, void (*f)(void *), void *arg)
|
Thread_SetupKThread(Thread *thr, void (*f)(),
|
||||||
|
uintptr_t arg1, uintptr_t arg2, uintptr_t arg3)
|
||||||
{
|
{
|
||||||
// Initialize stack
|
// Initialize stack
|
||||||
uint64_t stacktop = thr->kstack + PGSIZE;
|
uint64_t stacktop = thr->kstack + PGSIZE;
|
||||||
@ -46,30 +48,34 @@ Thread_SetupKThread(Thread *thr, void (*f)(void *), void *arg)
|
|||||||
tf->rsp = stacktop;
|
tf->rsp = stacktop;
|
||||||
tf->cs = SEL_KCS;
|
tf->cs = SEL_KCS;
|
||||||
tf->rip = (uint64_t)f;
|
tf->rip = (uint64_t)f;
|
||||||
tf->rdi = (uint64_t)arg;
|
tf->rdi = (uint64_t)arg1;
|
||||||
|
tf->rsi = (uint64_t)arg2;
|
||||||
|
tf->rdx = (uint64_t)arg3;
|
||||||
tf->rflags = RFLAGS_IF;
|
tf->rflags = RFLAGS_IF;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ThreadEnterUserLevelCB(void *arg)
|
ThreadEnterUserLevelCB(uintptr_t arg1, uintptr_t arg2, uintptr_t arg3)
|
||||||
{
|
{
|
||||||
TrapFrame tf;
|
TrapFrame tf;
|
||||||
|
|
||||||
memset(&tf, 0, sizeof(tf));
|
memset(&tf, 0, sizeof(tf));
|
||||||
tf.ds = SEL_UDS | 3;
|
tf.ds = SEL_UDS | 3;
|
||||||
tf.rip = (uint64_t)arg;
|
tf.rip = (uint64_t)arg1;
|
||||||
tf.cs = SEL_UCS | 3;
|
tf.cs = SEL_UCS | 3;
|
||||||
tf.rsp = 0x70000000 + PGSIZE;
|
tf.rsp = (uint64_t)arg2 + MEM_USERSPACE_STKLEN;
|
||||||
tf.ss = SEL_UDS | 3;
|
tf.ss = SEL_UDS | 3;
|
||||||
tf.rflags = RFLAGS_IF;
|
tf.rflags = RFLAGS_IF;
|
||||||
|
tf.rdi = (uint64_t)arg3; /* Userspace Argument */
|
||||||
|
|
||||||
Trap_Pop(&tf);
|
Trap_Pop(&tf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Thread_SetupUThread(Thread *thr, uint64_t rip)
|
Thread_SetupUThread(Thread *thr, uintptr_t rip, uintptr_t arg)
|
||||||
{
|
{
|
||||||
Thread_SetupKThread(thr, ThreadEnterUserLevelCB, (void *)rip);
|
Thread_SetupKThread(thr, ThreadEnterUserLevelCB, rip,
|
||||||
|
thr->ustack, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern TaskStateSegment64 TSS[MAX_CPUS];
|
extern TaskStateSegment64 TSS[MAX_CPUS];
|
||||||
|
@ -22,6 +22,7 @@ typedef struct Thread {
|
|||||||
ThreadArch arch;
|
ThreadArch arch;
|
||||||
AS *space;
|
AS *space;
|
||||||
uintptr_t kstack;
|
uintptr_t kstack;
|
||||||
|
uintptr_t ustack;
|
||||||
uint64_t tid;
|
uint64_t tid;
|
||||||
// Process
|
// Process
|
||||||
struct Process *proc;
|
struct Process *proc;
|
||||||
@ -43,6 +44,7 @@ typedef struct Thread {
|
|||||||
typedef struct Process {
|
typedef struct Process {
|
||||||
uint64_t pid;
|
uint64_t pid;
|
||||||
AS *space;
|
AS *space;
|
||||||
|
uintptr_t ustackNext; // Next user stack
|
||||||
TAILQ_ENTRY(Process) processList;
|
TAILQ_ENTRY(Process) processList;
|
||||||
// Threads
|
// Threads
|
||||||
uint64_t threads;
|
uint64_t threads;
|
||||||
@ -57,7 +59,7 @@ Thread *Thread_Current();
|
|||||||
Process *Thread_CreateProcess();
|
Process *Thread_CreateProcess();
|
||||||
Thread *Thread_Create(Process *proc);
|
Thread *Thread_Create(Process *proc);
|
||||||
Thread *Thread_KThreadCreate(void (*f)(void*), void *arg);
|
Thread *Thread_KThreadCreate(void (*f)(void*), void *arg);
|
||||||
Thread *Thread_UThreadCreate(Thread *oldThr, uint64_t rip);
|
Thread *Thread_UThreadCreate(Thread *oldThr, uint64_t rip, uint64_t arg);
|
||||||
void Thread_SetRunnable(Thread *thr);
|
void Thread_SetRunnable(Thread *thr);
|
||||||
void Thread_SetWaiting(Thread *thr);
|
void Thread_SetWaiting(Thread *thr);
|
||||||
void Thread_SetZombie(Thread *thr);
|
void Thread_SetZombie(Thread *thr);
|
||||||
@ -73,8 +75,9 @@ void Process_Destroy(Process *proc);
|
|||||||
|
|
||||||
// Platform functions
|
// Platform functions
|
||||||
void Thread_InitArch(Thread *thr);
|
void Thread_InitArch(Thread *thr);
|
||||||
void Thread_SetupKThread(Thread *thr, void (*f)(void *), void *arg);
|
void Thread_SetupKThread(Thread *thr, void (*f)(),
|
||||||
void Thread_SetupUThread(Thread *thr, uint64_t rip);
|
uintptr_t arg1, uintptr_t arg2, uintptr_t arg3);
|
||||||
|
void Thread_SetupUThread(Thread *thr, uint64_t rip, uint64_t arg);
|
||||||
void Thread_SwitchArch(Thread *oldthr, Thread *newthr);
|
void Thread_SwitchArch(Thread *oldthr, Thread *newthr);
|
||||||
|
|
||||||
// Handle Functions
|
// Handle Functions
|
||||||
|
@ -78,8 +78,7 @@ Loader_LoadFirst(Thread *thr, VNode *vn, void *buf, uint64_t len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void *stack = PAlloc_AllocPage();
|
PMap_AllocMap(as, MEM_USERSPACE_STKBASE, MEM_USERSPACE_STKLEN, PTE_W);
|
||||||
PMap_Map(as, (uint64_t)DMVA2PA(stack), 0x70000000, 1, 0);
|
|
||||||
PMap_LoadAS(as); // Reload CR3
|
PMap_LoadAS(as); // Reload CR3
|
||||||
|
|
||||||
for (i = 0; i < ehdr->e_phnum; i++)
|
for (i = 0; i < ehdr->e_phnum; i++)
|
||||||
@ -101,9 +100,10 @@ Loader_LoadFirst(Thread *thr, VNode *vn, void *buf, uint64_t len)
|
|||||||
tf.ds = SEL_UDS | 3;
|
tf.ds = SEL_UDS | 3;
|
||||||
tf.rip = ehdr->e_entry;
|
tf.rip = ehdr->e_entry;
|
||||||
tf.cs = SEL_UCS | 3;
|
tf.cs = SEL_UCS | 3;
|
||||||
tf.rsp = 0x70000000 + PGSIZE;
|
tf.rsp = MEM_USERSPACE_STKBASE + MEM_USERSPACE_STKLEN;
|
||||||
tf.ss = SEL_UDS | 3;
|
tf.ss = SEL_UDS | 3;
|
||||||
tf.rflags = RFLAGS_IF;
|
tf.rflags = RFLAGS_IF;
|
||||||
|
tf.rdi = 0;
|
||||||
Trap_Pop(&tf);
|
Trap_Pop(&tf);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -243,8 +243,7 @@ Loader_Load(Thread *thr, VNode *vn, void *buf, uint64_t len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void *stack = PAlloc_AllocPage();
|
PMap_AllocMap(as, MEM_USERSPACE_STKBASE, MEM_USERSPACE_STKLEN, PTE_W);
|
||||||
PMap_Map(as, (uint64_t)DMVA2PA(stack), 0x70000000, 1, 0);
|
|
||||||
|
|
||||||
for (i = 0; i < ehdr->e_phnum; i++)
|
for (i = 0; i < ehdr->e_phnum; i++)
|
||||||
{
|
{
|
||||||
@ -260,7 +259,7 @@ Loader_Load(Thread *thr, VNode *vn, void *buf, uint64_t len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread_SetupUThread(thr, ehdr->e_entry);
|
Thread_SetupUThread(thr, ehdr->e_entry, 0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -285,11 +285,11 @@ Syscall_ReadDir(uint64_t fd, char *user_buf, size_t len, uintptr_t user_off)
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
Syscall_ThreadCreate(uint64_t rip)
|
Syscall_ThreadCreate(uint64_t rip, uint64_t arg)
|
||||||
{
|
{
|
||||||
uint64_t threadId;
|
uint64_t threadId;
|
||||||
Thread *curThread = Thread_Current();
|
Thread *curThread = Thread_Current();
|
||||||
Thread *newThread = Thread_UThreadCreate(curThread, rip);
|
Thread *newThread = Thread_UThreadCreate(curThread, rip, arg);
|
||||||
if (newThread == NULL) {
|
if (newThread == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -386,7 +386,7 @@ Syscall_Entry(uint64_t syscall, uint64_t a1, uint64_t a2,
|
|||||||
case SYSCALL_READDIR:
|
case SYSCALL_READDIR:
|
||||||
return Syscall_ReadDir(a1, (char *)a2, a3, a4);
|
return Syscall_ReadDir(a1, (char *)a2, a3, a4);
|
||||||
case SYSCALL_THREADCREATE:
|
case SYSCALL_THREADCREATE:
|
||||||
return Syscall_ThreadCreate(a1);
|
return Syscall_ThreadCreate(a1, a2);
|
||||||
case SYSCALL_THREADEXIT:
|
case SYSCALL_THREADEXIT:
|
||||||
Syscall_ThreadExit(a1);
|
Syscall_ThreadExit(a1);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -83,6 +83,9 @@ Thread_Create(Process *proc)
|
|||||||
if (proc != NULL) {
|
if (proc != NULL) {
|
||||||
// XXX: Add to thread list
|
// XXX: Add to thread list
|
||||||
proc->threads++;
|
proc->threads++;
|
||||||
|
|
||||||
|
thr->ustack = proc->ustackNext;
|
||||||
|
proc->ustackNext += MEM_USERSPACE_STKLEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((proc != NULL) && (proc->space != NULL)) {
|
if ((proc != NULL) && (proc->space != NULL)) {
|
||||||
@ -124,6 +127,7 @@ Thread_CreateProcess()
|
|||||||
Slab_Free(&processSlab, proc);
|
Slab_Free(&processSlab, proc);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
proc->ustackNext = MEM_USERSPACE_STKBASE;
|
||||||
|
|
||||||
Handle_Init(proc);
|
Handle_Init(proc);
|
||||||
|
|
||||||
@ -139,13 +143,13 @@ Thread_KThreadCreate(void (*f)(void *), void *arg)
|
|||||||
if (!thr)
|
if (!thr)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
Thread_SetupKThread(thr, f, arg);
|
Thread_SetupKThread(thr, f, (uintptr_t)arg, 0, 0);
|
||||||
|
|
||||||
return thr;
|
return thr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread *
|
Thread *
|
||||||
Thread_UThreadCreate(Thread *oldThr, uint64_t rip)
|
Thread_UThreadCreate(Thread *oldThr, uint64_t rip, uint64_t arg)
|
||||||
{
|
{
|
||||||
Process *proc = oldThr->proc;
|
Process *proc = oldThr->proc;
|
||||||
Thread *thr = (Thread *)Slab_Alloc(&threadSlab);
|
Thread *thr = (Thread *)Slab_Alloc(&threadSlab);
|
||||||
@ -165,10 +169,14 @@ Thread_UThreadCreate(Thread *oldThr, uint64_t rip)
|
|||||||
thr->space = oldThr->space;
|
thr->space = oldThr->space;
|
||||||
thr->schedState = SCHED_STATE_NULL;
|
thr->schedState = SCHED_STATE_NULL;
|
||||||
|
|
||||||
|
thr->ustack = proc->ustackNext;
|
||||||
|
proc->ustackNext += MEM_USERSPACE_STKLEN;
|
||||||
|
PMap_AllocMap(thr->space, thr->ustack, MEM_USERSPACE_STKLEN, PTE_W);
|
||||||
|
|
||||||
Thread_InitArch(thr);
|
Thread_InitArch(thr);
|
||||||
// Initialize queue
|
// Initialize queue
|
||||||
|
|
||||||
Thread_SetupUThread(thr, rip);
|
Thread_SetupUThread(thr, rip, arg);
|
||||||
|
|
||||||
thr->proc = proc;
|
thr->proc = proc;
|
||||||
proc->threads++;
|
proc->threads++;
|
||||||
|
Loading…
Reference in New Issue
Block a user