Jump to content

DosMuxSemWait: Difference between revisions

From EDM2
No edit summary
Ak120 (talk | contribs)
mNo edit summary
 
(One intermediate revision by the same user not shown)
Line 1: Line 1:
{{Legacy
|RepFunc=
|Remarks=This page list the older version of the function for reference.
}}
This call blocks a current thread until one of the specified semaphores is cleared.
This call blocks a current thread until one of the specified semaphores is cleared.


Line 18: Line 14:
: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.
: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 none of the semaphores in the list is available. The values that can be specified are:
;Timeout (LONG) - input : Action taken by the requesting thread when none of the semaphores in the list is available. The values that can be specified are:
'''Value  Definition'''
::-1 - The requesting thread waits indefinitely for a semaphore to be cleared.
-1   The requesting thread waits indefinitely for a semaphore to be cleared.
::0 - The requesting thread returns immediately.
0   The requesting thread returns immediately.
::>0 - The requesting thread waits the indicated number of milliseconds for a semaphore to be cleared before resuming execution.
> 0 The requesting thread waits the indicated number of milliseconds
      for a semaphore to be cleared before resuming execution.


==Return Code==
==Return Code==
rc (USHORT) - return
;rc (USHORT) - return:Return code descriptions are:
Return code descriptions are:
*0 NO_ERROR
* 0         NO_ERROR
*95 ERROR_INTERRUPT
* 95         ERROR_INTERRUPT
*101 ERROR_EXCL_SEM_ALREADY_OWNED
* 101       ERROR_EXCL_SEM_ALREADY_OWNED
*121 ERROR_SEM_TIMEOUT
* 121       ERROR_SEM_TIMEOUT
*151 ERROR_INVALID_EVENT_COUNT
* 151       ERROR_INVALID_EVENT_COUNT  
*152 ERROR_TOO_MANY_MUXWAITERS
* 152       ERROR_TOO_MANY_MUXWAITERS  
*153 ERROR_INVALID_LIST_FORMAT
* 153       ERROR_INVALID_LIST_FORMAT


==Remarks==
==Remarks==
Line 40: Line 33:
Unlike other semaphore calls that block (DosSemRequest, DosSemWait, and DosSemSetWait), DosMuxSemWait is an edge-triggered, rather than a level-triggered, procedure. This means it returns whenever one of the semaphores on the list is cleared, regardless of how long that semaphore may remain clear. It is possible the semaphore may be reset before DosMuxSemWait returns. If a semaphore is cleared and then set prior to the thread's executing the DosMuxSemWait call, the event is lost. Events are only effective while a thread is in a DosMuxSemWait call.
Unlike other semaphore calls that block (DosSemRequest, DosSemWait, and DosSemSetWait), DosMuxSemWait is an edge-triggered, rather than a level-triggered, procedure. This means it returns whenever one of the semaphores on the list is cleared, regardless of how long that semaphore may remain clear. It is possible the semaphore may be reset before DosMuxSemWait returns. If a semaphore is cleared and then set prior to the thread's executing the DosMuxSemWait call, the event is lost. Events are only effective while a thread is in a DosMuxSemWait call.


This implementation allows DosMuxSemWait to be used in conjunction with one or more semaphores as a triggering or synchronizing device. One or more threads can call DosMuxSemWait for a particular semaphore. When an event occurs, another thread can clear the semaphore and then immediately set it again, arming it for the next event. Threads that were waiting on that semaphore return from DosMuxSemWait and resume execution.  
This implementation allows DosMuxSemWait to be used in conjunction with one or more semaphores as a triggering or synchronizing device. One or more threads can call DosMuxSemWait for a particular semaphore. When an event occurs, another thread can clear the semaphore and then immediately set it again, arming it for the next event. Threads that were waiting on that semaphore return from DosMuxSemWait and resume execution.


==Example Code==
==Bindings==
===C Binding===
===C===
<PRE>
<PRE>
typedef struct _MUXSEMLIST {   /* mxsl */
typedef struct _MUXSEMLIST { /* mxsl */
   USHORT  cmxs;               /* count of MuxSem structures */
   USHORT  cmxs;               /* count of MuxSem structures */
   MUXSEM  amxs[16];           /* MuxSem structure */
   MUXSEM  amxs[16];           /* MuxSem structure */
} MUXSEMLIST;
} MUXSEMLIST;


Line 59: Line 52:
USHORT  rc = DosMuxSemWait(IndexNbr, ListAddr, Timeout);
USHORT  rc = DosMuxSemWait(IndexNbr, ListAddr, Timeout);


PUSHORT          IndexNbr;     /* Index number of event (returned) */
PUSHORT          IndexNbr;   /* Index number of event (returned) */
PVOID            ListAddr;     /* Semaphore list */
PVOID            ListAddr;   /* Semaphore list */
LONG            Timeout;       /* Timeout (in milliseconds) */
LONG            Timeout;     /* Timeout (in milliseconds) */


USHORT          rc;           /* return code */
USHORT          rc;         /* return code */
</PRE>
</PRE>
The following example illustrates notification of events between threads of the same process. The main thread sets two RAM semaphores and invokes two threads, each of which clears one of the semaphores. Meanwhile, the main thread waits for either of the two semaphores to clear, and then resumes execution, indicating the thread that notified first.  
 
===MASM===
<PRE>
MUXSEMLIST struc
  mxsl_cmxs dw  ? ;count of MuxSem structures
  mxsl_amxs dw (size MUXSEM)/2 * 16 dup (?) ;MuxSem structure
MUXSEMLIST ends
 
MUXSEM  struc
  mxs_zero  dw  ? ;zero
  mxs_hsem  dd  ? ;semaphore handle
MUXSEM  ends
 
EXTRN  DosMuxSemWait:FAR
INCL_DOSSEMAPHORES  EQU 1
 
PUSH@  WORD    IndexNbr      ;Index number of event (returned)
PUSH@  OTHER  ListAddr      ;Semaphore list
PUSH  DWORD  Timeout      ;Timeout (in milliseconds)
CALL  DosMuxSemWait
 
Returns WORD
</PRE>
 
==Example Code==
The following example illustrates notification of events between threads of the same process. The main thread sets two RAM semaphores and invokes two threads, each of which clears one of the semaphores. Meanwhile, the main thread waits for either of the two semaphores to clear, and then resumes execution, indicating the thread that notified first.
<PRE>
<PRE>
#define INCL_DOSPROCESS
#define INCL_DOSPROCESS
Line 133: Line 155:
   /* Start the two threads */
   /* Start the two threads */
   if(!(DosCreateThread((PFNTHREAD) Thread_1,  /* Thread address */
   if(!(DosCreateThread((PFNTHREAD) Thread_1,  /* Thread address */
                       &ThreadID[0],          /* Thread ID
                       &ThreadID[0],          /* Thread ID (returned) */
                                                                (returned) */
                       &ThreadStack1[3999])))  /* End of thread stack */
                       &ThreadStack1[3999])))  /* End of thread
                                                                stack */
     printf("Thread_1 created. \n");
     printf("Thread_1 created. \n");
   if(!(DosCreateThread((PFNTHREAD) Thread_2,  /* Thread address */
   if(!(DosCreateThread((PFNTHREAD) Thread_2,  /* Thread address */
                       &ThreadID[1],          /* Thread ID
                       &ThreadID[1],          /* Thread ID (returned) */
                                                                (returned) */
                       &ThreadStack2[3999])))  /* End of thread stack */
                       &ThreadStack2[3999])))  /* End of thread
                                                                stack */
     printf("Thread_2 created. \n");
     printf("Thread_2 created. \n");


Line 148: Line 166:
   /*  thread notified first.                                */
   /*  thread notified first.                                */


   if(!(DosMuxSemWait(&IndexNbr,    /* Index of semaphore   */
   if(!(DosMuxSemWait(&IndexNbr,    /* Index of semaphore cleared (returned) */
                                  /*  cleared (returned) */
                     &SemList,    /* Address of sem. list structure */
                     &SemList,    /* Address of sem. list structure */
                     TIMEOUT)))    /* Timeout period */
                     TIMEOUT)))    /* Timeout period */
Line 158: Line 175:
</PRE>
</PRE>


===MASM Binding===
[[Category:Dos16]]
<PRE>
MUXSEMLIST struc
  mxsl_cmxs dw  ? ;count of MuxSem structures
  mxsl_amxs dw (size MUXSEM)/2 * 16 dup (?) ;MuxSem structure
MUXSEMLIST ends
 
MUXSEM  struc
  mxs_zero  dw  ? ;zero
  mxs_hsem  dd  ? ;semaphore handle
MUXSEM  ends
 
EXTRN  DosMuxSemWait:FAR
INCL_DOSSEMAPHORES  EQU 1
 
PUSH@  WORD    IndexNbr      ;Index number of event (returned)
PUSH@  OTHER  ListAddr      ;Semaphore list
PUSH  DWORD  Timeout      ;Timeout (in milliseconds)
CALL  DosMuxSemWait
 
Returns WORD
</PRE>
==Related Functions==
*
 
[[Category:Dos]]

Latest revision as of 23:57, 25 January 2020

This call blocks a current thread until one of the specified semaphores is cleared.

Syntax

DosMuxSemWait (IndexNbr, ListAddr, Timeout)

Parameters

IndexNbr (PUSHORT) - output
Address of the index number of the semaphore in the list of semaphores that satisfies the wait request.
ListAddr (PVOID) - input
Address of the structure for list of descriptors that define the semaphores to be waited on.
semcount (USHORT) : Number of semaphores.
sementry (MUXSEM) : Array of MUXSEM structures:
reserved (USHORT) - Reserved; must be zero.
hsem (HSEM) - 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 none of the semaphores in the list is available. The values that can be specified are:
-1 - The requesting thread waits indefinitely for a semaphore to be cleared.
0 - The requesting thread returns immediately.
>0 - The requesting thread waits the indicated number of milliseconds for a 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
  • 121 ERROR_SEM_TIMEOUT
  • 151 ERROR_INVALID_EVENT_COUNT
  • 152 ERROR_TOO_MANY_MUXWAITERS
  • 153 ERROR_INVALID_LIST_FORMAT

Remarks

DosMuxSemWait checks a semaphore list. If any of the semaphores are clear, DosMuxSemWait returns. If all are set, DosMuxSemWait blocks until one of the semaphores is cleared or until the time out occurs.

Unlike other semaphore calls that block (DosSemRequest, DosSemWait, and DosSemSetWait), DosMuxSemWait is an edge-triggered, rather than a level-triggered, procedure. This means it returns whenever one of the semaphores on the list is cleared, regardless of how long that semaphore may remain clear. It is possible the semaphore may be reset before DosMuxSemWait returns. If a semaphore is cleared and then set prior to the thread's executing the DosMuxSemWait call, the event is lost. Events are only effective while a thread is in a DosMuxSemWait call.

This implementation allows DosMuxSemWait to be used in conjunction with one or more semaphores as a triggering or synchronizing device. One or more threads can call DosMuxSemWait for a particular semaphore. When an event occurs, another thread can clear the semaphore and then immediately set it again, arming it for the next event. Threads that were waiting on that semaphore return from DosMuxSemWait and resume execution.

Bindings

C

typedef struct _MUXSEMLIST {  /* mxsl */
  USHORT  cmxs;               /* count of MuxSem structures */
  MUXSEM  amxs[16];           /* MuxSem structure */
} MUXSEMLIST;

typedef struct _MUXSEM {    /* mxs */
  USHORT zero;              /* zero */
  HSEM   hsem;              /* semaphore handle */
} MUXSEM;

#define INCL_DOSSEMAPHORES

USHORT  rc = DosMuxSemWait(IndexNbr, ListAddr, Timeout);

PUSHORT          IndexNbr;    /* Index number of event (returned) */
PVOID            ListAddr;    /* Semaphore list */
LONG             Timeout;     /* Timeout (in milliseconds) */

USHORT           rc;          /* return code */

MASM

MUXSEMLIST struc
 
  mxsl_cmxs dw  ? ;count of MuxSem structures
  mxsl_amxs dw (size MUXSEM)/2 * 16 dup (?) ;MuxSem structure
 
MUXSEMLIST ends

MUXSEM  struc
 
  mxs_zero  dw  ? ;zero
  mxs_hsem  dd  ? ;semaphore handle
 
MUXSEM  ends

EXTRN  DosMuxSemWait:FAR
INCL_DOSSEMAPHORES  EQU 1

PUSH@  WORD    IndexNbr      ;Index number of event (returned)
PUSH@  OTHER   ListAddr      ;Semaphore list
PUSH   DWORD   Timeout       ;Timeout (in milliseconds)
CALL   DosMuxSemWait

Returns WORD

Example Code

The following example illustrates notification of events between threads of the same process. The main thread sets two RAM semaphores and invokes two threads, each of which clears one of the semaphores. Meanwhile, the main thread waits for either of the two semaphores to clear, and then resumes execution, indicating the thread that notified first.

#define INCL_DOSPROCESS
#define INCL_DOSSEMAPHORES

#include<os2.h>
#include<stdio.h>

#define NUM_SEMS         2       /* Number of semaphores to wait on */
#define TIMEOUT          2000L   /* Timeout period */
#define SLEEPTIME        1000L   /* Sleep period for Thread_1 */
#define RETURN_CODE      0       /* Return Code for thread termination */

ULONG       RamSem1 = 0L;        /* Allocation and initialization of   */
ULONG       RamSem2 = 0L;        /*  two RAM semaphores                */
ULONG far   *RamSem1Handle = &RamSem1;  /* Semaphore handles */
ULONG far   *RamSem2Handle = &RamSem2;
TID         ThreadID[2];         /* Thread Identification */
BYTE        ThreadStack1[4000];  /* Thread Stack Area */
BYTE        ThreadStack2[4000];
MUXSEMLIST  SemList;             /* Semaphore list structure */
USHORT      IndexNbr;            /* Index number for DosMuxSemWait */
USHORT      rc;                  /* Return Code */

VOID APIENTRY Thread_1()
{
  USHORT r;

  printf("Begin Thread_1. It will sleep for 1 second. \n");

  /* Give Thread_2 a chance to execute */
  DosSleep(SLEEPTIME);                 /* Sleep Interval */
  if(!(r=DosSemClear(RamSem1Handle)))  /* Semaphore handle */
    printf("RamSem1 cleared. \n");
  DosExit(EXIT_THREAD,                 /* Action Code */
          RETURN_CODE);                /* Result Code */
}

VOID APIENTRY Thread_2()
{
  USHORT r;

  printf("Begin Thread_2. It will try to clear RamSem2 now. \n");
  if(!(r=DosSemClear(RamSem2Handle)))  /* Semaphore Handle */
    printf("RamSem2 cleared. \n");
  DosExit(EXIT_THREAD,                 /* Action Code */
          RETURN_CODE);                /* Result Code */
}

main()
{
  USHORT  rc;                          /* Return Code */

  /* Set both semaphores */
  if(!(rc=DosSemSet(RamSem1Handle)))   /* Semaphore Handle */
    printf("RamSem1 set. \n");
  if(!(rc=DosSemSet(RamSem2Handle)))   /* Semaphore Handle */
    printf("RamSem2 set. \n");

  /* Initialize Semaphore list structure */
  SemList.cmxs = NUM_SEMS;             /* Number of semaphores */
  SemList.amxs[0].zero = 0;            /* This field must be 0 */
  SemList.amxs[1].zero = 0;            /* This field must be 0 */
  SemList.amxs[0].hsem = RamSem1Handle;  /* Semaphore handle */
  SemList.amxs[1].hsem = RamSem2Handle;  /* Semaphore handle */

  /* Start the two threads */
  if(!(DosCreateThread((PFNTHREAD) Thread_1,   /* Thread address */
                       &ThreadID[0],           /* Thread ID (returned) */
                       &ThreadStack1[3999])))  /* End of thread stack */
    printf("Thread_1 created. \n");
  if(!(DosCreateThread((PFNTHREAD) Thread_2,   /* Thread address */
                       &ThreadID[1],           /* Thread ID (returned) */
                       &ThreadStack2[3999])))  /* End of thread stack */
    printf("Thread_2 created. \n");

  /* Wait for either semaphore to clear; then, indicate which */
  /*   thread notified first.                                 */

  if(!(DosMuxSemWait(&IndexNbr,    /* Index of semaphore cleared (returned) */
                     &SemList,     /* Address of sem. list structure */
                     TIMEOUT)))    /* Timeout period */
    printf("Back to main thread; semaphore cleared by Thread%d.\n",
           IndexNbr + 1);
  }
}