1 mike 1.2 //%2006////////////////////////////////////////////////////////////////////////
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 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
13 //
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 //
21 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 mike 1.2 // 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 "ReadWriteSem.h"
35 #include "Time.h"
36 #include "PegasusAssert.h"
37 #include "Threads.h"
38
39 PEGASUS_NAMESPACE_BEGIN
40
41 //==============================================================================
42 //
43 mike 1.2 // PEGASUS_USE_POSIX_RWLOCK
44 //
45 //==============================================================================
46
47 #ifdef PEGASUS_USE_POSIX_RWLOCK
48
49 ReadWriteSem::ReadWriteSem():_readers(0), _writers(0)
50 {
51 pthread_rwlock_init(&_rwlock.rwlock, NULL);
52 Threads::clear(_rwlock.owner);
53 }
54
55 ReadWriteSem::~ReadWriteSem()
56 {
|
57 kumpf 1.5 int r = 0;
|
58 mike 1.6 while ((r = pthread_rwlock_destroy(&_rwlock.rwlock)) == EBUSY ||
|
59 kumpf 1.5 (r == -1 && errno == EBUSY))
|
60 mike 1.2 {
61 Threads::yield();
62 }
63 }
64
|
65 kumpf 1.8 void ReadWriteSem::_wait(Boolean writeLock, ThreadType caller)
|
66 mike 1.2 {
67 int errorcode;
|
68 kumpf 1.8 if (writeLock)
|
69 mike 1.2 {
|
70 kumpf 1.8 if (0 == (errorcode = pthread_rwlock_wrlock(&_rwlock.rwlock)))
|
71 mike 1.2 {
|
72 kumpf 1.8 _rwlock.owner = caller;
73 _writers++;
|
74 mike 1.2 return;
75 }
76 }
|
77 kumpf 1.8 else
|
78 mike 1.2 {
|
79 kumpf 1.8 if (0 == (errorcode = pthread_rwlock_rdlock(&_rwlock.rwlock)))
|
80 mike 1.2 {
|
81 kumpf 1.8 _readers++;
|
82 mike 1.2 return;
83 }
84 }
85
86 if (errorcode == EDEADLK)
87 throw(Deadlock(_rwlock.owner));
88 else
89 throw(WaitFailed(Threads::self()));
90 }
91
|
92 kumpf 1.8 void ReadWriteSem::_unlock(Boolean writeLock, ThreadType caller)
|
93 mike 1.2 {
94 ThreadType owner;
95
|
96 kumpf 1.8 if (writeLock)
|
97 mike 1.2 {
98 owner = _rwlock.owner;
99 Threads::clear(_rwlock.owner);
100 }
101 if (0 != pthread_rwlock_unlock(&_rwlock.rwlock))
102 {
103 _rwlock.owner = owner;
104 throw(Permission(Threads::self()));
105 }
|
106 kumpf 1.8 if (!writeLock && _readers.get() != 0)
|
107 mike 1.2 _readers--;
108 else if (_writers.get() != 0)
109 _writers--;
110 }
111
112 int ReadWriteSem::read_count() const
113 {
|
114 kumpf 1.5 return _readers.get();
|
115 mike 1.2 }
116
117 int ReadWriteSem::write_count() const
118 {
|
119 kumpf 1.5 return _writers.get();
|
120 mike 1.2 }
121
122 #endif /* PEGASUS_USE_POSIX_RWLOCK */
123
124 //==============================================================================
125 //
126 // PEGASUS_USE_SEMAPHORE_RWLOCK
127 //
128 //==============================================================================
129
130 #if defined(PEGASUS_USE_SEMAPHORE_RWLOCK)
131
132 // // If i get cancelled, I MUST ensure:
133 // 1) I do not hold the internal mutex
134 // 2) I do not hold the write lock
135 // 3) I am not using a reader slot
136
137 ReadWriteSem::ReadWriteSem():_readers(0), _writers(0), _rwlock()
138 {
139 }
140
141 mike 1.2 ReadWriteSem::~ReadWriteSem()
142 {
143 // lock everyone out of this object
144 try
145 {
146 _rwlock._internal_lock.lock();
147 }
|
148 kumpf 1.5 catch (Deadlock &)
|
149 mike 1.2 {
150 // no problem - we own the lock, which is what we want
151 }
|
152 kumpf 1.5 catch (IPCException &)
|
153 mike 1.2 {
154 PEGASUS_ASSERT(0);
155 }
156 while (_readers.get() > 0 || _writers.get() > 0)
157 {
158 Threads::yield();
159 }
160 _rwlock._internal_lock.unlock();
161 }
162
|
163 marek 1.7 //---------------------------------------------------------------------
|
164 kumpf 1.8 void ReadWriteSem::_wait(Boolean writeLock, ThreadType caller)
|
165 mike 1.2 {
166 //-----------------------------------------------------------------
167 // Lock this object to maintain integrity while we decide
168 // exactly what to do next.
169 //-----------------------------------------------------------------
|
170 kumpf 1.8 _rwlock._internal_lock.lock();
|
171 mike 1.2
|
172 kumpf 1.8 if (writeLock)
|
173 mike 1.2 {
174 //-----------------------------------------------------------------
175 // Write Lock Step 1: lock the object and allow all the readers to exit
176 //-----------------------------------------------------------------
|
177 kumpf 1.8 while (_readers.get() > 0)
178 Threads::yield();
|
179 mike 1.2 //-----------------------------------------------------------------
180 // Write Lock Step 2: Obtain the Write Mutex
181 // Although there are no readers, there may be a writer
182 //-----------------------------------------------------------------
|
183 kumpf 1.8 try
184 {
185 _rwlock._wlock.lock();
186 }
187 catch (const IPCException&)
188 {
189 _rwlock._internal_lock.unlock();
190 throw;
191 }
|
192 mike 1.2 //-----------------------------------------------------------------
193 // Write Lock Step 3: set the writer count to one, unlock the object
194 // There are no readers and we are the only writer !
195 //-----------------------------------------------------------------
|
196 kumpf 1.8 _writers = 1;
197 // set the owner
198 _rwlock._owner = Threads::self();
199 // unlock the object
200 _rwlock._internal_lock.unlock();
201 }
202 else
203 {
|
204 mike 1.2 //-----------------------------------------------------------------
205 // Read Lock Step 1: Wait for the existing writer (if any) to clear
206 //-----------------------------------------------------------------
|
207 kumpf 1.8 while (_writers.get() > 0)
208 Threads::yield();
|
209 mike 1.2 //-----------------------------------------------------------------
210 // Read Lock Step 2: wait for a reader slot to open up, then return
211 // At this point there are no writers, but there may be too many
212 // readers.
213 //-----------------------------------------------------------------
|
214 kumpf 1.8 try
215 {
216 _rwlock._rlock.wait();
217 }
218 catch (const IPCException&)
219 {
220 _rwlock._internal_lock.unlock();
221 throw;
222 }
|
223 mike 1.2 //-----------------------------------------------------------------
224 // Read Lock Step 3: increment the number of readers, unlock the object,
225 // return
226 //-----------------------------------------------------------------
|
227 kumpf 1.8 _readers++;
228 _rwlock._internal_lock.unlock();
|
229 mike 1.2 }
230 }
231
|
232 kumpf 1.8 void ReadWriteSem::_unlock(Boolean writeLock, ThreadType caller)
|
233 mike 1.2 {
|
234 kumpf 1.8 if (writeLock && _writers.get() != 0)
|
235 mike 1.2 {
236 _writers = 0;
237 _rwlock._wlock.unlock();
238 }
239 else if (_readers.get() != 0)
240 {
241 _readers--;
242 _rwlock._rlock.signal();
243 }
244 }
245
246 int ReadWriteSem::read_count() const
247 {
|
248 kumpf 1.5 return _readers.get();
|
249 mike 1.2 }
250
251 int ReadWriteSem::write_count() const
252 {
|
253 kumpf 1.5 return _writers.get();
|
254 mike 1.2 }
255
256 #endif /* !PEGASUS_USE_SEMAPHORE_RWLOCK */
257
258 PEGASUS_NAMESPACE_END
|