This patch doesn't affect D19878's context. So D19878 still cleanly applies. llvm-svn: 270252
283 lines
10 KiB
C++
283 lines
10 KiB
C++
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
|
// Source Licenses. See LICENSE.txt for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
#include "kmp.h"
|
|
#include "kmp_i18n.h"
|
|
#include "kmp_io.h"
|
|
#include "kmp_str.h"
|
|
|
|
#if OMP_40_ENABLED
|
|
|
|
/*!
|
|
@ingroup CANCELLATION
|
|
@param loc_ref location of the original task directive
|
|
@param gtid Global thread ID of encountering thread
|
|
@param cncl_kind Cancellation kind (parallel, for, sections, taskgroup)
|
|
|
|
@return returns true if the cancellation request has been activated and the execution thread
|
|
needs to proceed to the end of the canceled region.
|
|
|
|
Request cancellation of the binding OpenMP region.
|
|
*/
|
|
kmp_int32 __kmpc_cancel(ident_t* loc_ref, kmp_int32 gtid, kmp_int32 cncl_kind) {
|
|
kmp_info_t *this_thr = __kmp_threads [ gtid ];
|
|
|
|
KC_TRACE( 10, ("__kmpc_cancel: T#%d request %d OMP_CANCELLATION=%d\n", gtid, cncl_kind, __kmp_omp_cancellation) );
|
|
|
|
KMP_DEBUG_ASSERT(cncl_kind != cancel_noreq);
|
|
KMP_DEBUG_ASSERT(cncl_kind == cancel_parallel || cncl_kind == cancel_loop ||
|
|
cncl_kind == cancel_sections || cncl_kind == cancel_taskgroup);
|
|
KMP_DEBUG_ASSERT(__kmp_get_gtid() == gtid);
|
|
|
|
if (__kmp_omp_cancellation) {
|
|
switch (cncl_kind) {
|
|
case cancel_parallel:
|
|
case cancel_loop:
|
|
case cancel_sections:
|
|
// cancellation requests for parallel and worksharing constructs
|
|
// are handled through the team structure
|
|
{
|
|
kmp_team_t *this_team = this_thr->th.th_team;
|
|
KMP_DEBUG_ASSERT(this_team);
|
|
kmp_int32 old = KMP_COMPARE_AND_STORE_RET32(&(this_team->t.t_cancel_request), cancel_noreq, cncl_kind);
|
|
if (old == cancel_noreq || old == cncl_kind) {
|
|
//printf("__kmpc_cancel: this_team->t.t_cancel_request=%d @ %p\n",
|
|
// this_team->t.t_cancel_request, &(this_team->t.t_cancel_request));
|
|
// we do not have a cancellation request in this team or we do have one
|
|
// that matches the current request -> cancel
|
|
return 1 /* true */;
|
|
}
|
|
break;
|
|
}
|
|
case cancel_taskgroup:
|
|
// cancellation requests for a task group
|
|
// are handled through the taskgroup structure
|
|
{
|
|
kmp_taskdata_t* task;
|
|
kmp_taskgroup_t* taskgroup;
|
|
|
|
task = this_thr->th.th_current_task;
|
|
KMP_DEBUG_ASSERT( task );
|
|
|
|
taskgroup = task->td_taskgroup;
|
|
if (taskgroup) {
|
|
kmp_int32 old = KMP_COMPARE_AND_STORE_RET32(&(taskgroup->cancel_request), cancel_noreq, cncl_kind);
|
|
if (old == cancel_noreq || old == cncl_kind) {
|
|
// we do not have a cancellation request in this taskgroup or we do have one
|
|
// that matches the current request -> cancel
|
|
return 1 /* true */;
|
|
}
|
|
}
|
|
else {
|
|
// TODO: what needs to happen here?
|
|
// the specification disallows cancellation w/o taskgroups
|
|
// so we might do anything here, let's abort for now
|
|
KMP_ASSERT( 0 /* false */);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
KMP_ASSERT (0 /* false */);
|
|
}
|
|
}
|
|
|
|
// ICV OMP_CANCELLATION=false, so we ignored this cancel request
|
|
KMP_DEBUG_ASSERT(!__kmp_omp_cancellation);
|
|
return 0 /* false */;
|
|
}
|
|
|
|
/*!
|
|
@ingroup CANCELLATION
|
|
@param loc_ref location of the original task directive
|
|
@param gtid Global thread ID of encountering thread
|
|
@param cncl_kind Cancellation kind (parallel, for, sections, taskgroup)
|
|
|
|
@return returns true if a matching cancellation request has been flagged in the RTL and the
|
|
encountering thread has to cancel..
|
|
|
|
Cancellation point for the encountering thread.
|
|
*/
|
|
kmp_int32 __kmpc_cancellationpoint(ident_t* loc_ref, kmp_int32 gtid, kmp_int32 cncl_kind) {
|
|
kmp_info_t *this_thr = __kmp_threads [ gtid ];
|
|
|
|
KC_TRACE( 10, ("__kmpc_cancellationpoint: T#%d request %d OMP_CANCELLATION=%d\n", gtid, cncl_kind, __kmp_omp_cancellation) );
|
|
|
|
KMP_DEBUG_ASSERT(cncl_kind != cancel_noreq);
|
|
KMP_DEBUG_ASSERT(cncl_kind == cancel_parallel || cncl_kind == cancel_loop ||
|
|
cncl_kind == cancel_sections || cncl_kind == cancel_taskgroup);
|
|
KMP_DEBUG_ASSERT(__kmp_get_gtid() == gtid);
|
|
|
|
if (__kmp_omp_cancellation) {
|
|
switch (cncl_kind) {
|
|
case cancel_parallel:
|
|
case cancel_loop:
|
|
case cancel_sections:
|
|
// cancellation requests for parallel and worksharing constructs
|
|
// are handled through the team structure
|
|
{
|
|
kmp_team_t *this_team = this_thr->th.th_team;
|
|
KMP_DEBUG_ASSERT(this_team);
|
|
if (this_team->t.t_cancel_request) {
|
|
if (cncl_kind == this_team->t.t_cancel_request) {
|
|
// the request in the team structure matches the type of
|
|
// cancellation point so we can cancel
|
|
return 1 /* true */;
|
|
}
|
|
KMP_ASSERT( 0 /* false */);
|
|
}
|
|
else {
|
|
// we do not have a cancellation request pending, so we just
|
|
// ignore this cancellation point
|
|
return 0;
|
|
}
|
|
break;
|
|
}
|
|
case cancel_taskgroup:
|
|
// cancellation requests for a task group
|
|
// are handled through the taskgroup structure
|
|
{
|
|
kmp_taskdata_t* task;
|
|
kmp_taskgroup_t* taskgroup;
|
|
|
|
task = this_thr->th.th_current_task;
|
|
KMP_DEBUG_ASSERT( task );
|
|
|
|
taskgroup = task->td_taskgroup;
|
|
if (taskgroup) {
|
|
// return the current status of cancellation for the
|
|
// taskgroup
|
|
return !!taskgroup->cancel_request;
|
|
}
|
|
else {
|
|
// if a cancellation point is encountered by a task
|
|
// that does not belong to a taskgroup, it is OK
|
|
// to ignore it
|
|
return 0 /* false */;
|
|
}
|
|
}
|
|
default:
|
|
KMP_ASSERT (0 /* false */);
|
|
}
|
|
}
|
|
|
|
// ICV OMP_CANCELLATION=false, so we ignore the cancellation point
|
|
KMP_DEBUG_ASSERT(!__kmp_omp_cancellation);
|
|
return 0 /* false */;
|
|
}
|
|
|
|
/*!
|
|
@ingroup CANCELLATION
|
|
@param loc_ref location of the original task directive
|
|
@param gtid Global thread ID of encountering thread
|
|
|
|
@return returns true if a matching cancellation request has been flagged in the RTL and the
|
|
encountering thread has to cancel..
|
|
|
|
Barrier with cancellation point to send threads from the barrier to the
|
|
end of the parallel region. Needs a special code pattern as documented
|
|
in the design document for the cancellation feature.
|
|
*/
|
|
kmp_int32
|
|
__kmpc_cancel_barrier(ident_t *loc, kmp_int32 gtid) {
|
|
int ret = 0 /* false */;
|
|
kmp_info_t *this_thr = __kmp_threads [ gtid ];
|
|
kmp_team_t *this_team = this_thr->th.th_team;
|
|
|
|
KMP_DEBUG_ASSERT(__kmp_get_gtid() == gtid);
|
|
|
|
// call into the standard barrier
|
|
__kmpc_barrier(loc, gtid);
|
|
|
|
// if cancellation is active, check cancellation flag
|
|
if (__kmp_omp_cancellation) {
|
|
// depending on which construct to cancel, check the flag and
|
|
// reset the flag
|
|
switch (this_team->t.t_cancel_request) {
|
|
case cancel_parallel:
|
|
ret = 1;
|
|
// ensure that threads have checked the flag, when
|
|
// leaving the above barrier
|
|
__kmpc_barrier(loc, gtid);
|
|
this_team->t.t_cancel_request = cancel_noreq;
|
|
// the next barrier is the fork/join barrier, which
|
|
// synchronizes the threads leaving here
|
|
break;
|
|
case cancel_loop:
|
|
case cancel_sections:
|
|
ret = 1;
|
|
// ensure that threads have checked the flag, when
|
|
// leaving the above barrier
|
|
__kmpc_barrier(loc, gtid);
|
|
this_team->t.t_cancel_request = cancel_noreq;
|
|
// synchronize the threads again to make sure we
|
|
// do not have any run-away threads that cause a race
|
|
// on the cancellation flag
|
|
__kmpc_barrier(loc, gtid);
|
|
break;
|
|
case cancel_taskgroup:
|
|
// this case should not occur
|
|
KMP_ASSERT (0 /* false */ );
|
|
break;
|
|
case cancel_noreq:
|
|
// do nothing
|
|
break;
|
|
default:
|
|
KMP_ASSERT ( 0 /* false */);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*!
|
|
@ingroup CANCELLATION
|
|
@param loc_ref location of the original task directive
|
|
@param gtid Global thread ID of encountering thread
|
|
|
|
@return returns true if a matching cancellation request has been flagged in the RTL and the
|
|
encountering thread has to cancel..
|
|
|
|
Query function to query the current status of cancellation requests.
|
|
Can be used to implement the following pattern:
|
|
|
|
if (kmp_get_cancellation_status(kmp_cancel_parallel)) {
|
|
perform_cleanup();
|
|
#pragma omp cancellation point parallel
|
|
}
|
|
*/
|
|
int __kmp_get_cancellation_status(int cancel_kind) {
|
|
if (__kmp_omp_cancellation) {
|
|
kmp_info_t *this_thr = __kmp_entry_thread();
|
|
|
|
switch (cancel_kind) {
|
|
case cancel_parallel:
|
|
case cancel_loop:
|
|
case cancel_sections:
|
|
{
|
|
kmp_team_t *this_team = this_thr->th.th_team;
|
|
return this_team->t.t_cancel_request == cancel_kind;
|
|
}
|
|
case cancel_taskgroup:
|
|
{
|
|
kmp_taskdata_t* task;
|
|
kmp_taskgroup_t* taskgroup;
|
|
task = this_thr->th.th_current_task;
|
|
taskgroup = task->td_taskgroup;
|
|
return taskgroup && taskgroup->cancel_request;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0 /* false */;
|
|
}
|
|
|
|
#endif
|