Difference between revisions of "OCEOS/oceos kernel/task"

From wiki
Jump to navigation Jump to search
 
(44 intermediate revisions by the same user not shown)
Line 1: Line 1:
=<span style="color:#0000ff">'''OCEOS Task'''</span>=
=<span style="color:#0000ff">'''OCEOS Task'''</span>=
==<span style="color:#0000ff">Introduction</span>==
==<span style="color:#0000ff">Task Introduction</span>==
 
In OCEOS all tasks are defined before scheduling begins and each task assigned a fixed priority, a pre-emption threshold, a current jobs limit, a maximum start to completion time, and an expected minimum inter start request time.
A task’s pre-emption threshold limits the tasks that can pre-empt it to those with higher priority than this threshold. Tasks with short run times can use this to avoid context switch overheads.
Each task has two main states, enabled or disabled. OCEOS provides system calls to change task state. The state is usually enabled when the task is created, but can be initially disabled.
A disabled task will not be executed, and any attempt to start it will be logged and the system state variable updated.<br>
A request to start an enabled task creates an execution instance of the task, a ‘job’. A count is kept for each task of the number of times it has been started, i.e. total number of jobs created.
Multiple jobs of the same task can be in existence simultaneously. A limit for the maximum number of these current jobs is set when a task is created, the ‘current jobs limit’.
Each task has a current jobs count. This increments each time a task is started and decrements on job completion unless completion creates a further job from this task.
A further execution instance of a task is not created if the current jobs count has reached the current jobs limit. Such job creation failures are logged and the system state updated.
For each task a record is kept of the shortest time between attempts to create a new job, and a record of the maximum time between these attempts.
For each task a record is kept also of the maximum time a job was waiting before starting, the minimum execution time, the maximum execution time, the maximum time from job creation to completion, and the maximum number of job pre-emptions. The system state variable is updated if necessary.<br>
Task chaining is supported. A job can create a new job and pass this to the scheduler or place it on the [[OCEOS/oceos introduction#Timed_Actions_Queue|timed actions queue]] .<br>
Tasks provide a start address for a termination routine for use if task execution must be abandoned.
<blockquote style="background-color: #c6e2f7; border-left-style: solid; border-left-width: 3px; border-left-color: blue; "> '''Note'''<br>
All Tasks must be created before [[OCEOS/oceos kernel/initialisation#oceos_init_finish()|oceos_init_finish()]] is called.
</blockquote>
 
==<span style="color:#0000ff">Task Configuration</span>==
 
<blockquote>
User must define NUMBER_OF_TASKS. The example can be found in OCEOS demo projects.<br>
User must create defined number of tasks before calling [[OCEOS/oceos kernel/initialisation#oceos_init_finish()|oceos_init_finish()]]
<syntaxhighlight lang="C">
    #define NUMBER_OF_TASKS 2
    /*
    * Create the application configuration structure
    */
    struct application_configuration          app_config = {0};
    app_config.number_of_tasks              = NUMBER_OF_TASKS;              // >= 1
</syntaxhighlight>
</blockquote>
<blockquote>
User must define NUMBER_OF_READYQ_ENTRIES. The example can be found in OCEOS demo projects.<br>
Number of ready queue entries, 0 to 254. Defaults to number of tasks, as each task should have at least one job.
If Number of ready queue entries is larger that number of total jobs it defaults to number of total jobs
<syntaxhighlight lang="C">
    #define NUMBER_OF_READYQ_ENTRIES 5
    /*
    * Create the application configuration structure
    */
    struct application_configuration          app_config = {0};
    app_config.number_of_readyQ_entries      = NUMBER_OF_READYQ_ENTRIES;      // 0 => calculate size
</syntaxhighlight>
</blockquote>


==<span style="color:#0000ff">API Functions</span>==
==<span style="color:#0000ff">API Functions</span>==
Line 6: Line 50:
|+ API Functions
|+ API Functions
|-
|-
! Directive                                                                    !! Description                       !! main !! task !! IRQ handler
! Directive                                                                    !! Description                         !! main !! task !! IRQ handler
|-
| [[OCEOS/oceos kernel/task#oceos_task_create()| oceos_task_create()]]            || Create Task                        || *    ||      ||
|-
| [[OCEOS/oceos kernel/task#oceos_task_start()| oceos_task_start()]]              || Start Task                        ||      ||  *  || *
|-
| [[OCEOS/oceos kernel/task#oceos_task_timed_start()| oceos_task_timed_start()]]  || Schedule a task to start execution at a given system time||      ||  *  || *
|-
| [[OCEOS/oceos kernel/task#oceos_task_disable()| oceos_task_disable()]]          || Disable Task                      ||      ||  *  || *
|-
| [[OCEOS/oceos kernel/task#oceos_task_enable()| oceos_task_enable()]]            || Enable Task                        ||      ||  *  || *
|-
| [[OCEOS/oceos kernel/task#oceos_task_self()| oceos_task_self()]]                || Returns the task ID of the currently executing task ||    ||  *  || *
|-
| [[OCEOS/oceos kernel/task#oceos_task_get_priority()| oceos_task_get_priority()]] || Get priority of a task            ||      ||  *  || *
|-
| [[OCEOS/oceos kernel/task#oceos_task_get_status()| oceos_task_get_status()]]    || Get status of a task              ||      ||  *  || *
|-
| [[OCEOS/oceos kernel/task#oceos_task_kill()| oceos_task_kill()]]                || Directive to terminate current task||      ||  *  || *
|-
|-
| [[OCEOS/oceos kernel/task#()| oceos_init()]]                                   || Initialize fixed data            || *   ||     ||  
| [[OCEOS/oceos kernel/task#oceos_task_get_info()| oceos_task_get_info()]]         || Get task information              ||      ||  *  || *
|}
===<span style="color:#0000ff">oceos_task_create()</span>===
<blockquote style="border-left-style: none;">
<span style="color:#1b7ac2">'''Header File'''</span><br>
'''''tasks.h'''''<br>
 
<span style="color:#1b7ac2">'''Description'''</span><br>
Create a task.
Can only be use before OCEOS starts. Stores the task information in the OCEOS fixed data area.
This directive populates the data structures for a task. It should be called after [[OCEOS/oceos kernel/initialisation#oceos_init()|oceos_init()]] and before [[OCEOS/oceos kernel/initialisation#oceos_init_finish()|oceos_init_finish()]].<br>
It must be called for each task otherwise [[OCEOS/oceos kernel/initialisation#oceos_start()|oceos_start()]] will return an error.


<span style="color:#1b7ac2">'''Prototype'''</span><br>
<syntaxhighlight lang="C">
enum DIRECTIVE_STATUS  oceos_task_create(
    unsigned int taskID,        // unique, 0 to TASKS_MAX_ID
    U32_t priority,              // TASK_MAX_PRIORITY to TASK_MIN_PRIORITY
    U32_t threshold,            // TASK_MAX_PRIORITY to priority
    U32_t jobs_max,              // 1 to JOBS_MAX
    BOOLE_t FP_used,            // whether uses floating point hardware
    BOOLE_t initially_enabled,  // whether task enabled initially
    void (void *) start_function,// task start address
    void (void *) end_function,  // start of task end function
    U32_t time_deadline,        // maximum time to complete (ignore if 0)
    U32_t time_mininterstart    // minimum time between start requests
);
</syntaxhighlight>
<span style="color:#1b7ac2">'''Parameters'''</span><br>
{| class="wikitable"
|-
! Parameter          !! Description
|-
|taskID              || Unique task ID from 0 to TASKS_MAX_ID
|-
|priority            || TASK_MAX_PRIORITY to TASK_MIN_PRIORITY
|-
|threshold            || TASK_MAX_PRIORITY to priority
|-
|jobs_max            || Number of 1 to JOBS_MAX
|-
|FP_used              || whether uses floating point hardware
|-
|initially_enabled    || whether task enabled initially
|-
|start_function      || task start address
|-
|end_function        || start of task end function
|-
|time_deadline        || maximum time to complete (ignore if 0)
|-
|time_mininterstart  || minimum time between start requests
|}
|}
<span style="color:#1b7ac2">'''Returns'''</span><br>
This function returns enum DIRECTIVE_STATUS.<br>
{| class="wikitable"
|-
! enum DIRECTIVE_STATUS !! Description
|-
|INCORRECT_STATE  || Init Meta Pointer is NULL or
                    Pointer to Task fixed data is NULL
|-
|TOO_MANY        || Exceeds number of MAX Tasks or
                    Exceeds number of MAX Jobs
|-
|INTERNAL_ERROR  || System Meta pointer is NULL or
                    System Meta pointer start sentinel is corrupt
|-
|INVALID_ID      || Failed on task ID check
|-
|INVALID_NAME    || Task ID is already in use
|-
|INVALID_PRIORITY || Failed on task priority check
|-
|INVALID_NUMBER  || Failed on task threshold check
|-
|INVALID_SIZE    || Failed on task max job check
|-
|SUCCESSFUL      || All is OK
|}
<span style="color:#1b7ac2">'''Example Usage'''</span><br>
<syntaxhighlight lang="C">
enum TASK_NAME{
    t_tom,                      // will have task ID 0
    t_dick,                    // will have task ID 1
};
extern int task_tom_start(void* data);
...
enum DIRECTIVE_STATUS status;
    // Task 0: priority 10, max jobs 1, enabled (consumer task)
    status  = oceos_task_create(t_tom, // unique, 0 to TASKS_MAX_ID 
                              10, // TASK_MAX_PRIORITY to TASK_MIN_PRIORITY
  10, // TASK_MAX_PRIORITY to priority
    1, // 1 to JOBS_MAX
    0, // whether uses floating point hardware
        TASK_ENABLED, // whether task enabled initially
      task_tom_start, // task start address
        NULL, // start of task end function
            0, // maximum time to complete (ignore if 0)
            0  // minimum time between start requests
                    );   
</syntaxhighlight>
</blockquote>
===<span style="color:#0000ff">oceos_task_start()</span>===
<blockquote style="border-left-style: none;">
<span style="color:#1b7ac2">'''Header File'''</span><br>
'''''tasks.h'''''<br>
<span style="color:#1b7ac2">'''Description'''</span><br>
Starting a task involves three main stages:<br> 
* Setting up a job
**Finding a free job entry
**Setting up this entry
* Placing the job on ready queue
* Doing a context switch
This function should only be called after OCEOS is initialized and the dynamic task and job structures are set up.
When used from an interrupt handler, the context switch is only done after all nested interrupts have unwound.
<blockquote style="background-color: #c6e2f7; border-left-style: solid; border-left-width: 3px; border-left-color: blue; "> '''Note'''<br>
'''FOR SPARC ONLY : Tasks can be started in IRQ routines but CANNOT be started in TRAP handlers'''.
</blockquote>
<span style="color:#1b7ac2">'''Prototype'''</span><br>
<syntaxhighlight lang="C">
enum DIRECTIVE_STATUS  oceos_task_start(
    const unsigned int taskID, // task ID, must be in range 0 to 254
    void * const ptr          // pointer to data
);
</syntaxhighlight>
<span style="color:#1b7ac2">'''Parameters'''</span><br>
{| class="wikitable"
|-
! Parameter !! Description
|-
| taskID || Task ID must be in range 0 to 254
|-
| ptr    || Pointer to task data
|}
<span style="color:#1b7ac2">'''Returns'''</span><br>
This function returns enum DIRECTIVE_STATUS.<br>
{| class="wikitable"
|-
! enum DIRECTIVE_STATUS !! Description
|-
|NOT_CONFIGURED            ||System Meta pointer is NULL or Fixed data start sentinel is corrupt
|-                         
|INCORRECT_STATE            || One of the System Meta pointers is NULL
|-                         
|INVALID_ID                || Failed on task ID check
|-                         
|INCORRECT_STATE            || Tried to start disabled task
|-                         
|TOO_MANY                  || Max number of jobs(requests to start) for task is exceeded
|-                         
|FAILED_TO_PUT_JOB_ON_REDYQ || Failed to put job for task on ready Q
|-                         
|SUCCESSFUL                || All is OK
|}
<span style="color:#1b7ac2">'''Example Usage'''</span><br>
<syntaxhighlight lang="C">
enum TASK_NAME{
    t_tom,                      // will have task ID 0
    t_dick,                    // will have task ID 1
};
...
enum DIRECTIVE_STATUS status;
status = oceos_task_start(t_tom, NULL);
if (SUCCESS != status) {
  // Deal with the problem
  return status;
}
</syntaxhighlight>
</blockquote>
===<span style="color:#0000ff">oceos_task_timed_start()</span>===
<blockquote style="border-left-style: none;">
<span style="color:#1b7ac2">'''Header File'''</span><br>
'''''tasks.h'''''<br>
<span style="color:#1b7ac2">'''Description'''</span><br>
Schedule a task to start execution at a given system time.<br>
The before and after offsets define a window around the selected time in which the task may be started.<br>
If the current system time is before the start window a job is created and a corresponding action put on the timed action queue.<br>
If the current system time is within the time window for starting the task, it is started immediately.<br>
If the current system time is after the window, an error is reported.<br>
return_job_id can be stored and used later to cancel if need.<br>
Times are in microseconds.<br>
This function should only be used after [[OCEOS/oceos kernel/initialisation#oceos_start()|oceos_start()]] is called.
<blockquote style="background-color: #c6e2f7; border-left-style: solid; border-left-width: 3px; border-left-color: blue; "> '''Note'''<br>
This directive can only be called if timed actions (software timers) are initialized. Please see [[OCEOS/oceos timed actions|'''HERE''']].
</blockquote>
<span style="color:#1b7ac2">'''Prototype'''</span><br>
<syntaxhighlight lang="C">
enum DIRECTIVE_STATUS oceos_task_timed_start(
    const unsigned int taskID,// Task ID
    void * const ptr,        // data to be used by task
    U64_t start_time,        // system time at which task should start
    U32_t before,            // offset before time in which start o.k.
    U32_t after,              // offset after time in which start o.k.
    U32_t *return_job_id      // in case need to cancel later
);
</syntaxhighlight>
<span style="color:#1b7ac2">'''Parameters'''</span><br>
{| class="wikitable"
|-
! Parameter !! Description
|-
|taskID        || Task ID must be in range 0 to 254
|-
|ptr          || Pointer to data
|-
|start_time    || System time at which job should start
|-
|before        || Forward tolerance for time
|-
|after        || Backward tolerance for time
|-
|return_job_id || Return job_id to the user, to remove this job from timed action if needed
|}
<span style="color:#1b7ac2">'''Returns'''</span><br>
This function returns enum DIRECTIVE_STATUS.<br>
{| class="wikitable"
|-
! enum DIRECTIVE_STATUS !! Description
|-
|NOT_CONFIGURED  || System Meta pointer is NULL or
Fixed data start sentinel is corrupt
|-
|INCORRECT_STATE || One of the System Meta pointers is NULL or
System time is not initialized or
Tried to start disabled task
|-
|INVALID_ID      || Failed on task ID check
|-
|UNSATISFIED    || System time is greater when start time plus after time
|-
|TOO_MANY        || Max number of jobs(requests to start) for task is exceeded
|-
|INTERNAL_ERROR  || Failed to put job for task on ready Q
|-
|SUCCESSFUL      || All is OK
|}
<span style="color:#1b7ac2">'''Example Usage'''</span><br>
<syntaxhighlight lang="C">
enum TASK_NAME{
    t_tom,                      // will have task ID 0
    t_dick,                    // will have task ID 1
};
...
enum DIRECTIVE_STATUS status;
U32_t return_job_id = 0;
U64_t time = oceos_time_sys_get64();
status = oceos_task_timed_start(t_tom, // Task ID must be in range 0 to 254
                                NULL, // Pointer to data
                      time + 1000000, // System time at which job should start
                                1000, // Forward tolerance for time
                                1000, // Backward tolerance for time
                      &return_job_id  // Return job_id to the user, to remove this job from timed action if needed
                                    );
if (SUCCESS != status) {
  // Handle ERROR
  return status;
</syntaxhighlight>
</blockquote>
===<span style="color:#0000ff">oceos_task_disable()</span>===
<blockquote style="border-left-style: none;">
<span style="color:#1b7ac2">'''Header File'''</span><br>
'''''tasks.h'''''<br>
<span style="color:#1b7ac2">'''Description'''</span><br>
Disable a task and remove any current pending jobs on ready queue. A disabled task's jobs will not be put into execution nor put on ready queue.
<blockquote style="background-color: #c6e2f7; border-left-style: solid; border-left-width: 3px; border-left-color: blue; "> '''Note'''<br>
If execution of a task has already commenced, disabling the task will not prevent it from completing.
</blockquote>
<span style="color:#1b7ac2">'''Prototype'''</span><br>
<syntaxhighlight lang="C">
enum DIRECTIVE_STATUS  oceos_task_disable(
    const unsigned int taskID // task ID, must be in range 0 to 254
);
</syntaxhighlight>
<span style="color:#1b7ac2">'''Parameters'''</span><br>
{| class="wikitable"
|-
! Parameter !! Description
|-
| taskID || Task ID must be in range 0 to 254
|}
<span style="color:#1b7ac2">'''Returns'''</span><br>
This function returns enum DIRECTIVE_STATUS.<br>
{| class="wikitable"
|-
! enum DIRECTIVE_STATUS !! Description
|-
|NOT_CONFIGURED    || System Meta pointer is NULL or
Fixed data start sentinel is corrupt
|-
|INTERNAL_ERROR    || One of the System Meta pointers is NULL or
Dynamic Meta pointer is NULL
|-
|INVALID_ID        || Failed on task ID check
|-
|ALREADY_SUSPENDED  || Task is already disabled
|-
|SUCCESSFUL        || All is OK
|}
<span style="color:#1b7ac2">'''Example Usage'''</span><br>
<syntaxhighlight lang="C">
enum TASK_NAME{
    t_tom,                      // will have task ID 0
    t_dick,                    // will have task ID 1
};
...
enum DIRECTIVE_STATUS status;
status =  oceos_task_disable(t_tom);
if (SUCCESS != status) {
  // Deal with the problem
  return status;
}
</syntaxhighlight>
</blockquote>
===<span style="color:#0000ff">oceos_task_enable()</span>===
<blockquote style="border-left-style: none;">
<span style="color:#1b7ac2">'''Header File'''</span><br>
'''''tasks.h'''''<br>
<span style="color:#1b7ac2">'''Description'''</span><br>
Enable a task - only enabled tasks are placed on ready queue or started.<br>
<span style="color:#1b7ac2">'''Prototype'''</span><br>
<syntaxhighlight lang="C">
enum DIRECTIVE_STATUS  oceos_task_enable(
    const unsigned int taskID  // task ID, must be in range 0 to 254
);
</syntaxhighlight>
<span style="color:#1b7ac2">'''Parameters'''</span><br>
{| class="wikitable"
|-
! Parameter !! Description
|-
| taskID || Task ID must be in range 0 to 254
|}
<span style="color:#1b7ac2">'''Returns'''</span><br>
This function returns enum DIRECTIVE_STATUS.<br>
{| class="wikitable"
|-
! enum DIRECTIVE_STATUS !! Description
|-
|NOT_CONFIGURED    || System Meta pointer is NULL or
Fixed data start sentinel is corrupt
|-
|INCORRECT_STATE    || One of the System Meta pointers is NULL
|-
|INTERNAL_ERROR    || Dynamic Meta pointer is NULL
|-
|INVALID_ID        || Failed on task ID check
|-
|ALREADY_SUSPENDED  || Task is already disabled
|-
|SUCCESSFUL        || All is OK
|}
<span style="color:#1b7ac2">'''Example Usage'''</span><br>
<syntaxhighlight lang="C">
enum TASK_NAME{
    t_tom,                      // will have task ID 0
    t_dick,                    // will have task ID 1
};
...
enum DIRECTIVE_STATUS status;
status =  oceos_task_enable(t_tom);
if (SUCCESS != status) {
  // Deal with the problem
  return status;
</syntaxhighlight>
</blockquote>
===<span style="color:#0000ff">oceos_task_self()</span>===
<blockquote style="border-left-style: none;">
<span style="color:#1b7ac2">'''Header File'''</span><br>
'''''tasks.h'''''<br>
<span style="color:#1b7ac2">'''Description'''</span><br>
Get the task ID of the current job
<span style="color:#1b7ac2">'''Prototype'''</span><br>
<syntaxhighlight lang="C">
unsigned int  oceos_task_self();
</syntaxhighlight>
<span style="color:#1b7ac2">'''Parameters'''</span><br>
{| class="wikitable"
|-
! Parameter !! Description
|-
|  ||
|}
<span style="color:#1b7ac2">'''Returns'''</span><br>
This function returns enum DIRECTIVE_STATUS.<br>
{| class="wikitable"
|-
! unsigned int !! Description
|-
| ID              || Task ID of currently executing job
|-
| TASK_ID_INVALID || ERROR
|}
<span style="color:#1b7ac2">'''Example Usage'''</span><br>
<syntaxhighlight lang="C">
  U32_t id;
  id = oceos_task_self();
  if (TASK_ID_INVALID == id) {
    // Handle ERROR
  } 
</syntaxhighlight>
</blockquote>
===<span style="color:#0000ff">oceos_task_get_priority()</span>===
<blockquote style="border-left-style: none;">
<span style="color:#1b7ac2">'''Header File'''</span><br>
'''''tasks.h'''''<br>
<span style="color:#1b7ac2">'''Description'''</span><br>
Get priority of a task. The higher number is lower priority. 
<span style="color:#1b7ac2">'''Prototype'''</span><br>
<syntaxhighlight lang="C">
U8_t  oceos_task_get_priority(
    const unsigned int taskID  // task ID, must be in range 0 to 254
);
</syntaxhighlight>
<span style="color:#1b7ac2">'''Parameters'''</span><br>
{| class="wikitable"
|-
! Parameter !! Description
|-
| taskID  || Task ID must be in range 0 to 254
|}
<span style="color:#1b7ac2">'''Returns'''</span><br>
This function returns U8_t.<br>
{| class="wikitable"
|-
! U8_t  !! Description
|-
| priority            || Priority of the given task ID
|-
| TASK_INVALID_PRIORITY|| ERROR
|}
<span style="color:#1b7ac2">'''Example Usage'''</span><br>
<syntaxhighlight lang="C">
enum TASK_NAME{
    t_tom,                      // will have task ID 0
    t_dick,                    // will have task ID 1
};
...
  U32_t priority;
  priority = oceos_task_get_priority(t_tom);
  if (TASK_INVALID_PRIORITY == priority ) {
    // Handle ERROR
  }     
</syntaxhighlight>
</blockquote>
===<span style="color:#0000ff">oceos_task_get_status()</span>===
<blockquote style="border-left-style: none;">
<span style="color:#1b7ac2">'''Header File'''</span><br>
'''''tasks.h'''''<br>
<span style="color:#1b7ac2">'''Description'''</span><br>
Get status of a task.
<span style="color:#1b7ac2">'''Prototype'''</span><br>
<syntaxhighlight lang="C">
enum TASK_STATUS  oceos_task_get_status(
    const unsigned int taskID // task ID, must be in range 0 to 254
);
</syntaxhighlight>
<span style="color:#1b7ac2">'''Parameters'''</span><br>
{| class="wikitable"
|-
! Parameter !! Description
|-
| taskID  || Task ID must be in range 0 to 254
|}
<span style="color:#1b7ac2">'''Returns'''</span><br>
This function returns enum TASK_STATUS.<br>
{| class="wikitable"
|-
! enum TASK_STATUS!! Description
|-
|TASK_DISABLED  ||Cannot be scheduled, and no current jobs
|-             
|TASK_ENABLED  ||Can be scheduled, but no current jobs
|-             
|TASK_INVALID  ||Task does not exist
|}
<span style="color:#1b7ac2">'''Example Usage'''</span><br>
<syntaxhighlight lang="C">
enum TASK_NAME{
    t_tom,                      // will have task ID 0
    t_dick,                    // will have task ID 1
};
...
enum TASK_STATUS status;
status = oceos_task_get_status(t_tom);
if (TASK_ENABLED == status) {
    // Do Something
} else if (TASK_DISABLED == status) {
    // Do Something
} else {
  // Handle ERROR
</syntaxhighlight>
</blockquote>
===<span style="color:#0000ff">oceos_task_kill()</span>===
<blockquote style="border-left-style: none;">
<span style="color:#1b7ac2">'''Header File'''</span><br>
'''''tasks.h'''''<br>
<span style="color:#1b7ac2">'''Description'''</span><br>
Directive to terminate current task when undesired behavior was detected.<br>
Current task is terminated and back to scheduler. This task can be restarted later.<br>
If oceos_task_kill() is called from IRQ handler, the task is terminated when IRQ nesting is unraveled.<br>
The user provided '''end_function''' for this task when created with [[OCEOS/oceos kernel/task#oceos_task_create()|oceos_task_create()]] is called from the scheduler.<br>
OCEOS can only kill the current job due to its single stack design. Application scenarios where this directive could be used include:<br>
* Application regular interrupt checking job status<br>
If such an application interrupt detected an error in the current job it can call oceos_task_kill() as part of its recovery actions.
* oceos_on_error()<br>
OCEOS calls oceos_on_error(<span style="color:red">TODO ADD THE LINK TO DESCRIPTION OF THIS FUNCTION</span>) in the case of a system error. This is user implemented function where application recovery code is located.<br>
oceos_task_kill() is a possible directive to be used as part of error recovery.
<span style="color:#1b7ac2">'''Prototype'''</span><br>
<syntaxhighlight lang="C">
enum DIRECTIVE_STATUS        oceos_task_kill();
</syntaxhighlight>
<span style="color:#1b7ac2">'''Parameters'''</span><br>
{| class="wikitable"
|-
! Parameter !! Description
|-
|  ||
|}
<span style="color:#1b7ac2">'''Returns'''</span><br>
This function returns enum DIRECTIVE_STATUS.<br>
{| class="wikitable"
|-
! enum DIRECTIVE_STATUS !! Description
|-
|NOT_CONFIGURED      || System Meta pointer is NULL or
Fixed data start sentinel is corrupt
|-
|INCORRECT_STATE    || Called while initialisation is ongoing or
Scheduling is not started
|-
|INTERNAL_ERROR      || Dynamic Meta pointer is NULL
|-
|SUCCESSFUL          || All is OK (only return this if was called from IRQ handler)
|}
<span style="color:#1b7ac2">'''Example Usage'''</span><br>
<syntaxhighlight lang="C">
enum DIRECTIVE_STATUS status;
status = oceos_task_kill();
  if (SUCCESSFUL != status ) {
      // Handle ERROR
  } 
</syntaxhighlight>
</blockquote>
===<span style="color:#0000ff">oceos_task_get_info()</span>===
<blockquote style="border-left-style: none;">
<span style="color:#1b7ac2">'''Header File'''</span><br>
'''''tasks.h'''''<br>
<span style="color:#1b7ac2">'''Description'''</span><br>
Get task information for task with ID.<br>
User must pass pointer to struct task_info in order to retrieve data.
<span style="color:#1b7ac2">'''Prototype'''</span><br>
<syntaxhighlight lang="C">
enum DIRECTIVE_STATUS oceos_task_get_info (
    const unsigned int Task,  // Task ID
    struct task_info *info    // Pointer to struct task_info
);
</syntaxhighlight>
<span style="color:#1b7ac2">'''Parameters'''</span><br>
{| class="wikitable"
|-
! Parameter !! Description
|-
| task_id || Task ID
|-
| info    || Pointer to struct task_info
|}
<span style="color:#1b7ac2">'''Returns'''</span><br>
This function returns enum DIRECTIVE_STATUS.<br>
{| class="wikitable"
|-
! enum DIRECTIVE_STATUS !! Description
|-
|NOT_CONFIGURED      || System Meta pointer is NULL or
Fixed data start sentinel is corrupt
|-
|INCORRECT_STATE    || Called while initialisation is ongoing
|-
|INTERNAL_ERROR      || Dynamic Meta pointer is NULL
|-
|INVALID_ID          || Failed on task ID check
|-
|NOT_DEFINED        || Pointer to task_info is NULL
|-
|SUCCESSFUL          || All is OK and data is valid
|}
<span style="color:#1b7ac2">'''Example Usage'''</span><br>
<syntaxhighlight lang="C">
/**
* task info to be used with oceos_task_get_info
*/
struct task_info {
    unsigned int    jobs_current_max  :16;        // maximum number of current jobs for this task, no roll over, can be reset
    unsigned int    jobs_total        :16;        // number of times this task was started, no roll-over, can be reset
    unsigned int    jobs_current;                // Number of task instances currently in use by oceos
    U32_t          time_max_delay;              // maximum time job is waiting on ready queue before becoming active
    U32_t          time_max_finish;              // maximum time to finish job execution after starting
    U32_t          time_max_exec;                // maximum time spent executing
    U32_t          time_total_exec_low;          // total CPU time used by this task low bits
    U32_t          time_total_exec_high;        // total CPU time used by this task high bits
    U32_t          time_min_gap_starts;          // minimum time between job creations, can be reset
    U32_t          time_min_gap_finish_start;    // minimum time between job ending and new job creation, can be reset
    U32_t          time_last_start;              // time of most recent job creation
    U32_t          time_last_finish;            // time of most recent job finish
    U32_t          preempt_max;                  // maximum times any job was pre-empted, no roll-over, can be reset
};
enum TASK_NAME{
    t_tom,                      // will have task ID 0
    t_dick,                    // will have task ID 1
};
...
struct task_info info;
enum DIRECTIVE_STATUS status;
status = oceos_task_get_info(t_tom, &info);
if (SUCCESS != status) {
  // Deal with the problem
  return status;
}
</syntaxhighlight>
</blockquote>

Latest revision as of 09:53, 24 March 2022

OCEOS Task

Task Introduction

In OCEOS all tasks are defined before scheduling begins and each task assigned a fixed priority, a pre-emption threshold, a current jobs limit, a maximum start to completion time, and an expected minimum inter start request time. A task’s pre-emption threshold limits the tasks that can pre-empt it to those with higher priority than this threshold. Tasks with short run times can use this to avoid context switch overheads. Each task has two main states, enabled or disabled. OCEOS provides system calls to change task state. The state is usually enabled when the task is created, but can be initially disabled. A disabled task will not be executed, and any attempt to start it will be logged and the system state variable updated.
A request to start an enabled task creates an execution instance of the task, a ‘job’. A count is kept for each task of the number of times it has been started, i.e. total number of jobs created. Multiple jobs of the same task can be in existence simultaneously. A limit for the maximum number of these current jobs is set when a task is created, the ‘current jobs limit’. Each task has a current jobs count. This increments each time a task is started and decrements on job completion unless completion creates a further job from this task. A further execution instance of a task is not created if the current jobs count has reached the current jobs limit. Such job creation failures are logged and the system state updated. For each task a record is kept of the shortest time between attempts to create a new job, and a record of the maximum time between these attempts. For each task a record is kept also of the maximum time a job was waiting before starting, the minimum execution time, the maximum execution time, the maximum time from job creation to completion, and the maximum number of job pre-emptions. The system state variable is updated if necessary.
Task chaining is supported. A job can create a new job and pass this to the scheduler or place it on the timed actions queue .
Tasks provide a start address for a termination routine for use if task execution must be abandoned.

Note

All Tasks must be created before oceos_init_finish() is called.

Task Configuration

User must define NUMBER_OF_TASKS. The example can be found in OCEOS demo projects.
User must create defined number of tasks before calling oceos_init_finish()

    #define NUMBER_OF_TASKS 2
    /*
     * Create the application configuration structure
     */
    struct application_configuration           app_config = {0};
    app_config.number_of_tasks               = NUMBER_OF_TASKS;               // >= 1

User must define NUMBER_OF_READYQ_ENTRIES. The example can be found in OCEOS demo projects.
Number of ready queue entries, 0 to 254. Defaults to number of tasks, as each task should have at least one job. If Number of ready queue entries is larger that number of total jobs it defaults to number of total jobs

    #define NUMBER_OF_READYQ_ENTRIES 5
    /*
     * Create the application configuration structure
     */
    struct application_configuration           app_config = {0};
    app_config.number_of_readyQ_entries      = NUMBER_OF_READYQ_ENTRIES;      // 0 => calculate size

API Functions

API Functions
Directive Description main task IRQ handler
oceos_task_create() Create Task *
oceos_task_start() Start Task * *
oceos_task_timed_start() Schedule a task to start execution at a given system time * *
oceos_task_disable() Disable Task * *
oceos_task_enable() Enable Task * *
oceos_task_self() Returns the task ID of the currently executing task * *
oceos_task_get_priority() Get priority of a task * *
oceos_task_get_status() Get status of a task * *
oceos_task_kill() Directive to terminate current task * *
oceos_task_get_info() Get task information * *

oceos_task_create()

Header File
tasks.h

Description
Create a task. Can only be use before OCEOS starts. Stores the task information in the OCEOS fixed data area. This directive populates the data structures for a task. It should be called after oceos_init() and before oceos_init_finish().
It must be called for each task otherwise oceos_start() will return an error.

Prototype

enum DIRECTIVE_STATUS   oceos_task_create(
    unsigned int taskID,         // unique, 0 to TASKS_MAX_ID
    U32_t priority,              // TASK_MAX_PRIORITY to TASK_MIN_PRIORITY
    U32_t threshold,             // TASK_MAX_PRIORITY to priority
    U32_t jobs_max,              // 1 to JOBS_MAX
    BOOLE_t FP_used,             // whether uses floating point hardware
    BOOLE_t initially_enabled,   // whether task enabled initially
    void (void *) start_function,// task start address
    void (void *) end_function,  // start of task end function
    U32_t time_deadline,         // maximum time to complete (ignore if 0)
    U32_t time_mininterstart     // minimum time between start requests
 );

Parameters

Parameter Description
taskID Unique task ID from 0 to TASKS_MAX_ID
priority TASK_MAX_PRIORITY to TASK_MIN_PRIORITY
threshold TASK_MAX_PRIORITY to priority
jobs_max Number of 1 to JOBS_MAX
FP_used whether uses floating point hardware
initially_enabled whether task enabled initially
start_function task start address
end_function start of task end function
time_deadline maximum time to complete (ignore if 0)
time_mininterstart minimum time between start requests

Returns
This function returns enum DIRECTIVE_STATUS.

enum DIRECTIVE_STATUS Description
INCORRECT_STATE Init Meta Pointer is NULL or

Pointer to Task fixed data is NULL

TOO_MANY Exceeds number of MAX Tasks or

Exceeds number of MAX Jobs

INTERNAL_ERROR System Meta pointer is NULL or

System Meta pointer start sentinel is corrupt

INVALID_ID Failed on task ID check
INVALID_NAME Task ID is already in use
INVALID_PRIORITY Failed on task priority check
INVALID_NUMBER Failed on task threshold check
INVALID_SIZE Failed on task max job check
SUCCESSFUL All is OK

Example Usage

 enum TASK_NAME{
    t_tom,                      // will have task ID 0
    t_dick,                     // will have task ID 1
 };
 extern int task_tom_start(void* data);
 ...
 enum DIRECTIVE_STATUS status;
    // Task 0: priority 10, max jobs 1, enabled (consumer task)
    status  = oceos_task_create(t_tom, // unique, 0 to TASKS_MAX_ID  
	                               10, // TASK_MAX_PRIORITY to TASK_MIN_PRIORITY
								   10, // TASK_MAX_PRIORITY to priority
								    1, // 1 to JOBS_MAX
								    0, // whether uses floating point hardware
				         TASK_ENABLED, // whether task enabled initially
				       task_tom_start, // task start address
						         NULL, // start of task end function
						            0, // maximum time to complete (ignore if 0)
						            0  // minimum time between start requests
				                    );

oceos_task_start()

Header File
tasks.h

Description
Starting a task involves three main stages:

  • Setting up a job
    • Finding a free job entry
    • Setting up this entry
  • Placing the job on ready queue
  • Doing a context switch

This function should only be called after OCEOS is initialized and the dynamic task and job structures are set up.

When used from an interrupt handler, the context switch is only done after all nested interrupts have unwound.

Note

FOR SPARC ONLY : Tasks can be started in IRQ routines but CANNOT be started in TRAP handlers.

Prototype

enum DIRECTIVE_STATUS   oceos_task_start(
    const unsigned int taskID, // task ID, must be in range 0 to 254
    void * const ptr           // pointer to data
 );

Parameters

Parameter Description
taskID Task ID must be in range 0 to 254
ptr Pointer to task data

Returns
This function returns enum DIRECTIVE_STATUS.

enum DIRECTIVE_STATUS Description
NOT_CONFIGURED System Meta pointer is NULL or Fixed data start sentinel is corrupt
INCORRECT_STATE One of the System Meta pointers is NULL
INVALID_ID Failed on task ID check
INCORRECT_STATE Tried to start disabled task
TOO_MANY Max number of jobs(requests to start) for task is exceeded
FAILED_TO_PUT_JOB_ON_REDYQ Failed to put job for task on ready Q
SUCCESSFUL All is OK

Example Usage

 enum TASK_NAME{
    t_tom,                      // will have task ID 0
    t_dick,                     // will have task ID 1
 };
 ...
 enum DIRECTIVE_STATUS status;
 status = oceos_task_start(t_tom, NULL); 
 if (SUCCESS != status) {
  // Deal with the problem
  return status;
 }

oceos_task_timed_start()

Header File
tasks.h

Description
Schedule a task to start execution at a given system time.
The before and after offsets define a window around the selected time in which the task may be started.
If the current system time is before the start window a job is created and a corresponding action put on the timed action queue.
If the current system time is within the time window for starting the task, it is started immediately.
If the current system time is after the window, an error is reported.
return_job_id can be stored and used later to cancel if need.
Times are in microseconds.
This function should only be used after oceos_start() is called.

Note

This directive can only be called if timed actions (software timers) are initialized. Please see HERE.

Prototype

enum DIRECTIVE_STATUS oceos_task_timed_start(
    const unsigned int taskID,// Task ID
    void * const ptr,         // data to be used by task
    U64_t start_time,         // system time at which task should start
    U32_t before,             // offset before time in which start o.k.
    U32_t after,              // offset after time in which start o.k.
    U32_t *return_job_id      // in case need to cancel later
);

Parameters

Parameter Description
taskID Task ID must be in range 0 to 254
ptr Pointer to data
start_time System time at which job should start
before Forward tolerance for time
after Backward tolerance for time
return_job_id Return job_id to the user, to remove this job from timed action if needed

Returns
This function returns enum DIRECTIVE_STATUS.

enum DIRECTIVE_STATUS Description
NOT_CONFIGURED System Meta pointer is NULL or

Fixed data start sentinel is corrupt

INCORRECT_STATE One of the System Meta pointers is NULL or

System time is not initialized or Tried to start disabled task

INVALID_ID Failed on task ID check
UNSATISFIED System time is greater when start time plus after time
TOO_MANY Max number of jobs(requests to start) for task is exceeded
INTERNAL_ERROR Failed to put job for task on ready Q
SUCCESSFUL All is OK

Example Usage

enum TASK_NAME{
    t_tom,                      // will have task ID 0
    t_dick,                     // will have task ID 1
};
...
enum DIRECTIVE_STATUS status;
U32_t return_job_id = 0;
U64_t time = oceos_time_sys_get64();
status = oceos_task_timed_start(t_tom, // Task ID must be in range 0 to 254
                                 NULL, // Pointer to data
                       time + 1000000, // System time at which job should start
                                 1000, // Forward tolerance for time
                                 1000, // Backward tolerance for time
                       &return_job_id  // Return job_id to the user, to remove this job from timed action if needed
                                    );
if (SUCCESS != status) {
  // Handle ERROR
  return status;
}

oceos_task_disable()

Header File
tasks.h

Description
Disable a task and remove any current pending jobs on ready queue. A disabled task's jobs will not be put into execution nor put on ready queue.

Note

If execution of a task has already commenced, disabling the task will not prevent it from completing.

Prototype

enum DIRECTIVE_STATUS   oceos_task_disable(
    const unsigned int taskID // task ID, must be in range 0 to 254
 );

Parameters

Parameter Description
taskID Task ID must be in range 0 to 254

Returns
This function returns enum DIRECTIVE_STATUS.

enum DIRECTIVE_STATUS Description
NOT_CONFIGURED System Meta pointer is NULL or

Fixed data start sentinel is corrupt

INTERNAL_ERROR One of the System Meta pointers is NULL or

Dynamic Meta pointer is NULL

INVALID_ID Failed on task ID check
ALREADY_SUSPENDED Task is already disabled
SUCCESSFUL All is OK

Example Usage

 enum TASK_NAME{
    t_tom,                      // will have task ID 0
    t_dick,                     // will have task ID 1
 };
 ...
 enum DIRECTIVE_STATUS status;
 status =  oceos_task_disable(t_tom); 
 if (SUCCESS != status) {
  // Deal with the problem
  return status;
 }

oceos_task_enable()

Header File
tasks.h

Description
Enable a task - only enabled tasks are placed on ready queue or started.

Prototype

enum DIRECTIVE_STATUS   oceos_task_enable(
    const unsigned int taskID  // task ID, must be in range 0 to 254
 );

Parameters

Parameter Description
taskID Task ID must be in range 0 to 254

Returns
This function returns enum DIRECTIVE_STATUS.

enum DIRECTIVE_STATUS Description
NOT_CONFIGURED System Meta pointer is NULL or

Fixed data start sentinel is corrupt

INCORRECT_STATE One of the System Meta pointers is NULL
INTERNAL_ERROR Dynamic Meta pointer is NULL
INVALID_ID Failed on task ID check
ALREADY_SUSPENDED Task is already disabled
SUCCESSFUL All is OK

Example Usage

 enum TASK_NAME{
    t_tom,                      // will have task ID 0
    t_dick,                     // will have task ID 1
 };
 ...
 enum DIRECTIVE_STATUS status;
 status =  oceos_task_enable(t_tom); 
 if (SUCCESS != status) {
  // Deal with the problem
  return status;
 }

oceos_task_self()

Header File
tasks.h

Description
Get the task ID of the current job

Prototype

unsigned int  oceos_task_self();

Parameters

Parameter Description

Returns
This function returns enum DIRECTIVE_STATUS.

unsigned int Description
ID Task ID of currently executing job
TASK_ID_INVALID ERROR

Example Usage

  U32_t id;
  id = oceos_task_self();
  if (TASK_ID_INVALID == id) {
    // Handle ERROR
  }

oceos_task_get_priority()

Header File
tasks.h

Description
Get priority of a task. The higher number is lower priority.

Prototype

 U8_t  oceos_task_get_priority(
    const unsigned int taskID   // task ID, must be in range 0 to 254
 );

Parameters

Parameter Description
taskID Task ID must be in range 0 to 254

Returns
This function returns U8_t.

U8_t Description
priority Priority of the given task ID
TASK_INVALID_PRIORITY ERROR

Example Usage

 enum TASK_NAME{
    t_tom,                      // will have task ID 0
    t_dick,                     // will have task ID 1
 };
 ...
  U32_t priority;
  priority = oceos_task_get_priority(t_tom);
  if (TASK_INVALID_PRIORITY == priority ) {
    // Handle ERROR
  }

oceos_task_get_status()

Header File
tasks.h

Description
Get status of a task.

Prototype

enum TASK_STATUS  oceos_task_get_status(
    const unsigned int taskID // task ID, must be in range 0 to 254
 );

Parameters

Parameter Description
taskID Task ID must be in range 0 to 254

Returns
This function returns enum TASK_STATUS.

enum TASK_STATUS Description
TASK_DISABLED Cannot be scheduled, and no current jobs
TASK_ENABLED Can be scheduled, but no current jobs
TASK_INVALID Task does not exist

Example Usage

 enum TASK_NAME{
    t_tom,                      // will have task ID 0
    t_dick,                     // will have task ID 1
 };
 ...
 enum TASK_STATUS status;
 status = oceos_task_get_status(t_tom);
 if (TASK_ENABLED == status) {
    // Do Something
 } else if (TASK_DISABLED == status) {
    // Do Something
 } else {
   // Handle ERROR
 }

oceos_task_kill()

Header File
tasks.h

Description
Directive to terminate current task when undesired behavior was detected.
Current task is terminated and back to scheduler. This task can be restarted later.
If oceos_task_kill() is called from IRQ handler, the task is terminated when IRQ nesting is unraveled.
The user provided end_function for this task when created with oceos_task_create() is called from the scheduler.
OCEOS can only kill the current job due to its single stack design. Application scenarios where this directive could be used include:

  • Application regular interrupt checking job status

If such an application interrupt detected an error in the current job it can call oceos_task_kill() as part of its recovery actions.

  • oceos_on_error()

OCEOS calls oceos_on_error(TODO ADD THE LINK TO DESCRIPTION OF THIS FUNCTION) in the case of a system error. This is user implemented function where application recovery code is located.
oceos_task_kill() is a possible directive to be used as part of error recovery.

Prototype

enum DIRECTIVE_STATUS        oceos_task_kill();

Parameters

Parameter Description

Returns
This function returns enum DIRECTIVE_STATUS.

enum DIRECTIVE_STATUS Description
NOT_CONFIGURED System Meta pointer is NULL or

Fixed data start sentinel is corrupt

INCORRECT_STATE Called while initialisation is ongoing or

Scheduling is not started

INTERNAL_ERROR Dynamic Meta pointer is NULL
SUCCESSFUL All is OK (only return this if was called from IRQ handler)

Example Usage

 enum DIRECTIVE_STATUS status;
 status = oceos_task_kill();
  if (SUCCESSFUL != status ) {
      // Handle ERROR
  }

oceos_task_get_info()

Header File
tasks.h

Description
Get task information for task with ID.
User must pass pointer to struct task_info in order to retrieve data.

Prototype

enum DIRECTIVE_STATUS oceos_task_get_info (
    const unsigned int Task,  // Task ID
    struct task_info *info    // Pointer to struct task_info
 );

Parameters

Parameter Description
task_id Task ID
info Pointer to struct task_info

Returns
This function returns enum DIRECTIVE_STATUS.

enum DIRECTIVE_STATUS Description
NOT_CONFIGURED System Meta pointer is NULL or

Fixed data start sentinel is corrupt

INCORRECT_STATE Called while initialisation is ongoing
INTERNAL_ERROR Dynamic Meta pointer is NULL
INVALID_ID Failed on task ID check
NOT_DEFINED Pointer to task_info is NULL
SUCCESSFUL All is OK and data is valid

Example Usage

 /**
 * task info to be used with oceos_task_get_info
 */
struct task_info {

    unsigned int    jobs_current_max  :16;        // maximum number of current jobs for this task, no roll over, can be reset
    unsigned int    jobs_total        :16;        // number of times this task was started, no roll-over, can be reset
    unsigned int    jobs_current;                 // Number of task instances currently in use by oceos
    U32_t           time_max_delay;               // maximum time job is waiting on ready queue before becoming active
    U32_t           time_max_finish;              // maximum time to finish job execution after starting
    U32_t           time_max_exec;                // maximum time spent executing
    U32_t           time_total_exec_low;          // total CPU time used by this task low bits
    U32_t           time_total_exec_high;         // total CPU time used by this task high bits
    U32_t           time_min_gap_starts;          // minimum time between job creations, can be reset
    U32_t           time_min_gap_finish_start;    // minimum time between job ending and new job creation, can be reset
    U32_t           time_last_start;              // time of most recent job creation
    U32_t           time_last_finish;             // time of most recent job finish
    U32_t           preempt_max;                  // maximum times any job was pre-empted, no roll-over, can be reset
};
 enum TASK_NAME{
    t_tom,                      // will have task ID 0
    t_dick,                     // will have task ID 1
 };
...
 struct task_info info;
 enum DIRECTIVE_STATUS status;
 status = oceos_task_get_info(t_tom, &info);
 if (SUCCESS != status) {
  // Deal with the problem
  return status;
 }