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 // Author: Mike Day (mdday@us.ibm.com)
33 //
34 // Modified By: Markus Mueller
35 // Ramnath Ravindran (Ramnath.Ravindran@compaq.com)
36 // David Eger (dteger@us.ibm.com)
37 // Amit K Arora, IBM (amita@in.ibm.com) for PEP#101
38 // Sean Keenan, Hewlett-Packard Company (sean.keenan@hp.com)
39 // Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
40 // David Dillard, VERITAS Software Corp.
41 // (david.dillard@veritas.com)
42 mike 1.2 // Aruran, IBM (ashanmug@in.ibm.com) for BUG# 3518
43 //
|
44 mike 1.3.14.1 // Reworked By: Mike Brasher (m.brasher@inovadevelopment.com)
45 //
|
46 mike 1.2 //%/////////////////////////////////////////////////////////////////////////////
47
48 #include "Mutex.h"
|
49 mike 1.3.14.1 #include "Time.h"
50 #include "PegasusAssert.h"
|
51 mike 1.2
52 PEGASUS_NAMESPACE_BEGIN
53
|
54 mike 1.3.14.1 //==============================================================================
55 //
56 // PEGASUS_HAVE_PTHREADS
57 //
58 //==============================================================================
59
60 #if defined(PEGASUS_HAVE_PTHREADS)
61
62 Mutex::Mutex()
63 {
64 pthread_mutexattr_init(&_rep.attr);
65
66 // If your platform does not define PTHREAD_MUTEX_RECURSIVE, try
67 // PTHREAD_MUTEX_RECURSIVE_NP.
68 pthread_mutexattr_settype(&_rep.attr, PTHREAD_MUTEX_RECURSIVE);
69
70 pthread_mutex_init(&_rep.mutex, &_rep.attr);
|
71 mike 1.3.14.2 _rep.owner.clear();
|
72 mike 1.3.14.1 }
73
74 Mutex::~Mutex()
75 {
76 PEGASUS_DEBUG_ASSERT(_magic);
77
78 if (pthread_mutex_destroy(&_rep.mutex) == 0)
79 pthread_mutexattr_destroy(&_rep.attr);
80 }
81
82 void Mutex::lock(ThreadType caller)
83 {
84 PEGASUS_DEBUG_ASSERT(_magic);
85
86 switch (pthread_mutex_lock(&_rep.mutex))
87 {
88 case 0:
89 _rep.owner = caller;
90 break;
91
92 case EDEADLK:
93 mike 1.3.14.1 throw Deadlock(_rep.owner);
94
95 default:
96 throw WaitFailed(_rep.owner);
97 }
98 }
99
100 void Mutex::try_lock(ThreadType caller)
101 {
102 PEGASUS_DEBUG_ASSERT(_magic);
103
104 switch (pthread_mutex_trylock(&_rep.mutex))
105 {
106 case 0:
107 _rep.owner = caller;
108 break;
109
110 case EBUSY:
111 throw AlreadyLocked(_rep.owner);
112
113 case EDEADLK:
114 mike 1.3.14.1 throw Deadlock(_rep.owner);
115
116 default:
117 throw WaitFailed(_rep.owner);
118 }
119 }
120
121 void Mutex::timed_lock(Uint32 milliseconds, ThreadType caller)
122 {
123 PEGASUS_DEBUG_ASSERT(_magic);
124
125 struct timeval now;
126 struct timeval finish;
127 struct timeval remaining;
128 {
129 Uint32 usec;
130 gettimeofday(&finish, NULL);
131 finish.tv_sec += (milliseconds / 1000 );
132 milliseconds %= 1000;
133 usec = finish.tv_usec + ( milliseconds * 1000 );
134 finish.tv_sec += (usec / 1000000);
135 mike 1.3.14.1 finish.tv_usec = usec % 1000000;
136 }
137
138 for (;;)
139 {
140 switch (pthread_mutex_trylock(&_rep.mutex))
141 {
142 case 0:
143 return;
144
145 case EBUSY:
146 {
147 gettimeofday(&now, NULL);
148
149 if (Time::subtract(&remaining, &finish, &now))
150 throw TimeOut(Threads::self());
151
152 Threads::yield();
153 break;
154 }
155
156 mike 1.3.14.1 case EDEADLK:
157 throw Deadlock(Threads::self());
158
159 default:
160 throw WaitFailed(Threads::self());
161 }
162 }
163 }
164
165 void Mutex::unlock()
166 {
167 PEGASUS_DEBUG_ASSERT(_magic);
168
169 ThreadType owner = _rep.owner;
|
170 mike 1.3.14.2 _rep.owner.clear();
|
171 mike 1.3.14.1
172 if (pthread_mutex_unlock(&_rep.mutex) != 0)
173 {
174 _rep.owner = owner;
175 throw Permission(_rep.owner);
176 }
177 }
178
179 #endif /* PEGASUS_HAVE_PTHREADS */
180
181 //==============================================================================
182 //
183 // PEGASUS_HAVE_WINDOWS_THREADS
184 //
185 //==============================================================================
186
187 #if defined(PEGASUS_HAVE_WINDOWS_THREADS)
188
189 Mutex::Mutex()
190 {
191 _rep.handle = CreateMutex(NULL, FALSE, NULL);
192 mike 1.3.14.1 _rep.owner = ThreadType(0);
|
193 mike 1.3.14.2 _rep.count.clear();
|
194 mike 1.3.14.1 }
195
196 Mutex::~Mutex()
197 {
198 PEGASUS_DEBUG_ASSERT(_magic);
199
200 WaitForSingleObject(_rep.handle, INFINITE);
201 CloseHandle(_rep.handle);
202 }
203
204 void Mutex::lock(ThreadType caller)
205 {
206 PEGASUS_DEBUG_ASSERT(_magic);
207
208 DWORD rc = WaitForSingleObject(_rep.handle, INFINITE);
209
210 if (rc == WAIT_FAILED)
211 throw WaitFailed(_rep.owner);
212
213 _rep.owner = caller;
214 _rep.count++;
215 mike 1.3.14.1 }
216
217 void Mutex::try_lock(ThreadType caller)
218 {
219 PEGASUS_DEBUG_ASSERT(_magic);
220
221 DWORD rc = WaitForSingleObject(_rep.handle, 0);
222
223 if (rc == WAIT_TIMEOUT)
224 throw AlreadyLocked(_rep.owner);
225
226 if (rc == WAIT_FAILED)
227 throw WaitFailed(_rep.owner);
228
229 _rep.owner = caller;
230 _rep.count++;
231 }
232
233 void Mutex::timed_lock(Uint32 milliseconds , ThreadType caller)
234 {
235 PEGASUS_DEBUG_ASSERT(_magic);
236 mike 1.3.14.1
237 DWORD rc = WaitForSingleObject(_rep.handle, milliseconds);
238
239 if (rc == WAIT_TIMEOUT)
240 throw TimeOut(_rep.owner);
241
242 if (rc == WAIT_FAILED)
243 throw WaitFailed(_rep.owner);
244
245 _rep.owner = caller;
246 _rep.count++;
247 }
248
249 void Mutex::unlock()
250 {
251 PEGASUS_DEBUG_ASSERT(_magic);
252
|
253 mike 1.3.14.2 _rep.owner.clear();
|
254 mike 1.3.14.1 _rep.count--;
255 ReleaseMutex(_rep.handle);
256 }
257
258 #endif /* PEGASUS_HAVE_WINDOWS_THREADS */
259
|
260 mike 1.2 PEGASUS_NAMESPACE_END
|