Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
module_init.cpp
Go to the documentation of this file.
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  * helpers for module initialization/shutdown.
25  */
26 
27 #include "precompiled.h"
28 #include "lib/module_init.h"
29 
30 #include "lib/sysdep/cpu.h" // cpu_CAS
31 
32 // not yet initialized, or already shutdown
33 static const ModuleInitState UNINITIALIZED = 0; // value documented in header
34 // running user callback - concurrent ModuleInit callers must spin
35 static const ModuleInitState BUSY = ERR::AGAIN; // never returned
36 // init succeeded; allow shutdown
38 
39 
41 {
42  for(;;)
43  {
44  if(cpu_CAS(initState, UNINITIALIZED, BUSY))
45  {
46  Status ret = init();
47  *initState = (ret == INFO::OK)? INITIALIZED : ret;
49  return ret;
50  }
51 
52  const ModuleInitState latchedInitState = *initState;
53  if(latchedInitState == UNINITIALIZED || latchedInitState == BUSY)
54  {
55  cpu_Pause();
56  continue;
57  }
58 
59  ENSURE(latchedInitState == INITIALIZED || latchedInitState < 0);
60  return (Status)latchedInitState;
61  }
62 }
63 
64 
65 Status ModuleShutdown(volatile ModuleInitState* initState, void (*shutdown)())
66 {
67  for(;;)
68  {
69  if(cpu_CAS(initState, INITIALIZED, BUSY))
70  {
71  shutdown();
72  *initState = UNINITIALIZED;
74  return INFO::OK;
75  }
76 
77  const ModuleInitState latchedInitState = *initState;
78  if(latchedInitState == INITIALIZED || latchedInitState == BUSY)
79  {
80  cpu_Pause();
81  continue;
82  }
83 
84  if(latchedInitState == UNINITIALIZED)
85  return INFO::SKIPPED;
86 
87  ENSURE(latchedInitState < 0);
88  return (Status)latchedInitState;
89  }
90 }
Definition: debug.cpp:485
#define COMPILER_FENCE
prevent the compiler from reordering loads or stores across this point.
const Status OK
Definition: status.h:386
static const ModuleInitState INITIALIZED
Definition: module_init.cpp:37
static ModuleInitState initState
Definition: h_mgr.cpp:742
const Status AGAIN
Definition: status.h:427
#define ENSURE(expr)
ensure the expression &lt;expr&gt; evaluates to non-zero.
Definition: debug.h:282
intptr_t ModuleInitState
initialization state of a module (class, source file, etc.) must be initialized to zero (e...
Definition: module_init.h:35
i64 Status
Error handling system.
Definition: status.h:171
Status ModuleShutdown(volatile ModuleInitState *initState, void(*shutdown)())
calls a user-defined shutdown function if initState is &quot;initialized&quot;.
Definition: module_init.cpp:65
const Status SKIPPED
Definition: status.h:392
bool cpu_CAS(volatile intptr_t *location, intptr_t expected, intptr_t newValue)
atomic &quot;compare and swap&quot;.
Definition: arm.cpp:36
Status ModuleInit(volatile ModuleInitState *initState, Status(*init)())
calls a user-defined init function if initState is zero.
Definition: module_init.cpp:40
static const ModuleInitState UNINITIALIZED
Definition: module_init.cpp:33
void cpu_Pause()
pause in spin-wait loops, as a performance optimisation.
Definition: cpu.h:91