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

Author: Philippe Gerum <r...@xenomai.org>
Date:   Mon Jan 11 17:41:08 2010 +0100

nucleus: rework skin reference counting

The previous implementation fell short of actually protecting against
deregistration of busy skins.

Just simplify the whole stuff by counting thread attachments (to API
modules) and process bindings (to the system skin). The
non-operational-yet state that exists between the binding to the
system skin, and the actual attachment to the API skin, is inherently
protected by the kernel returning -ENOSYS to userland, when the API
module is not reachable anymore.

---

 ksrc/nucleus/shadow.c |   74 ++++++++++++++++++------------------------------
 1 files changed, 28 insertions(+), 46 deletions(-)

diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c
index 53d5873..fa27e0c 100644
--- a/ksrc/nucleus/shadow.c
+++ b/ksrc/nucleus/shadow.c
@@ -807,14 +807,7 @@ static void xnshadow_dereference_skin(unsigned magic)
 
        for (muxid = 0; muxid < XENOMAI_MUX_NR; muxid++) {
                if (muxtable[muxid].props && muxtable[muxid].props->magic == 
magic) {
-                       if (xnarch_atomic_dec_and_test(&muxtable[0].refcnt))
-                               xnarch_atomic_dec(&muxtable[0].refcnt);
-                       if (xnarch_atomic_dec_and_test(&muxtable[muxid].refcnt))
-
-                               /* We were the last thread, decrement the 
counter,
-                                  since it was incremented by the xn_sys_bind
-                                  operation. */
-                               xnarch_atomic_dec(&muxtable[muxid].refcnt);
+                       xnarch_atomic_dec(&muxtable[muxid].refcnt);
                        if (muxtable[muxid].props->module)
                                module_put(muxtable[muxid].props->module);
 
@@ -1314,11 +1307,10 @@ int xnshadow_map(xnthread_t *thread, xncompletion_t 
__user *u_completion,
 
        for (muxid = 0; muxid < XENOMAI_MUX_NR; muxid++) {
                if (muxtable[muxid].props && muxtable[muxid].props->magic == 
magic) {
-                       xnarch_atomic_inc(&muxtable[muxid].refcnt);
-                       xnarch_atomic_inc(&muxtable[0].refcnt);
                        if (muxtable[muxid].props->module
                            && !try_module_get(muxtable[muxid].props->module))
                                return -ENOSYS;
+                       xnarch_atomic_inc(&muxtable[muxid].refcnt);
                        break;
                }
        }
@@ -1635,15 +1627,6 @@ static int xnshadow_sys_bind(struct pt_regs *regs)
 
       do_bind:
 
-       /* Increment the reference count now (actually, only the first
-          call to bind_to_interface() really increments the counter), so
-          that the interface cannot be removed under our feet. */
-
-       if (!xnarch_atomic_inc_and_test(&muxtable[muxid].refcnt))
-               xnarch_atomic_dec(&muxtable[muxid].refcnt);
-       if (!xnarch_atomic_inc_and_test(&muxtable[0].refcnt))
-               xnarch_atomic_dec(&muxtable[0].refcnt);
-
        xnlock_put_irqrestore(&nklock, s);
 
        /* Since the pod might be created by the event callback and not
@@ -1657,18 +1640,15 @@ static int xnshadow_sys_bind(struct pt_regs *regs)
        if (sys_ppd)
                goto muxid_eventcb;
 
-       sys_ppd = (xnshadow_ppd_t *) 
muxtable[0].props->eventcb(XNSHADOW_CLIENT_ATTACH,
-                                                                current);
-
+       sys_ppd = muxtable[0].props->eventcb(XNSHADOW_CLIENT_ATTACH, current);
        if (IS_ERR(sys_ppd)) {
                err = PTR_ERR(sys_ppd);
                goto fail;
        }
 
-       if (!sys_ppd)
+       if (sys_ppd == NULL)
                goto muxid_eventcb;
 
-
        sys_ppd->key.muxid = 0;
        sys_ppd->key.mm = current->mm;
 
@@ -1679,7 +1659,8 @@ static int xnshadow_sys_bind(struct pt_regs *regs)
                sys_ppd = NULL;
        }
 
-  muxid_eventcb:
+muxid_eventcb:
+
        if (!muxtable[muxid].props->eventcb)
                goto eventcb_done;
 
@@ -1691,8 +1672,7 @@ static int xnshadow_sys_bind(struct pt_regs *regs)
        if (ppd)
                goto eventcb_done;
 
-       ppd = (xnshadow_ppd_t *) 
muxtable[muxid].props->eventcb(XNSHADOW_CLIENT_ATTACH,
-                                                               current);
+       ppd = muxtable[muxid].props->eventcb(XNSHADOW_CLIENT_ATTACH, current);
 
        if (IS_ERR(ppd)) {
                err = PTR_ERR(ppd);
@@ -1739,10 +1719,6 @@ static int xnshadow_sys_bind(struct pt_regs *regs)
                        muxtable[0].props->eventcb(XNSHADOW_CLIENT_DETACH, 
sys_ppd);
                }
              fail:
-               if (!xnarch_atomic_get(&muxtable[muxid].refcnt))
-                       xnarch_atomic_dec(&muxtable[muxid].refcnt);
-               if (!xnarch_atomic_get(&muxtable[muxid].refcnt))
-                       xnarch_atomic_dec(&muxtable[0].refcnt);
                return err;
        }
 
@@ -2007,8 +1983,8 @@ static void *xnshadow_sys_event(int event, void *data)
 
        switch(event) {
        case XNSHADOW_CLIENT_ATTACH:
-               p = (struct xnsys_ppd *) xnarch_alloc_host_mem(sizeof(*p));
-               if (!p)
+               p = xnarch_alloc_host_mem(sizeof(*p));
+               if (p == NULL)
                        return ERR_PTR(-ENOMEM);
 
                err = xnheap_init_mapped(&p->sem_heap,
@@ -2020,12 +1996,13 @@ static void *xnshadow_sys_event(int event, void *data)
                }
                xnheap_set_label(&p->sem_heap,
                                 "private sem heap [%d]", current->pid);
-
+               xnarch_atomic_inc(&muxtable[0].refcnt);
                return &p->ppd;
 
        case XNSHADOW_CLIENT_DETACH:
-               p = ppd2sys((xnshadow_ppd_t *) data);
+               p = ppd2sys(data);
                xnheap_destroy_mapped(&p->sem_heap, post_ppd_release, NULL);
+               xnarch_atomic_dec(&muxtable[0].refcnt);
 
                return NULL;
        }
@@ -2640,9 +2617,10 @@ int xnshadow_register_interface(struct xnskin_props 
*props)
        int muxid;
        spl_t s;
 
-       /* We can only handle up to 256 syscalls per skin, check for over-
-          and underflow (MKL). */
-
+       /*
+        * We can only handle up to MAX_SYSENT syscalls per skin,
+        * check for over- and underflow (MKL).
+        */
        if (XENOMAI_MAX_SYSENT < props->nrcalls || 0 > props->nrcalls)
                return -EINVAL;
 
@@ -2651,16 +2629,20 @@ int xnshadow_register_interface(struct xnskin_props 
*props)
        for (muxid = 0; muxid < XENOMAI_MUX_NR; muxid++) {
                if (muxtable[muxid].props == NULL) {
                        muxtable[muxid].props = props;
-                       xnarch_atomic_set(&muxtable[muxid].refcnt, -1);
-                       xnlock_put_irqrestore(&nklock, s);
-                       xnshadow_declare_proc(muxtable + muxid);
-                       return muxid;
+                       xnarch_atomic_set(&muxtable[muxid].refcnt, 0);
+                       break;
                }
        }
 
        xnlock_put_irqrestore(&nklock, s);
 
-       return -ENOBUFS;
+       if (muxid >= XENOMAI_MUX_NR)
+               return -ENOBUFS;
+
+       xnshadow_declare_proc(muxtable + muxid);
+
+       return muxid;
+
 }
 EXPORT_SYMBOL_GPL(xnshadow_register_interface);
 
@@ -2686,7 +2668,6 @@ int xnshadow_unregister_interface(int muxid)
 
        name = muxtable[muxid].props->name;
        muxtable[muxid].props = NULL;
-       xnarch_atomic_set(&muxtable[muxid].refcnt, -1);
 
        xnlock_put_irqrestore(&nklock, s);
 
@@ -2850,9 +2831,10 @@ static int iface_read_proc(char *page,
                           off_t off, int count, int *eof, void *data)
 {
        struct xnskin_slot *iface = data;
-       int len, refcnt = xnarch_atomic_get(&iface->refcnt);
+       int len, refcnt;
 
-       len = sprintf(page, "%d\n", refcnt < 0 ? 0 : refcnt);
+       refcnt = xnarch_atomic_get(&iface->refcnt);
+       len = sprintf(page, "%d\n", refcnt);
 
        len -= off;
        if (len <= off + count)


_______________________________________________
Xenomai-git mailing list
Xenomai-git@gna.org
https://mail.gna.org/listinfo/xenomai-git

Reply via email to