xref: /onnv-gate/usr/src/uts/common/io/mega_sas/list.h (revision 7698:44d51e063f92)
16447Ssusans /*
26447Ssusans  * list.h: header for mega_sas
36447Ssusans  *
46447Ssusans  * Solaris MegaRAID driver for SAS controllers
56447Ssusans  * Copyright (c) 2004-2008, LSI Logic Corporation.
66447Ssusans  * All rights reserved.
76447Ssusans  *
86447Ssusans  * Redistribution and use in source and binary forms, with or without
96447Ssusans  * modification, are permitted provided that the following conditions are met:
106447Ssusans  *
116447Ssusans  * 1. Redistributions of source code must retain the above copyright notice,
126447Ssusans  *    this list of conditions and the following disclaimer.
136447Ssusans  *
146447Ssusans  * 2. Redistributions in binary form must reproduce the above copyright notice,
156447Ssusans  *    this list of conditions and the following disclaimer in the documentation
166447Ssusans  *    and/or other materials provided with the distribution.
176447Ssusans  *
186447Ssusans  * 3. Neither the name of the author nor the names of its contributors may be
196447Ssusans  *    used to endorse or promote products derived from this software without
206447Ssusans  *    specific prior written permission.
216447Ssusans  *
226447Ssusans  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
236447Ssusans  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
246447Ssusans  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
256447Ssusans  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
266447Ssusans  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
276447Ssusans  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
286447Ssusans  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
296447Ssusans  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
306447Ssusans  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
316447Ssusans  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
326447Ssusans  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
336447Ssusans  * DAMAGE.
346447Ssusans  */
356447Ssusans 
366447Ssusans /*
376447Ssusans  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
386447Ssusans  * Use is subject to license terms.
396447Ssusans  */
406447Ssusans 
416447Ssusans #ifndef	_LIST_H_
426447Ssusans #define	_LIST_H_
436447Ssusans 
446447Ssusans #ifdef __cplusplus
456447Ssusans extern "C" {
466447Ssusans #endif
476447Ssusans 
486447Ssusans /*
496447Ssusans  * Simple doubly linked list implementation.
506447Ssusans  *
516447Ssusans  * Some of the internal functions ("__xxx") are useful when
526447Ssusans  * manipulating whole lists rather than single entries, as
536447Ssusans  * sometimes we already know the next/prev entries and we can
546447Ssusans  * generate better code by using them directly rather than
556447Ssusans  * using the generic single-entry routines.
566447Ssusans  */
576447Ssusans 
586447Ssusans struct mlist_head {
596447Ssusans 	struct mlist_head *next, *prev;
606447Ssusans };
616447Ssusans 
626447Ssusans typedef struct mlist_head mlist_t;
636447Ssusans 
646447Ssusans #define	LIST_HEAD_INIT(name) { &(name), &(name) }
656447Ssusans 
666447Ssusans #define	LIST_HEAD(name) \
676447Ssusans 	struct mlist_head name = LIST_HEAD_INIT(name)
686447Ssusans 
696447Ssusans #define	INIT_LIST_HEAD(ptr) { \
706447Ssusans 	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
716447Ssusans }
726447Ssusans 
736447Ssusans 
746447Ssusans /*
756447Ssusans  * Insert a new entry between two known consecutive entries.
766447Ssusans  *
776447Ssusans  * This is only for internal list manipulation where we know
786447Ssusans  * the prev/next entries already!
796447Ssusans  */
__list_add(struct mlist_head * new,struct mlist_head * prev,struct mlist_head * next)806447Ssusans static void __list_add(struct mlist_head *new,
816447Ssusans 	struct mlist_head *prev,
826447Ssusans 	struct mlist_head *next)
836447Ssusans {
846447Ssusans 	next->prev = new;
856447Ssusans 	new->next = next;
866447Ssusans 	new->prev = prev;
876447Ssusans 	prev->next = new;
886447Ssusans }
896447Ssusans 
906447Ssusans 
916447Ssusans /*
926447Ssusans  * mlist_add - add a new entry
936447Ssusans  * @new: new entry to be added
946447Ssusans  * @head: list head to add it after
956447Ssusans  *
966447Ssusans  * Insert a new entry after the specified head.
976447Ssusans  * This is good for implementing stacks.
986447Ssusans  */
mlist_add(struct mlist_head * new,struct mlist_head * head)996447Ssusans static void mlist_add(struct mlist_head *new, struct mlist_head *head)
1006447Ssusans {
1016447Ssusans 	__list_add(new, head, head->next);
1026447Ssusans }
1036447Ssusans 
1046447Ssusans 
1056447Ssusans /*
1066447Ssusans  * mlist_add_tail - add a new entry
1076447Ssusans  * @new: new entry to be added
1086447Ssusans  * @head: list head to add it before
1096447Ssusans  *
1106447Ssusans  * Insert a new entry before the specified head.
1116447Ssusans  * This is useful for implementing queues.
1126447Ssusans  */
mlist_add_tail(struct mlist_head * new,struct mlist_head * head)1136447Ssusans static void mlist_add_tail(struct mlist_head *new, struct mlist_head *head)
1146447Ssusans {
1156447Ssusans 	__list_add(new, head->prev, head);
1166447Ssusans }
1176447Ssusans 
1186447Ssusans 
1196447Ssusans 
1206447Ssusans /*
1216447Ssusans  * Delete a list entry by making the prev/next entries
1226447Ssusans  * point to each other.
1236447Ssusans  *
1246447Ssusans  * This is only for internal list manipulation where we know
1256447Ssusans  * the prev/next entries already!
1266447Ssusans  */
__list_del(struct mlist_head * prev,struct mlist_head * next)1276447Ssusans static void __list_del(struct mlist_head *prev,
1286447Ssusans 			struct mlist_head *next)
1296447Ssusans {
1306447Ssusans 	next->prev = prev;
1316447Ssusans 	prev->next = next;
1326447Ssusans }
1336447Ssusans 
1346447Ssusans 
135*7698SSusan.Scheufele@Sun.COM #if 0
1366447Ssusans /*
1376447Ssusans  * mlist_del - deletes entry from list.
1386447Ssusans  * @entry:	the element to delete from the list.
1396447Ssusans  * Note:	list_empty on entry does not return true after this, the entry
1406447Ssusans  * is in an undefined state.
1416447Ssusans  */
142*7698SSusan.Scheufele@Sun.COM 
1436447Ssusans static void mlist_del(struct mlist_head *entry)
1446447Ssusans {
1456447Ssusans 	__list_del(entry->prev, entry->next);
1466447Ssusans 	entry->next = entry->prev = 0;
1476447Ssusans }
148*7698SSusan.Scheufele@Sun.COM #endif
1496447Ssusans 
1506447Ssusans /*
1516447Ssusans  * mlist_del_init - deletes entry from list and reinitialize it.
1526447Ssusans  * @entry: the element to delete from the list.
1536447Ssusans  */
mlist_del_init(struct mlist_head * entry)1546447Ssusans static void mlist_del_init(struct mlist_head *entry)
1556447Ssusans {
1566447Ssusans 	__list_del(entry->prev, entry->next);
1576447Ssusans 	INIT_LIST_HEAD(entry);
1586447Ssusans }
1596447Ssusans 
1606447Ssusans 
1616447Ssusans /*
1626447Ssusans  * mlist_empty - tests whether a list is empty
1636447Ssusans  * @head: the list to test.
1646447Ssusans  */
mlist_empty(struct mlist_head * head)1656447Ssusans static int mlist_empty(struct mlist_head *head)
1666447Ssusans {
1676447Ssusans 	return (head->next == head);
1686447Ssusans }
1696447Ssusans 
1706447Ssusans 
1716447Ssusans /*
1726447Ssusans  * mlist_splice - join two lists
1736447Ssusans  * @list: the new list to add.
1746447Ssusans  * @head: the place to add it in the first list.
1756447Ssusans  */
mlist_splice(struct mlist_head * list,struct mlist_head * head)1766447Ssusans static void mlist_splice(struct mlist_head *list, struct mlist_head *head)
1776447Ssusans {
1786447Ssusans 	struct mlist_head *first = list->next;
1796447Ssusans 
1806447Ssusans 	if (first != list) {
1816447Ssusans 		struct mlist_head *last = list->prev;
1826447Ssusans 		struct mlist_head *at = head->next;
1836447Ssusans 
1846447Ssusans 		first->prev = head;
1856447Ssusans 		head->next = first;
1866447Ssusans 
1876447Ssusans 		last->next = at;
1886447Ssusans 		at->prev = last;
1896447Ssusans 	}
1906447Ssusans }
1916447Ssusans 
1926447Ssusans 
1936447Ssusans 
1946447Ssusans /* TODO: set this */
1956447Ssusans #if 0
1966447Ssusans #pragma	inline(list_add, list_add_tail, __list_del, list_del,
1976447Ssusans 		list_del_init, list_empty, list_splice)
1986447Ssusans #endif
1996447Ssusans 
2006447Ssusans 
2016447Ssusans /*
2026447Ssusans  * mlist_entry - get the struct for this entry
2036447Ssusans  * @ptr:	the &struct mlist_head pointer.
2046447Ssusans  * @type:	the type of the struct this is embedded in.
2056447Ssusans  * @member:	the name of the list_struct within the struct.
2066447Ssusans  */
2076447Ssusans #define	mlist_entry(ptr, type, member) \
208*7698SSusan.Scheufele@Sun.COM 	((type *)((size_t)(ptr) - offsetof(type, member)))
2096447Ssusans 
2106447Ssusans 
2116447Ssusans /*
2126447Ssusans  * mlist_for_each	-	iterate over a list
2136447Ssusans  * @pos:	the &struct mlist_head to use as a loop counter.
2146447Ssusans  * @head:	the head for your list.
2156447Ssusans  */
2166447Ssusans #define	mlist_for_each(pos, head) \
2176447Ssusans 	for (pos = (head)->next, prefetch(pos->next); pos != (head); \
2186447Ssusans 		pos = pos->next, prefetch(pos->next))
2196447Ssusans 
2206447Ssusans 
2216447Ssusans /*
2226447Ssusans  * mlist_for_each_safe - iterate over a list safe against removal of list entry
2236447Ssusans  * @pos:	the &struct mlist_head to use as a loop counter.
2246447Ssusans  * @n:		another &struct mlist_head to use as temporary storage
2256447Ssusans  * @head:	the head for your list.
2266447Ssusans  */
2276447Ssusans #define	mlist_for_each_safe(pos, n, head) \
2286447Ssusans 	for (pos = (head)->next, n = pos->next; pos != (head); \
2296447Ssusans 		pos = n, n = pos->next)
2306447Ssusans 
2316447Ssusans #ifdef __cplusplus
2326447Ssusans }
2336447Ssusans #endif
2346447Ssusans 
2356447Ssusans #endif /* _LIST_H_ */
236