PageRenderTime 81ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/libspl/list.c

http://github.com/zfsonlinux/zfs
C | 242 lines | 175 code | 36 blank | 31 comment | 24 complexity | ba98bff9cd26d929b0de6343e9bc03cc MD5 | raw file
Possible License(s): Apache-2.0, MPL-2.0-no-copyleft-exception
  1. /*
  2. * CDDL HEADER START
  3. *
  4. * The contents of this file are subject to the terms of the
  5. * Common Development and Distribution License (the "License").
  6. * You may not use this file except in compliance with the License.
  7. *
  8. * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  9. * or http://www.opensolaris.org/os/licensing.
  10. * See the License for the specific language governing permissions
  11. * and limitations under the License.
  12. *
  13. * When distributing Covered Code, include this CDDL HEADER in each
  14. * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15. * If applicable, add the following below this CDDL HEADER, with the
  16. * fields enclosed by brackets "[]" replaced with your own identifying
  17. * information: Portions Copyright [yyyy] [name of copyright owner]
  18. *
  19. * CDDL HEADER END
  20. */
  21. /*
  22. * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
  23. * Use is subject to license terms.
  24. */
  25. /*
  26. * Generic doubly-linked list implementation
  27. */
  28. #include <sys/list.h>
  29. #include <sys/list_impl.h>
  30. #include <sys/types.h>
  31. #include <sys/sysmacros.h>
  32. #include <sys/debug.h>
  33. #define list_d2l(a, obj) ((list_node_t *)(((char *)obj) + (a)->list_offset))
  34. #define list_object(a, node) ((void *)(((char *)node) - (a)->list_offset))
  35. #define list_empty(a) ((a)->list_head.next == &(a)->list_head)
  36. #define list_insert_after_node(list, node, object) { \
  37. list_node_t *lnew = list_d2l(list, object); \
  38. lnew->prev = (node); \
  39. lnew->next = (node)->next; \
  40. (node)->next->prev = lnew; \
  41. (node)->next = lnew; \
  42. }
  43. #define list_insert_before_node(list, node, object) { \
  44. list_node_t *lnew = list_d2l(list, object); \
  45. lnew->next = (node); \
  46. lnew->prev = (node)->prev; \
  47. (node)->prev->next = lnew; \
  48. (node)->prev = lnew; \
  49. }
  50. #define list_remove_node(node) \
  51. (node)->prev->next = (node)->next; \
  52. (node)->next->prev = (node)->prev; \
  53. (node)->next = (node)->prev = NULL
  54. void
  55. list_create(list_t *list, size_t size, size_t offset)
  56. {
  57. ASSERT(list);
  58. ASSERT(size > 0);
  59. ASSERT(size >= offset + sizeof (list_node_t));
  60. list->list_size = size;
  61. list->list_offset = offset;
  62. list->list_head.next = list->list_head.prev = &list->list_head;
  63. }
  64. void
  65. list_destroy(list_t *list)
  66. {
  67. list_node_t *node = &list->list_head;
  68. ASSERT(list);
  69. ASSERT(list->list_head.next == node);
  70. ASSERT(list->list_head.prev == node);
  71. node->next = node->prev = NULL;
  72. }
  73. void
  74. list_insert_after(list_t *list, void *object, void *nobject)
  75. {
  76. if (object == NULL) {
  77. list_insert_head(list, nobject);
  78. } else {
  79. list_node_t *lold = list_d2l(list, object);
  80. list_insert_after_node(list, lold, nobject);
  81. }
  82. }
  83. void
  84. list_insert_before(list_t *list, void *object, void *nobject)
  85. {
  86. if (object == NULL) {
  87. list_insert_tail(list, nobject);
  88. } else {
  89. list_node_t *lold = list_d2l(list, object);
  90. list_insert_before_node(list, lold, nobject);
  91. }
  92. }
  93. void
  94. list_insert_head(list_t *list, void *object)
  95. {
  96. list_node_t *lold = &list->list_head;
  97. list_insert_after_node(list, lold, object);
  98. }
  99. void
  100. list_insert_tail(list_t *list, void *object)
  101. {
  102. list_node_t *lold = &list->list_head;
  103. list_insert_before_node(list, lold, object);
  104. }
  105. void
  106. list_remove(list_t *list, void *object)
  107. {
  108. list_node_t *lold = list_d2l(list, object);
  109. ASSERT(!list_empty(list));
  110. ASSERT(lold->next != NULL);
  111. list_remove_node(lold);
  112. }
  113. void *
  114. list_remove_head(list_t *list)
  115. {
  116. list_node_t *head = list->list_head.next;
  117. if (head == &list->list_head)
  118. return (NULL);
  119. list_remove_node(head);
  120. return (list_object(list, head));
  121. }
  122. void *
  123. list_remove_tail(list_t *list)
  124. {
  125. list_node_t *tail = list->list_head.prev;
  126. if (tail == &list->list_head)
  127. return (NULL);
  128. list_remove_node(tail);
  129. return (list_object(list, tail));
  130. }
  131. void *
  132. list_head(list_t *list)
  133. {
  134. if (list_empty(list))
  135. return (NULL);
  136. return (list_object(list, list->list_head.next));
  137. }
  138. void *
  139. list_tail(list_t *list)
  140. {
  141. if (list_empty(list))
  142. return (NULL);
  143. return (list_object(list, list->list_head.prev));
  144. }
  145. void *
  146. list_next(list_t *list, void *object)
  147. {
  148. list_node_t *node = list_d2l(list, object);
  149. if (node->next != &list->list_head)
  150. return (list_object(list, node->next));
  151. return (NULL);
  152. }
  153. void *
  154. list_prev(list_t *list, void *object)
  155. {
  156. list_node_t *node = list_d2l(list, object);
  157. if (node->prev != &list->list_head)
  158. return (list_object(list, node->prev));
  159. return (NULL);
  160. }
  161. /*
  162. * Insert src list after dst list. Empty src list thereafter.
  163. */
  164. void
  165. list_move_tail(list_t *dst, list_t *src)
  166. {
  167. list_node_t *dstnode = &dst->list_head;
  168. list_node_t *srcnode = &src->list_head;
  169. ASSERT(dst->list_size == src->list_size);
  170. ASSERT(dst->list_offset == src->list_offset);
  171. if (list_empty(src))
  172. return;
  173. dstnode->prev->next = srcnode->next;
  174. srcnode->next->prev = dstnode->prev;
  175. dstnode->prev = srcnode->prev;
  176. srcnode->prev->next = dstnode;
  177. /* empty src list */
  178. srcnode->next = srcnode->prev = srcnode;
  179. }
  180. void
  181. list_link_replace(list_node_t *lold, list_node_t *lnew)
  182. {
  183. ASSERT(list_link_active(lold));
  184. ASSERT(!list_link_active(lnew));
  185. lnew->next = lold->next;
  186. lnew->prev = lold->prev;
  187. lold->prev->next = lnew;
  188. lold->next->prev = lnew;
  189. lold->next = lold->prev = NULL;
  190. }
  191. void
  192. list_link_init(list_node_t *ln)
  193. {
  194. ln->next = NULL;
  195. ln->prev = NULL;
  196. }
  197. int
  198. list_link_active(list_node_t *ln)
  199. {
  200. return (ln->next != NULL);
  201. }
  202. int
  203. list_is_empty(list_t *list)
  204. {
  205. return (list_empty(list));
  206. }