@@ -279,9 +279,11 @@ struct htab;
struct gomp_task_depend_entry
{
+ /* Address of dependency. */
void *addr;
struct gomp_task_depend_entry *next;
struct gomp_task_depend_entry *prev;
+ /* Task that provides the depdency in ADDR. */
struct gomp_task *task;
/* Depend entry is of type "IN". */
bool is_in;
@@ -312,10 +314,14 @@ struct gomp_taskwait
struct gomp_task
{
struct gomp_task *parent;
+ /* Children of this task. Siblings are chained by
+ NEXT/PREV_CHILD fields below. */
struct gomp_task *children;
struct gomp_task *next_child;
struct gomp_task *prev_child;
+ /* Next task in TASK_QUEUE list in `struct gomp_team'. */
struct gomp_task *next_queue;
+ /* Prev task in TASK_QUEUE list in `struct gomp_team'. */
struct gomp_task *prev_queue;
/* Next task in the current taskgroup. */
struct gomp_task *next_taskgroup;
@@ -323,10 +329,13 @@ struct gomp_task
struct gomp_task *prev_taskgroup;
/* Taskgroup this task belongs in. */
struct gomp_taskgroup *taskgroup;
+ /* Tasks that depend on this task. */
struct gomp_dependers_vec *dependers;
struct htab *depend_hash;
struct gomp_taskwait *taskwait;
+ /* Number of items in DEPEND. */
size_t depend_count;
+ /* Number of tasks in the DEPENDERS field above. */
size_t num_dependees;
struct gomp_task_icv icv;
void (*fn) (void *);
@@ -335,13 +344,20 @@ struct gomp_task
bool in_tied_task;
bool final_task;
bool copy_ctors_done;
+ /* Set for undeferred tasks with unsatisfied dependencies which
+ block further execution of their parent until the dependencies
+ are satisfied. */
bool parent_depends_on;
+ /* Dependencies provided and/or needed for this task. DEPEND_COUNT
+ is the number of items available. */
struct gomp_task_depend_entry depend[];
};
struct gomp_taskgroup
{
struct gomp_taskgroup *prev;
+ /* List of tasks that belong in this taskgroup. Tasks are chained
+ by next/prev_taskgroup within the gomp_task. */
struct gomp_task *children;
bool in_taskgroup_wait;
bool cancelled;
@@ -411,6 +427,8 @@ struct gomp_team
struct gomp_work_share work_shares[8];
gomp_mutex_t task_lock;
+ /* Scheduled tasks. Chain fields are next/prev_queue within a
+ gomp_task. */
struct gomp_task *task_queue;
/* Number of all GOMP_TASK_{WAITING,TIED} tasks in the team. */
unsigned int task_count;
@@ -463,14 +463,26 @@ gomp_task_run_pre (struct gomp_task *child_task, struct gomp_task *parent,
if (parent->children == child_task)
parent->children = child_task->next_child;
+ /* If the current task (child_task) is at the top of the
+ parent's last_parent_depends_on, it's about to be removed
+ from it. Adjust last_parent_depends_on appropriately. */
if (__builtin_expect (child_task->parent_depends_on, 0)
&& parent->taskwait->last_parent_depends_on == child_task)
{
+ /* The last_parent_depends_on list was built with all
+ parent_depends_on entries linked to the prev_child. Grab
+ the next last_parent_depends_on head from this prev_child if
+ available... */
if (child_task->prev_child->kind == GOMP_TASK_WAITING
&& child_task->prev_child->parent_depends_on)
parent->taskwait->last_parent_depends_on = child_task->prev_child;
else
- parent->taskwait->last_parent_depends_on = NULL;
+ {
+ /* ...otherwise, there are no more parent_depends_on
+ entries waiting to run. In which case, clear the
+ list. */
+ parent->taskwait->last_parent_depends_on = NULL;
+ }
}
}
@@ -529,6 +541,11 @@ gomp_task_run_post_handle_depend_hash (struct gomp_task *child_task)
}
}
+/* After CHILD_TASK has been run, adjust the various task queues to
+ give higher priority to the tasks that depend on CHILD_TASK.
+
+ TEAM is the team to which CHILD_TASK belongs to. */
+
static size_t
gomp_task_run_post_handle_dependers (struct gomp_task *child_task,
struct gomp_team *team)
@@ -552,7 +569,7 @@ gomp_task_run_post_handle_dependers (struct gomp_task *child_task,
if (parent->taskwait && parent->taskwait->last_parent_depends_on
&& !task->parent_depends_on)
{
- /* Put task in last_parent_depends_on. */
+ /* Put depender in last_parent_depends_on. */
struct gomp_task *last_parent_depends_on
= parent->taskwait->last_parent_depends_on;
task->next_child = last_parent_depends_on->next_child;
@@ -560,7 +577,8 @@ gomp_task_run_post_handle_dependers (struct gomp_task *child_task,
}
else
{
- /* Put task at the top of the sibling list. */
+ /* Make depender a sibling of child_task, and place
+ it at the top of said sibling list. */
task->next_child = parent->children;
task->prev_child = parent->children->prev_child;
parent->children = task;
@@ -570,7 +588,7 @@ gomp_task_run_post_handle_dependers (struct gomp_task *child_task,
}
else
{
- /* Put task in the sibling list. */
+ /* Make depender a sibling of child_task. */
task->next_child = task;
task->prev_child = task;
parent->children = task;
@@ -592,6 +610,8 @@ gomp_task_run_post_handle_dependers (struct gomp_task *child_task,
parent->taskwait->last_parent_depends_on = task;
}
}
+ /* If depender is in a taskgroup, put it at the TOP of its
+ taskgroup. */
if (taskgroup)
{
if (taskgroup->children)
@@ -613,6 +633,8 @@ gomp_task_run_post_handle_dependers (struct gomp_task *child_task,
gomp_sem_post (&taskgroup->taskgroup_sem);
}
}
+ /* Put depender of child_task at the END of the team's
+ task_queue. */
if (team->task_queue)
{
task->next_queue = team->task_queue;
@@ -829,7 +851,9 @@ gomp_barrier_handle_tasks (gomp_barrier_state_t state)
}
}
-/* Called when encountering a taskwait directive. */
+/* Called when encountering a taskwait directive.
+
+ Wait for all children of the current task. */
void
GOMP_taskwait (void)
@@ -1024,6 +1048,10 @@ gomp_task_maybe_wait_for_dependencies (void **depend)
tsk->prev_child->next_child = tsk;
tsk->next_child->prev_child = tsk;
}
+ else
+ {
+ /* It's already in task->children. Nothing to do. */;
+ }
last_parent_depends_on = tsk;
}
}