![]() |
|
|||
File indexing completed on 2025-05-11 08:24:14
0001 /* SPDX-License-Identifier: BSD-2-Clause */ 0002 0003 /** 0004 * @file 0005 * 0006 * @ingroup RegulatorAPI 0007 * 0008 * @brief This header file defines the Regulator API. 0009 * 0010 */ 0011 0012 /* 0013 * Copyright (C) 2023 On-Line Applications Research Corporation (OAR) 0014 * 0015 * Redistribution and use in source and binary forms, with or without 0016 * modification, are permitted provided that the following conditions 0017 * are met: 0018 * 1. Redistributions of source code must retain the above copyright 0019 * notice, this list of conditions and the following disclaimer. 0020 * 2. Redistributions in binary form must reproduce the above copyright 0021 * notice, this list of conditions and the following disclaimer in the 0022 * documentation and/or other materials provided with the distribution. 0023 * 0024 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 0025 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 0026 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 0027 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 0028 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 0029 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 0030 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 0031 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 0032 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 0033 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 0034 * POSSIBILITY OF SUCH DAMAGE. 0035 */ 0036 0037 /** 0038 * @defgroup RegulatorAPI Regulator API 0039 * 0040 * @brief Regulator APIs 0041 * 0042 * The Regulator provides a set of APIs to manage input sources which 0043 * produces bursts of message traffic. 0044 * 0045 * The regulator is designed to sit logically between two entities -- a 0046 * source and a destination, where it limits the traffic sent to the 0047 * destination to prevent it from being flooded with messages from the 0048 * source. This can be used to accommodate bursts of input from a source 0049 * and meter it out to a destination. The maximum number of messages 0050 * which can be buffered in the regulator is specified by the 0051 * @a maximum_messages field in the @a rtems_regulator_attributes 0052 * structure passed as an argument to @a rtems_regulator_create(). 0053 * 0054 * The regulator library accepts an input stream of messages from a 0055 * source and delivers them to a destination. The regulator assumes that the 0056 * input stream from the source contains sporadic bursts of data which can 0057 * exceed the acceptable rate of the destination. By limiting the message rate, 0058 * the regulator prevents an overflow of messages. 0059 * 0060 * The regulator can be configured for the input buffering required to manage 0061 * the maximum burst and for the metering rate for the output. The output rate 0062 * is in messages per second. If the sender produces data too fast, the 0063 * regulator will buffer the configured number of messages. 0064 * 0065 * A configuration capability is provided to allow for adaptation to different 0066 * message streams. The regulator can also support running multiple instances, 0067 * which could be used on independent message streams. 0068 * 0069 * The regulator provides a simple interface to the application for avoiding 0070 * bursts of input from a fast source overflowing a slower destination. 0071 * 0072 * It is assumed that the application has a design limit on the number of 0073 * messages which may be buffered. All messages accepted by the regulator, 0074 * assuming no overflow on input, will eventually be output by the Delivery 0075 * thread. 0076 * 0077 * A regulator instance is used as follows from the producer/source side: 0078 * 0079 * @code 0080 * while (1) 0081 * use rtems_regulator_obtain_buffer to obtain a buffer 0082 * input operation to fetch data into the buffer 0083 * rtems_regulator_send(buffer, size of message) 0084 * @endcode 0085 * 0086 * The delivery of message buffers to the Destination and subsequent 0087 * release is performed in the context of the delivery thread by either 0088 * the delivery function or delivery thread. Details are below. 0089 * 0090 * The sequence diagram below shows the interaction between a message Source, 0091 * a Regulator instance, and RTEMS, given the usage described in the above 0092 * paragraphs. 0093 * 0094 * \startuml "Regulator Application Input Source Usage" 0095 * Source -> Regulator : rtems_regulator_obtain_buffer(regulator, buffer) 0096 * Regulator -> RTEMS : rtems_partition_get_buffer(id, buffer) 0097 * RTEMS --> Regulator : rtems_status_code 0098 * Regulator --> Source : rtems_status_code 0099 * Source -> Regulator : rtems_regulator_send(regulator, message, length) 0100 * Regulator -> RTEMS : rtems_message_queue_send(id, message, size) 0101 * RTEMS --> Regulator : rtems_status_code 0102 * Regulator --> Source : rtems_status_code 0103 * \enduml 0104 * 0105 * As illustrated in the sequence diagram, the Source usually corresponds 0106 * to application software reading a system input. The Source obtains a 0107 * buffer from the Regulator instance and fills it with incoming data. 0108 * The application explicitly obtaining a buffer and filling it in allows 0109 * for zero copy operations on the Source side. 0110 * 0111 * The Source then sends the buffer to the Regulator instance. The Regulator 0112 * the sends the buffer via a message queue which to the Delivery thread. 0113 * The Delivery thread executes periodically at a rate specified at 0114 * Regulation creation. At each period, the Delivery thread attempts to 0115 * receive up to a configured number of buffers and invoke the Delivery 0116 * function to deliver them to the Destination. 0117 * 0118 * The Delivery function is provided by the application for this 0119 * specific Regulator instance. Depending on the Destination, it may use 0120 * a function which copies the buffer contents (e.g., write()) or which 0121 * operates directly on the buffer contents (e.g. DMA from buffer). In 0122 * the case of a Destination which copies the buffer contents, the buffer 0123 * can be released via @a rtems_regulator_release_buffer() as soon as the 0124 * function or copying completes. In the case where the delivery uses the 0125 * buffer and returns, the call to @a rtems_regulator_release_buffer() 0126 * will occur when the use of the buffer is complete (e.g. completion 0127 * of DMA transfer). This explicit and deliberate exposure of buffering 0128 * provides the application with the ability to avoid copying the contents. 0129 * 0130 * After the Source has sent the message to the Regulator instance, 0131 * the Source is free to process another input and the Regulator 0132 * instance will ensure that the buffer is delivered to the Delivery 0133 * function and Destination. 0134 * 0135 * The Regulator implementation uses the RTEMS Classic API Partition Manager 0136 * to manage the buffer pool and the RTEMS Classic API Message Queue 0137 * Manager to send the buffer to the Delivery thread. 0138 */ 0139 0140 #ifndef REGULATOR_H 0141 #define REGULATOR_H 0142 0143 #include <stdlib.h> 0144 0145 #include <rtems.h> 0146 0147 /** 0148 * @ingroup RegulatorAPI 0149 * 0150 * @brief Regulator Delivery Function Type 0151 * 0152 * The user provides a function which is invoked to deliver a message 0153 * to the output. It is invoked by the Delivery thread created as part 0154 * of @a rtems_regulator_create(). The priority and stack size of the 0155 * Delivery thread are specified in the regulator attribute set. 0156 * 0157 * It takes three parameters: 0158 * 0159 * @param[in] context is an untyped pointer to a user context 0160 * @param[in] message points to the message 0161 * @param[in] length is the message size 0162 * 0163 * The following is an example deliverer function. It assumes that the 0164 * application has defined the my_context_t structure and it has at least 0165 * the socket field. The @a message passed in originated with an 0166 * application source which obtained the @a message buffer using 0167 * @a rtems_regulator_obtain_buffer(), filled it in with source data, 0168 * and used @a rtems_regulator_send() to hand to the regulator instance 0169 * for later delivery. 0170 * 0171 * @code 0172 * bool my_deliverer( 0173 * void *context, 0174 * void *message, 0175 * size_t length 0176 * ) 0177 * { 0178 * my_context_t *my_context; 0179 * 0180 * my_context = (my_context_t *)context; 0181 * 0182 * write(my_context->socket, message, length); 0183 * rtems_regulator_release_buffer(message); 0184 * // return false to indicate we released the buffer 0185 * return false; 0186 * } 0187 * @endcode 0188 * 0189 * The delivery function returns true to indicate that the delivery thread 0190 * should release the buffer or false to indicate that it released the 0191 * buffer. If the delivery function invokes a function like @a write() 0192 * to deliver the message to the destination, then the buffer can be 0193 * released immediately after the call. If the delivery function does 0194 * something like setting up a DMA transfer of the buffer, it cannot be 0195 * released until after the DMA is complete. 0196 * 0197 * The following sequence diagram shows the behavior of the Delivery thread 0198 * body and its interaction with the user-supplied deliverer() function. 0199 * 0200 * \startuml "Regulator Delivery Thread Body" 0201 * loop while (1) 0202 * "Delivery Thread" -> RTEMS : rtems_rate_monotonic_period(id, delivery_thread_period) 0203 * loop for 0 : maximum_to_dequeue_per_period 0204 * "Delivery Thread" -> RTEMS : rtems_message_queue_receive(id, message, size, wait, 0) 0205 * RTEMS --> "Delivery Thread" : rtems_status_code 0206 * group if [rtems_status_code != RTEMS_SUCCESSFUL] 0207 * RTEMS -> "Delivery Thread" : break 0208 * end 0209 * "Delivery Thread" -> Application : deliverer(context, buffer, length) 0210 * "Delivery Thread" -> RTEMS : rtems_partition_return_buffer(id, buffer) 0211 * RTEMS --> "Delivery Thread" : rtems_status_code 0212 * end 0213 * end 0214 * \enduml 0215 * 0216 * In the above sequence diagram, the key points are: 0217 * 0218 * -# The Delivery Thread Body is periodically executed. 0219 * -# During each period, up to the instance configuration parameter 0220 * @a maximum_to_dequeue_per_period may be dequeued and 0221 * passed the application's delivery function for processing. 0222 * 0223 * Note that the application explicitly obtains buffers from the 0224 * regulator instance but that the release may be done by Delivery 0225 * Thread, the Delivery function, or later when the buffer contents 0226 * are transferred. 0227 */ 0228 typedef bool (*rtems_regulator_deliverer)( 0229 void *context, 0230 void *message, 0231 size_t length 0232 ); 0233 0234 /** 0235 * @ingroup RegulatorAPI 0236 * 0237 * @brief Attributes for Regulator Instance 0238 * 0239 * An instance of this structure must be populated by the application 0240 * before creating an instance of the regulator. These settings tailor 0241 * the behavior of the regulator instance. 0242 */ 0243 typedef struct { 0244 /** Application function to invoke to output a message to the destination*/ 0245 rtems_regulator_deliverer deliverer; 0246 0247 /** Context pointer to pass to deliver function */ 0248 void *deliverer_context; 0249 0250 /** Maximum size message to process */ 0251 size_t maximum_message_size; 0252 0253 /** Maximum number of messages to be able to buffer */ 0254 size_t maximum_messages; 0255 0256 /** Priority of Delivery thread */ 0257 rtems_task_priority delivery_thread_priority; 0258 0259 /** Stack size of Delivery thread */ 0260 size_t delivery_thread_stack_size; 0261 0262 /** Period (in ticks) of Delivery thread */ 0263 rtems_interval delivery_thread_period; 0264 0265 /** Maximum messages to dequeue per period */ 0266 size_t maximum_to_dequeue_per_period; 0267 0268 } rtems_regulator_attributes; 0269 0270 /** 0271 * @ingroup RegulatorAPI 0272 * 0273 * @brief Statistics for Regulator Instance 0274 * 0275 * An instance of this structure is provided to the directive 0276 * @a rtems_regulator_get_statistics and is filled in by that service. 0277 */ 0278 typedef struct { 0279 /** Number of successfully obtained buffers. */ 0280 size_t obtained; 0281 0282 /** Number of successfully released buffers. */ 0283 size_t released; 0284 0285 /** Number of successfully delivered buffers. */ 0286 size_t delivered; 0287 0288 /** Rate Monotonic Period statistics for Delivery Thread */ 0289 rtems_rate_monotonic_period_statistics period_statistics; 0290 0291 } rtems_regulator_statistics; 0292 0293 /** 0294 * @ingroup RegulatorAPI 0295 * 0296 * @brief Regulator Internal Structure 0297 */ 0298 struct _Regulator_Control; 0299 0300 /** 0301 * @ingroup RegulatorAPI 0302 * 0303 * @brief Regulator Instance 0304 * 0305 * This is used by the application as the handle to a Regulator instance. 0306 */ 0307 typedef struct _Regulator_Control *rtems_regulator_instance; 0308 0309 /** 0310 * @ingroup RegulatorAPI 0311 * 0312 * @brief Create a regulator 0313 * 0314 * This function creates an instance of a regulator. It uses the provided 0315 * @a attributes to create the instance return in @a regulator. This instance 0316 * will allocate the buffers associated with the regulator instance as well 0317 * as the Delivery thread. 0318 * 0319 * The @a attributes structure defines the priority and stack size of 0320 * the Delivery thread dedicated to this regulator instance. It also 0321 * defines the period of the Delivery thread and the maximum number of 0322 * messages that may be delivered per period via invocation of the 0323 * delivery function. 0324 * 0325 * For each regulator instance, the following resources are allocated: 0326 * 0327 * - A memory area for the regulator control block using @a malloc(). 0328 * - A RTEMS Classic API Message Queue is constructed with message 0329 * buffer memory allocated using @a malloc(). Each message consists 0330 * of a pointer and a length. 0331 * - A RTEMS Classic API Partition. 0332 * - A RTEMS Classic API Rate Monotonic Period. 0333 * 0334 * @param[in] attributes specify the regulator instance attributes 0335 * @param[inout] regulator will point to the regulator instance 0336 * 0337 * @return an RTEMS status code indicating success or failure. 0338 * 0339 * @note This function allocates memory for the buffers holding messages, 0340 * an Delivery thread and an RTEMS partition. When it executes, the 0341 * Delivery thread will create an RTEMS rate monotonic period. 0342 */ 0343 rtems_status_code rtems_regulator_create( 0344 rtems_regulator_attributes *attributes, 0345 rtems_regulator_instance **regulator 0346 ); 0347 0348 /** 0349 * @ingroup RegulatorAPI 0350 * 0351 * @brief Delete a regulator 0352 * 0353 * This function is used to delete the specified @a regulator instance. 0354 * 0355 * It is the responsibility of the user to ensure that any resources 0356 * such as sockets or open file descriptors used by the delivery 0357 * function are also deleted. It is likely safer to delete those 0358 * delivery resources after deleting the regulator instance rather than 0359 * before. 0360 * 0361 * @param[in] regulator is the instance to delete 0362 * @param[in] ticks is the maximum number of ticks to wait for 0363 * the delivery thread to shutdown. 0364 * 0365 * @return an RTEMS status code indicating success or failure. 0366 * 0367 * @note This function deallocates the resources allocated during 0368 * @a rtems_regulator_create(). 0369 */ 0370 rtems_status_code rtems_regulator_delete( 0371 rtems_regulator_instance *regulator, 0372 rtems_interval ticks 0373 ); 0374 0375 /** 0376 * @ingroup RegulatorAPI 0377 * 0378 * @brief Obtain Buffer from Regulator 0379 * 0380 * This function is used to obtain a buffer from the regulator's pool. The 0381 * @a buffer returned is assumed to be filled in with contents and used 0382 * in a subsequent call to @a rtems_regulator_send(). When the @a buffer is 0383 * delivered, it is expected to be released. If the @a buffer is not 0384 * successfully accepted by this function, then it should be returned 0385 * using @a rtems_regulator_release_buffer() or used to send another message. 0386 * 0387 * The @a buffer is of the maximum_message_size specified in the attributes 0388 * passed in to @a rtems_regulator_create(). 0389 * 0390 * @param[in] regulator is the regulator instance to operate upon 0391 * @param[out] buffer will point to the allocated buffer 0392 * 0393 * @return an RTEMS status code indicating success or failure. 0394 * 0395 * @note This function does not perform dynamic allocation. It obtains a 0396 * buffer from the pool allocated during @a rtems_regulator_create(). 0397 * 0398 * @note Any attempt to write outside the buffer area is undefined. 0399 */ 0400 rtems_status_code rtems_regulator_obtain_buffer( 0401 rtems_regulator_instance *regulator, 0402 void **buffer 0403 ); 0404 0405 /** 0406 * @ingroup RegulatorAPI 0407 * 0408 * @brief Release Previously Obtained Regulator Buffer 0409 * 0410 * This function is used to release a buffer to the regulator's pool. It is 0411 * assumed that the @a buffer returned will not be used by the application 0412 * anymore. The @a buffer must have previously been allocated by 0413 * @a rtems_regulator_obtain_buffer() and NOT passed to 0414 * @a rtems_regulator_send(). 0415 * 0416 * If a subsequent @a rtems_regulator_send() using this @a buffer is 0417 * successful, the @a buffer will eventually be processed by the delivery 0418 * thread and released. 0419 * 0420 * @param[in] regulator is the regulator instance to operate upon 0421 * @param[out] buffer will point to the buffer to release 0422 * 0423 * @return an RTEMS status code indicating success or failure. 0424 * 0425 * @note This function does not perform dynamic deallocation. It releases a 0426 * buffer to the pool allocated during @a rtems_regulator_create(). 0427 */ 0428 rtems_status_code rtems_regulator_release_buffer( 0429 rtems_regulator_instance *regulator, 0430 void *buffer 0431 ); 0432 0433 /** 0434 * @ingroup RegulatorAPI 0435 * 0436 * @brief Send to regulator instance 0437 * 0438 * This function is used by the producer to send a @a message to the 0439 * @a regulator for later delivery by the Delivery thread. The message is 0440 * contained in the memory pointed to by @a message and is @a length 0441 * bytes in length. 0442 * 0443 * It is required that the @a message buffer was obtained via 0444 * @a rtems_regulator_obtain_buffer(). 0445 * 0446 * It is assumed that the @a message buffer has been filled in with 0447 * application content to deliver. 0448 * 0449 * If the @a rtems_regulator_send() is successful, the buffer is enqueued 0450 * inside the regulator instance for subsequent delivery. After the 0451 * @a message is delivered, it may be released by either delivery 0452 * function or the application code depending on the implementation. 0453 * 0454 * The status @a RTEMS_TOO_MANY is returned if the regulator's 0455 * internal queue is full. This indicates that the configured 0456 * maximum number of messages was insufficient. It is the 0457 * responsibility of the caller to decide whether to hold messages, 0458 * drop them, or print a message that the maximum number of messages 0459 * should be increased. 0460 * 0461 * If @a rtems_regulator_send() is unsuccessful, it is the application's 0462 * responsibility to release the buffer. If it is successfully sent, 0463 * then it becomes the responsibility of the delivery function to 0464 * release it. 0465 * 0466 * @param[in] regulator is the regulator instance to operate upon 0467 * @param[out] message points to the message to deliver 0468 * @param[out] length is the size of the message in bytes 0469 * 0470 * @return an RTEMS status code indicating success or failure. 0471 * 0472 */ 0473 rtems_status_code rtems_regulator_send( 0474 rtems_regulator_instance *regulator, 0475 void *message, 0476 size_t length 0477 ); 0478 0479 /** 0480 * @ingroup RegulatorAPI 0481 * 0482 * @brief Obtain statistics for regulator instance 0483 * 0484 * This function is used by the application to obtain statistics 0485 * information about the regulator instance. 0486 * 0487 * If the @a obtained and @a released fields in the returned 0488 * @a statistics structure are equal, then there are no buffers 0489 * outstanding from this regulator instance. 0490 * 0491 * @param[in] regulator is the regulator instance to operate upon 0492 * @param[inout] statistics points to the statistics structure to fill in 0493 * 0494 * @return an RTEMS status code indicating success or failure. 0495 * 0496 */ 0497 rtems_status_code rtems_regulator_get_statistics( 0498 rtems_regulator_instance *regulator, 0499 rtems_regulator_statistics *statistics 0500 ); 0501 0502 #endif /* REGULATOR_H */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |