summaryrefslogtreecommitdiff
path: root/halimpl/osi/osi_timer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'halimpl/osi/osi_timer.cc')
-rw-r--r--halimpl/osi/osi_timer.cc263
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);
+}