diff options
author | rpj <rpj> | 1998-07-22 16:42:53 +0000 |
---|---|---|
committer | rpj <rpj> | 1998-07-22 16:42:53 +0000 |
commit | f33f4460f9de9c2d2ae6f3bf05caed391c6ad485 (patch) | |
tree | 12bb86525d369c1c4de220bb58d92d3eab2f5a7e /create.c | |
parent | b84f1cc523f4236200689b2f78b16b26bc05f429 (diff) |
Wed Jul 22 00:16:22 1998 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
* attr.c, implement.h, pthread.h, ChangeLog: Resolve CVS merge
conflicts.
* private.c (_pthread_find_thread_entry): Changes to return type
to support leaner _pthread_threads_table[] which now only stores
_pthread_thread_thread_t *.
(_pthread_new_thread_entry): Internal changes.
(_pthread_delete_thread_entry): Internal changes to avoid contention.
Calling routines changed accordingly.
* pthread.h: Modified cleanup macros to use new generic push and pop.
Added destructor and atfork stacks to _pthread_threads_thread_t.
* cleanup.c (_pthread_handler_push, _pthread_handler_pop,
_pthread_handler_pop_all): Renamed cleanup push and pop routines
and made generic to handle destructors and atfork handlers as
well.
* create.c (_pthread_start_call): New function is a wrapper for
all new threads. It allows us to do some cleanup when the thread
returns, ie. that is otherwise only done if the thread is cancelled.
* exit.c (_pthread_vacuum): New function contains code from
pthread_exit() that we need in the new _pthread_start_call()
as well.
* implement.h: Various additions and minor changes.
* pthread.h: Various additions and minor changes.
Change cleanup handler macros to use generic handler push and pop
functions.
* attr.c: Minor mods to all functions.
(is_attr): Implemented missing function.
* create.c (pthread_create): More clean up.
* private.c (_pthread_find_thread_entry): Implement.
(_pthread_delete_thread_entry): Implement.
(_pthread_new_thread_entry): Implement.
These functions manipulate the implementations internal thread
table and are part of general code cleanup and modularisation.
They replace _pthread_getthreadindex() which was removed.
* exit.c (pthread_exit): Changed to use the new code above.
* pthread.h: Add cancelability constants. Update comments.
Diffstat (limited to 'create.c')
-rw-r--r-- | create.c | 171 |
1 files changed, 73 insertions, 98 deletions
@@ -11,18 +11,34 @@ #include "pthread.h" #include "implement.h" +unsigned +_pthread_start_call(void *this) +{ + /* We're now in a running thread. Any local variables here are on + this threads private stack so we're safe to leave data in them + until we leave. */ + unsigned (*func)(void *) = this->call.routine; + void * arg = this->call.arg; + unsigned ret; + + ret = (*func)(arg); + + /* If we get to here then we're returning naturally and haven't + been cancelled. We need to cleanup and remove the thread + from the threads table. */ + _pthread_vacuum(); + + return ret; +} + int -pthread_create(pthread_t *thread, const pthread_attr_t *attr, - void * (*start_routine) (void *), void * arg) +pthread_create(pthread_t *thread, + const pthread_attr_t *attr, + void * (*start_routine) (void *), + void * arg) { - /* Call Win32 CreateThread. - Map attributes as correctly as possible. - The passed in attr structure will be modified by this routine - to reflect any default values used. This is POSIX semantics. - */ HANDLE handle = NULL; unsigned flags; - unsigned stack; void * security = NULL; /* FIXME: This needs to be moved into process space. @@ -33,109 +49,68 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr, */ SECURITY_ATTRIBUTES security_attr; DWORD threadID; - int t; - int ret = 0; /* Success unless otherwise set */ - char * privmem; + /* Success unless otherwise set. */ + int ret = 0; pthread_attr_t * attr_copy; - _pthread_cleanup_stack_t * cleanup_stack; - - /* Use and modify attr_copy. Only after we've succeeded in creating the - new thread can we modify any passed-in structures. - - To save time we use one malloc() to get all of our heap space and - then allocate it further. - */ - - if (NULL == - (privmem = (char) malloc(RND_SIZEOF(pthread_attr_t) + - RND_SIZEOF(_pthread_cleanup_stack_t)))) { - return EAGAIN; - } - - attr_copy = (pthread_attr_t *) privmem; - - /* Force cleanup_stack to start at a DWORD boundary within privmem. - */ - cleanup_stack = - (_pthread_cleanup_stack_t *) &privmem[RND_SIZEOF(pthread_attr_t)]; - - (void) memcpy(attr_copy, attr); + _pthread_threads_thread_t * this; /* CRITICAL SECTION */ pthread_mutex_lock(&_pthread_count_mutex); - if (_pthread_threads_count < PTHREAD_THREADS_MAX) { - switch (attr) - { - case NULL: - /* Use POSIX default attributes */ - stack = attr_copy->stacksize = PTHREAD_STACK_MIN; - break; - default: - /* Map attributes */ - if (attr_copy.stacksize != NULL) - stack = (DWORD) attr_copy->stacksize; - else - stack = attr_copy->stacksize = PTHREAD_STACK_MIN; - break; - } - - flags = 1; /* Start suspended and resume at the last moment to avoid - race conditions, ie. where a thread may enquire it's - attributes before we finish storing them away. - */ - - handle = (HANDLE) _beginthreadex(security, - stack, - (unsigned (_stdcall *)(void *)) start_routine, - arg, - flags, - &threadID); - - if (handle != NULL) { - _pthread_threads_count++; - - /* The hash table works as follows: - hash into the table, - if the slot is occupied then start single stepping from there - until we find an available slot. - */ - t = _PTHREAD_HASH_INDEX(handle); - while ((_pthread_threads_table[t])->thread != NULL) { - t++; - - if (t == PTHREAD_THREADS_MAX) - t = 0; /* Wrap to the top of the table. */ - } - - if ((_pthread_threads_table[t])->thread != NULL) { - /* INTERNAL ERROR */ - } else { - (_pthread_threads_table[t])->thread = handle; - (_pthread_threads_table[t])->attr = attr_copy; - (_pthread_threads_table[t])->cleanupstack = cleanup_stack; - } - } else { + if (_pthread_new_thread_entry((pthread_t) handle, &this) == 0) + { + attr_copy = &(this->attr); + + if (attr != NULL) + { + /* Map attributes */ + if (attr_copy->stacksize == 0) + { + attr_copy->stacksize = PTHREAD_STACK_MIN; + } + + attr_copy->cancelability = attr->cancelability; + } + + /* Start suspended and resume at the last moment to avoid + race conditions, ie. where a thread may enquire it's + attributes before we finish storing them away. */ + flags = 1; + + handle = (HANDLE) _beginthreadex(security, + attr_copy->stacksize, + _pthread_start_call, + (void *) this, + flags, + &threadID); + + if (handle == NULL) + { + ret = EAGAIN; + } + } + else + { ret = EAGAIN; } - } else { - ret = EAGAIN; - } /* Let others in as soon as possible. */ pthread_mutex_unlock(&_pthread_count_mutex); /* END CRITICAL SECTION */ - if (ret == 0) { - *thread = (pthread_t) handle; - (void) memcpy(attr, attr_copy); + if (ret == 0) + { + /* Let the caller know the thread handle. */ + *thread = (pthread_t) handle; - /* POSIX threads are always running after creation. - */ - ResumeThread(handle); - } else { - free(privmem); - } + /* POSIX threads are always running after creation. */ + ResumeThread(handle); + } + else + { + /* Undo everything. */ + _pthread_delete_thread_entry(this); + } return ret; } |