diff --git a/lib/isc/astack.c b/lib/isc/astack.c index d67df51181..0d494fa94b 100644 --- a/lib/isc/astack.c +++ b/lib/isc/astack.c @@ -19,65 +19,123 @@ #include #include -struct isc_astack { - isc_mem_t *mctx; +typedef struct nodes { size_t size; size_t pos; + void **nodes; +} nodes_t; + +struct isc_astack { + isc_mem_t *mctx; isc_mutex_t lock; - uintptr_t nodes[]; + size_t min_size; + size_t max_size; + nodes_t cur; + nodes_t old; }; -isc_astack_t * -isc_astack_new(isc_mem_t *mctx, size_t size) { - isc_astack_t *stack = isc_mem_get( - mctx, sizeof(isc_astack_t) + size * sizeof(uintptr_t)); +static void +nodes_new(isc_mem_t *mctx, nodes_t *cur, size_t size) { + *cur = (nodes_t){ .size = size }; - *stack = (isc_astack_t){ - .size = size, - }; + if (size > 0) { + cur->nodes = isc_mem_get(mctx, cur->size * sizeof(void *)); + memset(cur->nodes, 0, cur->size * sizeof(void *)); + } +} + +static void +nodes_free(isc_mem_t *mctx, nodes_t *cur) { + REQUIRE(cur->pos == 0); + + if (cur->size > 0) { + REQUIRE(cur->nodes != NULL); + isc_mem_put(mctx, cur->nodes, cur->size * sizeof(void *)); + } + + *cur = (nodes_t){ .size = 0 }; +} + +#define IS_POWEROF2(bits) (bits && !(bits & (bits - 1))) + +isc_astack_t * +isc_astack_new(isc_mem_t *mctx, size_t min_size, size_t max_size) { + isc_astack_t *stack = isc_mem_get(mctx, sizeof(isc_astack_t)); + + REQUIRE(IS_POWEROF2(min_size)); + REQUIRE(IS_POWEROF2(max_size)); + + *stack = (isc_astack_t){ .min_size = min_size, .max_size = max_size }; isc_mem_attach(mctx, &stack->mctx); - memset(stack->nodes, 0, size * sizeof(uintptr_t)); isc_mutex_init(&stack->lock); + + nodes_new(mctx, &stack->cur, stack->min_size); + nodes_new(mctx, &stack->old, 0); + return (stack); } bool isc_astack_trypush(isc_astack_t *stack, void *obj) { - if (!isc_mutex_trylock(&stack->lock)) { - if (stack->pos >= stack->size) { + if (isc_mutex_trylock(&stack->lock) != ISC_R_SUCCESS) { + return (false); + } + + if (stack->cur.pos >= stack->cur.size) { + if (stack->old.size > 0) { UNLOCK(&stack->lock); return (false); } - stack->nodes[stack->pos++] = (uintptr_t)obj; - UNLOCK(&stack->lock); - return (true); - } else { - return (false); + + if (stack->cur.size * 2 > stack->max_size) { + UNLOCK(&stack->lock); + return (false); + } + + stack->old = stack->cur; + nodes_new(stack->mctx, &stack->cur, stack->old.size * 2); } + + stack->cur.nodes[stack->cur.pos++] = obj; + UNLOCK(&stack->lock); + return (true); } void * isc_astack_pop(isc_astack_t *stack) { - LOCK(&stack->lock); - uintptr_t rv; - if (stack->pos == 0) { - rv = 0; + void *rv; + + if (isc_mutex_trylock(&stack->lock) != ISC_R_SUCCESS) { + return (false); + } + + if (stack->old.size > 0) { + REQUIRE(stack->old.pos > 0); + + rv = stack->old.nodes[--stack->old.pos]; + + if (stack->old.pos == 0) { + nodes_free(stack->mctx, &stack->old); + } + } else if (stack->cur.pos > 0) { + rv = stack->cur.nodes[--stack->cur.pos]; } else { - rv = stack->nodes[--stack->pos]; + rv = NULL; } UNLOCK(&stack->lock); - return ((void *)rv); + return (rv); } void isc_astack_destroy(isc_astack_t *stack) { LOCK(&stack->lock); - REQUIRE(stack->pos == 0); + REQUIRE(stack->cur.pos == 0); + REQUIRE(stack->old.size == 0); UNLOCK(&stack->lock); + nodes_free(stack->mctx, &stack->cur); + isc_mutex_destroy(&stack->lock); - isc_mem_putanddetach(&stack->mctx, stack, - sizeof(struct isc_astack) + - stack->size * sizeof(uintptr_t)); + isc_mem_putanddetach(&stack->mctx, stack, sizeof(struct isc_astack)); } diff --git a/lib/isc/include/isc/astack.h b/lib/isc/include/isc/astack.h index c85fee64d1..0f55fc45f3 100644 --- a/lib/isc/include/isc/astack.h +++ b/lib/isc/include/isc/astack.h @@ -17,9 +17,10 @@ #include isc_astack_t * -isc_astack_new(isc_mem_t *mctx, size_t size); +isc_astack_new(isc_mem_t *mctx, size_t min_size, size_t max_size); /*%< - * Allocate and initialize a new array stack of size 'size'. + * Allocate and initialize a new bounded array stack. Initially, min_size + * entries will be allocated, but would grow up to max_size entries. */ void diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index e81ad4673e..5498c22e54 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -48,8 +48,11 @@ * How many isc_nmhandles and isc_nm_uvreqs will we be * caching for reuse in a socket. */ -#define ISC_NM_HANDLES_STACK_SIZE 600 -#define ISC_NM_REQS_STACK_SIZE 600 +#define ISC_NM_HANDLES_MIN_STACK_SIZE 32 +#define ISC_NM_HANDLES_MAX_STACK_SIZE 1024 + +#define ISC_NM_REQS_MIN_STACK_SIZE 32 +#define ISC_NM_REQS_MAX_STACK_SIZE 1024 /*% * Shortcut index arrays to get access to statistics counters. @@ -1441,14 +1444,20 @@ isc___nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr, isc_nmsocket_type type, family = iface->type.sa.sa_family; - *sock = (isc_nmsocket_t){ .type = type, - .iface = *iface, - .fd = -1, - .ah_size = 32, - .inactivehandles = isc_astack_new( - mgr->mctx, ISC_NM_HANDLES_STACK_SIZE), - .inactivereqs = isc_astack_new( - mgr->mctx, ISC_NM_REQS_STACK_SIZE) }; + *sock = (isc_nmsocket_t){ + .type = type, + .iface = *iface, + .fd = -1, + .ah_size = 32, + }; + + sock->inactivehandles = isc_astack_new(mgr->mctx, + ISC_NM_HANDLES_MIN_STACK_SIZE, + ISC_NM_HANDLES_MAX_STACK_SIZE); + + sock->inactivereqs = isc_astack_new(mgr->mctx, + ISC_NM_REQS_MIN_STACK_SIZE, + ISC_NM_REQS_MAX_STACK_SIZE); #if NETMGR_TRACE sock->backtrace_size = backtrace(sock->backtrace, TRACE_SIZE);