1 /* Copyright (C) 2010 Wildfire Games.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining
4 * a copy of this software and associated documentation files (the
5 * "Software"), to deal in the Software without restriction, including
6 * without limitation the rights to use, copy, modify, merge, publish,
7 * distribute, sublicense, and/or sell copies of the Software, and to
8 * permit persons to whom the Software is furnished to do so, subject to
9 * the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23 /*
24 * windows-specific module init and shutdown mechanism
25 */
26
27 #include "precompiled.h"
28 #include "lib/sysdep/os/win/winit.h"
29
30 #include "lib/sysdep/os/win/win.h" // GetTickCount for quick'n dirty timing
31
32 // see http://blogs.msdn.com/larryosterman/archive/2004/09/27/234840.aspx
33 // for discussion of a similar mechanism.
34 //
35 // note: this module is kept distinct from the CRT's init/shutdown mechanism
36 // to insulate against changes there. another advantage is that callbacks
37 // can return Status instead of int.
38
39 // currently (2008-02-17) the init groups are populated as follows:
40 // critical : wposix
41 // early : wutil
42 // early2 : whrt, wdbg_heap
43 // main : waio, wsock, wtime, wdir_watch
44 // late : wsdl
45
46 typedef Status (*PfnLibError)();
47
48 // pointers to start and end of function tables.
49 // notes:
50 // - COFF tosses out empty segments, so we have to put in one value
51 // (zero, because CallFunctionPointers has to ignore entries =0 anyway).
52 // - ASCII '$' and 'Z' come before resp. after '0'..'9', so use that to
53 // bound the section names.
54 __declspec(allocate(".WINIT$I$")) PfnLibError initBegin = 0;
55 __declspec(allocate(".WINIT$IZ")) PfnLibError initEnd = 0;
56 __declspec(allocate(".WINIT$S$")) PfnLibError shutdownBegin = 0;
57 __declspec(allocate(".WINIT$SZ")) PfnLibError shutdownEnd = 0;
58 // note: #pragma comment(linker, "/include") is not necessary since
59 // these are referenced below.
60
61
62 /**
63 * call into a range of function pointers.
64 * @param [begin, end): STL-style range
65 *
66 * note: pointers = 0 are ignored. this is because the above placeholders
67 * are initialized to 0 and because the range may be larger than
68 * expected due to COFF section padding (with zeroes).
69 **/
CallFunctionPointers(PfnLibError * begin,PfnLibError * end)70 static void CallFunctionPointers(PfnLibError* begin, PfnLibError* end)
71 {
72 const DWORD t0 = GetTickCount();
73
74 for(PfnLibError* ppfunc = begin; ppfunc < end; ppfunc++)
75 {
76 if(*ppfunc)
77 {
78 (*ppfunc)();
79 }
80 }
81
82 const DWORD t1 = GetTickCount();
83 debug_printf("WINIT| total elapsed time in callbacks %d ms (+-10)\n", t1-t0);
84 }
85
86
winit_CallInitFunctions()87 void winit_CallInitFunctions()
88 {
89 CallFunctionPointers(&initBegin, &initEnd);
90 }
91
winit_CallShutdownFunctions()92 void winit_CallShutdownFunctions()
93 {
94 CallFunctionPointers(&shutdownBegin, &shutdownEnd);
95 }
96