Annotation of embedaddon/ntp/lib/isc/win32/app.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
! 3: * Copyright (C) 1999-2001 Internet Software Consortium.
! 4: *
! 5: * Permission to use, copy, modify, and/or distribute this software for any
! 6: * purpose with or without fee is hereby granted, provided that the above
! 7: * copyright notice and this permission notice appear in all copies.
! 8: *
! 9: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
! 10: * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
! 11: * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
! 12: * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
! 13: * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
! 14: * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
! 15: * PERFORMANCE OF THIS SOFTWARE.
! 16: */
! 17:
! 18: /* $Id: app.c,v 1.7 2007/06/19 23:47:19 tbox Exp $ */
! 19:
! 20: #include <config.h>
! 21:
! 22: #include <sys/types.h>
! 23:
! 24: #include <stddef.h>
! 25: #include <stdlib.h>
! 26: #include <errno.h>
! 27: #include <unistd.h>
! 28: #include <process.h>
! 29:
! 30: #include <isc/app.h>
! 31: #include <isc/boolean.h>
! 32: #include <isc/condition.h>
! 33: #include <isc/msgs.h>
! 34: #include <isc/mutex.h>
! 35: #include <isc/event.h>
! 36: #include <isc/platform.h>
! 37: #include <isc/string.h>
! 38: #include <isc/task.h>
! 39: #include <isc/time.h>
! 40: #include <isc/util.h>
! 41: #include <isc/thread.h>
! 42:
! 43: static isc_eventlist_t on_run;
! 44: static isc_mutex_t lock;
! 45: static isc_boolean_t shutdown_requested = ISC_FALSE;
! 46: static isc_boolean_t running = ISC_FALSE;
! 47: /*
! 48: * We assume that 'want_shutdown' can be read and written atomically.
! 49: */
! 50: static isc_boolean_t want_shutdown = ISC_FALSE;
! 51: /*
! 52: * We assume that 'want_reload' can be read and written atomically.
! 53: */
! 54: static isc_boolean_t want_reload = ISC_FALSE;
! 55:
! 56: static isc_boolean_t blocked = ISC_FALSE;
! 57:
! 58: static isc_thread_t blockedthread;
! 59:
! 60: /* Events to wait for */
! 61:
! 62: #define NUM_EVENTS 2
! 63:
! 64: enum {
! 65: RELOAD_EVENT,
! 66: SHUTDOWN_EVENT
! 67: };
! 68:
! 69: static HANDLE hEvents[NUM_EVENTS];
! 70: DWORD dwWaitResult;
! 71:
! 72: /*
! 73: * We need to remember which thread is the main thread...
! 74: */
! 75: static isc_thread_t main_thread;
! 76:
! 77: isc_result_t
! 78: isc_app_start(void) {
! 79: isc_result_t result;
! 80:
! 81: /*
! 82: * Start an ISC library application.
! 83: */
! 84:
! 85: main_thread = GetCurrentThread();
! 86:
! 87: result = isc_mutex_init(&lock);
! 88: if (result != ISC_R_SUCCESS)
! 89: return (result);
! 90:
! 91: /* Create the reload event in a non-signaled state */
! 92: hEvents[RELOAD_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
! 93:
! 94: /* Create the shutdown event in a non-signaled state */
! 95: hEvents[SHUTDOWN_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
! 96:
! 97: ISC_LIST_INIT(on_run);
! 98: return (ISC_R_SUCCESS);
! 99: }
! 100:
! 101: isc_result_t
! 102: isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
! 103: void *arg) {
! 104: isc_event_t *event;
! 105: isc_task_t *cloned_task = NULL;
! 106: isc_result_t result;
! 107:
! 108:
! 109: LOCK(&lock);
! 110: if (running) {
! 111: result = ISC_R_ALREADYRUNNING;
! 112: goto unlock;
! 113: }
! 114:
! 115: /*
! 116: * Note that we store the task to which we're going to send the event
! 117: * in the event's "sender" field.
! 118: */
! 119: isc_task_attach(task, &cloned_task);
! 120: event = isc_event_allocate(mctx, cloned_task, ISC_APPEVENT_SHUTDOWN,
! 121: action, arg, sizeof(*event));
! 122: if (event == NULL) {
! 123: result = ISC_R_NOMEMORY;
! 124: goto unlock;
! 125: }
! 126:
! 127: ISC_LIST_APPEND(on_run, event, ev_link);
! 128: result = ISC_R_SUCCESS;
! 129:
! 130: unlock:
! 131: UNLOCK(&lock);
! 132: return (result);
! 133: }
! 134:
! 135: isc_result_t
! 136: isc_app_run(void) {
! 137: isc_event_t *event, *next_event;
! 138: isc_task_t *task;
! 139: HANDLE *pHandles = NULL;
! 140:
! 141: REQUIRE(main_thread == GetCurrentThread());
! 142: LOCK(&lock);
! 143: if (!running) {
! 144: running = ISC_TRUE;
! 145:
! 146: /*
! 147: * Post any on-run events (in FIFO order).
! 148: */
! 149: for (event = ISC_LIST_HEAD(on_run);
! 150: event != NULL;
! 151: event = next_event) {
! 152: next_event = ISC_LIST_NEXT(event, ev_link);
! 153: ISC_LIST_UNLINK(on_run, event, ev_link);
! 154: task = event->ev_sender;
! 155: event->ev_sender = NULL;
! 156: isc_task_sendanddetach(&task, &event);
! 157: }
! 158:
! 159: }
! 160:
! 161: UNLOCK(&lock);
! 162:
! 163: /*
! 164: * There is no danger if isc_app_shutdown() is called before we wait
! 165: * for events.
! 166: */
! 167:
! 168: while (!want_shutdown) {
! 169: dwWaitResult = WaitForMultipleObjects(NUM_EVENTS, hEvents,
! 170: FALSE, INFINITE);
! 171:
! 172: /* See why we returned */
! 173:
! 174: if (WaitSucceeded(dwWaitResult, NUM_EVENTS)) {
! 175: /*
! 176: * The return was due to one of the events
! 177: * being signaled
! 178: */
! 179: switch (WaitSucceededIndex(dwWaitResult)) {
! 180: case RELOAD_EVENT:
! 181: want_reload = ISC_TRUE;
! 182: break;
! 183:
! 184: case SHUTDOWN_EVENT:
! 185: want_shutdown = ISC_TRUE;
! 186: break;
! 187: }
! 188: }
! 189: if (want_reload) {
! 190: want_reload = ISC_FALSE;
! 191: return (ISC_R_RELOAD);
! 192: }
! 193:
! 194: if (want_shutdown && blocked)
! 195: exit(-1);
! 196: }
! 197:
! 198: return (ISC_R_SUCCESS);
! 199: }
! 200:
! 201: isc_result_t
! 202: isc_app_shutdown(void) {
! 203: isc_boolean_t want_kill = ISC_TRUE;
! 204:
! 205: LOCK(&lock);
! 206: REQUIRE(running);
! 207:
! 208: if (shutdown_requested)
! 209: want_kill = ISC_FALSE; /* We're only signaling once */
! 210: else
! 211: shutdown_requested = ISC_TRUE;
! 212:
! 213: UNLOCK(&lock);
! 214: if (want_kill)
! 215: SetEvent(hEvents[SHUTDOWN_EVENT]);
! 216:
! 217: return (ISC_R_SUCCESS);
! 218: }
! 219:
! 220: isc_result_t
! 221: isc_app_reload(void) {
! 222: isc_boolean_t want_reload = ISC_TRUE;
! 223:
! 224: LOCK(&lock);
! 225: REQUIRE(running);
! 226:
! 227: /*
! 228: * Don't send the reload signal if we're shutting down.
! 229: */
! 230: if (shutdown_requested)
! 231: want_reload = ISC_FALSE;
! 232:
! 233: UNLOCK(&lock);
! 234: if (want_reload)
! 235: SetEvent(hEvents[RELOAD_EVENT]);
! 236:
! 237: return (ISC_R_SUCCESS);
! 238: }
! 239:
! 240: void
! 241: isc_app_finish(void) {
! 242: DESTROYLOCK(&lock);
! 243: }
! 244:
! 245: void
! 246: isc_app_block(void) {
! 247: REQUIRE(running);
! 248: REQUIRE(!blocked);
! 249:
! 250: blocked = ISC_TRUE;
! 251: blockedthread = GetCurrentThread();
! 252: }
! 253:
! 254: void
! 255: isc_app_unblock(void) {
! 256: REQUIRE(running);
! 257: REQUIRE(blocked);
! 258: blocked = ISC_FALSE;
! 259: REQUIRE(blockedthread == GetCurrentThread());
! 260: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>