mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 02:30:03 +01:00
include <poll.h> for struct pollfd include <sys/time.h> for struct timeval Fixes gcc complaints about implicit declaration. Signed-off-by: Christoph Egger <Christoph.Egger@amd.com> Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com> Acked-by: Ian Jackson <ian.jackson@eu.citrix.com> Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
383 lines
16 KiB
C
383 lines
16 KiB
C
/*
|
|
* Copyright (C) 2011 Citrix Ltd.
|
|
* Author Ian Jackson <ian.jackson@eu.citrix.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published
|
|
* by the Free Software Foundation; version 2.1 only. with the special
|
|
* exception on linking described in file LICENSE.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*/
|
|
|
|
#ifndef LIBXL_EVENT_H
|
|
#define LIBXL_EVENT_H
|
|
|
|
#include <libxl.h>
|
|
#include <poll.h>
|
|
#include <sys/time.h>
|
|
|
|
/*======================================================================*/
|
|
|
|
/*
|
|
* Domain event handling - getting Xen events from libxl
|
|
*
|
|
* (Callers inside libxl may not call libxl_event_check or _wait.)
|
|
*/
|
|
|
|
#define LIBXL_EVENTMASK_ALL (~(unsigned long)0)
|
|
|
|
typedef int libxl_event_predicate(const libxl_event*, void *user);
|
|
/* Return value is 0 if the event is unwanted or non-0 if it is.
|
|
* Predicates are not allowed to fail.
|
|
*/
|
|
|
|
int libxl_event_check(libxl_ctx *ctx, libxl_event **event_r,
|
|
uint64_t typemask,
|
|
libxl_event_predicate *predicate, void *predicate_user);
|
|
/* Searches for an event, already-happened, which matches typemask
|
|
* and predicate. predicate==0 matches any event.
|
|
* libxl_event_check returns the event, which must then later be
|
|
* freed by the caller using libxl_event_free.
|
|
*
|
|
* Returns ERROR_NOT_READY if no such event has happened.
|
|
*/
|
|
|
|
int libxl_event_wait(libxl_ctx *ctx, libxl_event **event_r,
|
|
uint64_t typemask,
|
|
libxl_event_predicate *predicate, void *predicate_user);
|
|
/* Like libxl_event_check but blocks if no suitable events are
|
|
* available, until some are. Uses libxl_osevent_beforepoll/
|
|
* _afterpoll so may be inefficient if very many domains are being
|
|
* handled by a single program.
|
|
*/
|
|
|
|
void libxl_event_free(libxl_ctx *ctx, libxl_event *event);
|
|
|
|
|
|
/* Alternatively or additionally, the application may also use this: */
|
|
|
|
typedef struct libxl_event_hooks {
|
|
uint64_t event_occurs_mask;
|
|
void (*event_occurs)(void *user, const libxl_event *event);
|
|
void (*disaster)(void *user, libxl_event_type type,
|
|
const char *msg, int errnoval);
|
|
} libxl_event_hooks;
|
|
|
|
void libxl_event_register_callbacks(libxl_ctx *ctx,
|
|
const libxl_event_hooks *hooks, void *user);
|
|
/*
|
|
* Arranges that libxl will henceforth call event_occurs for any
|
|
* events whose type is set in event_occurs_mask, rather than
|
|
* queueing the event for retrieval by libxl_event_check/wait.
|
|
* Events whose bit is clear in mask are not affected.
|
|
*
|
|
* event becomes owned by the application and must be freed, either
|
|
* by event_occurs or later.
|
|
*
|
|
* event_occurs may be NULL if mask is 0.
|
|
*
|
|
* libxl_event_register_callback also provides a way for libxl to
|
|
* report to the application that there was a problem reporting
|
|
* events; this can occur due to lack of host memory during event
|
|
* handling, or other wholly unrecoverable errors from system calls
|
|
* made by libxl. This will not happen for frivolous reasons - only
|
|
* if the system, or the Xen components of it, are badly broken.
|
|
*
|
|
* msg and errnoval will describe the action that libxl was trying
|
|
* to do, and type specifies the type of libxl events which may be
|
|
* missing. type may be 0 in which case events of all types may be
|
|
* missing.
|
|
*
|
|
* disaster may be NULL. If it is, or if _register_callbacks has
|
|
* not been called, errors of this kind are fatal to the entire
|
|
* application: libxl will print messages to its logs and to stderr
|
|
* and call exit(-1).
|
|
*
|
|
* If disaster returns, it may be the case that some or all future
|
|
* libxl calls will return errors; likewise it may be the case that
|
|
* no more events (of the specified type, if applicable) can be
|
|
* produced. An application which supplies a disaster function
|
|
* should normally react either by exiting, or by (when it has
|
|
* returned to its main event loop) shutting down libxl with
|
|
* libxl_ctx_free and perhaps trying to restart it with
|
|
* libxl_ctx_init.
|
|
*
|
|
* In any case before calling disaster, libxl will have logged a
|
|
* message with level XTL_CRITICAL.
|
|
*
|
|
* Reentrancy: it IS permitted to call libxl from within
|
|
* event_occurs. It is NOT permitted to call libxl from within
|
|
* disaster. The event_occurs and disaster callbacks may occur on
|
|
* any thread in which the application calls libxl.
|
|
*
|
|
* libxl_event_register_callbacks may be called as many times, with
|
|
* different parameters, as the application likes; the most recent
|
|
* call determines the libxl behaviour. However it is NOT safe to
|
|
* call _register_callbacks concurrently with, or reentrantly from,
|
|
* any other libxl function.
|
|
*
|
|
* Calls to _register_callbacks do not affect events which have
|
|
* already occurred.
|
|
*/
|
|
|
|
|
|
/*
|
|
* Events are only generated if they have been requested.
|
|
* The following functions request the generation of specific events.
|
|
*
|
|
* Each set of functions for controlling event generation has this form:
|
|
*
|
|
* typedef struct libxl__evgen_FOO libxl__evgen_FOO;
|
|
* int libxl_evenable_FOO(libxl_ctx *ctx, FURTHER PARAMETERS,
|
|
* libxl_ev_user user, libxl__evgen_FOO **evgen_out);
|
|
* void libxl_evdisable_FOO(libxl_ctx *ctx, libxl__evgen_FOO *evgen);
|
|
*
|
|
* The evenable function arranges that the events (as described in the
|
|
* doc comment for the individual function) will start to be generated
|
|
* by libxl. On success, *evgen_out is set to a non-null pointer to
|
|
* an opaque struct.
|
|
*
|
|
* The user value is returned in the generated events and may be
|
|
* used by the caller for whatever it likes. The type ev_user is
|
|
* guaranteed to be an unsigned integer type which is at least
|
|
* as big as uint64_t and is also guaranteed to be big enough to
|
|
* contain any intptr_t value.
|
|
*
|
|
* If it becomes desirable to stop generation of the relevant events,
|
|
* or to reclaim the resources in libxl associated with the evgen
|
|
* structure, the same evgen value should be passed to the evdisable
|
|
* function. However, note that events which occurred prior to the
|
|
* evdisable call may still be returned.
|
|
*
|
|
* The caller may enable identical events more than once. If they do
|
|
* so, each actual occurrence will generate several events to be
|
|
* returned by libxl_event_check, with the appropriate user value(s).
|
|
* Aside from this, each occurrence of each event is returned by
|
|
* libxl_event_check exactly once.
|
|
*
|
|
* An evgen is associated with the libxl_ctx used for its creation.
|
|
* After libxl_ctx_free, all corresponding evgen handles become
|
|
* invalid and must no longer be passed to evdisable.
|
|
*
|
|
* Events enabled with evenable prior to a fork and libxl_ctx_postfork
|
|
* are no longer generated after the fork/postfork; however the evgen
|
|
* structures are still valid and must be passed to evdisable if the
|
|
* memory they use should not be leaked.
|
|
*
|
|
* Applications should ensure that they eventually retrieve every
|
|
* event using libxl_event_check or libxl_event_wait, since events
|
|
* which occur but are not retreived by the application will be queued
|
|
* inside libxl indefinitely. libxl_event_check/_wait may be O(n)
|
|
* where n is the number of queued events which do not match the
|
|
* criteria specified in the arguments to check/wait.
|
|
*/
|
|
|
|
typedef struct libxl__evgen_domain_death libxl_evgen_domain_death;
|
|
int libxl_evenable_domain_death(libxl_ctx *ctx, uint32_t domid,
|
|
libxl_ev_user, libxl_evgen_domain_death **evgen_out);
|
|
void libxl_evdisable_domain_death(libxl_ctx *ctx, libxl_evgen_domain_death*);
|
|
/* Arranges for the generation of DOMAIN_SHUTDOWN and DOMAIN_DESTROY
|
|
* events. A domain which is destroyed before it shuts down
|
|
* may generate only a DESTROY event.
|
|
*/
|
|
|
|
typedef struct libxl__evgen_disk_eject libxl_evgen_disk_eject;
|
|
int libxl_evenable_disk_eject(libxl_ctx *ctx, uint32_t domid, const char *vdev,
|
|
libxl_ev_user, libxl_evgen_disk_eject **evgen_out);
|
|
void libxl_evdisable_disk_eject(libxl_ctx *ctx, libxl_evgen_disk_eject*);
|
|
/* Arranges for the generation of DISK_EJECT events. A copy of the
|
|
* string *vdev will be made for libxl's internal use, and a pointer
|
|
* to this (or some other) copy will be returned as the vdev
|
|
* member of event.u.
|
|
*/
|
|
|
|
|
|
/*======================================================================*/
|
|
|
|
/*
|
|
* OS event handling - passing low-level OS events to libxl
|
|
*
|
|
* Event-driven programs must use these facilities to allow libxl
|
|
* to become aware of readability/writeability of file descriptors
|
|
* and the occurrence of timeouts.
|
|
*
|
|
* There are two approaches available. The first is appropriate for
|
|
* simple programs handling reasonably small numbers of domains:
|
|
*
|
|
* for (;;) {
|
|
* libxl_osevent_beforepoll(...)
|
|
* poll();
|
|
* libxl_osevent_afterpoll(...);
|
|
* for (;;) {
|
|
* r = libxl_event_check(...);
|
|
* if (r==LIBXL_NOT_READY) break;
|
|
* if (r) goto error_out;
|
|
* do something with the event;
|
|
* }
|
|
* }
|
|
*
|
|
* The second approach uses libxl_osevent_register_hooks and is
|
|
* suitable for programs which are already using a callback-based
|
|
* event library.
|
|
*
|
|
* An application may freely mix the two styles of interaction.
|
|
*
|
|
* (Callers inside libxl may not call libxl_osevent_... functions.)
|
|
*/
|
|
|
|
struct pollfd;
|
|
|
|
/* The caller should provide beforepoll with some space for libxl's
|
|
* fds, and tell libxl how much space is available by setting *nfds_io.
|
|
* fds points to the start of this space (and fds may be a pointer into
|
|
* a larger array, for example, if the application has some fds of
|
|
* its own that it is interested in).
|
|
*
|
|
* On return *nfds_io will in any case have been updated by libxl
|
|
* according to how many fds libxl wants to poll on.
|
|
*
|
|
* If the space was sufficient, libxl fills in fds[0..<new
|
|
* *nfds_io>] suitably for poll(2), updates *timeout_upd if needed,
|
|
* and returns ok.
|
|
*
|
|
* If space was insufficient, fds[0..<old *nfds_io>] is undefined on
|
|
* return; *nfds_io on return will be greater than the value on
|
|
* entry; *timeout_upd may or may not have been updated; and
|
|
* libxl_osevent_beforepoll returns ERROR_BUFERFULL. In this case
|
|
* the application needs to make more space (enough space for
|
|
* *nfds_io struct pollfd) and then call beforepoll again, before
|
|
* entering poll(2). Typically this will involve calling realloc.
|
|
*
|
|
* The application may call beforepoll with fds==NULL and
|
|
* *nfds_io==0 in order to find out how much space is needed.
|
|
*
|
|
* *timeout_upd is as for poll(2): it's in milliseconds, and
|
|
* negative values mean no timeout (infinity).
|
|
* libxl_osevent_beforepoll will only reduce the timeout, naturally.
|
|
*/
|
|
int libxl_osevent_beforepoll(libxl_ctx *ctx, int *nfds_io,
|
|
struct pollfd *fds, int *timeout_upd,
|
|
struct timeval now);
|
|
|
|
/* nfds and fds[0..nfds] must be from the most recent call to
|
|
* _beforepoll, as modified by poll. (It is therefore not possible
|
|
* to have multiple threads simultaneously polling using this
|
|
* interface.)
|
|
*
|
|
* This function actually performs all of the IO and other actions,
|
|
* and generates events (libxl_event), which are implied by either
|
|
* (a) the time of day or (b) both (i) the returned information from
|
|
* _beforepoll, and (ii) the results from poll specified in
|
|
* fds[0..nfds-1]. Generated events can then be retrieved by
|
|
* libxl_event_check.
|
|
*/
|
|
void libxl_osevent_afterpoll(libxl_ctx *ctx, int nfds, const struct pollfd *fds,
|
|
struct timeval now);
|
|
|
|
|
|
typedef struct libxl_osevent_hooks {
|
|
int (*fd_register)(void *user, int fd, void **for_app_registration_out,
|
|
short events, void *for_libxl);
|
|
int (*fd_modify)(void *user, int fd, void **for_app_registration_update,
|
|
short events);
|
|
void (*fd_deregister)(void *user, int fd, void *for_app_registration);
|
|
int (*timeout_register)(void *user, void **for_app_registration_out,
|
|
struct timeval abs, void *for_libxl);
|
|
int (*timeout_modify)(void *user, void **for_app_registration_update,
|
|
struct timeval abs);
|
|
void (*timeout_deregister)(void *user, void *for_app_registration);
|
|
} libxl_osevent_hooks;
|
|
|
|
/* The application which calls register_fd_hooks promises to
|
|
* maintain a register of fds and timeouts that libxl is interested
|
|
* in, and make calls into libxl (libxl_osevent_occurred_*)
|
|
* when those fd events and timeouts occur. This is more efficient
|
|
* than _beforepoll/_afterpoll if there are many fds (which can
|
|
* happen if the same libxl application is managing many domains).
|
|
*
|
|
* For an fd event, events is as for poll(). register or modify may
|
|
* be called with events==0, in which case it must still work
|
|
* normally, just not generate any events.
|
|
*
|
|
* For a timeout event, milliseconds is as for poll().
|
|
* Specifically, negative values of milliseconds mean NO TIMEOUT.
|
|
* This is used by libxl to temporarily disable a timeout.
|
|
*
|
|
* If the register or modify hook succeeds it may update
|
|
* *for_app_registration_out/_update and must then return 0.
|
|
* On entry to register, *for_app_registration_out is always NULL.
|
|
*
|
|
* A registration or modification hook may fail, in which case it
|
|
* must leave the registration state of the fd or timeout unchanged.
|
|
* It may then either return ERROR_OSEVENT_REG_FAIL or any positive
|
|
* int. The value returned will be passed up through libxl and
|
|
* eventually returned back to the application. When register
|
|
* fails, any value stored into *for_registration_out is ignored by
|
|
* libxl; when modify fails, any changed value stored into
|
|
* *for_registration_update is honoured by libxl and will be passed
|
|
* to future modify or deregister calls.
|
|
*
|
|
* libxl will only attempt to register one callback for any one fd.
|
|
* libxl will remember the value stored in *for_app_registration_out
|
|
* (or *for_app_registration_update) by a successful call to
|
|
* register (or modify), and pass it to subsequent calls to modify
|
|
* or deregister.
|
|
*
|
|
* register_fd_hooks may be called only once for each libxl_ctx.
|
|
* libxl may make calls to register/modify/deregister from within
|
|
* any libxl function (indeed, it will usually call register from
|
|
* register_event_hooks). Conversely, the application MUST NOT make
|
|
* the event occurrence calls (libxl_osevent_occurred_*) into libxl
|
|
* reentrantly from within libxl (for example, from within the
|
|
* register/modify functions).
|
|
*
|
|
* Lock hierarchy: the register/modify/deregister functions may be
|
|
* called with locks held. These locks (the "libxl internal locks")
|
|
* are inside the libxl_ctx. Therefore, if those register functions
|
|
* acquire any locks of their own ("caller register locks") outside
|
|
* libxl, to avoid deadlock one of the following must hold for each
|
|
* such caller register lock:
|
|
* (a) "acquire libxl internal locks before caller register lock":
|
|
* No libxl function may be called with the caller register
|
|
* lock held.
|
|
* (b) "acquire caller register lock before libxl internal locks":
|
|
* No libxl function may be called _without_ the caller
|
|
* register lock held.
|
|
* Of these we would normally recommend (a).
|
|
*
|
|
* The value *hooks is not copied and must outlast the libxl_ctx.
|
|
*/
|
|
void libxl_osevent_register_hooks(libxl_ctx *ctx,
|
|
const libxl_osevent_hooks *hooks,
|
|
void *user);
|
|
|
|
/* It is NOT legal to call _occurred_ reentrantly within any libxl
|
|
* function. Specifically it is NOT legal to call it from within
|
|
* a register callback. Conversely, libxl MAY call register/deregister
|
|
* from within libxl_event_registered_call_*.
|
|
*/
|
|
|
|
void libxl_osevent_occurred_fd(libxl_ctx *ctx, void *for_libxl,
|
|
int fd, short events, short revents);
|
|
|
|
/* Implicitly, on entry to this function the timeout has been
|
|
* deregistered. If _occurred_timeout is called, libxl will not
|
|
* call timeout_deregister; if it wants to requeue the timeout it
|
|
* will call timeout_register again.
|
|
*/
|
|
void libxl_osevent_occurred_timeout(libxl_ctx *ctx, void *for_libxl);
|
|
|
|
#endif
|
|
|
|
/*
|
|
* Local variables:
|
|
* mode: C
|
|
* c-basic-offset: 4
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*/
|