Module Name:    src
Committed By:   pooka
Date:           Wed Nov 17 17:51:22 UTC 2010

Modified Files:
        src/sys/rump/net/lib/libshmif: if_shmem.c

Log Message:
Support destroy in shmif.


To generate a diff of this commit:
cvs rdiff -u -r1.31 -r1.32 src/sys/rump/net/lib/libshmif/if_shmem.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/rump/net/lib/libshmif/if_shmem.c
diff -u src/sys/rump/net/lib/libshmif/if_shmem.c:1.31 src/sys/rump/net/lib/libshmif/if_shmem.c:1.32
--- src/sys/rump/net/lib/libshmif/if_shmem.c:1.31	Tue Nov 16 20:08:24 2010
+++ src/sys/rump/net/lib/libshmif/if_shmem.c	Wed Nov 17 17:51:22 2010
@@ -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;
 
-	kmem_free(sc->sc_backfile, sc->sc_backfilelen);
-	sc->sc_backfile = NULL;
-	sc->sc_backfilelen = 0;
+	if (sc->sc_backfile == NULL)
+		return;
+
+	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;
+
+	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);
 
-	return EOPNOTSUPP;
+	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;
 
-	for (;;) {
+ reup:
+	mutex_enter(&sc->sc_mtx);
+	while ((ifp->if_flags & IFF_RUNNING) == 0 && !sc->sc_dying)
+		cv_wait(&sc->sc_cv, &sc->sc_mtx);
+	mutex_exit(&sc->sc_mtx);
+
+	busmem = sc->sc_busmem;
+
+	while (ifp->if_flags & IFF_RUNNING) {
 		struct shmif_pkthdr sp;
 
 		if (m == NULL) {
@@ -566,6 +642,7 @@
 			rumpuser_writewatchfile_wait(sc->sc_kq, NULL, &error);
 			if (__predict_false(error))
 				printf("shmif_rcv: wait failed %d\n", error);
+			membar_consumer();
 			continue;
 		}
 
@@ -620,6 +697,11 @@
 			m = NULL;
 		}
 	}
+	m_freem(m);
+	m = NULL;
+
+	if (!sc->sc_dying)
+		goto reup;
 
-	panic("shmif_worker is a lazy boy %d\n", error);
+	kthread_exit(0);
 }

Reply via email to