RTEMS 6.1-rc2
|
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_Control * | rtems_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. | |
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:
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.
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:
[in] | context | is an untyped pointer to a user context |
[in] | message | points to the message |
[in] | length | is 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.
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:
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.
typedef struct _Regulator_Control* rtems_regulator_instance |
Regulator Instance.
This is used by the application as the handle to a Regulator instance.
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:
[in] | attributes | specify the regulator instance attributes |
[in,out] | regulator | will point to the regulator instance |
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
Create the output thread Using the priority and stack size attributes specified by the user.
Start the output thread.
The regulator is successfully initialized. Set the initialized field to reflect this and return the instance pointer.
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.
[in] | regulator | is the instance to delete |
[in] | ticks | is the maximum number of ticks to wait for the delivery thread to shutdown. |
Convert external handle to internal instance pointer
There can be no buffers outstanding
Free the resources associated with this regulator instance.
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.
[in] | regulator | is the regulator instance to operate upon |
[in,out] | statistics | points to the statistics structure to fill in |
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_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().
[in] | regulator | is the regulator instance to operate upon |
[out] | buffer | will point to the allocated buffer |
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_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.
[in] | regulator | is the regulator instance to operate upon |
[out] | buffer | will point to the buffer to release |
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_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.
[in] | regulator | is the regulator instance to operate upon |
[out] | message | points to the message to deliver |
[out] | length | is the size of the message in bytes |
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.