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 void Mutex::try_lock()
108 {
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 switch (r)
|
115 mike 1.4 {
116 case 0:
117 #if defined(PEGASUS_DEBUG)
118 _rep.count++;
119 #endif
120 break;
121
122 case EBUSY:
123 throw AlreadyLocked(Threads::self());
124
125 default:
126 throw WaitFailed(Threads::self());
127 }
128 }
129
130 void Mutex::timed_lock(Uint32 milliseconds)
131 {
132 PEGASUS_DEBUG_ASSERT(_magic);
133
134 struct timeval now;
135 struct timeval finish;
136 mike 1.4 struct timeval remaining;
137 {
138 Uint32 usec;
139 gettimeofday(&finish, NULL);
140 finish.tv_sec += (milliseconds / 1000 );
141 milliseconds %= 1000;
142 usec = finish.tv_usec + ( milliseconds * 1000 );
143 finish.tv_sec += (usec / 1000000);
144 finish.tv_usec = usec % 1000000;
145 }
146
147 for (;;)
148 {
|
149 marek 1.5 int r=pthread_mutex_trylock(&_rep.mutex);
150 if (r == -1)
151 r = errno;
152 switch (r)
|
153 mike 1.4 {
154 case 0:
155 #if defined(PEGASUS_DEBUG)
156 _rep.count++;
157 #endif
158 return;
159
160 case EBUSY:
161 {
162 gettimeofday(&now, NULL);
163
164 if (Time::subtract(&remaining, &finish, &now))
165 throw TimeOut(Threads::self());
166
167 Threads::yield();
168 break;
169 }
170
171 default:
172 throw WaitFailed(Threads::self());
173 }
174 mike 1.4 }
175 }
176
177 void Mutex::unlock()
178 {
179 PEGASUS_DEBUG_ASSERT(_magic);
180 PEGASUS_DEBUG_ASSERT(_rep.count > 0);
181
182 #if defined(PEGASUS_DEBUG)
183 _rep.count--;
184 #endif
185
186 if (pthread_mutex_unlock(&_rep.mutex) != 0)
187 throw Permission(Threads::self());
188 }
189
|
190 kumpf 1.8 #if defined(PEGASUS_OS_LINUX)
191 void Mutex::reinitialize()
192 {
193 pthread_mutex_init(&_rep.mutex, &_attr);
194 #if defined(PEGASUS_DEBUG)
195 _rep.count = 0;
196 #endif
197 }
198 #endif
199
|
200 mike 1.4 #endif /* PEGASUS_HAVE_PTHREADS */
201
202 //==============================================================================
203 //
204 // PEGASUS_HAVE_WINDOWS_THREADS
205 //
206 //==============================================================================
207
208 #if defined(PEGASUS_HAVE_WINDOWS_THREADS)
209
|
210 mike 1.7 static inline void _initialize(MutexRep& rep)
211 {
212 rep.handle = CreateMutex(NULL, FALSE, NULL);
213 #if defined(PEGASUS_DEBUG)
214 rep.count = 0;
215 #endif
216 }
217
|
218 mike 1.4 Mutex::Mutex()
219 {
|
220 mike 1.7 _initialize(_rep);
221 }
222
|
223 mike 1.6 Mutex::Mutex(RecursiveTag)
224 {
|
225 mike 1.7 _initialize(_rep);
|
226 mike 1.6 }
227
228 Mutex::Mutex(NonRecursiveTag)
229 {
|
230 mike 1.7 _initialize(_rep);
|
231 mike 1.4 }
232
233 Mutex::~Mutex()
234 {
235 PEGASUS_DEBUG_ASSERT(_magic);
236
237 WaitForSingleObject(_rep.handle, INFINITE);
238 CloseHandle(_rep.handle);
239 }
240
241 void Mutex::lock()
242 {
243 PEGASUS_DEBUG_ASSERT(_magic);
244
245 DWORD rc = WaitForSingleObject(_rep.handle, INFINITE);
246
247 if (rc == WAIT_FAILED)
248 throw WaitFailed(Threads::self());
249
250 #if defined(PEGASUS_DEBUG)
251 _rep.count++;
252 mike 1.4 #endif
253 }
254
255 void Mutex::try_lock()
256 {
257 PEGASUS_DEBUG_ASSERT(_magic);
258
259 DWORD rc = WaitForSingleObject(_rep.handle, 0);
260
261 if (rc == WAIT_TIMEOUT)
262 throw AlreadyLocked(Threads::self());
263
264 if (rc == WAIT_FAILED)
265 throw WaitFailed(Threads::self());
266
267 #if defined(PEGASUS_DEBUG)
268 _rep.count++;
269 #endif
270 }
271
272 void Mutex::timed_lock(Uint32 milliseconds)
273 mike 1.4 {
274 PEGASUS_DEBUG_ASSERT(_magic);
275
276 DWORD rc = WaitForSingleObject(_rep.handle, milliseconds);
277
278 if (rc == WAIT_TIMEOUT)
279 throw TimeOut(Threads::self());
280
281 if (rc == WAIT_FAILED)
282 throw WaitFailed(Threads::self());
283
284 #if defined(PEGASUS_DEBUG)
285 _rep.count++;
286 #endif
287 }
288
289 void Mutex::unlock()
290 {
291 PEGASUS_DEBUG_ASSERT(_magic);
292 PEGASUS_DEBUG_ASSERT(_rep.count > 0);
293
294 mike 1.4 #if defined(PEGASUS_DEBUG)
295 _rep.count--;
296 #endif
297 ReleaseMutex(_rep.handle);
298 }
299
300 #endif /* PEGASUS_HAVE_WINDOWS_THREADS */
301
|
302 mike 1.2 PEGASUS_NAMESPACE_END
|