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. --- private.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 132 insertions(+), 26 deletions(-) (limited to 'private.c') diff --git a/private.c b/private.c index 9499e07..77f0334 100644 --- a/private.c +++ b/private.c @@ -11,32 +11,138 @@ #include "pthread.h" #include "implement.h" +/* The threads table works as follows: + hash into the table, + if the thread in this slot doesn't match then start single + stepping from there until we find it, or we hit an empty slot, or + we end up where we started from. + + The scheme should have these characteristics: + - if the thread handle is a sequence number then the hash will + succeed first time every time, + - if the thread handle is a pseudo randomish value (eg. a pointer) + then the hash should succeed first time most times. + */ + int -_pthread_getthreadindex(pthread_t thread) +_pthread_new_thread_entry(pthread_t thread, + _pthread_threads_thread_t ** entry) { - /* The hash table works as follows: - hash into the table, - if the thread in this slot doesn't match then start single - stepping from there until we find it, or we hit an empty slot, or - we end up where we started from. - - The scheme should have these characteristics: - - if the thread handle is a sequence number then the hash will - succeed first time every time, - - if the thread handle is a pseudo randomish value (eg. a pointer) - then the hash should succeed first time most times. - */ - int t = _PTHREAD_HASH_INDEX(thread); - int it = t; /* Remember where we started from. */ - - while ((_pthread_threads_table[t])->thread != thread) { - t++; - - if (t == PTHREAD_THREADS_MAX) - t = 0; /* Wrap around to the first slot */ - - if ((_pthread_threads_table[t])->thread == NULL || t == it) - return -1; /* Failed to find the thread */ - } - return t; + _pthread_threads_thread_t ** this; + + if (_pthread_threads_count >= PTHREAD_THREADS_MAX) + { + return EAGAIN; + } + + this = &_pthread_threads_table[_PTHREAD_HASH_INDEX(thread)]; + + while ((*this)->thread != NULL) + { + this++; + + if (this == &_pthread_threads_table[PTHREAD_THREADS_MAX]) + { + /* Wrap to the top of the table. */ + this == _pthread_threads_table; + } + } + + if ((*this)->thread != NULL) + { + /* INTERNAL ERROR: There should be at least one slot left. */ + return ESRCH; + } + else + { + new = (_pthread_threads_thread_t *) malloc(sizeof(_pthread_threads_thread_t)); + + if (new == NULL) + { + return ENOMEM; + } + + new->thread = thread; + pthread_attr_init(&(new->attr)); + new->cleanupstack = NULL; + new->destructorstack = NULL; + new->forkpreparestack = NULL; + new->forkparentstack = NULL; + new->forkchildstack = NULL; + *this = new; + } + + _pthread_threads_count++; + entry = this; + + return 0; } + +_pthread_threads_thread ** +_pthread_find_thread_entry(pthread_t thread) +{ + _pthread_threads_thread_t ** this; + _pthread_threads_thread_t ** start; + + start = this = &_pthread_threads_table[_PTHREAD_HASH_INDEX(thread)]; + + while ((*this)->thread != thread) + { + this++; + + if (this == &_pthread_threads_table[PTHREAD_THREADS_MAX]) + { + /* Wrap to top of table. */ + this = _pthread_threads_table; + } + + if ((*this)->thread == NULL || this == start) + { + /* Failed to find the thread. */ + return -1; + } + } + + return this; +} + +void +_pthread_delete_thread_entry(_pthread_threads_thread_t ** this) +{ + /* We don't check that the thread has been properly cleaned up, so + it had better be done already. */ + _pthread_threads_thread ** this; + _pthread_threads_thread ** entry; + + /* CRITICAL SECTION */ + pthread_mutex_lock(&_pthread_count_mutex); + + /* If this is not NULL then we are removing an entry for a + failed thread start. If this is NULL we need to get this + here within the critical section. */ + if (this == NULL) + { + this = _PTHREAD_THIS; + } + + if (this != NULL) + { + entry = this; + /* Do this first to avoid contention and then free the storage. */ + this = NULL; + free(*entry); + + if (_pthread_threads_count > 0) + { + _pthread_threads_count--; + } + else + { + /* FIXME: INTERNAL ERROR: This should not happen. */ + } + } + + pthread_mutex_unlock(&_pthread_count_mutex); + /* END CRITICAL SECTION */ +} + -- cgit v1.2.3