+/**
+ * Run a asynchronous job represented by 'callback'
+ * with the 'timeout' but only returns after job completion.
+ * @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.
+ * @return 0 in case of success or -1 in case of error
+ */
+int jobs_invoke0(
+ int timeout,
+ void (*callback)(int signum))
+{
+ return jobs_invoke3(timeout, (job_cb_t)callback, NULL, NULL, NULL);
+}
+
+/**
+ * Run a asynchronous job represented by 'callback' and 'arg1'
+ * with the 'timeout' but only returns after job completion.
+ * @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 arg1 The second argument for 'callback'
+ * @return 0 in case of success or -1 in case of error
+ */
+int jobs_invoke(
+ int timeout,
+ void (*callback)(int, void*),
+ void *arg)
+{
+ return jobs_invoke3(timeout, (job_cb_t)callback, arg, NULL, NULL);
+}
+
+/**
+ * Run a asynchronous job represented by 'callback' and 'arg[12]'
+ * with the 'timeout' but only returns after job completion.
+ * @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 parameters are the parameters 'arg[12]'
+ * given here.
+ * @param arg1 The second argument for 'callback'
+ * @param arg2 The third argument for 'callback'
+ * @return 0 in case of success or -1 in case of error
+ */
+int jobs_invoke2(
+ int timeout,
+ void (*callback)(int, void*, void*),
+ void *arg1,
+ void *arg2)
+{
+ return jobs_invoke3(timeout, (job_cb_t)callback, arg1, arg2, NULL);
+}
+
+/**
+ * Stops the thread pointed by 'arg1'. Used with
+ * invoke familly to return to the caller after completion.
+ * @param signum Unused
+ * @param arg1 The thread to stop
+ * @param arg2 Unused
+ * @param arg3 Unused
+ */
+static void unlock_invoker(int signum, void *arg1, void *arg2, void *arg3)
+{
+ struct thread *t = arg1;
+ pthread_mutex_lock(&mutex);
+ t->stop = 1;
+ if (t->waits)
+ pthread_cond_broadcast(&cond);
+ pthread_mutex_unlock(&mutex);
+}
+
+/**
+ * Run a asynchronous job represented by 'callback' and 'arg[123]'
+ * with the 'timeout' but only returns after job completion.
+ * @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 parameters are the parameters 'arg[123]'
+ * given here.
+ * @param arg1 The second argument for 'callback'
+ * @param arg2 The third argument for 'callback'
+ * @param arg3 The forth argument for 'callback'
+ * @return 0 in case of success or -1 in case of error
+ */
+int jobs_invoke3(
+ int timeout,
+ void (*callback)(int, void*, void *, void*),
+ void *arg1,
+ void *arg2,
+ void *arg3)
+{
+ struct job *job1, *job2;
+ struct thread me;
+
+ pthread_mutex_lock(&mutex);
+
+ /* allocates the job */
+ job1 = job_create(&me, timeout, callback, arg1, arg2, arg3);
+ job2 = job_create(&me, 0, unlock_invoker, &me, NULL, NULL);
+ if (!job1 || !job2) {
+ ERROR("out of memory");
+ errno = ENOMEM;
+ if (job1) {
+ job1->next = free_jobs;
+ free_jobs = job1;
+ }
+ if (job2) {
+ job2->next = free_jobs;
+ free_jobs = job2;
+ }
+ pthread_mutex_unlock(&mutex);
+ return -1;
+ }
+
+ /* queues the job */
+ job_add2(job1, job2);
+
+ /* run until stopped */
+ thread_run(&me);
+ pthread_mutex_unlock(&mutex);
+ return 0;
+}
+
+/**
+ * Initialise the job stuff.
+ * @param allowed_count Maximum count of thread for jobs (can be 0,
+ * see 'jobs_add_me' for merging new threads)
+ * @param start_count Count of thread to start now, must be lower.
+ * @param waiter_count Maximum count of jobs that can be waiting.
+ * @return 0 in case of success or -1 in case of error.
+ */