if we traverse art tables and nodes via srps, this allows us to
add sleeping srp_finalize calls before the pool_puts.

ok?

Index: art.c
===================================================================
RCS file: /cvs/src/sys/net/art.c,v
retrieving revision 1.17
diff -u -p -r1.17 art.c
--- art.c       2 Jun 2016 00:39:22 -0000       1.17
+++ art.c       2 Jun 2016 00:49:00 -0000
@@ -31,6 +31,7 @@
 #include <sys/systm.h>
 #include <sys/malloc.h>
 #include <sys/pool.h>
+#include <sys/task.h>
 #include <sys/socket.h>
 #endif
 
@@ -82,9 +83,20 @@ void                  art_table_ref(struct art_root *,
 int                     art_table_free(struct art_root *, struct art_table *);
 int                     art_table_walk(struct art_root *, struct art_table *,
                             int (*f)(struct art_node *, void *), void *);
+void                    art_table_gc(void *);
+void                    art_gc(void *);
 
 struct pool            an_pool, at_pool, at_heap_4_pool, at_heap_8_pool;
 
+struct art_table       *art_table_gc_list = NULL;
+struct mutex            art_table_gc_mtx = MUTEX_INITIALIZER(IPL_SOFTNET);
+struct task             art_table_gc_task =
+                            TASK_INITIALIZER(art_table_gc, NULL);
+
+struct art_node                *art_node_gc_list = NULL;
+struct mutex            art_node_gc_mtx = MUTEX_INITIALIZER(IPL_SOFTNET);
+struct task             art_node_gc_task = TASK_INITIALIZER(art_gc, NULL);
+
 void
 art_init(void)
 {
@@ -715,22 +727,46 @@ art_table_put(struct art_root *ar, struc
                ar->ar_root = NULL;
        }
 
-       switch (AT_HEAPSIZE(at->at_bits)) {
-       case AT_HEAPSIZE(4):
-               pool_put(&at_heap_4_pool, at->at_heap);
-               break;
-       case AT_HEAPSIZE(8):
-               pool_put(&at_heap_8_pool, at->at_heap);
-               break;
-       default:
-               panic("incorrect stride length %u", at->at_bits);
-       }
+       mtx_enter(&art_table_gc_mtx);
+       at->at_parent = art_table_gc_list;
+       art_table_gc_list = at;
+       mtx_leave(&art_table_gc_mtx);
 
-       pool_put(&at_pool, at);
+       task_add(systqmp, &art_table_gc_task);
 
        return (parent);
 }
 
+void
+art_table_gc(void *null)
+{
+       struct art_table *at, *next;
+
+       mtx_enter(&art_table_gc_mtx);
+       at = art_table_gc_list;
+       art_table_gc_list = NULL;
+       mtx_leave(&art_table_gc_mtx);
+
+       while (at != NULL) {
+               next = at->at_parent;
+
+               switch (AT_HEAPSIZE(at->at_bits)) {
+               case AT_HEAPSIZE(4):
+                       pool_put(&at_heap_4_pool, at->at_heap);
+                       break;
+               case AT_HEAPSIZE(8):
+                       pool_put(&at_heap_8_pool, at->at_heap);
+                       break;
+               default:
+                       panic("incorrect stride length %u", at->at_bits);
+               }
+
+               pool_put(&at_pool, at);
+
+               at = next;
+       }
+}
+
 /*
  * Substitute a node by another in the subtree whose root index is given.
  *
@@ -817,5 +853,31 @@ art_get(struct sockaddr *dst, uint8_t pl
 void
 art_put(struct art_node *an)
 {
-       pool_put(&an_pool, an);
+       KASSERT(SRPL_EMPTY_LOCKED(&an->an_rtlist));
+
+       mtx_enter(&art_node_gc_mtx);
+       an->an_gc = art_node_gc_list;
+       art_node_gc_list = an;
+       mtx_leave(&art_node_gc_mtx);
+
+       task_add(systqmp, &art_node_gc_task);
+}
+
+void
+art_gc(void *null)
+{
+       struct art_node         *an, *next;
+
+       mtx_enter(&art_node_gc_mtx);
+       an = art_node_gc_list;
+       art_node_gc_list = NULL;
+       mtx_leave(&art_node_gc_mtx);
+
+       while (an != NULL) {
+               next = an->an_gc;
+
+               pool_put(&an_pool, an);
+
+               an = next;
+       }
 }
Index: art.h
===================================================================
RCS file: /cvs/src/sys/net/art.h,v
retrieving revision 1.12
diff -u -p -r1.12 art.h
--- art.h       13 Apr 2016 08:04:14 -0000      1.12
+++ art.h       2 Jun 2016 00:49:00 -0000
@@ -44,9 +44,14 @@ struct rtentry;
  */
 struct art_node {
        SRPL_HEAD(, rtentry)     an_rtlist;     /* Route related to this node */
-       struct sockaddr         *an_dst;        /* Destination address (key) */
+       union {
+               struct sockaddr *an__dst;       /* Destination address (key) */
+               struct art_node *an__gc;        /* Entry on GC list */
+       }                        an_pointer;
        uint8_t                  an_plen;       /* Prefix length */
 };
+#define an_dst an_pointer.an__dst
+#define an_gc  an_pointer.an__gc
 
 void            art_init(void);
 struct art_root        *art_alloc(unsigned int, unsigned int, unsigned int);

Reply via email to