user_thread #9
@ -191,3 +191,39 @@ pid_t processGetId(struct process *proc){
|
|||||||
pid_t processGetNextTid(struct process *proc){
|
pid_t processGetNextTid(struct process *proc){
|
||||||
return proc->nextTid++;
|
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);
|
int processInitHeap(struct process *proc, uaddr_t lastUserAddr);
|
||||||
pid_t processGetId(struct process *proc);
|
pid_t processGetId(struct process *proc);
|
||||||
pid_t processGetNextTid(struct process *proc);
|
pid_t processGetNextTid(struct process *proc);
|
||||||
|
int processJoinThread(struct process *proc, pid_t tid);
|
||||||
|
@ -172,11 +172,20 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SYSCALL_ID_GETPID: {
|
case SYSCALL_ID_GETPID: {
|
||||||
ret = processGetId(getCurrentThread()->process);
|
ret = processGetId(getCurrentThread()->process);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SYSCALL_ID_GETTID: {
|
case SYSCALL_ID_GETTID: {
|
||||||
ret = threadGetId(getCurrentThread());
|
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;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#define SYSCALL_ID_USLEEP 10
|
#define SYSCALL_ID_USLEEP 10
|
||||||
#define SYSCALL_ID_GETPID 11
|
#define SYSCALL_ID_GETPID 11
|
||||||
#define SYSCALL_ID_GETTID 12
|
#define SYSCALL_ID_GETTID 12
|
||||||
|
#define SYSCALL_ID_THREAD_JOIN 13
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
int syscallExecute(int syscallId, const struct cpu_state *user_ctx);
|
int syscallExecute(int syscallId, const struct cpu_state *user_ctx);
|
||||||
|
@ -89,8 +89,9 @@ struct thread *threadCreate(const char *name, cpu_kstate_function_arg1_t func, v
|
|||||||
(cpu_kstate_function_arg1_t *)threadExit, 0))
|
(cpu_kstate_function_arg1_t *)threadExit, 0))
|
||||||
goto free_mem;
|
goto free_mem;
|
||||||
|
|
||||||
thread->state = READY;
|
thread->state = READY;
|
||||||
thread->tid = nextTid++;
|
thread->tid = nextTid++;
|
||||||
|
thread->wqExit = NULL;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
disable_IRQs(flags);
|
disable_IRQs(flags);
|
||||||
list_add_tail(currentThread, thread);
|
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->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)
|
if (name)
|
||||||
strzcpy(thread->name, name, THREAD_NAME_MAX_LENGTH);
|
strzcpy(thread->name, name, THREAD_NAME_MAX_LENGTH);
|
||||||
else
|
else
|
||||||
@ -151,6 +160,10 @@ void threadDelete(struct thread *thread)
|
|||||||
restore_IRQs(flags);
|
restore_IRQs(flags);
|
||||||
assert(thread->state == EXITING);
|
assert(thread->state == EXITING);
|
||||||
|
|
||||||
|
if (thread->wqExit) {
|
||||||
|
waitUp(thread->wqExit);
|
||||||
|
}
|
||||||
|
|
||||||
if (thread->squattedContext) {
|
if (thread->squattedContext) {
|
||||||
threadChangeCurrentContext(NULL);
|
threadChangeCurrentContext(NULL);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ struct thread;
|
|||||||
#include "cpu_context.h"
|
#include "cpu_context.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "process.h"
|
#include "process.h"
|
||||||
|
#include "wait.h"
|
||||||
|
|
||||||
#define THREAD_NAME_MAX_LENGTH 32
|
#define THREAD_NAME_MAX_LENGTH 32
|
||||||
#define THREAD_DEFAULT_STACK_SIZE PAGE_SIZE
|
#define THREAD_DEFAULT_STACK_SIZE PAGE_SIZE
|
||||||
@ -35,6 +36,7 @@ struct thread {
|
|||||||
// For User thread only
|
// For User thread only
|
||||||
struct thread *nextInProcess, *prevInProcess;
|
struct thread *nextInProcess, *prevInProcess;
|
||||||
struct process *process;
|
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
|
* Address space currently "squatted" by the thread, or used to be
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#define SYSCALL_ID_USLEEP 10
|
#define SYSCALL_ID_USLEEP 10
|
||||||
#define SYSCALL_ID_GETPID 11
|
#define SYSCALL_ID_GETPID 11
|
||||||
#define SYSCALL_ID_GETTID 12
|
#define SYSCALL_ID_GETTID 12
|
||||||
|
#define SYSCALL_ID_THREAD_JOIN 13
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
int syscallExecute(int syscallId, const struct cpu_state *user_ctx);
|
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);
|
(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) {
|
int usleep(useconds_t usec) {
|
||||||
return syscall1(SYSCALL_ID_USLEEP, (unsigned int)usec);
|
return syscall1(SYSCALL_ID_USLEEP, (unsigned int)usec);
|
||||||
}
|
}
|
||||||
|
@ -124,14 +124,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 %lu\n", gettid());
|
printf("Hello World from thread %lu\n", gettid());
|
||||||
usleep(100);
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int func_thread() {
|
int func_thread() {
|
||||||
pthread_t id;
|
pthread_t id;
|
||||||
|
void *retval;
|
||||||
thread_create(&id, print_hello, NULL, 4096);
|
thread_create(&id, print_hello, NULL, 4096);
|
||||||
|
thread_join(id, &retval);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -163,7 +164,10 @@ int main(int argc, char *argv[]) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (strcmp(buf, "tiny") == 0) {
|
if (strcmp(buf, "tiny") == 0) {
|
||||||
func_tiny();
|
pthread_t id;
|
||||||
|
void *retval;
|
||||||
|
thread_create(&id, func_tiny, NULL, 4096);
|
||||||
|
thread_join(id, &retval);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (strcmp(buf, "mmap") == 0) {
|
if (strcmp(buf, "mmap") == 0) {
|
||||||
|
@ -4,3 +4,5 @@
|
|||||||
typedef unsigned long int pthread_t;
|
typedef unsigned long int pthread_t;
|
||||||
typedef void *(start_routine)(void *);
|
typedef void *(start_routine)(void *);
|
||||||
int thread_create(pthread_t *thread, start_routine *func, void *arg, size_t stackSize);
|
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. */
|
/* Main program. */
|
||||||
|
|
||||||
int func_tiny()
|
void * func_tiny(void *args)
|
||||||
{
|
{
|
||||||
|
(void)args;
|
||||||
printf("Enter your program then ESC\n\n");
|
printf("Enter your program then ESC\n\n");
|
||||||
printf("TinyC grammar\n");
|
printf("TinyC grammar\n");
|
||||||
printf("<program> ::= <statement>\n");
|
printf("<program> ::= <statement>\n");
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
int func_tiny();
|
void * func_tiny(void *args);
|
||||||
|
Loading…
Reference in New Issue
Block a user