mirror of
https://github.com/apache/nuttx.git
synced 2026-08-18 01:49:24 +08:00
sched/timer: Fix timer multiple return.
Fix timer multiple return. Signed-off-by: jiangtao16 <jiangtao16@xiaomi.com>
This commit is contained in:
+47
-43
@@ -158,7 +158,7 @@ static FAR struct posix_timer_s *timer_allocate(void)
|
||||
int timer_create(clockid_t clockid, FAR struct sigevent *evp,
|
||||
FAR timer_t *timerid)
|
||||
{
|
||||
FAR struct posix_timer_s *ret;
|
||||
FAR struct posix_timer_s *ret = NULL;
|
||||
FAR struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Sanity checks. */
|
||||
@@ -169,57 +169,61 @@ int timer_create(clockid_t clockid, FAR struct sigevent *evp,
|
||||
!GOOD_SIGNO(evp->sigev_signo)))
|
||||
{
|
||||
set_errno(EINVAL);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Allocate a timer instance to contain the watchdog */
|
||||
|
||||
ret = timer_allocate();
|
||||
if (!ret)
|
||||
{
|
||||
set_errno(EAGAIN);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Initialize the timer instance */
|
||||
|
||||
ret->pt_clock = clockid;
|
||||
ret->pt_crefs = 1;
|
||||
ret->pt_owner = tcb->pid;
|
||||
ret->pt_delay = 0;
|
||||
ret->pt_expected = 0;
|
||||
|
||||
/* Was a struct sigevent provided? */
|
||||
|
||||
if (evp)
|
||||
{
|
||||
/* Yes, copy the entire struct sigevent content */
|
||||
|
||||
memcpy(&ret->pt_event, evp, sizeof(struct sigevent));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* "If the evp argument is NULL, the effect is as if the evp argument
|
||||
* pointed to a sigevent structure with the sigev_notify member
|
||||
* having the value SIGEV_SIGNAL, the sigev_signo having a default
|
||||
* signal number, and the sigev_value member having the value of the
|
||||
* timer ID."
|
||||
*/
|
||||
/* Allocate a timer instance to contain the watchdog */
|
||||
|
||||
ret->pt_event.sigev_notify = SIGEV_SIGNAL;
|
||||
ret->pt_event.sigev_signo = SIGALRM;
|
||||
ret->pt_event.sigev_value.sival_ptr = ret;
|
||||
ret = timer_allocate();
|
||||
if (!ret)
|
||||
{
|
||||
set_errno(EAGAIN);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Initialize the timer instance */
|
||||
|
||||
ret->pt_clock = clockid;
|
||||
ret->pt_crefs = 1;
|
||||
ret->pt_owner = tcb->pid;
|
||||
ret->pt_delay = 0;
|
||||
ret->pt_expected = 0;
|
||||
|
||||
/* Was a struct sigevent provided? */
|
||||
|
||||
if (evp)
|
||||
{
|
||||
/* Yes, copy the entire struct sigevent content */
|
||||
|
||||
memcpy(&ret->pt_event, evp, sizeof(struct sigevent));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* "If the evp argument is NULL, the effect is as if the evp
|
||||
* argument pointed to a sigevent structure with the
|
||||
* sigev_notify member having the value SIGEV_SIGNAL,
|
||||
* the sigev_signo having a default signal number,
|
||||
* and the sigev_value member having the value of the
|
||||
* timer ID."
|
||||
*/
|
||||
|
||||
ret->pt_event.sigev_notify = SIGEV_SIGNAL;
|
||||
ret->pt_event.sigev_signo = SIGALRM;
|
||||
ret->pt_event.sigev_value.sival_ptr = ret;
|
||||
|
||||
#ifdef CONFIG_SIG_EVTHREAD
|
||||
ret->pt_event.sigev_notify_function = NULL;
|
||||
ret->pt_event.sigev_notify_attributes = NULL;
|
||||
ret->pt_event.sigev_notify_function = NULL;
|
||||
ret->pt_event.sigev_notify_attributes = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return the timer */
|
||||
|
||||
*timerid = ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the timer */
|
||||
|
||||
*timerid = ret;
|
||||
return OK;
|
||||
return ret ? OK : ERROR;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DISABLE_POSIX_TIMERS */
|
||||
|
||||
@@ -68,10 +68,10 @@ int timer_delete(timer_t timerid)
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
return ERROR;
|
||||
ret = ERROR;
|
||||
}
|
||||
|
||||
return OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DISABLE_POSIX_TIMERS */
|
||||
|
||||
@@ -82,18 +82,20 @@ int getitimer(int which, FAR struct itimerval *value)
|
||||
if (which != ITIMER_REAL || !value)
|
||||
{
|
||||
set_errno(EINVAL);
|
||||
return ERROR;
|
||||
ret = ERROR;
|
||||
}
|
||||
|
||||
if (rtcb->group->itimer)
|
||||
else
|
||||
{
|
||||
ret = timer_gettime(rtcb->group->itimer, &spec);
|
||||
}
|
||||
if (rtcb->group->itimer)
|
||||
{
|
||||
ret = timer_gettime(rtcb->group->itimer, &spec);
|
||||
}
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
TIMESPEC_TO_TIMEVAL(&value->it_value, &spec.it_value);
|
||||
TIMESPEC_TO_TIMEVAL(&value->it_interval, &spec.it_interval);
|
||||
if (ret == OK)
|
||||
{
|
||||
TIMESPEC_TO_TIMEVAL(&value->it_value, &spec.it_value);
|
||||
TIMESPEC_TO_TIMEVAL(&value->it_interval, &spec.it_interval);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -83,12 +83,15 @@ int timer_getoverrun(timer_t timerid)
|
||||
if (!timer)
|
||||
{
|
||||
set_errno(EINVAL);
|
||||
return ERROR;
|
||||
ret = ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = timer->pt_overrun;
|
||||
ret = ret > DELAYTIMER_MAX ? DELAYTIMER_MAX : ret;
|
||||
}
|
||||
|
||||
ret = timer->pt_overrun;
|
||||
|
||||
return ret > DELAYTIMER_MAX ? DELAYTIMER_MAX : ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DISABLE_POSIX_TIMERS */
|
||||
|
||||
+14
-10
@@ -74,22 +74,26 @@ int timer_gettime(timer_t timerid, FAR struct itimerspec *value)
|
||||
{
|
||||
FAR struct posix_timer_s *timer = timer_gethandle(timerid);
|
||||
sclock_t ticks;
|
||||
int ret = OK;
|
||||
|
||||
if (!timer || !value)
|
||||
{
|
||||
set_errno(EINVAL);
|
||||
return ERROR;
|
||||
ret = ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the number of ticks before the underlying watchdog expires */
|
||||
|
||||
ticks = wd_gettime(&timer->pt_wdog);
|
||||
|
||||
/* Convert that to a struct timespec and return it */
|
||||
|
||||
clock_ticks2time(&value->it_value, ticks);
|
||||
clock_ticks2time(&value->it_interval, timer->pt_delay);
|
||||
}
|
||||
|
||||
/* Get the number of ticks before the underlying watchdog expires */
|
||||
|
||||
ticks = wd_gettime(&timer->pt_wdog);
|
||||
|
||||
/* Convert that to a struct timespec and return it */
|
||||
|
||||
clock_ticks2time(&value->it_value, ticks);
|
||||
clock_ticks2time(&value->it_interval, timer->pt_delay);
|
||||
return OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DISABLE_POSIX_TIMERS */
|
||||
|
||||
+20
-15
@@ -105,35 +105,40 @@ static inline void timer_free(struct posix_timer_s *timer)
|
||||
|
||||
int timer_release(FAR struct posix_timer_s *timer)
|
||||
{
|
||||
int ret = OK;
|
||||
|
||||
/* Some sanity checks */
|
||||
|
||||
if (timer == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
/* Release one reference to timer. Don't delete the timer until the count
|
||||
* would decrement to zero.
|
||||
*/
|
||||
|
||||
if (timer->pt_crefs > 1)
|
||||
else if (timer->pt_crefs > 1)
|
||||
{
|
||||
timer->pt_crefs--;
|
||||
return 1;
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Cancel the underlying watchdog instance */
|
||||
|
||||
wd_cancel(&timer->pt_wdog);
|
||||
|
||||
/* Cancel any pending notification */
|
||||
|
||||
nxsig_cancel_notification(&timer->pt_work);
|
||||
|
||||
/* Release the timer structure */
|
||||
|
||||
timer_free(timer);
|
||||
}
|
||||
|
||||
/* Cancel the underlying watchdog instance */
|
||||
|
||||
wd_cancel(&timer->pt_wdog);
|
||||
|
||||
/* Cancel any pending notification */
|
||||
|
||||
nxsig_cancel_notification(&timer->pt_work);
|
||||
|
||||
/* Release the timer structure */
|
||||
|
||||
timer_free(timer);
|
||||
return OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DISABLE_POSIX_TIMERS */
|
||||
|
||||
@@ -97,33 +97,34 @@ int setitimer(int which, FAR const struct itimerval *value,
|
||||
if (which != ITIMER_REAL || !value)
|
||||
{
|
||||
set_errno(EINVAL);
|
||||
return ERROR;
|
||||
ret = ERROR;
|
||||
}
|
||||
|
||||
rtcb = this_task();
|
||||
|
||||
nxrmutex_lock(&rtcb->group->tg_mutex);
|
||||
|
||||
if (!rtcb->group->itimer)
|
||||
else
|
||||
{
|
||||
ret = timer_create(CLOCK_REALTIME, NULL, &rtcb->group->itimer);
|
||||
}
|
||||
rtcb = this_task();
|
||||
|
||||
nxrmutex_unlock(&rtcb->group->tg_mutex);
|
||||
nxrmutex_lock(&rtcb->group->tg_mutex);
|
||||
|
||||
if (ret != OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
if (!rtcb->group->itimer)
|
||||
{
|
||||
ret = timer_create(CLOCK_REALTIME, NULL, &rtcb->group->itimer);
|
||||
}
|
||||
|
||||
TIMEVAL_TO_TIMESPEC(&value->it_value, &spec.it_value);
|
||||
TIMEVAL_TO_TIMESPEC(&value->it_interval, &spec.it_interval);
|
||||
nxrmutex_unlock(&rtcb->group->tg_mutex);
|
||||
|
||||
ret = timer_settime(rtcb->group->itimer, 0, &spec, ovalue ? &ospec : NULL);
|
||||
if (ret == OK && ovalue)
|
||||
{
|
||||
TIMESPEC_TO_TIMEVAL(&ovalue->it_value, &ospec.it_value);
|
||||
TIMESPEC_TO_TIMEVAL(&ovalue->it_interval, &ospec.it_interval);
|
||||
if (ret == OK)
|
||||
{
|
||||
TIMEVAL_TO_TIMESPEC(&value->it_value, &spec.it_value);
|
||||
TIMEVAL_TO_TIMESPEC(&value->it_interval, &spec.it_interval);
|
||||
|
||||
ret = timer_settime(rtcb->group->itimer, 0, &spec,
|
||||
ovalue ? &ospec : NULL);
|
||||
if (ret == OK && ovalue)
|
||||
{
|
||||
TIMESPEC_TO_TIMEVAL(&ovalue->it_value, &ospec.it_value);
|
||||
TIMESPEC_TO_TIMEVAL(&ovalue->it_interval, &ospec.it_interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
+80
-78
@@ -158,28 +158,26 @@ static void timer_timeout(wdparm_t itimer)
|
||||
{
|
||||
FAR struct posix_timer_s *timer = timer_gethandle((timer_t)itimer);
|
||||
|
||||
if (timer == NULL)
|
||||
if (timer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
/* Send the specified signal to the specified task. Increment the
|
||||
* reference count on the timer first so that will not be deleted until
|
||||
* after the signal handler returns.
|
||||
*/
|
||||
|
||||
/* Send the specified signal to the specified task. Increment the
|
||||
* reference count on the timer first so that will not be deleted until
|
||||
* after the signal handler returns.
|
||||
*/
|
||||
timer->pt_crefs++;
|
||||
timer_signotify(timer);
|
||||
|
||||
timer->pt_crefs++;
|
||||
timer_signotify(timer);
|
||||
/* Release the reference. timer_release will return nonzero if
|
||||
* the timer was not deleted.
|
||||
*/
|
||||
|
||||
/* Release the reference. timer_release will return nonzero if the timer
|
||||
* was not deleted.
|
||||
*/
|
||||
if (timer_release(timer))
|
||||
{
|
||||
/* If this is a repetitive timer, the restart the watchdog */
|
||||
|
||||
if (timer_release(timer))
|
||||
{
|
||||
/* If this is a repetitive timer, the restart the watchdog */
|
||||
|
||||
timer_restart(timer, itimer);
|
||||
timer_restart(timer, itimer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,77 +262,81 @@ int timer_settime(timer_t timerid, int flags,
|
||||
if (!timer || !value)
|
||||
{
|
||||
set_errno(EINVAL);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if (ovalue)
|
||||
{
|
||||
/* Get the number of ticks before the underlying watchdog expires */
|
||||
|
||||
delay = wd_gettime(&timer->pt_wdog);
|
||||
|
||||
/* Convert that to a struct timespec and return it */
|
||||
|
||||
clock_ticks2time(&ovalue->it_value, delay);
|
||||
clock_ticks2time(&ovalue->it_interval, timer->pt_delay);
|
||||
}
|
||||
|
||||
/* Disarm the timer (in case the timer was already armed when
|
||||
* timer_settime() is called).
|
||||
*/
|
||||
|
||||
wd_cancel(&timer->pt_wdog);
|
||||
|
||||
/* Cancel any pending notification */
|
||||
|
||||
nxsig_cancel_notification(&timer->pt_work);
|
||||
|
||||
/* If the it_value member of value is zero, the timer will not be
|
||||
* re-armed
|
||||
*/
|
||||
|
||||
if (value->it_value.tv_sec <= 0 && value->it_value.tv_nsec <= 0)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Setup up any repetitive timer */
|
||||
|
||||
if (value->it_interval.tv_sec > 0 || value->it_interval.tv_nsec > 0)
|
||||
{
|
||||
delay = clock_time2ticks(&value->it_interval);
|
||||
timer->pt_delay = delay;
|
||||
ret = -EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
timer->pt_delay = 0;
|
||||
}
|
||||
if (ovalue)
|
||||
{
|
||||
/* Get the number of ticks before the underlying watchdog expires */
|
||||
|
||||
/* Check if abstime is selected */
|
||||
delay = wd_gettime(&timer->pt_wdog);
|
||||
|
||||
if ((flags & TIMER_ABSTIME) != 0)
|
||||
{
|
||||
/* Calculate a delay corresponding to the absolute time in 'value' */
|
||||
/* Convert that to a struct timespec and return it */
|
||||
|
||||
clock_abstime2ticks(timer->pt_clock, &value->it_value, &delay);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Calculate a delay assuming that 'value' holds the relative time
|
||||
* to wait. We have internal knowledge that clock_time2ticks always
|
||||
* returns success.
|
||||
clock_ticks2time(&ovalue->it_value, delay);
|
||||
clock_ticks2time(&ovalue->it_interval, timer->pt_delay);
|
||||
}
|
||||
|
||||
/* Disarm the timer (in case the timer was already armed when
|
||||
* timer_settime() is called).
|
||||
*/
|
||||
|
||||
delay = clock_time2ticks(&value->it_value);
|
||||
wd_cancel(&timer->pt_wdog);
|
||||
|
||||
/* Cancel any pending notification */
|
||||
|
||||
nxsig_cancel_notification(&timer->pt_work);
|
||||
|
||||
/* If the it_value member of value is zero, the timer will not be
|
||||
* re-armed
|
||||
*/
|
||||
|
||||
if (value->it_value.tv_sec > 0 || value->it_value.tv_nsec > 0)
|
||||
{
|
||||
/* Setup up any repetitive timer */
|
||||
|
||||
if (value->it_interval.tv_sec > 0 ||
|
||||
value->it_interval.tv_nsec > 0)
|
||||
{
|
||||
delay = clock_time2ticks(&value->it_interval);
|
||||
timer->pt_delay = delay;
|
||||
}
|
||||
else
|
||||
{
|
||||
timer->pt_delay = 0;
|
||||
}
|
||||
|
||||
/* Check if abstime is selected */
|
||||
|
||||
if ((flags & TIMER_ABSTIME) != 0)
|
||||
{
|
||||
/* Calculate a delay corresponding to the
|
||||
* absolute time in 'value'.
|
||||
*/
|
||||
|
||||
clock_abstime2ticks(timer->pt_clock, &value->it_value, &delay);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Calculate a delay assuming that 'value' holds the
|
||||
* relative time to wait.
|
||||
* We have internal knowledge that clock_time2ticks always
|
||||
* returns success.
|
||||
*/
|
||||
|
||||
delay = clock_time2ticks(&value->it_value);
|
||||
}
|
||||
|
||||
timer->pt_expected = clock_delay2abstick(delay);
|
||||
|
||||
/* Then start the watchdog */
|
||||
|
||||
ret = wd_start_abstick(&timer->pt_wdog, timer->pt_expected,
|
||||
timer_timeout, (wdparm_t)timer);
|
||||
}
|
||||
}
|
||||
|
||||
timer->pt_expected = clock_delay2abstick(delay);
|
||||
|
||||
/* Then start the watchdog */
|
||||
|
||||
ret = wd_start_abstick(&timer->pt_wdog, timer->pt_expected,
|
||||
timer_timeout, (wdparm_t)timer);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
|
||||
Reference in New Issue
Block a user