xref: /aoo42x/main/sal/osl/w32/mutex.c (revision cdf0e10c)
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