Skip to content

Commit

Permalink
Fixed issues with timerfd
Browse files Browse the repository at this point in the history
  • Loading branch information
zmq810150896 committed Oct 10, 2023
1 parent 2d630e3 commit 6d62051
Showing 1 changed file with 84 additions and 39 deletions.
123 changes: 84 additions & 39 deletions components/libc/posix/io/timerfd/timerfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ struct rt_timerfd
struct rt_mutex lock;
struct timespec pre_time;
rt_uint64_t timeout_num;
struct rt_wqueue_node wqn;
int ticks;
int clockid;
int isperiodic;
Expand Down Expand Up @@ -75,6 +76,8 @@ static int timerfd_close(struct dfs_file *file)
tfd->timer = RT_NULL;
}

rt_wqueue_remove(&tfd->wqn);

rt_mutex_detach(&tfd->lock);
rt_free(tfd);
}
Expand Down Expand Up @@ -109,6 +112,7 @@ static ssize_t timerfd_read(struct dfs_file *file, void *buf, size_t count, off_
{
struct rt_timerfd *tfd;
rt_uint64_t *buffer;
int ret = 0;

buffer = (rt_uint64_t *)buf;

Expand All @@ -135,20 +139,37 @@ static ssize_t timerfd_read(struct dfs_file *file, void *buf, size_t count, off_
{
if (tfd->ticks == 0)
{
rt_wqueue_wait(&tfd->timerfd_queue, 0, RT_WAITING_FOREVER);
tfd->wqn.polling_thread = rt_thread_self();

rt_wqueue_remove(&tfd->wqn);
rt_wqueue_add(&tfd->timerfd_queue, &tfd->wqn);

ret = rt_thread_suspend_with_flag(tfd->wqn.polling_thread, RT_INTERRUPTIBLE);
if (ret == RT_EOK)
{
rt_schedule();
}
else
{
return ret;
}
}

rt_mutex_take(&tfd->lock, RT_WAITING_FOREVER);
(*buffer) = tfd->timeout_num;
rt_atomic_store(&(tfd->ticks), 0);
rt_mutex_release(&tfd->lock);
}

tfd->ticks = 0;

return sizeof(buffer);
}

static int timerfd_create_do(int clockid, int flags)
static int timerfd_wqueue_callback(struct rt_wqueue_node *wait, void *key)
{
return 0;
}

static int timerfd_do_create(int clockid, int flags)
{
struct rt_timerfd *tfd = RT_NULL;
struct dfs_file *df;
Expand Down Expand Up @@ -189,20 +210,23 @@ static int timerfd_create_do(int clockid, int flags)

tfd = (struct rt_timerfd *)rt_malloc(sizeof(struct rt_timerfd));

rt_mutex_init(&tfd->lock, TIMERFD_MUTEX_NAME, RT_IPC_FLAG_FIFO);
rt_wqueue_init(&tfd->timerfd_queue);

tfd->isperiodic = INIT_PERIODIC;
tfd->ticks = 0;
tfd->timeout_num = 0;
tfd->tick_out = 0;
tfd->clockid = clockid;
tfd->timer = RT_NULL;
tfd->pre_time.tv_sec = 0;
tfd->pre_time.tv_nsec = 0;

if (tfd)
{
rt_mutex_init(&tfd->lock, TIMERFD_MUTEX_NAME, RT_IPC_FLAG_FIFO);
rt_wqueue_init(&tfd->timerfd_queue);

tfd->isperiodic = INIT_PERIODIC;
tfd->ticks = 0;
tfd->timeout_num = 0;
tfd->tick_out = 0;
tfd->clockid = clockid;
tfd->timer = RT_NULL;
tfd->pre_time.tv_sec = 0;
tfd->pre_time.tv_nsec = 0;
tfd->wqn.polling_thread = rt_thread_self();
rt_list_init(&(tfd->wqn.list));
tfd->wqn.wakeup = timerfd_wqueue_callback;

df->vnode = (struct dfs_vnode *)rt_malloc(sizeof(struct dfs_vnode));
if (df->vnode)
{
Expand Down Expand Up @@ -278,15 +302,18 @@ static void timerfd_timeout(void *parameter)

rt_mutex_take(&tfd->lock, RT_WAITING_FOREVER);

tfd->ticks = 1;
rt_atomic_store(&(tfd->ticks), 1);
tfd->timeout_num ++;

get_current_time(tfd, RT_NULL);
if (tfd->isperiodic == OPEN_PERIODIC)
{
rt_timer_stop(tfd->timer);
rt_timer_delete(tfd->timer);
tfd->timer = RT_NULL;
if (tfd->timer)
{
rt_timer_stop(tfd->timer);
rt_timer_delete(tfd->timer);
tfd->timer = RT_NULL;
}
tfd->isperiodic = ENTER_PERIODIC;
tfd->timer = rt_timer_create(TIMERFD_MUTEX_NAME, timerfd_timeout,
tfd, tfd->tick_out,
Expand All @@ -307,9 +334,15 @@ static void timerfd_time_operation(time_t *sec, long *nsec)
*nsec = 1 * SEC_TO_NSEC + *nsec;
}
}

if (*sec < 0 || *nsec < 0)
{
*sec = 0;
*nsec = 0;
}
}

static int timerfd_settime_do(int fd, int flags, const struct itimerspec *new, struct itimerspec *old)
static int timerfd_do_settime(int fd, int flags, const struct itimerspec *new, struct itimerspec *old)
{
int ret = 0;
struct rt_timerfd *tfd;
Expand All @@ -331,10 +364,11 @@ static int timerfd_settime_do(int fd, int flags, const struct itimerspec *new, s
return -EINVAL;

tfd = df->vnode->data;
tfd->timeout_num = 0;

rt_mutex_take(&tfd->lock, RT_WAITING_FOREVER);
tfd->isperiodic = INIT_PERIODIC;
tfd->timeout_num = 0;
rt_atomic_store(&(tfd->ticks), 0);

if (old)
{
Expand All @@ -346,6 +380,18 @@ static int timerfd_settime_do(int fd, int flags, const struct itimerspec *new, s

if (new)
{
if (tfd->timer != RT_NULL)
{
rt_timer_stop(tfd->timer);
rt_timer_delete(tfd->timer);
tfd->timer = RT_NULL;
}

if (new->it_value.tv_nsec == 0 && new->it_value.tv_sec == 0)
{
return 0;
}

value_msec = (new->it_value.tv_nsec / MSEC_TO_NSEC) + (new->it_value.tv_sec * SEC_TO_MSEC);
interval_msec = (new->it_interval.tv_nsec / MSEC_TO_NSEC) + (new->it_interval.tv_sec * SEC_TO_MSEC);

Expand All @@ -369,13 +415,16 @@ static int timerfd_settime_do(int fd, int flags, const struct itimerspec *new, s
tfd->ittimer.it_value.tv_nsec = new->it_value.tv_nsec - current_time.tv_nsec;
timerfd_time_operation(&tfd->ittimer.it_value.tv_sec, &tfd->ittimer.it_value.tv_nsec);

if (tfd->timer != RT_NULL)
if ((interval_msec > 0) && (interval_msec <= TIME_INT32_MAX))
{
rt_timer_stop(tfd->timer);
rt_timer_delete(tfd->timer);
tfd->timer = RT_NULL;
tfd->tick_out = rt_tick_from_millisecond(interval_msec);
if (tfd->tick_out < 0)
return -EINVAL;
tfd->isperiodic = OPEN_PERIODIC;
}

get_current_time(tfd, RT_NULL);

if (value_msec > 0)
{
if (value_msec > TIME_INT32_MAX)
Expand All @@ -385,20 +434,15 @@ static int timerfd_settime_do(int fd, int flags, const struct itimerspec *new, s
if (tick_out < 0)
return -EINVAL;

if ((interval_msec > 0) && (interval_msec <= TIME_INT32_MAX))
{
tfd->tick_out = rt_tick_from_millisecond(interval_msec);
if (tfd->tick_out < 0)
return -EINVAL;
tfd->isperiodic = OPEN_PERIODIC;
}

get_current_time(tfd, RT_NULL);
tfd->timer = rt_timer_create(TIMERFD_MUTEX_NAME, timerfd_timeout,
tfd, tick_out,
RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER);
rt_timer_start(tfd->timer);
}
else
{
timerfd_timeout(tfd);
}
}
else
{
Expand All @@ -411,7 +455,7 @@ static int timerfd_settime_do(int fd, int flags, const struct itimerspec *new, s
return ret;
}

static int timerfd_gettime_do(int fd, struct itimerspec *cur)
static int timerfd_do_gettime(int fd, struct itimerspec *cur)
{
struct rt_timerfd *tfd;
struct dfs_file *df = RT_NULL;
Expand Down Expand Up @@ -443,6 +487,7 @@ static int timerfd_gettime_do(int fd, struct itimerspec *cur)
{
cur->it_value.tv_nsec = tfd->ittimer.it_interval.tv_nsec - tv_nsec;
cur->it_value.tv_sec = tfd->ittimer.it_interval.tv_sec - tv_sec;
timerfd_time_operation(&cur->it_value.tv_sec, &cur->it_value.tv_nsec);
}
else
{
Expand All @@ -466,15 +511,15 @@ static int timerfd_gettime_do(int fd, struct itimerspec *cur)

int timerfd_create(int clockid, int flags)
{
return timerfd_create_do(clockid, flags);
return timerfd_do_create(clockid, flags);
}

int timerfd_settime(int fd, int flags, const struct itimerspec *new, struct itimerspec *old)
{
return timerfd_settime_do(fd, flags, new, old);
return timerfd_do_settime(fd, flags, new, old);
}

int timerfd_gettime(int fd, struct itimerspec *cur)
{
return timerfd_gettime_do(fd, cur);
return timerfd_do_gettime(fd, cur);
}

0 comments on commit 6d62051

Please sign in to comment.