From ecf6b86c92e0d25ab16870477dce21531a7faee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 9 Nov 2009 21:33:35 +0000 Subject: [PATCH] * The pthread_thread structure is now allocated for all threads. * Therefore, all pthread functions should now work fine on all threads. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33967 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../private/libroot}/pthread_private.h | 5 +- headers/private/system/tls.h | 10 +-- src/system/libroot/os/thread.c | 64 ++++++++++++------- src/system/libroot/posix/pthread/pthread.c | 64 ++++++++++--------- 4 files changed, 84 insertions(+), 59 deletions(-) rename {src/system/libroot/posix/pthread => headers/private/libroot}/pthread_private.h (91%) diff --git a/src/system/libroot/posix/pthread/pthread_private.h b/headers/private/libroot/pthread_private.h similarity index 91% rename from src/system/libroot/posix/pthread/pthread_private.h rename to headers/private/libroot/pthread_private.h index 29ce14edfb..6477d30576 100644 --- a/src/system/libroot/posix/pthread/pthread_private.h +++ b/headers/private/libroot/pthread_private.h @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2003-2009, Axel Dörfler, axeld@pinc-software.de. * Copyright 2007, Ryan Leavengood, leavengood@gmail.com. * All rights reserved. Distributed under the terms of the MIT License. */ @@ -60,7 +60,6 @@ typedef struct _pthread_thread { bool cancelled; struct pthread_key_data specific[PTHREAD_KEYS_MAX]; struct __pthread_cleanup_handler *cleanup_handlers; - // TODO: move pthread keys in here, too } pthread_thread; @@ -69,6 +68,8 @@ extern "C" { #endif void __pthread_key_call_destructors(pthread_thread *thread); +void __pthread_destroy_thread(void); +pthread_thread *__allocate_pthread(void *data); #ifdef __cplusplus } diff --git a/headers/private/system/tls.h b/headers/private/system/tls.h index bd44614d3e..ebb470d859 100644 --- a/headers/private/system/tls.h +++ b/headers/private/system/tls.h @@ -1,10 +1,11 @@ -/* -** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. -** Distributed under the terms of the OpenBeOS License. -*/ +/* + * Copyright 2003-2009, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ #ifndef _KERNEL_TLS_H #define _KERNEL_TLS_H + #include @@ -18,6 +19,7 @@ enum { 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() diff --git a/src/system/libroot/os/thread.c b/src/system/libroot/os/thread.c index 51ce429155..2419ca21fc 100644 --- a/src/system/libroot/os/thread.c +++ b/src/system/libroot/os/thread.c @@ -1,5 +1,5 @@ /* - * Copyright 2002-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -29,10 +30,15 @@ typedef struct callback_node { 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(); @@ -40,10 +46,39 @@ thread_entry(thread_func entry, void *data) } +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 @@ spawn_thread(thread_func entry, const char *name, int32 priority, void *data) 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 @@ wait_for_thread(thread_id thread, status_t *_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); -} - - status_t on_exit_thread(void (*callback)(void *), void *data) { diff --git a/src/system/libroot/posix/pthread/pthread.c b/src/system/libroot/posix/pthread/pthread.c index ee40992a8b..b702de4863 100644 --- a/src/system/libroot/posix/pthread/pthread.c +++ b/src/system/libroot/posix/pthread/pthread.c @@ -14,6 +14,7 @@ #include #include +#include #define THREAD_DETACHED 0x01 @@ -28,12 +29,27 @@ static const pthread_attr pthread_attr_default = { 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(); @@ -54,18 +70,23 @@ pthread_destroy_thread(void* data) } -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 @@ pthread_create(pthread_t* _thread, const pthread_attr_t* _attr, 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_self(void) { 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;