* 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
This commit is contained in:
Axel Dörfler 2009-11-09 21:33:35 +00:00
parent f982813b1e
commit ecf6b86c92
4 changed files with 84 additions and 59 deletions

View File

@ -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
}

View File

@ -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 <support/TLS.h>
@ -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()

View File

@ -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 <stdio.h>
#include <libroot_private.h>
#include <pthread_private.h>
#include <thread_defs.h>
#include <tls.h>
#include <syscalls.h>
@ -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)
{

View File

@ -14,6 +14,7 @@
#include <syscalls.h>
#include <thread_defs.h>
#include <tls.h>
#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;