You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

264 lines
7.5 KiB

/*
* 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);
}