[Xenomai-git] Philippe Gerum : cobalt/posix/sem: fix spurious wakeup on aborted wait
Module: xenomai-3 Branch: master Commit: 081cbb8b150f30a019245dfb0e2f0b92cc7f2dfd URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=081cbb8b150f30a019245dfb0e2f0b92cc7f2dfd Author: Philippe Gerum r...@xenomai.org Date: Wed Jul 29 10:13:08 2015 +0200 cobalt/posix/sem: fix spurious wakeup on aborted wait sem_wait() must not pull any waiter from the sleep queue when undoing do_trywait() upon XNBREAK. At this chance, fold a few routines to avoid unnecessary hops, improving readability too. --- kernel/cobalt/posix/sem.c | 148 + 1 file changed, 69 insertions(+), 79 deletions(-) diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c index 1c47f2a..dc7ff0d 100644 --- a/kernel/cobalt/posix/sem.c +++ b/kernel/cobalt/posix/sem.c @@ -1,5 +1,6 @@ /* * Written by Gilles Chanteperdrix gilles.chanteperd...@xenomai.org. + * Copyright (C) 2014,2015 Philippe Gerum r...@xenomai.org * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -30,6 +31,18 @@ static inline struct cobalt_resources *sem_kqueue(struct cobalt_sem *sem) return cobalt_current_resources(pshared); } +static inline int sem_check(struct cobalt_sem *sem) +{ + if (sem == NULL || sem-magic != COBALT_SEM_MAGIC) + return -EINVAL; + + if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_POSIX_SYNCHRO) + sem-resnode.scope sem-resnode.scope != sem_kqueue(sem)) + return -EPERM; + + return 0; +} + int __cobalt_sem_destroy(xnhandle_t handle) { struct cobalt_sem *sem; @@ -170,51 +183,44 @@ static int sem_destroy(struct cobalt_sem_shadow *sm) spl_t s; xnlock_get_irqsave(nklock, s); + if (sm-magic != COBALT_SEM_MAGIC) { ret = -EINVAL; - goto error; + goto fail; } sem = xnregistry_lookup(sm-handle, NULL); - if (!cobalt_obj_active(sem, COBALT_SEM_MAGIC, typeof(*sem))) { - ret = -EINVAL; - goto error; - } - - if (sem-resnode.scope sem_kqueue(sem) != sem-resnode.scope) { - ret = -EPERM; - goto error; - } + ret = sem_check(sem); + if (ret) + goto fail; if ((sem-flags SEM_NOBUSYDEL) != 0 xnsynch_pended_p(sem-synchbase)) { ret = -EBUSY; - goto error; + goto fail; } warn = sem-flags SEM_WARNDEL; cobalt_mark_deleted(sm); + xnlock_put_irqrestore(nklock, s); ret = __cobalt_sem_destroy(sem-resnode.handle); return warn ? ret : 0; - - error: - +fail: xnlock_put_irqrestore(nklock, s); return ret; } -static inline int sem_trywait_inner(struct cobalt_sem *sem) +static inline int do_trywait(struct cobalt_sem *sem) { - if (sem == NULL || sem-magic != COBALT_SEM_MAGIC) - return -EINVAL; - - if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_POSIX_SYNCHRO) - sem-resnode.scope sem-resnode.scope != sem_kqueue(sem)) - return -EPERM; + int ret; + + ret = sem_check(sem); + if (ret) + return ret; if (atomic_sub_return(1, sem-state-value) 0) return -EAGAIN; @@ -222,48 +228,6 @@ static inline int sem_trywait_inner(struct cobalt_sem *sem) return 0; } -static int sem_trywait(xnhandle_t handle) -{ - int err; - spl_t s; - - xnlock_get_irqsave(nklock, s); - err = sem_trywait_inner(xnregistry_lookup(handle, NULL)); - xnlock_put_irqrestore(nklock, s); - - return err; -} - -static int sem_post_inner(struct cobalt_sem *sem, int bcast) -{ - if (sem == NULL || sem-magic != COBALT_SEM_MAGIC) - return -EINVAL; - - if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_POSIX_SYNCHRO) - sem-resnode.scope sem-resnode.scope != sem_kqueue(sem)) - return -EPERM; - - if (atomic_read(sem-state-value) == SEM_VALUE_MAX) - return -EINVAL; - - if (!bcast) { - if (atomic_inc_return(sem-state-value) = 0) { - if (xnsynch_wakeup_one_sleeper(sem-synchbase)) - xnsched_run(); - } else if (sem-flags SEM_PULSE) - atomic_set(sem-state-value, 0); - } else { - if (atomic_read(sem-state-value) 0) { - atomic_set(sem-state-value, 0); - if (xnsynch_flush(sem-synchbase, 0) == - XNSYNCH_RESCHED) - xnsched_run(); - } - } - - return 0; -} - static int sem_wait(xnhandle_t handle) { struct cobalt_sem *sem; @@ -273,7 +237,7 @@ static int sem_wait(xnhandle_t handle) xnlock_get_irqsave(nklock, s); sem =
[Xenomai-git] Philippe Gerum : cobalt/posix/sem: fix spurious wakeup on aborted wait
Module: xenomai-3 Branch: next Commit: 081cbb8b150f30a019245dfb0e2f0b92cc7f2dfd URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=081cbb8b150f30a019245dfb0e2f0b92cc7f2dfd Author: Philippe Gerum r...@xenomai.org Date: Wed Jul 29 10:13:08 2015 +0200 cobalt/posix/sem: fix spurious wakeup on aborted wait sem_wait() must not pull any waiter from the sleep queue when undoing do_trywait() upon XNBREAK. At this chance, fold a few routines to avoid unnecessary hops, improving readability too. --- kernel/cobalt/posix/sem.c | 148 + 1 file changed, 69 insertions(+), 79 deletions(-) diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c index 1c47f2a..dc7ff0d 100644 --- a/kernel/cobalt/posix/sem.c +++ b/kernel/cobalt/posix/sem.c @@ -1,5 +1,6 @@ /* * Written by Gilles Chanteperdrix gilles.chanteperd...@xenomai.org. + * Copyright (C) 2014,2015 Philippe Gerum r...@xenomai.org * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -30,6 +31,18 @@ static inline struct cobalt_resources *sem_kqueue(struct cobalt_sem *sem) return cobalt_current_resources(pshared); } +static inline int sem_check(struct cobalt_sem *sem) +{ + if (sem == NULL || sem-magic != COBALT_SEM_MAGIC) + return -EINVAL; + + if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_POSIX_SYNCHRO) + sem-resnode.scope sem-resnode.scope != sem_kqueue(sem)) + return -EPERM; + + return 0; +} + int __cobalt_sem_destroy(xnhandle_t handle) { struct cobalt_sem *sem; @@ -170,51 +183,44 @@ static int sem_destroy(struct cobalt_sem_shadow *sm) spl_t s; xnlock_get_irqsave(nklock, s); + if (sm-magic != COBALT_SEM_MAGIC) { ret = -EINVAL; - goto error; + goto fail; } sem = xnregistry_lookup(sm-handle, NULL); - if (!cobalt_obj_active(sem, COBALT_SEM_MAGIC, typeof(*sem))) { - ret = -EINVAL; - goto error; - } - - if (sem-resnode.scope sem_kqueue(sem) != sem-resnode.scope) { - ret = -EPERM; - goto error; - } + ret = sem_check(sem); + if (ret) + goto fail; if ((sem-flags SEM_NOBUSYDEL) != 0 xnsynch_pended_p(sem-synchbase)) { ret = -EBUSY; - goto error; + goto fail; } warn = sem-flags SEM_WARNDEL; cobalt_mark_deleted(sm); + xnlock_put_irqrestore(nklock, s); ret = __cobalt_sem_destroy(sem-resnode.handle); return warn ? ret : 0; - - error: - +fail: xnlock_put_irqrestore(nklock, s); return ret; } -static inline int sem_trywait_inner(struct cobalt_sem *sem) +static inline int do_trywait(struct cobalt_sem *sem) { - if (sem == NULL || sem-magic != COBALT_SEM_MAGIC) - return -EINVAL; - - if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_POSIX_SYNCHRO) - sem-resnode.scope sem-resnode.scope != sem_kqueue(sem)) - return -EPERM; + int ret; + + ret = sem_check(sem); + if (ret) + return ret; if (atomic_sub_return(1, sem-state-value) 0) return -EAGAIN; @@ -222,48 +228,6 @@ static inline int sem_trywait_inner(struct cobalt_sem *sem) return 0; } -static int sem_trywait(xnhandle_t handle) -{ - int err; - spl_t s; - - xnlock_get_irqsave(nklock, s); - err = sem_trywait_inner(xnregistry_lookup(handle, NULL)); - xnlock_put_irqrestore(nklock, s); - - return err; -} - -static int sem_post_inner(struct cobalt_sem *sem, int bcast) -{ - if (sem == NULL || sem-magic != COBALT_SEM_MAGIC) - return -EINVAL; - - if (IS_ENABLED(CONFIG_XENO_OPT_DEBUG_POSIX_SYNCHRO) - sem-resnode.scope sem-resnode.scope != sem_kqueue(sem)) - return -EPERM; - - if (atomic_read(sem-state-value) == SEM_VALUE_MAX) - return -EINVAL; - - if (!bcast) { - if (atomic_inc_return(sem-state-value) = 0) { - if (xnsynch_wakeup_one_sleeper(sem-synchbase)) - xnsched_run(); - } else if (sem-flags SEM_PULSE) - atomic_set(sem-state-value, 0); - } else { - if (atomic_read(sem-state-value) 0) { - atomic_set(sem-state-value, 0); - if (xnsynch_flush(sem-synchbase, 0) == - XNSYNCH_RESCHED) - xnsched_run(); - } - } - - return 0; -} - static int sem_wait(xnhandle_t handle) { struct cobalt_sem *sem; @@ -273,7 +237,7 @@ static int sem_wait(xnhandle_t handle) xnlock_get_irqsave(nklock, s); sem =