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