Annotation of embedaddon/ntp/lib/isc/win32/app.c, revision 1.1.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>