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 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 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 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 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 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 * 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 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 * 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