Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 5 Jan 2010 16:49:12 +0000 (UTC)
From:      Luigi Rizzo <luigi@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r201592 - user/luigi/ipfw3-head/sys/netinet/ipfw
Message-ID:  <201001051649.o05GnCbt054721@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: luigi
Date: Tue Jan  5 16:49:12 2010
New Revision: 201592
URL: http://svn.freebsd.org/changeset/base/201592

Log:
  introduce heap_scan() to run a callback on all heap elements.

Modified:
  user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c
  user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h
  user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c	Tue Jan  5 15:54:09 2010	(r201591)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c	Tue Jan  5 16:49:12 2010	(r201592)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 1998-2002 Luigi Rizzo, Universita` di Pisa
+ * Copyright (c) 1998-2002,2010 Luigi Rizzo, Universita` di Pisa
  * All rights reserved
  *
  * Redistribution and use in source and binary forms, with or without
@@ -180,7 +180,7 @@ heap_extract(struct dn_heap *h, void *ob
 	 * reach the bottom level.
 	 */
 	// XXX why removing RESET_OFFSET increases runtime by 10% ?
-	//RESET_OFFSET(h, father);
+	RESET_OFFSET(h, father);
 	while ( (child = HEAP_LEFT(father)) <= max ) {
 		if (child != max &&
 		    DN_KEY_LT(h->p[child+1].key, h->p[child].key) )
@@ -249,17 +249,37 @@ heap_move(struct dn_heap *h, uint64_t ne
  * heapify() will reorganize data inside an array to maintain the
  * heap property. It is needed when we delete a bunch of entries.
  */
-void
+static void
 heapify(struct dn_heap *h)
 {
 	int i;
 
-	printf("%s on %p for %d elements\n",
-		__FUNCTION__, h, h->elements);
 	for (i = 0; i < h->elements; i++ )
 		heap_insert(h, i , NULL);
 }
 
+int
+heap_scan(struct dn_heap *h, int (*fn)(void *, uintptr_t),
+	uintptr_t arg)
+{
+	int i, ret, found;
+
+	for (i = found = 0 ; i < h->elements ;) {
+		ret = fn(h->p[i].object, arg);
+		if (ret & HEAP_SCAN_DEL) {
+			h->elements-- ;
+			h->p[i] = h->p[h->elements] ;
+			found++ ;
+		} else
+			i++ ;
+		if (ret & HEAP_SCAN_END)
+			break;
+	}
+	if (found)
+		heapify(h);
+	return found;
+}
+
 /*
  * cleanup the heap and free data structure
  */

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h	Tue Jan  5 15:54:09 2010	(r201591)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h	Tue Jan  5 16:49:12 2010	(r201592)
@@ -66,7 +66,20 @@ struct dn_heap {
 int     heap_init(struct dn_heap *h, int size);
 int     heap_insert (struct dn_heap *h, uint64_t key1, void *p);
 void    heap_extract(struct dn_heap *h, void *obj);
-void heapify(struct dn_heap *h);
+/* void heapify(struct dn_heap *h); */
 void heap_free(struct dn_heap *h);
+enum {
+	HEAP_SCAN_DEL = 1,
+	HEAP_SCAN_END = 2,
+};
+/*
+ * heap_scan scans the entire heap calling fn on each entry. 
+ * fn() can return a combination of HEAP_SCAN_DEL and HEAP_SCAN_END,
+ * where HEAP_SCAN_DEL means the current element must be removed,
+ * and HEAP_SCAN_END means no further entry need to be analysed.
+ * At the end, heap_scan calls heapify() if records are deleted.
+ * The function returns the number of matching elements.
+ */
+int heap_scan(struct dn_heap *, int (*)(void *, uintptr_t), uintptr_t);
 
 #endif /* _IP_DN_HEAP_H */

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c	Tue Jan  5 15:54:09 2010	(r201591)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c	Tue Jan  5 16:49:12 2010	(r201592)
@@ -521,6 +521,17 @@ ready_event(struct dn_flow_queue *q, str
 		transmit_event(p, head, tail);
 }
 
+/* callback to clean the idle heap */
+static int
+clean_fq(void *_q, uintptr_t arg)
+{
+	struct dn_flow_queue *q = _q;
+
+	q->F = 0;
+	q->S = q->F + 1;
+	return HEAP_SCAN_DEL;
+}
+
 /*
  * Called when we can transmit packets on WF2Q queues. Take pkts out of
  * the queues at their start time, and enqueue into the delay line.
@@ -627,16 +638,7 @@ ready_event_wfq(struct dn_pipe *p, struc
 		 * We can get rid of idle-heap.
 		 */
 		if (p->idle_heap->elements > 0) {
-			int i;
-
-			/* XXX do a heap_extract perhaps ? */
-			for (i = 0; i < p->idle_heap->elements; i++) {
-				struct dn_flow_queue *q;
-				
-				q = p->idle_heap->p[i].object;
-				q->F = 0;
-				q->S = q->F + 1;
-			}
+			heap_scan(p->idle_heap, clean_fq, 0);
 			p->sum = 0;
 			p->V = 0;
 			p->idle_heap->elements = 0;
@@ -1761,39 +1763,26 @@ config_pipe(struct dn_pipe *p)
  * XXX this should be moved to the heap code, as we remove entries
  * from the heap under certain conditions.
  */
+static int
+scan_remove_fs(void *_o, uintptr_t fs)
+{
+	struct dn_flow_queue *fq = _o;
+	return (fq->fs == (struct dn_flow_set *)fs) ? HEAP_SCAN_DEL : 0;
+}
+
 static void
 fs_remove_from_heap(struct dn_heap *h, struct dn_flow_set *fs)
 {
-    int i, found;
-
-    for (i = found = 0 ; i < h->elements ;) {
-	if ( ((struct dn_flow_queue *)h->p[i].object)->fs == fs) {
-	    h->elements-- ;
-	    h->p[i] = h->p[h->elements] ;
-	    found++ ;
-	} else
-	    i++ ;
-    }
-    if (found)
-	heapify(h);
+	heap_scan(h, scan_remove_fs, (uintptr_t)fs);
 }
 
 /*
  * helper function to remove a pipe from a heap (can be there at most once)
  */
-static void
-pipe_remove_from_heap(struct dn_heap *h, struct dn_pipe *p)
+static int
+scan_remove_pipe(void *_o, uintptr_t p)
 {
-	int i;
-
-	for (i=0; i < h->elements ; i++ ) {
-		if (h->p[i].object == p) { /* found it */
-			h->elements-- ;
-			h->p[i] = h->p[h->elements] ;
-			heapify(h);
-			break ;
-		}
-	}
+	return (0 == (void *)p) ? HEAP_SCAN_DEL | HEAP_SCAN_END : 0;
 }
 
 /*
@@ -1866,8 +1855,8 @@ delete_pipe(struct dn_pipe *p)
 	fs_remove_from_heap(&ready_heap, &(pipe->fs));
 	purge_pipe(pipe); /* remove all data associated to this pipe */
 	/* remove reference to here from extract_heap and wfq_ready_heap */
-	pipe_remove_from_heap(&extract_heap, pipe);
-	pipe_remove_from_heap(&wfq_ready_heap, pipe);
+	heap_scan(&extract_heap, scan_remove_pipe, (uintptr_t)pipe);
+	heap_scan(&wfq_ready_heap, scan_remove_pipe, (uintptr_t)pipe);
 	DUMMYNET_UNLOCK();
 
 	free_pipe(pipe);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001051649.o05GnCbt054721>