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>