diff options
author | 2016-06-03 03:59:43 +0000 | |
---|---|---|
committer | 2016-06-03 03:59:43 +0000 | |
commit | 55c556fb60abfdd302561e2752f191adf800076f (patch) | |
tree | 5d2c02a0004b36e17a7a839ec6b98c60c028bb40 | |
parent | Add 'sshd' to the test ID as I'm about to add a similar set for ssh. (diff) | |
download | wireguard-openbsd-55c556fb60abfdd302561e2752f191adf800076f.tar.xz wireguard-openbsd-55c556fb60abfdd302561e2752f191adf800076f.zip |
defer the freeing of art tables and nodes to a task.
this will allow us to sleep in srp_finalize before freeing the
memory.
the defer is done by putting the tables and nodes on a list which
is serviced by a task. the task removes all the entries from the
list and pool_puts them.
the art_tables gc code uses at_parent as its list entry, and the
art_node gc code uses a union with the an_dst pointer. both at_parent
and an_dst are only used when theyre active as part of an art data
structure, and are not used in lookups. once the art is done with
them we can reuse these pointers safely.
ok mpi@
-rw-r--r-- | sys/net/art.c | 88 | ||||
-rw-r--r-- | sys/net/art.h | 9 |
2 files changed, 82 insertions, 15 deletions
diff --git a/sys/net/art.c b/sys/net/art.c index 4b9a5facb5c..f6f6e413d05 100644 --- a/sys/net/art.c +++ b/sys/net/art.c @@ -1,4 +1,4 @@ -/* $OpenBSD: art.c,v 1.17 2016/06/02 00:39:22 dlg Exp $ */ +/* $OpenBSD: art.c,v 1.18 2016/06/03 03:59:43 dlg Exp $ */ /* * Copyright (c) 2015 Martin Pieuchot @@ -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 *, struct art_table *); 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, struct art_table *at) 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 plen) 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; + } } diff --git a/sys/net/art.h b/sys/net/art.h index 48e172bce95..856a80bc182 100644 --- a/sys/net/art.h +++ b/sys/net/art.h @@ -1,4 +1,4 @@ -/* $OpenBSD: art.h,v 1.12 2016/04/13 08:04:14 mpi Exp $ */ +/* $OpenBSD: art.h,v 1.13 2016/06/03 03:59:43 dlg Exp $ */ /* * Copyright (c) 2015 Martin Pieuchot @@ -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); |