diff --git a/examples/ExternalPointMass/run.sh b/examples/ExternalPointMass/run.sh index 9f90ca395a5c8cf83e67928b3fdbd4d8529ac254..4ac513f09cb8ac8dcefc256a68478e215b8bc320 100755 --- a/examples/ExternalPointMass/run.sh +++ b/examples/ExternalPointMass/run.sh @@ -7,4 +7,4 @@ then python makeIC.py 10000 fi -../swift -g -t 2 externalPointMass.yml 2>&1 | tee output.log +../swift -g -t 1 externalPointMass.yml 2>&1 | tee output.log diff --git a/src/cell.c b/src/cell.c index 8728f32cb04f2f1de389386b632371a27d523bb9..c694ef9abff1dd183ec135765b3d227f55116ead 100644 --- a/src/cell.c +++ b/src/cell.c @@ -892,3 +892,23 @@ int cell_is_drift_needed(struct cell *c, int ti_current) { /* No neighbouring cell has active particles. Drift not necessary */ return 0; } + +/** + * @brief Set the super-cell pointers for all cells in a hierarchy. + * + * @param c The top-level #cell to play with. + * @param super Pointer to the deepest cell with tasks in this part of the tree. + */ +void cell_set_super(struct cell *c, struct cell *super) { + + /* Are we in a cell with some kind of self/pair task ? */ + if (super == NULL && c->nr_tasks > 0) super = c; + + /* Set the super-cell */ + c->super = super; + + /* Recurse */ + if (c->split) + for (int k = 0; k < 8; k++) + if (c->progeny[k] != NULL) cell_set_super(c->progeny[k], super); +} diff --git a/src/cell.h b/src/cell.h index f87420c86c5765f42fe04e8dee95558edff90cf9..576d2db695720b3aa1b49b89128496a7ca12a6bb 100644 --- a/src/cell.h +++ b/src/cell.h @@ -130,14 +130,9 @@ struct cell { /* Parent cell. */ struct cell *parent; - /* Super cell, i.e. the highest-level supercell that has hydro interactions. - */ + /* Super cell, i.e. the highest-level supercell that has pair/self tasks */ struct cell *super; - /* Super cell, i.e. the highest-level supercell that has gravity interactions. - */ - struct cell *gsuper; - /* The task computing this cell's sorts. */ struct task *sorts; int sortsize; @@ -240,5 +235,6 @@ int cell_are_neighbours(const struct cell *restrict ci, void cell_check_multipole(struct cell *c, void *data); void cell_clean(struct cell *c); int cell_is_drift_needed(struct cell *c, int ti_current); +void cell_set_super(struct cell *c, struct cell *super); #endif /* SWIFT_CELL_H */ diff --git a/src/engine.c b/src/engine.c index 0793305deae05defac654b293c6d5c354bf40c29..caaa54574b4d279361aa8adabdba13dc39a576f0 100644 --- a/src/engine.c +++ b/src/engine.c @@ -111,119 +111,57 @@ void engine_addlink(struct engine *e, struct link **l, struct task *t) { res->next = atomic_swap(l, res); } -/** - * @brief Generate the gravity hierarchical tasks for a hierarchy of cells - - * i.e. all the O(Npart) tasks. - * - * Tasks are only created here. The dependencies will be added later on. - * - * @param e The #engine. - * @param c The #cell. - * @param gsuper The gsuper #cell. - */ -void engine_make_gravity_hierarchical_tasks(struct engine *e, struct cell *c, - struct cell *gsuper) { - - struct scheduler *s = &e->sched; - const int is_with_external_gravity = - (e->policy & engine_policy_external_gravity) == - engine_policy_external_gravity; - const int is_fixdt = (e->policy & engine_policy_fixdt) == engine_policy_fixdt; - - /* Is this the super-cell? */ - if (gsuper == NULL && (c->grav != NULL || (!c->split && c->gcount > 0))) { - - /* This is the super cell, i.e. the first with gravity tasks attached. */ - gsuper = c; - - /* Local tasks only... */ - if (c->nodeID == e->nodeID) { - - /* Add the init task. */ - if (c->init == NULL) - c->init = scheduler_addtask(s, task_type_init, task_subtype_none, 0, 0, - c, NULL, 0); - - /* Add the kick task that matches the policy. */ - if (is_fixdt) { - if (c->kick == NULL) - c->kick = scheduler_addtask(s, task_type_kick_fixdt, - task_subtype_none, 0, 0, c, NULL, 0); - } else { - if (c->kick == NULL) - c->kick = scheduler_addtask(s, task_type_kick, task_subtype_none, 0, - 0, c, NULL, 0); - } - - if (is_with_external_gravity) - c->grav_external = scheduler_addtask( - s, task_type_grav_external, task_subtype_none, 0, 0, c, NULL, 0); - } - } - - /* Set the super-cell. */ - c->gsuper = gsuper; - - /* Recurse. */ - if (c->split) - for (int k = 0; k < 8; k++) - if (c->progeny[k] != NULL) - engine_make_gravity_hierarchical_tasks(e, c->progeny[k], gsuper); -} - /** * @brief Generate the hydro hierarchical tasks for a hierarchy of cells - * i.e. all the O(Npart) tasks. * * Tasks are only created here. The dependencies will be added later on. * + * Note that there is no need to recurse below the super-cell. + * * @param e The #engine. * @param c The #cell. - * @param super The super #cell. */ -void engine_make_hydro_hierarchical_tasks(struct engine *e, struct cell *c, - struct cell *super) { +void engine_make_hierarchical_tasks(struct engine *e, struct cell *c) { struct scheduler *s = &e->sched; - const int is_fixdt = (e->policy & engine_policy_fixdt) == engine_policy_fixdt; - const int is_with_cooling = - (e->policy & engine_policy_cooling) == engine_policy_cooling; - const int is_with_sourceterms = - (e->policy & engine_policy_sourceterms) == engine_policy_sourceterms; + const int is_fixdt = (e->policy & engine_policy_fixdt); + const int is_hydro = (e->policy & engine_policy_hydro); + const int is_with_cooling = (e->policy & engine_policy_cooling); + const int is_with_sourceterms = (e->policy & engine_policy_sourceterms); - /* Is this the super-cell? */ - if (super == NULL && (c->density != NULL || (c->count > 0 && !c->split))) { - - /* This is the super cell, i.e. the first with density tasks attached. */ - super = c; + /* Are we in a super-cell ? */ + if (c->super == c) { /* Local tasks only... */ if (c->nodeID == e->nodeID) { /* Add the init task. */ - if (c->init == NULL) - c->init = scheduler_addtask(s, task_type_init, task_subtype_none, 0, 0, - c, NULL, 0); + c->init = scheduler_addtask(s, task_type_init, task_subtype_none, 0, 0, c, + NULL, 0); /* Add the kick task that matches the policy. */ if (is_fixdt) { - if (c->kick == NULL) - c->kick = scheduler_addtask(s, task_type_kick_fixdt, - task_subtype_none, 0, 0, c, NULL, 0); + c->kick = scheduler_addtask(s, task_type_kick_fixdt, task_subtype_none, + 0, 0, c, NULL, 0); } else { - if (c->kick == NULL) - c->kick = scheduler_addtask(s, task_type_kick, task_subtype_none, 0, - 0, c, NULL, 0); + c->kick = scheduler_addtask(s, task_type_kick, task_subtype_none, 0, 0, + c, NULL, 0); } /* Generate the ghost task. */ - c->ghost = scheduler_addtask(s, task_type_ghost, task_subtype_none, 0, 0, - c, NULL, 0); + if (is_hydro) + c->ghost = scheduler_addtask(s, task_type_ghost, task_subtype_none, 0, + 0, c, NULL, 0); + #ifdef EXTRA_HYDRO_LOOP /* Generate the extra ghost task. */ - c->extra_ghost = scheduler_addtask(s, task_type_extra_ghost, - task_subtype_none, 0, 0, c, NULL, 0); + if (is_hydro) + c->extra_ghost = scheduler_addtask(s, task_type_extra_ghost, + task_subtype_none, 0, 0, c, NULL, 0); #endif + + /* Cooling task */ if (is_with_cooling) c->cooling = scheduler_addtask(s, task_type_cooling, task_subtype_none, 0, 0, c, NULL, 0); @@ -232,16 +170,19 @@ void engine_make_hydro_hierarchical_tasks(struct engine *e, struct cell *c, c->sourceterms = scheduler_addtask(s, task_type_sourceterms, task_subtype_none, 0, 0, c, NULL, 0); } - } - /* Set the super-cell. */ - c->super = super; + } else { /* We are above the super-cell so need to go deeper */ - /* Recurse. */ - if (c->split) - for (int k = 0; k < 8; k++) - if (c->progeny[k] != NULL) - engine_make_hydro_hierarchical_tasks(e, c->progeny[k], super); +#ifdef SWIFT_DEBUG_CHECKS + if (c->super != NULL) error("Incorrectly set super pointer"); +#endif + + /* Recurse. */ + if (c->split) + for (int k = 0; k < 8; k++) + if (c->progeny[k] != NULL) + engine_make_hierarchical_tasks(e, c->progeny[k]); + } } /** @@ -1289,6 +1230,30 @@ void engine_make_gravity_tasks(struct engine *e) { } } +void engine_make_external_gravity_tasks(struct engine *e) { + + struct space *s = e->s; + struct scheduler *sched = &e->sched; + const int nodeID = e->nodeID; + struct cell *cells = s->cells_top; + const int nr_cells = s->nr_cells; + + for (int cid = 0; cid < nr_cells; ++cid) { + + struct cell *ci = &cells[cid]; + + /* Skip cells without gravity particles */ + if (ci->gcount == 0) continue; + + /* Is that neighbour local ? */ + if (ci->nodeID != nodeID) continue; + + /* If the cells is local build a self-interaction */ + scheduler_addtask(sched, task_type_self, task_subtype_external_grav, 0, 0, + ci, NULL, 0); + } +} + /** * @brief Constructs the top-level pair tasks for the first hydro loop over * neighbours @@ -1434,11 +1399,27 @@ static inline void engine_make_gravity_dependencies(struct scheduler *sched, struct cell *c) { /* init --> gravity --> kick */ - scheduler_addunlock(sched, c->gsuper->init, gravity); - scheduler_addunlock(sched, gravity, c->gsuper->kick); + scheduler_addunlock(sched, c->super->init, gravity); + scheduler_addunlock(sched, gravity, c->super->kick); /* grav_up --> gravity ( --> kick) */ - scheduler_addunlock(sched, c->gsuper->grav_up, gravity); + scheduler_addunlock(sched, c->super->grav_up, gravity); +} + +/** + * @brief Creates the dependency network for the external gravity tasks of a + * given cell. + * + * @param sched The #scheduler. + * @param gravity The gravity task to link. + * @param c The cell. + */ +static inline void engine_make_external_gravity_dependencies( + struct scheduler *sched, struct task *gravity, struct cell *c) { + + /* init --> external gravity --> kick */ + scheduler_addunlock(sched, c->super->init, gravity); + scheduler_addunlock(sched, gravity, c->super->kick); } /** @@ -1480,19 +1461,27 @@ void engine_link_gravity_tasks(struct engine *e) { /* Gather the multipoles --> mm interaction --> kick */ scheduler_addunlock(sched, gather, t); - scheduler_addunlock(sched, t, t->ci->gsuper->kick); + scheduler_addunlock(sched, t, t->ci->super->kick); /* init --> mm interaction */ - scheduler_addunlock(sched, t->ci->gsuper->init, t); + scheduler_addunlock(sched, t->ci->super->init, t); } - /* Self-interaction? */ + /* Self-interaction for self-gravity? */ if (t->type == task_type_self && t->subtype == task_subtype_grav) { engine_make_gravity_dependencies(sched, t, t->ci); } + /* Self-interaction for external gravity ? */ + else if (t->type == task_type_self && + t->subtype == task_subtype_external_grav) { + + engine_make_external_gravity_dependencies(sched, t, t->ci); + + } + /* Otherwise, pair interaction? */ else if (t->type == task_type_pair && t->subtype == task_subtype_grav) { @@ -1501,7 +1490,7 @@ void engine_link_gravity_tasks(struct engine *e) { engine_make_gravity_dependencies(sched, t, t->ci); } - if (t->cj->nodeID == nodeID && t->ci->gsuper != t->cj->gsuper) { + if (t->cj->nodeID == nodeID && t->ci->super != t->cj->super) { engine_make_gravity_dependencies(sched, t, t->cj); } @@ -1516,6 +1505,15 @@ void engine_link_gravity_tasks(struct engine *e) { } } + /* Sub-self-interaction for external gravity ? */ + else if (t->type == task_type_sub_self && + t->subtype == task_subtype_external_grav) { + + if (t->ci->nodeID == nodeID) { + engine_make_external_gravity_dependencies(sched, t, t->ci); + } + } + /* Otherwise, sub-pair interaction? */ else if (t->type == task_type_sub_pair && t->subtype == task_subtype_grav) { @@ -1523,7 +1521,7 @@ void engine_link_gravity_tasks(struct engine *e) { engine_make_gravity_dependencies(sched, t, t->ci); } - if (t->cj->nodeID == nodeID && t->ci->gsuper != t->cj->gsuper) { + if (t->cj->nodeID == nodeID && t->ci->super != t->cj->super) { engine_make_gravity_dependencies(sched, t, t->cj); } @@ -1790,12 +1788,6 @@ void engine_make_extra_hydroloop_tasks(struct engine *e) { } #endif } - - /* External gravity tasks should depend on init and unlock the kick */ - else if (t->type == task_type_grav_external) { - scheduler_addunlock(sched, t->ci->init, t); - scheduler_addunlock(sched, t, t->ci->kick); - } /* Cooling tasks should depend on kick and unlock sourceterms */ else if (t->type == task_type_cooling) { scheduler_addunlock(sched, t->ci->kick, t); @@ -1871,6 +1863,13 @@ void engine_maketasks(struct engine *e) { /* Add the gravity mm tasks. */ if (e->policy & engine_policy_self_gravity) engine_make_gravity_tasks(e); + /* Add the external gravity tasks. */ + if (e->policy & engine_policy_external_gravity) + engine_make_external_gravity_tasks(e); + + if (e->sched.nr_tasks == 0 && (s->nr_gparts > 0 || s->nr_parts > 0)) + error("We have particles but no hydro or gravity tasks were created."); + /* Split the tasks. */ scheduler_splittasks(sched); @@ -1894,25 +1893,24 @@ void engine_maketasks(struct engine *e) { /* Count the number of tasks associated with each cell and store the density tasks in each cell, and make each sort depend on the sorts of its progeny. */ - if (e->policy & engine_policy_hydro) engine_count_and_link_tasks(e); + engine_count_and_link_tasks(e); - /* Append hierarchical tasks to each cells */ - if (e->policy & engine_policy_hydro) - for (int k = 0; k < nr_cells; k++) - engine_make_hydro_hierarchical_tasks(e, &cells[k], NULL); + /* Now that the self/pair tasks are at the right level, set the super + * pointers. */ + for (int k = 0; k < nr_cells; k++) cell_set_super(&cells[k], NULL); - if ((e->policy & engine_policy_self_gravity) || - (e->policy & engine_policy_external_gravity)) - for (int k = 0; k < nr_cells; k++) - engine_make_gravity_hierarchical_tasks(e, &cells[k], NULL); + /* Append hierarchical tasks to each cells */ + for (int k = 0; k < nr_cells; k++) + engine_make_hierarchical_tasks(e, &cells[k]); /* Run through the tasks and make force tasks for each density task. Each force task depends on the cell ghosts and unlocks the kick task of its super-cell. */ if (e->policy & engine_policy_hydro) engine_make_extra_hydroloop_tasks(e); - /* Add the dependencies for the self-gravity stuff */ - if (e->policy & engine_policy_self_gravity) engine_link_gravity_tasks(e); + /* Add the dependencies for the gravity stuff */ + if (e->policy & (engine_policy_self_gravity | engine_policy_external_gravity)) + engine_link_gravity_tasks(e); #ifdef WITH_MPI @@ -2654,7 +2652,10 @@ void engine_init_particles(struct engine *e, int flag_entropy_ICs) { /* Add the tasks corresponding to external gravity to the masks */ if (e->policy & engine_policy_external_gravity) { - mask |= 1 << task_type_grav_external; + mask |= 1 << task_type_self; + mask |= 1 << task_type_sub_self; + + submask |= 1 << task_subtype_external_grav; } /* Add MPI tasks if need be */ @@ -2823,7 +2824,11 @@ void engine_step(struct engine *e) { /* Add the tasks corresponding to external gravity to the masks */ if (e->policy & engine_policy_external_gravity) { - mask |= 1 << task_type_grav_external; + + mask |= 1 << task_type_self; + mask |= 1 << task_type_sub_self; + + submask |= 1 << task_subtype_external_grav; } /* Add the tasks corresponding to cooling to the masks */ diff --git a/src/runner.c b/src/runner.c index e036030c772847a5c0a0ecb81b6aea0b01258d75..06cef10cde74f034dd9b15fe7ef124f267341a25 100644 --- a/src/runner.c +++ b/src/runner.c @@ -184,12 +184,12 @@ void runner_do_grav_external(struct runner *r, struct cell *c, int timer) { for (int i = 0; i < gcount; i++) { /* Get a direct pointer on the part. */ - struct gpart *restrict g = &gparts[i]; + struct gpart *restrict gp = &gparts[i]; /* Is this part within the time step? */ - if (g->ti_end <= ti_current) { + if (gp->ti_end <= ti_current) { - external_gravity_acceleration(time, potential, constants, g); + external_gravity_acceleration(time, potential, constants, gp); } } @@ -1280,9 +1280,12 @@ void *runner_main(void *data) { runner_doself2_force(r, ci); else if (t->subtype == task_subtype_grav) runner_doself_grav(r, ci, 1); + else if (t->subtype == task_subtype_external_grav) + runner_do_grav_external(r, ci, 1); else error("Unknown task subtype."); break; + case task_type_pair: if (t->subtype == task_subtype_density) runner_dopair1_density(r, ci, cj); @@ -1297,9 +1300,7 @@ void *runner_main(void *data) { else error("Unknown task subtype."); break; - case task_type_sort: - runner_do_sort(r, ci, t->flags, 1); - break; + case task_type_sub_self: if (t->subtype == task_subtype_density) runner_dosub_self1_density(r, ci, 1); @@ -1311,9 +1312,12 @@ void *runner_main(void *data) { runner_dosub_self2_force(r, ci, 1); else if (t->subtype == task_subtype_grav) runner_dosub_grav(r, ci, cj, 1); + else if (t->subtype == task_subtype_external_grav) + runner_do_grav_external(r, ci, 1); else error("Unknown task subtype."); break; + case task_type_sub_pair: if (t->subtype == task_subtype_density) runner_dosub_pair1_density(r, ci, cj, t->flags, 1); @@ -1328,6 +1332,10 @@ void *runner_main(void *data) { else error("Unknown task subtype."); break; + + case task_type_sort: + runner_do_sort(r, ci, t->flags, 1); + break; case task_type_init: runner_do_init(r, ci, 1); break; @@ -1371,9 +1379,6 @@ void *runner_main(void *data) { case task_type_grav_fft: runner_do_grav_fft(r); break; - case task_type_grav_external: - runner_do_grav_external(r, t->ci, 1); - break; case task_type_cooling: runner_do_cooling(r, t->ci, 1); break; diff --git a/src/scheduler.c b/src/scheduler.c index f98f8824c00186956e8abe5e5c2aa3aae73abf4e..76e0ecb41b9068e471caa75db95d572265bdcb22 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -1110,20 +1110,10 @@ void scheduler_enqueue(struct scheduler *s, struct task *t) { break; case task_type_pair: case task_type_sub_pair: - if (t->subtype == task_subtype_grav) { - - qid = t->ci->gsuper->owner; - if (qid < 0 || - s->queues[qid].count > s->queues[t->cj->gsuper->owner].count) - qid = t->cj->gsuper->owner; - - } else { - - qid = t->ci->super->owner; - if (qid < 0 || - s->queues[qid].count > s->queues[t->cj->super->owner].count) - qid = t->cj->super->owner; - } + qid = t->ci->super->owner; + if (qid < 0 || + s->queues[qid].count > s->queues[t->cj->super->owner].count) + qid = t->cj->super->owner; break; case task_type_recv: #ifdef WITH_MPI diff --git a/src/space.c b/src/space.c index d5a5e6d8a402b645c171a347521796bdf1df7eb5..ed7ee5ef5715be67d0de44599d291a9a678a0f96 100644 --- a/src/space.c +++ b/src/space.c @@ -335,7 +335,6 @@ void space_regrid(struct space *s, double cell_max, int verbose) { c->count = 0; c->gcount = 0; c->super = c; - c->gsuper = c; c->ti_old = ti_current; lock_init(&c->lock); } @@ -408,7 +407,6 @@ void space_regrid(struct space *s, double cell_max, int verbose) { s->cells_top[k].ghost = NULL; s->cells_top[k].kick = NULL; s->cells_top[k].super = &s->cells_top[k]; - s->cells_top[k].gsuper = &s->cells_top[k]; } s->maxdepth = 0; } @@ -1480,7 +1478,6 @@ void space_split_mapper(void *map_data, int num_cells, void *extra_data) { temp->nodeID = c->nodeID; temp->parent = c; temp->super = NULL; - temp->gsuper = NULL; c->progeny[k] = temp; } diff --git a/src/task.c b/src/task.c index 00068f45769b4ca606cc729bd5e89c13ae729eef..54b9363b7ac3d5c372b591c00b0b03cc274f66b5 100644 --- a/src/task.c +++ b/src/task.c @@ -48,13 +48,13 @@ /* Task type names. */ const char *taskID_names[task_type_count] = { - "none", "sort", "self", "pair", "sub_self", - "sub_pair", "init", "ghost", "extra_ghost", "kick", - "kick_fixdt", "send", "recv", "grav_gather_m", "grav_fft", - "grav_mm", "grav_up", "grav_external", "cooling", "sourceterms"}; + "none", "sort", "self", "pair", "sub_self", + "sub_pair", "init", "ghost", "extra_ghost", "kick", + "kick_fixdt", "send", "recv", "grav_gather_m", "grav_fft", + "grav_mm", "grav_up", "cooling", "sourceterms"}; const char *subtaskID_names[task_subtype_count] = { - "none", "density", "gradient", "force", "grav", "tend"}; + "none", "density", "gradient", "force", "grav", "external_grav", "tend"}; /** * @brief Computes the overlap between the parts array of two given cells. @@ -135,6 +135,7 @@ __attribute__((always_inline)) INLINE static enum task_actions task_acts_on( break; case task_subtype_grav: + case task_subtype_external_grav: return task_action_gpart; break; @@ -150,7 +151,14 @@ __attribute__((always_inline)) INLINE static enum task_actions task_acts_on( case task_type_kick_fixdt: case task_type_send: case task_type_recv: - return task_action_all; + if (t->ci->count > 0 && t->ci->gcount > 0) + return task_action_all; + else if (t->ci->count > 0) + return task_action_part; + else if (t->ci->gcount > 0) + return task_action_gpart; + else + error("Task without particles"); break; case task_type_grav_gather_m: @@ -160,10 +168,6 @@ __attribute__((always_inline)) INLINE static enum task_actions task_acts_on( return task_action_multipole; break; - case task_type_grav_external: - return task_action_gpart; - break; - default: error("Unknown task_action for task"); return task_action_none; @@ -393,3 +397,15 @@ void task_print_submask(unsigned int submask) { printf(" %s=%s", subtaskID_names[k], (submask & (1 << k)) ? "yes" : "no"); printf(" ]\n"); } + +/** + * @brief Print basic information about a task. + * + * @param t The #task. + */ +void task_print(const struct task *t) { + + message("Type:'%s' sub_type:'%s' wait=%d nr_unlocks=%d skip=%d", + taskID_names[t->type], subtaskID_names[t->subtype], t->wait, + t->nr_unlock_tasks, t->skip); +} diff --git a/src/task.h b/src/task.h index bc4df3dc2a4cfee3c382e9f2059cba84f29299f7..f840c0b4b8e807dce28f6f13479dbdf4995ab66d 100644 --- a/src/task.h +++ b/src/task.h @@ -53,7 +53,6 @@ enum task_types { task_type_grav_fft, task_type_grav_mm, task_type_grav_up, - task_type_grav_external, task_type_cooling, task_type_sourceterms, task_type_count @@ -68,6 +67,7 @@ enum task_subtypes { task_subtype_gradient, task_subtype_force, task_subtype_grav, + task_subtype_external_grav, task_subtype_tend, task_subtype_count } __attribute__((packed)); @@ -160,5 +160,6 @@ int task_lock(struct task *t); void task_print_mask(unsigned int mask); void task_print_submask(unsigned int submask); void task_do_rewait(struct task *t); +void task_print(const struct task *t); #endif /* SWIFT_TASK_H */