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