svn commit: r202680 - user/luigi/ipfw3-head/sys/netinet/ipfw

Luigi Rizzo luigi at FreeBSD.org
Wed Jan 20 08:41:59 UTC 2010


Author: luigi
Date: Wed Jan 20 08:41:58 2010
New Revision: 202680
URL: http://svn.freebsd.org/changeset/base/202680

Log:
  rename locks

Modified:
  user/luigi/ipfw3-head/sys/netinet/ipfw/dummynet.txt
  user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c
  user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h
  user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dummynet.txt
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dummynet.txt	Wed Jan 20 07:36:29 2010	(r202679)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dummynet.txt	Wed Jan 20 08:41:58 2010	(r202680)
@@ -1,5 +1,6 @@
 Notes on the internal structure of dummynet (2010 version)
 by Riccardo Panicucci and Luigi Rizzo
+Work supported by the EC project ONELAB2
 
 *********
 * INDEX *
@@ -67,8 +68,10 @@ Internal structure
 Dummynet-related data is split into several data structures,
 part of them constituting the userland-kernel API, and others
 specific to the kernel.
+NOTE: for up-to-date details please look at the relevant source
+	headers (ip_dummynet.h, ip_dn_private.h, dn_sched.h)
 
-USERLAND-KERNEL API
+USERLAND-KERNEL API	(ip_dummynet.h)
 
     struct new_pipe:
 	contains data about the physical link such as
@@ -88,40 +91,38 @@ USERLAND-KERNEL API
 	buckets, queue size, plr, weight, and other scheduler-specific
 	parameters.
 
-KERNEL REPRESENTATION
+KERNEL REPRESENTATION	(ip_dn_private.h)
 
     struct new_queue
-	individual queue of packets, which are created by a
-	flowset and attached to a scheduler instance.
+	individual queue of packets, created by a flowset using
+	flow_mask and attached to a scheduler instance selected
+	through sched_mask.
 	A new_queue has a pointer to the new_fsk (which in turn counts
 	how many queues point to it), a pointer to the
-	new_sch_inst it attaches to, and is linked in a list
-	of queues attached to the new_sch_inst
+	new_sch_inst it attaches to, and is in a hash table in the
+	flowset. scheduler instances also should store queues in
+	their own containers used for scheduling (lists, trees, etc.)
 	CREATE: done on packet arrivals when a flow matches a flowset.
 	DELETE: done only when deleting the parent new_sch_inst
+		or draining memory.
 
     struct new_fsk
 	includes a new_fs; a pointer to the new_schk; a link field
-	for the list of new_fsk attached to the same scheduler;
+	for the list of new_fsk attached to the same scheduler,
+	or for the unlinked list;
 	a refcount for the number of queues pointing to it;
-	The new_fsk is in a hash table when it is attached to a
-	scheduler, or in the fsunlinked list when shutting down
-	or no scheduler is active.
+	The new_fsk is in a hash table, fshash.
 	CREATE: done on configuration commands.
-	DELETE: configuration commands mark the flowset as DN_DELETE,
-		and move it to fsunlinked. Then as queue are drained,
-		they are deleted and when the last one goes away,
-		also the flowset goes away.
+	DELETE: on configuration commands.
 
     struct new_sch_inst
 	a scheduler instance, created from a new_schk applying sched_mask.
-	Contains a delay line, a list of queues, and a reference to the
-	parent. Both new_sch_inst and its delay line can be in the
-	system_heap if they have events to be processed.
+	Contains a delay line, a reference to the parent, and scheduler-
+	specific info.  Both new_sch_inst and its delay line can be in the
+	evheap if they have events to be processed.
 	CREATE: created from a new_schk applying sched_mask
 	DELETE: configuration command delete a scheduler which in turn
-		sweeps the hash table of instances, deletes all queues
-		and then the instance.
+		sweeps the hash table of instances deleting them
 
     struct new_schk
 	includes new_sch, new_pipe, a pointer to new_profile,
@@ -153,34 +154,30 @@ KERNEL REPRESENTATION
 The following global data structures contain all
 schedulers and flowsets.
 
-- schedulerhash[x]: contains all scheduler templates in the system
-	this needs to be a hash table because we may have to do
-	a lookup upon arrival of a packet.
+- schedhash[x]: contains all scheduler templates in the system.
+	Looked up only on manual configurations, where flowsets
+	are attached to matching schedulers.
 	We have one entry per 'sched X config' command
 	(plus one for each 'pipe X config').
 
-- flowsethash[x]:   contains all flowset linked with a scheduler (or pipe).
-	we do a lookup on this for each packet.
+- fshash[x]: contains all flowsets.
+	We do a lookup on this for each packet.
 	We have one entry for each 'queue X config'
 	(plus one for each 'pipe X config').
 
 Additionally, a list that contains all unlinked flowset:
-- unlinkedflowset:  contains flowset that are not linked with any scheduler
-	flowset are put in this list when they refer to a non
-	existing scheduler or pipe.
-	We keep them out of the main hash table because we do not
-	want to send packets to those flowsets.
+- fsu:  contains flowset that are not linked with any scheduler.
+	Flowset are put in this list when they refer to a non
+	existing scheduler.
 	We don't need an efficient data structure as we never search
-	here on a packet arrival -- at most we put here a flowset
-	for which a scheduler does not exist anymore.
+	here on a packet arrivals.
 
 Scheduler instances and the delay lines associated with each scheduler
 instance need to be woken up at certain times. Because we have many
 such objects, we keep them in a priority heap (system_heap).
 
-Almost all objects in this implementation are preceded
-by a structure (struct dn_id) which makes it easier to
-identify it.
+Almost all objects in this implementation are preceded by a structure
+(struct dn_id) which makes it easier to identify them.
 
 
 Files
@@ -188,50 +185,60 @@ Files
 New dummynet is split in several files.
 Two headers, a file to implement the userland part and some files for the
 kernel side are provided.
-- ip_dummynet_s.h is the minimal header that is used to implement
+- dn_sched.h is the minimal header that is used to implement
   a scheduler
-- ip_dummynet.h is the main header, that includes the ip_dummynet_s.h and is
-  use by both kernel and user space.
+- ip_dummynet.h is the main header defining the kenrel-userland API
+- ip_dn_io.c is the main files for the kernel side of dummynet. It contains
+  main functions for processing packets, some functions exported to help
+  writing new scheduler;
+- ip_dummynet.c cointains module glue and sockopt handlers.
 - dummynet.c is the file used to implement the user side of dummynet.
   It contains the function to parsing command line, and functions to
   show the output of dummynet objects.
-- ip_dummynet.c is the main files for the kernel side of dummynet. It contains
-  main functions for processing packets, some functions exported to help
-  writing new scheduler, and the handler for the various dummynet socket
-  options.
-- ip_dummynet_config.c cointains functions to create and delete objects.
-- ip_dummynet_get.c contains functions to prepare the buffer to pass to
-  userland to show object info.
 Moreover, there are two new file (ip_dummynet_glue.c and ip_fw_glue.c) that
 are used to allow compatibility with the "ipfw" binary from FreeBSd 7.2 and
 FreeBSD 8.
 
+LOCKING
+=======
+At the moment the entire processing occurs under a single lock
+which is expected to be acquired in exclusive mode
+DN_BH_WLOCK() / DN_BH_WUNLOCK().
+
+In perspective we aim at the following:
+- the 'busy' flag, 'pending' list and all structures modified by packet
+  arrivals and departures are protected by the BH_WLOCK.
+  This is normally acquired in exclusive mode by the packet processing
+  functions for short sections of code (exception -- the timer).
+  If 'busy' is not set, we can do regular packet processing.
+  If 'busy' is set, no pieces can be accessed.
+  We must enqueue the packet on 'pending' and return immediately.
+
+- the 'busy' flag is set/cleared by long sections of code as follows:
+	UH_WLOCK(); KASSERT(busy == 0);
+	BH_WLOCK(); busy=1; BH_WUNLOCK();
+	... do processing ...
+	BH_WLOCK(); busy=0; drain_queue(pending); BH_WUNLOCK();
+	UH_WUNLOCK();
+  this normally happens when the upper half has something heavy
+  to do. The prologue and epilogue are not in the critical path.
+
+- the main containers (fshash, schedhash, ...) are protected by
+  UH_WLOCK.
+  
+	TO BE COMPLETED
 
-Packet arrival
+Packet processing
 ==============
-A packet enter in dummynet process throught the function dummynet_io().
-When a packet arrives, first it is checked the flow set number and the flowset
-is searched in the flowset list and if it isn't found the packet is dropped.
-Dummynet uses a generation number to check if pointers are valid. The
-flowset has a pointer to the scheduler that could be deleted, so in the
-flowset struct there is a value that contain a number. If this number doesn't
-match the generation number, a reconfigure routine is started to check if
-pointers are valid. The generation number is incremented when a change in
-the internal struct occurs (for example when a new object is inserted or
-deleted).
-
-At this point, the pointer to the scheduler is valid, and the scheduler
-instance is searched from all scheduler instance of the scheduler, depending
-of the sched_mask field. If a scheduler instance isn't found, a new one is
-created now.
-
-Now the enqueue() function of the scheduler is called and if the scheduler
-instance was idle the dequeue() function is called now, else it will
-be called by system later. After the dequeue(), the packet returned is moved
-in the delay line and send after a delay depending on link parameters.
-See ip_dummynet.c dummynet_io() function for more details
+A packet enters dummynet through dummynet_io(). We first lookup
+the flowset number in fshash(), then possibly use masks to determine
+queue and scheduler instance, and call the enqueue routine for the
+scheduler.
+If enqueue is successful, we may call dequeue for further processing,
+and possibly return the packet upstream. If the packet does not
+return, it will be sent later according to the scheduler.
 
-The reconfiguretion routine
+The reconfiguration routine
 ---------------------------
 The reconfigure routine is called by the system when the flowset ptr_sched_val
 number differs from the generation number. This means that a new object is

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c	Wed Jan 20 07:36:29 2010	(r202679)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c	Wed Jan 20 08:41:58 2010	(r202680)
@@ -377,7 +377,7 @@ dummynet_task(void *context, int pending
 	struct timeval t;
 	struct mq q = { NULL, NULL }; /* queue to accumulate results */
 
-	DUMMYNET_LOCK();
+	DN_BH_WLOCK();
 
 	/* Update number of lost(coalesced) ticks. */
 	tick_lost += pending - 1;
@@ -431,7 +431,7 @@ dummynet_task(void *context, int pending
 			transmit_event(&q, (struct delay_line *)p, curr_time);
 		}
 	}
-	DUMMYNET_UNLOCK();
+	DN_BH_WUNLOCK();
 	dn_reschedule();
 	if (q.head != NULL)
 		dummynet_send(q.head);
@@ -570,13 +570,22 @@ dummynet_io(struct mbuf **m0, int dir, s
 	struct new_fsk *fs = NULL;
 	struct new_sch_inst *si;
 	struct new_queue *q = NULL;	/* default */
-	dn_key now; /* save a copy of curr_time */
 
 	int fs_id = (fwa->rule.info & IPFW_INFO_MASK) +
 		((fwa->rule.info & IPFW_IS_PIPE) ? 2*DN_MAX_ID : 0);
-	DUMMYNET_LOCK();
+	DN_BH_WLOCK();
 	io_pkt++;
-	now = curr_time;
+	/* we could actually tag outside the lock, but who cares... */
+	if (tag_mbuf(m, dir, fwa))
+		goto dropit;
+	if (dn_cfg.busy) {
+		/* if the upper half is busy doing something expensive,
+		 * lets queue the packet and move forward
+		 */
+		mq_append(&dn_cfg.pending, m);
+		m = *m0 = NULL; /* consumed */
+		goto done; /* already active, nothing to do */
+	}
 	/* XXX locate_flowset could be optimised with a direct ref. */
 	fs = dn_ht_find(dn_cfg.fshash, fs_id, 0, NULL);
 	if (fs == NULL)
@@ -587,8 +596,6 @@ dummynet_io(struct mbuf **m0, int dir, s
 	si = ipdn_si_find(fs->sched, &(fwa->f_id));
 	if (si == NULL)
 		goto dropit;
-	if (tag_mbuf(m, dir, fwa))
-		goto dropit;
 	/*
 	 * If the support multiple queues, find the right one
 	 * (otherwise it will be ignored by enqueue).
@@ -616,14 +623,14 @@ dummynet_io(struct mbuf **m0, int dir, s
 	    struct new_pipe *p = &fs->sched->pipe;
 	    si->credit = dn_cfg.io_fast ? p->bandwidth : 0;
 	    if (p->burst) {
-		uint64_t burst = (now - si->idle_time) * p->bandwidth;
+		uint64_t burst = (curr_time - si->idle_time) * p->bandwidth;
 		if (burst > p->burst)
 			burst = p->burst;
 		si->credit += burst;
 	    }
 	}
 	/* pass through scheduler and delay line */
-	m = serve_sched(NULL, si, now);
+	m = serve_sched(NULL, si, curr_time);
 
 	/* optimization -- pass it back to ipfw for immediate send */
 	if (dn_cfg.io_fast && m == *m0 && (dir & PROTO_LAYER2) == 0 ) {
@@ -638,14 +645,14 @@ dummynet_io(struct mbuf **m0, int dir, s
 		*m0 = NULL;
 	}
 done:
-	DUMMYNET_UNLOCK();
+	DN_BH_WUNLOCK();
 	if (m)
 		dummynet_send(m);
 	return 0;
 
 dropit:
 	io_pkt_drop++;
-	DUMMYNET_UNLOCK();
+	DN_BH_WUNLOCK();
 	if (m)
 		FREE_PKT(m);
 	*m0 = NULL;

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h	Wed Jan 20 07:36:29 2010	(r202679)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h	Wed Jan 20 08:41:58 2010	(r202680)
@@ -38,13 +38,27 @@ MALLOC_DECLARE(M_DUMMYNET);
 #endif
 #define div64(a, b)  ((int64_t)(a) / (int64_t)(b))
 
-extern struct mtx dummynet_mtx;
-#define DUMMYNET_LOCK_INIT() \
-        mtx_init(&dummynet_mtx, "dummynet", NULL, MTX_DEF)
-#define DUMMYNET_LOCK_DESTROY() mtx_destroy(&dummynet_mtx)
-#define DUMMYNET_LOCK()         mtx_lock(&dummynet_mtx)
-#define DUMMYNET_UNLOCK()       mtx_unlock(&dummynet_mtx)
-#define DUMMYNET_LOCK_ASSERT()  mtx_assert(&dummynet_mtx, MA_OWNED)
+#define DN_LOCK_INIT() do {				\
+	mtx_init(&dn_cfg.uh_mtx, "dn_uh", NULL, MTX_DEF);	\
+	mtx_init(&dn_cfg.bh_mtx, "dn_bh", NULL, MTX_DEF);	\
+	} while (0)
+#define DUMMYNET_LOCK_DESTROY() do {			\
+	mtx_destroy(&dn_cfg.uh_mtx);			\
+	mtx_destroy(&dn_cfg.bh_mtx);			\
+	} while (0)
+#if 0 /* not used yet */
+#define DN_UH_RLOCK()		mtx_lock(&dn_cfg.uh_mtx)
+#define DN_UH_RUNLOCK()		mtx_unlock(&dn_cfg.uh_mtx)
+#define DN_UH_WLOCK()		mtx_lock(&dn_cfg.uh_mtx)
+#define DN_UH_WUNLOCK()		mtx_unlock(&dn_cfg.uh_mtx)
+#define DN_UH_LOCK_ASSERT()	mtx_assert(&dn_cfg.uh_mtx, MA_OWNED)
+#endif
+
+#define DN_BH_RLOCK()		mtx_lock(&dn_cfg.uh_mtx)
+#define DN_BH_RUNLOCK()		mtx_unlock(&dn_cfg.uh_mtx)
+#define DN_BH_WLOCK()		mtx_lock(&dn_cfg.uh_mtx)
+#define DN_BH_WUNLOCK()		mtx_unlock(&dn_cfg.uh_mtx)
+#define DN_BH_LOCK_ASSERT()	mtx_assert(&dn_cfg.uh_mtx, MA_OWNED)
 
 SLIST_HEAD(new_schk_head, new_schk);
 SLIST_HEAD(new_sch_inst_head, new_sch_inst);
@@ -110,7 +124,16 @@ struct dn_parms {
 	 */
 	int	busy;
 	struct	mq	pending;
-	
+
+	/* uh_mtx arbitrates between system calls and also
+	 * protects fshash, schedhash and fsunlinked.
+	 * These structures are readonly for the lower half.
+	 */
+	struct mtx uh_mtx;
+	/* bh_mtx protects all other structures which may be
+	 * modified upon packet arrivals
+	 */
+	struct mtx bh_mtx;
 };
 
 /*

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c	Wed Jan 20 07:36:29 2010	(r202679)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c	Wed Jan 20 08:41:58 2010	(r202680)
@@ -586,7 +586,7 @@ delete_fs(int i, int locked)
 	int err = 0;
 
 	if (!locked)
-		DUMMYNET_LOCK();
+		DN_BH_WLOCK();
 	fs = dn_ht_find(dn_cfg.fshash, i, DNHT_REMOVE, NULL);
 	printf("%s fs %d found %p\n", __FUNCTION__, i, fs);
 	if (fs) {
@@ -595,7 +595,7 @@ delete_fs(int i, int locked)
 	} else
 		err = EINVAL;
 	if (!locked)
-		DUMMYNET_UNLOCK();
+		DN_BH_WUNLOCK();
 	return err;
 }
 
@@ -862,12 +862,12 @@ config_pipe(struct new_pipe *p, struct d
 	/* Scale burst size: bytes -> bits * hz */
 	p->burst *= 8 * hz;
 
-	DUMMYNET_LOCK();
+	DN_BH_WLOCK();
 	/* do it twice, base pipe and FIFO pipe */
 	for (; i < 2*DN_MAX_ID; i += DN_MAX_ID) {
 	    struct new_schk *s = locate_scheduler(i);
 	    if (s == NULL) {
-		DUMMYNET_UNLOCK();
+		DN_BH_WUNLOCK();
 		printf("%s sched %d not found\n", __FUNCTION__, i);
 		return EINVAL;
 	    }
@@ -880,7 +880,7 @@ config_pipe(struct new_pipe *p, struct d
 	    schk_reset_credit(s);
 	}
 	dn_cfg.id++;
-	DUMMYNET_UNLOCK();
+	DN_BH_WUNLOCK();
 	return 0;
 }
 
@@ -921,7 +921,7 @@ config_fs(struct new_fs *nfs, struct dn_
 		nfs->buckets = 1;	/* we only need 1 */
 	}
 	if (!locked)
-		DUMMYNET_LOCK();
+		DN_BH_WLOCK();
 	do { /* exit with break when done */
 	    struct new_schk *s;
 
@@ -956,7 +956,7 @@ config_fs(struct new_fs *nfs, struct dn_
 		fsk_attach(fs, s);
 	} while (0);
 	if (!locked)
-		DUMMYNET_UNLOCK();
+		DN_BH_WUNLOCK();
 	return fs;
 }
 
@@ -986,26 +986,33 @@ config_sched(struct new_sch *_nsch, stru
 		return EINVAL;
 	/* XXX other sanity checks */
 	bzero(&p, sizeof(0));
-	DUMMYNET_LOCK();
+	DN_BH_WLOCK();
 again: /* run twice, for wfq and fifo */
 	a.fp = find_sched_type(a.sch->oid.subtype, a.sch->type);
-	if (a.fp == NULL) {
-		DUMMYNET_UNLOCK();
-		printf("invalid scheduler type %s %d\n",
-			a.sch->type, a.sch->oid.subtype);
-		return EINVAL;
+	if (a.fp != NULL) {
+		a.sch->oid.subtype = a.fp->type;
+		s = dn_ht_find(dn_cfg.schedhash, i, DNHT_INSERT, &a);
+	} else {
+		/* accept missing type if sched already exists */
+		s = dn_ht_find(dn_cfg.schedhash, i, 0, &a);
+		if (s == NULL) {
+			DN_BH_WUNLOCK();
+			printf("invalid scheduler type %s %d\n",
+				a.sch->type, a.sch->oid.subtype);
+			return EINVAL;
+		}
+		a.fp = s->fp;
+		a.sch->oid.subtype = a.fp->type;
 	}
-	a.sch->oid.subtype = a.fp->type;
-	s = dn_ht_find(dn_cfg.schedhash, i, DNHT_INSERT, &a);
 	printf("%s start i %d ty %s -> %s\n",
 		__FUNCTION__, i, a.sch->type,
 			s ? (s->fp?"old":"new"):"none");
 	if (s == NULL) {
-		DUMMYNET_UNLOCK();
+		DN_BH_WUNLOCK();
 		printf("cannot allocate scheduler\n");
 		return ENOMEM;
 	}
-	/* preserve existing pipe if any */
+	/* restore existing pipe if any */
 	if (p.pipe_nr)
 		s->pipe = p;
 	p.pipe_nr = 0;
@@ -1016,12 +1023,12 @@ again: /* run twice, for wfq and fifo */
 	} else if (s->fp != a.fp ||
 			bcmp(a.sch, &s->sch, sizeof(*a.sch)) ) {
 		/* already existing. */
-		/* Detach flowsets, preserve pipe&queues. */
 		printf("sched %d type changed from %s to %s\n",
 			i, s->fp->name, a.fp->name);
-		p = s->pipe;
+		p = s->pipe;	/* preserve pipe */
 		/* remove from the hash */
 		dn_ht_find(dn_cfg.schedhash, i, DNHT_REMOVE, NULL);
+		/* Detach flowsets, preserve queues. */
 		schk_delete_cb(s, NULL);
 		printf("schk_delete_cb done\n");
 		goto again;
@@ -1057,7 +1064,7 @@ again: /* run twice, for wfq and fifo */
 		a.sch->oid.subtype = DN_SCHED_FIFO;
 		goto again;
 	}
-	DUMMYNET_UNLOCK();
+	DN_BH_WUNLOCK();
 	printf("%s end\n", __FUNCTION__);
 	return 0;
 }
@@ -1079,11 +1086,11 @@ config_profile(struct new_profile *pf, s
 	if (i <= 0 || i >= DN_MAX_ID)
 		return EINVAL;
 	/* XXX other sanity checks */
-	DUMMYNET_LOCK();
+	DN_BH_WLOCK();
 	s = locate_scheduler(i);
 
 	if (s == NULL) {
-		DUMMYNET_UNLOCK();
+		DN_BH_WUNLOCK();
 		printf("%s: no scheduler %d\n", __FUNCTION__, i);
 		return EINVAL;
 	}
@@ -1107,7 +1114,7 @@ config_profile(struct new_profile *pf, s
 			s->profile = malloc(pf->oid.len,
 			    M_DUMMYNET, M_NOWAIT | M_ZERO);
 		if (s->profile == NULL) {
-			DUMMYNET_UNLOCK();
+			DN_BH_WUNLOCK();
 			printf("%s: no memory\n", __FUNCTION__);
 			return ENOMEM;
 		}
@@ -1118,7 +1125,7 @@ config_profile(struct new_profile *pf, s
 		bcopy(pf, s->profile, pf->oid.len);
 		s->profile->oid.len = olen;
 	}
-	DUMMYNET_UNLOCK();
+	DN_BH_WUNLOCK();
 	return 0;
 }
 
@@ -1176,10 +1183,10 @@ do_config(void *p, int l)
 			switch (o->subtype) {
 			case DN_PIPE:
 				/* delete base and derived schedulers */
-				DUMMYNET_LOCK();
+				DN_BH_WLOCK();
 				err = delete_schk(o->id);
 				err2 = delete_schk(o->id + DN_MAX_ID);
-				DUMMYNET_UNLOCK();
+				DN_BH_WUNLOCK();
 				if (!err)
 					err = err2;
 				break;
@@ -1198,9 +1205,9 @@ do_config(void *p, int l)
 			break;
 
 		case DN_CMD_FLUSH:
-			DUMMYNET_LOCK();
+			DN_BH_WLOCK();
 			dummynet_flush();
-			DUMMYNET_UNLOCK();
+			DN_BH_WUNLOCK();
 			break;
 		case DN_TEXT:	/* store argument the next block */
 			prev = NULL;
@@ -1284,17 +1291,17 @@ dummynet_get(struct sockopt *sopt)
 	 * Try a few times then give up.
 	 */
 	for (have = 0, i = 0; i < 10; i++) {
-		DUMMYNET_LOCK();
+		DN_BH_WLOCK();
 		need = compute_space(&cmd, &to_copy);
 		if (need < 0) {
-			DUMMYNET_UNLOCK();
+			DN_BH_WUNLOCK();
 			return EINVAL;
 		}
 		need += sizeof(cmd);
 		cmd.id = need;
 		if (have >= need)
 			break;
-		DUMMYNET_UNLOCK();
+		DN_BH_WUNLOCK();
 		if (start)
 			free(start, M_DUMMYNET);
 		buf = NULL;
@@ -1319,17 +1326,19 @@ dummynet_get(struct sockopt *sopt)
 		a.end = end;
 		a.flags = to_copy;
 		a.extra = 0;
-		printf("copy schedulers %d)\n",
+		printf("copy schedulers (%d : %d)\n",
+			dn_cfg.schk_count,
 			dn_ht_entries(dn_cfg.schedhash));
 		a.type = DN_SCH;
 		dn_ht_scan(dn_cfg.schedhash, copy_data_helper, &a);
-		printf("copy unlinked flowsets %d\n",
+		printf("copy unlinked flowsets (%d : %d)\n",
+			dn_cfg.fsk_count,
 			dn_ht_entries(dn_cfg.fshash));
 		a.type = DN_FS;
 		a.extra = 1;
 		dn_ht_scan(dn_cfg.fshash, copy_data_helper, &a);
 	}
-	DUMMYNET_UNLOCK();
+	DN_BH_WUNLOCK();
 	error = sooptcopyout(sopt, start, buf - start);
 	free(start, M_DUMMYNET);
 	return error;
@@ -1420,7 +1429,7 @@ ip_dn_init(void)
 	SLIST_INIT(&dn_cfg.fsu);
 	SLIST_INIT(&dn_cfg.schedlist);
 
-	DUMMYNET_LOCK_INIT();
+	DN_LOCK_INIT();
 	ip_dn_ctl_ptr = ip_dn_ctl;
 	ip_dn_io_ptr = dummynet_io;
 
@@ -1440,13 +1449,13 @@ ip_dn_init(void)
 static void
 ip_dn_destroy(void)
 {
-	DUMMYNET_LOCK();
+	DN_BH_WLOCK();
 	ip_dn_ctl_ptr = NULL;
 	ip_dn_io_ptr = NULL;
 
 	callout_stop(&dn_timeout);
 	dummynet_flush();
-	DUMMYNET_UNLOCK();
+	DN_BH_WUNLOCK();
 	taskqueue_drain(dn_tq, &dn_task);
 	taskqueue_free(dn_tq);
 
@@ -1454,7 +1463,7 @@ ip_dn_destroy(void)
 	dn_ht_free(dn_cfg.fshash, 0);
 	heap_free(&dn_cfg.evheap);
 
-	DUMMYNET_LOCK_DESTROY();
+	DN_LOCK_DESTROY();
 }
 #endif /* KLD_MODULE */
 
@@ -1503,7 +1512,7 @@ load_dn_sched(struct dn_sched *d)
 	}
 
 	/* Search if scheduler already exists */
-	DUMMYNET_LOCK();
+	DN_BH_WLOCK();
 	SLIST_FOREACH(s, &dn_cfg.schedlist, next) {
 		if (strcmp(s->name, d->name) == 0) {
 			printf("%s %s already loaded\n", __FUNCTION__, d->name);
@@ -1512,7 +1521,7 @@ load_dn_sched(struct dn_sched *d)
 	}
 	if (s == NULL)
 		SLIST_INSERT_HEAD(&dn_cfg.schedlist, d, next);
-	DUMMYNET_UNLOCK();
+	DN_BH_WUNLOCK();
 	printf("dn_sched %s %sloaded\n", d->name, s ? "not ":"");
 	return s ? 1 : 0;
 }
@@ -1525,7 +1534,7 @@ unload_dn_sched(struct dn_sched *s)
 
 	printf("%s %s called\n", __FUNCTION__, s->name);
 
-	DUMMYNET_LOCK();
+	DN_BH_WLOCK();
 	SLIST_FOREACH_SAFE(r, &dn_cfg.schedlist, next, tmp) {
 		if (strcmp(s->name, r->name) != 0)
 			continue;
@@ -1535,7 +1544,7 @@ unload_dn_sched(struct dn_sched *s)
 			SLIST_REMOVE(&dn_cfg.schedlist, r, dn_sched, next);
 		break;
 	}
-	DUMMYNET_UNLOCK();
+	DN_BH_WUNLOCK();
 	printf("dn_sched %s %sunloaded\n", s->name, err ? "not ":"");
 	return err;
 }


More information about the svn-src-user mailing list