static int32_t dt_control_run_job(dt_control_t *control) { _dt_job_t *job = dt_control_schedule_job(control); if(!job) return -1; /* change state to running */ dt_pthread_mutex_lock(&job->wait_mutex); if(dt_control_job_get_state(job) == DT_JOB_STATE_QUEUED) { dt_print(DT_DEBUG_CONTROL, "[run_job+] %02d %f ", DT_CTL_WORKER_RESERVED + dt_control_get_threadid(), dt_get_wtime()); dt_control_job_print(job); dt_print(DT_DEBUG_CONTROL, "\n"); dt_control_job_set_state(job, DT_JOB_STATE_RUNNING); /* execute job */ job->result = job->execute(job); dt_control_job_set_state(job, DT_JOB_STATE_FINISHED); dt_print(DT_DEBUG_CONTROL, "[run_job-] %02d %f ", DT_CTL_WORKER_RESERVED + dt_control_get_threadid(), dt_get_wtime()); dt_control_job_print(job); dt_print(DT_DEBUG_CONTROL, "\n"); } /* free job */ dt_pthread_mutex_unlock(&job->wait_mutex); dt_control_job_dispose(job); return 0; }
int32_t dt_control_add_job_res(dt_control_t *control, _dt_job_t *job, int32_t res) { if(((unsigned int)res) >= DT_CTL_WORKER_RESERVED || !job) { dt_control_job_dispose(job); return 1; } // TODO: pthread cancel and restart in tough cases? dt_pthread_mutex_lock(&control->queue_mutex); // if there is a job in the queue we have to discard that first if(control->job_res[res]) { dt_control_job_set_state(control->job_res[res], DT_JOB_STATE_DISCARDED); dt_control_job_dispose(control->job_res[res]); } dt_print(DT_DEBUG_CONTROL, "[add_job_res] %d | ", res); dt_control_job_print(job); dt_print(DT_DEBUG_CONTROL, "\n"); dt_control_job_set_state(job, DT_JOB_STATE_QUEUED); control->job_res[res] = job; control->new_res[res] = 1; dt_pthread_mutex_unlock(&control->queue_mutex); dt_pthread_mutex_lock(&control->cond_mutex); pthread_cond_broadcast(&control->cond); dt_pthread_mutex_unlock(&control->cond_mutex); return 0; }
void dt_control_job_dispose(_dt_job_t *job) { if(!job) return; dt_control_job_set_state(job, DT_JOB_STATE_DISPOSED); dt_pthread_mutex_destroy(&job->state_mutex); dt_pthread_mutex_destroy(&job->wait_mutex); free(job); }
static void dt_control_job_execute(_dt_job_t *job) { dt_print(DT_DEBUG_CONTROL, "[run_job+] %02d %f ", DT_CTL_WORKER_RESERVED + dt_control_get_threadid(), dt_get_wtime()); dt_control_job_print(job); dt_print(DT_DEBUG_CONTROL, "\n"); dt_control_job_set_state(job, DT_JOB_STATE_RUNNING); /* execute job */ job->result = job->execute(job); dt_control_job_set_state(job, DT_JOB_STATE_FINISHED); dt_print(DT_DEBUG_CONTROL, "[run_job-] %02d %f ", DT_CTL_WORKER_RESERVED + dt_control_get_threadid(), dt_get_wtime()); dt_control_job_print(job); dt_print(DT_DEBUG_CONTROL, "\n"); }
void dt_control_job_dispose(_dt_job_t *job) { if(!job) return; if(job->progress) dt_control_progress_destroy(darktable.control, job->progress); job->progress = NULL; dt_control_job_set_state(job, DT_JOB_STATE_DISPOSED); if(job->params_destroy) job->params_destroy(job->params); dt_pthread_mutex_destroy(&job->state_mutex); dt_pthread_mutex_destroy(&job->wait_mutex); free(job); }
static int32_t dt_control_run_job(dt_control_t *control) { _dt_job_t *job = dt_control_schedule_job(control); if(!job) return -1; /* change state to running */ dt_pthread_mutex_lock(&job->wait_mutex); if(dt_control_job_get_state(job) == DT_JOB_STATE_QUEUED) { dt_print(DT_DEBUG_CONTROL, "[run_job+] %02d %f ", DT_CTL_WORKER_RESERVED + dt_control_get_threadid(), dt_get_wtime()); dt_control_job_print(job); dt_print(DT_DEBUG_CONTROL, "\n"); dt_control_job_set_state(job, DT_JOB_STATE_RUNNING); /* execute job */ job->result = job->execute(job); dt_control_job_set_state(job, DT_JOB_STATE_FINISHED); dt_print(DT_DEBUG_CONTROL, "[run_job-] %02d %f ", DT_CTL_WORKER_RESERVED + dt_control_get_threadid(), dt_get_wtime()); dt_control_job_print(job); dt_print(DT_DEBUG_CONTROL, "\n"); } dt_pthread_mutex_unlock(&job->wait_mutex); // remove the job from scheduled job array (for job deduping) dt_pthread_mutex_lock(&control->queue_mutex); control->job[dt_control_get_threadid()] = NULL; if(job->queue == DT_JOB_QUEUE_USER_EXPORT) control->export_scheduled = FALSE; dt_pthread_mutex_unlock(&control->queue_mutex); // and free it dt_control_job_dispose(job); return 0; }
static int32_t dt_control_run_job_res(dt_control_t *control, int32_t res) { if(((unsigned int)res) >= DT_CTL_WORKER_RESERVED) return -1; _dt_job_t *job = NULL; dt_pthread_mutex_lock(&control->queue_mutex); if(control->new_res[res]) { job = control->job_res[res]; control->job_res[res] = NULL; // this job belongs to us now, the queue may not touch it any longer } control->new_res[res] = 0; dt_pthread_mutex_unlock(&control->queue_mutex); if(!job) return -1; /* change state to running */ dt_pthread_mutex_lock(&job->wait_mutex); if(dt_control_job_get_state(job) == DT_JOB_STATE_QUEUED) { dt_print(DT_DEBUG_CONTROL, "[run_job+] %02d %f ", res, dt_get_wtime()); dt_control_job_print(job); dt_print(DT_DEBUG_CONTROL, "\n"); dt_control_job_set_state(job, DT_JOB_STATE_RUNNING); /* execute job */ job->result = job->execute(job); dt_control_job_set_state(job, DT_JOB_STATE_FINISHED); dt_print(DT_DEBUG_CONTROL, "[run_job-] %02d %f ", res, dt_get_wtime()); dt_control_job_print(job); dt_print(DT_DEBUG_CONTROL, "\n"); } dt_pthread_mutex_unlock(&job->wait_mutex); dt_control_job_dispose(job); return 0; }
int dt_control_add_job(dt_control_t *control, dt_job_queue_t queue_id, _dt_job_t *job) { if(((unsigned int)queue_id) >= DT_JOB_QUEUE_MAX || !job) { dt_control_job_dispose(job); return 1; } job->queue = queue_id; dt_pthread_mutex_lock(&control->queue_mutex); GList **queue = &control->queues[queue_id]; size_t length = control->queue_length[queue_id]; dt_print(DT_DEBUG_CONTROL, "[add_job] %ld | ", length); dt_control_job_print(job); dt_print(DT_DEBUG_CONTROL, "\n"); if(queue_id == DT_JOB_QUEUE_SYSTEM_FG) { // this is a stack with limited size and bubble up and all that stuff job->priority = DT_CONTROL_FG_PRIORITY; // if the job is already in the queue -> move it to the top for(GList *iter = *queue; iter; iter = g_list_next(iter)) { _dt_job_t *other_job = (_dt_job_t *)iter->data; if(dt_control_job_equal(job, other_job)) { dt_print(DT_DEBUG_CONTROL, "[add_job] found job already in queue: "); dt_control_job_print(job); dt_print(DT_DEBUG_CONTROL, "\n"); *queue = g_list_delete_link(*queue, iter); length--; dt_control_job_set_state(job, DT_JOB_STATE_DISCARDED); dt_control_job_dispose(job); job = other_job; break; // there can't be any further copy in the list } } // now we can add the new job to the list *queue = g_list_prepend(*queue, job); length++; // and take care of the maximal queue size if(length > DT_CONTROL_MAX_JOBS) { GList *last = g_list_last(*queue); dt_control_job_set_state((_dt_job_t *)last->data, DT_JOB_STATE_DISCARDED); *queue = g_list_delete_link(*queue, last); length--; } control->queue_length[queue_id] = length; } else { // the rest are FIFOs if(queue_id == DT_JOB_QUEUE_USER_BG || queue_id == DT_JOB_QUEUE_SYSTEM_BG) job->priority = 0; else job->priority = DT_CONTROL_FG_PRIORITY; *queue = g_list_append(*queue, job); control->queue_length[queue_id]++; } dt_control_job_set_state(job, DT_JOB_STATE_QUEUED); dt_pthread_mutex_unlock(&control->queue_mutex); // notify workers dt_pthread_mutex_lock(&control->cond_mutex); pthread_cond_broadcast(&control->cond); dt_pthread_mutex_unlock(&control->cond_mutex); return 0; }
void dt_control_job_cancel(_dt_job_t *job) { dt_control_job_set_state(job, DT_JOB_STATE_CANCELLED); }
int dt_control_add_job(dt_control_t *control, dt_job_queue_t queue_id, _dt_job_t *job) { if(((unsigned int)queue_id) >= DT_JOB_QUEUE_MAX || !job) { dt_control_job_dispose(job); return 1; } if(!control->running) { // whatever we are adding here won't be scheduled as the system isn't running. execute it synchronous instead. dt_pthread_mutex_lock(&job->wait_mutex); // is that even needed? dt_control_job_execute(job); dt_pthread_mutex_unlock(&job->wait_mutex); dt_control_job_dispose(job); return 0; } job->queue = queue_id; _dt_job_t *job_for_disposal = NULL; dt_pthread_mutex_lock(&control->queue_mutex); GList **queue = &control->queues[queue_id]; size_t length = control->queue_length[queue_id]; dt_print(DT_DEBUG_CONTROL, "[add_job] %zu | ", length); dt_control_job_print(job); dt_print(DT_DEBUG_CONTROL, "\n"); if(queue_id == DT_JOB_QUEUE_SYSTEM_FG) { // this is a stack with limited size and bubble up and all that stuff job->priority = DT_CONTROL_FG_PRIORITY; // check if we have already scheduled the job for(int k = 0; k < control->num_threads; k++) { _dt_job_t *other_job = (_dt_job_t *)control->job[k]; if(dt_control_job_equal(job, other_job)) { dt_print(DT_DEBUG_CONTROL, "[add_job] found job already in scheduled: "); dt_control_job_print(other_job); dt_print(DT_DEBUG_CONTROL, "\n"); dt_pthread_mutex_unlock(&control->queue_mutex); dt_control_job_set_state(job, DT_JOB_STATE_DISCARDED); dt_control_job_dispose(job); return 0; // there can't be any further copy } } // if the job is already in the queue -> move it to the top for(GList *iter = *queue; iter; iter = g_list_next(iter)) { _dt_job_t *other_job = (_dt_job_t *)iter->data; if(dt_control_job_equal(job, other_job)) { dt_print(DT_DEBUG_CONTROL, "[add_job] found job already in queue: "); dt_control_job_print(other_job); dt_print(DT_DEBUG_CONTROL, "\n"); *queue = g_list_delete_link(*queue, iter); length--; job_for_disposal = job; job = other_job; break; // there can't be any further copy in the list } } // now we can add the new job to the list *queue = g_list_prepend(*queue, job); length++; // and take care of the maximal queue size if(length > DT_CONTROL_MAX_JOBS) { GList *last = g_list_last(*queue); dt_control_job_set_state((_dt_job_t *)last->data, DT_JOB_STATE_DISCARDED); dt_control_job_dispose((_dt_job_t *)last->data); *queue = g_list_delete_link(*queue, last); length--; } control->queue_length[queue_id] = length; } else { // the rest are FIFOs if(queue_id == DT_JOB_QUEUE_USER_BG || queue_id == DT_JOB_QUEUE_USER_EXPORT || queue_id == DT_JOB_QUEUE_SYSTEM_BG) job->priority = 0; else job->priority = DT_CONTROL_FG_PRIORITY; *queue = g_list_append(*queue, job); control->queue_length[queue_id]++; } dt_control_job_set_state(job, DT_JOB_STATE_QUEUED); dt_pthread_mutex_unlock(&control->queue_mutex); // notify workers dt_pthread_mutex_lock(&control->cond_mutex); pthread_cond_broadcast(&control->cond); dt_pthread_mutex_unlock(&control->cond_mutex); // dispose of dropped job, if any dt_control_job_set_state(job_for_disposal, DT_JOB_STATE_DISCARDED); dt_control_job_dispose(job_for_disposal); return 0; }