From f33f4460f9de9c2d2ae6f3bf05caed391c6ad485 Mon Sep 17 00:00:00 2001 From: rpj Date: Wed, 22 Jul 1998 16:42:53 +0000 Subject: Wed Jul 22 00:16:22 1998 Ross Johnson * 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. --- create.c | 171 +++++++++++++++++++++++++++------------------------------------ 1 file changed, 73 insertions(+), 98 deletions(-) (limited to 'create.c') 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; } -- cgit v1.2.3