Beispiel #1
0
// Deletes a pthread_key_t. note that the standard mandates that this does
// not call the destructors for non-NULL key values. Instead, it is the
// responsibility of the caller to properly dispose of the corresponding data
// and resources, using any means it finds suitable.
int pthread_key_delete(pthread_key_t key) {
  ScopedTlsMapAccess tls_map;

  if (!IsValidUserKey(key) || !tls_map.IsInUse(key)) {
    return EINVAL;
  }

  // Clear value in all threads.
  pthread_mutex_lock(&g_thread_list_lock);
  for (pthread_internal_t*  t = g_thread_list; t != NULL; t = t->next) {
    // Skip zombie threads. They don't have a valid TLS area any more.
    // Similarly, it is possible to have t->tls == NULL for threads that
    // were just recently created through pthread_create() but whose
    // startup trampoline (__pthread_start) hasn't been run yet by the
    // scheduler. t->tls will also be NULL after a thread's stack has been
    // unmapped but before the ongoing pthread_join() is finished.
    if (t->tid == 0 || t->tls == NULL) {
      continue;
    }

    t->tls[key] = NULL;
  }
  tls_map.DeleteKey(key);

  pthread_mutex_unlock(&g_thread_list_lock);
  return 0;
}
// Deletes a pthread_key_t. note that the standard mandates that this does
// not call the destructors for non-NULL key values. Instead, it is the
// responsibility of the caller to properly dispose of the corresponding data
// and resources, using any means it finds suitable.
int pthread_key_delete(pthread_key_t key) {
  ScopedTlsMapAccess tls_map;

  if (!IsValidUserKey(key) || !tls_map.IsInUse(key)) {
    return EINVAL;
  }

  // Clear value in all threads.
  pthread_mutex_lock(&gThreadListLock);
  for (pthread_internal_t*  t = gThreadList; t != NULL; t = t->next) {
    // Avoid zombie threads with a negative 'join_count'. These are really
    // already dead and don't have a TLS area anymore.

    // Similarly, it is possible to have t->tls == NULL for threads that
    // were just recently created through pthread_create() but whose
    // startup trampoline (__thread_entry) hasn't been run yet by the
    // scheduler. t->tls will also be NULL after it's stack has been
    // unmapped but before the ongoing pthread_join() is finished.
    // so check for this too.
    if (t->join_count < 0 || !t->tls) {
      continue;
    }

    t->tls[key] = NULL;
  }
  tls_map.DeleteKey(key);

  pthread_mutex_unlock(&gThreadListLock);
  return 0;
}
Beispiel #3
0
int pthread_setspecific(pthread_key_t key, const void* ptr) {
  ScopedTlsMapAccess tls_map;

  if (!IsValidUserKey(key) || !tls_map.IsInUse(key)) {
    return EINVAL;
  }

  __get_tls()[key] = const_cast<void*>(ptr);
  return 0;
}
int pthread_setspecific(pthread_key_t key, const void* ptr) {
  ScopedTlsMapAccess tls_map;

  if (!IsValidUserKey(key) || !tls_map.IsInUse(key)) {
    return EINVAL;
  }

  ((uint32_t *)__get_tls())[key] = (uint32_t)ptr;
  return 0;
}
Beispiel #5
0
void* pthread_getspecific(pthread_key_t key) {
  if (!IsValidUserKey(key)) {
    return NULL;
  }

  // For performance reasons, we do not lock/unlock the global TLS map
  // to check that the key is properly allocated. If the key was not
  // allocated, the value read from the TLS should always be NULL
  // due to pthread_key_delete() clearing the values for all threads.
  return __get_tls()[key];
}
// Deletes a pthread_key_t. note that the standard mandates that this does
// not call the destructors for non-NULL key values. Instead, it is the
// responsibility of the caller to properly dispose of the corresponding data
// and resources, using any means it finds suitable.
int pthread_key_delete(pthread_key_t key) {
  ScopedTlsMapAccess tls_map;

  if (!IsValidUserKey(key) || !tls_map.IsInUse(key)) {
    return EINVAL;
  }

  // Clear value in all threads.
  pthread_mutex_lock(&g_thread_list_lock);
  for (pthread_internal_t*  t = g_thread_list; t != NULL; t = t->next) {
    t->tls[key] = NULL;
  }
  tls_map.DeleteKey(key);

  pthread_mutex_unlock(&g_thread_list_lock);
  return 0;
}