xref: /trunk/main/sal/osl/w32/mutex.c (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "system.h"
29 
30 #include <osl/mutex.h>
31 #include <osl/diagnose.h>
32 
33 /*
34     Implementation notes:
35     The void* hidden by oslMutex points to a WIN32
36     CRITICAL_SECTION structure.
37 */
38 
39 typedef struct _oslMutexImpl {
40     CRITICAL_SECTION    m_Mutex;
41     int                 m_Locks;
42     DWORD               m_Owner;
43     DWORD               m_Requests;
44 } oslMutexImpl;
45 
46 static BOOL (WINAPI *lpfTryEnterCriticalSection)(LPCRITICAL_SECTION)
47     = (BOOL (WINAPI *)(LPCRITICAL_SECTION))0xFFFFFFFF;
48 
49 static CRITICAL_SECTION MutexLock;
50 
51 /*****************************************************************************/
52 /* osl_createMutex */
53 /*****************************************************************************/
54 oslMutex SAL_CALL osl_createMutex(void)
55 {
56     oslMutexImpl *pMutexImpl;
57 
58     /* Window 95 does not support "TryEnterCriticalSection" */
59 
60     if (lpfTryEnterCriticalSection ==
61                 (BOOL (WINAPI *)(LPCRITICAL_SECTION))0xFFFFFFFF)
62     {
63         OSVERSIONINFO VersionInformation =
64 
65         {
66             sizeof(OSVERSIONINFO),
67             0,
68             0,
69             0,
70             0,
71             "",
72         };
73 
74         /* ts: Window 98 does not support "TryEnterCriticalSection" but export the symbol !!!
75            calls to that symbol always returns FALSE */
76         if (
77             GetVersionEx(&VersionInformation) &&
78             (VersionInformation.dwPlatformId == VER_PLATFORM_WIN32_NT)
79            )
80         {
81             lpfTryEnterCriticalSection = (BOOL (WINAPI *)(LPCRITICAL_SECTION))
82                     GetProcAddress(GetModuleHandle("KERNEL32"),
83                                    "TryEnterCriticalSection");
84         }
85         else
86         {
87             lpfTryEnterCriticalSection = (BOOL (WINAPI *)(LPCRITICAL_SECTION))NULL;
88         }
89 
90 
91         InitializeCriticalSection(&MutexLock);
92     }
93 
94     pMutexImpl= calloc(sizeof(oslMutexImpl), 1);
95 
96     OSL_ASSERT(pMutexImpl); /* alloc successful? */
97 
98     InitializeCriticalSection(&pMutexImpl->m_Mutex);
99 
100     return (oslMutex)pMutexImpl;
101 }
102 
103 /*****************************************************************************/
104 /* osl_destroyMutex */
105 /*****************************************************************************/
106 void SAL_CALL osl_destroyMutex(oslMutex Mutex)
107 {
108     oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex;
109 
110     if (pMutexImpl)
111     {
112         DeleteCriticalSection(&pMutexImpl->m_Mutex);
113         free(pMutexImpl);
114     }
115 }
116 
117 /*****************************************************************************/
118 /* osl_acquireMutex */
119 /*****************************************************************************/
120 sal_Bool SAL_CALL osl_acquireMutex(oslMutex Mutex)
121 {
122     oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex;
123 
124     OSL_ASSERT(Mutex);
125 
126     if (lpfTryEnterCriticalSection == NULL)
127     {
128         EnterCriticalSection(&MutexLock);
129         pMutexImpl->m_Requests++;
130         LeaveCriticalSection(&MutexLock);
131 
132         EnterCriticalSection(&pMutexImpl->m_Mutex);
133 
134         EnterCriticalSection(&MutexLock);
135         pMutexImpl->m_Requests--;
136         if (pMutexImpl->m_Locks++ == 0)
137             pMutexImpl->m_Owner = GetCurrentThreadId();
138         LeaveCriticalSection(&MutexLock);
139     }
140     else
141         EnterCriticalSection(&pMutexImpl->m_Mutex);
142 
143     return sal_True;
144 }
145 
146 /*****************************************************************************/
147 /* osl_tryToAcquireMutex */
148 /*****************************************************************************/
149 sal_Bool SAL_CALL osl_tryToAcquireMutex(oslMutex Mutex)
150 {
151     sal_Bool     ret = sal_False;
152     oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex;
153 
154     OSL_ASSERT(Mutex);
155 
156     if (lpfTryEnterCriticalSection != NULL)
157         return (sal_Bool)(lpfTryEnterCriticalSection(&pMutexImpl->m_Mutex) != FALSE);
158     else
159     {
160         EnterCriticalSection(&MutexLock);
161 
162         if ( ((pMutexImpl->m_Requests == 0) && (pMutexImpl->m_Locks == 0)) ||
163              (pMutexImpl->m_Owner == GetCurrentThreadId()) )
164             ret = osl_acquireMutex(Mutex);
165 
166         LeaveCriticalSection(&MutexLock);
167     }
168 
169     return ret;
170 }
171 
172 /*****************************************************************************/
173 /* osl_releaseMutex */
174 /*****************************************************************************/
175 sal_Bool SAL_CALL osl_releaseMutex(oslMutex Mutex)
176 {
177     oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex;
178 
179     OSL_ASSERT(Mutex);
180 
181     if (lpfTryEnterCriticalSection == NULL)
182     {
183         EnterCriticalSection(&MutexLock);
184 
185         if (--(pMutexImpl->m_Locks) == 0)
186             pMutexImpl->m_Owner = 0;
187 
188         LeaveCriticalSection(&MutexLock);
189     }
190 
191     LeaveCriticalSection(&pMutexImpl->m_Mutex);
192 
193     return sal_True;
194 }
195 
196 /*****************************************************************************/
197 /* osl_getGlobalMutex */
198 /*****************************************************************************/
199 
200 /* initialized in dllentry.c */
201 oslMutex g_Mutex;
202 
203 oslMutex * SAL_CALL osl_getGlobalMutex(void)
204 {
205     return &g_Mutex;
206 }
207