* 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:
+3
-2
@@ -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.
|
* Copyright 2007, Ryan Leavengood, leavengood@gmail.com.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
@@ -60,7 +60,6 @@ typedef struct _pthread_thread {
|
|||||||
bool cancelled;
|
bool cancelled;
|
||||||
struct pthread_key_data specific[PTHREAD_KEYS_MAX];
|
struct pthread_key_data specific[PTHREAD_KEYS_MAX];
|
||||||
struct __pthread_cleanup_handler *cleanup_handlers;
|
struct __pthread_cleanup_handler *cleanup_handlers;
|
||||||
// TODO: move pthread keys in here, too
|
|
||||||
} pthread_thread;
|
} pthread_thread;
|
||||||
|
|
||||||
|
|
||||||
@@ -69,6 +68,8 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void __pthread_key_call_destructors(pthread_thread *thread);
|
void __pthread_key_call_destructors(pthread_thread *thread);
|
||||||
|
void __pthread_destroy_thread(void);
|
||||||
|
pthread_thread *__allocate_pthread(void *data);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2003, Axel Dörfler, [email protected]. All rights reserved.
|
* Copyright 2003-2009, Axel Dörfler, [email protected].
|
||||||
** Distributed under the terms of the OpenBeOS License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef _KERNEL_TLS_H
|
#ifndef _KERNEL_TLS_H
|
||||||
#define _KERNEL_TLS_H
|
#define _KERNEL_TLS_H
|
||||||
|
|
||||||
|
|
||||||
#include <support/TLS.h>
|
#include <support/TLS.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ enum {
|
|||||||
TLS_ERRNO_SLOT,
|
TLS_ERRNO_SLOT,
|
||||||
TLS_ON_EXIT_THREAD_SLOT,
|
TLS_ON_EXIT_THREAD_SLOT,
|
||||||
TLS_USER_THREAD_SLOT,
|
TLS_USER_THREAD_SLOT,
|
||||||
|
TLS_PTHREAD_SLOT,
|
||||||
|
|
||||||
// Note: these entries can safely be changed between
|
// Note: these entries can safely be changed between
|
||||||
// releases; 3rd party code always calls tls_allocate()
|
// releases; 3rd party code always calls tls_allocate()
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2005, Axel Dörfler, [email protected]. All rights reserved.
|
* Copyright 2002-2009, Axel Dörfler, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <libroot_private.h>
|
#include <libroot_private.h>
|
||||||
|
#include <pthread_private.h>
|
||||||
#include <thread_defs.h>
|
#include <thread_defs.h>
|
||||||
#include <tls.h>
|
#include <tls.h>
|
||||||
#include <syscalls.h>
|
#include <syscalls.h>
|
||||||
@@ -29,10 +30,15 @@ typedef struct callback_node {
|
|||||||
void _thread_do_exit_notification(void);
|
void _thread_do_exit_notification(void);
|
||||||
|
|
||||||
|
|
||||||
static int32
|
static status_t
|
||||||
thread_entry(thread_func entry, void *data)
|
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();
|
_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
|
thread_id
|
||||||
spawn_thread(thread_func entry, const char *name, int32 priority, void *data)
|
spawn_thread(thread_func entry, const char *name, int32 priority, void *data)
|
||||||
{
|
{
|
||||||
struct thread_creation_attributes attributes;
|
struct thread_creation_attributes attributes;
|
||||||
|
pthread_thread* thread;
|
||||||
|
|
||||||
|
thread = __allocate_pthread(data);
|
||||||
|
if (thread == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
_single_threaded = false;
|
_single_threaded = false;
|
||||||
// used for I/O locking - BeOS compatibility issue
|
// 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.name = name;
|
||||||
attributes.priority = priority;
|
attributes.priority = priority;
|
||||||
attributes.args1 = entry;
|
attributes.args1 = entry;
|
||||||
attributes.args2 = data;
|
attributes.args2 = thread;
|
||||||
attributes.stack_address = NULL;
|
attributes.stack_address = NULL;
|
||||||
attributes.stack_size = 0;
|
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
|
status_t
|
||||||
on_exit_thread(void (*callback)(void *), void *data)
|
on_exit_thread(void (*callback)(void *), void *data)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include <syscalls.h>
|
#include <syscalls.h>
|
||||||
#include <thread_defs.h>
|
#include <thread_defs.h>
|
||||||
|
#include <tls.h>
|
||||||
|
|
||||||
|
|
||||||
#define THREAD_DETACHED 0x01
|
#define THREAD_DETACHED 0x01
|
||||||
@@ -28,12 +29,27 @@ static const pthread_attr pthread_attr_default = {
|
|||||||
|
|
||||||
|
|
||||||
static pthread_thread sMainThread;
|
static pthread_thread sMainThread;
|
||||||
static int32 sPthreadSlot = -1;
|
|
||||||
static int sConcurrencyLevel;
|
static int sConcurrencyLevel;
|
||||||
|
|
||||||
|
|
||||||
static void
|
static status_t
|
||||||
pthread_destroy_thread(void* data)
|
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();
|
pthread_thread* thread = pthread_self();
|
||||||
|
|
||||||
@@ -54,18 +70,23 @@ pthread_destroy_thread(void* data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int32
|
pthread_thread*
|
||||||
pthread_thread_entry(thread_func _unused, void* _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
|
thread->entry = NULL;
|
||||||
*tls_address(sPthreadSlot) = thread;
|
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);
|
return thread;
|
||||||
|
|
||||||
pthread_exit(thread->entry(thread->entry_argument));
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -91,27 +112,15 @@ pthread_create(pthread_t* _thread, const pthread_attr_t* _attr,
|
|||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
thread = (pthread_thread*)malloc(sizeof(pthread_thread));
|
thread = __allocate_pthread(arg);
|
||||||
if (thread == NULL)
|
if (thread == NULL)
|
||||||
return EAGAIN;
|
return EAGAIN;
|
||||||
|
|
||||||
thread->entry = startRoutine;
|
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)
|
if (attr->detach_state == PTHREAD_CREATE_DETACHED)
|
||||||
thread->flags |= THREAD_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.entry = pthread_thread_entry;
|
||||||
attributes.name = "pthread func";
|
attributes.name = "pthread func";
|
||||||
attributes.priority = attr->sched_priority;
|
attributes.priority = attr->sched_priority;
|
||||||
@@ -139,10 +148,7 @@ pthread_self(void)
|
|||||||
{
|
{
|
||||||
pthread_thread* thread;
|
pthread_thread* thread;
|
||||||
|
|
||||||
if (sPthreadSlot == -1)
|
thread = (pthread_thread*)tls_get(TLS_PTHREAD_SLOT);
|
||||||
return &sMainThread;
|
|
||||||
|
|
||||||
thread = (pthread_thread*)tls_get(sPthreadSlot);
|
|
||||||
if (thread == NULL)
|
if (thread == NULL)
|
||||||
return &sMainThread;
|
return &sMainThread;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user