1 /*
2 * Copyright (C) 2011 Citrix Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published
6 * by the Free Software Foundation; version 2.1 only. with the special
7 * exception on linking described in file LICENSE.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 */
14 /*
15 * Internal event machinery for use by other parts of libxl
16 */
17
18 #include <poll.h>
19
20 #include "libxl_internal.h"
21
22
23 //#define DEBUG 1
24
25 #ifdef DEBUG
26 # define LIBXL__DBG_LOG(ctx, args, ...) \
27 LIBXL__LOG((ctx), XTL_DEBUG, args, __VA_ARGS__)
28 #else
29 # define LIBXL__DBG_LOG(ctx, args, ...) ((void)0)
30 #endif
31 #define DBG(args, ...) LIBXL__DBG_LOG(CTX, args, __VA_ARGS__)
32
33
34 static libxl__ao *ao_nested_root(libxl__ao *ao);
35
36 static void ao__check_destroy(libxl_ctx *ctx, libxl__ao *ao);
37
38
39 /*
40 * osevent update baton handling
41 *
42 * We need the following property (the "unstale liveness property"):
43 *
44 * Whenever any thread is blocking as a result of being given an fd
45 * set or timeout by libxl, at least one thread must be using an up to
46 * date osevent set. It is OK for all but one threads to have stale
47 * event sets, because so long as one waiting thread has the right
48 * event set, any actually interesting event will, if nothing else,
49 * wake that "right" thread up. It will then make some progress
50 * and/or, if it exits, ensure that some other thread becomes the
51 * "right" thread.
52 *
53 * For threads blocking outside libxl and which are receiving libxl's
54 * fd and timeout information via the libxl_osevent_hooks callbacks,
55 * libxl calls this function as soon as it becomes interested. It is
56 * the responsiblity of a provider of these functions in a
57 * multithreaded environment to make arrangements to wake up event
58 * waiting thread(s) with stale event sets.
59 *
60 * Waiters outside libxl using _beforepoll are dealt with below.
61 *
62 * For the libxl event loop, the argument is as follows:
63 *
64 * The issue we are concerned about is libxl sleeping on an out of
65 * date fd set, or too long a timeout, so that it doesn't make
66 * progress. If the property above is satisfied, then if any thread
67 * is waiting in libxl at least one such thread will be waiting on a
68 * sufficient osevent set, so any relevant osevent will wake up a
69 * libxl thread which will either handle the event, or arrange that at
70 * least one other libxl thread has the right set.
71 *
72 * There are two calls to poll in libxl: one is the fd recheck, which
73 * is not blocking. There is only the one blocking call, in
74 * eventloop_iteration. poll runs with the ctx unlocked, so osevents
75 * might be added after it unlocks the ctx - that is what we are
76 * worried about.
77 *
78 * To demonstrate that the unstale liveness property is satisfied:
79 *
80 * We define a baton holder as follows: a libxl thread is a baton
81 * holder if
82 * (a) it has an egc or an ao and holds the ctx lock, or
83 * (b) it has an active non-app poller and no osevents have been
84 * added since it released the lock, or
85 * (c) it has an active non-app poller which has been woken
86 * (by writing to its pipe), so it will not sleep
87 * We will maintain the invariant (the "baton invariant") that
88 * whenever there is any active poller, there is at least
89 * one baton holder. ("non-app" means simply "not poller_app".)
90 *
91 * No thread outside libxl can have an active non-app poller: pollers
92 * are put on the active list by poller_get which is called in three
93 * places: libxl_event_wait, which puts it before returning;
94 * libxl__ao_create but only in the synchronous case, in which case
95 * the poller is put before returning; and the poller_app, during
96 * initialisation.
97 *
98 * So any time when all libxl threads are blocking (and therefore do
99 * not have the ctx lock), the non-app active pollers belong to those
100 * threads. If at least one is a baton holder (the invariant), that
101 * thread has a good enough event set.
102 *
103 * Now we will demonstrate that the "baton invariant" is maintained:
104 *
105 * The rule is that any thread which might be the baton holder is
106 * responsible for checking that there continues to be a baton holder
107 * as needed.
108 *
109 * Firstly, consider the case when the baton holders (b) cease to be
110 * baton holders because osevents are added.
111 *
112 * There are only two kinds of osevents: timeouts and fds. Every
113 * other internal event source reduces to one of these eventually.
114 * Both of these cases are handled (in the case of fd events, add and
115 * modify, separately), calling pollers_note_osevent_added.
116 *
117 * This walks the poller_active list, marking the active pollers
118 * osevents_added=1. Such a poller cannot be the baton holder. But
119 * pollers_note_osevent_added is called only from ev_* functions,
120 * which are only called from event-chain libxl code: ie, code with an
121 * ao or an egc. So at this point we are a baton holder, and there is
122 * still a baton holder.
123 *
124 * Secondly, consider the case where baton holders (a) cease to be
125 * batton holders because they dispose of their egc or ao. We call
126 * libxl__egc_ao_cleanup_1_baton on every exit path. We arrange that
127 * everything that disposes of an egc or an ao checks that there is a
128 * new baton holder by calling libxl__egc_ao_cleanup_1_baton.
129 *
130 * This function handles the invariant explicitly: if we have any
131 * non-app active pollers it looks for one which is up to date (baton
132 * holder category (b)), and failing that it picks a victim to turn
133 * into the baton holder category (c) by waking it up. (Correctness
134 * depends on this function not spotting its own thread as the
135 * baton-holder, since it is on its way to not being the baton-holder,
136 * so it must be called after the poller has been put back.)
137 *
138 * Thirdly, we must consider the case (c). A thread in category (c)
139 * will reenter libxl when it gains the lock and necessarily then
140 * becomes a baton holder in category (a).
141 *
142 * So the "baton invariant" is maintained.
143 * QED (for waiters in libxl).
144 *
145 *
146 * For waiters outside libxl which used libxl_osevent_beforepoll
147 * to get the fd set:
148 *
149 * As above, adding an osevent involves having an egc or an ao.
150 * It sets poller->osevents_added on all active pollers. Notably
151 * it sets it on poller_app, which is always active.
152 *
153 * The thread which does this will dispose of its egc or ao before
154 * exiting libxl so it will always wake up the poller_app if the last
155 * call to _beforepoll was before the osevents were added. So the
156 * application's fd set contains at least a wakeup in the form of the
157 * poller_app fd. The application cannot sleep on the libxl fd set
158 * until it has called _afterpoll which empties the pipe, and it
159 * is expected to then call _beforepoll again before sleeping.
160 *
161 * So all the application's event waiting thread(s) will always have
162 * an up to date osevent set, and will be woken up if necessary to
163 * achieve this. (This is in contrast libxl's own event loop where
164 * only one thread need be up to date, as discussed above.)
165 */
pollers_note_osevent_added(libxl_ctx * ctx)166 static void pollers_note_osevent_added(libxl_ctx *ctx) {
167 libxl__poller *poller;
168 XEN_LIST_FOREACH(poller, &ctx->pollers_active, active_entry)
169 poller->osevents_added = 1;
170 }
171
baton_wake(libxl__gc * gc,libxl__poller * wake)172 static void baton_wake(libxl__gc *gc, libxl__poller *wake)
173 {
174 libxl__poller_wakeup(gc, wake);
175
176 wake->osevents_added = 0;
177 /* This serves to make _1_baton idempotent. It is OK even though
178 * that poller may currently be sleeping on only old osevents,
179 * because it is going to wake up because we've just prodded it,
180 * and it pick up new osevents on its next iteration (or pass
181 * on the baton). */
182 }
183
libxl__egc_ao_cleanup_1_baton(libxl__gc * gc)184 void libxl__egc_ao_cleanup_1_baton(libxl__gc *gc)
185 /* Any poller we had must have been `put' already. */
186 {
187 libxl__poller *search, *wake=0;
188
189 if (CTX->poller_app->osevents_added)
190 baton_wake(gc, CTX->poller_app);
191
192 XEN_LIST_FOREACH(search, &CTX->pollers_active, active_entry) {
193 if (search == CTX->poller_app)
194 /* This one is special. We can't give it the baton. */
195 continue;
196 if (!search->osevents_added)
197 /* This poller is up to date and will wake up as needed. */
198 return;
199 if (!wake)
200 wake = search;
201 }
202
203 if (!wake)
204 /* no-one in libxl waiting for any events */
205 return;
206
207 baton_wake(gc, wake);
208 }
209
210 /*
211 * The counter osevent_in_hook is used to ensure that the application
212 * honours the reentrancy restriction documented in libxl_event.h.
213 *
214 * The application's registration hooks should be called ONLY via
215 * these macros, with the ctx locked. Likewise all the "occurred"
216 * entrypoints from the application should assert(!in_hook);
217 *
218 * During the hook call - including while the arguments are being
219 * evaluated - ev->nexus is guaranteed to be valid and refer to the
220 * nexus which is being used for this event registration. The
221 * arguments should specify ev->nexus for the for_libxl argument and
222 * ev->nexus->for_app_reg (or a pointer to it) for for_app_reg.
223 */
224 #define OSEVENT_HOOK_INTERN(retval, failedp, evkind, hookop, nexusop, ...) do { \
225 if (CTX->osevent_hooks) { \
226 CTX->osevent_in_hook++; \
227 libxl__osevent_hook_nexi *nexi = &CTX->hook_##evkind##_nexi_idle; \
228 osevent_hook_pre_##nexusop(gc, ev, nexi, &ev->nexus); \
229 retval CTX->osevent_hooks->evkind##_##hookop \
230 (CTX->osevent_user, __VA_ARGS__); \
231 if ((failedp)) \
232 osevent_hook_failed_##nexusop(gc, ev, nexi, &ev->nexus); \
233 CTX->osevent_in_hook--; \
234 } \
235 } while (0)
236
237 #define OSEVENT_HOOK(evkind, hookop, nexusop, ...) ({ \
238 int osevent_hook_rc = 0; \
239 OSEVENT_HOOK_INTERN(osevent_hook_rc =, !!osevent_hook_rc, \
240 evkind, hookop, nexusop, __VA_ARGS__); \
241 osevent_hook_rc; \
242 })
243
244 #define OSEVENT_HOOK_VOID(evkind, hookop, nexusop, ...) \
245 OSEVENT_HOOK_INTERN(/* void */, 0, evkind, hookop, nexusop, __VA_ARGS__)
246
247 /*
248 * The application's calls to libxl_osevent_occurred_... may be
249 * indefinitely delayed with respect to the rest of the program (since
250 * they are not necessarily called with any lock held). So the
251 * for_libxl value we receive may be (almost) arbitrarily old. All we
252 * know is that it came from this ctx.
253 *
254 * Therefore we may not free the object referred to by any for_libxl
255 * value until we free the whole libxl_ctx. And if we reuse it we
256 * must be able to tell when an old use turns up, and discard the
257 * stale event.
258 *
259 * Thus we cannot use the ev directly as the for_libxl value - we need
260 * a layer of indirection.
261 *
262 * We do this by keeping a pool of libxl__osevent_hook_nexus structs,
263 * and use pointers to them as for_libxl values. In fact, there are
264 * two pools: one for fds and one for timeouts. This ensures that we
265 * don't risk a type error when we upcast nexus->ev. In each nexus
266 * the ev is either null or points to a valid libxl__ev_time or
267 * libxl__ev_fd, as applicable.
268 *
269 * We /do/ allow ourselves to reassociate an old nexus with a new ev
270 * as otherwise we would have to leak nexi. (This reassociation
271 * might, of course, be an old ev being reused for a new purpose so
272 * simply comparing the ev pointer is not sufficient.) Thus the
273 * libxl_osevent_occurred functions need to check that the condition
274 * allegedly signalled by this event actually exists.
275 *
276 * The nexi and the lists are all protected by the ctx lock.
277 */
278
279 struct libxl__osevent_hook_nexus {
280 void *ev;
281 void *for_app_reg;
282 XEN_SLIST_ENTRY(libxl__osevent_hook_nexus) next;
283 };
284
osevent_ev_from_hook_nexus(libxl_ctx * ctx,libxl__osevent_hook_nexus * nexus)285 static void *osevent_ev_from_hook_nexus(libxl_ctx *ctx,
286 libxl__osevent_hook_nexus *nexus /* pass void *for_libxl */)
287 {
288 return nexus->ev;
289 }
290
osevent_release_nexus(libxl__gc * gc,libxl__osevent_hook_nexi * nexi_idle,libxl__osevent_hook_nexus * nexus)291 static void osevent_release_nexus(libxl__gc *gc,
292 libxl__osevent_hook_nexi *nexi_idle,
293 libxl__osevent_hook_nexus *nexus)
294 {
295 nexus->ev = 0;
296 XEN_SLIST_INSERT_HEAD(nexi_idle, nexus, next);
297 }
298
299 /*----- OSEVENT* hook functions for nexusop "alloc" -----*/
osevent_hook_pre_alloc(libxl__gc * gc,void * ev,libxl__osevent_hook_nexi * nexi_idle,libxl__osevent_hook_nexus ** nexus_r)300 static void osevent_hook_pre_alloc(libxl__gc *gc, void *ev,
301 libxl__osevent_hook_nexi *nexi_idle,
302 libxl__osevent_hook_nexus **nexus_r)
303 {
304 libxl__osevent_hook_nexus *nexus = XEN_SLIST_FIRST(nexi_idle);
305 if (nexus) {
306 XEN_SLIST_REMOVE_HEAD(nexi_idle, next);
307 } else {
308 nexus = libxl__zalloc(NOGC, sizeof(*nexus));
309 }
310 nexus->ev = ev;
311 *nexus_r = nexus;
312 }
osevent_hook_failed_alloc(libxl__gc * gc,void * ev,libxl__osevent_hook_nexi * nexi_idle,libxl__osevent_hook_nexus ** nexus)313 static void osevent_hook_failed_alloc(libxl__gc *gc, void *ev,
314 libxl__osevent_hook_nexi *nexi_idle,
315 libxl__osevent_hook_nexus **nexus)
316 {
317 osevent_release_nexus(gc, nexi_idle, *nexus);
318 }
319
320 /*----- OSEVENT* hook functions for nexusop "release" -----*/
osevent_hook_pre_release(libxl__gc * gc,void * ev,libxl__osevent_hook_nexi * nexi_idle,libxl__osevent_hook_nexus ** nexus)321 static void osevent_hook_pre_release(libxl__gc *gc, void *ev,
322 libxl__osevent_hook_nexi *nexi_idle,
323 libxl__osevent_hook_nexus **nexus)
324 {
325 osevent_release_nexus(gc, nexi_idle, *nexus);
326 }
osevent_hook_failed_release(libxl__gc * gc,void * ev,libxl__osevent_hook_nexi * nexi_idle,libxl__osevent_hook_nexus ** nexus)327 static void osevent_hook_failed_release(libxl__gc *gc, void *ev,
328 libxl__osevent_hook_nexi *nexi_idle,
329 libxl__osevent_hook_nexus **nexus)
330 {
331 abort();
332 }
333
334 /*----- OSEVENT* hook functions for nexusop "noop" -----*/
osevent_hook_pre_noop(libxl__gc * gc,void * ev,libxl__osevent_hook_nexi * nexi_idle,libxl__osevent_hook_nexus ** nexus)335 static void osevent_hook_pre_noop(libxl__gc *gc, void *ev,
336 libxl__osevent_hook_nexi *nexi_idle,
337 libxl__osevent_hook_nexus **nexus) { }
osevent_hook_failed_noop(libxl__gc * gc,void * ev,libxl__osevent_hook_nexi * nexi_idle,libxl__osevent_hook_nexus ** nexus)338 static void osevent_hook_failed_noop(libxl__gc *gc, void *ev,
339 libxl__osevent_hook_nexi *nexi_idle,
340 libxl__osevent_hook_nexus **nexus) { }
341
342
343 /*
344 * fd events
345 */
346
libxl__ev_fd_register(libxl__gc * gc,libxl__ev_fd * ev,libxl__ev_fd_callback * func,int fd,short events)347 int libxl__ev_fd_register(libxl__gc *gc, libxl__ev_fd *ev,
348 libxl__ev_fd_callback *func,
349 int fd, short events)
350 {
351 int rc;
352
353 assert(fd >= 0);
354
355 CTX_LOCK;
356
357 DBG("ev_fd=%p register fd=%d events=%x", ev, fd, events);
358
359 rc = OSEVENT_HOOK(fd,register, alloc, fd, &ev->nexus->for_app_reg,
360 events, ev->nexus);
361 if (rc) goto out;
362
363 ev->fd = fd;
364 ev->events = events;
365 ev->func = func;
366
367 XEN_LIST_INSERT_HEAD(&CTX->efds, ev, entry);
368 pollers_note_osevent_added(CTX);
369
370 rc = 0;
371
372 out:
373 CTX_UNLOCK;
374 return rc;
375 }
376
libxl__ev_fd_modify(libxl__gc * gc,libxl__ev_fd * ev,short events)377 int libxl__ev_fd_modify(libxl__gc *gc, libxl__ev_fd *ev, short events)
378 {
379 int rc;
380
381 CTX_LOCK;
382 assert(libxl__ev_fd_isregistered(ev));
383
384 DBG("ev_fd=%p modify fd=%d events=%x", ev, ev->fd, events);
385
386 rc = OSEVENT_HOOK(fd,modify, noop, ev->fd, &ev->nexus->for_app_reg, events);
387 if (rc) goto out;
388
389 if ((events & ~ev->events))
390 pollers_note_osevent_added(CTX);
391 ev->events = events;
392
393 rc = 0;
394 out:
395 CTX_UNLOCK;
396 return rc;
397 }
398
libxl__ev_fd_deregister(libxl__gc * gc,libxl__ev_fd * ev)399 void libxl__ev_fd_deregister(libxl__gc *gc, libxl__ev_fd *ev)
400 {
401 CTX_LOCK;
402 libxl__poller *poller;
403
404 if (!libxl__ev_fd_isregistered(ev)) {
405 DBG("ev_fd=%p deregister unregistered",ev);
406 goto out;
407 }
408
409 DBG("ev_fd=%p deregister fd=%d", ev, ev->fd);
410
411 OSEVENT_HOOK_VOID(fd,deregister, release, ev->fd, ev->nexus->for_app_reg);
412 XEN_LIST_REMOVE(ev, entry);
413 ev->fd = -1;
414
415 XEN_LIST_FOREACH(poller, &CTX->pollers_active, active_entry)
416 poller->fds_deregistered = 1;
417
418 out:
419 CTX_UNLOCK;
420 }
421
libxl__fd_poll_recheck(libxl__egc * egc,int fd,short events)422 short libxl__fd_poll_recheck(libxl__egc *egc, int fd, short events) {
423 struct pollfd check;
424 int r;
425 EGC_GC;
426
427 for (;;) {
428 check.fd = fd;
429 check.events = events;
430 r = poll(&check, 1, 0);
431 DBG("poll recheck fd=%d r=%d revents=%#x", fd, r, check.revents);
432 if (!r)
433 break;
434 if (r==1)
435 break;
436 assert(r<0);
437 if (errno != EINTR) {
438 LIBXL__EVENT_DISASTER(gc, "failed poll to check for fd", errno, 0);
439 return 0;
440 }
441 }
442 assert(!!r == !!check.revents);
443 return check.revents;
444 }
445
446 /*
447 * timeouts
448 */
449
450
libxl__gettimeofday(libxl__gc * gc,struct timeval * now_r)451 int libxl__gettimeofday(libxl__gc *gc, struct timeval *now_r)
452 {
453 int rc = gettimeofday(now_r, 0);
454 if (rc) {
455 LOGE(ERROR, "gettimeofday failed");
456 return ERROR_FAIL;
457 }
458 return 0;
459 }
460
time_rel_to_abs(libxl__gc * gc,int ms,struct timeval * abs_out)461 static int time_rel_to_abs(libxl__gc *gc, int ms, struct timeval *abs_out)
462 {
463 int rc;
464 struct timeval additional = {
465 .tv_sec = ms / 1000,
466 .tv_usec = (ms % 1000) * 1000
467 };
468 struct timeval now;
469
470 rc = libxl__gettimeofday(gc, &now);
471 if (rc) return rc;
472
473 timeradd(&now, &additional, abs_out);
474 return 0;
475 }
476
time_register_finite(libxl__gc * gc,libxl__ev_time * ev,struct timeval absolute)477 static int time_register_finite(libxl__gc *gc, libxl__ev_time *ev,
478 struct timeval absolute)
479 {
480 int rc;
481 libxl__ev_time *evsearch;
482
483 rc = OSEVENT_HOOK(timeout,register, alloc, &ev->nexus->for_app_reg,
484 absolute, ev->nexus);
485 if (rc) return rc;
486
487 ev->infinite = 0;
488 ev->abs = absolute;
489 LIBXL_TAILQ_INSERT_SORTED(&CTX->etimes, entry, ev, evsearch, /*empty*/,
490 timercmp(&ev->abs, &evsearch->abs, >));
491
492 pollers_note_osevent_added(CTX);
493 return 0;
494 }
495
time_deregister(libxl__gc * gc,libxl__ev_time * ev)496 static void time_deregister(libxl__gc *gc, libxl__ev_time *ev)
497 {
498 libxl__ao_abortable_deregister(&ev->abrt);
499
500 if (!ev->infinite) {
501 struct timeval right_away = { 0, 0 };
502 if (ev->nexus) /* only set if app provided hooks */
503 ev->nexus->ev = 0;
504 OSEVENT_HOOK_VOID(timeout,modify,
505 noop /* release nexus in _occurred_ */,
506 &ev->nexus->for_app_reg, right_away);
507 XEN_TAILQ_REMOVE(&CTX->etimes, ev, entry);
508 }
509 }
510
time_done_debug(libxl__gc * gc,const char * func,libxl__ev_time * ev,int rc)511 static void time_done_debug(libxl__gc *gc, const char *func,
512 libxl__ev_time *ev, int rc)
513 {
514 #ifdef DEBUG
515 libxl__log(CTX, XTL_DEBUG, -1, __FILE__, 0, func, INVALID_DOMID,
516 "ev_time=%p done rc=%d .func=%p infinite=%d abs=%lu.%06lu",
517 ev, rc, ev->func, ev->infinite,
518 (unsigned long)ev->abs.tv_sec, (unsigned long)ev->abs.tv_usec);
519 #endif
520 }
521
time_aborted(libxl__egc * egc,libxl__ao_abortable * abrt,int rc)522 static void time_aborted(libxl__egc *egc, libxl__ao_abortable *abrt, int rc)
523 {
524 libxl__ev_time *ev = CONTAINER_OF(abrt, *ev, abrt);
525 EGC_GC;
526
527 time_deregister(gc, ev);
528 DBG("ev_time=%p aborted", ev);
529 ev->func(egc, ev, &ev->abs, rc);
530 }
531
time_register_abortable(libxl__ao * ao,libxl__ev_time * ev)532 static int time_register_abortable(libxl__ao *ao, libxl__ev_time *ev)
533 {
534 ev->abrt.ao = ao;
535 ev->abrt.callback = time_aborted;
536 return libxl__ao_abortable_register(&ev->abrt);
537 }
538
libxl__ev_time_register_abs(libxl__ao * ao,libxl__ev_time * ev,libxl__ev_time_callback * func,struct timeval absolute)539 int libxl__ev_time_register_abs(libxl__ao *ao, libxl__ev_time *ev,
540 libxl__ev_time_callback *func,
541 struct timeval absolute)
542 {
543 AO_GC;
544 int rc;
545
546 CTX_LOCK;
547
548 DBG("ev_time=%p register abs=%lu.%06lu",
549 ev, (unsigned long)absolute.tv_sec, (unsigned long)absolute.tv_usec);
550
551 rc = time_register_abortable(ao, ev);
552 if (rc) goto out;
553
554 rc = time_register_finite(gc, ev, absolute);
555 if (rc) goto out;
556
557 ev->func = func;
558
559 rc = 0;
560 out:
561 libxl__ao_abortable_deregister(&ev->abrt);
562 time_done_debug(gc,__func__,ev,rc);
563 CTX_UNLOCK;
564 return rc;
565 }
566
567
libxl__ev_time_register_rel(libxl__ao * ao,libxl__ev_time * ev,libxl__ev_time_callback * func,int milliseconds)568 int libxl__ev_time_register_rel(libxl__ao *ao, libxl__ev_time *ev,
569 libxl__ev_time_callback *func,
570 int milliseconds /* as for poll(2) */)
571 {
572 AO_GC;
573 struct timeval absolute;
574 int rc;
575
576 CTX_LOCK;
577
578 DBG("ev_time=%p register ms=%d", ev, milliseconds);
579
580 rc = time_register_abortable(ao, ev);
581 if (rc) goto out;
582
583 if (milliseconds < 0) {
584 ev->infinite = 1;
585 } else {
586 rc = time_rel_to_abs(gc, milliseconds, &absolute);
587 if (rc) goto out;
588
589 rc = time_register_finite(gc, ev, absolute);
590 if (rc) goto out;
591 }
592
593 ev->func = func;
594 rc = 0;
595
596 out:
597 if (!libxl__ev_time_isregistered(ev))
598 libxl__ao_abortable_deregister(&ev->abrt);
599 time_done_debug(gc,__func__,ev,rc);
600 CTX_UNLOCK;
601 return rc;
602 }
603
libxl__ev_time_deregister(libxl__gc * gc,libxl__ev_time * ev)604 void libxl__ev_time_deregister(libxl__gc *gc, libxl__ev_time *ev)
605 {
606 CTX_LOCK;
607
608 DBG("ev_time=%p deregister", ev);
609
610 if (!libxl__ev_time_isregistered(ev))
611 goto out;
612
613 time_deregister(gc, ev);
614 ev->func = 0;
615
616 out:
617 time_done_debug(gc,__func__,ev,0);
618 CTX_UNLOCK;
619 return;
620 }
621
time_occurs(libxl__egc * egc,libxl__ev_time * etime,int rc)622 static void time_occurs(libxl__egc *egc, libxl__ev_time *etime, int rc)
623 {
624 EGC_GC;
625
626 DBG("ev_time=%p occurs abs=%lu.%06lu",
627 etime, (unsigned long)etime->abs.tv_sec,
628 (unsigned long)etime->abs.tv_usec);
629
630 libxl__ev_time_callback *func = etime->func;
631 etime->func = 0;
632 func(egc, etime, &etime->abs, rc);
633 }
634
635
636 /*
637 * xenstore watches
638 */
639
libxl__watch_slot_contents(libxl__gc * gc,int slotnum)640 libxl__ev_xswatch *libxl__watch_slot_contents(libxl__gc *gc, int slotnum)
641 {
642 libxl__ev_watch_slot *slot = &CTX->watch_slots[slotnum];
643 libxl__ev_watch_slot *slotcontents = XEN_SLIST_NEXT(slot, empty);
644
645 if (slotcontents == NULL ||
646 ((uintptr_t)slotcontents >= (uintptr_t)CTX->watch_slots &&
647 (uintptr_t)slotcontents < (uintptr_t)(CTX->watch_slots +
648 CTX->watch_nslots)))
649 /* An empty slot has either a NULL pointer (end of the
650 * free list), or a pointer to another entry in the array.
651 * So we can do a bounds check to distinguish empty from
652 * full slots.
653 */
654 /* We need to do the comparisons as uintptr_t because
655 * comparing pointers which are not in the same object is
656 * undefined behaviour; if the compiler managed to figure
657 * out that watch_slots[0..watch_nslots-1] is all of the
658 * whole array object it could prove that the above bounds
659 * check was always true if it was legal, and remove it!
660 *
661 * uintptr_t because even on a machine with signed
662 * pointers, objects do not cross zero; whereas on
663 * machines with unsigned pointers, they may cross
664 * 0x8bazillion.
665 */
666 return NULL;
667
668 /* see comment near libxl__ev_watch_slot definition */
669 return (void*)slotcontents;
670 }
671
libxl__set_watch_slot_contents(libxl__ev_watch_slot * slot,libxl__ev_xswatch * w)672 static void libxl__set_watch_slot_contents(libxl__ev_watch_slot *slot,
673 libxl__ev_xswatch *w)
674 {
675 /* we look a bit behind the curtain of XEN_SLIST, to explicitly
676 * assign to the pointer that's the next link. See the comment
677 * by the definition of libxl__ev_watch_slot */
678 slot->empty.sle_next = (void*)w;
679 }
680
watchfd_callback(libxl__egc * egc,libxl__ev_fd * ev,int fd,short events,short revents)681 static void watchfd_callback(libxl__egc *egc, libxl__ev_fd *ev,
682 int fd, short events, short revents)
683 {
684 EGC_GC;
685
686 if (revents & (POLLERR|POLLHUP))
687 LIBXL__EVENT_DISASTER(gc, "unexpected poll event on watch fd", 0, 0);
688
689 for (;;) {
690 char **event = xs_check_watch(CTX->xsh);
691 if (!event) {
692 if (errno == EAGAIN) break;
693 if (errno == EINTR) continue;
694 LIBXL__EVENT_DISASTER(gc, "cannot check/read watches", errno, 0);
695 return;
696 }
697
698 const char *epath = event[0];
699 const char *token = event[1];
700 int slotnum;
701 uint32_t counterval;
702 int rc = sscanf(token, "%d/%"SCNx32, &slotnum, &counterval);
703 if (rc != 2) {
704 LOG(ERROR, "watch epath=%s token=%s: failed to parse token",
705 epath, token);
706 /* oh well */
707 goto ignore;
708 }
709 if (slotnum < 0 || slotnum >= CTX->watch_nslots) {
710 /* perhaps in the future we will make the watchslots array shrink */
711 LIBXL__LOG(CTX, LIBXL__LOG_DEBUG, "watch epath=%s token=%s:"
712 " slotnum %d out of range [0,%d>",
713 epath, token, slotnum, CTX->watch_nslots);
714 goto ignore;
715 }
716
717 libxl__ev_xswatch *w = libxl__watch_slot_contents(gc, slotnum);
718
719 if (!w) {
720 LOG(DEBUG, "watch epath=%s token=%s: empty slot", epath, token);
721 goto ignore;
722 }
723
724 if (w->counterval != counterval) {
725 LOG(DEBUG, "watch w=%p epath=%s token=%s: counter != %"PRIx32,
726 w, epath, token, w->counterval);
727 goto ignore;
728 }
729
730 /* Now it's possible, though unlikely, that this was an event
731 * from a previous use of the same slot with the same counterval.
732 *
733 * In that case either:
734 * - the event path is a child of the watch path, in
735 * which case this watch would really have generated this
736 * event if it had been registered soon enough and we are
737 * OK to give this possibly-spurious event to the caller; or
738 * - it is not, in which case we must suppress it as the
739 * caller should not see events for unrelated paths.
740 *
741 * See also docs/misc/xenstore.txt.
742 */
743 if (!xs_path_is_subpath(w->path, epath)) {
744 LOG(DEBUG, "watch w=%p wpath=%s token=%s: unexpected epath=%s",
745 w, w->path, token, epath);
746 goto ignore;
747 }
748
749 /* At last, we have checked everything! */
750 LOG(DEBUG, "watch w=%p wpath=%s token=%s: event epath=%s",
751 w, w->path, token, epath);
752 w->callback(egc, w, w->path, epath);
753
754 ignore:
755 free(event);
756 }
757 }
758
watch_token(libxl__gc * gc,int slotnum,uint32_t counterval)759 static char *watch_token(libxl__gc *gc, int slotnum, uint32_t counterval)
760 {
761 return GCSPRINTF("%d/%"PRIx32, slotnum, counterval);
762 }
763
watches_check_fd_deregister(libxl__gc * gc)764 static void watches_check_fd_deregister(libxl__gc *gc)
765 {
766 assert(CTX->nwatches>=0);
767 if (!CTX->nwatches)
768 libxl__ev_fd_deregister(gc, &CTX->watch_efd);
769 }
770
libxl__ev_xswatch_register(libxl__gc * gc,libxl__ev_xswatch * w,libxl__ev_xswatch_callback * func,const char * path)771 int libxl__ev_xswatch_register(libxl__gc *gc, libxl__ev_xswatch *w,
772 libxl__ev_xswatch_callback *func,
773 const char *path /* copied */)
774 {
775 libxl__ev_watch_slot *use = NULL;
776 char *path_copy = NULL;
777 int rc;
778
779 CTX_LOCK;
780
781 if (!libxl__ev_fd_isregistered(&CTX->watch_efd)) {
782 rc = libxl__ev_fd_register(gc, &CTX->watch_efd, watchfd_callback,
783 xs_fileno(CTX->xsh), POLLIN);
784 if (rc) goto out_rc;
785 }
786
787 if (XEN_SLIST_EMPTY(&CTX->watch_freeslots)) {
788 /* Free list is empty so there is not in fact a linked
789 * free list in the array and we can safely realloc it */
790 int newarraysize = (CTX->watch_nslots + 1) << 2;
791 int i;
792 libxl__ev_watch_slot *newarray =
793 libxl__realloc(NOGC,
794 CTX->watch_slots, sizeof(*newarray) * newarraysize);
795 if (!newarray) goto out_nomem;
796 for (i = CTX->watch_nslots; i < newarraysize; i++)
797 XEN_SLIST_INSERT_HEAD(&CTX->watch_freeslots, &newarray[i], empty);
798 CTX->watch_slots = newarray;
799 CTX->watch_nslots = newarraysize;
800 }
801 use = XEN_SLIST_FIRST(&CTX->watch_freeslots);
802 assert(use);
803 XEN_SLIST_REMOVE_HEAD(&CTX->watch_freeslots, empty);
804
805 path_copy = strdup(path);
806 if (!path_copy) goto out_nomem;
807
808 int slotnum = use - CTX->watch_slots;
809 w->counterval = CTX->watch_counter++;
810
811 const char *token = watch_token(gc, slotnum, w->counterval);
812 LOG(DEBUG, "watch w=%p wpath=%s token=%s: register slotnum=%d",
813 w, path, token, slotnum);
814
815 if (!xs_watch(CTX->xsh, path, token)) {
816 LOGEV(ERROR, errno, "create watch for path %s", path);
817 rc = ERROR_FAIL;
818 goto out_rc;
819 }
820
821 w->slotnum = slotnum;
822 w->path = path_copy;
823 w->callback = func;
824 CTX->nwatches++;
825 libxl__set_watch_slot_contents(use, w);
826
827 CTX_UNLOCK;
828 return 0;
829
830 out_nomem:
831 rc = ERROR_NOMEM;
832 out_rc:
833 if (use)
834 XEN_SLIST_INSERT_HEAD(&CTX->watch_freeslots, use, empty);
835 free(path_copy);
836 watches_check_fd_deregister(gc);
837 CTX_UNLOCK;
838 return rc;
839 }
840
libxl__ev_xswatch_deregister(libxl__gc * gc,libxl__ev_xswatch * w)841 void libxl__ev_xswatch_deregister(libxl__gc *gc, libxl__ev_xswatch *w)
842 {
843 /* it is legal to deregister from within _callback */
844 CTX_LOCK;
845
846 if (w->slotnum >= 0) {
847 const char *token = watch_token(gc, w->slotnum, w->counterval);
848
849 LOG(DEBUG, "watch w=%p wpath=%s token=%s: deregister slotnum=%d",
850 w, w->path, token, w->slotnum);
851
852 if (!xs_unwatch(CTX->xsh, w->path, token))
853 /* Oh well, we will just get watch events forever more
854 * and ignore them. But we should complain to the log. */
855 LOGEV(ERROR, errno, "remove watch for path %s", w->path);
856
857 libxl__ev_watch_slot *slot = &CTX->watch_slots[w->slotnum];
858 XEN_SLIST_INSERT_HEAD(&CTX->watch_freeslots, slot, empty);
859 w->slotnum = -1;
860 CTX->nwatches--;
861 watches_check_fd_deregister(gc);
862 } else {
863 LOG(DEBUG, "watch w=%p: deregister unregistered", w);
864 }
865
866 free(w->path);
867 w->path = NULL;
868
869 CTX_UNLOCK;
870 }
871
872 /*
873 * evtchn
874 */
875
evtchn_revents_check(libxl__egc * egc,int revents)876 static int evtchn_revents_check(libxl__egc *egc, int revents)
877 {
878 EGC_GC;
879
880 if (revents & ~POLLIN) {
881 LOG(ERROR, "unexpected poll event on event channel fd: %x", revents);
882 LIBXL__EVENT_DISASTER(gc,
883 "unexpected poll event on event channel fd", 0, 0);
884 libxl__ev_fd_deregister(gc, &CTX->evtchn_efd);
885 return ERROR_FAIL;
886 }
887
888 assert(revents & POLLIN);
889
890 return 0;
891 }
892
evtchn_fd_callback(libxl__egc * egc,libxl__ev_fd * ev,int fd,short events,short revents)893 static void evtchn_fd_callback(libxl__egc *egc, libxl__ev_fd *ev,
894 int fd, short events, short revents)
895 {
896 EGC_GC;
897 libxl__ev_evtchn *evev;
898 int rc;
899 xenevtchn_port_or_error_t port;
900
901 rc = evtchn_revents_check(egc, revents);
902 if (rc) return;
903
904 for (;;) {
905 /* Check the fd again. The incoming revent may no longer be
906 * true, because the libxl ctx lock has not necessarily been
907 * held continuously since someone noticed the fd. Normally
908 * this wouldn't be a problem but evtchn devices don't always
909 * honour O_NONBLOCK (see xenctrl.h). */
910 revents = libxl__fd_poll_recheck(egc,fd,POLLIN);
911 if (!revents)
912 break;
913 rc = evtchn_revents_check(egc, revents);
914 if (rc) return;
915
916 /* OK, that's that workaround done. We can actually check for
917 * work for us to do: */
918
919 port = xenevtchn_pending(CTX->xce);
920 if (port < 0) {
921 if (errno == EAGAIN)
922 break;
923 LIBXL__EVENT_DISASTER(gc,
924 "unexpected failure fetching occurring event port number from evtchn",
925 errno, 0);
926 return;
927 }
928
929 XEN_LIST_FOREACH(evev, &CTX->evtchns_waiting, entry)
930 if (port == evev->port)
931 goto found;
932 /* not found */
933 DBG("ev_evtchn port=%d no-one cared", port);
934 continue;
935
936 found:
937 DBG("ev_evtchn=%p port=%d signaled", evev, port);
938 evev->waiting = 0;
939 XEN_LIST_REMOVE(evev, entry);
940 evev->callback(egc, evev);
941 }
942 }
943
libxl__ctx_evtchn_init(libxl__gc * gc)944 int libxl__ctx_evtchn_init(libxl__gc *gc) {
945 xenevtchn_handle *xce;
946 int rc, fd;
947
948 if (CTX->xce)
949 return 0;
950
951 xce = xenevtchn_open(CTX->lg, 0);
952 if (!xce) {
953 LOGE(ERROR,"cannot open libxc evtchn handle");
954 rc = ERROR_FAIL;
955 goto out;
956 }
957
958 fd = xenevtchn_fd(xce);
959 assert(fd >= 0);
960
961 rc = libxl_fd_set_nonblock(CTX, fd, 1);
962 if (rc) goto out;
963
964 CTX->xce = xce;
965 return 0;
966
967 out:
968 xenevtchn_close(xce);
969 return rc;
970 }
971
evtchn_check_fd_deregister(libxl__gc * gc)972 static void evtchn_check_fd_deregister(libxl__gc *gc)
973 {
974 if (CTX->xce && XEN_LIST_EMPTY(&CTX->evtchns_waiting))
975 libxl__ev_fd_deregister(gc, &CTX->evtchn_efd);
976 }
977
libxl__ev_evtchn_wait(libxl__gc * gc,libxl__ev_evtchn * evev)978 int libxl__ev_evtchn_wait(libxl__gc *gc, libxl__ev_evtchn *evev)
979 {
980 int r, rc;
981
982 DBG("ev_evtchn=%p port=%d wait (was waiting=%d)",
983 evev, evev->port, evev->waiting);
984
985 rc = libxl__ctx_evtchn_init(gc);
986 if (rc) goto out;
987
988 if (!libxl__ev_fd_isregistered(&CTX->evtchn_efd)) {
989 rc = libxl__ev_fd_register(gc, &CTX->evtchn_efd, evtchn_fd_callback,
990 xenevtchn_fd(CTX->xce), POLLIN);
991 if (rc) goto out;
992 }
993
994 if (evev->waiting)
995 return 0;
996
997 r = xenevtchn_unmask(CTX->xce, evev->port);
998 if (r) {
999 LOGE(ERROR,"cannot unmask event channel %d",evev->port);
1000 rc = ERROR_FAIL;
1001 goto out;
1002 }
1003
1004 evev->waiting = 1;
1005 XEN_LIST_INSERT_HEAD(&CTX->evtchns_waiting, evev, entry);
1006 return 0;
1007
1008 out:
1009 evtchn_check_fd_deregister(gc);
1010 return rc;
1011 }
1012
libxl__ev_evtchn_cancel(libxl__gc * gc,libxl__ev_evtchn * evev)1013 void libxl__ev_evtchn_cancel(libxl__gc *gc, libxl__ev_evtchn *evev)
1014 {
1015 DBG("ev_evtchn=%p port=%d cancel (was waiting=%d)",
1016 evev, evev->port, evev->waiting);
1017
1018 if (!evev->waiting)
1019 return;
1020
1021 evev->waiting = 0;
1022 XEN_LIST_REMOVE(evev, entry);
1023 evtchn_check_fd_deregister(gc);
1024 }
1025
1026 /*
1027 * waiting for device state
1028 */
1029
devstate_callback(libxl__egc * egc,libxl__xswait_state * xsw,int rc,const char * sstate)1030 static void devstate_callback(libxl__egc *egc, libxl__xswait_state *xsw,
1031 int rc, const char *sstate)
1032 {
1033 EGC_GC;
1034 libxl__ev_devstate *ds = CONTAINER_OF(xsw, *ds, w);
1035
1036 if (rc) {
1037 if (rc == ERROR_TIMEDOUT)
1038 LOG(DEBUG, "backend %s wanted state %d "" timed out", ds->w.path,
1039 ds->wanted);
1040 goto out;
1041 }
1042 if (!sstate) {
1043 LOG(DEBUG, "backend %s wanted state %d"" but it was removed",
1044 ds->w.path, ds->wanted);
1045 rc = ERROR_INVAL;
1046 goto out;
1047 }
1048
1049 int got = atoi(sstate);
1050 if (got == ds->wanted) {
1051 LOG(DEBUG, "backend %s wanted state %d ok", ds->w.path, ds->wanted);
1052 rc = 0;
1053 } else {
1054 LOG(DEBUG, "backend %s wanted state %d"" still waiting state %d",
1055 ds->w.path, ds->wanted, got);
1056 return;
1057 }
1058
1059 out:
1060 libxl__ev_devstate_cancel(gc, ds);
1061 ds->callback(egc, ds, rc);
1062 }
1063
libxl__ev_devstate_wait(libxl__ao * ao,libxl__ev_devstate * ds,libxl__ev_devstate_callback cb,const char * state_path,int state,int milliseconds)1064 int libxl__ev_devstate_wait(libxl__ao *ao, libxl__ev_devstate *ds,
1065 libxl__ev_devstate_callback cb,
1066 const char *state_path, int state, int milliseconds)
1067 {
1068 AO_GC;
1069 int rc;
1070
1071 libxl__xswait_init(&ds->w);
1072 ds->wanted = state;
1073 ds->callback = cb;
1074
1075 ds->w.ao = ao;
1076 ds->w.what = GCSPRINTF("backend %s (hoping for state change to %d)",
1077 state_path, state);
1078 ds->w.path = state_path;
1079 ds->w.timeout_ms = milliseconds;
1080 ds->w.callback = devstate_callback;
1081 rc = libxl__xswait_start(gc, &ds->w);
1082 if (rc) goto out;
1083
1084 return 0;
1085
1086 out:
1087 libxl__ev_devstate_cancel(gc, ds);
1088 return rc;
1089 }
1090
1091 /*
1092 * immediate non-reentrant callback
1093 */
1094
libxl__ev_immediate_register(libxl__egc * egc,libxl__ev_immediate * ei)1095 void libxl__ev_immediate_register(libxl__egc *egc, libxl__ev_immediate *ei)
1096 {
1097 XEN_STAILQ_INSERT_TAIL(&egc->ev_immediates, ei, entry);
1098 }
1099
1100 /*
1101 * domain death/destruction
1102 */
1103
1104 /*
1105 * We use a xenstore watch on the domain's path, rather than using an
1106 * @releaseDomain watch and asking the hypervisor. This is simpler
1107 * because turning @releaseDomain into domain-specific information is
1108 * complicated.
1109 *
1110 * It is also sufficient for our callers, which are generally trying
1111 * to do cleanup of their own execution state on domain death, for the
1112 * following reason: if the domain is destroyed then either (a) the
1113 * entries in xenstore have already been deleted, in which case the
1114 * test here works or (b) they have not in which case something has
1115 * gone very badly wrong and we are going to leak those xenstore
1116 * entries, in which case trying to avoid leaking other stuff is
1117 * futile.
1118 */
1119
libxl__domaindeathcheck_init(libxl__domaindeathcheck * dc)1120 void libxl__domaindeathcheck_init(libxl__domaindeathcheck *dc)
1121 {
1122 libxl__ao_abortable_init(&dc->abrt);
1123 libxl__ev_xswatch_init(&dc->watch);
1124 }
1125
libxl__domaindeathcheck_stop(libxl__gc * gc,libxl__domaindeathcheck * dc)1126 void libxl__domaindeathcheck_stop(libxl__gc *gc, libxl__domaindeathcheck *dc)
1127 {
1128 libxl__ao_abortable_deregister(&dc->abrt);
1129 libxl__ev_xswatch_deregister(gc,&dc->watch);
1130 }
1131
domaindeathcheck_callback(libxl__egc * egc,libxl__ev_xswatch * w,const char * watch_path,const char * event_path)1132 static void domaindeathcheck_callback(libxl__egc *egc, libxl__ev_xswatch *w,
1133 const char *watch_path, const char *event_path)
1134 {
1135 libxl__domaindeathcheck *dc = CONTAINER_OF(w, *dc, watch);
1136 EGC_GC;
1137 const char *p = libxl__xs_read(gc, XBT_NULL, watch_path);
1138 if (p) return;
1139
1140 libxl__domaindeathcheck_stop(gc,dc);
1141
1142 if (errno!=ENOENT) {
1143 LIBXL__EVENT_DISASTER(gc,"failed to read xenstore"
1144 " for domain detach check", errno, 0);
1145 return;
1146 }
1147
1148 LOG(ERROR,"%s: domain %"PRIu32" removed (%s no longer in xenstore)",
1149 dc->what, dc->domid, watch_path);
1150 dc->callback(egc, dc, ERROR_DOMAIN_DESTROYED);
1151 }
1152
domaindeathcheck_abort(libxl__egc * egc,libxl__ao_abortable * abrt,int rc)1153 static void domaindeathcheck_abort(libxl__egc *egc,
1154 libxl__ao_abortable *abrt,
1155 int rc)
1156 {
1157 libxl__domaindeathcheck *dc = CONTAINER_OF(abrt, *dc, abrt);
1158 EGC_GC;
1159
1160 libxl__domaindeathcheck_stop(gc,dc);
1161 dc->callback(egc, dc, rc);
1162 }
1163
libxl__domaindeathcheck_start(libxl__ao * ao,libxl__domaindeathcheck * dc)1164 int libxl__domaindeathcheck_start(libxl__ao *ao,
1165 libxl__domaindeathcheck *dc)
1166 {
1167 AO_GC;
1168 int rc;
1169 const char *path = GCSPRINTF("/local/domain/%"PRIu32, dc->domid);
1170
1171 libxl__domaindeathcheck_init(dc);
1172
1173 dc->abrt.ao = ao;
1174 dc->abrt.callback = domaindeathcheck_abort;
1175 rc = libxl__ao_abortable_register(&dc->abrt);
1176 if (rc) goto out;
1177
1178 rc = libxl__ev_xswatch_register(gc, &dc->watch,
1179 domaindeathcheck_callback, path);
1180 if (rc) goto out;
1181
1182 return 0;
1183
1184 out:
1185 libxl__domaindeathcheck_stop(gc,dc);
1186 return rc;
1187 }
1188
1189 /*
1190 * osevent poll
1191 */
1192
beforepoll_internal(libxl__gc * gc,libxl__poller * poller,int * nfds_io,struct pollfd * fds,int * timeout_upd,struct timeval now)1193 static int beforepoll_internal(libxl__gc *gc, libxl__poller *poller,
1194 int *nfds_io, struct pollfd *fds,
1195 int *timeout_upd, struct timeval now)
1196 {
1197 libxl__ev_fd *efd;
1198 int rc;
1199
1200 /*
1201 * We need to look at the fds we want twice: firstly, to count
1202 * them so we can make the rindex array big enough, and secondly
1203 * to actually fill the arrays in.
1204 *
1205 * To ensure correctness and avoid repeating the logic for
1206 * deciding which fds are relevant, we define a macro
1207 * REQUIRE_FDS( BODY )
1208 * which calls
1209 * do{
1210 * int req_fd;
1211 * int req_events;
1212 * BODY;
1213 * }while(0)
1214 * for each fd with a nonzero events. This is invoked twice.
1215 *
1216 * The definition of REQUIRE_FDS is simplified with the helper
1217 * macro
1218 * void REQUIRE_FD(int req_fd, int req_events, BODY);
1219 */
1220
1221 #define REQUIRE_FDS(BODY) do{ \
1222 \
1223 XEN_LIST_FOREACH(efd, &CTX->efds, entry) \
1224 REQUIRE_FD(efd->fd, efd->events, BODY); \
1225 \
1226 REQUIRE_FD(poller->wakeup_pipe[0], POLLIN, BODY); \
1227 \
1228 }while(0)
1229
1230 #define REQUIRE_FD(req_fd_, req_events_, BODY) do{ \
1231 int req_events = (req_events_); \
1232 int req_fd = (req_fd_); \
1233 if (req_events) { \
1234 BODY; \
1235 } \
1236 }while(0)
1237
1238
1239 /*
1240 * In order to be able to efficiently find the libxl__ev_fd for a
1241 * struct poll during _afterpoll, we maintain a shadow data
1242 * structure in CTX->fd_rindices: each fd corresponds to a slot in
1243 * fd_rindices, and each element in the rindices is three indices
1244 * into the fd array (for POLLIN, POLLPRI and POLLOUT).
1245 */
1246
1247 if (*nfds_io) {
1248 /*
1249 * As an optimisation, we don't touch fd_rindex
1250 * if *nfds_io is zero on entry, since in that case the
1251 * caller just wanted to know how big an array to give us.
1252 *
1253 * If !*nfds_io, the unconditional parts below are guaranteed
1254 * not to mess with fd_rindex.
1255 */
1256
1257 int maxfd = 0;
1258
1259 REQUIRE_FDS({
1260 if (req_fd >= maxfd)
1261 maxfd = req_fd + 1;
1262 });
1263
1264 /* make sure our array is as big as *nfds_io */
1265 if (poller->fd_rindices_allocd < maxfd) {
1266 assert(ARRAY_SIZE_OK(poller->fd_rindices, maxfd));
1267 poller->fd_rindices =
1268 libxl__realloc(NOGC, poller->fd_rindices,
1269 maxfd * sizeof(*poller->fd_rindices));
1270 memset(poller->fd_rindices + poller->fd_rindices_allocd,
1271 0,
1272 (maxfd - poller->fd_rindices_allocd)
1273 * sizeof(*poller->fd_rindices));
1274 poller->fd_rindices_allocd = maxfd;
1275 }
1276 }
1277
1278 int used = 0;
1279
1280 REQUIRE_FDS({
1281 if (used < *nfds_io) {
1282 fds[used].fd = req_fd;
1283 fds[used].events = req_events;
1284 fds[used].revents = 0;
1285 assert(req_fd < poller->fd_rindices_allocd);
1286 if (req_events & POLLIN) poller->fd_rindices[req_fd][0] = used;
1287 if (req_events & POLLPRI) poller->fd_rindices[req_fd][1] = used;
1288 if (req_events & POLLOUT) poller->fd_rindices[req_fd][2] = used;
1289 }
1290 used++;
1291 });
1292
1293 rc = used <= *nfds_io ? 0 : ERROR_BUFFERFULL;
1294
1295 *nfds_io = used;
1296
1297 poller->fds_deregistered = 0;
1298 poller->osevents_added = 0;
1299
1300 libxl__ev_time *etime = XEN_TAILQ_FIRST(&CTX->etimes);
1301 if (etime) {
1302 int our_timeout;
1303 struct timeval rel;
1304 static struct timeval zero;
1305
1306 timersub(&etime->abs, &now, &rel);
1307
1308 if (timercmp(&rel, &zero, <)) {
1309 our_timeout = 0;
1310 } else if (rel.tv_sec >= 2000000) {
1311 our_timeout = 2000000000;
1312 } else {
1313 our_timeout = rel.tv_sec * 1000 + (rel.tv_usec + 999) / 1000;
1314 }
1315 if (*timeout_upd < 0 || our_timeout < *timeout_upd)
1316 *timeout_upd = our_timeout;
1317 }
1318
1319 return rc;
1320 }
1321
libxl_osevent_beforepoll(libxl_ctx * ctx,int * nfds_io,struct pollfd * fds,int * timeout_upd,struct timeval now)1322 int libxl_osevent_beforepoll(libxl_ctx *ctx, int *nfds_io,
1323 struct pollfd *fds, int *timeout_upd,
1324 struct timeval now)
1325 {
1326 EGC_INIT(ctx);
1327 CTX_LOCK;
1328 int rc = beforepoll_internal(gc, ctx->poller_app,
1329 nfds_io, fds, timeout_upd, now);
1330 CTX_UNLOCK_EGC_FREE;
1331 return rc;
1332 }
1333
afterpoll_check_fd(libxl__poller * poller,const struct pollfd * fds,int nfds,int fd,int events)1334 static int afterpoll_check_fd(libxl__poller *poller,
1335 const struct pollfd *fds, int nfds,
1336 int fd, int events)
1337 /* Returns mask of events which were requested and occurred. Will
1338 * return nonzero only once for each (poller,fd,events)
1339 * combination, until the next beforepoll. If events from
1340 * different combinations overlap, between one such combination
1341 * and all distinct combinations will produce nonzero returns. */
1342 {
1343 if (fd >= poller->fd_rindices_allocd)
1344 /* added after we went into poll, have to try again */
1345 return 0;
1346
1347 events |= POLLERR | POLLHUP;
1348
1349 int i, revents = 0;
1350 for (i=0; i<3; i++) {
1351 int *slotp = &poller->fd_rindices[fd][i];
1352 int slot = *slotp;
1353
1354 if (slot >= nfds)
1355 /* stale slot entry (again, added afterwards), */
1356 /* or slot for which we have already returned nonzero */
1357 continue;
1358
1359 if (fds[slot].fd != fd)
1360 /* again, stale slot entry */
1361 continue;
1362
1363 assert(poller->fds_deregistered || !(fds[slot].revents & POLLNVAL));
1364
1365 /* we mask in case requested events have changed */
1366 int slot_revents = fds[slot].revents & events;
1367 if (!slot_revents)
1368 /* this slot is for a different set of events */
1369 continue;
1370
1371 revents |= slot_revents;
1372 *slotp = INT_MAX; /* so that next time we'll see slot >= nfds */
1373 }
1374
1375 return revents;
1376 }
1377
fd_occurs(libxl__egc * egc,libxl__ev_fd * efd,short revents_ign)1378 static void fd_occurs(libxl__egc *egc, libxl__ev_fd *efd, short revents_ign)
1379 {
1380 short revents_current = libxl__fd_poll_recheck(egc, efd->fd, efd->events);
1381 EGC_GC;
1382
1383 DBG("ev_fd=%p occurs fd=%d events=%x revents_ign=%x revents_current=%x",
1384 efd, efd->fd, efd->events, revents_ign, revents_current);
1385
1386 if (revents_current)
1387 efd->func(egc, efd, efd->fd, efd->events, revents_current);
1388 }
1389
afterpoll_internal(libxl__egc * egc,libxl__poller * poller,int nfds,const struct pollfd * fds,struct timeval now)1390 static void afterpoll_internal(libxl__egc *egc, libxl__poller *poller,
1391 int nfds, const struct pollfd *fds,
1392 struct timeval now)
1393 {
1394 /* May make callbacks into the application for child processes.
1395 * ctx must be locked exactly once */
1396 EGC_GC;
1397 libxl__ev_fd *efd;
1398
1399 /*
1400 * Warning! Reentrancy hazards!
1401 *
1402 * Many parts of this function eventually call arbitrary callback
1403 * functions which may modify the event handling data structures.
1404 *
1405 * Of the data structures used here:
1406 *
1407 * egc, poller, now
1408 * are allocated by our caller and relate to the
1409 * current thread and its call stack down into the
1410 * event machinery; it is not freed until we return.
1411 * So it is safe.
1412 *
1413 * fds is either what application passed into
1414 * libxl_osevent_afterpoll (which, although this
1415 * isn't explicitly stated, clearly must remain
1416 * valid until libxl_osevent_afterpoll returns) or
1417 * it's poller->fd_polls which is modified only by
1418 * our (non-recursive) caller eventloop_iteration.
1419 *
1420 * CTX comes from our caller, and applications are
1421 * forbidden from destroying it while we are running.
1422 * So the ctx pointer itself is safe to use; now
1423 * for its contents:
1424 *
1425 * CTX->etimes is used in a simple reentrancy-safe manner.
1426 *
1427 * CTX->efds is more complicated; see below.
1428 */
1429
1430 for (;;) {
1431 /* We restart our scan of fd events whenever we call a
1432 * callback function. This is necessary because such
1433 * a callback might make arbitrary changes to CTX->efds.
1434 * We invalidate the fd_rindices[] entries which were used
1435 * so that we don't call the same function again. */
1436 int revents;
1437
1438 XEN_LIST_FOREACH(efd, &CTX->efds, entry) {
1439
1440 if (!efd->events)
1441 continue;
1442
1443 revents = afterpoll_check_fd(poller,fds,nfds,
1444 efd->fd,efd->events);
1445 if (revents)
1446 goto found_fd_event;
1447 }
1448 /* no ordinary fd events, then */
1449 break;
1450
1451 found_fd_event:
1452 fd_occurs(egc, efd, revents);
1453 }
1454
1455 for (;;) {
1456 libxl__ev_time *etime = XEN_TAILQ_FIRST(&CTX->etimes);
1457 if (!etime)
1458 break;
1459
1460 assert(!etime->infinite);
1461
1462 if (timercmp(&etime->abs, &now, >))
1463 break;
1464
1465 time_deregister(gc, etime);
1466
1467 time_occurs(egc, etime, ERROR_TIMEDOUT);
1468 }
1469
1470 if (afterpoll_check_fd(poller,fds,nfds, poller->wakeup_pipe[0],POLLIN)) {
1471 poller->pipe_nonempty = 0;
1472 int e = libxl__self_pipe_eatall(poller->wakeup_pipe[0]);
1473 if (e) LIBXL__EVENT_DISASTER(gc, "read wakeup", e, 0);
1474 }
1475 }
1476
libxl_osevent_afterpoll(libxl_ctx * ctx,int nfds,const struct pollfd * fds,struct timeval now)1477 void libxl_osevent_afterpoll(libxl_ctx *ctx, int nfds, const struct pollfd *fds,
1478 struct timeval now)
1479 {
1480 EGC_INIT(ctx);
1481 CTX_LOCK;
1482 afterpoll_internal(egc, ctx->poller_app, nfds, fds, now);
1483 CTX_UNLOCK_EGC_FREE;
1484 }
1485
1486 /*
1487 * osevent hook and callback machinery
1488 */
1489
libxl_osevent_register_hooks(libxl_ctx * ctx,const libxl_osevent_hooks * hooks,void * user)1490 void libxl_osevent_register_hooks(libxl_ctx *ctx,
1491 const libxl_osevent_hooks *hooks,
1492 void *user)
1493 {
1494 GC_INIT(ctx);
1495 CTX_LOCK;
1496 assert(XEN_LIST_EMPTY(&ctx->efds));
1497 assert(XEN_TAILQ_EMPTY(&ctx->etimes));
1498 ctx->osevent_hooks = hooks;
1499 ctx->osevent_user = user;
1500 CTX_UNLOCK;
1501 GC_FREE;
1502 }
1503
1504
libxl_osevent_occurred_fd(libxl_ctx * ctx,void * for_libxl,int fd,short events_ign,short revents_ign)1505 void libxl_osevent_occurred_fd(libxl_ctx *ctx, void *for_libxl,
1506 int fd, short events_ign, short revents_ign)
1507 {
1508 EGC_INIT(ctx);
1509 CTX_LOCK;
1510 assert(!CTX->osevent_in_hook);
1511
1512 libxl__ev_fd *ev = osevent_ev_from_hook_nexus(ctx, for_libxl);
1513 if (!ev) goto out;
1514 if (ev->fd != fd) goto out;
1515
1516 fd_occurs(egc, ev, revents_ign);
1517
1518 out:
1519 CTX_UNLOCK_EGC_FREE;
1520 }
1521
libxl_osevent_occurred_timeout(libxl_ctx * ctx,void * for_libxl)1522 void libxl_osevent_occurred_timeout(libxl_ctx *ctx, void *for_libxl)
1523 {
1524 EGC_INIT(ctx);
1525 CTX_LOCK;
1526 assert(!CTX->osevent_in_hook);
1527
1528 libxl__osevent_hook_nexus *nexus = for_libxl;
1529 libxl__ev_time *ev = osevent_ev_from_hook_nexus(ctx, nexus);
1530
1531 osevent_release_nexus(gc, &CTX->hook_timeout_nexi_idle, nexus);
1532
1533 if (!ev) goto out;
1534 assert(!ev->infinite);
1535
1536 XEN_TAILQ_REMOVE(&CTX->etimes, ev, entry);
1537
1538 time_occurs(egc, ev, ERROR_TIMEDOUT);
1539
1540 out:
1541 CTX_UNLOCK_EGC_FREE;
1542 }
1543
libxl__event_disaster(libxl__gc * gc,const char * msg,int errnoval,libxl_event_type type,const char * file,int line,const char * func)1544 void libxl__event_disaster(libxl__gc *gc, const char *msg, int errnoval,
1545 libxl_event_type type /* may be 0 */,
1546 const char *file, int line, const char *func)
1547 {
1548 libxl__log(CTX, XTL_CRITICAL, errnoval, file, line, func, INVALID_DOMID,
1549 "DISASTER in event loop: %s%s%s%s",
1550 msg,
1551 type ? " (relates to event type " : "",
1552 type ? libxl_event_type_to_string(type) : "",
1553 type ? ")" : "");
1554
1555 if (CTX->event_hooks && CTX->event_hooks->disaster) {
1556 CTX->event_hooks->disaster(CTX->event_hooks_user, type, msg, errnoval);
1557 return;
1558 }
1559
1560 const char verybad[] =
1561 "DISASTER in event loop not handled by libxl application";
1562 LIBXL__LOG(CTX, XTL_CRITICAL, verybad);
1563 fprintf(stderr, "libxl: fatal error, exiting program: %s\n", verybad);
1564 exit(-1);
1565 }
1566
egc_run_callbacks(libxl__egc * egc)1567 static void egc_run_callbacks(libxl__egc *egc)
1568 {
1569 /*
1570 * The callbacks must happen with the ctx unlocked. See the
1571 * comment near #define EGC_GC in libxl_internal.h and those in
1572 * the definitions of libxl__egc, libxl__ao and libxl__aop.
1573 */
1574 EGC_GC;
1575 libxl_event *ev, *ev_tmp;
1576 libxl__aop_occurred *aop, *aop_tmp;
1577 libxl__ev_immediate *ei;
1578
1579 while (!XEN_STAILQ_EMPTY(&egc->ev_immediates)) {
1580 ei = XEN_STAILQ_FIRST(&egc->ev_immediates);
1581 XEN_STAILQ_REMOVE_HEAD(&egc->ev_immediates, entry);
1582 CTX_LOCK;
1583 /* This callback is internal to libxl and expects CTX to be
1584 * locked. */
1585 ei->callback(egc, ei);
1586 CTX_UNLOCK;
1587 }
1588
1589 XEN_TAILQ_FOREACH_SAFE(ev, &egc->occurred_for_callback, link, ev_tmp) {
1590 XEN_TAILQ_REMOVE(&egc->occurred_for_callback, ev, link);
1591 LOG(DEBUG,"event %p callback type=%s",
1592 ev, libxl_event_type_to_string(ev->type));
1593 CTX->event_hooks->event_occurs(CTX->event_hooks_user, ev);
1594 }
1595
1596 XEN_TAILQ_FOREACH_SAFE(aop, &egc->aops_for_callback, entry, aop_tmp) {
1597 XEN_TAILQ_REMOVE(&egc->aops_for_callback, aop, entry);
1598 LOG(DEBUG,"ao %p: progress report: callback aop=%p", aop->ao, aop);
1599 aop->how->callback(CTX, aop->ev, aop->how->for_callback);
1600
1601 CTX_LOCK;
1602 assert(aop->ao->magic == LIBXL__AO_MAGIC);
1603 aop->ao->progress_reports_outstanding--;
1604 libxl__ao_complete_check_progress_reports(egc, aop->ao);
1605 CTX_UNLOCK;
1606 }
1607
1608 libxl__ao *ao, *ao_tmp;
1609 XEN_TAILQ_FOREACH_SAFE(ao, &egc->aos_for_callback,
1610 entry_for_callback, ao_tmp) {
1611 XEN_TAILQ_REMOVE(&egc->aos_for_callback, ao, entry_for_callback);
1612 LOG(DEBUG,"ao %p: completion callback", ao);
1613 ao->how.callback(CTX, ao->rc, ao->how.u.for_callback);
1614 CTX_LOCK;
1615 ao->notified = 1;
1616 ao__check_destroy(CTX, ao);
1617 CTX_UNLOCK;
1618 }
1619 }
1620
libxl__egc_cleanup_2_ul_cb_gc(libxl__egc * egc)1621 void libxl__egc_cleanup_2_ul_cb_gc(libxl__egc *egc)
1622 {
1623 EGC_GC;
1624 egc_run_callbacks(egc);
1625
1626 libxl__free_all(gc);
1627 }
1628
1629 /*
1630 * Event retrieval etc.
1631 */
1632
libxl_event_register_callbacks(libxl_ctx * ctx,const libxl_event_hooks * hooks,void * user)1633 void libxl_event_register_callbacks(libxl_ctx *ctx,
1634 const libxl_event_hooks *hooks, void *user)
1635 {
1636 ctx->event_hooks = hooks;
1637 ctx->event_hooks_user = user;
1638 }
1639
libxl__event_occurred(libxl__egc * egc,libxl_event * event)1640 void libxl__event_occurred(libxl__egc *egc, libxl_event *event)
1641 {
1642 EGC_GC;
1643
1644 if (CTX->event_hooks &&
1645 (CTX->event_hooks->event_occurs_mask & (1UL << event->type))) {
1646 /* libxl__egc_cleanup will call the callback, just before exit
1647 * from libxl. This helps avoid reentrancy bugs: parts of
1648 * libxl that call libxl__event_occurred do not have to worry
1649 * that libxl might be reentered at that point. */
1650 XEN_TAILQ_INSERT_TAIL(&egc->occurred_for_callback, event, link);
1651 return;
1652 } else {
1653 libxl__poller *poller;
1654 XEN_TAILQ_INSERT_TAIL(&CTX->occurred, event, link);
1655 XEN_LIST_FOREACH(poller, &CTX->pollers_event, entry)
1656 libxl__poller_wakeup(gc, poller);
1657 }
1658 }
1659
libxl_event_free(libxl_ctx * ctx,libxl_event * event)1660 void libxl_event_free(libxl_ctx *ctx, libxl_event *event)
1661 {
1662 /* Exceptionally, this function may be called from libxl, with ctx==0 */
1663 libxl_event_dispose(event);
1664 free(event);
1665 }
1666
libxl__event_new(libxl__egc * egc,libxl_event_type type,uint32_t domid,libxl_ev_user for_user)1667 libxl_event *libxl__event_new(libxl__egc *egc,
1668 libxl_event_type type, uint32_t domid,
1669 libxl_ev_user for_user)
1670 {
1671 EGC_GC;
1672 libxl_event *ev;
1673
1674 ev = libxl__zalloc(NOGC,sizeof(*ev));
1675
1676 libxl_event_init(ev);
1677 libxl_event_init_type(ev, type);
1678
1679 ev->domid = domid;
1680 ev->for_user = for_user;
1681
1682 return ev;
1683 }
1684
event_check_internal(libxl__egc * egc,libxl_event ** event_r,unsigned long typemask,libxl_event_predicate * pred,void * pred_user)1685 static int event_check_internal(libxl__egc *egc, libxl_event **event_r,
1686 unsigned long typemask,
1687 libxl_event_predicate *pred, void *pred_user)
1688 {
1689 EGC_GC;
1690 libxl_event *ev;
1691 int rc;
1692
1693 XEN_TAILQ_FOREACH(ev, &CTX->occurred, link) {
1694 if (!(typemask & ((uint64_t)1 << ev->type)))
1695 continue;
1696
1697 if (pred && !pred(ev, pred_user))
1698 continue;
1699
1700 /* got one! */
1701 XEN_TAILQ_REMOVE(&CTX->occurred, ev, link);
1702 *event_r = ev;
1703 rc = 0;
1704 goto out;
1705 }
1706 rc = ERROR_NOT_READY;
1707
1708 out:
1709 return rc;
1710 }
1711
libxl_event_check(libxl_ctx * ctx,libxl_event ** event_r,uint64_t typemask,libxl_event_predicate * pred,void * pred_user)1712 int libxl_event_check(libxl_ctx *ctx, libxl_event **event_r,
1713 uint64_t typemask,
1714 libxl_event_predicate *pred, void *pred_user)
1715 {
1716 EGC_INIT(ctx);
1717 CTX_LOCK;
1718 int rc = event_check_internal(egc, event_r, typemask, pred, pred_user);
1719 CTX_UNLOCK_EGC_FREE;
1720 return rc;
1721 }
1722
1723 /*
1724 * Utilities for pipes (specifically, useful for self-pipes)
1725 */
1726
libxl__pipe_close(int fds[2])1727 void libxl__pipe_close(int fds[2])
1728 {
1729 if (fds[0] >= 0) close(fds[0]);
1730 if (fds[1] >= 0) close(fds[1]);
1731 fds[0] = fds[1] = -1;
1732 }
1733
libxl__pipe_nonblock(libxl_ctx * ctx,int fds[2])1734 int libxl__pipe_nonblock(libxl_ctx *ctx, int fds[2])
1735 {
1736 int r, rc;
1737
1738 r = libxl_pipe(ctx, fds);
1739 if (r) {
1740 fds[0] = fds[1] = -1;
1741 rc = ERROR_FAIL;
1742 goto out;
1743 }
1744
1745 rc = libxl_fd_set_nonblock(ctx, fds[0], 1);
1746 if (rc) goto out;
1747
1748 rc = libxl_fd_set_nonblock(ctx, fds[1], 1);
1749 if (rc) goto out;
1750
1751 return 0;
1752
1753 out:
1754 libxl__pipe_close(fds);
1755 return rc;
1756 }
1757
libxl__self_pipe_wakeup(int fd)1758 int libxl__self_pipe_wakeup(int fd)
1759 {
1760 /* Called from signal handlers, so needs to be async-signal-safe */
1761 static const char buf[1] = "";
1762
1763 for (;;) {
1764 int r = write(fd, buf, 1);
1765 if (r==1) return 0;
1766 assert(r==-1);
1767 if (errno == EINTR) continue;
1768 if (errno == EWOULDBLOCK) return 0;
1769 if (!errno) abort();
1770 return errno;
1771 }
1772 }
1773
libxl__self_pipe_eatall(int fd)1774 int libxl__self_pipe_eatall(int fd)
1775 {
1776 char buf[256];
1777 for (;;) {
1778 int r = read(fd, buf, sizeof(buf));
1779 if (r == sizeof(buf)) continue;
1780 if (r >= 0) return 0;
1781 assert(r == -1);
1782 if (errno == EINTR) continue;
1783 if (errno == EWOULDBLOCK) return 0;
1784 assert(errno);
1785 return errno;
1786 }
1787 }
1788
1789 /*
1790 * Manipulation of pollers
1791 */
1792
libxl__poller_init(libxl__gc * gc,libxl__poller * p)1793 int libxl__poller_init(libxl__gc *gc, libxl__poller *p)
1794 {
1795 int rc;
1796 p->fd_polls = 0;
1797 p->fd_rindices = 0;
1798 p->fds_deregistered = 0;
1799
1800 rc = libxl__pipe_nonblock(CTX, p->wakeup_pipe);
1801 if (rc) goto out;
1802
1803 libxl_fd_set_cloexec(CTX, p->wakeup_pipe[0], 1);
1804 libxl_fd_set_cloexec(CTX, p->wakeup_pipe[1], 1);
1805
1806 return 0;
1807
1808 out:
1809 libxl__poller_dispose(p);
1810 return rc;
1811 }
1812
libxl__poller_dispose(libxl__poller * p)1813 void libxl__poller_dispose(libxl__poller *p)
1814 {
1815 libxl__pipe_close(p->wakeup_pipe);
1816 free(p->fd_polls);
1817 free(p->fd_rindices);
1818 }
1819
libxl__poller_get(libxl__gc * gc)1820 libxl__poller *libxl__poller_get(libxl__gc *gc)
1821 {
1822 /* must be called with ctx locked */
1823 int rc;
1824
1825 libxl__poller *p = XEN_LIST_FIRST(&CTX->pollers_idle);
1826 if (p) {
1827 XEN_LIST_REMOVE(p, entry);
1828 } else {
1829 p = libxl__zalloc(NOGC, sizeof(*p));
1830
1831 rc = libxl__poller_init(gc, p);
1832 if (rc) {
1833 free(p);
1834 return NULL;
1835 }
1836 }
1837
1838 XEN_LIST_INSERT_HEAD(&CTX->pollers_active, p, active_entry);
1839 return p;
1840 }
1841
libxl__poller_put(libxl_ctx * ctx,libxl__poller * p)1842 void libxl__poller_put(libxl_ctx *ctx, libxl__poller *p)
1843 {
1844 if (!p) return;
1845 XEN_LIST_REMOVE(p, active_entry);
1846 XEN_LIST_INSERT_HEAD(&ctx->pollers_idle, p, entry);
1847 }
1848
libxl__poller_wakeup(libxl__gc * gc,libxl__poller * p)1849 void libxl__poller_wakeup(libxl__gc *gc, libxl__poller *p)
1850 {
1851 if (p->pipe_nonempty) return;
1852 p->pipe_nonempty = 1;
1853 int e = libxl__self_pipe_wakeup(p->wakeup_pipe[1]);
1854 if (e) LIBXL__EVENT_DISASTER(gc, "cannot poke watch pipe", e, 0);
1855 }
1856
1857 /*
1858 * Main event loop iteration
1859 */
1860
eventloop_iteration(libxl__egc * egc,libxl__poller * poller)1861 static int eventloop_iteration(libxl__egc *egc, libxl__poller *poller) {
1862 /* The CTX must be locked EXACTLY ONCE so that this function
1863 * can unlock it when it polls.
1864 */
1865 EGC_GC;
1866 int rc, nfds;
1867 struct timeval now;
1868
1869 rc = libxl__gettimeofday(gc, &now);
1870 if (rc) goto out;
1871
1872 int timeout;
1873
1874 for (;;) {
1875 nfds = poller->fd_polls_allocd;
1876 timeout = -1;
1877 rc = beforepoll_internal(gc, poller, &nfds, poller->fd_polls,
1878 &timeout, now);
1879 if (!rc) break;
1880 if (rc != ERROR_BUFFERFULL) goto out;
1881
1882 struct pollfd *newarray =
1883 (nfds > INT_MAX / sizeof(struct pollfd) / 2) ? 0 :
1884 libxl__realloc(NOGC, poller->fd_polls, sizeof(*newarray) * nfds);
1885
1886 if (!newarray) { rc = ERROR_NOMEM; goto out; }
1887
1888 poller->fd_polls = newarray;
1889 poller->fd_polls_allocd = nfds;
1890 }
1891
1892 CTX_UNLOCK;
1893 rc = poll(poller->fd_polls, nfds, timeout);
1894 CTX_LOCK;
1895
1896 if (rc < 0) {
1897 if (errno == EINTR)
1898 return 0; /* will go round again if caller requires */
1899
1900 LOGEV(ERROR, errno, "poll failed");
1901 rc = ERROR_FAIL;
1902 goto out;
1903 }
1904
1905 rc = libxl__gettimeofday(gc, &now);
1906 if (rc) goto out;
1907
1908 afterpoll_internal(egc, poller, nfds, poller->fd_polls, now);
1909
1910 rc = 0;
1911 out:
1912 return rc;
1913 }
1914
libxl_event_wait(libxl_ctx * ctx,libxl_event ** event_r,uint64_t typemask,libxl_event_predicate * pred,void * pred_user)1915 int libxl_event_wait(libxl_ctx *ctx, libxl_event **event_r,
1916 uint64_t typemask,
1917 libxl_event_predicate *pred, void *pred_user)
1918 {
1919 int rc;
1920 libxl__poller *poller = NULL;
1921
1922 EGC_INIT(ctx);
1923 CTX_LOCK;
1924
1925 poller = libxl__poller_get(gc);
1926 if (!poller) { rc = ERROR_FAIL; goto out; }
1927
1928 for (;;) {
1929 rc = event_check_internal(egc, event_r, typemask, pred, pred_user);
1930 if (rc != ERROR_NOT_READY) goto out;
1931
1932 rc = eventloop_iteration(egc, poller);
1933 if (rc) goto out;
1934
1935 /* we unlock and cleanup the egc each time we go through this
1936 * loop, so that (a) we don't accumulate garbage and (b) any
1937 * events which are to be dispatched by callback are actually
1938 * delivered in a timely fashion. _1_baton will be
1939 * called to pass the baton iff we actually leave; otherwise
1940 * we are still carrying it.
1941 */
1942 CTX_UNLOCK;
1943 libxl__egc_cleanup_2_ul_cb_gc(egc);
1944 CTX_LOCK;
1945 }
1946
1947 out:
1948 libxl__poller_put(ctx, poller);
1949
1950 CTX_UNLOCK_EGC_FREE;
1951 return rc;
1952 }
1953
1954
1955
1956 /*
1957 * The two possible state flow of an ao:
1958 *
1959 * Completion before initiator return:
1960 *
1961 * Initiator thread Possible other threads
1962 *
1963 * * ao_create allocates memory and
1964 * initialises the struct
1965 *
1966 * * the initiator function does its
1967 * work, setting up various internal
1968 * asynchronous operations -----------> * asynchronous operations
1969 * start to take place and
1970 * might cause ao completion
1971 * |
1972 * * initiator calls ao_inprogress |
1973 * - if synchronous, run event loop |
1974 * until the ao completes |
1975 * - ao completes on some thread
1976 * - completing thread releases the lock
1977 * <--------------'
1978 * - ao_inprogress takes the lock
1979 * - destroy the ao
1980 *
1981 *
1982 * Completion after initiator return (asynch. only):
1983 *
1984 *
1985 * Initiator thread Possible other threads
1986 *
1987 * * ao_create allocates memory and
1988 * initialises the struct
1989 *
1990 * * the initiator function does its
1991 * work, setting up various internal
1992 * asynchronous operations -----------> * asynchronous operations
1993 * start to take place and
1994 * might cause ao completion
1995 * |
1996 * * initiator calls ao_inprogress |
1997 * - observes event not yet done, |
1998 * - returns to caller |
1999 * |
2000 * - ao completes on some thread
2001 * - generate the event or call the callback
2002 * - destroy the ao
2003 */
2004
2005
2006 /*
2007 * A "manip" is a libxl public function manipulating this ao, which
2008 * has a pointer to it. We have to not destroy it while that's the
2009 * case, obviously. Callers must have the ctx locked, obviously.
2010 */
ao__manip_enter(libxl__ao * ao)2011 static void ao__manip_enter(libxl__ao *ao)
2012 {
2013 assert(ao->manip_refcnt < INT_MAX);
2014 ao->manip_refcnt++;
2015 }
2016
ao__manip_leave(libxl_ctx * ctx,libxl__ao * ao)2017 static void ao__manip_leave(libxl_ctx *ctx, libxl__ao *ao)
2018 {
2019 assert(ao->manip_refcnt > 0);
2020 ao->manip_refcnt--;
2021 ao__check_destroy(ctx, ao);
2022 }
2023
ao__check_destroy(libxl_ctx * ctx,libxl__ao * ao)2024 static void ao__check_destroy(libxl_ctx *ctx, libxl__ao *ao)
2025 {
2026 if (!ao->manip_refcnt && ao->notified) {
2027 assert(ao->complete);
2028 libxl__ao__destroy(ctx, ao);
2029 }
2030 }
2031
libxl__ao__destroy(libxl_ctx * ctx,libxl__ao * ao)2032 void libxl__ao__destroy(libxl_ctx *ctx, libxl__ao *ao)
2033 {
2034 AO_GC;
2035 if (!ao) return;
2036 LOG(DEBUG,"ao %p: destroy",ao);
2037 libxl__poller_put(ctx, ao->poller);
2038 ao->magic = LIBXL__AO_MAGIC_DESTROYED;
2039 libxl__free_all(&ao->gc);
2040 free(ao);
2041 }
2042
libxl__ao_create_fail(libxl__ao * ao)2043 void libxl__ao_create_fail(libxl__ao *ao)
2044 {
2045 AO_GC;
2046 LOG(DEBUG,"ao %p: create fail",ao);
2047 assert(ao->magic == LIBXL__AO_MAGIC);
2048 assert(ao->in_initiator);
2049 assert(!ao->complete);
2050 assert(!ao->progress_reports_outstanding);
2051 assert(!ao->aborting);
2052 XEN_LIST_REMOVE(ao, inprogress_entry);
2053 libxl__ao__destroy(CTX, ao);
2054 }
2055
libxl__ao_inprogress_gc(libxl__ao * ao)2056 libxl__gc *libxl__ao_inprogress_gc(libxl__ao *ao)
2057 {
2058 assert(ao);
2059 assert(ao->magic == LIBXL__AO_MAGIC);
2060 assert(!ao->complete);
2061 return &ao->gc;
2062 }
2063
libxl__ao_complete(libxl__egc * egc,libxl__ao * ao,int rc)2064 void libxl__ao_complete(libxl__egc *egc, libxl__ao *ao, int rc)
2065 {
2066 AO_GC;
2067 LOG(DEBUG,"ao %p: complete, rc=%d",ao,rc);
2068 assert(ao->magic == LIBXL__AO_MAGIC);
2069 assert(!ao->complete);
2070 assert(!ao->nested_root);
2071 assert(!ao->nested_progeny);
2072 ao->complete = 1;
2073 ao->rc = rc;
2074 XEN_LIST_REMOVE(ao, inprogress_entry);
2075 if (ao->outstanding_killed_child)
2076 LOG(DEBUG, "ao %p: .. but waiting for %d fork to exit",
2077 ao, ao->outstanding_killed_child);
2078 libxl__ao_complete_check_progress_reports(egc, ao);
2079 }
2080
ao_work_outstanding(libxl__ao * ao)2081 static bool ao_work_outstanding(libxl__ao *ao)
2082 {
2083 /*
2084 * We don't consider an ao complete if it has any outstanding
2085 * callbacks. These callbacks might be outstanding on other
2086 * threads, queued up in the other threads' egc's. Those threads
2087 * will, after making the callback, take out the lock again,
2088 * decrement progress_reports_outstanding, and call
2089 * libxl__ao_complete_check_progress_reports.
2090 */
2091 return !ao->complete || ao->progress_reports_outstanding
2092 || ao->outstanding_killed_child;
2093 }
2094
libxl__ao_complete_check_progress_reports(libxl__egc * egc,libxl__ao * ao)2095 void libxl__ao_complete_check_progress_reports(libxl__egc *egc, libxl__ao *ao)
2096 {
2097 EGC_GC;
2098 libxl_ctx *ctx = libxl__gc_owner(&egc->gc);
2099 assert(ao->progress_reports_outstanding >= 0);
2100
2101 if (ao_work_outstanding(ao))
2102 return;
2103
2104 if (ao->poller) {
2105 assert(ao->in_initiator);
2106 if (!ao->constructing)
2107 /* don't bother with this if we're not in the event loop */
2108 libxl__poller_wakeup(gc, ao->poller);
2109 } else if (ao->how.callback) {
2110 LOG(DEBUG, "ao %p: complete for callback", ao);
2111 XEN_TAILQ_INSERT_TAIL(&egc->aos_for_callback, ao, entry_for_callback);
2112 } else {
2113 libxl_event *ev;
2114 ev = NEW_EVENT(egc, OPERATION_COMPLETE, ao->domid, ao->how.u.for_event);
2115 if (ev) {
2116 ev->u.operation_complete.rc = ao->rc;
2117 libxl__event_occurred(egc, ev);
2118 }
2119 ao->notified = 1;
2120 }
2121
2122 ao__check_destroy(ctx, ao);
2123 }
2124
libxl__ao_create(libxl_ctx * ctx,uint32_t domid,const libxl_asyncop_how * how,const char * file,int line,const char * func)2125 libxl__ao *libxl__ao_create(libxl_ctx *ctx, uint32_t domid,
2126 const libxl_asyncop_how *how,
2127 const char *file, int line, const char *func)
2128 {
2129 libxl__ao *ao;
2130
2131 ao = calloc(1, sizeof(*ao));
2132 if (!ao) goto out;
2133
2134 ao->magic = LIBXL__AO_MAGIC;
2135 ao->constructing = 1;
2136 ao->in_initiator = 1;
2137 ao__manip_enter(ao);
2138 ao->poller = 0;
2139 ao->domid = domid;
2140 LIBXL_INIT_GC(ao->gc, ctx);
2141
2142 if (how) {
2143 ao->how = *how;
2144 } else {
2145 ao->poller = libxl__poller_get(&ao->gc);
2146 if (!ao->poller) goto out;
2147 }
2148 libxl__log(ctx,XTL_DEBUG,-1,file,line,func,domid,
2149 "ao %p: create: how=%p callback=%p poller=%p",
2150 ao, how, ao->how.callback, ao->poller);
2151
2152 XEN_LIST_INSERT_HEAD(&ctx->aos_inprogress, ao, inprogress_entry);
2153
2154 return ao;
2155
2156 out:
2157 if (ao) libxl__ao__destroy(ctx, ao);
2158 return NULL;
2159 }
2160
2161
libxl__ao_inprogress(libxl__ao * ao,const char * file,int line,const char * func)2162 int libxl__ao_inprogress(libxl__ao *ao,
2163 const char *file, int line, const char *func)
2164 {
2165 AO_GC;
2166 int rc;
2167 uint32_t domid = ao->domid;
2168
2169 assert(ao->magic == LIBXL__AO_MAGIC);
2170 assert(ao->constructing);
2171 assert(ao->in_initiator);
2172 ao->constructing = 0;
2173
2174 if (ao->nested_root)
2175 domid = ao->nested_root->domid;
2176
2177 libxl__log(CTX,XTL_DEBUG,-1,file,line,func,domid,
2178 "ao %p: inprogress: poller=%p, flags=%s%s%s%s",
2179 ao, ao->poller,
2180 ao->constructing ? "o" : "",
2181 ao->in_initiator ? "i" : "",
2182 ao->complete ? "c" : "",
2183 ao->notified ? "n" : "");
2184
2185 if (ao->poller) {
2186 /* Caller wants it done synchronously. */
2187 /* We use a fresh gc, so that we can free things
2188 * each time round the loop. */
2189 libxl__egc egc;
2190 LIBXL_INIT_EGC(egc,CTX);
2191
2192 for (;;) {
2193 assert(ao->magic == LIBXL__AO_MAGIC);
2194
2195 if (!ao_work_outstanding(ao)) {
2196 rc = ao->rc;
2197 ao->notified = 1;
2198 break;
2199 }
2200
2201 DBG("ao %p: not ready, waiting",ao);
2202
2203 rc = eventloop_iteration(&egc,ao->poller);
2204 if (rc) {
2205 /* Oh dear, this is quite unfortunate. */
2206 LOG(ERROR,
2207 "Error waiting for"" event during long-running operation (rc=%d)",
2208 rc);
2209 sleep(1);
2210 /* It's either this or return ERROR_I_DONT_KNOW_WHETHER
2211 * _THE_THING_YOU_ASKED_FOR_WILL_BE_DONE_LATER_WHEN
2212 * _YOU_DIDNT_EXPECT_IT, since we don't have a
2213 * synchronous cancellation ability. */
2214 }
2215
2216 /* The call to egc..1_baton is below, only if we are leaving. */
2217 CTX_UNLOCK;
2218 libxl__egc_cleanup_2_ul_cb_gc(&egc);
2219 CTX_LOCK;
2220 }
2221
2222 /* Dispose of this early so libxl__egc_ao_cleanup_1_baton
2223 * doesn't mistake us for a baton-holder. No-one much is
2224 * going to look at this ao now so setting this to 0 is fine.
2225 * We can't call _baton below _leave because _leave destroys
2226 * our gc, which _baton needs. */
2227 libxl__poller_put(CTX, ao->poller);
2228 ao->poller = 0;
2229 } else {
2230 rc = 0;
2231 }
2232
2233 libxl__egc_ao_cleanup_1_baton(gc);
2234 ao->in_initiator = 0;
2235 ao__manip_leave(CTX, ao);
2236
2237 return rc;
2238 }
2239
2240
2241 /* abort requests */
2242
ao__abort(libxl_ctx * ctx,libxl__ao * parent)2243 static int ao__abort(libxl_ctx *ctx, libxl__ao *parent)
2244 /* Temporarily unlocks ctx, which must be locked exactly once on entry. */
2245 {
2246 libxl__egc egc;
2247 LIBXL_INIT_EGC(egc,ctx);
2248
2249 int rc;
2250 ao__manip_enter(parent);
2251
2252 if (parent->aborting) {
2253 rc = ERROR_ABORTED;
2254 goto out;
2255 }
2256
2257 parent->aborting = 1;
2258
2259 if (XEN_LIST_EMPTY(&parent->abortables)) {
2260 LIBXL__LOG(ctx, LIBXL__LOG_DEBUG,
2261 "ao %p: abort requested and noted, but no-one interested",
2262 parent);
2263 rc = 0;
2264 goto out;
2265 }
2266
2267 /* We keep calling abort hooks until there are none left */
2268 while (!XEN_LIST_EMPTY(&parent->abortables)) {
2269 assert(!parent->complete);
2270
2271 libxl__ao_abortable *abrt = XEN_LIST_FIRST(&parent->abortables);
2272 assert(parent == ao_nested_root(abrt->ao));
2273
2274 XEN_LIST_REMOVE(abrt, entry);
2275 abrt->registered = 0;
2276
2277 LIBXL__LOG(ctx, LIBXL__LOG_DEBUG,
2278 "ao %p: abrt=%p: aborting", parent, abrt->ao);
2279 abrt->callback(&egc, abrt, ERROR_ABORTED);
2280
2281 /* The call to egc..1_baton is in the out block below. */
2282 libxl__ctx_unlock(ctx);
2283 libxl__egc_cleanup_2_ul_cb_gc(&egc);
2284 libxl__ctx_lock(ctx);
2285 }
2286
2287 rc = 0;
2288
2289 out:
2290 libxl__egc_ao_cleanup_1_baton(&egc.gc);
2291 ao__manip_leave(ctx, parent);
2292 /* The call to egc..2_ul_cb_gc is above. This is sufficient
2293 * because only code inside the loop adds anything to the egc, and
2294 * we ensures that the egc is clean when we leave the loop. */
2295 return rc;
2296 }
2297
libxl_ao_abort(libxl_ctx * ctx,const libxl_asyncop_how * how)2298 int libxl_ao_abort(libxl_ctx *ctx, const libxl_asyncop_how *how)
2299 {
2300 libxl__ao *search;
2301 libxl__ctx_lock(ctx);
2302 int rc;
2303
2304 XEN_LIST_FOREACH(search, &ctx->aos_inprogress, inprogress_entry) {
2305 if (how) {
2306 /* looking for ao to be reported by callback or event */
2307 if (search->poller)
2308 /* sync */
2309 continue;
2310 if (how->callback != search->how.callback)
2311 continue;
2312 if (how->callback
2313 ? (how->u.for_callback != search->how.u.for_callback)
2314 : (how->u.for_event != search->how.u.for_event))
2315 continue;
2316 } else {
2317 /* looking for synchronous call */
2318 if (!search->poller)
2319 /* async */
2320 continue;
2321 }
2322 goto found;
2323 }
2324 rc = ERROR_NOTFOUND;
2325 goto out;
2326
2327 found:
2328 rc = ao__abort(ctx, search);
2329 out:
2330 libxl__ctx_unlock(ctx);
2331 return rc;
2332 }
2333
libxl__ao_aborting(libxl__ao * ao)2334 int libxl__ao_aborting(libxl__ao *ao)
2335 {
2336 libxl__ao *root = ao_nested_root(ao);
2337 AO_GC;
2338
2339 if (root->aborting) {
2340 DBG("ao=%p: aborting at explicit check (root=%p)", ao, root);
2341 return ERROR_ABORTED;
2342 }
2343
2344 return 0;
2345 }
2346
libxl__ao_abortable_register(libxl__ao_abortable * abrt)2347 int libxl__ao_abortable_register(libxl__ao_abortable *abrt)
2348 {
2349 libxl__ao *ao = abrt->ao;
2350 libxl__ao *root = ao_nested_root(ao);
2351 AO_GC;
2352
2353 if (root->aborting) {
2354 DBG("ao=%p: preemptively aborting ao_abortable registration %p (root=%p)",
2355 ao, abrt, root);
2356 return ERROR_ABORTED;
2357 }
2358
2359 DBG("ao=%p, abrt=%p: registering (root=%p)", ao, abrt, root);
2360 XEN_LIST_INSERT_HEAD(&root->abortables, abrt, entry);
2361 abrt->registered = 1;
2362
2363 return 0;
2364 }
2365
libxl__ao_abortable_deregister(libxl__ao_abortable * abrt)2366 _hidden void libxl__ao_abortable_deregister(libxl__ao_abortable *abrt)
2367 {
2368 if (!abrt->registered)
2369 return;
2370
2371 libxl__ao *ao = abrt->ao;
2372 libxl__ao *root __attribute__((unused)) = ao_nested_root(ao);
2373 AO_GC;
2374
2375 DBG("ao=%p, abrt=%p: deregistering (root=%p)", ao, abrt, root);
2376 XEN_LIST_REMOVE(abrt, entry);
2377 abrt->registered = 0;
2378 }
2379
2380
2381 /* progress reporting */
2382
2383 /* The application indicates a desire to ignore events by passing NULL
2384 * for how. But we want to copy *how. So we have this dummy function
2385 * whose address is stored in callback if the app passed how==NULL. */
dummy_asyncprogress_callback_ignore(libxl_ctx * ctx,libxl_event * ev,void * for_callback)2386 static void dummy_asyncprogress_callback_ignore
2387 (libxl_ctx *ctx, libxl_event *ev, void *for_callback) { }
2388
libxl__ao_progress_gethow(libxl_asyncprogress_how * in_state,const libxl_asyncprogress_how * from_app)2389 void libxl__ao_progress_gethow(libxl_asyncprogress_how *in_state,
2390 const libxl_asyncprogress_how *from_app) {
2391 if (from_app)
2392 *in_state = *from_app;
2393 else
2394 in_state->callback = dummy_asyncprogress_callback_ignore;
2395 }
2396
libxl__ao_progress_report(libxl__egc * egc,libxl__ao * ao,const libxl_asyncprogress_how * how,libxl_event * ev)2397 void libxl__ao_progress_report(libxl__egc *egc, libxl__ao *ao,
2398 const libxl_asyncprogress_how *how, libxl_event *ev)
2399 {
2400 AO_GC;
2401 assert(!ao->nested_root);
2402 if (how->callback == dummy_asyncprogress_callback_ignore) {
2403 LOG(DEBUG,"ao %p: progress report: ignored",ao);
2404 libxl_event_free(CTX,ev);
2405 /* ignore */
2406 } else if (how->callback) {
2407 libxl__aop_occurred *aop = libxl__zalloc(&egc->gc, sizeof(*aop));
2408 ao->progress_reports_outstanding++;
2409 aop->ao = ao;
2410 aop->ev = ev;
2411 aop->how = how;
2412 XEN_TAILQ_INSERT_TAIL(&egc->aops_for_callback, aop, entry);
2413 LOG(DEBUG,"ao %p: progress report: callback queued aop=%p",ao,aop);
2414 } else {
2415 LOG(DEBUG,"ao %p: progress report: event queued ev=%p type=%s",
2416 ao, ev, libxl_event_type_to_string(ev->type));
2417 libxl__event_occurred(egc, ev);
2418 }
2419 }
2420
2421
2422 /* nested ao */
2423
ao_nested_root(libxl__ao * ao)2424 static libxl__ao *ao_nested_root(libxl__ao *ao) {
2425 libxl__ao *root = ao->nested_root ? : ao;
2426 assert(!root->nested_root);
2427 return root;
2428 }
2429
libxl__nested_ao_create(libxl__ao * parent)2430 _hidden libxl__ao *libxl__nested_ao_create(libxl__ao *parent)
2431 {
2432 libxl__ao *child = NULL, *root;
2433 libxl_ctx *ctx = libxl__gc_owner(&parent->gc);
2434
2435 assert(parent->magic == LIBXL__AO_MAGIC);
2436 root = ao_nested_root(parent);
2437
2438 child = libxl__zalloc(&ctx->nogc_gc, sizeof(*child));
2439 child->magic = LIBXL__AO_MAGIC;
2440 child->nested_root = root;
2441 assert(root->nested_progeny < INT_MAX);
2442 root->nested_progeny++;
2443 LIBXL_INIT_GC(child->gc, ctx);
2444 libxl__gc *gc = &child->gc;
2445
2446 LOG(DEBUG,"ao %p: nested ao, parent %p", child, parent);
2447 return child;
2448 }
2449
libxl__nested_ao_free(libxl__ao * child)2450 _hidden void libxl__nested_ao_free(libxl__ao *child)
2451 {
2452 assert(child->magic == LIBXL__AO_MAGIC);
2453 libxl__ao *root = child->nested_root;
2454 assert(root);
2455 assert(root->nested_progeny > 0);
2456 root->nested_progeny--;
2457 libxl_ctx *ctx = libxl__gc_owner(&child->gc);
2458 libxl__ao__destroy(ctx, child);
2459 }
2460
2461
2462 /*
2463 * Local variables:
2464 * mode: C
2465 * c-basic-offset: 4
2466 * indent-tabs-mode: nil
2467 * End:
2468 */
2469