/* ** Copyright (C) 2004-2007 by Carnegie Mellon University. ** ** @OPENSOURCE_HEADER_START@ ** ** Use of the SILK system and related source code is subject to the terms ** of the following licenses: ** ** GNU Public License (GPL) Rights pursuant to Version 2, June 1991 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.225-7013 ** ** NO WARRANTY ** ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE ** DELIVERABLES UNDER THIS LICENSE. ** ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie ** Mellon University, its trustees, officers, employees, and agents from ** all claims or demands made against them (and any related losses, ** expenses, or attorney's fees) arising out of, or relating to Licensee's ** and/or its sub licensees' negligent use or willful misuse of or ** negligent conduct or willful misconduct regarding the Software, ** facilities, or other rights or assistance granted by Carnegie Mellon ** University under this License, including, but not limited to, any ** claims of product liability, personal injury, death, damage to ** property, or violation of any laws or regulations. ** ** Carnegie Mellon University Software Engineering Institute authored ** documents are sponsored by the U.S. Department of Defense under ** Contract F19628-00-C-0003. Carnegie Mellon University retains ** copyrights in all material produced under this contract. The U.S. ** Government retains a non-exclusive, royalty-free license to publish or ** reproduce these documents, or allow others to do so, for U.S. ** Government purposes only pursuant to the copyright license under the ** contract clause at 252.227.7013. ** ** @OPENSOURCE_HEADER_END@ */ /* ** Generic timers which will run callback functions in a seperate ** thread context after a given amount of time. */ #include "silk.h" RCSIDENT("$SiLK: sktimer.c 6543 2007-03-05 00:52:42Z mwd $"); #include "sktimer.h" #include "skthread.h" typedef struct sk_timer_t { uint32_t secs; skTimerFn_t callBack; void *clientData; pthread_mutex_t mutex; pthread_cond_t cond; pthread_cond_t end; unsigned running : 1; } sk_timer_t; static void *sk_timer_thread(void *data) { sk_timer_t *ttd = (sk_timer_t *)data; struct timespec wait_time; struct timeval current_time; sigset_t sigs; int rv; skTimerRepeat_t repeat; /* Lock the mutex */ pthread_mutex_lock(&ttd->mutex); /* Have we been asked to be destroyed before we've even started? */ if (!ttd->running) { goto end; } gettimeofday(¤t_time, NULL); sigfillset(&sigs); pthread_sigmask(SIG_SETMASK, &sigs, NULL); /* No signals */ pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); wait_time.tv_nsec = current_time.tv_usec * 1000; wait_time.tv_sec = current_time.tv_sec; do { wait_time.tv_sec += ttd->secs; /* Mutex should be released while within pthread_cond_timedwait */ /* For some reason, this is getting interrupted by a signal, even though we know it shouldn't be. So handle the case. */ do { rv = pthread_cond_timedwait(&ttd->cond, &ttd->mutex, &wait_time); } while (rv == EINTR); if (rv == ETIMEDOUT) { repeat = ttd->callBack(ttd->clientData); } else { repeat = SK_TIMER_END; } } while (repeat == SK_TIMER_REPEAT); ttd->running = 0; end: /* Notify destroy function that we have ended properly. */ pthread_cond_broadcast(&ttd->end); pthread_mutex_unlock(&ttd->mutex); return NULL; } int skTimerCreate( sk_timer_t **timer, uint32_t secs, skTimerFn_t callBack, void *clientData) { sk_timer_t *data; pthread_t thread; int err; data = (sk_timer_t *)malloc(sizeof(sk_timer_t)); data->secs = secs; data->callBack = callBack; data->clientData = clientData; data->running = 1; pthread_mutex_init(&data->mutex, NULL); pthread_cond_init(&data->cond, NULL); pthread_cond_init(&data->end, NULL); /* Mutex starts locked */ pthread_mutex_lock(&data->mutex); err = skthread_create_detatched("sktimer", &thread, sk_timer_thread, (void *)data); if (err) { pthread_mutex_unlock(&data->mutex); pthread_mutex_destroy(&data->mutex); pthread_cond_destroy(&data->cond); pthread_cond_destroy(&data->end); free(data); return err; } pthread_mutex_unlock(&data->mutex); *timer = data; return 0; } int skTimerDestroy(sk_timer_t *timer) { /* Grab the mutex */ pthread_mutex_lock(&timer->mutex); if (timer->running) { timer->running = 0; /* Broadcast a stop to the timer */ pthread_cond_broadcast(&timer->cond); /* Wait for timer process to end */ pthread_cond_wait(&timer->end, &timer->mutex); } /* Unlock and destroy mutexes */ pthread_mutex_unlock(&timer->mutex); pthread_mutex_destroy(&timer->mutex); pthread_cond_destroy(&timer->cond); pthread_cond_destroy(&timer->end); free(timer); return 0; }