PageRenderTime 43ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/include/sys/list.h

http://github.com/zfsonlinux/spl
C Header | 219 lines | 143 code | 37 blank | 39 comment | 17 complexity | 109f8854e3ea8517e921322fc5c0efdb MD5 | raw file
Possible License(s): GPL-2.0
  1. /*****************************************************************************\
  2. * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
  3. * Copyright (C) 2007 The Regents of the University of California.
  4. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  5. * Written by Brian Behlendorf <behlendorf1@llnl.gov>.
  6. * UCRL-CODE-235197
  7. *
  8. * This file is part of the SPL, Solaris Porting Layer.
  9. * For details, see <http://zfsonlinux.org/>.
  10. *
  11. * The SPL is free software; you can redistribute it and/or modify it
  12. * under the terms of the GNU General Public License as published by the
  13. * Free Software Foundation; either version 2 of the License, or (at your
  14. * option) any later version.
  15. *
  16. * The SPL is distributed in the hope that it will be useful, but WITHOUT
  17. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  18. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  19. * for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License along
  22. * with the SPL. If not, see <http://www.gnu.org/licenses/>.
  23. \*****************************************************************************/
  24. #ifndef _SPL_LIST_H
  25. #define _SPL_LIST_H
  26. #include <sys/types.h>
  27. #include <linux/list.h>
  28. /*
  29. * NOTE: I have implemented the Solaris list API in terms of the native
  30. * linux API. This has certain advantages in terms of leveraging the linux
  31. * list debugging infrastructure, but it also means that the internals of a
  32. * list differ slightly than on Solaris. This is not a problem as long as
  33. * all callers stick to the published API. The two major differences are:
  34. *
  35. * 1) A list_node_t is mapped to a linux list_head struct which changes
  36. * the name of the list_next/list_prev pointers to next/prev respectively.
  37. *
  38. * 2) A list_node_t which is not attached to a list on Solaris is denoted
  39. * by having its list_next/list_prev pointers set to NULL. Under linux
  40. * the next/prev pointers are set to LIST_POISON1 and LIST_POISON2
  41. * respectively. At this moment this only impacts the implementation
  42. * of the list_link_init() and list_link_active() functions.
  43. */
  44. typedef struct list_head list_node_t;
  45. typedef struct list {
  46. size_t list_size;
  47. size_t list_offset;
  48. list_node_t list_head;
  49. } list_t;
  50. #define list_d2l(a, obj) ((list_node_t *)(((char *)obj) + (a)->list_offset))
  51. #define list_object(a, node) ((void *)(((char *)node) - (a)->list_offset))
  52. static inline int
  53. list_is_empty(list_t *list)
  54. {
  55. return list_empty(&list->list_head);
  56. }
  57. static inline void
  58. list_link_init(list_node_t *node)
  59. {
  60. node->next = LIST_POISON1;
  61. node->prev = LIST_POISON2;
  62. }
  63. static inline void
  64. list_create(list_t *list, size_t size, size_t offset)
  65. {
  66. ASSERT(list);
  67. ASSERT(size > 0);
  68. ASSERT(size >= offset + sizeof(list_node_t));
  69. list->list_size = size;
  70. list->list_offset = offset;
  71. INIT_LIST_HEAD(&list->list_head);
  72. }
  73. static inline void
  74. list_destroy(list_t *list)
  75. {
  76. ASSERT(list);
  77. ASSERT(list_is_empty(list));
  78. list_del(&list->list_head);
  79. }
  80. static inline void
  81. list_insert_head(list_t *list, void *object)
  82. {
  83. list_add(list_d2l(list, object), &list->list_head);
  84. }
  85. static inline void
  86. list_insert_tail(list_t *list, void *object)
  87. {
  88. list_add_tail(list_d2l(list, object), &list->list_head);
  89. }
  90. static inline void
  91. list_insert_after(list_t *list, void *object, void *nobject)
  92. {
  93. if (object == NULL)
  94. list_insert_head(list, nobject);
  95. else
  96. list_add(list_d2l(list, nobject), list_d2l(list, object));
  97. }
  98. static inline void
  99. list_insert_before(list_t *list, void *object, void *nobject)
  100. {
  101. if (object == NULL)
  102. list_insert_tail(list, nobject);
  103. else
  104. list_add_tail(list_d2l(list, nobject), list_d2l(list, object));
  105. }
  106. static inline void
  107. list_remove(list_t *list, void *object)
  108. {
  109. ASSERT(!list_is_empty(list));
  110. list_del(list_d2l(list, object));
  111. }
  112. static inline void *
  113. list_remove_head(list_t *list)
  114. {
  115. list_node_t *head = list->list_head.next;
  116. if (head == &list->list_head)
  117. return NULL;
  118. list_del(head);
  119. return list_object(list, head);
  120. }
  121. static inline void *
  122. list_remove_tail(list_t *list)
  123. {
  124. list_node_t *tail = list->list_head.prev;
  125. if (tail == &list->list_head)
  126. return NULL;
  127. list_del(tail);
  128. return list_object(list, tail);
  129. }
  130. static inline void *
  131. list_head(list_t *list)
  132. {
  133. if (list_is_empty(list))
  134. return NULL;
  135. return list_object(list, list->list_head.next);
  136. }
  137. static inline void *
  138. list_tail(list_t *list)
  139. {
  140. if (list_is_empty(list))
  141. return NULL;
  142. return list_object(list, list->list_head.prev);
  143. }
  144. static inline void *
  145. list_next(list_t *list, void *object)
  146. {
  147. list_node_t *node = list_d2l(list, object);
  148. if (node->next != &list->list_head)
  149. return list_object(list, node->next);
  150. return NULL;
  151. }
  152. static inline void *
  153. list_prev(list_t *list, void *object)
  154. {
  155. list_node_t *node = list_d2l(list, object);
  156. if (node->prev != &list->list_head)
  157. return list_object(list, node->prev);
  158. return NULL;
  159. }
  160. static inline int
  161. list_link_active(list_node_t *node)
  162. {
  163. return (node->next != LIST_POISON1) && (node->prev != LIST_POISON2);
  164. }
  165. static inline void
  166. spl_list_move_tail(list_t *dst, list_t *src)
  167. {
  168. list_splice_init(&src->list_head, dst->list_head.prev);
  169. }
  170. #define list_move_tail(dst, src) spl_list_move_tail(dst, src)
  171. static inline void
  172. list_link_replace(list_node_t *old_node, list_node_t *new_node)
  173. {
  174. ASSERT(list_link_active(old_node));
  175. ASSERT(!list_link_active(new_node));
  176. new_node->next = old_node->next;
  177. new_node->prev = old_node->prev;
  178. old_node->prev->next = new_node;
  179. old_node->next->prev = new_node;
  180. list_link_init(old_node);
  181. }
  182. #endif /* SPL_LIST_H */