Module: xenomai-forge Branch: master Commit: d227b6fe960b65abfbd567c90e981df2391412aa URL: http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=d227b6fe960b65abfbd567c90e981df2391412aa
Author: Philippe Gerum <[email protected]> Date: Fri Nov 11 19:02:28 2011 +0100 cobalt/sem: introduce SEM_WARNDEL option to sem_init_np() When set, this modifier slightly changes the behavior of sem_destroy() to make it return a non-zero positive value in case the semaphore was pended by threads. This information may be required by some RTOS emulations (e.g. pSOS), for using Copperplate's semobj abstraction. --- include/cobalt/semaphore.h | 1 + kernel/cobalt/sem.c | 38 ++++++++++++++++++++++++++++++-------- kernel/cobalt/syscall.c | 4 ++-- lib/cobalt/semaphore.c | 4 ++-- 4 files changed, 35 insertions(+), 12 deletions(-) diff --git a/include/cobalt/semaphore.h b/include/cobalt/semaphore.h index 69a4afc..3804bcb 100644 --- a/include/cobalt/semaphore.h +++ b/include/cobalt/semaphore.h @@ -146,6 +146,7 @@ COBALT_DECL(int, sem_unlink(const char *name)); #define SEM_PULSE 0x2 #define SEM_PSHARED 0x4 #define SEM_REPORT 0x8 +#define SEM_WARNDEL 0x10 int sem_init_np(sem_t *sem, int flags, diff --git a/kernel/cobalt/sem.c b/kernel/cobalt/sem.c index 6aae150..4c69c6c 100644 --- a/kernel/cobalt/sem.c +++ b/kernel/cobalt/sem.c @@ -78,20 +78,25 @@ typedef struct cobalt_uptr { #endif /* !__XENO_SIM__ */ -static void sem_destroy_inner(cobalt_sem_t * sem, cobalt_kqueues_t *q) +static int sem_destroy_inner(cobalt_sem_t * sem, cobalt_kqueues_t *q) { + int ret = 0; spl_t s; xnlock_get_irqsave(&nklock, s); removeq(&q->semq, &sem->link); - if (xnsynch_destroy(&sem->synchbase) == XNSYNCH_RESCHED) + if (xnsynch_destroy(&sem->synchbase) == XNSYNCH_RESCHED) { xnpod_schedule(); + ret = 1; + } xnlock_put_irqrestore(&nklock, s); if (sem->flags & SEM_NAMED) xnfree(sem2named_sem(sem)); else xnfree(sem); + + return ret; } /* Called with nklock locked, irq off. */ @@ -125,6 +130,11 @@ static int do_sem_init(sem_t *sm, int flags, unsigned int value) int ret; spl_t s; + if ((flags & SEM_PULSE) != 0 && value > 0) { + ret = EINVAL; + goto error; + } + sem = xnmalloc(sizeof(cobalt_sem_t)); if (sem == NULL) { ret = ENOSPC; @@ -231,6 +241,10 @@ int sem_init(sem_t *sm, int pshared, unsigned int value) * default, sem_getvalue() returns a current value of zero for a * depleted semaphore with waiters. * + * - SEM_WARNDEL causes sem_destroy() to return a strictly positive + * value instead of zero, in case threads were pending on the + * successfully deleted semaphore. + * * @param value the semaphore initial value. * * @retval 0 on success, @@ -244,7 +258,7 @@ int sem_init(sem_t *sm, int pshared, unsigned int value) */ int sem_init_np(sem_t *sm, int flags, unsigned int value) { - if (flags & ~(SEM_FIFO|SEM_PULSE|SEM_PSHARED|SEM_REPORT)) { + if (flags & ~(SEM_FIFO|SEM_PULSE|SEM_PSHARED|SEM_REPORT|SEM_WARNDEL)) { thread_set_errno(EINVAL); return -1; } @@ -264,7 +278,11 @@ int sem_init_np(sem_t *sm, int flags, unsigned int value) * * @param sm the semaphore to be destroyed. * - * @retval 0 on success, + * @retval always 0 on success if SEM_WARNDEL was not mentioned via + * sem_init_np(). If SEM_WARNDEL was mentioned, then a strictly + * positive value is returned to warn the caller if threads were + * pending on the semaphore, or zero otherwise. + * * @retval -1 with @a errno set if: * - EINVAL, the semaphore @a sm is invalid or a named semaphore; * - EPERM, the semaphore @a sm is not process-shared and does not belong to the @@ -278,6 +296,8 @@ int sem_init_np(sem_t *sm, int flags, unsigned int value) int sem_destroy(sem_t * sm) { struct __shadow_sem *shadow = &((union __xeno_sem *)sm)->shadow_sem; + cobalt_sem_t *sem; + int warn, ret; spl_t s; xnlock_get_irqsave(&nklock, s); @@ -287,18 +307,20 @@ int sem_destroy(sem_t * sm) goto error; } - if (sem_kqueue(shadow->sem) != shadow->sem->owningq) { + sem = shadow->sem; + if (sem_kqueue(sem) != sem->owningq) { thread_set_errno(EPERM); goto error; } + warn = sem->flags & SEM_WARNDEL; cobalt_mark_deleted(shadow); - cobalt_mark_deleted(shadow->sem); + cobalt_mark_deleted(sem); xnlock_put_irqrestore(&nklock, s); - sem_destroy_inner(shadow->sem, sem_kqueue(shadow->sem)); + ret = sem_destroy_inner(sem, sem_kqueue(sem)); - return 0; + return warn ? ret : 0; error: diff --git a/kernel/cobalt/syscall.c b/kernel/cobalt/syscall.c index f9398cf..d28eec7 100644 --- a/kernel/cobalt/syscall.c +++ b/kernel/cobalt/syscall.c @@ -684,11 +684,11 @@ static int __sem_destroy(union __xeno_sem __user *u_sem) return -EFAULT; err = sem_destroy(&sm.native_sem); - if (err) + if (err < 0) return -thread_get_errno(); return __xn_safe_copy_to_user(&u_sem->shadow_sem, - &sm.shadow_sem, sizeof(u_sem->shadow_sem)); + &sm.shadow_sem, sizeof(u_sem->shadow_sem)) ?: err; } static int __sem_open(unsigned long __user *u_addr, diff --git a/lib/cobalt/semaphore.c b/lib/cobalt/semaphore.c index ceea9c3..72d0dd2 100644 --- a/lib/cobalt/semaphore.c +++ b/lib/cobalt/semaphore.c @@ -49,8 +49,8 @@ int __wrap_sem_destroy(sem_t * sem) err = -XENOMAI_SKINCALL1(__cobalt_muxid, __cobalt_sem_destroy, &_sem->shadow_sem); - if (!err) - return 0; + if (err >= 0) + return err; errno = err; _______________________________________________ Xenomai-git mailing list [email protected] https://mail.gna.org/listinfo/xenomai-git
