示例#1
0
文件: specific.c 项目: dotrees/tools
void __pthread_destroy_specifics()
{
  pthread_descr self = thread_self();
  int i, j, round, found_nonzero;
  destr_function destr;
  void * data;

  for (round = 0, found_nonzero = 1;
       found_nonzero && round < PTHREAD_DESTRUCTOR_ITERATIONS;
       round++) {
    found_nonzero = 0;
    for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++)
      if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL)
        for (j = 0; j < PTHREAD_KEY_2NDLEVEL_SIZE; j++) {
          destr = pthread_keys[i * PTHREAD_KEY_2NDLEVEL_SIZE + j].destr;
          data = THREAD_GETMEM_NC(self, p_specific[i])[j];
          if (destr != NULL && data != NULL) {
            THREAD_GETMEM_NC(self, p_specific[i])[j] = NULL;
            destr(data);
            found_nonzero = 1;
          }
        }
  }
  __pthread_lock(THREAD_GETMEM(self, p_lock), self);
  for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++) {
    if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL) {
      free(THREAD_GETMEM_NC(self, p_specific[i]));
      THREAD_SETMEM_NC(self, p_specific[i], NULL);
    }
  }
  __pthread_unlock(THREAD_GETMEM(self, p_lock));
}
示例#2
0
文件: specific.c 项目: dotrees/tools
void * __pthread_getspecific(pthread_key_t key)
{
  pthread_descr self = thread_self();
  unsigned int idx1st, idx2nd;

  if (key >= PTHREAD_KEYS_MAX)
    return NULL;
  idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE;
  idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE;
  if (THREAD_GETMEM_NC(self, p_specific[idx1st]) == NULL
      || !pthread_keys[key].in_use)
    return NULL;
  return THREAD_GETMEM_NC(self, p_specific[idx1st])[idx2nd];
}
示例#3
0
文件: specific.c 项目: dotrees/tools
static void *
libc_internal_tsd_get(enum __libc_tsd_key_t key)
{
  pthread_descr self = thread_self();

  return THREAD_GETMEM_NC(self, p_libc_specific[key]);
}
示例#4
0
文件: specific.c 项目: Jaden-J/uClibc
void *
__pthread_internal_tsd_get (int key)
{
  pthread_descr self = thread_self();

  return THREAD_GETMEM_NC(self, p_libc_specific[key]);
}
示例#5
0
attribute_hidden
__pthread_internal_tsd_get (int key)
{
  pthread_descr self = thread_self();

  return THREAD_GETMEM_NC(self, p_libc_specific, key);
}
示例#6
0
文件: specific.c 项目: dotrees/tools
int __pthread_setspecific(pthread_key_t key, const void * pointer)
{
  pthread_descr self = thread_self();
  unsigned int idx1st, idx2nd;

  if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use)
    return EINVAL;
  idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE;
  idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE;
  if (THREAD_GETMEM_NC(self, p_specific[idx1st]) == NULL) {
    void *newp = calloc(PTHREAD_KEY_2NDLEVEL_SIZE, sizeof (void *));
    if (newp == NULL)
      return ENOMEM;
    THREAD_SETMEM_NC(self, p_specific[idx1st], newp);
  }
  THREAD_GETMEM_NC(self, p_specific[idx1st])[idx2nd] = (void *) pointer;
  return 0;
}
示例#7
0
attribute_protected
void *
__pthread_getspecific (pthread_key_t key)
{
  struct pthread_key_data *data;

  /* Special case access to the first 2nd-level block.  This is the
     usual case.  */
  if (__builtin_expect (key < PTHREAD_KEY_2NDLEVEL_SIZE, 1))
    data = &THREAD_SELF->specific_1stblock[key];
  else
    {
      /* Verify the key is sane.  */
      if (key >= PTHREAD_KEYS_MAX)
	/* Not valid.  */
	return NULL;

      unsigned int idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE;
      unsigned int idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE;

      /* If the sequence number doesn't match or the key cannot be defined
	 for this thread since the second level array is not allocated
	 return NULL, too.  */
      struct pthread_key_data *level2 = THREAD_GETMEM_NC (THREAD_SELF,
							  specific, idx1st);
      if (level2 == NULL)
	/* Not allocated, therefore no data.  */
	return NULL;

      /* There is data.  */
      data = &level2[idx2nd];
    }

  void *result = data->data;
  if (result != NULL)
    {
      uintptr_t seq = data->seq;

      if (__builtin_expect (seq != __pthread_keys[key].seq, 0))
	result = data->data = NULL;
    }

  return result;
}
示例#8
0
void __pthread_do_exit(void *retval, char *currentframe)
{
  pthread_descr self = thread_self();
  pthread_descr joining;
  struct pthread_request request;
  PDEBUG("self=%p, pid=%d\n", self, self->p_pid);

  /* obey POSIX behavior and prevent cancellation functions from
   * being called more than once.
   * http://sourceware.org/ml/libc-ports/2006-10/msg00043.html
   */
  THREAD_SETMEM(self, p_cancelstate, PTHREAD_CANCEL_DISABLE);
  THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED);

  /* Call cleanup functions and destroy the thread-specific data */
  __pthread_perform_cleanup(currentframe);
  __pthread_destroy_specifics();
  /* Store return value */
  __pthread_lock(THREAD_GETMEM(self, p_lock), self);
  THREAD_SETMEM(self, p_retval, retval);
  /* See whether we have to signal the death.  */
  if (THREAD_GETMEM(self, p_report_events))
    {
      /* See whether TD_DEATH is in any of the mask.  */
      int idx = __td_eventword (TD_DEATH);
      uint32_t mask = __td_eventmask (TD_DEATH);

      if ((mask & (__pthread_threads_events.event_bits[idx]
		   | THREAD_GETMEM_NC(self,
				   p_eventbuf.eventmask).event_bits[idx]))
	  != 0)
	{
	  /* Yep, we have to signal the death.  */
	  THREAD_SETMEM(self, p_eventbuf.eventnum, TD_DEATH);
	  THREAD_SETMEM(self, p_eventbuf.eventdata, self);
	  __pthread_last_event = self;

	  /* Now call the function to signal the event.  */
	  __linuxthreads_death_event();
	}
    }
  /* Say that we've terminated */
  THREAD_SETMEM(self, p_terminated, 1);
  /* See if someone is joining on us */
  joining = THREAD_GETMEM(self, p_joining);
  PDEBUG("joining = %p, pid=%d\n", joining, joining->p_pid);
  __pthread_unlock(THREAD_GETMEM(self, p_lock));
  /* Restart joining thread if any */
  if (joining != NULL) restart(joining);
  /* If this is the initial thread, block until all threads have terminated.
     If another thread calls exit, we'll be terminated from our signal
     handler. */
  if (self == __pthread_main_thread && __pthread_manager_request >= 0) {
    request.req_thread = self;
    request.req_kind = REQ_MAIN_THREAD_EXIT;
    TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,
		(char *)&request, sizeof(request)));
    suspend(self);
    /* Main thread flushes stdio streams and runs atexit functions.
     * It also calls a handler within LinuxThreads which sends a process exit
     * request to the thread manager. */
    exit(0);
  }
  /* Exit the process (but don't flush stdio streams, and don't run
     atexit functions). */
  _exit(0);
}