+ * Queues a new asynchronous job represented by 'callback' and 'arg'
+ * for the 'group' and the 'timeout'.
+ * Jobs are queued FIFO and are possibly executed in parallel
+ * concurrently except for job of the same group that are
+ * executed sequentially in FIFO order.
+ * @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'
+ * @param start The start mode for threads
+ * @return 0 in case of success or -1 in case of error
+ */
+static int queue_job_internal(
+ const void *group,
+ int timeout,
+ void (*callback)(int, void*),
+ void *arg,
+ enum start_mode start_mode)
+{
+ struct job *job;
+ int rc, busy;
+
+ /* check availability */
+ if (remaining_job_count <= 0) {
+ ERROR("can't process job with threads: too many jobs");
+ errno = EBUSY;
+ goto error;
+ }
+
+ /* allocates the job */
+ job = job_create(group, timeout, callback, arg);
+ if (!job)
+ goto error;
+
+ /* start a thread if needed */
+ busy = busy_thread_count == started_thread_count;
+ if (start_mode != Start_Lazy
+ && busy
+ && (start_mode == Start_Urgent || remaining_job_count + started_thread_count < allowed_job_count)
+ && started_thread_count < allowed_thread_count) {
+ /* all threads are busy and a new can be started */
+ rc = start_one_thread();
+ if (rc < 0 && started_thread_count == 0) {
+ ERROR("can't start initial thread: %m");
+ goto error2;
+ }
+ busy = 0;
+ }
+
+ /* queues the job */
+ job_add(job);
+
+ /* wakeup an evloop if needed */
+ if (busy)
+ evloop_wakeup();
+
+ pthread_cond_signal(&cond);
+ return 0;
+
+error2:
+ job->next = first_free_job;
+ first_free_job = job;
+error:
+ return -1;
+}
+
+/**
+ * Queues a new asynchronous job represented by 'callback' and 'arg'