#include <signal.h>#include "gwlib/gwlib.h"#include "wap_events.h"#include "timers.h"Include dependency graph for timers.c:

Go to the source code of this file.
Data Structures | |
| struct | TimerHeap |
| struct | Timerset |
| struct | Timer |
Typedefs | |
| typedef TimerHeap | TimerHeap |
| typedef Timerset | Timerset |
Functions | |
| void | abort_elapsed (Timer *timer) |
| TimerHeap * | heap_create (void) |
| void | heap_destroy (TimerHeap *heap) |
| void | heap_delete (TimerHeap *heap, long index) |
| int | heap_adjust (TimerHeap *heap, long index) |
| void | heap_insert (TimerHeap *heap, Timer *timer) |
| void | heap_swap (TimerHeap *heap, long index1, long index2) |
| void | lock (Timerset *set) |
| void | unlock (Timerset *set) |
| void | watch_timers (void *arg) |
| void | elapse_timer (Timer *timer) |
| void | timers_init (void) |
| void | timers_shutdown (void) |
| Timer * | gwtimer_create (List *outputlist) |
| void | gwtimer_destroy (Timer *timer) |
| void | gwtimer_start (Timer *timer, int interval, WAPEvent *event) |
| void | gwtimer_stop (Timer *timer) |
Variables | |
| Timerset * | timers |
| int | initialized = 0 |
|
|
Definition at line 88 of file timers.c. Referenced by heap_create(). |
|
|
Definition at line 114 of file timers.c. Referenced by watch_timers(). |
|
|
Definition at line 338 of file timers.c. References debug(), Timer::elapsed_event, gwlist_delete_equal(), Timer::output, WAPEvent::type, wap_event_destroy(), and wap_event_name(). Referenced by gwtimer_start(), and gwtimer_stop(). 00339 {
00340 long count;
00341
00342 if (timer->elapsed_event == NULL)
00343 return;
00344
00345 count = gwlist_delete_equal(timer->output, timer->elapsed_event);
00346 if (count > 0) {
00347 debug("timers", 0, "Aborting %s timer.",
00348 wap_event_name(timer->elapsed_event->type));
00349 wap_event_destroy(timer->elapsed_event);
00350 }
00351 timer->elapsed_event = NULL;
00352 }
|
Here is the call graph for this function:

|
|
Definition at line 514 of file timers.c. References debug(), Timer::elapsed_event, Timer::elapses, Timer::event, gw_assert, gwlist_produce(), Timer::output, timers, WAPEvent::type, wap_event_duplicate(), and wap_event_name(). Referenced by watch_timers(). 00515 {
00516 gw_assert(timer != NULL);
00517 gw_assert(timers != NULL);
00518 /* This must be true because abort_elapsed is always called
00519 * before a timer is activated. */
00520 gw_assert(timer->elapsed_event == NULL);
00521
00522 debug("timers", 0, "%s elapsed.", wap_event_name(timer->event->type));
00523
00524 timer->elapsed_event = wap_event_duplicate(timer->event);
00525 gwlist_produce(timer->output, timer->elapsed_event);
00526 timer->elapses = -1;
00527 }
|
Here is the call graph for this function:

|
|
Definition at line 224 of file timers.c. References Timer::elapses, Timer::event, gw_assert, gwlist_add_producer(), and initialized. 00225 {
00226 Timer *t;
00227
00228 gw_assert(initialized);
00229
00230 t = gw_malloc(sizeof(*t));
00231 t->elapses = -1;
00232 t->event = NULL;
00233 t->elapsed_event = NULL;
00234 t->index = -1;
00235 t->output = outputlist;
00236 gwlist_add_producer(outputlist);
00237
00238 return t;
00239 }
|
Here is the call graph for this function:

|
|
Definition at line 241 of file timers.c. References Timer::event, gw_assert, gwlist_remove_producer(), gwtimer_stop(), initialized, Timer::output, and wap_event_destroy(). 00242 {
00243 gw_assert(initialized);
00244
00245 if (timer == NULL)
00246 return;
00247
00248 gwtimer_stop(timer);
00249 gwlist_remove_producer(timer->output);
00250 wap_event_destroy(timer->event);
00251 gw_free(timer);
00252 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 254 of file timers.c. References abort_elapsed(), Timer::elapses, event, Timer::event, gw_assert, gwthread_wakeup(), Timerset::heap, heap_adjust(), heap_insert(), Timer::index, initialized, interval, lock, TimerHeap::tab, Timerset::thread, timers, unlock, and wap_event_destroy(). Referenced by start_initiator_timer_R(), start_timer_A(), start_timer_R(), and start_timer_W(). 00255 {
00256 int wakeup = 0;
00257
00258 gw_assert(initialized);
00259 gw_assert(timer != NULL);
00260 gw_assert(event != NULL || timer->event != NULL);
00261
00262 lock(timers);
00263
00264 /* Convert to absolute time */
00265 interval += time(NULL);
00266
00267 if (timer->elapses > 0) {
00268 /* Resetting an existing timer. Move it to its new
00269 * position in the heap. */
00270 if (interval < timer->elapses && timer->index == 0)
00271 wakeup = 1;
00272 timer->elapses = interval;
00273 gw_assert(timers->heap->tab[timer->index] == timer);
00274 wakeup |= heap_adjust(timers->heap, timer->index);
00275 } else {
00276 /* Setting a new timer, or resetting an elapsed one.
00277 * First deal with a possible elapse event that may
00278 * still be on the output list. */
00279 abort_elapsed(timer);
00280
00281 /* Then activate the timer. */
00282 timer->elapses = interval;
00283 gw_assert(timer->index < 0);
00284 heap_insert(timers->heap, timer);
00285 wakeup = timer->index == 0; /* Do we have a new top? */
00286 }
00287
00288 if (event != NULL) {
00289 wap_event_destroy(timer->event);
00290 timer->event = event;
00291 }
00292
00293 unlock(timers);
00294
00295 if (wakeup)
00296 gwthread_wakeup(timers->thread);
00297 }
|
Here is the call graph for this function:

|
|
Definition at line 299 of file timers.c. References abort_elapsed(), Timer::elapses, gw_assert, Timerset::heap, heap_delete(), Timer::index, initialized, lock, TimerHeap::tab, timers, and unlock. Referenced by gwtimer_destroy(), stop_initiator_timer(), and timers_shutdown(). 00300 {
00301 gw_assert(initialized);
00302 gw_assert(timer != NULL);
00303 lock(timers);
00304
00305 /*
00306 * If the timer is active, make it inactive and remove it from
00307 * the heap.
00308 */
00309 if (timer->elapses > 0) {
00310 timer->elapses = -1;
00311 gw_assert(timers->heap->tab[timer->index] == timer);
00312 heap_delete(timers->heap, timer->index);
00313 }
00314
00315 abort_elapsed(timer);
00316
00317 unlock(timers);
00318 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 446 of file timers.c. References Timer::elapses, gw_assert, heap_swap(), TimerHeap::len, and TimerHeap::tab. Referenced by gwtimer_start(), heap_delete(), and heap_insert(). 00447 {
00448 Timer *t;
00449 Timer *parent;
00450 long child_index;
00451
00452 /*
00453 * We can assume that the heap was fine before this element's
00454 * elapse time was changed. There are three cases to deal
00455 * with:
00456 * - Element's new elapse time is too small; it should be
00457 * moved toward the top.
00458 * - Element's new elapse time is too large; it should be
00459 * moved toward the bottom.
00460 * - Element's new elapse time still fits here, we don't
00461 * have to do anything.
00462 */
00463
00464 gw_assert(index >= 0);
00465 gw_assert(index < heap->len);
00466
00467 /* Move to top? */
00468 t = heap->tab[index];
00469 parent = heap->tab[index / 2];
00470 if (t->elapses < parent->elapses) {
00471 /* This will automatically terminate when it reaches
00472 * the top, because in that t == parent. */
00473 do {
00474 heap_swap(heap, index, index / 2);
00475 index = index / 2;
00476 parent = heap->tab[index / 2];
00477 } while (t->elapses < parent->elapses);
00478 /* We're done. Return 1 if we changed the top. */
00479 return index == 0;
00480 }
00481
00482 /* Move to bottom? */
00483 for (; ; ) {
00484 child_index = index * 2;
00485 if (child_index >= heap->len)
00486 return 0; /* Already at bottom */
00487 if (child_index == heap->len - 1) {
00488 /* Only one child */
00489 if (heap->tab[child_index]->elapses < t->elapses)
00490 heap_swap(heap, index, child_index);
00491 break;
00492 }
00493
00494 /* Find out which child elapses first */
00495 if (heap->tab[child_index + 1]->elapses <
00496 heap->tab[child_index]->elapses) {
00497 child_index++;
00498 }
00499
00500 if (heap->tab[child_index]->elapses < t->elapses) {
00501 heap_swap(heap, index, child_index);
00502 index = child_index;
00503 } else {
00504 break;
00505 }
00506 }
00507
00508 return 0;
00509 }
|
Here is the call graph for this function:

|
|
Definition at line 357 of file timers.c. References TimerHeap::tab, and TimerHeap. Referenced by timers_init(). 00358 {
00359 TimerHeap *heap;
00360
00361 heap = gw_malloc(sizeof(*heap));
00362 heap->tab = gw_malloc(sizeof(heap->tab[0]));
00363 heap->size = 1;
00364 heap->len = 0;
00365
00366 return heap;
00367 }
|
|
||||||||||||
|
Definition at line 383 of file timers.c. References gw_assert, heap_adjust(), heap_swap(), Timer::index, TimerHeap::len, and TimerHeap::tab. Referenced by gwtimer_stop(), and watch_timers(). 00384 {
00385 long last;
00386
00387 gw_assert(index >= 0);
00388 gw_assert(index < heap->len);
00389 gw_assert(heap->tab[index]->index == index);
00390
00391 last = heap->len - 1;
00392 heap_swap(heap, index, last);
00393 heap->tab[last]->index = -1;
00394 heap->len--;
00395 if (index != last)
00396 heap_adjust(heap, index);
00397 }
|
Here is the call graph for this function:

|
|
Definition at line 369 of file timers.c. References TimerHeap::tab. Referenced by timers_shutdown(). 00370 {
00371 if (heap == NULL)
00372 return;
00373
00374 gw_free(heap->tab);
00375 gw_free(heap);
00376 }
|
|
||||||||||||
|
Definition at line 403 of file timers.c. References heap_adjust(), Timer::index, TimerHeap::len, TimerHeap::size, and TimerHeap::tab. Referenced by gwtimer_start(). 00404 {
00405 heap->len++;
00406 if (heap->len > heap->size) {
00407 heap->tab = gw_realloc(heap->tab,
00408 heap->len * sizeof(heap->tab[0]));
00409 heap->size = heap->len;
00410 }
00411 heap->tab[heap->len - 1] = timer;
00412 timer->index = heap->len - 1;
00413 heap_adjust(heap, timer->index);
00414 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 420 of file timers.c. References gw_assert, Timer::index, and TimerHeap::tab. Referenced by heap_adjust(), and heap_delete(). 00421 {
00422 Timer *t;
00423
00424 gw_assert(index1 >= 0);
00425 gw_assert(index1 < heap->len);
00426 gw_assert(index2 >= 0);
00427 gw_assert(index2 < heap->len);
00428
00429 if (index1 == index2)
00430 return;
00431
00432 t = heap->tab[index1];
00433 heap->tab[index1] = heap->tab[index2];
00434 heap->tab[index2] = t;
00435 heap->tab[index1]->index = index1;
00436 heap->tab[index2]->index = index2;
00437 }
|
|
|
Definition at line 320 of file timers.c. References gw_assert, Timerset::mutex, and mutex_lock. 00321 {
00322 gw_assert(set != NULL);
00323 mutex_lock(set->mutex);
00324 }
|
|
|
Definition at line 184 of file timers.c. References gwthread_create, Timerset::heap, heap_create(), initialized, Timerset::mutex, mutex_create, Timerset::stopping, Timerset::thread, timers, and watch_timers(). Referenced by wtp_initiator_init(), and wtp_resp_init(). 00185 {
00186 if (initialized == 0) {
00187 timers = gw_malloc(sizeof(*timers));
00188 timers->mutex = mutex_create();
00189 timers->heap = heap_create();
00190 timers->stopping = 0;
00191 timers->thread = gwthread_create(watch_timers, timers);
00192 }
00193 initialized++;
00194 }
|
Here is the call graph for this function:

|
|
Definition at line 196 of file timers.c. References gwthread_join(), gwthread_wakeup(), gwtimer_stop(), Timerset::heap, heap_destroy(), initialized, TimerHeap::len, Timerset::mutex, mutex_destroy(), Timerset::stopping, TimerHeap::tab, Timerset::thread, timers, and warning(). Referenced by wtp_initiator_shutdown(), and wtp_resp_shutdown(). 00197 {
00198 if (initialized > 1) {
00199 initialized--;
00200 return;
00201 }
00202
00203 /* Stop all timers. */
00204 if (timers->heap->len > 0)
00205 warning(0, "Timers shutting down with %ld active timers.",
00206 timers->heap->len);
00207 while (timers->heap->len > 0)
00208 gwtimer_stop(timers->heap->tab[0]);
00209
00210 /* Kill timer thread */
00211 timers->stopping = 1;
00212 gwthread_wakeup(timers->thread);
00213 gwthread_join(timers->thread);
00214
00215 initialized = 0;
00216
00217 /* Free resources */
00218 heap_destroy(timers->heap);
00219 mutex_destroy(timers->mutex);
00220 gw_free(timers);
00221 }
|
Here is the call graph for this function:

|
|
Definition at line 326 of file timers.c. References gw_assert, Timerset::mutex, and mutex_unlock. 00327 {
00328 gw_assert(set != NULL);
00329 mutex_unlock(set->mutex);
00330 }
|
|
|
Definition at line 532 of file timers.c. References elapse_timer(), Timer::elapses, gwthread_sleep(), Timerset::heap, heap_delete(), TimerHeap::len, lock, Timerset::stopping, TimerHeap::tab, Timerset, and unlock. Referenced by timers_init(). 00533 {
00534 Timerset *set;
00535 long top_time;
00536 long now;
00537
00538 set = arg;
00539
00540 while (!set->stopping) {
00541 lock(set);
00542
00543 now = time(NULL);
00544
00545 while (set->heap->len > 0 && set->heap->tab[0]->elapses <= now) {
00546 elapse_timer(set->heap->tab[0]);
00547 heap_delete(set->heap, 0);
00548 }
00549
00550 /*
00551 * Now sleep until the next timer elapses. If there isn't one,
00552 * then just sleep very long. We will get woken up if the
00553 * top of the heap changes before we wake.
00554 */
00555
00556 if (set->heap->len == 0) {
00557 unlock(set);
00558 gwthread_sleep(1000000.0);
00559 } else {
00560 top_time = set->heap->tab[0]->elapses;
00561 unlock(set);
00562 gwthread_sleep(top_time - now);
00563 }
00564 }
00565 }
|
Here is the call graph for this function:

|
|
Definition at line 166 of file timers.c. Referenced by gwtimer_create(), gwtimer_destroy(), gwtimer_start(), gwtimer_stop(), timers_init(), and timers_shutdown(). |
|
|
Definition at line 160 of file timers.c. Referenced by elapse_timer(), gwtimer_start(), gwtimer_stop(), timers_init(), and timers_shutdown(). |