diff options
author | Dmitriy Ivanov <dimitry@google.com> | 2015-03-25 17:38:10 -0700 |
---|---|---|
committer | Dmitriy Ivanov <dimitry@google.com> | 2015-03-25 18:07:59 -0700 |
commit | df79c330d895af31f39ee301dee62731fa586168 (patch) | |
tree | 7129c6e46b2c150027605af4c6f08c1e6de24815 /libc | |
parent | 0c3b632bd6570064bab1055d2b8a51cfb85e60bb (diff) | |
download | bionic-df79c330d895af31f39ee301dee62731fa586168.zip bionic-df79c330d895af31f39ee301dee62731fa586168.tar.gz bionic-df79c330d895af31f39ee301dee62731fa586168.tar.bz2 |
Initial implementation of __cxa_thread_atexit_impl
This is initial implementations; does not yet handle
dlclose - undefined behavior, needs linker support to
handle it right.
Bug: 19800080
Bug: 16696563
Change-Id: I7a3e21ed7f7ec01e62ea1b7cb2ab253590ea0686
Diffstat (limited to 'libc')
-rw-r--r-- | libc/Android.mk | 22 | ||||
-rw-r--r-- | libc/bionic/__cxa_thread_atexit_impl.cpp | 48 | ||||
-rw-r--r-- | libc/bionic/pthread_exit.cpp | 6 |
3 files changed, 75 insertions, 1 deletions
diff --git a/libc/Android.mk b/libc/Android.mk index 6f430cc..ebc59de 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -533,6 +533,9 @@ libc_pthread_src_files := \ bionic/pthread_setschedparam.cpp \ bionic/pthread_sigmask.cpp \ +libc_thread_atexit_impl_src_files := \ + bionic/__cxa_thread_atexit_impl.cpp \ + libc_arch_static_src_files := \ bionic/dl_iterate_phdr_static.cpp \ @@ -1002,6 +1005,24 @@ $(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags)) $(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_bionic_src_files)) include $(BUILD_STATIC_LIBRARY) +include $(CLEAR_VARS) +LOCAL_SRC_FILES := $(libc_thread_atexit_impl_src_files) +LOCAL_CFLAGS := $(libc_common_cflags) -fno-data-sections -Wframe-larger-than=2048 + +LOCAL_CONLYFLAGS := $(libc_common_conlyflags) +LOCAL_CPPFLAGS := $(libc_common_cppflags) -Wold-style-cast +LOCAL_C_INCLUDES := $(libc_common_c_includes) +LOCAL_MODULE := libc_thread_atexit_impl +# TODO: Clang tries to use __tls_get_addr which is not supported yet +# remove after it is implemented. +LOCAL_CLANG := false +LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies) +LOCAL_CXX_STL := none +LOCAL_SYSTEM_SHARED_LIBRARIES := +LOCAL_ADDRESS_SANITIZER := false +LOCAL_NATIVE_COVERAGE := $(bionic_coverage) + +include $(BUILD_STATIC_LIBRARY) # ======================================================== # libc_pthread.a - pthreads parts that previously lived in @@ -1206,6 +1227,7 @@ LOCAL_WHOLE_STATIC_LIBRARIES := \ libc_pthread \ libc_stack_protector \ libc_syscalls \ + libc_thread_atexit_impl \ libc_tzcode \ LOCAL_WHOLE_STATIC_LIBRARIES_arm := libc_aeabi diff --git a/libc/bionic/__cxa_thread_atexit_impl.cpp b/libc/bionic/__cxa_thread_atexit_impl.cpp new file mode 100644 index 0000000..9ae6dfd --- /dev/null +++ b/libc/bionic/__cxa_thread_atexit_impl.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <sys/cdefs.h> + +struct thread_local_dtor { + void (*func) (void *); + void *arg; + void *dso_handle; // unused... + thread_local_dtor* next; +}; + +__thread thread_local_dtor* thread_local_dtors = nullptr; + +extern "C" int __cxa_thread_atexit_impl(void (*func) (void *), void *arg, void *dso_handle) { + thread_local_dtor* dtor = new thread_local_dtor(); + + dtor->func = func; + dtor->arg = arg; + dtor->dso_handle = dso_handle; + dtor->next = thread_local_dtors; + + thread_local_dtors = dtor; + + return 0; +} + +extern "C" __LIBC_HIDDEN__ void __cxa_thread_finalize() { + while (thread_local_dtors != nullptr) { + thread_local_dtor* current = thread_local_dtors; + thread_local_dtors = current->next; + + current->func(current->arg); + delete current; + } +} diff --git a/libc/bionic/pthread_exit.cpp b/libc/bionic/pthread_exit.cpp index c2232a9..1de85f5 100644 --- a/libc/bionic/pthread_exit.cpp +++ b/libc/bionic/pthread_exit.cpp @@ -37,6 +37,7 @@ extern "C" __noreturn void _exit_with_stack_teardown(void*, size_t); extern "C" __noreturn void __exit(int); extern "C" int __set_tid_address(int*); +extern "C" void __cxa_thread_finalize(); /* CAVEAT: our implementation of pthread_cleanup_push/pop doesn't support C++ exceptions * and thread cancelation @@ -59,10 +60,13 @@ void __pthread_cleanup_pop(__pthread_cleanup_t* c, int execute) { } void pthread_exit(void* return_value) { + // Call dtors for thread_local objects first. + __cxa_thread_finalize(); + pthread_internal_t* thread = __get_thread(); thread->return_value = return_value; - // Call the cleanup handlers first. + // Call the cleanup handlers. while (thread->cleanup_stack) { __pthread_cleanup_t* c = thread->cleanup_stack; thread->cleanup_stack = c->__cleanup_prev; |