|
|
Line 1: |
Line 1: |
| This service prevents the thread executing in the physical device driver from executing ("puts it to sleep") until either a call to the DevHlp_ProcRun is issued on the event identifier, or a timeout occurs. | | This service is the companion routine to ProcBlock. When ProcRun is called, it awakens all the threads that were blocked for this particular event identifier. |
|
| |
|
| ==Syntax== | | ==Syntax== |
| ===C=== | | ===C=== |
| <PRE> | | <PRE> |
| USHORT APIENTRY DevHelp_ProcBlock( ULONG EventId, | | USHORT APIENTRY DevHelp_ProcRun( ULONG EventId, |
| ULONG WaitTime,
| | PUSHORT AwakeCount) |
| USHORT IntWaitFlag)
| |
| </PRE> | | </PRE> |
|
| |
|
| ===Assembler=== | | ===Assembler=== |
| <PRE> | | <PRE> |
| MOV BX,event_id_low ; Low word of event id | | MOV BX,event_id_low ; Low word of event identifier. |
| MOV AX,event_id_high ; High word of event id | | MOV AX,event_id_high ; High word of event identifier. |
| MOV DI,time_limit_high ; Timeout interval in milliseconds
| | MOV DL,DevHlp_ProcRun |
| MOV CX,time_limit_low ; ( = -1 if to never timeout)
| |
| MOV DH,interruptible_flag ; Tells if sleep is interruptible
| |
| ; 0 = interruptible
| |
| ; 1 = non-interruptible
| |
| MOV DL,DevHlp_ProcBlock | |
|
| |
|
| CALL [Device_Help] | | CALL [Device_Help] |
Line 24: |
Line 18: |
| ==Parameters== | | ==Parameters== |
| ===C=== | | ===C=== |
| ; EventId (ULONG) : Event identifier - an arbitrary 32-bit value. | | ; EventId (ULONG): Event identifier. |
| : The standard convention for ProcBlock/ProcRun operations is to use the address of some structure or memory cell associated with the reason for blocking and running. For example, a thread blocking until some resource is cleared normally blocks on the address of ownership flag for that resource.
| |
| | |
| ; WaitTime (ULONG) : Timeout interval in milliseconds.
| |
| : -1 = wait forever.
| |
| | |
| IntWaitFlag (USHORT) : Tells if sleep is interruptible.
| |
| : 0 = interruptible, 1 = non-interruptible.
| |
|
| |
|
| | ; AwakeCount (PUSHORT) : Count of threads awakened to be returned. |
| ===Assembler=== | | ===Assembler=== |
| <PRE> | | <PRE> |
| MOV BX,event_id_low ; Low word of event id | | MOV BX,event_id_low ; Low word of event identifier. |
| MOV AX,event_id_high ; High word of event id | | MOV AX,event_id_high ; High word of event identifier. |
| MOV DI,time_limit_high ; Timeout interval in milliseconds
| |
| MOV CX,time_limit_low ; ( = -1 if to never timeout)
| |
| MOV DH,interruptible_flag ; Tells if sleep is interruptible
| |
| ; 0 = interruptible
| |
| ; 1 = non-interruptible
| |
| </PRE> | | </PRE> |
|
| |
|
Line 47: |
Line 30: |
|
| |
|
| ===C=== | | ===C=== |
| Success Indicator: Returns awake code. | | Success Indicator: 0 |
|
| |
|
| Possible errors: | | Possible errors: None. |
| WAIT_INTERRUPTED
| |
| WAIT_TIMED_OUT
| |
|
| |
|
| ===Assembler=== | | ===Assembler=== |
| <PRE> | | <PRE> |
| 'C' Clear if event wakeup. | | AX = Count of threads awakened. |
| 'C' Set if unusual wakeup.
| |
| 'Z' Set if wakeup due to timeout.
| |
| 'Z' Clear if sleep was interrupted.
| |
|
| |
|
| AL = Awake code, non-zero if unusual wakeup.
| | 'Z' Set or clear according to the contents of AX. |
| </PRE> | | </PRE> |
|
| |
|
| ==Remarks== | | ==Remarks== |
| The return from the call to ProcBlock indicates whether the "wakeup" occurred as the result of a call to ProcRun or an expiration of the time limit. ProcBlock removes the current thread from the ProcRun queue and starts executing some other thread. The thread blocked in the physical device driver is reactivated and ProcBlock returns when ProcRun is called with the same event identifier, when the time limit expires, or when the thread is signalled.
| | ProcRun returns immediately to its caller; the awakened threads are run at the next available opportunity. ProcRun is often called at interrupt time. See ProcBlock for a more detailed discussion of blocking and running threads. |
| | |
| The event identifier is an arbitrary 32-bit value, but a convention must be followed to coordinate with the thread issuing the ProcRun function. The standard convention for ProcBlock/ProcRun operations is to use the address of some structure or memory cell associated with the reason for blocking and running. For example, a thread blocking until some resource is cleared normally blocks on the address of the ownership flag for that resource.
| |
| | |
| The ProcBlock/ProcRun mechanism is so designed that it cannot guarantee immunity from a faulty wakeup by some other thread in the system running a 32-bit key value (which happens to match the key of some unrelated blocking thread). The goal is to choose keys that have a high likelihood of being unique. However, users of ProcBlock/ProcRun must always check the reason for the wakeup to make sure that the event actually took place, and that the wakeup was not accidental.
| |
| | |
| When calling ProcBlock, it is important to use the sequence:
| |
| | |
| Disable Interrupts
| |
|
| |
| while (need to wait)
| |
| Block (value)
| |
| Disable Interrupts
| |
| | |
| Interrupts must be turned off before checking the condition (for example, I/O done, resource freed). This is necessary to avoid a deadlock caused by getting an interrupt-time ProcRun call before completing the call to ProcBlock. ProcBlock re-enables the interrupts. Note the use of the WHILE clause. It is essential to recheck the awaited condition and, if necessary, re-disable interrupts and call ProcBlock again. The convention of using an address as an event identifier should prevent double use of an identifier. A time limit of -1 means that ProcBlock waits indefinitely until ProcRun is called. ProcBlock can be called only by the task-time portion of a physical device driver.
| |
| | |
| When using ProcBlock to block a thread, the driver can specify whether the sleep can be interrupted. If the sleep is interruptible, then the kernel can abort the blocked thread and return from the ProcBlock, without using a corresponding ProcRun. In general, the sleep should be marked as interruptible unless the sleep duration is expected to be short (that is, less than a second).
| |
| | |
| If the return from the ProcBlock indicates that the sleep was interrupted, some internal event occurred that requires attention (such as a signal, process death, or some other forced action). The device driver should respond by performing any necessary cleanup, setting the error code in the status field of the request packet, setting the done bit, and returning the request packet to the kernel.
| |
|
| |
|
| ==Example Code== | | ==Example Code== |
Line 89: |
Line 49: |
| #include "dhcalls.h" | | #include "dhcalls.h" |
|
| |
|
| USHORT APIENTRY DevHelp_ProcBlock( ULONG EventId, | | USHORT APIENTRY DevHelp_ProcRun( ULONG EventId, |
| ULONG WaitTime,
| | PUSHORT AwakeCount) |
| USHORT IntWaitFlag)
| |
| </PRE> | | </PRE> |
|
| |
|
This service is the companion routine to ProcBlock. When ProcRun is called, it awakens all the threads that were blocked for this particular event identifier.
Syntax
C
USHORT APIENTRY DevHelp_ProcRun( ULONG EventId,
PUSHORT AwakeCount)
Assembler
MOV BX,event_id_low ; Low word of event identifier.
MOV AX,event_id_high ; High word of event identifier.
MOV DL,DevHlp_ProcRun
CALL [Device_Help]
Parameters
C
- EventId (ULONG)
- Event identifier.
- AwakeCount (PUSHORT)
- Count of threads awakened to be returned.
Assembler
MOV BX,event_id_low ; Low word of event identifier.
MOV AX,event_id_high ; High word of event identifier.
Return Code
C
Success Indicator: 0
Possible errors: None.
Assembler
AX = Count of threads awakened.
'Z' Set or clear according to the contents of AX.
ProcRun returns immediately to its caller; the awakened threads are run at the next available opportunity. ProcRun is often called at interrupt time. See ProcBlock for a more detailed discussion of blocking and running threads.
Example Code
C
#include "dhcalls.h"
USHORT APIENTRY DevHelp_ProcRun( ULONG EventId,
PUSHORT AwakeCount)
Related Functions