DosSemSetWait

From EDM2
Jump to: navigation, search

This call sets a semaphore if the semaphore is not already set and waits until another thread clears the semaphore with a DosSemClear call.

Syntax

DosSemSetWait (SemHandle, Timeout)

Parameters

SemHandle (HSEM) - input 
Reference to the semaphore.
For a system semaphore, this reference is the handle returned by a DosCreateSem or DosOpenSem request that granted the requesting thread access to the semaphore.
For a RAM semaphore, this reference is the address of a doubleword of storage, allocated and initialized to zero by the application. This sets the semaphore as unowned. Other than initializing the doubleword to zero, an application must not modify a RAM semaphore directly; instead it manipulates the semaphore with semaphore function calls.
Timeout (LONG) - input
Action taken by the requesting thread when the semaphore is set. The values that can be specified are:
-1 - The requesting thread waits indefinitely for the semaphore to be cleared.
0 - The requesting thread returns immediately.
>0 - The requesting thread waits the indicated number of milliseconds for the semaphore to be cleared before resuming execution.

Return Code

rc (USHORT) - return
Return code descriptions are:
  • 0 NO_ERROR
  • 95 ERROR_INTERRUPT
  • 101 ERROR_EXCL_SEM_ALREADY_OWNED
  • 103 ERROR_TOO_MANY_SEM_REQUESTS
  • 121 ERROR_SEM_TIMEOUT

Remarks

DosSemSetWait combines the functions of DosSemSet and DosSemWait and is used when there is a chance the semaphore may be cleared by a thread that gets an intervening time slice between calls by the current thread to set the semaphore and wait until it is cleared.

A DosSemSetWait request differs from a DosSemWait request in that it ensures that the semaphore is set so that it can block on it. Issuing DosSemWait on a semaphore that has been cleared has no effect. Instead of blocking, the caller continues to execute.

The unblocking of a thread blocked by a DosSemSetWait is level-triggered. That is, DosSemSetWait does not return until the semaphore remains clear long enough for the affected thread to be redispatched and determine that the semaphore is clear.

DosSemSetWait cannot be issued against a system semaphore owned by another thread unless the NoExclusive option was selected on the DosCreateSem request that created the semaphore.

Bindings

C

#define INCL_DOSSEMAPHORES

USHORT  rc = DosSemSetWait(SemHandle, Timeout);

HSEM    SemHandle;     /* Semaphore handle */
LONG    Timeout;       /* Timeout (in milliseconds) */

USHORT  rc;            /* return code */

MASM

EXTRN  DosSemSetWait:FAR
INCL_DOSSEMAPHORES  EQU 1

PUSH   DWORD   SemHandle     ;Semaphore handle
PUSH   DWORD   Timeout       ;Timeout (in milliseconds)
CALL   DosSemSetWait

Returns WORD

Example

The following example illustrates the notification of an event between threads of different processes. Process1 creates a nonexclusive system semaphore named process1.sem. It then invokes process2 to run asynchronously. Finally, process1 sets the semaphore and waits, with a timeout of 4.5 seconds, for process2 to open the semaphore and clear it. Process1 resumes after this clearance. The following example is different from the one given for DosSemSet and DosSemWait only in that the set and wait functions are performed in one atomic step, via DosSemSetWait. Hence, in the following example, there is no possibility for process1 to miss the notification because of a premature clear by process2.

/* ----- process1.c ---- */

#define INCL_DOSSEMAPHORES
#define INCL_DOSPROCESS

#include <os2.h>

#define SEM_NAME "\\SEM\\process1.sem" /* Semaphore name */
#define TIMEOUT 4500L                  /* Timeout period */
#define START_PROGRAM "process2.exe"   /* Name of program file */

main()
{
  HSEM          SemHandle;
  CHAR          ObjFail [50];
  PSZ           Args;
  PSZ           Envs;
  RESULTCODES   ReturnCodes;
  USHORT        rc;

  printf("Process1 now running. \n");
  rc = DosCreateSem(CSEM_PUBLIC,       /* Ownership indicator */
                    &SemHandle,        /* Semaphore handle (returned) */
                    SEM_NAME);         /* Semaphore name string */
  printf("Process1.sem created; return code is %d \n", rc);

  /* Start a separate process */
  if(!(DosExecPgm(ObjFail,           /* Object name buffer */
                  sizeof(ObjFail),   /* Length of obj. name buffer */
                  EXEC_ASYNC,        /* Execution flag - asynchronous */
                  Args,              /* Ptr. to argument string */
                  Envs,              /* Ptr. to environment string */
                  &ReturnCodes,      /* Ptr. to resultcodes struct. */
                  START_PROGRAM)))   /* Name of program file */
    printf("Process2 started. Process1 will try to wait for notification. \n");

  /************* SET semaphore and WAIT for a notification ************/
  /*************   from process2 on process1.sem           ************/

  if((rc = DosSemSetWait(SemHandle,     /* Semaphore handle */
                         TIMEOUT)))     /* Timeout period */

  /****************************************/
  {
    /* No notification (either interrupt or timeout); error processing */
  }
  else
  {
    /* Notification received.  Normal processing */
    printf("Process2 cleared semaphore; process1 running again. \n");
  }
}
/* ----- process2.c ----*/

#define INCL_DOSSEMAPHORES

#include <os2.h>

#define SEM_NAME "\\SEM\\process1.sem"    /* Semaphore name */

main()
{
  HSEM SemHandle;
  USHORT rc;

  /* Obtain access to semaphore created by process1 via OPEN */
  if((rc=DosOpenSem(&SemHandle,      /* Semaphore handle (returned) */
                    SEM_NAME)))      /* Semaphore Name */
  {
    /* Could not open -- error processing (switch on rc). */
  }
  else
  {
    /* Opened semaphore; normal processing.  Clear semaphore when done. */
    printf("Semaphore OPENED. \n");
    if(!(rc=DosSemClear(SemHandle)))      /* Semaphore handle */
      printf("Semaphore CLEARED. \n");
  }
}