1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/other-licenses/android/ev_timers.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,522 @@ 1.4 +/* $NetBSD: ev_timers.c,v 1.2 2004/05/20 19:52:31 christos Exp $ */ 1.5 + 1.6 +/* 1.7 + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 1.8 + * Copyright (c) 1995-1999 by Internet Software Consortium 1.9 + * 1.10 + * Permission to use, copy, modify, and distribute this software for any 1.11 + * purpose with or without fee is hereby granted, provided that the above 1.12 + * copyright notice and this permission notice appear in all copies. 1.13 + * 1.14 + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 1.15 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1.16 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 1.17 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1.18 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1.19 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 1.20 + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1.21 + */ 1.22 + 1.23 +/* ev_timers.c - implement timers for the eventlib 1.24 + * vix 09sep95 [initial] 1.25 + */ 1.26 + 1.27 +/* 1.28 + * This version of this file is derived from Android 2.3 "Gingerbread", 1.29 + * which contains uncredited changes by Android/Google developers. It has 1.30 + * been modified in 2011 for use in the Android build of Mozilla Firefox by 1.31 + * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>, 1.32 + * and Steve Workman <sjhworkman@gmail.com>). 1.33 + * These changes are offered under the same license as the original NetBSD 1.34 + * file, whose copyright and license are unchanged above. 1.35 + */ 1.36 + 1.37 +#define ANDROID_CHANGES 1 1.38 +#define MOZILLA_NECKO_EXCLUDE_CODE 1 1.39 + 1.40 +#include <sys/cdefs.h> 1.41 +#if !defined(LINT) && !defined(CODECENTER) && !defined(lint) 1.42 +#ifdef notdef 1.43 +static const char rcsid[] = "Id: ev_timers.c,v 1.2.2.1.4.5 2004/03/17 02:39:13 marka Exp"; 1.44 +#else 1.45 +__RCSID("$NetBSD: ev_timers.c,v 1.2 2004/05/20 19:52:31 christos Exp $"); 1.46 +#endif 1.47 +#endif 1.48 + 1.49 +/* Import. */ 1.50 + 1.51 +#include <errno.h> 1.52 +#include <time.h> 1.53 + 1.54 +#include "assertions.h" 1.55 +#include "eventlib.h" 1.56 +#include "eventlib_p.h" 1.57 + 1.58 +/* Constants. */ 1.59 + 1.60 +#define MILLION 1000000 1.61 +#define BILLION 1000000000 1.62 + 1.63 +/* Forward. */ 1.64 + 1.65 +#ifndef _LIBC 1.66 +static int due_sooner(void *, void *); 1.67 +static void set_index(void *, int); 1.68 +static void free_timer(void *, void *); 1.69 +static void print_timer(void *, void *); 1.70 +static void idle_timeout(evContext, void *, struct timespec, struct timespec); 1.71 + 1.72 +/* Private type. */ 1.73 + 1.74 +typedef struct { 1.75 + evTimerFunc func; 1.76 + void * uap; 1.77 + struct timespec lastTouched; 1.78 + struct timespec max_idle; 1.79 + evTimer * timer; 1.80 +} idle_timer; 1.81 +#endif 1.82 + 1.83 +/* Public. */ 1.84 + 1.85 +struct timespec 1.86 +evConsTime(time_t sec, long nsec) { 1.87 + struct timespec x; 1.88 + 1.89 + x.tv_sec = sec; 1.90 + x.tv_nsec = nsec; 1.91 + return (x); 1.92 +} 1.93 + 1.94 +struct timespec 1.95 +evAddTime(struct timespec addend1, struct timespec addend2) { 1.96 + struct timespec x; 1.97 + 1.98 + x.tv_sec = addend1.tv_sec + addend2.tv_sec; 1.99 + x.tv_nsec = addend1.tv_nsec + addend2.tv_nsec; 1.100 + if (x.tv_nsec >= BILLION) { 1.101 + x.tv_sec++; 1.102 + x.tv_nsec -= BILLION; 1.103 + } 1.104 + return (x); 1.105 +} 1.106 + 1.107 +struct timespec 1.108 +evSubTime(struct timespec minuend, struct timespec subtrahend) { 1.109 + struct timespec x; 1.110 + 1.111 + x.tv_sec = minuend.tv_sec - subtrahend.tv_sec; 1.112 + if (minuend.tv_nsec >= subtrahend.tv_nsec) 1.113 + x.tv_nsec = minuend.tv_nsec - subtrahend.tv_nsec; 1.114 + else { 1.115 + x.tv_nsec = BILLION - subtrahend.tv_nsec + minuend.tv_nsec; 1.116 + x.tv_sec--; 1.117 + } 1.118 + return (x); 1.119 +} 1.120 + 1.121 +int 1.122 +evCmpTime(struct timespec a, struct timespec b) { 1.123 + long x = a.tv_sec - b.tv_sec; 1.124 + 1.125 + if (x == 0L) 1.126 + x = a.tv_nsec - b.tv_nsec; 1.127 + return (x < 0L ? (-1) : x > 0L ? (1) : (0)); 1.128 +} 1.129 + 1.130 +struct timespec 1.131 +evNowTime() { 1.132 + struct timeval now; 1.133 +#ifdef CLOCK_REALTIME 1.134 + struct timespec tsnow; 1.135 + int m = CLOCK_REALTIME; 1.136 + 1.137 +#ifdef CLOCK_MONOTONIC 1.138 + if (__evOptMonoTime) 1.139 + m = CLOCK_MONOTONIC; 1.140 +#endif 1.141 + if (clock_gettime(m, &tsnow) == 0) 1.142 + return (tsnow); 1.143 +#endif 1.144 + if (gettimeofday(&now, NULL) < 0) 1.145 + return (evConsTime(0L, 0L)); 1.146 + return (evTimeSpec(now)); 1.147 +} 1.148 + 1.149 +#ifndef MOZILLA_NECKO_EXCLUDE_CODE 1.150 +struct timespec 1.151 +evUTCTime(void) { 1.152 + struct timeval now; 1.153 +#ifdef CLOCK_REALTIME 1.154 + struct timespec tsnow; 1.155 + if (clock_gettime(CLOCK_REALTIME, &tsnow) == 0) 1.156 + return (tsnow); 1.157 +#endif 1.158 + if (gettimeofday(&now, NULL) < 0) 1.159 + return (evConsTime(0L, 0L)); 1.160 + return (evTimeSpec(now)); 1.161 +} 1.162 + 1.163 +#ifndef _LIBC 1.164 +struct timespec 1.165 +evLastEventTime(evContext opaqueCtx) { 1.166 + evContext_p *ctx = opaqueCtx.opaque; 1.167 + 1.168 + return (ctx->lastEventTime); 1.169 +} 1.170 +#endif 1.171 +#endif 1.172 + 1.173 +struct timespec 1.174 +evTimeSpec(struct timeval tv) { 1.175 + struct timespec ts; 1.176 + 1.177 + ts.tv_sec = tv.tv_sec; 1.178 + ts.tv_nsec = tv.tv_usec * 1000; 1.179 + return (ts); 1.180 +} 1.181 + 1.182 +#ifndef MOZILLA_NECKO_EXCLUDE_CODE 1.183 +struct timeval 1.184 +evTimeVal(struct timespec ts) { 1.185 + struct timeval tv; 1.186 + 1.187 + tv.tv_sec = ts.tv_sec; 1.188 + tv.tv_usec = ts.tv_nsec / 1000; 1.189 + return (tv); 1.190 +} 1.191 + 1.192 +#ifndef _LIBC 1.193 +int 1.194 +evSetTimer(evContext opaqueCtx, 1.195 + evTimerFunc func, 1.196 + void *uap, 1.197 + struct timespec due, 1.198 + struct timespec inter, 1.199 + evTimerID *opaqueID 1.200 +) { 1.201 + evContext_p *ctx = opaqueCtx.opaque; 1.202 + evTimer *id; 1.203 + 1.204 + printf("evSetTimer(ctx %p, func %p, uap %p, due %ld.%09ld, inter %ld.%09ld)\n", 1.205 + ctx, func, uap, 1.206 + (long)due.tv_sec, due.tv_nsec, 1.207 + (long)inter.tv_sec, inter.tv_nsec); 1.208 + 1.209 +#ifdef __hpux 1.210 + /* 1.211 + * tv_sec and tv_nsec are unsigned. 1.212 + */ 1.213 + if (due.tv_nsec >= BILLION) 1.214 + EV_ERR(EINVAL); 1.215 + 1.216 + if (inter.tv_nsec >= BILLION) 1.217 + EV_ERR(EINVAL); 1.218 +#else 1.219 + if (due.tv_sec < 0 || due.tv_nsec < 0 || due.tv_nsec >= BILLION) 1.220 + EV_ERR(EINVAL); 1.221 + 1.222 + if (inter.tv_sec < 0 || inter.tv_nsec < 0 || inter.tv_nsec >= BILLION) 1.223 + EV_ERR(EINVAL); 1.224 +#endif 1.225 + 1.226 + /* due={0,0} is a magic cookie meaning "now." */ 1.227 + if (due.tv_sec == (time_t)0 && due.tv_nsec == 0L) 1.228 + due = evNowTime(); 1.229 + 1.230 + /* Allocate and fill. */ 1.231 + OKNEW(id); 1.232 + id->func = func; 1.233 + id->uap = uap; 1.234 + id->due = due; 1.235 + id->inter = inter; 1.236 + 1.237 + if (heap_insert(ctx->timers, id) < 0) 1.238 + return (-1); 1.239 + 1.240 + /* Remember the ID if the caller provided us a place for it. */ 1.241 + if (opaqueID) 1.242 + opaqueID->opaque = id; 1.243 + 1.244 + if (ctx->debug > 7) { 1.245 + printf("timers after evSetTimer:\n"); 1.246 + (void) heap_for_each(ctx->timers, print_timer, (void *)ctx); 1.247 + } 1.248 + 1.249 + return (0); 1.250 +} 1.251 + 1.252 +int 1.253 +evClearTimer(evContext opaqueCtx, evTimerID id) { 1.254 + evContext_p *ctx = opaqueCtx.opaque; 1.255 + evTimer *del = id.opaque; 1.256 + 1.257 + if (ctx->cur != NULL && 1.258 + ctx->cur->type == Timer && 1.259 + ctx->cur->u.timer.this == del) { 1.260 + printf("deferring delete of timer (executing)\n"); 1.261 + /* 1.262 + * Setting the interval to zero ensures that evDrop() will 1.263 + * clean up the timer. 1.264 + */ 1.265 + del->inter = evConsTime(0, 0); 1.266 + return (0); 1.267 + } 1.268 + 1.269 + if (heap_element(ctx->timers, del->index) != del) 1.270 + EV_ERR(ENOENT); 1.271 + 1.272 + if (heap_delete(ctx->timers, del->index) < 0) 1.273 + return (-1); 1.274 + FREE(del); 1.275 + 1.276 + if (ctx->debug > 7) { 1.277 + printf("timers after evClearTimer:\n"); 1.278 + (void) heap_for_each(ctx->timers, print_timer, (void *)ctx); 1.279 + } 1.280 + 1.281 + return (0); 1.282 +} 1.283 + 1.284 +int 1.285 +evConfigTimer(evContext opaqueCtx, 1.286 + evTimerID id, 1.287 + const char *param, 1.288 + int value 1.289 +) { 1.290 + evContext_p *ctx = opaqueCtx.opaque; 1.291 + evTimer *timer = id.opaque; 1.292 + int result=0; 1.293 + 1.294 + UNUSED(value); 1.295 + 1.296 + if (heap_element(ctx->timers, timer->index) != timer) 1.297 + EV_ERR(ENOENT); 1.298 + 1.299 + if (strcmp(param, "rate") == 0) 1.300 + timer->mode |= EV_TMR_RATE; 1.301 + else if (strcmp(param, "interval") == 0) 1.302 + timer->mode &= ~EV_TMR_RATE; 1.303 + else 1.304 + EV_ERR(EINVAL); 1.305 + 1.306 + return (result); 1.307 +} 1.308 + 1.309 +int 1.310 +evResetTimer(evContext opaqueCtx, 1.311 + evTimerID id, 1.312 + evTimerFunc func, 1.313 + void *uap, 1.314 + struct timespec due, 1.315 + struct timespec inter 1.316 +) { 1.317 + evContext_p *ctx = opaqueCtx.opaque; 1.318 + evTimer *timer = id.opaque; 1.319 + struct timespec old_due; 1.320 + int result=0; 1.321 + 1.322 + if (heap_element(ctx->timers, timer->index) != timer) 1.323 + EV_ERR(ENOENT); 1.324 + 1.325 +#ifdef __hpux 1.326 + /* 1.327 + * tv_sec and tv_nsec are unsigned. 1.328 + */ 1.329 + if (due.tv_nsec >= BILLION) 1.330 + EV_ERR(EINVAL); 1.331 + 1.332 + if (inter.tv_nsec >= BILLION) 1.333 + EV_ERR(EINVAL); 1.334 +#else 1.335 + if (due.tv_sec < 0 || due.tv_nsec < 0 || due.tv_nsec >= BILLION) 1.336 + EV_ERR(EINVAL); 1.337 + 1.338 + if (inter.tv_sec < 0 || inter.tv_nsec < 0 || inter.tv_nsec >= BILLION) 1.339 + EV_ERR(EINVAL); 1.340 +#endif 1.341 + 1.342 + old_due = timer->due; 1.343 + 1.344 + timer->func = func; 1.345 + timer->uap = uap; 1.346 + timer->due = due; 1.347 + timer->inter = inter; 1.348 + 1.349 + switch (evCmpTime(due, old_due)) { 1.350 + case -1: 1.351 + result = heap_increased(ctx->timers, timer->index); 1.352 + break; 1.353 + case 0: 1.354 + result = 0; 1.355 + break; 1.356 + case 1: 1.357 + result = heap_decreased(ctx->timers, timer->index); 1.358 + break; 1.359 + } 1.360 + 1.361 + if (ctx->debug > 7) { 1.362 + printf("timers after evResetTimer:\n"); 1.363 + (void) heap_for_each(ctx->timers, print_timer, (void *)ctx); 1.364 + } 1.365 + 1.366 + return (result); 1.367 +} 1.368 + 1.369 +int 1.370 +evSetIdleTimer(evContext opaqueCtx, 1.371 + evTimerFunc func, 1.372 + void *uap, 1.373 + struct timespec max_idle, 1.374 + evTimerID *opaqueID 1.375 +) { 1.376 + evContext_p *ctx = opaqueCtx.opaque; 1.377 + idle_timer *tt; 1.378 + 1.379 + /* Allocate and fill. */ 1.380 + OKNEW(tt); 1.381 + tt->func = func; 1.382 + tt->uap = uap; 1.383 + tt->lastTouched = ctx->lastEventTime; 1.384 + tt->max_idle = max_idle; 1.385 + 1.386 + if (evSetTimer(opaqueCtx, idle_timeout, tt, 1.387 + evAddTime(ctx->lastEventTime, max_idle), 1.388 + max_idle, opaqueID) < 0) { 1.389 + FREE(tt); 1.390 + return (-1); 1.391 + } 1.392 + 1.393 + tt->timer = opaqueID->opaque; 1.394 + 1.395 + return (0); 1.396 +} 1.397 + 1.398 +int 1.399 +evClearIdleTimer(evContext opaqueCtx, evTimerID id) { 1.400 + evTimer *del = id.opaque; 1.401 + idle_timer *tt = del->uap; 1.402 + 1.403 + FREE(tt); 1.404 + return (evClearTimer(opaqueCtx, id)); 1.405 +} 1.406 + 1.407 +int 1.408 +evResetIdleTimer(evContext opaqueCtx, 1.409 + evTimerID opaqueID, 1.410 + evTimerFunc func, 1.411 + void *uap, 1.412 + struct timespec max_idle 1.413 +) { 1.414 + evContext_p *ctx = opaqueCtx.opaque; 1.415 + evTimer *timer = opaqueID.opaque; 1.416 + idle_timer *tt = timer->uap; 1.417 + 1.418 + tt->func = func; 1.419 + tt->uap = uap; 1.420 + tt->lastTouched = ctx->lastEventTime; 1.421 + tt->max_idle = max_idle; 1.422 + 1.423 + return (evResetTimer(opaqueCtx, opaqueID, idle_timeout, tt, 1.424 + evAddTime(ctx->lastEventTime, max_idle), 1.425 + max_idle)); 1.426 +} 1.427 + 1.428 +int 1.429 +evTouchIdleTimer(evContext opaqueCtx, evTimerID id) { 1.430 + evContext_p *ctx = opaqueCtx.opaque; 1.431 + evTimer *t = id.opaque; 1.432 + idle_timer *tt = t->uap; 1.433 + 1.434 + tt->lastTouched = ctx->lastEventTime; 1.435 + 1.436 + return (0); 1.437 +} 1.438 + 1.439 +/* Public to the rest of eventlib. */ 1.440 + 1.441 +heap_context 1.442 +evCreateTimers(const evContext_p *ctx) { 1.443 + 1.444 + UNUSED(ctx); 1.445 + 1.446 + return (heap_new(due_sooner, set_index, 2048)); 1.447 +} 1.448 + 1.449 +void 1.450 +evDestroyTimers(const evContext_p *ctx) { 1.451 + (void) heap_for_each(ctx->timers, free_timer, NULL); 1.452 + (void) heap_free(ctx->timers); 1.453 +} 1.454 + 1.455 +/* Private. */ 1.456 + 1.457 +static int 1.458 +due_sooner(void *a, void *b) { 1.459 + evTimer *a_timer, *b_timer; 1.460 + 1.461 + a_timer = a; 1.462 + b_timer = b; 1.463 + return (evCmpTime(a_timer->due, b_timer->due) < 0); 1.464 +} 1.465 + 1.466 +static void 1.467 +set_index(void *what, int idx) { 1.468 + evTimer *timer; 1.469 + 1.470 + timer = what; 1.471 + timer->index = idx; 1.472 +} 1.473 + 1.474 +static void 1.475 +free_timer(void *what, void *uap) { 1.476 + evTimer *t = what; 1.477 + 1.478 + UNUSED(uap); 1.479 + 1.480 + FREE(t); 1.481 +} 1.482 + 1.483 +static void 1.484 +print_timer(void *what, void *uap) { 1.485 + evTimer *cur = what; 1.486 + evContext_p *ctx = uap; 1.487 + 1.488 + cur = what; 1.489 + evPrintf(ctx, 7, 1.490 + " func %p, uap %p, due %ld.%09ld, inter %ld.%09ld\n", 1.491 + cur->func, cur->uap, 1.492 + (long)cur->due.tv_sec, cur->due.tv_nsec, 1.493 + (long)cur->inter.tv_sec, cur->inter.tv_nsec); 1.494 +} 1.495 + 1.496 +static void 1.497 +idle_timeout(evContext opaqueCtx, 1.498 + void *uap, 1.499 + struct timespec due, 1.500 + struct timespec inter 1.501 +) { 1.502 + evContext_p *ctx = opaqueCtx.opaque; 1.503 + idle_timer *this = uap; 1.504 + struct timespec idle; 1.505 + 1.506 + UNUSED(due); 1.507 + UNUSED(inter); 1.508 + 1.509 + idle = evSubTime(ctx->lastEventTime, this->lastTouched); 1.510 + if (evCmpTime(idle, this->max_idle) >= 0) { 1.511 + (this->func)(opaqueCtx, this->uap, this->timer->due, 1.512 + this->max_idle); 1.513 + /* 1.514 + * Setting the interval to zero will cause the timer to 1.515 + * be cleaned up in evDrop(). 1.516 + */ 1.517 + this->timer->inter = evConsTime(0L, 0L); 1.518 + FREE(this); 1.519 + } else { 1.520 + /* evDrop() will reschedule the timer. */ 1.521 + this->timer->inter = evSubTime(this->max_idle, idle); 1.522 + } 1.523 +} 1.524 +#endif 1.525 +#endif