| 1 | // | 
| 2 | // Copyright (C) 2002-2005  3Dlabs Inc. Ltd. | 
| 3 | // All rights reserved. | 
| 4 | // | 
| 5 | // Redistribution and use in source and binary forms, with or without | 
| 6 | // modification, are permitted provided that the following conditions | 
| 7 | // are met: | 
| 8 | // | 
| 9 | //    Redistributions of source code must retain the above copyright | 
| 10 | //    notice, this list of conditions and the following disclaimer. | 
| 11 | // | 
| 12 | //    Redistributions in binary form must reproduce the above | 
| 13 | //    copyright notice, this list of conditions and the following | 
| 14 | //    disclaimer in the documentation and/or other materials provided | 
| 15 | //    with the distribution. | 
| 16 | // | 
| 17 | //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its | 
| 18 | //    contributors may be used to endorse or promote products derived | 
| 19 | //    from this software without specific prior written permission. | 
| 20 | // | 
| 21 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
| 22 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
| 23 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 
| 24 | // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 
| 25 | // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | 
| 26 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | 
| 27 | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 
| 28 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | 
| 29 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 
| 30 | // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | 
| 31 | // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 
| 32 | // POSSIBILITY OF SUCH DAMAGE. | 
| 33 | // | 
| 34 |  | 
| 35 | #define SH_EXPORTING | 
| 36 |  | 
| 37 | #include <cassert> | 
| 38 |  | 
| 39 | #include "InitializeDll.h" | 
| 40 | #include "../glslang/Include/InitializeGlobals.h" | 
| 41 | #include "../glslang/Public/ShaderLang.h" | 
| 42 | #include "../glslang/Include/PoolAlloc.h" | 
| 43 |  | 
| 44 | namespace glslang { | 
| 45 |  | 
| 46 | OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX; | 
| 47 |  | 
| 48 | // Per-process initialization. | 
| 49 | // Needs to be called at least once before parsing, etc. is done. | 
| 50 | // Will also do thread initialization for the calling thread; other | 
| 51 | // threads will need to do that explicitly. | 
| 52 | bool InitProcess() | 
| 53 | { | 
| 54 |     glslang::GetGlobalLock(); | 
| 55 |  | 
| 56 |     if (ThreadInitializeIndex != OS_INVALID_TLS_INDEX) { | 
| 57 |         // | 
| 58 |         // Function is re-entrant. | 
| 59 |         // | 
| 60 |  | 
| 61 |         glslang::ReleaseGlobalLock(); | 
| 62 |         return true; | 
| 63 |     } | 
| 64 |  | 
| 65 |     ThreadInitializeIndex = OS_AllocTLSIndex(); | 
| 66 |  | 
| 67 |     if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) { | 
| 68 |         assert(0 && "InitProcess(): Failed to allocate TLS area for init flag" ); | 
| 69 |  | 
| 70 |         glslang::ReleaseGlobalLock(); | 
| 71 |         return false; | 
| 72 |     } | 
| 73 |  | 
| 74 |     if (! InitializePoolIndex()) { | 
| 75 |         assert(0 && "InitProcess(): Failed to initialize global pool" ); | 
| 76 |  | 
| 77 |         glslang::ReleaseGlobalLock(); | 
| 78 |         return false; | 
| 79 |     } | 
| 80 |  | 
| 81 |     if (! InitThread()) { | 
| 82 |         assert(0 && "InitProcess(): Failed to initialize thread" ); | 
| 83 |  | 
| 84 |         glslang::ReleaseGlobalLock(); | 
| 85 |         return false; | 
| 86 |     } | 
| 87 |  | 
| 88 |     glslang::ReleaseGlobalLock(); | 
| 89 |     return true; | 
| 90 | } | 
| 91 |  | 
| 92 | // Per-thread scoped initialization. | 
| 93 | // Must be called at least once by each new thread sharing the | 
| 94 | // symbol tables, etc., needed to parse. | 
| 95 | bool InitThread() | 
| 96 | { | 
| 97 |     // | 
| 98 |     // This function is re-entrant | 
| 99 |     // | 
| 100 |     if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) { | 
| 101 |         assert(0 && "InitThread(): Process hasn't been initalised." ); | 
| 102 |         return false; | 
| 103 |     } | 
| 104 |  | 
| 105 |     if (OS_GetTLSValue(ThreadInitializeIndex) != nullptr) | 
| 106 |         return true; | 
| 107 |  | 
| 108 |     if (! OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) { | 
| 109 |         assert(0 && "InitThread(): Unable to set init flag." ); | 
| 110 |         return false; | 
| 111 |     } | 
| 112 |  | 
| 113 |     glslang::SetThreadPoolAllocator(nullptr); | 
| 114 |  | 
| 115 |     return true; | 
| 116 | } | 
| 117 |  | 
| 118 | // Not necessary to call this: InitThread() is reentrant, and the need | 
| 119 | // to do per thread tear down has been removed. | 
| 120 | // | 
| 121 | // This is kept, with memory management removed, to satisfy any exiting | 
| 122 | // calls to it that rely on it. | 
| 123 | bool DetachThread() | 
| 124 | { | 
| 125 |     bool success = true; | 
| 126 |  | 
| 127 |     if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) | 
| 128 |         return true; | 
| 129 |  | 
| 130 |     // | 
| 131 |     // Function is re-entrant and this thread may not have been initialized. | 
| 132 |     // | 
| 133 |     if (OS_GetTLSValue(ThreadInitializeIndex) != nullptr) { | 
| 134 |         if (!OS_SetTLSValue(ThreadInitializeIndex, nullptr)) { | 
| 135 |             assert(0 && "DetachThread(): Unable to clear init flag." ); | 
| 136 |             success = false; | 
| 137 |         } | 
| 138 |     } | 
| 139 |  | 
| 140 |     return success; | 
| 141 | } | 
| 142 |  | 
| 143 | // Not necessary to call this: InitProcess() is reentrant. | 
| 144 | // | 
| 145 | // This is kept, with memory management removed, to satisfy any exiting | 
| 146 | // calls to it that rely on it. | 
| 147 | // | 
| 148 | // Users of glslang should call shFinalize() or glslang::FinalizeProcess() for | 
| 149 | // process-scoped memory tear down. | 
| 150 | bool DetachProcess() | 
| 151 | { | 
| 152 |     bool success = true; | 
| 153 |  | 
| 154 |     if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) | 
| 155 |         return true; | 
| 156 |  | 
| 157 |     success = DetachThread(); | 
| 158 |  | 
| 159 |     OS_FreeTLSIndex(ThreadInitializeIndex); | 
| 160 |     ThreadInitializeIndex = OS_INVALID_TLS_INDEX; | 
| 161 |  | 
| 162 |     return success; | 
| 163 | } | 
| 164 |  | 
| 165 | } // end namespace glslang | 
| 166 |  |