diff --git a/libpthread/Makefile b/libpthread/Makefile
index 9e1ea196..f6a3f729 100644
--- a/libpthread/Makefile
+++ b/libpthread/Makefile
@@ -30,6 +30,7 @@ pthread_equal.o \
pthread_exit.o \
pthread_getspecific.o \
pthread_initialize.o \
+pthread_join.o \
pthread_key_create.o \
pthread_key_delete.o \
pthread_mutexattr_destroy.o \
diff --git a/libpthread/include/pthread.h b/libpthread/include/pthread.h
index 50632da5..c5f09508 100644
--- a/libpthread/include/pthread.h
+++ b/libpthread/include/pthread.h
@@ -138,8 +138,10 @@ typedef __pthread_t pthread_t;
struct pthread
{
struct uthread uthread;
+ pthread_mutex_t join_lock;
void* (*entry_function)(void*);
void* entry_cookie;
+ void* exit_result;
void** keys;
size_t keys_length;
};
@@ -242,7 +244,7 @@ void pthread_exit(void*);
/* TODO: pthread_getcpuclockid */
/* TODO: pthread_getschedparam */
void* pthread_getspecific(pthread_key_t);
-/* TODO: pthread_join */
+int pthread_join(pthread_t, void**);
int pthread_key_create(pthread_key_t*, void (*)(void*));
int pthread_key_delete(pthread_key_t);
/* TODO: pthread_mutex_consistent */
diff --git a/libpthread/pthread_create.c++ b/libpthread/pthread_create.c++
index ec7c2fb1..f174fb32 100644
--- a/libpthread/pthread_create.c++
+++ b/libpthread/pthread_create.c++
@@ -203,6 +203,10 @@ int pthread_create(pthread_t* restrict thread_ptr,
thread->uthread.tls_size = tls_size;
thread->uthread.arg_mmap = self->uthread.arg_mmap;
thread->uthread.arg_size = self->uthread.arg_size;
+ thread->join_lock = PTHREAD_NORMAL_MUTEX_INITIALIZER_NP;
+ thread->join_lock.lock = 1 /* LOCKED_VALUE */;
+ thread->join_lock.type = PTHREAD_MUTEX_NORMAL;
+ thread->join_lock.owner = (unsigned long) thread;
thread->entry_function = entry_function;
thread->entry_cookie = entry_cookie;
diff --git a/libpthread/pthread_exit.c++ b/libpthread/pthread_exit.c++
index edb2348b..c2835a19 100644
--- a/libpthread/pthread_exit.c++
+++ b/libpthread/pthread_exit.c++
@@ -31,7 +31,7 @@
extern "C"
__attribute__((__noreturn__))
-void pthread_exit(void* /*return_value*/)
+void pthread_exit(void* return_value)
{
struct pthread* thread = pthread_self();
@@ -61,10 +61,13 @@ void pthread_exit(void* /*return_value*/)
pthread_mutex_unlock(&__pthread_num_threads_lock);
if ( num_threads == 1 )
exit(0);
+ thread->exit_result = return_value;
struct exit_thread extended;
memset(&extended, 0, sizeof(extended));
extended.unmap_from = thread->uthread.stack_mmap;
extended.unmap_size = thread->uthread.stack_size;
- exit_thread(0, EXIT_THREAD_UNMAP, &extended);
+ extended.zero_from = &thread->join_lock.lock;
+ extended.zero_size = sizeof(thread->join_lock.lock);
+ exit_thread(0, EXIT_THREAD_UNMAP | EXIT_THREAD_ZERO, &extended);
__builtin_unreachable();
}
diff --git a/libpthread/pthread_initialize.c++ b/libpthread/pthread_initialize.c++
index 644a4db3..9c744db0 100644
--- a/libpthread/pthread_initialize.c++
+++ b/libpthread/pthread_initialize.c++
@@ -72,4 +72,10 @@ static void elf_note_sortix_pthread_size()
extern "C" void pthread_initialize(void)
{
+ struct pthread* self = pthread_self();
+
+ self->join_lock = PTHREAD_NORMAL_MUTEX_INITIALIZER_NP;
+ self->join_lock.lock = 1 /* LOCKED_VALUE */;
+ self->join_lock.type = PTHREAD_MUTEX_NORMAL;
+ self->join_lock.owner = (unsigned long) self;
}
diff --git a/libpthread/pthread_join.c++ b/libpthread/pthread_join.c++
new file mode 100644
index 00000000..a57f2be1
--- /dev/null
+++ b/libpthread/pthread_join.c++
@@ -0,0 +1,40 @@
+/*******************************************************************************
+
+ Copyright(C) Jonas 'Sortie' Termansen 2014.
+
+ This file is part of Sortix libpthread.
+
+ Sortix libpthread is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation, either version 3 of the License, or (at your
+ option) any later version.
+
+ Sortix libpthread is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with Sortix libpthread. If not, see .
+
+ pthread_join.c++
+ Wait for thread termination.
+
+*******************************************************************************/
+
+#include
+
+#include
+#include
+#include
+
+extern "C" int pthread_join(pthread_t thread, void** result_ptr)
+{
+ pthread_mutex_lock(&thread->join_lock);
+ pthread_mutex_unlock(&thread->join_lock);
+ void* result = thread->exit_result;
+ munmap(thread->uthread.tls_mmap, thread->uthread.tls_size);
+ if ( result_ptr )
+ *result_ptr = result;
+ return 0;
+}