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

Reply via email to