Repository navigation
Expand file tree
/
Copy pathTactilityRuntime.cpp
More file actions
118 lines (96 loc) · 2.9 KB
/
Copy pathTactilityRuntime.cpp
File metadata and controls
118 lines (96 loc) · 2.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// Static construction and destruction for a Tactility device app (see
// TactilityRuntime.h).
#if defined(DEKI_TACTILITY_TARGET) && !defined(DEKI_EDITOR)
#include "TactilityRuntime.h"
#if defined(ESP_PLATFORM)
#include <cstdint>
#include <cstdlib>
extern "C"
{
// This module's handle, which the compiler passes to __cxa_atexit for every
// static with a destructor. A start file defines it in each executable or
// shared object; the app links without start files, so it is defined here.
// Hidden, as the app is built: it identifies this app, not the firmware.
void* __dso_handle = &__dso_handle;
// Ends of the constructor tables, from the link script.
typedef void (*DekiCtor)();
extern DekiCtor __deki_ctors_start[];
extern DekiCtor __deki_ctors_end[];
extern DekiCtor __deki_init_array_start[];
extern DekiCtor __deki_init_array_end[];
int __cxa_atexit(void (*destructor)(void*), void* object, void* dso);
}
namespace
{
struct Destructor
{
void (*fn)(void*);
void* object;
};
// Plain storage, not a container: entries arrive while the statics are being
// constructed, before any container here could be.
Destructor* g_Destructors = nullptr;
size_t g_DestructorCount = 0;
size_t g_DestructorCapacity = 0;
bool g_Constructed = false;
} // namespace
extern "C" int __cxa_atexit(void (*destructor)(void*), void* object, void*)
{
if (g_DestructorCount == g_DestructorCapacity)
{
const size_t capacity = g_DestructorCapacity == 0 ? 64 : g_DestructorCapacity * 2;
auto* grown = static_cast<Destructor*>(std::realloc(g_Destructors, capacity * sizeof(Destructor)));
if (grown == nullptr)
{
return -1;
}
g_Destructors = grown;
g_DestructorCapacity = capacity;
}
g_Destructors[g_DestructorCount++] = { destructor, object };
return 0;
}
namespace DekiTactility
{
void RunStaticConstructors()
{
if (g_Constructed)
{
return;
}
g_Constructed = true;
// .ctors runs last entry first, as GCC's own start files run it.
for (DekiCtor* ctor = __deki_ctors_end; ctor != __deki_ctors_start;)
{
--ctor;
const auto value = reinterpret_cast<uintptr_t>(*ctor);
if (value != 0 && value != UINTPTR_MAX)
{
(*ctor)();
}
}
for (DekiCtor* ctor = __deki_init_array_start; ctor != __deki_init_array_end; ++ctor)
{
(*ctor)();
}
}
void RunStaticDestructors()
{
while (g_DestructorCount > 0)
{
const Destructor d = g_Destructors[--g_DestructorCount];
d.fn(d.object);
}
std::free(g_Destructors);
g_Destructors = nullptr;
g_DestructorCapacity = 0;
}
} // namespace DekiTactility
#else // the simulator: dlopen() and dlclose() do both
namespace DekiTactility
{
void RunStaticConstructors() {}
void RunStaticDestructors() {}
} // namespace DekiTactility
#endif // ESP_PLATFORM
#endif // DEKI_TACTILITY_TARGET && !DEKI_EDITOR