LCOV - code coverage report
Current view: top level - zephyr/sys - notify.h Coverage Total Hit
Test: new.info Lines: 40.0 % 25 10
Test Date: 2025-09-05 16:43:28

            Line data    Source code
       1            0 : /*
       2              :  * Copyright (c) 2019 Peter Bigot Consulting, LLC
       3              :  * Copyright (c) 2020 Nordic Semiconductor ASA
       4              :  *
       5              :  * SPDX-License-Identifier: Apache-2.0
       6              :  */
       7              : 
       8              : #ifndef ZEPHYR_INCLUDE_SYS_NOTIFY_H_
       9              : #define ZEPHYR_INCLUDE_SYS_NOTIFY_H_
      10              : 
      11              : #include <zephyr/kernel.h>
      12              : #include <zephyr/types.h>
      13              : 
      14              : #ifdef __cplusplus
      15              : extern "C" {
      16              : #endif
      17              : 
      18              : struct sys_notify;
      19              : 
      20              : /*
      21              :  * Flag value that overwrites the method field when the operation has
      22              :  * completed.
      23              :  */
      24            0 : #define SYS_NOTIFY_METHOD_COMPLETED 0
      25              : 
      26              : /*
      27              :  * Indicates that no notification will be provided.
      28              :  *
      29              :  * Callers must check for completions using
      30              :  * sys_notify_fetch_result().
      31              :  *
      32              :  * See sys_notify_init_spinwait().
      33              :  */
      34            0 : #define SYS_NOTIFY_METHOD_SPINWAIT 1
      35              : 
      36              : /*
      37              :  * Select notification through @ref k_poll signal
      38              :  *
      39              :  * See sys_notify_init_signal().
      40              :  */
      41            0 : #define SYS_NOTIFY_METHOD_SIGNAL 2
      42              : 
      43              : /*
      44              :  * Select notification through a user-provided callback.
      45              :  *
      46              :  * See sys_notify_init_callback().
      47              :  */
      48            0 : #define SYS_NOTIFY_METHOD_CALLBACK 3
      49              : 
      50            0 : #define SYS_NOTIFY_METHOD_MASK 0x03U
      51            0 : #define SYS_NOTIFY_METHOD_POS 0
      52              : 
      53              : /**
      54              :  * @brief Identify the region of sys_notify flags available for
      55              :  * containing services.
      56              :  *
      57              :  * Bits of the flags field of the sys_notify structure at and above
      58              :  * this position may be used by extensions to the sys_notify
      59              :  * structure.
      60              :  *
      61              :  * These bits are intended for use by containing service
      62              :  * implementations to record client-specific information.  The bits
      63              :  * are cleared by sys_notify_validate().  Use of these does not
      64              :  * imply that the flags field becomes public API.
      65              :  */
      66            1 : #define SYS_NOTIFY_EXTENSION_POS 2
      67              : 
      68              : /*
      69              :  * Mask isolating the bits of sys_notify::flags that are available
      70              :  * for extension.
      71              :  */
      72            0 : #define SYS_NOTIFY_EXTENSION_MASK (~BIT_MASK(SYS_NOTIFY_EXTENSION_POS))
      73              : 
      74              : /**
      75              :  * @defgroup sys_notify_apis Asynchronous Notification APIs
      76              :  * @ingroup os_services
      77              :  * @{
      78              :  */
      79              : 
      80              : /**
      81              :  * @brief Generic signature used to notify of result completion by
      82              :  * callback.
      83              :  *
      84              :  * Functions with this role may be invoked from any context including
      85              :  * pre-kernel, ISR, or cooperative or pre-emptible threads.
      86              :  * Compatible functions must be isr-ok and not sleep.
      87              :  *
      88              :  * Parameters that should generally be passed to such functions include:
      89              :  *
      90              :  * * a pointer to a specific client request structure, i.e. the one
      91              :  *   that contains the sys_notify structure.
      92              :  * * the result of the operation, either as passed to
      93              :  *   sys_notify_finalize() or extracted afterwards using
      94              :  *   sys_notify_fetch_result().  Expected values are
      95              :  *   service-specific, but the value shall be non-negative if the
      96              :  *   operation succeeded, and negative if the operation failed.
      97              :  */
      98            1 : typedef void (*sys_notify_generic_callback)();
      99              : 
     100              : /**
     101              :  * @brief State associated with notification for an asynchronous
     102              :  * operation.
     103              :  *
     104              :  * Objects of this type are allocated by a client, which must use an
     105              :  * initialization function (e.g. sys_notify_init_signal()) to
     106              :  * configure them.  Generally the structure is a member of a
     107              :  * service-specific client structure, such as onoff_client.
     108              :  *
     109              :  * Control of the containing object transfers to the service provider
     110              :  * when a pointer to the object is passed to a service function that
     111              :  * is documented to take control of the object, such as
     112              :  * onoff_service_request().  While the service provider controls the
     113              :  * object the client must not change any object fields.  Control
     114              :  * reverts to the client:
     115              :  * * if the call to the service API returns an error;
     116              :  * * when operation completion is posted.  This may occur before the
     117              :  *   call to the service API returns.
     118              :  *
     119              :  * Operation completion is technically posted when the flags field is
     120              :  * updated so that sys_notify_fetch_result() returns success.  This
     121              :  * will happen before the signal is posted or callback is invoked.
     122              :  * Note that although the manager will no longer reference the
     123              :  * sys_notify object past this point, the containing object may have
     124              :  * state that will be referenced within the callback.  Where callbacks
     125              :  * are used control of the containing object does not revert to the
     126              :  * client until the callback has been invoked.  (Re-use within the
     127              :  * callback is explicitly permitted.)
     128              :  *
     129              :  * After control has reverted to the client the notify object must be
     130              :  * reinitialized for the next operation.
     131              :  *
     132              :  * The content of this structure is not public API to clients: all
     133              :  * configuration and inspection should be done with functions like
     134              :  * sys_notify_init_callback() and sys_notify_fetch_result().
     135              :  * However, services that use this structure may access certain
     136              :  * fields directly.
     137              :  */
     138            1 : struct sys_notify {
     139            0 :         union method {
     140              :                 /* Pointer to signal used to notify client.
     141              :                  *
     142              :                  * The signal value corresponds to the res parameter
     143              :                  * of sys_notify_callback.
     144              :                  */
     145            0 :                 struct k_poll_signal *signal;
     146              : 
     147              :                 /* Generic callback function for callback notification. */
     148            0 :                 sys_notify_generic_callback callback;
     149            0 :         } method;
     150              : 
     151              :         /*
     152              :          * Flags recording information about the operation.
     153              :          *
     154              :          * Bits below SYS_NOTIFY_EXTENSION_POS are initialized by
     155              :          * async notify API init functions like
     156              :          * sys_notify_init_callback(), and must not by modified by
     157              :          * extensions or client code.
     158              :          *
     159              :          * Bits at and above SYS_NOTIFY_EXTENSION_POS are available
     160              :          * for use by service extensions while the containing object
     161              :          * is managed by the service.  They are not for client use,
     162              :          * are zeroed by the async notify API init functions, and will
     163              :          * be zeroed by sys_notify_finalize().
     164              :          */
     165            0 :         uint32_t volatile flags;
     166              : 
     167              :         /*
     168              :          * The result of the operation.
     169              :          *
     170              :          * This is the value that was (or would be) passed to the
     171              :          * async infrastructure.  This field is the sole record of
     172              :          * success or failure for spin-wait synchronous operations.
     173              :          */
     174            0 :         int volatile result;
     175              : };
     176              : 
     177              : /** @internal */
     178            0 : static inline uint32_t sys_notify_get_method(const struct sys_notify *notify)
     179              : {
     180              :         uint32_t method = notify->flags >> SYS_NOTIFY_METHOD_POS;
     181              : 
     182              :         return method & SYS_NOTIFY_METHOD_MASK;
     183              : }
     184              : 
     185              : /**
     186              :  * @brief Validate and initialize the notify structure.
     187              :  *
     188              :  * This should be invoked at the start of any service-specific
     189              :  * configuration validation.  It ensures that the basic asynchronous
     190              :  * notification configuration is consistent, and clears the result.
     191              :  *
     192              :  * Note that this function does not validate extension bits (zeroed by
     193              :  * async notify API init functions like sys_notify_init_callback()).
     194              :  * It may fail to recognize that an uninitialized structure has been
     195              :  * passed because only method bits of flags are tested against method
     196              :  * settings.  To reduce the chance of accepting an uninitialized
     197              :  * operation service validation of structures that contain an
     198              :  * sys_notify instance should confirm that the extension bits are
     199              :  * set or cleared as expected.
     200              :  *
     201              :  * @retval 0 on successful validation and reinitialization
     202              :  * @retval -EINVAL if the configuration is not valid.
     203              :  */
     204            1 : int sys_notify_validate(struct sys_notify *notify);
     205              : 
     206              : /**
     207              :  * @brief Record and signal the operation completion.
     208              :  *
     209              :  * @param notify pointer to the notification state structure.
     210              :  *
     211              :  * @param res the result of the operation.  Expected values are
     212              :  * service-specific, but the value shall be non-negative if the
     213              :  * operation succeeded, and negative if the operation failed.
     214              :  *
     215              :  * @return If the notification is to be done by callback this returns
     216              :  * the generic version of the function to be invoked.  The caller must
     217              :  * immediately invoke that function with whatever arguments are
     218              :  * expected by the callback.  If notification is by spin-wait or
     219              :  * signal, the notification has been completed by the point this
     220              :  * function returns, and a null pointer is returned.
     221              :  */
     222            1 : sys_notify_generic_callback sys_notify_finalize(struct sys_notify *notify,
     223              :                                                     int res);
     224              : 
     225              : /**
     226              :  * @brief Check for and read the result of an asynchronous operation.
     227              :  *
     228              :  * @param notify pointer to the object used to specify asynchronous
     229              :  * function behavior and store completion information.
     230              :  *
     231              :  * @param result pointer to storage for the result of the operation.
     232              :  * The result is stored only if the operation has completed.
     233              :  *
     234              :  * @retval 0 if the operation has completed.
     235              :  * @retval -EAGAIN if the operation has not completed.
     236              :  */
     237            1 : static inline int sys_notify_fetch_result(const struct sys_notify *notify,
     238              :                                             int *result)
     239              : {
     240              :         __ASSERT_NO_MSG(notify != NULL);
     241              :         __ASSERT_NO_MSG(result != NULL);
     242              :         int rv = -EAGAIN;
     243              : 
     244              :         if (sys_notify_get_method(notify) == SYS_NOTIFY_METHOD_COMPLETED) {
     245              :                 rv = 0;
     246              :                 *result = notify->result;
     247              :         }
     248              : 
     249              :         return rv;
     250              : }
     251              : 
     252              : /**
     253              :  * @brief Initialize a notify object for spin-wait notification.
     254              :  *
     255              :  * Clients that use this initialization receive no asynchronous
     256              :  * notification, and instead must periodically check for completion
     257              :  * using sys_notify_fetch_result().
     258              :  *
     259              :  * On completion of the operation the client object must be
     260              :  * reinitialized before it can be re-used.
     261              :  *
     262              :  * @param notify pointer to the notification configuration object.
     263              :  */
     264            1 : static inline void sys_notify_init_spinwait(struct sys_notify *notify)
     265              : {
     266              :         __ASSERT_NO_MSG(notify != NULL);
     267              : 
     268              :         *notify = (struct sys_notify){
     269              :                 .flags = SYS_NOTIFY_METHOD_SPINWAIT,
     270              :         };
     271              : }
     272              : 
     273              : /**
     274              :  * @brief Initialize a notify object for (k_poll) signal notification.
     275              :  *
     276              :  * Clients that use this initialization will be notified of the
     277              :  * completion of operations through the provided signal.
     278              :  *
     279              :  * On completion of the operation the client object must be
     280              :  * reinitialized before it can be re-used.
     281              :  *
     282              :  * @note
     283              :  *   This capability is available only when @kconfig{CONFIG_POLL} is
     284              :  *   selected.
     285              :  *
     286              :  * @param notify pointer to the notification configuration object.
     287              :  *
     288              :  * @param sigp pointer to the signal to use for notification.  The
     289              :  * value must not be null.  The signal must be reset before the client
     290              :  * object is passed to the on-off service API.
     291              :  */
     292            1 : static inline void sys_notify_init_signal(struct sys_notify *notify,
     293              :                                             struct k_poll_signal *sigp)
     294              : {
     295              :         __ASSERT_NO_MSG(notify != NULL);
     296              :         __ASSERT_NO_MSG(sigp != NULL);
     297              : 
     298              :         *notify = (struct sys_notify){
     299              :                 .method = {
     300              :                         .signal = sigp,
     301              :                 },
     302              :                 .flags = SYS_NOTIFY_METHOD_SIGNAL,
     303              :         };
     304              : }
     305              : 
     306              : /**
     307              :  * @brief Initialize a notify object for callback notification.
     308              :  *
     309              :  * Clients that use this initialization will be notified of the
     310              :  * completion of operations through the provided callback.  Note that
     311              :  * callbacks may be invoked from various contexts depending on the
     312              :  * specific service; see @ref sys_notify_generic_callback.
     313              :  *
     314              :  * On completion of the operation the client object must be
     315              :  * reinitialized before it can be re-used.
     316              :  *
     317              :  * @param notify pointer to the notification configuration object.
     318              :  *
     319              :  * @param handler a function pointer to use for notification.
     320              :  */
     321            1 : static inline void sys_notify_init_callback(struct sys_notify *notify,
     322              :                                               sys_notify_generic_callback handler)
     323              : {
     324              :         __ASSERT_NO_MSG(notify != NULL);
     325              :         __ASSERT_NO_MSG(handler != NULL);
     326              : 
     327              :         *notify = (struct sys_notify){
     328              :                 .method = {
     329              :                         .callback = handler,
     330              :                 },
     331              :                 .flags = SYS_NOTIFY_METHOD_CALLBACK,
     332              :         };
     333              : }
     334              : 
     335              : /**
     336              :  * @brief Detect whether a particular notification uses a callback.
     337              :  *
     338              :  * The generic handler does not capture the signature expected by the
     339              :  * callback, and the translation to a service-specific callback must
     340              :  * be provided by the service.  This check allows abstracted services
     341              :  * to reject callback notification requests when the service doesn't
     342              :  * provide a translation function.
     343              :  *
     344              :  * @return true if and only if a callback is to be used for notification.
     345              :  */
     346            1 : static inline bool sys_notify_uses_callback(const struct sys_notify *notify)
     347              : {
     348              :         __ASSERT_NO_MSG(notify != NULL);
     349              : 
     350              :         return sys_notify_get_method(notify) == SYS_NOTIFY_METHOD_CALLBACK;
     351              : }
     352              : 
     353              : /** @} */
     354              : 
     355              : #ifdef __cplusplus
     356              : }
     357              : #endif
     358              : 
     359              : #endif /* ZEPHYR_INCLUDE_SYS_NOTIFY_H_ */
        

Generated by: LCOV version 2.0-1