/* Get first job from queue(removes it from queue) * * Notice: Caller MUST hold a mutex */ static struct job* jobqueue_pull(thpool_* thpool_p){ job* job_p; job_p = thpool_p->jobqueue_p->front; switch(thpool_p->jobqueue_p->len){ case 0: /* if no jobs in queue */ break; case 1: /* if one job in queue */ thpool_p->jobqueue_p->front = NULL; thpool_p->jobqueue_p->rear = NULL; thpool_p->jobqueue_p->len = 0; break; default: /* if >1 jobs in queue */ thpool_p->jobqueue_p->front = job_p->prev; thpool_p->jobqueue_p->len--; /* more than one job in queue -> post it */ bsem_post(thpool_p->jobqueue_p->has_jobs); } return job_p; }
/* Get first job from queue(removes it from queue) * * Notice: Caller MUST hold a mutex */ static struct job* jobqueue_pull(thpool_* thpool_p){ job* job_p; job_p = thpool_p->jobqueue_p->front; switch(thpool_p->jobqueue_p->len){ case 0: /* if no jobs in queue */ return NULL; case 1: /* if one job in queue */ thpool_p->jobqueue_p->front = NULL; thpool_p->jobqueue_p->rear = NULL; break; default: /* if >1 jobs in queue */ thpool_p->jobqueue_p->front = job_p->prev; } thpool_p->jobqueue_p->len--; /* Make sure has_jobs has right value */ if (thpool_p->jobqueue_p->len > 0) { bsem_post(thpool_p->jobqueue_p->has_jobs); } return job_p; }
/** * Add (allocated) job to queue */ static void jobqueue_push(JobQueue* queue, Job* newjob) { pthread_mutex_lock(&queue->rwmutex); jobqueue_push_internal(queue, newjob); bsem_post(queue->has_jobs); pthread_mutex_unlock(&queue->rwmutex); }
/* Add (allocated) job to queue * * Notice: Caller MUST hold a mutex */ static void jobqueue_push(thpool_* thpool_p, struct job* newjob){ newjob->prev = NULL; switch(thpool_p->jobqueue_p->len){ case 0: /* if no jobs in queue */ thpool_p->jobqueue_p->front = newjob; thpool_p->jobqueue_p->rear = newjob; break; default: /* if jobs in queue */ thpool_p->jobqueue_p->rear->prev = newjob; thpool_p->jobqueue_p->rear = newjob; } thpool_p->jobqueue_p->len++; bsem_post(thpool_p->jobqueue_p->has_jobs); }
/* Add (allocated) job to queue */ static void jobqueue_push(jobqueue* jobqueue_p, struct job* newjob){ pthread_mutex_lock(&jobqueue_p->rwmutex); newjob->prev = NULL; switch(jobqueue_p->len){ case 0: /* if no jobs in queue */ jobqueue_p->front = newjob; jobqueue_p->rear = newjob; break; default: /* if jobs in queue */ jobqueue_p->rear->prev = newjob; jobqueue_p->rear = newjob; } jobqueue_p->len++; bsem_post(jobqueue_p->has_jobs); pthread_mutex_unlock(&jobqueue_p->rwmutex); }
/** * Get jobs from the queue(removes them from the queue) * * Notice: Caller MUST hold a mutex */ static WorkGroup* jobqueue_pull(ThPool* thpool, int id) { WorkGroup* group; Job* job; float current_time; float duration, duration_next, min_duration, target_duration; struct timespec timeAux; int info; int i; JobQueue* queue = thpool->jobqueue; if (schedule_strategy == SCHED_STATIC && queue->group_front != NULL) { // STATIC group = queue->group_front; queue->group_front = group->prev; group->prev = NULL; } else if (queue->len == 0) { // nothing to do group = NULL; } else if (schedule_strategy == SCHED_DYNAMIC || queue->len == 1 || queue->total_time <= 0) { // SCHED_DYNAMIC group = (WorkGroup*) malloc(sizeof(WorkGroup)); group->prev = NULL; if (cppadcg_pool_verbose) { if (schedule_strategy == SCHED_GUIDED) { if (queue->len == 1) fprintf(stdout, "jobqueue_pull(): Thread %i given a work group with 1 job\n", id); else if (queue->total_time <= 0) fprintf(stdout, "jobqueue_pull(): Thread %i using single-job instead of multi-job (no timing information)\n", id); } else if (schedule_strategy == SCHED_STATIC && queue->len >= 1) { if (queue->total_time >= 0) { // this should not happen but just in case the user messed up fprintf(stderr, "jobqueue_pull(): Thread %i given a work group with 1 job\n", id); } else { fprintf(stdout, "jobqueue_pull(): Thread %i given a work group with 1 job\n", id); } } } jobqueue_extract_single_group(thpool->jobqueue, group); } else { // schedule_strategy == SCHED_GUIDED // SCHED_GUIDED group = (WorkGroup*) malloc(sizeof(WorkGroup)); group->prev = NULL; job = queue->front; if (job->avgElapsed == NULL) { if (cppadcg_pool_verbose) { fprintf(stderr, "jobqueue_pull(): Thread %i using single job instead of multi-job (No timing information for current job)\n", id); } // cannot use this strategy (something went wrong!) jobqueue_extract_single_group(thpool->jobqueue, group); } else { // there are at least 2 jobs in the queue group->size = 1; duration = *job->avgElapsed; duration_next = duration; job = job->prev; target_duration = queue->total_time * cppadcg_pool_guided_maxgroupwork / thpool->num_threads; // always positive current_time = get_monotonic_time(&timeAux, &info); if (queue->highest_expected_return > 0 && info) { min_duration = 0.9f * (queue->highest_expected_return - current_time); if (target_duration < min_duration) { target_duration = min_duration; } } do { if (job->avgElapsed == NULL) { break; } duration_next += *job->avgElapsed; if (duration_next < target_duration) { group->size++; duration = duration_next; } else { break; } job = job->prev; } while (job != queue->front); if (cppadcg_pool_verbose) { fprintf(stdout, "jobqueue_pull(): Thread %i given a work group with %i jobs for %e s (target: %e s)\n", id, group->size, duration, target_duration); } group->jobs = (Job*) malloc(group->size * sizeof(Job)); for (i = 0; i < group->size; ++i) { job = jobqueue_extract_single(thpool->jobqueue); group->jobs[i] = *job; // copy free(job); } duration_next = current_time + duration; // the time when the current work is expected to end if(duration_next > queue->highest_expected_return) queue->highest_expected_return = duration_next; } } /* more than one job in queue -> post it */ if (queue->len > 0 || queue->group_front != NULL) { bsem_post(queue->has_jobs); } return group; }