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);