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