Esempio n. 1
0
static const char* __bionic_set_dlerror(char* new_value) {
  char** dlerror_slot = &reinterpret_cast<char**>(__get_tls())[TLS_SLOT_DLERROR];

  const char* old_value = *dlerror_slot;
  *dlerror_slot = new_value;
  return old_value;
}
Esempio n. 2
0
// We flag the __libc_preinit function as a constructor to ensure
// that its address is listed in libc.so's .init_array section.
// This ensures that the function is called by the dynamic linker
// as soon as the shared library is loaded.
__attribute__((constructor)) static void __libc_preinit() {
  /* ARC MOD BEGIN */
#endif
  /* Initialize IRT table using __nacl_irt_query. */
#if defined(__native_client__) || defined(BARE_METAL_BIONIC)
  __nacl_irt_query = irt_query;
  __init_irt_table();
#endif
  /* ARC MOD END */
  // Read the kernel argument block pointer from TLS.
  void* tls = const_cast<void*>(__get_tls());
  KernelArgumentBlock** args_slot = &reinterpret_cast<KernelArgumentBlock**>(tls)[TLS_SLOT_BIONIC_PREINIT];
  KernelArgumentBlock* args = *args_slot;

  // Clear the slot so no other initializer sees its value.
  // __libc_init_common() will change the TLS area so the old one won't be accessible anyway.
  *args_slot = NULL;

  __libc_init_common(*args);

  // Hooks for the debug malloc and pthread libraries to let them know that we're starting up.
  /* ARC MOD BEGIN */
  // We do not use the pthread debug feature.
  // pthread_debug_init();
  /* ARC MOD END */
  malloc_debug_init();
}
void __libc_preinit(void)
{
    /* Read the ELF data pointer from a special slot of the
     * TLS area, then call __libc_init_common with it.
     *
     * Note that:
     * - we clear the slot so no other initializer sees its value.
     * - __libc_init_common() will change the TLS area so the old one
     *   won't be accessible anyway.
     */
    void**      tls_area = (void**)__get_tls();
    unsigned*   elfdata   = tls_area[TLS_SLOT_BIONIC_PREINIT];

    tls_area[TLS_SLOT_BIONIC_PREINIT] = NULL;

    __libc_init_common(elfdata);

    /* Setup pthread routines accordingly to the environment.
     * Requires system properties
     */
#ifdef PTHREAD_DEBUG
    extern void pthread_debug_init(void);
    pthread_debug_init();
#endif
    /* Setup malloc routines accordingly to the environment.
     * Requires system properties
     */
    extern void malloc_debug_init(void);
    malloc_debug_init();
}
Esempio n. 4
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;
}
Esempio n. 6
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];
}
// We flag the __libc_preinit function as a constructor to ensure
// that its address is listed in libc.so's .init_array section.
// This ensures that the function is called by the dynamic linker
// as soon as the shared library is loaded.
__attribute__((constructor)) static void __libc_preinit() {
  // Read the kernel argument block pointer from TLS.
  void** tls = __get_tls();
  KernelArgumentBlock** args_slot = &reinterpret_cast<KernelArgumentBlock**>(tls)[TLS_SLOT_BIONIC_PREINIT];
  KernelArgumentBlock* args = *args_slot;

  // Clear the slot so no other initializer sees its value.
  // __libc_init_common() will change the TLS area so the old one won't be accessible anyway.
  *args_slot = NULL;

  __libc_init_common(*args);

  // Hooks for various libraries to let them know that we're starting up.
  malloc_debug_init();
  netdClientInit();
}
Esempio n. 8
0
TEST(tls, get_tls_for_art) {
  get_tls_fn_t get_tls_for_art = NULL;
#if !defined(__native_client__) && defined(__i386__)
  get_tls_for_art = *(get_tls_fn_t*)POINTER_TO_GET_TLS_FUNC_ON_BMM_I386;
#elif defined(__native_client__) && defined(__x86_64__)
  get_tls_for_art = *(get_tls_fn_t*)POINTER_TO_GET_TLS_FUNC_ON_NACL_X86_64;
#elif ((defined(__native_client__) && defined(__i386__)) ||     \
       (!defined(__native_client__) && defined(__arm__)))
  // No fixed address for __get_tls on this target, skipping this test
  return;
#else
# error Unsupported target
#endif

  // Note we cannot test get_tls_for_art == __get_tls as
  // get_tls_for_art is a pointer to __get_tls in runnable-ld.so,
  // not in libc.so.
  EXPECT_EQ(get_tls_for_art(), __get_tls());
}
Esempio n. 9
0
  // Called from pthread_exit() to remove all TLS key data
  // from this thread's TLS area. This must call the destructor of all keys
  // that have a non-NULL data value and a non-NULL destructor.
  void CleanAll() {
    void** tls = __get_tls();

    // Because destructors can do funky things like deleting/creating other
    // keys, we need to implement this in a loop.
    for (int rounds = PTHREAD_DESTRUCTOR_ITERATIONS; rounds > 0; --rounds) {
      size_t called_destructor_count = 0;
      for (int key = 0; key < BIONIC_TLS_SLOTS; ++key) {
        if (IsInUse(key)) {
          void* data = tls[key];
          void (*key_destructor)(void*) = s_tls_map_.key_destructors[key];

          if (data != NULL && key_destructor != NULL) {
            // we need to clear the key data now, this will prevent the
            // destructor (or a later one) from seeing the old value if
            // it calls pthread_getspecific() for some odd reason

            // we do not do this if 'key_destructor == NULL' just in case another
            // destructor function might be responsible for manually
            // releasing the corresponding data.
            tls[key] = NULL;

            // because the destructor is free to call pthread_key_create
            // and/or pthread_key_delete, we need to temporarily unlock
            // the TLS map
            Unlock();
            (*key_destructor)(data);
            Lock();
            ++called_destructor_count;
          }
        }
      }

      // If we didn't call any destructors, there is no need to check the TLS data again.
      if (called_destructor_count == 0) {
        break;
      }
    }
  }
Esempio n. 10
0
volatile int*  __errno() {
  return reinterpret_cast<int*>(&(__get_tls()[TLS_SLOT_ERRNO]));
}
pthread_internal_t* __get_thread(void) {
  return reinterpret_cast<pthread_internal_t*>(__get_tls()[TLS_SLOT_THREAD_ID]);
}
Esempio n. 12
0
volatile int*  __errno( void )
{
  return  &((volatile int*)__get_tls())[TLS_SLOT_ERRNO];
}