* 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:
parent
f982813b1e
commit
ecf6b86c92
@ -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
|
||||
}
|
@ -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()
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user