LCOV - code coverage report
Current view: top level - include/zephyr/sys - notify.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 7 7 100.0 %
Date: 2022-08-18 11:36:24 Functions: 2 2 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 1 2 50.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       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 <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                 :            : #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                 :            : #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                 :            : #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                 :            : #define SYS_NOTIFY_METHOD_CALLBACK 3
      49                 :            : 
      50                 :            : #define SYS_NOTIFY_METHOD_MASK 0x03U
      51                 :            : #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                 :            : #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                 :            : #define SYS_NOTIFY_EXTENSION_MASK (~BIT_MASK(SYS_NOTIFY_EXTENSION_POS))
      73                 :            : 
      74                 :            : /**
      75                 :            :  * @defgroup sys_notify_apis Asynchronous Notification APIs
      76                 :            :  * @ingroup kernel_apis
      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                 :            : 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                 :            : struct sys_notify {
     139                 :            :         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                 :            :                 struct k_poll_signal *signal;
     146                 :            : 
     147                 :            :                 /* Generic callback function for callback notification. */
     148                 :            :                 sys_notify_generic_callback callback;
     149                 :            :         } 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                 :            :         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                 :            :         int volatile result;
     175                 :            : };
     176                 :            : 
     177                 :            : /** @internal */
     178                 :          2 : static inline uint32_t sys_notify_get_method(const struct sys_notify *notify)
     179                 :            : {
     180                 :          2 :         uint32_t method = notify->flags >> SYS_NOTIFY_METHOD_POS;
     181                 :            : 
     182                 :          2 :         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                 :            : 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                 :            : 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                 :            : 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         [ -  + ]:          1 :         __ASSERT_NO_MSG(notify != NULL);
     267                 :            : 
     268                 :          1 :         *notify = (struct sys_notify){
     269                 :            :                 .flags = SYS_NOTIFY_METHOD_SPINWAIT,
     270                 :            :         };
     271                 :          1 : }
     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                 :            : 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                 :            : 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                 :            : 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 1.14