Scheduling Points
Scheduling occurs at scheduling points and nothing special must be done in the application code since scheduling occurs automatically based on the conditions described below.
A task signals or sends a message to another task:
This occurs when the task signaling or sending the message calls one of the post services, OS???Post()
. Scheduling occurs towards the end of the OS???Post()
call. Note that scheduling does not occur if one specifies (as part of the post call) to not invoke the scheduler (i.e., by setting the option argument to OS_OPT_POST_NO_SCHED
).
A task calls OSTimeDly()
or OSTimeDlyHMSM()
:
If the delay is non-zero, scheduling always occurs since the calling task is placed in a list waiting for time to expire. Scheduling occurs as soon as the task is inserted in the wait list and this call will always result in a context switch to the next task that is ready-to-run at the same or lower priority than the task that called OSTimeDly()
or OSTimeDlyHMSM()
.
A task waits for an event to occur and the event has not yet occurred:
This occurs when one of the OS???Pend()
functions are called. The task is placed in the wait list for the event and, if a non-zero timeout is specified, the task is also inserted in the list of tasks waiting to timeout. The scheduler is then called to select the next most important task to run.
If a task aborts a pend:
A task is able to abort the wait (i.e., pend) of another task by calling OS???PendAbort()
. Scheduling occurs when the task is removed from the wait list for the specified kernel object.
If a task is created:
The newly created task may have a higher priority than the task’s creator. In this case, the scheduler is called.
If a task is deleted:
When terminating a task, the scheduler is called if the current task is deleted.
If a kernel object is deleted:
If you delete an event flag group, a semaphore, a message queue, or a mutual exclusion semaphore, if tasks are waiting on the kernel object, those tasks will be made ready-to-run and the scheduler will be called to determine if any of the tasks have a higher priority than the task that deleted the kernel object. Those tasks will be notified that the kernel object was deleted.
A task changes the priority of itself or another task:
The scheduler is called when a task changes the priority of another task (or itself) and the new priority of that task is higher than the task that changed the priority.
A task suspends itself by calling OSTaskSuspend()
:
The scheduler is called since the task that called OSTaskSuspend()
is no longer able to execute. The suspended task must be resumed by another task.
A task resumes another task that was suspended by OSTaskSuspend()
:
The scheduler is called if the resumed task has a higher priority than the task that calls OSTaskResume()
.
At the end of all nested ISRs:
The scheduler is called at the end of all nested ISRs to determine whether a more important task is made ready-to-run by one of the ISRs. The scheduling is actually performed by OSIntExit()
instead of OSSched()
.
The scheduler is unlocked by calling OSSchedUnlock():
The scheduler is unlocked after being locked. You can lock the scheduler by calling OSSchedLock()
. Note that locking the scheduler can be nested and the scheduler must be unlocked a number of times equal to the number of locks.
A task gives up its time quanta by calling OSSchedRoundRobinYield()
:
This assumes that the task is running alongside with other tasks at the same priority and the currently running task decides that it can give up its time quanta and let another task run.
The user calls OSSched()
:
The application code can call OSSched()
to run the scheduler. This only makes sense if calling OS???Post()
functions and specifying OS_OPT_POST_NO_SCHED
so that multiple posts can be accomplished without running the scheduler on every post. However, in the above situation, the last post can be a post without the OS_OPT_POST_NO_SCHED
option.