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 /private.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 'private.c')
-rw-r--r-- | private.c | 158 |
1 files changed, 132 insertions, 26 deletions
@@ -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 */ +} + |