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 int rc = pthread_mutex_unlock(&_rep.mutex);
191 // All documented error codes represent coding errors.
192 PEGASUS_ASSERT(rc == 0);
|
193 mike 1.4 }
194
|
195 thilo.boehm 1.15 #if defined(PEGASUS_OS_LINUX)
|
196 kumpf 1.8 void Mutex::reinitialize()
197 {
198 pthread_mutex_init(&_rep.mutex, &_attr);
199 #if defined(PEGASUS_DEBUG)
200 _rep.count = 0;
201 #endif
202 }
203 #endif
204
|
205 mike 1.4 #endif /* PEGASUS_HAVE_PTHREADS */
206
207 //==============================================================================
208 //
209 // PEGASUS_HAVE_WINDOWS_THREADS
210 //
211 //==============================================================================
212
213 #if defined(PEGASUS_HAVE_WINDOWS_THREADS)
214
|
215 mike 1.7 static inline void _initialize(MutexRep& rep)
216 {
217 rep.handle = CreateMutex(NULL, FALSE, NULL);
|
218 kavita.gupta 1.18 if (rep.handle == NULL)
219 {
220 throw Exception(MessageLoaderParms(
221 "Common.InternalException.CREATE_MUTEX_FAILED",
222 "CreateMutex failed : $0",
223 PEGASUS_SYSTEM_ERRORMSG_NLS));
224 }
|
225 mike 1.7 rep.count = 0;
226 }
227
|
228 mike 1.4 Mutex::Mutex()
229 {
|
230 mike 1.7 _initialize(_rep);
231 }
232
|
233 mike 1.6 Mutex::Mutex(RecursiveTag)
234 {
|
235 mike 1.7 _initialize(_rep);
|
236 mike 1.6 }
237
238 Mutex::Mutex(NonRecursiveTag)
239 {
|
240 mike 1.7 _initialize(_rep);
|
241 mike 1.4 }
242
243 Mutex::~Mutex()
244 {
245 PEGASUS_DEBUG_ASSERT(_magic);
246
247 WaitForSingleObject(_rep.handle, INFINITE);
248 CloseHandle(_rep.handle);
249 }
250
251 void Mutex::lock()
252 {
253 PEGASUS_DEBUG_ASSERT(_magic);
254
255 DWORD rc = WaitForSingleObject(_rep.handle, INFINITE);
256
257 if (rc == WAIT_FAILED)
|
258 kumpf 1.14 {
259 throw Exception(MessageLoaderParms(
260 MUTEX_LOCK_FAILED_KEY,
261 MUTEX_LOCK_FAILED_MSG,
262 PEGASUS_SYSTEM_ERRORMSG_NLS));
263 }
|
264 mike 1.4
265 _rep.count++;
266 }
267
|
268 kumpf 1.12 Boolean Mutex::try_lock()
|
269 mike 1.4 {
270 PEGASUS_DEBUG_ASSERT(_magic);
271
272 DWORD rc = WaitForSingleObject(_rep.handle, 0);
273
274 if (rc == WAIT_TIMEOUT)
|
275 kumpf 1.12 {
276 return false;
277 }
|
278 mike 1.4
279 if (rc == WAIT_FAILED)
|
280 kumpf 1.12 {
|
281 kumpf 1.14 throw Exception(MessageLoaderParms(
282 MUTEX_LOCK_FAILED_KEY,
283 MUTEX_LOCK_FAILED_MSG,
284 PEGASUS_SYSTEM_ERRORMSG_NLS));
|
285 kumpf 1.12 }
|
286 mike 1.4
287 _rep.count++;
|
288 kumpf 1.12 return true;
|
289 mike 1.4 }
290
|
291 kumpf 1.11 Boolean Mutex::timed_lock(Uint32 milliseconds)
|
292 mike 1.4 {
293 PEGASUS_DEBUG_ASSERT(_magic);
294
295 DWORD rc = WaitForSingleObject(_rep.handle, milliseconds);
296
297 if (rc == WAIT_TIMEOUT)
|
298 kumpf 1.11 return false;
|
299 mike 1.4
300 if (rc == WAIT_FAILED)
|
301 kumpf 1.14 {
302 throw Exception(MessageLoaderParms(
303 MUTEX_LOCK_FAILED_KEY,
304 MUTEX_LOCK_FAILED_MSG,
305 PEGASUS_SYSTEM_ERRORMSG_NLS));
306 }
|
307 mike 1.4
308 _rep.count++;
|
309 kumpf 1.11 return true;
|
310 mike 1.4 }
311
312 void Mutex::unlock()
313 {
314 PEGASUS_DEBUG_ASSERT(_magic);
315 PEGASUS_DEBUG_ASSERT(_rep.count > 0);
316
317 _rep.count--;
318 ReleaseMutex(_rep.handle);
319 }
320
321 #endif /* PEGASUS_HAVE_WINDOWS_THREADS */
322
|
323 mike 1.2 PEGASUS_NAMESPACE_END
|