aboutsummaryrefslogtreecommitdiffstats
path: root/src/evmgr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/evmgr.c')
-rw-r--r--src/evmgr.c202
1 files changed, 161 insertions, 41 deletions
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