yield.txt 3.96 KB
THIS FILE DESCRIBES HOW YIELD WORKS, HOW TO USE YIELD, AND HOW TO TEST YIELD
----------------------------------------------------------------------------
File created 4/6/95 by Acorn

WHAT YIELD IS
-------------
A yield should occur when there is a microcode task running and the CPU 
wants to stop that task and run a new task, and possably later restore 
the first task.

HOW YIELD WORKS
---------------
When the CPU wants to interrupt the currently running microcode task it
calls the function:
	void             osSpTaskYield(void);
Which requests the microcode to yield and then immediately returns.  The 
microcode has not yielded yet, but it is preparing to.  In preparation for
yielding the microcode saves the DMEM in the buffer pointed to by
	RSPTask->t.yield_data_ptr
Which must be initialized *BEFORE EVER STARTING THE TASK IN THE FIRST PLACE* to
point to a buffer of OS_YIELD_DATA_SIZE bytes (OS_YIELD_DATA_SIZE is defined 
in os.h).  The osSpTaskYield function also indicates that the yield was 
successful by setting the SP_STATUS_YIELDED bit (which is SP_STATUS_SIG1) in 
the SP_STATUS_REG.  
NOTE: If a task will NEVER be yielded then the taskHdrPtr->t.yield_data_ptr may
be null.

(NOTE: the cpu may perform other tasks while the microcode is doing this work)

When the microcode has finished yielding it executes a break instruction
which sets the HALT flag and causes an OS_EVENT_SP event  (Note: this event can be attatched to a message queue with the osSetEventMesg function).

Once the CPU detects that the microcode is finished (via the HALT flag or the
OS_EVENT_SP event) it must call the 
	OSYieldResult    osSpTaskYielded(OSTask *tp);
function which returns true if the yield was successful and false if the
microcode was able to complete before the yield occurred.  

At this point the cpu can start a new task from scratch.

If the CPU does not want to finish the original task, it should set
	taskHeaderPtr->t.flags &= ~OS_TASK_YIELDED;

If, on the other hand, the CPU DOES want to complete the original task (after
one or more other tasks have been run) it may do so by calling 
	void             osSpTaskStart(OSTask *tp);
(supply the original task pointer which was used to star the task from scratch).
IMPORTANT:  THE TASK SHOULD NEVER BE RESTARTED (with this call) IF THE RETURN
VALUE OF osSpTaskYielded WHEN CALLED (as described above) IS FALSE!!!!
After the task is restarted with osSpTaskStart, things are back to normal:
the task will continue until it is complete, or until the CPU decides that it
again must perform a yield.

TO SUMMARIZE: 
-------------

IF osSpTaskYielded returned TRUE and you want to restart the task from where it
left off:  call
	osSpTaskStart(OSTask *tp);

IF osSpTaskYielded returned TRUE and you want to start the task from scratch
(eg for the next frame):
	taskHeaderPtr->t.flags &= ~OS_TASK_YIELDED;
	osSpTaskStart(OSTask *tp);

IF osSpTaskYielded returned FALSE and you want to restart from scratch, DONT.
In this case the task has already completed.

IF osSpTaskYielded returned FALSE and you want to start the task from scratch
(eg for the next frame) call
	osSpTaskStart(OSTask *tp);


HOW TO TEST YIELD
-----------------
Yield may be tested in the emulator environment using the rdp*/rdpverif tests.
It will only work when used with the shared memory model (-S flag for emulate).
To run a test with yield use the -S option with the emulator and the -y 
option with the application.  For example, to run rdpcov test 34 with yield:
   emulate -S -s -a "-y -a -o 34 -f 34 -n InData/test034 -m" rdpverif rom
When you use the -y optiom (and the -S option) the rdpverif program starts the
task running, waits a while (alter the DELAYLEN #define to alter the length of
the delay, bigger numbers=longer delay), and then causes a yield.  When the
RSP has finished yielding the rdpverif program restarts the task and allows
it to complete.

NOTE: if you set the -y flag without setting the -S flag you may get strange
behavior...

Any questions, please feel free to  ask me
-Acorn (acorn@sgi)