> net#arf:$.a500.riscos+.doc.Sleep

Author: Neil Raine
  Date: 13-Feb-91

The Sleep upcall
----------------

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.

