Remove whitespace, update email addresses and URLs.
[kodak.git] / semaphore.cpp
1 //+----------------------------------------------------------------------------
2 //
3 // File:     semaphore.cpp
4 //
5 // Module:   
6 //
7 // Synopsis: 
8 //
9 // Copyright (C) 1999 Microsoft Corporation.  All rights reserved.
10 //
11 // Author:       sgasch
12 //
13 // Created    8 Jun 1999
14 //
15 //+----------------------------------------------------------------------------
16
17 #include "lock.h"
18
19 //+----------------------------------------------------------------------------
20 //
21 // Function:  CCriticalSection
22 //
23 // Synopsis:  Constructor for a "critical section" mutual exclusion device.
24 //            It basically just creates a private semaphore.  It also sets
25 //            an initialized flag on success.
26 //
27 // Arguments: int iNum - the number of concurrent threads allowed into the
28 //                       critical section.
29 //            
30 // Returns:   none
31 //
32 // History:   sgasch Created Header    9 Jun 1999
33 //
34 //+----------------------------------------------------------------------------
35 CCriticalSection::CCriticalSection(int iNum)
36 {
37 #ifdef SHOWCALLS
38         Trace("Entering CCriticalSection constructor.");
39 #endif
40
41         //
42         // Precondition: the number of concurrent threads is sane.
43         //
44         ASSERT(iNum > 0);
45         ASSERT(iNum < 128);
46
47         //
48         // Initialize attributes.
49         //
50         m_fInitialized = false;
51         m_hSem = -1;
52
53         //
54         // Create the semaphore.
55         //
56         if (false == CreateSemaphore())
57         {
58                 Trace("CCriticalSection: failed to create a semaphore.");
59                 return;
60         }
61         ASSERT(m_hSem != -1);
62
63         //
64         // Set the number of concurrent threads allowed into the semaphore.
65         //
66         if (false == SetNumConcurrentThreads(iNum))
67         {
68                 return;
69         }
70
71         //
72         // Success
73         //
74         m_fInitialized = true;
75 }
76
77
78 //+----------------------------------------------------------------------------
79 //
80 // Function:  CCriticalSection
81 //
82 // Synopsis:  Destructor; delete the critical section.
83 //
84 // Arguments: void
85 //            
86 // Returns:   none
87 //
88 // History:   sgasch Created Header    9 Jun 1999
89 //
90 //+----------------------------------------------------------------------------
91 CCriticalSection::~CCriticalSection(void)
92 {
93 #ifdef SHOWCALLS
94         Trace("Entering ~CSemaphore destructor.");
95 #endif
96
97         //
98         // Delete the semaphore.
99         //
100         if (m_hSem >= 0)
101         {
102                 (void) RemoveSemaphore();
103         }
104
105         m_fInitialized = false;
106         m_hSem = -1;
107 }
108
109
110 //+----------------------------------------------------------------------------
111 //
112 // Function:  CreateSemaphore
113 //
114 // Synopsis:  Called by the constructor to create a private semaphore.
115 //
116 // Arguments: void
117 //            
118 // Returns:   bool - true on success
119 //
120 // History:   sgasch Created Header    9 Jun 1999
121 //
122 //+----------------------------------------------------------------------------
123 bool CCriticalSection::CreateSemaphore(void)
124 {
125         union semun uSun;                      // required by the system call
126         
127 #ifdef SHOWCALLS
128         Trace("Entering CreateSemaphore.");
129 #endif
130         
131         //
132         // No preconditions: we do _not_ assert initialized because we are
133         // called by the constructor before fully inited.
134         //
135
136         //
137         // Create the semaphore
138         //
139         m_hSem = semget(IPC_PRIVATE, 
140                                         1,
141                                         IPC_CREAT | SEM_R | (SEM_R >> 3) | SEM_A | (SEM_A >> 3));
142         
143         if (m_hSem < 0)
144         {
145                 Trace("CreateSemaphore: error creating semaphore.");
146                 return(false);
147         }
148
149         //
150         // Initialize the semaphore.
151         //
152         uSun.val = 1;
153         if (semctl(m_hSem, 0, SETVAL, uSun) < 0)
154         {
155                 Trace("CreateSemaphore: error setting semaphore value.");
156                 return(false);
157         }
158
159         //
160         // Success
161         //
162         return(true);
163 }
164
165
166 //+----------------------------------------------------------------------------
167 //
168 // Function:  RemoveSemaphore
169 //
170 // Synopsis:  Delete a semaphore created by CreateSemaphore.
171 //
172 // Arguments: void
173 //            
174 // Returns:   bool - true on success.
175 //
176 // History:   sgasch Created Header    9 Jun 1999
177 //
178 //+----------------------------------------------------------------------------
179 bool CCriticalSection::RemoveSemaphore(void)
180 {
181         union semun uSun;                      // required by the system call
182
183 #ifdef SHOWCALLS
184         Trace("Entering RemoveSemaphore.");
185 #endif
186
187         //
188         // Preconditions: we are initialized.
189         //
190         ASSERT(m_fInitialized);
191
192         //
193         // Remove the semaphore
194         //
195         uSun.val = 0;
196         if (semctl(m_hSem, 0, IPC_RMID, uSun) < 0)
197         {
198                 Trace("RemoveSemaphore: error removing semaphore.");
199                 return(false);
200         }
201
202         //
203         // Success
204         //
205         return(true);
206 }
207
208
209 //+----------------------------------------------------------------------------
210 //
211 // Function:  GetNumberConcurrentThreads
212 //
213 // Synopsis:  Return the number of concurrent threads allowed into the
214 //            critical section.
215 //
216 // Arguments: int *piAnswer - location to place the answer
217 //            
218 // Returns:   bool - true on success
219 //
220 // History:   sgasch Created Header    9 Jun 1999
221 //
222 //+----------------------------------------------------------------------------
223 bool CCriticalSection::GetNumberConcurrentThreads(int *piAnswer)
224 {
225         int iSemVal;                           // Temp local storage for the answer
226         union semun uSun;                      // required by the system call
227
228 #ifdef SHOWCALLS
229         Trace("Entering GetNumberConcurrentThreads.");
230 #endif
231         
232         //
233         // Preconditions: we are initialized and the pointer is valid.
234         //
235         ASSERT(m_fInitialized);
236         ASSERT(GOOD_PTR(piAnswer));
237
238         //
239         // Get the value of the semaphore
240         //
241         uSun.val = 0;
242         iSemVal = semctl(m_hSem, 0, GETVAL, uSun);
243         if (iSemVal < 0)
244         {
245                 Trace("GetValue: error reading semaphore value.");
246                 return(false);
247         }
248         else
249         {
250                 *piAnswer = iSemVal;
251                 return(true);
252         }
253 }
254
255
256 //+----------------------------------------------------------------------------
257 //
258 // Function:  SetNumberConcurrentThreads
259 //
260 // Synopsis:  Set the number of concurrent threads allowed into the critical
261 //            section.
262 //
263 // Arguments: int iValue - number to set to
264 //            
265 // Returns:   bool - true on success
266 //
267 // History:   sgasch Created Header    9 Jun 1999
268 //
269 //+----------------------------------------------------------------------------
270 bool CCriticalSection::SetNumberConcurrentThreads(int iValue)
271 {
272         union semun uSun;                      // required by the system call
273
274 #ifdef SHOWCALLS
275         Trace("Entering SetNumberConcurrentThreads.");
276 #endif
277
278         //
279         // Precondition: the value is valid.  We do _not_ assert initialized
280         // here because we get called by the constructor before fully inited.
281         //
282         ASSERT(iValue > 0);
283         ASSERT(iValue < 128);
284
285         //
286         // Set the value of the semaphore
287         //
288         uSun.val = iValue;
289         if (semctl(m_hSem, 0, SETVAL, uSun) < 0)
290         {
291                 Trace("SetValue: error writing semaphore value.");
292                 return(false);
293         }
294
295         //
296         // Success
297         //
298         return(true);
299 }
300
301
302 //+----------------------------------------------------------------------------
303 //
304 // Function:  TryToEnter
305 //
306 // Synopsis:  Attempt to enter the critical section; if the call to enter
307 //            would cause the thread to block waiting for another to leave
308 //            then simply return false.  If the call to enter succeeds, ret-
309 //            urn true.
310 //
311 // Arguments: void
312 //            
313 // Returns:   bool - true on successful enter, false on failure.
314 //
315 // History:   sgasch Created Header    9 Jun 1999
316 //
317 //+----------------------------------------------------------------------------
318 bool CCriticalSection::TryToEnter(void)
319 {
320         static struct sembuf sb[1];            // required by the system call
321         int iError;                            // result of trying to enter C.S.
322
323 #ifdef SHOWCALLS
324         Trace("Entering TryToEnter.");
325 #endif
326         
327         // 
328         // Preconditions: we are initialized.
329         //
330         ASSERT(m_fInitialized);
331
332         sb[0].sem_op = -1;
333         sb[0].sem_num = 0;
334         sb[0].sem_flg = IPC_NOWAIT;
335
336         if ((iError = semop(m_hSem, &sb[0], 1)) < 0)
337         {
338                 if (EAGAIN == iError)
339                 {
340                         Trace("TryToEnter: could not enter critical section.");
341                         return(false);
342                 }
343                 else
344                 {
345                         Trace("TryToEnter: error waiting on semaphore.");
346                         return(false);
347                 }
348         }
349         Trace("TryToEnter: entered critical section successfully.");
350         return(true);
351 }
352
353
354 //+----------------------------------------------------------------------------
355 //
356 // Function:  Enter
357 //
358 // Synopsis:  Enter the critical section.  If we cannot, sleep until we
359 //            can.
360 //
361 // Arguments: void
362 //            
363 // Returns:   bool - true on success
364 //
365 // History:   sgasch Created Header    9 Jun 1999
366 //
367 //+----------------------------------------------------------------------------
368 bool CCriticalSection::Enter(void)
369 {
370         static struct sembuf sb[1];            // required by the system call
371
372 #ifdef SHOWCALLS
373         Trace("Enter: beginning to wait on a critical section.");
374 #endif
375
376         //
377         // Precondition: we are initialized.
378         // 
379         ASSERT(m_fInitialized);
380
381         //
382         // Wait on the semaphore.
383         //
384         sb[0].sem_op = -1;
385         sb[0].sem_num = 0;
386         sb[0].sem_flg = 0;
387         
388         if (semop(m_hSem, &sb[0], 1) < 0)
389         {
390                 Trace("Enter: error waiting on semaphore.");
391                 return(false);
392         }
393
394         //
395         // Success
396         //
397 #ifdef SHOWCALLS
398         Trace("Enter: entered critical section.");
399 #endif
400         return(true);
401 }
402
403
404 //+----------------------------------------------------------------------------
405 //
406 // Function:  Leave
407 //
408 // Synopsis:  Leave a critical section.  Make room for other(s) waiting if
409 //            they exist.
410 //
411 // Arguments: void
412 //            
413 // Returns:   bool - true on success
414 //
415 // History:   sgasch Created Header    9 Jun 1999
416 //
417 //+----------------------------------------------------------------------------
418 bool CCriticalSection::Leave(void)
419 {
420         static struct sembuf sb[1];            // required by the system call
421
422 #ifdef SHOWCALLS
423         Trace("Entering Leave.");
424 #endif
425
426         //
427         // Signal the semaphore.
428         //
429         sb[0].sem_op  = 1;
430         sb[0].sem_num = 0;
431         sb[0].sem_flg = 0;
432
433         if (semop(m_hSem, &sb[0], 1) < 0)
434         {
435                 Trace("Leave: error signaling semaphore.");
436                 return(false);
437         }
438
439         //
440         // Success
441         //
442         return(true);
443 }
444
445
446
447
448
449