sched/timer: Fix timer multiple return.

Fix timer multiple return.

Signed-off-by: jiangtao16 <jiangtao16@xiaomi.com>
This commit is contained in:
jiangtao16
2026-01-22 22:14:00 +08:00
committed by Xiang Xiao
parent 3b005dbdf7
commit 51bb9e0417
8 changed files with 203 additions and 182 deletions
+47 -43
View File
@@ -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 */
+2 -2
View File
@@ -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 */
+11 -9
View File
@@ -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;
+7 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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 */
+22 -21
View File
@@ -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
View File
@@ -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);