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 * Copyright (c) 2002-2006 Neterion, Inc.
22 */
23
24#ifndef XGE_LIST_H
25#define XGE_LIST_H
26
27#include "xge-debug.h"
28
29__EXTERN_BEGIN_DECLS
30
31/**
32 * struct xge_list_t - List item.
33 * @prev: Previous list item.
34 * @next: Next list item.
35 *
36 * Item of a bi-directional linked list.
37 */
38typedef struct xge_list_t {
39	struct xge_list_t* prev;
40	struct xge_list_t* next;
41} xge_list_t;
42
43/**
44 * xge_list_init - Initialize linked list.
45 * header: first element of the list (head)
46 *
47 * Initialize linked list.
48 * See also: xge_list_t{}.
49 */
50static inline void xge_list_init (xge_list_t *header)
51{
52	header->next = header;
53	header->prev = header;
54}
55
56/**
57 * xge_list_is_empty - Is the list empty?
58 * header: first element of the list (head)
59 *
60 * Determine whether the bi-directional list is empty. Return '1' in
61 * case of 'empty'.
62 * See also: xge_list_t{}.
63 */
64static inline int xge_list_is_empty(xge_list_t *header)
65{
66    xge_assert(header != NULL);
67
68    return header->next == header;
69}
70
71/**
72 * xge_list_first_get - Return the first item from the linked list.
73 * header: first element of the list (head)
74 *
75 * Returns the next item from the header.
76 * Returns NULL if the next item is header itself
77 * See also: xge_list_remove(), xge_list_insert(), xge_list_t{}.
78 */
79static inline xge_list_t *xge_list_first_get(xge_list_t *header)
80{
81	xge_assert(header != NULL);
82	xge_assert(header->next != NULL);
83	xge_assert(header->prev != NULL);
84
85	if(header->next == header)
86		return NULL;
87	else
88		return header->next;
89}
90
91/**
92 * xge_list_remove - Remove the specified item from the linked list.
93 * item: element of the list
94 *
95 * Remove item from a list.
96 * See also: xge_list_insert(), xge_list_t{}.
97 */
98static inline void xge_list_remove(xge_list_t *item)
99{
100	xge_assert(item != NULL);
101	xge_assert(item->next != NULL);
102	xge_assert(item->prev != NULL);
103
104	item->next->prev = item->prev;
105	item->prev->next = item->next;
106#ifdef XGE_DEBUG_ASSERT
107	item->next = item->prev = NULL;
108#endif
109}
110
111/**
112 * xge_list_insert - Insert a new item after the specified item.
113 * new_item: new element of the list
114 * prev_item: element of the list after which the new element is
115 *             inserted
116 *
117 * Insert new item (new_item) after given item (prev_item).
118 * See also: xge_list_remove(), xge_list_insert_before(), xge_list_t{}.
119 */
120static inline void xge_list_insert (xge_list_t *new_item,
121				    xge_list_t *prev_item)
122{
123	xge_assert(new_item  != NULL);
124	xge_assert(prev_item != NULL);
125	xge_assert(prev_item->next != NULL);
126
127	new_item->next = prev_item->next;
128	new_item->prev = prev_item;
129	prev_item->next->prev = new_item;
130	prev_item->next = new_item;
131}
132
133/**
134 * xge_list_insert_before - Insert a new item before the specified item.
135 * new_item: new element of the list
136 * next_item: element of the list after which the new element is inserted
137 *
138 * Insert new item (new_item) before given item (next_item).
139 */
140static inline void xge_list_insert_before (xge_list_t *new_item,
141				    	   xge_list_t *next_item)
142{
143	xge_assert(new_item  != NULL);
144	xge_assert(next_item != NULL);
145	xge_assert(next_item->next != NULL);
146
147	new_item->next = next_item;
148	new_item->prev = next_item->prev;
149	next_item->prev->next = new_item;
150	next_item->prev = new_item;
151}
152
153#define xge_list_for_each(_p, _h) \
154	for (_p = (_h)->next, xge_os_prefetch(_p->next); _p != (_h); \
155		_p = _p->next, xge_os_prefetch(_p->next))
156
157#define xge_list_for_each_safe(_p, _n, _h) \
158        for (_p = (_h)->next, _n = _p->next; _p != (_h); \
159                _p = _n, _n = _p->next)
160
161#ifdef __GNUC__
162/**
163 * xge_container_of - Given a member, return the containing structure.
164 * @ptr:	the pointer to the member.
165 * @type:	the type of the container struct this is embedded in.
166 * @member:	the name of the member within the struct.
167 *
168 * Cast a member of a structure out to the containing structure.
169 */
170#define xge_container_of(ptr, type, member) ({			\
171         __typeof( ((type *)0)->member ) *__mptr = (ptr);	\
172        (type *)(void *)( (char *)__mptr - ((size_t) &((type *)0)->member) );})
173#else
174/* type unsafe version */
175#define xge_container_of(ptr, type, member) \
176                ((type*)(void*)((char*)(ptr) - ((size_t) &((type *)0)->member)))
177#endif
178
179/**
180 * xge_offsetof - Offset of the member in the containing structure.
181 * @t:	struct name.
182 * @m:	the name of the member within the struct.
183 *
184 * Return the offset of the member @m in the structure @t.
185 */
186#define xge_offsetof(t, m) ((size_t) (&((t *)0)->m))
187
188__EXTERN_END_DECLS
189
190#endif /* XGE_LIST_H */
191