Created
March 14, 2018 02:07
-
-
Save Dzejrou/bf2ef4c4d645117d369817236fb07067 to your computer and use it in GitHub Desktop.
Atexit diff
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- a/uspace/app/cpptest/main.cpp | |
+++ b/uspace/app/cpptest/main.cpp | |
@@ -1,12 +1,100 @@ | |
+#include <iostream> | |
+#include <tuple> | |
+ | |
+struct Foo | |
+{ | |
+ Foo() | |
+ { | |
+ /* std::ios_base::Init init{}; */ | |
+ std::cout << "Foo::Foo()" << std::endl; | |
+ } | |
+ | |
+ ~Foo() | |
+ { | |
+ std::cout << "Foo::~Foo()" << std::endl; | |
+ } | |
+ | |
+ void say() | |
+ { | |
+ std::cout << "Foo::say()" << std::endl; | |
+ } | |
+}; | |
+ | |
+Foo foo{}; | |
+ | |
+struct Bar | |
+{ | |
+ Bar() | |
+ : foo{} | |
+ { | |
+ std::cout << "Bar::Bar()" << std::endl; | |
+ foo.say(); | |
+ } | |
+ | |
+ ~Bar() | |
+ { | |
+ std::cout << "Bar::~Bar()" << std::endl; | |
+ } | |
+ | |
+ void say() | |
+ { | |
+ std::cout << "Bar::say()" << std::endl; | |
+ } | |
+ | |
+ Foo foo; | |
+}; | |
+ | |
+Bar bar{}; | |
+ | |
+__attribute__((constructor)) | |
+void start() | |
+{ | |
+ std::cout << "START" << std::endl; | |
+} | |
+ | |
+__attribute__((destructor)) | |
+void end() | |
+{ | |
+ std::cout << "END" << std::endl; | |
+} | |
int main() | |
{ | |
+ auto t = std::make_tuple<int, float>(2, 1.23f); | |
+ std::cout << "tuple<int, float> = " << std::get<0>(t) << ", " << std::get<1>(t) << std::endl; | |
+ std::get<0>(t) = 1; | |
+ std::get<1>(t) = 3.14f; | |
+ std::cout << "tuple<int, float> = " << std::get<0>(t) << ", " << std::get<1>(t) << std::endl; | |
+ | |
+ int i{}; | |
+ float f{}; | |
+ std::tie(i, f) = t; | |
+ std::cout << "tie: i = " << i << " | f = " << f << std::endl; | |
+ | |
+ i = 0; | |
+ f = 0.f; | |
+ std::tie(i, std::ignore) = t; | |
+ std::cout << "tie+ignore: i = " << i << " | f = " << f << std::endl; | |
+ | |
+ auto t1 = std::make_tuple<int, int>(1, 2); | |
+ auto t2 = std::make_tuple<int, int>(2, 1); | |
+ std::cout << "before swap t1: (" << std::get<0>(t1) << ", " << std::get<1>(t1) << ")" << std::endl; | |
+ std::cout << "before swap t2: (" << std::get<0>(t2) << ", " << std::get<1>(t2) << ")" << std::endl; | |
+ t1.swap(t2); | |
+ std::cout << "after swap t1: (" << std::get<0>(t1) << ", " << std::get<1>(t1) << ")" << std::endl; | |
+ std::cout << "after swap t2: (" << std::get<0>(t2) << ", " << std::get<1>(t2) << ")" << std::endl; | |
+ | |
+ auto t3 = std::make_tuple<float, int>(1.1, 10); | |
+ std::cout << "get<int>: " << std::get<int>(t3) << std::endl; | |
+ return 0; | |
} | |
diff --git a/uspace/lib/c/generic/libc.c b/uspace/lib/c/generic/libc.c | |
index 246d1ae39..07c0b57db 100644 | |
--- a/uspace/lib/c/generic/libc.c | |
+++ b/uspace/lib/c/generic/libc.c | |
@@ -117,7 +118,20 @@ void __main(void *pcb_ptr) | |
vfs_root_set(inbox_get("root")); | |
(void) vfs_cwd_set(__pcb->cwd); | |
} | |
- | |
+ | |
+ /* | |
+ * C++ Static constructor calls. | |
+ */ | |
+ if (__pcb != NULL) { | |
+ void **ctors = __pcb->cpp_data.ctors; | |
+ int count = __pcb->cpp_data.ctors_count; | |
+ | |
+ for (int i = 0; i < count; ++i) { | |
+ void *ctor = ctors[count - i - 1]; | |
+ ((void (*)())ctor)(); | |
+ } | |
+ } | |
+ | |
/* | |
* Run main() and set task return value | |
* according the result | |
@@ -128,6 +142,29 @@ void __main(void *pcb_ptr) | |
void exit(int status) | |
{ | |
+ /* | |
+ * GCC adds __attribute__((constructor)) functions | |
+ * before C++ constructors, so we call C++ destructors | |
+ * before __attribute((destructor)) functions to keep | |
+ * the correct ordering. | |
+ */ | |
+ call_atexit_handlers(); | |
+ | |
+ /* | |
+ * GCC extension __attribute__((destructor)), | |
+ * C++ destructors are added to __cxa_finalize call | |
+ * when called. | |
+ */ | |
+ if (__pcb != NULL) { | |
+ void **dtors = __pcb->cpp_data.dtors; | |
+ int count = __pcb->cpp_data.dtors_count; | |
+ | |
+ for (int i = 0; i < count; ++i) { | |
+ void *dtor = dtors[count - i - 1]; | |
+ ((void (*)())dtor)(); | |
+ } | |
+ } | |
+ | |
if (env_setup) { | |
__stdio_done(); | |
task_retval(status); | |
diff --git a/uspace/lib/c/generic/stdlib.c b/uspace/lib/c/generic/stdlib.c | |
index bede7db6a..7aefd2ec4 100644 | |
--- a/uspace/lib/c/generic/stdlib.c | |
+++ b/uspace/lib/c/generic/stdlib.c | |
@@ -46,5 +46,35 @@ void srandom(unsigned int seed) | |
glbl_seed = seed % RAND_MAX; | |
} | |
+/** | |
+ * Standard requires atleast 32, but except | |
+ * for this upper bound the limit is implementation | |
+ * defined. | |
+ */ | |
+#define MAX_ATEXIT_HANDLERS 64 | |
+ | |
+typedef void (*atexit_handler_t)(void); | |
+ | |
+static atexit_handler_t atexit_handlers[MAX_ATEXIT_HANDLERS]; | |
+static size_t atexit_handler_count = 0; | |
+ | |
+int atexit(atexit_handler_t handler) | |
+{ | |
+ if (atexit_handler_count >= MAX_ATEXIT_HANDLERS) | |
+ return 1; | |
+ atexit_handlers[atexit_handler_count++] = handler; | |
+ | |
+ return 0; | |
+} | |
+ | |
+void call_atexit_handlers(void) | |
+{ | |
+ for (size_t i = atexit_handler_count; i > 0; --i) | |
+ { | |
+ if (atexit_handlers[i - 1]) | |
+ atexit_handlers[i - 1](); | |
+ } | |
+} | |
+ | |
diff --git a/uspace/lib/c/include/stdlib.h b/uspace/lib/c/include/stdlib.h | |
index ec7d0a945..99283bbc9 100644 | |
--- a/uspace/lib/c/include/stdlib.h | |
+++ b/uspace/lib/c/include/stdlib.h | |
@@ -53,6 +53,8 @@ extern void srandom(unsigned int seed); | |
extern void abort(void) __attribute__((noreturn)); | |
extern void exit(int) __attribute__((noreturn)); | |
+extern int atexit(void (*)(void)); | |
+extern void call_atexit_handlers(void); | |
#ifdef __cplusplus | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment