diff --git a/src/scheduler.c b/src/scheduler.c index e1074a32e9459d0b4c6439055fcc92ac41e6e514..1e35d7f11b96f50e37b5867bf7c8c1a8a382b093 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -111,6 +111,45 @@ void scheduler_addunlock(struct scheduler *s, struct task *ta, atomic_inc(&s->completed_unlock_writes); } +/** + * @brief Create the drift and sort tasks for the hierarchy of cells under + * a sub-cell task. + * + * @param s The #scheduler. + * @param c A #cell. + * @param t The sub-cell #task that will be unlocked by the sort tasks. + */ + +void scheduler_add_subcell_tasks(struct scheduler *s, struct cell *c, + struct task *t) { + /* Recurse? */ + if (c->split) + for (int k = 0; k < 8; k++) + if (c->progeny[k] != NULL) + scheduler_add_subcell_tasks(s, c->progeny[k], t); + + /* Lock the cell before potentially adding tasks. */ + lock_lock(&c->lock); + + /* Add a drift task if not present. */ + if (c->drift == NULL) + c->drift = + scheduler_addtask(s, task_type_drift, task_subtype_none, 0, 0, c, NULL); + + /* Add a sort task if not present. Note that the sort flags will be + populated in cell_activate_subcell_tasks. */ + if (c->sorts == NULL) { + c->sorts = + scheduler_addtask(s, task_type_sort, task_subtype_none, 0, 0, c, NULL); + } + + /* Unlock the cell. */ + lock_unlock_blind(&c->lock); + + /* The provided task should depend on the sort. */ + scheduler_addunlock(s, c->sorts, t); +} + /** * @brief Split a task if too large. * @@ -183,8 +222,8 @@ static void scheduler_splittask(struct task *t, struct scheduler *s) { lock_unlock_blind(&ci->lock); } - /* Depend on local sorts on this cell. */ - if (ci->sorts != NULL) scheduler_addunlock(s, ci->sorts, t); + /* Depend on local sorts on this cell and its sub-cells. */ + scheduler_add_subcell_tasks(s, ci, t); /* Otherwise, make tasks explicitly. */ } else { @@ -262,8 +301,8 @@ static void scheduler_splittask(struct task *t, struct scheduler *s) { t->type = task_type_sub_pair; /* Depend on the sort tasks of both cells. */ - if (ci->sorts != NULL) scheduler_addunlock(s, ci->sorts, t); - if (cj->sorts != NULL) scheduler_addunlock(s, cj->sorts, t); + scheduler_add_subcell_tasks(s, ci, t); + scheduler_add_subcell_tasks(s, cj, t); /* Otherwise, split it. */ } else { @@ -1149,14 +1188,14 @@ void scheduler_start(struct scheduler *s) { ci->ti_end_min); /* Special treatment for sort tasks */ - if (ci->ti_end_min == ti_current && t->skip && + /* if (ci->ti_end_min == ti_current && t->skip && t->type == task_type_sort && t->flags == 0) error( "Task (type='%s/%s') should not have been skipped " "ti_current=%lld " "c->ti_end_min=%lld t->flags=%d", taskID_names[t->type], subtaskID_names[t->subtype], ti_current, - ci->ti_end_min, t->flags); + ci->ti_end_min, t->flags); */ } else { /* pair */