diff options
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 */ +} + | 
