+ thread_data = (context->thread_datas) ? context->thread_datas [worker_index] : NULL;
+ if (!should_work (context, thread_data))
+ continue;
+ if (context->job_queue.next_slot > 0)
+ return TRUE;
+ if (continue_idle_job (context, thread_data))
+ return TRUE;
+ }
+
+ /* Return if job enqueued on current context. Jobs have priority over idle work */
+ if (pool_contexts [current_context].job_queue.next_slot > 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+/*
+ * Gets the highest priority work. If there is none, it waits
+ * for work_cond. Should always be called with lock held.
+ */
+static void
+get_work (int worker_index, int *work_context, int *do_idle, SgenThreadPoolJob **job)
+{
+ while (!threadpool_shutdown) {
+ int i;
+
+ for (i = 0; i < contexts_num; i++) {
+ SgenThreadPoolContext *context = &pool_contexts [i];
+ void *thread_data;
+
+ if (worker_index >= context->num_threads)
+ continue;
+ thread_data = (context->thread_datas) ? context->thread_datas [worker_index] : NULL;
+
+ if (!should_work (context, thread_data))
+ continue;
+
+ /*
+ * It's important that we check the continue idle flag with the lock held.
+ * Suppose we didn't check with the lock held, and the result is FALSE. The
+ * main thread might then set continue idle and signal us before we can take
+ * the lock, and we'd lose the signal.
+ */
+ *do_idle = continue_idle_job (context, thread_data);
+ *job = get_job_and_set_in_progress (context);
+
+ if (*job || *do_idle) {
+ *work_context = i;
+ return;
+ }