slist.h 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. /*
  2. * Copyright (c) 2017 Richard Braun.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. * Upstream site with license notes :
  18. * http://git.sceen.net/rbraun/librbraun.git/
  19. *
  20. *
  21. * Singly-linked list.
  22. */
  23. #ifndef KERN_SLIST_H
  24. #define KERN_SLIST_H
  25. #include <stdbool.h>
  26. #include <stddef.h>
  27. #include <kern/macros.h>
  28. #include <kern/rcu.h>
  29. #include <kern/slist_types.h>
  30. struct slist;
  31. struct slist_node;
  32. // Static list initializer.
  33. #define SLIST_INITIALIZER(list) { NULL, NULL }
  34. // Initialize a list.
  35. static inline void
  36. slist_init (struct slist *list)
  37. {
  38. list->first = list->last = NULL;
  39. }
  40. // Initialize a list node.
  41. static inline void
  42. slist_node_init (struct slist_node *node)
  43. {
  44. node->next = NULL;
  45. }
  46. // Return the first node of a list.
  47. static inline struct slist_node*
  48. slist_first (const struct slist *list)
  49. {
  50. return (list->first);
  51. }
  52. // Return the last node of a list.
  53. static inline struct slist_node*
  54. slist_last (const struct slist *list)
  55. {
  56. return (list->last);
  57. }
  58. // Return the node next to the given node.
  59. static inline struct slist_node*
  60. slist_next (const struct slist_node *node)
  61. {
  62. return (node->next);
  63. }
  64. // Return true if node is invalid and denotes one of the ends of the list.
  65. static inline bool
  66. slist_end (const struct slist_node *node)
  67. {
  68. return (node == NULL);
  69. }
  70. /*
  71. * Return true if list is empty.
  72. */
  73. static inline bool
  74. slist_empty (const struct slist *list)
  75. {
  76. return (list->first == NULL);
  77. }
  78. // Return true if list contains exactly one node.
  79. static inline bool
  80. slist_singular (const struct slist *list)
  81. {
  82. return (!slist_empty (list) && list->first == list->last);
  83. }
  84. /*
  85. * Append the nodes of list2 at the end of list1.
  86. *
  87. * After completion, list2 is stale.
  88. */
  89. static inline void
  90. slist_concat (struct slist *list1, const struct slist *list2)
  91. {
  92. if (slist_empty (list2))
  93. return;
  94. else if (slist_empty (list1))
  95. list1->first = list2->first;
  96. else
  97. list1->last->next = list2->first;
  98. list1->last = list2->last;
  99. }
  100. /*
  101. * Set the new head of a list.
  102. *
  103. * This function is an optimized version of :
  104. * list_init(&new_list);
  105. * list_concat(&new_list, &old_list);
  106. */
  107. static inline void
  108. slist_set_head (struct slist *new_head, const struct slist *old_head)
  109. {
  110. *new_head = *old_head;
  111. }
  112. // Insert a node at the head of a list.
  113. static inline void
  114. slist_insert_head (struct slist *list, struct slist_node *node)
  115. {
  116. if (slist_empty (list))
  117. list->last = node;
  118. node->next = list->first;
  119. list->first = node;
  120. }
  121. // Insert a node at the tail of a list.
  122. static inline void
  123. slist_insert_tail (struct slist *list, struct slist_node *node)
  124. {
  125. node->next = NULL;
  126. if (slist_empty (list))
  127. list->first = node;
  128. else
  129. list->last->next = node;
  130. list->last = node;
  131. }
  132. /*
  133. * Insert a node after another node.
  134. *
  135. * The prev node must be valid.
  136. */
  137. static inline void
  138. slist_insert_after (struct slist *list, struct slist_node *node,
  139. struct slist_node *prev)
  140. {
  141. node->next = prev->next;
  142. prev->next = node;
  143. if (list->last == prev)
  144. list->last = node;
  145. }
  146. /*
  147. * Remove a node from a list.
  148. *
  149. * The prev argument must point to the node immediately preceding the target
  150. * node. It may safely denote the end of the given list (NULL), in which case
  151. * the first node is removed.
  152. */
  153. static inline void
  154. slist_remove (struct slist *list, struct slist_node *prev)
  155. {
  156. struct slist_node *node;
  157. if (slist_end (prev))
  158. {
  159. node = list->first;
  160. list->first = node->next;
  161. if (list->last == node)
  162. list->last = NULL;
  163. }
  164. else
  165. {
  166. node = prev->next;
  167. prev->next = node->next;
  168. if (list->last == node)
  169. list->last = prev;
  170. }
  171. }
  172. #define slist_pop_entry(list, type, member) \
  173. ({ \
  174. struct slist *slist_ = (list); \
  175. type *ret_ = slist_first_entry (slist_, type, member); \
  176. slist_remove (slist_, NULL); \
  177. ret_; \
  178. })
  179. /*
  180. * Macro that evaluates to the address of the structure containing the
  181. * given node based on the given type and member.
  182. */
  183. #define slist_entry(node, type, member) structof (node, type, member)
  184. // Get the first entry of a list.
  185. #define slist_first_entry(list, type, member) \
  186. MACRO_BEGIN \
  187. struct slist_node *first_ = (list)->first; \
  188. slist_end (first_) ? NULL : slist_entry (first_, type, member); \
  189. MACRO_END
  190. // Get the last entry of a list.
  191. #define slist_last_entry(list, type, member) \
  192. MACRO_BEGIN \
  193. struct slist_node *last_ = (list)->last; \
  194. slist_end (last_) ? NULL : slist_entry(last_, type, member); \
  195. MACRO_END
  196. // Get the entry next to the given entry.
  197. #define slist_next_entry(entry, member) \
  198. MACRO_BEGIN \
  199. struct slist_node *next_ = (entry)->member.next; \
  200. slist_end (next_) ? \
  201. NULL : slist_entry(next_, typeof(*entry), member); \
  202. MACRO_END
  203. /*
  204. * Forge a loop to process all nodes of a list.
  205. *
  206. * The node must not be altered during the loop.
  207. */
  208. #define slist_for_each(list, node) \
  209. for (_Auto node = slist_first (list); \
  210. !slist_end (node); \
  211. node = slist_next (node))
  212. // Forge a loop to process all nodes of a list.
  213. #define slist_for_each_safe(list, node, tmp) \
  214. for (node = slist_first (list), \
  215. tmp = slist_end (node) ? NULL : slist_next (node); \
  216. !slist_end (node); \
  217. node = tmp, \
  218. tmp = slist_end (node) ? NULL : slist_next (node))
  219. /*
  220. * Forge a loop to process all entries of a list.
  221. *
  222. * The entry node must not be altered during the loop.
  223. */
  224. #define slist_for_each_entry(list, entry, member) \
  225. for (entry = slist_first_entry (list, typeof (*entry), member); \
  226. entry != NULL; \
  227. entry = slist_next_entry (entry, member))
  228. // Forge a loop to process all entries of a list.
  229. #define slist_for_each_entry_safe(list, entry, tmp, member) \
  230. for (entry = slist_first_entry (list, typeof(*entry), member), \
  231. tmp = entry ? slist_next_entry (entry, member) : NULL; \
  232. entry != NULL; \
  233. entry = tmp, \
  234. tmp = entry ? slist_next_entry (entry, member) : NULL)
  235. /*
  236. * Lockless variants
  237. *
  238. * The slist_end() function may be used from read-side critical sections.
  239. */
  240. /*
  241. * Return the first node of a list.
  242. */
  243. static inline struct slist_node*
  244. slist_rcu_first (const struct slist *list)
  245. {
  246. return (rcu_load (&list->first));
  247. }
  248. /*
  249. * Return the node next to the given node.
  250. */
  251. static inline struct slist_node*
  252. slist_rcu_next (const struct slist_node *node)
  253. {
  254. return (rcu_load (&node->next));
  255. }
  256. /*
  257. * Insert a node at the head of a list.
  258. */
  259. static inline void
  260. slist_rcu_insert_head (struct slist *list, struct slist_node *node)
  261. {
  262. if (slist_empty (list))
  263. list->last = node;
  264. node->next = list->first;
  265. rcu_store (&list->first, node);
  266. }
  267. // Insert a node at the tail of a list.
  268. static inline void
  269. slist_rcu_insert_tail (struct slist *list, struct slist_node *node)
  270. {
  271. node->next = NULL;
  272. rcu_store (slist_empty (list) ? &list->first : &list->last->next, node);
  273. list->last = node;
  274. }
  275. /*
  276. * Insert a node after another node.
  277. *
  278. * The prev node must be valid.
  279. */
  280. static inline void
  281. slist_rcu_insert_after (struct slist *list, struct slist_node *node,
  282. struct slist_node *prev)
  283. {
  284. node->next = prev->next;
  285. rcu_store (&prev->next, node);
  286. if (list->last == prev)
  287. list->last = node;
  288. }
  289. /*
  290. * Remove a node from a list.
  291. *
  292. * The prev argument must point to the node immediately preceding the target
  293. * node. It may safely denote the end of the given list, in which case the
  294. * first node is removed.
  295. */
  296. static inline void
  297. slist_rcu_remove (struct slist *list, struct slist_node *prev)
  298. {
  299. if (slist_end (prev))
  300. {
  301. _Auto node = list->first;
  302. rcu_store (&list->first, node->next);
  303. if (list->last == node)
  304. list->last = NULL;
  305. }
  306. else
  307. {
  308. _Auto node = prev->next;
  309. rcu_store (&prev->next, node->next);
  310. if (list->last == node)
  311. list->last = prev;
  312. }
  313. }
  314. /*
  315. * Macro that evaluates to the address of the structure containing the
  316. * given node based on the given type and member.
  317. */
  318. #define slist_rcu_entry(node, type, member) \
  319. structof(rcu_load (&(node)), type, member)
  320. // Get the first entry of a list.
  321. #define slist_rcu_first_entry(list, type, member) \
  322. MACRO_BEGIN \
  323. struct slist_node *first_ = slist_rcu_first (list); \
  324. slist_end (first_) ? NULL : slist_entry (first_, type, member); \
  325. MACRO_END
  326. // Get the entry next to the given entry.
  327. #define slist_rcu_next_entry(entry, member) \
  328. MACRO_BEGIN \
  329. struct slist_node *next_ = slist_rcu_next (&entry->member); \
  330. slist_end (next_) ? \
  331. NULL : slist_entry (next_, typeof (*entry), member); \
  332. MACRO_END
  333. // Forge a loop to process all nodes of a list.
  334. #define slist_rcu_for_each(list, node) \
  335. for (_Auto node = slist_rcu_first (list); \
  336. !slist_end (node); \
  337. node = slist_rcu_next (node))
  338. // Forge a loop to process all entries of a list.
  339. #define slist_rcu_for_each_entry(list, entry, member) \
  340. for (entry = slist_rcu_first_entry (list, typeof (*entry), member); \
  341. entry != NULL; \
  342. entry = slist_rcu_next_entry (entry, member))
  343. #endif