11.3. Operations

11.3.1. Creating a Rate Monotonic Period

The rtems_rate_monotonic_create directive creates a rate monotonic period which is to be used by the calling task to delineate a period. RTEMS allocates a Period Control Block (PCB) from the PCB free list. This data structure is used by RTEMS to manage the newly created rate monotonic period. RTEMS returns a unique period ID to the application which is used by other rate monotonic manager directives to access this rate monotonic period.

11.3.2. Manipulating a Period

The rtems_rate_monotonic_period directive is used to establish and maintain periodic execution utilizing a previously created rate monotonic period. Once initiated by the rtems_rate_monotonic_period directive, the period is said to run until it either expires or is reinitiated. The state of the rate monotonic period results in one of the following scenarios:

  • If the rate monotonic period is running, the calling task will be blocked for the remainder of the outstanding period and, upon completion of that period, the period will be reinitiated with the specified period.

  • If the rate monotonic period is not currently running and has not expired, it is initiated with a length of period ticks and the calling task returns immediately.

  • If the rate monotonic period has expired before the task invokes the rtems_rate_monotonic_period directive, the postponed job will be released until there is no more postponed jobs. The calling task returns immediately with a timeout error status. In the watchdog routine, the period will still be updated periodically and track the count of the postponed jobs [CvdBruggenC16]. Please note, the count of the postponed jobs is only saturated until 0xffffffff.

11.3.3. Obtaining the Status of a Period

If the rtems_rate_monotonic_period directive is invoked with a period of RTEMS_PERIOD_STATUS ticks, the current state of the specified rate monotonic period will be returned. The following table details the relationship between the period’s status and the directive status code returned by the rtems_rate_monotonic_period directive:

RTEMS_SUCCESSFUL

period is running

RTEMS_TIMEOUT

period has expired

RTEMS_NOT_DEFINED

period has never been initiated

Obtaining the status of a rate monotonic period does not alter the state or length of that period.

11.3.4. Canceling a Period

The rtems_rate_monotonic_cancel directive is used to stop the period maintained by the specified rate monotonic period. The period is stopped and the rate monotonic period can be reinitiated using the rtems_rate_monotonic_period directive.

11.3.5. Deleting a Rate Monotonic Period

The rtems_rate_monotonic_delete directive is used to delete a rate monotonic period. If the period is running and has not expired, the period is automatically canceled. The rate monotonic period’s control block is returned to the PCB free list when it is deleted. A rate monotonic period can be deleted by a task other than the task which created the period.

11.3.6. Examples

The following sections illustrate common uses of rate monotonic periods to construct periodic tasks.

11.3.7. Simple Periodic Task

This example consists of a single periodic task which, after initialization, executes every 100 clock ticks.

 1rtems_task Periodic_task(rtems_task_argument arg)
 2{
 3    rtems_name        name;
 4    rtems_id          period;
 5    rtems_status_code status;
 6    name = rtems_build_name( 'P', 'E', 'R', 'D' );
 7    status = rtems_rate_monotonic_create( name, &period );
 8    if ( status != RTEMS_SUCCESSFUL ) {
 9        printf( "rtems_monotonic_create failed with status of %d.\n", status );
10        exit( 1 );
11    }
12    while ( 1 ) {
13        if ( rtems_rate_monotonic_period( period, 100 ) == RTEMS_TIMEOUT )
14            break;
15        /* Perform some periodic actions */
16    }
17    /* missed period so delete period and SELF */
18    status = rtems_rate_monotonic_delete( period );
19    if ( status != RTEMS_SUCCESSFUL ) {
20        printf( "rtems_rate_monotonic_delete failed with status of %d.\n", status );
21        exit( 1 );
22    }
23    status = rtems_task_delete( RTEMS_SELF );    /* should not return */
24    printf( "rtems_task_delete returned with status of %d.\n", status );
25    exit( 1 );
26}

The above task creates a rate monotonic period as part of its initialization. The first time the loop is executed, the rtems_rate_monotonic_period directive will initiate the period for 100 ticks and return immediately. Subsequent invocations of the rtems_rate_monotonic_period directive will result in the task blocking for the remainder of the 100 tick period. If, for any reason, the body of the loop takes more than 100 ticks to execute, the rtems_rate_monotonic_period directive will return the RTEMS_TIMEOUT status. If the above task misses its deadline, it will delete the rate monotonic period and itself.

11.3.8. Task with Multiple Periods

This example consists of a single periodic task which, after initialization, performs two sets of actions every 100 clock ticks. The first set of actions is performed in the first forty clock ticks of every 100 clock ticks, while the second set of actions is performed between the fortieth and seventieth clock ticks. The last thirty clock ticks are not used by this task.

 1rtems_task Periodic_task(rtems_task_argument arg)
 2{
 3    rtems_name        name_1, name_2;
 4    rtems_id          period_1, period_2;
 5    name_1 = rtems_build_name( 'P', 'E', 'R', '1' );
 6    name_2 = rtems_build_name( 'P', 'E', 'R', '2' );
 7    (void ) rtems_rate_monotonic_create( name_1, &period_1 );
 8    (void ) rtems_rate_monotonic_create( name_2, &period_2 );
 9    while ( 1 ) {
10        if ( rtems_rate_monotonic_period( period_1, 100 ) == RTEMS_TIMEOUT )
11            break;
12        if ( rtems_rate_monotonic_period( period_2, 40 ) == RTEMS_TIMEOUT )
13        break;
14        /*
15         *  Perform first set of actions between clock
16         *  ticks 0 and 39 of every 100 ticks.
17         */
18        if ( rtems_rate_monotonic_period( period_2, 30 ) == RTEMS_TIMEOUT )
19            break;
20        /*
21         *  Perform second set of actions between clock 40 and 69
22         *  of every 100 ticks.  THEN ...
23         *
24         *  Check to make sure we didn't miss the period_2 period.
25         */
26        if ( rtems_rate_monotonic_period( period_2, RTEMS_PERIOD_STATUS ) == RTEMS_TIMEOUT )
27            break;
28        (void) rtems_rate_monotonic_cancel( period_2 );
29    }
30    /* missed period so delete period and SELF */
31    (void ) rtems_rate_monotonic_delete( period_1 );
32    (void ) rtems_rate_monotonic_delete( period_2 );
33    (void ) rtems_task_delete( RTEMS_SELF );
34}

The above task creates two rate monotonic periods as part of its initialization. The first time the loop is executed, the rtems_rate_monotonic_period directive will initiate the period_1 period for 100 ticks and return immediately. Subsequent invocations of the rtems_rate_monotonic_period directive for period_1 will result in the task blocking for the remainder of the 100 tick period. The period_2 period is used to control the execution time of the two sets of actions within each 100 tick period established by period_1. The rtems_rate_monotonic_cancel( period_2 ) call is performed to ensure that the period_2 period does not expire while the task is blocked on the period_1 period. If this cancel operation were not performed, every time the rtems_rate_monotonic_period( period_2, 40 ) call is executed, except for the initial one, a directive status of RTEMS_TIMEOUT is returned. It is important to note that every time this call is made, the period_2 period will be initiated immediately and the task will not block.

If, for any reason, the task misses any deadline, the rtems_rate_monotonic_period directive will return the RTEMS_TIMEOUT directive status. If the above task misses its deadline, it will delete the rate monotonic periods and itself.