summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openmp/runtime/src/kmp.h1
-rw-r--r--openmp/runtime/src/kmp_tasking.c38
2 files changed, 37 insertions, 2 deletions
diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h
index e1f17a04589..b115648e8cb 100644
--- a/openmp/runtime/src/kmp.h
+++ b/openmp/runtime/src/kmp.h
@@ -2189,6 +2189,7 @@ struct kmp_taskdata { /* aligned during dynamic
/* Currently not used except for perhaps IDB */
kmp_taskdata_t * td_parent; /* parent task */
kmp_int32 td_level; /* task nesting level */
+ kmp_int32 td_untied_count; /* untied task active parts counter */
ident_t * td_ident; /* task identifier */
// Taskwait data.
ident_t * td_taskwait_ident;
diff --git a/openmp/runtime/src/kmp_tasking.c b/openmp/runtime/src/kmp_tasking.c
index 044b7ff442c..2758027f572 100644
--- a/openmp/runtime/src/kmp_tasking.c
+++ b/openmp/runtime/src/kmp_tasking.c
@@ -284,6 +284,13 @@ __kmp_push_task(kmp_int32 gtid, kmp_task_t * task )
KA_TRACE(20, ("__kmp_push_task: T#%d trying to push task %p.\n", gtid, taskdata ) );
+ if ( taskdata->td_flags.tiedness == TASK_UNTIED ) {
+ // untied task needs to increment counter so that the task structure is not freed prematurely
+ kmp_int32 counter = 1 + KMP_TEST_THEN_INC32(&taskdata->td_untied_count);
+ KA_TRACE(20, ( "__kmp_push_task: T#%d untied_count (%d) incremented for task %p\n",
+ gtid, counter, taskdata ) );
+ }
+
// The first check avoids building task_team thread data if serialized
if ( taskdata->td_flags.task_serial ) {
KA_TRACE(20, ( "__kmp_push_task: T#%d team serialized; returning TASK_NOT_PUSHED for task %p\n",
@@ -436,8 +443,8 @@ __kmp_task_start( kmp_int32 gtid, kmp_task_t * task, kmp_taskdata_t * current_ta
// mark starting task as executing and as current task
thread -> th.th_current_task = taskdata;
- KMP_DEBUG_ASSERT( taskdata -> td_flags.started == 0 );
- KMP_DEBUG_ASSERT( taskdata -> td_flags.executing == 0 );
+ KMP_DEBUG_ASSERT( taskdata->td_flags.started == 0 || taskdata->td_flags.tiedness == TASK_UNTIED );
+ KMP_DEBUG_ASSERT( taskdata->td_flags.executing == 0 || taskdata->td_flags.tiedness == TASK_UNTIED );
taskdata -> td_flags.started = 1;
taskdata -> td_flags.executing = 1;
KMP_DEBUG_ASSERT( taskdata -> td_flags.complete == 0 );
@@ -498,6 +505,13 @@ __kmpc_omp_task_begin_if0( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t * task )
KA_TRACE(10, ("__kmpc_omp_task_begin_if0(enter): T#%d loc=%p task=%p current_task=%p\n",
gtid, loc_ref, taskdata, current_task ) );
+ if ( taskdata->td_flags.tiedness == TASK_UNTIED ) {
+ // untied task needs to increment counter so that the task structure is not freed prematurely
+ kmp_int32 counter = 1 + KMP_TEST_THEN_INC32(&taskdata->td_untied_count);
+ KA_TRACE(20, ( "__kmpc_omp_task_begin_if0: T#%d untied_count (%d) incremented for task %p\n",
+ gtid, counter, taskdata ) );
+ }
+
taskdata -> td_flags.task_serial = 1; // Execute this task immediately, not deferred.
__kmp_task_start( gtid, task, current_task );
@@ -646,6 +660,25 @@ __kmp_task_finish( kmp_int32 gtid, kmp_task_t *task, kmp_taskdata_t *resumed_tas
}
#endif /* BUILD_TIED_TASK_STACK */
+ if ( taskdata->td_flags.tiedness == TASK_UNTIED ) {
+ // untied task needs to check the counter so that the task structure is not freed prematurely
+ kmp_int32 counter = KMP_TEST_THEN_DEC32(&taskdata->td_untied_count) - 1;
+ KA_TRACE(20, ( "__kmp_task_finish: T#%d untied_count (%d) decremented for task %p\n",
+ gtid, counter, taskdata ) );
+ if ( counter > 0 ) {
+ // untied task is not done, to be continued possibly by other thread, do not free it now
+ if (resumed_task == NULL) {
+ KMP_DEBUG_ASSERT( taskdata->td_flags.task_serial );
+ resumed_task = taskdata->td_parent; // In a serialized task, the resumed task is the parent
+ }
+ thread->th.th_current_task = resumed_task; // restore current_task
+ resumed_task->td_flags.executing = 1; // resume previous task
+ KA_TRACE(10, ("__kmp_task_finish(exit): T#%d partially done task %p, resuming task %p\n",
+ gtid, taskdata, resumed_task) );
+ return;
+ }
+ }
+
KMP_DEBUG_ASSERT( taskdata -> td_flags.complete == 0 );
taskdata -> td_flags.complete = 1; // mark the task as completed
KMP_DEBUG_ASSERT( taskdata -> td_flags.started == 1 );
@@ -980,6 +1013,7 @@ __kmp_task_alloc( ident_t *loc_ref, kmp_int32 gtid, kmp_tasking_flags_t *flags,
taskdata->td_alloc_thread = thread;
taskdata->td_parent = parent_task;
taskdata->td_level = parent_task->td_level + 1; // increment nesting level
+ taskdata->td_untied_count = 0;
taskdata->td_ident = loc_ref;
taskdata->td_taskwait_ident = NULL;
taskdata->td_taskwait_counter = 0;
OpenPOWER on IntegriCloud