xref: /AOO41X/main/sal/osl/w32/mutex.c (revision 647f063d49501903f1667b75f5634541fc603283)
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 /*****************************************************************************/
osl_createMutex(void)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 /*****************************************************************************/
osl_destroyMutex(oslMutex Mutex)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 /*****************************************************************************/
osl_acquireMutex(oslMutex Mutex)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 /*****************************************************************************/
osl_tryToAcquireMutex(oslMutex Mutex)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 /*****************************************************************************/
osl_releaseMutex(oslMutex Mutex)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 
osl_getGlobalMutex(void)199 oslMutex * SAL_CALL osl_getGlobalMutex(void)
200 {
201     return &g_Mutex;
202 }
203