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 thilo.boehm 1.10 #if defined(PEGASUS_OS_LINUX) || \
191 (defined(PEGASUS_OS_ZOS) && !(__TARGET_LIB__ < 0x41090000))
|
192 kumpf 1.8 void Mutex::reinitialize()
193 {
194 pthread_mutex_init(&_rep.mutex, &_attr);
195 #if defined(PEGASUS_DEBUG)
196 _rep.count = 0;
197 #endif
198 }
199 #endif
200
|
201 mike 1.4 #endif /* PEGASUS_HAVE_PTHREADS */
202
203 //==============================================================================
204 //
205 // PEGASUS_HAVE_WINDOWS_THREADS
206 //
207 //==============================================================================
208
209 #if defined(PEGASUS_HAVE_WINDOWS_THREADS)
210
|
211 mike 1.7 static inline void _initialize(MutexRep& rep)
212 {
213 rep.handle = CreateMutex(NULL, FALSE, NULL);
214 rep.count = 0;
215 }
216
|
217 mike 1.4 Mutex::Mutex()
218 {
|
219 mike 1.7 _initialize(_rep);
220 }
221
|
222 mike 1.6 Mutex::Mutex(RecursiveTag)
223 {
|
224 mike 1.7 _initialize(_rep);
|
225 mike 1.6 }
226
227 Mutex::Mutex(NonRecursiveTag)
228 {
|
229 mike 1.7 _initialize(_rep);
|
230 mike 1.4 }
231
232 Mutex::~Mutex()
233 {
234 PEGASUS_DEBUG_ASSERT(_magic);
235
236 WaitForSingleObject(_rep.handle, INFINITE);
237 CloseHandle(_rep.handle);
238 }
239
240 void Mutex::lock()
241 {
242 PEGASUS_DEBUG_ASSERT(_magic);
243
244 DWORD rc = WaitForSingleObject(_rep.handle, INFINITE);
245
246 if (rc == WAIT_FAILED)
247 throw WaitFailed(Threads::self());
248
249 _rep.count++;
250 }
251 mike 1.4
252 void Mutex::try_lock()
253 {
254 PEGASUS_DEBUG_ASSERT(_magic);
255
256 DWORD rc = WaitForSingleObject(_rep.handle, 0);
257
258 if (rc == WAIT_TIMEOUT)
259 throw AlreadyLocked(Threads::self());
260
261 if (rc == WAIT_FAILED)
262 throw WaitFailed(Threads::self());
263
264 _rep.count++;
265 }
266
267 void Mutex::timed_lock(Uint32 milliseconds)
268 {
269 PEGASUS_DEBUG_ASSERT(_magic);
270
271 DWORD rc = WaitForSingleObject(_rep.handle, milliseconds);
272 mike 1.4
273 if (rc == WAIT_TIMEOUT)
274 throw TimeOut(Threads::self());
275
276 if (rc == WAIT_FAILED)
277 throw WaitFailed(Threads::self());
278
279 _rep.count++;
280 }
281
282 void Mutex::unlock()
283 {
284 PEGASUS_DEBUG_ASSERT(_magic);
285 PEGASUS_DEBUG_ASSERT(_rep.count > 0);
286
287 _rep.count--;
288 ReleaseMutex(_rep.handle);
289 }
290
291 #endif /* PEGASUS_HAVE_WINDOWS_THREADS */
292
|
293 mike 1.2 PEGASUS_NAMESPACE_END
|