xref: /minix3/external/bsd/bind/dist/lib/isc/win32/app.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: app.c,v 1.6 2014/12/10 04:38:01 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2004, 2007, 2009, 2013, 2014  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Copyright (C) 1999-2001  Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek  *
7*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek  */
19*00b67f09SDavid van Moolenbroek 
20*00b67f09SDavid van Moolenbroek /* Id: app.c,v 1.9 2009/09/02 23:48:03 tbox Exp  */
21*00b67f09SDavid van Moolenbroek 
22*00b67f09SDavid van Moolenbroek #include <config.h>
23*00b67f09SDavid van Moolenbroek 
24*00b67f09SDavid van Moolenbroek #include <sys/types.h>
25*00b67f09SDavid van Moolenbroek 
26*00b67f09SDavid van Moolenbroek #include <stddef.h>
27*00b67f09SDavid van Moolenbroek #include <stdlib.h>
28*00b67f09SDavid van Moolenbroek #include <errno.h>
29*00b67f09SDavid van Moolenbroek #include <unistd.h>
30*00b67f09SDavid van Moolenbroek #include <process.h>
31*00b67f09SDavid van Moolenbroek 
32*00b67f09SDavid van Moolenbroek #include <isc/app.h>
33*00b67f09SDavid van Moolenbroek #include <isc/boolean.h>
34*00b67f09SDavid van Moolenbroek #include <isc/condition.h>
35*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
36*00b67f09SDavid van Moolenbroek #include <isc/msgs.h>
37*00b67f09SDavid van Moolenbroek #include <isc/mutex.h>
38*00b67f09SDavid van Moolenbroek #include <isc/event.h>
39*00b67f09SDavid van Moolenbroek #include <isc/platform.h>
40*00b67f09SDavid van Moolenbroek #include <isc/string.h>
41*00b67f09SDavid van Moolenbroek #include <isc/task.h>
42*00b67f09SDavid van Moolenbroek #include <isc/time.h>
43*00b67f09SDavid van Moolenbroek #include <isc/util.h>
44*00b67f09SDavid van Moolenbroek #include <isc/thread.h>
45*00b67f09SDavid van Moolenbroek 
46*00b67f09SDavid van Moolenbroek /*%
47*00b67f09SDavid van Moolenbroek  * For BIND9 internal applications built with threads, we use a single app
48*00b67f09SDavid van Moolenbroek  * context and let multiple worker, I/O, timer threads do actual jobs.
49*00b67f09SDavid van Moolenbroek  */
50*00b67f09SDavid van Moolenbroek 
51*00b67f09SDavid van Moolenbroek static isc_thread_t	blockedthread;
52*00b67f09SDavid van Moolenbroek 
53*00b67f09SDavid van Moolenbroek /*%
54*00b67f09SDavid van Moolenbroek  * The following are intended for internal use (indicated by "isc__"
55*00b67f09SDavid van Moolenbroek  * prefix) but are not declared as static, allowing direct access from
56*00b67f09SDavid van Moolenbroek  * unit tests etc.
57*00b67f09SDavid van Moolenbroek  */
58*00b67f09SDavid van Moolenbroek isc_result_t isc__app_start(void);
59*00b67f09SDavid van Moolenbroek isc_result_t isc__app_ctxstart(isc_appctx_t *ctx);
60*00b67f09SDavid van Moolenbroek isc_result_t isc__app_onrun(isc_mem_t *mctx, isc_task_t *task,
61*00b67f09SDavid van Moolenbroek 			    isc_taskaction_t action, void *arg);
62*00b67f09SDavid van Moolenbroek isc_result_t isc__app_ctxrun(isc_appctx_t *ctx);
63*00b67f09SDavid van Moolenbroek isc_result_t isc__app_run(void);
64*00b67f09SDavid van Moolenbroek isc_result_t isc__app_ctxshutdown(isc_appctx_t *ctx);
65*00b67f09SDavid van Moolenbroek isc_result_t isc__app_shutdown(void);
66*00b67f09SDavid van Moolenbroek isc_result_t isc__app_reload(void);
67*00b67f09SDavid van Moolenbroek isc_result_t isc__app_ctxsuspend(isc_appctx_t *ctx);
68*00b67f09SDavid van Moolenbroek void isc__app_ctxfinish(isc_appctx_t *ctx);
69*00b67f09SDavid van Moolenbroek void isc__app_finish(void);
70*00b67f09SDavid van Moolenbroek void isc__app_block(void);
71*00b67f09SDavid van Moolenbroek void isc__app_unblock(void);
72*00b67f09SDavid van Moolenbroek isc_result_t isc__appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp);
73*00b67f09SDavid van Moolenbroek void isc__appctx_destroy(isc_appctx_t **ctxp);
74*00b67f09SDavid van Moolenbroek void isc__appctx_settaskmgr(isc_appctx_t *ctx, isc_taskmgr_t *taskmgr);
75*00b67f09SDavid van Moolenbroek void isc__appctx_setsocketmgr(isc_appctx_t *ctx, isc_socketmgr_t *socketmgr);
76*00b67f09SDavid van Moolenbroek void isc__appctx_settimermgr(isc_appctx_t *ctx, isc_timermgr_t *timermgr);
77*00b67f09SDavid van Moolenbroek isc_result_t isc__app_ctxonrun(isc_appctx_t *ctx, isc_mem_t *mctx,
78*00b67f09SDavid van Moolenbroek 			       isc_task_t *task, isc_taskaction_t action,
79*00b67f09SDavid van Moolenbroek 			       void *arg);
80*00b67f09SDavid van Moolenbroek 
81*00b67f09SDavid van Moolenbroek /*
82*00b67f09SDavid van Moolenbroek  * The application context of this module.  This implementation actually
83*00b67f09SDavid van Moolenbroek  * doesn't use it. (This may change in the future).
84*00b67f09SDavid van Moolenbroek  */
85*00b67f09SDavid van Moolenbroek #define APPCTX_MAGIC		ISC_MAGIC('A', 'p', 'c', 'x')
86*00b67f09SDavid van Moolenbroek #define VALID_APPCTX(c)		ISC_MAGIC_VALID(c, APPCTX_MAGIC)
87*00b67f09SDavid van Moolenbroek 
88*00b67f09SDavid van Moolenbroek /* Events to wait for */
89*00b67f09SDavid van Moolenbroek 
90*00b67f09SDavid van Moolenbroek #define NUM_EVENTS 2
91*00b67f09SDavid van Moolenbroek 
92*00b67f09SDavid van Moolenbroek enum {
93*00b67f09SDavid van Moolenbroek 	RELOAD_EVENT,
94*00b67f09SDavid van Moolenbroek 	SHUTDOWN_EVENT
95*00b67f09SDavid van Moolenbroek };
96*00b67f09SDavid van Moolenbroek 
97*00b67f09SDavid van Moolenbroek typedef struct isc__appctx {
98*00b67f09SDavid van Moolenbroek 	isc_appctx_t		common;
99*00b67f09SDavid van Moolenbroek 	isc_mem_t		*mctx;
100*00b67f09SDavid van Moolenbroek 	isc_eventlist_t		on_run;
101*00b67f09SDavid van Moolenbroek 	isc_mutex_t		lock;
102*00b67f09SDavid van Moolenbroek 	isc_boolean_t		shutdown_requested;
103*00b67f09SDavid van Moolenbroek 	isc_boolean_t		running;
104*00b67f09SDavid van Moolenbroek 	/*
105*00b67f09SDavid van Moolenbroek 	 * We assume that 'want_shutdown' can be read and written atomically.
106*00b67f09SDavid van Moolenbroek 	 */
107*00b67f09SDavid van Moolenbroek 	isc_boolean_t		want_shutdown;
108*00b67f09SDavid van Moolenbroek 	/*
109*00b67f09SDavid van Moolenbroek 	 * We assume that 'want_reload' can be read and written atomically.
110*00b67f09SDavid van Moolenbroek 	 */
111*00b67f09SDavid van Moolenbroek 	isc_boolean_t		want_reload;
112*00b67f09SDavid van Moolenbroek 
113*00b67f09SDavid van Moolenbroek 	isc_boolean_t		blocked;
114*00b67f09SDavid van Moolenbroek 
115*00b67f09SDavid van Moolenbroek 	HANDLE			hEvents[NUM_EVENTS];
116*00b67f09SDavid van Moolenbroek 
117*00b67f09SDavid van Moolenbroek 	isc_taskmgr_t		*taskmgr;
118*00b67f09SDavid van Moolenbroek 	isc_socketmgr_t		*socketmgr;
119*00b67f09SDavid van Moolenbroek 	isc_timermgr_t		*timermgr;
120*00b67f09SDavid van Moolenbroek } isc__appctx_t;
121*00b67f09SDavid van Moolenbroek 
122*00b67f09SDavid van Moolenbroek static isc__appctx_t isc_g_appctx;
123*00b67f09SDavid van Moolenbroek 
124*00b67f09SDavid van Moolenbroek static struct {
125*00b67f09SDavid van Moolenbroek 	isc_appmethods_t methods;
126*00b67f09SDavid van Moolenbroek 
127*00b67f09SDavid van Moolenbroek 	/*%
128*00b67f09SDavid van Moolenbroek 	 * The following are defined just for avoiding unused static functions.
129*00b67f09SDavid van Moolenbroek 	 */
130*00b67f09SDavid van Moolenbroek 	void *run, *shutdown, *start, *reload, *finish, *block, *unblock;
131*00b67f09SDavid van Moolenbroek } appmethods = {
132*00b67f09SDavid van Moolenbroek 	{
133*00b67f09SDavid van Moolenbroek 		isc__appctx_destroy,
134*00b67f09SDavid van Moolenbroek 		isc__app_ctxstart,
135*00b67f09SDavid van Moolenbroek 		isc__app_ctxrun,
136*00b67f09SDavid van Moolenbroek 		isc__app_ctxsuspend,
137*00b67f09SDavid van Moolenbroek 		isc__app_ctxshutdown,
138*00b67f09SDavid van Moolenbroek 		isc__app_ctxfinish,
139*00b67f09SDavid van Moolenbroek 		isc__appctx_settaskmgr,
140*00b67f09SDavid van Moolenbroek 		isc__appctx_setsocketmgr,
141*00b67f09SDavid van Moolenbroek 		isc__appctx_settimermgr,
142*00b67f09SDavid van Moolenbroek 		isc__app_ctxonrun
143*00b67f09SDavid van Moolenbroek 	},
144*00b67f09SDavid van Moolenbroek 	(void *)isc__app_run,
145*00b67f09SDavid van Moolenbroek 	(void *)isc__app_shutdown,
146*00b67f09SDavid van Moolenbroek 	(void *)isc__app_start,
147*00b67f09SDavid van Moolenbroek 	(void *)isc__app_reload,
148*00b67f09SDavid van Moolenbroek 	(void *)isc__app_finish,
149*00b67f09SDavid van Moolenbroek 	(void *)isc__app_block,
150*00b67f09SDavid van Moolenbroek 	(void *)isc__app_unblock
151*00b67f09SDavid van Moolenbroek };
152*00b67f09SDavid van Moolenbroek 
153*00b67f09SDavid van Moolenbroek /*
154*00b67f09SDavid van Moolenbroek  * We need to remember which thread is the main thread...
155*00b67f09SDavid van Moolenbroek  */
156*00b67f09SDavid van Moolenbroek static isc_thread_t	main_thread;
157*00b67f09SDavid van Moolenbroek 
158*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_ctxstart(isc_appctx_t * ctx0)159*00b67f09SDavid van Moolenbroek isc__app_ctxstart(isc_appctx_t *ctx0) {
160*00b67f09SDavid van Moolenbroek 	isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
161*00b67f09SDavid van Moolenbroek 	isc_result_t result;
162*00b67f09SDavid van Moolenbroek 
163*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_APPCTX(ctx));
164*00b67f09SDavid van Moolenbroek 
165*00b67f09SDavid van Moolenbroek 	/*
166*00b67f09SDavid van Moolenbroek 	 * Start an ISC library application.
167*00b67f09SDavid van Moolenbroek 	 */
168*00b67f09SDavid van Moolenbroek 
169*00b67f09SDavid van Moolenbroek 	main_thread = GetCurrentThread();
170*00b67f09SDavid van Moolenbroek 
171*00b67f09SDavid van Moolenbroek 	result = isc_mutex_init(&ctx->lock);
172*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
173*00b67f09SDavid van Moolenbroek 		return (result);
174*00b67f09SDavid van Moolenbroek 
175*00b67f09SDavid van Moolenbroek 	ctx->shutdown_requested = ISC_FALSE;
176*00b67f09SDavid van Moolenbroek 	ctx->running = ISC_FALSE;
177*00b67f09SDavid van Moolenbroek 	ctx->want_shutdown = ISC_FALSE;
178*00b67f09SDavid van Moolenbroek 	ctx->want_reload = ISC_FALSE;
179*00b67f09SDavid van Moolenbroek 	ctx->blocked  = ISC_FALSE;
180*00b67f09SDavid van Moolenbroek 
181*00b67f09SDavid van Moolenbroek 	/* Create the reload event in a non-signaled state */
182*00b67f09SDavid van Moolenbroek 	ctx->hEvents[RELOAD_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
183*00b67f09SDavid van Moolenbroek 
184*00b67f09SDavid van Moolenbroek 	/* Create the shutdown event in a non-signaled state */
185*00b67f09SDavid van Moolenbroek 	ctx->hEvents[SHUTDOWN_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
186*00b67f09SDavid van Moolenbroek 
187*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(ctx->on_run);
188*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
189*00b67f09SDavid van Moolenbroek }
190*00b67f09SDavid van Moolenbroek 
191*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_start(void)192*00b67f09SDavid van Moolenbroek isc__app_start(void) {
193*00b67f09SDavid van Moolenbroek 	isc_g_appctx.common.impmagic = APPCTX_MAGIC;
194*00b67f09SDavid van Moolenbroek 	isc_g_appctx.common.magic = ISCAPI_APPCTX_MAGIC;
195*00b67f09SDavid van Moolenbroek 	isc_g_appctx.common.methods = &appmethods.methods;
196*00b67f09SDavid van Moolenbroek 	isc_g_appctx.mctx = NULL;
197*00b67f09SDavid van Moolenbroek 	/* The remaining members will be initialized in ctxstart() */
198*00b67f09SDavid van Moolenbroek 
199*00b67f09SDavid van Moolenbroek 	return (isc__app_ctxstart((isc_appctx_t *)&isc_g_appctx));
200*00b67f09SDavid van Moolenbroek }
201*00b67f09SDavid van Moolenbroek 
202*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_onrun(isc_mem_t * mctx,isc_task_t * task,isc_taskaction_t action,void * arg)203*00b67f09SDavid van Moolenbroek isc__app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
204*00b67f09SDavid van Moolenbroek 	       void *arg)
205*00b67f09SDavid van Moolenbroek {
206*00b67f09SDavid van Moolenbroek 	return (isc__app_ctxonrun((isc_appctx_t *)&isc_g_appctx, mctx,
207*00b67f09SDavid van Moolenbroek 				  task, action, arg));
208*00b67f09SDavid van Moolenbroek }
209*00b67f09SDavid van Moolenbroek 
210*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_ctxonrun(isc_appctx_t * ctx0,isc_mem_t * mctx,isc_task_t * task,isc_taskaction_t action,void * arg)211*00b67f09SDavid van Moolenbroek isc__app_ctxonrun(isc_appctx_t *ctx0, isc_mem_t *mctx, isc_task_t *task,
212*00b67f09SDavid van Moolenbroek 		  isc_taskaction_t action, void *arg)
213*00b67f09SDavid van Moolenbroek {
214*00b67f09SDavid van Moolenbroek 	isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
215*00b67f09SDavid van Moolenbroek 	isc_event_t *event;
216*00b67f09SDavid van Moolenbroek 	isc_task_t *cloned_task = NULL;
217*00b67f09SDavid van Moolenbroek 	isc_result_t result;
218*00b67f09SDavid van Moolenbroek 
219*00b67f09SDavid van Moolenbroek 	LOCK(&ctx->lock);
220*00b67f09SDavid van Moolenbroek 
221*00b67f09SDavid van Moolenbroek 	if (ctx->running) {
222*00b67f09SDavid van Moolenbroek 		result = ISC_R_ALREADYRUNNING;
223*00b67f09SDavid van Moolenbroek 		goto unlock;
224*00b67f09SDavid van Moolenbroek 	}
225*00b67f09SDavid van Moolenbroek 
226*00b67f09SDavid van Moolenbroek 	/*
227*00b67f09SDavid van Moolenbroek 	 * Note that we store the task to which we're going to send the event
228*00b67f09SDavid van Moolenbroek 	 * in the event's "sender" field.
229*00b67f09SDavid van Moolenbroek 	 */
230*00b67f09SDavid van Moolenbroek 	isc_task_attach(task, &cloned_task);
231*00b67f09SDavid van Moolenbroek 	event = isc_event_allocate(mctx, cloned_task, ISC_APPEVENT_SHUTDOWN,
232*00b67f09SDavid van Moolenbroek 				   action, arg, sizeof(*event));
233*00b67f09SDavid van Moolenbroek 	if (event == NULL) {
234*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOMEMORY;
235*00b67f09SDavid van Moolenbroek 		goto unlock;
236*00b67f09SDavid van Moolenbroek 	}
237*00b67f09SDavid van Moolenbroek 
238*00b67f09SDavid van Moolenbroek 	ISC_LIST_APPEND(ctx->on_run, event, ev_link);
239*00b67f09SDavid van Moolenbroek 
240*00b67f09SDavid van Moolenbroek 	result = ISC_R_SUCCESS;
241*00b67f09SDavid van Moolenbroek 
242*00b67f09SDavid van Moolenbroek  unlock:
243*00b67f09SDavid van Moolenbroek 	UNLOCK(&ctx->lock);
244*00b67f09SDavid van Moolenbroek 
245*00b67f09SDavid van Moolenbroek 	return (result);
246*00b67f09SDavid van Moolenbroek }
247*00b67f09SDavid van Moolenbroek 
248*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_ctxrun(isc_appctx_t * ctx0)249*00b67f09SDavid van Moolenbroek isc__app_ctxrun(isc_appctx_t *ctx0) {
250*00b67f09SDavid van Moolenbroek 	isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
251*00b67f09SDavid van Moolenbroek 	isc_event_t *event, *next_event;
252*00b67f09SDavid van Moolenbroek 	isc_task_t *task;
253*00b67f09SDavid van Moolenbroek 	HANDLE *pHandles = NULL;
254*00b67f09SDavid van Moolenbroek 	DWORD  dwWaitResult;
255*00b67f09SDavid van Moolenbroek 
256*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_APPCTX(ctx));
257*00b67f09SDavid van Moolenbroek 
258*00b67f09SDavid van Moolenbroek 	REQUIRE(main_thread == GetCurrentThread());
259*00b67f09SDavid van Moolenbroek 
260*00b67f09SDavid van Moolenbroek 	LOCK(&ctx->lock);
261*00b67f09SDavid van Moolenbroek 
262*00b67f09SDavid van Moolenbroek 	if (!ctx->running) {
263*00b67f09SDavid van Moolenbroek 		ctx->running = ISC_TRUE;
264*00b67f09SDavid van Moolenbroek 
265*00b67f09SDavid van Moolenbroek 		/*
266*00b67f09SDavid van Moolenbroek 		 * Post any on-run events (in FIFO order).
267*00b67f09SDavid van Moolenbroek 		 */
268*00b67f09SDavid van Moolenbroek 		for (event = ISC_LIST_HEAD(ctx->on_run);
269*00b67f09SDavid van Moolenbroek 		     event != NULL;
270*00b67f09SDavid van Moolenbroek 		     event = next_event) {
271*00b67f09SDavid van Moolenbroek 			next_event = ISC_LIST_NEXT(event, ev_link);
272*00b67f09SDavid van Moolenbroek 			ISC_LIST_UNLINK(ctx->on_run, event, ev_link);
273*00b67f09SDavid van Moolenbroek 			task = event->ev_sender;
274*00b67f09SDavid van Moolenbroek 			event->ev_sender = NULL;
275*00b67f09SDavid van Moolenbroek 			isc_task_sendanddetach(&task, &event);
276*00b67f09SDavid van Moolenbroek 		}
277*00b67f09SDavid van Moolenbroek 
278*00b67f09SDavid van Moolenbroek 	}
279*00b67f09SDavid van Moolenbroek 
280*00b67f09SDavid van Moolenbroek 	UNLOCK(&ctx->lock);
281*00b67f09SDavid van Moolenbroek 
282*00b67f09SDavid van Moolenbroek 	/*
283*00b67f09SDavid van Moolenbroek 	 * There is no danger if isc_app_shutdown() is called before we wait
284*00b67f09SDavid van Moolenbroek 	 * for events.
285*00b67f09SDavid van Moolenbroek 	 */
286*00b67f09SDavid van Moolenbroek 
287*00b67f09SDavid van Moolenbroek 	while (!ctx->want_shutdown) {
288*00b67f09SDavid van Moolenbroek 		dwWaitResult = WaitForMultipleObjects(NUM_EVENTS, ctx->hEvents,
289*00b67f09SDavid van Moolenbroek 						      FALSE, INFINITE);
290*00b67f09SDavid van Moolenbroek 
291*00b67f09SDavid van Moolenbroek 		/* See why we returned */
292*00b67f09SDavid van Moolenbroek 
293*00b67f09SDavid van Moolenbroek 		if (WaitSucceeded(dwWaitResult, NUM_EVENTS)) {
294*00b67f09SDavid van Moolenbroek 			/*
295*00b67f09SDavid van Moolenbroek 			 * The return was due to one of the events
296*00b67f09SDavid van Moolenbroek 			 * being signaled
297*00b67f09SDavid van Moolenbroek 			 */
298*00b67f09SDavid van Moolenbroek 			switch (WaitSucceededIndex(dwWaitResult)) {
299*00b67f09SDavid van Moolenbroek 			case RELOAD_EVENT:
300*00b67f09SDavid van Moolenbroek 				ctx->want_reload = ISC_TRUE;
301*00b67f09SDavid van Moolenbroek 				break;
302*00b67f09SDavid van Moolenbroek 
303*00b67f09SDavid van Moolenbroek 			case SHUTDOWN_EVENT:
304*00b67f09SDavid van Moolenbroek 				ctx->want_shutdown = ISC_TRUE;
305*00b67f09SDavid van Moolenbroek 				break;
306*00b67f09SDavid van Moolenbroek 			}
307*00b67f09SDavid van Moolenbroek 		}
308*00b67f09SDavid van Moolenbroek 
309*00b67f09SDavid van Moolenbroek 		if (ctx->want_reload) {
310*00b67f09SDavid van Moolenbroek 			ctx->want_reload = ISC_FALSE;
311*00b67f09SDavid van Moolenbroek 			return (ISC_R_RELOAD);
312*00b67f09SDavid van Moolenbroek 		}
313*00b67f09SDavid van Moolenbroek 
314*00b67f09SDavid van Moolenbroek 		if (ctx->want_shutdown && ctx->blocked)
315*00b67f09SDavid van Moolenbroek 			exit(-1);
316*00b67f09SDavid van Moolenbroek 	}
317*00b67f09SDavid van Moolenbroek 
318*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
319*00b67f09SDavid van Moolenbroek }
320*00b67f09SDavid van Moolenbroek 
321*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_run(void)322*00b67f09SDavid van Moolenbroek isc__app_run(void) {
323*00b67f09SDavid van Moolenbroek 	return (isc__app_ctxrun((isc_appctx_t *)&isc_g_appctx));
324*00b67f09SDavid van Moolenbroek }
325*00b67f09SDavid van Moolenbroek 
326*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_ctxshutdown(isc_appctx_t * ctx0)327*00b67f09SDavid van Moolenbroek isc__app_ctxshutdown(isc_appctx_t *ctx0) {
328*00b67f09SDavid van Moolenbroek 	isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
329*00b67f09SDavid van Moolenbroek 	isc_boolean_t want_kill = ISC_TRUE;
330*00b67f09SDavid van Moolenbroek 
331*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_APPCTX(ctx));
332*00b67f09SDavid van Moolenbroek 
333*00b67f09SDavid van Moolenbroek 	LOCK(&ctx->lock);
334*00b67f09SDavid van Moolenbroek 
335*00b67f09SDavid van Moolenbroek 	REQUIRE(ctx->running);
336*00b67f09SDavid van Moolenbroek 
337*00b67f09SDavid van Moolenbroek 	if (ctx->shutdown_requested)
338*00b67f09SDavid van Moolenbroek 		want_kill = ISC_FALSE;		/* We're only signaling once */
339*00b67f09SDavid van Moolenbroek 	else
340*00b67f09SDavid van Moolenbroek 		ctx->shutdown_requested = ISC_TRUE;
341*00b67f09SDavid van Moolenbroek 
342*00b67f09SDavid van Moolenbroek 	UNLOCK(&ctx->lock);
343*00b67f09SDavid van Moolenbroek 
344*00b67f09SDavid van Moolenbroek 	if (want_kill)
345*00b67f09SDavid van Moolenbroek 		SetEvent(ctx->hEvents[SHUTDOWN_EVENT]);
346*00b67f09SDavid van Moolenbroek 
347*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
348*00b67f09SDavid van Moolenbroek }
349*00b67f09SDavid van Moolenbroek 
350*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_shutdown(void)351*00b67f09SDavid van Moolenbroek isc__app_shutdown(void) {
352*00b67f09SDavid van Moolenbroek 	return (isc__app_ctxshutdown((isc_appctx_t *)&isc_g_appctx));
353*00b67f09SDavid van Moolenbroek }
354*00b67f09SDavid van Moolenbroek 
355*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_ctxsuspend(isc_appctx_t * ctx0)356*00b67f09SDavid van Moolenbroek isc__app_ctxsuspend(isc_appctx_t *ctx0) {
357*00b67f09SDavid van Moolenbroek 	isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
358*00b67f09SDavid van Moolenbroek 	isc_boolean_t want_kill = ISC_TRUE;
359*00b67f09SDavid van Moolenbroek 
360*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_APPCTX(ctx));
361*00b67f09SDavid van Moolenbroek 
362*00b67f09SDavid van Moolenbroek 	LOCK(&ctx->lock);
363*00b67f09SDavid van Moolenbroek 
364*00b67f09SDavid van Moolenbroek 	REQUIRE(ctx->running);
365*00b67f09SDavid van Moolenbroek 
366*00b67f09SDavid van Moolenbroek 	/*
367*00b67f09SDavid van Moolenbroek 	 * Don't send the reload signal if we're shutting down.
368*00b67f09SDavid van Moolenbroek 	 */
369*00b67f09SDavid van Moolenbroek 	if (ctx->shutdown_requested)
370*00b67f09SDavid van Moolenbroek 		want_kill = ISC_FALSE;
371*00b67f09SDavid van Moolenbroek 
372*00b67f09SDavid van Moolenbroek 	UNLOCK(&ctx->lock);
373*00b67f09SDavid van Moolenbroek 
374*00b67f09SDavid van Moolenbroek 	if (want_kill)
375*00b67f09SDavid van Moolenbroek 		SetEvent(ctx->hEvents[RELOAD_EVENT]);
376*00b67f09SDavid van Moolenbroek 
377*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
378*00b67f09SDavid van Moolenbroek }
379*00b67f09SDavid van Moolenbroek 
380*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_reload(void)381*00b67f09SDavid van Moolenbroek isc__app_reload(void) {
382*00b67f09SDavid van Moolenbroek 	return (isc__app_ctxsuspend((isc_appctx_t *)&isc_g_appctx));
383*00b67f09SDavid van Moolenbroek }
384*00b67f09SDavid van Moolenbroek 
385*00b67f09SDavid van Moolenbroek void
isc__app_ctxfinish(isc_appctx_t * ctx0)386*00b67f09SDavid van Moolenbroek isc__app_ctxfinish(isc_appctx_t *ctx0) {
387*00b67f09SDavid van Moolenbroek 	isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
388*00b67f09SDavid van Moolenbroek 
389*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_APPCTX(ctx));
390*00b67f09SDavid van Moolenbroek 
391*00b67f09SDavid van Moolenbroek 	DESTROYLOCK(&ctx->lock);
392*00b67f09SDavid van Moolenbroek }
393*00b67f09SDavid van Moolenbroek 
394*00b67f09SDavid van Moolenbroek void
isc__app_finish(void)395*00b67f09SDavid van Moolenbroek isc__app_finish(void) {
396*00b67f09SDavid van Moolenbroek 	isc__app_ctxfinish((isc_appctx_t *)&isc_g_appctx);
397*00b67f09SDavid van Moolenbroek }
398*00b67f09SDavid van Moolenbroek 
399*00b67f09SDavid van Moolenbroek void
isc__app_block(void)400*00b67f09SDavid van Moolenbroek isc__app_block(void) {
401*00b67f09SDavid van Moolenbroek 	REQUIRE(isc_g_appctx.running);
402*00b67f09SDavid van Moolenbroek 	REQUIRE(!isc_g_appctx.blocked);
403*00b67f09SDavid van Moolenbroek 
404*00b67f09SDavid van Moolenbroek 	isc_g_appctx.blocked = ISC_TRUE;
405*00b67f09SDavid van Moolenbroek 	blockedthread = GetCurrentThread();
406*00b67f09SDavid van Moolenbroek }
407*00b67f09SDavid van Moolenbroek 
408*00b67f09SDavid van Moolenbroek void
isc__app_unblock(void)409*00b67f09SDavid van Moolenbroek isc__app_unblock(void) {
410*00b67f09SDavid van Moolenbroek 	REQUIRE(isc_g_appctx.running);
411*00b67f09SDavid van Moolenbroek 	REQUIRE(isc_g_appctx.blocked);
412*00b67f09SDavid van Moolenbroek 
413*00b67f09SDavid van Moolenbroek 	isc_g_appctx.blocked = ISC_FALSE;
414*00b67f09SDavid van Moolenbroek 	REQUIRE(blockedthread == GetCurrentThread());
415*00b67f09SDavid van Moolenbroek }
416*00b67f09SDavid van Moolenbroek 
417*00b67f09SDavid van Moolenbroek isc_result_t
isc__appctx_create(isc_mem_t * mctx,isc_appctx_t ** ctxp)418*00b67f09SDavid van Moolenbroek isc__appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp) {
419*00b67f09SDavid van Moolenbroek 	isc__appctx_t *ctx;
420*00b67f09SDavid van Moolenbroek 
421*00b67f09SDavid van Moolenbroek 	REQUIRE(mctx != NULL);
422*00b67f09SDavid van Moolenbroek 	REQUIRE(ctxp != NULL && *ctxp == NULL);
423*00b67f09SDavid van Moolenbroek 
424*00b67f09SDavid van Moolenbroek 	ctx = isc_mem_get(mctx, sizeof(*ctx));
425*00b67f09SDavid van Moolenbroek 	if (ctx == NULL)
426*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
427*00b67f09SDavid van Moolenbroek 
428*00b67f09SDavid van Moolenbroek 	ctx->common.impmagic = APPCTX_MAGIC;
429*00b67f09SDavid van Moolenbroek 	ctx->common.magic = ISCAPI_APPCTX_MAGIC;
430*00b67f09SDavid van Moolenbroek 	ctx->common.methods = &appmethods.methods;
431*00b67f09SDavid van Moolenbroek 
432*00b67f09SDavid van Moolenbroek 	ctx->mctx = NULL;
433*00b67f09SDavid van Moolenbroek 	isc_mem_attach(mctx, &ctx->mctx);
434*00b67f09SDavid van Moolenbroek 
435*00b67f09SDavid van Moolenbroek 	ctx->taskmgr = NULL;
436*00b67f09SDavid van Moolenbroek 	ctx->socketmgr = NULL;
437*00b67f09SDavid van Moolenbroek 	ctx->timermgr = NULL;
438*00b67f09SDavid van Moolenbroek 
439*00b67f09SDavid van Moolenbroek 	*ctxp = (isc_appctx_t *)ctx;
440*00b67f09SDavid van Moolenbroek 
441*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
442*00b67f09SDavid van Moolenbroek }
443*00b67f09SDavid van Moolenbroek 
444*00b67f09SDavid van Moolenbroek void
isc__appctx_destroy(isc_appctx_t ** ctxp)445*00b67f09SDavid van Moolenbroek isc__appctx_destroy(isc_appctx_t **ctxp) {
446*00b67f09SDavid van Moolenbroek 	isc__appctx_t *ctx;
447*00b67f09SDavid van Moolenbroek 
448*00b67f09SDavid van Moolenbroek 	REQUIRE(ctxp != NULL);
449*00b67f09SDavid van Moolenbroek 	ctx = (isc__appctx_t *)*ctxp;
450*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_APPCTX(ctx));
451*00b67f09SDavid van Moolenbroek 
452*00b67f09SDavid van Moolenbroek 	isc_mem_putanddetach(&ctx->mctx, ctx, sizeof(*ctx));
453*00b67f09SDavid van Moolenbroek 
454*00b67f09SDavid van Moolenbroek 	*ctxp = NULL;
455*00b67f09SDavid van Moolenbroek }
456*00b67f09SDavid van Moolenbroek 
457*00b67f09SDavid van Moolenbroek void
isc__appctx_settaskmgr(isc_appctx_t * ctx0,isc_taskmgr_t * taskmgr)458*00b67f09SDavid van Moolenbroek isc__appctx_settaskmgr(isc_appctx_t *ctx0, isc_taskmgr_t *taskmgr) {
459*00b67f09SDavid van Moolenbroek 	isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
460*00b67f09SDavid van Moolenbroek 
461*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_APPCTX(ctx));
462*00b67f09SDavid van Moolenbroek 
463*00b67f09SDavid van Moolenbroek 	ctx->taskmgr = taskmgr;
464*00b67f09SDavid van Moolenbroek }
465*00b67f09SDavid van Moolenbroek 
466*00b67f09SDavid van Moolenbroek void
isc__appctx_setsocketmgr(isc_appctx_t * ctx0,isc_socketmgr_t * socketmgr)467*00b67f09SDavid van Moolenbroek isc__appctx_setsocketmgr(isc_appctx_t *ctx0, isc_socketmgr_t *socketmgr) {
468*00b67f09SDavid van Moolenbroek 	isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
469*00b67f09SDavid van Moolenbroek 
470*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_APPCTX(ctx));
471*00b67f09SDavid van Moolenbroek 
472*00b67f09SDavid van Moolenbroek 	ctx->socketmgr = socketmgr;
473*00b67f09SDavid van Moolenbroek }
474*00b67f09SDavid van Moolenbroek 
475*00b67f09SDavid van Moolenbroek void
isc__appctx_settimermgr(isc_appctx_t * ctx0,isc_timermgr_t * timermgr)476*00b67f09SDavid van Moolenbroek isc__appctx_settimermgr(isc_appctx_t *ctx0, isc_timermgr_t *timermgr) {
477*00b67f09SDavid van Moolenbroek 	isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
478*00b67f09SDavid van Moolenbroek 
479*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_APPCTX(ctx));
480*00b67f09SDavid van Moolenbroek 
481*00b67f09SDavid van Moolenbroek 	ctx->timermgr = timermgr;
482*00b67f09SDavid van Moolenbroek }
483*00b67f09SDavid van Moolenbroek 
484*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_register(void)485*00b67f09SDavid van Moolenbroek isc__app_register(void) {
486*00b67f09SDavid van Moolenbroek 	return (isc_app_register(isc__appctx_create));
487*00b67f09SDavid van Moolenbroek }
488*00b67f09SDavid van Moolenbroek 
489*00b67f09SDavid van Moolenbroek #include "../app_api.c"
490