doubao_chat/lib/net/libduer-device/platform/source-jl/net_timer.c

183 lines
4.3 KiB
C

#include "os/os_api.h"
#include "generic/list.h"
static int net_timer_task_pid;
static struct list_head timer_head;
static OS_MUTEX timer_mutex;
static u8 net_timer_task_exit_flag;
static u8 net_timer_init_flag;
static u64 s_timestamp = 0;
static u32 last_timestamp = 0;
extern u32 timer_get_ms(void);
struct timer_list {
struct list_head entry;
void (*function)(void *priv);
void *data;
u64 expires;
u32 msec;
u8 periodic;
u8 del;
};
static inline u64 net_timer_get_timestamp()
{
u32 read_timestamp = timer_get_ms();
if (s_timestamp <= read_timestamp) {
s_timestamp = read_timestamp;
last_timestamp = read_timestamp;
} else {
if (last_timestamp > read_timestamp) {
s_timestamp += (~read_timestamp + 1);
}
s_timestamp += read_timestamp;
last_timestamp = read_timestamp;
}
return s_timestamp;
}
static void net_timer_task(void *arg)
{
struct timer_list *curr;
struct timer_list *p;
while (1) {
os_mutex_pend(&timer_mutex, 0);
while (!list_empty(&timer_head)) {
curr = list_first_entry(&timer_head, struct timer_list, entry);
if (curr == NULL || !curr->function) {
printf("\n net_timer_check error happend -> 0x%x, 0x%x \n", (u32)curr, (u32)(curr->function));
break;
}
if (net_timer_get_timestamp() < curr->expires) {
break;
}
list_del(&curr->entry);
os_mutex_post(&timer_mutex);
if (!curr->del) {
curr->function(curr->data);
}
os_mutex_pend(&timer_mutex, 0);
if (curr->periodic && !curr->del) {
curr->expires = net_timer_get_timestamp() + curr->msec;
list_for_each_entry(p, &timer_head, entry) {
if (p->expires > curr->expires) {
break;
}
}
__list_add(&curr->entry, p->entry.prev, &p->entry);
} else {
free(curr);
}
}
#if 0
list_for_each_entry(p, &timer_head, entry) {
if (p->del) {
list_del(&p->entry);
free(p);
}
}
#endif
os_mutex_post(&timer_mutex);
if (net_timer_task_exit_flag) {
os_mutex_pend(&timer_mutex, 0);
while (!list_empty(&timer_head)) {
curr = list_first_entry(&timer_head, struct timer_list, entry);
if (!curr->del) {
printf("The timer list should be del before uninit !!!\n");
}
list_del(&curr->entry);
free(curr);
}
os_mutex_post(&timer_mutex);
return;
}
msleep(80);
}
}
int net_timer_init(void)
{
if (!net_timer_init_flag) {
INIT_LIST_HEAD(&timer_head);
net_timer_init_flag = 1;
os_mutex_create(&timer_mutex);
return thread_fork("net_timer_task", 22, 256, 0, &net_timer_task_pid, net_timer_task, NULL);
}
return 0;
}
void net_timer_uninit(void)
{
if (net_timer_init_flag) {
net_timer_task_exit_flag = 1;
thread_kill(&net_timer_task_pid, KILL_WAIT);
net_timer_task_exit_flag = 0;
os_mutex_del(&timer_mutex, 1);
net_timer_init_flag = 0;
}
}
int net_timer_add(void *priv, void (*func)(void *priv), u32 msec, u8 periodic)
{
struct timer_list *t;
struct timer_list *p;
t = calloc(1, sizeof(struct timer_list));
if (!t) {
return -1;
}
t->msec = msec;
t->data = priv;
t->function = func;
t->periodic = periodic;
t->del = 0;
os_mutex_pend(&timer_mutex, 0);
t->expires = net_timer_get_timestamp() + msec;
list_for_each_entry(p, &timer_head, entry) {
if (p->expires > t->expires) {
break;
}
}
__list_add(&t->entry, p->entry.prev, &p->entry);
os_mutex_post(&timer_mutex);
return (int)t;
}
void net_timer_del(int __t)
{
struct timer_list *t = (struct timer_list *)__t;
struct timer_list *p;
os_mutex_pend(&timer_mutex, 0);
list_for_each_entry(p, &timer_head, entry) {
if (p == t) {
t->del = 1;
break;
}
}
os_mutex_post(&timer_mutex);
}