Author: axeld Date: 2009-11-09 22:33:35 +0100 (Mon, 09 Nov 2009) New Revision: 33967 Changeset: http://dev.haiku-os.org/changeset/33967/haiku Added: haiku/trunk/headers/private/libroot/pthread_private.h Removed: haiku/trunk/src/system/libroot/posix/pthread/pthread_private.h Modified: haiku/trunk/headers/private/system/tls.h haiku/trunk/src/system/libroot/os/thread.c haiku/trunk/src/system/libroot/posix/pthread/pthread.c Log: * The pthread_thread structure is now allocated for all threads. * Therefore, all pthread functions should now work fine on all threads. Copied: haiku/trunk/headers/private/libroot/pthread_private.h (from rev 33960, haiku/trunk/src/system/libroot/posix/pthread/pthread_private.h) =================================================================== --- haiku/trunk/headers/private/libroot/pthread_private.h (rev 0) +++ haiku/trunk/headers/private/libroot/pthread_private.h 2009-11-09 21:33:35 UTC (rev 33967) @@ -0,0 +1,78 @@ +/* + * Copyright 2003-2009, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx + * Copyright 2007, Ryan Leavengood, leavengood@xxxxxxxxxx + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef _PTHREAD_PRIVATE_H_ +#define _PTHREAD_PRIVATE_H_ + + +#include <pthread.h> + +#include <OS.h> + +// The public *_t types are only pointers to these structures +// This way, we are completely free to change them, which might be +// necessary in the future (not only due to the incomplete implementation +// at this point). + +typedef struct _pthread_condattr { + bool process_shared; +} pthread_condattr; + +typedef struct _pthread_mutexattr { + int32 type; + bool process_shared; +} pthread_mutexattr; + +typedef struct _pthread_attr { + int32 detach_state; + int32 sched_priority; + size_t stack_size; +} pthread_attr; + +typedef struct _pthread_rwlockattr { + uint32_t flags; +} pthread_rwlockattr; + +typedef void (*pthread_key_destructor)(void *data); + +struct pthread_key { + vint32 sequence; + pthread_key_destructor destructor; +}; + +struct pthread_key_data { + vint32 sequence; + void *value; +}; + +#define PTHREAD_UNUSED_SEQUENCE 0 + +typedef struct _pthread_thread { + thread_id id; + int32 flags; + void *(*entry)(void*); + void *entry_argument; + void *exit_value; + int cancel_state; + int cancel_type; + bool cancelled; + struct pthread_key_data specific[PTHREAD_KEYS_MAX]; + struct __pthread_cleanup_handler *cleanup_handlers; +} pthread_thread; + + +#ifdef __cplusplus +extern "C" { +#endif + +void __pthread_key_call_destructors(pthread_thread *thread); +void __pthread_destroy_thread(void); +pthread_thread *__allocate_pthread(void *data); + +#ifdef __cplusplus +} +#endif + +#endif /* _PTHREAD_PRIVATE_H_ */ Modified: haiku/trunk/headers/private/system/tls.h =================================================================== --- haiku/trunk/headers/private/system/tls.h 2009-11-09 21:26:24 UTC (rev 33966) +++ haiku/trunk/headers/private/system/tls.h 2009-11-09 21:33:35 UTC (rev 33967) @@ -1,10 +1,11 @@ -/* -** Copyright 2003, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx All rights reserved. -** Distributed under the terms of the OpenBeOS License. -*/ +/* + * Copyright 2003-2009, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx + * Distributed under the terms of the MIT License. + */ #ifndef _KERNEL_TLS_H #define _KERNEL_TLS_H + #include <support/TLS.h> @@ -18,6 +19,7 @@ TLS_ERRNO_SLOT, TLS_ON_EXIT_THREAD_SLOT, TLS_USER_THREAD_SLOT, + TLS_PTHREAD_SLOT, // Note: these entries can safely be changed between // releases; 3rd party code always calls tls_allocate() Modified: haiku/trunk/src/system/libroot/os/thread.c =================================================================== --- haiku/trunk/src/system/libroot/os/thread.c 2009-11-09 21:26:24 UTC (rev 33966) +++ haiku/trunk/src/system/libroot/os/thread.c 2009-11-09 21:33:35 UTC (rev 33967) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2005, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx All rights reserved. + * Copyright 2002-2009, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx * Distributed under the terms of the MIT License. */ @@ -10,6 +10,7 @@ #include <stdio.h> #include <libroot_private.h> +#include <pthread_private.h> #include <thread_defs.h> #include <tls.h> #include <syscalls.h> @@ -29,22 +30,56 @@ void _thread_do_exit_notification(void); -static int32 -thread_entry(thread_func entry, void *data) +static status_t +thread_entry(thread_func entry, void* _thread) { - int32 returnCode = entry(data); + pthread_thread* thread = (pthread_thread*)_thread; + status_t returnCode; + *tls_address(TLS_PTHREAD_SLOT) = thread; + + returnCode = entry(thread->entry_argument); + _thread_do_exit_notification(); return returnCode; } +void +_thread_do_exit_notification(void) +{ + callback_node *node = tls_get(TLS_ON_EXIT_THREAD_SLOT); + callback_node *next; + + while (node != NULL) { + next = node->next; + + node->function(node->argument); + free(node); + + node = next; + } + + tls_set(TLS_ON_EXIT_THREAD_SLOT, NULL); + + __pthread_destroy_thread(); +} + + +// #pragma mark - + + thread_id spawn_thread(thread_func entry, const char *name, int32 priority, void *data) { struct thread_creation_attributes attributes; + pthread_thread* thread; + thread = __allocate_pthread(data); + if (thread == NULL) + return B_NO_MEMORY; + _single_threaded = false; // used for I/O locking - BeOS compatibility issue @@ -52,7 +87,7 @@ attributes.name = name; attributes.priority = priority; attributes.args1 = entry; - attributes.args2 = data; + attributes.args2 = thread; attributes.stack_address = NULL; attributes.stack_size = 0; @@ -110,25 +145,6 @@ } -void -_thread_do_exit_notification(void) -{ - callback_node *node = tls_get(TLS_ON_EXIT_THREAD_SLOT); - callback_node *next; - - while (node != NULL) { - next = node->next; - - node->function(node->argument); - free(node); - - node = next; - } - - tls_set(TLS_ON_EXIT_THREAD_SLOT, NULL); -} - - status_t on_exit_thread(void (*callback)(void *), void *data) { Modified: haiku/trunk/src/system/libroot/posix/pthread/pthread.c =================================================================== --- haiku/trunk/src/system/libroot/posix/pthread/pthread.c 2009-11-09 21:26:24 UTC (rev 33966) +++ haiku/trunk/src/system/libroot/posix/pthread/pthread.c 2009-11-09 21:33:35 UTC (rev 33967) @@ -14,6 +14,7 @@ #include <syscalls.h> #include <thread_defs.h> +#include <tls.h> #define THREAD_DETACHED 0x01 @@ -28,13 +29,28 @@ static pthread_thread sMainThread; -static int32 sPthreadSlot = -1; static int sConcurrencyLevel; -static void -pthread_destroy_thread(void* data) +static status_t +pthread_thread_entry(thread_func _unused, void* _thread) { + pthread_thread* thread = (pthread_thread*)_thread; + + // store thread data in TLS + *tls_address(TLS_PTHREAD_SLOT) = thread; + + pthread_exit(thread->entry(thread->entry_argument)); + return 0; +} + + +// #pragma mark - private API + + +void +__pthread_destroy_thread(void) +{ pthread_thread* thread = pthread_self(); // call cleanup handlers @@ -54,18 +70,23 @@ } -static int32 -pthread_thread_entry(thread_func _unused, void* _thread) +pthread_thread* +__allocate_pthread(void *data) { - pthread_thread* thread = (pthread_thread*)_thread; + pthread_thread* thread = (pthread_thread*)malloc(sizeof(pthread_thread)); + if (thread == NULL) + return NULL; - // store thread data in TLS - *tls_address(sPthreadSlot) = thread; + thread->entry = NULL; + thread->entry_argument = data; + thread->exit_value = NULL; + thread->cancel_state = PTHREAD_CANCEL_ENABLE; + thread->cancel_type = PTHREAD_CANCEL_DEFERRED; + thread->cancelled = false; + thread->cleanup_handlers = NULL; + thread->flags = 0; - on_exit_thread(pthread_destroy_thread, NULL); - - pthread_exit(thread->entry(thread->entry_argument)); - return 0; + return thread; } @@ -91,27 +112,15 @@ return EINVAL; } - thread = (pthread_thread*)malloc(sizeof(pthread_thread)); + thread = __allocate_pthread(arg); if (thread == NULL) return EAGAIN; thread->entry = startRoutine; - thread->entry_argument = arg; - thread->exit_value = NULL; - thread->cancel_state = PTHREAD_CANCEL_ENABLE; - thread->cancel_type = PTHREAD_CANCEL_DEFERRED; - thread->cancelled = false; - thread->cleanup_handlers = NULL; - thread->flags = 0; if (attr->detach_state == PTHREAD_CREATE_DETACHED) thread->flags |= THREAD_DETACHED; - if (sPthreadSlot == -1) { - // In a clean pthread environment, this is even thread-safe! - sPthreadSlot = tls_allocate(); - } - attributes.entry = pthread_thread_entry; attributes.name = "pthread func"; attributes.priority = attr->sched_priority; @@ -139,10 +148,7 @@ { pthread_thread* thread; - if (sPthreadSlot == -1) - return &sMainThread; - - thread = (pthread_thread*)tls_get(sPthreadSlot); + thread = (pthread_thread*)tls_get(TLS_PTHREAD_SLOT); if (thread == NULL) return &sMainThread;