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 kumpf 1.8 if (writeLock)
|
68 mike 1.2 {
|
69 kumpf 1.9 if (0 == pthread_rwlock_wrlock(&_rwlock.rwlock))
|
70 mike 1.2 {
|
71 kumpf 1.8 _rwlock.owner = caller;
72 _writers++;
|
73 mike 1.2 return;
74 }
75 }
|
76 kumpf 1.8 else
|
77 mike 1.2 {
|
78 kumpf 1.9 if (0 == pthread_rwlock_rdlock(&_rwlock.rwlock))
|
79 mike 1.2 {
|
80 kumpf 1.8 _readers++;
|
81 mike 1.2 return;
82 }
83 }
84
|
85 kumpf 1.9 throw WaitFailed(Threads::self());
|
86 mike 1.2 }
87
|
88 kumpf 1.8 void ReadWriteSem::_unlock(Boolean writeLock, ThreadType caller)
|
89 mike 1.2 {
|
90 kumpf 1.8 if (writeLock)
|
91 mike 1.2 {
92 Threads::clear(_rwlock.owner);
|
93 kumpf 1.10 PEGASUS_ASSERT(_writers.get() == 1);
94 _writers = 0;
|
95 mike 1.2 }
|
96 kumpf 1.10 else
|
97 mike 1.2 {
|
98 kumpf 1.10 PEGASUS_ASSERT(_readers.get() > 0);
99 _readers--;
|
100 mike 1.2 }
|
101 kumpf 1.10
102 int rc = pthread_rwlock_unlock(&_rwlock.rwlock);
103 // All documented error codes represent coding errors.
104 PEGASUS_ASSERT(rc == 0);
|
105 mike 1.2 }
106
107 int ReadWriteSem::read_count() const
108 {
|
109 kumpf 1.5 return _readers.get();
|
110 mike 1.2 }
111
112 int ReadWriteSem::write_count() const
113 {
|
114 kumpf 1.5 return _writers.get();
|
115 mike 1.2 }
116
117 #endif /* PEGASUS_USE_POSIX_RWLOCK */
118
119 //==============================================================================
120 //
121 // PEGASUS_USE_SEMAPHORE_RWLOCK
122 //
123 //==============================================================================
124
125 #if defined(PEGASUS_USE_SEMAPHORE_RWLOCK)
126
127 // // If i get cancelled, I MUST ensure:
128 // 1) I do not hold the internal mutex
129 // 2) I do not hold the write lock
130 // 3) I am not using a reader slot
131
132 ReadWriteSem::ReadWriteSem():_readers(0), _writers(0), _rwlock()
133 {
134 }
135
136 mike 1.2 ReadWriteSem::~ReadWriteSem()
137 {
138 // lock everyone out of this object
139 try
140 {
141 _rwlock._internal_lock.lock();
142 }
|
143 kumpf 1.5 catch (IPCException &)
|
144 mike 1.2 {
145 PEGASUS_ASSERT(0);
146 }
147 while (_readers.get() > 0 || _writers.get() > 0)
148 {
149 Threads::yield();
150 }
151 _rwlock._internal_lock.unlock();
152 }
153
|
154 marek 1.7 //---------------------------------------------------------------------
|
155 kumpf 1.8 void ReadWriteSem::_wait(Boolean writeLock, ThreadType caller)
|
156 mike 1.2 {
157 //-----------------------------------------------------------------
158 // Lock this object to maintain integrity while we decide
159 // exactly what to do next.
160 //-----------------------------------------------------------------
|
161 kumpf 1.8 _rwlock._internal_lock.lock();
|
162 mike 1.2
|
163 kumpf 1.8 if (writeLock)
|
164 mike 1.2 {
165 //-----------------------------------------------------------------
166 // Write Lock Step 1: lock the object and allow all the readers to exit
167 //-----------------------------------------------------------------
|
168 kumpf 1.8 while (_readers.get() > 0)
169 Threads::yield();
|
170 mike 1.2 //-----------------------------------------------------------------
171 // Write Lock Step 2: Obtain the Write Mutex
172 // Although there are no readers, there may be a writer
173 //-----------------------------------------------------------------
|
174 kumpf 1.8 try
175 {
176 _rwlock._wlock.lock();
177 }
178 catch (const IPCException&)
179 {
180 _rwlock._internal_lock.unlock();
181 throw;
182 }
|
183 mike 1.2 //-----------------------------------------------------------------
184 // Write Lock Step 3: set the writer count to one, unlock the object
185 // There are no readers and we are the only writer !
186 //-----------------------------------------------------------------
|
187 kumpf 1.8 _writers = 1;
188 // set the owner
189 _rwlock._owner = Threads::self();
190 // unlock the object
191 _rwlock._internal_lock.unlock();
192 }
193 else
194 {
|
195 mike 1.2 //-----------------------------------------------------------------
196 // Read Lock Step 1: Wait for the existing writer (if any) to clear
197 //-----------------------------------------------------------------
|
198 kumpf 1.8 while (_writers.get() > 0)
199 Threads::yield();
|
200 mike 1.2 //-----------------------------------------------------------------
201 // Read Lock Step 2: wait for a reader slot to open up, then return
202 // At this point there are no writers, but there may be too many
203 // readers.
204 //-----------------------------------------------------------------
|
205 kumpf 1.8 try
206 {
207 _rwlock._rlock.wait();
208 }
209 catch (const IPCException&)
210 {
211 _rwlock._internal_lock.unlock();
212 throw;
213 }
|
214 mike 1.2 //-----------------------------------------------------------------
215 // Read Lock Step 3: increment the number of readers, unlock the object,
216 // return
217 //-----------------------------------------------------------------
|
218 kumpf 1.8 _readers++;
219 _rwlock._internal_lock.unlock();
|
220 mike 1.2 }
221 }
222
|
223 kumpf 1.8 void ReadWriteSem::_unlock(Boolean writeLock, ThreadType caller)
|
224 mike 1.2 {
|
225 kumpf 1.10 if (writeLock)
|
226 mike 1.2 {
|
227 kumpf 1.10 PEGASUS_ASSERT(_writers.get() == 1);
|
228 mike 1.2 _writers = 0;
229 _rwlock._wlock.unlock();
230 }
|
231 kumpf 1.10 else
|
232 mike 1.2 {
|
233 kumpf 1.10 PEGASUS_ASSERT(_readers.get() > 0);
|
234 mike 1.2 _readers--;
235 _rwlock._rlock.signal();
236 }
237 }
238
239 int ReadWriteSem::read_count() const
240 {
|
241 kumpf 1.5 return _readers.get();
|
242 mike 1.2 }
243
244 int ReadWriteSem::write_count() const
245 {
|
246 kumpf 1.5 return _writers.get();
|
247 mike 1.2 }
248
249 #endif /* !PEGASUS_USE_SEMAPHORE_RWLOCK */
250
251 PEGASUS_NAMESPACE_END
|