This removes some statistics counters and timers which were not used, adds new counters and timers for some language features that were not monitored previously and separates the counters and timers into those which are of interest for investigating user code and those which are only of interest to the developer of the runtime itself. The runtime developer statistics are now ony collected if the additional #define KMP_DEVELOPER_STATS is set. Additional user statistics which are now collected include: * Count of nested parallelism (omp parallel inside a parallel region) * Count of omp distribute occurrences * Count of omp teams occurrences * Counts of task related statistics (taskyield, task execution, task cancellation, task steal) * Values passed to omp_set_numtheads * Time spent in omp single and omp master None of this affects code compiled without stats gathering enabled, which is the normal library build mode. This also fixes the CMake build by linking to the standard c++ library when building the stats library as it is a requirement. The normal library does not have this requirement and its link phase is left alone. Differential Revision: http://reviews.llvm.org/D11759 git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@244677 91177308-0d34-0410-b5e6-96231b3b80d8
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
|