Remove isc_task_onshutdown()
The isc_task_onshutdown() was used to post event that should be run when the task is being shutdown. This could happen explicitly in the isc_test_shutdown() call or implicitly when we detach the last reference to the task and there are no more events posted on the task. This whole task onshutdown mechanism just makes things more complicated, and it's easier to post the "shutdown" events when we are shutting down explicitly and the existing code already always knows when it should shutdown the task that's being used to execute the onshutdown events. Replace the isc_task_onshutdown() calls with explicit calls to execute the shutdown tasks.
This commit is contained in:
@@ -205,17 +205,6 @@ basic_cb(isc_task_t *task, isc_event_t *event) {
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
static void
|
||||
basic_shutdown(isc_task_t *task, isc_event_t *event) {
|
||||
UNUSED(task);
|
||||
|
||||
if (verbose) {
|
||||
print_message("# shutdown %s\n", (char *)event->ev_arg);
|
||||
}
|
||||
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
static void
|
||||
basic_tick(isc_task_t *task, isc_event_t *event) {
|
||||
UNUSED(task);
|
||||
@@ -260,15 +249,6 @@ basic(void **state) {
|
||||
result = isc_task_create(taskmgr, 0, &task4);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_task_onshutdown(task1, basic_shutdown, one);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
result = isc_task_onshutdown(task2, basic_shutdown, two);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
result = isc_task_onshutdown(task3, basic_shutdown, three);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
result = isc_task_onshutdown(task4, basic_shutdown, four);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
isc_interval_set(&interval, 1, 0);
|
||||
isc_timer_create(timermgr, task1, basic_tick, tick, &ti1);
|
||||
result = isc_timer_reset(ti1, isc_timertype_ticker, &interval, false);
|
||||
@@ -421,53 +401,39 @@ task_exclusive(void **state) {
|
||||
* Max tasks test:
|
||||
* The task system can create and execute many tasks. Tests with 10000.
|
||||
*/
|
||||
static void
|
||||
maxtask_shutdown(isc_task_t *task, isc_event_t *event) {
|
||||
UNUSED(task);
|
||||
|
||||
if (event->ev_arg != NULL) {
|
||||
isc_task_destroy((isc_task_t **)&event->ev_arg);
|
||||
static void
|
||||
maxtask_cb(isc_task_t *task, isc_event_t *event) {
|
||||
isc_result_t result;
|
||||
uintptr_t ntasks = (uintptr_t)event->ev_arg;
|
||||
|
||||
if (ntasks-- > 0) {
|
||||
task = NULL;
|
||||
|
||||
event->ev_arg = (void *)ntasks;
|
||||
|
||||
/*
|
||||
* Create a new task and forward the message.
|
||||
*/
|
||||
result = isc_task_create(taskmgr, 0, &task);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
isc_task_send(task, &event);
|
||||
isc_task_detach(&task);
|
||||
} else {
|
||||
isc_event_free(&event);
|
||||
|
||||
LOCK(&lock);
|
||||
atomic_store(&done, true);
|
||||
SIGNAL(&cv);
|
||||
UNLOCK(&lock);
|
||||
}
|
||||
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
static void
|
||||
maxtask_cb(isc_task_t *task, isc_event_t *event) {
|
||||
isc_result_t result;
|
||||
|
||||
if (event->ev_arg != NULL) {
|
||||
isc_task_t *newtask = NULL;
|
||||
|
||||
event->ev_arg = (void *)(((uintptr_t)event->ev_arg) - 1);
|
||||
|
||||
/*
|
||||
* Create a new task and forward the message.
|
||||
*/
|
||||
result = isc_task_create(taskmgr, 0, &newtask);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_task_onshutdown(newtask, maxtask_shutdown,
|
||||
(void *)task);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
isc_task_send(newtask, &event);
|
||||
} else if (task != NULL) {
|
||||
isc_task_destroy(&task);
|
||||
isc_event_free(&event);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
manytasks(void **state) {
|
||||
isc_mem_t *mctx = NULL;
|
||||
isc_event_t *event = NULL;
|
||||
uintptr_t ntasks = 10000;
|
||||
uintptr_t ntasks = 2; /* 0000; */
|
||||
|
||||
UNUSED(state);
|
||||
|
||||
@@ -479,14 +445,9 @@ manytasks(void **state) {
|
||||
isc_mutex_init(&lock);
|
||||
isc_condition_init(&cv);
|
||||
|
||||
isc_mem_debugging = ISC_MEM_DEBUGRECORD;
|
||||
isc_mem_create(&mctx);
|
||||
|
||||
isc_managers_create(mctx, 4, 0, &netmgr, &taskmgr, NULL);
|
||||
|
||||
atomic_init(&done, false);
|
||||
|
||||
event = isc_event_allocate(mctx, (void *)1, 1, maxtask_cb,
|
||||
event = isc_event_allocate(test_mctx, NULL, 1, maxtask_cb,
|
||||
(void *)ntasks, sizeof(*event));
|
||||
assert_non_null(event);
|
||||
|
||||
@@ -497,221 +458,10 @@ manytasks(void **state) {
|
||||
}
|
||||
UNLOCK(&lock);
|
||||
|
||||
isc_managers_destroy(&netmgr, &taskmgr, NULL);
|
||||
|
||||
isc_mem_destroy(&mctx);
|
||||
isc_condition_destroy(&cv);
|
||||
isc_mutex_destroy(&lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Shutdown test:
|
||||
* When isc_task_shutdown() is called, shutdown events are posted
|
||||
* in LIFO order.
|
||||
*/
|
||||
|
||||
static int nevents = 0;
|
||||
static int nsdevents = 0;
|
||||
static int senders[4];
|
||||
atomic_bool ready, all_done;
|
||||
|
||||
static void
|
||||
sd_sde1(isc_task_t *task, isc_event_t *event) {
|
||||
UNUSED(task);
|
||||
|
||||
assert_int_equal(nevents, 256);
|
||||
assert_int_equal(nsdevents, 1);
|
||||
++nsdevents;
|
||||
|
||||
if (verbose) {
|
||||
print_message("# shutdown 1\n");
|
||||
}
|
||||
|
||||
isc_event_free(&event);
|
||||
|
||||
atomic_store(&all_done, true);
|
||||
}
|
||||
|
||||
static void
|
||||
sd_sde2(isc_task_t *task, isc_event_t *event) {
|
||||
UNUSED(task);
|
||||
|
||||
assert_int_equal(nevents, 256);
|
||||
assert_int_equal(nsdevents, 0);
|
||||
++nsdevents;
|
||||
|
||||
if (verbose) {
|
||||
print_message("# shutdown 2\n");
|
||||
}
|
||||
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
static void
|
||||
sd_event1(isc_task_t *task, isc_event_t *event) {
|
||||
UNUSED(task);
|
||||
|
||||
LOCK(&lock);
|
||||
while (!atomic_load(&ready)) {
|
||||
WAIT(&cv, &lock);
|
||||
}
|
||||
UNLOCK(&lock);
|
||||
|
||||
if (verbose) {
|
||||
print_message("# event 1\n");
|
||||
}
|
||||
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
static void
|
||||
sd_event2(isc_task_t *task, isc_event_t *event) {
|
||||
UNUSED(task);
|
||||
|
||||
++nevents;
|
||||
|
||||
if (verbose) {
|
||||
print_message("# event 2\n");
|
||||
}
|
||||
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
static void
|
||||
task_shutdown(void **state) {
|
||||
isc_result_t result;
|
||||
isc_eventtype_t event_type;
|
||||
isc_event_t *event = NULL;
|
||||
isc_task_t *task = NULL;
|
||||
int i;
|
||||
|
||||
UNUSED(state);
|
||||
|
||||
nevents = nsdevents = 0;
|
||||
event_type = 3;
|
||||
atomic_init(&ready, false);
|
||||
atomic_init(&all_done, false);
|
||||
|
||||
LOCK(&lock);
|
||||
|
||||
result = isc_task_create(taskmgr, 0, &task);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
/*
|
||||
* This event causes the task to wait on cv.
|
||||
*/
|
||||
event = isc_event_allocate(test_mctx, &senders[1], event_type,
|
||||
sd_event1, NULL, sizeof(*event));
|
||||
assert_non_null(event);
|
||||
isc_task_send(task, &event);
|
||||
|
||||
/*
|
||||
* Now we fill up the task's event queue with some events.
|
||||
*/
|
||||
for (i = 0; i < 256; ++i) {
|
||||
event = isc_event_allocate(test_mctx, &senders[1], event_type,
|
||||
sd_event2, NULL, sizeof(*event));
|
||||
assert_non_null(event);
|
||||
isc_task_send(task, &event);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we register two shutdown events.
|
||||
*/
|
||||
result = isc_task_onshutdown(task, sd_sde1, NULL);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_task_onshutdown(task, sd_sde2, NULL);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
isc_task_shutdown(task);
|
||||
isc_task_detach(&task);
|
||||
|
||||
/*
|
||||
* Now we free the task by signaling cv.
|
||||
*/
|
||||
atomic_store(&ready, true);
|
||||
SIGNAL(&cv);
|
||||
UNLOCK(&lock);
|
||||
|
||||
while (!atomic_load(&all_done)) {
|
||||
isc_test_nap(1000);
|
||||
}
|
||||
|
||||
assert_int_equal(nsdevents, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Post-shutdown test:
|
||||
* After isc_task_shutdown() has been called, any call to
|
||||
* isc_task_onshutdown() will return ISC_R_SHUTTINGDOWN.
|
||||
*/
|
||||
static void
|
||||
psd_event1(isc_task_t *task, isc_event_t *event) {
|
||||
UNUSED(task);
|
||||
|
||||
LOCK(&lock);
|
||||
|
||||
while (!atomic_load(&done)) {
|
||||
WAIT(&cv, &lock);
|
||||
}
|
||||
|
||||
UNLOCK(&lock);
|
||||
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
static void
|
||||
psd_sde(isc_task_t *task, isc_event_t *event) {
|
||||
UNUSED(task);
|
||||
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
static void
|
||||
post_shutdown(void **state) {
|
||||
isc_result_t result;
|
||||
isc_eventtype_t event_type;
|
||||
isc_event_t *event;
|
||||
isc_task_t *task;
|
||||
|
||||
UNUSED(state);
|
||||
|
||||
atomic_init(&done, false);
|
||||
event_type = 4;
|
||||
|
||||
isc_condition_init(&cv);
|
||||
|
||||
LOCK(&lock);
|
||||
|
||||
task = NULL;
|
||||
result = isc_task_create(taskmgr, 0, &task);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
/*
|
||||
* This event causes the task to wait on cv.
|
||||
*/
|
||||
event = isc_event_allocate(test_mctx, &senders[1], event_type,
|
||||
psd_event1, NULL, sizeof(*event));
|
||||
assert_non_null(event);
|
||||
isc_task_send(task, &event);
|
||||
|
||||
isc_task_shutdown(task);
|
||||
|
||||
result = isc_task_onshutdown(task, psd_sde, NULL);
|
||||
assert_int_equal(result, ISC_R_SHUTTINGDOWN);
|
||||
|
||||
/*
|
||||
* Release the task.
|
||||
*/
|
||||
atomic_store(&done, true);
|
||||
|
||||
SIGNAL(&cv);
|
||||
UNLOCK(&lock);
|
||||
|
||||
isc_task_detach(&task);
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper for the purge tests below:
|
||||
*/
|
||||
@@ -738,6 +488,11 @@ pge_event1(isc_task_t *task, isc_event_t *event) {
|
||||
}
|
||||
UNLOCK(&lock);
|
||||
|
||||
LOCK(&lock);
|
||||
atomic_store(&done, true);
|
||||
SIGNAL(&cv);
|
||||
UNLOCK(&lock);
|
||||
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
@@ -749,18 +504,6 @@ pge_event2(isc_task_t *task, isc_event_t *event) {
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
static void
|
||||
pge_sde(isc_task_t *task, isc_event_t *event) {
|
||||
UNUSED(task);
|
||||
|
||||
LOCK(&lock);
|
||||
atomic_store(&done, true);
|
||||
SIGNAL(&cv);
|
||||
UNLOCK(&lock);
|
||||
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
static void
|
||||
try_purgeevent(void) {
|
||||
isc_result_t result;
|
||||
@@ -781,9 +524,6 @@ try_purgeevent(void) {
|
||||
result = isc_task_create(taskmgr, 0, &task);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_task_onshutdown(task, pge_sde, NULL);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
/*
|
||||
* Block the task on cv.
|
||||
*/
|
||||
@@ -847,15 +587,11 @@ purgeevent(void **state) {
|
||||
int
|
||||
main(int argc, char **argv) {
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(manytasks),
|
||||
cmocka_unit_test_setup_teardown(manytasks, _setup, _teardown),
|
||||
cmocka_unit_test_setup_teardown(all_events, _setup, _teardown),
|
||||
cmocka_unit_test_setup_teardown(basic, _setup2, _teardown),
|
||||
cmocka_unit_test_setup_teardown(create_task, _setup, _teardown),
|
||||
cmocka_unit_test_setup_teardown(post_shutdown, _setup2,
|
||||
_teardown),
|
||||
cmocka_unit_test_setup_teardown(purgeevent, _setup2, _teardown),
|
||||
cmocka_unit_test_setup_teardown(task_shutdown, _setup4,
|
||||
_teardown),
|
||||
cmocka_unit_test_setup_teardown(task_exclusive, _setup4,
|
||||
_teardown),
|
||||
};
|
||||
|
||||
@@ -81,11 +81,9 @@ _teardown(void **state) {
|
||||
}
|
||||
|
||||
static void
|
||||
test_shutdown(isc_task_t *task, isc_event_t *event) {
|
||||
test_shutdown(void) {
|
||||
isc_result_t result;
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
/*
|
||||
* Signal shutdown processing complete.
|
||||
*/
|
||||
@@ -97,8 +95,6 @@ test_shutdown(isc_task_t *task, isc_event_t *event) {
|
||||
|
||||
result = isc_mutex_unlock(&mx);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -121,9 +117,6 @@ setup_test(isc_timertype_t timertype, isc_interval_t *interval,
|
||||
result = isc_task_create(taskmgr, 0, &task);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_task_onshutdown(task, test_shutdown, NULL);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
isc_mutex_lock(&lasttime_mx);
|
||||
result = isc_time_now(&lasttime);
|
||||
isc_mutex_unlock(&lasttime_mx);
|
||||
@@ -200,6 +193,8 @@ ticktock(isc_task_t *task, isc_event_t *event) {
|
||||
isc_interval_t interval;
|
||||
isc_eventtype_t expected_event_type;
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
int tick = atomic_fetch_add(&eventcnt, 1);
|
||||
|
||||
if (verbose) {
|
||||
@@ -247,7 +242,7 @@ ticktock(isc_task_t *task, isc_event_t *event) {
|
||||
result = isc_time_now(&endtime);
|
||||
subthread_assert_result_equal(result, ISC_R_SUCCESS);
|
||||
isc_timer_destroy(&timer);
|
||||
isc_task_shutdown(task);
|
||||
test_shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,6 +275,8 @@ test_idle(isc_task_t *task, isc_event_t *event) {
|
||||
isc_time_t llim;
|
||||
isc_interval_t interval;
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
int tick = atomic_fetch_add(&eventcnt, 1);
|
||||
|
||||
if (verbose) {
|
||||
@@ -315,7 +312,7 @@ test_idle(isc_task_t *task, isc_event_t *event) {
|
||||
isc_event_free(&event);
|
||||
|
||||
isc_timer_destroy(&timer);
|
||||
isc_task_shutdown(task);
|
||||
test_shutdown();
|
||||
}
|
||||
|
||||
/* timer type once idles out */
|
||||
@@ -344,6 +341,8 @@ test_reset(isc_task_t *task, isc_event_t *event) {
|
||||
isc_time_t llim;
|
||||
isc_interval_t interval;
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
int tick = atomic_fetch_add(&eventcnt, 1);
|
||||
|
||||
if (verbose) {
|
||||
@@ -395,7 +394,7 @@ test_reset(isc_task_t *task, isc_event_t *event) {
|
||||
|
||||
isc_event_free(&event);
|
||||
isc_timer_destroy(&timer);
|
||||
isc_task_shutdown(task);
|
||||
test_shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,7 +457,7 @@ tick_event(isc_task_t *task, isc_event_t *event) {
|
||||
&interval, true);
|
||||
subthread_assert_result_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
isc_task_shutdown(task);
|
||||
atomic_store(&shutdownflag, 1);
|
||||
}
|
||||
|
||||
isc_event_free(&event);
|
||||
@@ -466,6 +465,8 @@ tick_event(isc_task_t *task, isc_event_t *event) {
|
||||
|
||||
static void
|
||||
once_event(isc_task_t *task, isc_event_t *event) {
|
||||
UNUSED(task);
|
||||
|
||||
if (verbose) {
|
||||
print_message("# once_event\n");
|
||||
}
|
||||
@@ -475,24 +476,6 @@ once_event(isc_task_t *task, isc_event_t *event) {
|
||||
*/
|
||||
atomic_store(&startflag, true);
|
||||
|
||||
isc_event_free(&event);
|
||||
isc_task_shutdown(task);
|
||||
}
|
||||
|
||||
static void
|
||||
shutdown_purge(isc_task_t *task, isc_event_t *event) {
|
||||
UNUSED(task);
|
||||
UNUSED(event);
|
||||
|
||||
if (verbose) {
|
||||
print_message("# shutdown_event\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Signal shutdown processing complete.
|
||||
*/
|
||||
atomic_store(&shutdownflag, 1);
|
||||
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
@@ -513,9 +496,6 @@ purge(void **state) {
|
||||
result = isc_task_create(taskmgr, 0, &task1);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_task_onshutdown(task1, shutdown_purge, NULL);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_task_create(taskmgr, 0, &task2);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user