xref: /llvm-project/libc/test/integration/src/pthread/pthread_exit_test.cpp (revision b6bc9d72f65a5086f310f321e969d96e9a559e75)
10071a795SSiva Chandra Reddy //===-- Tests for pthread_exit --------------------------------------------===//
20071a795SSiva Chandra Reddy //
30071a795SSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40071a795SSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information.
50071a795SSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60071a795SSiva Chandra Reddy //
70071a795SSiva Chandra Reddy //===----------------------------------------------------------------------===//
80071a795SSiva Chandra Reddy 
90071a795SSiva Chandra Reddy #include "src/pthread/pthread_create.h"
100071a795SSiva Chandra Reddy #include "src/pthread/pthread_exit.h"
110071a795SSiva Chandra Reddy #include "src/pthread/pthread_join.h"
12af1315c2SSiva Chandra Reddy #include "test/IntegrationTest/test.h"
130071a795SSiva Chandra Reddy 
140071a795SSiva Chandra Reddy #include <pthread.h>
150071a795SSiva Chandra Reddy 
160071a795SSiva Chandra Reddy bool dtor_called = false;
170071a795SSiva Chandra Reddy 
180071a795SSiva Chandra Reddy class A {
190071a795SSiva Chandra Reddy   int val;
200071a795SSiva Chandra Reddy 
210071a795SSiva Chandra Reddy public:
A(int i)220071a795SSiva Chandra Reddy   A(int i) { val = i; }
230071a795SSiva Chandra Reddy 
set(int i)240071a795SSiva Chandra Reddy   void set(int i) { val = i; }
250071a795SSiva Chandra Reddy 
~A()260071a795SSiva Chandra Reddy   ~A() {
270071a795SSiva Chandra Reddy     val = 0;
280071a795SSiva Chandra Reddy     dtor_called = true;
290071a795SSiva Chandra Reddy   }
300071a795SSiva Chandra Reddy };
310071a795SSiva Chandra Reddy 
320071a795SSiva Chandra Reddy thread_local A thread_local_a(123);
330071a795SSiva Chandra Reddy 
func(void *)340071a795SSiva Chandra Reddy void *func(void *) {
350071a795SSiva Chandra Reddy   // Touch the thread local variable so that it gets initialized and a callback
360071a795SSiva Chandra Reddy   // for its destructor gets registered with __cxa_thread_atexit.
370071a795SSiva Chandra Reddy   thread_local_a.set(321);
38*b6bc9d72SGuillaume Chatelet   LIBC_NAMESPACE::pthread_exit(nullptr);
390071a795SSiva Chandra Reddy   return nullptr;
400071a795SSiva Chandra Reddy }
410071a795SSiva Chandra Reddy 
TEST_MAIN()420071a795SSiva Chandra Reddy TEST_MAIN() {
430071a795SSiva Chandra Reddy   pthread_t th;
440071a795SSiva Chandra Reddy   void *retval;
450071a795SSiva Chandra Reddy 
46*b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_create(&th, nullptr, func, nullptr), 0);
47*b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_join(th, &retval), 0);
480071a795SSiva Chandra Reddy 
490071a795SSiva Chandra Reddy   ASSERT_TRUE(dtor_called);
50*b6bc9d72SGuillaume Chatelet   LIBC_NAMESPACE::pthread_exit(nullptr);
510071a795SSiva Chandra Reddy   return 0;
520071a795SSiva Chandra Reddy }
530071a795SSiva Chandra Reddy 
540071a795SSiva Chandra Reddy extern "C" {
550071a795SSiva Chandra Reddy 
560071a795SSiva Chandra Reddy using Destructor = void(void *);
570071a795SSiva Chandra Reddy 
580071a795SSiva Chandra Reddy int __cxa_thread_atexit_impl(Destructor *, void *, void *);
590071a795SSiva Chandra Reddy 
600071a795SSiva Chandra Reddy // We do not link integration tests to C++ runtime pieces like the libcxxabi.
610071a795SSiva Chandra Reddy // So, we provide our own simple __cxa_thread_atexit implementation.
__cxa_thread_atexit(Destructor * dtor,void * obj,void *)620071a795SSiva Chandra Reddy int __cxa_thread_atexit(Destructor *dtor, void *obj, void *) {
630071a795SSiva Chandra Reddy   return __cxa_thread_atexit_impl(dtor, obj, nullptr);
640071a795SSiva Chandra Reddy }
650071a795SSiva Chandra Reddy }
66