Skip to content

Instantly share code, notes, and snippets.

@Dzejrou
Created March 14, 2018 02:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Dzejrou/bf2ef4c4d645117d369817236fb07067 to your computer and use it in GitHub Desktop.
Save Dzejrou/bf2ef4c4d645117d369817236fb07067 to your computer and use it in GitHub Desktop.
Atexit diff
--- 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