source: mainline/uspace/lib/cpp/src/__bits/runtime.cpp@ 28a5ebd

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 28a5ebd was 46c66f8, checked in by Jaroslav Jindrak <dzejrou@…>, 6 years ago

cpp: apply requested changes

  • Property mode set to 100644
File size: 6.2 KB
Line 
1/*
2 * Copyright (c) 2018 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <__bits/abi.hpp>
30#include <cassert>
31#include <cstdlib>
32#include <cstdint>
33#include <exception>
34#include <mutex>
35
36void* __dso_handle = nullptr;
37
38namespace __cxxabiv1
39{
40 namespace aux
41 {
42 struct destructor_t
43 {
44 void (*func)(void*);
45 void* ptr;
46 void* dso;
47 };
48
49 destructor_t* destructors{nullptr};
50 std::size_t destructor_count{0};
51 std::size_t destructor_size{32};
52
53 /**
54 * C atexit does not pass any arguments,
55 * but __cxa_finalize requires one so we
56 * use a wrapper.
57 */
58 void atexit_destructors()
59 {
60 __cxa_finalize(nullptr);
61 }
62 }
63
64 /**
65 * No need for a body, this function is called when a virtual
66 * call of a pure virtual function cannot be made.
67 */
68 extern "C" void __cxa_pure_virtual()
69 {
70 std::terminate();
71 }
72
73#ifdef __arm__
74 extern "C" int __aeabi_atexit(void* p, void (*f)(void*), void* d)
75 {
76 return __cxa_atexit(f, p, d);
77 }
78#endif
79
80 extern "C" int __cxa_atexit(void (*f)(void*), void* p, void* d)
81 {
82 if (!aux::destructors)
83 {
84 aux::destructors = new aux::destructor_t[aux::destructor_size];
85 std::atexit(aux::atexit_destructors);
86 }
87 else if (aux::destructor_count >= aux::destructor_size)
88 {
89 auto tmp = std::realloc(aux::destructors, aux::destructor_size * 2);
90
91 if (!tmp)
92 return -1;
93
94 aux::destructors = static_cast<aux::destructor_t*>(tmp);
95 aux::destructor_size *= 2;
96 }
97
98 auto& destr = aux::destructors[aux::destructor_count++];
99 destr.func = f;
100 destr.ptr = p;
101 destr.dso = d;
102
103 return 0;
104 }
105
106 extern "C" void __cxa_finalize(void *f)
107 {
108 if (!f)
109 {
110 for (std::size_t i = aux::destructor_count; i > 0; --i)
111 {
112 if (aux::destructors[i - 1].func)
113 (*aux::destructors[i - 1].func)(aux::destructors[i - 1].ptr);
114 }
115 }
116 else
117 {
118 for (std::size_t i = aux::destructor_count; i > 0; --i)
119 {
120 if (aux::destructors[i - 1].func == f)
121 {
122 (*aux::destructors[i - 1].func)(aux::destructors[i - 1].ptr);
123 aux::destructors[i - 1].func = nullptr;
124 aux::destructors[i - 1].ptr = nullptr;
125 aux::destructors[i - 1].dso = nullptr;
126 // TODO: shift and decrement count
127 }
128 }
129 }
130 }
131
132 using guard_t = std::uint64_t;
133 std::mutex static_guard_mtx{};
134
135 extern "C" int __cxa_guard_acquire(guard_t* guard)
136 {
137 static_guard_mtx.lock();
138
139 return !*((std::uint8_t*)guard);
140 }
141
142 extern "C" void __cxa_guard_release(guard_t* guard)
143 {
144 *((std::uint8_t*)guard) = 1;
145
146 static_guard_mtx.unlock();
147 }
148
149 extern "C" void __cxa_guard_abort(guard_t* guard)
150 {
151 static_guard_mtx.unlock();
152 }
153
154 __fundamental_type_info::~__fundamental_type_info()
155 { /* DUMMY BODY */ }
156
157 __array_type_info::~__array_type_info()
158 { /* DUMMY BODY */ }
159
160 __function_type_info::~__function_type_info()
161 { /* DUMMY BODY */ }
162
163 __enum_type_info::~__enum_type_info()
164 { /* DUMMY BODY */ }
165
166 __class_type_info::~__class_type_info()
167 { /* DUMMY BODY */ }
168
169 __si_class_type_info::~__si_class_type_info()
170 { /* DUMMY BODY */ }
171
172 __vmi_class_type_info::~__vmi_class_type_info()
173 { /* DUMMY BODY */ }
174
175 __pbase_type_info::~__pbase_type_info()
176 { /* DUMMY BODY */ }
177
178 __pointer_type_info::~__pointer_type_info()
179 { /* DUMMY BODY */ }
180
181 __pointer_to_member_type_info::~__pointer_to_member_type_info()
182 { /* DUMMY BODY */ }
183
184 /**
185 * This structure represents part of the vtable segment
186 * that contains data related to dynamic_cast.
187 */
188 struct vtable
189 {
190 // Unimportant to us.
191
192 std::ptrdiff_t offset_to_top;
193 std::type_info* tinfo;
194
195 // Actual vtable.
196 };
197 extern "C" void* __dynamic_cast(const void* sub, const __class_type_info* src,
198 const __class_type_info* dst, std::ptrdiff_t offset)
199 {
200 // TODO: implement
201 // NOTE: as far as I understand it, we get vtable prefix from sub, get the type_info
202 // ptr from that and then climb the inheritance hierarchy upwards till we either
203 // fint dst or fail and return nullptr
204 return nullptr;
205 }
206
207 // Needed on arm.
208 extern "C" void __cxa_end_cleanup()
209 { /* DUMMY BODY */ }
210
211 extern "C" int __cxa_thread_atexit(void(*)(void*), void*, void*)
212 {
213 // TODO: needed for thread_local variables
214 __unimplemented();
215 return 0;
216 }
217}
Note: See TracBrowser for help on using the repository browser.