diff --git a/so3/include/thread.h b/so3/include/thread.h index 7c53b09d4..8d1625eb3 100644 --- a/so3/include/thread.h +++ b/so3/include/thread.h @@ -80,7 +80,7 @@ struct tcb { pcb_t *pcb; int exit_status; - addr_t child_clear_tid; + int *clear_child_tid; struct list_head list; /* List of threads belonging to a process */ @@ -119,6 +119,7 @@ typedef struct { void threads_init(void); SYSCALL_DECLARE(exit, int exit_status); +SYSCALL_DECLARE(set_tid_address, int *tidptr); tcb_t *kernel_thread(th_fn_t start_routine, const char *name, void *arg, uint32_t prio); tcb_t *user_thread(clone_args_t *args); diff --git a/so3/kernel/thread.c b/so3/kernel/thread.c index 86efae402..c5b27a19a 100644 --- a/so3/kernel/thread.c +++ b/so3/kernel/thread.c @@ -266,12 +266,19 @@ void thread_exit(int exit_status) complete(&pcb->threads_active); } + /* If clear child tid is set, inform waiting thread */ + if (pcb && current() != pcb->main_thread) { + if (current()->clear_child_tid) { + *(current()->clear_child_tid) = 0; + do_futex(current()->clear_child_tid, FUTEX_WAKE, 1, NULL, NULL, 0, 0); + } + } + /* Check if this is a kernel thread OR a main thread before a image replacement (during exec()). * In this case, we do not leave the thread in zombie since we assume that no other threads are joining on it. * (This is currently a limitation: kernel threads can not join other threads). */ #warning Kernel threads cannot join other threads! -#warning TODO: check for clear_child_tid usage if (current()->pcb != NULL) zombie(); @@ -359,7 +366,7 @@ tcb_t *thread_create(clone_args_t *args) flags = local_irq_save(); - tcb = (tcb_t *) malloc(sizeof(tcb_t)); + tcb = (tcb_t *) calloc(1, sizeof(tcb_t)); if (tcb == NULL) { printk("%s: failed to alloc memory.\n", __func__); @@ -405,7 +412,7 @@ tcb_t *thread_create(clone_args_t *args) } if (args->flags & CLONE_CHILD_CLEARTID) - tcb->child_clear_tid = (addr_t) args->child_tid; + tcb->clear_child_tid = args->child_tid; local_irq_restore(flags); @@ -589,6 +596,12 @@ SYSCALL_DEFINE1(exit, int, exit_status) return 0; } +SYSCALL_DEFINE1(set_tid_address, int *, tidptr) +{ + current()->clear_child_tid = tidptr; + return current()->tid; +} + void threads_init(void) { int i; diff --git a/so3/syscall.tbl b/so3/syscall.tbl index 97c9611bd..adc0dcc31 100644 --- a/so3/syscall.tbl +++ b/so3/syscall.tbl @@ -48,6 +48,7 @@ getpid MMU execve MMU fork MMU clone MMU +set_tid_address MMU exit MMU exit_group MMU wait4 MMU