1bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo/* Copyright (c) 2013, The Linux Foundation. All rights reserved. 2bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * 3bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * Redistribution and use in source and binary forms, with or without 4bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * modification, are permitted provided that the following conditions are 5bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * met: 6bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * * Redistributions of source code must retain the above copyright 7bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * notice, this list of conditions and the following disclaimer. 8bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * * Redistributions in binary form must reproduce the above 9bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * copyright notice, this list of conditions and the following 10bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * disclaimer in the documentation and/or other materials provided 11bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * with the distribution. 12bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * * Neither the name of The Linux Foundation, nor the names of its 13bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * contributors may be used to endorse or promote products derived 14bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * from this software without specific prior written permission. 15bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * 16bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo * 28bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo */ 29bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo 30bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo#include<stdio.h> 31bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo#include<stdlib.h> 32bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo#include<sys/time.h> 33bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo#include "loc_timer.h" 34bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo#include<time.h> 35bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo#include<errno.h> 36bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo 37bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russoenum timer_state { 38bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo READY = 100, 39bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo WAITING, 40bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo DONE, 41bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo ABORT 42bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo}; 43bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo 44bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russotypedef struct { 45bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo loc_timer_callback callback_func; 46bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo void *user_data; 47bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo unsigned int time_msec; 48bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo pthread_cond_t timer_cond; 49bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo pthread_mutex_t timer_mutex; 50bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo enum timer_state state; 51bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo}timer_data; 52bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo 53bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russostatic void *timer_thread(void *thread_data) 54bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo{ 55bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo int ret = -ETIMEDOUT; 56bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo struct timespec ts; 57bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo struct timeval tv; 58bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo timer_data* t = (timer_data*)thread_data; 59bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo 60bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo LOC_LOGD("%s:%d]: Enter. Delay = %d\n", __func__, __LINE__, t->time_msec); 61bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo 62bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo gettimeofday(&tv, NULL); 63bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo clock_gettime(CLOCK_REALTIME, &ts); 64bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo if(t->time_msec >= 1000) { 65bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo ts.tv_sec += t->time_msec/1000; 66bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo t->time_msec = t->time_msec % 1000; 67bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo } 68bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo if(t->time_msec) 69bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo ts.tv_nsec += t->time_msec * 1000000; 70bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo if(ts.tv_nsec > 999999999) { 71bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo LOC_LOGD("%s:%d]: Large nanosecs\n", __func__, __LINE__); 72bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo ts.tv_sec += 1; 73bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo ts.tv_nsec -= 1000000000; 74bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo } 75bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo LOC_LOGD("%s:%d]: ts.tv_sec:%d; ts.tv_nsec:%d\n" 76bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo "\t Current time: %d sec; %d nsec", 77bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo __func__, __LINE__, (int)ts.tv_sec, (int)ts.tv_nsec, 78bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo (int)tv.tv_sec, (int)tv.tv_usec*1000); 79bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo 80bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo pthread_mutex_lock(&(t->timer_mutex)); 81bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo if (READY == t->state) { 82bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo t->state = WAITING; 83bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo ret = pthread_cond_timedwait(&t->timer_cond, &t->timer_mutex, &ts); 84bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo t->state = DONE; 85bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo } 86bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo pthread_mutex_unlock(&(t->timer_mutex)); 87bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo 88bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo switch (ret) { 89bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo case ETIMEDOUT: 90bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo LOC_LOGV("%s:%d]: loc_timer timed out", __func__, __LINE__); 91bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo break; 92bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo case 0: 93bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo LOC_LOGV("%s:%d]: loc_timer stopped", __func__, __LINE__); 94bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo break; 95bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo case -ETIMEDOUT: 96bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo LOC_LOGV("%s:%d]: loc_timer cancelled", __func__, __LINE__); 97bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo break; 98bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo default: 99bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo LOC_LOGE("%s:%d]: Call to pthread timedwait failed; ret=%d\n", 100bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo __func__, __LINE__, ret); 101bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo break; 102bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo } 103bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo 104bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo pthread_mutex_destroy(&t->timer_mutex); 105bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo pthread_cond_destroy(&t->timer_cond); 106bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo 107bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo if(ETIMEDOUT == ret) 108bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo t->callback_func(t->user_data, ret); 109bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo 110bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo free(t); 111bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo LOC_LOGD("%s:%d]: Exit\n", __func__, __LINE__); 112bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo return NULL; 113bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo} 114bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo 115bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russovoid* loc_timer_start(unsigned int msec, loc_timer_callback cb_func, 116bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo void* caller_data) 117bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo{ 118bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo timer_data *t=NULL; 119bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo pthread_attr_t tattr; 120bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo pthread_t id; 121bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo LOC_LOGD("%s:%d]: Enter\n", __func__, __LINE__); 122bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo if(cb_func == NULL || msec == 0) { 123bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo LOC_LOGE("%s:%d]: Error: Wrong parameters\n", __func__, __LINE__); 124bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo goto _err; 125bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo } 126bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo t = (timer_data *)calloc(1, sizeof(timer_data)); 127bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo if(t == NULL) { 128bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo LOC_LOGE("%s:%d]: Could not allocate memory. Failing.\n", 129bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo __func__, __LINE__); 130bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo goto _err; 131bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo } 132bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo 133bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo if(pthread_cond_init(&(t->timer_cond), NULL)) { 134bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo LOC_LOGE("%s:%d]: Pthread cond init failed\n", __func__, __LINE__); 135bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo goto t_err; 136bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo } 137bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo if(pthread_mutex_init(&(t->timer_mutex), NULL)) { 138bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo LOC_LOGE("%s:%d]: Pthread mutex init failed\n", __func__, __LINE__); 139bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo goto cond_err; 140bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo } 141bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo 142bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo t->callback_func = cb_func; 143bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo t->user_data = caller_data; 144bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo t->time_msec = msec; 145bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo t->state = READY; 146bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo 147bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo if (pthread_attr_init(&tattr)) { 148bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo LOC_LOGE("%s:%d]: Pthread mutex init failed\n", __func__, __LINE__); 149bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo goto mutex_err; 150bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo } 151bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 152bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo 153bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo if(pthread_create(&(id), &tattr, timer_thread, (void *)t)) { 154bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo LOC_LOGE("%s:%d]: Could not create thread\n", __func__, __LINE__); 155bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo goto attr_err; 156bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo } 157bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo 158bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo LOC_LOGD("%s:%d]: Created thread with id: %d\n", 159bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo __func__, __LINE__, (int)id); 160bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo goto _err; 161bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo 162bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russoattr_err: 163bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo pthread_attr_destroy(&tattr); 164bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russomutex_err: 165bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo pthread_mutex_destroy(&t->timer_mutex); 166bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russocond_err: 167bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo pthread_cond_destroy(&t->timer_cond); 168bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russot_err: 169bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo free(t); 170bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo_err: 171bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo LOC_LOGD("%s:%d]: Exit\n", __func__, __LINE__); 172bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo return t; 173bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo} 174bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo 175bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russovoid loc_timer_stop(void* handle) { 176bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo timer_data* t = (timer_data*)handle; 177bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo 178bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo if (NULL != t && (READY == t->state || WAITING == t->state)) { 179bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo pthread_mutex_lock(&(t->timer_mutex)); 180bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo if (READY == t->state || WAITING == t->state) { 181bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo pthread_cond_signal(&t->timer_cond); 182bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo t->state = ABORT; 183bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo } 184bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo pthread_mutex_unlock(&(t->timer_mutex)); 185bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo } 186bfff6343845ad9ff062c5fd97bb3b9be1053340eDante Russo} 187