Starting and Ending Tasks


A user task on a CD can start on boot-up if it's named "LaunchMe." The operating system loads on boot-up and runs the executable code in LaunchMe, which starts a task that becomes the child of the shell-a user task. Once the user task is running, it can spawn child tasks in a manner similar to someone running a program from a terminal-the original user task uses a filesystem call to supply the filename of a file containing the executable code of a second task. The kernel launches the second task as a child of the first task.

Creating a Task

Each task is an item in the system. Tasks are created through the CreateItem() function call, a low-level call that returns the item number of the new task. (CreateItem() is discussed in Managing Items.)

Each task has a TCB (task control block) associated with it. The TCB data structure is created and maintained by the kernel; a user task can't write to the TCB directly. The settings of the various fields in the TCB are determined by the kind of task (privileged or non-privileged), the parameters passed to the kernel when the task is started, and changes made to the task while it runs. The kernel uses the TCB to allocate and control task resources, memory usage, and so on.

While you can create a task using CreateItem(), it's easier to use the following File folio calls which in turn call CreateItem():

Item LoadProgram( char *path )
Item LoadProgramPrio( char *path, int32 prio )

LoadProgram() launches a child task that has the same priority as the launching, or parent, task. The path argument for LoadProgram() contains the pathname for the file containing the executable code for the task. This parameter can also include arguments for the application, if arguments are required. Specifying the path argument is very much like specifying a program to run, with arguments, on a UNIX system.

LoadProgramPrio() allows you to specify a priority for the task. As with LoadProgram(), you include a path argument that specifies your program file and any arguments that you wish to pass to the task when it begins. The second argument, priority, specifies a new priority for the child task so it can run at a higher or lower priority than the parent task.

Both LoadProgram() and LoadProgramPrio() return the item number of the newly started task. Example 1 shows how to set up a text string for your program and launch it:

Example 1: Setting up a text string and launching it as a task.

char *cmdline = "mysrc/testprogram arg1 arg2"
Item    task_id
...
{
...
task_id = LoadProgram(cmdline);
...
}

Setting Priority

If you use LoadProgramPrio(), you should get the parent task's priority before setting up a new priority value for the child task. You can read the current task's priority by reading the n_Priority field of the ItemNode data structure that's embedded in the TCB of each task- CURRENTTASK->t.n_Priority as shown in Example 2:

Example 2: Getting a parent task's priority.

/* Determine the priority of the current task. */
Priority = CURRENTTASK->t.n_Priority;

The Life of a Task

Child tasks created through LoadProgram() or LoadProgramPrio() allocate completely separate memory areas for the parent task and its child tasks. Once a child task is launched, it remains in the system as an item until:

The launching task remains the owner of the child task throughout the life of the child task unless it passes ownership to another task.

Ending a Task

Typically, a child task ends when its parent task ends. It's good practice to end a child task, before the parent task quits, if you no longer need it to free up resources. To end a task, use DeleteItem(), passing in the task's item number. An error code (a negative number) is returned if an error occurs.

Err DeleteItem( Item i )
Alternatively, a child task can end itself by calling exit() or just return:

void exit (int status)
The function exit() never returns.

Note: The return or exit status can be passed on to the parent task through an exit message if the child was created with CREATETASK_TAG_MSGFROMCHILD.

Deleting the child task lets the kernel clean up all the task's allocated resources, freeing that space for other tasks.