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 #include #include +#include #include #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);