summaryrefslogtreecommitdiff
path: root/private.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 /private.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 'private.c')
-rw-r--r--private.c158
1 files changed, 132 insertions, 26 deletions
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 */
+}
+