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