1 //==========================================
2 // LIBCTINY - Matt Pietrek 2001
3 // MSDN Magazine, January 2001
4 // ==========================================
11 #pragma data_seg(".CRT$XCA")
12 _PVFV __xc_a
[] = { NULL
};
13 #pragma data_seg(".CRT$XCZ")
14 _PVFV __xc_z
[] = { NULL
};
17 #pragma data_seg(".CRT$XIA")
18 _PVFV __xi_a[] = { NULL };
19 #pragma data_seg(".CRT$XIZ")
20 _PVFV __xi_z[] = { NULL };
22 #pragma data_seg(".CRT$XTA")
23 _PVFV __xt_a[] = { NULL };
24 #pragma data_seg(".CRT$XTZ")
25 _PVFV __xt_z[] = { NULL };
27 #pragma data_seg(".CRT$XPA")
28 _PVFV __xp_a[] = { NULL };
29 #pragma data_seg(".CRT$XPZ")
30 _PVFV __xp_z[] = { NULL };
33 #pragma data_seg() /* reset */
35 #pragma comment(linker, "/merge:.CRT=.data")
37 typedef void (__cdecl
*_PVFV
)();
39 void __cdecl
_initterm(
43 // walk the table of function pointers from the bottom up, until
44 // the end is encountered. Do not skip the first entry. The initial
45 // value of pfbegin points to the first valid entry. Do not try to
46 // execute what pfend points to. Only entries before pfend are valid.
47 while (pfbegin
< pfend
)
49 // if current table entry is non-NULL, call thru it.
56 static _PVFV
* pf_atexitlist
= 0;
57 static unsigned max_atexitlist_entries
= 0;
58 static unsigned cur_atexitlist_entries
= 0;
60 void __cdecl
_atexit_init() {
61 max_atexitlist_entries
= 32;
62 pf_atexitlist
= (_PVFV
*)calloc( max_atexitlist_entries
,
66 int __cdecl
atexit(_PVFV func
) {
67 if (cur_atexitlist_entries
< max_atexitlist_entries
)
69 pf_atexitlist
[cur_atexitlist_entries
++] = func
;
76 void __cdecl
_DoExit() {
77 if (cur_atexitlist_entries
)
79 _initterm( pf_atexitlist
,
80 // Use ptr math to find the end of the array
81 pf_atexitlist
+ cur_atexitlist_entries
);
85 // -----------------------------------------------------
88 static HANDLE g_hProcessHeap = NULL;
90 extern "C" _PVFV* __onexitbegin = NULL;
91 extern "C" _PVFV* __onexitend = NULL;
93 extern "C" _PVFV __xi_a[], __xi_z[]; // C initializers
94 extern "C" _PVFV __xc_a[], __xc_z[]; // C++ initializers
95 extern "C" _PVFV __xp_a[], __xp_z[]; // C pre-terminators
96 extern "C" _PVFV __xt_a[], __xt_z[]; // C terminators
98 // Critical section to protect initialization/exit code
99 static CRITICAL_SECTION g_csInit;
101 extern "C" void DoInitialization() {
104 // memset(&osi, 0, sizeof(OSVERSIONINFO));
105 // osi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
106 // GetVersionEx(&osi);
107 // _osplatform = osi.dwPlatformId;
109 InitializeCriticalSection( &g_csInit );
111 EnterCriticalSection( &g_csInit );
115 g_hProcessHeap = GetProcessHeap();
117 // Call initialization routines (contructors for globals, etc.)
118 for (pf = __xi_a; pf < __xi_z; pf++)
126 for (pf = __xc_a; pf < __xc_z; pf++)
136 LeaveCriticalSection(&g_csInit);
140 extern "C" void DoCleanup() {
143 EnterCriticalSection(&g_csInit); // Protect access to the atexit table
147 // Call routines registered with atexit() from most recently registered
148 // to least recently registered
149 if (__onexitbegin != NULL)
151 for (pf = __onexitend-1; pf >= __onexitbegin; pf--)
159 __onexitbegin = NULL;
162 for (pf = __xp_a; pf < __xp_z; pf++)
170 for (pf = __xt_a; pf < __xt_z; pf++)
180 LeaveCriticalSection(&g_csInit);
181 DeleteCriticalSection(&g_csInit);
185 int __cdecl atexit(_PVFV pf) {
189 EnterCriticalSection(&g_csInit);
193 if (__onexitbegin == NULL)
195 __onexitbegin = (_PVFV*)malloc(16*sizeof(_PVFV));
196 if (__onexitbegin == NULL)
198 LeaveCriticalSection(&g_csInit);
201 __onexitend = __onexitbegin;
204 nCurrentSize = _msize(__onexitbegin);
205 if ((nCurrentSize+sizeof(_PVFV)) < ULONG(((const byte*)__onexitend-
206 (const byte*)__onexitbegin)))
210 pNew = (_PVFV*)realloc(__onexitbegin, 2*nCurrentSize);
213 LeaveCriticalSection(&g_csInit);
226 LeaveCriticalSection(&g_csInit);