Ptask Manual 0.4
ptask_manual_0.4
User Manual:
Open the PDF directly: View PDF
.
Page Count: 10
| Download | |
| Open PDF In Browser | View PDF |
Ptask Library: A Quick Guide
Giorgio Buttazzo and Giuseppe Lipari
RETIS Lab - Scuola Superiore Sant’Anna
Version 0.4
Summary
Ptask is a C-library for fast development of periodic and aperiodic real-time tasks under
Linux. It is written on top of the Pthread library with the aim of simplifying the creation of threads
with typical timing parameters, like periods and deadlines. Ptask functions allow programmers to
quickly
create periodic and aperiodic tasks;
specify timing constraints such periods and relative deadlines;
monitor deadline misses;
monitor average and worst-case execution times;
activate tasks with specific offsets;
manage task groups;
handle mode changes.
Table of contents
This document includes the following sections:
1.
New data types.
2.
System functions
3.
Task functions
4.
Measuring execution times
5.
Handling mode changes
6.
Examples
1.
New data types
The following new types are defined in the ptask library:
ptime
this is the type used for the time variables. It is basically a shortcut for a long
integer.
tspec
this type is used for specifying a precise time, and it is used by the library for internal
time representation. It is a shortcut for struct timespec. The Ptask library provides
appropriate functions to operate on tspec and to convert a ptime into a tspec, and
viceversa.
tpars
this type of structure i s u se d to store all task parameters and it is initialized at task
creation.
1
ptask
2.
this type is used for defining the task code. It is a shortcut for void.
System functions
void
ptask_init(int scheduler, int schedtype, int protocol);
Initializes the ptask library, resets the system time, set the scheduler for all the tasks and the
resource access protocol for all the semaphores.
scheduler
can be SCHED_OTHER, SCHED_FIFO, SCHED_RR, SCHED_DEADLINE.
schedtype
can be PARTITIONED or GLOBAL, and it is only useful for multicore systems.
protocol
can be NO_PROTOCOL for classical semaphores, INHERITANCE for Priority
Inheritance, or CEILING for Immediate Priority Ceiling.
Note (from version 0.4): in order to use SCHED_DEADLINE in PARTITIONED mode, the user has
first to disable the admission control in Linux. This can be done by invoking the script noadmission.sh (included in the distribution) with root privileges.
ptime
ptask_gettime(int unit);
Returns the current time (from the system start time) in the specified unit, which can be SEC,
MILLI, MICRO, or NANO.
int
ptask_getnumcores();
Returns the number of available cores in the system.
3.
Task functions
The Ptask library maintains a Task Control Block (TCB) for every task, used to store the task state,
the current task parameters, and some information collected about the task during its execution.
The content of the TCB is for internal use only, therefore it is not reported in this manual. Please
refer to the source code for more information.
int
ptask_create(void (*body)(void), int period, int prio, int flag);
Creates a concurrent task and returns the task index that can be used to differentiate multiple
instances of the same task. The arguments have the following meaning:
body
is the name of the function containing the task body;
period
specifies the task period (equal to the relative deadline) in milliseconds.
prio
specifies the task priority between 1 (low) and 99 (high);
flag
specifies the activation mode of the task (NOW or DEFERRED): if set to NOW, the
task is immediately activated; if set to DEFERRED, the task will block on the
wait_for_activation() until a ptask_activate() is invoked by another task.
If task creation cannot be performed or an error occurs, the function returns the value -1.
Note (from version 0.4): this function has been deprecated since 0.4 because it is not compatible
with the SCHED_DEADLINE scheduler.
2
int ptask_create_prio(void (*body)(void), int period, int prio,
int aflag);
Creates a concurrent task and returns the task index that can be used to differentiate multiple
instances of the same task. This function is supposed to be used with fixed priority scheduling
(SCHED_FIFO or SCHED_RR) only. The arguments have the following meaning:
body
is the name of the function containing the task body;
period
specifies the task period (equal to the relative deadline) in milliseconds.
prio
specifies the task priority between 1 (low) and 99 (high);
flag
specifies the activation mode of the task (NOW or DEFERRED): if set to NOW, the
task is immediately activated; if set to DEFERRED, the task will block on the
wait_for_activation() until a ptask_activate() is invoked by another task.
If task creation cannot be performed or an error occurs, the function returns the value -1.
Note: since version 0.4
int
ptask_create_edf(void (*task)(void), int period, int runtime,
int dline, int aflag);
Creates a concurrent task for the SCHED_DEADLINE scheduler, and returns the task index that
can be used to differentiate multiple instances of the same task. The arguments have the following
meaning:
body
is the name of the function containing the task body;
period
specifies the task period (equal to the relative deadline) in milliseconds;
runtime
specifies the budget of the task in milliseconds, it must be less than the period.;
dline
specifies the relative deadline of the task in milliseconds;
flag
specifies the activation mode of the task (NOW or DEFERRED): if set to NOW, the
task is immediately activated; if set to DEFERRED, the task will block on the
wait_for_activation() until a ptask_activate() is invoked by another task.
If task creation cannot be performed or an error occurs, the function returns the value -1.
In the current version of Linux (4.4), there is no way to create a task so that it is immediately
scheduled by SCHED_DEADLINE: the only possibility is to create the task with some other
scheduler (for example: SCHED_OTHER), and then modify its scheduling parameters once the
task has been created.
Since ptask uses the Linux API, function ptask_create_edf() will create the task in
SCHED_OTHER; when the task starts executing, it will change its scheduling parameters to
SCHED_DEADLINE. Therefore, it is recommended to leave the possibility for the task to get a
chance to execute and go into SCHED_DEADLINE during the initialization phase, for example by
setting its activation flag to DEFERRED, and the activate the task with a certain offset in the future.
Also, if the SCHED_DEADLINE parameters cannot be set, the user will not receive any error at the
time of task creation, but the error will be communicated later when the task effectively tries to set
its scheduling parameters.
void
ptask_activate(int tid);
Activates the task with index tid.
3
void
ptask_activate_at(int tid, ptime t);
Activates the task with index tid at the absolute time t. If t has already passed, the task is
immediately activated.
void
ptask_wait_for_period();
It suspends the calling task until the beginning of its next period. The typical usage of this call in a
task body is shown in Figure 1.
void ptask_wait_for_activation();
It suspends the calling task until an explicit activation is invoked by another task. The typical usage
of this call in a task body is shown in Figure 2.
ptask
{
int
my_periodic_task()
i;
i = ptask_get_index();
while (1) {
ptask_wait_for_period();
}
}
Figure 1: General structure of a periodic task.
ptask
{
int
my_aperiodic_task()
i;
i = ptask_get_index();
ptask_wait_for_activation();
while (1) {
}
ptask_wait_for_activation();
}
Figure 2: General structure of an aperiodic task.
The example illustrated in Figure 3 shows how to define a periodic task that starts executing upon
an explicit activation.
4
ptask
{
int
activated_periodic_task()
i;
i = ptask_get_index();
ptask_wait_for_activation();
while (1) {
ptask_wait_for_period();
}
}
Figure 3: General structure of a periodic task with an explicit activation.
The following functions are used to obtain and modify the parameters of a running task.
int
ptask_get_index();
Returns the index of the calling task.
int
ptask_get_priority(int i);
Returns the priority of the task with index i.
void
ptask_set_priority(int i, int prio);
Sets the priority of the task with index i to the value specified by prio, which must be a value
between 1 (the lowest priority) and 99 (the highest priority).
int
ptask_get_period(int i, int units);
Returns the period of the task with index i (in units).
void
ptask_set_period(int i, int myper, int units);
Sets the period of the task with index i to myper (in units).
ptime
ptask_get_deadline(int i, int units);
Returns the relative deadline of the task with index i (in units).
void
ptask_set_deadline(int i, int mydline, int units);
Sets the relative deadline of the task with index i to mydline (in units).
5
int
ptask_deadline_miss();
Returns 1 if the current time is greater than the absolute deadline of the current job, 0 otherwise.
int
ptask_migrate_to(int i, int core_id);
Moves the task with index i to the core specified by core_id.
More specific parameters can be passed to a task at creation time through the following structure:
typedef struct {
tspec
tspec
tspec
int
int
int
int
void
rtmode_t
int
int
} tpars;
In particular:
runtime
runtime;
// task budget (only for SCHED_DEADLINE)
period;
// task period (in ms)
rdline;
// relative deadline (in ms)
priority;
// from 1 (low) to 99 (high) (not used in SCHED_DEADLINE)
processor;
// processor where task should be allocated
act_flag;
// activation flag (NOW, DEFERRED)
measure_flag; // enable/disable exec. time measurements
*arg;
// pointer to a task argument
*modes;
// pointer to the mode handler
mode_list[RTMODE_MAX_MODES];
// the maximum number of modes
nmodes;
// num of modes in which the task is active
specifies the budget of the task (only for SCHED_DEADLINE)
period
specifies the task period in ms;
rdline
specifies the task relative deadline in ms (by default it is set equal to period);
priority
specifies the task priority between 1 (low) and 99 (high); this is only used for fixed
priority scheduling (SCHED_FIFO and SCHED_RR);
processor
specifies the processor where the task has to be allocated (default value is 0);
act_flag
if set to NOW, the task is immediately activated, if set to DEFERRED (default value),
the task will block on the wait_for_activation() until a ptask_activate() is invoked by
another task;
measure_flag
if set to a non-zero the library automatically profiles the execution time of the task;
arg
pointer to a memory area used to pass arguments to the task; the structure and the
content of such a memory are user-defined;
modes
used to manage mode changes (see Section 5);
nmodes
number of modes of the task;
mode_list
list of task modes.
6
Such parameters can be set either directly or by using the following functions (for efficiency
reasons, and following a common practice in C programming, these functions are actually
implemented as macros).
void
ptask_param_init(tpars tp);
Initializes the task parameters in the tp structure with the default values.
void
ptask_param_period(tpars tp, int myper, int units);
Initializes the task period in the tp structure with the value specified by myper expressed in given
units (SEC, MILLI, MICRO, or NANO).
void
ptask_param_deadline(tpars tp, int mydline, int units);
Initializes the task relative deadline in the tp structure with the value specified by mydline
expressed in given units (SEC, MILLI, MICRO, or NANO).
void
ptask_param_priority(tpars tp, int myprio);
Initializes the task priority in the tp structure with the value specified by myprio, which must be a
value between 1 (the lowest priority) and 99 (the highest priority).
void
ptask_param_activation(tpars tp, int myact);
Initializes the task activation mode in the tp structure with the value specified by myact, which can
be either NOW, for immediately activation, or DEFERRED; in this case the task will block on the
wait_for_activation() until a ptask_activate() is invoked by another task.
void
ptask_param_processor(tpars tp, int proc_id);
Specifies the index of the processor on which the task is supposed to run. Note that this is valid
only if the PARTITIONED strategy has been set by ptask_init(). This call has no effect when the
scheduling strategy is set to GLOBAL.
void
ptask_param_measure(tpars tp);
Sets the measuring flag to 1, so enabling ptask to automatically profile the execution time of the task.
void
ptask_param_argument(tpars tp, void *arg);
Passes to the tp structure the user-defined arguments pointed by arg.
void
ptask_param_modes(tpars tp, rtmode *modes, int nmodes);
7
Allows specifying the set of execution modes in the task that is going to be created. The argument
modes is a pointer to a structure that defines the system modes and nmodes specifies the number
of modes in which this task is going to be active.
void
ptask_param_mode_add(tpars tp, int mode_num);
Specifies that the current task is active in mode mode_num. See Section 5 for an example of use of
this function.
Once all the specific parameters are set, the task can be created using the following function.
int
ptask_create_param(void (*body)(void), tpars *tp);
Creates a concurrent task and returns the task index that can be used to differentiate multiple
instances of the same task. The arguments have the following meaning:
body
is the name of the function containing the task body;
tp
is a pointer to the task parameter structure; if tp is set to NULL, then the task is created
with the following default values:
type:
APERIODIC
period
1000 ms
rdline
1000 ms
priority
1
act_flag
DEFERRED
processor
0
measure
NO
arg
NULL
modes
NULL
nmodes
0
mode_list
an empty array
8
4.
Measuring execution times
To measure the execution time of a task it is necessary to set its measure_flag when the task is
created. Then, after the task has completed its execution, it is possible to obtain its execution time
by calling the following functions.
WARNING:
tspec
calling these functions while the task is executing may give inconsistent values,
because the internal data structures are not protected by semaphores for containing
the overhead. Therefore, it is up to the user to make sure that the task is no
executing before calling this function.
ptask_stat_getwcet(int i)
Returns the maximum execution time among all the jobs of task i since its first activation.
tspec
ptask_stat_getavg(int i)
Returns the average execution time among all the jobs of task i since its first activation.
int
ptask_stat_getnuminstances(int i)
Returns the number of jobs of task i activated since its creation.
tspec
ptask_stat_gettotal(int i)
Returns the total execution time consumed by all the jobs of task i since its creation.
5.
Handling mode changes
The Ptask library allows the user to specify a set of execution modes for the whole system and
handle mode changes transparently through the following functions.
int
rtmode_init(rtmode_t *g, int nmodes);
Initializes the mode manager and the data structure pointed by g, which will contain the task
groups involved in each mode. The second parameter nmodes is the total number of system
modes.
void
rtmode_changemode(rtmode_t *g, int new_mode_id);
This function has to be called every time we want the system to perform a mode change. The
parameter new_mode_id specifies the new mode in which the system must switch. The mode
change is performed by an internal mode manager that executes the mode change protocol. In the
current implementation, before activating the tasks involved in the new mode, the mode manager
waits for the largest absolute deadline of those tasks that are only present in the old mode. An
example of mode change is shown in Figure 4.
#define
#define
MODE_OFF
MODE_ON
0
1
9
#define
MODE_FAIL
ptask
{
taskbody()
2
ptask_wait_for_activation();
while (1) {
printf("Task T%d is running\n", ptask_get_index());
ptask_wait_for_period();
}
}
int
{
rtmode_t
tpars
int
main()
mymodes;
param;
res;
ptask_init(SCHED_FIFO, GLOBAL, PRIO_INHERITANCE);
res = rtmode_init(&mymodes, 3);
// System with 3 modes
ptask_param_init(param);
ptask_param_period(param, 1, SEC);
ptask_param_priority(param, 4);
// this task is present in two modes
ptask_param_modes(param, &mymodes, 2);
// the task is present in mode MODE_ON
ptask_param_mode_add(param, MODE_ON);
// The task is present in mode MODE_FAIL
ptask_param_mode_add(param, MODE_FAIL);
// The task is NOT present in MODE_OFF
res = ptask_create_param(taskbody, ¶m);
// create the other tasks in a similar way
rtmode_changemode(&mymodes, MODE_OFF);
}
// set initial mode
if (condition)
// activates MODE_ON; all tasks not in this mode
// are suspended; after that, the tasks in MODE_ON
// not already active, are activated
rtmode_changemode(&mymodes, MODE_ON);
else if (error_condition)
// activates MODE_FAIL; all tasks not in this mode
// are suspended; after that, the tasks in MODE_FAIL
// not yet active, are activated
rtmode_changemode(&mymodes, MODE_FAIL);
...
Figure 4: example of mode change.
10
Source Exif Data:
File Type : PDF File Type Extension : pdf MIME Type : application/pdf PDF Version : 1.4 Linearized : No Page Count : 10 Language : en-US Author : Online2PDF.com Creator : Writer Producer : LibreOffice 5.1 Create Date : 2017:06:23 14:29:27+02:00EXIF Metadata provided by EXIF.tools