#define _GNU_SOURCE
#include <stdlib.h>
+#include <stdint.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#define sig_monitor(to,cb,arg) (cb(0,arg))
#endif
+#define EVENT_TIMEOUT_TOP ((uint64_t)-1)
+#define EVENT_TIMEOUT_CHILD ((uint64_t)10000)
+
/** Internal shortcut for callback */
typedef void (*job_cb_t)(int, void*, void *, void*);
{
struct events *next;
struct sd_event *event;
+ uint64_t timeout;
unsigned runs: 1;
};
unsigned waits: 1; /**< is waiting? */
};
+/**
+ * Description of synchonous callback
+ */
+struct sync
+{
+ void (*callback)(int, void*); /**< the synchrnous callback */
+ void *arg; /**< the argument of the callback */
+};
+
/* synchronisation of threads */
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
{
struct events *events = arg;
if (!signum)
- sd_event_run(events->event, (uint64_t) -1);
+ sd_event_run(events->event, events->timeout);
}
/**
struct thread **prv;
struct job *job;
struct events *events;
+ uint64_t evto;
/* initialize description of itself and link it in the list */
me->tid = pthread_self();
me->upper = current;
if (current) {
current->lowered = 1;
+ evto = EVENT_TIMEOUT_CHILD;
} else {
started++;
sig_monitor_init_timeouts();
+ evto = EVENT_TIMEOUT_TOP;
}
me->next = threads;
threads = (struct thread*)me;
if (events) {
/* run the events */
events->runs = 1;
+ events->timeout = evto;
me->events = events;
pthread_mutex_unlock(&mutex);
sig_monitor(0, events_call, events);
* or the signal number that broke the normal flow.
* The remaining parameter is the parameter 'arg1'
* given here.
- * @param arg1 The second argument for 'callback'
+ * @param arg The second argument for 'callback'
* @return 0 in case of success or -1 in case of error
*/
int jobs_queue(
/**
* Enter a synchronisation point: activates the job given by 'callback'
- * @param group the gro
+ * and 'closure' using 'group' and 'timeout' to control sequencing and
+ * execution time.
+ * @param group the group for sequencing jobs
+ * @param timeout the time in seconds allocated to the job
+ * @param callback the callback that will handle the job.
+ * it receives 3 parameters: 'signum' that will be 0
+ * on normal flow or the catched signal number in case
+ * of interrupted flow, the context 'closure' as given and
+ * a 'jobloop' reference that must be used when the job is
+ * terminated to unlock the current execution flow.
+ * @param closure the context completion closure for the callback
+ * @return 0 on success or -1 in case of error
*/
int jobs_enter(
void *group,
int timeout,
void (*callback)(int signum, void *closure, struct jobloop *jobloop),
- void *closure)
+ void *closure
+)
{
struct job *job;
return 0;
}
+/**
+ * Unlocks the execution flow designed by 'jobloop'.
+ * @param jobloop indication of the flow to unlock
+ * @return 0 in case of success of -1 on error
+ */
int jobs_leave(struct jobloop *jobloop)
{
struct thread *t;
- pthread_mutex_lock(&mutex);
+ pthread_mutex_lock(&mutex);
t = threads;
while (t && t != (struct thread*)jobloop)
t = t->next;
return -!t;
}
+/**
+ * Internal helper function for 'jobs_call'.
+ * @see jobs_call, jobs_enter, jobs_leave
+ */
+static void call_cb(int signum, void *closure, struct jobloop *jobloop)
+{
+ struct sync *sync = closure;
+ sync->callback(signum, sync->arg);
+ jobs_leave(jobloop);
+}
+
+/**
+ * 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(
+ void *group,
+ int timeout,
+ void (*callback)(int, void*),
+ void *arg)
+{
+ struct sync sync;
+
+ sync.callback = callback;
+ sync.arg = arg;
+ return jobs_enter(group, timeout, call_cb, &sync);
+}
+
/**
* Gets a sd_event item for the current thread.
* @return a sd_event or NULL in case of error