LCOV - code coverage report
Current view: top level - zephyr/sys - sflist.h Hit Total Coverage
Test: new.info Lines: 31 33 93.9 %
Date: 2024-12-22 00:14:23

          Line data    Source code
       1           0 : /*
       2             :  * Copyright (c) 2016 Intel Corporation
       3             :  *
       4             :  * SPDX-License-Identifier: Apache-2.0
       5             :  */
       6             : 
       7             :  /**
       8             :   * @file
       9             :   * @defgroup flagged-single-linked-list_apis Flagged Single-linked list
      10             :   * @ingroup datastructure_apis
      11             :   *
      12             :   * @brief Flagged single-linked list implementation.
      13             :   *
      14             :   * Similar to @ref single-linked-list_apis with the added ability to define
      15             :   * user "flags" bits for each node. They can be accessed and modified
      16             :   * using the sys_sfnode_flags_get() and sys_sfnode_flags_set() APIs.
      17             :   *
      18             :   * Flagged single-linked list implementation using inline macros/functions.
      19             :   * This API is not thread safe, and thus if a list is used across threads,
      20             :   * calls to functions must be protected with synchronization primitives.
      21             :   *
      22             :   * @{
      23             :   */
      24             : 
      25             : #ifndef ZEPHYR_INCLUDE_SYS_SFLIST_H_
      26             : #define ZEPHYR_INCLUDE_SYS_SFLIST_H_
      27             : 
      28             : #include <stdint.h>
      29             : #include <stdbool.h>
      30             : #include <zephyr/sys/__assert.h>
      31             : #include "list_gen.h"
      32             : 
      33             : #ifdef __cplusplus
      34             : extern "C" {
      35             : #endif
      36             : 
      37             : /** @cond INTERNAL_HIDDEN */
      38             : struct _sfnode {
      39             :         uintptr_t next_and_flags;
      40             : };
      41             : /** @endcond */
      42             : 
      43             : /** Flagged single-linked list node structure. */
      44           1 : typedef struct _sfnode sys_sfnode_t;
      45             : 
      46             : /** @cond INTERNAL_HIDDEN */
      47             : struct _sflist {
      48             :         sys_sfnode_t *head;
      49             :         sys_sfnode_t *tail;
      50             : };
      51             : /** @endcond */
      52             : 
      53             : /** Flagged single-linked list structure. */
      54           1 : typedef struct _sflist sys_sflist_t;
      55             : 
      56             : /**
      57             :  * @brief Provide the primitive to iterate on a list
      58             :  * Note: the loop is unsafe and thus __sn should not be removed
      59             :  *
      60             :  * User _MUST_ add the loop statement curly braces enclosing its own code:
      61             :  *
      62             :  *     SYS_SFLIST_FOR_EACH_NODE(l, n) {
      63             :  *         <user code>
      64             :  *     }
      65             :  *
      66             :  * This and other SYS_SFLIST_*() macros are not thread safe.
      67             :  *
      68             :  * @param __sl A pointer on a sys_sflist_t to iterate on
      69             :  * @param __sn A sys_sfnode_t pointer to peek each node of the list
      70             :  */
      71           1 : #define SYS_SFLIST_FOR_EACH_NODE(__sl, __sn)                            \
      72             :         Z_GENLIST_FOR_EACH_NODE(sflist, __sl, __sn)
      73             : 
      74             : /**
      75             :  * @brief Provide the primitive to iterate on a list, from a node in the list
      76             :  * Note: the loop is unsafe and thus __sn should not be removed
      77             :  *
      78             :  * User _MUST_ add the loop statement curly braces enclosing its own code:
      79             :  *
      80             :  *     SYS_SFLIST_ITERATE_FROM_NODE(l, n) {
      81             :  *         <user code>
      82             :  *     }
      83             :  *
      84             :  * Like SYS_SFLIST_FOR_EACH_NODE(), but __dn already contains a node in the list
      85             :  * where to start searching for the next entry from. If NULL, it starts from
      86             :  * the head.
      87             :  *
      88             :  * This and other SYS_SFLIST_*() macros are not thread safe.
      89             :  *
      90             :  * @param __sl A pointer on a sys_sflist_t to iterate on
      91             :  * @param __sn A sys_sfnode_t pointer to peek each node of the list
      92             :  *             it contains the starting node, or NULL to start from the head
      93             :  */
      94           1 : #define SYS_SFLIST_ITERATE_FROM_NODE(__sl, __sn)                                \
      95             :         Z_GENLIST_ITERATE_FROM_NODE(sflist, __sl, __sn)
      96             : 
      97             : /**
      98             :  * @brief Provide the primitive to safely iterate on a list
      99             :  * Note: __sn can be removed, it will not break the loop.
     100             :  *
     101             :  * User _MUST_ add the loop statement curly braces enclosing its own code:
     102             :  *
     103             :  *     SYS_SFLIST_FOR_EACH_NODE_SAFE(l, n, s) {
     104             :  *         <user code>
     105             :  *     }
     106             :  *
     107             :  * This and other SYS_SFLIST_*() macros are not thread safe.
     108             :  *
     109             :  * @param __sl A pointer on a sys_sflist_t to iterate on
     110             :  * @param __sn A sys_sfnode_t pointer to peek each node of the list
     111             :  * @param __sns A sys_sfnode_t pointer for the loop to run safely
     112             :  */
     113           1 : #define SYS_SFLIST_FOR_EACH_NODE_SAFE(__sl, __sn, __sns)                        \
     114             :         Z_GENLIST_FOR_EACH_NODE_SAFE(sflist, __sl, __sn, __sns)
     115             : 
     116             : /**
     117             :  * @brief Provide the primitive to resolve the container of a list node
     118             :  * Note: it is safe to use with NULL pointer nodes
     119             :  *
     120             :  * @param __ln A pointer on a sys_sfnode_t to get its container
     121             :  * @param __cn Container struct type pointer
     122             :  * @param __n The field name of sys_sfnode_t within the container struct
     123             :  */
     124           1 : #define SYS_SFLIST_CONTAINER(__ln, __cn, __n) \
     125             :         Z_GENLIST_CONTAINER(__ln, __cn, __n)
     126             : 
     127             : /**
     128             :  * @brief Provide the primitive to peek container of the list head
     129             :  *
     130             :  * @param __sl A pointer on a sys_sflist_t to peek
     131             :  * @param __cn Container struct type pointer
     132             :  * @param __n The field name of sys_sfnode_t within the container struct
     133             :  */
     134           1 : #define SYS_SFLIST_PEEK_HEAD_CONTAINER(__sl, __cn, __n) \
     135             :         Z_GENLIST_PEEK_HEAD_CONTAINER(sflist, __sl, __cn, __n)
     136             : 
     137             : /**
     138             :  * @brief Provide the primitive to peek container of the list tail
     139             :  *
     140             :  * @param __sl A pointer on a sys_sflist_t to peek
     141             :  * @param __cn Container struct type pointer
     142             :  * @param __n The field name of sys_sfnode_t within the container struct
     143             :  */
     144           1 : #define SYS_SFLIST_PEEK_TAIL_CONTAINER(__sl, __cn, __n) \
     145             :         Z_GENLIST_PEEK_TAIL_CONTAINER(sflist, __sl, __cn, __n)
     146             : 
     147             : /**
     148             :  * @brief Provide the primitive to peek the next container
     149             :  *
     150             :  * @param __cn Container struct type pointer
     151             :  * @param __n The field name of sys_sfnode_t within the container struct
     152             :  */
     153           1 : #define SYS_SFLIST_PEEK_NEXT_CONTAINER(__cn, __n) \
     154             :         Z_GENLIST_PEEK_NEXT_CONTAINER(sflist, __cn, __n)
     155             : 
     156             : /**
     157             :  * @brief Provide the primitive to iterate on a list under a container
     158             :  * Note: the loop is unsafe and thus __cn should not be detached
     159             :  *
     160             :  * User _MUST_ add the loop statement curly braces enclosing its own code:
     161             :  *
     162             :  *     SYS_SFLIST_FOR_EACH_CONTAINER(l, c, n) {
     163             :  *         <user code>
     164             :  *     }
     165             :  *
     166             :  * @param __sl A pointer on a sys_sflist_t to iterate on
     167             :  * @param __cn A pointer to peek each entry of the list
     168             :  * @param __n The field name of sys_sfnode_t within the container struct
     169             :  */
     170           1 : #define SYS_SFLIST_FOR_EACH_CONTAINER(__sl, __cn, __n)                  \
     171             :         Z_GENLIST_FOR_EACH_CONTAINER(sflist, __sl, __cn, __n)
     172             : 
     173             : /**
     174             :  * @brief Provide the primitive to safely iterate on a list under a container
     175             :  * Note: __cn can be detached, it will not break the loop.
     176             :  *
     177             :  * User _MUST_ add the loop statement curly braces enclosing its own code:
     178             :  *
     179             :  *     SYS_SFLIST_FOR_EACH_NODE_SAFE(l, c, cn, n) {
     180             :  *         <user code>
     181             :  *     }
     182             :  *
     183             :  * @param __sl A pointer on a sys_sflist_t to iterate on
     184             :  * @param __cn A pointer to peek each entry of the list
     185             :  * @param __cns A pointer for the loop to run safely
     186             :  * @param __n The field name of sys_sfnode_t within the container struct
     187             :  */
     188           1 : #define SYS_SFLIST_FOR_EACH_CONTAINER_SAFE(__sl, __cn, __cns, __n)      \
     189             :         Z_GENLIST_FOR_EACH_CONTAINER_SAFE(sflist, __sl, __cn, __cns, __n)
     190             : 
     191             : 
     192             : /*
     193             :  * Required function definitions for the list_gen.h interface
     194             :  *
     195             :  * These are the only functions that do not treat the list/node pointers
     196             :  * as completely opaque types.
     197             :  */
     198             : 
     199             : /**
     200             :  * @brief Initialize a list
     201             :  *
     202             :  * @param list A pointer on the list to initialize
     203             :  */
     204           1 : static inline void sys_sflist_init(sys_sflist_t *list)
     205             : {
     206             :         list->head = NULL;
     207             :         list->tail = NULL;
     208             : }
     209             : 
     210             : /**
     211             :  * @brief Statically initialize a flagged single-linked list
     212             :  * @param ptr_to_list A pointer on the list to initialize
     213             :  */
     214           1 : #define SYS_SFLIST_STATIC_INIT(ptr_to_list) {NULL, NULL}
     215             : 
     216             : /* Flag bits are stored in unused LSB of the sys_sfnode_t pointer */
     217           0 : #define SYS_SFLIST_FLAGS_MASK   ((uintptr_t)(__alignof__(sys_sfnode_t) - 1))
     218             : /* At least 2 available flag bits are expected */
     219             : BUILD_ASSERT(SYS_SFLIST_FLAGS_MASK >= 0x3);
     220             : 
     221             : static inline sys_sfnode_t *z_sfnode_next_peek(sys_sfnode_t *node)
     222             : {
     223             :         return (sys_sfnode_t *)(node->next_and_flags & ~SYS_SFLIST_FLAGS_MASK);
     224             : }
     225             : 
     226             : static inline uint8_t sys_sfnode_flags_get(sys_sfnode_t *node);
     227             : 
     228             : static inline void z_sfnode_next_set(sys_sfnode_t *parent,
     229             :                                        sys_sfnode_t *child)
     230             : {
     231             :         uint8_t cur_flags = sys_sfnode_flags_get(parent);
     232             : 
     233             :         parent->next_and_flags = cur_flags | (uintptr_t)child;
     234             : }
     235             : 
     236             : static inline void z_sflist_head_set(sys_sflist_t *list, sys_sfnode_t *node)
     237             : {
     238             :         list->head = node;
     239             : }
     240             : 
     241             : static inline void z_sflist_tail_set(sys_sflist_t *list, sys_sfnode_t *node)
     242             : {
     243             :         list->tail = node;
     244             : }
     245             : 
     246             : /**
     247             :  * @brief Peek the first node from the list
     248             :  *
     249             :  * @param list A point on the list to peek the first node from
     250             :  *
     251             :  * @return A pointer on the first node of the list (or NULL if none)
     252             :  */
     253           1 : static inline sys_sfnode_t *sys_sflist_peek_head(sys_sflist_t *list)
     254             : {
     255             :         return list->head;
     256             : }
     257             : 
     258             : /**
     259             :  * @brief Peek the last node from the list
     260             :  *
     261             :  * @param list A point on the list to peek the last node from
     262             :  *
     263             :  * @return A pointer on the last node of the list (or NULL if none)
     264             :  */
     265           1 : static inline sys_sfnode_t *sys_sflist_peek_tail(sys_sflist_t *list)
     266             : {
     267             :         return list->tail;
     268             : }
     269             : 
     270             : /*
     271             :  * APIs specific to sflist type
     272             :  */
     273             : 
     274             : /**
     275             :  * @brief Fetch flags value for a particular sfnode
     276             :  *
     277             :  * @param node A pointer to the node to fetch flags from
     278             :  * @return The value of flags, which will be between 0 and 3 on 32-bit
     279             :  *         architectures, or between 0 and 7 on 64-bit architectures
     280             :  */
     281           1 : static inline uint8_t sys_sfnode_flags_get(sys_sfnode_t *node)
     282             : {
     283             :         return node->next_and_flags & SYS_SFLIST_FLAGS_MASK;
     284             : }
     285             : 
     286             : /**
     287             :  * @brief Initialize an sflist node
     288             :  *
     289             :  * Set an initial flags value for this slist node, which can be a value between
     290             :  * 0 and 3 on 32-bit architectures, or between 0 and 7 on 64-bit architectures.
     291             :  * These flags will persist even if the node is moved around within a list,
     292             :  * removed, or transplanted to a different slist.
     293             :  *
     294             :  * This is ever so slightly faster than sys_sfnode_flags_set() and should
     295             :  * only be used on a node that hasn't been added to any list.
     296             :  *
     297             :  * @param node A pointer to the node to set the flags on
     298             :  * @param flags The flags value to set
     299             :  */
     300           1 : static inline void sys_sfnode_init(sys_sfnode_t *node, uint8_t flags)
     301             : {
     302             :         __ASSERT((flags & ~SYS_SFLIST_FLAGS_MASK) == 0UL, "flags too large");
     303             :         node->next_and_flags = flags;
     304             : }
     305             : 
     306             : /**
     307             :  * @brief Set flags value for an sflist node
     308             :  *
     309             :  * Set a flags value for this slist node, which can be a value between
     310             :  * 0 and 3 on 32-bit architectures, or between 0 and 7 on 64-bit architectures.
     311             :  * These flags will persist even if the node is moved around within a list,
     312             :  * removed, or transplanted to a different slist.
     313             :  *
     314             :  * @param node A pointer to the node to set the flags on
     315             :  * @param flags The flags value to set
     316             :  */
     317           1 : static inline void sys_sfnode_flags_set(sys_sfnode_t *node, uint8_t flags)
     318             : {
     319             :         __ASSERT((flags & ~SYS_SFLIST_FLAGS_MASK) == 0UL, "flags too large");
     320             :         node->next_and_flags = (uintptr_t)(z_sfnode_next_peek(node)) | flags;
     321             : }
     322             : 
     323             : /*
     324             :  * Derived, generated APIs
     325             :  */
     326             : 
     327             : /**
     328             :  * @brief Test if the given list is empty
     329             :  *
     330             :  * @param list A pointer on the list to test
     331             :  *
     332             :  * @return a boolean, true if it's empty, false otherwise
     333             :  */
     334             : static inline bool sys_sflist_is_empty(sys_sflist_t *list);
     335             : 
     336           1 : Z_GENLIST_IS_EMPTY(sflist)
     337             : 
     338             : /**
     339             :  * @brief Peek the next node from current node, node is not NULL
     340             :  *
     341             :  * Faster then sys_sflist_peek_next() if node is known not to be NULL.
     342             :  *
     343             :  * @param node A pointer on the node where to peek the next node
     344             :  *
     345             :  * @return a pointer on the next node (or NULL if none)
     346             :  */
     347             : static inline sys_sfnode_t *sys_sflist_peek_next_no_check(sys_sfnode_t *node);
     348             : 
     349           1 : Z_GENLIST_PEEK_NEXT_NO_CHECK(sflist, sfnode)
     350             : 
     351             : /**
     352             :  * @brief Peek the next node from current node
     353             :  *
     354             :  * @param node A pointer on the node where to peek the next node
     355             :  *
     356             :  * @return a pointer on the next node (or NULL if none)
     357             :  */
     358             : static inline sys_sfnode_t *sys_sflist_peek_next(sys_sfnode_t *node);
     359             : 
     360           1 : Z_GENLIST_PEEK_NEXT(sflist, sfnode)
     361             : 
     362             : /**
     363             :  * @brief Prepend a node to the given list
     364             :  *
     365             :  * This and other sys_sflist_*() functions are not thread safe.
     366             :  *
     367             :  * @param list A pointer on the list to affect
     368             :  * @param node A pointer on the node to prepend
     369             :  */
     370             : static inline void sys_sflist_prepend(sys_sflist_t *list,
     371             :                                       sys_sfnode_t *node);
     372             : 
     373           1 : Z_GENLIST_PREPEND(sflist, sfnode)
     374             : 
     375             : /**
     376             :  * @brief Append a node to the given list
     377             :  *
     378             :  * This and other sys_sflist_*() functions are not thread safe.
     379             :  *
     380             :  * @param list A pointer on the list to affect
     381             :  * @param node A pointer on the node to append
     382             :  */
     383             : static inline void sys_sflist_append(sys_sflist_t *list,
     384             :                                      sys_sfnode_t *node);
     385             : 
     386           1 : Z_GENLIST_APPEND(sflist, sfnode)
     387             : 
     388             : /**
     389             :  * @brief Append a list to the given list
     390             :  *
     391             :  * Append a singly-linked, NULL-terminated list consisting of nodes containing
     392             :  * the pointer to the next node as the first element of a node, to @a list.
     393             :  * This and other sys_sflist_*() functions are not thread safe.
     394             :  *
     395             :  * FIXME: Why are the element parameters void *?
     396             :  *
     397             :  * @param list A pointer on the list to affect
     398             :  * @param head A pointer to the first element of the list to append
     399             :  * @param tail A pointer to the last element of the list to append
     400             :  */
     401             : static inline void sys_sflist_append_list(sys_sflist_t *list,
     402             :                                           void *head, void *tail);
     403             : 
     404           1 : Z_GENLIST_APPEND_LIST(sflist, sfnode)
     405             : 
     406             : /**
     407             :  * @brief merge two sflists, appending the second one to the first
     408             :  *
     409             :  * When the operation is completed, the appending list is empty.
     410             :  * This and other sys_sflist_*() functions are not thread safe.
     411             :  *
     412             :  * @param list A pointer on the list to affect
     413             :  * @param list_to_append A pointer to the list to append.
     414             :  */
     415             : static inline void sys_sflist_merge_sflist(sys_sflist_t *list,
     416             :                                            sys_sflist_t *list_to_append);
     417             : 
     418           1 : Z_GENLIST_MERGE_LIST(sflist, sfnode)
     419             : 
     420             : /**
     421             :  * @brief Insert a node to the given list
     422             :  *
     423             :  * This and other sys_sflist_*() functions are not thread safe.
     424             :  *
     425             :  * @param list A pointer on the list to affect
     426             :  * @param prev A pointer on the previous node
     427             :  * @param node A pointer on the node to insert
     428             :  */
     429             : static inline void sys_sflist_insert(sys_sflist_t *list,
     430             :                                      sys_sfnode_t *prev,
     431             :                                      sys_sfnode_t *node);
     432             : 
     433           1 : Z_GENLIST_INSERT(sflist, sfnode)
     434             : 
     435             : /**
     436             :  * @brief Fetch and remove the first node of the given list
     437             :  *
     438             :  * List must be known to be non-empty.
     439             :  * This and other sys_sflist_*() functions are not thread safe.
     440             :  *
     441             :  * @param list A pointer on the list to affect
     442             :  *
     443             :  * @return A pointer to the first node of the list
     444             :  */
     445             : static inline sys_sfnode_t *sys_sflist_get_not_empty(sys_sflist_t *list);
     446             : 
     447           1 : Z_GENLIST_GET_NOT_EMPTY(sflist, sfnode)
     448             : 
     449             : /**
     450             :  * @brief Fetch and remove the first node of the given list
     451             :  *
     452             :  * This and other sys_sflist_*() functions are not thread safe.
     453             :  *
     454             :  * @param list A pointer on the list to affect
     455             :  *
     456             :  * @return A pointer to the first node of the list (or NULL if empty)
     457             :  */
     458             : static inline sys_sfnode_t *sys_sflist_get(sys_sflist_t *list);
     459             : 
     460           1 : Z_GENLIST_GET(sflist, sfnode)
     461             : 
     462             : /**
     463             :  * @brief Remove a node
     464             :  *
     465             :  * This and other sys_sflist_*() functions are not thread safe.
     466             :  *
     467             :  * @param list A pointer on the list to affect
     468             :  * @param prev_node A pointer on the previous node
     469             :  *        (can be NULL, which means the node is the list's head)
     470             :  * @param node A pointer on the node to remove
     471             :  */
     472             : static inline void sys_sflist_remove(sys_sflist_t *list,
     473             :                                      sys_sfnode_t *prev_node,
     474             :                                      sys_sfnode_t *node);
     475             : 
     476           1 : Z_GENLIST_REMOVE(sflist, sfnode)
     477             : 
     478             : /**
     479             :  * @brief Find and remove a node from a list
     480             :  *
     481             :  * This and other sys_sflist_*() functions are not thread safe.
     482             :  *
     483             :  * @param list A pointer on the list to affect
     484             :  * @param node A pointer on the node to remove from the list
     485             :  *
     486             :  * @return true if node was removed
     487             :  */
     488             : static inline bool sys_sflist_find_and_remove(sys_sflist_t *list,
     489             :                                               sys_sfnode_t *node);
     490             : 
     491           1 : Z_GENLIST_FIND_AND_REMOVE(sflist, sfnode)
     492             : 
     493             : /**
     494             :  * @brief Compute the size of the given list in O(n) time
     495             :  *
     496             :  * @param list A pointer on the list
     497             :  *
     498             :  * @return an integer equal to the size of the list, or 0 if empty
     499             :  */
     500             : static inline size_t sys_sflist_len(sys_sflist_t *list);
     501             : 
     502           1 : Z_GENLIST_LEN(sflist, sfnode)
     503             : 
     504             : /** @} */
     505             : 
     506             : #ifdef __cplusplus
     507             : }
     508             : #endif
     509             : 
     510             : #endif /* ZEPHYR_INCLUDE_SYS_SFLIST_H_ */

Generated by: LCOV version 1.14