1 martin 1.16 //%LICENSE////////////////////////////////////////////////////////////////
|
2 martin 1.17 //
|
3 martin 1.16 // Licensed to The Open Group (TOG) under one or more contributor license
4 // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
5 // this work for additional information regarding copyright ownership.
6 // Each contributor licenses this file to you under the OpenPegasus Open
7 // Source License; you may not use this file except in compliance with the
8 // License.
|
9 martin 1.17 //
|
10 martin 1.16 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
|
16 martin 1.17 //
|
17 martin 1.16 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
|
19 martin 1.17 //
|
20 martin 1.16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
21 martin 1.17 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22 martin 1.16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27 martin 1.17 //
|
28 martin 1.16 //////////////////////////////////////////////////////////////////////////
|
29 mike 1.2 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
32 #include "Mutex.h"
|
33 mike 1.4 #include "Time.h"
34 #include "PegasusAssert.h"
35 #include "Once.h"
|
36 kumpf 1.14 #include "Exception.h"
37 #include "System.h"
38
39 #define MUTEX_LOCK_FAILED_KEY "Common.InternalException.MUTEX_LOCK_FAILED"
40 #define MUTEX_LOCK_FAILED_MSG "Failed to acquire mutex lock: $0"
|
41 mike 1.2
42 PEGASUS_NAMESPACE_BEGIN
43
|
44 mike 1.4 //==============================================================================
45 //
46 // PEGASUS_HAVE_PTHREADS
47 //
48 //==============================================================================
49
50 #if defined(PEGASUS_HAVE_PTHREADS)
51
52 static Once _once = PEGASUS_ONCE_INITIALIZER;
53 static pthread_mutexattr_t _attr;
54
55 static void _init_attr()
56 {
57 pthread_mutexattr_init(&_attr);
58 pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_RECURSIVE);
59 }
60
61 Mutex::Mutex()
62 {
63 once(&_once, _init_attr);
64 pthread_mutex_init(&_rep.mutex, &_attr);
65 mike 1.4 #if defined(PEGASUS_DEBUG)
66 _rep.count = 0;
67 #endif
68 }
69
|
70 mike 1.6 Mutex::Mutex(RecursiveTag)
71 {
72 once(&_once, _init_attr);
73 pthread_mutex_init(&_rep.mutex, &_attr);
74 #if defined(PEGASUS_DEBUG)
75 _rep.count = 0;
76 #endif
77 }
78
79 Mutex::Mutex(NonRecursiveTag)
80 {
81 pthread_mutex_init(&_rep.mutex, NULL);
82 #if defined(PEGASUS_DEBUG)
83 _rep.count = 0;
84 #endif
85 }
86
|
87 mike 1.4 Mutex::~Mutex()
88 {
89 PEGASUS_DEBUG_ASSERT(_magic);
90 pthread_mutex_destroy(&_rep.mutex);
91 }
92
93 void Mutex::lock()
94 {
95 PEGASUS_DEBUG_ASSERT(_magic);
96
|
97 kumpf 1.14 int r = pthread_mutex_lock(&_rep.mutex);
98
99 if (r == 0)
|
100 mike 1.4 {
101 #if defined(PEGASUS_DEBUG)
|
102 kumpf 1.14 _rep.count++;
|
103 mike 1.4 #endif
|
104 kumpf 1.14 }
105 else
106 {
107 if (r != -1)
108 {
109 // Special behavior for Single UNIX Specification, Version 3
110 errno = r;
111 }
|
112 mike 1.4
|
113 kumpf 1.14 throw Exception(MessageLoaderParms(
114 MUTEX_LOCK_FAILED_KEY,
115 MUTEX_LOCK_FAILED_MSG,
116 PEGASUS_SYSTEM_ERRORMSG_NLS));
|
117 mike 1.4 }
118 }
119
|
120 kumpf 1.12 Boolean Mutex::try_lock()
|
121 mike 1.4 {
122 PEGASUS_DEBUG_ASSERT(_magic);
123
|
124 marek 1.5 int r = pthread_mutex_trylock(&_rep.mutex);
|
125 kumpf 1.12
126 if (r == 0)
|
127 mike 1.4 {
128 #if defined(PEGASUS_DEBUG)
|
129 kumpf 1.12 _rep.count++;
|
130 mike 1.4 #endif
|
131 kumpf 1.12 return true;
132 }
|
133 mike 1.4
|
134 kumpf 1.14 if (r != -1)
135 {
136 // Special behavior for Single UNIX Specification, Version 3
137 errno = r;
138 }
139
140 if (errno == EBUSY)
|
141 kumpf 1.12 {
142 return false;
143 }
|
144 mike 1.4
|
145 kumpf 1.14 throw Exception(MessageLoaderParms(
146 MUTEX_LOCK_FAILED_KEY,
147 MUTEX_LOCK_FAILED_MSG,
148 PEGASUS_SYSTEM_ERRORMSG_NLS));
|
149 mike 1.4 }
150
|
151 kumpf 1.11 Boolean Mutex::timed_lock(Uint32 milliseconds)
|
152 mike 1.4 {
153 struct timeval now;
154 struct timeval finish;
155 struct timeval remaining;
156 {
157 Uint32 usec;
158 gettimeofday(&finish, NULL);
159 finish.tv_sec += (milliseconds / 1000 );
160 milliseconds %= 1000;
161 usec = finish.tv_usec + ( milliseconds * 1000 );
162 finish.tv_sec += (usec / 1000000);
163 finish.tv_usec = usec % 1000000;
164 }
165
|
166 kumpf 1.14 while (!try_lock())
|
167 mike 1.4 {
|
168 kumpf 1.14 gettimeofday(&now, NULL);
|
169 kumpf 1.11
|
170 kumpf 1.14 if (Time::subtract(&remaining, &finish, &now))
|
171 kumpf 1.11 {
|
172 kumpf 1.14 return false;
|
173 kumpf 1.11 }
|
174 mike 1.4
|
175 kumpf 1.14 Threads::yield();
|
176 mike 1.4 }
|
177 kumpf 1.11
178 return true;
|
179 mike 1.4 }
180
181 void Mutex::unlock()
182 {
183 PEGASUS_DEBUG_ASSERT(_magic);
184 PEGASUS_DEBUG_ASSERT(_rep.count > 0);
185
186 #if defined(PEGASUS_DEBUG)
187 _rep.count--;
188 #endif
189
|
190 kumpf 1.13 // All documented error codes represent coding errors.
|
191 marek 1.19 PEGASUS_FCT_EXECUTE_AND_ASSERT(0, pthread_mutex_unlock(&_rep.mutex));
|
192 mike 1.4 }
193
|
194 thilo.boehm 1.15 #if defined(PEGASUS_OS_LINUX)
|
195 kumpf 1.8 void Mutex::reinitialize()
196 {
197 pthread_mutex_init(&_rep.mutex, &_attr);
198 #if defined(PEGASUS_DEBUG)
199 _rep.count = 0;
200 #endif
201 }
202 #endif
203
|
204 mike 1.4 #endif /* PEGASUS_HAVE_PTHREADS */
205
206 //==============================================================================
207 //
208 // PEGASUS_HAVE_WINDOWS_THREADS
209 //
210 //==============================================================================
211
212 #if defined(PEGASUS_HAVE_WINDOWS_THREADS)
213
|
214 mike 1.7 static inline void _initialize(MutexRep& rep)
215 {
216 rep.handle = CreateMutex(NULL, FALSE, NULL);
|
217 kavita.gupta 1.18 if (rep.handle == NULL)
218 {
219 throw Exception(MessageLoaderParms(
220 "Common.InternalException.CREATE_MUTEX_FAILED",
221 "CreateMutex failed : $0",
222 PEGASUS_SYSTEM_ERRORMSG_NLS));
223 }
|
224 mike 1.7 rep.count = 0;
225 }
226
|
227 mike 1.4 Mutex::Mutex()
228 {
|
229 mike 1.7 _initialize(_rep);
230 }
231
|
232 mike 1.6 Mutex::Mutex(RecursiveTag)
233 {
|
234 mike 1.7 _initialize(_rep);
|
235 mike 1.6 }
236
237 Mutex::Mutex(NonRecursiveTag)
238 {
|
239 mike 1.7 _initialize(_rep);
|
240 mike 1.4 }
241
242 Mutex::~Mutex()
243 {
244 PEGASUS_DEBUG_ASSERT(_magic);
245
246 WaitForSingleObject(_rep.handle, INFINITE);
247 CloseHandle(_rep.handle);
248 }
249
250 void Mutex::lock()
251 {
252 PEGASUS_DEBUG_ASSERT(_magic);
253
254 DWORD rc = WaitForSingleObject(_rep.handle, INFINITE);
255
256 if (rc == WAIT_FAILED)
|
257 kumpf 1.14 {
258 throw Exception(MessageLoaderParms(
259 MUTEX_LOCK_FAILED_KEY,
260 MUTEX_LOCK_FAILED_MSG,
261 PEGASUS_SYSTEM_ERRORMSG_NLS));
262 }
|
263 mike 1.4
264 _rep.count++;
265 }
266
|
267 kumpf 1.12 Boolean Mutex::try_lock()
|
268 mike 1.4 {
269 PEGASUS_DEBUG_ASSERT(_magic);
270
271 DWORD rc = WaitForSingleObject(_rep.handle, 0);
272
273 if (rc == WAIT_TIMEOUT)
|
274 kumpf 1.12 {
275 return false;
276 }
|
277 mike 1.4
278 if (rc == WAIT_FAILED)
|
279 kumpf 1.12 {
|
280 kumpf 1.14 throw Exception(MessageLoaderParms(
281 MUTEX_LOCK_FAILED_KEY,
282 MUTEX_LOCK_FAILED_MSG,
283 PEGASUS_SYSTEM_ERRORMSG_NLS));
|
284 kumpf 1.12 }
|
285 mike 1.4
286 _rep.count++;
|
287 kumpf 1.12 return true;
|
288 mike 1.4 }
289
|
290 kumpf 1.11 Boolean Mutex::timed_lock(Uint32 milliseconds)
|
291 mike 1.4 {
292 PEGASUS_DEBUG_ASSERT(_magic);
293
294 DWORD rc = WaitForSingleObject(_rep.handle, milliseconds);
295
296 if (rc == WAIT_TIMEOUT)
|
297 kumpf 1.11 return false;
|
298 mike 1.4
299 if (rc == WAIT_FAILED)
|
300 kumpf 1.14 {
301 throw Exception(MessageLoaderParms(
302 MUTEX_LOCK_FAILED_KEY,
303 MUTEX_LOCK_FAILED_MSG,
304 PEGASUS_SYSTEM_ERRORMSG_NLS));
305 }
|
306 mike 1.4
307 _rep.count++;
|
308 kumpf 1.11 return true;
|
309 mike 1.4 }
310
311 void Mutex::unlock()
312 {
313 PEGASUS_DEBUG_ASSERT(_magic);
314 PEGASUS_DEBUG_ASSERT(_rep.count > 0);
315
316 _rep.count--;
317 ReleaseMutex(_rep.handle);
318 }
319
320 #endif /* PEGASUS_HAVE_WINDOWS_THREADS */
321
|
322 mike 1.2 PEGASUS_NAMESPACE_END
|