event flag manager API

Andrei Dimitrief-Jianu andrei.dimitrief.jianu at gmail.com
Tue Oct 2 14:31:34 UTC 2012


Hello,

Below is a description for an event flag manager API. It would be used
to synchronize
tasks, but in a manner that is independent of a particular task.

I am interested in feedback. I am not sure if the API covers all
possible scenarios
or if it needs clarifications.

Regards,
Andrei.


*** EVENT FLAG MANAGER

The event flag manager uses multiple bits in a bit pattern to
synchronize tasks.
Each bit in the bit pattern represents an event that can be set, cleared, and
waited for. An event flag can use a maximum of 32 events to synchronize tasks.


** EFLAG_CREATE

* CALLING SEQUENCE:

rtems_status_code rtems_eflag_create(
  rtems_name name,
  uint32_t flag_pattern,
  rtems_attribute attribute_set,
  rtems_id *id
);

* DIRECTIVE STATUS CODES:

RTEMS_SUCCESSFUL - event flag created successfully

RTEMS_INVALID_ADDRESS - id is NULL
RTEMS_INVALID_ATTRIBUTE - the attribute set contains invalid flag
RTEMS_INVALID_FLAG - the flag is invalid
RTEMS_INVALID_NAME - invalid event flag name
RTEMS_NOT_DEFINED - invalid attribute set
RTEMS_TOO_MANY - too many event flags or too many global objects created

* DESCRIPTION:

The directive creates an event flag with the specified flag pattern.

* NOTES:

The attribute set can be a combination of the following:

RTEMS_LOCAL - local task (default)
RTEMS_GLOBAL - global task
RTEMS_FIFO - tasks wait by FIFO (default)
RTEMS_PRIORITY - tasks wait by priority

RTEMS_DEFAULT_ATTRIBUTES - all default attributes are desired

If RTEMS_FIFO is used in the attribute set, the tasks will wait for the
events to occur in the order they were blocked.


** EFLAG_IDENT

* CALLING SEQUENCE:

rtems_status_code rtems_eflag_ident(
  rtems_name name,
  uint32_t node,
  rtems_id *id
);

* DIRECTIVE STATUS CODES:

RTEMS_SUCCESSFUL - event flag identified successfully

RTEMS_INVALID_NAME - event flag name not found
RTEMS_INVALID_NODE - invalid node id

* DESCRIPTION:

The directive returns the event flag id associated with the event flag name.

* NOTES:

If node is RTEMS_SEARCH_ALL_NODES, all nodes are searched with the
local node being
searched first. All other nodes are searched with the lowest numbered
node searched first.


** EFLAG_DELETE

* CALLING SEQUENCE:

rtems_status_code rtems_eflag_delete(
  rtems_id id
);

* DIRECTIVE STATUS CODES:

RTEMS_SUCCESSFUL - event flag deleted successfully

RTEMS_INVALID_ID - invalid event flag id
RTEMS_NOT_OWNER_OF_RESOURCE - calling task does not own the event flag
RTEMS_RESOURCE_IN_USE - event flag in use

* DESCRIPTION:

The directive deletes the event flag specified by id. All tasks blocked waiting
for the event(s) will be readied and returned a status code
(RTEMS_OBJECT_WAS_DELETED)
which indicates that the event flag was deleted.

* NOTES:

The event flag should be flushed before calling rtems_eflag_delete
directive. Otherwise,
rtems_eflag_delete returns with a status code of RTEMS_RESOURCE_IN_USE.


** EFLAG_WAIT_ONE

* CALLING SEQUENCE:

rtems_status_code rtems_eflag_wait_one(
  rtems_id id,
  uint32_t flag,
  rtems_options option_set,
  rtems_interval timeout
);

* DIRECTIVE STATUS CODES:

RTEMS_SUCCESSFUL - directive returned after event was set

RTEMS_INVALID_FLAG - the flag is invalid
RTEMS_INVALID_ID - invalid event flag id
RTEMS_OBJECT_WAS_DELETED - event flag deleted while waiting
RTEMS_TIMEOUT - timed out waiting for the event
RTEMS_UNSATISFIED - event made unavailable by a flush directive

* DESCRIPTION:

The directive blocks waiting for the event specified by flag.

* NOTES:

The option set can have the values:

RTEMS_WAIT - the task will wait for the lock (default)
RTEMS_NO_WAIT - task does not wait

If RTEMS_NO_TIMEOUT is passed as timeout, the directive blocks waiting for
the event, even if option set does not contain RTEMS_WAIT.

The flag passed as argument must contain one and only one bit set, otherwise
an error status code RTEMS_INVALID_FLAG is returned.


** EFLAG_WAIT_ANY

* CALLING SEQUENCE:

rtems_status_code rtems_eflag_wait_any(
  rtems_id id,
  uint32_t flag_pattern,
  rtems_options option_set,
  rtems_interval timeout
);

* DIRECTIVE STATUS CODES:

RTEMS_SUCCESSFUL - directive returned after any of the events is set

RTEMS_INVALID_FLAG - the flag is invalid
RTEMS_INVALID_ID - invalid event flag id
RTEMS_OBJECT_WAS_DELETED - event flag deleted while waiting
RTEMS_TIMEOUT - timed out waiting for the event
RTEMS_UNSATISFIED - any of the events specified by the flag pattern
made unavailable by a flush directive

* DESCRIPTION:

The directive blocks waiting for any of the events specified by the
flag pattern to be set.

* NOTES:

The option set can have the values:

RTEMS_WAIT - the task will wait for the lock (default)
RTEMS_NO_WAIT - task does not wait

If RTEMS_NO_TIMEOUT is passed as timeout, the directive blocks waiting for
any if the events, even if option set does not contain RTEMS_WAIT.

The flag passed as argument must contain at least one bit set, otherwise
an error status code RTEMS_INVALID_FLAG is returned.


** EFLAG_WAIT_ALL

* CALLING SEQUENCE:

rtems_status_code rtems_eflag_wait_all(
  rtems_id id,
  uint32_t flag_pattern,
  rtems_options option_set,
  rtems_interval timeout
);

* DIRECTIVE STATUS CODES:

RTEMS_SUCCESSFUL - directive returned after all events were set

RTEMS_INVALID_FLAG - the flag is invalid
RTEMS_INVALID_ID - invalid event flag id
RTEMS_OBJECT_WAS_DELETED - event flag deleted while waiting
RTEMS_TIMEOUT - timed out waiting for the event
RTEMS_UNSATISFIED - all of the events specified by the flag pattern
made unavailable by a flush directive

* DESCRIPTION:

The directive blocks waiting for all of the events specified by the
flag pattern to be set.

* NOTES:

The option set can have the values:

RTEMS_WAIT - the task will wait for the lock (default)
RTEMS_NO_WAIT - task does not wait

If RTEMS_NO_TIMEOUT is passed as timeout, the directive blocks waiting for
all the events, even if option set does not contain RTEMS_WAIT.

The flag passed as argument must contain at least one bit set, otherwise
an error status code RTEMS_INVALID_FLAG is returned.


** EFLAG_SET

* CALLING SEQUENCE:

rtems_status_code rtems_eflag_set(
  rtems_id id,
  uint32_t flag_pattern
);

* DIRECTIVE STATUS CODES:

RTEMS_SUCCESSFUL - event flags set successfully

RTEMS_INVALID_FLAG - the flag pattern is invalid
RTEMS_INVALID_ID - invalid event flag id

* DESCRIPTION:

The directive sets the events specified by the flag pattern in the
event flag specified by id.

* NOTES:

The flag pattern passed as argument must contain at least one bit set,
otherwise an error status code RTEMS_INVALID_FLAG is returned.


** EFLAG_SET_AND_CLEAR

* CALLING SEQUENCE:

rtems_status_code rtems_eflag_set_and_clear(
  rtems_id id,
  uint32_t flag_pattern
);

* DIRECTIVE STATUS CODES:

RTEMS_SUCCESSFUL - event flags set and cleared successfully

RTEMS_INVALID_FLAG - the flag pattern is invalid
RTEMS_INVALID_ID - invalid event flag id

* DESCRIPTION:

The directive sets the events specified by the flag pattern in the event flag
specified by id and after all tasks waiting for the events are unblocked,
it clears the events flag set. Operations are executed atomically.

* NOTES:

The flag pattern passed as argument must contain at least one bit set,
otherwise an error status code RTEMS_INVALID_FLAG is returned.


** EFLAG_CLEAR

* CALLING SEQUENCE:

rtems_status_code rtems_eflag_clear(
  rtems_id id,
  uint32_t flag_pattern
);

* DIRECTIVE STATUS CODES:

RTEMS_SUCCESSFUL - event flags cleared successfully

RTEMS_INVALID_FLAG - the flag pattern is invalid
RTEMS_INVALID_ID - invalid event flag id

* DESCRIPTION:

The directive clears the events specified by the flag pattern.

* NOTES:

The flag pattern passed as argument must contain at least one bit set,
otherwise an error status code RTEMS_INVALID_FLAG is returned.


** EFLAG_FLUSH

* CALLING SEQUENCE:

rtems_status_code rtems_eflag_flush(
  rtems_id id,
  uint32_t flag_pattern
);

* DIRECTIVE STATUS CODES:

RTEMS_SUCCESSFUL - event flags flushed successfully

RTEMS_INVALID_FLAG - the flag pattern is invalid
RTEMS_INVALID_ID - invalid event flag id

* DESCRIPTION:

The directive flushes the events specified by the flag pattern.

* NOTES:

The flag pattern passed as argument must contain at least one bit set,
otherwise an error status code RTEMS_INVALID_FLAG is returned.

The tasks which are unblocked as the result of this directive will
return from the rtems_eflag_wait_one, rtems_eflag_wait_any or
rtems_eflag_wait_all directive with a status code of RTEMS_UNSATISFIED.

As a result, the event flags described by the flag pattern will be cleared.


** EFLAG_STATUS

* CALLING SEQUENCE:

rtems_status_code rtems_eflag_status(
  rtems_id id,
  uint32_t *flag_pattern
);

* DIRECTIVE STATUS CODES:

RTEMS_SUCCESSFUL - event status returned successfully

RTEMS_INVALID_ADDRESS - the flag pattern pointer is NULL
RTEMS_INVALID_ID - invalid event flag id

* DESCRIPTION:

The directive returns the status of the event flag specified by id.

* NOTES:

[...]


** USE CASE:

////////////////////////////////////////////////////////////////////
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
#define CONFIGURE_MICROSECONDS_PER_TICK 1000
#define CONFIGURE_TICKS_PER_TIMESLICE 50
#define CONFIGURE_MAXIMUM_TASKS 4
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
#define CONFIGURE_INIT

#include <bsp.h>
#include <stdlib.h>
#include <stdio.h>
#include <rtems/confdefs.h>

#define EVENT_FLAG_1 0x01
#define EVENT_FLAG_2 0x02
#define EVENT_FLAG_3 0x04

rtems_task worker_task( rtems_task_argument argument );

rtems_id eflag_id;

rtems_task
Init( rtems_task_argument ignored )
{
  rtems_id  task_id;
  rtems_status_code status_code;
  rtems_name task_name;

  rtems_name eflag_name;
  eflag_name = rtems_build_name( 'E', 'F', 'L', 'G' );
  status_code = rtems_eflag_create(
    eflag_name,
    EVENT_FLAG_1 | EVENT_FLAG_2 | EVENT_FLAG_3,
    RTEMS_LOCAL | RTEMS_FIFO,
    &eflag_id
    );
  if( RTEMS_SUCCESSFUL != status_code )
  {
    printf( "\nrtems_eflag_create failed with status of %d.\n", status_code );
    exit( 1 );
  }

  /////////////////////////////////////////////////////////////////////////////
  task_name = rtems_build_name( 'T', 'S', 'K', '1' );

  status_code = rtems_task_create(
    task_name, 1, RTEMS_MINIMUM_STACK_SIZE,
    RTEMS_NO_PREEMPT, RTEMS_FLOATING_POINT, &task_id );
  if( RTEMS_SUCCESSFUL != status_code )
  {
    printf( "\nrtems_task_create failed with status of %d.\n", status_code );
    exit( 1 );
  }

  status_code = rtems_task_start( task_id, worker_task, EVENT_FLAG_1 );
  if( RTEMS_SUCCESSFUL != status_code )
  {
    printf( "\nrtems_task_start failed with status of %d.\n", status_code );
    exit( 1 );
  }
  /////////////////////////////////////////////////////////////////////////////
  task_name = rtems_build_name( 'T', 'S', 'K', '2' );

  status_code = rtems_task_create(
    task_name, 1, RTEMS_MINIMUM_STACK_SIZE,
    RTEMS_NO_PREEMPT, RTEMS_FLOATING_POINT, &task_id );
  if( RTEMS_SUCCESSFUL != status_code )
  {
    printf( "\nrtems_task_create failed with status of %d.\n", status_code );
    exit( 1 );
  }

  status_code = rtems_task_start( task_id, worker_task, EVENT_FLAG_2 );
  if( RTEMS_SUCCESSFUL != status_code )
  {
    printf( "\nrtems_task_start failed with status of %d.\n", status_code );
    exit( 1 );
  }
  /////////////////////////////////////////////////////////////////////////////
  task_name = rtems_build_name( 'T', 'S', 'K', '3' );

  status_code = rtems_task_create(
    task_name, 1, RTEMS_MINIMUM_STACK_SIZE,
    RTEMS_NO_PREEMPT, RTEMS_FLOATING_POINT, &task_id );
  if( RTEMS_SUCCESSFUL != status_code )
  {
    printf( "\nrtems_task_create failed with status of %d.\n", status_code );
    exit( 1 );
  }

  status_code = rtems_task_start( task_id, worker_task, EVENT_FLAG_3 );
  if( RTEMS_SUCCESSFUL != status_code )
  {
    printf( "\nrtems_task_start failed with status of %d.\n", status_code );
    exit( 1 );
  }
  /////////////////////////////////////////////////////////////////////////////

  printf( "\nmain task waiting for the workers to finish...\n" );
  status_code = rtems_eflag_wait_all(
    eflag_id,
    EVENT_FLAG_1 | EVENT_FLAG_2 | EVENT_FLAG_3,
    RTEMS_WAIT,
    RTEMS_NO_TIMEOUT
  );
  if( RTEMS_SUCCESSFUL != status_code )
  {
    printf( "\nrtems_eflag_wait_all failed with status of %d.\n", status_code );
    exit( 1 );
  }

  status_code = rtems_eflag_delete( eflag_id );
  if( RTEMS_SUCCESSFUL != status_code )
  {
    printf( "\nrtems_eflag_delete failed with status of %d.\n", status_code );
    exit( 1 );
  }

  printf( "\nmain task is exiting...\n" );

  exit( 0 );
}

rtems_task
worker_task( rtems_task_argument argument )
{
  int index = 0;
  while( index++ < 10 * argument )
  {
    printf( "\ntask [%d] > doing something in the user task [%d].\n",
(uint32_t)argument, index );
    rtems_task_wake_after( RTEMS_MILLISECONDS_TO_TICKS( 1000 ) );
  }

  rtems_eflag_set( eflag_id, (uint32_t)argument );

  printf( "\ntask [%d] is exiting...\n", (uint32_t)argument );
  rtems_task_delete( rtems_task_self() );

}
////////////////////////////////////////////////////////////////////



More information about the devel mailing list