[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 14/15] libxl: New API for providing OS events to libxl
> [...snip already reviewed bits...] > +/* > + * osevent poll > + */ > + > +int libxl_osevent_beforepoll(libxl_ctx *ctx, int *nfds_io, > + struct pollfd *fds, int *timeout_upd, > + struct timeval now) { > + libxl__ev_fd *efd; > + int i; > + > + /* > + * In order to be able to efficiently find the libxl__ev_fd > + * for a struct poll during _afterpoll, we maintain a shadow > + * data structure in CTX->fd_beforepolled: each slot in > + * the fds array corresponds to a slot in fd_beforepolled. > + */ > + > + GC_INIT(ctx); > + CTX_LOCK; > + > + if (*nfds_io) { > + /* > + * As an optimisation, we don't touch fd_beforepolled_used > + * if *nfds_io is zero on entry, since in that case the > + * caller just wanted to know how big an array to give us. > + * > + * If !*nfds_io, the unconditional parts below are guaranteed > + * not to mess with fd_beforepolled... or any in_beforepolled. > + */ > + > + /* Remove all the old references into beforepolled */ > + for (i = 0; i < CTX->fd_beforepolled_used; i++) { > + efd = CTX->fd_beforepolled[i]; > + if (efd) { > + assert(efd->in_beforepolled == i); > + efd->in_beforepolled = -1; > + CTX->fd_beforepolled[i] = NULL; > + } > + } > + CTX->fd_beforepolled_used = 0; > + > + /* make sure our array is as big as *nfds_io */ > + if (CTX->fd_beforepolled_allocd < *nfds_io) { > + assert(*nfds_io < INT_MAX / sizeof(libxl__ev_fd*) / 2); What is the /2 for? > + libxl__ev_fd **newarray = > + realloc(CTX->fd_beforepolled, sizeof(*newarray) * *nfds_io); > + if (!newarray) > + return ERROR_NOMEM; Need to CTX_UNLOCK here. > + CTX->fd_beforepolled = newarray; > + CTX->fd_beforepolled_allocd = *nfds_io; > + } > + } > + > + int used = 0; > + LIBXL_LIST_FOREACH(efd, &CTX->efds, entry) { > + if (used < *nfds_io) { > + fds[used].fd = efd->fd; > + fds[used].events = efd->events; > + fds[used].revents = 0; > + CTX->fd_beforepolled[used] = efd; > + efd->in_beforepolled = used; > + } > + used++; > + } > + int rc = used <= *nfds_io ? 0 : ERROR_BUFFERFULL; > + > + if (*nfds_io) { > + CTX->fd_beforepolled_used = used; > + } > + > + *nfds_io = used; > + > + libxl__ev_time *etime = LIBXL_TAILQ_FIRST(&CTX->etimes); > + if (etime) { > + int our_timeout; > + struct timeval rel; > + static struct timeval zero; > + > + timersub(&etime->abs, &now, &rel); > + > + if (timercmp(&rel, &zero, <)) { > + our_timeout = 0; > + } else if (rel.tv_sec >= 2000000) { > + our_timeout = 2000000000; > + } else { > + our_timeout = rel.tv_sec * 1000 + (rel.tv_usec + 999) / 1000; > + } > + if (*timeout_upd < 0 || our_timeout < *timeout_upd) > + *timeout_upd = our_timeout; > + } > + > + CTX_UNLOCK; > + GC_FREE; > + return rc; > +} > + > +void libxl_osevent_afterpoll(libxl_ctx *ctx, int nfds, const struct pollfd > *fds, > + struct timeval now) { > + int i; > + GC_INIT(ctx); > + CTX_LOCK; > + > + assert(nfds <= CTX->fd_beforepolled_used); > + > + for (i = 0; i < nfds; i++) { > + if (!fds[i].revents) > + continue; > + > + libxl__ev_fd *efd = CTX->fd_beforepolled[i]; > + if (!efd) > + continue; Would this be a bug? If we've set it up for polling how can it be NULL? > + > + assert(efd->in_beforepolled == i); > + assert(fds[i].fd == efd->fd); > + > + int revents = fds[i].revents & efd->events; > + if (!revents) > + continue; > + > + efd->func(gc, efd, efd->fd, efd->events, revents); > + } > + > + for (;;) { > + libxl__ev_time *etime = LIBXL_TAILQ_FIRST(&CTX->etimes); > + if (!etime) > + break; > + > + assert(!etime->infinite); > + > + if (timercmp(&etime->abs, &now, >)) > + break; > + > + time_deregister(gc, etime); > + > + etime->func(gc, etime, &etime->abs); > + } > + > + CTX_UNLOCK; > + GC_FREE; > +} > + > + > +/* > + * osevent hook and callback machinery > + */ > + > +void libxl_osevent_register_hooks(libxl_ctx *ctx, > + const libxl_osevent_hooks *hooks, > + void *user) { > + GC_INIT(ctx); I nearly said, "there's no gc used in this function" but actually it is artfully concealed in CTX_LOCK. I wonder if CTX_LOCK should take the context, e.g. either CTX_LOCK(CTX) or CTX_LOCK(ctx)? Another alternative would be to have CTX_INIT to parallel GC_INIT which creates a local *ctx instead of having CTX. This would also avoid the need to s/CTX/ctx/ if you make an internal function into an external one and vice versa. > + CTX_LOCK; > + ctx->osevent_hooks = hooks; > + ctx->osevent_user = user; > + CTX_UNLOCK; > + GC_FREE; > +} > + > + [...] > diff --git a/tools/libxl/libxl_event.h b/tools/libxl/libxl_event.h > new file mode 100644 > index 0000000..25efbdf > --- /dev/null > +++ b/tools/libxl/libxl_event.h > @@ -0,0 +1,199 @@ [...] > +int libxl_osevent_beforepoll(libxl_ctx *ctx, int *nfds_io, > + struct pollfd *fds, int *timeout_upd, > + struct timeval now); > + /* 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 ERROR_BUFFERFULL [...] > diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h > index d015c7c..88e7dbb 100644 > --- a/tools/libxl/libxl_internal.h > +++ b/tools/libxl/libxl_internal.h [...] > @@ -138,12 +218,12 @@ typedef struct { > > #define PRINTF_ATTRIBUTE(x, y) __attribute__((format(printf, x, y))) > > -typedef struct { > +struct libxl__gc { > /* mini-GC */ > int alloc_maxsize; > void **alloc_ptrs; > libxl_ctx *owner; > -} libxl__gc; > +}; Is this an unrelated change which has snuck in? I'd hack expected an equivalent change to GC_INIT if not. [...] > -- > 1.7.2.5 Phew! _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |