xref: /netbsd-src/external/bsd/libbind/dist/isc/ev_waits.c (revision 5bbd2a12505d72a8177929a37b5cee489d0a1cfd)
1 /*	$NetBSD: ev_waits.c,v 1.1.1.2 2012/09/09 16:08:02 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5  * Copyright (c) 1996-1999 by Internet Software Consortium
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /* ev_waits.c - implement deferred function calls for the eventlib
21  * vix 05dec95 [initial]
22  */
23 
24 #if !defined(LINT) && !defined(CODECENTER)
25 static const char rcsid[] = "Id: ev_waits.c,v 1.4 2005/04/27 04:56:36 sra Exp ";
26 #endif
27 
28 #include "port_before.h"
29 #include "fd_setsize.h"
30 
31 #include <errno.h>
32 
33 #include <isc/eventlib.h>
34 #include <isc/assertions.h>
35 #include "eventlib_p.h"
36 
37 #include "port_after.h"
38 
39 /* Forward. */
40 
41 static void		print_waits(evContext_p *ctx);
42 static evWaitList *	evNewWaitList(evContext_p *);
43 static void		evFreeWaitList(evContext_p *, evWaitList *);
44 static evWaitList *	evGetWaitList(evContext_p *, const void *, int);
45 
46 
47 /* Public. */
48 
49 /*%
50  * Enter a new wait function on the queue.
51  */
52 int
evWaitFor(evContext opaqueCtx,const void * tag,evWaitFunc func,void * uap,evWaitID * id)53 evWaitFor(evContext opaqueCtx, const void *tag,
54 	  evWaitFunc func, void *uap, evWaitID *id)
55 {
56 	evContext_p *ctx = opaqueCtx.opaque;
57 	evWait *new;
58 	evWaitList *wl = evGetWaitList(ctx, tag, 1);
59 
60 	OKNEW(new);
61 	new->func = func;
62 	new->uap = uap;
63 	new->tag = tag;
64 	new->next = NULL;
65 	if (wl->last != NULL)
66 		wl->last->next = new;
67 	else
68 		wl->first = new;
69 	wl->last = new;
70 	if (id != NULL)
71 		id->opaque = new;
72 	if (ctx->debug >= 9)
73 		print_waits(ctx);
74 	return (0);
75 }
76 
77 /*%
78  * Mark runnable all waiting functions having a certain tag.
79  */
80 int
evDo(evContext opaqueCtx,const void * tag)81 evDo(evContext opaqueCtx, const void *tag) {
82 	evContext_p *ctx = opaqueCtx.opaque;
83 	evWaitList *wl = evGetWaitList(ctx, tag, 0);
84 	evWait *first;
85 
86 	if (!wl) {
87 		errno = ENOENT;
88 		return (-1);
89 	}
90 
91 	first = wl->first;
92 	INSIST(first != NULL);
93 
94 	if (ctx->waitDone.last != NULL)
95 		ctx->waitDone.last->next = first;
96 	else
97 		ctx->waitDone.first = first;
98 	ctx->waitDone.last = wl->last;
99 	evFreeWaitList(ctx, wl);
100 
101 	return (0);
102 }
103 
104 /*%
105  * Remove a waiting (or ready to run) function from the queue.
106  */
107 int
evUnwait(evContext opaqueCtx,evWaitID id)108 evUnwait(evContext opaqueCtx, evWaitID id) {
109 	evContext_p *ctx = opaqueCtx.opaque;
110 	evWait *this, *prev;
111 	evWaitList *wl;
112 	int found = 0;
113 
114 	this = id.opaque;
115 	INSIST(this != NULL);
116 	wl = evGetWaitList(ctx, this->tag, 0);
117 	if (wl != NULL) {
118 		for (prev = NULL, this = wl->first;
119 		     this != NULL;
120 		     prev = this, this = this->next)
121 			if (this == (evWait *)id.opaque) {
122 				found = 1;
123 				if (prev != NULL)
124 					prev->next = this->next;
125 				else
126 					wl->first = this->next;
127 				if (wl->last == this)
128 					wl->last = prev;
129 				if (wl->first == NULL)
130 					evFreeWaitList(ctx, wl);
131 				break;
132 			}
133 	}
134 
135 	if (!found) {
136 		/* Maybe it's done */
137 		for (prev = NULL, this = ctx->waitDone.first;
138 		     this != NULL;
139 		     prev = this, this = this->next)
140 			if (this == (evWait *)id.opaque) {
141 				found = 1;
142 				if (prev != NULL)
143 					prev->next = this->next;
144 				else
145 					ctx->waitDone.first = this->next;
146 				if (ctx->waitDone.last == this)
147 					ctx->waitDone.last = prev;
148 				break;
149 			}
150 	}
151 
152 	if (!found) {
153 		errno = ENOENT;
154 		return (-1);
155 	}
156 
157 	FREE(this);
158 
159 	if (ctx->debug >= 9)
160 		print_waits(ctx);
161 
162 	return (0);
163 }
164 
165 int
evDefer(evContext opaqueCtx,evWaitFunc func,void * uap)166 evDefer(evContext opaqueCtx, evWaitFunc func, void *uap) {
167 	evContext_p *ctx = opaqueCtx.opaque;
168 	evWait *new;
169 
170 	OKNEW(new);
171 	new->func = func;
172 	new->uap = uap;
173 	new->tag = NULL;
174 	new->next = NULL;
175 	if (ctx->waitDone.last != NULL)
176 		ctx->waitDone.last->next = new;
177 	else
178 		ctx->waitDone.first = new;
179 	ctx->waitDone.last = new;
180 	if (ctx->debug >= 9)
181 		print_waits(ctx);
182 	return (0);
183 }
184 
185 /* Private. */
186 
187 static void
print_waits(evContext_p * ctx)188 print_waits(evContext_p *ctx) {
189 	evWaitList *wl;
190 	evWait *this;
191 
192 	evPrintf(ctx, 9, "wait waiting:\n");
193 	for (wl = ctx->waitLists; wl != NULL; wl = wl->next) {
194 		INSIST(wl->first != NULL);
195 		evPrintf(ctx, 9, "  tag %p:", wl->first->tag);
196 		for (this = wl->first; this != NULL; this = this->next)
197 			evPrintf(ctx, 9, " %p", this);
198 		evPrintf(ctx, 9, "\n");
199 	}
200 	evPrintf(ctx, 9, "wait done:");
201 	for (this = ctx->waitDone.first; this != NULL; this = this->next)
202 		evPrintf(ctx, 9, " %p", this);
203 	evPrintf(ctx, 9, "\n");
204 }
205 
206 static evWaitList *
evNewWaitList(evContext_p * ctx)207 evNewWaitList(evContext_p *ctx) {
208 	evWaitList *new;
209 
210 	NEW(new);
211 	if (new == NULL)
212 		return (NULL);
213 	new->first = new->last = NULL;
214 	new->prev = NULL;
215 	new->next = ctx->waitLists;
216 	if (new->next != NULL)
217 		new->next->prev = new;
218 	ctx->waitLists = new;
219 	return (new);
220 }
221 
222 static void
evFreeWaitList(evContext_p * ctx,evWaitList * this)223 evFreeWaitList(evContext_p *ctx, evWaitList *this) {
224 
225 	INSIST(this != NULL);
226 
227 	if (this->prev != NULL)
228 		this->prev->next = this->next;
229 	else
230 		ctx->waitLists = this->next;
231 	if (this->next != NULL)
232 		this->next->prev = this->prev;
233 	FREE(this);
234 }
235 
236 static evWaitList *
evGetWaitList(evContext_p * ctx,const void * tag,int should_create)237 evGetWaitList(evContext_p *ctx, const void *tag, int should_create) {
238 	evWaitList *this;
239 
240 	for (this = ctx->waitLists; this != NULL; this = this->next) {
241 		if (this->first != NULL && this->first->tag == tag)
242 			break;
243 	}
244 	if (this == NULL && should_create)
245 		this = evNewWaitList(ctx);
246 	return (this);
247 }
248 
249 /*! \file */
250