xref: /illumos-gate/usr/src/cmd/vntsd/queue.c (revision 628e3cbed6489fa1db545d8524a06cd6535af456)
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 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 #pragma ident	"%Z%%M%	%I%	%E% SMI"
26 
27 /*
28  * utility for vntsd queue handling
29  */
30 #include <stdio.h>
31 #include <sys/types.h>
32 #include <sys/ipc.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <sys/socket.h>
37 #include <sys/ipc.h>
38 #include <sys/shm.h>
39 #include <sys/sem.h>
40 #include <wait.h>
41 #include <time.h>
42 #include <netinet/in.h>
43 #include <thread.h>
44 #include <signal.h>
45 #include "vntsd.h"
46 
47 /* alloc_que_el() allocates a queue element */
48 static vntsd_que_t *
49 alloc_que_el(void *handle)
50 {
51 	vntsd_que_t *el;
52 
53 	/* allocate a queue element */
54 	el = (vntsd_que_t *)malloc(sizeof (vntsd_que_t));
55 	if (el == NULL) {
56 		return (NULL);
57 	}
58 
59 
60 	el->nextp = NULL;
61 	el->prevp = NULL;
62 	el->handle = handle;
63 
64 	return (el);
65 }
66 
67 /* vntsd_que_append() appends a element to a queue */
68 int
69 vntsd_que_append(vntsd_que_t **que_hd, void *handle)
70 {
71 	vntsd_que_t *p;
72 	vntsd_que_t *el;
73 
74 	assert(que_hd);
75 	assert(handle);
76 
77 	/* allocate a queue element */
78 	el = alloc_que_el(handle);
79 
80 	if (el == NULL) {
81 		return (VNTSD_ERR_NO_MEM);
82 	}
83 
84 	p = *que_hd;
85 
86 	if (p == NULL) {
87 		/* first one */
88 		*que_hd  = el;
89 	} else {
90 		/* walk to the last one */
91 		while (p->nextp != NULL)
92 			p = p->nextp;
93 		p->nextp = el;
94 	}
95 
96 	el->prevp = p;
97 
98 	return (VNTSD_SUCCESS);
99 }
100 
101 /* vntsd_que_insert_after() inserts element arter the handle */
102 int
103 vntsd_que_insert_after(vntsd_que_t *que, void *handle, void *next)
104 {
105 	vntsd_que_t *q, *el;
106 
107 	assert(que);
108 
109 	q = que;
110 
111 	while (q != NULL) {
112 		if (q->handle == handle) {
113 			break;
114 		}
115 
116 		q = q->nextp;
117 	}
118 
119 	if (q == NULL) {
120 		/* not in queue */
121 		return (VNTSD_ERR_EL_NOT_FOUND);
122 	}
123 
124 	el = alloc_que_el(next);
125 
126 	if (el == NULL) {
127 		return (VNTSD_ERR_NO_MEM);
128 	}
129 
130 	el->nextp = q->nextp;
131 	q->nextp = el;
132 	el->prevp = q;
133 
134 	return (VNTSD_SUCCESS);
135 }
136 
137 
138 
139 /* vntsd_que_rm() removes an element from a queue */
140 int
141 vntsd_que_rm(vntsd_que_t **que_hd, void *handle)
142 {
143 	vntsd_que_t	*p = *que_hd;
144 	vntsd_que_t	*prevp = NULL;
145 
146 
147 	while (p != NULL) {
148 		/* match handle */
149 		if (p->handle == handle) {
150 			break;
151 		}
152 		prevp = p;
153 		p = p->nextp;
154 	}
155 
156 	if (p == NULL) {
157 		/* not found */
158 		return (VNTSD_ERR_EL_NOT_FOUND);
159 	}
160 
161 	/* found */
162 	if (p == *que_hd) {
163 		/* first one */
164 		*que_hd = p->nextp;
165 	} else {
166 		prevp->nextp = p->nextp;
167 	}
168 
169 	if (p->nextp != NULL) {
170 		p->nextp->prevp = prevp;
171 	}
172 
173 	handle = p->handle;
174 
175 	free(p);
176 
177 	return (VNTSD_SUCCESS);
178 
179 }
180 
181 /* vntsd_que_walk() - walk queue and apply function to each element */
182 void *
183 vntsd_que_walk(vntsd_que_t *que_hd, el_func_t el_func)
184 {
185 	vntsd_que_t *p = que_hd;
186 
187 	while (p != NULL) {
188 		if ((*el_func)(p->handle)) {
189 		    return (p->handle);
190 		}
191 
192 		p = p->nextp;
193 	}
194 	return (VNTSD_SUCCESS);
195 }
196 
197 
198 /* vntsd_que_find() finds first match */
199 void *
200 vntsd_que_find(vntsd_que_t *que_hd, compare_func_t compare_func, void *data)
201 {
202 	vntsd_que_t *p = que_hd;
203 
204 	assert(compare_func != NULL);
205 	while (p != NULL) {
206 		if ((*compare_func)(p->handle, data)) {
207 			/* found match */
208 			return (p->handle);
209 		}
210 
211 		p = p->nextp;
212 	}
213 
214 	/* not found */
215 	return (NULL);
216 }
217 
218 /* vntsd_free_que() frees entire queue */
219 void
220 vntsd_free_que(vntsd_que_t **q, clean_func_t clean_func)
221 {
222 	vntsd_que_t *p;
223 
224 	while (*q != NULL) {
225 		p = *q;
226 
227 		*q  = p->nextp;
228 
229 		if (clean_func) {
230 			/* clean func will free the handle */
231 			(*clean_func)(p->handle);
232 		} else {
233 			free(p->handle);
234 		}
235 
236 		free(p);
237 	}
238 }
239 
240 /*
241  * vntsd_que_pos() matches a handle and returns a handle located at "pos"
242  * relative to the matched handle. pos supported are 1 or -1.
243  */
244 void *
245 vntsd_que_pos(vntsd_que_t *que_hd, void *handle, int pos)
246 {
247 	vntsd_que_t *p = que_hd;
248 
249 	assert((pos == 1) || (pos == -1));
250 
251 
252 	while (p != NULL) {
253 		if (p->handle == handle) {
254 			/* find match */
255 			if (pos == 1) {
256 				/* forward 1 */
257 				if (p->nextp != NULL) {
258 					return (p->nextp->handle);
259 				}
260 
261 				/* last one go to first */
262 				return (que_hd->handle);
263 
264 			} else {
265 				/* backward 1 */
266 				if (p->prevp != NULL) {
267 					return (p->prevp->handle);
268 				}
269 
270 				/* first one, return last one */
271 				while (p->nextp != NULL) {
272 					p = p->nextp;
273 				}
274 
275 				assert(p != NULL);
276 				assert(p->handle != NULL);
277 				return (p->handle);
278 
279 			}
280 		}
281 		p = p->nextp;
282 	}
283 
284 	DERR(stderr, "t@%d vntsd_que_pos can not find handle \n",
285 	    thr_self());
286 
287 	return (NULL);
288 }
289