1 /*-------------------------------------------------------------------------
2  * drawElements Thread Library
3  * ---------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * 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, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Win32 implementation of mutex.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "deMutex.h"
25 
26 #if (DE_OS == DE_OS_WIN32 || DE_OS == DE_OS_WINCE)
27 
28 #include "deMemory.h"
29 
30 #define VC_EXTRALEAN
31 #define WIN32_LEAN_AND_MEAN
32 #define NOMINMAX
33 #include <windows.h>
34 
35 /* Critical section objects are more lightweight than mutexes on Win32. */
36 #define USE_CRITICAL_SECTION 1
37 
38 #if defined(USE_CRITICAL_SECTION)
39 
40 enum
41 {
42 	CRITICAL_SECTION_SPIN_COUNT	= 2048
43 };
44 
45 DE_STATIC_ASSERT(sizeof(deMutex) >= sizeof(CRITICAL_SECTION*));
46 
deMutex_create(const deMutexAttributes * attributes)47 deMutex deMutex_create (const deMutexAttributes* attributes)
48 {
49 	CRITICAL_SECTION* criticalSection = (CRITICAL_SECTION*)deMalloc(sizeof(CRITICAL_SECTION));
50 	if (!criticalSection)
51 		return 0;
52 
53 	DE_UNREF(attributes);
54 	/* \note [2012-11-05 pyry] Critical sections are always recursive. */
55 
56 	if (!InitializeCriticalSectionAndSpinCount(criticalSection, CRITICAL_SECTION_SPIN_COUNT))
57 	{
58 		deFree(criticalSection);
59 		return 0;
60 	}
61 
62 	return (deMutex)criticalSection;
63 }
64 
deMutex_destroy(deMutex mutex)65 void deMutex_destroy (deMutex mutex)
66 {
67 	DeleteCriticalSection((CRITICAL_SECTION*)mutex);
68 	deFree((CRITICAL_SECTION*)mutex);
69 }
70 
deMutex_lock(deMutex mutex)71 void deMutex_lock (deMutex mutex)
72 {
73 	EnterCriticalSection((CRITICAL_SECTION*)mutex);
74 }
75 
deMutex_unlock(deMutex mutex)76 void deMutex_unlock (deMutex mutex)
77 {
78 	LeaveCriticalSection((CRITICAL_SECTION*)mutex);
79 }
80 
deMutex_tryLock(deMutex mutex)81 deBool deMutex_tryLock (deMutex mutex)
82 {
83 	return TryEnterCriticalSection((CRITICAL_SECTION*)mutex) == TRUE;
84 }
85 
86 #else
87 
88 DE_STATIC_ASSERT(sizeof(deMutex) >= sizeof(HANDLE));
89 
deMutex_create(const deMutexAttributes * attributes)90 deMutex deMutex_create (const deMutexAttributes* attributes)
91 {
92 	HANDLE handle = DE_NULL;
93 
94 	DE_UNREF(attributes);
95 	/* \note [2009-11-12 pyry] Created mutex is always recursive. */
96 
97 	handle = CreateMutex(DE_NULL, FALSE, DE_NULL);
98 	return (deMutex)handle;
99 }
100 
deMutex_destroy(deMutex mutex)101 void deMutex_destroy (deMutex mutex)
102 {
103 	HANDLE handle = (HANDLE)mutex;
104 	CloseHandle(handle);
105 }
106 
deMutex_lock(deMutex mutex)107 void deMutex_lock (deMutex mutex)
108 {
109 	HANDLE	handle	= (HANDLE)mutex;
110 	DWORD	ret		= WaitForSingleObject(handle, INFINITE);
111 	DE_ASSERT(ret == WAIT_OBJECT_0);
112 }
113 
deMutex_unlock(deMutex mutex)114 void deMutex_unlock (deMutex mutex)
115 {
116 	HANDLE	handle	= (HANDLE)mutex;
117 	BOOL	ret		= ReleaseMutex(handle);
118 	DE_ASSERT(ret == TRUE);
119 }
120 
deMutex_tryLock(deMutex mutex)121 deBool deMutex_tryLock (deMutex mutex)
122 {
123 	HANDLE	handle	= (HANDLE)mutex;
124 	DWORD	ret		= WaitForSingleObject(handle, 0);
125 	return (ret == WAIT_OBJECT_0);
126 }
127 
128 #endif /* USE_CRITICAL_SECTION */
129 
130 #endif /* DE_OS */
131