summaryrefslogtreecommitdiff
path: root/create.c
diff options
context:
space:
mode:
authorrpj <rpj>1998-07-22 16:42:53 +0000
committerrpj <rpj>1998-07-22 16:42:53 +0000
commitf33f4460f9de9c2d2ae6f3bf05caed391c6ad485 (patch)
tree12bb86525d369c1c4de220bb58d92d3eab2f5a7e /create.c
parentb84f1cc523f4236200689b2f78b16b26bc05f429 (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.c171
1 files changed, 73 insertions, 98 deletions
diff --git a/create.c b/create.c
index 3814a23..37ce88f 100644
--- a/create.c
+++ b/create.c
@@ -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;
}