Module: xenomai-forge Branch: master Commit: aa643f5a1a84ae35a02f793c316ce76757a6a8da URL: http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=aa643f5a1a84ae35a02f793c316ce76757a6a8da
Author: Philippe Gerum <r...@xenomai.org> Date: Fri Aug 30 10:35:41 2013 +0200 cobalt/posix/timer: introduce extension handler for deletion --- kernel/cobalt/posix/extension.h | 1 + kernel/cobalt/posix/timer.c | 63 ++++++++++++++++++++++++-------------- 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/kernel/cobalt/posix/extension.h b/kernel/cobalt/posix/extension.h index 8c85425..e73c46f 100644 --- a/kernel/cobalt/posix/extension.h +++ b/kernel/cobalt/posix/extension.h @@ -41,6 +41,7 @@ struct cobalt_extension { int flags); int (*timer_gettime)(struct cobalt_extref *reftimer, /* nklocked, IRQs off. */ struct itimerspec *__restrict__ value); + int (*timer_delete)(struct cobalt_extref *reftimer); /* nklocked, IRQs off. */ int (*timer_cleanup)(struct cobalt_extref *reftimer); /* nklocked, IRQs off. */ int (*signal_deliver)(struct cobalt_extref *refthread, struct siginfo *si, diff --git a/kernel/cobalt/posix/timer.c b/kernel/cobalt/posix/timer.c index 1c8ded4..2ea7719 100644 --- a/kernel/cobalt/posix/timer.c +++ b/kernel/cobalt/posix/timer.c @@ -207,8 +207,6 @@ unlock_and_error: static void timer_cleanup(struct cobalt_timer *timer) { - int ret; - xntimer_destroy(&timer->timerbase); list_del(&timer->link); @@ -216,7 +214,6 @@ static void timer_cleanup(struct cobalt_timer *timer) if (!list_empty(&timer->sigp.next)) list_del(&timer->sigp.next); - cobalt_call_extension(timer_cleanup, &timer->extref, ret); list_add(&timer->link, &timer_freeq); /* Favour earliest reuse. */ } @@ -224,26 +221,44 @@ static inline int timer_delete(timer_t timerid) { struct cobalt_timer *timer; + int ret = 0; spl_t s; - if ((unsigned int)timerid >= CONFIG_XENO_OPT_NRTIMERS) + if (timerid >= CONFIG_XENO_OPT_NRTIMERS) return -EINVAL; xnlock_get_irqsave(&nklock, s); - timer = &cobalt_timer_pool[(unsigned int)timerid]; + timer = cobalt_timer_pool + timerid; if (!xntimer_active_p(&timer->timerbase) || - timer->owningq != cobalt_kqueues(0)) - goto fail; + timer->owningq != cobalt_kqueues(0)) { + ret = -EINVAL; + goto out; + } - timer_cleanup(timer); + /* + * If an extension runs and actually handles the deletion, we + * should not call the timer_cleanup extension handler for + * this timer, but we shall destroy the core timer. If the + * handler returns on error, the whole deletion process is + * aborted, leaving the timer untouched. In all other cases, + * we do the core timer cleanup work, firing the timer_cleanup + * extension handler if defined. + */ + if (cobalt_call_extension(timer_delete, &timer->extref, ret) && ret < 0) + goto out; - return 0; -fail: + if (ret == 0) + cobalt_call_extension(timer_cleanup, &timer->extref, ret); + else + ret = 0; + + timer_cleanup(timer); +out: xnlock_put_irqrestore(&nklock, s); - return -EINVAL; + return ret; } static inline void @@ -332,7 +347,7 @@ timer_deliver_late(timer_t timerid) * We dropped the lock shortly, revalidate the timer handle in * case a deletion slipped in. */ - timer = &cobalt_timer_pool[(unsigned int)timerid]; + timer = cobalt_timer_pool + timerid; if (xntimer_active_p(&timer->timerbase)) cobalt_timer_handler(&timer->timerbase); @@ -398,12 +413,12 @@ timer_settime(timer_t timerid, int flags, int ret; spl_t s; - if ((unsigned int)timerid >= CONFIG_XENO_OPT_NRTIMERS) + if (timerid >= CONFIG_XENO_OPT_NRTIMERS) return -EINVAL; xnlock_get_irqsave(&nklock, s); - timer = &cobalt_timer_pool[(unsigned int)timerid]; + timer = cobalt_timer_pool + timerid; if (!xntimer_active_p(&timer->timerbase) || timer->owningq != cobalt_kqueues(0)) { @@ -464,12 +479,12 @@ static inline int timer_gettime(timer_t timerid, struct itimerspec *value) struct cobalt_timer *timer; spl_t s; - if ((unsigned int)timerid >= CONFIG_XENO_OPT_NRTIMERS) + if (timerid >= CONFIG_XENO_OPT_NRTIMERS) return -EINVAL; xnlock_get_irqsave(&nklock, s); - timer = &cobalt_timer_pool[(unsigned int)timerid]; + timer = cobalt_timer_pool + timerid; if (!xntimer_active_p(&timer->timerbase) || timer->owningq != cobalt_kqueues(0)) @@ -496,7 +511,7 @@ int cobalt_timer_create(clockid_t clock, timer_t __user *u_tm) { struct sigevent sev, *evp = NULL; - timer_t tm = 0; + timer_t timerid = 0; int ret; if (u_sev) { @@ -505,12 +520,12 @@ int cobalt_timer_create(clockid_t clock, return -EFAULT; } - ret = timer_create(clock, evp, &tm); + ret = timer_create(clock, evp, &timerid); if (ret) return ret; - if (__xn_safe_copy_to_user(u_tm, &tm, sizeof(tm))) { - cobalt_timer_delete(tm); + if (__xn_safe_copy_to_user(u_tm, &timerid, sizeof(timerid))) { + timer_delete(timerid); return -EFAULT; } @@ -559,12 +574,12 @@ int cobalt_timer_getoverrun(timer_t timerid) int overruns; spl_t s; - if ((unsigned int)timerid >= CONFIG_XENO_OPT_NRTIMERS) + if (timerid >= CONFIG_XENO_OPT_NRTIMERS) return -EINVAL; xnlock_get_irqsave(&nklock, s); - timer = &cobalt_timer_pool[(unsigned int)timerid]; + timer = cobalt_timer_pool + timerid; if (!xntimer_active_p(&timer->timerbase)) goto fail; @@ -588,7 +603,7 @@ int cobalt_timer_deliver(timer_t timerid) /* nklocked, IRQs off. */ struct cobalt_timer *timer; xnticks_t now; - timer = &cobalt_timer_pool[(unsigned int)timerid]; + timer = cobalt_timer_pool + timerid; if (!xntimer_active_p(&timer->timerbase)) /* Killed before ultimate delivery, who cares then? */ @@ -610,6 +625,7 @@ void cobalt_timerq_cleanup(struct cobalt_kqueues *q) { struct cobalt_timer *timer, *tmp; spl_t s; + int ret; xnlock_get_irqsave(&nklock, s); @@ -617,6 +633,7 @@ void cobalt_timerq_cleanup(struct cobalt_kqueues *q) goto out; list_for_each_entry_safe(timer, tmp, &q->timerq, link) { + cobalt_call_extension(timer_cleanup, &timer->extref, ret); timer_cleanup(timer); xnlock_put_irqrestore(&nklock, s); #if XENO_DEBUG(COBALT) _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git