user_thread #9
@ -191,3 +191,39 @@ pid_t processGetId(struct process *proc){
|
||||
pid_t processGetNextTid(struct process *proc){
|
||||
return proc->nextTid++;
|
||||
}
|
||||
|
||||
//Should be called with IRQ disabled
|
||||
struct thread *processGetThread(struct process *proc, pid_t tid)
|
||||
{
|
||||
int count;
|
||||
struct thread *th;
|
||||
struct thread *thFound = NULL;
|
||||
|
||||
list_foreach_named(proc->thList, th, count, prevInProcess, nextInProcess)
|
||||
{
|
||||
if (th->tid == tid) {
|
||||
thFound = th;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return thFound;
|
||||
}
|
||||
|
||||
int processJoinThread(struct process *proc, pid_t tid)
|
||||
{
|
||||
uint32_t flags;
|
||||
struct thread *th;
|
||||
int ret = -1;
|
||||
|
||||
disable_IRQs(flags);
|
||||
|
||||
th = processGetThread(proc, tid);
|
||||
if (th && th->wqExit) {
|
||||
wait(th->wqExit);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
restore_IRQs(flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -22,3 +22,4 @@ struct uAddrSpace *processGetAddrSpace(struct process *proc);
|
||||
int processInitHeap(struct process *proc, uaddr_t lastUserAddr);
|
||||
pid_t processGetId(struct process *proc);
|
||||
pid_t processGetNextTid(struct process *proc);
|
||||
int processJoinThread(struct process *proc, pid_t tid);
|
||||
|
@ -179,6 +179,15 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx)
|
||||
ret = threadGetId(getCurrentThread());
|
||||
break;
|
||||
}
|
||||
case SYSCALL_ID_THREAD_JOIN: {
|
||||
thread_id_t tid;
|
||||
|
||||
ret = syscallGet1arg(userCtx, (unsigned int *)&tid);
|
||||
if (ret)
|
||||
break;
|
||||
ret = processJoinThread(getCurrentThread()->process, tid);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf("Unknon syscall id %d\n", syscallId);
|
||||
ret = -ENOENT;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define SYSCALL_ID_USLEEP 10
|
||||
#define SYSCALL_ID_GETPID 11
|
||||
#define SYSCALL_ID_GETTID 12
|
||||
#define SYSCALL_ID_THREAD_JOIN 13
|
||||
|
||||
#ifdef __KERNEL__
|
||||
int syscallExecute(int syscallId, const struct cpu_state *user_ctx);
|
||||
|
@ -91,6 +91,7 @@ struct thread *threadCreate(const char *name, cpu_kstate_function_arg1_t func, v
|
||||
|
||||
thread->state = READY;
|
||||
thread->tid = nextTid++;
|
||||
thread->wqExit = NULL;
|
||||
uint32_t flags;
|
||||
disable_IRQs(flags);
|
||||
list_add_tail(currentThread, thread);
|
||||
@ -117,6 +118,14 @@ struct thread *threadCreateUser(const char *name, struct process *proc, uaddr_t
|
||||
}
|
||||
thread->stackSize = THREAD_DEFAULT_STACK_SIZE;
|
||||
|
||||
thread->wqExit = (struct wait_queue * )malloc(sizeof(struct wait_queue));
|
||||
if (!thread->wqExit) {
|
||||
free((void *)thread->stackAddr);
|
||||
free(thread);
|
||||
return NULL;
|
||||
}
|
||||
waitQueueInit(thread->wqExit);
|
||||
|
||||
if (name)
|
||||
strzcpy(thread->name, name, THREAD_NAME_MAX_LENGTH);
|
||||
else
|
||||
@ -151,6 +160,10 @@ void threadDelete(struct thread *thread)
|
||||
restore_IRQs(flags);
|
||||
assert(thread->state == EXITING);
|
||||
|
||||
if (thread->wqExit) {
|
||||
waitUp(thread->wqExit);
|
||||
}
|
||||
|
||||
if (thread->squattedContext) {
|
||||
threadChangeCurrentContext(NULL);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ struct thread;
|
||||
#include "cpu_context.h"
|
||||
#include "mem.h"
|
||||
#include "process.h"
|
||||
#include "wait.h"
|
||||
|
||||
#define THREAD_NAME_MAX_LENGTH 32
|
||||
#define THREAD_DEFAULT_STACK_SIZE PAGE_SIZE
|
||||
@ -35,6 +36,7 @@ struct thread {
|
||||
// For User thread only
|
||||
struct thread *nextInProcess, *prevInProcess;
|
||||
struct process *process;
|
||||
struct wait_queue *wqExit; // This will be signaled at thread exit (user only)
|
||||
|
||||
/**
|
||||
* Address space currently "squatted" by the thread, or used to be
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define SYSCALL_ID_USLEEP 10
|
||||
#define SYSCALL_ID_GETPID 11
|
||||
#define SYSCALL_ID_GETTID 12
|
||||
#define SYSCALL_ID_THREAD_JOIN 13
|
||||
|
||||
#ifdef __KERNEL__
|
||||
int syscallExecute(int syscallId, const struct cpu_state *user_ctx);
|
||||
|
@ -807,6 +807,12 @@ int thread_create(pthread_t *thread, start_routine *func, void *arg, size_t stac
|
||||
(unsigned int)arg, stackSize);
|
||||
}
|
||||
|
||||
int thread_join(pthread_t thread, void **retval){
|
||||
(void)retval;
|
||||
return syscall1(SYSCALL_ID_THREAD_JOIN, (unsigned int)thread);
|
||||
}
|
||||
|
||||
|
||||
int usleep(useconds_t usec) {
|
||||
return syscall1(SYSCALL_ID_USLEEP, (unsigned int)usec);
|
||||
}
|
||||
|
@ -124,14 +124,15 @@ int func_munmap()
|
||||
static void *print_hello(void *arg) {
|
||||
(void)arg;
|
||||
printf("Hello World from thread %lu\n", gettid());
|
||||
usleep(100);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int func_thread() {
|
||||
pthread_t id;
|
||||
void *retval;
|
||||
thread_create(&id, print_hello, NULL, 4096);
|
||||
thread_join(id, &retval);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -163,7 +164,10 @@ int main(int argc, char *argv[]) {
|
||||
continue;
|
||||
}
|
||||
if (strcmp(buf, "tiny") == 0) {
|
||||
func_tiny();
|
||||
pthread_t id;
|
||||
void *retval;
|
||||
thread_create(&id, func_tiny, NULL, 4096);
|
||||
thread_join(id, &retval);
|
||||
continue;
|
||||
}
|
||||
if (strcmp(buf, "mmap") == 0) {
|
||||
|
@ -4,3 +4,5 @@
|
||||
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);
|
||||
/* retval is ignored ATM */
|
||||
int thread_join(pthread_t thread, void **retval);
|
||||
|
@ -282,8 +282,9 @@ void run()
|
||||
|
||||
/* Main program. */
|
||||
|
||||
int func_tiny()
|
||||
void * func_tiny(void *args)
|
||||
{
|
||||
(void)args;
|
||||
printf("Enter your program then ESC\n\n");
|
||||
printf("TinyC grammar\n");
|
||||
printf("<program> ::= <statement>\n");
|
||||
|
@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
int func_tiny();
|
||||
void * func_tiny(void *args);
|
||||
|
Loading…
Reference in New Issue
Block a user