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