blob: fc0ee9ba004e46a7429188db42024cc150406663 [file] [edit]
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file consists of an integration test written to the functionality
/// of __cxa_thread_atexit_impl() function while an exit of a pthread
///
//===----------------------------------------------------------------------===//
#include "src/pthread/pthread_create.h"
#include "src/pthread/pthread_exit.h"
#include "src/pthread/pthread_join.h"
#include "src/stdlib/__cxa_thread_atexit_impl.h"
#include "test/IntegrationTest/test.h"
#include "hdr/types/pthread_t.h"
namespace {
int dtor_order[3];
int dtor_count = 0;
struct Obj {
int id;
Obj(int i) : id(i) {}
~Obj() { dtor_order[dtor_count++] = id; }
};
thread_local Obj tl_first(1);
thread_local Obj tl_second(2);
thread_local Obj tl_third(3);
void touch_all() {
// touch is in definition order so the destruction order becomes well defined.
(void)tl_first.id;
(void)tl_second.id;
(void)tl_third.id;
}
void *return_func(void *) {
touch_all();
return nullptr;
}
void *exit_func(void *) {
touch_all();
LIBC_NAMESPACE::pthread_exit(nullptr);
return nullptr;
}
void run_thread(void *(*fn)(void *)) {
dtor_count = 0;
pthread_t th;
void *retval;
ASSERT_EQ(LIBC_NAMESPACE::pthread_create(&th, nullptr, fn, nullptr), 0);
ASSERT_EQ(LIBC_NAMESPACE::pthread_join(th, &retval), 0);
ASSERT_EQ(dtor_count, 3);
ASSERT_EQ(dtor_order[0], 3);
ASSERT_EQ(dtor_order[1], 2);
ASSERT_EQ(dtor_order[2], 1);
}
} // namespace
extern "C" {
// Integration tests are not linked to the C++ runtime, so provide a minimal
// __cxa_thread_atexit for the compiler-emitted calls.
int __cxa_thread_atexit(void (*dtor)(void *), void *obj, void *) {
return LIBC_NAMESPACE::__cxa_thread_atexit_impl(dtor, obj, nullptr);
}
}
TEST_MAIN() {
run_thread(return_func);
run_thread(exit_func);
return 0;
}