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