user_thread #9
@ -11,6 +11,7 @@ struct process {
|
|||||||
char name[PROCESS_NAME_MAX_LENGTH];
|
char name[PROCESS_NAME_MAX_LENGTH];
|
||||||
int ref;
|
int ref;
|
||||||
int pid;
|
int pid;
|
||||||
|
int nextTid;
|
||||||
struct uAddrSpace *addrSpace;
|
struct uAddrSpace *addrSpace;
|
||||||
struct thread *thList;
|
struct thread *thList;
|
||||||
|
|
||||||
@ -47,7 +48,8 @@ struct process *processCreate(char *name)
|
|||||||
new->ref = 1;
|
new->ref = 1;
|
||||||
|
|
||||||
disable_IRQs(flags);
|
disable_IRQs(flags);
|
||||||
new->pid = nextPid++;
|
new->pid = nextPid++;
|
||||||
|
new->nextTid = new->pid;
|
||||||
list_add_tail(processList, new);
|
list_add_tail(processList, new);
|
||||||
restore_IRQs(flags);
|
restore_IRQs(flags);
|
||||||
|
|
||||||
@ -180,3 +182,11 @@ struct uAddrSpace *processGetAddrSpace(struct process *proc){
|
|||||||
int processInitHeap(struct process *proc, uaddr_t lastUserAddr){
|
int processInitHeap(struct process *proc, uaddr_t lastUserAddr){
|
||||||
return uAddrSpaceSetHeap(proc->addrSpace, lastUserAddr, 0);
|
return uAddrSpaceSetHeap(proc->addrSpace, lastUserAddr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int processGetId(struct process *proc){
|
||||||
|
return proc->pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int processGetNextTid(struct process *proc){
|
||||||
|
return proc->nextTid++;
|
||||||
|
}
|
||||||
|
@ -18,3 +18,5 @@ int processRemoveThread(struct thread *th);
|
|||||||
struct mmu_context *processGetMMUContext(struct process *th);
|
struct mmu_context *processGetMMUContext(struct process *th);
|
||||||
struct uAddrSpace *processGetAddrSpace(struct process *proc);
|
struct uAddrSpace *processGetAddrSpace(struct process *proc);
|
||||||
int processInitHeap(struct process *proc, uaddr_t lastUserAddr);
|
int processInitHeap(struct process *proc, uaddr_t lastUserAddr);
|
||||||
|
int processGetId(struct process *proc);
|
||||||
|
int processGetNextTid(struct process *proc);
|
||||||
|
@ -113,11 +113,14 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx)
|
|||||||
}
|
}
|
||||||
case SYSCALL_ID_NEW_THREAD: {
|
case SYSCALL_ID_NEW_THREAD: {
|
||||||
struct uAddrSpace *as;
|
struct uAddrSpace *as;
|
||||||
|
thread_id_t threadIdPtr;
|
||||||
|
thread_id_t threadId;
|
||||||
uaddr_t funcAddr;
|
uaddr_t funcAddr;
|
||||||
uint32_t arg1, arg2;
|
uint32_t arg1, arg2;
|
||||||
size_t stackSize;
|
size_t stackSize;
|
||||||
|
|
||||||
ret = syscallGet4args(userCtx, (unsigned int *)&funcAddr, (unsigned int *)&arg1,
|
ret = syscallGet5args(userCtx, (unsigned int *)&threadIdPtr,
|
||||||
|
(unsigned int *)&funcAddr, (unsigned int *)&arg1,
|
||||||
(unsigned int *)&arg2, (unsigned int *)&stackSize);
|
(unsigned int *)&arg2, (unsigned int *)&stackSize);
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
@ -125,6 +128,11 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx)
|
|||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (memcpyFromUser((vaddr_t)&threadId, threadIdPtr, sizeof(threadId)) !=
|
||||||
|
sizeof(threadId)) {
|
||||||
|
ret = -EFAULT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
as = processGetAddrSpace(getCurrentThread()->process);
|
as = processGetAddrSpace(getCurrentThread()->process);
|
||||||
stackSize = ALIGN(stackSize, PAGE_SIZE);
|
stackSize = ALIGN(stackSize, PAGE_SIZE);
|
||||||
@ -142,6 +150,13 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx)
|
|||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
uAddrSpaceUnmap(as, stackAddr, stackSize);
|
uAddrSpaceUnmap(as, stackAddr, stackSize);
|
||||||
}
|
}
|
||||||
|
threadId = threadGetId(th);
|
||||||
|
|
||||||
|
if (memcpyToUser(threadIdPtr, (vaddr_t)&threadId, sizeof(threadId)) !=
|
||||||
|
sizeof(threadId)) {
|
||||||
|
ret = -EFAULT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -156,6 +171,14 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SYSCALL_ID_GETPID: {
|
||||||
|
ret = processGetId(getCurrentThread()->process);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SYSCALL_ID_GETTID: {
|
||||||
|
ret = threadGetId(getCurrentThread());
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
printf("Unknon syscall id %d\n", syscallId);
|
printf("Unknon syscall id %d\n", syscallId);
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
#define SYSCALL_ID_MUNMAP 8
|
#define SYSCALL_ID_MUNMAP 8
|
||||||
#define SYSCALL_ID_NEW_THREAD 9
|
#define SYSCALL_ID_NEW_THREAD 9
|
||||||
#define SYSCALL_ID_USLEEP 10
|
#define SYSCALL_ID_USLEEP 10
|
||||||
|
#define SYSCALL_ID_GETPID 11
|
||||||
|
#define SYSCALL_ID_GETTID 12
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
int syscallExecute(int syscallId, const struct cpu_state *user_ctx);
|
int syscallExecute(int syscallId, const struct cpu_state *user_ctx);
|
||||||
|
@ -12,6 +12,12 @@
|
|||||||
|
|
||||||
static struct thread *currentThread;
|
static struct thread *currentThread;
|
||||||
static struct thread *threadWithTimeout;
|
static struct thread *threadWithTimeout;
|
||||||
|
static thread_id_t nextTid; // This is the TID for kernel thread ONLY
|
||||||
|
|
||||||
|
thread_id_t threadGetId(struct thread *th)
|
||||||
|
{
|
||||||
|
return th->tid;
|
||||||
|
}
|
||||||
|
|
||||||
static void threadPrepareContext(struct thread *th);
|
static void threadPrepareContext(struct thread *th);
|
||||||
|
|
||||||
@ -84,6 +90,7 @@ struct thread *threadCreate(const char *name, cpu_kstate_function_arg1_t func, v
|
|||||||
goto free_mem;
|
goto free_mem;
|
||||||
|
|
||||||
thread->state = READY;
|
thread->state = READY;
|
||||||
|
thread->tid = nextTid++;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
disable_IRQs(flags);
|
disable_IRQs(flags);
|
||||||
list_add_tail(currentThread, thread);
|
list_add_tail(currentThread, thread);
|
||||||
@ -124,6 +131,7 @@ struct thread *threadCreateUser(const char *name, struct process *proc, uaddr_t
|
|||||||
goto free_mem;
|
goto free_mem;
|
||||||
|
|
||||||
thread->state = READY;
|
thread->state = READY;
|
||||||
|
thread->tid = processGetNextTid(proc);
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
disable_IRQs(flags);
|
disable_IRQs(flags);
|
||||||
list_add_tail(currentThread, thread);
|
list_add_tail(currentThread, thread);
|
||||||
|
@ -17,8 +17,11 @@ typedef enum {
|
|||||||
EXITING
|
EXITING
|
||||||
} thread_state;
|
} thread_state;
|
||||||
|
|
||||||
|
typedef unsigned long int thread_id_t;
|
||||||
|
|
||||||
struct thread {
|
struct thread {
|
||||||
char name[THREAD_NAME_MAX_LENGTH];
|
char name[THREAD_NAME_MAX_LENGTH];
|
||||||
|
thread_id_t tid;
|
||||||
struct cpu_state *cpuState;
|
struct cpu_state *cpuState;
|
||||||
thread_state state;
|
thread_state state;
|
||||||
vaddr_t stackAddr;
|
vaddr_t stackAddr;
|
||||||
@ -89,3 +92,4 @@ struct thread *getCurrentThread();
|
|||||||
int threadAddThread(struct thread *th);
|
int threadAddThread(struct thread *th);
|
||||||
int threadChangeCurrentContext(struct mmu_context *ctx);
|
int threadChangeCurrentContext(struct mmu_context *ctx);
|
||||||
int threadCount();
|
int threadCount();
|
||||||
|
thread_id_t threadGetId(struct thread *th);
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
#define SYSCALL_ID_MUNMAP 8
|
#define SYSCALL_ID_MUNMAP 8
|
||||||
#define SYSCALL_ID_NEW_THREAD 9
|
#define SYSCALL_ID_NEW_THREAD 9
|
||||||
#define SYSCALL_ID_USLEEP 10
|
#define SYSCALL_ID_USLEEP 10
|
||||||
|
#define SYSCALL_ID_GETPID 11
|
||||||
|
#define SYSCALL_ID_GETTID 12
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
int syscallExecute(int syscallId, const struct cpu_state *user_ctx);
|
int syscallExecute(int syscallId, const struct cpu_state *user_ctx);
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "swintr.h"
|
#include "swintr.h"
|
||||||
#include "sys/mman.h"
|
#include "sys/mman.h"
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
|
#include "thread.h"
|
||||||
#include "unistd.h"
|
#include "unistd.h"
|
||||||
|
|
||||||
int errno = 0;
|
int errno = 0;
|
||||||
@ -761,12 +762,19 @@ static void thread_runner()
|
|||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int new_thread(start_routine *func, void *arg, size_t stackSize)
|
int thread_create(pthread_t *thread, start_routine *func, void *arg, size_t stackSize) {
|
||||||
{
|
return syscall5(SYSCALL_ID_NEW_THREAD, (unsigned int)thread, (unsigned int)thread_runner, (unsigned int)func,
|
||||||
return syscall4(SYSCALL_ID_NEW_THREAD, (unsigned int)thread_runner, (unsigned int)func,
|
|
||||||
(unsigned int)arg, stackSize);
|
(unsigned int)arg, stackSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
int usleep(useconds_t usec) {
|
int usleep(useconds_t usec) {
|
||||||
return syscall1(SYSCALL_ID_USLEEP, (unsigned int)usec);
|
return syscall1(SYSCALL_ID_USLEEP, (unsigned int)usec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pid_t gettid(void) {
|
||||||
|
return syscall0(SYSCALL_ID_GETTID);
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t getpid(void) {
|
||||||
|
return syscall0(SYSCALL_ID_GETPID);
|
||||||
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
#include "stddef.h"
|
#include "stddef.h"
|
||||||
#include "minmax.h"
|
#include "minmax.h"
|
||||||
|
#include "unistd.h"
|
||||||
|
|
||||||
#define islower(c) (('a' <= (c)) && ((c) <= 'z'))
|
#define islower(c) (('a' <= (c)) && ((c) <= 'z'))
|
||||||
#define isupper(c) (('A' <= (c)) && ((c) <= 'Z'))
|
#define isupper(c) (('A' <= (c)) && ((c) <= 'Z'))
|
||||||
@ -63,6 +64,6 @@ void *malloc(size_t size);
|
|||||||
void *calloc(size_t nmemb, size_t size);
|
void *calloc(size_t nmemb, size_t size);
|
||||||
void *realloc(void *ptr, size_t size);
|
void *realloc(void *ptr, size_t size);
|
||||||
void free(void *ptr);
|
void free(void *ptr);
|
||||||
|
pid_t gettid(void);
|
||||||
|
pid_t getpid(void);
|
||||||
|
|
||||||
typedef void *(start_routine)(void *);
|
|
||||||
int new_thread(start_routine *func, void *arg, size_t stackSize);
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "stdarg.h"
|
#include "stdarg.h"
|
||||||
#include "stddef.h"
|
#include "stddef.h"
|
||||||
#include "sys/mman.h"
|
#include "sys/mman.h"
|
||||||
|
#include "thread.h"
|
||||||
#include "tiny.h"
|
#include "tiny.h"
|
||||||
#include "unistd.h"
|
#include "unistd.h"
|
||||||
|
|
||||||
@ -122,14 +123,15 @@ int func_munmap()
|
|||||||
|
|
||||||
static void *print_hello(void *arg) {
|
static void *print_hello(void *arg) {
|
||||||
(void)arg;
|
(void)arg;
|
||||||
printf("Hello World from thread\n");
|
printf("Hello World from thread %d\n", gettid());
|
||||||
usleep(100);
|
usleep(100);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int func_thread() {
|
int func_thread() {
|
||||||
new_thread(print_hello, NULL, 4096);
|
pthread_t id;
|
||||||
|
thread_create(&id, print_hello, NULL, 4096);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -138,6 +140,7 @@ int main(int argc, char *argv[]) {
|
|||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
char buf[64];
|
char buf[64];
|
||||||
|
assert(getpid() == gettid());
|
||||||
printf("Shell starting... type \"help\" for help\n");
|
printf("Shell starting... type \"help\" for help\n");
|
||||||
while (1) {
|
while (1) {
|
||||||
printf(">");
|
printf(">");
|
||||||
|
6
userspace/thread.h
Normal file
6
userspace/thread.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef unsigned long int pthread_t;
|
||||||
|
typedef void *(start_routine)(void *);
|
||||||
|
int thread_create(pthread_t *thread, start_routine *func, void *arg, size_t stackSize);
|
@ -2,3 +2,5 @@
|
|||||||
|
|
||||||
typedef unsigned int useconds_t;
|
typedef unsigned int useconds_t;
|
||||||
int usleep(useconds_t usec);
|
int usleep(useconds_t usec);
|
||||||
|
|
||||||
|
typedef int pid_t;
|
||||||
|
Loading…
Reference in New Issue
Block a user