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 //
36 // This file contains the Linux-specific functions
37 //
38 #include "../osinclude.h"
39 #include "../../../OGLCompilersDLL/InitializeDll.h"
40
41 #include <pthread.h>
42 #include <semaphore.h>
43 #include <assert.h>
44 #include <errno.h>
45 #include <stdint.h>
46 #include <cstdio>
47 #include <sys/time.h>
48
49 #if !defined(__Fuchsia__)
50 #include <sys/resource.h>
51 #endif
52
53 namespace glslang {
54
55 //
56 // Thread cleanup
57 //
58
59 //
60 // Wrapper for Linux call to DetachThread. This is required as pthread_cleanup_push() expects
61 // the cleanup routine to return void.
62 //
DetachThreadLinux(void *)63 static void DetachThreadLinux(void *)
64 {
65 DetachThread();
66 }
67
68 //
69 // Registers cleanup handler, sets cancel type and state, and executes the thread specific
70 // cleanup handler. This function will be called in the Standalone.cpp for regression
71 // testing. When OpenGL applications are run with the driver code, Linux OS does the
72 // thread cleanup.
73 //
OS_CleanupThreadData(void)74 void OS_CleanupThreadData(void)
75 {
76 #if defined(__ANDROID__) || defined(__Fuchsia__)
77 DetachThreadLinux(NULL);
78 #else
79 int old_cancel_state, old_cancel_type;
80 void *cleanupArg = NULL;
81
82 //
83 // Set thread cancel state and push cleanup handler.
84 //
85 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_cancel_state);
86 pthread_cleanup_push(DetachThreadLinux, (void *) cleanupArg);
87
88 //
89 // Put the thread in deferred cancellation mode.
90 //
91 //pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &old_cancel_type);
92
93 //
94 // Pop cleanup handler and execute it prior to unregistering the cleanup handler.
95 //
96 pthread_cleanup_pop(1);
97
98 //
99 // Restore the thread's previous cancellation mode.
100 //
101 //pthread_setcanceltype(old_cancel_state, NULL);
102 #endif
103 }
104
105 //
106 // Thread Local Storage Operations
107 //
PthreadKeyToTLSIndex(pthread_key_t key)108 inline OS_TLSIndex PthreadKeyToTLSIndex(pthread_key_t key)
109 {
110 return (OS_TLSIndex)((uintptr_t)key + 1);
111 }
112
TLSIndexToPthreadKey(OS_TLSIndex nIndex)113 inline pthread_key_t TLSIndexToPthreadKey(OS_TLSIndex nIndex)
114 {
115 return (pthread_key_t)((uintptr_t)nIndex - 1);
116 }
117
OS_AllocTLSIndex()118 OS_TLSIndex OS_AllocTLSIndex()
119 {
120 pthread_key_t pPoolIndex;
121
122 //
123 // Create global pool key.
124 //
125 if ((pthread_key_create(&pPoolIndex, NULL)) != 0) {
126 assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
127 return OS_INVALID_TLS_INDEX;
128 }
129 else
130 return PthreadKeyToTLSIndex(pPoolIndex);
131 }
132
OS_SetTLSValue(OS_TLSIndex nIndex,void * lpvValue)133 bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
134 {
135 if (nIndex == OS_INVALID_TLS_INDEX) {
136 assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
137 return false;
138 }
139
140 if (pthread_setspecific(TLSIndexToPthreadKey(nIndex), lpvValue) == 0)
141 return true;
142 else
143 return false;
144 }
145
OS_GetTLSValue(OS_TLSIndex nIndex)146 void* OS_GetTLSValue(OS_TLSIndex nIndex)
147 {
148 //
149 // This function should return 0 if nIndex is invalid.
150 //
151 assert(nIndex != OS_INVALID_TLS_INDEX);
152 return pthread_getspecific(TLSIndexToPthreadKey(nIndex));
153 }
154
OS_FreeTLSIndex(OS_TLSIndex nIndex)155 bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
156 {
157 if (nIndex == OS_INVALID_TLS_INDEX) {
158 assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
159 return false;
160 }
161
162 //
163 // Delete the global pool key.
164 //
165 if (pthread_key_delete(TLSIndexToPthreadKey(nIndex)) == 0)
166 return true;
167 else
168 return false;
169 }
170
171 namespace {
172 pthread_mutex_t gMutex;
173 }
174
InitGlobalLock()175 void InitGlobalLock()
176 {
177 pthread_mutexattr_t mutexattr;
178 pthread_mutexattr_init(&mutexattr);
179 pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
180 pthread_mutex_init(&gMutex, &mutexattr);
181 }
182
GetGlobalLock()183 void GetGlobalLock()
184 {
185 pthread_mutex_lock(&gMutex);
186 }
187
ReleaseGlobalLock()188 void ReleaseGlobalLock()
189 {
190 pthread_mutex_unlock(&gMutex);
191 }
192
193 // #define DUMP_COUNTERS
194
OS_DumpMemoryCounters()195 void OS_DumpMemoryCounters()
196 {
197 #ifdef DUMP_COUNTERS
198 struct rusage usage;
199
200 if (getrusage(RUSAGE_SELF, &usage) == 0)
201 printf("Working set size: %ld\n", usage.ru_maxrss * 1024);
202 #else
203 printf("Recompile with DUMP_COUNTERS defined to see counters.\n");
204 #endif
205 }
206
207 } // end namespace glslang
208