Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/rump/net/lib/libshmif Support destroy in shmif.



details:   https://anonhg.NetBSD.org/src/rev/9f952f83e240
branches:  trunk
changeset: 758837:9f952f83e240
user:      pooka <pooka%NetBSD.org@localhost>
date:      Wed Nov 17 17:51:22 2010 +0000

description:
Support destroy in shmif.

diffstat:

 sys/rump/net/lib/libshmif/if_shmem.c |  154 ++++++++++++++++++++++++++--------
 1 files changed, 118 insertions(+), 36 deletions(-)

diffs (truncated from 335 to 300 lines):

diff -r f5a7df461d77 -r 9f952f83e240 sys/rump/net/lib/libshmif/if_shmem.c
--- a/sys/rump/net/lib/libshmif/if_shmem.c      Wed Nov 17 17:36:14 2010 +0000
+++ b/sys/rump/net/lib/libshmif/if_shmem.c      Wed Nov 17 17:51:22 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_shmem.c,v 1.31 2010/11/16 20:08:24 pooka Exp $      */
+/*     $NetBSD: if_shmem.c,v 1.32 2010/11/17 17:51:22 pooka Exp $      */
 
 /*
  * Copyright (c) 2009 Antti Kantee.  All Rights Reserved.
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_shmem.c,v 1.31 2010/11/16 20:08:24 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_shmem.c,v 1.32 2010/11/17 17:51:22 pooka Exp $");
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -81,12 +81,19 @@
        struct shmif_mem *sc_busmem;
        int sc_memfd;
        int sc_kq;
+       int sc_unit;
 
        char *sc_backfile;
        size_t sc_backfilelen;
 
        uint64_t sc_devgen;
        uint32_t sc_nextpacket;
+
+       kmutex_t sc_mtx;
+       kcondvar_t sc_cv;
+
+       struct lwp *sc_rcvl;
+       bool sc_dying;
 };
 
 static const uint32_t busversion = SHMIF_VERSION;
@@ -142,18 +149,19 @@
        struct shmif_sc *sc;
        struct ifnet *ifp;
        uint32_t randnum;
-       unsigned mynum = unit;
+       int error;
 
        randnum = arc4random();
        memcpy(&enaddr[2], &randnum, sizeof(randnum));
 
        sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
        sc->sc_memfd = -1;
+       sc->sc_unit = unit;
 
        ifp = &sc->sc_ec.ec_if;
        memcpy(sc->sc_myaddr, enaddr, sizeof(enaddr));
 
-       sprintf(ifp->if_xname, "shmif%d", mynum);
+       sprintf(ifp->if_xname, "shmif%d", unit);
        ifp->if_softc = sc;
        ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST;
        ifp->if_init = shmif_init;
@@ -162,16 +170,32 @@
        ifp->if_stop = shmif_stop;
        ifp->if_mtu = ETHERMTU;
 
+       mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NONE);
+       cv_init(&sc->sc_cv, "shmifcv");
+
        if_attach(ifp);
        ether_ifattach(ifp, enaddr);
 
        aprint_verbose("shmif%d: Ethernet address %s\n",
-           mynum, ether_sprintf(enaddr));
+           unit, ether_sprintf(enaddr));
 
        if (scp)
                *scp = sc;
 
-       return 0;
+       error = 0;
+       if (rump_threads) {
+               error = kthread_create(PRI_NONE,
+                   KTHREAD_MPSAFE | KTHREAD_JOINABLE, NULL,
+                   shmif_rcv, ifp, &sc->sc_rcvl, "shmif");
+       } else {
+               printf("WARNING: threads not enabled, shmif NOT working\n");
+       }
+
+       if (error) {
+               shmif_unclone(ifp);
+       }
+
+       return error;
 }
 
 static int
@@ -221,48 +245,56 @@
        shmif_unlockbus(sc->sc_busmem);
 
        sc->sc_kq = rumpuser_writewatchfile_setup(-1, memfd, 0, &error);
-       if (sc->sc_kq == -1)
+       if (sc->sc_kq == -1) {
+               rumpuser_unmap(sc->sc_busmem, BUSMEM_SIZE);
                return error;
+       }
 
        sc->sc_memfd = memfd;
-       return 0;
+
+       return error;
 }
 
 static void
 finibackend(struct shmif_sc *sc)
 {
-       int dummy;
+
+       if (sc->sc_backfile == NULL)
+               return;
 
-       kmem_free(sc->sc_backfile, sc->sc_backfilelen);
-       sc->sc_backfile = NULL;
-       sc->sc_backfilelen = 0;
+       if (sc->sc_backfile) {
+               kmem_free(sc->sc_backfile, sc->sc_backfilelen);
+               sc->sc_backfile = NULL;
+               sc->sc_backfilelen = 0;
+       }
 
        rumpuser_unmap(sc->sc_busmem, BUSMEM_SIZE);
-       rumpuser_close(sc->sc_memfd, &dummy);
-       rumpuser_close(sc->sc_kq, &dummy);
+       rumpuser_close(sc->sc_memfd, NULL);
+       rumpuser_close(sc->sc_kq, NULL);
+
+       sc->sc_memfd = -1;
 }
 
 int
 rump_shmif_create(const char *path, int *ifnum)
 {
        struct shmif_sc *sc;
-       int mynum, error, memfd, dummy;
+       int unit, error, memfd;
 
        memfd = rumpuser_open(path, O_RDWR | O_CREAT, &error);
        if (memfd == -1)
                return error;
 
-       mynum = vmem_xalloc(shmif_units, 1, 0, 0, 0, 0, 0,
+       unit = vmem_xalloc(shmif_units, 1, 0, 0, 0, 0, 0,
            VM_INSTANTFIT | VM_SLEEP) - 1;
 
-       if ((error = allocif(mynum, &sc)) != 0) {
+       if ((error = allocif(unit, &sc)) != 0) {
                rumpuser_close(memfd, NULL);
                return error;
        }
        error = initbackend(sc, memfd);
        if (error) {
-               rumpuser_close(memfd, &dummy);
-               /* XXX: free sc */
+               shmif_unclone(&sc->sc_ec.ec_if);
                return error;
        }
 
@@ -271,7 +303,7 @@
        strcpy(sc->sc_backfile, path);
 
        if (ifnum)
-               *ifnum = mynum;
+               *ifnum = unit;
 
        return 0;
 }
@@ -300,8 +332,32 @@
 static int
 shmif_unclone(struct ifnet *ifp)
 {
+       struct shmif_sc *sc = ifp->if_softc;
 
-       return EOPNOTSUPP;
+       shmif_stop(ifp, 1);
+       if_down(ifp);
+       finibackend(sc);
+
+       mutex_enter(&sc->sc_mtx);
+       sc->sc_dying = true;
+       cv_broadcast(&sc->sc_cv);
+       mutex_exit(&sc->sc_mtx);
+
+       if (sc->sc_rcvl)
+               kthread_join(sc->sc_rcvl);
+       sc->sc_rcvl = NULL;
+
+       vmem_xfree(shmif_units, sc->sc_unit+1, 1);
+
+       ether_ifdetach(ifp);
+       if_detach(ifp);
+
+       cv_destroy(&sc->sc_cv);
+       mutex_destroy(&sc->sc_mtx);
+
+       kmem_free(sc, sizeof(*sc));
+
+       return 0;
 }
 
 static int
@@ -312,15 +368,17 @@
 
        if (sc->sc_memfd == -1)
                return ENXIO;
-
-       if (rump_threads) {
-               error = kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL,
-                   shmif_rcv, ifp, NULL, "shmif");
-       } else {
-               printf("WARNING: threads not enabled, shmif NOT working\n");
-       }
+       KASSERT(sc->sc_busmem);
 
        ifp->if_flags |= IFF_RUNNING;
+
+       mutex_enter(&sc->sc_mtx);
+       sc->sc_nextpacket = sc->sc_busmem->shm_last;
+       sc->sc_devgen = sc->sc_busmem->shm_gen;
+
+       cv_broadcast(&sc->sc_cv);
+       mutex_exit(&sc->sc_mtx);
+
        return error;
 }
 
@@ -330,7 +388,7 @@
        struct shmif_sc *sc = ifp->if_softc;
        struct ifdrv *ifd;
        char *path;
-       int s, rv, memfd, dummy;
+       int s, rv, memfd;
 
        s = splnet();
        switch (cmd) {
@@ -397,7 +455,7 @@
                rv = initbackend(sc, memfd);
                if (rv) {
                        kmem_free(path, ifd->ifd_len);
-                       rumpuser_close(memfd, &dummy);
+                       rumpuser_close(memfd, NULL);
                        break;
                }
                sc->sc_backfile = path;
@@ -415,7 +473,7 @@
        return rv;
 }
 
-/* send everything in-context */
+/* send everything in-context since it's just a matter of mem-to-mem copy */
 static void
 shmif_start(struct ifnet *ifp)
 {
@@ -479,7 +537,7 @@
 
        ifp->if_flags &= ~IFF_OACTIVE;
 
-       /* wakeup */
+       /* wakeup? */
        if (wrote)
                rumpuser_pwrite(sc->sc_memfd,
                    &busversion, sizeof(busversion), IFMEM_WAKEUP, &error);
@@ -488,8 +546,18 @@
 static void
 shmif_stop(struct ifnet *ifp, int disable)
 {
+       struct shmif_sc *sc = ifp->if_softc;
 
-       panic("%s: unimpl", __func__);
+       ifp->if_flags &= ~IFF_RUNNING;
+       membar_producer();
+
+       /*
+        * wakeup thread.  this will of course wake up all bus
+        * listeners, but that's life.
+        */
+       if (sc->sc_memfd != -1)
+               rumpuser_pwrite(sc->sc_memfd,
+                   &busversion, sizeof(busversion), IFMEM_WAKEUP, NULL);
 }
 
 
@@ -535,14 +603,22 @@
 {
        struct ifnet *ifp = arg;
        struct shmif_sc *sc = ifp->if_softc;
-       struct shmif_mem *busmem = sc->sc_busmem;
+       struct shmif_mem *busmem;
        struct mbuf *m = NULL;
        struct ether_header *eth;
        uint32_t nextpkt;
        bool wrap;
        int error;



Home | Main Index | Thread Index | Old Index