1 //+----------------------------------------------------------------------------
9 // Copyright (C) 1999 Microsoft Corporation. All rights reserved.
15 //+----------------------------------------------------------------------------
19 //+----------------------------------------------------------------------------
21 // Function: CCriticalSection
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.
27 // Arguments: int iNum - the number of concurrent threads allowed into the
32 // History: sgasch Created Header 9 Jun 1999
34 //+----------------------------------------------------------------------------
35 CCriticalSection::CCriticalSection(int iNum)
38 Trace("Entering CCriticalSection constructor.");
42 // Precondition: the number of concurrent threads is sane.
48 // Initialize attributes.
50 m_fInitialized = false;
54 // Create the semaphore.
56 if (false == CreateSemaphore())
58 Trace("CCriticalSection: failed to create a semaphore.");
64 // Set the number of concurrent threads allowed into the semaphore.
66 if (false == SetNumConcurrentThreads(iNum))
74 m_fInitialized = true;
78 //+----------------------------------------------------------------------------
80 // Function: CCriticalSection
82 // Synopsis: Destructor; delete the critical section.
88 // History: sgasch Created Header 9 Jun 1999
90 //+----------------------------------------------------------------------------
91 CCriticalSection::~CCriticalSection(void)
94 Trace("Entering ~CSemaphore destructor.");
98 // Delete the semaphore.
102 (void) RemoveSemaphore();
105 m_fInitialized = false;
110 //+----------------------------------------------------------------------------
112 // Function: CreateSemaphore
114 // Synopsis: Called by the constructor to create a private semaphore.
118 // Returns: bool - true on success
120 // History: sgasch Created Header 9 Jun 1999
122 //+----------------------------------------------------------------------------
123 bool CCriticalSection::CreateSemaphore(void)
125 union semun uSun; // required by the system call
128 Trace("Entering CreateSemaphore.");
132 // No preconditions: we do _not_ assert initialized because we are
133 // called by the constructor before fully inited.
137 // Create the semaphore
139 m_hSem = semget(IPC_PRIVATE,
141 IPC_CREAT | SEM_R | (SEM_R >> 3) | SEM_A | (SEM_A >> 3));
145 Trace("CreateSemaphore: error creating semaphore.");
150 // Initialize the semaphore.
153 if (semctl(m_hSem, 0, SETVAL, uSun) < 0)
155 Trace("CreateSemaphore: error setting semaphore value.");
166 //+----------------------------------------------------------------------------
168 // Function: RemoveSemaphore
170 // Synopsis: Delete a semaphore created by CreateSemaphore.
174 // Returns: bool - true on success.
176 // History: sgasch Created Header 9 Jun 1999
178 //+----------------------------------------------------------------------------
179 bool CCriticalSection::RemoveSemaphore(void)
181 union semun uSun; // required by the system call
184 Trace("Entering RemoveSemaphore.");
188 // Preconditions: we are initialized.
190 ASSERT(m_fInitialized);
193 // Remove the semaphore
196 if (semctl(m_hSem, 0, IPC_RMID, uSun) < 0)
198 Trace("RemoveSemaphore: error removing semaphore.");
209 //+----------------------------------------------------------------------------
211 // Function: GetNumberConcurrentThreads
213 // Synopsis: Return the number of concurrent threads allowed into the
216 // Arguments: int *piAnswer - location to place the answer
218 // Returns: bool - true on success
220 // History: sgasch Created Header 9 Jun 1999
222 //+----------------------------------------------------------------------------
223 bool CCriticalSection::GetNumberConcurrentThreads(int *piAnswer)
225 int iSemVal; // Temp local storage for the answer
226 union semun uSun; // required by the system call
229 Trace("Entering GetNumberConcurrentThreads.");
233 // Preconditions: we are initialized and the pointer is valid.
235 ASSERT(m_fInitialized);
236 ASSERT(GOOD_PTR(piAnswer));
239 // Get the value of the semaphore
242 iSemVal = semctl(m_hSem, 0, GETVAL, uSun);
245 Trace("GetValue: error reading semaphore value.");
256 //+----------------------------------------------------------------------------
258 // Function: SetNumberConcurrentThreads
260 // Synopsis: Set the number of concurrent threads allowed into the critical
263 // Arguments: int iValue - number to set to
265 // Returns: bool - true on success
267 // History: sgasch Created Header 9 Jun 1999
269 //+----------------------------------------------------------------------------
270 bool CCriticalSection::SetNumberConcurrentThreads(int iValue)
272 union semun uSun; // required by the system call
275 Trace("Entering SetNumberConcurrentThreads.");
279 // Precondition: the value is valid. We do _not_ assert initialized
280 // here because we get called by the constructor before fully inited.
283 ASSERT(iValue < 128);
286 // Set the value of the semaphore
289 if (semctl(m_hSem, 0, SETVAL, uSun) < 0)
291 Trace("SetValue: error writing semaphore value.");
302 //+----------------------------------------------------------------------------
304 // Function: TryToEnter
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-
313 // Returns: bool - true on successful enter, false on failure.
315 // History: sgasch Created Header 9 Jun 1999
317 //+----------------------------------------------------------------------------
318 bool CCriticalSection::TryToEnter(void)
320 static struct sembuf sb[1]; // required by the system call
321 int iError; // result of trying to enter C.S.
324 Trace("Entering TryToEnter.");
328 // Preconditions: we are initialized.
330 ASSERT(m_fInitialized);
334 sb[0].sem_flg = IPC_NOWAIT;
336 if ((iError = semop(m_hSem, &sb[0], 1)) < 0)
338 if (EAGAIN == iError)
340 Trace("TryToEnter: could not enter critical section.");
345 Trace("TryToEnter: error waiting on semaphore.");
349 Trace("TryToEnter: entered critical section successfully.");
354 //+----------------------------------------------------------------------------
358 // Synopsis: Enter the critical section. If we cannot, sleep until we
363 // Returns: bool - true on success
365 // History: sgasch Created Header 9 Jun 1999
367 //+----------------------------------------------------------------------------
368 bool CCriticalSection::Enter(void)
370 static struct sembuf sb[1]; // required by the system call
373 Trace("Enter: beginning to wait on a critical section.");
377 // Precondition: we are initialized.
379 ASSERT(m_fInitialized);
382 // Wait on the semaphore.
388 if (semop(m_hSem, &sb[0], 1) < 0)
390 Trace("Enter: error waiting on semaphore.");
398 Trace("Enter: entered critical section.");
404 //+----------------------------------------------------------------------------
408 // Synopsis: Leave a critical section. Make room for other(s) waiting if
413 // Returns: bool - true on success
415 // History: sgasch Created Header 9 Jun 1999
417 //+----------------------------------------------------------------------------
418 bool CCriticalSection::Leave(void)
420 static struct sembuf sb[1]; // required by the system call
423 Trace("Entering Leave.");
427 // Signal the semaphore.
433 if (semop(m_hSem, &sb[0], 1) < 0)
435 Trace("Leave: error signaling semaphore.");