diff options
Diffstat (limited to 'halimpl/osi/osi_timer.cc')
-rw-r--r-- | halimpl/osi/osi_timer.cc | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/halimpl/osi/osi_timer.cc b/halimpl/osi/osi_timer.cc new file mode 100644 index 0000000..6d65cab --- /dev/null +++ b/halimpl/osi/osi_timer.cc @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2013 SAMSUNG S.LSI + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * + */ + +/************************************************************************ +** OS interface for task handling +*************************************************************************/ +#include <errno.h> +#include <pthread.h> +#include <string.h> +#include <sys/time.h> +#include "osi.h" + +/************************************************************************ +** Internal function prototype +*************************************************************************/ +void timer_thread(void); + +/************************************************************************ +** Public functions +*************************************************************************/ +tOSI_TIMER_HANDLER OSI_timer_allocate(const char* timer_name) { + tOSI_TIMER_HANDLER free_timer = NULL; + int index; + + osi_lock(); + for (index = 0; index < OSI_MAX_TIMER; index++) { + if (osi_info.timer[index].state == OSI_FREE) { + if (free_timer == NULL) + free_timer = (tOSI_TIMER_HANDLER)&osi_info.timer[index]; + } else { + if ((char const*)osi_info.timer[index].name == NULL) continue; + + if (strcmp((char const*)osi_info.timer[index].name, + (char const*)timer_name) == 0) { + OSI_loge("%s : %s timer is already allocated [%d]", __func__, + timer_name, index); + free_timer = NULL; + break; + } + } + } + + if (free_timer == NULL) { + OSI_loge("%s : Failed to find free timer(max: %d)", __func__, + OSI_MAX_TIMER); + } else { + free_timer->timeout = 0; + free_timer->name = timer_name; + free_timer->callback = NULL; + free_timer->callback_param = NULL; + free_timer->state = OSI_ALLOCATED; + } + osi_unlock(); + + return free_timer; +} + +int OSI_timer_start(tOSI_TIMER_HANDLER timer, uint32_t timeout, + tOSI_TIMER_CALLBACK callback, void* param) { + pthread_attr_t attr; + int ret_th; + + if (timer == NULL) { + OSI_loge("%s : Invalid parameters", __func__); + return 0; + } else if (timer->state == OSI_FREE) { + OSI_loge("%s : The timer is not allocated", __func__); + return 0; + } else { + osi_lock(); + OSI_logt("enter,osi_lock"); + timer->timeout = timeout; + timer->exact_time = OSI_timer_get_current_time(); + timer->init_timeout = timeout - 10; + timer->callback = callback; + timer->callback_param = param; + + if (timer->state != OSI_RUN) { + timer->state = OSI_RUN; + + /* start timer thread */ + if (osi_info.usingTimer < 1) { + osi_info.timer_thread_flag |= OSI_TIMER_THREAD_FLAG_DETACH; + //[START] S.LSI - To increase usingTimer prior to timer_thread + osi_info.usingTimer++; + //[END] S.LSI - To increase usingTimer prior to timer_thread + ret_th = pthread_attr_init(&attr); + if (ret_th != 0) + OSI_loge("%s : Error pthread_attr_init! ,erron: %d", __func__, + ret_th); + + OSI_logt("before pthread_create for timer thread"); + ret_th = pthread_create(&osi_info.timer_thread, &attr, + (void* (*)(void*))timer_thread, NULL); + OSI_logt("after pthread_create for timer thread"); + if (ret_th != 0) + OSI_loge("%s : Error to create timer_thread! ,erron: %d", __func__, + ret_th); + + ret_th = pthread_attr_destroy(&attr); + if (ret_th != 0) + OSI_loge("%s : Error pthread_arrt_destroy ,erron: %d", __func__, + ret_th); + } else + osi_info.usingTimer++; + } + OSI_logt("before osi_unlock"); + osi_unlock(); + OSI_logt("exit"); + return timeout; + } +} + +void OSI_timer_stop(tOSI_TIMER_HANDLER timer) { + if (timer == NULL) { + OSI_loge("%s : Invalid parameters", __func__); + } else if (timer->state != OSI_RUN) { + OSI_logd("%s : This timer is not running", __func__); + } else { + osi_lock(); + timer->state = OSI_STOP; + osi_info.usingTimer--; + if (osi_info.usingTimer <= 0) { + /* Cancle pthread_detach */ + osi_info.timer_thread_flag &= ~OSI_TIMER_THREAD_FLAG_DETACH; + osi_unlock(); + pthread_join(osi_info.timer_thread, NULL); + } else + osi_unlock(); + } +} + +void OSI_timer_free(tOSI_TIMER_HANDLER timer) { + if (timer) { + osi_lock(); + + if (timer->state == OSI_RUN) osi_info.usingTimer--; + + timer->state = OSI_FREE; + timer->name = NULL; + timer->callback = NULL; + timer->callback_param = NULL; + + osi_unlock(); + } +} + +tOSI_TIMER_HANDLER OSI_timer_get_handler(char* name) { + tOSI_TIMER_HANDLER timer = NULL; + int index; + + if (name == NULL) return NULL; + + osi_lock(); + for (index = 0; index < OSI_MAX_TIMER; index++) { + if ((char const*)osi_info.timer[index].name == NULL) continue; + + if (strcmp((char const*)osi_info.timer[index].name, (char const*)name) == + 0) { + timer = &osi_info.timer[index]; + break; + } + } + osi_unlock(); + + return timer; +} + +int32_t OSI_timer_get_current_time() { + struct timeval sec; + struct tm* now; + time_t rawtime; + + gettimeofday(&sec, NULL); + time(&rawtime); + now = gmtime(&rawtime); + + return (((now->tm_hour * 3600) + (now->tm_min * 60) + (now->tm_sec)) * 1000) + + (sec.tv_usec / 1000); +} +/************************************************************************ +** Internal function +*************************************************************************/ +void OSI_timer_update(int32_t tick) { + int index; + + osi_lock(); + + /* timer is not using */ + if (osi_info.usingTimer <= 0) { + osi_unlock(); + return; + } + + for (index = 0; index < OSI_MAX_TIMER; index++) { + if (osi_info.timer[index].state == OSI_RUN) { + osi_info.timer[index].timeout -= tick; + + if (osi_info.timer[index].timeout <= 0) { + /* START [16051100] - RTCC Patch */ + if (((OSI_timer_get_current_time() - osi_info.timer[index].exact_time) > + osi_info.timer[index].init_timeout) || + (OSI_timer_get_current_time() < osi_info.timer[index].exact_time)) + /* END [16051100] - RTCC Patch */ + { + osi_info.timer[index].state = OSI_STOP; + osi_info.usingTimer--; + + if (osi_info.timer[index].callback != NULL) + osi_info.timer[index].callback( + osi_info.timer[index].callback_param); + } else { + osi_info.timer[index].timeout = + osi_info.timer[index].init_timeout - + (OSI_timer_get_current_time() - osi_info.timer[index].exact_time); + } + } + } + } + osi_unlock(); +} + +void timer_thread(void) { + struct timespec delay; + int err; + + while (osi_info.usingTimer > 0) { + /* delay */ + // OSI_delay(1); + { + /* 1ms sleep for nanosleep()*/ + delay.tv_sec = 0; + delay.tv_nsec = 1000 * 1000; + + do { + err = nanosleep(&delay, &delay); + if (err < 0) OSI_loge("%s:Fail nanosleep", __func__); + } while (err < 0 && errno == EINTR); + } + + OSI_timer_update(1); + } + + if (osi_info.timer_thread_flag & OSI_TIMER_THREAD_FLAG_DETACH) + pthread_detach(pthread_self()); + + pthread_exit(NULL); +} |