/* * Copyright (c) 2015, EURECOM (www.eurecom.fr) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of the FreeBSD Project. */ /***************************************************************************** Source timer.c Version 0.1 Date 2012/11/27 Product Test Subsystem Timer utility main test Author Frederic Maurel Description Tests the timer utility functions *****************************************************************************/ #include "nas_timer.h" #include "commonDef.h" #include #include // printf #include // exit #include // clock_gettime #include // poll /****************************************************************************/ /**************** E X T E R N A L D E F I N I T I O N S ****************/ /****************************************************************************/ /****************************************************************************/ /******************* L O C A L D E F I N I T I O N S *******************/ /****************************************************************************/ #define TIMER_1S 1 /* 1 second */ #define TIMER_2S 2 /* 2 seconds */ #define TIMER_3S 3 /* 3 seconds */ #define TIMER_4S 4 /* 4 seconds */ typedef struct { unsigned int id; unsigned int sec; struct timespec start; } _timer_t; static void* _timer_callback(void* args); static void* _timer_callback_joinable(void* args); static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER; static unsigned int _nb_timers = 0; static int _start(_timer_t* timer, unsigned int sec); static int _stop(_timer_t* timer); /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ int main (int argc, const char* argv[]) { int rc; _timer_t timer1, timer2, timer3, timer4; #define NB_TIMERS_MAX 10 _timer_t timer[NB_TIMERS_MAX]; /* Initialize timer utility */ rc = timer_init(); if (rc == RETURNerror) { printf("ERROR: timer_init() failed\n"); exit (EXIT_FAILURE); } /* Start NB_TIMERS_MAX timers to expire at time interval of 1s */ for (int i=0; i < NB_TIMERS_MAX; i++) { if (_start(&timer[i], i) != RETURNok) { printf("ERROR: timer_start(i=%u) failed\n", i); } } /* Start timer 1 to expire in 1s */ if (_start(&timer1, TIMER_1S) != RETURNok) { printf("ERROR: timer_start() failed\n"); } /* Start timer 2 to expire in 3s */ if (_start(&timer2, TIMER_3S) != RETURNok) { printf("ERROR: timer_start() failed\n"); } /* Start timer 3 to expire in 2s */ if (_start(&timer3, TIMER_2S) != RETURNok) { printf("ERROR: timer_start() failed\n"); } /* Stop timer 1 */ if (_stop(&timer1) != RETURNok) { printf("ERROR: timer_stop(id=%u) failed\n", timer3.id); } /* Wait for the first timer to expire */ poll(0, 0, -1); /* Start timer 4 to expire in 4s */ if (_start(&timer4, TIMER_4S) != RETURNok) { printf("ERROR: timer_start() failed\n"); } /* Wait for all timers to expire */ while (_nb_timers > 0) { poll(0, 0, 10000); } exit(EXIT_SUCCESS); } /****************************************************************************/ /********************* L O C A L F U N C T I O N S *********************/ /****************************************************************************/ static int _timespec_sub(struct timespec* a, struct timespec* b, struct timespec* result) { if (a->tv_sec < b->tv_sec) return -1; else if (a->tv_nsec < b->tv_nsec) return -1; result->tv_sec = a->tv_sec - b->tv_sec; result->tv_nsec = a->tv_nsec - b->tv_nsec; if (result->tv_nsec < 0) { result->tv_sec--; result->tv_nsec += 1000000000; } return 0; } static void* _timer_callback(void* args) { _timer_t* timer = (_timer_t*) args; struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); if (_timespec_sub(&ts, &timer->start, &ts) < 0) { printf("ERROR:_timespec_sub() failed: %ld.%.9ld > %ld.%.9ld\n", timer->start.tv_sec, timer->start.tv_nsec, ts.tv_sec, ts.tv_nsec); } else { printf("%s\t: Timer %u expired after %ld.%.9ld seconds (%u s)\n", __FUNCTION__, timer->id, ts.tv_sec, ts.tv_nsec, timer->sec); timer->id = timer_stop(timer->id); pthread_mutex_lock(&_mutex); _nb_timers -= 1; pthread_mutex_unlock(&_mutex); } return NULL; } static void* _timer_callback_joinable(void* args) { _timer_t* timer = (_timer_t*) args; struct timespec ts; int* rc = (int*)malloc(sizeof(int)); clock_gettime(CLOCK_MONOTONIC, &ts); if (_timespec_sub(&ts, &timer->start, &ts) < 0) { printf("ERROR:_timespec_sub() failed: %ld.%.9ld > %ld.%.9ld\n", timer->start.tv_sec, timer->start.tv_nsec, ts.tv_sec, ts.tv_nsec); *rc = RETURNerror; } else { printf("%s\t: Timer %u expired after %ld.%.9ld seconds (%u s)\n", __FUNCTION__, timer->id, ts.tv_sec, ts.tv_nsec, timer->sec); timer->id = timer_stop(timer->id); pthread_mutex_lock(&_mutex); _nb_timers -= 1; pthread_mutex_unlock(&_mutex); *rc = timer->id; } return rc; } static int _start(_timer_t* timer, unsigned int sec) { int rc = RETURNerror; timer->sec = sec; clock_gettime(CLOCK_MONOTONIC, &timer->start); timer->id = timer_start(timer->sec, _timer_callback_joinable, (void*) timer); if (timer->id != TIMER_INACTIVE_ID) { printf("Timer id=%u scheduled to expire in %u seconds\n", timer->id, timer->sec); _nb_timers += 1; rc = RETURNok; } return (rc); } static int _stop(_timer_t* timer) { int rc = RETURNerror; printf("Stop timer id=%u\n", timer->id); timer->id = timer_stop(timer->id); if (timer->id == TIMER_INACTIVE_ID) { _nb_timers -= 1; rc = RETURNok; } return (rc); }