Home | History | Annotate | Line # | Download | only in os
      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