Entering Critical Sections

A thread can prevent execution of any of the other threads in its process by calling DosEnterCritSec.

This function temporarily prevents a thread from being preempted by other threads within its process. The other threads in the process will not be executed until the current thread calls DosExitCritSec. This enables the calling thread to access a time-critical resource of the process.

The following code fragment enters a section that will not be preempted, performs a simple task, and then exits quickly.

    #define INCL_DOSPROCESS     /* Process and thread values */
    #include <os2.h>
    #include <stdio.h>

    BOOL    flag;         /* Program control flag */
    APIRET  ulrc;         /* Return code          */

    ulrc = DosEnterCritSec();

    if (ulrc != 0) {
        printf("DosEnterCritSec error: return code = %ld",
               ulrc);
        return;
    }

    flag = TRUE;           /* Set the flag */

    ulrc = DosExitCritSec();

    if (ulrc != 0) {
        printf("DosExitCritSec error: return code = %ld",
               ulrc);
        return;
    }

A count is maintained of the outstanding DosEnterCritSec requests. The count is incremented when a DosEnterCritSec request is made, and decremented when a DosExitCritSec request is made. A DosExitCritSec request will not cause normal thread dispatching to be restored while the count is greater than 0.

This count is maintained in a WORD-sized variable. If overflow occurs, the count is set to its maximum value, and an error is returned. The operation is not performed when this occurs.

Threads that call DosEnterCritSec must not must not make dynamic link calls within these critical sections. The dynamic link procedure could be using semaphores to serialize a resource. If a thread entering the critical section blocks another thread that already owns the resource which the dynamic link function is about to request, a deadlock occurs.

For example, threads of an application are serializing their access to a queue by means of a semaphore. A thread enters a critical section and makes a request to read the queue while another thread already has the semaphore that controls access to the queue. The thread that has the semaphore is now effectively blocked by DosEnterCritSec, and the thread that has requested the queue waits forever to access it.

Note: Thread 1 is the initial thread of execution. It handles all signals (Ctrl+C, Ctrl+Break, and KillProcess). If a signal occurs while DosEnterCritSec is active, thread 1 can begin execution to process the signal. Thread 1 must not access the critical resource that is being protected by the use of DosEnterCritSec.