While I'm here... I've added more comments throughout.
I'm still not convinced we need anything but GOMP_TASK_WAITING in enum gomp_task_kind, but perhaps you needed it for future usage? If so, could you provide a description for GOMP_TASK_IFFALSE?
OK for branch?
commit 45fdbc84123fefde6bf99aaf87099317aaa38f24 Author: Aldy Hernandez <al...@redhat.com> Date: Wed Aug 26 07:28:39 2015 -0700 * libgomp.h (enum gomp_task_kind): Comment fields. (struct gomp_task): Comment some fields. * task.c (GOMP_task): Add comments. (gomp_task_run_pre): Same. diff --git a/libgomp/libgomp.h b/libgomp/libgomp.h index 3d705ef..34f064c 100644 --- a/libgomp/libgomp.h +++ b/libgomp/libgomp.h @@ -263,9 +263,13 @@ extern char *goacc_device_type; enum gomp_task_kind { + /* Thread not directly created by user. For instance, when creating + a team of threads or an ICV. */ GOMP_TASK_IMPLICIT, GOMP_TASK_IFFALSE, + /* Task created by GOMP_task and waiting to be run. */ GOMP_TASK_WAITING, + /* Task currently scheduled and about to execute. */ GOMP_TASK_TIED }; @@ -313,8 +317,11 @@ struct gomp_task struct gomp_task *prev_child; struct gomp_task *next_queue; struct gomp_task *prev_queue; + /* Next task in the current taskgroup. */ struct gomp_task *next_taskgroup; + /* Previous task in the current taskgroup. */ struct gomp_task *prev_taskgroup; + /* Taskgroup this task belongs in. */ struct gomp_taskgroup *taskgroup; struct gomp_dependers_vec *dependers; struct htab *depend_hash; diff --git a/libgomp/task.c b/libgomp/task.c index 7c7bae4..c0197cd 100644 --- a/libgomp/task.c +++ b/libgomp/task.c @@ -388,6 +388,7 @@ GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *), parent->children = task; if (taskgroup) { + /* If applicable, place task into its taskgroup. */ if (taskgroup->children) { task->next_taskgroup = taskgroup->children; @@ -451,7 +452,14 @@ gomp_task_run_pre (struct gomp_task *child_task, struct gomp_task *parent, { if (parent) { - /* Remove child_task from parent. */ + /* Adjust children such that it will point to a next child, + while the current one is scheduled to be executed. This way, + GOMP_taskwait (and others) can schedule a next task while + waiting. + + Do not remove it entirely from the circular list, as it is + still a child, though not one we should consider first (say + by GOMP_taskwait). */ if (parent->children == child_task) parent->children = child_task->next_child; @@ -465,10 +473,14 @@ gomp_task_run_pre (struct gomp_task *child_task, struct gomp_task *parent, parent->taskwait->last_parent_depends_on = NULL; } } - /* Remove child_task from taskgroup. */ + + /* Adjust taskgroup to point to the next taskgroup. See note above + regarding adjustment of children as to why the child_task is not + removed entirely from the circular list. */ if (taskgroup && taskgroup->children == child_task) taskgroup->children = child_task->next_taskgroup; + /* Remove child_task from the task_queue. */ child_task->prev_queue->next_queue = child_task->next_queue; child_task->next_queue->prev_queue = child_task->prev_queue; if (team->task_queue == child_task) @@ -479,6 +491,7 @@ gomp_task_run_pre (struct gomp_task *child_task, struct gomp_task *parent, team->task_queue = NULL; } child_task->kind = GOMP_TASK_TIED; + if (--team->task_queued_count == 0) gomp_team_barrier_clear_task_pending (&team->barrier); if ((gomp_team_barrier_cancelled (&team->barrier)