- return jobs_queue3(group, timeout, (job_cb_t)callback, NULL, NULL, NULL);
+ struct job *job;
+ int rc, busy;
+
+ pthread_mutex_lock(&mutex);
+
+ /* 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();
+
+ /* signal an existing job */
+ pthread_cond_signal(&cond);
+ pthread_mutex_unlock(&mutex);
+ return 0;
+
+error2:
+ job->next = first_free_job;
+ first_free_job = job;
+error:
+ pthread_mutex_unlock(&mutex);
+ return -1;