qdf_slist.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /*
  2. * Copyright (c) 2019 The Linux Foundation. All rights reserved.
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for
  5. * any purpose with or without fee is hereby granted, provided that the
  6. * above copyright notice and this permission notice appear in all
  7. * copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  10. * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  11. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  12. * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  13. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  14. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  15. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  16. * PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. /**
  19. * DOC: qdf_slist.h
  20. *
  21. * A minimal, singly linked list implementation, with push front, pop front, and
  22. * remove capabilities. These are all O(1) operations.
  23. *
  24. * In order to remove an item, a pointer to the previous item must be known.
  25. * Thus, removing an item is most efficient when combined with
  26. * qdf_slist_for_each_del(). For cases where you need efficient removal of an
  27. * arbitrary list node without iteration, consider using the doubly linked list
  28. * qdf_list instead.
  29. */
  30. #ifndef __QDF_SLIST_H
  31. #define __QDF_SLIST_H
  32. #include "qdf_trace.h"
  33. #include "qdf_util.h"
  34. #define __qdf_slist_poison ((void *)0xdeaddeaddeaddeadull)
  35. /**
  36. * struct qdf_slist - a singly linked list
  37. * @head: pointer to the head of the list
  38. */
  39. struct qdf_slist {
  40. struct qdf_slist_node *head;
  41. };
  42. /**
  43. * struct qdf_slist_node - a singly linked list node
  44. * @next: pointer to the next node in the list, NULL if there is none
  45. */
  46. struct qdf_slist_node {
  47. struct qdf_slist_node *next;
  48. };
  49. #define __qdf_slist_item(node, cursor, node_field) ({ \
  50. struct qdf_slist_node *__n = (node); \
  51. (__n ? qdf_container_of(__n, typeof(*(cursor)), node_field) : NULL); })
  52. #define __qdf_slist_next_item(slist, cursor, node_field) \
  53. __qdf_slist_item(cursor ? (cursor)->node_field.next : \
  54. (slist)->head, cursor, node_field)
  55. /**
  56. * qdf_slist_for_each - iterate over all of the items in @slist
  57. * @slist: pointer to the qdf_slist to iterate over
  58. * @cursor: cursor pointer of the list's item type, populated for each item
  59. * @node_field: name of the qdf_slist_node field in the item's type
  60. */
  61. #define qdf_slist_for_each(slist, cursor, node_field) \
  62. for (cursor = __qdf_slist_item((slist)->head, cursor, node_field); \
  63. cursor; \
  64. cursor = __qdf_slist_item((cursor)->node_field.next, \
  65. cursor, node_field))
  66. /**
  67. * qdf_slist_for_each_del - iterate over all of the items in @slist,
  68. * allowing for the safe deletion of nodes during iteration
  69. * @slist: pointer to the qdf_slist to iterate over
  70. * @prev: cursor pointer, populated with the previous item
  71. * @cursor: cursor pointer of the list's item type, populated for each item
  72. * @node_field: name of the qdf_slist_node field in the item's type
  73. */
  74. #define qdf_slist_for_each_del(slist, prev, cursor, node_field) \
  75. for (prev = NULL, \
  76. cursor = __qdf_slist_item((slist)->head, cursor, node_field); \
  77. cursor; \
  78. prev = __qdf_slist_next_item(slist, prev, node_field) == \
  79. cursor ? cursor : prev, \
  80. cursor = __qdf_slist_next_item(slist, prev, node_field))
  81. /**
  82. * qdf_slist_init() - initialize a qdf_slist
  83. * @slist: the list to initialize
  84. *
  85. * Return: None
  86. */
  87. static inline void qdf_slist_init(struct qdf_slist *slist)
  88. {
  89. slist->head = NULL;
  90. }
  91. /**
  92. * qdf_slist_deinit() - deinitialize a qdf_slist
  93. * @slist: the list to deinitialize
  94. *
  95. * Return: None
  96. */
  97. static inline void qdf_slist_deinit(struct qdf_slist *slist)
  98. {
  99. QDF_BUG(!slist->head);
  100. slist->head = __qdf_slist_poison;
  101. }
  102. /**
  103. * qdf_slist_empty() - check if a qdf_slist is empty
  104. * @slist: the list to check
  105. *
  106. * Return: true if @slist contains zero items
  107. */
  108. static inline bool qdf_slist_empty(struct qdf_slist *slist)
  109. {
  110. return !slist->head;
  111. }
  112. /**
  113. * qdf_slist_push() - push an item into the front of a qdf_slist
  114. * @slist: the list to push into
  115. * @cursor: the item to push
  116. * @node_field: name of the qdf_slist_node field in the item's type
  117. *
  118. * Return: None
  119. */
  120. #define qdf_slist_push(slist, cursor, node_field) \
  121. __qdf_slist_push(slist, &(cursor)->node_field)
  122. static inline void
  123. __qdf_slist_push(struct qdf_slist *slist, struct qdf_slist_node *node)
  124. {
  125. node->next = slist->head;
  126. slist->head = node;
  127. }
  128. /**
  129. * qdf_slist_pop() - pop an item from the front of a qdf_slist
  130. * @slist: the list to pop from
  131. * @cursor: cursor pointer of the list's item type, not populated
  132. * @node_field: name of the qdf_slist_node field in the item's type
  133. *
  134. * Return: pointer to the popped item, NULL if @slist was empty
  135. */
  136. #define qdf_slist_pop(slist, cursor, node_field) \
  137. __qdf_slist_item(__qdf_slist_pop(slist), cursor, node_field)
  138. static inline struct qdf_slist_node *__qdf_slist_pop(struct qdf_slist *slist)
  139. {
  140. struct qdf_slist_node *node = slist->head;
  141. if (!node)
  142. return NULL;
  143. slist->head = node->next;
  144. node->next = __qdf_slist_poison;
  145. return node;
  146. }
  147. /**
  148. * qdf_slist_remove() - remove an item from a qdf_slist
  149. * @slist: the list to remove from
  150. * @prev: pointer to the item previous to the item to remove, NULL removes head
  151. * @node_field: name of the qdf_slist_node field in the item's type
  152. *
  153. * Return: pointer to the removed item, NULL if none was removed
  154. */
  155. #define qdf_slist_remove(slist, prev, node_field) \
  156. __qdf_slist_item(__qdf_slist_remove(slist, \
  157. prev ? &(prev)->node_field : NULL), prev, node_field)
  158. static inline struct qdf_slist_node *
  159. __qdf_slist_remove(struct qdf_slist *slist, struct qdf_slist_node *prev)
  160. {
  161. struct qdf_slist_node *node;
  162. if (!prev)
  163. return __qdf_slist_pop(slist);
  164. if (!prev->next)
  165. return NULL;
  166. node = prev->next;
  167. prev->next = node->next;
  168. node->next = __qdf_slist_poison;
  169. return node;
  170. }
  171. #endif /* __QDF_SLIST_H */