In order to access a shared resource, a process must own the mutex semaphore that is protecting the shared resource. Ownership is obtained by first opening the mutex semaphore with DosOpenMutexSem, then using DosRequestMutexSem to request ownership of the semaphore. If another process already owns the semaphore, the requesting process is blocked. If the semaphore is not owned, OS/2 grants ownership to the requesting process and the process can access the shared resource. When the process is finished using the shared resource, it uses DosReleaseMutexSem to relinquish its ownership of the semaphore, thereby enabling another process to gain ownership.
A process can gain ownership of a mutex semaphore in three ways:
Note that ownership of a mutex semaphore is given only to the requesting thread; it is not shared by other threads in the same process.
If a mutex semaphore is unowned, DosRequestMutexSem sets it as owned and returns immediately to the caller. If the semaphore is already owned, the calling thread is blocked until either the owning thread calls DosReleaseMutexSem to release the semaphore, or a specified time limit is reached.
The following code fragment shows how a process opens a mutex semaphore, requests it, and, after writing to the shared file, releases and closes the semaphore:
#define INCL_DOSSEMAPHORES /* Semaphore values */ #include <os2.h> HMTX hmtxProtFile; DosOpenMutexSem("\\sem32\\ProtFile", &hmtxProtFile); /* Opens for this process */ DosRequestMutexSem(hmtxProtFile, 5000); /* Returns in 5 seconds if */ . /* Ownership not obtained */ . . /* Write data to shared file */ . . DosReleaseMutexSem(hmtxProtFile); /* Releases ownership */ . . /* Continue execution */ . . DosCloseMutexSem(hmtxProtFile); /* Finished with shared file */
If more than one thread is blocked on a DosRequestMutexSem request, the thread with the highest priority level is the first to be unblocked and given ownership of the semaphore. If more than 1 of the waiting threads have the same priority level, then FIFO ordering is used to determine which thread is unblocked and given ownership.
The time-out parameter (5000 milliseconds in the example above) places a limit on the amount of time a thread blocks on a DosRequestMutexSem request. If the time limit is reached before the thread gains ownership of the semaphore, ERROR_TIMEOUT is returned. If SEM_IMMEDIATE_RETURN is specified for the time limit, DosRequestMutexSem returns without blocking the thread. The thread can then perform other operations and call DosRequestMutexSem again later if it still requires access to the protected resource. If SEM_INDEFINITE_WAIT is specified for the time limit, the thread waits indefinitely. If the thread is unblocked by an external event while it is waiting for the mutex semaphore (as when a No Wait I/O request has just been completed), ERROR_INTERRUPT is returned to the caller.
In addition to the usage count that OS/2 maintains for all semaphores, OS/2 maintains a request count for each mutex semaphore. Each call to DosRequestMutexSem increments the count, and each call to DosReleaseMutexSem decrements it.
Calls to DosRequestMutexSem and DosReleaseMutexSem can be nested, but the request count for a semaphore cannot exceed 65535. If an attempt is made to exceed this number, ERROR_TOO_MANY_SEM_REQUESTS is returned. When calls to DosRequestMutexSem and DosReleaseMutexSem are nested, a call to DosReleaseMutexSem merely decrements the request count for the semaphore; the semaphore is not actually released to another thread until its request count is 0. If a process ends while it owns a mutex semaphore, all of the currently blocked DosRequestMutexSem requests, as well as any future requests for the semaphore, return ERROR_SEM_OWNER_DIED. This return code indicates that the owning process ended abnormally, leaving the protected resource in an indeterminate state. An application that receives this error should close the mutex semaphore (so that it can be deleted from OS/2), because it is no longer valid. Appropriate action should also be taken concerning the protected resource.