22.2 Using the Scheduler

The Scheduler is a host CPU thread that addresses the issues discussed above. It is responsible for executing audio and graphics tasks on the RCP so that host and RCP overrun is minimized or eliminated.

Each video retrace, the Scheduler reads the new tasks generated by client threads from the task queue and adds them to the end of a real-time (audio) or non-real-time (graphics) task schedule list.

If the previous frame's graphics task has overrun, the Scheduler causes the task to yield. It then runs the next audio task, resuming the yielded task when the audio task has completely processed, and, if any, additional graphics tasks that are to be run in the current frame.

When a task completes, the Scheduler sends a message to the client indicating that the work it requested is complete.


22.2.1 Creating the Scheduler: osCreateScheduler()

In order to use the Scheduler, you must first call osCreateScheduler() to initialize the OSSched data structure, its message queues and the Vi Manager. The osCreateScheduler() function spawns a thread to schedule and manage task execution. One of the parameters to this call is the thread priority, which should be higher than that of the threads which generate the command lists.


22.2.2 Adding Clients to the Scheduler: osScAddClient()

The Scheduler instantiates the Vi Manager and receives all retrace messages. However, clients of the Scheduler can receive a copy of the retrace message by providing a message queue when they sign in. This is accomplished by calling the osScAddClient() function.

Note: One of the parameters to osScAddClient() is the message queue on which you wish to receive retrace messages. Make sure that the queue is big enough if you do not want to lose messages, as the Scheduler does not block when the queue is full.


22.2.3 Creating Scheduler Tasks: OSScTask Structure

In order to send tasks to the Scheduler for execution, you must first create and initialize an OSScTask structure. The structure and a description of its fields is listed below.

typedef struct OSScTask_s{
        struct OSScTask_s   *next;
        s32                 state;
        u32                 flags;
        void                *framebuffer;

        OSTask              list;
        OSMesgQueue         *msgQ;
        OSMesg              msg;
Table 22-1 OSScTask structure fields
nextNot used by client (used by the scheduler for list management).
stateNot used by client (used by the scheduler for state management).
framebufferAddress of the frame buffer for this task (if it is a graphics task).
listStructure containing task code and command list data (described below).
msgQThe message queue on which the client is to receive the task done message.
msgThe message that the client is to receive when the task in done.
typeTask type: should be initialized to M_AUDTASK for audio tasks or M_GFXTASK for graphics tasks.
flagsVarious task state bits: should be initialized to 0 for audio tasks, or OS_TASK_DP_WAIT for most graphics tasks
ucode_boot Pointer to boot microcode : should be initialized to rspbootTextStart.
ucode_boot_sizePointer to boot microcode size in bytes: should be initialized to ((u32)rspbootTextEnd - (u32)rspbootTextStart).
ucodePointer to task microcode: Should be set to one of gspFast3DTextStart, gspFast3D_dramTextStart, gspLine3DTextStart, or gspLine3D_dramTextStart for graphics tasks; otherwise aspMainTextStart for audio tasks.
ucode_sizeSize of microcode; should be initialized to SP_UCODE_SIZE.
ucode_dataPointer to task microcode. Should be set to one of gspFast3DDataStart, gspFast3D_dramDataStart, gspLine3DDataStart, or gspLine3D_dramDataStart for graphics tasks; otherwise aspMainDataStart for audio tasks.
ucode_data_sizeSize of microcode data; should be initialized to SP_UCODE_DATA_SIZE.
dram_stackPointer to DRAM matrix stack: should be initialized to 0 for audio tasks, and for graphic tasks to memory region of size SP_DRAM_STACK_SIZE8 bytes.
dram_stack_sizeDRAM matrix stack size in bytes: should be initialized to 0 for audio tasks or SP_DRAM_STACK_SIZE8 for graphics tasks.
output_buffPointer to output buffer. The "_dram"versions of the graphics microcode will route the SP output to DRAM rather than to the DP. When this microcode is used, this should point to a memory region to which the SP will write the DP command list.
output_buff_sizePointer to store output buffer length. The SP will write the size of the DP command list in bytes to this location.
data_ptrSP command list pointer. For graphics tasks, this is the application constructed display list. For audio tasks, this command list is created by alAudioFrame().
data_sizeLength of SP command list in bytes.
yield_data_ptrPointer to buffer to store saved state of yielding task. If the application is going to support preemption of graphics tasks, the graphics tasks should have this structure member set. This should point to a memory region of size OS_YIELD_DATA_SIZE bytes. If task preemption is not supported by the application, this field be initialized to 0. Audio tasks should always set this field to 0.
yield_data_sizeSize of yield buffer in bytes. When task yielding is to be supported by the application, this should be initialized to OS_YIELD_DATA_SIZE for the graphics task. This should always be 0 for audio tasks.

Note: Refer to the osSpTaskLoad() man page for information about the alignment rule of the data pointers.


22.2.4 Sending Tasks to the Scheduler: osScGetTaskQ()

Once you have created and initialized a Scheduler task, you can send it to the Scheduler thread via the Scheduler's task queue. You can obtain a pointer to this queue by calling osScGetTaskQ().

The Scheduler will read this task queue after the next retrace message from the Vi Manager. Normally, you will send one audio and one graphics task to the Scheduler each frame.

Note: After you send the task to the Scheduler, you should not modify it until you receive the "Done" message.