+ if (t->waits)
+ pthread_cond_broadcast(&cond);
+ }
+ pthread_mutex_unlock(&mutex);
+ return -!t;
+}
+
+/**
+ * Calls synchronously the job represented by 'callback' and 'arg1'
+ * for the 'group' and the 'timeout' and waits for its completion.
+ * @param group The group of the job or NULL when no group.
+ * @param timeout The maximum execution time in seconds of the job
+ * or 0 for unlimited time.
+ * @param callback The function to execute for achieving the job.
+ * Its first parameter is either 0 on normal flow
+ * or the signal number that broke the normal flow.
+ * The remaining parameter is the parameter 'arg1'
+ * given here.
+ * @param arg The second argument for 'callback'
+ * @return 0 in case of success or -1 in case of error
+ */
+int jobs_call(
+ const void *group,
+ int timeout,
+ void (*callback)(int, void*),
+ void *arg)
+{
+ struct sync sync;
+
+ sync.callback = callback;
+ sync.arg = arg;
+
+ return do_sync(group, timeout, call_cb, &sync);
+}
+
+/**
+ * Internal callback for evloop management.
+ * The effect of this function is hidden: it exits
+ * the waiting poll if any. Then it wakes up a thread
+ * awaiting the evloop using signal.
+ */
+static int on_evloop_efd(sd_event_source *s, int fd, uint32_t revents, void *userdata)
+{
+ uint64_t x;
+ struct evloop *evloop = userdata;
+ read(evloop->efd, &x, sizeof x);
+ pthread_cond_signal(&evloop->cond);
+ return 1;
+}
+
+/**
+ * Gets a sd_event item for the current thread.
+ * @return a sd_event or NULL in case of error
+ */
+struct sd_event *jobs_get_sd_event()
+{
+ struct evloop *el;
+ uint64_t x;
+ int rc;
+
+ pthread_mutex_lock(&mutex);
+
+ /* creates the evloop on need */
+ el = &evloop[0];
+ if (!el->sdev) {
+ /* creates the eventfd for waking up polls */
+ el->efd = eventfd(0, EFD_CLOEXEC|EFD_SEMAPHORE);
+ if (el->efd < 0) {
+ ERROR("can't make eventfd for events");
+ goto error1;
+ }
+ /* create the systemd event loop */
+ rc = sd_event_new(&el->sdev);
+ if (rc < 0) {
+ ERROR("can't make new event loop");
+ goto error2;
+ }
+ /* put the eventfd in the event loop */
+ rc = sd_event_add_io(el->sdev, NULL, el->efd, EPOLLIN, on_evloop_efd, el);
+ if (rc < 0) {
+ ERROR("can't register eventfd");
+ sd_event_unref(el->sdev);
+ el->sdev = NULL;
+error2:
+ close(el->efd);
+error1:
+ pthread_mutex_unlock(&mutex);
+ return NULL;
+ }
+ /* terminate creation */
+ el->state = 0;