list.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /* Copyright (C) 2017 University of North Carolina at Chapel Hill and
  2. Fortanix, Inc.
  3. This file is part of Graphene Library OS.
  4. Graphene Library OS is free software: you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public License
  6. as published by the Free Software Foundation, either version 3 of the
  7. License, or (at your option) any later version.
  8. Graphene Library OS is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  14. /*
  15. * list.h
  16. *
  17. * This file defines the list API for the PAL and Library OS.
  18. */
  19. #ifndef LIST_H
  20. #define LIST_H
  21. // Use a new list implementation
  22. /* This list implementation stores a pointer to the next object and casts to
  23. * the object, rather than using offsetof(). We try to encapsulate this
  24. * change in a macro for declarations, which generates a type declaration for
  25. * each list object (giving marginally more help from the compiler
  26. * in detecting bugs.
  27. *
  28. * In particular, there is a small trade-off in that the association between
  29. * list heads and nodes is more explicit and a few more casting errors can be
  30. * caught by the compiler, but we add a parameter to some functions (well,
  31. * macros) to pass the field of the struct.
  32. */
  33. /* How-to:
  34. *
  35. * Each list has a pointer (listp) type, and a node (list)type. We assume
  36. * list nodes are embedded in a larger structure; the name of this structure
  37. * is used as part of the list type.
  38. *
  39. * To define a listp/list pair for a struct foo:
  40. *
  41. * DEFINE_LIST(foo);
  42. * struct foo {
  43. * int x;
  44. * LIST_TYPE(foo) list; // The list node
  45. * };
  46. *
  47. * DEFINE_LISTP(foo);
  48. * static LISTP_TYPE(foo) the_list = LISTP_INIT;
  49. *
  50. * -----
  51. *
  52. * From here, you can use LISTP_ADD variants to add an object from the list:
  53. *
  54. * struct foo *f = malloc(sizeof(struct foo));
  55. * f->x = 1;
  56. * INIT_LIST_HEAD(f, list); // The second parameter is the structure member
  57. * LISTP_ADD(f, &the_list, list);
  58. *
  59. * -----
  60. *
  61. * There are a number of add variants, some that add in a given position,
  62. * others that add to the head or the tail.
  63. *
  64. * You can search for an object using a variant of listp_for_each_entry. The
  65. * safe variants are safe against deletion.
  66. *
  67. * You can remove an object from a list using LISTP_DEL.
  68. *
  69. * In this example, we delete everything with a key bigger than 5.
  70. *
  71. * LIST_TYPE(foo) *f, *n; // n is not used, just for scratch space
  72. * LISTP_FOR_EACH_ENTRY_SAFE(f, n, &the_list, list) {
  73. * if (f->x > 4) {
  74. * LISTP_DEL(f, &the_list, list);
  75. * free(f);
  76. * }
  77. * }
  78. *
  79. *
  80. * LISTP_SPLICE moves an entire listp onto another, and list_move_tail takes
  81. * an element off of one list and places it on another.
  82. *
  83. * static LISTP_TYPE(foo) other_list; // Assume it is full of goodies
  84. * // Move everything on other_list to the_list
  85. * LISTP_SPLICE_TAIL(&other_list, &the_list, list, foo); // the third argument
  86. * // is the field; the
  87. * // fourth is the type
  88. * // of the nodes (not
  89. * // the head pointer).
  90. *
  91. * // Use LISTP_EMPTY to test for emptiness of the list
  92. * assert(LISTP_EMPTY(&other_ist));
  93. *
  94. * // Now move back anythign less than 6 back to other_list
  95. * LISTP_FOR_EACH_ENTRY_SAFE(f, n, &the_list, list) {
  96. * if (f->x < 6)
  97. * LISTP_MOVE_TAIL(f, &other_list, &the_list, list);
  98. * }
  99. *
  100. */
  101. // Maybe TODO?
  102. //
  103. // Change the order of (node, head, field) -> (head, node, field)
  104. // drop the listp type to reduce code changes?
  105. // Cleaner way to express types
  106. // Add assertion to delete (in debugging mode) that item is on list
  107. // There are a few places where knowing the listp for deletion is cumbersome;
  108. // maybe drop this requirement?
  109. #include <stdbool.h>
  110. #ifdef DEBUG
  111. #include <assert.h>
  112. #define LIST_ASSERT(COND) assert(COND)
  113. #else
  114. #define LIST_ASSERT(COND)
  115. #endif
  116. #define LIST_TYPE(STRUCT_NAME) struct list_head##_##STRUCT_NAME
  117. #define LISTP_TYPE(STRUCT_NAME) struct listp##_##STRUCT_NAME
  118. /* Declare the enclosing struct for convenience, on
  119. * the assumption that this is primarily used in structure
  120. * definitions, and harmless if duplicated. */
  121. #define DEFINE_LIST(STRUCT_NAME) \
  122. struct STRUCT_NAME; \
  123. LIST_TYPE(STRUCT_NAME) { \
  124. struct STRUCT_NAME* next; \
  125. struct STRUCT_NAME* prev; \
  126. }
  127. /* We use LISTP for pointers to a list. This project only really needs
  128. * doubly-linked lists. We used hlists to get a single pointer for more
  129. * efficient hash tables, but they were still effectively doubly-linked
  130. * lists. */
  131. #define DEFINE_LISTP(STRUCT) \
  132. LISTP_TYPE(STRUCT) { \
  133. struct STRUCT* first; \
  134. }
  135. #define LISTP_INIT {NULL}
  136. /* A node not on a list uses NULL; on a list, you
  137. * store self pointers */
  138. #define INIT_LIST_HEAD(OBJECT, FIELD) \
  139. do { \
  140. (OBJECT)->FIELD.next = NULL; \
  141. (OBJECT)->FIELD.prev = NULL; \
  142. } while (0)
  143. #define INIT_LISTP(OBJECT) \
  144. do { \
  145. (OBJECT)->first = NULL; \
  146. } while (0)
  147. #define LISTP_EMPTY(HEAD) ((HEAD)->first == NULL)
  148. #define LIST_EMPTY(NODE, FIELD) ((NODE)->FIELD.next == NULL)
  149. /* This helper takes 3 arguments - all should be containing structures,
  150. * and the field to use for the offset to the list node */
  151. #define __LIST_ADD(NEW, NEXT, PREV, FIELD) \
  152. do { \
  153. __typeof__(NEW) __tmp_next = (NEXT); \
  154. __typeof__(NEW) __tmp_prev = (PREV); \
  155. __tmp_prev->FIELD.next = (NEW); \
  156. __tmp_next->FIELD.prev = (NEW); \
  157. (NEW)->FIELD.next = __tmp_next; \
  158. (NEW)->FIELD.prev = __tmp_prev; \
  159. } while (0)
  160. #define LIST_ADD(NEW, HEAD, FIELD) __LIST_ADD(NEW, (HEAD)->FIELD.next, HEAD, FIELD)
  161. #define LISTP_ADD(NEW, HEAD, FIELD) \
  162. do { \
  163. if ((HEAD)->first == NULL) { \
  164. (HEAD)->first = (NEW); \
  165. (NEW)->FIELD.next = (NEW); \
  166. (NEW)->FIELD.prev = (NEW); \
  167. } else { \
  168. __LIST_ADD(NEW, (HEAD)->first, (HEAD)->first->FIELD.prev, FIELD); \
  169. (HEAD)->first = (NEW); \
  170. } \
  171. } while (0)
  172. /* If NODE is defined, add NEW after NODE; if not,
  173. * put NEW at the front of the list */
  174. #define LISTP_ADD_AFTER(NEW, NODE, HEAD, FIELD) \
  175. do { \
  176. if (NODE) \
  177. LIST_ADD(NEW, NODE, FIELD); \
  178. else \
  179. LISTP_ADD(NEW, HEAD, FIELD); \
  180. } while (0)
  181. #define LIST_ADD_TAIL(NEW, HEAD, FIELD) __LIST_ADD(NEW, HEAD, (HEAD)->FIELD.prev, FIELD)
  182. #define LISTP_ADD_TAIL(NEW, HEAD, FIELD) \
  183. do { \
  184. if ((HEAD)->first == NULL) { \
  185. (HEAD)->first = (NEW); \
  186. (NEW)->FIELD.next = (NEW); \
  187. (NEW)->FIELD.prev = (NEW); \
  188. } else \
  189. LIST_ADD_TAIL(NEW, (HEAD)->first, FIELD); \
  190. } while (0)
  191. /* Or deletion needs to know the list root */
  192. #define LISTP_DEL(NODE, HEAD, FIELD) \
  193. do { \
  194. if ((HEAD)->first == (NODE)) { \
  195. if ((NODE)->FIELD.next == (NODE)) { \
  196. (HEAD)->first = NULL; \
  197. } else { \
  198. (HEAD)->first = (NODE)->FIELD.next; \
  199. } \
  200. } \
  201. LIST_ASSERT((NODE)->FIELD.prev->FIELD.next == (NODE)); \
  202. LIST_ASSERT((NODE)->FIELD.next->FIELD.prev == (NODE)); \
  203. (NODE)->FIELD.prev->FIELD.next = (NODE)->FIELD.next; \
  204. (NODE)->FIELD.next->FIELD.prev = (NODE)->FIELD.prev; \
  205. } while (0)
  206. #define LISTP_DEL_INIT(NODE, HEAD, FIELD) \
  207. do { \
  208. LISTP_DEL(NODE, HEAD, FIELD); \
  209. INIT_LIST_HEAD(NODE, FIELD); \
  210. } while (0)
  211. /* Keep vestigial TYPE and FIELD parameters to minimize disruption
  212. * when switching from Linux list implementation */
  213. #define LISTP_FIRST_ENTRY(LISTP, TYPE, FIELD) ((LISTP)->first)
  214. /* New API: return last entry in list */
  215. #define LISTP_LAST_ENTRY(LISTP, TYPE, FIELD) ((LISTP)->first->FIELD.prev)
  216. /* New API: return next entry in list */
  217. #define LISTP_NEXT_ENTRY(NODE, LISTP, FIELD) \
  218. ((NODE) == (LISTP)->first->FIELD.prev ? NULL : (NODE)->FIELD.next)
  219. /* New API: return previous entry in list */
  220. #define LISTP_PREV_ENTRY(NODE, LISTP, FIELD) ((NODE) == (LISTP)->first ? NULL : (NODE)->FIELD.prev)
  221. /* Vestigial - for compat with Linux list code; rename to listp?
  222. */
  223. #define LIST_ENTRY(LISTP, TYPE, FIELD) (LISTP)
  224. #define LISTP_FOR_EACH_ENTRY(CURSOR, HEAD, FIELD) \
  225. for (bool first_iter = ((CURSOR) = (HEAD)->first, !!(HEAD)->first); \
  226. first_iter || (CURSOR) != (HEAD)->first; \
  227. (CURSOR) = (CURSOR)->FIELD.next, first_iter = false)
  228. #define LISTP_FOR_EACH_ENTRY_REVERSE(CURSOR, HEAD, FIELD) \
  229. for (bool first_iter = \
  230. ((CURSOR) = ((HEAD)->first ? (HEAD)->first->FIELD.prev : (HEAD)->first), \
  231. !!(HEAD)->first); \
  232. first_iter || ((CURSOR) && (CURSOR)->FIELD.next != (HEAD)->first); \
  233. (CURSOR) = (CURSOR)->FIELD.prev, first_iter = false)
  234. #define LISTP_FOR_EACH_ENTRY_SAFE(CURSOR, TMP, HEAD, FIELD) \
  235. for (bool first_iter = ((CURSOR) = (HEAD)->first, \
  236. (TMP) = ((CURSOR) ? (CURSOR)->FIELD.next : (CURSOR)), !!(HEAD)->first); \
  237. (HEAD)->first && \
  238. (first_iter || (CURSOR) != (HEAD)->first); \
  239. /* Handle the case where the first element was removed. */ \
  240. first_iter = first_iter && (TMP) != (CURSOR) && (HEAD)->first == (TMP), (CURSOR) = (TMP), \
  241. (TMP) = (TMP)->FIELD.next)
  242. /* Continue safe iteration with CURSOR->next */
  243. #define LISTP_FOR_EACH_ENTRY_SAFE_CONTINUE(CURSOR, TMP, HEAD, FIELD) \
  244. for ((CURSOR) = (CURSOR)->FIELD.next, (TMP) = (CURSOR)->FIELD.next; \
  245. (CURSOR) != (HEAD)->first && (HEAD)->first; (CURSOR) = (TMP), (TMP) = (TMP)->FIELD.next)
  246. /* Assertion code written in Graphene project */
  247. #define CHECK_LIST_HEAD(TYPE, HEAD, FIELD) \
  248. do { \
  249. TYPE pos; \
  250. LISTP_FOR_EACH_ENTRY(pos, HEAD, FIELD) { \
  251. assert((pos->FIELD.prev != pos && pos->FIELD.next != pos) || \
  252. (pos->FIELD.prev == pos && pos->FIELD.next == pos)); \
  253. assert(pos->FIELD.prev->FIELD.next == pos); \
  254. assert(pos->FIELD.next->FIELD.prev == pos); \
  255. } \
  256. } while (0)
  257. // Add NEW to OLD at position first (assuming first is all we need for now)
  258. // Can probably drop TYPE with some preprocessor smarts
  259. #define LISTP_SPLICE(NEW, OLD, FIELD, TYPE) \
  260. do { \
  261. if (!LISTP_EMPTY(NEW)) { \
  262. if (LISTP_EMPTY(OLD)) { \
  263. (OLD)->first = (NEW)->first; \
  264. } else { \
  265. struct TYPE* last_old = (OLD)->first->FIELD.prev; \
  266. (OLD)->first->FIELD.prev->FIELD.next = (NEW)->first; \
  267. (OLD)->first->FIELD.prev = (NEW)->first->FIELD.prev; \
  268. (NEW)->first->FIELD.prev->FIELD.next = (OLD)->first; \
  269. (NEW)->first->FIELD.prev = last_old; \
  270. (OLD)->first = (NEW)->first; \
  271. } \
  272. } \
  273. } while (0)
  274. // Add NEW to OLD at last position
  275. // Can probably drop TYPE with some preprocessor smarts
  276. #define LISTP_SPLICE_TAIL(NEW, OLD, FIELD, TYPE) \
  277. do { \
  278. if (!LISTP_EMPTY(NEW)) { \
  279. if (LISTP_EMPTY(OLD)) { \
  280. (OLD)->first = (NEW)->first; \
  281. } else { \
  282. struct TYPE* last_old = (OLD)->first->FIELD.prev; \
  283. last_old->FIELD.next = (NEW)->first; \
  284. (OLD)->first->FIELD.prev = (NEW)->first->FIELD.prev; \
  285. (NEW)->first->FIELD.prev->FIELD.next = (OLD)->first; \
  286. (NEW)->first->FIELD.prev = last_old; \
  287. } \
  288. } \
  289. } while (0)
  290. #define LISTP_SPLICE_INIT(NEW, OLD, FIELD, TYPE) \
  291. do { \
  292. LISTP_SPLICE(NEW, OLD, FIELD, TYPE); \
  293. INIT_LISTP(NEW); \
  294. } while (0);
  295. #define LISTP_SPLICE_TAIL_INIT(NEW, OLD, FIELD, TYPE) \
  296. do { \
  297. LISTP_SPLICE_TAIL(NEW, OLD, FIELD, TYPE); \
  298. INIT_LISTP(NEW); \
  299. } while (0);
  300. // list_move_tail - delete from OLD, make tail of NEW
  301. #define LISTP_MOVE_TAIL(NODE, NEW, OLD, FIELD) \
  302. do { \
  303. LISTP_DEL_INIT(NODE, OLD, FIELD); \
  304. LISTP_ADD_TAIL(NODE, NEW, FIELD); \
  305. } while (0)
  306. #endif // LIST_H