+++ /dev/null
-/*
- * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
- *
- * 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 http://mozilla.org/MPL/2.0/.
- *
- * See the COPYRIGHT file distributed with this work for additional
- * information regarding copyright ownership.
- */
-
-/* $Id: t_tasks.c,v 1.49 2011/07/27 07:45:55 marka Exp $ */
-
-#include <config.h>
-
-#include <stdlib.h>
-#include <unistd.h>
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h> /* uintptr_t */
-#endif
-#include <isc/condition.h>
-#include <isc/mem.h>
-#include <isc/platform.h>
-#include <isc/task.h>
-#include <isc/time.h>
-#include <isc/timer.h>
-#include <isc/util.h>
-
-#include <tests/t_api.h>
-
-
-#ifdef ISC_PLATFORM_USETHREADS
-isc_boolean_t threaded = ISC_TRUE;
-#else
-isc_boolean_t threaded = ISC_FALSE;
-#endif
-
-static int senders[4];
-
-static void
-require_threads(void) {
- t_info("This test requires threads\n");
- t_result(T_THREADONLY);
- return;
-}
-
-static void
-t1_callback(isc_task_t *task, isc_event_t *event) {
- int i;
- int j;
-
- UNUSED(task);
-
- j = 0;
-
- for (i = 0; i < 1000000; i++)
- j += 100;
-
- t_info("task %s\n", (char *)event->ev_arg);
- isc_event_free(&event);
-}
-
-static void
-t1_shutdown(isc_task_t *task, isc_event_t *event) {
-
- UNUSED(task);
-
- t_info("shutdown %s\n", (char *)event->ev_arg);
- isc_event_free(&event);
-}
-
-static void
-my_tick(isc_task_t *task, isc_event_t *event) {
-
- UNUSED(task);
-
- t_info("%s\n", (char *)event->ev_arg);
- isc_event_free(&event);
-}
-
-/*
- * Adapted from RTH's original task_test program
- */
-
-static char one[] = "1";
-static char two[] = "2";
-static char three[] = "3";
-static char four[] = "4";
-static char tick[] = "tick";
-static char tock[] = "tock";
-
-static int
-t_tasks1(void) {
- char *p;
- isc_mem_t *mctx;
- isc_taskmgr_t *manager;
- isc_task_t *task1;
- isc_task_t *task2;
- isc_task_t *task3;
- isc_task_t *task4;
- isc_event_t *event;
- unsigned int workers;
- isc_timermgr_t *timgr;
- isc_timer_t *ti1;
- isc_timer_t *ti2;
- isc_result_t isc_result;
- isc_time_t absolute;
- isc_interval_t interval;
-
- manager = NULL;
- task1 = NULL;
- task2 = NULL;
- task3 = NULL;
- task4 = NULL;
- mctx = NULL;
-
- workers = 2;
- p = t_getenv("ISC_TASK_WORKERS");
- if (p != NULL)
- workers = atoi(p);
- if (workers < 1) {
- t_info("Bad config value for ISC_TASK_WORKERS, %d\n", workers);
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_mem_create(0, 0, &mctx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mem_create failed %d\n", isc_result);
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_taskmgr_create(mctx, workers, 0, &manager);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_taskmgr_create failed %d\n", isc_result);
- return(T_FAIL);
- }
-
- isc_result = isc_task_create(manager, 0, &task1);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_task_create failed %d\n", isc_result);
- return(T_FAIL);
- }
-
- isc_result = isc_task_create(manager, 0, &task2);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_task_create failed %d\n", isc_result);
- return(T_FAIL);
- }
-
- isc_result = isc_task_create(manager, 0, &task3);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_task_create failed %d\n", isc_result);
- return(T_FAIL);
- }
-
- isc_result = isc_task_create(manager, 0, &task4);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_task_create failed %d\n", isc_result);
- return(T_FAIL);
- }
-
- isc_result = isc_task_onshutdown(task1, t1_shutdown, one);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_task_onshutdown failed %d\n", isc_result);
- return(T_FAIL);
- }
-
- isc_result = isc_task_onshutdown(task2, t1_shutdown, two);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_task_onshutdown failed %d\n", isc_result);
- return(T_FAIL);
- }
-
- isc_result = isc_task_onshutdown(task3, t1_shutdown, three);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_task_onshutdown failed %d\n", isc_result);
- return(T_FAIL);
- }
-
- isc_result = isc_task_onshutdown(task4, t1_shutdown, four);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_task_onshutdown failed %d\n", isc_result);
- return(T_FAIL);
- }
-
- timgr = NULL;
- isc_result = isc_timermgr_create(mctx, &timgr);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_timermgr_create %d\n", isc_result);
- return(T_UNRESOLVED);
- }
-
- ti1 = NULL;
- isc_time_settoepoch(&absolute);
- isc_interval_set(&interval, 1, 0);
- isc_result = isc_timer_create(timgr, isc_timertype_ticker,
- &absolute, &interval,
- task1, my_tick, tick, &ti1);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_timer_create %d\n", isc_result);
- return(T_UNRESOLVED);
- }
-
- ti2 = NULL;
- isc_time_settoepoch(&absolute);
- isc_interval_set(&interval, 1, 0);
- isc_result = isc_timer_create(timgr, isc_timertype_ticker,
- &absolute, &interval,
- task2, my_tick, tock, &ti2);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_timer_create %d\n", isc_result);
- return(T_UNRESOLVED);
- }
-
-
-#ifndef WIN32
- sleep(2);
-#else
- Sleep(2000);
-#endif
-
- /*
- * Note: (void *)1 is used as a sender here, since some compilers
- * don't like casting a function pointer to a (void *).
- *
- * In a real use, it is more likely the sender would be a
- * structure (socket, timer, task, etc) but this is just a test
- * program.
- */
- event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, one,
- sizeof(*event));
- if (event == NULL) {
- t_info("isc_event_allocate failed\n");
- return(T_UNRESOLVED);
- }
-
- isc_task_send(task1, &event);
-
- event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, one,
- sizeof(*event));
- if (event == NULL) {
- t_info("isc_event_allocate failed\n");
- return(T_UNRESOLVED);
- }
-
- isc_task_send(task1, &event);
-
- event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, one,
- sizeof(*event));
- if (event == NULL) {
- t_info("isc_event_allocate failed\n");
- return(T_UNRESOLVED);
- }
-
- isc_task_send(task1, &event);
-
- event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, one,
- sizeof(*event));
- if (event == NULL) {
- t_info("isc_event_allocate failed\n");
- return(T_UNRESOLVED);
- }
-
- isc_task_send(task1, &event);
-
- event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, one,
- sizeof(*event));
- if (event == NULL) {
- t_info("isc_event_allocate failed\n");
- return(T_UNRESOLVED);
- }
-
- isc_task_send(task1, &event);
-
- event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, one,
- sizeof(*event));
- if (event == NULL) {
- t_info("isc_event_allocate failed\n");
- return(T_UNRESOLVED);
- }
-
- isc_task_send(task1, &event);
-
- event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, one,
- sizeof(*event));
- if (event == NULL) {
- t_info("isc_event_allocate failed\n");
- return(T_UNRESOLVED);
- }
-
- isc_task_send(task1, &event);
-
- event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, one,
- sizeof(*event));
- if (event == NULL) {
- t_info("isc_event_allocate failed\n");
- return(T_UNRESOLVED);
- }
-
- isc_task_send(task1, &event);
-
- event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, one,
- sizeof(*event));
- if (event == NULL) {
- t_info("isc_event_allocate failed\n");
- return(T_UNRESOLVED);
- }
-
- isc_task_send(task1, &event);
-
- event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, two,
- sizeof(*event));
- if (event == NULL) {
- t_info("isc_event_allocate failed\n");
- return(T_UNRESOLVED);
- }
-
- isc_task_send(task2, &event);
-
- event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, three,
- sizeof(*event));
- if (event == NULL) {
- t_info("isc_event_allocate failed\n");
- return(T_UNRESOLVED);
- }
-
- isc_task_send(task3, &event);
-
- event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, four,
- sizeof(*event));
- if (event == NULL) {
- t_info("isc_event_allocate failed\n");
- return(T_UNRESOLVED);
- }
-
- isc_task_send(task4, &event);
-
- event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, two,
- sizeof(*event));
- if (event == NULL) {
- t_info("isc_event_allocate failed\n");
- return(T_UNRESOLVED);
- }
-
- isc_task_send(task2, &event);
-
- event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, three,
- sizeof(*event));
- if (event == NULL) {
- t_info("isc_event_allocate failed\n");
- return(T_UNRESOLVED);
- }
-
- isc_task_send(task3, &event);
-
- event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, four,
- sizeof(*event));
- if (event == NULL) {
- t_info("isc_event_allocate failed\n");
- return(T_UNRESOLVED);
- }
-
- isc_task_send(task4, &event);
-
- (void)isc_task_purge(task3, NULL, 0, 0);
-
- isc_task_detach(&task1);
- isc_task_detach(&task2);
- isc_task_detach(&task3);
- isc_task_detach(&task4);
-
-#ifndef WIN32
- sleep(10);
-#else
- Sleep(10000);
-#endif
- isc_timer_detach(&ti1);
- isc_timer_detach(&ti2);
- isc_timermgr_destroy(&timgr);
- isc_taskmgr_destroy(&manager);
-
- isc_mem_destroy(&mctx);
- return(T_PASS);
-}
-
-static const char *a1 = "The task subsystem can create and manage tasks";
-
-static void
-t1(void) {
- int result;
-
- t_assert("tasks", 1, T_REQUIRED, "%s", a1);
- result = t_tasks1();
- t_result(result);
-}
-
-#define T2_NTASKS 10000
-
-static isc_event_t *T2_event;
-static isc_taskmgr_t *T2_manager;
-static isc_mem_t *T2_mctx;
-static isc_condition_t T2_cv;
-static isc_mutex_t T2_mx;
-static int T2_done;
-static int T2_nprobs;
-static int T2_nfails;
-static int T2_ntasks;
-
-static void
-t2_shutdown(isc_task_t *task, isc_event_t *event) {
-
- isc_result_t isc_result;
-
- UNUSED(task);
-
- if (event->ev_arg != NULL) {
- isc_task_destroy((isc_task_t**) &event->ev_arg);
- }
- else {
- isc_result = isc_mutex_lock(&T2_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_lock failed %d\n", isc_result);
- ++T2_nprobs;
- }
-
- T2_done = 1;
-
- isc_result = isc_condition_signal(&T2_cv);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_condition_signal failed %d\n", isc_result);
- ++T2_nprobs;
- }
-
- isc_result = isc_mutex_unlock(&T2_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_unlock failed %d\n", isc_result);
- ++T2_nprobs;
- }
-
- isc_event_free(&T2_event);
- isc_taskmgr_destroy(&T2_manager);
- isc_mem_destroy(&T2_mctx);
- }
-}
-
-static void
-t2_callback(isc_task_t *task, isc_event_t *event) {
- isc_result_t isc_result;
- isc_task_t *newtask;
-
- ++T2_ntasks;
-
- if (T_debug && ((T2_ntasks % 100) == 0)) {
- t_info("T2_ntasks %d\n", T2_ntasks);
- }
-
- if (event->ev_arg) {
-
- event->ev_arg = (void *)(((uintptr_t) event->ev_arg) - 1);
-
- /*
- * Create a new task and forward the message.
- */
- newtask = NULL;
- isc_result = isc_task_create(T2_manager, 0, &newtask);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_task_create failed %d\n", isc_result);
- ++T2_nfails;
- return;
- }
-
- isc_result = isc_task_onshutdown(newtask, t2_shutdown,
- (void *)task);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_task_onshutdown failed %d\n",
- isc_result);
- ++T2_nfails;
- return;
- }
-
- isc_task_send(newtask, &event);
- } else {
- /*
- * Time to unwind, shutdown should perc back up.
- */
- isc_task_destroy(&task);
- }
-}
-
-static int
-t_tasks2(void) {
- uintptr_t ntasks;
- int result;
- char *p;
- unsigned int workers;
- isc_result_t isc_result;
-
- T2_manager = NULL;
- T2_done = 0;
- T2_nprobs = 0;
- T2_nfails = 0;
- T2_ntasks = 0;
-
- workers = 2;
- p = t_getenv("ISC_TASK_WORKERS");
- if (p != NULL)
- workers = atoi(p);
- if (workers < 1) {
- t_info("Bad config value for ISC_TASK_WORKERS, %d\n", workers);
- return(T_UNRESOLVED);
- }
-
- p = t_getenv("ISC_TASKS_MIN");
- if (p != NULL)
- ntasks = atoi(p);
- else
- ntasks = T2_NTASKS;
- if (ntasks == 0U) {
- t_info("Bad config value for ISC_TASKS_MIN, %lu\n",
- (unsigned long)ntasks);
- return(T_UNRESOLVED);
- }
-
- t_info("Testing with %lu tasks\n", (unsigned long)ntasks);
-
- isc_result = isc_mutex_init(&T2_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_init failed %d\n", isc_result);
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_condition_init(&T2_cv);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_condition_init failed %d\n", isc_result);
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_mem_create(0, 0, &T2_mctx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mem_create failed %d\n", isc_result);
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_taskmgr_create(T2_mctx, workers, 0, &T2_manager);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_taskmgr_create failed %d\n", isc_result);
- return(T_FAIL);
- }
-
- T2_event = isc_event_allocate(T2_mctx, (void *)1, 1, t2_callback,
- (void *)ntasks, sizeof(*T2_event));
- if (T2_event == NULL) {
- t_info("isc_event_allocate failed\n");
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_mutex_lock(&T2_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_lock failed %d\n", isc_result);
- return(T_UNRESOLVED);
- }
-
- t2_callback(NULL, T2_event);
-
- while (T2_done == 0) {
- isc_result = isc_condition_wait(&T2_cv, &T2_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_condition_wait failed %d\n", isc_result);
- return(T_UNRESOLVED);
- }
- }
-
- result = T_UNRESOLVED;
-
- if ((T2_nfails == 0) && (T2_nprobs == 0))
- result = T_PASS;
- else if (T2_nfails != 0)
- result = T_FAIL;
-
- return(result);
-}
-
-static const char *a2 = "The task subsystem can create ISC_TASKS_MIN tasks";
-
-static void
-t2(void) {
- t_assert("tasks", 2, T_REQUIRED, "%s", a2);
-
- if (threaded)
- t_result(t_tasks2());
- else
- require_threads();
-}
-
-#define T3_NEVENTS 256
-
-static int T3_flag;
-static int T3_nevents;
-static int T3_nsdevents;
-static isc_mutex_t T3_mx;
-static isc_condition_t T3_cv;
-static int T3_nfails;
-static int T3_nprobs;
-
-static void
-t3_sde1(isc_task_t *task, isc_event_t *event) {
-
- UNUSED(task);
-
- if (T3_nevents != T3_NEVENTS) {
- t_info("Some events were not processed\n");
- ++T3_nprobs;
- }
- if (T3_nsdevents == 1) {
- ++T3_nsdevents;
- } else {
- t_info("Shutdown events not processed in LIFO order\n");
- ++T3_nfails;
- }
- isc_event_free(&event);
-}
-
-static void
-t3_sde2(isc_task_t *task, isc_event_t *event) {
-
- UNUSED(task);
-
- if (T3_nevents != T3_NEVENTS) {
- t_info("Some events were not processed\n");
- ++T3_nprobs;
- }
- if (T3_nsdevents == 0) {
- ++T3_nsdevents;
- } else {
- t_info("Shutdown events not processed in LIFO order\n");
- ++T3_nfails;
- }
- isc_event_free(&event);
-}
-
-static void
-t3_event1(isc_task_t *task, isc_event_t *event) {
- isc_result_t isc_result;
-
- UNUSED(task);
-
- isc_result = isc_mutex_lock(&T3_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_lock failed %s\n",
- isc_result_totext(isc_result));
- ++T3_nprobs;
- }
- while (T3_flag != 1) {
- (void) isc_condition_wait(&T3_cv, &T3_mx);
- }
-
- isc_result = isc_mutex_unlock(&T3_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_unlock failed %s\n",
- isc_result_totext(isc_result));
- ++T3_nprobs;
- }
- isc_event_free(&event);
-}
-
-static void
-t3_event2(isc_task_t *task, isc_event_t *event) {
- UNUSED(task);
-
- ++T3_nevents;
- isc_event_free(&event);
-}
-
-static int
-t_tasks3(void) {
- int cnt;
- int result;
- char *p;
- isc_mem_t *mctx;
- isc_taskmgr_t *tmgr;
- isc_task_t *task;
- unsigned int workers;
- isc_event_t *event;
- isc_result_t isc_result;
- isc_eventtype_t event_type;
-
- T3_flag = 0;
- T3_nevents = 0;
- T3_nsdevents = 0;
- T3_nfails = 0;
- T3_nprobs = 0;
-
- event_type = 3;
-
- workers = 2;
- p = t_getenv("ISC_TASK_WORKERS");
- if (p != NULL)
- workers = atoi(p);
-
- mctx = NULL;
- isc_result = isc_mem_create(0, 0, &mctx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mem_create failed %s\n",
- isc_result_totext(isc_result));
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_mutex_init(&T3_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_init failed %s\n",
- isc_result_totext(isc_result));
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_condition_init(&T3_cv);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_condition_init failed %s\n",
- isc_result_totext(isc_result));
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
-
- tmgr = NULL;
- isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_taskmgr_create failed %s\n",
- isc_result_totext(isc_result));
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_mutex_lock(&T3_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_lock failed %s\n",
- isc_result_totext(isc_result));
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
-
- task = NULL;
- isc_result = isc_task_create(tmgr, 0, &task);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_task_create failed %s\n",
- isc_result_totext(isc_result));
- (void) isc_mutex_unlock(&T3_mx);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
-
- /*
- * This event causes the task to wait on T3_cv.
- */
- event = isc_event_allocate(mctx, &senders[1], event_type, t3_event1,
- NULL, sizeof(*event));
- if (event == NULL) {
- t_info("isc_event_allocate failed\n");
- (void) isc_mutex_unlock(&T3_mx);
- isc_task_destroy(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
- isc_task_send(task, &event);
-
- /*
- * Now we fill up the task's event queue with some events.
- */
- for (cnt = 0; cnt < T3_NEVENTS; ++cnt) {
- event = isc_event_allocate(mctx, &senders[1], event_type,
- t3_event2, NULL, sizeof(*event));
- if (event == NULL) {
- t_info("isc_event_allocate failed\n");
- (void) isc_mutex_unlock(&T3_mx);
- isc_task_destroy(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
- isc_task_send(task, &event);
- }
-
- /*
- * Now we register two shutdown events.
- */
- isc_result = isc_task_onshutdown(task, t3_sde1, NULL);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_task_send failed %s\n",
- isc_result_totext(isc_result));
- (void) isc_mutex_unlock(&T3_mx);
- isc_task_destroy(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_task_onshutdown(task, t3_sde2, NULL);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_task_send failed %s\n",
- isc_result_totext(isc_result));
- (void) isc_mutex_unlock(&T3_mx);
- isc_task_destroy(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
-
- isc_task_shutdown(task);
-
- /*
- * Now we free the task by signaling T3_cv.
- */
- T3_flag = 1;
- isc_result = isc_condition_signal(&T3_cv);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_condition_signal failed %s\n",
- isc_result_totext(isc_result));
- ++T3_nprobs;
- }
-
- isc_result = isc_mutex_unlock(&T3_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_unlock failed %s\n",
- isc_result_totext(isc_result));
- ++T3_nprobs;
- }
-
-
- isc_task_detach(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
-
- if (T3_nsdevents != 2) {
- t_info("T3_nsdevents == %d, expected 2\n", T3_nsdevents);
- ++T3_nfails;
- }
-
- result = T_UNRESOLVED;
-
- if (T3_nfails != 0)
- result = T_FAIL;
- else if ((T3_nfails == 0) && (T3_nprobs == 0))
- result = T_PASS;
-
- return(result);
-}
-
-static const char *a3 = "When isc_task_shutdown() is called, any shutdown "
- "events that have been requested via prior "
- "isc_task_onshutdown() calls are posted in "
- "LIFO order.";
-static void
-t3(void) {
- t_assert("tasks", 3, T_REQUIRED, "%s", a3);
-
- if (threaded)
- t_result(t_tasks3());
- else
- require_threads();
-}
-
-static isc_mutex_t T4_mx;
-static isc_condition_t T4_cv;
-static int T4_flag;
-static int T4_nprobs;
-static int T4_nfails;
-
-static void
-t4_event1(isc_task_t *task, isc_event_t *event) {
- isc_result_t isc_result;
-
- UNUSED(task);
-
- isc_result = isc_mutex_lock(&T4_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_lock failed %s\n",
- isc_result_totext(isc_result));
- ++T4_nprobs;
- }
- while (T4_flag != 1) {
- (void) isc_condition_wait(&T4_cv, &T4_mx);
- }
-
- isc_result = isc_mutex_unlock(&T4_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_unlock failed %s\n",
- isc_result_totext(isc_result));
- ++T4_nprobs;
- }
- isc_event_free(&event);
-}
-
-static void
-t4_sde(isc_task_t *task, isc_event_t *event) {
- UNUSED(task);
-
- /*
- * No-op.
- */
-
- isc_event_free(&event);
-}
-
-static int
-t_tasks4(void) {
- int result;
- char *p;
- isc_mem_t *mctx;
- isc_taskmgr_t *tmgr;
- isc_task_t *task;
- unsigned int workers;
- isc_result_t isc_result;
- isc_eventtype_t event_type;
- isc_event_t *event;
-
- T4_nprobs = 0;
- T4_nfails = 0;
- T4_flag = 0;
-
- event_type = 4;
-
- workers = 2;
- p = t_getenv("ISC_TASK_WORKERS");
- if (p != NULL)
- workers = atoi(p);
-
- mctx = NULL;
- isc_result = isc_mem_create(0, 0, &mctx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mem_create failed %s\n",
- isc_result_totext(isc_result));
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_mutex_init(&T4_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_init failed %s\n",
- isc_result_totext(isc_result));
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_condition_init(&T4_cv);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_condition_init failed %s\n",
- isc_result_totext(isc_result));
- DESTROYLOCK(&T4_mx);
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
-
- tmgr = NULL;
- isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_taskmgr_create failed %s\n",
- isc_result_totext(isc_result));
- DESTROYLOCK(&T4_mx);
- (void) isc_condition_destroy(&T4_cv);
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_mutex_lock(&T4_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_lock failed %s\n",
- isc_result_totext(isc_result));
- DESTROYLOCK(&T4_mx);
- (void) isc_condition_destroy(&T4_cv);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
-
- task = NULL;
- isc_result = isc_task_create(tmgr, 0, &task);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_task_create failed %s\n",
- isc_result_totext(isc_result));
- isc_result = isc_mutex_unlock(&T4_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_unlock failed %s\n",
- isc_result_totext(isc_result));
- ++T4_nprobs;
- }
- DESTROYLOCK(&T4_mx);
- (void) isc_condition_destroy(&T4_cv);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
-
- /*
- * This event causes the task to wait on T4_cv.
- */
- event = isc_event_allocate(mctx, &senders[1], event_type, t4_event1,
- NULL, sizeof(*event));
- if (event == NULL) {
- t_info("isc_event_allocate failed\n");
- isc_result = isc_mutex_unlock(&T4_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_unlock failed %s\n",
- isc_result_totext(isc_result));
- ++T4_nprobs;
- }
- DESTROYLOCK(&T4_mx);
- isc_task_destroy(&task);
- (void) isc_condition_destroy(&T4_cv);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
- isc_task_send(task, &event);
-
- isc_task_shutdown(task);
-
- isc_result = isc_task_onshutdown(task, t4_sde, NULL);
- if (isc_result != ISC_R_SHUTTINGDOWN) {
- t_info("isc_task_onshutdown returned %s\n",
- isc_result_totext(isc_result));
- ++T4_nfails;
- }
-
- /*
- * Release the task.
- */
- T4_flag = 1;
-
- isc_result = isc_condition_signal(&T4_cv);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_condition_signal failed %s\n",
- isc_result_totext(isc_result));
- ++T4_nprobs;
- }
-
- isc_result = isc_mutex_unlock(&T4_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_unlock failed %s\n",
- isc_result_totext(isc_result));
- ++T4_nprobs;
- }
-
- isc_task_detach(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- (void) isc_condition_destroy(&T4_cv);
- DESTROYLOCK(&T4_mx);
-
- result = T_UNRESOLVED;
-
- if (T4_nfails != 0)
- result = T_FAIL;
- else if ((T4_nfails == 0) && (T4_nprobs == 0))
- result = T_PASS;
-
- return(result);
-}
-
-static const char *a4 =
- "After isc_task_shutdown() has been called, any call to "
- "isc_task_onshutdown() will return ISC_R_SHUTTINGDOWN.";
-
-static void
-t4(void) {
- t_assert("tasks", 4, T_REQUIRED, "%s", a4);
-
- if (threaded)
- t_result(t_tasks4());
- else
- require_threads();
-}
-
-static int T7_nprobs;
-static int T7_eflag;
-static int T7_sdflag;
-static isc_mutex_t T7_mx;
-static isc_condition_t T7_cv;
-
-static int T7_nfails;
-
-static void
-t7_event1(isc_task_t *task, isc_event_t *event) {
- UNUSED(task);
-
- ++T7_eflag;
-
- isc_event_free(&event);
-}
-
-static void
-t7_sde(isc_task_t *task, isc_event_t *event) {
- isc_result_t isc_result;
-
- UNUSED(task);
-
- isc_result = isc_mutex_lock(&T7_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_lock failed %s\n",
- isc_result_totext(isc_result));
- ++T7_nprobs;
- }
-
- ++T7_sdflag;
-
- isc_result = isc_condition_signal(&T7_cv);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_condition_signal failed %s\n",
- isc_result_totext(isc_result));
- ++T7_nprobs;
- }
-
- isc_result = isc_mutex_unlock(&T7_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_unlock failed %s\n",
- isc_result_totext(isc_result));
- ++T7_nprobs;
- }
-
- isc_event_free(&event);
-}
-
-static int
-t_tasks7(void) {
- int result;
- char *p;
- isc_mem_t *mctx;
- isc_taskmgr_t *tmgr;
- isc_task_t *task;
- unsigned int workers;
- isc_result_t isc_result;
- isc_eventtype_t event_type;
- isc_event_t *event;
- isc_time_t now;
- isc_interval_t interval;
-
- T7_nprobs = 0;
- T7_nfails = 0;
- T7_sdflag = 0;
- T7_eflag = 0;
-
- event_type = 7;
-
- workers = 2;
- p = t_getenv("ISC_TASK_WORKERS");
- if (p != NULL)
- workers = atoi(p);
-
- mctx = NULL;
- isc_result = isc_mem_create(0, 0, &mctx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mem_create failed %s\n",
- isc_result_totext(isc_result));
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_mutex_init(&T7_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_init failed %s\n",
- isc_result_totext(isc_result));
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_condition_init(&T7_cv);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_condition_init failed %s\n",
- isc_result_totext(isc_result));
- DESTROYLOCK(&T7_mx);
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
-
- tmgr = NULL;
- isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_taskmgr_create failed %s\n",
- isc_result_totext(isc_result));
- DESTROYLOCK(&T7_mx);
- (void) isc_condition_destroy(&T7_cv);
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_mutex_lock(&T7_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_lock failed %s\n",
- isc_result_totext(isc_result));
- DESTROYLOCK(&T7_mx);
- (void) isc_condition_destroy(&T7_cv);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- return(T_FAIL);
- }
-
- task = NULL;
- isc_result = isc_task_create(tmgr, 0, &task);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_task_create failed %s\n",
- isc_result_totext(isc_result));
- DESTROYLOCK(&T7_mx);
- (void) isc_condition_destroy(&T7_cv);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- return(T_FAIL);
- }
-
- isc_result = isc_task_onshutdown(task, t7_sde, NULL);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_task_onshutdown returned %s\n",
- isc_result_totext(isc_result));
- DESTROYLOCK(&T7_mx);
- (void) isc_condition_destroy(&T7_cv);
- isc_task_destroy(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
-
- event = isc_event_allocate(mctx, &senders[1], event_type, t7_event1,
- NULL, sizeof(*event));
- if (event == NULL) {
- t_info("isc_event_allocate failed\n");
- DESTROYLOCK(&T7_mx);
- (void) isc_condition_destroy(&T7_cv);
- isc_task_destroy(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
- isc_task_send(task, &event);
-
- isc_task_shutdown(task);
-
- isc_interval_set(&interval, 5, 0);
-
- while (T7_sdflag == 0) {
- isc_result = isc_time_nowplusinterval(&now, &interval);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_time_nowplusinterval failed %s\n",
- isc_result_totext(isc_result));
- DESTROYLOCK(&T7_mx);
- (void) isc_condition_destroy(&T7_cv);
- isc_task_destroy(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_condition_waituntil(&T7_cv, &T7_mx, &now);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_condition_waituntil returned %s\n",
- isc_result_totext(isc_result));
- DESTROYLOCK(&T7_mx);
- (void) isc_condition_destroy(&T7_cv);
- isc_task_destroy(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- return(T_FAIL);
- }
- }
-
- isc_result = isc_mutex_unlock(&T7_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_unlock failed %s\n",
- isc_result_totext(isc_result));
- ++T7_nprobs;
- }
-
- isc_task_detach(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- (void) isc_condition_destroy(&T7_cv);
- DESTROYLOCK(&T7_mx);
-
- result = T_UNRESOLVED;
-
- if (T7_eflag == 0)
- ++T7_nfails;
-
- if (T7_nfails != 0)
- result = T_FAIL;
- else if ((T7_nfails == 0) && (T7_nprobs == 0))
- result = T_PASS;
-
- return(result);
-}
-
-static const char *a7 = "A call to isc_task_create() creates a task that can "
- "receive events.";
-
-static void
-t7(void) {
- t_assert("tasks", 7, T_REQUIRED, "%s", a7);
-
- if (threaded)
- t_result(t_tasks7());
- else
- require_threads();
-}
-
-#define T10_SENDERCNT 3
-#define T10_TYPECNT 4
-#define T10_TAGCNT 5
-#define T10_NEVENTS (T10_SENDERCNT*T10_TYPECNT*T10_TAGCNT)
-#define T_CONTROL 99999
-
-static int T10_nprobs;
-static int T10_nfails;
-static int T10_startflag;
-static int T10_shutdownflag;
-static int T10_eventcnt;
-static isc_mutex_t T10_mx;
-static isc_condition_t T10_cv;
-
-static void *T10_purge_sender;
-static isc_eventtype_t T10_purge_type_first;
-static isc_eventtype_t T10_purge_type_last;
-static void *T10_purge_tag;
-static int T10_testrange;
-
-static void
-t10_event1(isc_task_t *task, isc_event_t *event) {
- isc_result_t isc_result;
-
- UNUSED(task);
-
- isc_result = isc_mutex_lock(&T10_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_lock failed %s\n",
- isc_result_totext(isc_result));
- ++T10_nprobs;
- }
-
- while (T10_startflag == 0) {
- isc_result = isc_condition_wait(&T10_cv, &T10_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_lock failed %s\n",
- isc_result_totext(isc_result));
- ++T10_nprobs;
- }
- }
-
- isc_result = isc_mutex_unlock(&T10_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_unlock failed %s\n",
- isc_result_totext(isc_result));
- ++T10_nprobs;
- }
-
- isc_event_free(&event);
-}
-
-static void
-t10_event2(isc_task_t *task, isc_event_t *event) {
-
- int sender_match;
- int type_match;
- int tag_match;
-
- UNUSED(task);
-
- sender_match = 0;
- type_match = 0;
- tag_match = 0;
-
- if (T_debug) {
- t_info("Event %p,%d,%p,%s\n",
- event->ev_sender,
- (int)event->ev_type,
- event->ev_tag,
- ((event->ev_attributes & ISC_EVENTATTR_NOPURGE) != 0) ?
- "NP" : "P");
- }
-
- if ((T10_purge_sender == NULL) ||
- (T10_purge_sender == event->ev_sender)) {
- sender_match = 1;
- }
- if (T10_testrange == 0) {
- if (T10_purge_type_first == event->ev_type) {
- type_match = 1;
- }
- } else {
- if ((T10_purge_type_first <= event->ev_type) &&
- (event->ev_type <= T10_purge_type_last)) {
- type_match = 1;
- }
- }
- if ((T10_purge_tag == NULL) ||
- (T10_purge_tag == event->ev_tag)) {
- tag_match = 1;
- }
-
- if (sender_match && type_match && tag_match) {
- if (event->ev_attributes & ISC_EVENTATTR_NOPURGE) {
- t_info("event %p,%d,%p matched but was not purgable\n",
- event->ev_sender, (int)event->ev_type,
- event->ev_tag);
- ++T10_eventcnt;
- } else {
- t_info("*** event %p,%d,%p not purged\n",
- event->ev_sender, (int)event->ev_type,
- event->ev_tag);
- }
- } else {
- ++T10_eventcnt;
- }
- isc_event_free(&event);
-}
-
-
-static void
-t10_sde(isc_task_t *task, isc_event_t *event) {
- isc_result_t isc_result;
-
- UNUSED(task);
-
- isc_result = isc_mutex_lock(&T10_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_lock failed %s\n",
- isc_result_totext(isc_result));
- ++T10_nprobs;
- }
-
- ++T10_shutdownflag;
-
- isc_result = isc_condition_signal(&T10_cv);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_condition_signal failed %s\n",
- isc_result_totext(isc_result));
- ++T10_nprobs;
- }
-
- isc_result = isc_mutex_unlock(&T10_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_unlock failed %s\n",
- isc_result_totext(isc_result));
- ++T10_nprobs;
- }
-
- isc_event_free(&event);
-}
-
-static void
-t_taskpurge_x(int sender, int type, int tag, void *purge_sender,
- int purge_type_first, int purge_type_last, void *purge_tag,
- int exp_nevents, int *nfails, int *nprobs, int testrange)
-{
- char *p;
- isc_mem_t *mctx;
- isc_taskmgr_t *tmgr;
- isc_task_t *task;
- unsigned int workers;
- isc_result_t isc_result;
- isc_event_t *event;
- isc_time_t now;
- isc_interval_t interval;
- int sender_cnt;
- int type_cnt;
- int tag_cnt;
- int event_cnt;
- int cnt;
- int nevents;
- isc_event_t *eventtab[T10_NEVENTS];
-
-
- T10_startflag = 0;
- T10_shutdownflag = 0;
- T10_eventcnt = 0;
- T10_purge_sender = purge_sender;
- T10_purge_type_first = (isc_eventtype_t) purge_type_first;
- T10_purge_type_last = (isc_eventtype_t) purge_type_last;
- T10_purge_tag = purge_tag;
- T10_testrange = testrange;
-
- workers = 2;
- p = t_getenv("ISC_TASK_WORKERS");
- if (p != NULL)
- workers = atoi(p);
-
- mctx = NULL;
- isc_result = isc_mem_create(0, 0, &mctx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mem_create failed %s\n",
- isc_result_totext(isc_result));
- ++*nprobs;
- return;
- }
-
- isc_result = isc_mutex_init(&T10_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_init failed %s\n",
- isc_result_totext(isc_result));
- isc_mem_destroy(&mctx);
- ++*nprobs;
- return;
- }
-
- isc_result = isc_condition_init(&T10_cv);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_condition_init failed %s\n",
- isc_result_totext(isc_result));
- isc_mem_destroy(&mctx);
- DESTROYLOCK(&T10_mx);
- ++*nprobs;
- return;
- }
-
- tmgr = NULL;
- isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_taskmgr_create failed %s\n",
- isc_result_totext(isc_result));
- isc_mem_destroy(&mctx);
- DESTROYLOCK(&T10_mx);
- (void) isc_condition_destroy(&T10_cv);
- ++*nprobs;
- return;
- }
-
- task = NULL;
- isc_result = isc_task_create(tmgr, 0, &task);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_task_create failed %s\n",
- isc_result_totext(isc_result));
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- DESTROYLOCK(&T10_mx);
- (void) isc_condition_destroy(&T10_cv);
- ++*nprobs;
- return;
- }
-
- isc_result = isc_task_onshutdown(task, t10_sde, NULL);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_task_onshutdown returned %s\n",
- isc_result_totext(isc_result));
- isc_task_destroy(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- DESTROYLOCK(&T10_mx);
- (void) isc_condition_destroy(&T10_cv);
- ++*nprobs;
- return;
- }
-
- /*
- * Block the task on T10_cv.
- */
- event = isc_event_allocate(mctx, (void *)1, (isc_eventtype_t)T_CONTROL,
- t10_event1, NULL, sizeof(*event));
-
- if (event == NULL) {
- t_info("isc_event_allocate failed\n");
- isc_task_destroy(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- DESTROYLOCK(&T10_mx);
- (void) isc_condition_destroy(&T10_cv);
- ++*nprobs;
- return;
- }
- isc_task_send(task, &event);
-
- /*
- * Fill the task's queue with some messages with varying
- * sender, type, tag, and purgable attribute values.
- */
-
- event_cnt = 0;
- for (sender_cnt = 0; sender_cnt < T10_SENDERCNT; ++sender_cnt) {
- for (type_cnt = 0; type_cnt < T10_TYPECNT; ++type_cnt) {
- for (tag_cnt = 0; tag_cnt < T10_TAGCNT; ++tag_cnt) {
- eventtab[event_cnt] =
- isc_event_allocate(mctx,
- &senders[sender + sender_cnt],
- (isc_eventtype_t)(type + type_cnt),
- t10_event2, NULL, sizeof(*event));
-
- if (eventtab[event_cnt] == NULL) {
- t_info("isc_event_allocate failed\n");
- isc_task_destroy(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- DESTROYLOCK(&T10_mx);
- (void) isc_condition_destroy(&T10_cv);
- ++*nprobs;
- return;
- }
-
- eventtab[event_cnt]->ev_tag =
- (void *)((uintptr_t)tag + tag_cnt);
-
- /*
- * Make all odd message non-purgable.
- */
- if ((sender_cnt % 2) && (type_cnt %2) &&
- (tag_cnt %2))
- eventtab[event_cnt]->ev_attributes |=
- ISC_EVENTATTR_NOPURGE;
- ++event_cnt;
- }
- }
- }
-
- for (cnt = 0; cnt < event_cnt; ++cnt)
- isc_task_send(task, &eventtab[cnt]);
-
- if (T_debug)
- t_info("%d events queued\n", cnt);
-
- if (testrange == 0) {
- /*
- * We're testing isc_task_purge.
- */
- nevents = isc_task_purge(task, purge_sender,
- (isc_eventtype_t)purge_type_first,
- purge_tag);
- if (nevents != exp_nevents) {
- t_info("*** isc_task_purge returned %d, expected %d\n",
- nevents, exp_nevents);
- ++*nfails;
- } else if (T_debug)
- t_info("isc_task_purge returned %d\n", nevents);
- } else {
- /*
- * We're testing isc_task_purgerange.
- */
- nevents = isc_task_purgerange(task, purge_sender,
- (isc_eventtype_t)purge_type_first,
- (isc_eventtype_t)purge_type_last,
- purge_tag);
- if (nevents != exp_nevents) {
- t_info("*** isc_task_purgerange returned %d, "
- "expected %d\n", nevents, exp_nevents);
- ++*nfails;
- } else if (T_debug)
- t_info("isc_task_purgerange returned %d\n", nevents);
- }
-
- isc_result = isc_mutex_lock(&T10_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_lock failed %s\n",
- isc_result_totext(isc_result));
- isc_task_destroy(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- DESTROYLOCK(&T10_mx);
- (void) isc_condition_destroy(&T10_cv);
- ++*nprobs;
- return;
- }
-
- /*
- * Unblock the task, allowing event processing.
- */
- T10_startflag = 1;
- isc_result = isc_condition_signal(&T10_cv);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_condition_signal failed %s\n",
- isc_result_totext(isc_result));
- ++*nprobs;
- }
-
- isc_task_shutdown(task);
-
- isc_interval_set(&interval, 5, 0);
-
- /*
- * Wait for shutdown processing to complete.
- */
- while (T10_shutdownflag == 0) {
- isc_result = isc_time_nowplusinterval(&now, &interval);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_time_nowplusinterval failed %s\n",
- isc_result_totext(isc_result));
- isc_task_detach(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- DESTROYLOCK(&T10_mx);
- (void) isc_condition_destroy(&T10_cv);
- ++*nprobs;
- return;
- }
-
- isc_result = isc_condition_waituntil(&T10_cv, &T10_mx, &now);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_condition_waituntil returned %s\n",
- isc_result_totext(isc_result));
- isc_task_detach(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- DESTROYLOCK(&T10_mx);
- (void) isc_condition_destroy(&T10_cv);
- ++*nfails;
- return;
- }
- }
-
- isc_result = isc_mutex_unlock(&T10_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_unlock failed %s\n",
- isc_result_totext(isc_result));
- ++*nprobs;
- }
-
- isc_task_detach(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- DESTROYLOCK(&T10_mx);
- (void) isc_condition_destroy(&T10_cv);
-
- if (T_debug)
- t_info("task processed %d events\n", T10_eventcnt);
-
- if ((T10_eventcnt + nevents) != event_cnt) {
- t_info("*** processed %d, purged %d, total %d\n",
- T10_eventcnt, nevents, event_cnt);
- ++*nfails;
- }
-}
-
-static int
-t_tasks10(void) {
- int result;
-
- T10_nprobs = 0;
- T10_nfails = 0;
-
- /*
- * Try purging on a specific sender.
- */
- t_info("testing purge on 2,4,8 expecting 1\n");
- t_taskpurge_x(1, 4, 7, &senders[2], 4, 4, (void *)8, 1, &T10_nfails,
- &T10_nprobs, 0);
-
- /*
- * Try purging on all senders.
- */
- t_info("testing purge on 0,4,8 expecting 3\n");
- t_taskpurge_x(1, 4, 7, NULL, 4, 4, (void *)8, 3, &T10_nfails,
- &T10_nprobs, 0);
-
- /*
- * Try purging on all senders, specified type, all tags.
- */
- t_info("testing purge on 0,4,0 expecting 15\n");
- t_taskpurge_x(1, 4, 7, NULL, 4, 4, NULL, 15, &T10_nfails,
- &T10_nprobs, 0);
-
- /*
- * Try purging on a specified tag, no such type.
- */
- t_info("testing purge on 0,99,8 expecting 0\n");
- t_taskpurge_x(1, 4, 7, NULL, 99, 99, (void *)8, 0, &T10_nfails,
- &T10_nprobs, 0);
-
- /*
- * Try purging on specified sender, type, all tags.
- */
- t_info("testing purge on 0,5,0 expecting 5\n");
- t_taskpurge_x(1, 4, 7, &senders[3], 5, 5, NULL, 5, &T10_nfails,
- &T10_nprobs, 0);
-
- result = T_UNRESOLVED;
-
- if ((T10_nfails == 0) && (T10_nprobs == 0))
- result = T_PASS;
- else if (T10_nfails != 0)
- result = T_FAIL;
-
- return(result);
-}
-
-static const char *a10 =
- "A call to isc_task_purge(task, sender, type, tag) "
- "purges all events of type 'type' and with tag 'tag' "
- "not marked as unpurgable from sender from the task's "
- "queue and returns the number of events purged.";
-
-static void
-t10(void) {
- t_assert("tasks", 10, T_REQUIRED, "%s", a10);
-
- if (threaded)
- t_result(t_tasks10());
- else
- require_threads();
-}
-
-static int T11_nprobs;
-static int T11_nfails;
-static int T11_startflag;
-static int T11_shutdownflag;
-static int T11_eventcnt;
-static isc_mutex_t T11_mx;
-static isc_condition_t T11_cv;
-
-static void
-t11_event1(isc_task_t *task, isc_event_t *event) {
- isc_result_t isc_result;
-
- UNUSED(task);
-
- isc_result = isc_mutex_lock(&T11_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_lock failed %s\n",
- isc_result_totext(isc_result));
- ++T11_nprobs;
- }
-
- while (T11_startflag == 0) {
- isc_result = isc_condition_wait(&T11_cv, &T11_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_lock failed %s\n",
- isc_result_totext(isc_result));
- ++T11_nprobs;
- }
- }
-
- isc_result = isc_mutex_unlock(&T11_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_unlock failed %s\n",
- isc_result_totext(isc_result));
- ++T11_nprobs;
- }
-
- isc_event_free(&event);
-}
-
-static void
-t11_event2(isc_task_t *task, isc_event_t *event) {
- UNUSED(task);
-
- ++T11_eventcnt;
- isc_event_free(&event);
-}
-
-
-static void
-t11_sde(isc_task_t *task, isc_event_t *event) {
- isc_result_t isc_result;
-
- UNUSED(task);
-
- isc_result = isc_mutex_lock(&T11_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_lock failed %s\n",
- isc_result_totext(isc_result));
- ++T11_nprobs;
- }
-
- ++T11_shutdownflag;
-
- isc_result = isc_condition_signal(&T11_cv);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_condition_signal failed %s\n",
- isc_result_totext(isc_result));
- ++T11_nprobs;
- }
-
- isc_result = isc_mutex_unlock(&T11_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_unlock failed %s\n",
- isc_result_totext(isc_result));
- ++T11_nprobs;
- }
-
- isc_event_free(&event);
-}
-
-static int
-t_tasks11(int purgable) {
- char *p;
- isc_mem_t *mctx;
- isc_taskmgr_t *tmgr;
- isc_task_t *task;
- isc_boolean_t rval;
- unsigned int workers;
- isc_result_t isc_result;
- isc_event_t *event1;
- isc_event_t *event2, *event2_clone;
- isc_time_t now;
- isc_interval_t interval;
- int result;
-
- T11_startflag = 0;
- T11_shutdownflag = 0;
- T11_eventcnt = 0;
-
- workers = 2;
- p = t_getenv("ISC_TASK_WORKERS");
- if (p != NULL)
- workers = atoi(p);
-
- mctx = NULL;
- isc_result = isc_mem_create(0, 0, &mctx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mem_create failed %s\n",
- isc_result_totext(isc_result));
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_mutex_init(&T11_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_init failed %s\n",
- isc_result_totext(isc_result));
- isc_mem_destroy(&mctx);
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_condition_init(&T11_cv);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_condition_init failed %s\n",
- isc_result_totext(isc_result));
- isc_mem_destroy(&mctx);
- DESTROYLOCK(&T11_mx);
- return(T_UNRESOLVED);
- }
-
- tmgr = NULL;
- isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_taskmgr_create failed %s\n",
- isc_result_totext(isc_result));
- isc_mem_destroy(&mctx);
- DESTROYLOCK(&T11_mx);
- (void) isc_condition_destroy(&T11_cv);
- return(T_UNRESOLVED);
- }
-
- task = NULL;
- isc_result = isc_task_create(tmgr, 0, &task);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_task_create failed %s\n",
- isc_result_totext(isc_result));
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- DESTROYLOCK(&T11_mx);
- (void) isc_condition_destroy(&T11_cv);
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_task_onshutdown(task, t11_sde, NULL);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_task_onshutdown returned %s\n",
- isc_result_totext(isc_result));
- isc_task_destroy(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- DESTROYLOCK(&T11_mx);
- (void) isc_condition_destroy(&T11_cv);
- return(T_UNRESOLVED);
- }
-
- /*
- * Block the task on T11_cv.
- */
- event1 = isc_event_allocate(mctx, (void *)1, (isc_eventtype_t)1,
- t11_event1, NULL, sizeof(*event1));
- if (event1 == NULL) {
- t_info("isc_event_allocate failed\n");
- isc_task_destroy(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- DESTROYLOCK(&T11_mx);
- (void) isc_condition_destroy(&T11_cv);
- return(T_UNRESOLVED);
- }
- isc_task_send(task, &event1);
-
- event2 = isc_event_allocate(mctx, (void *)1, (isc_eventtype_t)1,
- t11_event2, NULL, sizeof(*event2));
- if (event2 == NULL) {
- t_info("isc_event_allocate failed\n");
- isc_task_destroy(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- DESTROYLOCK(&T11_mx);
- (void) isc_condition_destroy(&T11_cv);
- return(T_UNRESOLVED);
- }
- event2_clone = event2;
- if (purgable)
- event2->ev_attributes &= ~ISC_EVENTATTR_NOPURGE;
- else
- event2->ev_attributes |= ISC_EVENTATTR_NOPURGE;
-
- isc_task_send(task, &event2);
-
- rval = isc_task_purgeevent(task, event2_clone);
- if (rval != (purgable ? ISC_TRUE : ISC_FALSE)) {
- t_info("isc_task_purgeevent returned %s, expected %s\n",
- (rval ? "ISC_TRUE" : "ISC_FALSE"),
- (purgable ? "ISC_TRUE" : "ISC_FALSE"));
- ++T11_nfails;
- }
-
- isc_result = isc_mutex_lock(&T11_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_lock failed %s\n",
- isc_result_totext(isc_result));
- ++T11_nprobs;
- }
-
- /*
- * Unblock the task, allowing event processing.
- */
- T11_startflag = 1;
- isc_result = isc_condition_signal(&T11_cv);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_condition_signal failed %s\n",
- isc_result_totext(isc_result));
- ++T11_nprobs;
- }
-
- isc_task_shutdown(task);
-
- isc_interval_set(&interval, 5, 0);
-
- /*
- * Wait for shutdown processing to complete.
- */
- while (T11_shutdownflag == 0) {
- isc_result = isc_time_nowplusinterval(&now, &interval);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_time_nowplusinterval failed %s\n",
- isc_result_totext(isc_result));
- ++T11_nprobs;
- }
-
- isc_result = isc_condition_waituntil(&T11_cv, &T11_mx, &now);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_condition_waituntil returned %s\n",
- isc_result_totext(isc_result));
- ++T11_nprobs;
- }
- }
-
- isc_result = isc_mutex_unlock(&T11_mx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mutex_unlock failed %s\n",
- isc_result_totext(isc_result));
- ++T11_nprobs;
- }
-
- isc_task_detach(&task);
- isc_taskmgr_destroy(&tmgr);
- isc_mem_destroy(&mctx);
- DESTROYLOCK(&T11_mx);
- (void) isc_condition_destroy(&T11_cv);
-
- if (T11_eventcnt != (purgable ? 0 : 1)) {
- t_info("Event was %s purged\n",
- (purgable ? "not" : "unexpectedly"));
- ++T11_nfails;
- }
-
- result = T_UNRESOLVED;
-
- if ((T11_nfails == 0) && (T11_nprobs == 0))
- result = T_PASS;
- else if (T11_nfails)
- result = T_FAIL;
-
- return(result);
-}
-
-static const char *a11 =
- "When the event is marked as purgable, a call to "
- "isc_task_purgeevent(task, event) purges the event 'event' "
- "from the task's queue and returns ISC_TRUE.";
-
-static void
-t11(void) {
- t_assert("tasks", 11, T_REQUIRED, "%s", a11);
-
- if (threaded)
- t_result(t_tasks11(1));
- else
- require_threads();
-}
-
-static const char *a12 =
- "When the event is not marked as purgable, a call to "
- "isc_task_purgeevent(task, event) does not purge the "
- "event 'event' from the task's queue and returns "
- "ISC_FALSE.";
-
-static int
-t_tasks12(void) {
- return(t_tasks11(0));
-}
-
-static void
-t12(void) {
- t_assert("tasks", 12, T_REQUIRED, "%s", a12);
-
- if (threaded)
- t_result(t_tasks12());
- else
- require_threads();
-}
-
-static int T13_nfails;
-static int T13_nprobs;
-
-static const char *a13 =
- "A call to "
- "isc_event_purgerange(task, sender, first, last, tag) "
- "purges all events not marked unpurgable from "
- "sender 'sender' and of type within the range 'first' "
- "to 'last' inclusive from the task's event queue and "
- "returns the number of tasks purged.";
-
-static int
-t_tasks13(void) {
- int result;
-
- T13_nfails = 0;
- T13_nprobs = 0;
-
- /*
- * First let's try the same cases we used in t10.
- */
-
- /*
- * Try purging on a specific sender.
- */
- t_info("testing purge on 2,4,8 expecting 1\n");
- t_taskpurge_x(1, 4, 7, &senders[2], 4, 4, (void *)8, 1,
- &T13_nfails, &T13_nprobs, 1);
-
- /*
- * Try purging on all senders.
- */
- t_info("testing purge on 0,4,8 expecting 3\n");
- t_taskpurge_x(1, 4, 7, NULL, 4, 4, (void *)8, 3,
- &T13_nfails, &T13_nprobs, 1);
-
- /*
- * Try purging on all senders, specified type, all tags.
- */
- t_info("testing purge on 0,4,0 expecting 15\n");
- t_taskpurge_x(1, 4, 7, NULL, 4, 4, NULL, 15, &T13_nfails, &T13_nprobs, 1);
-
- /*
- * Try purging on a specified tag, no such type.
- */
- t_info("testing purge on 0,99,8 expecting 0\n");
- t_taskpurge_x(1, 4, 7, NULL, 99, 99, (void *)8, 0,
- &T13_nfails, &T13_nprobs, 1);
-
- /*
- * Try purging on specified sender, type, all tags.
- */
- t_info("testing purge on 3,5,0 expecting 5\n");
- t_taskpurge_x(1, 4, 7, &senders[3], 5, 5, 0, 5, &T13_nfails, &T13_nprobs, 1);
-
- /*
- * Now let's try some ranges.
- */
-
- t_info("testing purgerange on 2,4-5,8 expecting 2\n");
- t_taskpurge_x(1, 4, 7, &senders[2], 4, 5, (void *)8, 1,
- &T13_nfails, &T13_nprobs, 1);
-
- /*
- * Try purging on all senders.
- */
- t_info("testing purge on 0,4-5,8 expecting 5\n");
- t_taskpurge_x(1, 4, 7, NULL, 4, 5, (void *)8, 5,
- &T13_nfails, &T13_nprobs, 1);
-
- /*
- * Try purging on all senders, specified type, all tags.
- */
- t_info("testing purge on 0,5-6,0 expecting 28\n");
- t_taskpurge_x(1, 4, 7, NULL, 5, 6, NULL, 28, &T13_nfails, &T13_nprobs, 1);
-
- /*
- * Try purging on a specified tag, no such type.
- */
- t_info("testing purge on 0,99-101,8 expecting 0\n");
- t_taskpurge_x(1, 4, 7, NULL, 99, 101, (void *)8, 0,
- &T13_nfails, &T13_nprobs, 1);
-
- /*
- * Try purging on specified sender, type, all tags.
- */
- t_info("testing purge on 3,5-6,0 expecting 10\n");
- t_taskpurge_x(1, 4, 7, &senders[3], 5, 6, NULL, 10, &T13_nfails,
- &T13_nprobs, 1);
-
- result = T_UNRESOLVED;
-
- if ((T13_nfails == 0) && (T13_nprobs == 0))
- result = T_PASS;
- else if (T13_nfails)
- result = T_FAIL;
-
- return (result);
-}
-
-static void
-t13(void) {
- t_assert("tasks", 13, T_REQUIRED, "%s", a13);
-
- if (threaded)
- t_result(t_tasks13());
- else
- require_threads();
-}
-
-#define T14_NTASKS 10
-#define T14_EXCLTASK 6
-
-int t14_exclusiveerror = ISC_R_SUCCESS;
-int t14_error = 0;
-int t14_done = 0;
-
-int spin(int n);
-
-int t14_active[T14_NTASKS];
-
-static void
-t14_callback(isc_task_t *task, isc_event_t *event) {
- int taskno = *(int *)(event->ev_arg);
-
-
- t_info("task enter %d\n", taskno);
- if (taskno == T14_EXCLTASK) {
- int i;
- t14_exclusiveerror = isc_task_beginexclusive(task);
- if (t14_exclusiveerror == ISC_R_SUCCESS)
- t_info("task %d got exclusive access\n", taskno);
- else
- t_info("task %d failed to got exclusive access: %d\n",
- taskno, t14_exclusiveerror);
- for (i = 0; i < T14_NTASKS; i++) {
- t_info("task %d state %d\n", i , t14_active[i]);
- if (t14_active[i])
- t14_error++;
- }
- isc_task_endexclusive(task);
- t14_done = 1;
- } else {
- t14_active[taskno]++;
- (void) spin(10000000);
- t14_active[taskno]--;
- }
- t_info("task exit %d\n", taskno);
- if (t14_done) {
- isc_mem_put(event->ev_destroy_arg, event->ev_arg, sizeof (int));
- isc_event_free(&event);
- } else {
- isc_task_send(task, &event);
- }
-}
-
-int spin(int n) {
- int i;
- int r = 0;
- for (i = 0; i < n; i++) {
- r += i;
- if (r > 1000000)
- r = 0;
- }
- return (r);
-}
-
-static int
-t_tasks14(void) {
- char *p;
- isc_mem_t *mctx;
- isc_taskmgr_t *manager;
- isc_task_t *tasks[T14_NTASKS];
- unsigned int workers;
- isc_result_t isc_result;
- int i;
-
- manager = NULL;
- mctx = NULL;
-
- for (i = 0; i < T14_NTASKS; i++)
- tasks[i] = NULL;
-
- workers = 4;
- p = t_getenv("ISC_TASK_WORKERS");
- if (p != NULL)
- workers = atoi(p);
- if (workers < 1) {
- t_info("Bad config value for ISC_TASK_WORKERS, %d\n", workers);
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_mem_create(0, 0, &mctx);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_mem_create failed %d\n", isc_result);
- return(T_UNRESOLVED);
- }
-
- isc_result = isc_taskmgr_create(mctx, workers, 0, &manager);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_taskmgr_create failed %d\n", isc_result);
- return(T_FAIL);
- }
-
- for (i = 0; i < T14_NTASKS; i++) {
- isc_event_t *event;
- int *v;
-
- isc_result = isc_task_create(manager, 0, &tasks[i]);
- if (isc_result != ISC_R_SUCCESS) {
- t_info("isc_task_create failed %d\n", isc_result);
- return(T_FAIL);
- }
-
- v = isc_mem_get(mctx, sizeof *v);
- if (v == NULL) {
- isc_task_detach(&tasks[i]);
- t_info("isc_mem_get failed\n");
- return(T_FAIL);
- }
- *v = i;
-
- event = isc_event_allocate(mctx, NULL, 1, t14_callback,
- v, sizeof(*event));
- if (event == NULL) {
- isc_mem_put(mctx, v, sizeof *v);
- t_info("isc_event_allocate failed\n");
- return(T_UNRESOLVED);
- }
- isc_task_send(tasks[i], &event);
- }
-
- for (i = 0; i < T14_NTASKS; i++) {
- isc_task_detach(&tasks[i]);
- }
-
- isc_taskmgr_destroy(&manager);
-
- if (t14_exclusiveerror != ISC_R_SUCCESS || t14_error) {
- if (t14_exclusiveerror != ISC_R_SUCCESS)
- t_info("isc_task_beginexclusive() failed\n");
- if (t14_error)
- t_info("mutual access occurred\n");
- return(T_FAIL);
- }
-
- isc_mem_destroy(&mctx);
- return(T_PASS);
-}
-
-static void
-t14(void) {
- int result;
-
- t_assert("tasks", 14, T_REQUIRED, "%s",
- "isc_task_beginexclusive() gets exclusive access");
- result = t_tasks14();
- t_result(result);
-}
-
-testspec_t T_testlist[] = {
- { (PFV) t1, "basic task subsystem" },
- { (PFV) t2, "maxtasks" },
- { (PFV) t3, "isc_task_shutdown" },
- { (PFV) t4, "isc_task_shutdown" },
- { (PFV) t7, "isc_task_create" },
- { (PFV) t10, "isc_task_purge" },
- { (PFV) t11, "isc_task_purgeevent" },
- { (PFV) t12, "isc_task_purgeevent" },
- { (PFV) t13, "isc_task_purgerange" },
- { (PFV) t14, "isc_task_beginexclusive" },
- { (PFV) 0, NULL }
-};
-
-#ifdef WIN32
-int
-main(int argc, char **argv) {
- t_settests(T_testlist);
- return (t_main(argc, argv));
-}
-#endif
#include <atf-c.h>
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h> /* uintptr_t */
+#endif
+#include <stdlib.h>
#include <unistd.h>
+#include <isc/condition.h>
+#include <isc/mem.h>
+#include <isc/platform.h>
#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/timer.h>
#include <isc/util.h>
#include "isctest.h"
* Helper functions
*/
-/* task event handler, sets a boolean to true */
+static isc_mutex_t lock;
+static isc_condition_t cv;
int counter = 0;
-isc_mutex_t set_lock;
+static int active[10];
+static isc_boolean_t done = ISC_FALSE;
static void
set(isc_task_t *task, isc_event_t *event) {
UNUSED(task);
isc_event_free(&event);
- LOCK(&set_lock);
+ LOCK(&lock);
*value = counter++;
- UNLOCK(&set_lock);
+ UNLOCK(&lock);
}
static void
UNUSED(task);
isc_event_free(&event);
- LOCK(&set_lock);
+ LOCK(&lock);
*value = (int) isc_taskmgr_mode(taskmgr);
counter++;
- UNLOCK(&set_lock);
+ UNLOCK(&lock);
isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_normal);
}
ATF_TC_BODY(all_events, tc) {
isc_result_t result;
isc_task_t *task = NULL;
- isc_event_t *event;
+ isc_event_t *event = NULL;
int a = 0, b = 0;
int i = 0;
counter = 1;
- result = isc_mutex_init(&set_lock);
+ result = isc_mutex_init(&lock);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
result = isc_test_begin(NULL, ISC_TRUE, 0);
ATF_TC_BODY(privileged_events, tc) {
isc_result_t result;
isc_task_t *task1 = NULL, *task2 = NULL;
- isc_event_t *event;
+ isc_event_t *event = NULL;
int a = 0, b = 0, c = 0, d = 0, e = 0;
int i = 0;
UNUSED(tc);
counter = 1;
- result = isc_mutex_init(&set_lock);
+ result = isc_mutex_init(&lock);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
result = isc_test_begin(NULL, ISC_TRUE, 0);
ATF_TC_BODY(privilege_drop, tc) {
isc_result_t result;
isc_task_t *task1 = NULL, *task2 = NULL;
- isc_event_t *event;
+ isc_event_t *event = NULL;
int a = -1, b = -1, c = -1, d = -1, e = -1; /* non valid states */
int i = 0;
UNUSED(tc);
counter = 1;
- result = isc_mutex_init(&set_lock);
+ result = isc_mutex_init(&lock);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
result = isc_test_begin(NULL, ISC_TRUE, 0);
isc_test_end();
}
+/*
+ * Basic task functions:
+ */
+static void
+basic_cb(isc_task_t *task, isc_event_t *event) {
+ int i;
+ int j;
+
+ UNUSED(task);
+
+ j = 0;
+ for (i = 0; i < 1000000; i++) {
+ j += 100;
+ }
+
+ printf("task %s\n", (char *)event->ev_arg);
+ isc_event_free(&event);
+}
+
+static void
+basic_shutdown(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+
+ printf("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);
+
+ printf("%s\n", (char *)event->ev_arg);
+ isc_event_free(&event);
+}
+
+static char one[] = "1";
+static char two[] = "2";
+static char three[] = "3";
+static char four[] = "4";
+static char tick[] = "tick";
+static char tock[] = "tock";
+
+
+ATF_TC(basic);
+ATF_TC_HEAD(basic, tc) {
+ atf_tc_set_md_var(tc, "descr", "basic task system check");
+}
+ATF_TC_BODY(basic, tc) {
+ isc_result_t result;
+ isc_task_t *task1 = NULL;
+ isc_task_t *task2 = NULL;
+ isc_task_t *task3 = NULL;
+ isc_task_t *task4 = NULL;
+ isc_event_t *event = NULL;
+ isc_timer_t *ti1 = NULL;
+ isc_timer_t *ti2 = NULL;
+ isc_time_t absolute;
+ isc_interval_t interval;
+ char *testarray[] = {
+ one, one, one, one, one, one, one, one, one,
+ two, three, four, two, three, four, NULL
+ };
+ int i;
+
+ UNUSED(tc);
+
+ result = isc_test_begin(NULL, ISC_TRUE, 2);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = isc_task_create(taskmgr, 0, &task1);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+ result = isc_task_create(taskmgr, 0, &task2);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+ result = isc_task_create(taskmgr, 0, &task3);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+ result = isc_task_create(taskmgr, 0, &task4);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = isc_task_onshutdown(task1, basic_shutdown, one);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+ result = isc_task_onshutdown(task2, basic_shutdown, two);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+ result = isc_task_onshutdown(task3, basic_shutdown, three);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+ result = isc_task_onshutdown(task4, basic_shutdown, four);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ isc_time_settoepoch(&absolute);
+ isc_interval_set(&interval, 1, 0);
+ result = isc_timer_create(timermgr, isc_timertype_ticker,
+ &absolute, &interval,
+ task1, basic_tick, tick, &ti1);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ ti2 = NULL;
+ isc_time_settoepoch(&absolute);
+ isc_interval_set(&interval, 1, 0);
+ result = isc_timer_create(timermgr, isc_timertype_ticker,
+ &absolute, &interval,
+ task2, basic_tick, tock, &ti2);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+#ifndef WIN32
+ sleep(2);
+#else
+ Sleep(2000);
+#endif
+
+ for (i = 0; testarray[i] != NULL; i++) {
+ /*
+ * Note: (void *)1 is used as a sender here, since some
+ * compilers don't like casting a function pointer to a
+ * (void *).
+ *
+ * In a real use, it is more likely the sender would be a
+ * structure (socket, timer, task, etc) but this is just a
+ * test program.
+ */
+ event = isc_event_allocate(mctx, (void *)1, 1, basic_cb,
+ testarray[i], sizeof(*event));
+ ATF_REQUIRE(event != NULL);
+ isc_task_send(task1, &event);
+ }
+
+ (void)isc_task_purge(task3, NULL, 0, 0);
+
+ isc_task_detach(&task1);
+ isc_task_detach(&task2);
+ isc_task_detach(&task3);
+ isc_task_detach(&task4);
+
+#ifndef WIN32
+ sleep(10);
+#else
+ Sleep(10000);
+#endif
+ isc_timer_detach(&ti1);
+ isc_timer_detach(&ti2);
+
+ isc_test_end();
+}
+
+/*
+ * Exclusive mode test:
+ * When one task enters exclusive mode, all other active
+ * tasks complete first.
+ */
+static
+int spin(int n) {
+ int i;
+ int r = 0;
+ for (i = 0; i < n; i++) {
+ r += i;
+ if (r > 1000000)
+ r = 0;
+ }
+ return (r);
+}
+
+static void
+exclusive_cb(isc_task_t *task, isc_event_t *event) {
+ int taskno = *(int *)(event->ev_arg);
+
+ printf("task enter %d\n", taskno);
+
+ /* task chosen from the middle of the range */
+ if (taskno == 6) {
+ isc_result_t result;
+ int i;
+
+ result = isc_task_beginexclusive(task);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ for (i = 0; i < 10; i++) {
+ ATF_CHECK(active[i] == 0);
+ }
+
+ isc_task_endexclusive(task);
+ done = ISC_TRUE;
+ } else {
+ active[taskno]++;
+ (void) spin(10000000);
+ active[taskno]--;
+ }
+
+ printf("task exit %d\n", taskno);
+
+ if (done) {
+ isc_mem_put(event->ev_destroy_arg, event->ev_arg, sizeof (int));
+ isc_event_free(&event);
+ } else {
+ isc_task_send(task, &event);
+ }
+}
+
+ATF_TC(task_exclusive);
+ATF_TC_HEAD(task_exclusive, tc) {
+ atf_tc_set_md_var(tc, "descr", "test exclusive mode");
+}
+ATF_TC_BODY(task_exclusive, tc) {
+ isc_task_t *tasks[10];
+ isc_result_t result;
+ int i;
+
+ UNUSED(tc);
+
+ result = isc_test_begin(NULL, ISC_TRUE, 4);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ for (i = 0; i < 10; i++) {
+ isc_event_t *event = NULL;
+ int *v;
+
+ tasks[i] = NULL;
+
+ result = isc_task_create(taskmgr, 0, &tasks[i]);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ v = isc_mem_get(mctx, sizeof *v);
+ ATF_REQUIRE(v != NULL);
+
+ *v = i;
+
+ event = isc_event_allocate(mctx, NULL, 1, exclusive_cb,
+ v, sizeof(*event));
+ ATF_REQUIRE(event != NULL);
+
+ isc_task_send(tasks[i], &event);
+ }
+
+ for (i = 0; i < 10; i++) {
+ isc_task_detach(&tasks[i]);
+ }
+ isc_test_end();
+}
+
+/*
+ * 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);
+ } else {
+ LOCK(&lock);
+ done = ISC_TRUE;
+ SIGNAL(&cv);
+ UNLOCK(&lock);
+
+ isc_event_free(&event);
+ isc_taskmgr_destroy(&taskmgr);
+ isc_mem_destroy(&mctx);
+
+ isc_condition_destroy(&cv);
+ DESTROYLOCK(&lock);
+ }
+}
+
+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);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = isc_task_onshutdown(newtask, maxtask_shutdown,
+ (void *)task);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ isc_task_send(newtask, &event);
+ } else if (task != NULL) {
+ isc_task_destroy(&task);
+ }
+}
+
+ATF_TC(manytasks);
+ATF_TC_HEAD(manytasks, tc) {
+ atf_tc_set_md_var(tc, "descr", "many tasks");
+}
+ATF_TC_BODY(manytasks, tc) {
+ isc_result_t result;
+ isc_event_t *event = NULL;
+ uintptr_t ntasks = 10000;
+
+ UNUSED(tc);
+
+ printf("Testing with %lu tasks\n", (unsigned long)ntasks);
+
+ result = isc_mutex_init(&lock);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = isc_condition_init(&cv);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = isc_mem_create(0, 0, &mctx);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = isc_taskmgr_create(mctx, 4, 0, &taskmgr);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ event = isc_event_allocate(mctx, (void *)1, 1, maxtask_cb,
+ (void *)ntasks, sizeof(*event));
+ ATF_REQUIRE(event != NULL);
+
+ LOCK(&lock);
+ maxtask_cb(NULL, event);
+ while (!done) {
+ WAIT(&cv, &lock);
+ }
+}
+
+
+/*
+ * Shutdown test:
+ * When isc_task_shutdown() is called, shutdown events are posted
+ * in LIFO order.
+ */
+
+static int senders[4];
+static int nevents = 0;
+static int nsdevents = 0;
+
+static void
+sd_sde1(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+
+ ATF_CHECK_EQ(nevents, 256);
+ ATF_REQUIRE_EQ(nsdevents, 1);
+ ++nsdevents;
+ printf("shutdown 1\n");
+
+ isc_event_free(&event);
+}
+
+static void
+sd_sde2(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+
+ ATF_CHECK_EQ(nevents, 256);
+ ATF_REQUIRE_EQ(nsdevents, 0);
+ ++nsdevents;
+ printf("shutdown 2\n");
+
+ isc_event_free(&event);
+}
+
+static void
+sd_event1(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+
+ LOCK(&lock);
+ while (!done) {
+ WAIT(&cv, &lock);
+ }
+
+ printf("event 1\n");
+
+ isc_event_free(&event);
+}
+
+static void
+sd_event2(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+
+ ++nevents;
+
+ printf("event 2\n");
+
+ isc_event_free(&event);
+}
+
+ATF_TC(shutdown);
+ATF_TC_HEAD(shutdown, tc) {
+ atf_tc_set_md_var(tc, "descr", "task shutdown");
+}
+ATF_TC_BODY(shutdown, tc) {
+ isc_result_t result;
+ isc_eventtype_t event_type;
+ isc_event_t *event = NULL;
+ isc_task_t *task = NULL;
+ int i;
+
+ nevents = nsdevents = 0;
+ done = ISC_FALSE;
+
+ event_type = 3;
+
+ result = isc_test_begin(NULL, ISC_TRUE, 4);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = isc_mutex_init(&lock);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = isc_condition_init(&cv);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ LOCK(&lock);
+
+ task = NULL;
+ result = isc_task_create(taskmgr, 0, &task);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ /*
+ * This event causes the task to wait on cv.
+ */
+ event = isc_event_allocate(mctx, &senders[1], event_type, sd_event1,
+ NULL, sizeof(*event));
+ ATF_REQUIRE(event != NULL);
+ 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(mctx, &senders[1], event_type,
+ sd_event2, NULL, sizeof(*event));
+ ATF_REQUIRE(event != NULL);
+ isc_task_send(task, &event);
+ }
+
+ /*
+ * Now we register two shutdown events.
+ */
+ result = isc_task_onshutdown(task, sd_sde1, NULL);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = isc_task_onshutdown(task, sd_sde2, NULL);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ isc_task_shutdown(task);
+
+ /*
+ * Now we free the task by signaling cv.
+ */
+ done = ISC_TRUE;
+ SIGNAL(&cv);
+ UNLOCK(&lock);
+
+ isc_task_detach(&task);
+
+ isc_test_end();
+
+ ATF_REQUIRE_EQ(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 (!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);
+}
+
+ATF_TC(post_shutdown);
+ATF_TC_HEAD(post_shutdown, tc) {
+ atf_tc_set_md_var(tc, "descr", "post-shutdown");
+}
+ATF_TC_BODY(post_shutdown, tc) {
+ isc_result_t result;
+ isc_eventtype_t event_type;
+ isc_event_t *event;
+ isc_task_t *task;
+
+ done = ISC_FALSE;
+ event_type = 4;
+
+ result = isc_mutex_init(&lock);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = isc_condition_init(&cv);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = isc_test_begin(NULL, ISC_TRUE, 2);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ LOCK(&lock);
+
+ task = NULL;
+ result = isc_task_create(taskmgr, 0, &task);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ /*
+ * This event causes the task to wait on cv.
+ */
+ event = isc_event_allocate(mctx, &senders[1], event_type, psd_event1,
+ NULL, sizeof(*event));
+ ATF_REQUIRE(event != NULL);
+ isc_task_send(task, &event);
+
+ isc_task_shutdown(task);
+
+ result = isc_task_onshutdown(task, psd_sde, NULL);
+ ATF_CHECK_EQ(result, ISC_R_SHUTTINGDOWN);
+
+ /*
+ * Release the task.
+ */
+ done = ISC_TRUE;
+
+ SIGNAL(&cv);
+ UNLOCK(&lock);
+
+ isc_task_detach(&task);
+ isc_test_end();
+
+ (void) isc_condition_destroy(&cv);
+ DESTROYLOCK(&lock);
+}
+
+/*
+ * Helper for the purge tests below:
+ */
+
+#define SENDERCNT 3
+#define TYPECNT 4
+#define TAGCNT 5
+#define NEVENTS (SENDERCNT * TYPECNT * TAGCNT)
+
+static isc_boolean_t testrange;
+static void *purge_sender;
+static isc_eventtype_t purge_type_first;
+static isc_eventtype_t purge_type_last;
+static void *purge_tag;
+static int eventcnt;
+
+isc_boolean_t started = ISC_FALSE;
+
+static void
+pg_event1(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+
+ LOCK(&lock);
+ while (!started) {
+ WAIT(&cv, &lock);
+ }
+ UNLOCK(&lock);
+
+ isc_event_free(&event);
+}
+
+static void
+pg_event2(isc_task_t *task, isc_event_t *event) {
+ isc_boolean_t sender_match = ISC_FALSE;
+ isc_boolean_t type_match = ISC_FALSE;
+ isc_boolean_t tag_match = ISC_FALSE;
+
+ UNUSED(task);
+
+ if ((purge_sender == NULL) || (purge_sender == event->ev_sender)) {
+ sender_match = ISC_TRUE;
+ }
+
+ if (testrange) {
+ if ((purge_type_first <= event->ev_type) &&
+ (event->ev_type <= purge_type_last))
+ {
+ type_match = ISC_TRUE;
+ }
+ } else {
+ if (purge_type_first == event->ev_type) {
+ type_match = ISC_TRUE;
+ }
+ }
+
+ if ((purge_tag == NULL) || (purge_tag == event->ev_tag)) {
+ tag_match = ISC_TRUE;
+ }
+
+ if (sender_match && type_match && tag_match) {
+ if (event->ev_attributes & ISC_EVENTATTR_NOPURGE) {
+ printf("event %p,%d,%p matched but was not purgeable\n",
+ event->ev_sender, (int)event->ev_type,
+ event->ev_tag);
+ ++eventcnt;
+ } else {
+ printf("*** event %p,%d,%p not purged\n",
+ event->ev_sender, (int)event->ev_type,
+ event->ev_tag);
+ }
+ } else {
+ ++eventcnt;
+ }
+
+ isc_event_free(&event);
+}
+
+static void
+pg_sde(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+
+ LOCK(&lock);
+ done = ISC_TRUE;
+ SIGNAL(&cv);
+ UNLOCK(&lock);
+
+ isc_event_free(&event);
+}
+
+static void
+test_purge(int sender, int type, int tag, int exp_purged) {
+ isc_result_t result;
+ isc_task_t *task = NULL;
+ isc_event_t *eventtab[NEVENTS];
+ isc_event_t *event = NULL;
+ isc_interval_t interval;
+ isc_time_t now;
+ int sender_cnt, type_cnt, tag_cnt, event_cnt, i;
+ int purged = 0;
+
+ started = ISC_FALSE;
+ done = ISC_FALSE;
+ eventcnt = 0;
+
+ result = isc_test_begin(NULL, ISC_TRUE, 2);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = isc_mutex_init(&lock);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = isc_condition_init(&cv);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = isc_task_create(taskmgr, 0, &task);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = isc_task_onshutdown(task, pg_sde, NULL);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ /*
+ * Block the task on cv.
+ */
+ event = isc_event_allocate(mctx, (void *)1, 9999,
+ pg_event1, NULL, sizeof(*event));
+
+ ATF_REQUIRE(event != NULL);
+ isc_task_send(task, &event);
+
+ /*
+ * Fill the task's queue with some messages with varying
+ * sender, type, tag, and purgeable attribute values.
+ */
+ event_cnt = 0;
+ for (sender_cnt = 0; sender_cnt < SENDERCNT; ++sender_cnt) {
+ for (type_cnt = 0; type_cnt < TYPECNT; ++type_cnt) {
+ for (tag_cnt = 0; tag_cnt < TAGCNT; ++tag_cnt) {
+ eventtab[event_cnt] =
+ isc_event_allocate(mctx,
+ &senders[sender + sender_cnt],
+ (isc_eventtype_t)(type + type_cnt),
+ pg_event2, NULL, sizeof(*event));
+
+ ATF_REQUIRE(eventtab[event_cnt] != NULL);
+
+ eventtab[event_cnt]->ev_tag =
+ (void *)((uintptr_t)tag + tag_cnt);
+
+ /*
+ * Mark events as non-purgeable if
+ * sender, type and tag are all
+ * odd-numbered. (There should be 4
+ * of these out of 60 events total.)
+ */
+ if (((sender_cnt % 2) != 0) &&
+ ((type_cnt % 2) != 0) &&
+ ((tag_cnt % 2) != 0))
+ {
+ eventtab[event_cnt]->ev_attributes |=
+ ISC_EVENTATTR_NOPURGE;
+ }
+ ++event_cnt;
+ }
+ }
+ }
+
+ for (i = 0; i < event_cnt; ++i) {
+ isc_task_send(task, &eventtab[i]);
+ }
+
+ if (testrange) {
+ /*
+ * We're testing isc_task_purgerange.
+ */
+ purged = isc_task_purgerange(task, purge_sender,
+ (isc_eventtype_t)purge_type_first,
+ (isc_eventtype_t)purge_type_last,
+ purge_tag);
+ ATF_CHECK_EQ(purged, exp_purged);
+ } else {
+ /*
+ * We're testing isc_task_purge.
+ */
+ printf("purge events %p,%d,%p\n",
+ purge_sender, purge_type_first, purge_tag);
+ purged = isc_task_purge(task, purge_sender,
+ (isc_eventtype_t)purge_type_first,
+ purge_tag);
+ printf("purged %d expected %d\n", purged, exp_purged);
+ ATF_CHECK_EQ(purged, exp_purged);
+ }
+
+ /*
+ * Unblock the task, allowing event processing.
+ */
+ LOCK(&lock);
+ started = ISC_TRUE;
+ SIGNAL(&cv);
+
+ isc_task_shutdown(task);
+
+ isc_interval_set(&interval, 5, 0);
+
+ /*
+ * Wait for shutdown processing to complete.
+ */
+ while (!done) {
+ result = isc_time_nowplusinterval(&now, &interval);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ WAITUNTIL(&cv, &lock, &now);
+ }
+
+ UNLOCK(&lock);
+
+ isc_task_detach(&task);
+
+ isc_test_end();
+ DESTROYLOCK(&lock);
+ (void) isc_condition_destroy(&cv);
+
+ ATF_CHECK_EQ(eventcnt, event_cnt - exp_purged);
+}
+
+/*
+ * Purge test:
+ * A call to isc_task_purge(task, sender, type, tag) purges all events of
+ * type 'type' and with tag 'tag' not marked as unpurgeable from sender
+ * from the task's " queue and returns the number of events purged.
+ */
+ATF_TC(purge);
+ATF_TC_HEAD(purge, tc) {
+ atf_tc_set_md_var(tc, "descr", "purge");
+}
+ATF_TC_BODY(purge, tc) {
+ /* Try purging on a specific sender. */
+ printf("testing purge on 2,4,8 expecting 1\n");
+ purge_sender = &senders[2];
+ purge_type_first = 4;
+ purge_type_last = 4;
+ purge_tag = (void *)8;
+ testrange = ISC_FALSE;
+ test_purge(1, 4, 7, 1);
+
+ /* Try purging on all senders. */
+ printf("testing purge on 0,4,8 expecting 3\n");
+ purge_sender = NULL;
+ purge_type_first = 4;
+ purge_type_last = 4;
+ purge_tag = (void *)8;
+ testrange = ISC_FALSE;
+ test_purge(1, 4, 7, 3);
+
+ /* Try purging on all senders, specified type, all tags. */
+ printf("testing purge on 0,4,0 expecting 15\n");
+ purge_sender = NULL;
+ purge_type_first = 4;
+ purge_type_last = 4;
+ purge_tag = NULL;
+ testrange = ISC_FALSE;
+ test_purge(1, 4, 7, 15);
+
+ /* Try purging on a specified tag, no such type. */
+ printf("testing purge on 0,99,8 expecting 0\n");
+ purge_sender = NULL;
+ purge_type_first = 99;
+ purge_type_last = 99;
+ purge_tag = (void *)8;
+ testrange = ISC_FALSE;
+ test_purge(1, 4, 7, 0);
+
+ /*
+ * Try purging on specified sender, type, all tags.
+ */
+ printf("testing purge on 3,5,0 expecting 5\n");
+ purge_sender = &senders[3];
+ purge_type_first = 5;
+ purge_type_last = 5;
+ purge_tag = NULL;
+ testrange = ISC_FALSE;
+ test_purge(1, 4, 7, 5);
+}
+
+/*
+ * Purge range test:
+ * A call to isc_event_purgerange(task, sender, first, last, tag) purges
+ * all events not marked unpurgeable from sender 'sender' and of type within
+ * the range 'first' to 'last' inclusive from the task's event queue and
+ * returns the number of tasks purged.
+ */
+
+ATF_TC(purgerange);
+ATF_TC_HEAD(purgerange, tc) {
+ atf_tc_set_md_var(tc, "descr", "purge-range");
+}
+ATF_TC_BODY(purgerange, tc) {
+ /* Now let's try some ranges. */
+ printf("testing purgerange on 2,4-5,8 expecting 1\n");
+ purge_sender = &senders[2];
+ purge_type_first = 4;
+ purge_type_last = 5;
+ purge_tag = (void *)8;
+ testrange = ISC_TRUE;
+ test_purge(1, 4, 7, 1);
+
+ /* Try purging on all senders. */
+ printf("testing purge on 0,4-5,8 expecting 5\n");
+ purge_sender = NULL;
+ purge_type_first = 4;
+ purge_type_last = 5;
+ purge_tag = (void *)8;
+ testrange = ISC_TRUE;
+ test_purge(1, 4, 7, 5);
+
+ /* Try purging on all senders, specified type, all tags. */
+ printf("testing purge on 0,5-6,0 expecting 28\n");
+ purge_sender = NULL;
+ purge_type_first = 5;
+ purge_type_last = 6;
+ purge_tag = NULL;
+ testrange = ISC_TRUE;
+ test_purge(1, 4, 7, 28);
+
+ /* Try purging on a specified tag, no such type. */
+ printf("testing purge on 0,99-101,8 expecting 0\n");
+ purge_sender = NULL;
+ purge_type_first = 99;
+ purge_type_last = 101;
+ purge_tag = (void *)8;
+ testrange = ISC_TRUE;
+ test_purge(1, 4, 7, 0);
+
+ /* Try purging on specified sender, type, all tags. */
+ printf("testing purge on 3,5-6,0 expecting 10\n");
+ purge_sender = &senders[3];
+ purge_type_first = 5;
+ purge_type_last = 6;
+ purge_tag = NULL;
+ testrange = ISC_TRUE;
+ test_purge(1, 4, 7, 10);
+}
+
+/*
+ * Helpers for purge event tests
+ */
+static void
+pge_event1(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+
+ LOCK(&lock);
+ while (!started) {
+ WAIT(&cv, &lock);
+ }
+ UNLOCK(&lock);
+
+ isc_event_free(&event);
+}
+
+static void
+pge_event2(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+
+ ++eventcnt;
+ isc_event_free(&event);
+}
+
+
+static void
+pge_sde(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+
+ LOCK(&lock);
+ done = ISC_TRUE;
+ SIGNAL(&cv);
+ UNLOCK(&lock);
+
+ isc_event_free(&event);
+}
+
+static void
+try_purgeevent(isc_boolean_t purgeable) {
+ isc_result_t result;
+ isc_task_t *task = NULL;
+ isc_boolean_t purged;
+ isc_event_t *event1 = NULL;
+ isc_event_t *event2 = NULL;
+ isc_event_t *event2_clone = NULL;;
+ isc_time_t now;
+ isc_interval_t interval;
+
+ started = ISC_FALSE;
+ done = ISC_FALSE;
+ eventcnt = 0;
+
+ result = isc_mutex_init(&lock);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = isc_condition_init(&cv);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = isc_test_begin(NULL, ISC_TRUE, 2);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = isc_task_create(taskmgr, 0, &task);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = isc_task_onshutdown(task, pge_sde, NULL);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ /*
+ * Block the task on cv.
+ */
+ event1 = isc_event_allocate(mctx, (void *)1, (isc_eventtype_t)1,
+ pge_event1, NULL, sizeof(*event1));
+ ATF_REQUIRE(event1 != NULL);
+ isc_task_send(task, &event1);
+
+ event2 = isc_event_allocate(mctx, (void *)1, (isc_eventtype_t)1,
+ pge_event2, NULL, sizeof(*event2));
+ ATF_REQUIRE(event2 != NULL);
+
+ event2_clone = event2;
+
+ if (purgeable) {
+ event2->ev_attributes &= ~ISC_EVENTATTR_NOPURGE;
+ } else {
+ event2->ev_attributes |= ISC_EVENTATTR_NOPURGE;
+ }
+
+ isc_task_send(task, &event2);
+
+ purged = isc_task_purgeevent(task, event2_clone);
+ ATF_CHECK_EQ(purgeable, purged);
+
+ /*
+ * Unblock the task, allowing event processing.
+ */
+ LOCK(&lock);
+ started = ISC_TRUE;
+ SIGNAL(&cv);
+
+ isc_task_shutdown(task);
+
+ isc_interval_set(&interval, 5, 0);
+
+ /*
+ * Wait for shutdown processing to complete.
+ */
+ while (!done) {
+ result = isc_time_nowplusinterval(&now, &interval);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ WAITUNTIL(&cv, &lock, &now);
+ }
+
+ UNLOCK(&lock);
+
+ isc_task_detach(&task);
+
+ isc_test_end();
+ DESTROYLOCK(&lock);
+ (void) isc_condition_destroy(&cv);
+
+ ATF_REQUIRE_EQ(eventcnt, (purgeable ? 0 : 1));
+}
+
+/*
+ * Purge event test:
+ * When the event is marked as purgeable, a call to
+ * isc_task_purgeevent(task, event) purges the event 'event' from the
+ * task's queue and returns ISC_TRUE.
+ */
+
+ATF_TC(purgeevent);
+ATF_TC_HEAD(purgeevent, tc) {
+ atf_tc_set_md_var(tc, "descr", "purge-event");
+}
+ATF_TC_BODY(purgeevent, tc) {
+ try_purgeevent(ISC_TRUE);
+}
+
+/*
+ * Purge event not purgeable test:
+ * When the event is not marked as purgable, a call to
+ * isc_task_purgeevent(task, event) does not purge the event
+ * 'event' from the task's queue and returns ISC_FALSE.
+ */
+
+ATF_TC(purgeevent_notpurge);
+ATF_TC_HEAD(purgeevent_notpurge, tc) {
+ atf_tc_set_md_var(tc, "descr", "purge-event");
+}
+ATF_TC_BODY(purgeevent_notpurge, tc) {
+ try_purgeevent(ISC_FALSE);
+}
+
/*
* Main
*/
ATF_TP_ADD_TC(tp, all_events);
ATF_TP_ADD_TC(tp, privileged_events);
ATF_TP_ADD_TC(tp, privilege_drop);
+ ATF_TP_ADD_TC(tp, basic);
+ ATF_TP_ADD_TC(tp, task_exclusive);
+
+#ifdef ISC_PLATFORM_USETHREADS
+ ATF_TP_ADD_TC(tp, manytasks);
+ ATF_TP_ADD_TC(tp, shutdown);
+ ATF_TP_ADD_TC(tp, post_shutdown);
+ ATF_TP_ADD_TC(tp, purge);
+ ATF_TP_ADD_TC(tp, purgerange);
+ ATF_TP_ADD_TC(tp, purgeevent);
+ ATF_TP_ADD_TC(tp, purgeevent_notpurge);
+#endif
return (atf_no_error());
}