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
44namespace glslang {
45
46OS_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.
52bool 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.
95bool 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.
123bool 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.
150bool 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