Module: xenomai-3
Branch: master
Commit: b9d2168c3567f86e5721a71d0046ac243a2a45a4
URL:    
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=b9d2168c3567f86e5721a71d0046ac243a2a45a4

Author: Philippe Gerum <r...@xenomai.org>
Date:   Wed Mar 18 20:59:40 2015 +0100

cobalt/posix/sem: use resource management API

---

 kernel/cobalt/posix/nsem.c    |   28 ++++-----
 kernel/cobalt/posix/process.c |    8 +--
 kernel/cobalt/posix/sem.c     |  125 ++++++++++++++++++-----------------------
 kernel/cobalt/posix/sem.h     |   13 ++---
 4 files changed, 74 insertions(+), 100 deletions(-)

diff --git a/kernel/cobalt/posix/nsem.c b/kernel/cobalt/posix/nsem.c
index 4ed2e80..0cc6860 100644
--- a/kernel/cobalt/posix/nsem.c
+++ b/kernel/cobalt/posix/nsem.c
@@ -28,15 +28,14 @@
 
 DEFINE_PRIVATE_XNLOCK(named_sem_lock);
 
-struct named_sem {
+struct cobalt_named_sem {
        struct cobalt_sem *sem;
        struct cobalt_sem_shadow __user *usem;
        unsigned int refs;
        struct xnid id;
-       struct filename *filename;
 };
 
-static struct named_sem *
+static struct cobalt_named_sem *
 sem_search(struct cobalt_process *process, xnhandle_t handle)
 {
        struct xnid *i;
@@ -45,7 +44,7 @@ sem_search(struct cobalt_process *process, xnhandle_t handle)
        if (i == NULL)
                return NULL;
 
-       return container_of(i, struct named_sem, id);
+       return container_of(i, struct cobalt_named_sem, id);
 }
 
 static struct cobalt_sem_shadow __user *
@@ -56,7 +55,7 @@ sem_open(struct cobalt_process *process,
 {
        const char *name = filename->name;
        struct cobalt_sem_shadow shadow;
-       struct named_sem *u, *v;
+       struct cobalt_named_sem *u, *v;
        struct cobalt_sem *sem;
        xnhandle_t handle;
        spl_t s;
@@ -117,6 +116,7 @@ sem_open(struct cobalt_process *process,
                        __cobalt_sem_destroy(shadow.handle);
                        return ERR_PTR(-EFAULT);
                }
+               sem->pathname = filename;
                handle = shadow.handle;
                break;
 
@@ -131,7 +131,6 @@ sem_open(struct cobalt_process *process,
        u->sem = sem;
        u->usem = ushadow;
        u->refs = 1;
-       u->filename = filename;
 
        xnlock_get_irqsave(&named_sem_lock, s);
        v = sem_search(process, handle);
@@ -141,7 +140,6 @@ sem_open(struct cobalt_process *process,
                xnlock_get_irqsave(&nklock, s);
                --sem->refs;
                xnlock_put_irqrestore(&nklock, s);
-
                putname(filename);
                xnfree(u);
                u = v;
@@ -157,7 +155,7 @@ sem_open(struct cobalt_process *process,
 
 static int sem_close(struct cobalt_process *process, xnhandle_t handle)
 {
-       struct named_sem *u;
+       struct cobalt_named_sem *u;
        spl_t s;
        int err;
 
@@ -178,7 +176,6 @@ static int sem_close(struct cobalt_process *process, 
xnhandle_t handle)
 
        __cobalt_sem_destroy(handle);
 
-       putname(u->filename);
        xnfree(u);
        return 1;
 
@@ -187,12 +184,6 @@ static int sem_close(struct cobalt_process *process, 
xnhandle_t handle)
        return err;
 }
 
-void __cobalt_sem_unlink(xnhandle_t handle)
-{
-       if (__cobalt_sem_destroy(handle) == -EBUSY)
-               xnregistry_unlink(xnregistry_key(handle));
-}
-
 struct cobalt_sem_shadow __user *
 __cobalt_sem_open(struct cobalt_sem_shadow __user *usm,
                  const char __user *u_name,
@@ -264,7 +255,8 @@ static inline int sem_unlink(const char *name)
        if (ret == -EWOULDBLOCK)
                return -ENOENT;
 
-       __cobalt_sem_unlink(handle);
+       if (__cobalt_sem_destroy(handle) == -EBUSY)
+               xnregistry_unlink(xnregistry_key(handle));
 
        return 0;
 }
@@ -289,9 +281,9 @@ COBALT_SYSCALL(sem_unlink, lostage,
 static void reclaim_named_sem(void *arg, struct xnid *i)
 {
        struct cobalt_process *process = arg;
-       struct named_sem *u;
+       struct cobalt_named_sem *u;
 
-       u = container_of(i, struct named_sem, id);
+       u = container_of(i, struct cobalt_named_sem, id);
        u->refs = 1;
        sem_close(process, xnid_key(i));
 }
diff --git a/kernel/cobalt/posix/process.c b/kernel/cobalt/posix/process.c
index f473dc1..c2d65f0 100644
--- a/kernel/cobalt/posix/process.c
+++ b/kernel/cobalt/posix/process.c
@@ -1404,14 +1404,14 @@ static void cobalt_process_detach(void *arg)
 {
        struct cobalt_process *process = arg;
 
+       cobalt_nsem_reclaim(process);
+       cobalt_timer_reclaim(process);
+       cobalt_sched_reclaim(process);
        cobalt_reclaim_resource(process, cobalt_cond_reclaim, cond);
        cobalt_reclaim_resource(process, cobalt_mutex_reclaim, mutex);
        cobalt_reclaim_resource(process, cobalt_event_reclaim, event);
        cobalt_reclaim_resource(process, cobalt_monitor_reclaim, monitor);
-       cobalt_nsem_reclaim(process);
-       cobalt_timer_reclaim(process);
-       cobalt_sem_reclaim(process);
-       cobalt_sched_reclaim(process);
+       cobalt_reclaim_resource(process, cobalt_sem_reclaim, sem);
        detach_process(process);
        /*
         * The cobalt_process descriptor release may be deferred until
diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
index 3f18a4c..e63967f 100644
--- a/kernel/cobalt/posix/sem.c
+++ b/kernel/cobalt/posix/sem.c
@@ -40,17 +40,17 @@ int __cobalt_sem_destroy(xnhandle_t handle)
        sem = xnregistry_lookup(handle, NULL);
        if (!cobalt_obj_active(sem, COBALT_SEM_MAGIC, typeof(*sem))) {
                ret = -EINVAL;
-               goto unlock_error;
+               goto fail;
        }
+
        if (--sem->refs) {
                ret = -EBUSY;
-         unlock_error:
-               xnlock_put_irqrestore(&nklock, s);
-               return ret;
+               goto fail;
        }
 
        cobalt_mark_deleted(sem);
-       list_del(&sem->link);
+       xnregistry_remove(sem->resnode.handle);
+       cobalt_del_resource(&sem->resnode);
        if (xnsynch_destroy(&sem->synchbase) == XNSYNCH_RESCHED) {
                xnsched_run();
                ret = 1;
@@ -58,13 +58,19 @@ int __cobalt_sem_destroy(xnhandle_t handle)
 
        xnlock_put_irqrestore(&nklock, s);
 
+       if (sem->pathname)
+               putname(sem->pathname);
+
        cobalt_umm_free(&cobalt_ppd_get(!!(sem->flags & SEM_PSHARED))->umm,
                        sem->state);
-       xnregistry_remove(sem->handle);
 
        xnfree(sem);
 
        return ret;
+fail:
+       xnlock_put_irqrestore(&nklock, s);
+
+       return ret;
 }
 
 struct cobalt_sem *
@@ -73,9 +79,9 @@ __cobalt_sem_init(const char *name, struct cobalt_sem_shadow 
*sm,
 {
        struct cobalt_sem_state *state;
        struct cobalt_sem *sem, *osem;
-       struct cobalt_resources *rs;
        struct cobalt_ppd *sys_ppd;
-       int ret, sflags;
+       int ret, sflags, pshared;
+       struct list_head *semq;
        spl_t s;
 
        if ((flags & SEM_PULSE) != 0 && value > 0) {
@@ -89,7 +95,8 @@ __cobalt_sem_init(const char *name, struct cobalt_sem_shadow 
*sm,
                goto out;
        }
 
-       sys_ppd = cobalt_ppd_get(!!(flags & SEM_PSHARED));
+       pshared = !!(flags & SEM_PSHARED);
+       sys_ppd = cobalt_ppd_get(pshared);
        state = cobalt_umm_alloc(&sys_ppd->umm, sizeof(*state));
        if (state == NULL) {
                ret = -EAGAIN;
@@ -98,45 +105,28 @@ __cobalt_sem_init(const char *name, struct 
cobalt_sem_shadow *sm,
 
        xnlock_get_irqsave(&nklock, s);
 
-       rs = cobalt_current_resources(!!(flags & SEM_PSHARED));
-       if (list_empty(&rs->semq))
-               goto do_init;
-
-       if (sm->magic != COBALT_SEM_MAGIC &&
-           sm->magic != COBALT_NAMED_SEM_MAGIC)
-               goto do_init;
-
-       /*
-        * Make sure we are not reinitializing a valid semaphore. As a
-        * special exception, we allow reinitializing a shared
-        * anonymous semaphore. Rationale: if the process creating
-        * such semaphore exits, we may assume that other processes
-        * sharing that semaphore won't be able to keep on running.
-        */
-       osem = xnregistry_lookup(sm->handle, NULL);
-       if (!cobalt_obj_active(osem, COBALT_SEM_MAGIC, typeof(*osem)))
-               goto do_init;
-
-       if ((flags & SEM_PSHARED) == 0 || sm->magic != COBALT_SEM_MAGIC) {
-               ret = -EBUSY;
-               goto err_lock_put;
+       semq = &cobalt_current_resources(pshared)->semq;
+       if (!list_empty(semq) &&
+           (sm->magic == COBALT_SEM_MAGIC ||
+            sm->magic == COBALT_NAMED_SEM_MAGIC)) {
+               osem = xnregistry_lookup(sm->handle, NULL);
+               if (cobalt_obj_active(osem, COBALT_SEM_MAGIC, typeof(*osem))) {
+                       ret = -EBUSY;
+                       goto err_lock_put;
+               }
        }
 
-       xnlock_put_irqrestore(&nklock, s);
-       __cobalt_sem_destroy(sm->handle);
-       xnlock_get_irqsave(&nklock, s);
-  do_init:
        if (value > (unsigned)SEM_VALUE_MAX) {
                ret = -EINVAL;
                goto err_lock_put;
        }
 
-       ret = xnregistry_enter(name ?: "", sem, &sem->handle, NULL);
+       ret = xnregistry_enter(name ?: "", sem, &sem->resnode.handle, NULL);
        if (ret < 0)
                goto err_lock_put;
 
        sem->magic = COBALT_SEM_MAGIC;
-       list_add_tail(&sem->link, &rs->semq);
+       cobalt_add_resource(&sem->resnode, sem, pshared);
        sflags = flags & SEM_FIFO ? 0 : XNSYNCH_PRIO;
        xnsynch_init(&sem->synchbase, sflags, NULL);
 
@@ -144,17 +134,18 @@ __cobalt_sem_init(const char *name, struct 
cobalt_sem_shadow *sm,
        atomic_set(&state->value, value);
        state->flags = flags;
        sem->flags = flags;
-       sem->scope = rs;
        sem->refs = name ? 2 : 1;
+       sem->pathname = NULL;
 
        sm->magic = name ? COBALT_NAMED_SEM_MAGIC : COBALT_SEM_MAGIC;
-       sm->handle = sem->handle;
+       sm->handle = sem->resnode.handle;
        sm->state_offset = cobalt_umm_offset(&sys_ppd->umm, state);
        if (flags & SEM_PSHARED)
                sm->state_offset = -sm->state_offset;
        xnlock_put_irqrestore(&nklock, s);
 
-       trace_cobalt_psem_init(name ?: "anon", sem->handle, flags, value);
+       trace_cobalt_psem_init(name ?: "anon",
+                              sem->resnode.handle, flags, value);
 
        return sem;
 
@@ -187,7 +178,7 @@ static int sem_destroy(struct cobalt_sem_shadow *sm)
                goto error;
        }
 
-       if (sem_kqueue(sem) != sem->scope) {
+       if (sem_kqueue(sem) != sem->resnode.scope) {
                ret = -EPERM;
                goto error;
        }
@@ -202,7 +193,7 @@ static int sem_destroy(struct cobalt_sem_shadow *sm)
        cobalt_mark_deleted(sm);
        xnlock_put_irqrestore(&nklock, s);
 
-       ret = __cobalt_sem_destroy(sem->handle);
+       ret = __cobalt_sem_destroy(sem->resnode.handle);
 
        return warn ? ret : 0;
 
@@ -219,7 +210,7 @@ static inline int sem_trywait_inner(struct cobalt_sem *sem)
                return -EINVAL;
 
 #if XENO_DEBUG(USER)
-       if (sem->scope != sem_kqueue(sem))
+       if (sem->resnode.scope != sem_kqueue(sem))
                return -EPERM;
 #endif
 
@@ -241,14 +232,13 @@ static int sem_trywait(xnhandle_t handle)
        return err;
 }
 
-static int sem_post_inner(struct cobalt_sem *sem,
-                         struct cobalt_resources *ownq, int bcast)
+static int sem_post_inner(struct cobalt_sem *sem, int bcast)
 {
        if (sem == NULL || sem->magic != COBALT_SEM_MAGIC)
                return -EINVAL;
 
 #if XENO_DEBUG(USER)
-       if (ownq && ownq != sem_kqueue(sem))
+       if (sem->resnode.scope && sem->resnode.scope != sem_kqueue(sem))
                return -EPERM;
 #endif
 
@@ -291,7 +281,7 @@ static int sem_wait(xnhandle_t handle)
        if (info & XNRMID) {
                ret = -EINVAL;
        } else if (info & XNBREAK) {
-               sem_post_inner(sem, sem->scope, 0);
+               sem_post_inner(sem, 0);
                ret = -EINTR;
        }
 out:
@@ -371,13 +361,13 @@ int __cobalt_sem_timedwait(struct cobalt_sem_shadow 
__user *u_sem,
 
 static int sem_post(xnhandle_t handle)
 {
-       struct cobalt_sem *sm;
+       struct cobalt_sem *sem;
        int ret;
        spl_t s;
 
        xnlock_get_irqsave(&nklock, s);
-       sm = xnregistry_lookup(handle, NULL);
-       ret = sem_post_inner(sm, sm->scope, 0);
+       sem = xnregistry_lookup(handle, NULL);
+       ret = sem_post_inner(sem, 0);
        xnlock_put_irqrestore(&nklock, s);
 
        return ret;
@@ -397,7 +387,7 @@ static int sem_getvalue(xnhandle_t handle, int *value)
                return -EINVAL;
        }
 
-       if (sem->scope != sem_kqueue(sem)) {
+       if (sem->resnode.scope != sem_kqueue(sem)) {
                xnlock_put_irqrestore(&nklock, s);
                return -EPERM;
        }
@@ -510,7 +500,7 @@ COBALT_SYSCALL(sem_destroy, current,
 COBALT_SYSCALL(sem_broadcast_np, current,
               (struct cobalt_sem_shadow __user *u_sem))
 {
-       struct cobalt_sem *sm;
+       struct cobalt_sem *sem;
        xnhandle_t handle;
        spl_t s;
        int err;
@@ -519,8 +509,8 @@ COBALT_SYSCALL(sem_broadcast_np, current,
        trace_cobalt_psem_broadcast(u_sem->handle);
 
        xnlock_get_irqsave(&nklock, s);
-       sm = xnregistry_lookup(handle, NULL);
-       err = sem_post_inner(sm, sm->scope, 1);
+       sem = xnregistry_lookup(handle, NULL);
+       err = sem_post_inner(sem, 1);
        xnlock_put_irqrestore(&nklock, s);
 
        return err;
@@ -609,24 +599,17 @@ COBALT_SYSCALL(sem_inquire, current,
        return ret ?: nrwait;
 }
 
-void cobalt_sem_reclaim(struct cobalt_process *process)
+void cobalt_sem_reclaim(struct cobalt_resnode *node, spl_t s)
 {
-       struct cobalt_resources *p = &process->resources;
-       struct cobalt_sem *sem, *tmp;
-       spl_t s;
-
-       xnlock_get_irqsave(&nklock, s);
-
-       if (list_empty(&p->semq))
-               goto out;
+       struct cobalt_sem *sem;
+       xnhandle_t handle;
+       int named, ret;
 
-       list_for_each_entry_safe(sem, tmp, &p->semq, link) {
-               xnlock_put_irqrestore(&nklock, s);
-               if (sem->flags & SEM_NAMED)
-                       __cobalt_sem_unlink(sem->handle);
-               __cobalt_sem_destroy(sem->handle);
-               xnlock_get_irqsave(&nklock, s);
-       }
-out:
+       sem = container_of(node, struct cobalt_sem, resnode);
+       named = (sem->flags & SEM_NAMED) != 0;
+       handle = node->handle;
        xnlock_put_irqrestore(&nklock, s);
+       ret = __cobalt_sem_destroy(handle);
+       if (named && ret == -EBUSY)
+               xnregistry_unlink(xnregistry_key(handle));
 }
diff --git a/kernel/cobalt/posix/sem.h b/kernel/cobalt/posix/sem.h
index 56a4da4..a95b6c4 100644
--- a/kernel/cobalt/posix/sem.h
+++ b/kernel/cobalt/posix/sem.h
@@ -23,19 +23,19 @@
 #include <cobalt/kernel/thread.h>
 #include <cobalt/kernel/registry.h>
 #include <xenomai/posix/syscall.h>
+#include <xenomai/posix/process.h>
 
 struct cobalt_process;
+struct filename;
 
 struct cobalt_sem {
        unsigned int magic;
        struct xnsynch synchbase;
-       /** semq */
-       struct list_head link;
        struct cobalt_sem_state *state;
        int flags;
-       struct cobalt_resources *scope;
-       xnhandle_t handle;
        unsigned int refs;
+       struct filename *pathname;
+       struct cobalt_resnode resnode;
 };
 
 /* Copied from Linuxthreads semaphore.h. */
@@ -70,8 +70,6 @@ int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user 
*u_sem,
 
 int __cobalt_sem_destroy(xnhandle_t handle);
 
-void __cobalt_sem_unlink(xnhandle_t handle);
-
 void cobalt_nsem_reclaim(struct cobalt_process *process);
 
 struct cobalt_sem *
@@ -121,6 +119,7 @@ COBALT_SYSCALL_DECL(sem_inquire,
                     pid_t __user *u_waitlist,
                     size_t waitsz));
 
-void cobalt_sem_reclaim(struct cobalt_process *process);
+void cobalt_sem_reclaim(struct cobalt_resnode *node,
+                       spl_t s);
 
 #endif /* !_COBALT_POSIX_SEM_H */


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to