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