mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-01 06:55:30 +00:00
Create per-thread task and memory context for zonemgr
Previously, the zonemgr created 1 task per 100 zones and 1 memory context per 1000 zones (with minimum 10 tasks and 2 memory contexts) to reduce the contention between threads. Instead of reducing the contention by having many resources, create a per-nm_thread memory context, loadtask and zonetask and spread the zones between just per-thread resources. Note: this commit alone does decrease performance when loading the zone by couple seconds (in case of 1M zone) and thus there's more work in this whole MR fixing the performance.
This commit is contained in:
@@ -90,7 +90,6 @@ libisc_la_HEADERS = \
|
||||
include/isc/symtab.h \
|
||||
include/isc/syslog.h \
|
||||
include/isc/task.h \
|
||||
include/isc/taskpool.h \
|
||||
include/isc/thread.h \
|
||||
include/isc/time.h \
|
||||
include/isc/timer.h \
|
||||
@@ -191,7 +190,6 @@ libisc_la_SOURCES = \
|
||||
syslog.c \
|
||||
task.c \
|
||||
task_p.h \
|
||||
taskpool.c \
|
||||
thread.c \
|
||||
time.c \
|
||||
timer.c \
|
||||
|
@@ -84,45 +84,7 @@ void *
|
||||
isc_pool_get(isc_pool_t *pool);
|
||||
/*%<
|
||||
* Returns a pointer to an object from the pool. Currently the object
|
||||
* is chosen from the pool at random. (This may be changed in the future
|
||||
* to something that guaratees balance.)
|
||||
*/
|
||||
|
||||
int
|
||||
isc_pool_count(isc_pool_t *pool);
|
||||
/*%<
|
||||
* Returns the number of objcts in the pool 'pool'.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_pool_expand(isc_pool_t **sourcep, unsigned int count, isc_pool_t **targetp);
|
||||
|
||||
/*%<
|
||||
* If 'size' is larger than the number of objects in the pool pointed to by
|
||||
* 'sourcep', then a new pool of size 'count' is allocated, the existing
|
||||
* objects are copied into it, additional ones created to bring the
|
||||
* total number up to 'count', and the resulting pool is attached to
|
||||
* 'targetp'.
|
||||
*
|
||||
* If 'count' is less than or equal to the number of objects in 'source', then
|
||||
* 'sourcep' is attached to 'targetp' without any other action being taken.
|
||||
*
|
||||
* In either case, 'sourcep' is detached.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
* \li 'sourcep' is not NULL and '*source' is not NULL
|
||||
* \li 'targetp' is not NULL and '*source' is NULL
|
||||
*
|
||||
* Ensures:
|
||||
*
|
||||
* \li On success, '*targetp' points to a valid task pool.
|
||||
* \li On success, '*sourcep' points to NULL.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* \li #ISC_R_SUCCESS
|
||||
* \li #ISC_R_NOMEMORY
|
||||
* is chosen from the pool at random.
|
||||
*/
|
||||
|
||||
void
|
||||
|
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/*****
|
||||
***** Module Info
|
||||
*****/
|
||||
|
||||
/*! \file isc/taskpool.h
|
||||
* \brief A task pool is a mechanism for sharing a small number of tasks
|
||||
* among a large number of objects such that each object is
|
||||
* assigned a unique task, but each task may be shared by several
|
||||
* objects.
|
||||
*
|
||||
* Task pools are used to let objects that can exist in large
|
||||
* numbers (e.g., zones) use tasks for synchronization without
|
||||
* the memory overhead and unfair scheduling competition that
|
||||
* could result from creating a separate task for each object.
|
||||
*/
|
||||
|
||||
/***
|
||||
*** Imports.
|
||||
***/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <isc/lang.h>
|
||||
#include <isc/task.h>
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
/*****
|
||||
***** Types.
|
||||
*****/
|
||||
|
||||
typedef struct isc_taskpool isc_taskpool_t;
|
||||
|
||||
/*****
|
||||
***** Functions.
|
||||
*****/
|
||||
|
||||
isc_result_t
|
||||
isc_taskpool_create(isc_taskmgr_t *tmgr, isc_mem_t *mctx, unsigned int ntasks,
|
||||
unsigned int quantum, bool priv, isc_taskpool_t **poolp);
|
||||
/*%<
|
||||
* Create a task pool of "ntasks" tasks, each with quantum
|
||||
* "quantum".
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li 'tmgr' is a valid task manager.
|
||||
*
|
||||
*\li 'mctx' is a valid memory context.
|
||||
*
|
||||
*\li poolp != NULL && *poolp == NULL
|
||||
*
|
||||
* Ensures:
|
||||
*
|
||||
*\li On success, '*taskp' points to the new task pool.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
*\li #ISC_R_SUCCESS
|
||||
*\li #ISC_R_NOMEMORY
|
||||
*\li #ISC_R_UNEXPECTED
|
||||
*/
|
||||
|
||||
void
|
||||
isc_taskpool_gettask(isc_taskpool_t *pool, isc_task_t **targetp);
|
||||
/*%<
|
||||
* Attach to a task from the pool. Currently the next task is chosen
|
||||
* from the pool at random. (This may be changed in the future to
|
||||
* something that guaratees balance.)
|
||||
*/
|
||||
|
||||
int
|
||||
isc_taskpool_size(isc_taskpool_t *pool);
|
||||
/*%<
|
||||
* Returns the number of tasks in the task pool 'pool'.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_taskpool_expand(isc_taskpool_t **sourcep, unsigned int size, bool priv,
|
||||
isc_taskpool_t **targetp);
|
||||
|
||||
/*%<
|
||||
* If 'size' is larger than the number of tasks in the pool pointed to by
|
||||
* 'sourcep', then a new taskpool of size 'size' is allocated, the existing
|
||||
* tasks from are moved into it, additional tasks are created to bring the
|
||||
* total number up to 'size', and the resulting pool is attached to
|
||||
* 'targetp'.
|
||||
*
|
||||
* If 'size' is less than or equal to the tasks in pool 'source', then
|
||||
* 'sourcep' is attached to 'targetp' without any other action being taken.
|
||||
*
|
||||
* In either case, 'sourcep' is detached.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
* \li 'sourcep' is not NULL and '*source' is not NULL
|
||||
* \li 'targetp' is not NULL and '*source' is NULL
|
||||
*
|
||||
* Ensures:
|
||||
*
|
||||
* \li On success, '*targetp' points to a valid task pool.
|
||||
* \li On success, '*sourcep' points to NULL.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* \li #ISC_R_SUCCESS
|
||||
* \li #ISC_R_NOMEMORY
|
||||
*/
|
||||
|
||||
void
|
||||
isc_taskpool_destroy(isc_taskpool_t **poolp);
|
||||
/*%<
|
||||
* Destroy a task pool. The tasks in the pool are detached but not
|
||||
* shut down.
|
||||
*
|
||||
* Requires:
|
||||
* \li '*poolp' is a valid task pool.
|
||||
*/
|
||||
|
||||
ISC_LANG_ENDDECLS
|
@@ -37,24 +37,6 @@ struct isc_pool {
|
||||
*** Functions.
|
||||
***/
|
||||
|
||||
static isc_result_t
|
||||
alloc_pool(isc_mem_t *mctx, unsigned int count, isc_pool_t **poolp) {
|
||||
isc_pool_t *pool;
|
||||
|
||||
pool = isc_mem_get(mctx, sizeof(*pool));
|
||||
pool->count = count;
|
||||
pool->free = NULL;
|
||||
pool->init = NULL;
|
||||
pool->initarg = NULL;
|
||||
pool->mctx = NULL;
|
||||
isc_mem_attach(mctx, &pool->mctx);
|
||||
pool->pool = isc_mem_get(mctx, count * sizeof(void *));
|
||||
memset(pool->pool, 0, count * sizeof(void *));
|
||||
|
||||
*poolp = pool;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_pool_create(isc_mem_t *mctx, unsigned int count,
|
||||
isc_pooldeallocator_t release, isc_poolinitializer_t init,
|
||||
@@ -66,14 +48,16 @@ isc_pool_create(isc_mem_t *mctx, unsigned int count,
|
||||
INSIST(count > 0);
|
||||
|
||||
/* Allocate the pool structure */
|
||||
result = alloc_pool(mctx, count, &pool);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
|
||||
pool->free = release;
|
||||
pool->init = init;
|
||||
pool->initarg = initarg;
|
||||
pool = isc_mem_get(mctx, sizeof(*pool));
|
||||
*pool = (isc_pool_t){
|
||||
.count = count,
|
||||
.free = release,
|
||||
.init = init,
|
||||
.initarg = initarg,
|
||||
};
|
||||
isc_mem_attach(mctx, &pool->mctx);
|
||||
pool->pool = isc_mem_get(mctx, count * sizeof(void *));
|
||||
memset(pool->pool, 0, count * sizeof(void *));
|
||||
|
||||
/* Populate the pool */
|
||||
for (i = 0; i < count; i++) {
|
||||
@@ -93,61 +77,6 @@ isc_pool_get(isc_pool_t *pool) {
|
||||
return (pool->pool[isc_random_uniform(pool->count)]);
|
||||
}
|
||||
|
||||
int
|
||||
isc_pool_count(isc_pool_t *pool) {
|
||||
REQUIRE(pool != NULL);
|
||||
return (pool->count);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_pool_expand(isc_pool_t **sourcep, unsigned int count,
|
||||
isc_pool_t **targetp) {
|
||||
isc_result_t result;
|
||||
isc_pool_t *pool;
|
||||
|
||||
REQUIRE(sourcep != NULL && *sourcep != NULL);
|
||||
REQUIRE(targetp != NULL && *targetp == NULL);
|
||||
|
||||
pool = *sourcep;
|
||||
*sourcep = NULL;
|
||||
if (count > pool->count) {
|
||||
isc_pool_t *newpool = NULL;
|
||||
unsigned int i;
|
||||
|
||||
/* Allocate a new pool structure */
|
||||
result = alloc_pool(pool->mctx, count, &newpool);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
|
||||
newpool->free = pool->free;
|
||||
newpool->init = pool->init;
|
||||
newpool->initarg = pool->initarg;
|
||||
|
||||
/* Populate the new entries */
|
||||
for (i = pool->count; i < count; i++) {
|
||||
result = newpool->init(&newpool->pool[i],
|
||||
newpool->initarg);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_pool_destroy(&newpool);
|
||||
return (result);
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy over the objects from the old pool */
|
||||
for (i = 0; i < pool->count; i++) {
|
||||
newpool->pool[i] = pool->pool[i];
|
||||
pool->pool[i] = NULL;
|
||||
}
|
||||
|
||||
isc_pool_destroy(&pool);
|
||||
pool = newpool;
|
||||
}
|
||||
|
||||
*targetp = pool;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
isc_pool_destroy(isc_pool_t **poolp) {
|
||||
unsigned int i;
|
||||
|
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <isc/mem.h>
|
||||
#include <isc/random.h>
|
||||
#include <isc/taskpool.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
/***
|
||||
*** Types.
|
||||
***/
|
||||
|
||||
struct isc_taskpool {
|
||||
isc_mem_t *mctx;
|
||||
isc_taskmgr_t *tmgr;
|
||||
unsigned int ntasks;
|
||||
unsigned int quantum;
|
||||
isc_task_t **tasks;
|
||||
};
|
||||
|
||||
/***
|
||||
*** Functions.
|
||||
***/
|
||||
|
||||
static void
|
||||
alloc_pool(isc_taskmgr_t *tmgr, isc_mem_t *mctx, unsigned int ntasks,
|
||||
unsigned int quantum, isc_taskpool_t **poolp) {
|
||||
isc_taskpool_t *pool;
|
||||
unsigned int i;
|
||||
|
||||
pool = isc_mem_get(mctx, sizeof(*pool));
|
||||
|
||||
pool->mctx = NULL;
|
||||
isc_mem_attach(mctx, &pool->mctx);
|
||||
pool->ntasks = ntasks;
|
||||
pool->quantum = quantum;
|
||||
pool->tmgr = tmgr;
|
||||
pool->tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
|
||||
for (i = 0; i < ntasks; i++) {
|
||||
pool->tasks[i] = NULL;
|
||||
}
|
||||
|
||||
*poolp = pool;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_taskpool_create(isc_taskmgr_t *tmgr, isc_mem_t *mctx, unsigned int ntasks,
|
||||
unsigned int quantum, bool priv, isc_taskpool_t **poolp) {
|
||||
unsigned int i;
|
||||
isc_taskpool_t *pool = NULL;
|
||||
|
||||
INSIST(ntasks > 0);
|
||||
|
||||
/* Allocate the pool structure */
|
||||
alloc_pool(tmgr, mctx, ntasks, quantum, &pool);
|
||||
|
||||
/* Create the tasks */
|
||||
for (i = 0; i < ntasks; i++) {
|
||||
isc_result_t result = isc_task_create_bound(tmgr, quantum,
|
||||
&pool->tasks[i], i);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_taskpool_destroy(&pool);
|
||||
return (result);
|
||||
}
|
||||
isc_task_setprivilege(pool->tasks[i], priv);
|
||||
isc_task_setname(pool->tasks[i], "taskpool", NULL);
|
||||
}
|
||||
|
||||
*poolp = pool;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
isc_taskpool_gettask(isc_taskpool_t *pool, isc_task_t **targetp) {
|
||||
isc_task_attach(pool->tasks[isc_random_uniform(pool->ntasks)], targetp);
|
||||
}
|
||||
|
||||
int
|
||||
isc_taskpool_size(isc_taskpool_t *pool) {
|
||||
REQUIRE(pool != NULL);
|
||||
return (pool->ntasks);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_taskpool_expand(isc_taskpool_t **sourcep, unsigned int size, bool priv,
|
||||
isc_taskpool_t **targetp) {
|
||||
isc_taskpool_t *pool;
|
||||
|
||||
REQUIRE(sourcep != NULL && *sourcep != NULL);
|
||||
REQUIRE(targetp != NULL && *targetp == NULL);
|
||||
|
||||
pool = *sourcep;
|
||||
*sourcep = NULL;
|
||||
if (size > pool->ntasks) {
|
||||
isc_taskpool_t *newpool = NULL;
|
||||
unsigned int i;
|
||||
|
||||
/* Allocate a new pool structure */
|
||||
alloc_pool(pool->tmgr, pool->mctx, size, pool->quantum,
|
||||
&newpool);
|
||||
|
||||
/* Copy over the tasks from the old pool */
|
||||
for (i = 0; i < pool->ntasks; i++) {
|
||||
newpool->tasks[i] = pool->tasks[i];
|
||||
pool->tasks[i] = NULL;
|
||||
}
|
||||
|
||||
/* Create new tasks */
|
||||
for (i = pool->ntasks; i < size; i++) {
|
||||
isc_result_t result =
|
||||
isc_task_create_bound(pool->tmgr, pool->quantum,
|
||||
&newpool->tasks[i], i);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
*sourcep = pool;
|
||||
isc_taskpool_destroy(&newpool);
|
||||
return (result);
|
||||
}
|
||||
isc_task_setprivilege(newpool->tasks[i], priv);
|
||||
isc_task_setname(newpool->tasks[i], "taskpool", NULL);
|
||||
}
|
||||
|
||||
isc_taskpool_destroy(&pool);
|
||||
pool = newpool;
|
||||
}
|
||||
|
||||
*targetp = pool;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
isc_taskpool_destroy(isc_taskpool_t **poolp) {
|
||||
unsigned int i;
|
||||
isc_taskpool_t *pool = *poolp;
|
||||
*poolp = NULL;
|
||||
for (i = 0; i < pool->ntasks; i++) {
|
||||
if (pool->tasks[i] != NULL) {
|
||||
isc_task_detach(&pool->tasks[i]);
|
||||
}
|
||||
}
|
||||
isc_mem_put(pool->mctx, pool->tasks,
|
||||
pool->ntasks * sizeof(isc_task_t *));
|
||||
isc_mem_putanddetach(&pool->mctx, pool, sizeof(*pool));
|
||||
}
|
@@ -42,7 +42,6 @@ check_PROGRAMS = \
|
||||
stats_test \
|
||||
symtab_test \
|
||||
task_test \
|
||||
taskpool_test \
|
||||
time_test \
|
||||
timer_test
|
||||
|
||||
|
@@ -84,57 +84,11 @@ create_pool(void **state) {
|
||||
result = isc_pool_create(test_mctx, 8, poolfree, poolinit, taskmgr,
|
||||
&pool);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_int_equal(isc_pool_count(pool), 8);
|
||||
|
||||
isc_pool_destroy(&pool);
|
||||
assert_null(pool);
|
||||
}
|
||||
|
||||
/* Resize a pool */
|
||||
static void
|
||||
expand_pool(void **state) {
|
||||
isc_result_t result;
|
||||
isc_pool_t *pool1 = NULL, *pool2 = NULL, *hold = NULL;
|
||||
|
||||
UNUSED(state);
|
||||
|
||||
result = isc_pool_create(test_mctx, 10, poolfree, poolinit, taskmgr,
|
||||
&pool1);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_int_equal(isc_pool_count(pool1), 10);
|
||||
|
||||
/* resizing to a smaller size should have no effect */
|
||||
hold = pool1;
|
||||
result = isc_pool_expand(&pool1, 5, &pool2);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_int_equal(isc_pool_count(pool2), 10);
|
||||
assert_ptr_equal(pool2, hold);
|
||||
assert_null(pool1);
|
||||
pool1 = pool2;
|
||||
pool2 = NULL;
|
||||
|
||||
/* resizing to the same size should have no effect */
|
||||
hold = pool1;
|
||||
result = isc_pool_expand(&pool1, 10, &pool2);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_int_equal(isc_pool_count(pool2), 10);
|
||||
assert_ptr_equal(pool2, hold);
|
||||
assert_null(pool1);
|
||||
pool1 = pool2;
|
||||
pool2 = NULL;
|
||||
|
||||
/* resizing to larger size should make a new pool */
|
||||
hold = pool1;
|
||||
result = isc_pool_expand(&pool1, 20, &pool2);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_int_equal(isc_pool_count(pool2), 20);
|
||||
assert_ptr_not_equal(pool2, hold);
|
||||
assert_null(pool1);
|
||||
|
||||
isc_pool_destroy(&pool2);
|
||||
assert_null(pool2);
|
||||
}
|
||||
|
||||
/* Get objects */
|
||||
static void
|
||||
get_objects(void **state) {
|
||||
@@ -148,7 +102,6 @@ get_objects(void **state) {
|
||||
result = isc_pool_create(test_mctx, 2, poolfree, poolinit, taskmgr,
|
||||
&pool);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_int_equal(isc_pool_count(pool), 2);
|
||||
|
||||
item = isc_pool_get(pool);
|
||||
assert_non_null(item);
|
||||
@@ -174,7 +127,6 @@ int
|
||||
main(void) {
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(create_pool, _setup, _teardown),
|
||||
cmocka_unit_test_setup_teardown(expand_pool, _setup, _teardown),
|
||||
cmocka_unit_test_setup_teardown(get_objects, _setup, _teardown),
|
||||
};
|
||||
|
||||
|
@@ -1,204 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
#if HAVE_CMOCKA
|
||||
|
||||
#include <sched.h> /* IWYU pragma: keep */
|
||||
#include <setjmp.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define UNIT_TESTING
|
||||
#include <cmocka.h>
|
||||
|
||||
#include <isc/task.h>
|
||||
#include <isc/taskpool.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include "isctest.h"
|
||||
|
||||
#define TASK_MAGIC ISC_MAGIC('T', 'A', 'S', 'K')
|
||||
#define VALID_TASK(t) ISC_MAGIC_VALID(t, TASK_MAGIC)
|
||||
|
||||
static int
|
||||
_setup(void **state) {
|
||||
isc_result_t result;
|
||||
|
||||
UNUSED(state);
|
||||
|
||||
result = isc_test_begin(NULL, true, 0);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
_teardown(void **state) {
|
||||
UNUSED(state);
|
||||
|
||||
isc_test_end();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Create a taskpool */
|
||||
static void
|
||||
create_pool(void **state) {
|
||||
isc_result_t result;
|
||||
isc_taskpool_t *pool = NULL;
|
||||
|
||||
UNUSED(state);
|
||||
|
||||
result = isc_taskpool_create(taskmgr, test_mctx, 8, 2, false, &pool);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_int_equal(isc_taskpool_size(pool), 8);
|
||||
|
||||
isc_taskpool_destroy(&pool);
|
||||
assert_null(pool);
|
||||
}
|
||||
|
||||
/* Resize a taskpool */
|
||||
static void
|
||||
expand_pool(void **state) {
|
||||
isc_result_t result;
|
||||
isc_taskpool_t *pool1 = NULL, *pool2 = NULL, *hold = NULL;
|
||||
|
||||
UNUSED(state);
|
||||
|
||||
result = isc_taskpool_create(taskmgr, test_mctx, 10, 2, false, &pool1);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_int_equal(isc_taskpool_size(pool1), 10);
|
||||
|
||||
/* resizing to a smaller size should have no effect */
|
||||
hold = pool1;
|
||||
result = isc_taskpool_expand(&pool1, 5, false, &pool2);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_int_equal(isc_taskpool_size(pool2), 10);
|
||||
assert_ptr_equal(pool2, hold);
|
||||
assert_null(pool1);
|
||||
pool1 = pool2;
|
||||
pool2 = NULL;
|
||||
|
||||
/* resizing to the same size should have no effect */
|
||||
hold = pool1;
|
||||
result = isc_taskpool_expand(&pool1, 10, false, &pool2);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_int_equal(isc_taskpool_size(pool2), 10);
|
||||
assert_ptr_equal(pool2, hold);
|
||||
assert_null(pool1);
|
||||
pool1 = pool2;
|
||||
pool2 = NULL;
|
||||
|
||||
/* resizing to larger size should make a new pool */
|
||||
hold = pool1;
|
||||
result = isc_taskpool_expand(&pool1, 20, false, &pool2);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_int_equal(isc_taskpool_size(pool2), 20);
|
||||
assert_ptr_not_equal(pool2, hold);
|
||||
assert_null(pool1);
|
||||
|
||||
isc_taskpool_destroy(&pool2);
|
||||
assert_null(pool2);
|
||||
}
|
||||
|
||||
/* Get tasks */
|
||||
static void
|
||||
get_tasks(void **state) {
|
||||
isc_result_t result;
|
||||
isc_taskpool_t *pool = NULL;
|
||||
isc_task_t *task1 = NULL, *task2 = NULL, *task3 = NULL;
|
||||
|
||||
UNUSED(state);
|
||||
|
||||
result = isc_taskpool_create(taskmgr, test_mctx, 2, 2, false, &pool);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_int_equal(isc_taskpool_size(pool), 2);
|
||||
|
||||
/* two tasks in pool; make sure we can access them more than twice */
|
||||
isc_taskpool_gettask(pool, &task1);
|
||||
assert_true(VALID_TASK(task1));
|
||||
|
||||
isc_taskpool_gettask(pool, &task2);
|
||||
assert_true(VALID_TASK(task2));
|
||||
|
||||
isc_taskpool_gettask(pool, &task3);
|
||||
assert_true(VALID_TASK(task3));
|
||||
|
||||
isc_task_destroy(&task1);
|
||||
isc_task_destroy(&task2);
|
||||
isc_task_destroy(&task3);
|
||||
|
||||
isc_taskpool_destroy(&pool);
|
||||
assert_null(pool);
|
||||
}
|
||||
|
||||
/* Set privileges */
|
||||
static void
|
||||
set_privilege(void **state) {
|
||||
isc_result_t result;
|
||||
isc_taskpool_t *pool = NULL;
|
||||
isc_task_t *task1 = NULL, *task2 = NULL, *task3 = NULL;
|
||||
|
||||
UNUSED(state);
|
||||
|
||||
result = isc_taskpool_create(taskmgr, test_mctx, 2, 2, true, &pool);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_int_equal(isc_taskpool_size(pool), 2);
|
||||
|
||||
isc_taskpool_gettask(pool, &task1);
|
||||
isc_taskpool_gettask(pool, &task2);
|
||||
isc_taskpool_gettask(pool, &task3);
|
||||
|
||||
assert_true(VALID_TASK(task1));
|
||||
assert_true(VALID_TASK(task2));
|
||||
assert_true(VALID_TASK(task3));
|
||||
|
||||
assert_true(isc_task_getprivilege(task1));
|
||||
assert_true(isc_task_getprivilege(task2));
|
||||
assert_true(isc_task_getprivilege(task3));
|
||||
|
||||
isc_task_destroy(&task1);
|
||||
isc_task_destroy(&task2);
|
||||
isc_task_destroy(&task3);
|
||||
|
||||
isc_taskpool_destroy(&pool);
|
||||
assert_null(pool);
|
||||
}
|
||||
|
||||
int
|
||||
main(void) {
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(create_pool, _setup, _teardown),
|
||||
cmocka_unit_test_setup_teardown(expand_pool, _setup, _teardown),
|
||||
cmocka_unit_test_setup_teardown(get_tasks, _setup, _teardown),
|
||||
cmocka_unit_test_setup_teardown(set_privilege, _setup,
|
||||
_teardown),
|
||||
};
|
||||
|
||||
return (cmocka_run_group_tests(tests, NULL, NULL));
|
||||
}
|
||||
|
||||
#else /* HAVE_CMOCKA */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main(void) {
|
||||
printf("1..0 # Skipped: cmocka not available\n");
|
||||
return (SKIPPED_TEST_EXIT_CODE);
|
||||
}
|
||||
|
||||
#endif /* if HAVE_CMOCKA */
|
Reference in New Issue
Block a user