X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fevmgr.c;h=d26502df488e8c19a7360df6fb08fea1c4bf744b;hb=ba693048ce1a2b629bfed11fceacabe7edc18a78;hp=2dc35e4280aec940445a7edce556d97dd5082dac;hpb=8538d642f01c8ee185cb356eba2c2f19cf4cea58;p=src%2Fapp-framework-binder.git diff --git a/src/evmgr.c b/src/evmgr.c index 2dc35e42..d26502df 100644 --- a/src/evmgr.c +++ b/src/evmgr.c @@ -33,20 +33,92 @@ #include "evmgr.h" #include "verbose.h" + +#if WITH_SYSTEMD #include "systemd.h" +#else +#include "fdev-epoll.h" +#include "fdev.h" +#endif /** Description of handled event loops */ struct evmgr { - unsigned state; /**< encoded state */ int efd; /**< event notification */ + unsigned state; /**< encoded state */ void *holder; /**< holder of the evmgr */ +#if WITH_SYSTEMD struct sd_event *sdev; /**< the systemd event loop */ +#endif +#if WITH_FDEV_EPOLL + struct fdev_epoll *fdev_epoll; + struct fdev *fdev; +#endif }; #define EVLOOP_STATE_WAIT 1U #define EVLOOP_STATE_RUN 2U + +/** + * Internal callback for evmgr management. + * The effect of this function is hidden: it exits + * the waiting poll if any. + */ +static void evmgr_on_efd_event(struct evmgr *evmgr) +{ + uint64_t x; + read(evmgr->efd, &x, sizeof x); +} + +/** + * wakeup the event loop if needed by sending + * an event. + */ +void evmgr_wakeup(struct evmgr *evmgr) +{ + uint64_t x; + + if (evmgr->state & EVLOOP_STATE_WAIT) { + x = 1; + write(evmgr->efd, &x, sizeof x); + } +} + +/** + */ +void *evmgr_holder(struct evmgr *evmgr) +{ + return evmgr->holder; +} + +/** + */ +int evmgr_release_if(struct evmgr *evmgr, void *holder) +{ + if (evmgr->holder != holder) + return 0; + evmgr->holder = 0; + return 1; +} + +/** + */ +int evmgr_try_hold(struct evmgr *evmgr, void *holder) +{ + if (!evmgr->holder) + evmgr->holder = holder; + return evmgr->holder == holder; +} + +/******************************************************************************/ +/******************************************************************************/ +/****** SYSTEM D ******/ +/******************************************************************************/ +/******************************************************************************/ + +#if WITH_SYSTEMD + /** * Run the event loop is set. */ @@ -98,59 +170,101 @@ int evmgr_can_run(struct evmgr *evmgr) /** * Internal callback for evmgr management. * The effect of this function is hidden: it exits - * the waiting poll if any. + * the waiting poll if any. Then it wakes up a thread + * awaiting the evmgr using signal. */ -static void evmgr_on_efd_event(struct evmgr *evmgr) +static int on_evmgr_efd(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - uint64_t x; - read(evmgr->efd, &x, sizeof x); + struct evmgr *evmgr = userdata; + evmgr_on_efd_event(evmgr); + return 1; } /** - * wakeup the event loop if needed by sending - * an event. + * Gets a sd_event item for the current thread. + * @return a sd_event or NULL in case of error */ -void evmgr_wakeup(struct evmgr *evmgr) +int evmgr_create(struct evmgr **result) { - uint64_t x; + int rc; + struct evmgr *evmgr; - if (evmgr->state & EVLOOP_STATE_WAIT) { - x = 1; - write(evmgr->efd, &x, sizeof x); + /* creates the evmgr on need */ + evmgr = malloc(sizeof *evmgr); + if (!evmgr) { + ERROR("out of memory"); + rc = -ENOMEM; + goto error; + } + + /* creates the eventfd for waking up polls */ + evmgr->efd = eventfd(0, EFD_CLOEXEC|EFD_SEMAPHORE); + if (evmgr->efd < 0) { + ERROR("can't make eventfd for events"); + rc = -errno; + goto error1; } + /* create the systemd event loop */ + evmgr->sdev = systemd_get_event_loop(); + if (!evmgr->sdev) { + ERROR("can't make new event loop"); + goto error2; + } + /* put the eventfd in the event loop */ + rc = sd_event_add_io(evmgr->sdev, NULL, evmgr->efd, EPOLLIN, on_evmgr_efd, evmgr); + if (rc < 0) { + ERROR("can't register eventfd"); + goto error2; + } + + /* start the creation */ + evmgr->state = 0; + evmgr->holder = 0; + *result = evmgr; + return 0; + + +error2: + close(evmgr->efd); +error1: + free(evmgr); +error: + *result = 0; + return rc; } +#endif +#if WITH_FDEV_EPOLL + /** + * Run the event loop is set. */ -void *evmgr_holder(struct evmgr *evmgr) +void evmgr_run(struct evmgr *evmgr) { - return evmgr->holder; + int rc; + + evmgr->state = EVLOOP_STATE_WAIT|EVLOOP_STATE_RUN; + rc = fdev_epoll_wait_and_dispatch(evmgr->fdev_epoll, -1); + evmgr->state = 0; } -/** - */ -int evmgr_release_if(struct evmgr *evmgr, void *holder) +void evmgr_job_run(int signum, struct evmgr *evmgr) { - if (evmgr->holder != holder) - return 0; - evmgr->holder = 0; - return 1; + if (signum) + evmgr->state = 0; + else + evmgr_run(evmgr); } -/** - */ -int evmgr_try_hold(struct evmgr *evmgr, void *holder) +int evmgr_can_run(struct evmgr *evmgr) { - if (!evmgr->holder) - evmgr->holder = holder; - return evmgr->holder == holder; + return !evmgr->state; } -/******************************************************************************/ -/******************************************************************************/ -/****** SYSTEM D ******/ -/******************************************************************************/ -/******************************************************************************/ +struct fdev_epoll *evmgr_get_fdev_epoll(struct evmgr *evmgr) +{ + return evmgr->fdev_epoll; +} /** * Internal callback for evmgr management. @@ -158,11 +272,10 @@ int evmgr_try_hold(struct evmgr *evmgr, void *holder) * the waiting poll if any. Then it wakes up a thread * awaiting the evmgr using signal. */ -static int on_evmgr_efd(sd_event_source *s, int fd, uint32_t revents, void *userdata) +static void on_evmgr_efd(void *closure, uint32_t event, struct fdev *fdev) { - struct evmgr *evmgr = userdata; + struct evmgr *evmgr = closure; evmgr_on_efd_event(evmgr); - return 1; } /** @@ -189,19 +302,23 @@ int evmgr_create(struct evmgr **result) rc = -errno; goto error1; } + /* create the systemd event loop */ - evmgr->sdev = systemd_get_event_loop(); - if (!evmgr->sdev) { + evmgr->fdev_epoll = fdev_epoll_create(); + if (!evmgr->fdev_epoll) { ERROR("can't make new event loop"); goto error2; } /* put the eventfd in the event loop */ - rc = sd_event_add_io(evmgr->sdev, NULL, evmgr->efd, EPOLLIN, on_evmgr_efd, evmgr); - if (rc < 0) { - ERROR("can't register eventfd"); - goto error2; + evmgr->fdev = fdev_epoll_add(evmgr->fdev_epoll, evmgr->efd); + if (evmgr->fdev == NULL) { + ERROR("can't add eventfd"); + goto error3; } + fdev_set_callback(evmgr->fdev, on_evmgr_efd, evmgr); + fdev_set_events(evmgr->fdev, EPOLLIN); + /* start the creation */ evmgr->state = 0; evmgr->holder = 0; @@ -209,6 +326,8 @@ int evmgr_create(struct evmgr **result) return 0; +error3: + fdev_epoll_destroy(evmgr->fdev_epoll); error2: close(evmgr->efd); error1: @@ -218,3 +337,4 @@ error: return rc; } +#endif