The sleep upcall provides a mechanism for a task to "block", ie. if it needs to wait for something to happen and would like to let the rest of the system have a go.
If the task is running in a task window, then the TaskWindow module traps the upcall and starts polling the Wimp, returning to the task every so often to allow it to continue (or call UpCall_Sleep again).
PipeFS calls UpCall_Sleep if a pipe being read becomes empty, or if one being written to gets full, and thus cooperates with the Task Window.
UpCall_SleepNoMore is provided so that if the task which called PipeFS is killed by the user, the pipe can be released.
Note that a process must not call UpCall_Sleep if it is not re-entrant, or may have been called by a task which is not re-entrant.
For example, ADFS is not re-entrant, so cannot call UpCall_Sleep, because if it did, then the Task Window would poll the Wimp, and some other task might call ADFS, which would result in an error.
Definition:
SWI OS_UpCall In: R0 = UpCall_Sleep (6) R1 -> poll word (in a global memory area, eg. the RMA) Out: R0 = 0 if upcall claimed
The task wants to sleep until the contents of the poll word become non-zero.
The only program which should intercept this upcall is the task window, which copies away the supervisor stack, flattens it, switches to USR mode, stashes any pending callback and polls the Wimp until the poll word becomes non-zero. It then goes back to SVC mode, restores the supervisor stack, restores the pending callback (if any) and returns to the caller.
The caller should make the call, then set the poll word non-zero when the termination condition is met. If this cannot be done externally, ie. in another Wimp task or under interrupt, then the poll word should be set non-zero on entry, so the callee will return to the caller after each Wimp Poll.
Note that the callee may return before the poll word becomes non-zero, but may not return if the poll word does not become non-zero.
poll word non-zero => callee will return poll word zero => callee may or may not return
SWI OS_UpCall In: R0 = UpCall_SleepNoMore (7) R1 -> poll word Out: VC => R0 preserved VS => R0 -> error block This upcall should not be claimed unless an error is to be returned.
This call is made by PipeFS if an open pipe is closed or deleted. The Task Window module then traps this and objects if any of its tasks are currently waiting for the poll word related to that pipe to become non-zero, by returning an error.
This prevents a *Shut command from deleting the workspace which is being accessed by the Task Window, which could potentially cause address exceptions.