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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * Routines for manipulating a FIFO queue
31  */
32 
33 #include <stdlib.h>
34 
35 #include "fifo.h"
36 #include "memory.h"
37 
38 typedef struct fifonode {
39 	void *fn_data;
40 	struct fifonode *fn_next;
41 } fifonode_t;
42 
43 struct fifo {
44 	fifonode_t *f_head;
45 	fifonode_t *f_tail;
46 };
47 
48 fifo_t *
fifo_new(void)49 fifo_new(void)
50 {
51 	fifo_t *f;
52 
53 	f = xcalloc(sizeof (fifo_t));
54 
55 	return (f);
56 }
57 
58 /* Add to the end of the fifo */
59 void
fifo_add(fifo_t * f,void * data)60 fifo_add(fifo_t *f, void *data)
61 {
62 	fifonode_t *fn = xmalloc(sizeof (fifonode_t));
63 
64 	fn->fn_data = data;
65 	fn->fn_next = NULL;
66 
67 	if (f->f_tail == NULL)
68 		f->f_head = f->f_tail = fn;
69 	else {
70 		f->f_tail->fn_next = fn;
71 		f->f_tail = fn;
72 	}
73 }
74 
75 /* Remove from the front of the fifo */
76 void *
fifo_remove(fifo_t * f)77 fifo_remove(fifo_t *f)
78 {
79 	fifonode_t *fn;
80 	void *data;
81 
82 	if ((fn = f->f_head) == NULL)
83 		return (NULL);
84 
85 	data = fn->fn_data;
86 	if ((f->f_head = fn->fn_next) == NULL)
87 		f->f_tail = NULL;
88 
89 	free(fn);
90 
91 	return (data);
92 }
93 
94 /*ARGSUSED*/
95 static void
fifo_nullfree(void * arg)96 fifo_nullfree(void *arg)
97 {
98 	/* this function intentionally left blank */
99 }
100 
101 /* Free an entire fifo */
102 void
fifo_free(fifo_t * f,void (* freefn)(void *))103 fifo_free(fifo_t *f, void (*freefn)(void *))
104 {
105 	fifonode_t *fn = f->f_head;
106 	fifonode_t *tmp;
107 
108 	if (freefn == NULL)
109 		freefn = fifo_nullfree;
110 
111 	while (fn) {
112 		(*freefn)(fn->fn_data);
113 
114 		tmp = fn;
115 		fn = fn->fn_next;
116 		free(tmp);
117 	}
118 
119 	free(f);
120 }
121 
122 int
fifo_len(fifo_t * f)123 fifo_len(fifo_t *f)
124 {
125 	fifonode_t *fn;
126 	int i;
127 
128 	for (i = 0, fn = f->f_head; fn; fn = fn->fn_next, i++);
129 
130 	return (i);
131 }
132 
133 int
fifo_empty(fifo_t * f)134 fifo_empty(fifo_t *f)
135 {
136 	return (f->f_head == NULL);
137 }
138 
139 int
fifo_iter(fifo_t * f,int (* iter)(void * data,void * arg),void * arg)140 fifo_iter(fifo_t *f, int (*iter)(void *data, void *arg), void *arg)
141 {
142 	fifonode_t *fn;
143 	int rc;
144 	int ret = 0;
145 
146 	for (fn = f->f_head; fn; fn = fn->fn_next) {
147 		if ((rc = iter(fn->fn_data, arg)) < 0)
148 			return (-1);
149 		ret += rc;
150 	}
151 
152 	return (ret);
153 }
154