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