Home | History | Annotate | Download | only in bionic
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 #include <sys/cdefs.h>
     17 
     18 #include <private/bionic_defs.h>
     19 
     20 #include "pthread_internal.h"
     21 
     22 class thread_local_dtor {
     23  public:
     24   void (*func) (void *);
     25   void *arg;
     26   void *dso_handle; // unused...
     27   thread_local_dtor* next;
     28 };
     29 
     30 extern "C" int __cxa_thread_atexit_impl(void (*func) (void *), void *arg, void *dso_handle);
     31 extern "C" void __loader_add_thread_local_dtor(void* dso_handle) __attribute__((weak));
     32 extern "C" void __loader_remove_thread_local_dtor(void* dso_handle) __attribute__((weak));
     33 
     34 __BIONIC_WEAK_FOR_NATIVE_BRIDGE
     35 int __cxa_thread_atexit_impl(void (*func) (void *), void *arg, void *dso_handle) {
     36   thread_local_dtor* dtor = new thread_local_dtor();
     37 
     38   dtor->func = func;
     39   dtor->arg = arg;
     40   dtor->dso_handle = dso_handle;
     41 
     42   pthread_internal_t* thread = __get_thread();
     43   dtor->next = thread->thread_local_dtors;
     44   thread->thread_local_dtors = dtor;
     45   if (__loader_add_thread_local_dtor != nullptr) {
     46     __loader_add_thread_local_dtor(dso_handle);
     47   }
     48   return 0;
     49 }
     50 
     51 extern "C" __LIBC_HIDDEN__ void __cxa_thread_finalize() {
     52   pthread_internal_t* thread = __get_thread();
     53   while (thread->thread_local_dtors != nullptr) {
     54     thread_local_dtor* current = thread->thread_local_dtors;
     55     thread->thread_local_dtors = current->next;
     56 
     57     current->func(current->arg);
     58     if (__loader_remove_thread_local_dtor != nullptr) {
     59       __loader_remove_thread_local_dtor(current->dso_handle);
     60     }
     61     delete current;
     62   }
     63 }
     64