1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #include "system.h" 25 26 #include <osl/mutex.h> 27 #include <osl/diagnose.h> 28 29 /* 30 Implementation notes: 31 The void* hidden by oslMutex points to a WIN32 32 CRITICAL_SECTION structure. 33 */ 34 35 typedef struct _oslMutexImpl { 36 CRITICAL_SECTION m_Mutex; 37 int m_Locks; 38 DWORD m_Owner; 39 DWORD m_Requests; 40 } oslMutexImpl; 41 42 static BOOL (WINAPI *lpfTryEnterCriticalSection)(LPCRITICAL_SECTION) 43 = (BOOL (WINAPI *)(LPCRITICAL_SECTION))0xFFFFFFFF; 44 45 static CRITICAL_SECTION MutexLock; 46 47 /*****************************************************************************/ 48 /* osl_createMutex */ 49 /*****************************************************************************/ 50 oslMutex SAL_CALL osl_createMutex(void) 51 { 52 oslMutexImpl *pMutexImpl; 53 54 /* Window 95 does not support "TryEnterCriticalSection" */ 55 56 if (lpfTryEnterCriticalSection == 57 (BOOL (WINAPI *)(LPCRITICAL_SECTION))0xFFFFFFFF) 58 { 59 OSVERSIONINFO VersionInformation = 60 61 { 62 sizeof(OSVERSIONINFO), 63 0, 64 0, 65 0, 66 0, 67 "", 68 }; 69 70 /* ts: Window 98 does not support "TryEnterCriticalSection" but export the symbol !!! 71 calls to that symbol always returns FALSE */ 72 if ( 73 GetVersionEx(&VersionInformation) && 74 (VersionInformation.dwPlatformId == VER_PLATFORM_WIN32_NT) 75 ) 76 { 77 lpfTryEnterCriticalSection = (BOOL (WINAPI *)(LPCRITICAL_SECTION)) 78 GetProcAddress(GetModuleHandle("KERNEL32"), 79 "TryEnterCriticalSection"); 80 } 81 else 82 { 83 lpfTryEnterCriticalSection = (BOOL (WINAPI *)(LPCRITICAL_SECTION))NULL; 84 } 85 86 87 InitializeCriticalSection(&MutexLock); 88 } 89 90 pMutexImpl= calloc(sizeof(oslMutexImpl), 1); 91 92 OSL_ASSERT(pMutexImpl); /* alloc successful? */ 93 94 InitializeCriticalSection(&pMutexImpl->m_Mutex); 95 96 return (oslMutex)pMutexImpl; 97 } 98 99 /*****************************************************************************/ 100 /* osl_destroyMutex */ 101 /*****************************************************************************/ 102 void SAL_CALL osl_destroyMutex(oslMutex Mutex) 103 { 104 oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex; 105 106 if (pMutexImpl) 107 { 108 DeleteCriticalSection(&pMutexImpl->m_Mutex); 109 free(pMutexImpl); 110 } 111 } 112 113 /*****************************************************************************/ 114 /* osl_acquireMutex */ 115 /*****************************************************************************/ 116 sal_Bool SAL_CALL osl_acquireMutex(oslMutex Mutex) 117 { 118 oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex; 119 120 OSL_ASSERT(Mutex); 121 122 if (lpfTryEnterCriticalSection == NULL) 123 { 124 EnterCriticalSection(&MutexLock); 125 pMutexImpl->m_Requests++; 126 LeaveCriticalSection(&MutexLock); 127 128 EnterCriticalSection(&pMutexImpl->m_Mutex); 129 130 EnterCriticalSection(&MutexLock); 131 pMutexImpl->m_Requests--; 132 if (pMutexImpl->m_Locks++ == 0) 133 pMutexImpl->m_Owner = GetCurrentThreadId(); 134 LeaveCriticalSection(&MutexLock); 135 } 136 else 137 EnterCriticalSection(&pMutexImpl->m_Mutex); 138 139 return sal_True; 140 } 141 142 /*****************************************************************************/ 143 /* osl_tryToAcquireMutex */ 144 /*****************************************************************************/ 145 sal_Bool SAL_CALL osl_tryToAcquireMutex(oslMutex Mutex) 146 { 147 sal_Bool ret = sal_False; 148 oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex; 149 150 OSL_ASSERT(Mutex); 151 152 if (lpfTryEnterCriticalSection != NULL) 153 return (sal_Bool)(lpfTryEnterCriticalSection(&pMutexImpl->m_Mutex) != FALSE); 154 else 155 { 156 EnterCriticalSection(&MutexLock); 157 158 if ( ((pMutexImpl->m_Requests == 0) && (pMutexImpl->m_Locks == 0)) || 159 (pMutexImpl->m_Owner == GetCurrentThreadId()) ) 160 ret = osl_acquireMutex(Mutex); 161 162 LeaveCriticalSection(&MutexLock); 163 } 164 165 return ret; 166 } 167 168 /*****************************************************************************/ 169 /* osl_releaseMutex */ 170 /*****************************************************************************/ 171 sal_Bool SAL_CALL osl_releaseMutex(oslMutex Mutex) 172 { 173 oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex; 174 175 OSL_ASSERT(Mutex); 176 177 if (lpfTryEnterCriticalSection == NULL) 178 { 179 EnterCriticalSection(&MutexLock); 180 181 if (--(pMutexImpl->m_Locks) == 0) 182 pMutexImpl->m_Owner = 0; 183 184 LeaveCriticalSection(&MutexLock); 185 } 186 187 LeaveCriticalSection(&pMutexImpl->m_Mutex); 188 189 return sal_True; 190 } 191 192 /*****************************************************************************/ 193 /* osl_getGlobalMutex */ 194 /*****************************************************************************/ 195 196 /* initialized in dllentry.c */ 197 oslMutex g_Mutex; 198 199 oslMutex * SAL_CALL osl_getGlobalMutex(void) 200 { 201 return &g_Mutex; 202 } 203