RTEMS 6.1-rc6
Loading...
Searching...
No Matches
Files | Data Structures | Typedefs | Functions
Regulator API

Regulator APIs. More...

Files

file  regulator.h
 This header file defines the Regulator API.
 

Data Structures

struct  rtems_regulator_attributes
 Attributes for Regulator Instance. More...
 
struct  rtems_regulator_statistics
 Statistics for Regulator Instance. More...
 

Typedefs

typedef bool(* rtems_regulator_deliverer) (void *context, void *message, size_t length)
 Regulator Delivery Function Type.
 
typedef struct _Regulator_Controlrtems_regulator_instance
 Regulator Instance.
 

Functions

rtems_status_code rtems_regulator_create (rtems_regulator_attributes *attributes, rtems_regulator_instance **regulator)
 Create a regulator.
 
rtems_status_code rtems_regulator_delete (rtems_regulator_instance *regulator, rtems_interval ticks)
 Delete a regulator.
 
rtems_status_code rtems_regulator_obtain_buffer (rtems_regulator_instance *regulator, void **buffer)
 Obtain Buffer from Regulator.
 
rtems_status_code rtems_regulator_release_buffer (rtems_regulator_instance *regulator, void *buffer)
 Release Previously Obtained Regulator Buffer.
 
rtems_status_code rtems_regulator_send (rtems_regulator_instance *regulator, void *message, size_t length)
 Send to regulator instance.
 
rtems_status_code rtems_regulator_get_statistics (rtems_regulator_instance *regulator, rtems_regulator_statistics *statistics)
 Obtain statistics for regulator instance.
 

Detailed Description

Regulator APIs.

The Regulator provides a set of APIs to manage input sources which produces bursts of message traffic.

The regulator is designed to sit logically between two entities – a source and a destination, where it limits the traffic sent to the destination to prevent it from being flooded with messages from the source. This can be used to accommodate bursts of input from a source and meter it out to a destination. The maximum number of messages which can be buffered in the regulator is specified by the maximum_messages field in the rtems_regulator_attributes structure passed as an argument to rtems_regulator_create().

The regulator library accepts an input stream of messages from a source and delivers them to a destination. The regulator assumes that the input stream from the source contains sporadic bursts of data which can exceed the acceptable rate of the destination. By limiting the message rate, the regulator prevents an overflow of messages.

The regulator can be configured for the input buffering required to manage the maximum burst and for the metering rate for the output. The output rate is in messages per second. If the sender produces data too fast, the regulator will buffer the configured number of messages.

A configuration capability is provided to allow for adaptation to different message streams. The regulator can also support running multiple instances, which could be used on independent message streams.

The regulator provides a simple interface to the application for avoiding bursts of input from a fast source overflowing a slower destination.

It is assumed that the application has a design limit on the number of messages which may be buffered. All messages accepted by the regulator, assuming no overflow on input, will eventually be output by the Delivery thread.

A regulator instance is used as follows from the producer/source side:

while (1)
use rtems_regulator_obtain_buffer to obtain a buffer
input operation to fetch data into the buffer
rtems_regulator_send(buffer, size of message)
rtems_status_code rtems_regulator_obtain_buffer(rtems_regulator_instance *regulator, void **buffer)
Obtain Buffer from Regulator.
Definition: regulator.c:498
rtems_status_code rtems_regulator_send(rtems_regulator_instance *regulator, void *message, size_t length)
Send to regulator instance.
Definition: regulator.c:570
Definition: media-server.c:46

The delivery of message buffers to the Destination and subsequent release is performed in the context of the delivery thread by either the delivery function or delivery thread. Details are below.

The sequence diagram below shows the interaction between a message Source, a Regulator instance, and RTEMS, given the usage described in the above paragraphs.

As illustrated in the sequence diagram, the Source usually corresponds to application software reading a system input. The Source obtains a buffer from the Regulator instance and fills it with incoming data. The application explicitly obtaining a buffer and filling it in allows for zero copy operations on the Source side.

The Source then sends the buffer to the Regulator instance. The Regulator the sends the buffer via a message queue which to the Delivery thread. The Delivery thread executes periodically at a rate specified at Regulation creation. At each period, the Delivery thread attempts to receive up to a configured number of buffers and invoke the Delivery function to deliver them to the Destination.

The Delivery function is provided by the application for this specific Regulator instance. Depending on the Destination, it may use a function which copies the buffer contents (e.g., write()) or which operates directly on the buffer contents (e.g. DMA from buffer). In the case of a Destination which copies the buffer contents, the buffer can be released via rtems_regulator_release_buffer() as soon as the function or copying completes. In the case where the delivery uses the buffer and returns, the call to rtems_regulator_release_buffer() will occur when the use of the buffer is complete (e.g. completion of DMA transfer). This explicit and deliberate exposure of buffering provides the application with the ability to avoid copying the contents.

After the Source has sent the message to the Regulator instance, the Source is free to process another input and the Regulator instance will ensure that the buffer is delivered to the Delivery function and Destination.

The Regulator implementation uses the RTEMS Classic API Partition Manager to manage the buffer pool and the RTEMS Classic API Message Queue Manager to send the buffer to the Delivery thread.

Typedef Documentation

◆ rtems_regulator_deliverer

typedef bool(* rtems_regulator_deliverer) (void *context, void *message, size_t length)

Regulator Delivery Function Type.

The user provides a function which is invoked to deliver a message to the output. It is invoked by the Delivery thread created as part of rtems_regulator_create(). The priority and stack size of the Delivery thread are specified in the regulator attribute set.

It takes three parameters:

Parameters
[in]contextis an untyped pointer to a user context
[in]messagepoints to the message
[in]lengthis the message size

The following is an example deliverer function. It assumes that the application has defined the my_context_t structure and it has at least the socket field. The message passed in originated with an application source which obtained the message buffer using rtems_regulator_obtain_buffer(), filled it in with source data, and used rtems_regulator_send() to hand to the regulator instance for later delivery.

bool my_deliverer(
void *context,
void *message,
size_t length
)
{
my_context_t *my_context;
my_context = (my_context_t *)context;
write(my_context->socket, message, length);
// return false to indicate we released the buffer
return false;
}
rtems_status_code rtems_regulator_release_buffer(rtems_regulator_instance *regulator, void *buffer)
Release Previously Obtained Regulator Buffer.
Definition: regulator.c:535
ssize_t write(int fd, const void *buffer, size_t count)
Definition: write.c:49
rtems_termios_device_context * context
Definition: console-config.c:62

The delivery function returns true to indicate that the delivery thread should release the buffer or false to indicate that it released the buffer. If the delivery function invokes a function like write() to deliver the message to the destination, then the buffer can be released immediately after the call. If the delivery function does something like setting up a DMA transfer of the buffer, it cannot be released until after the DMA is complete.

The following sequence diagram shows the behavior of the Delivery thread body and its interaction with the user-supplied deliverer() function.

In the above sequence diagram, the key points are:

  1. The Delivery Thread Body is periodically executed.
  2. During each period, up to the instance configuration parameter maximum_to_dequeue_per_period may be dequeued and passed the application's delivery function for processing.

Note that the application explicitly obtains buffers from the regulator instance but that the release may be done by Delivery Thread, the Delivery function, or later when the buffer contents are transferred.

◆ rtems_regulator_instance

Regulator Instance.

This is used by the application as the handle to a Regulator instance.

Function Documentation

◆ rtems_regulator_create()

rtems_status_code rtems_regulator_create ( rtems_regulator_attributes attributes,
rtems_regulator_instance **  regulator 
)

Create a regulator.

This function creates an instance of a regulator. It uses the provided attributes to create the instance return in regulator. This instance will allocate the buffers associated with the regulator instance as well as the Delivery thread.

The attributes structure defines the priority and stack size of the Delivery thread dedicated to this regulator instance. It also defines the period of the Delivery thread and the maximum number of messages that may be delivered per period via invocation of the delivery function.

For each regulator instance, the following resources are allocated:

  • A memory area for the regulator control block using malloc().
  • A RTEMS Classic API Message Queue is constructed with message buffer memory allocated using malloc(). Each message consists of a pointer and a length.
  • A RTEMS Classic API Partition.
  • A RTEMS Classic API Rate Monotonic Period.
Parameters
[in]attributesspecify the regulator instance attributes
[in,out]regulatorwill point to the regulator instance
Returns
an RTEMS status code indicating success or failure.
Note
This function allocates memory for the buffers holding messages, an Delivery thread and an RTEMS partition. When it executes, the Delivery thread will create an RTEMS rate monotonic period.

Perform basic validation of parameters

Verify attributes are OK. Some are checked by calls to object create methods. Specifically the following are not checked:

Allocate memory for regulator instance

We do NOT want the delivery_thread_id field to be initialized to 0. If the rtems_task_create() fails, then the field will not be overwritten. This results in an attempt to rtems_task_delete(0) during clean up. The thread ID of 0 is self which results in the calling thread accidentally deleting itself.

Copy the attributes to an internal area for later use

Allocate memory for the messages. There is no need to zero out the message memory because the user should fill that in.

Associate message memory with a partition so allocations are atomic

Create the message queue between the sender and output thread

Note
A rate monotonic period object must be created by the thread using it. Thus that specific create operation is not included in this method. All other resources are allocated here.

Create the output thread Using the priority and stack size attributes specified by the user.

Start the output thread.

Note
There should be no way this call can fail. The task id is valid, the regulator output thread entry point is valid, and the argument is valid.

The regulator is successfully initialized. Set the initialized field to reflect this and return the instance pointer.

◆ rtems_regulator_delete()

rtems_status_code rtems_regulator_delete ( rtems_regulator_instance regulator,
rtems_interval  ticks 
)

Delete a regulator.

This function is used to delete the specified regulator instance.

It is the responsibility of the user to ensure that any resources such as sockets or open file descriptors used by the delivery function are also deleted. It is likely safer to delete those delivery resources after deleting the regulator instance rather than before.

Parameters
[in]regulatoris the instance to delete
[in]ticksis the maximum number of ticks to wait for the delivery thread to shutdown.
Returns
an RTEMS status code indicating success or failure.
Note
This function deallocates the resources allocated during rtems_regulator_create().

Convert external handle to internal instance pointer

There can be no buffers outstanding

Free the resources associated with this regulator instance.

◆ rtems_regulator_get_statistics()

rtems_status_code rtems_regulator_get_statistics ( rtems_regulator_instance regulator,
rtems_regulator_statistics statistics 
)

Obtain statistics for regulator instance.

This function is used by the application to obtain statistics information about the regulator instance.

If the obtained and released fields in the returned statistics structure are equal, then there are no buffers outstanding from this regulator instance.

Parameters
[in]regulatoris the regulator instance to operate upon
[in,out]statisticspoints to the statistics structure to fill in
Returns
an RTEMS status code indicating success or failure.

Validate the arguments and ensure the regulator was successfully initialized.

Convert external handle to internal instance pointer

Zero out the statistics structure in case the get period statistics fails below.

Fill in the caller's statistics structure from information maintained by the regulator instance about buffers processed.

Attempt to retrieve the delivery thread's period's statistics.

NOTE; If the Delivery Thread has not run yet, the period will not exist yet. We should not fail for this reason but it is why we zeroed out the entire structure above.

◆ rtems_regulator_obtain_buffer()

rtems_status_code rtems_regulator_obtain_buffer ( rtems_regulator_instance regulator,
void **  buffer 
)

Obtain Buffer from Regulator.

This function is used to obtain a buffer from the regulator's pool. The buffer returned is assumed to be filled in with contents and used in a subsequent call to rtems_regulator_send(). When the buffer is delivered, it is expected to be released. If the buffer is not successfully accepted by this function, then it should be returned using rtems_regulator_release_buffer() or used to send another message.

The buffer is of the maximum_message_size specified in the attributes passed in to rtems_regulator_create().

Parameters
[in]regulatoris the regulator instance to operate upon
[out]bufferwill point to the allocated buffer
Returns
an RTEMS status code indicating success or failure.
Note
This function does not perform dynamic allocation. It obtains a buffer from the pool allocated during rtems_regulator_create().
Any attempt to write outside the buffer area is undefined.

Allocate a buffer for the caller using the internal partition.

Convert external handle to internal instance pointer

Allocate a buffer for the user application from the buffer pool managed by an Classic API partition.

◆ rtems_regulator_release_buffer()

rtems_status_code rtems_regulator_release_buffer ( rtems_regulator_instance regulator,
void *  buffer 
)

Release Previously Obtained Regulator Buffer.

This function is used to release a buffer to the regulator's pool. It is assumed that the buffer returned will not be used by the application anymore. The buffer must have previously been allocated by rtems_regulator_obtain_buffer() and NOT passed to rtems_regulator_send().

If a subsequent rtems_regulator_send() using this buffer is successful, the buffer will eventually be processed by the delivery thread and released.

Parameters
[in]regulatoris the regulator instance to operate upon
[out]bufferwill point to the buffer to release
Returns
an RTEMS status code indicating success or failure.
Note
This function does not perform dynamic deallocation. It releases a buffer to the pool allocated during rtems_regulator_create().

Allocate a buffer for the caller using the internal partition.

Convert external handle to internal instance pointer

Deallocate the buffer to the buffer pool managed by a Classic API partition.

◆ rtems_regulator_send()

rtems_status_code rtems_regulator_send ( rtems_regulator_instance regulator,
void *  message,
size_t  length 
)

Send to regulator instance.

This function is used by the producer to send a message to the regulator for later delivery by the Delivery thread. The message is contained in the memory pointed to by message and is length bytes in length.

It is required that the message buffer was obtained via rtems_regulator_obtain_buffer().

It is assumed that the message buffer has been filled in with application content to deliver.

If the rtems_regulator_send() is successful, the buffer is enqueued inside the regulator instance for subsequent delivery. After the message is delivered, it may be released by either delivery function or the application code depending on the implementation.

The status RTEMS_TOO_MANY is returned if the regulator's internal queue is full. This indicates that the configured maximum number of messages was insufficient. It is the responsibility of the caller to decide whether to hold messages, drop them, or print a message that the maximum number of messages should be increased.

If rtems_regulator_send() is unsuccessful, it is the application's responsibility to release the buffer. If it is successfully sent, then it becomes the responsibility of the delivery function to release it.

Parameters
[in]regulatoris the regulator instance to operate upon
[out]messagepoints to the message to deliver
[out]lengthis the size of the message in bytes
Returns
an RTEMS status code indicating success or failure.

Validate the arguments and ensure the regulator was successfully initialized.

Convert external handle to internal instance pointer

Place the message pointer and length into a temporary structure. This lets the implementation internally send the message by reference and have a zero-copy implementation.

Send the application message to the output thread for delivery using a Classic API message queue.