// The master's scheduler. // It behaves as follows: // First, check conflicts withe previous cmds: // -- If any, look at the pending queue: // -- If FULL, return -1. // -- Else, return 0; // -- If none, call the select_worker() to return the worker id. static int scheduler(uint64_t cmd_id){ if (check_conflict(cmd_id) == 1){ if (master_pending.cnt == PENDING_QUEUE_SIZE) return -2; if (master_pending.tail == NULL){ master_pending.tail = malloc(sizeof(struct pending_task)); master_pending.head = master_pending.tail; master_pending.tail->prev = NULL; master_pending.tail->next = NULL; master_pending.cnt = 1; } else{ master_pending.cnt += 1; master_pending.tail->next = malloc(sizeof(struct pending_task)); master_pending.tail->next->next = NULL; master_pending.tail->next->prev = master_pending.tail; master_pending.tail = master_pending.tail->next; } master_pending.tail->cmd_id = cmd_id; pending_count += 1; return -1; } return select_worker(); }
static int ws_push_task(struct starpu_task *task) { unsigned sched_ctx_id = task->sched_ctx; struct _starpu_work_stealing_data *ws = (struct _starpu_work_stealing_data*)starpu_sched_ctx_get_policy_data(sched_ctx_id); struct _starpu_deque_jobq *deque_queue; struct _starpu_job *j = _starpu_get_job_associated_to_task(task); int workerid = starpu_worker_get_id(); unsigned worker = 0; struct starpu_worker_collection *workers = starpu_sched_ctx_get_worker_collection(sched_ctx_id); struct starpu_sched_ctx_iterator it; workers->init_iterator(workers, &it); /* !! C'est ballot de tout locker! */ while(workers->has_next(workers, &it)) { worker = workers->get_next(workers, &it); starpu_pthread_mutex_t *sched_mutex; starpu_pthread_cond_t *sched_cond; starpu_worker_get_sched_condition(worker, &sched_mutex, &sched_cond); STARPU_PTHREAD_MUTEX_LOCK(sched_mutex); } /* If the current thread is not a worker but * the main thread (-1), we find the better one to * put task on its queue */ if (workerid == -1) workerid = select_worker(sched_ctx_id); deque_queue = ws->queue_array[workerid]; #ifdef HAVE_AYUDAME_H if (AYU_event) { intptr_t id = workerid; AYU_event(AYU_ADDTASKTOQUEUE, j->job_id, &id); } #endif _starpu_job_list_push_back(&deque_queue->jobq, j); deque_queue->njobs++; starpu_push_task_end(task); while(workers->has_next(workers, &it)) { worker = workers->get_next(workers, &it); starpu_pthread_mutex_t *sched_mutex; starpu_pthread_cond_t *sched_cond; starpu_worker_get_sched_condition(worker, &sched_mutex, &sched_cond); #ifndef STARPU_NON_BLOCKING_DRIVERS STARPU_PTHREAD_COND_SIGNAL(sched_cond); #endif STARPU_PTHREAD_MUTEX_UNLOCK(sched_mutex); } return 0; }
// Clear the pending queue. static void clear_pending(void){ if (master_pending.cnt == 0) return; int cnt = 0; struct pending_task *target = master_pending.head; while (target){ int cflag = 0; uint64_t cmd_id = master_pending.head->cmd_id; // If head cmd still cannot issue, just return if (check_issue_conflict(cmd_id)) cflag = 1; if (!cflag){ struct pending_task *cp_ptr = master_pending.head; while (cp_ptr != target){ if (check_cover(cp_ptr->cmd_id, cmd_id)){ cflag = 1; break; } cp_ptr = cp_ptr->next; } } if (cflag){ target = target -> next; continue; } cnt += 1; // Here we issue first so that // the worker would receive all the cmds from the buf. int rc = select_worker(); master_issue(cmd_id, rc); master_pending.cnt -= 1; struct pending_task *back_target = target->next; if (target->prev) target->prev->next = target->next; if (target->next) target->next->prev = target->prev; if (target == master_pending.head) master_pending.head = target->next; if (target == master_pending.tail) master_pending.tail = target->prev; free(target); target = back_target; } }