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 mike 1.2
39 PEGASUS_NAMESPACE_BEGIN
40
|
41 mike 1.4 //==============================================================================
42 //
43 // PEGASUS_HAVE_PTHREADS
44 //
45 //==============================================================================
46
47 #if defined(PEGASUS_HAVE_PTHREADS)
48
49 static Once _once = PEGASUS_ONCE_INITIALIZER;
50 static pthread_mutexattr_t _attr;
51
52 static void _init_attr()
53 {
54 pthread_mutexattr_init(&_attr);
55 pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_RECURSIVE);
56 }
57
58 Mutex::Mutex()
59 {
60 once(&_once, _init_attr);
61 pthread_mutex_init(&_rep.mutex, &_attr);
62 mike 1.4 #if defined(PEGASUS_DEBUG)
63 _rep.count = 0;
64 #endif
65 }
66
|
67 mike 1.6 Mutex::Mutex(RecursiveTag)
68 {
69 once(&_once, _init_attr);
70 pthread_mutex_init(&_rep.mutex, &_attr);
71 #if defined(PEGASUS_DEBUG)
72 _rep.count = 0;
73 #endif
74 }
75
76 Mutex::Mutex(NonRecursiveTag)
77 {
78 pthread_mutex_init(&_rep.mutex, NULL);
79 #if defined(PEGASUS_DEBUG)
80 _rep.count = 0;
81 #endif
82 }
83
|
84 mike 1.4 Mutex::~Mutex()
85 {
86 PEGASUS_DEBUG_ASSERT(_magic);
87 pthread_mutex_destroy(&_rep.mutex);
88 }
89
90 void Mutex::lock()
91 {
92 PEGASUS_DEBUG_ASSERT(_magic);
93
94 switch (pthread_mutex_lock(&_rep.mutex))
95 {
96 case 0:
97 #if defined(PEGASUS_DEBUG)
98 _rep.count++;
99 #endif
100 break;
101
102 default:
103 throw WaitFailed(Threads::self());
104 }
105 mike 1.4 }
106
|
107 kumpf 1.12 Boolean Mutex::try_lock()
|
108 mike 1.4 {
109 PEGASUS_DEBUG_ASSERT(_magic);
110
|
111 marek 1.5 int r = pthread_mutex_trylock(&_rep.mutex);
112 if (r == -1)
113 r=errno;
|
114 kumpf 1.12
115 if (r == 0)
|
116 mike 1.4 {
117 #if defined(PEGASUS_DEBUG)
|
118 kumpf 1.12 _rep.count++;
|
119 mike 1.4 #endif
|
120 kumpf 1.12 return true;
121 }
|
122 mike 1.4
|
123 kumpf 1.12 if (r == EBUSY)
124 {
125 return false;
126 }
|
127 mike 1.4
|
128 kumpf 1.12 throw WaitFailed(Threads::self());
|
129 mike 1.4 }
130
|
131 kumpf 1.11 Boolean Mutex::timed_lock(Uint32 milliseconds)
|
132 mike 1.4 {
133 PEGASUS_DEBUG_ASSERT(_magic);
134
135 struct timeval now;
136 struct timeval finish;
137 struct timeval remaining;
138 {
139 Uint32 usec;
140 gettimeofday(&finish, NULL);
141 finish.tv_sec += (milliseconds / 1000 );
142 milliseconds %= 1000;
143 usec = finish.tv_usec + ( milliseconds * 1000 );
144 finish.tv_sec += (usec / 1000000);
145 finish.tv_usec = usec % 1000000;
146 }
147
148 for (;;)
149 {
|
150 marek 1.5 int r=pthread_mutex_trylock(&_rep.mutex);
151 if (r == -1)
152 r = errno;
|
153 kumpf 1.11
154 if (r == 0)
155 {
156 break;
157 }
158 else if (r == EBUSY)
|
159 mike 1.4 {
|
160 kumpf 1.11 gettimeofday(&now, NULL);
|
161 mike 1.4
|
162 kumpf 1.11 if (Time::subtract(&remaining, &finish, &now))
|
163 mike 1.4 {
|
164 kumpf 1.11 return false;
|
165 mike 1.4 }
166
|
167 kumpf 1.11 Threads::yield();
168 }
169 else
170 {
171 throw WaitFailed(Threads::self());
|
172 mike 1.4 }
173 }
|
174 kumpf 1.11
175 #if defined(PEGASUS_DEBUG)
176 _rep.count++;
177 #endif
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 if (pthread_mutex_unlock(&_rep.mutex) != 0)
191 throw Permission(Threads::self());
192 }
193
|
194 thilo.boehm 1.10 #if defined(PEGASUS_OS_LINUX) || \
195 (defined(PEGASUS_OS_ZOS) && !(__TARGET_LIB__ < 0x41090000))
|
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 rep.count = 0;
219 }
220
|
221 mike 1.4 Mutex::Mutex()
222 {
|
223 mike 1.7 _initialize(_rep);
224 }
225
|
226 mike 1.6 Mutex::Mutex(RecursiveTag)
227 {
|
228 mike 1.7 _initialize(_rep);
|
229 mike 1.6 }
230
231 Mutex::Mutex(NonRecursiveTag)
232 {
|
233 mike 1.7 _initialize(_rep);
|
234 mike 1.4 }
235
236 Mutex::~Mutex()
237 {
238 PEGASUS_DEBUG_ASSERT(_magic);
239
240 WaitForSingleObject(_rep.handle, INFINITE);
241 CloseHandle(_rep.handle);
242 }
243
244 void Mutex::lock()
245 {
246 PEGASUS_DEBUG_ASSERT(_magic);
247
248 DWORD rc = WaitForSingleObject(_rep.handle, INFINITE);
249
250 if (rc == WAIT_FAILED)
251 throw WaitFailed(Threads::self());
252
253 _rep.count++;
254 }
255 mike 1.4
|
256 kumpf 1.12 Boolean Mutex::try_lock()
|
257 mike 1.4 {
258 PEGASUS_DEBUG_ASSERT(_magic);
259
260 DWORD rc = WaitForSingleObject(_rep.handle, 0);
261
262 if (rc == WAIT_TIMEOUT)
|
263 kumpf 1.12 {
264 return false;
265 }
|
266 mike 1.4
267 if (rc == WAIT_FAILED)
|
268 kumpf 1.12 {
|
269 mike 1.4 throw WaitFailed(Threads::self());
|
270 kumpf 1.12 }
|
271 mike 1.4
272 _rep.count++;
|
273 kumpf 1.12 return true;
|
274 mike 1.4 }
275
|
276 kumpf 1.11 Boolean Mutex::timed_lock(Uint32 milliseconds)
|
277 mike 1.4 {
278 PEGASUS_DEBUG_ASSERT(_magic);
279
280 DWORD rc = WaitForSingleObject(_rep.handle, milliseconds);
281
282 if (rc == WAIT_TIMEOUT)
|
283 kumpf 1.11 return false;
|
284 mike 1.4
285 if (rc == WAIT_FAILED)
286 throw WaitFailed(Threads::self());
287
288 _rep.count++;
|
289 kumpf 1.11 return true;
|
290 mike 1.4 }
291
292 void Mutex::unlock()
293 {
294 PEGASUS_DEBUG_ASSERT(_magic);
295 PEGASUS_DEBUG_ASSERT(_rep.count > 0);
296
297 _rep.count--;
298 ReleaseMutex(_rep.handle);
299 }
300
301 #endif /* PEGASUS_HAVE_WINDOWS_THREADS */
302
|
303 mike 1.2 PEGASUS_NAMESPACE_END
|