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