LCOV - code coverage report
Current view: top level - include/linux - plist.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 7 8 87.5 %
Date: 2023-04-06 08:38:28 Functions: 0 0 -

          Line data    Source code
       1             : /* SPDX-License-Identifier: GPL-2.0-or-later */
       2             : /*
       3             :  * Descending-priority-sorted double-linked list
       4             :  *
       5             :  * (C) 2002-2003 Intel Corp
       6             :  * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>.
       7             :  *
       8             :  * 2001-2005 (c) MontaVista Software, Inc.
       9             :  * Daniel Walker <dwalker@mvista.com>
      10             :  *
      11             :  * (C) 2005 Thomas Gleixner <tglx@linutronix.de>
      12             :  *
      13             :  * Simplifications of the original code by
      14             :  * Oleg Nesterov <oleg@tv-sign.ru>
      15             :  *
      16             :  * Based on simple lists (include/linux/list.h).
      17             :  *
      18             :  * This is a priority-sorted list of nodes; each node has a
      19             :  * priority from INT_MIN (highest) to INT_MAX (lowest).
      20             :  *
      21             :  * Addition is O(K), removal is O(1), change of priority of a node is
      22             :  * O(K) and K is the number of RT priority levels used in the system.
      23             :  * (1 <= K <= 99)
      24             :  *
      25             :  * This list is really a list of lists:
      26             :  *
      27             :  *  - The tier 1 list is the prio_list, different priority nodes.
      28             :  *
      29             :  *  - The tier 2 list is the node_list, serialized nodes.
      30             :  *
      31             :  * Simple ASCII art explanation:
      32             :  *
      33             :  * pl:prio_list (only for plist_node)
      34             :  * nl:node_list
      35             :  *   HEAD|             NODE(S)
      36             :  *       |
      37             :  *       ||------------------------------------|
      38             :  *       ||->|pl|<->|pl|<--------------->|pl|<-|
      39             :  *       |   |10|   |21|   |21|   |21|   |40|   (prio)
      40             :  *       |   |  |   |  |   |  |   |  |   |  |
      41             :  *       |   |  |   |  |   |  |   |  |   |  |
      42             :  * |->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<-|
      43             :  * |-------------------------------------------|
      44             :  *
      45             :  * The nodes on the prio_list list are sorted by priority to simplify
      46             :  * the insertion of new nodes. There are no nodes with duplicate
      47             :  * priorites on the list.
      48             :  *
      49             :  * The nodes on the node_list are ordered by priority and can contain
      50             :  * entries which have the same priority. Those entries are ordered
      51             :  * FIFO
      52             :  *
      53             :  * Addition means: look for the prio_list node in the prio_list
      54             :  * for the priority of the node and insert it before the node_list
      55             :  * entry of the next prio_list node. If it is the first node of
      56             :  * that priority, add it to the prio_list in the right position and
      57             :  * insert it into the serialized node_list list
      58             :  *
      59             :  * Removal means remove it from the node_list and remove it from
      60             :  * the prio_list if the node_list list_head is non empty. In case
      61             :  * of removal from the prio_list it must be checked whether other
      62             :  * entries of the same priority are on the list or not. If there
      63             :  * is another entry of the same priority then this entry has to
      64             :  * replace the removed entry on the prio_list. If the entry which
      65             :  * is removed is the only entry of this priority then a simple
      66             :  * remove from both list is sufficient.
      67             :  *
      68             :  * INT_MIN is the highest priority, 0 is the medium highest, INT_MAX
      69             :  * is lowest priority.
      70             :  *
      71             :  * No locking is done, up to the caller.
      72             :  */
      73             : #ifndef _LINUX_PLIST_H_
      74             : #define _LINUX_PLIST_H_
      75             : 
      76             : #include <linux/container_of.h>
      77             : #include <linux/list.h>
      78             : #include <linux/types.h>
      79             : 
      80             : #include <asm/bug.h>
      81             : 
      82             : struct plist_head {
      83             :         struct list_head node_list;
      84             : };
      85             : 
      86             : struct plist_node {
      87             :         int                     prio;
      88             :         struct list_head        prio_list;
      89             :         struct list_head        node_list;
      90             : };
      91             : 
      92             : /**
      93             :  * PLIST_HEAD_INIT - static struct plist_head initializer
      94             :  * @head:       struct plist_head variable name
      95             :  */
      96             : #define PLIST_HEAD_INIT(head)                           \
      97             : {                                                       \
      98             :         .node_list = LIST_HEAD_INIT((head).node_list)   \
      99             : }
     100             : 
     101             : /**
     102             :  * PLIST_HEAD - declare and init plist_head
     103             :  * @head:       name for struct plist_head variable
     104             :  */
     105             : #define PLIST_HEAD(head) \
     106             :         struct plist_head head = PLIST_HEAD_INIT(head)
     107             : 
     108             : /**
     109             :  * PLIST_NODE_INIT - static struct plist_node initializer
     110             :  * @node:       struct plist_node variable name
     111             :  * @__prio:     initial node priority
     112             :  */
     113             : #define PLIST_NODE_INIT(node, __prio)                   \
     114             : {                                                       \
     115             :         .prio  = (__prio),                              \
     116             :         .prio_list = LIST_HEAD_INIT((node).prio_list),  \
     117             :         .node_list = LIST_HEAD_INIT((node).node_list),  \
     118             : }
     119             : 
     120             : /**
     121             :  * plist_head_init - dynamic struct plist_head initializer
     122             :  * @head:       &struct plist_head pointer
     123             :  */
     124             : static inline void
     125             : plist_head_init(struct plist_head *head)
     126             : {
     127         522 :         INIT_LIST_HEAD(&head->node_list);
     128             : }
     129             : 
     130             : /**
     131             :  * plist_node_init - Dynamic struct plist_node initializer
     132             :  * @node:       &struct plist_node pointer
     133             :  * @prio:       initial node priority
     134             :  */
     135             : static inline void plist_node_init(struct plist_node *node, int prio)
     136             : {
     137           1 :         node->prio = prio;
     138           2 :         INIT_LIST_HEAD(&node->prio_list);
     139           2 :         INIT_LIST_HEAD(&node->node_list);
     140             : }
     141             : 
     142             : extern void plist_add(struct plist_node *node, struct plist_head *head);
     143             : extern void plist_del(struct plist_node *node, struct plist_head *head);
     144             : 
     145             : extern void plist_requeue(struct plist_node *node, struct plist_head *head);
     146             : 
     147             : /**
     148             :  * plist_for_each - iterate over the plist
     149             :  * @pos:        the type * to use as a loop counter
     150             :  * @head:       the head for your list
     151             :  */
     152             : #define plist_for_each(pos, head)       \
     153             :          list_for_each_entry(pos, &(head)->node_list, node_list)
     154             : 
     155             : /**
     156             :  * plist_for_each_continue - continue iteration over the plist
     157             :  * @pos:        the type * to use as a loop cursor
     158             :  * @head:       the head for your list
     159             :  *
     160             :  * Continue to iterate over plist, continuing after the current position.
     161             :  */
     162             : #define plist_for_each_continue(pos, head)      \
     163             :          list_for_each_entry_continue(pos, &(head)->node_list, node_list)
     164             : 
     165             : /**
     166             :  * plist_for_each_safe - iterate safely over a plist of given type
     167             :  * @pos:        the type * to use as a loop counter
     168             :  * @n:  another type * to use as temporary storage
     169             :  * @head:       the head for your list
     170             :  *
     171             :  * Iterate over a plist of given type, safe against removal of list entry.
     172             :  */
     173             : #define plist_for_each_safe(pos, n, head)       \
     174             :          list_for_each_entry_safe(pos, n, &(head)->node_list, node_list)
     175             : 
     176             : /**
     177             :  * plist_for_each_entry - iterate over list of given type
     178             :  * @pos:        the type * to use as a loop counter
     179             :  * @head:       the head for your list
     180             :  * @mem:        the name of the list_head within the struct
     181             :  */
     182             : #define plist_for_each_entry(pos, head, mem)    \
     183             :          list_for_each_entry(pos, &(head)->node_list, mem.node_list)
     184             : 
     185             : /**
     186             :  * plist_for_each_entry_continue - continue iteration over list of given type
     187             :  * @pos:        the type * to use as a loop cursor
     188             :  * @head:       the head for your list
     189             :  * @m:          the name of the list_head within the struct
     190             :  *
     191             :  * Continue to iterate over list of given type, continuing after
     192             :  * the current position.
     193             :  */
     194             : #define plist_for_each_entry_continue(pos, head, m)     \
     195             :         list_for_each_entry_continue(pos, &(head)->node_list, m.node_list)
     196             : 
     197             : /**
     198             :  * plist_for_each_entry_safe - iterate safely over list of given type
     199             :  * @pos:        the type * to use as a loop counter
     200             :  * @n:          another type * to use as temporary storage
     201             :  * @head:       the head for your list
     202             :  * @m:          the name of the list_head within the struct
     203             :  *
     204             :  * Iterate over list of given type, safe against removal of list entry.
     205             :  */
     206             : #define plist_for_each_entry_safe(pos, n, head, m)      \
     207             :         list_for_each_entry_safe(pos, n, &(head)->node_list, m.node_list)
     208             : 
     209             : /**
     210             :  * plist_head_empty - return !0 if a plist_head is empty
     211             :  * @head:       &struct plist_head pointer
     212             :  */
     213             : static inline int plist_head_empty(const struct plist_head *head)
     214             : {
     215           6 :         return list_empty(&head->node_list);
     216             : }
     217             : 
     218             : /**
     219             :  * plist_node_empty - return !0 if plist_node is not on a list
     220             :  * @node:       &struct plist_node pointer
     221             :  */
     222             : static inline int plist_node_empty(const struct plist_node *node)
     223             : {
     224           2 :         return list_empty(&node->node_list);
     225             : }
     226             : 
     227             : /* All functions below assume the plist_head is not empty. */
     228             : 
     229             : /**
     230             :  * plist_first_entry - get the struct for the first entry
     231             :  * @head:       the &struct plist_head pointer
     232             :  * @type:       the type of the struct this is embedded in
     233             :  * @member:     the name of the list_head within the struct
     234             :  */
     235             : #ifdef CONFIG_DEBUG_PLIST
     236             : # define plist_first_entry(head, type, member)  \
     237             : ({ \
     238             :         WARN_ON(plist_head_empty(head)); \
     239             :         container_of(plist_first(head), type, member); \
     240             : })
     241             : #else
     242             : # define plist_first_entry(head, type, member)  \
     243             :         container_of(plist_first(head), type, member)
     244             : #endif
     245             : 
     246             : /**
     247             :  * plist_last_entry - get the struct for the last entry
     248             :  * @head:       the &struct plist_head pointer
     249             :  * @type:       the type of the struct this is embedded in
     250             :  * @member:     the name of the list_head within the struct
     251             :  */
     252             : #ifdef CONFIG_DEBUG_PLIST
     253             : # define plist_last_entry(head, type, member)   \
     254             : ({ \
     255             :         WARN_ON(plist_head_empty(head)); \
     256             :         container_of(plist_last(head), type, member); \
     257             : })
     258             : #else
     259             : # define plist_last_entry(head, type, member)   \
     260             :         container_of(plist_last(head), type, member)
     261             : #endif
     262             : 
     263             : /**
     264             :  * plist_next - get the next entry in list
     265             :  * @pos:        the type * to cursor
     266             :  */
     267             : #define plist_next(pos) \
     268             :         list_next_entry(pos, node_list)
     269             : 
     270             : /**
     271             :  * plist_prev - get the prev entry in list
     272             :  * @pos:        the type * to cursor
     273             :  */
     274             : #define plist_prev(pos) \
     275             :         list_prev_entry(pos, node_list)
     276             : 
     277             : /**
     278             :  * plist_first - return the first node (and thus, highest priority)
     279             :  * @head:       the &struct plist_head pointer
     280             :  *
     281             :  * Assumes the plist is _not_ empty.
     282             :  */
     283             : static inline struct plist_node *plist_first(const struct plist_head *head)
     284             : {
     285           1 :         return list_entry(head->node_list.next,
     286             :                           struct plist_node, node_list);
     287             : }
     288             : 
     289             : /**
     290             :  * plist_last - return the last node (and thus, lowest priority)
     291             :  * @head:       the &struct plist_head pointer
     292             :  *
     293             :  * Assumes the plist is _not_ empty.
     294             :  */
     295             : static inline struct plist_node *plist_last(const struct plist_head *head)
     296             : {
     297           0 :         return list_entry(head->node_list.prev,
     298             :                           struct plist_node, node_list);
     299             : }
     300             : 
     301             : #endif

Generated by: LCOV version 1.14