|
@@ -35,8 +35,9 @@ struct rt_timerfd
|
|
rt_timer_t timer;
|
|
rt_timer_t timer;
|
|
struct rt_mutex lock;
|
|
struct rt_mutex lock;
|
|
struct timespec pre_time;
|
|
struct timespec pre_time;
|
|
- rt_uint64_t timeout_num;
|
|
|
|
- int ticks;
|
|
|
|
|
|
+ rt_atomic_t timeout_num;
|
|
|
|
+ struct rt_wqueue_node wqn;
|
|
|
|
+ rt_atomic_t ticks;
|
|
int clockid;
|
|
int clockid;
|
|
int isperiodic;
|
|
int isperiodic;
|
|
int tick_out;
|
|
int tick_out;
|
|
@@ -75,6 +76,8 @@ static int timerfd_close(struct dfs_file *file)
|
|
tfd->timer = RT_NULL;
|
|
tfd->timer = RT_NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ rt_wqueue_remove(&tfd->wqn);
|
|
|
|
+
|
|
rt_mutex_detach(&tfd->lock);
|
|
rt_mutex_detach(&tfd->lock);
|
|
rt_free(tfd);
|
|
rt_free(tfd);
|
|
}
|
|
}
|
|
@@ -93,11 +96,11 @@ static int timerfd_poll(struct dfs_file *file, struct rt_pollreq *req)
|
|
|
|
|
|
rt_poll_add(&tfd->timerfd_queue, req);
|
|
rt_poll_add(&tfd->timerfd_queue, req);
|
|
|
|
|
|
- if (tfd->ticks)
|
|
|
|
- events |= POLLIN;
|
|
|
|
-
|
|
|
|
rt_mutex_release(&tfd->lock);
|
|
rt_mutex_release(&tfd->lock);
|
|
|
|
|
|
|
|
+ if (rt_atomic_load(&(tfd->ticks)) > 0)
|
|
|
|
+ events |= POLLIN;
|
|
|
|
+
|
|
return events;
|
|
return events;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -109,6 +112,7 @@ static ssize_t timerfd_read(struct dfs_file *file, void *buf, size_t count, off_
|
|
{
|
|
{
|
|
struct rt_timerfd *tfd;
|
|
struct rt_timerfd *tfd;
|
|
rt_uint64_t *buffer;
|
|
rt_uint64_t *buffer;
|
|
|
|
+ int ret = 0;
|
|
|
|
|
|
buffer = (rt_uint64_t *)buf;
|
|
buffer = (rt_uint64_t *)buf;
|
|
|
|
|
|
@@ -126,29 +130,45 @@ static ssize_t timerfd_read(struct dfs_file *file, void *buf, size_t count, off_
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
- if ((tfd->ticks == 0) && (file->flags & O_NONBLOCK))
|
|
|
|
|
|
+ if ((rt_atomic_load(&(tfd->ticks)) == 0) && (file->flags & O_NONBLOCK))
|
|
{
|
|
{
|
|
rt_set_errno(EAGAIN);
|
|
rt_set_errno(EAGAIN);
|
|
return -EAGAIN;
|
|
return -EAGAIN;
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
- if (tfd->ticks == 0)
|
|
|
|
|
|
+ if (rt_atomic_load(&(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_mutex_release(&tfd->lock);
|
|
|
|
- }
|
|
|
|
|
|
+ (*buffer) = rt_atomic_load(&(tfd->timeout_num));
|
|
|
|
|
|
- tfd->ticks = 0;
|
|
|
|
|
|
+ rt_atomic_store(&(tfd->ticks), 0);
|
|
|
|
+ }
|
|
|
|
|
|
return sizeof(buffer);
|
|
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 rt_timerfd *tfd = RT_NULL;
|
|
struct dfs_file *df;
|
|
struct dfs_file *df;
|
|
@@ -189,29 +209,32 @@ static int timerfd_create_do(int clockid, int flags)
|
|
|
|
|
|
tfd = (struct rt_timerfd *)rt_malloc(sizeof(struct rt_timerfd));
|
|
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)
|
|
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));
|
|
df->vnode = (struct dfs_vnode *)rt_malloc(sizeof(struct dfs_vnode));
|
|
if (df->vnode)
|
|
if (df->vnode)
|
|
{
|
|
{
|
|
dfs_vnode_init(df->vnode, FT_REGULAR, &timerfd_fops);
|
|
dfs_vnode_init(df->vnode, FT_REGULAR, &timerfd_fops);
|
|
df->vnode->data = tfd;
|
|
df->vnode->data = tfd;
|
|
|
|
|
|
- #ifdef RT_USING_DFS_V2
|
|
|
|
|
|
+#ifdef RT_USING_DFS_V2
|
|
df->fops = &timerfd_fops;
|
|
df->fops = &timerfd_fops;
|
|
- #endif
|
|
|
|
|
|
+#endif
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
@@ -276,17 +299,20 @@ static void timerfd_timeout(void *parameter)
|
|
|
|
|
|
rt_wqueue_wakeup(&tfd->timerfd_queue, (void *)POLLIN);
|
|
rt_wqueue_wakeup(&tfd->timerfd_queue, (void *)POLLIN);
|
|
|
|
|
|
- rt_mutex_take(&tfd->lock, RT_WAITING_FOREVER);
|
|
|
|
|
|
+ rt_atomic_store(&(tfd->ticks), 1);
|
|
|
|
+ rt_atomic_add(&(tfd->timeout_num), 1);
|
|
|
|
|
|
- tfd->ticks = 1;
|
|
|
|
- tfd->timeout_num ++;
|
|
|
|
|
|
+ rt_mutex_take(&tfd->lock, RT_WAITING_FOREVER);
|
|
|
|
|
|
get_current_time(tfd, RT_NULL);
|
|
get_current_time(tfd, RT_NULL);
|
|
if (tfd->isperiodic == OPEN_PERIODIC)
|
|
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->isperiodic = ENTER_PERIODIC;
|
|
tfd->timer = rt_timer_create(TIMERFD_MUTEX_NAME, timerfd_timeout,
|
|
tfd->timer = rt_timer_create(TIMERFD_MUTEX_NAME, timerfd_timeout,
|
|
tfd, tfd->tick_out,
|
|
tfd, tfd->tick_out,
|
|
@@ -307,9 +333,15 @@ static void timerfd_time_operation(time_t *sec, long *nsec)
|
|
*nsec = 1 * SEC_TO_NSEC + *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;
|
|
int ret = 0;
|
|
struct rt_timerfd *tfd;
|
|
struct rt_timerfd *tfd;
|
|
@@ -331,7 +363,9 @@ static int timerfd_settime_do(int fd, int flags, const struct itimerspec *new, s
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
tfd = df->vnode->data;
|
|
tfd = df->vnode->data;
|
|
- tfd->timeout_num = 0;
|
|
|
|
|
|
+
|
|
|
|
+ rt_atomic_store(&(tfd->ticks), 0);
|
|
|
|
+ rt_atomic_store(&(tfd->timeout_num), 0);
|
|
|
|
|
|
rt_mutex_take(&tfd->lock, RT_WAITING_FOREVER);
|
|
rt_mutex_take(&tfd->lock, RT_WAITING_FOREVER);
|
|
tfd->isperiodic = INIT_PERIODIC;
|
|
tfd->isperiodic = INIT_PERIODIC;
|
|
@@ -346,6 +380,18 @@ static int timerfd_settime_do(int fd, int flags, const struct itimerspec *new, s
|
|
|
|
|
|
if (new)
|
|
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);
|
|
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);
|
|
interval_msec = (new->it_interval.tv_nsec / MSEC_TO_NSEC) + (new->it_interval.tv_sec * SEC_TO_MSEC);
|
|
|
|
|
|
@@ -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;
|
|
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);
|
|
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 > 0)
|
|
{
|
|
{
|
|
if (value_msec > TIME_INT32_MAX)
|
|
if (value_msec > TIME_INT32_MAX)
|
|
@@ -385,20 +434,15 @@ static int timerfd_settime_do(int fd, int flags, const struct itimerspec *new, s
|
|
if (tick_out < 0)
|
|
if (tick_out < 0)
|
|
return -EINVAL;
|
|
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->timer = rt_timer_create(TIMERFD_MUTEX_NAME, timerfd_timeout,
|
|
tfd, tick_out,
|
|
tfd, tick_out,
|
|
RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER);
|
|
RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER);
|
|
rt_timer_start(tfd->timer);
|
|
rt_timer_start(tfd->timer);
|
|
}
|
|
}
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ timerfd_timeout(tfd);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
@@ -411,7 +455,7 @@ static int timerfd_settime_do(int fd, int flags, const struct itimerspec *new, s
|
|
return ret;
|
|
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 rt_timerfd *tfd;
|
|
struct dfs_file *df = RT_NULL;
|
|
struct dfs_file *df = RT_NULL;
|
|
@@ -443,10 +487,11 @@ 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_nsec = tfd->ittimer.it_interval.tv_nsec - tv_nsec;
|
|
cur->it_value.tv_sec = tfd->ittimer.it_interval.tv_sec - tv_sec;
|
|
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
|
|
else
|
|
{
|
|
{
|
|
- if (tfd->timeout_num == 1)
|
|
|
|
|
|
+ if (rt_atomic_load(&(tfd->timeout_num)) == 1)
|
|
{
|
|
{
|
|
cur->it_value.tv_nsec = 0;
|
|
cur->it_value.tv_nsec = 0;
|
|
cur->it_value.tv_sec = 0;
|
|
cur->it_value.tv_sec = 0;
|
|
@@ -466,15 +511,15 @@ static int timerfd_gettime_do(int fd, struct itimerspec *cur)
|
|
|
|
|
|
int timerfd_create(int clockid, int flags)
|
|
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)
|
|
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)
|
|
int timerfd_gettime(int fd, struct itimerspec *cur)
|
|
{
|
|
{
|
|
- return timerfd_gettime_do(fd, cur);
|
|
|
|
|
|
+ return timerfd_do_gettime(fd, cur);
|
|
}
|
|
}
|