slist.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  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. /*
  173. * Macro that evaluates to the address of the structure containing the
  174. * given node based on the given type and member.
  175. */
  176. #define slist_entry(node, type, member) structof (node, type, member)
  177. // Get the first entry of a list.
  178. #define slist_first_entry(list, type, member) \
  179. MACRO_BEGIN \
  180. struct slist_node *first_ = (list)->first; \
  181. slist_end (first_) ? NULL : slist_entry (first_, type, member); \
  182. MACRO_END
  183. // Get the last entry of a list.
  184. #define slist_last_entry(list, type, member) \
  185. MACRO_BEGIN \
  186. struct slist_node *last_ = (list)->last; \
  187. slist_end (last_) ? NULL : slist_entry(last_, type, member); \
  188. MACRO_END
  189. // Get the entry next to the given entry.
  190. #define slist_next_entry(entry, member) \
  191. MACRO_BEGIN \
  192. struct slist_node *next_ = (entry)->member.next; \
  193. slist_end (next_) ? \
  194. NULL : slist_entry(next_, typeof(*entry), member); \
  195. MACRO_END
  196. /*
  197. * Forge a loop to process all nodes of a list.
  198. *
  199. * The node must not be altered during the loop.
  200. */
  201. #define slist_for_each(list, node) \
  202. for (_Auto node = slist_first (list); \
  203. !slist_end (node); \
  204. node = slist_next (node))
  205. // Forge a loop to process all nodes of a list.
  206. #define slist_for_each_safe(list, node, tmp) \
  207. for (node = slist_first (list), \
  208. tmp = slist_end (node) ? NULL : slist_next (node); \
  209. !slist_end (node); \
  210. node = tmp, \
  211. tmp = slist_end (node) ? NULL : slist_next (node))
  212. /*
  213. * Forge a loop to process all entries of a list.
  214. *
  215. * The entry node must not be altered during the loop.
  216. */
  217. #define slist_for_each_entry(list, entry, member) \
  218. for (entry = slist_first_entry (list, typeof (*entry), member); \
  219. entry != NULL; \
  220. entry = slist_next_entry (entry, member))
  221. // Forge a loop to process all entries of a list.
  222. #define slist_for_each_entry_safe(list, entry, tmp, member) \
  223. for (entry = slist_first_entry (list, typeof(*entry), member), \
  224. tmp = entry ? slist_next_entry (entry, member) : NULL; \
  225. entry != NULL; \
  226. entry = tmp, \
  227. tmp = entry ? slist_next_entry (entry, member) : NULL)
  228. /*
  229. * Lockless variants
  230. *
  231. * The slist_end() function may be used from read-side critical sections.
  232. */
  233. /*
  234. * Return the first node of a list.
  235. */
  236. static inline struct slist_node*
  237. slist_rcu_first (const struct slist *list)
  238. {
  239. return (rcu_load (&list->first));
  240. }
  241. /*
  242. * Return the node next to the given node.
  243. */
  244. static inline struct slist_node*
  245. slist_rcu_next (const struct slist_node *node)
  246. {
  247. return (rcu_load (&node->next));
  248. }
  249. /*
  250. * Insert a node at the head of a list.
  251. */
  252. static inline void
  253. slist_rcu_insert_head (struct slist *list, struct slist_node *node)
  254. {
  255. if (slist_empty (list))
  256. list->last = node;
  257. node->next = list->first;
  258. rcu_store (&list->first, node);
  259. }
  260. // Insert a node at the tail of a list.
  261. static inline void
  262. slist_rcu_insert_tail (struct slist *list, struct slist_node *node)
  263. {
  264. node->next = NULL;
  265. rcu_store (slist_empty (list) ? &list->first : &list->last->next, node);
  266. list->last = node;
  267. }
  268. /*
  269. * Insert a node after another node.
  270. *
  271. * The prev node must be valid.
  272. */
  273. static inline void
  274. slist_rcu_insert_after (struct slist *list, struct slist_node *node,
  275. struct slist_node *prev)
  276. {
  277. node->next = prev->next;
  278. rcu_store (&prev->next, node);
  279. if (list->last == prev)
  280. list->last = node;
  281. }
  282. /*
  283. * Remove a node from a list.
  284. *
  285. * The prev argument must point to the node immediately preceding the target
  286. * node. It may safely denote the end of the given list, in which case the
  287. * first node is removed.
  288. */
  289. static inline void
  290. slist_rcu_remove (struct slist *list, struct slist_node *prev)
  291. {
  292. if (slist_end (prev))
  293. {
  294. _Auto node = list->first;
  295. rcu_store (&list->first, node->next);
  296. if (list->last == node)
  297. list->last = NULL;
  298. }
  299. else
  300. {
  301. _Auto node = prev->next;
  302. rcu_store (&prev->next, node->next);
  303. if (list->last == node)
  304. list->last = prev;
  305. }
  306. }
  307. /*
  308. * Macro that evaluates to the address of the structure containing the
  309. * given node based on the given type and member.
  310. */
  311. #define slist_rcu_entry(node, type, member) \
  312. structof(rcu_load (&(node)), type, member)
  313. // Get the first entry of a list.
  314. #define slist_rcu_first_entry(list, type, member) \
  315. MACRO_BEGIN \
  316. struct slist_node *first_ = slist_rcu_first (list); \
  317. slist_end (first_) ? NULL : slist_entry (first_, type, member); \
  318. MACRO_END
  319. // Get the entry next to the given entry.
  320. #define slist_rcu_next_entry(entry, member) \
  321. MACRO_BEGIN \
  322. struct slist_node *next_ = slist_rcu_next (&entry->member); \
  323. slist_end (next_) ? \
  324. NULL : slist_entry (next_, typeof (*entry), member); \
  325. MACRO_END
  326. // Forge a loop to process all nodes of a list.
  327. #define slist_rcu_for_each(list, node) \
  328. for (_Auto node = slist_rcu_first (list); \
  329. !slist_end (node); \
  330. node = slist_rcu_next (node))
  331. // Forge a loop to process all entries of a list.
  332. #define slist_rcu_for_each_entry(list, entry, member) \
  333. for (entry = slist_rcu_first_entry (list, typeof (*entry), member); \
  334. entry != NULL; \
  335. entry = slist_rcu_next_entry (entry, member))
  336. #endif