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