Compare commits

...
255 Commits
Author SHA1 Message Date
Hans Wennborg d5aa29cb3b Merging r325218:
------------------------------------------------------------------------
r325218 | hahnfeld | 2018-02-15 09:10:22 +0100 (Thu, 15 Feb 2018) | 10 lines

[CMake] Add -fno-experimental-isel for testing

GlobalISel doesn't yet implement blockaddress and falls back to
SelectionDAG. This results in additional branch instruction to
the next basic block which breaks the OMPT tests.
Disable GlobalISel for now when compiling the tests because fixing
them is not easily possible. See http://llvm.org/PR36313 for full
discussion history.

Differential Revision: https://reviews.llvm.org/D43195
------------------------------------------------------------------------


git-svn-id: https://llvm.org/svn/llvm-project/openmp/branches/release_60@325230 91177308-0d34-0410-b5e6-96231b3b80d8
2018-02-15 11:00:24 +00:00
Dimitry Andric 3d85b5b4aa Merging r322869:
------------------------------------------------------------------------
r322869 | dim | 2018-01-18 19:24:22 +0100 (Thu, 18 Jan 2018) | 3 lines

Sprinkle a few <cstdlib> includes, for libomptarget sources using
malloc, free, alloca and getenv.  NFCI.

------------------------------------------------------------------------


git-svn-id: https://llvm.org/svn/llvm-project/openmp/branches/release_60@323037 91177308-0d34-0410-b5e6-96231b3b80d8
2018-01-20 12:17:51 +00:00
Hans Wennborg f1a69ba0a0 Merging r322830:
------------------------------------------------------------------------
r322830 | hahnfeld | 2018-01-18 02:58:43 -0800 (Thu, 18 Jan 2018) | 1 line

Add missing headers for Debug builds
------------------------------------------------------------------------


git-svn-id: https://llvm.org/svn/llvm-project/openmp/branches/release_60@322837 91177308-0d34-0410-b5e6-96231b3b80d8
2018-01-18 11:19:22 +00:00
Hans Wennborg 92d4fe5037 Merging r322160:
------------------------------------------------------------------------
r322160 | hahnfeld | 2018-01-10 00:10:23 -0800 (Wed, 10 Jan 2018) | 5 lines

[OMPT] Fix cast and printf of wait_id in lock test

This didn't work on 32 bit platforms.

Differential Revision: https://reviews.llvm.org/D41853
------------------------------------------------------------------------


git-svn-id: https://llvm.org/svn/llvm-project/openmp/branches/release_60@322640 91177308-0d34-0410-b5e6-96231b3b80d8
2018-01-17 12:52:58 +00:00
Hans Wennborg 2d88abcec6 Merging r322068:
------------------------------------------------------------------------
r322068 | pawosm01 | 2018-01-09 02:54:06 -0800 (Tue, 09 Jan 2018) | 3 lines

Fix type mismatch in omp_control_tool() implementation that makes it run incorrectly on 32-bit machines.

Differential Revision: https://reviews.llvm.org/D41854
------------------------------------------------------------------------


git-svn-id: https://llvm.org/svn/llvm-project/openmp/branches/release_60@322639 91177308-0d34-0410-b5e6-96231b3b80d8
2018-01-17 12:51:30 +00:00
Hans Wennborg b1dec7c481 Merging r321964:
------------------------------------------------------------------------
r321964 | hahnfeld | 2018-01-07 08:54:36 -0800 (Sun, 07 Jan 2018) | 7 lines

Correct types of pointers to doacross_num_done

This field is defined as kmp_int32, so we should use neither
pointers to kmp_int64 nor 64 bit atomic instructions.
(Found while testing on a Raspberry Pi, 32 bit ARM)

Differential Revision: https://reviews.llvm.org/D41656
------------------------------------------------------------------------


git-svn-id: https://llvm.org/svn/llvm-project/openmp/branches/release_60@322560 91177308-0d34-0410-b5e6-96231b3b80d8
2018-01-16 15:18:22 +00:00
Hans Wennborg b3d58d09c4 Creating release_60 branch off revision 321711
git-svn-id: https://llvm.org/svn/llvm-project/openmp/branches/release_60@321723 91177308-0d34-0410-b5e6-96231b3b80d8
2018-01-03 14:54:54 +00:00
Joachim Protze 85a6d05495 [OMPT] Build runtime with OMPT support by default
This patch enables OMPT by default if version 50 or later is built and the config says, that OMPT will be supported.

Differential Revision: https://reviews.llvm.org/D41508

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@321675 91177308-0d34-0410-b5e6-96231b3b80d8
2018-01-02 21:09:00 +00:00
Jonas Hahnfeld 4a0909d000 Unify build documentation and convert to reStructuredText
We now have several options that apply for both libraries and they
shouldn't be documented in multiple files. When already merging
the two Build_With_CMake.txt documents, convert them to
reStructuredText which is used for all of LLVM's documentation.

Differential Revision: https://reviews.llvm.org/D40920

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@321481 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-27 09:15:10 +00:00
Joachim Protze 9976cd64ea [OMPT] Set and reset frame address when creating a task with dependences
As for normal task creation, the task frame addresses need to be stored
for the encountering task.

Differential Revision: https://reviews.llvm.org/D41165

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@321421 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-24 07:30:23 +00:00
Paul Osmialowski abbefd87f0 [OMPT] Add missing initialization in nested_lwt.c test case
Without this initialization this test case tend to fail.

Differential Revision: https://reviews.llvm.org/D41542

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@321379 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-22 19:24:06 +00:00
Joachim Protze aa01de3464 [OMPT] Fix failing test cases for gcc on Ubuntu
The compiler warns that _BSD_SOURCE is deprecated and _DEFAULT_SOURCE should
be used instead. We keep _BSD_SOURCE for older compilers, that don't know
about _DEFAULT_SOURCE.

The linker drops the tool when linking, since there is no visible need for
the library. So we need to tell the linker, that the tool should be linked
anyway.

Differential Revision: https://reviews.llvm.org/D41499

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@321362 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-22 16:40:32 +00:00
Joachim Protze 081e235183 Remove unused positional argument for printf
The format string for hints only prints the second argument (string) and drops
the first argument (hint id). Depending on how you read the POSIX text for
printf, this could be valid. But for practical reason, i.e., unpacking the
va_list passed to printf based on the formating information, it makes sense
to fix the implementation and not pass the id for hint.

Failing testcases were:

misc_bugs/teams-reduction.c
ompt/parallel/not_enough_threads.c

Differential Revision: https://reviews.llvm.org/D41504

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@321361 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-22 16:40:26 +00:00
Joachim Protze 00e405ede6 Add missing test case from D41171 commit
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@321270 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-21 14:36:36 +00:00
Joachim Protze 62dafa36f3 [OMPT] Add missing ompt_get_num_procs function
This function is defined in OpenMP-TR6 section 4.1.5.1.6
The functions was not implemented yet.

Since ompt-functions can only be called after the runtime was initialized and
has loaded a tool, it can assume the runtime to be initialized. In contrast
to omp_get_num_procs which needs to check whether the runtime is initialized.

Differential Revision: https://reviews.llvm.org/D40949

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@321269 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-21 14:36:30 +00:00
Joachim Protze 623b98e440 [OMPT] Fix return address handling in a few GOMP interface methods
This revision fixes failing testcases with parallel for loops and the gomp
interface. The return address needs to be stored at entry to runtime.
The storage is cleared on usage, so we need to update the storage before
calling again internal functions, that will trigger event callbacks.

Differential Revision: https://reviews.llvm.org/D41181

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@321265 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-21 13:55:39 +00:00
Joachim Protze 617a41cdba [OMPT] Handle null pointer in set_callback to improve performance
We use the bitmap ompt_enabled thoughout the runtime, to avoid loading the
vector of callback functions when testing if specific code should be executed.
Before invoking an event callback function, the pointer is tested for NULL.

This revision resets the corresponding bit in ompt_enabled to 0 if
NULL is passed in set_callback.

Differential Revision: https://reviews.llvm.org/D41171

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@321264 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-21 13:55:34 +00:00
Joachim Protze df39d67d94 [OMPT] Use frames at different level when using clang version 5 or higher with debug flag
Clang 5 or higher adds an intermediate function call in certain cases when
compiling with debug flag. This revision updates the testcases to work
correctly.

Differential Revision: https://reviews.llvm.org/D40595

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@321263 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-21 13:55:29 +00:00
Joachim Protze ad36fb50c7 [OMPT] Add annotations to testcases that are expected to fail when using certain compilers
Reasons for expected failures are mainly bugs when using lables in OpenMP regions
or missing support of some OpenMP features.
For some worksharing clauses, support to distinguish the kind of workshare was
added just recently.

If an issue was fixed in a minor release version of a compiler, we flag the
test as unsupported for this compiler version to avoid false positives.
Same for fixes that where backported to older compiler versions.

Differential Revision: https://reviews.llvm.org/D40384

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@321262 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-21 13:55:16 +00:00
Paul Osmialowski f8f48669a0 [AArch64] add required arch specific code for running OMPT test cases
Differential Revision: https://reviews.llvm.org/D41482

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@321258 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-21 12:33:31 +00:00
Dimitry Andric ebc0015ad7 Fix more inconsistent line endings. NFC.
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@321016 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-18 19:46:56 +00:00
Paul Osmialowski 7843965571 [AArch64] fix an issue with older /proc/cpuinfo layout
There are two /proc/cpuinfo layots in use for AArch64: old and new.
The old one has all 'processor : n' lines in one section, hence
checking for duplications does not make sense.

Differential Revision: https://reviews.llvm.org/D41000

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@320593 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-13 16:12:24 +00:00
Jonas Hahnfeld a5acc90e8d [CMake] Remove legacy LIBOMP_LIT_ARGS
The bots have been updated, this option isn't needed anymore.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@320153 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-08 15:07:08 +00:00
Jonas Hahnfeld 3cee55228e Use hyperbarrier by default on all architectures
All architectures except x86_64 used the linear barrier implementation
by default which doesn't give good performance for a larger number
of threads.

Improvements for PARALLEL overhead (EPCC) with this patch on a Power8
system (2 sockets x 10 cores x 8 threads, OMP_PLACES=cores)

 20 threads:  4.55us -> 3.49us
 40 threads:  8.84us -> 4.06us
 80 threads: 19.18us -> 4.74us
160 threads: 54.22us -> 6.73us

Differential Revision: https://reviews.llvm.org/D40358

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@320152 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-08 15:07:07 +00:00
Jonas Hahnfeld a0542f7865 Fix thread affinity on non-x86 Linux
To make thread affinity work according to the OpenMP spec, the
runtime needs information about the hardware topology. On Linux
the default way is to parse /proc/cpuinfo which contains this
information for x86 machines but (at least) not for AArch64 and
Power architectures.

Fortunately, there is a different code path which is able to get
that data from sysfs. The needed patch has landed in 2006 for
Linux 2.6.16 which is safe to assume nowadays (even RHEL 5 had
a kernel version derived from 2.6.18, and we are now at RHEL 7!).

Differential Revision: https://reviews.llvm.org/D40357

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@320151 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-08 15:07:05 +00:00
Jonas Hahnfeld c549ebcc76 Add missing memory barrier for queuing locks
Otherwise I see hangs in the omp_single_copyprivate test when
compiling in release mode. With the debug assertions, I get a
failure `head > 0 && tail > 0`.

Differential Revision: https://reviews.llvm.org/D40722

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@320150 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-08 15:07:02 +00:00
Jonas Hahnfeld 5a07983cf5 [libomptarget] Split implementation of interface functions
This last of four patches adds a new file for the interface
functions that Clang uses during code generation. The only
change except simply moving the current code is renaming the
function CheckDeviceAndCtors() and using the correct type for
64bit device ids.

Differential Revision: https://reviews.llvm.org/D40801

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@319972 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-06 21:59:15 +00:00
Jonas Hahnfeld 25af465ca4 [libomptarget] Split implementation of API functions
This third patch moves the implementation of the user-facing
OpenMP API functions into its own file. For now, the code is
only moved, no cleanups applied yet.

Differential Revision: https://reviews.llvm.org/D40800

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@319971 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-06 21:59:12 +00:00
Jonas Hahnfeld 4303e181d4 [libomptarget] Split device functionality
This is the second patch to split the current monolithic
implementation into separate files. Note that this change
doesn't cleanup the code yet.

Differential Revision: https://reviews.llvm.org/D40799

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@319970 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-06 21:59:09 +00:00
Jonas Hahnfeld c35df18503 [libomptarget] Split RTL plugin functionality
This is the first of four patches to split the target agnostic
library into multiple (smaller) files. It only moves the code
to separate implementation files and does no cleanup (yet) except
removing unneeded headers.

Differential Revision: https://reviews.llvm.org/D40798

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@319969 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-06 21:59:07 +00:00
Jonas Hahnfeld cac6ef05a1 [libomptarget] Move header files and CMake library definition
Future patches will add (private) header files in src/ that should
not be visible to plugins, so move the "public" ones to a new
include/ directory. This is still internal in a sense that the
contained files won't be installed for the user.
Similarly, the target agnostic offloading library should be built
directly in src/. The parent directory is responsible for finding
dependencies and including all subdirectories.

Differential Revision: https://reviews.llvm.org/D40797

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@319968 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-06 21:59:04 +00:00
Jonathan Peyton 74e9371341 [OpenMP] Add entry for Intel Compiler 18
Patch by Simon Convent

Differential Revision: https://reviews.llvm.org/D40386


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@319961 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-06 21:15:28 +00:00
Jonathan Peyton 865d07f101 Eliminate double printing of verbose affinity settings
Redundant extra verbose output of binding to full mask in case
affinity=balanced or OMP_PLACES=<any> or OMP_PROC_BIND=<any>

Differential Revision: https://reviews.llvm.org/D40624


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@319960 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-06 21:07:41 +00:00
Jonathan Peyton 441b330c98 Trivial enum fix
This change is a trivial fix for enums that removes specification of "last" or
"upper" values, or other boundary values. This simplifies the code in places,
and results in never needing to update the "upper" values again.

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D40804


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@319957 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-06 21:02:15 +00:00
Jonas Hahnfeld 93e7a82b80 Fix alignment in teams-reduction.c test
The runtime will use the global kmp_critical_name as a lock and
tries to atomically store a pointer in there. This will fail
if the global is only aligned by 4 bytes, the size of one int32_t
element. Use a union to ensure the global is aligned to the size
of a pointer on the current platform.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@319811 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-05 18:45:21 +00:00
Jonas Hahnfeld 3342a84ab0 Fix PR30890: Reduction across teams hangs
__kmpc_reduce_nowait() correctly swapped the teams for reductions
in a teams construct. Apply the same logic to __kmpc_reduce() and
__kmpc_reduce_end().

Differential Revision: https://reviews.llvm.org/D40753

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@319788 91177308-0d34-0410-b5e6-96231b3b80d8
2017-12-05 16:51:24 +00:00
Jonas Hahnfeld d180ffbb82 [CMake] Detect information about test compiler
Perform a nested CMake invocation to avoid writing our own parser
for compiler versions when we are not testing the in-tree compiler.
Use the extracted information to mark a test as unsupported that
hangs with Clang prior to version 4.0.1 and restrict tests for
libomptarget to Clang version 6.0.0 and later.

Differential Revision: https://reviews.llvm.org/D40083

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@319448 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-30 17:08:31 +00:00
Andrey Churbanov 1696d28687 Extension of HWLOC topology discovery with NUMA nodes and tiles
Patch by Olga Malysheva

Differential Revision: https://reviews.llvm.org/D40309


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@319422 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-30 11:51:47 +00:00
Jonathan Peyton 9cdb2558bd Make kmp_r_sched_t into a union
This change makes kmp_r_sched_t type into a union for simpler
comparisons and assignments

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D40374


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@319379 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-29 22:47:52 +00:00
Jonathan Peyton b77eb553e2 Fix aligned memory allocation in the stub library
kmp_aligned_malloc() always returned NULL on Windows (stub library only)
that may cause Fortran application crash.  With this change all memory
allocation functions were fixed to use aligned{m,re,rec}alloc() to
allocate/reallocate memory. To deallocate that memory _aligned_free() is
used in kmp_free().

Patch by Olga Malysheva

Differential Revision: https://reviews.llvm.org/D40296


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@319375 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-29 22:29:38 +00:00
Jonathan Peyton e9075904db Warning is emitted when tiles are requested but cannot be used
Added two warnings:
1) Before building the topology map check if tiles are requested but the
   topo method is not hwloc;
2) After building the topology map check if tiles are requested but not
   detected by the library.

Patch by Olga Malysheva

Differential Revision: https://reviews.llvm.org/D40340


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@319374 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-29 22:27:18 +00:00
Jonathan Peyton 61fa396215 Fix types of Fortran array elements
Fortran array elements made default integer in OMP_GET_PLACE_PROC_IDS and
OMP_GET_PARTITION_PLACE_NUMS subroutines, otherwise call to them produces
incorrect result.

Patch by Olga Malysheva

Differential Revision: https://reviews.llvm.org/D40356


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@319372 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-29 22:23:44 +00:00
Jonas Hahnfeld a1b4de8ad3 [CMake] Refactor testing infrastructure
The code for the two OpenMP runtime libraries was very similar.
Move to common CMake file that is included and provides a simple
interface for adding testsuites. Also add a common check-openmp
target that runs all testsuites that have been registered.

Note that this renames all test options to the common OPENMP
namespace, for example OPENMP_TEST_C_COMPILER instead of
LIBOMP_TEST_COMPILER and so on.

Differential Revision: https://reviews.llvm.org/D40082

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@319343 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-29 19:31:52 +00:00
Jonas Hahnfeld 41aebf5e26 [CMake] Refactor common settings and flags
These are needed by both libraries, so we can do that in a
common namespace and unify configuration parameters.
Also make sure that the user isn't requesting libomptarget
if the library cannot be built on the system. Issue an error
in that case.

Differential Revision: https://reviews.llvm.org/D40081

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@319342 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-29 19:31:48 +00:00
Jonas Hahnfeld b5f5bf534a [CMake] Disallow direct configuration
As a first step, this allows us to generalize the detection of
standalone builds and make it fully compatible when building in
llvm/runtimes/ which automatically sets OPENMP_STANDLONE_BUILD.

Differential Revision: https://reviews.llvm.org/D40080

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@319341 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-29 19:31:43 +00:00
Ben Hamilton 64790a3e29 [openmp] Set up .arcconfig to point to new Diffusion OMP repository
Summary:
We want to automatically copy the appropriate mailing list
for review requests to the openmp repository.

For context, see the proposal and discussion here:

http://lists.llvm.org/pipermail/cfe-dev/2017-November/056032.html

Similar to D40179, I set up a new Diffusion repository with callsign
"OMP" for OpenMP:

https://reviews.llvm.org/source/openmp/

This explicitly updates openmp's .arcconfig to point to the new
OMP repository in Diffusion, which will let us use Herald rule H272
to automatically subscribe openmp-commits to review requests.

Reviewers: hans, grokos, Hahnfeld

Reviewed By: grokos

Subscribers: sammccall, klimek, openmp-commits

Differential Revision: https://reviews.llvm.org/D40499

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@319254 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-28 23:28:45 +00:00
Sylvestre Ledru 9c6a06ae28 doxygen: disable the html timestamp: this is breaking the reproducible build of openmp
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@318978 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-25 14:12:33 +00:00
Jonas Hahnfeld 9da031d4d2 Fix for OMP doacross implementation on Power
Power has a weak consistency model so we need memory barriers to
make writes (both from runtime and from user code) available for
all threads.

Differential Revision: https://reviews.llvm.org/D40175

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@318848 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-22 17:15:20 +00:00
Jonas Hahnfeld b692e4cebf [CMake] Re-enable libomptarget and restrict tests to Clang 6.0.0
We have just fixed the codegen of omp_is_initial_device() to reliably work
when offloading to the same device, see commit r316001. This fixes the
failing tests that were the reason why we disabled the library for 5.0.

Differential Revision: https://reviews.llvm.org/D39052

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@318847 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-22 17:15:18 +00:00
George Rokos 2aa843c7d7 [Clang][OpenMP] New clang/libomptarget map interface: new function signatures, libomptarget-side
This is the libomptarget-side patch which changes the __tgt_* API function signatures in preparation for the new map interface.
Changes are: Device IDs 32bits --> 64bits, Flags 32bits --> 64bits

Differential revision: https://reviews.llvm.org/D40313



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@318790 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-21 18:26:41 +00:00
Andrey Churbanov 0b53bf7427 Fixed OMP doacross implementation on 32-bit platforms.
Differential Revision: https://reviews.llvm.org/D40171


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@318658 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-20 16:00:42 +00:00
Jonas Hahnfeld 2653e740fc [OMPT] Fix inaccuracies in worksharing tests
These tests were failing rarely on my MacBook when there was some
activity in the background. Read: one of a thousand executions?

 * sections.c missed the sorting based on thread ids. This worked
   as long as the master thread finished its section before the
   worker thread started the second one but failed if the master
   thread was put to sleep by the OS.
 * The checks in single.c assumed that the master thread executes
   the single region which works most of the time because it is
   usually faster than the newly spawned worker thread.

Differential Revision: https://reviews.llvm.org/D39853

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@318527 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-17 15:26:44 +00:00
Andrey Churbanov 73ebd2c677 Exclude untied tasks from checking of task scheduling constraint (TSC).
This can improve performance of tests with untied tasks.

Differential Revision: https://reviews.llvm.org/D39613


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@318388 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-16 10:45:07 +00:00
Jonathan Peyton 38c1d48226 [OpenMP] Remove the unused testsuite/ directory
The testsuite directory is not used or updated and confuses new users to the
OpenMP project. These tests were rewritten using the lit format and put under
the runtime/test directory. This patch removes the entire testsuite/ directory.

Differential Revision: https://reviews.llvm.org/D39767


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@318056 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-13 17:44:48 +00:00
Jonas Hahnfeld e139f2e769 [OMPT] Provide initialization for Mac OS X
Traditionally, the library had a weak symbol for ompt_start_tool()
that served as fallback and disabled OMPT if called. Tools could
provide their own version and replace the default implementation
to register callbacks and lookup functions. This mechanism has
worked reasonably well on Linux systems where this interface was
initially developed.

On Darwin / Mac OS X the situation is a bit more complicated and
the weak symbol doesn't work out-of-the-box. In my tests, the
library with the tool needed to link against the OpenMP runtime
to make the process work. This would effectively mean that a tool
needed to choose a runtime library whereas one design goal of the
interface was to allow tools that are agnostic of the runtime.

The solution is to use dlsym() with the argument RTLD_DEFAULT so
that static implementations of ompt_start_tool() are found in the
main executable. This works because the linker on Mac OS X includes
all symbols of an executable in the global symbol table by default.
To use the same code path on Linux, the application would need to
be built with -Wl,--export-dynamic. To avoid this restriction, we
continue to use weak symbols on Linux systems as before.

Finally this patch extends the existing test to cover all possible
ways of initializing the tool as described by the standard. It
also fixes ompt_finalize() to not call omp_get_thread_num() when
the library is shut down which resulted in hangs on Darwin.
The changes have been tested on Linux to make sure that it passes
the current tests as well as the newly extended one.

Differential Revision: https://reviews.llvm.org/D39801

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@317980 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-11 13:59:48 +00:00
Jonas Hahnfeld 31d41b07de [libomptarget] Build all libraries in libomptarget/
In standalone build, plugins where previously built in their
subdirectory in plugins/ and tests couldn't find them.

Differential Revision: https://reviews.llvm.org/D39920

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@317979 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-11 13:59:45 +00:00
Joachim Protze 50aea48c65 [OMPT] Fix assertion for OpenMP code generated with outdated compilers
For up-to-date compilers, this assertion is reasonable, but it breaks
compatibility with the typical compiler installed on most systems.
This patch changes the default value to what we had when there was no
compiler support. A warning about the outdated compiler is printed during
runtime, when this point is reached.

Differential Revision: https://reviews.llvm.org/D39890

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@317928 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-10 21:07:01 +00:00
Jonas Hahnfeld 67a8cd77e9 [OMPT] Purge OMPT_BLAME and OMPT_TRACE
This was replace by OMPT_OPTIONAL.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@317890 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-10 15:17:57 +00:00
Jonas Hahnfeld 3f9960d5d7 Add const to some variables to avoid const_casts
In these places the const attribute seems correct and doesn't
need any other change, so let's do it.

Differential Revision: https://reviews.llvm.org/D39756

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@317798 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-09 15:52:29 +00:00
Jonas Hahnfeld 11bae5e490 Remove const from variables with dynamic memory
Allocated memory is typically not 'const' if it needs to be freed.
This patch removes around 50 wrong const attributes, modifies the
corresponding functions and finally gets rid of some const_casts.
These have especially been strange for __kmp_str_fname_free() that
added a 'const' to call __kmp_str_free() which removed it again.

Two minor cleanups that I performed in this process:
 * __kmp_tool_libraries now lives in kmp_settings.cpp as it is
   used nowhere else.
 * __kmp_msg_empty was removed as it was never used and Clang
   now complained that it was assigned a string literal that
   is 'const char *'.

Differential Revision: https://reviews.llvm.org/D39755

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@317797 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-09 15:52:25 +00:00
Jonas Hahnfeld f0158dae29 [OMPT] Fix test cancel_parallel.c
If a parallel region is cancelled, execution resumes at the end
of the structured block. That is why this test cannot use the
"normal" macros that print right after inserting the label.
Instead it previously printed the addresses before the pragma
and swapped the checks compared to the other tests.

However, this does not work because FileChecks '*' is greedy
so that RETURN_ADDRESS always matched the second address. This
makes the test fail when an "overflow" occurrs and the first
address matches the value of codeptr_ra.

I discovered this on my MacBook but I'm unable to reproduce the
failure with the current version. Nevertheless we should fix this
problem to avoid that this test fails later after an unrelated change.

Differential Revision: https://reviews.llvm.org/D39708

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@317787 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-09 14:26:14 +00:00
Jonas Hahnfeld 8cf319e6de [OMPT] Add support for testing return addresses on POWER
Return addresses are determined based on the address of a label
that is inserted directly after a pragma / API call. In some cases
the tests can assume a known number of instructions between the
addresses. However, the instructions and their encoded lengths
depend on the target that the test is compiled on.

Firstly, this patch refactors the macro print_current_address() to
allow such target dependent modifications and adds information for
the observed instructions on POWER. Secondly, it adapts the related
macro print_fuzzy_address() to reuse much of "hacky" code and fixes
the used formatting strings in the printf() call. Finally, it also
adds documentation about how these macros are intended to work.

Differential Revision: https://reviews.llvm.org/D39699

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@317786 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-09 14:26:12 +00:00
Jonathan Peyton dc14379055 Cleanup version symbol macros and attributes/declspecs
1) Get rid of xaliasify, xexpand and xversionify for KMP_EXPAND_NAME and
KMP_VERSION_SYMBOL. KMP_VERSION_SYMBOL is a combination of xaliasify and
xversionify.

2) Put all attribute and __declspec definitions in kmp_os.h

Differential Revision: https://reviews.llvm.org/D39516


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@317636 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-07 23:32:13 +00:00
Jonas Hahnfeld e63fa83309 [OMPT] Fix null pointer in parallel/no_thread_num_clause.c
Looks like the implementation of printf on Darwin uses "0x0"
instead of "(nil)" like glibc does.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@317515 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-06 22:06:14 +00:00
Jonas Hahnfeld 6d785d31d8 [OMPT] Fix callback.h for tests for changes in TR6
This was also lost in the last commit.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@317484 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-06 15:13:06 +00:00
Jonas Hahnfeld 780ebd012d [OMPT] Improve cast that was lost on commit, NFC.
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@317480 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-06 14:33:09 +00:00
Joachim Protze 17015e8b68 Updating implementation of OMPT as specified in OpenMP 5.0 Preview 2 (TR6)
The TR6 document is expected to be publically released around November 15.
This patch does not implement OMPT for libomptarget.

Patch by Simon Convent and Joachim Protze

Differential Revision: https://reviews.llvm.org/D39182

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@317436 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-05 14:11:19 +00:00
Joachim Protze 28671628a4 Rename fields of ompt_frame_t
This is part of the renaming of data types from OpenMP TR4 to TR6

Patch by Simon Convent

Differential Revision: https://reviews.llvm.org/D39326

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@317435 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-05 14:11:10 +00:00
Jonas Hahnfeld 74248f8850 Revert "Rename fields of ompt_frame_t"
This reverts commit r317338 which discarded some recent commits.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@317347 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-03 18:28:25 +00:00
Jonas Hahnfeld ac062a9ef1 Revert "Updating implementation of OMPT as specified in OpenMP 5.0 Preview 2 (TR6)"
This reverts commit r317339 which discarded some recent commits.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@317346 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-03 18:28:19 +00:00
Joachim Protze 92e5a1069f Updating implementation of OMPT as specified in OpenMP 5.0 Preview 2 (TR6)
The TR6 document is expected to be publically released around November 15.
This patch does not implement OMPT for libomptarget.

Patch by Simon Convent and Joachim Protze

Differential Revision: https://reviews.llvm.org/D39182

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@317339 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-03 17:09:00 +00:00
Joachim Protze 1d2c9dccb9 Rename fields of ompt_frame_t
This is part of the renaming of data types from OpenMP TR4 to TR6

Patch by Simon Convent

Differential Revision: https://reviews.llvm.org/D39326

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@317338 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-03 17:08:40 +00:00
Jonas Hahnfeld f0ce92ef00 [libomptarget] Remove stale omp handle
This was never used in the upstream compiler and was responsible
for some problems with reductions in the clang-ykt fork.

Differential Revision: https://reviews.llvm.org/D39553

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@317214 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-02 15:59:51 +00:00
Jonathan Peyton 8f8a4cd5fa [OpenMP] Fix race condition in omp_init_lock
This is a partial fix for bug 34050.

This prevents callers of omp_set_lock (which does not hold __kmp_global_lock)
from ever seeing an uninitialized version of __kmp_i_lock_table.table.

It does not solve a use-after-free race condition if omp_set_lock obtains a
pointer to __kmp_i_lock_table.table before it is updated and then attempts to
dereference afterwards. That race is far less likely and can be handled in a
separate patch.

The unit test usually segfaults on the current trunk revision. It passes with
the patch.

Patch by Adam Azarchs

Differential Revision: https://reviews.llvm.org/D39439


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@317115 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-01 19:44:42 +00:00
Joachim Protze ff9d3f5109 Update implementation of OMPT to the specification OpenMP 5.0 Preview 1 (TR4).
The code is tested to work with latest clang, GNU and Intel compiler. The implementation
is optimized for low overhead when no tool is attached shifting the cost to execution with
tool attached.

This patch does not implement OMPT for libomptarget.

Patch by Simon Convent and Joachim Protze

Differential Revision: https://reviews.llvm.org/D38185

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@317085 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-01 10:08:30 +00:00
Joachim Protze 9bfe4eeb4f Test commit: sort names in CREDITS.txt
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@316922 91177308-0d34-0410-b5e6-96231b3b80d8
2017-10-30 16:44:00 +00:00
Jonathan Peyton 8c08442bf9 Fix fatal error message displaying
Replacing call to __kmp_msg(kmp_ms_fatal,...) with __kmp_fatal(...) caused an
issue when incomplete message is displayed in case an error message is followed
by another message (e.g. by a hint messa)ge. This is because __kmp_fatal()
passes incomplete list of arguments to __kmp_msg().

Patch by Olga Malysheva

Differential Revision: https://reviews.llvm.org/D39248


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@316623 91177308-0d34-0410-b5e6-96231b3b80d8
2017-10-25 22:05:02 +00:00
Jonathan Peyton 1d955d1acf Disable threadprivate data cleanup if runtime is terminating
The problem is due to the runtime's threadprivate cleanup code which tries to
access data that was already destroyed by one of the root threads.
__kmp_init_gtid is used as a checker here since it is set to false before actual
resource cleanup is done in __kmp_cleanup().

Patch by Hansang Bae


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@316452 91177308-0d34-0410-b5e6-96231b3b80d8
2017-10-24 16:10:09 +00:00
Jonathan Peyton 32c445b643 Restrict OMPT to OpenMP version 5.0 and remove old header files
Patch by Simon Convent

Differential Revision: https://reviews.llvm.org/D38876


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@316234 91177308-0d34-0410-b5e6-96231b3b80d8
2017-10-20 20:14:46 +00:00
Jonathan Peyton 1a34e9fe02 Add license envirable for testing Intel compilers
Patch by Simon Convent

Differential Revision: https://reviews.llvm.org/D38881


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@316232 91177308-0d34-0410-b5e6-96231b3b80d8
2017-10-20 19:45:43 +00:00
Jonathan Peyton fc64699438 Add C++ support for testcases
Patch by Simon Convent

Differential Revision: https://reviews.llvm.org/D38878


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@316230 91177308-0d34-0410-b5e6-96231b3b80d8
2017-10-20 19:42:32 +00:00
Jonathan Peyton be524d6135 Apply formatting changes
.clang-format's comments are removed and a (hopefully) final
set of formatting changes are applied.

Differential Revision: https://reviews.llvm.org/D38837
Differential Revision: https://reviews.llvm.org/D38920


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@316227 91177308-0d34-0410-b5e6-96231b3b80d8
2017-10-20 19:30:57 +00:00
Jonathan Peyton c376c2708f KMP_HW_SUBSET vs KMP_PLACE_THREADS rival envirables fix
If both KMP_HW_SUBSET and KMP_PLACE_THREADS are set and KMP_PLACE_THREADS gets
parsed first, then the current environment variable parser rejects both and
neither get used. This patch uses the rivals mechanism that is used for other
environment variable groups (e.g., KMP_STACKSIZE, GOMP_STACKSIZE, OMP_STACKSIZE).
If both are set, then it tells the user that it is ignoring KMP_PLACE_THREADS in
favor of KMP_HW_SUBSET. The message about deprecating KMP_PLACE_THREADS when it
is set is still printed regardless.

Differential Revision: https://reviews.llvm.org/D38292


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@315091 91177308-0d34-0410-b5e6-96231b3b80d8
2017-10-06 19:23:19 +00:00
Jonas Hahnfeld 7635c9dd1f [test] Fix uninitialized memory in omp_taskloop_grainsize.c
result was never initialized to zero which sometimes failed the test.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@314513 91177308-0d34-0410-b5e6-96231b3b80d8
2017-09-29 13:53:03 +00:00
Jonathan Peyton 5b33aeb207 Remove unnecessary semicolons
Removes semicolons after if {} blocks, function definitions, etc.
I was able to apply the large OMPT patch cleanly on top of this one
with no conflicts.


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@314340 91177308-0d34-0410-b5e6-96231b3b80d8
2017-09-27 20:36:27 +00:00
Jonathan Peyton 1957e1bc23 Allow printing of KMP_TOPOLOGY_METHOD when KMP_SETTINGS=true
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@314243 91177308-0d34-0410-b5e6-96231b3b80d8
2017-09-26 20:33:53 +00:00
Jonathan Peyton af6ac33754 Remove unused t_single_lock
Add padding inside team structure to keep same structure size.


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@314242 91177308-0d34-0410-b5e6-96231b3b80d8
2017-09-26 20:12:16 +00:00
Jonathan Peyton 31535f3451 Read blocktime value set by kmp_set_blocktime() before reading from KMP_BLOCKTIME
Patch by Hansang Bae

Differential Revision: https://reviews.llvm.org/D37403


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@312539 91177308-0d34-0410-b5e6-96231b3b80d8
2017-09-05 15:45:48 +00:00
Jonathan Peyton e945cccc7e Minor code cleanup of Klocwork issues
Minor code cleanup of Klocwork issues. Fatal messages are given no return
attribute. Define and use KMP_NORETURN to work for multiple C++ versions.

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D37275


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@312538 91177308-0d34-0410-b5e6-96231b3b80d8
2017-09-05 15:43:58 +00:00
Jonathan Peyton 5b2e14f0fe Use va_copy instead of __va_copy to fix building libomp against musl libc
Fixes https://bugs.llvm.org/show_bug.cgi?id=34040

Patch by Peter Levine

Differential Revision: https://reviews.llvm.org/D36343


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@311269 91177308-0d34-0410-b5e6-96231b3b80d8
2017-08-19 23:53:36 +00:00
Jonathan Peyton f4926388d0 Remove BUILD_TV
Cleanup code to remove BUILD_TV and unused code bracketed by it.

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D36011


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@311114 91177308-0d34-0410-b5e6-96231b3b80d8
2017-08-17 19:09:28 +00:00
Sergey Dmitriev 995b870acd [OpenMP] libomptarget: move debugging dumps under control of env var LIBOMPTARGET_DEBUG
Disable default debugging dumps for libomptarget and plugins and move dumps
under control of environment variable LIBOMPTARGET_DEBUG=<integer>. Dumps
are enabled when LIBOMPTARGET_DEBUG is set to a positive integer value.

Debugging dumps are available only in debug build; release build does not
support it.

Differential Revision: https://reviews.llvm.org/D33227


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@310841 91177308-0d34-0410-b5e6-96231b3b80d8
2017-08-14 15:09:59 +00:00
Paul Osmialowski 521c639c91 OMP_PROC_BIND: better spread
This change improves the way threads are spread across cores
when OMP_PROC_BIND=spread is set and no unusual affinity masks are in use.

Differential Revision: https://reviews.llvm.org/D36510

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@310670 91177308-0d34-0410-b5e6-96231b3b80d8
2017-08-10 23:04:11 +00:00
Jonathan Peyton bb3cd67f38 Exclude version symbols for static libomp
We use symbol versioning for GNU-compatibility but libgomp has versioned symbols
only in the shared library but not in the static.
Moreover, version symbols in the static library can cause an error at link time.

Patch by Olga Malysheva

Differential Revision: https://reviews.llvm.org/D36225


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@309877 91177308-0d34-0410-b5e6-96231b3b80d8
2017-08-02 20:10:00 +00:00
Jonathan Peyton 5321a36544 Move lock acquire/release functions in task deque cleanup code
The original locations can be reached without initializing the lock variable
(td_deque_lock), so it is potentially unsafe.  It is guaranteed that the lock
is initialized if the deque (td_deque) is not NULL, and lock functions can be
safely called.

Patch by Hansang Bae

Differential Revision: https://reviews.llvm.org/D36017


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@309875 91177308-0d34-0410-b5e6-96231b3b80d8
2017-08-02 20:06:32 +00:00
Jonathan Peyton ec81ddf65a Add new envirable KMP_TEAMS_THREAD_LIMIT
This change adds a new environment variable, KMP_TEAMS_THREAD_LIMIT, which is
used to set a new global variable, __kmp_teams_max_nth, which is checked when
determining the size and quantity of teams that will be created in the teams
construct. Specifically, it is a limit on the total number of threads in a given
teams construct. It differentiates the limits for the teams construct from the
limits for regular parallel regions (KMP_DEVICE_THREAD_LIMIT/__kmp_max_nth and
OMP_THREAD_LIMIT/__kmp_cg_max_nth). When each individual team is formed, it is
still subject to those limits. After the clauses to the teams construct are
parsed and calculated, we check to make sure we are within this limit, and if
not, reduce num_threads per team and/or number of teams, accordingly. The
default value is set to the number of available processors on the system.

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D36009


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@309874 91177308-0d34-0410-b5e6-96231b3b80d8
2017-08-02 20:04:45 +00:00
Jonathan Peyton 864fc14ee6 Fix comments and build messages concerning TSX
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@309418 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-28 19:05:17 +00:00
Jonathan Peyton 12f81b0f7c Fix implementation of OMP_THREAD_LIMIT
This change fixes the implementation of OMP_THREAD_LIMIT. The implementation of
this previously was not restricted to a contention group (but it should be,
according to the spec), and this is fixed here. A field is added to root thread
to store a counter of the threads in the contention group. An extra check is
added when reserving threads for a parallel region that checks this variable and
compares to threadlimit-var, which is implemented as a new global variable,
kmp_cg_max_nth. Associated settings changes were also made, and clean up of
comments that referred to OMP_THREAD_LIMIT, but should refer to the new
KMP_DEVICE_THREAD_LIMIT (added in an earlier patch).

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D35912


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@309319 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-27 20:58:41 +00:00
Jonathan Peyton c701446276 Introduce KMP_DEVICE_THREAD_LIMIT
This change drops in KMP_DEVICE_THREAD_LIMIT to replace KMP_MAX_THREADS. It's
possible there will eventually be a OMP_DEVICE_THREAD_LIMIT, and we need
something to distinguish from OMP_THREAD_LIMIT, which is currently implemented
incorrectly (the fix for that will be added soon in a separate patch).
KMP_ALL_THREADS is deprecated here, but we can keep the "all" option on
KMP_DEVICE_THREAD_LIMIT to support that functionality. KMP_DEVICE_THREAD_LIMIT
now has priority over its deprecated rival KMP_ALL_THREADS. I also cleaned up
some comments that incorrectly referred to non-existent kmp_max_threads variable
instead of kmp_max_nth.

I've left the name of where this setting eventually ends up as
__kmp_max_nth, for now.

This change does not change much in the way of functionality. It does NOT change
OMP_THREAD_LIMIT. It's just cleaning up and setting up for that.

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D35860


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@309168 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-26 20:07:58 +00:00
Jonas Hahnfeld 9dc1cc959a [CMake] Disable building libomptarget and add CMake switch
Introduce OPENMP_ENABLE_LIBOMPTARGET which defaults to OFF at the moment.

libomptarget is not yet ready for prime time:
 - Offloading to NVIDIA GPUs is not completed yet (compiler, device RTL)
 - The generic ELF plugin for offloading to the host (meant for testing)
   uses a single instance of the OpenMP runtime (libomp). That is why
   omp_is_initial_device() returns 1 which makes the tests fail.
Because of these reasons, we want to disable building (and testing!)
for release 5.0.

See https://bugs.llvm.org/show_bug.cgi?id=33859

Differential Revision: https://reviews.llvm.org/D35719

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@309115 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-26 13:55:00 +00:00
Jonathan Peyton 57d1ed03db Cleanup: __kmp_env_* variables
Removed unused __kmp_env_* variables. Also clangified other people's code.

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D35808


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@309000 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-25 18:20:16 +00:00
NAKAMURA Takumi a37b659927 Whitespace.
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@308693 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-20 23:12:39 +00:00
Andrey Churbanov 8072ba12e0 OpenMP RTL cleanup: two PAUSEs per spin loop iteration replaced with single one
Differential Revision: https://reviews.llvm.org/D35490


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@308423 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-19 09:26:13 +00:00
Dimitry Andric 4efa4a63cf For KMP_PAGE_SIZE, use getpagesize() on Unix, GetSystemInfo() on Windows
Summary:
The kmp_os.h header is defining the `PAGE_SIZE` macro unconditionally,
even while it is only used directly after its definition, for the
Windows implementation of the `KMP_GET_PAGE_SIZE()` macro.

On at least FreeBSD, but likely all other BSDs too, this macro conflicts
with the one defined in system headers, so remove it, since nothing else
uses it.  Make all Unixes use `getpagesize()` instead, and use
`GetSystemInfo()` for the Windows case.

Reviewers: jlpeyton, jcownie, emaste, AndreyChurbanov

Reviewed By: AndreyChurbanov

Subscribers: AndreyChurbanov, hfinkel, zturner

Differential Revision: https://reviews.llvm.org/D35072


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@308355 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-18 20:31:19 +00:00
Jonathan Peyton a07d8b0a66 Fix failing taskloop tests by omitting gcc
We do not have GOMP interface support for taskloop yet.


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@308351 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-18 20:16:25 +00:00
Jonathan Peyton 92f7b797ee Add recursive task scheduling strategy to taskloop implementation
Summary:
Taskloop implementation is extended by using recursive task scheduling.
Envirable KMP_TASKLOOP_MIN_TASKS added as a manual threshold for the user
to switch from recursive to linear tasks scheduling.

Details:
* The calculations for the loop parameters are moved from __kmp_taskloop_linear
  upper level
* Initial calculation is done in the __kmpc_taskloop, further range splitting
  is done in the __kmp_taskloop_recur.
* Added threshold to switch from recursive to linear tasks scheduling;
* One half of split range is scheduled as an internal task which just moves
  sub-range parameters to the stealing thread that continues recursive
  scheduling (if number of tasks still enough), the other half is processed
  recursively;
* Internal task duplication routine fixed to assign parent task, that was not
  needed when all tasks were scheduled by same thread, but is needed now.

Patch by Andrey Churbanov

Differential Revision: https://reviews.llvm.org/D35273


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@308338 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-18 18:50:13 +00:00
Andrey Churbanov 4c2424f72c Fix sporadic segfaults in tasking tests.
Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D35535


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@308298 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-18 11:56:16 +00:00
Andrey Churbanov dd87e37353 OpenMP RTL cleanup: nullify pointer after memory freeing
Differential Revision: https://reviews.llvm.org/D35497


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@308274 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-18 08:30:03 +00:00
Jonathan Peyton 3b5852c6a1 Removed "duplicates" from verbose affinity output
The internal details of this setting are not meant to be user visible and only create confusion.

Differential Revision: https://reviews.llvm.org/D35269


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@308189 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-17 17:06:43 +00:00
Andrey Churbanov b88a01f4ef OpenMP RTL cleanup: eliminated warnings with -Wcast-qual, patch 2.
Changes are: got all atomics to accept volatile pointers that allowed
to simplify many type conversions. Windows specific code fixed correspondingly.

Differential Revision: https://reviews.llvm.org/D35417


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@308164 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-17 09:03:14 +00:00
Jonas Hahnfeld 53e0c92a88 [GOMP] Fix (un)tied tasks with the GCC
The first bit is actually the "untied" flag. That is why the condition was
wrong and has to be inverted to set the flag correctly.

Found and initial patch by Simon Convent!

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@307899 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-13 10:38:11 +00:00
Dimitry Andric 4d238bda09 Rename z_Linux_asm.s to z_Linux_asm.S
Summary:
On Unix, a .S file is normally an assembly source which must be
preprocessed with a C preprocessor, while a .s file is "plain" assembly.
The former is handled by the compiler driver (cc), the latter is
directly passed to the assembler binary (as).

Because z_Linux_asm.s is supposed to be preprocessed, rename it to .S,
so it can be automatically picked up correctly by build systems.

Reviewers: AndreyChurbanov, emaste, jlpeyton

Reviewed By: AndreyChurbanov

Subscribers: mgorny, openmp-commits

Differential Revision: https://reviews.llvm.org/D35171

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@307680 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-11 18:04:56 +00:00
Dimitry Andric 0a8f95d15f Add a .arcconfig file for openmp.
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@307474 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-08 16:09:47 +00:00
Ed Maste 06426cf363 remove deprecated register storage class specifier
While importing libomp into the FreeBSD base system we encountered
Clang warnings that "'register' storage class specifier is deprecated
and incompatible with C++1z [-Wdeprecated-register]".

Differential Revision:	https://reviews.llvm.org/D35124


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@307441 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-07 21:06:05 +00:00
Ed Maste 597a305494 remove duplicate symbol version script entries
GNU ld ignores duplicates, but lld produces a warning.

Differential Revision:	https://reviews.llvm.org/D35121


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@307399 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-07 13:45:41 +00:00
Jonathan Peyton 3c37ab915c Fix wrong website in messages
Address user message bug where the messages were sending users to Intel's
website instead of the LLVM OpenMP runtime websites.

Bugzilla: https://bugs.llvm.org/show_bug.cgi?id=32892

Differential Revision: https://reviews.llvm.org/D35018


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@307206 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-05 22:01:05 +00:00
Andrey Churbanov 1c31fdada0 OpenMP RTL cleanup: eliminated warnings with -Wcast-qual.
Changes are: replaced C-style casts with cons_cast and reinterpret_cast;
type of several counters changed to signed; type of parameters of 32-bit and
64-bit AND and OR intrinsics changes to unsigned; changed files formatted
using clang-format version 3.8.1.

Differential Revision: https://reviews.llvm.org/D34759


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@307020 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-03 11:24:08 +00:00
Hal Finkel 5e8afb8077 Make test/parallel/omp_nested.c not use so many threads
I've found it very difficult to get test/parallel/omp_nested.c to pass
consistently across my build environments. The problem is that it creates N^2
threads (it is testing nested parallel regions), and that often exceeds the
thread limits on systems with many cores. We do raise the process limits in
lit, and that often helps, but if running lit with a smaller number of threads
or on a system where we're otherwise resource constrained, this particular test
tends to fail (because the runtime cannot create a sufficient number of
threads).

This seems to work: if the maximum number of threads is more than some small
number, then cap the number of threads used for the parallel region. The choice
of 4 here is somewhat arbitrary.

Differential Revision: https://reviews.llvm.org/D32033

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@306357 91177308-0d34-0410-b5e6-96231b3b80d8
2017-06-27 03:04:25 +00:00
Dimitry Andric 6943fc62c3 Only use libdl when it is available
Summary: On BSDs, there is no `libdl.so`, and functions like `dlopen`
are implemented in the main C library instead.  Use the `CMAKE_DL_LIBS`
variable instead of hardcoding a dependency on the `dl` library.

Reviewers: grokos, joerg, emaste

Reviewed By: emaste

Subscribers: jlpeyton, mgorny, openmp-commits

Differential Revision: https://reviews.llvm.org/D34632


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@306319 91177308-0d34-0410-b5e6-96231b3b80d8
2017-06-26 19:16:49 +00:00
Jonathan Peyton 862483e622 Set affinity to none/false in child processes
Reset affinity to none (false for proc-bind-var) so that threads in the child
processes are not bound tightly, unless the user explicitly sets this in
KMP_AFFINITY/OMP_PROC_BIND, in child processes. This can improve
performance for scripting languages which fork for parallelism like Python's
multiprocessing module.

Differential Revision: https://reviews.llvm.org/D34154


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@305513 91177308-0d34-0410-b5e6-96231b3b80d8
2017-06-15 21:51:07 +00:00
Jonathan Peyton 8924d7386a Replace platform macro with KMP_MIC_SUPPORTED
Differential Revision: https://reviews.llvm.org/D34119


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@305307 91177308-0d34-0410-b5e6-96231b3b80d8
2017-06-13 17:17:26 +00:00
Jonathan Peyton a8b80af9fc Reset initial affinity in children processes
If OpenMP is initialized before fork()-ing occurs and affinity is set to
something like compact, then the master thread will be pinned to a single HW
thread/core after initialization. If the master (or any other thread) then
forks N processes, all N processes will then be pinned to that same single HW
thread/core. To reset the affinity for the new child process, the atfork
handler for the child process can call kmp_set_thread_affinity_mask_initial()
to reset its affinity to the initial affinity of the application before it
re-initializes libomp. The parent process will not be affected and still
keeps its affinity setting.

Differential Revision: https://reviews.llvm.org/D34118


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@305306 91177308-0d34-0410-b5e6-96231b3b80d8
2017-06-13 17:16:12 +00:00
Samuel Antao 4bdc9afa72 [OpenMP] Prevent unused-variable warning in libomptarget when compiling in Release mode.
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@305090 91177308-0d34-0410-b5e6-96231b3b80d8
2017-06-09 16:46:07 +00:00
Jonathan Peyton 84e84f8bb4 Fix static initializers for locks.
Fix static initializers to use the proper unlocked value for the poll
field of the tas and futex locks.

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D33794


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@304828 91177308-0d34-0410-b5e6-96231b3b80d8
2017-06-06 20:24:41 +00:00
Andrey Churbanov 2b5580f57b OpenMP 4.5: implemented support of schedule(simd:guided) and
schedule(simd:runtime) - library part. Compiler generation should use newly
introduced scheduling kinds kmp_sch_guided_simd = 46, kmp_sch_runtime_simd = 47,
as parameters to __kmpc_dispatch_init_* entries.

Differential Revision: https://reviews.llvm.org/D31602


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@304724 91177308-0d34-0410-b5e6-96231b3b80d8
2017-06-05 17:17:33 +00:00
George Rokos d2cb509fa4 [OpenMP] libomptarget: eliminate compiler warnings at build
Thanks to Sergey Dmitriev for submitting the patch.

Differential Revision: https://reviews.llvm.org/D33851



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@304601 91177308-0d34-0410-b5e6-96231b3b80d8
2017-06-02 22:41:35 +00:00
Andrey Churbanov 20fe9e7270 Re-enable assertion after the problem that caused it to be hit had been fixed
Differential Revision: https://reviews.llvm.org/D31421


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@304443 91177308-0d34-0410-b5e6-96231b3b80d8
2017-06-01 18:10:45 +00:00
Jonathan Peyton fcec73a508 Fix minor formatting issues
Some code was restructured to move it under KMP_DEBUG.  The rest is
formatting changes to fix some things broken by clang-format

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D33744


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@304438 91177308-0d34-0410-b5e6-96231b3b80d8
2017-06-01 16:46:36 +00:00
Jonathan Peyton e60f480d75 Fix for KMP_AFFINITY=disabled and KMP_TOPOLOGY_METHOD=hwloc
With these settings, the create_hwloc_map() method was being called causing an
assert(). After some consideration, it was determined that disabling affinity
explicitly should just disable hwloc as well. i.e., KMP_AFFINITY overrides
KMP_TOPOLOGY_METHOD. This lets the user know that the Hwloc mechanism is being
ignored when KMP_AFFINITY=disabled.

Differential Revision: https://reviews.llvm.org/D33208


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@304344 91177308-0d34-0410-b5e6-96231b3b80d8
2017-05-31 20:35:22 +00:00
Jonathan Peyton 50a02e790e Address default pinning OpenMP process with multiple processor groups
This change checks if the initial affinity mask is equal to exactly one
Windows processor group's affinity mask. If it is, then the code does not
respect the initial affinity mask and uses the entire machine instead.
The reasoning behind this is that, by default, Windows assigns exactly one
processor group as the initial affinity mask even when there are multiple
Windows processor groups available. User's typically want to use the whole
machine, so we ignore this special case and use the entire machine.

If the initial affinity mask is a proper subset of one group, or spans multiple
groups, then the initial affinity mask is respected since we can assume that the
operating system did not assign this initial affinity mask. This change only
affects machines with multiple processor groups

Differential Revision: https://reviews.llvm.org/D33210


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@304343 91177308-0d34-0410-b5e6-96231b3b80d8
2017-05-31 20:33:56 +00:00
Jonathan Peyton e4c0f2b8d3 Fix for KMP_AFFINITY=respect with multiple processor groups
An assert() was being tripped when KMP_AFFINITY=respect + Multiple Processor
Groups. Let __kmp_affinity_create_proc_group_map() function be able to create
address2os object which contains a single group by deleting restriction that
process affinity mask must span multiple groups.


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@303101 91177308-0d34-0410-b5e6-96231b3b80d8
2017-05-15 19:05:59 +00:00
Jonathan Peyton c2f4638c23 Remove some outdated comments
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@303086 91177308-0d34-0410-b5e6-96231b3b80d8
2017-05-15 17:39:16 +00:00
Jonathan Peyton ac4f9700a7 Add the .clang-format file which the formatting was based on
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@303079 91177308-0d34-0410-b5e6-96231b3b80d8
2017-05-15 16:39:42 +00:00
Jonathan Peyton e703e783e7 Clang-format and whitespace cleanup of source code
This patch contains the clang-format and cleanup of the entire code base. Some
of clang-formats changes made the code look worse in places. A best effort was
made to resolve the bulk of these problems, but many remain. Most of the
problems were mangling line-breaks and tabbing of comments.

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D32659


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@302929 91177308-0d34-0410-b5e6-96231b3b80d8
2017-05-12 18:01:32 +00:00
George Rokos 07c5582c3b [OpenMP] Changes in the plugin interface
This patch chagnes the plugin interface so that:
1) future plugins can take advantage of systems with shared CPU/device storage
2) instead of using base addresses, target regions are launched by providing target addresseds and base offsets explicitly.

Differential revision: https://reviews.llvm.org/D33028
 


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@302663 91177308-0d34-0410-b5e6-96231b3b80d8
2017-05-10 14:12:36 +00:00
George Rokos 1a189314bd [OpenMP] libomptarget: test correction for use with OpenMP 4.5
Differential Revision: https://reviews.llvm.org/D32562

Thanks to Sergey Dmitriev for submitting the patch.



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@301577 91177308-0d34-0410-b5e6-96231b3b80d8
2017-04-27 18:54:00 +00:00
Jonathan Peyton 81a7c91728 Fix Hwloc API Incompatibility
Older Hwloc libraries (< 1.10.0) don't offer the HWLOC_OBJ_NUMANODE nor
HWLOC_OBJ_PACKAGE types. Instead they are named HWLOC_OBJ_NODE and
HWLOC_OBJ_SOCKET instead. This patch just defines the newer names based on
the older names when using an older Hwloc.

Differential Revision: https://reviews.llvm.org/D32496


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@301349 91177308-0d34-0410-b5e6-96231b3b80d8
2017-04-25 19:04:07 +00:00
George Rokos 23f1ee8d87 [OpenMP] Optimized default kernel launch parameters in CUDA plugin
Differential Revision: https://reviews.llvm.org/D32321



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@301321 91177308-0d34-0410-b5e6-96231b3b80d8
2017-04-25 16:34:13 +00:00
George Rokos 079ec52a07 [OpenMP] Add missing parenthesis which triggers a compile error
Differential Revision: https://reviews.llvm.org/D32490



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@301318 91177308-0d34-0410-b5e6-96231b3b80d8
2017-04-25 15:55:39 +00:00
George Rokos 1eb73292d2 [OpenMP] libomptarget: Set ref count for global objects to positive infinity
Differential Revision: https://reviews.llvm.org/D32326



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@301076 91177308-0d34-0410-b5e6-96231b3b80d8
2017-04-22 11:45:03 +00:00
George Rokos 305e440c56 [OpenMP] libomptarget: Remove obsolete negative device IDs -2/-3
Differential Revision: https://reviews.llvm.org/D32325



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@301075 91177308-0d34-0410-b5e6-96231b3b80d8
2017-04-22 11:21:54 +00:00
George Rokos f07924fd3f [OpenMP] Run libomptarget regression tests using all available system threads.
Differential Revision: https://reviews.llvm.org/D32327



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@301074 91177308-0d34-0410-b5e6-96231b3b80d8
2017-04-22 11:20:20 +00:00
Andrey Churbanov ef71bbcce4 Fix crash in invoking microtask on ios arm64.
Patch by Ni Hui.

Differential Revision: https://reviews.llvm.org/D31923


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@300448 91177308-0d34-0410-b5e6-96231b3b80d8
2017-04-17 11:58:20 +00:00
Andrey Churbanov 9a49cce023 KMP_HW_SUBSET extended with NUMA support when HWLOC enabled
Differential Revision: https://reviews.llvm.org/D31600


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@300220 91177308-0d34-0410-b5e6-96231b3b80d8
2017-04-13 17:15:07 +00:00
Olga Malysheva fa50db79c4 Test cancellation_for_sections.c expectedly fails on GCC
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@299437 91177308-0d34-0410-b5e6-96231b3b80d8
2017-04-04 14:39:52 +00:00
Olga Malysheva b8b75f9476 Reset cancellation status for 'parallel', 'sections' and 'for' constracts.
Without this fix cancellation status for parallel, sections and for persists 
across construct boundaries.

Differential Revision: https://reviews.llvm.org/D31419

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@299434 91177308-0d34-0410-b5e6-96231b3b80d8
2017-04-04 13:56:50 +00:00
Olga Malysheva c75321c16f Test check-in, comment changed
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@299428 91177308-0d34-0410-b5e6-96231b3b80d8
2017-04-04 12:56:55 +00:00
Andrey Churbanov e3e3d228fe Fix for bug https://llvm.org/bugs/show_bug.cgi?id=32456
ITT Notify disabled for static build of OpenMP RTL.

Differential Revision: https://reviews.llvm.org/D31466


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@299230 91177308-0d34-0410-b5e6-96231b3b80d8
2017-03-31 16:20:07 +00:00
Andrey Churbanov ea09034b77 Fix for bug https://llvm.org/bugs/show_bug.cgi?id=30889
Condition adjusted for Debug assertion.

Differential Revision: https://reviews.llvm.org/D29638


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@298915 91177308-0d34-0410-b5e6-96231b3b80d8
2017-03-28 13:35:42 +00:00
Paul Osmialowski b78659393e GOMP compatibility: add missing OpenMP4.0 task deps handling code
Differential Revision: https://reviews.llvm.org/D31071

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@298605 91177308-0d34-0410-b5e6-96231b3b80d8
2017-03-23 15:03:17 +00:00
George Rokos 3a5a5198c0 [OpenMP] CUDA plugin: More descriptive error messages
Differential Revision: https://reviews.llvm.org/D31206



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@298527 91177308-0d34-0410-b5e6-96231b3b80d8
2017-03-22 17:36:22 +00:00
George Rokos c5cb0abc91 [OpenMP] Allow multiple weak symbols to be loaded from the fat binary
For compatibility with Fortran.

Differential Revision: https://reviews.llvm.org/D31205



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@298516 91177308-0d34-0410-b5e6-96231b3b80d8
2017-03-22 16:43:40 +00:00
George Rokos 1c2799754b [OpenMP] CUDA plugin: add include directory for libelf
Allow the user to manually specify where libelf is installed.

Differential Revision: https://reviews.llvm.org/D31207



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@298515 91177308-0d34-0410-b5e6-96231b3b80d8
2017-03-22 16:41:46 +00:00
George Rokos c79f0d5955 [OpenMP] libomptarget: Disable on MacOS X
Disable compilation of libomptarget on MacOS X.

Differential Revision: https://reviews.llvm.org/D31055



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@298411 91177308-0d34-0410-b5e6-96231b3b80d8
2017-03-21 18:19:09 +00:00
Andrey Churbanov e70eb2bba4 Fixed intermittent hang on tests with "target teams if(0)" construct with no parallel inside.
Differential Revision: https://reviews.llvm.org/D29597


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@298373 91177308-0d34-0410-b5e6-96231b3b80d8
2017-03-21 13:48:52 +00:00
Andrey Churbanov 17fe17487c Stride in distribute parallel for loops with no chunk size.
Patch by George Rokos.

Differential Revision: https://reviews.llvm.org/D24486


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@298362 91177308-0d34-0410-b5e6-96231b3b80d8
2017-03-21 12:17:22 +00:00
Jonathan Peyton 6168925936 Minor improvement of KMP_YIELD_NOW() macro.
This change slightly improves performance of KMP_YIELD_NOW() macro, by using
_rdtsc() intrinsic function if possible.

Patch by Hansang Bae

Differential Revision: https://reviews.llvm.org/D31008


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@298314 91177308-0d34-0410-b5e6-96231b3b80d8
2017-03-20 22:11:31 +00:00
Jonathan Peyton d2a2afc3d4 Fix incorrect initial value of __kmp_affinity_type.
Affinity initialization code expects __kmp_affinity_type has the value
affinity_default by default, but the cleanup code does not properly set the
value back to affinity_default.  This may introduce some issues when multiple
roots are trying to initialize/uninitialize the runtime successively.

Patch by Hansang Bae

Differential Revision: https://reviews.llvm.org/D31012


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@298313 91177308-0d34-0410-b5e6-96231b3b80d8
2017-03-20 22:04:02 +00:00
Andrey Churbanov 96b04de80a Create a git ignore file for openmp runtime.
Patch by Guansong Zhang.

Differential Revision: https://reviews.llvm.org/D30784


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@297562 91177308-0d34-0410-b5e6-96231b3b80d8
2017-03-11 13:05:08 +00:00
Jonathan Peyton b61de7c64a Fix assertion failure when 'proclist' is used without 'explicit' in KMP_AFFINITY
This change fixes an assertion failure the in case KMP_AFFINITY is set with
'proclist' specified but without 'explicit'
e.g., KMP_AFFINITY=verbose,proclist=[0-31]

Patch by Olga Malysheva

Differential Revision: https://reviews.llvm.org/D30404


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@297480 91177308-0d34-0410-b5e6-96231b3b80d8
2017-03-10 17:22:47 +00:00
Dan Albert bff1acca47 Fix GNU strerror_r check for Android.
Summary:
Bionic didn't get a GNU style strerror_r until Android M. Until then
we unconditionally exposed the POSIX one. Expand the check to account
for this.

Reviewers: pirama, AndreyChurbanov, jlpeyton

Reviewed By: jlpeyton

Subscribers: openmp-commits, srhines

Differential Revision: https://reviews.llvm.org/D30056

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@297235 91177308-0d34-0410-b5e6-96231b3b80d8
2017-03-07 22:18:05 +00:00
Jonathan Peyton d3acdf9c86 OpenMP version 5.0 added
Add build option LIBOMP_OMP_VERSION=50, 5.0 headers, and add the year/month
associated with OpenMP 5.0 in relevant source locations. Also, remove the
deprecated LIBOMP_OMP_VERSION=41 option.

Patch by Olga Malysheva

Differential Revision: https://reviews.llvm.org/D30450


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@297083 91177308-0d34-0410-b5e6-96231b3b80d8
2017-03-06 22:07:40 +00:00
Jonathan Peyton 14e93081b9 Mixed type atomic routines added to Windows DLL
Patch by Olga Malysheva

Differential Revision: https://reviews.llvm.org/D30408


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@297082 91177308-0d34-0410-b5e6-96231b3b80d8
2017-03-06 21:46:36 +00:00
Paul Osmialowski fb0f861623 Add AArch64 support.
This adds AArch64 support to recently added part of the runtime responsible for offloading to target. This piece of code allows offloading-to-self on AArch64 machines.

Differential Revision: https://reviews.llvm.org/D30644

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@297070 91177308-0d34-0410-b5e6-96231b3b80d8
2017-03-06 21:00:07 +00:00
Jonathan Peyton c80d301009 Removing couple unnecessary architecture guards.
This section of code (__kmp_test_then_* functions) is guarded by
(KMP_ARCH_X86 || KMP_ARCH_X86_64) so it does not make sense to have other
architecture guards inside this section.  Non-x86 architectures always
use intrinsics (__sync_*)


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@296525 91177308-0d34-0410-b5e6-96231b3b80d8
2017-02-28 21:43:28 +00:00
Michal Gorny 7bd7063524 [test] Try to link -latomic to provide atomics when available
When using -rtlib=libgcc, the fallback implementation of __atomic_*
builtins is provided via libatomic (included in GCC). However, neither
GCC itself nor clang link libatomic implicitly, and it seems that GCC
upstream expects projects to link it explicitly as necessary.

Since compiler-rt provides __atomic_* builtins directly in the main
library, check if they are provided by the default libraries first.
If they are not, check if -latomic is available to provide them
and add explicit -latomic for tests in this case.

This fixes unresolved __atomic_load() references when running openmp
tests on i386 with libgcc backend.

Differential Revision: https://reviews.llvm.org/D30083

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@296183 91177308-0d34-0410-b5e6-96231b3b80d8
2017-02-24 22:15:24 +00:00
George Rokos b2806f6cc0 [OpenMP] Missing virtual destructor in KMPAffinity
Added virtual destructor in a class containing virtual functions.

Differential Revision: https://reviews.llvm.org/D30271



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@295896 91177308-0d34-0410-b5e6-96231b3b80d8
2017-02-22 22:50:28 +00:00
Jonathan Peyton 9c1e6c9bc1 [stats] add stats-gathering for static_steal scheduling method
Add counter to count number of static_steal for loops
Add counter for number of chunks executed per static_steal for loop
Add counter for number of chunks stolen per static_steal for loop


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@295461 91177308-0d34-0410-b5e6-96231b3b80d8
2017-02-17 17:06:16 +00:00
Andrey Churbanov 0f00053d19 Run-time library part of OpenMP 5.0 task reduction implementation.
Added test kmp_task_reduction_nest.cpp which has an example of
possible compiler codegen.

Differential Revision: https://reviews.llvm.org/D29600


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@295343 91177308-0d34-0410-b5e6-96231b3b80d8
2017-02-16 17:49:49 +00:00
Andrey Churbanov 8f2e239462 Added an option to bind initial thread at the start of application
via setting envirable KMP_INITIAL_THREAD_BIND=1.

Differential Revision: https://reviews.llvm.org/D29665


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@295339 91177308-0d34-0410-b5e6-96231b3b80d8
2017-02-16 17:08:40 +00:00
George Rokos c40fa62243 [OpenMP] libomptarget: Protect parent struct from being deallocated
Fixed bug due to which a parent struct was deallocated when one of the struct's pointers was being unmapped.

Differential Revision: https://reviews.llvm.org/D29914



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@295231 91177308-0d34-0410-b5e6-96231b3b80d8
2017-02-15 20:45:37 +00:00
Jonathan Peyton 1aaa414753 Enable yield cycle on Linux
This change allows the runtime to turn __kmp_yield() on/off repeatedly on Linux.
This feature was removed when disabling monitor thread, but there are
applications that perform better with this feature on.

Patch by Hansang Bae

Differential Revision: https://reviews.llvm.org/D29227


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@295203 91177308-0d34-0410-b5e6-96231b3b80d8
2017-02-15 17:19:21 +00:00
Jonas Hahnfeld 4726583580 [OpenMP] New Tsan annotations to remove false positive on reduction and barriers
Added new ThreadSanitizer annotations to remove false positives with OpenMP reduction.
Cleaned up Tsan annotations header file from unused annotations.

Patch by Simone Atzeni!

Differential Revision: https://reviews.llvm.org/D29202

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@295158 91177308-0d34-0410-b5e6-96231b3b80d8
2017-02-15 08:14:22 +00:00
Hans Wennborg f26c30f014 libomptarget: Disable on Win32
It's not supported, and currently breaks the weekly LLVM snapshot
builds.

Differential Revision: https://reviews.llvm.org/D29801

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@294758 91177308-0d34-0410-b5e6-96231b3b80d8
2017-02-10 17:13:28 +00:00
Jonas Hahnfeld cb9c397660 [libomptarget] Align test code with runtime/
This change allows setting LIBOMPTARGET_LLVM_LIT_EXECUTABLE and
LIBOMPTARGET_FILECHECK_EXECUTABLE as full path. It also honors
OPENMP_LLVM_TOOLS_DIR which is meant as a common configuration
for both libomp and libomptarget.

Maybe this should be done in a common CMake module, but I'm no expert here.

Differential Revision: https://reviews.llvm.org/D29172

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@294284 91177308-0d34-0410-b5e6-96231b3b80d8
2017-02-07 06:58:15 +00:00
Andrey Churbanov 273c4bfef1 Fix a race in shutdown when tasking is used.
Patch by Terry Wilmarth.

Differential Revision: https://reviews.llvm.org/D28377


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@294214 91177308-0d34-0410-b5e6-96231b3b80d8
2017-02-06 18:53:32 +00:00
George Rokos cf09abbf86 [OpenMP] Redefined macro warning in libomptarget
Fixed compilation warning in libomptarget.

Differential Revision: https://reviews.llvm.org/D29353



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@293747 91177308-0d34-0410-b5e6-96231b3b80d8
2017-02-01 08:33:38 +00:00
George Rokos 6009b4051a [OpenMP] Initial implementation of OpenMP offloading library - libomptarget plugins.
This is the patch upstreaming the plugins part of libomptarget (CUDA, generic-elf-64).

Differential Revision: https://reviews.llvm.org/D14253



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@293724 91177308-0d34-0410-b5e6-96231b3b80d8
2017-02-01 00:14:41 +00:00
Jonas Hahnfeld b00226fdf5 Correct wrong comment in bug_nested_proxy_task.c
The nested proxy task does not have dependencies.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@293472 91177308-0d34-0410-b5e6-96231b3b80d8
2017-01-30 09:51:02 +00:00
Jonas Hahnfeld bd223d612d [libomptarget] Fix Debug build with glibc < 2.18
glibc < 2.18 is C99 compliant and only provides the format macros in C++ if
__STDC_FORMAT_MACROS is defined. This change fixes the debug build for
GCC 4.8, GCC 6.2 and Clang 3.9.1 that were previously broken on my machine.

It shows no regression for libc++ >= 4.0.0 which has a fix since September:
http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20160926/171659.html

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@293468 91177308-0d34-0410-b5e6-96231b3b80d8
2017-01-30 08:11:20 +00:00
Jonathan Peyton 7ec028b27e Cleanup: put i_maxmin members and ___kmp_size_type into traits_t
Put the duplicated i_maxmin into traits_t by adding new members max_value and
min_value. Put ___kmp_size_type into traits_t by adding member type_size.

Differential Revision: https://reviews.llvm.org/D28847


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@293316 91177308-0d34-0410-b5e6-96231b3b80d8
2017-01-27 18:09:22 +00:00
Jonathan Peyton 78b78d175a Printing OS thread id, when KMP_AFFINITY is set.
Patch by Vishakha Agrawal

Differential Revision: https://reviews.llvm.org/D28873


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@293315 91177308-0d34-0410-b5e6-96231b3b80d8
2017-01-27 18:04:33 +00:00
Jonathan Peyton c0cfee9024 Fix performance issue incurred by removing monitor thread.
When the monitor thread is used, most threads in the team directly go to
sleep if the copy of bt_intervals/bt_set is not available in the cache,
and this happens at least once per thread in the wait function, making the
overall performance slightly better.
This change tries to mimic this behavior by using the bt_intervals cache,
which simply keeps the blocktime interval in terms of the platform-dependent
ticks or nanoseconds.

Patch by Hansang Bae

Differential Revision: https://reviews.llvm.org/D28906


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@293312 91177308-0d34-0410-b5e6-96231b3b80d8
2017-01-27 17:54:31 +00:00
Jonas Hahnfeld 1dc2e70de2 [libomptarget] Fix compilation with libc++
iterator is only guaranteed to be default-constructible, without any argument.

Differential Revision: https://reviews.llvm.org/D29171

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@293277 91177308-0d34-0410-b5e6-96231b3b80d8
2017-01-27 11:03:33 +00:00
George Rokos 7680cbb63a [OpenMP] Initial implementation of OpenMP offloading library - libomptarget.
This is the patch upstreaming the device-agnostic part of libomptarget.

Differential Revision: https://reviews.llvm.org/D14031



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@293094 91177308-0d34-0410-b5e6-96231b3b80d8
2017-01-25 21:27:24 +00:00
Jonathan Peyton 3585ec7dbc Use C++11 static_assert() for build asserts.
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@292350 91177308-0d34-0410-b5e6-96231b3b80d8
2017-01-18 07:49:30 +00:00
Jonathan Peyton fa45385094 Fix memory error in case of reinit using kmp_set_defaults() for lock code.
The lock tables were being reallocated if kmp_set_defaults() was called.
In the env_init code it says that the user should be able to switch between
different KMP_CONSISTENCY_CHECK values which is what this change enables.


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@292349 91177308-0d34-0410-b5e6-96231b3b80d8
2017-01-18 07:02:21 +00:00
Jonathan Peyton 0e5d1992ca Fix small memory leak regarding __kmp_nested_proc_bind
There is no corresponding free() for this expandable array.  The logic is
added in __kmp_cleanup() next to the freeing of __kmp_nested_nth.


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@292348 91177308-0d34-0410-b5e6-96231b3b80d8
2017-01-18 06:40:19 +00:00
Jonas Hahnfeld 0c93c1078c kmp_affinity: Fix check if specific bit is set
Clang 4.0 trunk warns:
warning: logical not is only applied to the left hand side of this bitwise operator [-Wlogical-not-parentheses]

This points to a potential bug if the code really wants to check if the single
bit is not set: If for example (buf.edx >> 9) = 2 (has any bit set except the
least significant one), 'logical not' will return 0 which stays 0 after the
'bitwise and'.
To do this correctly we first need to evaluate the 'bitwise and'. In that case
it returns 2 & 1 = 0 which after the 'logical not' evaluates to 1.

Differential Revision: https://reviews.llvm.org/D28599

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@291764 91177308-0d34-0410-b5e6-96231b3b80d8
2017-01-12 11:39:04 +00:00
Jonas Hahnfeld 5e5eadec29 [CMake] Make openmp build under runtimes/
runtimes/CMakeLists.txt in LLVM passes OPENMP_STANDALONE_BUILD.

Differential Revision: https://reviews.llvm.org/D28280

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@290978 91177308-0d34-0410-b5e6-96231b3b80d8
2017-01-04 18:11:37 +00:00
Andrey Churbanov dae8e28bec Fix for the __kmpc_global_num_threads function to return the value of the __kmp_all_nth global var.
Patch by Yonghong Yan.

Differential Revision: https://reviews.llvm.org/D27975


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@290272 91177308-0d34-0410-b5e6-96231b3b80d8
2016-12-21 21:20:20 +00:00
Oren Ben Simhon 71cbef1629 Reverting last change.
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@290245 91177308-0d34-0410-b5e6-96231b3b80d8
2016-12-21 09:04:08 +00:00
Oren Ben Simhon 5d3a2991ec [X86] Vectorcall Calling Convention - Adding CodeGen Complete Support
Fixing build issues.



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@290242 91177308-0d34-0410-b5e6-96231b3b80d8
2016-12-21 08:58:19 +00:00
Jonathan Peyton 4277fc10ad Follow up to r289732: Update comments in source files to reference .cpp files
Patch by Hansang Bae


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@289739 91177308-0d34-0410-b5e6-96231b3b80d8
2016-12-14 23:01:24 +00:00
Jonathan Peyton 844de54c9c Change source files from .c to .cpp
Patch by Hansang Bae

Differential Revision: https://reviews.llvm.org/D26688


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@289732 91177308-0d34-0410-b5e6-96231b3b80d8
2016-12-14 22:39:11 +00:00
Andrey Churbanov e48c1b6d4c Cleanup: debug print fixed and moved inside critical section.
Patch by Victor Campos.

Differential Revision: https://reviews.llvm.org/D27647


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@289640 91177308-0d34-0410-b5e6-96231b3b80d8
2016-12-14 08:29:00 +00:00
Sylvestre Ledru 070870b8e6 Support of mips & mips64 for openmprtl
Summary:
Implemented by Dejan Latinovic
See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=790735 for more more information

Reviewers: AndreyChurbanov, jlpeyton

Subscribers: openmp-commits, mgorny

Differential Revision: https://reviews.llvm.org/D26576

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@289032 91177308-0d34-0410-b5e6-96231b3b80d8
2016-12-08 09:22:24 +00:00
Andrey Churbanov 0fee15bb8f fixed type in Windows-specific code
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@288368 91177308-0d34-0410-b5e6-96231b3b80d8
2016-12-01 16:08:52 +00:00
Jonathan Peyton 8ba8798f2b Fixed typo in kmp_process_deps trace output
Patch by Victor Campos

Differential Revision: https://reviews.llvm.org/D27172


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@288056 91177308-0d34-0410-b5e6-96231b3b80d8
2016-11-28 20:10:32 +00:00
Andrey Churbanov 81094a8e67 Cleanup: memory leaks on warnings printing fixed; some memory freeing cleaned; poor indents and one typo fixed.
Patch by Victor Campos.

Differential Revision: https://reviews.llvm.org/D26786


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@288054 91177308-0d34-0410-b5e6-96231b3b80d8
2016-11-28 19:23:09 +00:00
Jonathan Peyton 7ca47d5c84 Set task->td_dephash to NULL after free
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@287552 91177308-0d34-0410-b5e6-96231b3b80d8
2016-11-21 16:24:59 +00:00
Jonathan Peyton 36b1103f95 Fix for D25504 - segfault because of double free()-ing in shutdown code.
Paul Osmialowski pointed out a double free bug in shutdown code.  This patch
Moves the freeing of the implicit task to above the freeing of all fast memory
to prevent the double-free issue.

Differential Revision: https://reviews.llvm.org/D26860


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@287551 91177308-0d34-0410-b5e6-96231b3b80d8
2016-11-21 16:18:57 +00:00
Jonathan Peyton 0859e6a24e Update stats-gathering code
Have developer timers use partitioning scheme which also required that some
redundant developer timers be removed in favor of the already existing normal
timers. Move per thread stats initialization to just after global thread id
assignment which is as early as possible. Also put all global stats
initialization code in __kmp_stats_init() and all global stats destruction code
in __kmp_stats_fini().

Differential Revision: https://reviews.llvm.org/D26361


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@286892 91177308-0d34-0410-b5e6-96231b3b80d8
2016-11-14 21:13:44 +00:00
Jonathan Peyton d4da538d3c Introduce dynamic affinity dispatch capabilities
This set of changes enables the affinity interface (Either the preexisting
native operating system or HWLOC) to be dynamically set at runtime
initialization. The point of this change is that we were seeing performance
degradations when using HWLOC. This allows the user to use the old affinity
mechanisms which on large machines (>64 cores) makes a large difference in
initialization time.

These changes mostly move affinity code under a small class hierarchy:

KMPAffinity
  class Mask {}
KMPNativeAffinity : public KMPAffinity
  class Mask : public KMPAffinity::Mask
KMPHwlocAffinity
  class Mask : public KMPAffinity::Mask

Since all interface functions (for both affinity and the mask implementation)
are virtual, the implementation can be chosen at runtime initialization.

Differential Revision: https://reviews.llvm.org/D26356


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@286890 91177308-0d34-0410-b5e6-96231b3b80d8
2016-11-14 21:08:35 +00:00
Andrey Churbanov 76755788c3 Added check for malloc return.
Patch by Victor Campos.

Differential Revision: https://reviews.llvm.org/D26318

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@286441 91177308-0d34-0410-b5e6-96231b3b80d8
2016-11-10 09:08:03 +00:00
Jonas Hahnfeld 3fd0cf124f [OpenMP] Enable ThreadSanitizer to check OpenMP programs
This patch allows ThreadSanitizer (Tsan) to verify OpenMP programs.
It means that no false positive will be reported by Tsan when
verifying an OpenMP programs.
This patch introduces annotations within the OpenMP runtime module to
provide information about thread synchronization to the Tsan runtime.

In order to enable the Tsan support when building the runtime, you must
enable the TSAN_SUPPORT option with the following environment variable:

-DLIBOMP_TSAN_SUPPORT=TRUE

The annotations will be enabled in the main shared library
(same mechanism of OMPT).

Patch by Simone Atzeni and Joachim Protze!

Differential Revision: https://reviews.llvm.org/D13072

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@286115 91177308-0d34-0410-b5e6-96231b3b80d8
2016-11-07 15:58:36 +00:00
Andrey Churbanov 1d64a304ca fixed typo in comment
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@285947 91177308-0d34-0410-b5e6-96231b3b80d8
2016-11-03 17:48:46 +00:00
Andrey Churbanov 50288ab6b7 Change task stealing to always get task from head of victim's deque.
Differential Revision: https://reviews.llvm.org/D26187

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@285833 91177308-0d34-0410-b5e6-96231b3b80d8
2016-11-02 16:45:25 +00:00
Andrey Churbanov bbdd8b334b Fixed problem introduced by part of https://reviews.llvm.org/D21196.
Check Task Scheduling Constraint (TSC) on stealing of untied task.
This is needed because the untied task can produce tied children
those can break TSC if untied is not a descendant of current task.
This can cause live lock on complex tyasking tests
(e.g. kastors/strassen-task-dep).

Differential Revision: https://reviews.llvm.org/D26182

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@285703 91177308-0d34-0410-b5e6-96231b3b80d8
2016-11-01 16:19:04 +00:00
Andrey Churbanov ae791ee6a5 Add more conditions to check whether task waiting is necessary in kmp_omp_taskwait.
Differential Revision: https://reviews.llvm.org/D26058

Patch by Victor Campos


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@285678 91177308-0d34-0410-b5e6-96231b3b80d8
2016-11-01 08:33:36 +00:00
Andrey Churbanov 72db09bb15 Fixed a memory leak related to task dependencies.
Differential Revision: http://reviews.llvm.org/D25504

Patch by Alex Duran.


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@285283 91177308-0d34-0410-b5e6-96231b3b80d8
2016-10-27 11:43:07 +00:00
Jonathan Peyton 2591774d31 Fixing typos in __kmp_release_deps trace outputs
Patch by Victor Campos

Differential Revision: https://reviews.llvm.org/D25972


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@285244 91177308-0d34-0410-b5e6-96231b3b80d8
2016-10-26 21:46:43 +00:00
Jonathan Peyton 754a33e6a1 Use getpagesize() instead of PAGE_SIZE macro when KMP_OS_LINUX is true
Patch by Victor Campos

Differential Revision: https://reviews.llvm.org/D26001


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@285243 91177308-0d34-0410-b5e6-96231b3b80d8
2016-10-26 21:42:48 +00:00
Andrey Churbanov a92421e813 Fixed memory leak mistakenly introduced by https://reviews.llvm.org/D23115
Differential Revision: http://reviews.llvm.org/D25510


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@284747 91177308-0d34-0410-b5e6-96231b3b80d8
2016-10-20 17:14:17 +00:00
Samuel Antao c39d28cd81 [OpenMP] Fix issue with directives used in a macro.
Summary:
If directives are used in a macro, clang complains with:
```
src/projects/openmp/runtime/src/kmp_runtime.c:7486:2: error: embedding a directive within macro arguments has undefined behavior [-Werror,-Wembedded-directive]
#if KMP_USE_MONITOR
```

This patch fixes two occurrences of the issue in `kmp_runtime.cpp`.

Reviewers: tlwilmar, jlpeyton, AndreyChurbanov, Hahnfeld

Subscribers: Hahnfeld, openmp-commits

Differential Revision: https://reviews.llvm.org/D25823

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@284728 91177308-0d34-0410-b5e6-96231b3b80d8
2016-10-20 13:20:17 +00:00
Jonathan Peyton 550c021715 Fix OpenMP 4.0 library build
Patch by Andrey Churbanov

Differential Revision: https://reviews.llvm.org/D25505


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@284499 91177308-0d34-0410-b5e6-96231b3b80d8
2016-10-18 17:39:06 +00:00
Michal Gorny 4fa7d5e207 Fix a compile error on musl-libc due to strerror_r() prototype
Function strerror_r() has different signatures in different
implementations of libc: glibc's version returns a char*, while BSDs
and musl return a int. libomp unconditionally assumes glibc on Linux
and thus fails to compile against musl-libc. This patch addresses this
issue.

Differential Revision: https://reviews.llvm.org/D25071

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@284492 91177308-0d34-0410-b5e6-96231b3b80d8
2016-10-18 16:38:44 +00:00
Jonathan Peyton 89e22fb843 Mixed type atomic routines added for capture and update/capture reverse.
New mixed type atomic routines added for regular capture operations as well as
reverse update/capture operations.  LHS - all integer and float types (no
complex so far), RHS - float16.

Patch by Olga Malysheva

Differential Revision: https://reviews.llvm.org/D25275


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@284489 91177308-0d34-0410-b5e6-96231b3b80d8
2016-10-18 16:20:55 +00:00
Jonathan Peyton 88b2b1cf48 Code cleanup for the runtime without monitor thread
This change removes/disables unnecessary code when monitor thread is not used.

Patch by Hansang Bae

Differential Revision: https://reviews.llvm.org/D25102


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@283577 91177308-0d34-0410-b5e6-96231b3b80d8
2016-10-07 18:12:19 +00:00
Jonathan Peyton f82ad7797b Enable omp_get_schedule() to return static steal type.
As the code is now, calling omp_get_schedule() when OMP_SCHEDULE=static_steal
will cause an assert.


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@283576 91177308-0d34-0410-b5e6-96231b3b80d8
2016-10-07 18:01:35 +00:00
Paul Osmialowski af29aaac46 [cmake] Fix for a bug https://llvm.org/bugs/show_bug.cgi?id=30489 "Cannot build with -DLIBOMP_FORTRAN_MODULES=True"
Differential Revision: https://reviews.llvm.org/D24959

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@282965 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-30 22:05:45 +00:00
Jonathan Peyton 0252c7b871 Insert missing checks for KMP_AFFINITY_CAPABLE() in affinity API.
If affinity is not capable, then these API functions will perform the stubs
version.


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@282947 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-30 20:56:44 +00:00
Michal Gorny 27bfdc4a3c [test] Support 'lit' executable name
Support finding lit as plain 'lit', which is the name used by setup.py
in LLVM's utils/lit.

Differential Revision: https://reviews.llvm.org/D25072

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@282876 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-30 16:56:16 +00:00
Jonathan Peyton 8ff412c00e Fix incorrect OpenMP version in Fortran module.
Add check for "45" version to use "201511" string for OpenMP 4.5,
otherwise "200505" is used in Fortran module. Also, fix kmp_openmp_version
variable (used for the debugger, e.g.) and kmp_version_omp_api that is used
in KMP_VERSION=1 output.

Patch by Olga Malysheva

Differential Revision: https://reviews.llvm.org/D24761


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@282868 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-30 15:50:14 +00:00
Jonathan Peyton d1a75f52fc Mixed type atomic routines for unsigned integers.
New routines should be used for atomics like "<int>OP=<float>" when <int> is
unsigned. Using functions __kmpc_atomic_fixed<bits>_<op>_fp) produces incorrect
results

Differential Revision: https://reviews.llvm.org/D24756


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@282509 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-27 17:38:48 +00:00
Jonathan Peyton 0af08c496b Disable monitor thread creation by default.
This change set disables creation of the monitor thread by default.  The global
counter maintained by the monitor thread was replaced by logic that uses system
time directly, and cyclic yielding on Linux target was also removed since there
was no clear benefit of using it. Turning on KMP_USE_MONITOR variable (=1)
enables creation of monitor thread again if it is really necessary for some
reasons.

Differential Revision: https://reviews.llvm.org/D24739


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@282507 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-27 17:11:17 +00:00
Michal Gorny c5fa69cd0b Fix respecting LIBOMP_LLVM_LIT_EXECUTABLE as full path
Fix lit search to correctly respect LIBOMP_LLVM_LIT_EXECUTABLE as full
program path.

The variable passed to find_program() is created by CMake as a cache
variable, and therefore can be directly overriden by the user. Since
this was the design of LIBOMP_LLVM_LIT_EXECUTABLE (as can be deduced
from the error messages) and there is no other use of LIT_EXECUTABLE,
remove the redundant variable and pass LIBOMP_LLVM_LIT_EXECUTABLE
directly to find_program().

Furthermore, the previous code did not work since the HINTS argument
specifies more search directories rather than expected full path.
Quoting the CMake documentation:

> 3. Search the paths specified by the HINTS option. These should be
> paths computed by system introspection, such as a hint provided by
> the location of another item already found. Hard-coded guesses should
> be specified with the PATHS option.

Differential Revision: https://reviews.llvm.org/D24710

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@281887 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-19 06:55:56 +00:00
Michal Gorny 89ab78e360 [cmake] Make libgomp & libiomp5 alias install optional
Introduce a new LIBOMP_INSTALL_VARIABLES cache variable that can be used
to disable creating libgomp and libiomp5 aliases on 'make install'.
Those aliases are undesired e.g. on Gentoo systems where libomp is used
purely by clang.

Differential Revision: https://reviews.llvm.org/D24563

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@281512 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-14 17:46:27 +00:00
Jonas Hahnfeld 8e30df72a9 [OMPT] fix task frame information for gomp interface
Previous differencials D23305-D23310 changed task frame information management only for the kmp interface, but not for the whole gomp interface. This broke some testcases when building with gcc.
This patch fixes the broken task frame information for the gomp interface.

Patch by Joachim Protze!

Differential Revision: https://reviews.llvm.org/D24502

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@281468 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-14 13:59:39 +00:00
Jonas Hahnfeld f091351474 [OMPT] save exit address to lwt if available
In case, the current team is a serialized team (lwt), the frame information should be written to this data structure.
Before, nested serialized teams would overwrite the same task information.

Patch by Joachim Protze!

Differential Revision: https://reviews.llvm.org/D23310

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@281467 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-14 13:59:31 +00:00
Jonas Hahnfeld cd7b29a48d [OMPT] fix __ompt_get_teaminfo to consult lwt entries of parent teams
The comment already states, that this function should work similarly as __ompt_get_taskinfo.

The function only looked for lwt entries of the current team, but not when unrolling the parents. This fix aligns the implementation to __ompt_get_taskinfo.

The new test case creates a single theaded team (->lwt) and then a nested active team.
Before the innermost print_id(1) would deliver a different team then the outer print_id(0).

Patch by Joachim Protze!

Differential Revision: https://reviews.llvm.org/D23309

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@281466 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-14 13:59:24 +00:00
Jonas Hahnfeld 1b9360b367 [OMPT] Reset task exit frame when execution is finished
The exit address is set when execution of a task is started and should be reset as soon as the execution is finished.
Especially for the asm implementation of __kmp_invoke_microtask, resetting in this call would be painfull, so reset just after the invokation.

The testcase shows the effect of this patch:
Before, the implicit barriers at the end of an implicit task would see an exit address for the implicit task.

This barrier is a task scheduling point. Thus, any explicit task scheduled there would see an exit, but no reenter address for the implicit task.

Patch by Joachim Protze!

Differential Revision: https://reviews.llvm.org/D23307

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@281465 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-14 13:59:19 +00:00
Jonas Hahnfeld 4890f69035 [OMPT] Align implementation of reenter frame address to latest (frozen) version of OMPT spec
The latest OMPT spec changed the semantic of a tasks reenter frame to be the application frame, that will be entered, when the runtime frame drops.
Before it was the last frame in the runtime. This doesn't work for some gcc execution pathes or even clang generated code for :
Since there is no runtime frame between the executed task and the encountering task.

The test case compares exit and reenter addresses against addresses captured in application code

Patch by Joachim Protze!

Differential Revision: https://reviews.llvm.org/D23305

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@281464 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-14 13:59:13 +00:00
Jonas Hahnfeld 75e689d1a6 [OMPT] extend ompt tests by checks for frame pointers
OMPT tests can check for right frame information of tasks:
 * parent_task_frame was directly printed as a pointer, but actually points to a struct ompt_frame {void*, void*}
 * NULL is printed in the beginning of execution and loaded to FileChecker variable [[NULL]]
 * implicit tasks now also print their frame information
 * macro to print frame address from application
 * print task info for barrier begin

Patch by Joachim Protze!

Differential Revision: https://reviews.llvm.org/D23304

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@281463 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-14 13:59:05 +00:00
Jonathan Peyton bf6a88004a Fix bitmask upper bounds check
Rather than checking KMP_CPU_SETSIZE, which doesn't exist when using Hwloc, we
use the get_max_proc() function which can vary based on the operating system.
For example on Windows with multiple processor groups, it might be the case that
the highest bit possible in the bitmask is not equal to the number of hardware
threads on the machine but something higher than that.

Differential Revision: https://reviews.llvm.org/D24206


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@281245 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-12 19:02:53 +00:00
George Rokos a24629dfeb [OPENMP] ppc64le recognized as big-endian
There is a bug in CMakeLists which causes powerpc64le systems to be recognized as big-endian. This patch fixes the issue.

Differential Revision: https://reviews.llvm.org/D23626



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@281068 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-09 18:04:23 +00:00
George Rokos 26eea9efa4 [OPENMP] Implementation of omp_get_default_device and omp_set_default_device
Implementation of missing OpenMP 4.0 API functions omp_get_default_device and omp_set_default_device.
Also, added support for the environment variable OMP_DEFAULT_DEVICE.

Differential Revision: https://reviews.llvm.org/D23587



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@281065 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-09 17:55:26 +00:00
Jonathan Peyton 0f2e782515 Move function into cpp file under KMP_AFFINITY_SUPPORTED guard.
When affinity isn't supported, __kmp_affinity_compact doesn't exist.  The
problem is that in kmp_affinity.h there is a function which uses it without the
proper KMP_AFFINITY_SUPPORTED guard around it.  The compiler was smart enough to
ignore it and the function __kmp_affinity_cmp_Address_child_num which relies on
it, but I think it is cleaner to have it under the proper guard.  Since the
function is only used in the kmp_affinity.cpp file and there aren't any plans to
have it elsewhere.  I have moved it there.


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@280542 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-02 20:54:58 +00:00
Jonathan Peyton dbb582e3a8 Decouple the kmp_affin_mask_t type from determining if affinity is capable
the __kmp_affinity_determine_capable() functions are highly operating system
specific.  This change has the functions use the type they expect explicitly.


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@280538 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-02 20:35:47 +00:00
Jonathan Peyton 0cbd31b98f Replace a bad instance of __kmp_free() with KMP_CPU_FREE_ARRAY() macro.
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@280530 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-02 19:37:12 +00:00
Jonathan Peyton 3a587a8c43 Use 'critical' reduction method when 'atomic' is not available but requested.
In case atomic reduction method is not available (the compiler can't generate
it) the assertion failure occurred if KMP_FORCE_REDUCTION=atomic was specified.
This change replaces the assertion with a warning and sets the reduction method
to the default one - 'critical'.

Patch by Olga Malysheva

Differential Revision: https://reviews.llvm.org/D23990


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@280519 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-02 18:29:45 +00:00
Jonathan Peyton bd0745e696 Appease older gcc compilers for the many-microtask-args.c test
Older gcc compilers error out with the C99 syntax of: for (int i =...)
so this change just moves the int i; declaration up above.


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@280138 91177308-0d34-0410-b5e6-96231b3b80d8
2016-08-30 19:28:58 +00:00
Andrey Churbanov 75f264c149 cleanup: fixed names of dummy arguments of Fortran interfaces declarations, no functional changes done
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@278951 91177308-0d34-0410-b5e6-96231b3b80d8
2016-08-17 18:18:21 +00:00
Andrey Churbanov 18238e42de Fixes for hierarchical barrier (possible hang if team size changed).
Differential Revision: http://reviews.llvm.org/D23175

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@278332 91177308-0d34-0410-b5e6-96231b3b80d8
2016-08-11 13:04:00 +00:00
Dimitry Andric de1011b67f Fix linking of omp_foreign_thread_team_reuse test on FreeBSD
Summary:
On FreeBSD, linking the misc_bugs/omp_foreign_thread_team_reuse.c test
case fails with:

   /usr/local/bin/ld: /tmp/omp_foreign_thread_team_reuse-c5e71b.o: undefined reference to symbol 'pthread_create@@FBSD_1.0'

This is because the program is linked without `-lpthread`.  Since the
%libomp-compile-and-run macro does not allow that option to be added to
the compile command line, split it up and add the required `-lpthread`
between %libomp-compile and %libomp-run.

Reviewers: jlpeyton, hfinkel, Hahnfeld

Subscribers: Hahnfeld, emaste, openmp-commits

Differential Revision: https://reviews.llvm.org/D23084

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@278036 91177308-0d34-0410-b5e6-96231b3b80d8
2016-08-08 18:34:05 +00:00
Jonas Hahnfeld 5c3fd1d828 kmp_gsupport: Fix library initialization with taskgroup
Differential Revision: https://reviews.llvm.org/D23259

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@278003 91177308-0d34-0410-b5e6-96231b3b80d8
2016-08-08 13:23:08 +00:00
Jonas Hahnfeld b5f8854970 Mark tests with task dependencies as unsupported with GCC
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@277996 91177308-0d34-0410-b5e6-96231b3b80d8
2016-08-08 11:52:49 +00:00
Jonas Hahnfeld a86e0bab74 Do not block on explicit task depending on proxy task
Consider the following code:

    int dep;
    #pragma omp target nowait depend(out: dep)
    {
        sleep(1);
    }
    #pragma omp task depend(in: dep)
    {
        printf("Task with dependency\n");
    }
    printf("Doing some work...\n");

In its current state the runtime will block on the second task and not
continue execution.

Differential Revision: https://reviews.llvm.org/D23116

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@277992 91177308-0d34-0410-b5e6-96231b3b80d8
2016-08-08 10:08:14 +00:00
Jonas Hahnfeld d9ae211c7d __kmp_free_task: Fix for serial explicit tasks producing proxy tasks
Consider the following code which may be executed by a serial team:

    int dep;
    #pragma omp target nowait depend(out: dep)
    {
        sleep(1);
    }
    #pragma omp task depend(in: dep)
    {
        #pragma omp target nowait
        {
            sleep(1);
        }
    }

Here the explicit task may not be freed until the nested proxy task has
finished. The current code hasn't considered this and called __kmp_free_task
anyway which triggered an assert because of remaining incomplete children:

    KMP_DEBUG_ASSERT( TCR_4(taskdata->td_incomplete_child_tasks) == 0 );

Differential Revision: https://reviews.llvm.org/D23115

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@277991 91177308-0d34-0410-b5e6-96231b3b80d8
2016-08-08 10:08:07 +00:00
Andrey Churbanov 6c90de7aaf Fixed x2APIC discovery for 256-processor architectures.
Mask for value read from ebx register returned by CPUID expanded to 0xFFFF.

Differential Revision: https://reviews.llvm.org/D23203

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@277825 91177308-0d34-0410-b5e6-96231b3b80d8
2016-08-05 15:59:11 +00:00
Jonas Hahnfeld 03a057fa63 Add test case for nested creation of tasks
For discussion in D23115

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@277730 91177308-0d34-0410-b5e6-96231b3b80d8
2016-08-04 14:55:56 +00:00
Jonas Hahnfeld 3558291c37 kmp_taskdeps.cpp: Fix debugging output
node->dn.task is only filled after the dependencies are already processed.
This currently leads to unhelpful output from KA_TRACE or even a crash
if one enables KMP_SUPPORT_GRAPH_OUTPUT.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@277717 91177308-0d34-0410-b5e6-96231b3b80d8
2016-08-04 11:03:47 +00:00
Pirama Arumuga Nainar 78d420b46a Disable KMP_CANCEL_THREADS on Android
Summary:
Android does not have pthread_cancel.  Disable KMP_CANCEL_THREADS if
__ANDROID__ is defined.

Subscribers: tberghammer, srhines, openmp-commits, danalbert

Differential Revision: https://reviews.llvm.org/D23029

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@277618 91177308-0d34-0410-b5e6-96231b3b80d8
2016-08-03 18:08:57 +00:00
Paul Osmialowski 0fd38d88a8 Make balanced affinity work on AArch64.
This patch enables balanced affinity on machines that do not have
hardware threads and have cores clustered into packages. In facts,
balacing algorithm could be generalized for any arrangement with
at least two levels of hierarchy (depth > 1).

Differential Revision: https://reviews.llvm.org/D22365

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@277212 91177308-0d34-0410-b5e6-96231b3b80d8
2016-07-29 20:55:03 +00:00
Samuel Antao 6dd28bf89f Replace enum types in variadic functions by build-in types.
Summary:
When compiling the runtime library with clang we get warnings like:
```
error: passing an object that undergoes default argument promotion to 'va_start' has undefined behavior [-Werror,-Wvarargs]
    va_start( args, id );
                    ^
note: parameter of type 'kmp_i18n_id_t' (aka 'kmp_i18n_id') is declared here
    kmp_i18n_id_t id,
```
My understanding is that the va_start macro only gets the promoted type so it won't know what was the exact type of the argument, which can potentially not work for some targets given that the implementation of the the calling convention could not be done properly.

This patch fixes that by using a built-in type in the function signature.

Reviewers: tlwilmar, jlpeyton, AndreyChurbanov

Subscribers: arpith-jacob, carlo.bertolli, caomhin, openmp-commits

Differential Revision: https://reviews.llvm.org/D22427

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@276428 91177308-0d34-0410-b5e6-96231b3b80d8
2016-07-22 16:05:35 +00:00
427 changed files with 82873 additions and 81770 deletions
+4
View File
@@ -0,0 +1,4 @@
{
"repository.callsign" : "OMP",
"conduit_uri" : "https://reviews.llvm.org/"
}
+42
View File
@@ -0,0 +1,42 @@
#==============================================================================#
# This file specifies intentionally untracked files that git should ignore.
# See: http://www.kernel.org/pub/software/scm/git/docs/gitignore.html
#
# This file is intentionally different from the output of `git svn show-ignore`,
# as most of those are useless.
#==============================================================================#
#==============================================================================#
# File extensions to be ignored anywhere in the tree.
#==============================================================================#
# Temp files created by most text editors.
*~
# Merge files created by git.
*.orig
# Byte compiled python modules.
*.pyc
# vim swap files
.*.sw?
.sw?
#OS X specific files.
.DS_store
#==============================================================================#
# Explicit files to ignore (only matches one).
#==============================================================================#
# Various tag programs
tags
/TAGS
/GPATH
/GRTAGS
/GSYMS
/GTAGS
.gitusers
#==============================================================================#
# Directories to ignore (do not add trailing '/'s, they skip symlinks).
#==============================================================================#
runtime/exports
# Nested build directory
/build
+77 -1
View File
@@ -1,5 +1,81 @@
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
set(OPENMP_LLVM_TOOLS_DIR "" CACHE PATH "Path to LLVM tools for testing")
# Add cmake directory to search for custom cmake functions.
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
# llvm/runtimes/ will set OPENMP_STANDALONE_BUILD.
if (OPENMP_STANDALONE_BUILD OR "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
set(OPENMP_STANDALONE_BUILD TRUE)
project(openmp C CXX)
# CMAKE_BUILD_TYPE was not set, default to Release.
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
# Group common settings.
set(OPENMP_ENABLE_WERROR FALSE CACHE BOOL
"Enable -Werror flags to turn warnings into errors for supporting compilers.")
set(OPENMP_LIBDIR_SUFFIX "" CACHE STRING
"Suffix of lib installation directory, e.g. 64 => lib64")
# Group test settings.
set(OPENMP_TEST_C_COMPILER ${CMAKE_C_COMPILER} CACHE STRING
"C compiler to use for testing OpenMP runtime libraries.")
set(OPENMP_TEST_CXX_COMPILER ${CMAKE_CXX_COMPILER} CACHE STRING
"C++ compiler to use for testing OpenMP runtime libraries.")
set(OPENMP_LLVM_TOOLS_DIR "" CACHE PATH "Path to LLVM tools for testing.")
else()
set(OPENMP_ENABLE_WERROR ${LLVM_ENABLE_WERROR})
# If building in tree, we honor the same install suffix LLVM uses.
set(OPENMP_LIBDIR_SUFFIX ${LLVM_LIBDIR_SUFFIX})
if (NOT MSVC)
set(OPENMP_TEST_C_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang)
set(OPENMP_TEST_CXX_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++)
else()
set(OPENMP_TEST_C_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang.exe)
set(OPENMP_TEST_CXX_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++.exe)
endif()
endif()
# Check and set up common compiler flags.
include(config-ix)
include(HandleOpenMPOptions)
# Set up testing infrastructure.
include(OpenMPTesting)
set(OPENMP_TEST_FLAGS "" CACHE STRING
"Extra compiler flags to send to the test compiler.")
set(OPENMP_TEST_OPENMP_FLAGS ${OPENMP_TEST_COMPILER_OPENMP_FLAGS} CACHE STRING
"OpenMP compiler flag to use for testing OpenMP runtime libraries.")
# Build host runtime library.
add_subdirectory(runtime)
set(ENABLE_LIBOMPTARGET ON)
# Currently libomptarget cannot be compiled on Windows or MacOS X.
# Since the device plugins are only supported on Linux anyway,
# there is no point in trying to compile libomptarget on other OSes.
if (APPLE OR WIN32 OR NOT OPENMP_HAVE_STD_CPP11_FLAG)
set(ENABLE_LIBOMPTARGET OFF)
endif()
option(OPENMP_ENABLE_LIBOMPTARGET "Enable building libomptarget for offloading."
${ENABLE_LIBOMPTARGET})
if (OPENMP_ENABLE_LIBOMPTARGET)
# Check that the library can acutally be built.
if (APPLE OR WIN32)
message(FATAL_ERROR "libomptarget cannot be built on Windows and MacOS X!")
elseif (NOT OPENMP_HAVE_STD_CPP11_FLAG)
message(FATAL_ERROR "Host compiler must support C++11 to build libomptarget!")
endif()
add_subdirectory(libomptarget)
endif()
# Now that we have seen all testuites, create the check-openmp target.
construct_check_openmp_target()
+8 -4
View File
@@ -8,10 +8,18 @@ beautification by scripts. The fields are: name (N), email (E), web-address
(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
(S).
N: Adam Azarchs
W: 10xgenomics.com
D: Bug fix for lock code
N: Carlo Bertolli
W: http://ibm.com
D: IBM contributor to PowerPC support in CMake files and elsewhere.
N: Diego Caballero
E: diego.l.caballero@gmail.com
D: Fork performance improvements
N: Sunita Chandrasekaran
D: Contributor to testsuite from OpenUH
@@ -51,7 +59,3 @@ D: Making build work for FreeBSD.
N: Cheng Wang
D: Contributor to testsuite from OpenUH
N: Diego Caballero
E: diego.l.caballero@gmail.com
D: Fork performance improvements
+307
View File
@@ -0,0 +1,307 @@
========================================
How to Build the LLVM* OpenMP* Libraries
========================================
This repository requires `CMake <http://www.cmake.org/>`_ v2.8.0 or later. LLVM
and Clang need a more recent version which also applies for in-tree builds. For
more information than available in this document please see
`LLVM's CMake documentation <http://llvm.org/docs/CMake.html>`_ and the
`official documentation <https://cmake.org/cmake/help/v2.8.0/cmake.html>`_.
.. contents::
:local:
How to Call CMake Initially, then Repeatedly
============================================
- When calling CMake for the first time, all needed compiler options must be
specified on the command line. After this initial call to CMake, the compiler
definitions must not be included for further calls to CMake. Other options
can be specified on the command line multiple times including all definitions
in the build options section below.
- Example of configuring, building, reconfiguring, rebuilding:
.. code-block:: console
$ mkdir build
$ cd build
$ cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ .. # Initial configuration
$ make
...
$ make clean
$ cmake -DCMAKE_BUILD_TYPE=Debug .. # Second configuration
$ make
...
$ rm -rf *
$ cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ .. # Third configuration
$ make
- Notice in the example how the compiler definitions are only specified for an
empty build directory, but other build options are used at any time.
- The file ``CMakeCache.txt`` which is created after the first call to CMake is
a configuration file which holds all values for the build options. These
values can be changed using a text editor to modify ``CMakeCache.txt`` as
opposed to using definitions on the command line.
- To have CMake create a particular type of build generator file simply include
the ``-G <Generator name>`` option:
.. code-block:: console
$ cmake -G "Unix Makefiles" ...
You can see a list of generators CMake supports by executing the cmake command
with no arguments.
Instructions to Build
=====================
.. code-block:: console
$ cd openmp_top_level/ [ this directory with libomptarget/, runtime/, etc. ]
$ mkdir build
$ cd build
[ Unix* Libraries ]
$ cmake -DCMAKE_C_COMPILER=<C Compiler> -DCMAKE_CXX_COMPILER=<C++ Compiler> ..
[ Windows* Libraries ]
$ cmake -G <Generator Type> -DCMAKE_C_COMPILER=<C Compiler> -DCMAKE_CXX_COMPILER=<C++ Compiler> -DCMAKE_ASM_MASM_COMPILER=[ml | ml64] -DCMAKE_BUILD_TYPE=Release ..
$ make
$ make install
CMake Options
=============
Builds with CMake can be customized by means of options as already seen above.
One possibility is to pass them via the command line:
.. code-block:: console
$ cmake -DOPTION=<value> path/to/source
.. note:: The first value listed is the respective default for that option.
Generic Options
---------------
For full documentation consult the CMake manual or execute
``cmake --help-variable VARIABLE_NAME`` to get information about a specific
variable.
**CMAKE_BUILD_TYPE** = ``Release|Debug|RelWithDebInfo``
Build type can be ``Release``, ``Debug``, or ``RelWithDebInfo`` which chooses
the optimization level and presence of debugging symbols.
**CMAKE_C_COMPILER** = <C compiler name>
Specify the C compiler.
**CMAKE_CXX_COMPILER** = <C++ compiler name>
Specify the C++ compiler.
**CMAKE_Fortran_COMPILER** = <Fortran compiler name>
Specify the Fortran compiler. This option is only needed when
**LIBOMP_FORTRAN_MODULES** is ``ON`` (see below). So typically, a Fortran
compiler is not needed during the build.
**CMAKE_ASM_MASM_COMPILER** = ``ml|ml64``
This option is only relevant for Windows*.
Options for all Libraries
-------------------------
**OPENMP_ENABLE_WERROR** = ``OFF|ON``
Treat warnings as errors and fail, if a compiler warning is triggered.
**OPENMP_LIBDIR_SUFFIX** = ``""``
Extra suffix to append to the directory where libraries are to be installed.
**OPENMP_TEST_C_COMPILER** = ``${CMAKE_C_COMPILER}``
Compiler to use for testing. Defaults to the compiler that was also used for
building.
**OPENMP_TEST_CXX_COMPILER** = ``${CMAKE_CXX_COMPILER}``
Compiler to use for testing. Defaults to the compiler that was also used for
building.
**OPENMP_LLVM_TOOLS_DIR** = ``/path/to/built/llvm/tools``
Additional path to search for LLVM tools needed by tests.
**OPENMP_LLVM_LIT_EXECUTABLE** = ``/path/to/llvm-lit``
Specify full path to ``llvm-lit`` executable for running tests. The default
is to search the ``PATH`` and the directory in **OPENMP_LLVM_TOOLS_DIR**.
**OPENMP_FILECHECK_EXECUTABLE** = ``/path/to/FileCheck``
Specify full path to ``FileCheck`` executable for running tests. The default
is to search the ``PATH`` and the directory in **OPENMP_LLVM_TOOLS_DIR**.
Options for ``libomp``
----------------------
**LIBOMP_ARCH** = ``aarch64|arm|i386|mic|mips|mips64|ppc64|ppc64le|x86_64``
The default value for this option is chosen based on probing the compiler for
architecture macros (e.g., is ``__x86_64__`` predefined by compiler?).
**LIBOMP_MIC_ARCH** = ``knc|knf``
Intel(R) Many Integrated Core Architecture (Intel(R) MIC Architecture) to
build for. This value is ignored if **LIBOMP_ARCH** does not equal ``mic``.
**LIBOMP_OMP_VERSION** = ``50|45|40|30``
OpenMP version to build for. Older versions will disable certain
functionality and entry points.
**LIBOMP_LIB_TYPE** = ``normal|profile|stubs``
Library type can be ``normal``, ``profile``, or ``stubs``.
**LIBOMP_USE_VERSION_SYMBOLS** = ``ON|OFF``
Use versioned symbols for building the library. This option only makes sense
for ELF based libraries where version symbols are supported (Linux*, some BSD*
variants). It is ``OFF`` by default for Windows* and macOS*, but ``ON`` for
other Unix based operating systems.
**LIBOMP_ENABLE_SHARED** = ``ON|OFF``
Build a shared library. If this option is ``OFF``, static OpenMP libraries
will be built instead of dynamic ones.
.. note::
Static libraries are not supported on Windows*.
**LIBOMP_FORTRAN_MODULES** = ``OFF|ON``
Create the Fortran modules (requires Fortran compiler).
macOS* Fat Libraries
""""""""""""""""""
On macOS* machines, it is possible to build universal (or fat) libraries which
include both i386 and x86_64 architecture objects in a single archive.
.. code-block:: console
$ cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_OSX_ARCHITECTURES='i386;x86_64' ..
$ make
There is also an option **LIBOMP_OSX_ARCHITECTURES** which can be set in case
this is an LLVM source tree build. It will only apply for the ``libomp`` library
avoids having the entire LLVM/Clang build produce universal binaries.
Optional Features
"""""""""""""""""
**LIBOMP_USE_ADAPTIVE_LOCKS** = ``ON|OFF``
Include adaptive locks, based on Intel(R) Transactional Synchronization
Extensions (Intel(R) TSX). This feature is x86 specific and turned ``ON``
by default for IA-32 architecture and Intel(R) 64 architecture.
**LIBOMP_USE_INTERNODE_ALIGNMENT** = ``OFF|ON``
Align certain data structures on 4096-byte. This option is useful on
multi-node systems where a small ``CACHE_LINE`` setting leads to false sharing.
**LIBOMP_OMPT_SUPPORT** = ``ON|OFF``
Include support for the OpenMP Tools Interface (OMPT).
This option is supported and ``ON`` by default for x86, x86_64, AArch64, and
PPC64 on Linux, Windows, and mac OS.
This option is ``OFF`` if this feature is not supported for the platform.
**LIBOMP_OMPT_OPTIONAL** = ``ON|OFF``
Include support for optional OMPT functionality. This option is ignored if
**LIBOMP_OMPT_SUPPORT** is ``OFF``.
**LIBOMP_STATS** = ``OFF|ON``
Include stats-gathering code.
**LIBOMP_USE_DEBUGGER** = ``OFF|ON``
Include the friendly debugger interface.
**LIBOMP_USE_HWLOC** = ``OFF|ON``
Use `OpenMPI's hwloc library <https://www.open-mpi.org/projects/hwloc/>`_ for
topology detection and affinity.
**LIBOMP_HWLOC_INSTALL_DIR** = ``/path/to/hwloc/install/dir``
Specify install location of hwloc. The configuration system will look for
``hwloc.h`` in ``${LIBOMP_HWLOC_INSTALL_DIR}/include`` and the library in
``${LIBOMP_HWLOC_INSTALL_DIR}/lib``. The default is ``/usr/local``.
This option is only used if **LIBOMP_USE_HWLOC** is ``ON``.
Additional Compiler Flags
"""""""""""""""""""""""""
These flags are **appended**, they do not overwrite any of the preset flags.
**LIBOMP_CPPFLAGS** = <space-separated flags>
Additional C preprocessor flags.
**LIBOMP_CFLAGS** = <space-separated flags>
Additional C compiler flags.
**LIBOMP_CXXFLAGS** = <space-separated flags>
Additional C++ compiler flags.
**LIBOMP_ASMFLAGS** = <space-separated flags>
Additional assembler flags.
**LIBOMP_LDFLAGS** = <space-separated flags>
Additional linker flags.
**LIBOMP_LIBFLAGS** = <space-separated flags>
Additional libraries to link.
**LIBOMP_FFLAGS** = <space-separated flags>
Additional Fortran compiler flags.
Options for ``libomptarget``
----------------------------
**LIBOMPTARGET_OPENMP_HEADER_FOLDER** = ``""``
Path of the folder that contains ``omp.h``. This is required for testing
out-of-tree builds.
**LIBOMPTARGET_OPENMP_HOST_RTL_FOLDER** = ``""``
Path of the folder that contains ``libomp.so``. This is required for testing
out-of-tree builds.
Example Usages of CMake
=======================
Typical Invocations
-------------------
.. code-block:: console
$ cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ ..
$ cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ ..
$ cmake -DCMAKE_C_COMPILER=icc -DCMAKE_CXX_COMPILER=icpc ..
Advanced Builds with Various Options
------------------------------------
- Build the i386 Linux* library using GCC*
.. code-block:: console
$ cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DLIBOMP_ARCH=i386 ..
- Build the x86_64 debug Mac library using Clang*
.. code-block:: console
$ cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DLIBOMP_ARCH=x86_64 -DCMAKE_BUILD_TYPE=Debug ..
- Build the library (architecture determined by probing compiler) using the
Intel(R) C Compiler and the Intel(R) C++ Compiler. Also, create Fortran
modules with the Intel(R) Fortran Compiler.
.. code-block:: console
$ cmake -DCMAKE_C_COMPILER=icc -DCMAKE_CXX_COMPILER=icpc -DCMAKE_Fortran_COMPILER=ifort -DLIBOMP_FORTRAN_MODULES=on ..
- Have CMake find the C/C++ compiler and specify additional flags for the C
compiler, preprocessor, and C++ compiler.
.. code-blocks:: console
$ cmake -DLIBOMP_CFLAGS='-specific-flag' -DLIBOMP_CPPFLAGS='-DNEW_FEATURE=1 -DOLD_FEATURE=0' -DLIBOMP_CXXFLAGS='--one-specific-flag --two-specific-flag' ..
- Build the stubs library
.. code-blocks:: console
$ cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DLIBOMP_LIB_TYPE=stubs ..
**Footnotes**
.. [*] Other names and brands may be claimed as the property of others.
+39
View File
@@ -0,0 +1,39 @@
cmake_minimum_required(VERSION 2.8)
project(DetectTestCompiler C CXX)
include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
function(write_compiler_information lang)
set(information "${CMAKE_${lang}_COMPILER}")
set(information "${information}\\;${CMAKE_${lang}_COMPILER_ID}")
set(information "${information}\\;${CMAKE_${lang}_COMPILER_VERSION}")
set(information "${information}\\;${${lang}_FLAGS}")
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${lang}CompilerInformation.txt ${information})
endfunction(write_compiler_information)
find_package(OpenMP)
if (NOT OpenMP_Found)
set(OpenMP_C_FLAGS "-fopenmp")
set(OpenMP_CXX_FLAGS "-fopenmp")
endif()
set(C_FLAGS ${flags} ${OpenMP_C_FLAGS})
set(CXX_FLAGS ${flags} ${OpenMP_CXX_FLAGS})
# TODO: Implement blockaddress in GlobalISel and remove this flag!
if (CMAKE_C_COMPILER_ID STREQUAL "Clang")
check_c_compiler_flag("-fno-experimental-isel" C_HAS_EXPERIMENTAL_ISEL_FLAG)
check_cxx_compiler_flag("-fno-experimental-isel" CXX_HAS_EXPERIMENTAL_ISEL_FLAG)
macro(add_experimental_isel_flag lang)
if (${lang}_HAS_EXPERIMENTAL_ISEL_FLAG)
set(${lang}_FLAGS "-fno-experimental-isel ${${lang}_FLAGS}")
endif()
endmacro(add_experimental_isel_flag)
add_experimental_isel_flag(C)
add_experimental_isel_flag(CXX)
endif()
write_compiler_information(C)
write_compiler_information(CXX)
+16
View File
@@ -0,0 +1,16 @@
if (${OPENMP_STANDALONE_BUILD})
# From HandleLLVMOptions.cmake
function(append_if condition value)
if (${condition})
foreach(variable ${ARGN})
set(${variable} "${${variable}} ${value}" PARENT_SCOPE)
endforeach(variable)
endif()
endfunction()
endif()
if (${OPENMP_ENABLE_WERROR})
append_if(OPENMP_HAVE_WERROR_FLAG "-Werror" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
endif()
append_if(OPENMP_HAVE_STD_CPP11_FLAG "-std=c++11" CMAKE_CXX_FLAGS)
+178
View File
@@ -0,0 +1,178 @@
# Keep track if we have all dependencies.
set(ENABLE_CHECK_TARGETS TRUE)
# Function to find required dependencies for testing.
function(find_standalone_test_dependencies)
include(FindPythonInterp)
if (NOT PYTHONINTERP_FOUND)
message(STATUS "Could not find Python.")
message(WARNING "The check targets will not be available!")
set(ENABLE_CHECK_TARGETS FALSE PARENT_SCOPE)
return()
endif()
# Find executables.
find_program(OPENMP_LLVM_LIT_EXECUTABLE
NAMES llvm-lit lit.py lit
PATHS ${OPENMP_LLVM_TOOLS_DIR})
if (NOT OPENMP_LLVM_LIT_EXECUTABLE)
message(STATUS "Cannot find llvm-lit.")
message(STATUS "Please put llvm-lit in your PATH, set OPENMP_LLVM_LIT_EXECUTABLE to its full path, or point OPENMP_LLVM_TOOLS_DIR to its directory.")
message(WARNING "The check targets will not be available!")
set(ENABLE_CHECK_TARGETS FALSE PARENT_SCOPE)
return()
endif()
find_program(OPENMP_FILECHECK_EXECUTABLE
NAMES FileCheck
PATHS ${OPENMP_LLVM_TOOLS_DIR})
if (NOT OPENMP_FILECHECK_EXECUTABLE)
message(STATUS "Cannot find FileCheck.")
message(STATUS "Please put FileCheck in your PATH, set OPENMP_FILECHECK_EXECUTABLE to its full path, or point OPENMP_LLVM_TOOLS_DIR to its directory.")
message(WARNING "The check targets will not be available!")
set(ENABLE_CHECK_TARGETS FALSE PARENT_SCOPE)
return()
endif()
endfunction()
if (${OPENMP_STANDALONE_BUILD})
find_standalone_test_dependencies()
# Make sure we can use the console pool for recent CMake and Ninja > 1.5.
if (CMAKE_VERSION VERSION_LESS 3.1.20141117)
set(cmake_3_2_USES_TERMINAL)
else()
set(cmake_3_2_USES_TERMINAL USES_TERMINAL)
endif()
# Set lit arguments.
set(DEFAULT_LIT_ARGS "-sv --show-unsupported --show-xfail")
if (MSVC OR XCODE)
set(DEFAULT_LIT_ARGS "${DEFAULT_LIT_ARGS} --no-progress-bar")
endif()
set(OPENMP_LIT_ARGS "${DEFAULT_LIT_ARGS}" CACHE STRING "Options for lit.")
separate_arguments(OPENMP_LIT_ARGS)
else()
set(OPENMP_FILECHECK_EXECUTABLE ${LLVM_RUNTIME_OUTPUT_INTDIR}/FileCheck)
endif()
# Macro to extract information about compiler from file. (no own scope)
macro(extract_test_compiler_information lang file)
file(READ ${file} information)
list(GET information 0 path)
list(GET information 1 id)
list(GET information 2 version)
list(GET information 3 openmp_flags)
set(OPENMP_TEST_${lang}_COMPILER_PATH ${path})
set(OPENMP_TEST_${lang}_COMPILER_ID ${id})
set(OPENMP_TEST_${lang}_COMPILER_VERSION ${version})
set(OPENMP_TEST_${lang}_COMPILER_OPENMP_FLAGS ${openmp_flags})
endmacro()
# Function to set variables with information about the test compiler.
function(set_test_compiler_information dir)
extract_test_compiler_information(C ${dir}/CCompilerInformation.txt)
extract_test_compiler_information(CXX ${dir}/CXXCompilerInformation.txt)
if (NOT("${OPENMP_TEST_C_COMPILER_ID}" STREQUAL "${OPENMP_TEST_CXX_COMPILER_ID}" AND
"${OPENMP_TEST_C_COMPILER_VERSION}" STREQUAL "${OPENMP_TEST_CXX_COMPILER_VERSION}"))
message(STATUS "Test compilers for C and C++ don't match.")
message(WARNING "The check targets will not be available!")
set(ENABLE_CHECK_TARGETS FALSE PARENT_SCOPE)
else()
set(OPENMP_TEST_COMPILER_ID "${OPENMP_TEST_C_COMPILER_ID}" PARENT_SCOPE)
set(OPENMP_TEST_COMPILER_VERSION "${OPENMP_TEST_C_COMPILER_VERSION}" PARENT_SCOPE)
set(OPENMP_TEST_COMPILER_OPENMP_FLAGS "${OPENMP_TEST_C_COMPILER_OPENMP_FLAGS}" PARENT_SCOPE)
# Determine major version.
string(REGEX MATCH "[0-9]+" major "${OPENMP_TEST_C_COMPILER_VERSION}")
set(OPENMP_TEST_COMPILER_VERSION_MAJOR "${major}" PARENT_SCOPE)
endif()
endfunction()
if (${OPENMP_STANDALONE_BUILD})
# Detect compiler that should be used for testing.
# We cannot use ExternalProject_Add() because its configuration runs when this
# project is built which is too late for detecting the compiler...
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/DetectTestCompiler)
execute_process(
COMMAND ${CMAKE_COMMAND} ${CMAKE_CURRENT_LIST_DIR}/DetectTestCompiler
-DCMAKE_C_COMPILER=${OPENMP_TEST_C_COMPILER}
-DCMAKE_CXX_COMPILER=${OPENMP_TEST_CXX_COMPILER}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/DetectTestCompiler
OUTPUT_VARIABLE DETECT_COMPILER_OUT
ERROR_VARIABLE DETECT_COMPILER_ERR
RESULT_VARIABLE DETECT_COMPILER_RESULT)
if (DETECT_COMPILER_RESULT)
message(STATUS "Could not detect test compilers.")
message(WARNING "The check targets will not be available!")
set(ENABLE_CHECK_TARGETS FALSE)
else()
set_test_compiler_information(${CMAKE_CURRENT_BINARY_DIR}/DetectTestCompiler)
endif()
else()
# Set the information that we know.
set(OPENMP_TEST_COMPILER_ID "Clang")
# Cannot use CLANG_VERSION because we are not guaranteed that this is already set.
set(OPENMP_TEST_COMPILER_VERSION "${LLVM_VERSION}")
set(OPENMP_TEST_COMPILER_VERSION_MAJOR "${LLVM_MAJOR_VERSION}")
# TODO: Implement blockaddress in GlobalISel and remove this flag!
set(OPENMP_TEST_COMPILER_OPENMP_FLAGS "-fopenmp -fno-experimental-isel")
endif()
# Function to set compiler features for use in lit.
function(set_test_compiler_features)
if ("${OPENMP_TEST_COMPILER_ID}" STREQUAL "GNU")
set(comp "gcc")
elseif ("${OPENMP_TEST_COMPILER_ID}" STREQUAL "Intel")
set(comp "icc")
else()
# Just use the lowercase of the compiler ID as fallback.
string(TOLOWER "${OPENMP_TEST_COMPILER_ID}" comp)
endif()
set(OPENMP_TEST_COMPILER_FEATURES "['${comp}', '${comp}-${OPENMP_TEST_COMPILER_VERSION_MAJOR}', '${comp}-${OPENMP_TEST_COMPILER_VERSION}']" PARENT_SCOPE)
endfunction()
set_test_compiler_features()
# Function to add a testsuite for an OpenMP runtime library.
function(add_openmp_testsuite target comment)
if (NOT ENABLE_CHECK_TARGETS)
add_custom_target(${target}
COMMAND ${CMAKE_COMMAND} -E echo "${target} does nothing, dependencies not found.")
message(STATUS "${target} does nothing.")
return()
endif()
cmake_parse_arguments(ARG "" "" "DEPENDS" ${ARGN})
# EXCLUDE_FROM_ALL excludes the test ${target} out of check-openmp.
if (NOT EXCLUDE_FROM_ALL)
# Register the testsuites and depends for the check-openmp rule.
set_property(GLOBAL APPEND PROPERTY OPENMP_LIT_TESTSUITES ${ARG_UNPARSED_ARGUMENTS})
set_property(GLOBAL APPEND PROPERTY OPENMP_LIT_DEPENDS ${ARG_DEPENDS})
endif()
if (${OPENMP_STANDALONE_BUILD})
add_custom_target(${target}
COMMAND ${PYTHON_EXECUTABLE} ${OPENMP_LLVM_LIT_EXECUTABLE} ${OPENMP_LIT_ARGS} ${ARG_UNPARSED_ARGUMENTS}
COMMENT ${comment}
DEPENDS ${ARG_DEPENDS}
${cmake_3_2_USES_TERMINAL}
)
else()
add_lit_testsuite(${target}
${comment}
${ARG_UNPARSED_ARGUMENTS}
DEPENDS clang clang-headers FileCheck ${ARG_DEPENDS}
)
endif()
endfunction()
function(construct_check_openmp_target)
get_property(OPENMP_LIT_TESTSUITES GLOBAL PROPERTY OPENMP_LIT_TESTSUITES)
get_property(OPENMP_LIT_DEPENDS GLOBAL PROPERTY OPENMP_LIT_DEPENDS)
# We already added the testsuites themselves, no need to do that again.
set(EXCLUDE_FROM_ALL True)
add_openmp_testsuite(check-openmp "Running OpenMP tests" ${OPENMP_LIT_TESTSUITES} DEPENDS ${OPENMP_LIT_DEPENDS})
endfunction()
+6
View File
@@ -0,0 +1,6 @@
include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
check_c_compiler_flag(-Werror OPENMP_HAVE_WERROR_FLAG)
check_cxx_compiler_flag(-std=c++11 OPENMP_HAVE_STD_CPP11_FLAG)
+72
View File
@@ -0,0 +1,72 @@
##===----------------------------------------------------------------------===##
#
# 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.
#
##===----------------------------------------------------------------------===##
#
# Build offloading library and related plugins.
#
##===----------------------------------------------------------------------===##
if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
message(FATAL_ERROR "Direct configuration not supported, please use parent directory!")
endif()
# Add cmake directory to search for custom cmake functions.
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules ${CMAKE_MODULE_PATH})
if(OPENMP_STANDALONE_BUILD)
# Build all libraries into a common place so that tests can find them.
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
endif()
# Message utilities.
include(LibomptargetUtils)
# Get dependencies for the different components of the project.
include(LibomptargetGetDependencies)
# This is a list of all the targets that are supported/tested right now.
set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} aarch64-unknown-linux-gnu")
set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} powerpc64le-ibm-linux-gnu")
set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} powerpc64-ibm-linux-gnu")
set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} x86_64-pc-linux-gnu")
set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} nvptx64-nvidia-cuda")
# Once the plugins for the different targets are validated, they will be added to
# the list of supported targets in the current system.
set (LIBOMPTARGET_SYSTEM_TARGETS "")
# Set base directories - required for lit to locate the tests.
set(LIBOMPTARGET_BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(LIBOMPTARGET_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
# If building this library in debug mode, we define a macro to enable
# dumping progress messages at runtime.
string( TOLOWER "${CMAKE_BUILD_TYPE}" LIBOMPTARGET_CMAKE_BUILD_TYPE)
if(LIBOMPTARGET_CMAKE_BUILD_TYPE MATCHES debug)
add_definitions(-DOMPTARGET_DEBUG)
add_definitions(-g)
add_definitions(-O0)
endif()
include_directories(include)
# Build target agnostic offloading library.
add_subdirectory(src)
# Retrieve the path to the resulting library so that it can be used for
# testing.
get_target_property(LIBOMPTARGET_LIBRARY_DIR omptarget LIBRARY_OUTPUT_DIRECTORY)
if(NOT LIBOMPTARGET_LIBRARY_DIR)
set(LIBOMPTARGET_LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
endif()
# Build offloading plugins and device RTLs if they are available.
add_subdirectory(plugins)
# Add tests.
add_subdirectory(test)
+73
View File
@@ -0,0 +1,73 @@
README for the LLVM* OpenMP* Offloading Runtime Library (libomptarget)
======================================================================
How to Build the LLVM* OpenMP* Offloading Runtime Library (libomptarget)
========================================================================
In-tree build:
$ cd where-you-want-to-live
Check out openmp (libomptarget lives under ./libomptarget) into llvm/projects
$ cd where-you-want-to-build
$ mkdir build && cd build
$ cmake path/to/llvm -DCMAKE_C_COMPILER=<C compiler> -DCMAKE_CXX_COMPILER=<C++ compiler>
$ make omptarget
Out-of-tree build:
$ cd where-you-want-to-live
Check out openmp (libomptarget lives under ./libomptarget)
$ cd where-you-want-to-live/openmp/libomptarget
$ mkdir build && cd build
$ cmake path/to/openmp -DCMAKE_C_COMPILER=<C compiler> -DCMAKE_CXX_COMPILER=<C++ compiler>
$ make
For details about building, please look at README.rst in the parent directory.
Architectures Supported
=======================
The current library has been only tested in Linux operating system and the
following host architectures:
* Intel(R) 64 architecture
* IBM(R) Power architecture (big endian)
* IBM(R) Power architecture (little endian)
* ARM(R) AArch64 architecture (little endian)
The currently supported offloading device architectures are:
* Intel(R) 64 architecture (generic 64-bit plugin - mostly for testing purposes)
* IBM(R) Power architecture (big endian) (generic 64-bit plugin - mostly for testing purposes)
* IBM(R) Power architecture (little endian) (generic 64-bit plugin - mostly for testing purposes)
* ARM(R) AArch64 architecture (little endian) (generic 64-bit plugin - mostly for testing purposes)
* CUDA(R) enabled 64-bit NVIDIA(R) GPU architectures
Supported RTL Build Configurations
==================================
Supported Architectures: Intel(R) 64, IBM(R) Power 7 and Power 8
---------------------------
| gcc | clang |
--------------|------------|------------|
| Linux* OS | Yes(1) | Yes(2) |
-----------------------------------------
(1) gcc version 4.8.2 or later is supported.
(2) clang version 3.7 or later is supported.
Front-end Compilers that work with this RTL
===========================================
The following compilers are known to do compatible code generation for
this RTL:
- clang (from https://github.com/clang-ykt )
- clang (development branch at http://clang.llvm.org - several features still
under development)
-----------------------------------------------------------------------
Notices
=======
This library and related compiler support is still under development, so the
employed interface is likely to change in the future.
*Other names and brands may be claimed as the property of others.
@@ -0,0 +1,124 @@
#
#//===----------------------------------------------------------------------===//
#//
#// 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.
#//
#//===----------------------------------------------------------------------===//
#
# Try to detect in the system several dependencies required by the different
# components of libomptarget. These are the dependencies we have:
#
# libelf : required by some targets to handle the ELF files at runtime.
# libffi : required to launch target kernels given function and argument
# pointers.
# CUDA : required to control offloading to NVIDIA GPUs.
include (FindPackageHandleStandardArgs)
################################################################################
# Looking for libelf...
################################################################################
find_path (
LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIR
NAMES
libelf.h
PATHS
/usr/include
/usr/local/include
/opt/local/include
/sw/include
ENV CPATH
PATH_SUFFIXES
libelf)
find_library (
LIBOMPTARGET_DEP_LIBELF_LIBRARIES
NAMES
elf
PATHS
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
ENV LIBRARY_PATH
ENV LD_LIBRARY_PATH)
set(LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIRS ${LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIR})
find_package_handle_standard_args(
LIBOMPTARGET_DEP_LIBELF
DEFAULT_MSG
LIBOMPTARGET_DEP_LIBELF_LIBRARIES
LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIRS)
mark_as_advanced(
LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIRS
LIBOMPTARGET_DEP_LIBELF_LIBRARIES)
################################################################################
# Looking for libffi...
################################################################################
find_package(PkgConfig)
pkg_check_modules(LIBOMPTARGET_SEARCH_LIBFFI QUIET libffi)
find_path (
LIBOMPTARGET_DEP_LIBFFI_INCLUDE_DIR
NAMES
ffi.h
HINTS
${LIBOMPTARGET_SEARCH_LIBFFI_INCLUDEDIR}
${LIBOMPTARGET_SEARCH_LIBFFI_INCLUDE_DIRS}
PATHS
/usr/include
/usr/local/include
/opt/local/include
/sw/include
ENV CPATH)
# Don't bother look for the library if the header files were not found.
if (LIBOMPTARGET_DEP_LIBFFI_INCLUDE_DIR)
find_library (
LIBOMPTARGET_DEP_LIBFFI_LIBRARIES
NAMES
ffi
HINTS
${LIBOMPTARGET_SEARCH_LIBFFI_LIBDIR}
${LIBOMPTARGET_SEARCH_LIBFFI_LIBRARY_DIRS}
PATHS
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
ENV LIBRARY_PATH
ENV LD_LIBRARY_PATH)
endif()
set(LIBOMPTARGET_DEP_LIBFFI_INCLUDE_DIRS ${LIBOMPTARGET_DEP_LIBFFI_INCLUDE_DIR})
find_package_handle_standard_args(
LIBOMPTARGET_DEP_LIBFFI
DEFAULT_MSG
LIBOMPTARGET_DEP_LIBFFI_LIBRARIES
LIBOMPTARGET_DEP_LIBFFI_INCLUDE_DIRS)
mark_as_advanced(
LIBOMPTARGET_DEP_LIBFFI_INCLUDE_DIRS
LIBOMPTARGET_DEP_LIBFFI_LIBRARIES)
################################################################################
# Looking for CUDA...
################################################################################
find_package(CUDA QUIET)
set(LIBOMPTARGET_DEP_CUDA_FOUND ${CUDA_FOUND})
set(LIBOMPTARGET_DEP_CUDA_LIBRARIES ${CUDA_LIBRARIES})
set(LIBOMPTARGET_DEP_CUDA_INCLUDE_DIRS ${CUDA_INCLUDE_DIRS})
mark_as_advanced(
LIBOMPTARGET_DEP_CUDA_FOUND
LIBOMPTARGET_DEP_CUDA_INCLUDE_DIRS
LIBOMPTARGET_DEP_CUDA_LIBRARIES)
@@ -0,0 +1,28 @@
#
#//===----------------------------------------------------------------------===//
#//
#// 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.
#//
#//===----------------------------------------------------------------------===//
#
# void libomptarget_say(string message_to_user);
# - prints out message_to_user
macro(libomptarget_say message_to_user)
message(STATUS "LIBOMPTARGET: ${message_to_user}")
endmacro()
# void libomptarget_warning_say(string message_to_user);
# - prints out message_to_user with a warning
macro(libomptarget_warning_say message_to_user)
message(WARNING "LIBOMPTARGET: ${message_to_user}")
endmacro()
# void libomptarget_error_say(string message_to_user);
# - prints out message_to_user with an error and exits cmake
macro(libomptarget_error_say message_to_user)
message(FATAL_ERROR "LIBOMPTARGET: ${message_to_user}")
endmacro()
+237
View File
@@ -0,0 +1,237 @@
//===-------- omptarget.h - Target independent OpenMP target RTL -- 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.
//
//===----------------------------------------------------------------------===//
//
// Interface to be used by Clang during the codegen of a
// target region.
//
//===----------------------------------------------------------------------===//
#ifndef _OMPTARGET_H_
#define _OMPTARGET_H_
#include <stdint.h>
#include <stddef.h>
#define OFFLOAD_SUCCESS (0)
#define OFFLOAD_FAIL (~0)
#define OFFLOAD_DEVICE_DEFAULT -1
#define HOST_DEVICE -10
/// Data attributes for each data reference used in an OpenMP target region.
enum tgt_map_type {
// No flags
OMP_TGT_MAPTYPE_NONE = 0x000,
// copy data from host to device
OMP_TGT_MAPTYPE_TO = 0x001,
// copy data from device to host
OMP_TGT_MAPTYPE_FROM = 0x002,
// copy regardless of the reference count
OMP_TGT_MAPTYPE_ALWAYS = 0x004,
// force unmapping of data
OMP_TGT_MAPTYPE_DELETE = 0x008,
// map the pointer as well as the pointee
OMP_TGT_MAPTYPE_PTR_AND_OBJ = 0x010,
// pass device base address to kernel
OMP_TGT_MAPTYPE_TARGET_PARAM = 0x020,
// return base device address of mapped data
OMP_TGT_MAPTYPE_RETURN_PARAM = 0x040,
// private variable - not mapped
OMP_TGT_MAPTYPE_PRIVATE = 0x080,
// copy by value - not mapped
OMP_TGT_MAPTYPE_LITERAL = 0x100,
// mapping is implicit
OMP_TGT_MAPTYPE_IMPLICIT = 0x200,
// member of struct, member given by 16 MSBs - 1
OMP_TGT_MAPTYPE_MEMBER_OF = 0xffff000000000000
};
enum OpenMPOffloadingDeclareTargetFlags {
/// Mark the entry as having a 'link' attribute.
OMP_DECLARE_TARGET_LINK = 0x01,
/// Mark the entry as being a global constructor.
OMP_DECLARE_TARGET_CTOR = 0x02,
/// Mark the entry as being a global destructor.
OMP_DECLARE_TARGET_DTOR = 0x04
};
/// This struct is a record of an entry point or global. For a function
/// entry point the size is expected to be zero
struct __tgt_offload_entry {
void *addr; // Pointer to the offload entry info (function or global)
char *name; // Name of the function or global
size_t size; // Size of the entry info (0 if it is a function)
int32_t flags; // Flags associated with the entry, e.g. 'link'.
int32_t reserved; // Reserved, to be used by the runtime library.
};
/// This struct is a record of the device image information
struct __tgt_device_image {
void *ImageStart; // Pointer to the target code start
void *ImageEnd; // Pointer to the target code end
__tgt_offload_entry *EntriesBegin; // Begin of table with all target entries
__tgt_offload_entry *EntriesEnd; // End of table (non inclusive)
};
/// This struct is a record of all the host code that may be offloaded to a
/// target.
struct __tgt_bin_desc {
int32_t NumDeviceImages; // Number of device types supported
__tgt_device_image *DeviceImages; // Array of device images (1 per dev. type)
__tgt_offload_entry *HostEntriesBegin; // Begin of table with all host entries
__tgt_offload_entry *HostEntriesEnd; // End of table (non inclusive)
};
/// This struct contains the offload entries identified by the target runtime
struct __tgt_target_table {
__tgt_offload_entry *EntriesBegin; // Begin of the table with all the entries
__tgt_offload_entry
*EntriesEnd; // End of the table with all the entries (non inclusive)
};
#ifdef __cplusplus
extern "C" {
#endif
// Implemented in libomp, they are called from within __tgt_* functions.
int omp_get_default_device(void) __attribute__((weak));
int32_t __kmpc_omp_taskwait(void *loc_ref, int32_t gtid) __attribute__((weak));
int omp_get_num_devices(void);
int omp_get_initial_device(void);
void *omp_target_alloc(size_t size, int device_num);
void omp_target_free(void *device_ptr, int device_num);
int omp_target_is_present(void *ptr, int device_num);
int omp_target_memcpy(void *dst, void *src, size_t length, size_t dst_offset,
size_t src_offset, int dst_device, int src_device);
int omp_target_memcpy_rect(void *dst, void *src, size_t element_size,
int num_dims, const size_t *volume, const size_t *dst_offsets,
const size_t *src_offsets, const size_t *dst_dimensions,
const size_t *src_dimensions, int dst_device, int src_device);
int omp_target_associate_ptr(void *host_ptr, void *device_ptr, size_t size,
size_t device_offset, int device_num);
int omp_target_disassociate_ptr(void *host_ptr, int device_num);
/// adds a target shared library to the target execution image
void __tgt_register_lib(__tgt_bin_desc *desc);
/// removes a target shared library from the target execution image
void __tgt_unregister_lib(__tgt_bin_desc *desc);
// creates the host to target data mapping, stores it in the
// libomptarget.so internal structure (an entry in a stack of data maps) and
// passes the data to the device;
void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes,
int64_t *arg_types);
void __tgt_target_data_begin_nowait(int64_t device_id, int32_t arg_num,
void **args_base, void **args,
int64_t *arg_sizes, int64_t *arg_types,
int32_t depNum, void *depList,
int32_t noAliasDepNum,
void *noAliasDepList);
// passes data from the target, release target memory and destroys the
// host-target mapping (top entry from the stack of data maps) created by
// the last __tgt_target_data_begin
void __tgt_target_data_end(int64_t device_id, int32_t arg_num, void **args_base,
void **args, int64_t *arg_sizes, int64_t *arg_types);
void __tgt_target_data_end_nowait(int64_t device_id, int32_t arg_num,
void **args_base, void **args,
int64_t *arg_sizes, int64_t *arg_types,
int32_t depNum, void *depList,
int32_t noAliasDepNum, void *noAliasDepList);
/// passes data to/from the target
void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes,
int64_t *arg_types);
void __tgt_target_data_update_nowait(int64_t device_id, int32_t arg_num,
void **args_base, void **args,
int64_t *arg_sizes, int64_t *arg_types,
int32_t depNum, void *depList,
int32_t noAliasDepNum,
void *noAliasDepList);
// Performs the same actions as data_begin in case arg_num is non-zero
// and initiates run of offloaded region on target platform; if arg_num
// is non-zero after the region execution is done it also performs the
// same action as data_end above. The following types are used; this
// function returns 0 if it was able to transfer the execution to a
// target and an int different from zero otherwise.
int __tgt_target(int64_t device_id, void *host_ptr, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes,
int64_t *arg_types);
int __tgt_target_nowait(int64_t device_id, void *host_ptr, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes,
int64_t *arg_types, int32_t depNum, void *depList,
int32_t noAliasDepNum, void *noAliasDepList);
int __tgt_target_teams(int64_t device_id, void *host_ptr, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes,
int64_t *arg_types, int32_t num_teams,
int32_t thread_limit);
int __tgt_target_teams_nowait(int64_t device_id, void *host_ptr,
int32_t arg_num, void **args_base, void **args,
int64_t *arg_sizes, int64_t *arg_types,
int32_t num_teams, int32_t thread_limit,
int32_t depNum, void *depList,
int32_t noAliasDepNum, void *noAliasDepList);
void __kmpc_push_target_tripcount(int64_t device_id, uint64_t loop_tripcount);
#ifdef __cplusplus
}
#endif
#ifdef OMPTARGET_DEBUG
#include <stdio.h>
#define DEBUGP(prefix, ...) \
{ \
fprintf(stderr, "%s --> ", prefix); \
fprintf(stderr, __VA_ARGS__); \
}
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif
#include <inttypes.h>
#define DPxMOD "0x%0*" PRIxPTR
#define DPxPTR(ptr) ((int)(2*sizeof(uintptr_t))), ((uintptr_t) (ptr))
/*
* To printf a pointer in hex with a fixed width of 16 digits and a leading 0x,
* use printf("ptr=" DPxMOD "...\n", DPxPTR(ptr));
*
* DPxMOD expands to:
* "0x%0*" PRIxPTR
* where PRIxPTR expands to an appropriate modifier for the type uintptr_t on a
* specific platform, e.g. "lu" if uintptr_t is typedef'd as unsigned long:
* "0x%0*lu"
*
* Ultimately, the whole statement expands to:
* printf("ptr=0x%0*lu...\n", // the 0* modifier expects an extra argument
* // specifying the width of the output
* (int)(2*sizeof(uintptr_t)), // the extra argument specifying the width
* // 8 digits for 32bit systems
* // 16 digits for 64bit
* (uintptr_t) ptr);
*/
#else
#define DEBUGP(prefix, ...) \
{}
#endif
#ifdef __cplusplus
#define EXTERN extern "C"
#else
#define EXTERN extern
#endif
#endif // _OMPTARGET_H_
+92
View File
@@ -0,0 +1,92 @@
//===-- omptargetplugin.h - Target dependent OpenMP Plugin API --*- 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.
//
//===----------------------------------------------------------------------===//
//
// This file defines an interface between target independent OpenMP offload
// runtime library libomptarget and target dependent plugin.
//
//===----------------------------------------------------------------------===//
#ifndef _OMPTARGETPLUGIN_H_
#define _OMPTARGETPLUGIN_H_
#include <omptarget.h>
#ifdef __cplusplus
extern "C" {
#endif
// Return the number of available devices of the type supported by the
// target RTL.
int32_t __tgt_rtl_number_of_devices(void);
// Return an integer different from zero if the provided device image can be
// supported by the runtime. The functionality is similar to comparing the
// result of __tgt__rtl__load__binary to NULL. However, this is meant to be a
// lightweight query to determine if the RTL is suitable for an image without
// having to load the library, which can be expensive.
int32_t __tgt_rtl_is_valid_binary(__tgt_device_image *Image);
// Initialize the specified device. In case of success return 0; otherwise
// return an error code.
int32_t __tgt_rtl_init_device(int32_t ID);
// Pass an executable image section described by image to the specified
// device and prepare an address table of target entities. In case of error,
// return NULL. Otherwise, return a pointer to the built address table.
// Individual entries in the table may also be NULL, when the corresponding
// offload region is not supported on the target device.
__tgt_target_table *__tgt_rtl_load_binary(int32_t ID,
__tgt_device_image *Image);
// Allocate data on the particular target device, of the specified size.
// HostPtr is a address of the host data the allocated target data
// will be associated with (HostPtr may be NULL if it is not known at
// allocation time, like for example it would be for target data that
// is allocated by omp_target_alloc() API). Return address of the
// allocated data on the target that will be used by libomptarget.so to
// initialize the target data mapping structures. These addresses are
// used to generate a table of target variables to pass to
// __tgt_rtl_run_region(). The __tgt_rtl_data_alloc() returns NULL in
// case an error occurred on the target device.
void *__tgt_rtl_data_alloc(int32_t ID, int64_t Size, void *HostPtr);
// Pass the data content to the target device using the target address.
// In case of success, return zero. Otherwise, return an error code.
int32_t __tgt_rtl_data_submit(int32_t ID, void *TargetPtr, void *HostPtr,
int64_t Size);
// Retrieve the data content from the target device using its address.
// In case of success, return zero. Otherwise, return an error code.
int32_t __tgt_rtl_data_retrieve(int32_t ID, void *HostPtr, void *TargetPtr,
int64_t Size);
// De-allocate the data referenced by target ptr on the device. In case of
// success, return zero. Otherwise, return an error code.
int32_t __tgt_rtl_data_delete(int32_t ID, void *TargetPtr);
// Transfer control to the offloaded entry Entry on the target device.
// Args and Offsets are arrays of NumArgs size of target addresses and
// offsets. An offset should be added to the target address before passing it
// to the outlined function on device side. In case of success, return zero.
// Otherwise, return an error code.
int32_t __tgt_rtl_run_target_region(int32_t ID, void *Entry, void **Args,
ptrdiff_t *Offsets, int32_t NumArgs);
// Similar to __tgt_rtl_run_target_region, but additionally specify the
// number of teams to be created and a number of threads in each team.
int32_t __tgt_rtl_run_target_team_region(int32_t ID, void *Entry, void **Args,
ptrdiff_t *Offsets, int32_t NumArgs,
int32_t NumTeams, int32_t ThreadLimit,
uint64_t loop_tripcount);
#ifdef __cplusplus
}
#endif
#endif // _OMPTARGETPLUGIN_H_
+72
View File
@@ -0,0 +1,72 @@
##===----------------------------------------------------------------------===##
#
# 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.
#
##===----------------------------------------------------------------------===##
#
# Build plugins for the user system if available.
#
##===----------------------------------------------------------------------===##
# void build_generic_elf64(string tmachine, string tmachine_name, string tmachine_libname, string elf_machine_id);
# - build a plugin for an ELF based generic 64-bit target based on libffi.
# - tmachine: name of the machine processor as used in the cmake build system.
# - tmachine_name: name of the machine to be printed with the debug messages.
# - tmachine_libname: machine name to be appended to the plugin library name.
macro(build_generic_elf64 tmachine tmachine_name tmachine_libname tmachine_triple elf_machine_id)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "${tmachine}$")
if(LIBOMPTARGET_DEP_LIBELF_FOUND)
if(LIBOMPTARGET_DEP_LIBFFI_FOUND)
libomptarget_say("Building ${tmachine_name} offloading plugin.")
include_directories(${LIBOMPTARGET_DEP_LIBFFI_INCLUDE_DIR})
include_directories(${LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIR})
# Define macro to be used as prefix of the runtime messages for this target.
add_definitions("-DTARGET_NAME=${tmachine_name}")
# Define macro with the ELF ID for this target.
add_definitions("-DTARGET_ELF_ID=${elf_machine_id}")
add_library("omptarget.rtl.${tmachine_libname}" SHARED
${CMAKE_CURRENT_SOURCE_DIR}/../generic-elf-64bit/src/rtl.cpp)
# Install plugin under the lib destination folder.
install(TARGETS "omptarget.rtl.${tmachine_libname}"
LIBRARY DESTINATION lib${OPENMP_LIBDIR_SUFFIX})
target_link_libraries(
"omptarget.rtl.${tmachine_libname}"
${LIBOMPTARGET_DEP_LIBFFI_LIBRARIES}
${LIBOMPTARGET_DEP_LIBELF_LIBRARIES}
dl
"-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../exports")
# Report to the parent scope that we are building a plugin.
set(LIBOMPTARGET_SYSTEM_TARGETS
"${LIBOMPTARGET_SYSTEM_TARGETS} ${tmachine_triple}" PARENT_SCOPE)
else(LIBOMPTARGET_DEP_LIBFFI_FOUND)
libomptarget_say("Not building ${tmachine_name} offloading plugin: libffi dependency not found.")
endif(LIBOMPTARGET_DEP_LIBFFI_FOUND)
else(LIBOMPTARGET_DEP_LIBELF_FOUND)
libomptarget_say("Not building ${tmachine_name} offloading plugin: libelf dependency not found.")
endif(LIBOMPTARGET_DEP_LIBELF_FOUND)
else()
libomptarget_say("Not building ${tmachine_name} offloading plugin: machine not found in the system.")
endif()
endmacro()
add_subdirectory(aarch64)
add_subdirectory(cuda)
add_subdirectory(ppc64)
add_subdirectory(ppc64le)
add_subdirectory(x86_64)
# Make sure the parent scope can see the plugins that will be created.
set(LIBOMPTARGET_SYSTEM_TARGETS "${LIBOMPTARGET_SYSTEM_TARGETS}" PARENT_SCOPE)
@@ -0,0 +1,18 @@
##===----------------------------------------------------------------------===##
#
# 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.
#
##===----------------------------------------------------------------------===##
#
# Build a plugin for an aarch64 machine if available.
#
##===----------------------------------------------------------------------===##
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
build_generic_elf64("aarch64" "aarch64" "aarch64" "aarch64-unknown-linux-gnu" "183")
else()
libomptarget_say("Not building aarch64 offloading plugin: machine not found in the system.")
endif()
+73
View File
@@ -0,0 +1,73 @@
//===-- elf_common.c - Common ELF functionality -------------------*- 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.
//
//===----------------------------------------------------------------------===//
//
// Common ELF functionality for target plugins.
// Must be included in the plugin source file AFTER omptarget.h has been
// included and macro DP(...) has been defined.
// .
//
//===----------------------------------------------------------------------===//
#if !(defined(_OMPTARGET_H_) && defined(DP))
#error Include elf_common.c in the plugin source AFTER omptarget.h has been\
included and macro DP(...) has been defined.
#endif
#include <elf.h>
#include <libelf.h>
// Check whether an image is valid for execution on target_id
static inline int32_t elf_check_machine(__tgt_device_image *image,
uint16_t target_id) {
// Is the library version incompatible with the header file?
if (elf_version(EV_CURRENT) == EV_NONE) {
DP("Incompatible ELF library!\n");
return 0;
}
char *img_begin = (char *)image->ImageStart;
char *img_end = (char *)image->ImageEnd;
size_t img_size = img_end - img_begin;
// Obtain elf handler
Elf *e = elf_memory(img_begin, img_size);
if (!e) {
DP("Unable to get ELF handle: %s!\n", elf_errmsg(-1));
return 0;
}
// Check if ELF is the right kind.
if (elf_kind(e) != ELF_K_ELF) {
DP("Unexpected ELF type!\n");
return 0;
}
Elf64_Ehdr *eh64 = elf64_getehdr(e);
Elf32_Ehdr *eh32 = elf32_getehdr(e);
if (!eh64 && !eh32) {
DP("Unable to get machine ID from ELF file!\n");
elf_end(e);
return 0;
}
uint16_t MachineID;
if (eh64 && !eh32)
MachineID = eh64->e_machine;
else if (eh32 && !eh64)
MachineID = eh32->e_machine;
else {
DP("Ambiguous ELF header!\n");
elf_end(e);
return 0;
}
elf_end(e);
return MachineID == target_id;
}
+50
View File
@@ -0,0 +1,50 @@
##===----------------------------------------------------------------------===##
#
# 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.
#
##===----------------------------------------------------------------------===##
#
# Build a plugin for a CUDA machine if available.
#
##===----------------------------------------------------------------------===##
if(LIBOMPTARGET_DEP_LIBELF_FOUND)
if(LIBOMPTARGET_DEP_CUDA_FOUND)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64)|(ppc64le)$" AND CMAKE_SYSTEM_NAME MATCHES "Linux")
libomptarget_say("Building CUDA offloading plugin.")
# Define the suffix for the runtime messaging dumps.
add_definitions(-DTARGET_NAME=CUDA)
if(LIBOMPTARGET_CMAKE_BUILD_TYPE MATCHES debug)
add_definitions(-DCUDA_ERROR_REPORT)
endif()
include_directories(${LIBOMPTARGET_DEP_CUDA_INCLUDE_DIRS})
include_directories(${LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIRS})
add_library(omptarget.rtl.cuda SHARED src/rtl.cpp)
# Install plugin under the lib destination folder.
install(TARGETS omptarget.rtl.cuda LIBRARY DESTINATION lib${OPENMP_LIBDIR_SUFFIX})
target_link_libraries(omptarget.rtl.cuda
${LIBOMPTARGET_DEP_CUDA_LIBRARIES}
cuda
${LIBOMPTARGET_DEP_LIBELF_LIBRARIES}
"-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../exports")
# Report to the parent scope that we are building a plugin for CUDA.
set(LIBOMPTARGET_SYSTEM_TARGETS "${LIBOMPTARGET_SYSTEM_TARGETS} nvptx64-nvidia-cuda" PARENT_SCOPE)
else()
libomptarget_say("Not building CUDA offloading plugin: only support CUDA in Linux x86_64 or ppc64le hosts.")
endif()
else()
libomptarget_say("Not building CUDA offloading plugin: CUDA not found in system.")
endif()
else(LIBOMPTARGET_DEP_LIBELF_FOUND)
libomptarget_say("Not building CUDA offloading plugin: libelf dependency not found.")
endif(LIBOMPTARGET_DEP_LIBELF_FOUND)
+711
View File
@@ -0,0 +1,711 @@
//===----RTLs/cuda/src/rtl.cpp - Target RTLs Implementation ------- 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.
//
//===----------------------------------------------------------------------===//
//
// RTL for CUDA machine
//
//===----------------------------------------------------------------------===//
#include <cassert>
#include <cstddef>
#include <cuda.h>
#include <cuda_runtime_api.h>
#include <list>
#include <string>
#include <vector>
#include "omptargetplugin.h"
#ifndef TARGET_NAME
#define TARGET_NAME CUDA
#endif
#ifdef OMPTARGET_DEBUG
static int DebugLevel = 0;
#define GETNAME2(name) #name
#define GETNAME(name) GETNAME2(name)
#define DP(...) \
do { \
if (DebugLevel > 0) { \
DEBUGP("Target " GETNAME(TARGET_NAME) " RTL", __VA_ARGS__); \
} \
} while (false)
#else // OMPTARGET_DEBUG
#define DP(...) {}
#endif // OMPTARGET_DEBUG
#include "../../common/elf_common.c"
// Utility for retrieving and printing CUDA error string.
#ifdef CUDA_ERROR_REPORT
#define CUDA_ERR_STRING(err) \
do { \
const char *errStr; \
cuGetErrorString(err, &errStr); \
DP("CUDA error is: %s\n", errStr); \
} while (0)
#else
#define CUDA_ERR_STRING(err) \
{}
#endif
/// Keep entries table per device.
struct FuncOrGblEntryTy {
__tgt_target_table Table;
std::vector<__tgt_offload_entry> Entries;
};
enum ExecutionModeType {
SPMD, // constructors, destructors,
// combined constructs (`teams distribute parallel for [simd]`)
GENERIC, // everything else
NONE
};
/// Use a single entity to encode a kernel and a set of flags
struct KernelTy {
CUfunction Func;
// execution mode of kernel
// 0 - SPMD mode (without master warp)
// 1 - Generic mode (with master warp)
int8_t ExecutionMode;
KernelTy(CUfunction _Func, int8_t _ExecutionMode)
: Func(_Func), ExecutionMode(_ExecutionMode) {}
};
/// List that contains all the kernels.
/// FIXME: we may need this to be per device and per library.
std::list<KernelTy> KernelsList;
/// Class containing all the device information.
class RTLDeviceInfoTy {
std::vector<FuncOrGblEntryTy> FuncGblEntries;
public:
int NumberOfDevices;
std::vector<CUmodule> Modules;
std::vector<CUcontext> Contexts;
// Device properties
std::vector<int> ThreadsPerBlock;
std::vector<int> BlocksPerGrid;
std::vector<int> WarpSize;
// OpenMP properties
std::vector<int> NumTeams;
std::vector<int> NumThreads;
// OpenMP Environment properties
int EnvNumTeams;
int EnvTeamLimit;
//static int EnvNumThreads;
static const int HardTeamLimit = 1<<16; // 64k
static const int HardThreadLimit = 1024;
static const int DefaultNumTeams = 128;
static const int DefaultNumThreads = 128;
// Record entry point associated with device
void addOffloadEntry(int32_t device_id, __tgt_offload_entry entry) {
assert(device_id < (int32_t)FuncGblEntries.size() &&
"Unexpected device id!");
FuncOrGblEntryTy &E = FuncGblEntries[device_id];
E.Entries.push_back(entry);
}
// Return true if the entry is associated with device
bool findOffloadEntry(int32_t device_id, void *addr) {
assert(device_id < (int32_t)FuncGblEntries.size() &&
"Unexpected device id!");
FuncOrGblEntryTy &E = FuncGblEntries[device_id];
for (auto &it : E.Entries) {
if (it.addr == addr)
return true;
}
return false;
}
// Return the pointer to the target entries table
__tgt_target_table *getOffloadEntriesTable(int32_t device_id) {
assert(device_id < (int32_t)FuncGblEntries.size() &&
"Unexpected device id!");
FuncOrGblEntryTy &E = FuncGblEntries[device_id];
int32_t size = E.Entries.size();
// Table is empty
if (!size)
return 0;
__tgt_offload_entry *begin = &E.Entries[0];
__tgt_offload_entry *end = &E.Entries[size - 1];
// Update table info according to the entries and return the pointer
E.Table.EntriesBegin = begin;
E.Table.EntriesEnd = ++end;
return &E.Table;
}
// Clear entries table for a device
void clearOffloadEntriesTable(int32_t device_id) {
assert(device_id < (int32_t)FuncGblEntries.size() &&
"Unexpected device id!");
FuncOrGblEntryTy &E = FuncGblEntries[device_id];
E.Entries.clear();
E.Table.EntriesBegin = E.Table.EntriesEnd = 0;
}
RTLDeviceInfoTy() {
#ifdef OMPTARGET_DEBUG
if (char *envStr = getenv("LIBOMPTARGET_DEBUG")) {
DebugLevel = std::stoi(envStr);
}
#endif // OMPTARGET_DEBUG
DP("Start initializing CUDA\n");
CUresult err = cuInit(0);
if (err != CUDA_SUCCESS) {
DP("Error when initializing CUDA\n");
CUDA_ERR_STRING(err);
return;
}
NumberOfDevices = 0;
err = cuDeviceGetCount(&NumberOfDevices);
if (err != CUDA_SUCCESS) {
DP("Error when getting CUDA device count\n");
CUDA_ERR_STRING(err);
return;
}
if (NumberOfDevices == 0) {
DP("There are no devices supporting CUDA.\n");
return;
}
FuncGblEntries.resize(NumberOfDevices);
Contexts.resize(NumberOfDevices);
ThreadsPerBlock.resize(NumberOfDevices);
BlocksPerGrid.resize(NumberOfDevices);
WarpSize.resize(NumberOfDevices);
NumTeams.resize(NumberOfDevices);
NumThreads.resize(NumberOfDevices);
// Get environment variables regarding teams
char *envStr = getenv("OMP_TEAM_LIMIT");
if (envStr) {
// OMP_TEAM_LIMIT has been set
EnvTeamLimit = std::stoi(envStr);
DP("Parsed OMP_TEAM_LIMIT=%d\n", EnvTeamLimit);
} else {
EnvTeamLimit = -1;
}
envStr = getenv("OMP_NUM_TEAMS");
if (envStr) {
// OMP_NUM_TEAMS has been set
EnvNumTeams = std::stoi(envStr);
DP("Parsed OMP_NUM_TEAMS=%d\n", EnvNumTeams);
} else {
EnvNumTeams = -1;
}
}
~RTLDeviceInfoTy() {
// Close modules
for (auto &module : Modules)
if (module) {
CUresult err = cuModuleUnload(module);
if (err != CUDA_SUCCESS) {
DP("Error when unloading CUDA module\n");
CUDA_ERR_STRING(err);
}
}
// Destroy contexts
for (auto &ctx : Contexts)
if (ctx) {
CUresult err = cuCtxDestroy(ctx);
if (err != CUDA_SUCCESS) {
DP("Error when destroying CUDA context\n");
CUDA_ERR_STRING(err);
}
}
}
};
static RTLDeviceInfoTy DeviceInfo;
#ifdef __cplusplus
extern "C" {
#endif
int32_t __tgt_rtl_is_valid_binary(__tgt_device_image *image) {
return elf_check_machine(image, 190); // EM_CUDA = 190.
}
int32_t __tgt_rtl_number_of_devices() { return DeviceInfo.NumberOfDevices; }
int32_t __tgt_rtl_init_device(int32_t device_id) {
CUdevice cuDevice;
DP("Getting device %d\n", device_id);
CUresult err = cuDeviceGet(&cuDevice, device_id);
if (err != CUDA_SUCCESS) {
DP("Error when getting CUDA device with id = %d\n", device_id);
CUDA_ERR_STRING(err);
return OFFLOAD_FAIL;
}
// Create the context and save it to use whenever this device is selected.
err = cuCtxCreate(&DeviceInfo.Contexts[device_id], CU_CTX_SCHED_BLOCKING_SYNC,
cuDevice);
if (err != CUDA_SUCCESS) {
DP("Error when creating a CUDA context\n");
CUDA_ERR_STRING(err);
return OFFLOAD_FAIL;
}
// scan properties to determine number of threads/block and blocks/grid.
struct cudaDeviceProp Properties;
cudaError_t error = cudaGetDeviceProperties(&Properties, device_id);
if (error != cudaSuccess) {
DP("Error getting device Properties, use defaults\n");
DeviceInfo.BlocksPerGrid[device_id] = RTLDeviceInfoTy::DefaultNumTeams;
DeviceInfo.ThreadsPerBlock[device_id] = RTLDeviceInfoTy::DefaultNumThreads;
DeviceInfo.WarpSize[device_id] = 32;
} else {
// Get blocks per grid
if (Properties.maxGridSize[0] <= RTLDeviceInfoTy::HardTeamLimit) {
DeviceInfo.BlocksPerGrid[device_id] = Properties.maxGridSize[0];
DP("Using %d CUDA blocks per grid\n", Properties.maxGridSize[0]);
} else {
DeviceInfo.BlocksPerGrid[device_id] = RTLDeviceInfoTy::HardTeamLimit;
DP("Max CUDA blocks per grid %d exceeds the hard team limit %d, capping "
"at the hard limit\n", Properties.maxGridSize[0],
RTLDeviceInfoTy::HardTeamLimit);
}
// Get threads per block, exploit threads only along x axis
if (Properties.maxThreadsDim[0] <= RTLDeviceInfoTy::HardThreadLimit) {
DeviceInfo.ThreadsPerBlock[device_id] = Properties.maxThreadsDim[0];
DP("Using %d CUDA threads per block\n", Properties.maxThreadsDim[0]);
if (Properties.maxThreadsDim[0] < Properties.maxThreadsPerBlock) {
DP("(fewer than max per block along all xyz dims %d)\n",
Properties.maxThreadsPerBlock);
}
} else {
DeviceInfo.ThreadsPerBlock[device_id] = RTLDeviceInfoTy::HardThreadLimit;
DP("Max CUDA threads per block %d exceeds the hard thread limit %d, "
"capping at the hard limit\n", Properties.maxThreadsDim[0],
RTLDeviceInfoTy::HardThreadLimit);
}
// Get warp size
DeviceInfo.WarpSize[device_id] = Properties.warpSize;
}
// Adjust teams to the env variables
if (DeviceInfo.EnvTeamLimit > 0 &&
DeviceInfo.BlocksPerGrid[device_id] > DeviceInfo.EnvTeamLimit) {
DeviceInfo.BlocksPerGrid[device_id] = DeviceInfo.EnvTeamLimit;
DP("Capping max CUDA blocks per grid to OMP_TEAM_LIMIT=%d\n",
DeviceInfo.EnvTeamLimit);
}
DP("Max number of CUDA blocks %d, threads %d & warp size %d\n",
DeviceInfo.BlocksPerGrid[device_id], DeviceInfo.ThreadsPerBlock[device_id],
DeviceInfo.WarpSize[device_id]);
// Set default number of teams
if (DeviceInfo.EnvNumTeams > 0) {
DeviceInfo.NumTeams[device_id] = DeviceInfo.EnvNumTeams;
DP("Default number of teams set according to environment %d\n",
DeviceInfo.EnvNumTeams);
} else {
DeviceInfo.NumTeams[device_id] = RTLDeviceInfoTy::DefaultNumTeams;
DP("Default number of teams set according to library's default %d\n",
RTLDeviceInfoTy::DefaultNumTeams);
}
if (DeviceInfo.NumTeams[device_id] > DeviceInfo.BlocksPerGrid[device_id]) {
DeviceInfo.NumTeams[device_id] = DeviceInfo.BlocksPerGrid[device_id];
DP("Default number of teams exceeds device limit, capping at %d\n",
DeviceInfo.BlocksPerGrid[device_id]);
}
// Set default number of threads
DeviceInfo.NumThreads[device_id] = RTLDeviceInfoTy::DefaultNumThreads;
DP("Default number of threads set according to library's default %d\n",
RTLDeviceInfoTy::DefaultNumThreads);
if (DeviceInfo.NumThreads[device_id] >
DeviceInfo.ThreadsPerBlock[device_id]) {
DeviceInfo.NumTeams[device_id] = DeviceInfo.ThreadsPerBlock[device_id];
DP("Default number of threads exceeds device limit, capping at %d\n",
DeviceInfo.ThreadsPerBlock[device_id]);
}
return OFFLOAD_SUCCESS;
}
__tgt_target_table *__tgt_rtl_load_binary(int32_t device_id,
__tgt_device_image *image) {
// Set the context we are using.
CUresult err = cuCtxSetCurrent(DeviceInfo.Contexts[device_id]);
if (err != CUDA_SUCCESS) {
DP("Error when setting a CUDA context for device %d\n", device_id);
CUDA_ERR_STRING(err);
return NULL;
}
// Clear the offload table as we are going to create a new one.
DeviceInfo.clearOffloadEntriesTable(device_id);
// Create the module and extract the function pointers.
CUmodule cumod;
DP("Load data from image " DPxMOD "\n", DPxPTR(image->ImageStart));
err = cuModuleLoadDataEx(&cumod, image->ImageStart, 0, NULL, NULL);
if (err != CUDA_SUCCESS) {
DP("Error when loading CUDA module\n");
CUDA_ERR_STRING(err);
return NULL;
}
DP("CUDA module successfully loaded!\n");
DeviceInfo.Modules.push_back(cumod);
// Find the symbols in the module by name.
__tgt_offload_entry *HostBegin = image->EntriesBegin;
__tgt_offload_entry *HostEnd = image->EntriesEnd;
for (__tgt_offload_entry *e = HostBegin; e != HostEnd; ++e) {
if (!e->addr) {
// We return NULL when something like this happens, the host should have
// always something in the address to uniquely identify the target region.
DP("Invalid binary: host entry '<null>' (size = %zd)...\n", e->size);
return NULL;
}
if (e->size) {
__tgt_offload_entry entry = *e;
CUdeviceptr cuptr;
size_t cusize;
err = cuModuleGetGlobal(&cuptr, &cusize, cumod, e->name);
if (err != CUDA_SUCCESS) {
DP("Loading global '%s' (Failed)\n", e->name);
CUDA_ERR_STRING(err);
return NULL;
}
if (cusize != e->size) {
DP("Loading global '%s' - size mismatch (%zd != %zd)\n", e->name,
cusize, e->size);
CUDA_ERR_STRING(err);
return NULL;
}
DP("Entry point " DPxMOD " maps to global %s (" DPxMOD ")\n",
DPxPTR(e - HostBegin), e->name, DPxPTR(cuptr));
entry.addr = (void *)cuptr;
DeviceInfo.addOffloadEntry(device_id, entry);
continue;
}
CUfunction fun;
err = cuModuleGetFunction(&fun, cumod, e->name);
if (err != CUDA_SUCCESS) {
DP("Loading '%s' (Failed)\n", e->name);
CUDA_ERR_STRING(err);
return NULL;
}
DP("Entry point " DPxMOD " maps to %s (" DPxMOD ")\n",
DPxPTR(e - HostBegin), e->name, DPxPTR(fun));
// default value GENERIC (in case symbol is missing from cubin file)
int8_t ExecModeVal = ExecutionModeType::GENERIC;
std::string ExecModeNameStr (e->name);
ExecModeNameStr += "_exec_mode";
const char *ExecModeName = ExecModeNameStr.c_str();
CUdeviceptr ExecModePtr;
size_t cusize;
err = cuModuleGetGlobal(&ExecModePtr, &cusize, cumod, ExecModeName);
if (err == CUDA_SUCCESS) {
if ((size_t)cusize != sizeof(int8_t)) {
DP("Loading global exec_mode '%s' - size mismatch (%zd != %zd)\n",
ExecModeName, cusize, sizeof(int8_t));
CUDA_ERR_STRING(err);
return NULL;
}
err = cuMemcpyDtoH(&ExecModeVal, ExecModePtr, cusize);
if (err != CUDA_SUCCESS) {
DP("Error when copying data from device to host. Pointers: "
"host = " DPxMOD ", device = " DPxMOD ", size = %zd\n",
DPxPTR(&ExecModeVal), DPxPTR(ExecModePtr), cusize);
CUDA_ERR_STRING(err);
return NULL;
}
if (ExecModeVal < 0 || ExecModeVal > 1) {
DP("Error wrong exec_mode value specified in cubin file: %d\n",
ExecModeVal);
return NULL;
}
} else {
DP("Loading global exec_mode '%s' - symbol missing, using default value "
"GENERIC (1)\n", ExecModeName);
CUDA_ERR_STRING(err);
}
KernelsList.push_back(KernelTy(fun, ExecModeVal));
__tgt_offload_entry entry = *e;
entry.addr = (void *)&KernelsList.back();
DeviceInfo.addOffloadEntry(device_id, entry);
}
return DeviceInfo.getOffloadEntriesTable(device_id);
}
void *__tgt_rtl_data_alloc(int32_t device_id, int64_t size, void *hst_ptr) {
if (size == 0) {
return NULL;
}
// Set the context we are using.
CUresult err = cuCtxSetCurrent(DeviceInfo.Contexts[device_id]);
if (err != CUDA_SUCCESS) {
DP("Error while trying to set CUDA current context\n");
CUDA_ERR_STRING(err);
return NULL;
}
CUdeviceptr ptr;
err = cuMemAlloc(&ptr, size);
if (err != CUDA_SUCCESS) {
DP("Error while trying to allocate %d\n", err);
CUDA_ERR_STRING(err);
return NULL;
}
void *vptr = (void *)ptr;
return vptr;
}
int32_t __tgt_rtl_data_submit(int32_t device_id, void *tgt_ptr, void *hst_ptr,
int64_t size) {
// Set the context we are using.
CUresult err = cuCtxSetCurrent(DeviceInfo.Contexts[device_id]);
if (err != CUDA_SUCCESS) {
DP("Error when setting CUDA context\n");
CUDA_ERR_STRING(err);
return OFFLOAD_FAIL;
}
err = cuMemcpyHtoD((CUdeviceptr)tgt_ptr, hst_ptr, size);
if (err != CUDA_SUCCESS) {
DP("Error when copying data from host to device. Pointers: host = " DPxMOD
", device = " DPxMOD ", size = %" PRId64 "\n", DPxPTR(hst_ptr),
DPxPTR(tgt_ptr), size);
CUDA_ERR_STRING(err);
return OFFLOAD_FAIL;
}
return OFFLOAD_SUCCESS;
}
int32_t __tgt_rtl_data_retrieve(int32_t device_id, void *hst_ptr, void *tgt_ptr,
int64_t size) {
// Set the context we are using.
CUresult err = cuCtxSetCurrent(DeviceInfo.Contexts[device_id]);
if (err != CUDA_SUCCESS) {
DP("Error when setting CUDA context\n");
CUDA_ERR_STRING(err);
return OFFLOAD_FAIL;
}
err = cuMemcpyDtoH(hst_ptr, (CUdeviceptr)tgt_ptr, size);
if (err != CUDA_SUCCESS) {
DP("Error when copying data from device to host. Pointers: host = " DPxMOD
", device = " DPxMOD ", size = %" PRId64 "\n", DPxPTR(hst_ptr),
DPxPTR(tgt_ptr), size);
CUDA_ERR_STRING(err);
return OFFLOAD_FAIL;
}
return OFFLOAD_SUCCESS;
}
int32_t __tgt_rtl_data_delete(int32_t device_id, void *tgt_ptr) {
// Set the context we are using.
CUresult err = cuCtxSetCurrent(DeviceInfo.Contexts[device_id]);
if (err != CUDA_SUCCESS) {
DP("Error when setting CUDA context\n");
CUDA_ERR_STRING(err);
return OFFLOAD_FAIL;
}
err = cuMemFree((CUdeviceptr)tgt_ptr);
if (err != CUDA_SUCCESS) {
DP("Error when freeing CUDA memory\n");
CUDA_ERR_STRING(err);
return OFFLOAD_FAIL;
}
return OFFLOAD_SUCCESS;
}
int32_t __tgt_rtl_run_target_team_region(int32_t device_id, void *tgt_entry_ptr,
void **tgt_args, ptrdiff_t *tgt_offsets, int32_t arg_num, int32_t team_num,
int32_t thread_limit, uint64_t loop_tripcount) {
// Set the context we are using.
CUresult err = cuCtxSetCurrent(DeviceInfo.Contexts[device_id]);
if (err != CUDA_SUCCESS) {
DP("Error when setting CUDA context\n");
CUDA_ERR_STRING(err);
return OFFLOAD_FAIL;
}
// All args are references.
std::vector<void *> args(arg_num);
std::vector<void *> ptrs(arg_num);
for (int32_t i = 0; i < arg_num; ++i) {
ptrs[i] = (void *)((intptr_t)tgt_args[i] + tgt_offsets[i]);
args[i] = &ptrs[i];
}
KernelTy *KernelInfo = (KernelTy *)tgt_entry_ptr;
int cudaThreadsPerBlock;
if (thread_limit > 0) {
cudaThreadsPerBlock = thread_limit;
DP("Setting CUDA threads per block to requested %d\n", thread_limit);
// Add master warp if necessary
if (KernelInfo->ExecutionMode == GENERIC) {
cudaThreadsPerBlock += DeviceInfo.WarpSize[device_id];
DP("Adding master warp: +%d threads\n", DeviceInfo.WarpSize[device_id]);
}
} else {
cudaThreadsPerBlock = DeviceInfo.NumThreads[device_id];
DP("Setting CUDA threads per block to default %d\n",
DeviceInfo.NumThreads[device_id]);
}
if (cudaThreadsPerBlock > DeviceInfo.ThreadsPerBlock[device_id]) {
cudaThreadsPerBlock = DeviceInfo.ThreadsPerBlock[device_id];
DP("Threads per block capped at device limit %d\n",
DeviceInfo.ThreadsPerBlock[device_id]);
}
int kernel_limit;
err = cuFuncGetAttribute(&kernel_limit,
CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK, KernelInfo->Func);
if (err == CUDA_SUCCESS) {
if (kernel_limit < cudaThreadsPerBlock) {
cudaThreadsPerBlock = kernel_limit;
DP("Threads per block capped at kernel limit %d\n", kernel_limit);
}
}
int cudaBlocksPerGrid;
if (team_num <= 0) {
if (loop_tripcount > 0 && DeviceInfo.EnvNumTeams < 0) {
if (KernelInfo->ExecutionMode == SPMD) {
// We have a combined construct, i.e. `target teams distribute parallel
// for [simd]`. We launch so many teams so that each thread will
// execute one iteration of the loop.
// round up to the nearest integer
cudaBlocksPerGrid = ((loop_tripcount - 1) / cudaThreadsPerBlock) + 1;
} else {
// If we reach this point, then we have a non-combined construct, i.e.
// `teams distribute` with a nested `parallel for` and each team is
// assigned one iteration of the `distribute` loop. E.g.:
//
// #pragma omp target teams distribute
// for(...loop_tripcount...) {
// #pragma omp parallel for
// for(...) {}
// }
//
// Threads within a team will execute the iterations of the `parallel`
// loop.
cudaBlocksPerGrid = loop_tripcount;
}
DP("Using %d teams due to loop trip count %" PRIu64 " and number of "
"threads per block %d\n", cudaBlocksPerGrid, loop_tripcount,
cudaThreadsPerBlock);
} else {
cudaBlocksPerGrid = DeviceInfo.NumTeams[device_id];
DP("Using default number of teams %d\n", DeviceInfo.NumTeams[device_id]);
}
} else if (team_num > DeviceInfo.BlocksPerGrid[device_id]) {
cudaBlocksPerGrid = DeviceInfo.BlocksPerGrid[device_id];
DP("Capping number of teams to team limit %d\n",
DeviceInfo.BlocksPerGrid[device_id]);
} else {
cudaBlocksPerGrid = team_num;
DP("Using requested number of teams %d\n", team_num);
}
// Run on the device.
DP("Launch kernel with %d blocks and %d threads\n", cudaBlocksPerGrid,
cudaThreadsPerBlock);
err = cuLaunchKernel(KernelInfo->Func, cudaBlocksPerGrid, 1, 1,
cudaThreadsPerBlock, 1, 1, 0 /*bytes of shared memory*/, 0, &args[0], 0);
if (err != CUDA_SUCCESS) {
DP("Device kernel launch failed!\n");
CUDA_ERR_STRING(err);
assert(err == CUDA_SUCCESS && "Unable to launch target execution!");
return OFFLOAD_FAIL;
}
DP("Launch of entry point at " DPxMOD " successful!\n",
DPxPTR(tgt_entry_ptr));
cudaError_t sync_error = cudaDeviceSynchronize();
if (sync_error != cudaSuccess) {
DP("Kernel execution error at " DPxMOD ", %s.\n", DPxPTR(tgt_entry_ptr),
cudaGetErrorString(sync_error));
return OFFLOAD_FAIL;
} else {
DP("Kernel execution at " DPxMOD " successful!\n", DPxPTR(tgt_entry_ptr));
}
return OFFLOAD_SUCCESS;
}
int32_t __tgt_rtl_run_target_region(int32_t device_id, void *tgt_entry_ptr,
void **tgt_args, ptrdiff_t *tgt_offsets, int32_t arg_num) {
// use one team and the default number of threads.
const int32_t team_num = 1;
const int32_t thread_limit = 0;
return __tgt_rtl_run_target_team_region(device_id, tgt_entry_ptr, tgt_args,
tgt_offsets, arg_num, team_num, thread_limit, 0);
}
#ifdef __cplusplus
}
#endif
+15
View File
@@ -0,0 +1,15 @@
VERS1.0 {
global:
__tgt_rtl_is_valid_binary;
__tgt_rtl_number_of_devices;
__tgt_rtl_init_device;
__tgt_rtl_load_binary;
__tgt_rtl_data_alloc;
__tgt_rtl_data_submit;
__tgt_rtl_data_retrieve;
__tgt_rtl_data_delete;
__tgt_rtl_run_target_team_region;
__tgt_rtl_run_target_region;
local:
*;
};
@@ -0,0 +1,339 @@
//===-RTLs/generic-64bit/src/rtl.cpp - Target RTLs Implementation - 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.
//
//===----------------------------------------------------------------------===//
//
// RTL for generic 64-bit machine
//
//===----------------------------------------------------------------------===//
#include <cassert>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <dlfcn.h>
#include <ffi.h>
#include <gelf.h>
#include <link.h>
#include <list>
#include <string>
#include <vector>
#include "omptargetplugin.h"
#ifndef TARGET_NAME
#define TARGET_NAME Generic ELF - 64bit
#endif
#ifndef TARGET_ELF_ID
#define TARGET_ELF_ID 0
#endif
#ifdef OMPTARGET_DEBUG
static int DebugLevel = 0;
#define GETNAME2(name) #name
#define GETNAME(name) GETNAME2(name)
#define DP(...) \
do { \
if (DebugLevel > 0) { \
DEBUGP("Target " GETNAME(TARGET_NAME) " RTL", __VA_ARGS__); \
} \
} while (false)
#else // OMPTARGET_DEBUG
#define DP(...) {}
#endif // OMPTARGET_DEBUG
#include "../../common/elf_common.c"
#define NUMBER_OF_DEVICES 4
#define OFFLOADSECTIONNAME ".omp_offloading.entries"
/// Array of Dynamic libraries loaded for this target.
struct DynLibTy {
char *FileName;
void *Handle;
};
/// Keep entries table per device.
struct FuncOrGblEntryTy {
__tgt_target_table Table;
};
/// Class containing all the device information.
class RTLDeviceInfoTy {
std::vector<FuncOrGblEntryTy> FuncGblEntries;
public:
std::list<DynLibTy> DynLibs;
// Record entry point associated with device.
void createOffloadTable(int32_t device_id, __tgt_offload_entry *begin,
__tgt_offload_entry *end) {
assert(device_id < (int32_t)FuncGblEntries.size() &&
"Unexpected device id!");
FuncOrGblEntryTy &E = FuncGblEntries[device_id];
E.Table.EntriesBegin = begin;
E.Table.EntriesEnd = end;
}
// Return true if the entry is associated with device.
bool findOffloadEntry(int32_t device_id, void *addr) {
assert(device_id < (int32_t)FuncGblEntries.size() &&
"Unexpected device id!");
FuncOrGblEntryTy &E = FuncGblEntries[device_id];
for (__tgt_offload_entry *i = E.Table.EntriesBegin, *e = E.Table.EntriesEnd;
i < e; ++i) {
if (i->addr == addr)
return true;
}
return false;
}
// Return the pointer to the target entries table.
__tgt_target_table *getOffloadEntriesTable(int32_t device_id) {
assert(device_id < (int32_t)FuncGblEntries.size() &&
"Unexpected device id!");
FuncOrGblEntryTy &E = FuncGblEntries[device_id];
return &E.Table;
}
RTLDeviceInfoTy(int32_t num_devices) {
#ifdef OMPTARGET_DEBUG
if (char *envStr = getenv("LIBOMPTARGET_DEBUG")) {
DebugLevel = std::stoi(envStr);
}
#endif // OMPTARGET_DEBUG
FuncGblEntries.resize(num_devices);
}
~RTLDeviceInfoTy() {
// Close dynamic libraries
for (auto &lib : DynLibs) {
if (lib.Handle) {
dlclose(lib.Handle);
remove(lib.FileName);
}
}
}
};
static RTLDeviceInfoTy DeviceInfo(NUMBER_OF_DEVICES);
#ifdef __cplusplus
extern "C" {
#endif
int32_t __tgt_rtl_is_valid_binary(__tgt_device_image *image) {
// If we don't have a valid ELF ID we can just fail.
#if TARGET_ELF_ID < 1
return 0;
#else
return elf_check_machine(image, TARGET_ELF_ID);
#endif
}
int32_t __tgt_rtl_number_of_devices() { return NUMBER_OF_DEVICES; }
int32_t __tgt_rtl_init_device(int32_t device_id) { return OFFLOAD_SUCCESS; }
__tgt_target_table *__tgt_rtl_load_binary(int32_t device_id,
__tgt_device_image *image) {
DP("Dev %d: load binary from " DPxMOD " image\n", device_id,
DPxPTR(image->ImageStart));
assert(device_id >= 0 && device_id < NUMBER_OF_DEVICES && "bad dev id");
size_t ImageSize = (size_t)image->ImageEnd - (size_t)image->ImageStart;
size_t NumEntries = (size_t)(image->EntriesEnd - image->EntriesBegin);
DP("Expecting to have %zd entries defined.\n", NumEntries);
// Is the library version incompatible with the header file?
if (elf_version(EV_CURRENT) == EV_NONE) {
DP("Incompatible ELF library!\n");
return NULL;
}
// Obtain elf handler
Elf *e = elf_memory((char *)image->ImageStart, ImageSize);
if (!e) {
DP("Unable to get ELF handle: %s!\n", elf_errmsg(-1));
return NULL;
}
if (elf_kind(e) != ELF_K_ELF) {
DP("Invalid Elf kind!\n");
elf_end(e);
return NULL;
}
// Find the entries section offset
Elf_Scn *section = 0;
Elf64_Off entries_offset = 0;
size_t shstrndx;
if (elf_getshdrstrndx(e, &shstrndx)) {
DP("Unable to get ELF strings index!\n");
elf_end(e);
return NULL;
}
while ((section = elf_nextscn(e, section))) {
GElf_Shdr hdr;
gelf_getshdr(section, &hdr);
if (!strcmp(elf_strptr(e, shstrndx, hdr.sh_name), OFFLOADSECTIONNAME)) {
entries_offset = hdr.sh_addr;
break;
}
}
if (!entries_offset) {
DP("Entries Section Offset Not Found\n");
elf_end(e);
return NULL;
}
DP("Offset of entries section is (" DPxMOD ").\n", DPxPTR(entries_offset));
// load dynamic library and get the entry points. We use the dl library
// to do the loading of the library, but we could do it directly to avoid the
// dump to the temporary file.
//
// 1) Create tmp file with the library contents.
// 2) Use dlopen to load the file and dlsym to retrieve the symbols.
char tmp_name[] = "/tmp/tmpfile_XXXXXX";
int tmp_fd = mkstemp(tmp_name);
if (tmp_fd == -1) {
elf_end(e);
return NULL;
}
FILE *ftmp = fdopen(tmp_fd, "wb");
if (!ftmp) {
elf_end(e);
return NULL;
}
fwrite(image->ImageStart, ImageSize, 1, ftmp);
fclose(ftmp);
DynLibTy Lib = {tmp_name, dlopen(tmp_name, RTLD_LAZY)};
if (!Lib.Handle) {
DP("Target library loading error: %s\n", dlerror());
elf_end(e);
return NULL;
}
DeviceInfo.DynLibs.push_back(Lib);
struct link_map *libInfo = (struct link_map *)Lib.Handle;
// The place where the entries info is loaded is the library base address
// plus the offset determined from the ELF file.
Elf64_Addr entries_addr = libInfo->l_addr + entries_offset;
DP("Pointer to first entry to be loaded is (" DPxMOD ").\n",
DPxPTR(entries_addr));
// Table of pointers to all the entries in the target.
__tgt_offload_entry *entries_table = (__tgt_offload_entry *)entries_addr;
__tgt_offload_entry *entries_begin = &entries_table[0];
__tgt_offload_entry *entries_end = entries_begin + NumEntries;
if (!entries_begin) {
DP("Can't obtain entries begin\n");
elf_end(e);
return NULL;
}
DP("Entries table range is (" DPxMOD ")->(" DPxMOD ")\n",
DPxPTR(entries_begin), DPxPTR(entries_end));
DeviceInfo.createOffloadTable(device_id, entries_begin, entries_end);
elf_end(e);
return DeviceInfo.getOffloadEntriesTable(device_id);
}
void *__tgt_rtl_data_alloc(int32_t device_id, int64_t size, void *hst_ptr) {
void *ptr = malloc(size);
return ptr;
}
int32_t __tgt_rtl_data_submit(int32_t device_id, void *tgt_ptr, void *hst_ptr,
int64_t size) {
memcpy(tgt_ptr, hst_ptr, size);
return OFFLOAD_SUCCESS;
}
int32_t __tgt_rtl_data_retrieve(int32_t device_id, void *hst_ptr, void *tgt_ptr,
int64_t size) {
memcpy(hst_ptr, tgt_ptr, size);
return OFFLOAD_SUCCESS;
}
int32_t __tgt_rtl_data_delete(int32_t device_id, void *tgt_ptr) {
free(tgt_ptr);
return OFFLOAD_SUCCESS;
}
int32_t __tgt_rtl_run_target_team_region(int32_t device_id, void *tgt_entry_ptr,
void **tgt_args, ptrdiff_t *tgt_offsets, int32_t arg_num, int32_t team_num,
int32_t thread_limit, uint64_t loop_tripcount /*not used*/) {
// ignore team num and thread limit.
// Use libffi to launch execution.
ffi_cif cif;
// All args are references.
std::vector<ffi_type *> args_types(arg_num, &ffi_type_pointer);
std::vector<void *> args(arg_num);
std::vector<void *> ptrs(arg_num);
for (int32_t i = 0; i < arg_num; ++i) {
ptrs[i] = (void *)((intptr_t)tgt_args[i] + tgt_offsets[i]);
args[i] = &ptrs[i];
}
ffi_status status = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, arg_num,
&ffi_type_void, &args_types[0]);
assert(status == FFI_OK && "Unable to prepare target launch!");
if (status != FFI_OK)
return OFFLOAD_FAIL;
DP("Running entry point at " DPxMOD "...\n", DPxPTR(tgt_entry_ptr));
void (*entry)(void);
*((void**) &entry) = tgt_entry_ptr;
ffi_call(&cif, entry, NULL, &args[0]);
return OFFLOAD_SUCCESS;
}
int32_t __tgt_rtl_run_target_region(int32_t device_id, void *tgt_entry_ptr,
void **tgt_args, ptrdiff_t *tgt_offsets, int32_t arg_num) {
// use one team and one thread.
return __tgt_rtl_run_target_team_region(device_id, tgt_entry_ptr, tgt_args,
tgt_offsets, arg_num, 1, 1, 0);
}
#ifdef __cplusplus
}
#endif
+18
View File
@@ -0,0 +1,18 @@
##===----------------------------------------------------------------------===##
#
# 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.
#
##===----------------------------------------------------------------------===##
#
# Build a plugin for a ppc64 machine if available.
#
##===----------------------------------------------------------------------===##
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
build_generic_elf64("ppc64" "PPC64" "ppc64" "powerpc64-ibm-linux-gnu" "21")
else()
libomptarget_say("Not building ppc64 offloading plugin: machine not found in the system.")
endif()
@@ -0,0 +1,18 @@
##===----------------------------------------------------------------------===##
#
# 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.
#
##===----------------------------------------------------------------------===##
#
# Build a plugin for a ppc64le machine if available.
#
##===----------------------------------------------------------------------===##
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
build_generic_elf64("ppc64le" "PPC64le" "ppc64" "powerpc64le-ibm-linux-gnu" "21")
else()
libomptarget_say("Not building ppc64le offloading plugin: machine not found in the system.")
endif()
@@ -0,0 +1,18 @@
##===----------------------------------------------------------------------===##
#
# 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.
#
##===----------------------------------------------------------------------===##
#
# Build a plugin for a x86_64 machine if available.
#
##===----------------------------------------------------------------------===##
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
build_generic_elf64("x86_64" "x86_64" "x86_64" "x86_64-pc-linux-gnu" "62")
else()
libomptarget_say("Not building x86_64 offloading plugin: machine not found in the system.")
endif()
+31
View File
@@ -0,0 +1,31 @@
##===----------------------------------------------------------------------===##
#
# 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.
#
##===----------------------------------------------------------------------===##
#
# Build offloading library libomptarget.so.
#
##===----------------------------------------------------------------------===##
libomptarget_say("Building offloading runtime library libomptarget.")
set(src_files
api.cpp
device.cpp
interface.cpp
rtl.cpp
omptarget.cpp
)
# Build libomptarget library with libdl dependency.
add_library(omptarget SHARED ${src_files})
target_link_libraries(omptarget
${CMAKE_DL_LIBS}
"-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/exports")
# Install libomptarget under the lib destination folder.
install(TARGETS omptarget LIBRARY DESTINATION lib${OPENMP_LIBDIR_SUFFIX})
+283
View File
@@ -0,0 +1,283 @@
//===----------- api.cpp - Target independent OpenMP target RTL -----------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
// Implementation of OpenMP API interface functions.
//
//===----------------------------------------------------------------------===//
#include <omptarget.h>
#include "device.h"
#include "private.h"
#include "rtl.h"
#include <climits>
#include <cstring>
#include <cstdlib>
EXTERN int omp_get_num_devices(void) {
RTLsMtx.lock();
size_t Devices_size = Devices.size();
RTLsMtx.unlock();
DP("Call to omp_get_num_devices returning %zd\n", Devices_size);
return Devices_size;
}
EXTERN int omp_get_initial_device(void) {
DP("Call to omp_get_initial_device returning %d\n", HOST_DEVICE);
return HOST_DEVICE;
}
EXTERN void *omp_target_alloc(size_t size, int device_num) {
DP("Call to omp_target_alloc for device %d requesting %zu bytes\n",
device_num, size);
if (size <= 0) {
DP("Call to omp_target_alloc with non-positive length\n");
return NULL;
}
void *rc = NULL;
if (device_num == omp_get_initial_device()) {
rc = malloc(size);
DP("omp_target_alloc returns host ptr " DPxMOD "\n", DPxPTR(rc));
return rc;
}
if (!device_is_ready(device_num)) {
DP("omp_target_alloc returns NULL ptr\n");
return NULL;
}
DeviceTy &Device = Devices[device_num];
rc = Device.RTL->data_alloc(Device.RTLDeviceID, size, NULL);
DP("omp_target_alloc returns device ptr " DPxMOD "\n", DPxPTR(rc));
return rc;
}
EXTERN void omp_target_free(void *device_ptr, int device_num) {
DP("Call to omp_target_free for device %d and address " DPxMOD "\n",
device_num, DPxPTR(device_ptr));
if (!device_ptr) {
DP("Call to omp_target_free with NULL ptr\n");
return;
}
if (device_num == omp_get_initial_device()) {
free(device_ptr);
DP("omp_target_free deallocated host ptr\n");
return;
}
if (!device_is_ready(device_num)) {
DP("omp_target_free returns, nothing to do\n");
return;
}
DeviceTy &Device = Devices[device_num];
Device.RTL->data_delete(Device.RTLDeviceID, (void *)device_ptr);
DP("omp_target_free deallocated device ptr\n");
}
EXTERN int omp_target_is_present(void *ptr, int device_num) {
DP("Call to omp_target_is_present for device %d and address " DPxMOD "\n",
device_num, DPxPTR(ptr));
if (!ptr) {
DP("Call to omp_target_is_present with NULL ptr, returning false\n");
return false;
}
if (device_num == omp_get_initial_device()) {
DP("Call to omp_target_is_present on host, returning true\n");
return true;
}
RTLsMtx.lock();
size_t Devices_size = Devices.size();
RTLsMtx.unlock();
if (Devices_size <= (size_t)device_num) {
DP("Call to omp_target_is_present with invalid device ID, returning "
"false\n");
return false;
}
DeviceTy& Device = Devices[device_num];
bool IsLast; // not used
int rc = (Device.getTgtPtrBegin(ptr, 0, IsLast, false) != NULL);
DP("Call to omp_target_is_present returns %d\n", rc);
return rc;
}
EXTERN int omp_target_memcpy(void *dst, void *src, size_t length,
size_t dst_offset, size_t src_offset, int dst_device, int src_device) {
DP("Call to omp_target_memcpy, dst device %d, src device %d, "
"dst addr " DPxMOD ", src addr " DPxMOD ", dst offset %zu, "
"src offset %zu, length %zu\n", dst_device, src_device, DPxPTR(dst),
DPxPTR(src), dst_offset, src_offset, length);
if (!dst || !src || length <= 0) {
DP("Call to omp_target_memcpy with invalid arguments\n");
return OFFLOAD_FAIL;
}
if (src_device != omp_get_initial_device() && !device_is_ready(src_device)) {
DP("omp_target_memcpy returns OFFLOAD_FAIL\n");
return OFFLOAD_FAIL;
}
if (dst_device != omp_get_initial_device() && !device_is_ready(dst_device)) {
DP("omp_target_memcpy returns OFFLOAD_FAIL\n");
return OFFLOAD_FAIL;
}
int rc = OFFLOAD_SUCCESS;
void *srcAddr = (char *)src + src_offset;
void *dstAddr = (char *)dst + dst_offset;
if (src_device == omp_get_initial_device() &&
dst_device == omp_get_initial_device()) {
DP("copy from host to host\n");
const void *p = memcpy(dstAddr, srcAddr, length);
if (p == NULL)
rc = OFFLOAD_FAIL;
} else if (src_device == omp_get_initial_device()) {
DP("copy from host to device\n");
DeviceTy& DstDev = Devices[dst_device];
rc = DstDev.data_submit(dstAddr, srcAddr, length);
} else if (dst_device == omp_get_initial_device()) {
DP("copy from device to host\n");
DeviceTy& SrcDev = Devices[src_device];
rc = SrcDev.data_retrieve(dstAddr, srcAddr, length);
} else {
DP("copy from device to device\n");
void *buffer = malloc(length);
DeviceTy& SrcDev = Devices[src_device];
DeviceTy& DstDev = Devices[dst_device];
rc = SrcDev.data_retrieve(buffer, srcAddr, length);
if (rc == OFFLOAD_SUCCESS)
rc = DstDev.data_submit(dstAddr, buffer, length);
}
DP("omp_target_memcpy returns %d\n", rc);
return rc;
}
EXTERN int omp_target_memcpy_rect(void *dst, void *src, size_t element_size,
int num_dims, const size_t *volume, const size_t *dst_offsets,
const size_t *src_offsets, const size_t *dst_dimensions,
const size_t *src_dimensions, int dst_device, int src_device) {
DP("Call to omp_target_memcpy_rect, dst device %d, src device %d, "
"dst addr " DPxMOD ", src addr " DPxMOD ", dst offsets " DPxMOD ", "
"src offsets " DPxMOD ", dst dims " DPxMOD ", src dims " DPxMOD ", "
"volume " DPxMOD ", element size %zu, num_dims %d\n", dst_device,
src_device, DPxPTR(dst), DPxPTR(src), DPxPTR(dst_offsets),
DPxPTR(src_offsets), DPxPTR(dst_dimensions), DPxPTR(src_dimensions),
DPxPTR(volume), element_size, num_dims);
if (!(dst || src)) {
DP("Call to omp_target_memcpy_rect returns max supported dimensions %d\n",
INT_MAX);
return INT_MAX;
}
if (!dst || !src || element_size < 1 || num_dims < 1 || !volume ||
!dst_offsets || !src_offsets || !dst_dimensions || !src_dimensions) {
DP("Call to omp_target_memcpy_rect with invalid arguments\n");
return OFFLOAD_FAIL;
}
int rc;
if (num_dims == 1) {
rc = omp_target_memcpy(dst, src, element_size * volume[0],
element_size * dst_offsets[0], element_size * src_offsets[0],
dst_device, src_device);
} else {
size_t dst_slice_size = element_size;
size_t src_slice_size = element_size;
for (int i=1; i<num_dims; ++i) {
dst_slice_size *= dst_dimensions[i];
src_slice_size *= src_dimensions[i];
}
size_t dst_off = dst_offsets[0] * dst_slice_size;
size_t src_off = src_offsets[0] * src_slice_size;
for (size_t i=0; i<volume[0]; ++i) {
rc = omp_target_memcpy_rect((char *) dst + dst_off + dst_slice_size * i,
(char *) src + src_off + src_slice_size * i, element_size,
num_dims - 1, volume + 1, dst_offsets + 1, src_offsets + 1,
dst_dimensions + 1, src_dimensions + 1, dst_device, src_device);
if (rc) {
DP("Recursive call to omp_target_memcpy_rect returns unsuccessfully\n");
return rc;
}
}
}
DP("omp_target_memcpy_rect returns %d\n", rc);
return rc;
}
EXTERN int omp_target_associate_ptr(void *host_ptr, void *device_ptr,
size_t size, size_t device_offset, int device_num) {
DP("Call to omp_target_associate_ptr with host_ptr " DPxMOD ", "
"device_ptr " DPxMOD ", size %zu, device_offset %zu, device_num %d\n",
DPxPTR(host_ptr), DPxPTR(device_ptr), size, device_offset, device_num);
if (!host_ptr || !device_ptr || size <= 0) {
DP("Call to omp_target_associate_ptr with invalid arguments\n");
return OFFLOAD_FAIL;
}
if (device_num == omp_get_initial_device()) {
DP("omp_target_associate_ptr: no association possible on the host\n");
return OFFLOAD_FAIL;
}
if (!device_is_ready(device_num)) {
DP("omp_target_associate_ptr returns OFFLOAD_FAIL\n");
return OFFLOAD_FAIL;
}
DeviceTy& Device = Devices[device_num];
void *device_addr = (void *)((uint64_t)device_ptr + (uint64_t)device_offset);
int rc = Device.associatePtr(host_ptr, device_addr, size);
DP("omp_target_associate_ptr returns %d\n", rc);
return rc;
}
EXTERN int omp_target_disassociate_ptr(void *host_ptr, int device_num) {
DP("Call to omp_target_disassociate_ptr with host_ptr " DPxMOD ", "
"device_num %d\n", DPxPTR(host_ptr), device_num);
if (!host_ptr) {
DP("Call to omp_target_associate_ptr with invalid host_ptr\n");
return OFFLOAD_FAIL;
}
if (device_num == omp_get_initial_device()) {
DP("omp_target_disassociate_ptr: no association possible on the host\n");
return OFFLOAD_FAIL;
}
if (!device_is_ready(device_num)) {
DP("omp_target_disassociate_ptr returns OFFLOAD_FAIL\n");
return OFFLOAD_FAIL;
}
DeviceTy& Device = Devices[device_num];
int rc = Device.disassociatePtr(host_ptr);
DP("omp_target_disassociate_ptr returns %d\n", rc);
return rc;
}
+365
View File
@@ -0,0 +1,365 @@
//===--------- device.cpp - Target independent OpenMP target RTL ----------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
// Functionality for managing devices that are handled by RTL plugins.
//
//===----------------------------------------------------------------------===//
#include "device.h"
#include "private.h"
#include "rtl.h"
#include <cassert>
#include <climits>
#include <string>
/// Map between Device ID (i.e. openmp device id) and its DeviceTy.
DevicesTy Devices;
int DeviceTy::associatePtr(void *HstPtrBegin, void *TgtPtrBegin, int64_t Size) {
DataMapMtx.lock();
// Check if entry exists
for (auto &HT : HostDataToTargetMap) {
if ((uintptr_t)HstPtrBegin == HT.HstPtrBegin) {
// Mapping already exists
bool isValid = HT.HstPtrBegin == (uintptr_t) HstPtrBegin &&
HT.HstPtrEnd == (uintptr_t) HstPtrBegin + Size &&
HT.TgtPtrBegin == (uintptr_t) TgtPtrBegin;
DataMapMtx.unlock();
if (isValid) {
DP("Attempt to re-associate the same device ptr+offset with the same "
"host ptr, nothing to do\n");
return OFFLOAD_SUCCESS;
} else {
DP("Not allowed to re-associate a different device ptr+offset with the "
"same host ptr\n");
return OFFLOAD_FAIL;
}
}
}
// Mapping does not exist, allocate it
HostDataToTargetTy newEntry;
// Set up missing fields
newEntry.HstPtrBase = (uintptr_t) HstPtrBegin;
newEntry.HstPtrBegin = (uintptr_t) HstPtrBegin;
newEntry.HstPtrEnd = (uintptr_t) HstPtrBegin + Size;
newEntry.TgtPtrBegin = (uintptr_t) TgtPtrBegin;
// refCount must be infinite
newEntry.RefCount = INF_REF_CNT;
DP("Creating new map entry: HstBase=" DPxMOD ", HstBegin=" DPxMOD ", HstEnd="
DPxMOD ", TgtBegin=" DPxMOD "\n", DPxPTR(newEntry.HstPtrBase),
DPxPTR(newEntry.HstPtrBegin), DPxPTR(newEntry.HstPtrEnd),
DPxPTR(newEntry.TgtPtrBegin));
HostDataToTargetMap.push_front(newEntry);
DataMapMtx.unlock();
return OFFLOAD_SUCCESS;
}
int DeviceTy::disassociatePtr(void *HstPtrBegin) {
DataMapMtx.lock();
// Check if entry exists
for (HostDataToTargetListTy::iterator ii = HostDataToTargetMap.begin();
ii != HostDataToTargetMap.end(); ++ii) {
if ((uintptr_t)HstPtrBegin == ii->HstPtrBegin) {
// Mapping exists
if (CONSIDERED_INF(ii->RefCount)) {
DP("Association found, removing it\n");
HostDataToTargetMap.erase(ii);
DataMapMtx.unlock();
return OFFLOAD_SUCCESS;
} else {
DP("Trying to disassociate a pointer which was not mapped via "
"omp_target_associate_ptr\n");
break;
}
}
}
// Mapping not found
DataMapMtx.unlock();
DP("Association not found\n");
return OFFLOAD_FAIL;
}
// Get ref count of map entry containing HstPtrBegin
long DeviceTy::getMapEntryRefCnt(void *HstPtrBegin) {
uintptr_t hp = (uintptr_t)HstPtrBegin;
long RefCnt = -1;
DataMapMtx.lock();
for (auto &HT : HostDataToTargetMap) {
if (hp >= HT.HstPtrBegin && hp < HT.HstPtrEnd) {
DP("DeviceTy::getMapEntry: requested entry found\n");
RefCnt = HT.RefCount;
break;
}
}
DataMapMtx.unlock();
if (RefCnt < 0) {
DP("DeviceTy::getMapEntry: requested entry not found\n");
}
return RefCnt;
}
LookupResult DeviceTy::lookupMapping(void *HstPtrBegin, int64_t Size) {
uintptr_t hp = (uintptr_t)HstPtrBegin;
LookupResult lr;
DP("Looking up mapping(HstPtrBegin=" DPxMOD ", Size=%ld)...\n", DPxPTR(hp),
Size);
for (lr.Entry = HostDataToTargetMap.begin();
lr.Entry != HostDataToTargetMap.end(); ++lr.Entry) {
auto &HT = *lr.Entry;
// Is it contained?
lr.Flags.IsContained = hp >= HT.HstPtrBegin && hp < HT.HstPtrEnd &&
(hp+Size) <= HT.HstPtrEnd;
// Does it extend into an already mapped region?
lr.Flags.ExtendsBefore = hp < HT.HstPtrBegin && (hp+Size) > HT.HstPtrBegin;
// Does it extend beyond the mapped region?
lr.Flags.ExtendsAfter = hp < HT.HstPtrEnd && (hp+Size) > HT.HstPtrEnd;
if (lr.Flags.IsContained || lr.Flags.ExtendsBefore ||
lr.Flags.ExtendsAfter) {
break;
}
}
if (lr.Flags.ExtendsBefore) {
DP("WARNING: Pointer is not mapped but section extends into already "
"mapped data\n");
}
if (lr.Flags.ExtendsAfter) {
DP("WARNING: Pointer is already mapped but section extends beyond mapped "
"region\n");
}
return lr;
}
// Used by target_data_begin
// Return the target pointer begin (where the data will be moved).
// Allocate memory if this is the first occurrence if this mapping.
// Increment the reference counter.
// If NULL is returned, then either data allocation failed or the user tried
// to do an illegal mapping.
void *DeviceTy::getOrAllocTgtPtr(void *HstPtrBegin, void *HstPtrBase,
int64_t Size, bool &IsNew, bool IsImplicit, bool UpdateRefCount) {
void *rc = NULL;
DataMapMtx.lock();
LookupResult lr = lookupMapping(HstPtrBegin, Size);
// Check if the pointer is contained.
if (lr.Flags.IsContained ||
((lr.Flags.ExtendsBefore || lr.Flags.ExtendsAfter) && IsImplicit)) {
auto &HT = *lr.Entry;
IsNew = false;
if (UpdateRefCount)
++HT.RefCount;
uintptr_t tp = HT.TgtPtrBegin + ((uintptr_t)HstPtrBegin - HT.HstPtrBegin);
DP("Mapping exists%s with HstPtrBegin=" DPxMOD ", TgtPtrBegin=" DPxMOD ", "
"Size=%ld,%s RefCount=%s\n", (IsImplicit ? " (implicit)" : ""),
DPxPTR(HstPtrBegin), DPxPTR(tp), Size,
(UpdateRefCount ? " updated" : ""),
(CONSIDERED_INF(HT.RefCount)) ? "INF" :
std::to_string(HT.RefCount).c_str());
rc = (void *)tp;
} else if ((lr.Flags.ExtendsBefore || lr.Flags.ExtendsAfter) && !IsImplicit) {
// Explicit extension of mapped data - not allowed.
DP("Explicit extension of mapping is not allowed.\n");
} else if (Size) {
// If it is not contained and Size > 0 we should create a new entry for it.
IsNew = true;
uintptr_t tp = (uintptr_t)RTL->data_alloc(RTLDeviceID, Size, HstPtrBegin);
DP("Creating new map entry: HstBase=" DPxMOD ", HstBegin=" DPxMOD ", "
"HstEnd=" DPxMOD ", TgtBegin=" DPxMOD "\n", DPxPTR(HstPtrBase),
DPxPTR(HstPtrBegin), DPxPTR((uintptr_t)HstPtrBegin + Size), DPxPTR(tp));
HostDataToTargetMap.push_front(HostDataToTargetTy((uintptr_t)HstPtrBase,
(uintptr_t)HstPtrBegin, (uintptr_t)HstPtrBegin + Size, tp));
rc = (void *)tp;
}
DataMapMtx.unlock();
return rc;
}
// Used by target_data_begin, target_data_end, target_data_update and target.
// Return the target pointer begin (where the data will be moved).
// Decrement the reference counter if called from target_data_end.
void *DeviceTy::getTgtPtrBegin(void *HstPtrBegin, int64_t Size, bool &IsLast,
bool UpdateRefCount) {
void *rc = NULL;
DataMapMtx.lock();
LookupResult lr = lookupMapping(HstPtrBegin, Size);
if (lr.Flags.IsContained || lr.Flags.ExtendsBefore || lr.Flags.ExtendsAfter) {
auto &HT = *lr.Entry;
IsLast = !(HT.RefCount > 1);
if (HT.RefCount > 1 && UpdateRefCount)
--HT.RefCount;
uintptr_t tp = HT.TgtPtrBegin + ((uintptr_t)HstPtrBegin - HT.HstPtrBegin);
DP("Mapping exists with HstPtrBegin=" DPxMOD ", TgtPtrBegin=" DPxMOD ", "
"Size=%ld,%s RefCount=%s\n", DPxPTR(HstPtrBegin), DPxPTR(tp), Size,
(UpdateRefCount ? " updated" : ""),
(CONSIDERED_INF(HT.RefCount)) ? "INF" :
std::to_string(HT.RefCount).c_str());
rc = (void *)tp;
} else {
IsLast = false;
}
DataMapMtx.unlock();
return rc;
}
// Return the target pointer begin (where the data will be moved).
// Lock-free version called when loading global symbols from the fat binary.
void *DeviceTy::getTgtPtrBegin(void *HstPtrBegin, int64_t Size) {
uintptr_t hp = (uintptr_t)HstPtrBegin;
LookupResult lr = lookupMapping(HstPtrBegin, Size);
if (lr.Flags.IsContained || lr.Flags.ExtendsBefore || lr.Flags.ExtendsAfter) {
auto &HT = *lr.Entry;
uintptr_t tp = HT.TgtPtrBegin + (hp - HT.HstPtrBegin);
return (void *)tp;
}
return NULL;
}
int DeviceTy::deallocTgtPtr(void *HstPtrBegin, int64_t Size, bool ForceDelete) {
// Check if the pointer is contained in any sub-nodes.
int rc;
DataMapMtx.lock();
LookupResult lr = lookupMapping(HstPtrBegin, Size);
if (lr.Flags.IsContained || lr.Flags.ExtendsBefore || lr.Flags.ExtendsAfter) {
auto &HT = *lr.Entry;
if (ForceDelete)
HT.RefCount = 1;
if (--HT.RefCount <= 0) {
assert(HT.RefCount == 0 && "did not expect a negative ref count");
DP("Deleting tgt data " DPxMOD " of size %ld\n",
DPxPTR(HT.TgtPtrBegin), Size);
RTL->data_delete(RTLDeviceID, (void *)HT.TgtPtrBegin);
DP("Removing%s mapping with HstPtrBegin=" DPxMOD ", TgtPtrBegin=" DPxMOD
", Size=%ld\n", (ForceDelete ? " (forced)" : ""),
DPxPTR(HT.HstPtrBegin), DPxPTR(HT.TgtPtrBegin), Size);
HostDataToTargetMap.erase(lr.Entry);
}
rc = OFFLOAD_SUCCESS;
} else {
DP("Section to delete (hst addr " DPxMOD ") does not exist in the allocated"
" memory\n", DPxPTR(HstPtrBegin));
rc = OFFLOAD_FAIL;
}
DataMapMtx.unlock();
return rc;
}
/// Init device, should not be called directly.
void DeviceTy::init() {
int32_t rc = RTL->init_device(RTLDeviceID);
if (rc == OFFLOAD_SUCCESS) {
IsInit = true;
}
}
/// Thread-safe method to initialize the device only once.
int32_t DeviceTy::initOnce() {
std::call_once(InitFlag, &DeviceTy::init, this);
// At this point, if IsInit is true, then either this thread or some other
// thread in the past successfully initialized the device, so we can return
// OFFLOAD_SUCCESS. If this thread executed init() via call_once() and it
// failed, return OFFLOAD_FAIL. If call_once did not invoke init(), it means
// that some other thread already attempted to execute init() and if IsInit
// is still false, return OFFLOAD_FAIL.
if (IsInit)
return OFFLOAD_SUCCESS;
else
return OFFLOAD_FAIL;
}
// Load binary to device.
__tgt_target_table *DeviceTy::load_binary(void *Img) {
RTL->Mtx.lock();
__tgt_target_table *rc = RTL->load_binary(RTLDeviceID, Img);
RTL->Mtx.unlock();
return rc;
}
// Submit data to device.
int32_t DeviceTy::data_submit(void *TgtPtrBegin, void *HstPtrBegin,
int64_t Size) {
return RTL->data_submit(RTLDeviceID, TgtPtrBegin, HstPtrBegin, Size);
}
// Retrieve data from device.
int32_t DeviceTy::data_retrieve(void *HstPtrBegin, void *TgtPtrBegin,
int64_t Size) {
return RTL->data_retrieve(RTLDeviceID, HstPtrBegin, TgtPtrBegin, Size);
}
// Run region on device
int32_t DeviceTy::run_region(void *TgtEntryPtr, void **TgtVarsPtr,
ptrdiff_t *TgtOffsets, int32_t TgtVarsSize) {
return RTL->run_region(RTLDeviceID, TgtEntryPtr, TgtVarsPtr, TgtOffsets,
TgtVarsSize);
}
// Run team region on device.
int32_t DeviceTy::run_team_region(void *TgtEntryPtr, void **TgtVarsPtr,
ptrdiff_t *TgtOffsets, int32_t TgtVarsSize, int32_t NumTeams,
int32_t ThreadLimit, uint64_t LoopTripCount) {
return RTL->run_team_region(RTLDeviceID, TgtEntryPtr, TgtVarsPtr, TgtOffsets,
TgtVarsSize, NumTeams, ThreadLimit, LoopTripCount);
}
/// Check whether a device has an associated RTL and initialize it if it's not
/// already initialized.
bool device_is_ready(int device_num) {
DP("Checking whether device %d is ready.\n", device_num);
// Devices.size() can only change while registering a new
// library, so try to acquire the lock of RTLs' mutex.
RTLsMtx.lock();
size_t Devices_size = Devices.size();
RTLsMtx.unlock();
if (Devices_size <= (size_t)device_num) {
DP("Device ID %d does not have a matching RTL\n", device_num);
return false;
}
// Get device info
DeviceTy &Device = Devices[device_num];
DP("Is the device %d (local ID %d) initialized? %d\n", device_num,
Device.RTLDeviceID, Device.IsInit);
// Init the device if not done before
if (!Device.IsInit && Device.initOnce() != OFFLOAD_SUCCESS) {
DP("Failed to init device %d\n", device_num);
return false;
}
DP("Device %d is ready to use.\n", device_num);
return true;
}
+167
View File
@@ -0,0 +1,167 @@
//===----------- device.h - Target independent OpenMP target RTL ----------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
// Declarations for managing devices that are handled by RTL plugins.
//
//===----------------------------------------------------------------------===//
#ifndef _OMPTARGET_DEVICE_H
#define _OMPTARGET_DEVICE_H
#include <cstddef>
#include <climits>
#include <list>
#include <map>
#include <mutex>
#include <vector>
// Forward declarations.
struct RTLInfoTy;
struct __tgt_bin_desc;
struct __tgt_target_table;
#define INF_REF_CNT (LONG_MAX>>1) // leave room for additions/subtractions
#define CONSIDERED_INF(x) (x > (INF_REF_CNT>>1))
/// Map between host data and target data.
struct HostDataToTargetTy {
uintptr_t HstPtrBase; // host info.
uintptr_t HstPtrBegin;
uintptr_t HstPtrEnd; // non-inclusive.
uintptr_t TgtPtrBegin; // target info.
long RefCount;
HostDataToTargetTy()
: HstPtrBase(0), HstPtrBegin(0), HstPtrEnd(0),
TgtPtrBegin(0), RefCount(0) {}
HostDataToTargetTy(uintptr_t BP, uintptr_t B, uintptr_t E, uintptr_t TB)
: HstPtrBase(BP), HstPtrBegin(B), HstPtrEnd(E),
TgtPtrBegin(TB), RefCount(1) {}
HostDataToTargetTy(uintptr_t BP, uintptr_t B, uintptr_t E, uintptr_t TB,
long RF)
: HstPtrBase(BP), HstPtrBegin(B), HstPtrEnd(E),
TgtPtrBegin(TB), RefCount(RF) {}
};
typedef std::list<HostDataToTargetTy> HostDataToTargetListTy;
struct LookupResult {
struct {
unsigned IsContained : 1;
unsigned ExtendsBefore : 1;
unsigned ExtendsAfter : 1;
} Flags;
HostDataToTargetListTy::iterator Entry;
LookupResult() : Flags({0,0,0}), Entry() {}
};
/// Map for shadow pointers
struct ShadowPtrValTy {
void *HstPtrVal;
void *TgtPtrAddr;
void *TgtPtrVal;
};
typedef std::map<void *, ShadowPtrValTy> ShadowPtrListTy;
///
struct PendingCtorDtorListsTy {
std::list<void *> PendingCtors;
std::list<void *> PendingDtors;
};
typedef std::map<__tgt_bin_desc *, PendingCtorDtorListsTy>
PendingCtorsDtorsPerLibrary;
struct DeviceTy {
int32_t DeviceID;
RTLInfoTy *RTL;
int32_t RTLDeviceID;
bool IsInit;
std::once_flag InitFlag;
bool HasPendingGlobals;
HostDataToTargetListTy HostDataToTargetMap;
PendingCtorsDtorsPerLibrary PendingCtorsDtors;
ShadowPtrListTy ShadowPtrMap;
std::mutex DataMapMtx, PendingGlobalsMtx, ShadowMtx;
uint64_t loopTripCnt;
DeviceTy(RTLInfoTy *RTL)
: DeviceID(-1), RTL(RTL), RTLDeviceID(-1), IsInit(false), InitFlag(),
HasPendingGlobals(false), HostDataToTargetMap(),
PendingCtorsDtors(), ShadowPtrMap(), DataMapMtx(), PendingGlobalsMtx(),
ShadowMtx(), loopTripCnt(0) {}
// The existence of mutexes makes DeviceTy non-copyable. We need to
// provide a copy constructor and an assignment operator explicitly.
DeviceTy(const DeviceTy &d)
: DeviceID(d.DeviceID), RTL(d.RTL), RTLDeviceID(d.RTLDeviceID),
IsInit(d.IsInit), InitFlag(), HasPendingGlobals(d.HasPendingGlobals),
HostDataToTargetMap(d.HostDataToTargetMap),
PendingCtorsDtors(d.PendingCtorsDtors), ShadowPtrMap(d.ShadowPtrMap),
DataMapMtx(), PendingGlobalsMtx(),
ShadowMtx(), loopTripCnt(d.loopTripCnt) {}
DeviceTy& operator=(const DeviceTy &d) {
DeviceID = d.DeviceID;
RTL = d.RTL;
RTLDeviceID = d.RTLDeviceID;
IsInit = d.IsInit;
HasPendingGlobals = d.HasPendingGlobals;
HostDataToTargetMap = d.HostDataToTargetMap;
PendingCtorsDtors = d.PendingCtorsDtors;
ShadowPtrMap = d.ShadowPtrMap;
loopTripCnt = d.loopTripCnt;
return *this;
}
long getMapEntryRefCnt(void *HstPtrBegin);
LookupResult lookupMapping(void *HstPtrBegin, int64_t Size);
void *getOrAllocTgtPtr(void *HstPtrBegin, void *HstPtrBase, int64_t Size,
bool &IsNew, bool IsImplicit, bool UpdateRefCount = true);
void *getTgtPtrBegin(void *HstPtrBegin, int64_t Size);
void *getTgtPtrBegin(void *HstPtrBegin, int64_t Size, bool &IsLast,
bool UpdateRefCount);
int deallocTgtPtr(void *TgtPtrBegin, int64_t Size, bool ForceDelete);
int associatePtr(void *HstPtrBegin, void *TgtPtrBegin, int64_t Size);
int disassociatePtr(void *HstPtrBegin);
// calls to RTL
int32_t initOnce();
__tgt_target_table *load_binary(void *Img);
int32_t data_submit(void *TgtPtrBegin, void *HstPtrBegin, int64_t Size);
int32_t data_retrieve(void *HstPtrBegin, void *TgtPtrBegin, int64_t Size);
int32_t run_region(void *TgtEntryPtr, void **TgtVarsPtr,
ptrdiff_t *TgtOffsets, int32_t TgtVarsSize);
int32_t run_team_region(void *TgtEntryPtr, void **TgtVarsPtr,
ptrdiff_t *TgtOffsets, int32_t TgtVarsSize, int32_t NumTeams,
int32_t ThreadLimit, uint64_t LoopTripCount);
private:
// Call to RTL
void init(); // To be called only via DeviceTy::initOnce()
};
/// Map between Device ID (i.e. openmp device id) and its DeviceTy.
typedef std::vector<DeviceTy> DevicesTy;
extern DevicesTy Devices;
extern bool device_is_ready(int device_num);
#endif
+28
View File
@@ -0,0 +1,28 @@
VERS1.0 {
global:
__tgt_register_lib;
__tgt_unregister_lib;
__tgt_target_data_begin;
__tgt_target_data_end;
__tgt_target_data_update;
__tgt_target;
__tgt_target_teams;
__tgt_target_data_begin_nowait;
__tgt_target_data_end_nowait;
__tgt_target_data_update_nowait;
__tgt_target_nowait;
__tgt_target_teams_nowait;
omp_get_num_devices;
omp_get_initial_device;
omp_target_alloc;
omp_target_free;
omp_target_is_present;
omp_target_memcpy;
omp_target_memcpy_rect;
omp_target_associate_ptr;
omp_target_disassociate_ptr;
__kmpc_push_target_tripcount;
local:
*;
};
+502
View File
@@ -0,0 +1,502 @@
//===-------- interface.cpp - Target independent OpenMP target RTL --------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
// Implementation of the interface to be used by Clang during the codegen of a
// target region.
//
//===----------------------------------------------------------------------===//
#include <omptarget.h>
#include "device.h"
#include "private.h"
#include "rtl.h"
#include <cassert>
#include <cstdlib>
////////////////////////////////////////////////////////////////////////////////
/// adds a target shared library to the target execution image
EXTERN void __tgt_register_lib(__tgt_bin_desc *desc) {
RTLs.RegisterLib(desc);
}
////////////////////////////////////////////////////////////////////////////////
/// unloads a target shared library
EXTERN void __tgt_unregister_lib(__tgt_bin_desc *desc) {
RTLs.UnregisterLib(desc);
}
// Following datatypes and functions (tgt_oldmap_type, combined_entry_t,
// translate_map, cleanup_map) will be removed once the compiler starts using
// the new map types.
// Old map types
enum tgt_oldmap_type {
OMP_TGT_OLDMAPTYPE_TO = 0x001, // copy data from host to device
OMP_TGT_OLDMAPTYPE_FROM = 0x002, // copy data from device to host
OMP_TGT_OLDMAPTYPE_ALWAYS = 0x004, // copy regardless of the ref. count
OMP_TGT_OLDMAPTYPE_DELETE = 0x008, // force unmapping of data
OMP_TGT_OLDMAPTYPE_MAP_PTR = 0x010, // map pointer as well as pointee
OMP_TGT_OLDMAPTYPE_FIRST_MAP = 0x020, // first occurrence of mapped variable
OMP_TGT_OLDMAPTYPE_RETURN_PTR = 0x040, // return TgtBase addr of mapped data
OMP_TGT_OLDMAPTYPE_PRIVATE_PTR = 0x080, // private variable - not mapped
OMP_TGT_OLDMAPTYPE_PRIVATE_VAL = 0x100 // copy by value - not mapped
};
// Temporary functions for map translation and cleanup
struct combined_entry_t {
int num_members; // number of members in combined entry
void *base_addr; // base address of combined entry
void *begin_addr; // begin address of combined entry
void *end_addr; // size of combined entry
};
static void translate_map(int32_t arg_num, void **args_base, void **args,
int64_t *arg_sizes, int64_t *arg_types, int32_t &new_arg_num,
void **&new_args_base, void **&new_args, int64_t *&new_arg_sizes,
int64_t *&new_arg_types, bool is_target_construct) {
if (arg_num <= 0) {
DP("Nothing to translate\n");
new_arg_num = 0;
return;
}
// array of combined entries
combined_entry_t *cmb_entries =
(combined_entry_t *) alloca(arg_num * sizeof(combined_entry_t));
// number of combined entries
long num_combined = 0;
// old entry is MAP_PTR?
bool *is_ptr_old = (bool *) alloca(arg_num * sizeof(bool));
// old entry is member of member_of[old] cmb_entry
int *member_of = (int *) alloca(arg_num * sizeof(int));
// temporary storage for modifications of the original arg_types
int64_t *mod_arg_types = (int64_t *) alloca(arg_num *sizeof(int64_t));
DP("Translating %d map entries\n", arg_num);
for (int i = 0; i < arg_num; ++i) {
member_of[i] = -1;
is_ptr_old[i] = false;
mod_arg_types[i] = arg_types[i];
// Scan previous entries to see whether this entry shares the same base
for (int j = 0; j < i; ++j) {
void *new_begin_addr = NULL;
void *new_end_addr = NULL;
if (mod_arg_types[i] & OMP_TGT_OLDMAPTYPE_MAP_PTR) {
if (args_base[i] == args[j]) {
if (!(mod_arg_types[j] & OMP_TGT_OLDMAPTYPE_MAP_PTR)) {
DP("Entry %d has the same base as entry %d's begin address\n", i,
j);
new_begin_addr = args_base[i];
new_end_addr = (char *)args_base[i] + sizeof(void *);
assert(arg_sizes[j] == sizeof(void *));
is_ptr_old[j] = true;
} else {
DP("Entry %d has the same base as entry %d's begin address, but "
"%d's base was a MAP_PTR too\n", i, j, j);
int32_t to_from_always_delete =
OMP_TGT_OLDMAPTYPE_TO | OMP_TGT_OLDMAPTYPE_FROM |
OMP_TGT_OLDMAPTYPE_ALWAYS | OMP_TGT_OLDMAPTYPE_DELETE;
if (mod_arg_types[j] & to_from_always_delete) {
DP("Resetting to/from/always/delete flags for entry %d because "
"it is only a pointer to pointer\n", j);
mod_arg_types[j] &= ~to_from_always_delete;
}
}
}
} else {
if (!(mod_arg_types[i] & OMP_TGT_OLDMAPTYPE_FIRST_MAP) &&
args_base[i] == args_base[j]) {
DP("Entry %d has the same base address as entry %d\n", i, j);
new_begin_addr = args[i];
new_end_addr = (char *)args[i] + arg_sizes[i];
}
}
// If we have combined the entry with a previous one
if (new_begin_addr) {
int id;
if(member_of[j] == -1) {
// We have a new entry
id = num_combined++;
DP("Creating new combined entry %d for old entry %d\n", id, j);
// Initialize new entry
cmb_entries[id].num_members = 1;
cmb_entries[id].base_addr = args_base[j];
if (mod_arg_types[j] & OMP_TGT_OLDMAPTYPE_MAP_PTR) {
cmb_entries[id].begin_addr = args_base[j];
cmb_entries[id].end_addr = (char *)args_base[j] + arg_sizes[j];
} else {
cmb_entries[id].begin_addr = args[j];
cmb_entries[id].end_addr = (char *)args[j] + arg_sizes[j];
}
member_of[j] = id;
} else {
// Reuse existing combined entry
DP("Reusing existing combined entry %d\n", member_of[j]);
id = member_of[j];
}
// Update combined entry
DP("Adding entry %d to combined entry %d\n", i, id);
cmb_entries[id].num_members++;
// base_addr stays the same
cmb_entries[id].begin_addr =
std::min(cmb_entries[id].begin_addr, new_begin_addr);
cmb_entries[id].end_addr =
std::max(cmb_entries[id].end_addr, new_end_addr);
member_of[i] = id;
break;
}
}
}
DP("New entries: %ld combined + %d original\n", num_combined, arg_num);
new_arg_num = arg_num + num_combined;
new_args_base = (void **) malloc(new_arg_num * sizeof(void *));
new_args = (void **) malloc(new_arg_num * sizeof(void *));
new_arg_sizes = (int64_t *) malloc(new_arg_num * sizeof(int64_t));
new_arg_types = (int64_t *) malloc(new_arg_num * sizeof(int64_t));
const int64_t alignment = 8;
int next_id = 0; // next ID
int next_cid = 0; // next combined ID
int *combined_to_new_id = (int *) alloca(num_combined * sizeof(int));
for (int i = 0; i < arg_num; ++i) {
// It is member_of
if (member_of[i] == next_cid) {
int cid = next_cid++; // ID of this combined entry
int nid = next_id++; // ID of the new (global) entry
combined_to_new_id[cid] = nid;
DP("Combined entry %3d will become new entry %3d\n", cid, nid);
int64_t padding = (int64_t)cmb_entries[cid].begin_addr % alignment;
if (padding) {
DP("Using a padding of %" PRId64 " for begin address " DPxMOD "\n",
padding, DPxPTR(cmb_entries[cid].begin_addr));
cmb_entries[cid].begin_addr =
(char *)cmb_entries[cid].begin_addr - padding;
}
new_args_base[nid] = cmb_entries[cid].base_addr;
new_args[nid] = cmb_entries[cid].begin_addr;
new_arg_sizes[nid] = (int64_t) ((char *)cmb_entries[cid].end_addr -
(char *)cmb_entries[cid].begin_addr);
new_arg_types[nid] = OMP_TGT_MAPTYPE_TARGET_PARAM;
DP("Entry %3d: base_addr " DPxMOD ", begin_addr " DPxMOD ", "
"size %" PRId64 ", type 0x%" PRIx64 "\n", nid,
DPxPTR(new_args_base[nid]), DPxPTR(new_args[nid]), new_arg_sizes[nid],
new_arg_types[nid]);
} else if (member_of[i] != -1) {
DP("Combined entry %3d has been encountered before, do nothing\n",
member_of[i]);
}
// Now that the combined entry (the one the old entry was a member of) has
// been inserted into the new arguments list, proceed with the old entry.
int nid = next_id++;
DP("Old entry %3d will become new entry %3d\n", i, nid);
new_args_base[nid] = args_base[i];
new_args[nid] = args[i];
new_arg_sizes[nid] = arg_sizes[i];
int64_t old_type = mod_arg_types[i];
if (is_ptr_old[i]) {
// Reset TO and FROM flags
old_type &= ~(OMP_TGT_OLDMAPTYPE_TO | OMP_TGT_OLDMAPTYPE_FROM);
}
if (member_of[i] == -1) {
if (!is_target_construct)
old_type &= ~OMP_TGT_MAPTYPE_TARGET_PARAM;
new_arg_types[nid] = old_type;
DP("Entry %3d: base_addr " DPxMOD ", begin_addr " DPxMOD ", size %" PRId64
", type 0x%" PRIx64 " (old entry %d not MEMBER_OF)\n", nid,
DPxPTR(new_args_base[nid]), DPxPTR(new_args[nid]), new_arg_sizes[nid],
new_arg_types[nid], i);
} else {
// Old entry is not FIRST_MAP
old_type &= ~OMP_TGT_OLDMAPTYPE_FIRST_MAP;
// Add MEMBER_OF
int new_member_of = combined_to_new_id[member_of[i]];
old_type |= ((int64_t)new_member_of + 1) << 48;
new_arg_types[nid] = old_type;
DP("Entry %3d: base_addr " DPxMOD ", begin_addr " DPxMOD ", size %" PRId64
", type 0x%" PRIx64 " (old entry %d MEMBER_OF %d)\n", nid,
DPxPTR(new_args_base[nid]), DPxPTR(new_args[nid]), new_arg_sizes[nid],
new_arg_types[nid], i, new_member_of);
}
}
}
static void cleanup_map(int32_t new_arg_num, void **new_args_base,
void **new_args, int64_t *new_arg_sizes, int64_t *new_arg_types,
int32_t arg_num, void **args_base) {
if (new_arg_num > 0) {
int offset = new_arg_num - arg_num;
for (int32_t i = 0; i < arg_num; ++i) {
// Restore old base address
args_base[i] = new_args_base[i+offset];
}
free(new_args_base);
free(new_args);
free(new_arg_sizes);
free(new_arg_types);
}
}
/// creates host-to-target data mapping, stores it in the
/// libomptarget.so internal structure (an entry in a stack of data maps)
/// and passes the data to the device.
EXTERN void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) {
DP("Entering data begin region for device %ld with %d mappings\n", device_id,
arg_num);
// No devices available?
if (device_id == OFFLOAD_DEVICE_DEFAULT) {
device_id = omp_get_default_device();
DP("Use default device id %ld\n", device_id);
}
if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) {
DP("Failed to get device %ld ready\n", device_id);
return;
}
DeviceTy& Device = Devices[device_id];
// Translate maps
int32_t new_arg_num;
void **new_args_base;
void **new_args;
int64_t *new_arg_sizes;
int64_t *new_arg_types;
translate_map(arg_num, args_base, args, arg_sizes, arg_types, new_arg_num,
new_args_base, new_args, new_arg_sizes, new_arg_types, false);
//target_data_begin(Device, arg_num, args_base, args, arg_sizes, arg_types);
target_data_begin(Device, new_arg_num, new_args_base, new_args, new_arg_sizes,
new_arg_types);
// Cleanup translation memory
cleanup_map(new_arg_num, new_args_base, new_args, new_arg_sizes,
new_arg_types, arg_num, args_base);
}
EXTERN void __tgt_target_data_begin_nowait(int64_t device_id, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types,
int32_t depNum, void *depList, int32_t noAliasDepNum,
void *noAliasDepList) {
if (depNum + noAliasDepNum > 0)
__kmpc_omp_taskwait(NULL, 0);
__tgt_target_data_begin(device_id, arg_num, args_base, args, arg_sizes,
arg_types);
}
/// passes data from the target, releases target memory and destroys
/// the host-target mapping (top entry from the stack of data maps)
/// created by the last __tgt_target_data_begin.
EXTERN void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) {
DP("Entering data end region with %d mappings\n", arg_num);
// No devices available?
if (device_id == OFFLOAD_DEVICE_DEFAULT) {
device_id = omp_get_default_device();
}
RTLsMtx.lock();
size_t Devices_size = Devices.size();
RTLsMtx.unlock();
if (Devices_size <= (size_t)device_id) {
DP("Device ID %ld does not have a matching RTL.\n", device_id);
return;
}
DeviceTy &Device = Devices[device_id];
if (!Device.IsInit) {
DP("uninit device: ignore");
return;
}
// Translate maps
int32_t new_arg_num;
void **new_args_base;
void **new_args;
int64_t *new_arg_sizes;
int64_t *new_arg_types;
translate_map(arg_num, args_base, args, arg_sizes, arg_types, new_arg_num,
new_args_base, new_args, new_arg_sizes, new_arg_types, false);
//target_data_end(Device, arg_num, args_base, args, arg_sizes, arg_types);
target_data_end(Device, new_arg_num, new_args_base, new_args, new_arg_sizes,
new_arg_types);
// Cleanup translation memory
cleanup_map(new_arg_num, new_args_base, new_args, new_arg_sizes,
new_arg_types, arg_num, args_base);
}
EXTERN void __tgt_target_data_end_nowait(int64_t device_id, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types,
int32_t depNum, void *depList, int32_t noAliasDepNum,
void *noAliasDepList) {
if (depNum + noAliasDepNum > 0)
__kmpc_omp_taskwait(NULL, 0);
__tgt_target_data_end(device_id, arg_num, args_base, args, arg_sizes,
arg_types);
}
EXTERN void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) {
DP("Entering data update with %d mappings\n", arg_num);
// No devices available?
if (device_id == OFFLOAD_DEVICE_DEFAULT) {
device_id = omp_get_default_device();
}
if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) {
DP("Failed to get device %ld ready\n", device_id);
return;
}
DeviceTy& Device = Devices[device_id];
target_data_update(Device, arg_num, args_base, args, arg_sizes, arg_types);
}
EXTERN void __tgt_target_data_update_nowait(
int64_t device_id, int32_t arg_num, void **args_base, void **args,
int64_t *arg_sizes, int64_t *arg_types, int32_t depNum, void *depList,
int32_t noAliasDepNum, void *noAliasDepList) {
if (depNum + noAliasDepNum > 0)
__kmpc_omp_taskwait(NULL, 0);
__tgt_target_data_update(device_id, arg_num, args_base, args, arg_sizes,
arg_types);
}
EXTERN int __tgt_target(int64_t device_id, void *host_ptr, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) {
DP("Entering target region with entry point " DPxMOD " and device Id %ld\n",
DPxPTR(host_ptr), device_id);
if (device_id == OFFLOAD_DEVICE_DEFAULT) {
device_id = omp_get_default_device();
}
if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) {
DP("Failed to get device %ld ready\n", device_id);
return OFFLOAD_FAIL;
}
// Translate maps
int32_t new_arg_num;
void **new_args_base;
void **new_args;
int64_t *new_arg_sizes;
int64_t *new_arg_types;
translate_map(arg_num, args_base, args, arg_sizes, arg_types, new_arg_num,
new_args_base, new_args, new_arg_sizes, new_arg_types, true);
//return target(device_id, host_ptr, arg_num, args_base, args, arg_sizes,
// arg_types, 0, 0, false /*team*/, false /*recursive*/);
int rc = target(device_id, host_ptr, new_arg_num, new_args_base, new_args,
new_arg_sizes, new_arg_types, 0, 0, false /*team*/);
// Cleanup translation memory
cleanup_map(new_arg_num, new_args_base, new_args, new_arg_sizes,
new_arg_types, arg_num, args_base);
return rc;
}
EXTERN int __tgt_target_nowait(int64_t device_id, void *host_ptr,
int32_t arg_num, void **args_base, void **args, int64_t *arg_sizes,
int64_t *arg_types, int32_t depNum, void *depList, int32_t noAliasDepNum,
void *noAliasDepList) {
if (depNum + noAliasDepNum > 0)
__kmpc_omp_taskwait(NULL, 0);
return __tgt_target(device_id, host_ptr, arg_num, args_base, args, arg_sizes,
arg_types);
}
EXTERN int __tgt_target_teams(int64_t device_id, void *host_ptr,
int32_t arg_num, void **args_base, void **args, int64_t *arg_sizes,
int64_t *arg_types, int32_t team_num, int32_t thread_limit) {
DP("Entering target region with entry point " DPxMOD " and device Id %ld\n",
DPxPTR(host_ptr), device_id);
if (device_id == OFFLOAD_DEVICE_DEFAULT) {
device_id = omp_get_default_device();
}
if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) {
DP("Failed to get device %ld ready\n", device_id);
return OFFLOAD_FAIL;
}
// Translate maps
int32_t new_arg_num;
void **new_args_base;
void **new_args;
int64_t *new_arg_sizes;
int64_t *new_arg_types;
translate_map(arg_num, args_base, args, arg_sizes, arg_types, new_arg_num,
new_args_base, new_args, new_arg_sizes, new_arg_types, true);
//return target(device_id, host_ptr, arg_num, args_base, args, arg_sizes,
// arg_types, team_num, thread_limit, true /*team*/,
// false /*recursive*/);
int rc = target(device_id, host_ptr, new_arg_num, new_args_base, new_args,
new_arg_sizes, new_arg_types, team_num, thread_limit, true /*team*/);
// Cleanup translation memory
cleanup_map(new_arg_num, new_args_base, new_args, new_arg_sizes,
new_arg_types, arg_num, args_base);
return rc;
}
EXTERN int __tgt_target_teams_nowait(int64_t device_id, void *host_ptr,
int32_t arg_num, void **args_base, void **args, int64_t *arg_sizes,
int64_t *arg_types, int32_t team_num, int32_t thread_limit, int32_t depNum,
void *depList, int32_t noAliasDepNum, void *noAliasDepList) {
if (depNum + noAliasDepNum > 0)
__kmpc_omp_taskwait(NULL, 0);
return __tgt_target_teams(device_id, host_ptr, arg_num, args_base, args,
arg_sizes, arg_types, team_num, thread_limit);
}
// The trip count mechanism will be revised - this scheme is not thread-safe.
EXTERN void __kmpc_push_target_tripcount(int64_t device_id,
uint64_t loop_tripcount) {
if (device_id == OFFLOAD_DEVICE_DEFAULT) {
device_id = omp_get_default_device();
}
if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) {
DP("Failed to get device %ld ready\n", device_id);
return;
}
DP("__kmpc_push_target_tripcount(%ld, %" PRIu64 ")\n", device_id,
loop_tripcount);
Devices[device_id].loopTripCnt = loop_tripcount;
}
+648
View File
@@ -0,0 +1,648 @@
//===------ omptarget.cpp - Target independent OpenMP target RTL -- 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.
//
//===----------------------------------------------------------------------===//
//
// Implementation of the interface to be used by Clang during the codegen of a
// target region.
//
//===----------------------------------------------------------------------===//
#include <omptarget.h>
#include "device.h"
#include "private.h"
#include "rtl.h"
#include <cassert>
#include <vector>
#ifdef OMPTARGET_DEBUG
int DebugLevel = 0;
#endif // OMPTARGET_DEBUG
/// Map global data and execute pending ctors
static int InitLibrary(DeviceTy& Device) {
/*
* Map global data
*/
int32_t device_id = Device.DeviceID;
int rc = OFFLOAD_SUCCESS;
Device.PendingGlobalsMtx.lock();
TrlTblMtx.lock();
for (HostEntriesBeginToTransTableTy::iterator
ii = HostEntriesBeginToTransTable.begin();
ii != HostEntriesBeginToTransTable.end(); ++ii) {
TranslationTable *TransTable = &ii->second;
if (TransTable->TargetsTable[device_id] != 0) {
// Library entries have already been processed
continue;
}
// 1) get image.
assert(TransTable->TargetsImages.size() > (size_t)device_id &&
"Not expecting a device ID outside the table's bounds!");
__tgt_device_image *img = TransTable->TargetsImages[device_id];
if (!img) {
DP("No image loaded for device id %d.\n", device_id);
rc = OFFLOAD_FAIL;
break;
}
// 2) load image into the target table.
__tgt_target_table *TargetTable =
TransTable->TargetsTable[device_id] = Device.load_binary(img);
// Unable to get table for this image: invalidate image and fail.
if (!TargetTable) {
DP("Unable to generate entries table for device id %d.\n", device_id);
TransTable->TargetsImages[device_id] = 0;
rc = OFFLOAD_FAIL;
break;
}
// Verify whether the two table sizes match.
size_t hsize =
TransTable->HostTable.EntriesEnd - TransTable->HostTable.EntriesBegin;
size_t tsize = TargetTable->EntriesEnd - TargetTable->EntriesBegin;
// Invalid image for these host entries!
if (hsize != tsize) {
DP("Host and Target tables mismatch for device id %d [%zx != %zx].\n",
device_id, hsize, tsize);
TransTable->TargetsImages[device_id] = 0;
TransTable->TargetsTable[device_id] = 0;
rc = OFFLOAD_FAIL;
break;
}
// process global data that needs to be mapped.
Device.DataMapMtx.lock();
__tgt_target_table *HostTable = &TransTable->HostTable;
for (__tgt_offload_entry *CurrDeviceEntry = TargetTable->EntriesBegin,
*CurrHostEntry = HostTable->EntriesBegin,
*EntryDeviceEnd = TargetTable->EntriesEnd;
CurrDeviceEntry != EntryDeviceEnd;
CurrDeviceEntry++, CurrHostEntry++) {
if (CurrDeviceEntry->size != 0) {
// has data.
assert(CurrDeviceEntry->size == CurrHostEntry->size &&
"data size mismatch");
// Fortran may use multiple weak declarations for the same symbol,
// therefore we must allow for multiple weak symbols to be loaded from
// the fat binary. Treat these mappings as any other "regular" mapping.
// Add entry to map.
if (Device.getTgtPtrBegin(CurrHostEntry->addr, CurrHostEntry->size))
continue;
DP("Add mapping from host " DPxMOD " to device " DPxMOD " with size %zu"
"\n", DPxPTR(CurrHostEntry->addr), DPxPTR(CurrDeviceEntry->addr),
CurrDeviceEntry->size);
Device.HostDataToTargetMap.push_front(HostDataToTargetTy(
(uintptr_t)CurrHostEntry->addr /*HstPtrBase*/,
(uintptr_t)CurrHostEntry->addr /*HstPtrBegin*/,
(uintptr_t)CurrHostEntry->addr + CurrHostEntry->size /*HstPtrEnd*/,
(uintptr_t)CurrDeviceEntry->addr /*TgtPtrBegin*/,
INF_REF_CNT /*RefCount*/));
}
}
Device.DataMapMtx.unlock();
}
TrlTblMtx.unlock();
if (rc != OFFLOAD_SUCCESS) {
Device.PendingGlobalsMtx.unlock();
return rc;
}
/*
* Run ctors for static objects
*/
if (!Device.PendingCtorsDtors.empty()) {
// Call all ctors for all libraries registered so far
for (auto &lib : Device.PendingCtorsDtors) {
if (!lib.second.PendingCtors.empty()) {
DP("Has pending ctors... call now\n");
for (auto &entry : lib.second.PendingCtors) {
void *ctor = entry;
int rc = target(device_id, ctor, 0, NULL, NULL, NULL,
NULL, 1, 1, true /*team*/);
if (rc != OFFLOAD_SUCCESS) {
DP("Running ctor " DPxMOD " failed.\n", DPxPTR(ctor));
Device.PendingGlobalsMtx.unlock();
return OFFLOAD_FAIL;
}
}
// Clear the list to indicate that this device has been used
lib.second.PendingCtors.clear();
DP("Done with pending ctors for lib " DPxMOD "\n", DPxPTR(lib.first));
}
}
}
Device.HasPendingGlobals = false;
Device.PendingGlobalsMtx.unlock();
return OFFLOAD_SUCCESS;
}
// Check whether a device has been initialized, global ctors have been
// executed and global data has been mapped; do so if not already done.
int CheckDeviceAndCtors(int64_t device_id) {
// Is device ready?
if (!device_is_ready(device_id)) {
DP("Device %" PRId64 " is not ready.\n", device_id);
return OFFLOAD_FAIL;
}
// Get device info.
DeviceTy &Device = Devices[device_id];
// Check whether global data has been mapped for this device
Device.PendingGlobalsMtx.lock();
bool hasPendingGlobals = Device.HasPendingGlobals;
Device.PendingGlobalsMtx.unlock();
if (hasPendingGlobals && InitLibrary(Device) != OFFLOAD_SUCCESS) {
DP("Failed to init globals on device %" PRId64 "\n", device_id);
return OFFLOAD_FAIL;
}
return OFFLOAD_SUCCESS;
}
static short member_of(int64_t type) {
return ((type & OMP_TGT_MAPTYPE_MEMBER_OF) >> 48) - 1;
}
/// Internal function to do the mapping and transfer the data to the device
int target_data_begin(DeviceTy &Device, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) {
// process each input.
int rc = OFFLOAD_SUCCESS;
for (int32_t i = 0; i < arg_num; ++i) {
// Ignore private variables and arrays - there is no mapping for them.
if ((arg_types[i] & OMP_TGT_MAPTYPE_LITERAL) ||
(arg_types[i] & OMP_TGT_MAPTYPE_PRIVATE))
continue;
void *HstPtrBegin = args[i];
void *HstPtrBase = args_base[i];
// Address of pointer on the host and device, respectively.
void *Pointer_HstPtrBegin, *Pointer_TgtPtrBegin;
bool IsNew, Pointer_IsNew;
bool IsImplicit = arg_types[i] & OMP_TGT_MAPTYPE_IMPLICIT;
bool UpdateRef = !(arg_types[i] & OMP_TGT_MAPTYPE_MEMBER_OF);
if (arg_types[i] & OMP_TGT_MAPTYPE_PTR_AND_OBJ) {
DP("Has a pointer entry: \n");
// base is address of pointer.
Pointer_TgtPtrBegin = Device.getOrAllocTgtPtr(HstPtrBase, HstPtrBase,
sizeof(void *), Pointer_IsNew, IsImplicit, UpdateRef);
if (!Pointer_TgtPtrBegin) {
DP("Call to getOrAllocTgtPtr returned null pointer (device failure or "
"illegal mapping).\n");
}
DP("There are %zu bytes allocated at target address " DPxMOD " - is%s new"
"\n", sizeof(void *), DPxPTR(Pointer_TgtPtrBegin),
(Pointer_IsNew ? "" : " not"));
Pointer_HstPtrBegin = HstPtrBase;
// modify current entry.
HstPtrBase = *(void **)HstPtrBase;
UpdateRef = true; // subsequently update ref count of pointee
}
void *TgtPtrBegin = Device.getOrAllocTgtPtr(HstPtrBegin, HstPtrBase,
arg_sizes[i], IsNew, IsImplicit, UpdateRef);
if (!TgtPtrBegin && arg_sizes[i]) {
// If arg_sizes[i]==0, then the argument is a pointer to NULL, so
// getOrAlloc() returning NULL is not an error.
DP("Call to getOrAllocTgtPtr returned null pointer (device failure or "
"illegal mapping).\n");
}
DP("There are %" PRId64 " bytes allocated at target address " DPxMOD
" - is%s new\n", arg_sizes[i], DPxPTR(TgtPtrBegin),
(IsNew ? "" : " not"));
if (arg_types[i] & OMP_TGT_MAPTYPE_RETURN_PARAM) {
void *ret_ptr;
if (arg_types[i] & OMP_TGT_MAPTYPE_PTR_AND_OBJ)
ret_ptr = Pointer_TgtPtrBegin;
else {
bool IsLast; // not used
ret_ptr = Device.getTgtPtrBegin(HstPtrBegin, 0, IsLast, false);
}
DP("Returning device pointer " DPxMOD "\n", DPxPTR(ret_ptr));
args_base[i] = ret_ptr;
}
if (arg_types[i] & OMP_TGT_MAPTYPE_TO) {
bool copy = false;
if (IsNew || (arg_types[i] & OMP_TGT_MAPTYPE_ALWAYS)) {
copy = true;
} else if (arg_types[i] & OMP_TGT_MAPTYPE_MEMBER_OF) {
// Copy data only if the "parent" struct has RefCount==1.
short parent_idx = member_of(arg_types[i]);
long parent_rc = Device.getMapEntryRefCnt(args[parent_idx]);
assert(parent_rc > 0 && "parent struct not found");
if (parent_rc == 1) {
copy = true;
}
}
if (copy) {
DP("Moving %" PRId64 " bytes (hst:" DPxMOD ") -> (tgt:" DPxMOD ")\n",
arg_sizes[i], DPxPTR(HstPtrBegin), DPxPTR(TgtPtrBegin));
int rt = Device.data_submit(TgtPtrBegin, HstPtrBegin, arg_sizes[i]);
if (rt != OFFLOAD_SUCCESS) {
DP("Copying data to device failed.\n");
rc = OFFLOAD_FAIL;
}
}
}
if (arg_types[i] & OMP_TGT_MAPTYPE_PTR_AND_OBJ) {
DP("Update pointer (" DPxMOD ") -> [" DPxMOD "]\n",
DPxPTR(Pointer_TgtPtrBegin), DPxPTR(TgtPtrBegin));
uint64_t Delta = (uint64_t)HstPtrBegin - (uint64_t)HstPtrBase;
void *TgtPtrBase = (void *)((uint64_t)TgtPtrBegin - Delta);
int rt = Device.data_submit(Pointer_TgtPtrBegin, &TgtPtrBase,
sizeof(void *));
if (rt != OFFLOAD_SUCCESS) {
DP("Copying data to device failed.\n");
rc = OFFLOAD_FAIL;
}
// create shadow pointers for this entry
Device.ShadowMtx.lock();
Device.ShadowPtrMap[Pointer_HstPtrBegin] = {HstPtrBase,
Pointer_TgtPtrBegin, TgtPtrBase};
Device.ShadowMtx.unlock();
}
}
return rc;
}
/// Internal function to undo the mapping and retrieve the data from the device.
int target_data_end(DeviceTy &Device, int32_t arg_num, void **args_base,
void **args, int64_t *arg_sizes, int64_t *arg_types) {
int rc = OFFLOAD_SUCCESS;
// process each input.
for (int32_t i = arg_num - 1; i >= 0; --i) {
// Ignore private variables and arrays - there is no mapping for them.
// Also, ignore the use_device_ptr directive, it has no effect here.
if ((arg_types[i] & OMP_TGT_MAPTYPE_LITERAL) ||
(arg_types[i] & OMP_TGT_MAPTYPE_PRIVATE))
continue;
void *HstPtrBegin = args[i];
bool IsLast;
bool UpdateRef = !(arg_types[i] & OMP_TGT_MAPTYPE_MEMBER_OF) ||
(arg_types[i] & OMP_TGT_MAPTYPE_PTR_AND_OBJ);
bool ForceDelete = arg_types[i] & OMP_TGT_MAPTYPE_DELETE;
// If PTR_AND_OBJ, HstPtrBegin is address of pointee
void *TgtPtrBegin = Device.getTgtPtrBegin(HstPtrBegin, arg_sizes[i], IsLast,
UpdateRef);
DP("There are %" PRId64 " bytes allocated at target address " DPxMOD
" - is%s last\n", arg_sizes[i], DPxPTR(TgtPtrBegin),
(IsLast ? "" : " not"));
bool DelEntry = IsLast || ForceDelete;
if ((arg_types[i] & OMP_TGT_MAPTYPE_MEMBER_OF) &&
!(arg_types[i] & OMP_TGT_MAPTYPE_PTR_AND_OBJ)) {
DelEntry = false; // protect parent struct from being deallocated
}
if ((arg_types[i] & OMP_TGT_MAPTYPE_FROM) || DelEntry) {
// Move data back to the host
if (arg_types[i] & OMP_TGT_MAPTYPE_FROM) {
bool Always = arg_types[i] & OMP_TGT_MAPTYPE_ALWAYS;
bool CopyMember = false;
if ((arg_types[i] & OMP_TGT_MAPTYPE_MEMBER_OF) &&
!(arg_types[i] & OMP_TGT_MAPTYPE_PTR_AND_OBJ)) {
// Copy data only if the "parent" struct has RefCount==1.
short parent_idx = member_of(arg_types[i]);
long parent_rc = Device.getMapEntryRefCnt(args[parent_idx]);
assert(parent_rc > 0 && "parent struct not found");
if (parent_rc == 1) {
CopyMember = true;
}
}
if (DelEntry || Always || CopyMember) {
DP("Moving %" PRId64 " bytes (tgt:" DPxMOD ") -> (hst:" DPxMOD ")\n",
arg_sizes[i], DPxPTR(TgtPtrBegin), DPxPTR(HstPtrBegin));
int rt = Device.data_retrieve(HstPtrBegin, TgtPtrBegin, arg_sizes[i]);
if (rt != OFFLOAD_SUCCESS) {
DP("Copying data from device failed.\n");
rc = OFFLOAD_FAIL;
}
}
}
// If we copied back to the host a struct/array containing pointers, we
// need to restore the original host pointer values from their shadow
// copies. If the struct is going to be deallocated, remove any remaining
// shadow pointer entries for this struct.
uintptr_t lb = (uintptr_t) HstPtrBegin;
uintptr_t ub = (uintptr_t) HstPtrBegin + arg_sizes[i];
Device.ShadowMtx.lock();
for (ShadowPtrListTy::iterator it = Device.ShadowPtrMap.begin();
it != Device.ShadowPtrMap.end(); ++it) {
void **ShadowHstPtrAddr = (void**) it->first;
// An STL map is sorted on its keys; use this property
// to quickly determine when to break out of the loop.
if ((uintptr_t) ShadowHstPtrAddr < lb)
continue;
if ((uintptr_t) ShadowHstPtrAddr >= ub)
break;
// If we copied the struct to the host, we need to restore the pointer.
if (arg_types[i] & OMP_TGT_MAPTYPE_FROM) {
DP("Restoring original host pointer value " DPxMOD " for host "
"pointer " DPxMOD "\n", DPxPTR(it->second.HstPtrVal),
DPxPTR(ShadowHstPtrAddr));
*ShadowHstPtrAddr = it->second.HstPtrVal;
}
// If the struct is to be deallocated, remove the shadow entry.
if (DelEntry) {
DP("Removing shadow pointer " DPxMOD "\n", DPxPTR(ShadowHstPtrAddr));
Device.ShadowPtrMap.erase(it);
}
}
Device.ShadowMtx.unlock();
// Deallocate map
if (DelEntry) {
int rt = Device.deallocTgtPtr(HstPtrBegin, arg_sizes[i], ForceDelete);
if (rt != OFFLOAD_SUCCESS) {
DP("Deallocating data from device failed.\n");
rc = OFFLOAD_FAIL;
}
}
}
}
return rc;
}
/// Internal function to pass data to/from the target.
void target_data_update(DeviceTy &Device, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) {
// process each input.
for (int32_t i = 0; i < arg_num; ++i) {
if ((arg_types[i] & OMP_TGT_MAPTYPE_LITERAL) ||
(arg_types[i] & OMP_TGT_MAPTYPE_PRIVATE))
continue;
void *HstPtrBegin = args[i];
int64_t MapSize = arg_sizes[i];
bool IsLast;
void *TgtPtrBegin = Device.getTgtPtrBegin(HstPtrBegin, MapSize, IsLast,
false);
if (arg_types[i] & OMP_TGT_MAPTYPE_FROM) {
DP("Moving %" PRId64 " bytes (tgt:" DPxMOD ") -> (hst:" DPxMOD ")\n",
arg_sizes[i], DPxPTR(TgtPtrBegin), DPxPTR(HstPtrBegin));
Device.data_retrieve(HstPtrBegin, TgtPtrBegin, MapSize);
uintptr_t lb = (uintptr_t) HstPtrBegin;
uintptr_t ub = (uintptr_t) HstPtrBegin + MapSize;
Device.ShadowMtx.lock();
for (ShadowPtrListTy::iterator it = Device.ShadowPtrMap.begin();
it != Device.ShadowPtrMap.end(); ++it) {
void **ShadowHstPtrAddr = (void**) it->first;
if ((uintptr_t) ShadowHstPtrAddr < lb)
continue;
if ((uintptr_t) ShadowHstPtrAddr >= ub)
break;
DP("Restoring original host pointer value " DPxMOD " for host pointer "
DPxMOD "\n", DPxPTR(it->second.HstPtrVal),
DPxPTR(ShadowHstPtrAddr));
*ShadowHstPtrAddr = it->second.HstPtrVal;
}
Device.ShadowMtx.unlock();
}
if (arg_types[i] & OMP_TGT_MAPTYPE_TO) {
DP("Moving %" PRId64 " bytes (hst:" DPxMOD ") -> (tgt:" DPxMOD ")\n",
arg_sizes[i], DPxPTR(HstPtrBegin), DPxPTR(TgtPtrBegin));
Device.data_submit(TgtPtrBegin, HstPtrBegin, MapSize);
uintptr_t lb = (uintptr_t) HstPtrBegin;
uintptr_t ub = (uintptr_t) HstPtrBegin + MapSize;
Device.ShadowMtx.lock();
for (ShadowPtrListTy::iterator it = Device.ShadowPtrMap.begin();
it != Device.ShadowPtrMap.end(); ++it) {
void **ShadowHstPtrAddr = (void**) it->first;
if ((uintptr_t) ShadowHstPtrAddr < lb)
continue;
if ((uintptr_t) ShadowHstPtrAddr >= ub)
break;
DP("Restoring original target pointer value " DPxMOD " for target "
"pointer " DPxMOD "\n", DPxPTR(it->second.TgtPtrVal),
DPxPTR(it->second.TgtPtrAddr));
Device.data_submit(it->second.TgtPtrAddr,
&it->second.TgtPtrVal, sizeof(void *));
}
Device.ShadowMtx.unlock();
}
}
}
/// performs the same actions as data_begin in case arg_num is
/// non-zero and initiates run of the offloaded region on the target platform;
/// if arg_num is non-zero after the region execution is done it also
/// performs the same action as data_update and data_end above. This function
/// returns 0 if it was able to transfer the execution to a target and an
/// integer different from zero otherwise.
int target(int64_t device_id, void *host_ptr, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types,
int32_t team_num, int32_t thread_limit, int IsTeamConstruct) {
DeviceTy &Device = Devices[device_id];
// Find the table information in the map or look it up in the translation
// tables.
TableMap *TM = 0;
TblMapMtx.lock();
HostPtrToTableMapTy::iterator TableMapIt = HostPtrToTableMap.find(host_ptr);
if (TableMapIt == HostPtrToTableMap.end()) {
// We don't have a map. So search all the registered libraries.
TrlTblMtx.lock();
for (HostEntriesBeginToTransTableTy::iterator
ii = HostEntriesBeginToTransTable.begin(),
ie = HostEntriesBeginToTransTable.end();
!TM && ii != ie; ++ii) {
// get the translation table (which contains all the good info).
TranslationTable *TransTable = &ii->second;
// iterate over all the host table entries to see if we can locate the
// host_ptr.
__tgt_offload_entry *begin = TransTable->HostTable.EntriesBegin;
__tgt_offload_entry *end = TransTable->HostTable.EntriesEnd;
__tgt_offload_entry *cur = begin;
for (uint32_t i = 0; cur < end; ++cur, ++i) {
if (cur->addr != host_ptr)
continue;
// we got a match, now fill the HostPtrToTableMap so that we
// may avoid this search next time.
TM = &HostPtrToTableMap[host_ptr];
TM->Table = TransTable;
TM->Index = i;
break;
}
}
TrlTblMtx.unlock();
} else {
TM = &TableMapIt->second;
}
TblMapMtx.unlock();
// No map for this host pointer found!
if (!TM) {
DP("Host ptr " DPxMOD " does not have a matching target pointer.\n",
DPxPTR(host_ptr));
return OFFLOAD_FAIL;
}
// get target table.
TrlTblMtx.lock();
assert(TM->Table->TargetsTable.size() > (size_t)device_id &&
"Not expecting a device ID outside the table's bounds!");
__tgt_target_table *TargetTable = TM->Table->TargetsTable[device_id];
TrlTblMtx.unlock();
assert(TargetTable && "Global data has not been mapped\n");
// Move data to device.
int rc = target_data_begin(Device, arg_num, args_base, args, arg_sizes,
arg_types);
if (rc != OFFLOAD_SUCCESS) {
DP("Call to target_data_begin failed, skipping target execution.\n");
// Call target_data_end to dealloc whatever target_data_begin allocated
// and return OFFLOAD_FAIL.
target_data_end(Device, arg_num, args_base, args, arg_sizes, arg_types);
return OFFLOAD_FAIL;
}
std::vector<void *> tgt_args;
std::vector<ptrdiff_t> tgt_offsets;
// List of (first-)private arrays allocated for this target region
std::vector<void *> fpArrays;
for (int32_t i = 0; i < arg_num; ++i) {
if (!(arg_types[i] & OMP_TGT_MAPTYPE_TARGET_PARAM)) {
// This is not a target parameter, do not push it into tgt_args.
continue;
}
void *HstPtrBegin = args[i];
void *HstPtrBase = args_base[i];
void *TgtPtrBegin;
ptrdiff_t TgtBaseOffset;
bool IsLast; // unused.
if (arg_types[i] & OMP_TGT_MAPTYPE_LITERAL) {
DP("Forwarding first-private value " DPxMOD " to the target construct\n",
DPxPTR(HstPtrBase));
TgtPtrBegin = HstPtrBase;
TgtBaseOffset = 0;
} else if (arg_types[i] & OMP_TGT_MAPTYPE_PRIVATE) {
// Allocate memory for (first-)private array
TgtPtrBegin = Device.RTL->data_alloc(Device.RTLDeviceID,
arg_sizes[i], HstPtrBegin);
if (!TgtPtrBegin) {
DP ("Data allocation for %sprivate array " DPxMOD " failed\n",
(arg_types[i] & OMP_TGT_MAPTYPE_TO ? "first-" : ""),
DPxPTR(HstPtrBegin));
rc = OFFLOAD_FAIL;
break;
} else {
fpArrays.push_back(TgtPtrBegin);
TgtBaseOffset = (intptr_t)HstPtrBase - (intptr_t)HstPtrBegin;
#ifdef OMPTARGET_DEBUG
void *TgtPtrBase = (void *)((intptr_t)TgtPtrBegin + TgtBaseOffset);
DP("Allocated %" PRId64 " bytes of target memory at " DPxMOD " for "
"%sprivate array " DPxMOD " - pushing target argument " DPxMOD "\n",
arg_sizes[i], DPxPTR(TgtPtrBegin),
(arg_types[i] & OMP_TGT_MAPTYPE_TO ? "first-" : ""),
DPxPTR(HstPtrBegin), DPxPTR(TgtPtrBase));
#endif
// If first-private, copy data from host
if (arg_types[i] & OMP_TGT_MAPTYPE_TO) {
int rt = Device.data_submit(TgtPtrBegin, HstPtrBegin, arg_sizes[i]);
if (rt != OFFLOAD_SUCCESS) {
DP ("Copying data to device failed.\n");
rc = OFFLOAD_FAIL;
break;
}
}
}
} else if (arg_types[i] & OMP_TGT_MAPTYPE_PTR_AND_OBJ) {
TgtPtrBegin = Device.getTgtPtrBegin(HstPtrBase, sizeof(void *), IsLast,
false);
TgtBaseOffset = 0; // no offset for ptrs.
DP("Obtained target argument " DPxMOD " from host pointer " DPxMOD " to "
"object " DPxMOD "\n", DPxPTR(TgtPtrBegin), DPxPTR(HstPtrBase),
DPxPTR(HstPtrBase));
} else {
TgtPtrBegin = Device.getTgtPtrBegin(HstPtrBegin, arg_sizes[i], IsLast,
false);
TgtBaseOffset = (intptr_t)HstPtrBase - (intptr_t)HstPtrBegin;
#ifdef OMPTARGET_DEBUG
void *TgtPtrBase = (void *)((intptr_t)TgtPtrBegin + TgtBaseOffset);
DP("Obtained target argument " DPxMOD " from host pointer " DPxMOD "\n",
DPxPTR(TgtPtrBase), DPxPTR(HstPtrBegin));
#endif
}
tgt_args.push_back(TgtPtrBegin);
tgt_offsets.push_back(TgtBaseOffset);
}
assert(tgt_args.size() == tgt_offsets.size() &&
"Size mismatch in arguments and offsets");
// Pop loop trip count
uint64_t ltc = Device.loopTripCnt;
Device.loopTripCnt = 0;
// Launch device execution.
if (rc == OFFLOAD_SUCCESS) {
DP("Launching target execution %s with pointer " DPxMOD " (index=%d).\n",
TargetTable->EntriesBegin[TM->Index].name,
DPxPTR(TargetTable->EntriesBegin[TM->Index].addr), TM->Index);
if (IsTeamConstruct) {
rc = Device.run_team_region(TargetTable->EntriesBegin[TM->Index].addr,
&tgt_args[0], &tgt_offsets[0], tgt_args.size(), team_num,
thread_limit, ltc);
} else {
rc = Device.run_region(TargetTable->EntriesBegin[TM->Index].addr,
&tgt_args[0], &tgt_offsets[0], tgt_args.size());
}
} else {
DP("Errors occurred while obtaining target arguments, skipping kernel "
"execution\n");
}
// Deallocate (first-)private arrays
for (auto it : fpArrays) {
int rt = Device.RTL->data_delete(Device.RTLDeviceID, it);
if (rt != OFFLOAD_SUCCESS) {
DP("Deallocation of (first-)private arrays failed.\n");
rc = OFFLOAD_FAIL;
}
}
// Move data from device.
int rt = target_data_end(Device, arg_num, args_base, args, arg_sizes,
arg_types);
if (rt != OFFLOAD_SUCCESS) {
DP("Call to target_data_end failed.\n");
rc = OFFLOAD_FAIL;
}
return rc;
}
+49
View File
@@ -0,0 +1,49 @@
//===---------- private.h - Target independent OpenMP target RTL ----------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
// Private function declarations and helper macros for debugging output.
//
//===----------------------------------------------------------------------===//
#ifndef _OMPTARGET_PRIVATE_H
#define _OMPTARGET_PRIVATE_H
#include <omptarget.h>
#include <cstdint>
extern int target_data_begin(DeviceTy &Device, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
extern int target_data_end(DeviceTy &Device, int32_t arg_num, void **args_base,
void **args, int64_t *arg_sizes, int64_t *arg_types);
extern void target_data_update(DeviceTy &Device, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
extern int target(int64_t device_id, void *host_ptr, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types,
int32_t team_num, int32_t thread_limit, int IsTeamConstruct);
extern int CheckDeviceAndCtors(int64_t device_id);
#ifdef OMPTARGET_DEBUG
extern int DebugLevel;
#define DP(...) \
do { \
if (DebugLevel > 0) { \
DEBUGP("Libomptarget", __VA_ARGS__); \
} \
} while (false)
#else // OMPTARGET_DEBUG
#define DP(...) {}
#endif // OMPTARGET_DEBUG
#endif
+368
View File
@@ -0,0 +1,368 @@
//===----------- rtl.cpp - Target independent OpenMP target RTL -----------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
// Functionality for handling RTL plugins.
//
//===----------------------------------------------------------------------===//
#include "device.h"
#include "private.h"
#include "rtl.h"
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <dlfcn.h>
#include <mutex>
#include <string>
// List of all plugins that can support offloading.
static const char *RTLNames[] = {
/* PowerPC target */ "libomptarget.rtl.ppc64.so",
/* x86_64 target */ "libomptarget.rtl.x86_64.so",
/* CUDA target */ "libomptarget.rtl.cuda.so",
/* AArch64 target */ "libomptarget.rtl.aarch64.so"};
RTLsTy RTLs;
std::mutex RTLsMtx;
HostEntriesBeginToTransTableTy HostEntriesBeginToTransTable;
std::mutex TrlTblMtx;
HostPtrToTableMapTy HostPtrToTableMap;
std::mutex TblMapMtx;
void RTLsTy::LoadRTLs() {
#ifdef OMPTARGET_DEBUG
if (char *envStr = getenv("LIBOMPTARGET_DEBUG")) {
DebugLevel = std::stoi(envStr);
}
#endif // OMPTARGET_DEBUG
// Parse environment variable OMP_TARGET_OFFLOAD (if set)
char *envStr = getenv("OMP_TARGET_OFFLOAD");
if (envStr && !strcmp(envStr, "DISABLED")) {
DP("Target offloading disabled by environment\n");
return;
}
DP("Loading RTLs...\n");
// Attempt to open all the plugins and, if they exist, check if the interface
// is correct and if they are supporting any devices.
for (auto *Name : RTLNames) {
DP("Loading library '%s'...\n", Name);
void *dynlib_handle = dlopen(Name, RTLD_NOW);
if (!dynlib_handle) {
// Library does not exist or cannot be found.
DP("Unable to load library '%s': %s!\n", Name, dlerror());
continue;
}
DP("Successfully loaded library '%s'!\n", Name);
// Retrieve the RTL information from the runtime library.
RTLInfoTy R;
R.LibraryHandler = dynlib_handle;
R.isUsed = false;
#ifdef OMPTARGET_DEBUG
R.RTLName = Name;
#endif
if (!(*((void**) &R.is_valid_binary) = dlsym(
dynlib_handle, "__tgt_rtl_is_valid_binary")))
continue;
if (!(*((void**) &R.number_of_devices) = dlsym(
dynlib_handle, "__tgt_rtl_number_of_devices")))
continue;
if (!(*((void**) &R.init_device) = dlsym(
dynlib_handle, "__tgt_rtl_init_device")))
continue;
if (!(*((void**) &R.load_binary) = dlsym(
dynlib_handle, "__tgt_rtl_load_binary")))
continue;
if (!(*((void**) &R.data_alloc) = dlsym(
dynlib_handle, "__tgt_rtl_data_alloc")))
continue;
if (!(*((void**) &R.data_submit) = dlsym(
dynlib_handle, "__tgt_rtl_data_submit")))
continue;
if (!(*((void**) &R.data_retrieve) = dlsym(
dynlib_handle, "__tgt_rtl_data_retrieve")))
continue;
if (!(*((void**) &R.data_delete) = dlsym(
dynlib_handle, "__tgt_rtl_data_delete")))
continue;
if (!(*((void**) &R.run_region) = dlsym(
dynlib_handle, "__tgt_rtl_run_target_region")))
continue;
if (!(*((void**) &R.run_team_region) = dlsym(
dynlib_handle, "__tgt_rtl_run_target_team_region")))
continue;
// No devices are supported by this RTL?
if (!(R.NumberOfDevices = R.number_of_devices())) {
DP("No devices supported in this RTL\n");
continue;
}
DP("Registering RTL %s supporting %d devices!\n",
R.RTLName.c_str(), R.NumberOfDevices);
// The RTL is valid! Will save the information in the RTLs list.
AllRTLs.push_back(R);
}
DP("RTLs loaded!\n");
return;
}
////////////////////////////////////////////////////////////////////////////////
// Functionality for registering libs
static void RegisterImageIntoTranslationTable(TranslationTable &TT,
RTLInfoTy &RTL, __tgt_device_image *image) {
// same size, as when we increase one, we also increase the other.
assert(TT.TargetsTable.size() == TT.TargetsImages.size() &&
"We should have as many images as we have tables!");
// Resize the Targets Table and Images to accommodate the new targets if
// required
unsigned TargetsTableMinimumSize = RTL.Idx + RTL.NumberOfDevices;
if (TT.TargetsTable.size() < TargetsTableMinimumSize) {
TT.TargetsImages.resize(TargetsTableMinimumSize, 0);
TT.TargetsTable.resize(TargetsTableMinimumSize, 0);
}
// Register the image in all devices for this target type.
for (int32_t i = 0; i < RTL.NumberOfDevices; ++i) {
// If we are changing the image we are also invalidating the target table.
if (TT.TargetsImages[RTL.Idx + i] != image) {
TT.TargetsImages[RTL.Idx + i] = image;
TT.TargetsTable[RTL.Idx + i] = 0; // lazy initialization of target table.
}
}
}
////////////////////////////////////////////////////////////////////////////////
// Functionality for registering Ctors/Dtors
static void RegisterGlobalCtorsDtorsForImage(__tgt_bin_desc *desc,
__tgt_device_image *img, RTLInfoTy *RTL) {
for (int32_t i = 0; i < RTL->NumberOfDevices; ++i) {
DeviceTy &Device = Devices[RTL->Idx + i];
Device.PendingGlobalsMtx.lock();
Device.HasPendingGlobals = true;
for (__tgt_offload_entry *entry = img->EntriesBegin;
entry != img->EntriesEnd; ++entry) {
if (entry->flags & OMP_DECLARE_TARGET_CTOR) {
DP("Adding ctor " DPxMOD " to the pending list.\n",
DPxPTR(entry->addr));
Device.PendingCtorsDtors[desc].PendingCtors.push_back(entry->addr);
} else if (entry->flags & OMP_DECLARE_TARGET_DTOR) {
// Dtors are pushed in reverse order so they are executed from end
// to beginning when unregistering the library!
DP("Adding dtor " DPxMOD " to the pending list.\n",
DPxPTR(entry->addr));
Device.PendingCtorsDtors[desc].PendingDtors.push_front(entry->addr);
}
if (entry->flags & OMP_DECLARE_TARGET_LINK) {
DP("The \"link\" attribute is not yet supported!\n");
}
}
Device.PendingGlobalsMtx.unlock();
}
}
void RTLsTy::RegisterLib(__tgt_bin_desc *desc) {
// Attempt to load all plugins available in the system.
std::call_once(initFlag, &RTLsTy::LoadRTLs, this);
RTLsMtx.lock();
// Register the images with the RTLs that understand them, if any.
for (int32_t i = 0; i < desc->NumDeviceImages; ++i) {
// Obtain the image.
__tgt_device_image *img = &desc->DeviceImages[i];
RTLInfoTy *FoundRTL = NULL;
// Scan the RTLs that have associated images until we find one that supports
// the current image.
for (auto &R : RTLs.AllRTLs) {
if (!R.is_valid_binary(img)) {
DP("Image " DPxMOD " is NOT compatible with RTL %s!\n",
DPxPTR(img->ImageStart), R.RTLName.c_str());
continue;
}
DP("Image " DPxMOD " is compatible with RTL %s!\n",
DPxPTR(img->ImageStart), R.RTLName.c_str());
// If this RTL is not already in use, initialize it.
if (!R.isUsed) {
// Initialize the device information for the RTL we are about to use.
DeviceTy device(&R);
size_t start = Devices.size();
Devices.resize(start + R.NumberOfDevices, device);
for (int32_t device_id = 0; device_id < R.NumberOfDevices;
device_id++) {
// global device ID
Devices[start + device_id].DeviceID = start + device_id;
// RTL local device ID
Devices[start + device_id].RTLDeviceID = device_id;
// Save pointer to device in RTL in case we want to unregister the RTL
R.Devices.push_back(&Devices[start + device_id]);
}
// Initialize the index of this RTL and save it in the used RTLs.
R.Idx = (RTLs.UsedRTLs.empty())
? 0
: RTLs.UsedRTLs.back()->Idx +
RTLs.UsedRTLs.back()->NumberOfDevices;
assert((size_t) R.Idx == start &&
"RTL index should equal the number of devices used so far.");
R.isUsed = true;
RTLs.UsedRTLs.push_back(&R);
DP("RTL " DPxMOD " has index %d!\n", DPxPTR(R.LibraryHandler), R.Idx);
}
// Initialize (if necessary) translation table for this library.
TrlTblMtx.lock();
if(!HostEntriesBeginToTransTable.count(desc->HostEntriesBegin)){
TranslationTable &tt =
HostEntriesBeginToTransTable[desc->HostEntriesBegin];
tt.HostTable.EntriesBegin = desc->HostEntriesBegin;
tt.HostTable.EntriesEnd = desc->HostEntriesEnd;
}
// Retrieve translation table for this library.
TranslationTable &TransTable =
HostEntriesBeginToTransTable[desc->HostEntriesBegin];
DP("Registering image " DPxMOD " with RTL %s!\n",
DPxPTR(img->ImageStart), R.RTLName.c_str());
RegisterImageIntoTranslationTable(TransTable, R, img);
TrlTblMtx.unlock();
FoundRTL = &R;
// Load ctors/dtors for static objects
RegisterGlobalCtorsDtorsForImage(desc, img, FoundRTL);
// if an RTL was found we are done - proceed to register the next image
break;
}
if (!FoundRTL) {
DP("No RTL found for image " DPxMOD "!\n", DPxPTR(img->ImageStart));
}
}
RTLsMtx.unlock();
DP("Done registering entries!\n");
}
void RTLsTy::UnregisterLib(__tgt_bin_desc *desc) {
DP("Unloading target library!\n");
RTLsMtx.lock();
// Find which RTL understands each image, if any.
for (int32_t i = 0; i < desc->NumDeviceImages; ++i) {
// Obtain the image.
__tgt_device_image *img = &desc->DeviceImages[i];
RTLInfoTy *FoundRTL = NULL;
// Scan the RTLs that have associated images until we find one that supports
// the current image. We only need to scan RTLs that are already being used.
for (auto *R : RTLs.UsedRTLs) {
assert(R->isUsed && "Expecting used RTLs.");
if (!R->is_valid_binary(img)) {
DP("Image " DPxMOD " is NOT compatible with RTL " DPxMOD "!\n",
DPxPTR(img->ImageStart), DPxPTR(R->LibraryHandler));
continue;
}
DP("Image " DPxMOD " is compatible with RTL " DPxMOD "!\n",
DPxPTR(img->ImageStart), DPxPTR(R->LibraryHandler));
FoundRTL = R;
// Execute dtors for static objects if the device has been used, i.e.
// if its PendingCtors list has been emptied.
for (int32_t i = 0; i < FoundRTL->NumberOfDevices; ++i) {
DeviceTy &Device = Devices[FoundRTL->Idx + i];
Device.PendingGlobalsMtx.lock();
if (Device.PendingCtorsDtors[desc].PendingCtors.empty()) {
for (auto &dtor : Device.PendingCtorsDtors[desc].PendingDtors) {
int rc = target(Device.DeviceID, dtor, 0, NULL, NULL, NULL, NULL, 1,
1, true /*team*/);
if (rc != OFFLOAD_SUCCESS) {
DP("Running destructor " DPxMOD " failed.\n", DPxPTR(dtor));
}
}
// Remove this library's entry from PendingCtorsDtors
Device.PendingCtorsDtors.erase(desc);
}
Device.PendingGlobalsMtx.unlock();
}
DP("Unregistered image " DPxMOD " from RTL " DPxMOD "!\n",
DPxPTR(img->ImageStart), DPxPTR(R->LibraryHandler));
break;
}
// if no RTL was found proceed to unregister the next image
if (!FoundRTL){
DP("No RTLs in use support the image " DPxMOD "!\n",
DPxPTR(img->ImageStart));
}
}
RTLsMtx.unlock();
DP("Done unregistering images!\n");
// Remove entries from HostPtrToTableMap
TblMapMtx.lock();
for (__tgt_offload_entry *cur = desc->HostEntriesBegin;
cur < desc->HostEntriesEnd; ++cur) {
HostPtrToTableMap.erase(cur->addr);
}
// Remove translation table for this descriptor.
auto tt = HostEntriesBeginToTransTable.find(desc->HostEntriesBegin);
if (tt != HostEntriesBeginToTransTable.end()) {
DP("Removing translation table for descriptor " DPxMOD "\n",
DPxPTR(desc->HostEntriesBegin));
HostEntriesBeginToTransTable.erase(tt);
} else {
DP("Translation table for descriptor " DPxMOD " cannot be found, probably "
"it has been already removed.\n", DPxPTR(desc->HostEntriesBegin));
}
TblMapMtx.unlock();
// TODO: Remove RTL and the devices it manages if it's not used anymore?
// TODO: Write some RTL->unload_image(...) function?
DP("Done unregistering library!\n");
}
+166
View File
@@ -0,0 +1,166 @@
//===------------ rtl.h - Target independent OpenMP target RTL ------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
// Declarations for handling RTL plugins.
//
//===----------------------------------------------------------------------===//
#ifndef _OMPTARGET_RTL_H
#define _OMPTARGET_RTL_H
#include <list>
#include <map>
#include <mutex>
#include <string>
#include <vector>
// Forward declarations.
struct DeviceTy;
struct __tgt_bin_desc;
struct RTLInfoTy {
typedef int32_t(is_valid_binary_ty)(void *);
typedef int32_t(number_of_devices_ty)();
typedef int32_t(init_device_ty)(int32_t);
typedef __tgt_target_table *(load_binary_ty)(int32_t, void *);
typedef void *(data_alloc_ty)(int32_t, int64_t, void *);
typedef int32_t(data_submit_ty)(int32_t, void *, void *, int64_t);
typedef int32_t(data_retrieve_ty)(int32_t, void *, void *, int64_t);
typedef int32_t(data_delete_ty)(int32_t, void *);
typedef int32_t(run_region_ty)(int32_t, void *, void **, ptrdiff_t *,
int32_t);
typedef int32_t(run_team_region_ty)(int32_t, void *, void **, ptrdiff_t *,
int32_t, int32_t, int32_t, uint64_t);
int32_t Idx; // RTL index, index is the number of devices
// of other RTLs that were registered before,
// i.e. the OpenMP index of the first device
// to be registered with this RTL.
int32_t NumberOfDevices; // Number of devices this RTL deals with.
std::vector<DeviceTy *> Devices; // one per device (NumberOfDevices in total).
void *LibraryHandler;
#ifdef OMPTARGET_DEBUG
std::string RTLName;
#endif
// Functions implemented in the RTL.
is_valid_binary_ty *is_valid_binary;
number_of_devices_ty *number_of_devices;
init_device_ty *init_device;
load_binary_ty *load_binary;
data_alloc_ty *data_alloc;
data_submit_ty *data_submit;
data_retrieve_ty *data_retrieve;
data_delete_ty *data_delete;
run_region_ty *run_region;
run_team_region_ty *run_team_region;
// Are there images associated with this RTL.
bool isUsed;
// Mutex for thread-safety when calling RTL interface functions.
// It is easier to enforce thread-safety at the libomptarget level,
// so that developers of new RTLs do not have to worry about it.
std::mutex Mtx;
// The existence of the mutex above makes RTLInfoTy non-copyable.
// We need to provide a copy constructor explicitly.
RTLInfoTy()
: Idx(-1), NumberOfDevices(-1), Devices(), LibraryHandler(0),
#ifdef OMPTARGET_DEBUG
RTLName(),
#endif
is_valid_binary(0), number_of_devices(0), init_device(0),
load_binary(0), data_alloc(0), data_submit(0), data_retrieve(0),
data_delete(0), run_region(0), run_team_region(0), isUsed(false),
Mtx() {}
RTLInfoTy(const RTLInfoTy &r) : Mtx() {
Idx = r.Idx;
NumberOfDevices = r.NumberOfDevices;
Devices = r.Devices;
LibraryHandler = r.LibraryHandler;
#ifdef OMPTARGET_DEBUG
RTLName = r.RTLName;
#endif
is_valid_binary = r.is_valid_binary;
number_of_devices = r.number_of_devices;
init_device = r.init_device;
load_binary = r.load_binary;
data_alloc = r.data_alloc;
data_submit = r.data_submit;
data_retrieve = r.data_retrieve;
data_delete = r.data_delete;
run_region = r.run_region;
run_team_region = r.run_team_region;
isUsed = r.isUsed;
}
};
/// RTLs identified in the system.
class RTLsTy {
private:
// Mutex-like object to guarantee thread-safety and unique initialization
// (i.e. the library attempts to load the RTLs (plugins) only once).
std::once_flag initFlag;
void LoadRTLs(); // not thread-safe
public:
// List of the detected runtime libraries.
std::list<RTLInfoTy> AllRTLs;
// Array of pointers to the detected runtime libraries that have compatible
// binaries.
std::vector<RTLInfoTy *> UsedRTLs;
explicit RTLsTy() {}
// Register a shared library with all (compatible) RTLs.
void RegisterLib(__tgt_bin_desc *desc);
// Unregister a shared library from all RTLs.
void UnregisterLib(__tgt_bin_desc *desc);
};
extern RTLsTy RTLs;
extern std::mutex RTLsMtx;
/// Map between the host entry begin and the translation table. Each
/// registered library gets one TranslationTable. Use the map from
/// __tgt_offload_entry so that we may quickly determine whether we
/// are trying to (re)register an existing lib or really have a new one.
struct TranslationTable {
__tgt_target_table HostTable;
// Image assigned to a given device.
std::vector<__tgt_device_image *> TargetsImages; // One image per device ID.
// Table of entry points or NULL if it was not already computed.
std::vector<__tgt_target_table *> TargetsTable; // One table per device ID.
};
typedef std::map<__tgt_offload_entry *, TranslationTable>
HostEntriesBeginToTransTableTy;
extern HostEntriesBeginToTransTableTy HostEntriesBeginToTransTable;
extern std::mutex TrlTblMtx;
/// Map between the host ptr and a table index
struct TableMap {
TranslationTable *Table; // table associated with the host ptr.
uint32_t Index; // index in which the host ptr translated entry is found.
TableMap() : Table(0), Index(0) {}
TableMap(TranslationTable *table, uint32_t index)
: Table(table), Index(index) {}
};
typedef std::map<void *, TableMap> HostPtrToTableMapTy;
extern HostPtrToTableMapTy HostPtrToTableMap;
extern std::mutex TblMapMtx;
#endif
+28
View File
@@ -0,0 +1,28 @@
# CMakeLists.txt file for unit testing OpenMP offloading runtime library.
if(NOT "${OPENMP_TEST_COMPILER_ID}" STREQUAL "Clang" OR
${OPENMP_TEST_COMPILER_VERSION} VERSION_LESS 6.0.0)
libomptarget_say("Can only test with Clang compiler in version 6.0.0 or later.")
libomptarget_warning_say("The check-libomptarget target will not be available!")
return()
endif()
if(LIBOMPTARGET_CMAKE_BUILD_TYPE MATCHES debug)
set(LIBOMPTARGET_DEBUG True)
else()
set(LIBOMPTARGET_DEBUG False)
endif()
add_openmp_testsuite(check-libomptarget "Running libomptarget tests" ${CMAKE_CURRENT_BINARY_DIR} DEPENDS omptarget omp)
if(${OPENMP_STANDALONE_BUILD})
set(LIBOMPTARGET_OPENMP_HEADER_FOLDER "${CMAKE_CURRENT_BINARY_DIR}/../../runtime/src" CACHE STRING
"Path to folder containing omp.h")
set(LIBOMPTARGET_OPENMP_HOST_RTL_FOLDER "${CMAKE_CURRENT_BINARY_DIR}/../../runtime/src" CACHE STRING
"Path to folder containing libomp.so")
else()
set(LIBOMPTARGET_OPENMP_HEADER_FOLDER "${LIBOMPTARGET_BINARY_DIR}/../runtime/src")
endif()
# Configure the lit.site.cfg.in file
set(AUTO_GEN_COMMENT "## Autogenerated by libomptarget configuration.\n# Do not edit!")
configure_file(lit.site.cfg.in lit.site.cfg @ONLY)
+20
View File
@@ -0,0 +1,20 @@
// RUN: %libomptarget-compile-aarch64-unknown-linux-gnu && env LIBOMPTARGET_DEBUG=1 %libomptarget-run-aarch64-unknown-linux-gnu 2>&1 | %fcheck-aarch64-unknown-linux-gnu -allow-empty -check-prefix=DEBUG
// RUN: %libomptarget-compile-aarch64-unknown-linux-gnu && env LIBOMPTARGET_DEBUG=0 %libomptarget-run-aarch64-unknown-linux-gnu 2>&1 | %fcheck-aarch64-unknown-linux-gnu -allow-empty -check-prefix=NDEBUG
// RUN: %libomptarget-compile-powerpc64-ibm-linux-gnu && env LIBOMPTARGET_DEBUG=1 %libomptarget-run-powerpc64-ibm-linux-gnu 2>&1 | %fcheck-powerpc64-ibm-linux-gnu -allow-empty -check-prefix=DEBUG
// RUN: %libomptarget-compile-powerpc64-ibm-linux-gnu && env LIBOMPTARGET_DEBUG=0 %libomptarget-run-powerpc64-ibm-linux-gnu 2>&1 | %fcheck-powerpc64-ibm-linux-gnu -allow-empty -check-prefix=NDEBUG
// RUN: %libomptarget-compile-powerpc64le-ibm-linux-gnu && env LIBOMPTARGET_DEBUG=1 %libomptarget-run-powerpc64le-ibm-linux-gnu 2>&1 | %fcheck-powerpc64le-ibm-linux-gnu -allow-empty -check-prefix=DEBUG
// RUN: %libomptarget-compile-powerpc64le-ibm-linux-gnu && env LIBOMPTARGET_DEBUG=0 %libomptarget-run-powerpc64le-ibm-linux-gnu 2>&1 | %fcheck-powerpc64le-ibm-linux-gnu -allow-empty -check-prefix=NDEBUG
// RUN: %libomptarget-compile-x86_64-pc-linux-gnu && env LIBOMPTARGET_DEBUG=1 %libomptarget-run-x86_64-pc-linux-gnu 2>&1 | %fcheck-x86_64-pc-linux-gnu -allow-empty -check-prefix=DEBUG
// RUN: %libomptarget-compile-x86_64-pc-linux-gnu && env LIBOMPTARGET_DEBUG=0 %libomptarget-run-x86_64-pc-linux-gnu 2>&1 | %fcheck-x86_64-pc-linux-gnu -allow-empty -check-prefix=NDEBUG
// REQUIRES: libomptarget-debug
int main(void) {
#pragma omp target
{}
return 0;
}
// DEBUG: Libomptarget
// NDEBUG-NOT: Libomptarget
// NDEBUG-NOT: Target
+137
View File
@@ -0,0 +1,137 @@
# -*- Python -*- vim: set ft=python ts=4 sw=4 expandtab tw=79:
# Configuration file for the 'lit' test runner.
import os
import lit.formats
# Tell pylint that we know config and lit_config exist somewhere.
if 'PYLINT_IMPORT' in os.environ:
config = object()
lit_config = object()
def append_dynamic_library_path(name, value, sep):
if name in config.environment:
config.environment[name] = value + sep + config.environment[name]
else:
config.environment[name] = value
# name: The name of this test suite.
config.name = 'libomptarget'
# suffixes: A list of file extensions to treat as test files.
config.suffixes = ['.c', '.cpp', '.cc']
# test_source_root: The root path where tests are located.
config.test_source_root = os.path.dirname(__file__)
# test_exec_root: The root object directory where output is placed
config.test_exec_root = config.libomptarget_obj_root
# test format
config.test_format = lit.formats.ShTest()
# compiler flags
config.test_flags = " -I " + config.test_source_root + \
" -I " + config.omp_header_directory + \
" -L " + config.library_dir;
if config.omp_host_rtl_directory:
config.test_flags = config.test_flags + " -L " + \
config.omp_host_rtl_directory
config.test_flags = config.test_flags + " " + config.test_extra_flags
if config.libomptarget_debug:
config.available_features.add('libomptarget-debug')
# Setup environment to find dynamic library at runtime
if config.operating_system == 'Windows':
append_dynamic_library_path('PATH', config.library_dir, ";")
append_dynamic_library_path('PATH', config.omp_host_rtl_directory, ";")
elif config.operating_system == 'Darwin':
append_dynamic_library_path('DYLD_LIBRARY_PATH', config.library_dir, ":")
append_dynamic_library_path('DYLD_LIBRARY_PATH', \
config.omp_host_rtl_directory, ";")
config.test_flags += " -Wl,-rpath," + config.library_dir
config.test_flags += " -Wl,-rpath," + config.omp_host_rtl_directory
else: # Unices
append_dynamic_library_path('LD_LIBRARY_PATH', config.library_dir, ":")
append_dynamic_library_path('LD_LIBRARY_PATH', \
config.omp_host_rtl_directory, ":")
# substitutions
# - for targets that exist in the system create the actual command.
# - for valid targets that do not exist in the system, return false, so that the
# same test can be used for different targets.
# Scan all the valid targets.
for libomptarget_target in config.libomptarget_all_targets:
# Is this target in the current system? If so create a compile, run and test
# command. Otherwise create command that return false.
if libomptarget_target in config.libomptarget_system_targets:
config.substitutions.append(("%libomptarget-compilexx-run-and-check-" + \
libomptarget_target, \
"%libomptarget-compilexx-and-run-" + libomptarget_target + \
" | " + config.libomptarget_filecheck + " %s"))
config.substitutions.append(("%libomptarget-compile-run-and-check-" + \
libomptarget_target, \
"%libomptarget-compile-and-run-" + libomptarget_target + \
" | " + config.libomptarget_filecheck + " %s"))
config.substitutions.append(("%libomptarget-compilexx-and-run-" + \
libomptarget_target, \
"%libomptarget-compilexx-" + libomptarget_target + " && " + \
"%libomptarget-run-" + libomptarget_target))
config.substitutions.append(("%libomptarget-compile-and-run-" + \
libomptarget_target, \
"%libomptarget-compile-" + libomptarget_target + " && " + \
"%libomptarget-run-" + libomptarget_target))
config.substitutions.append(("%libomptarget-compilexx-" + \
libomptarget_target, \
"%clangxx-" + libomptarget_target + " %s -o %t-" + \
libomptarget_target))
config.substitutions.append(("%libomptarget-compile-" + \
libomptarget_target, \
"%clang-" + libomptarget_target + " %s -o %t-" + \
libomptarget_target))
config.substitutions.append(("%libomptarget-run-" + \
libomptarget_target, \
"%t-" + libomptarget_target))
config.substitutions.append(("%clangxx-" + libomptarget_target, \
"%clangxx %openmp_flags %flags -fopenmp-targets=" + libomptarget_target))
config.substitutions.append(("%clang-" + libomptarget_target, \
"%clang %openmp_flags %flags -fopenmp-targets=" + libomptarget_target))
config.substitutions.append(("%fcheck-" + libomptarget_target, \
config.libomptarget_filecheck + " %s"))
else:
config.substitutions.append(("%libomptarget-compile-run-and-check-" + \
libomptarget_target, \
"echo ignored-command"))
config.substitutions.append(("%libomptarget-compilexx-run-and-check-" + \
libomptarget_target, \
"echo ignored-command"))
config.substitutions.append(("%libomptarget-compile-and-run-" + \
libomptarget_target, \
"echo ignored-command"))
config.substitutions.append(("%libomptarget-compilexx-and-run-" + \
libomptarget_target, \
"echo ignored-command"))
config.substitutions.append(("%libomptarget-compilexx-" + \
libomptarget_target, \
"echo ignored-command"))
config.substitutions.append(("%libomptarget-compile-" + \
libomptarget_target, \
"echo ignored-command"))
config.substitutions.append(("%libomptarget-run-" + \
libomptarget_target, \
"echo ignored-command"))
config.substitutions.append(("%clang-" + libomptarget_target, \
"echo ignored-command"))
config.substitutions.append(("%clangxx-" + libomptarget_target, \
"echo ignored-command"))
config.substitutions.append(("%fcheck-" + libomptarget_target, \
"echo ignored-command"))
config.substitutions.append(("%clangxx", config.test_cxx_compiler))
config.substitutions.append(("%clang", config.test_c_compiler))
config.substitutions.append(("%openmp_flags", config.test_openmp_flags))
config.substitutions.append(("%flags", config.test_flags))
+18
View File
@@ -0,0 +1,18 @@
@AUTO_GEN_COMMENT@
config.test_c_compiler = "@OPENMP_TEST_C_COMPILER@"
config.test_cxx_compiler = "@OPENMP_TEST_CXX_COMPILER@"
config.test_openmp_flags = "@OPENMP_TEST_OPENMP_FLAGS@"
config.test_extra_flags = "@OPENMP_TEST_FLAGS@"
config.libomptarget_obj_root = "@CMAKE_CURRENT_BINARY_DIR@"
config.library_dir = "@LIBOMPTARGET_LIBRARY_DIR@"
config.omp_header_directory = "@LIBOMPTARGET_OPENMP_HEADER_FOLDER@"
config.omp_host_rtl_directory = "@LIBOMPTARGET_OPENMP_HOST_RTL_FOLDER@"
config.operating_system = "@CMAKE_SYSTEM_NAME@"
config.libomptarget_all_targets = "@LIBOMPTARGET_ALL_TARGETS@".split()
config.libomptarget_system_targets = "@LIBOMPTARGET_SYSTEM_TARGETS@".split()
config.libomptarget_filecheck = "@OPENMP_FILECHECK_EXECUTABLE@"
config.libomptarget_debug = @LIBOMPTARGET_DEBUG@
# Let the main config do the real work.
lit_config.load_config(config, "@LIBOMPTARGET_BASE_DIR@/test/lit.cfg")
@@ -0,0 +1,23 @@
// RUN: %libomptarget-compile-run-and-check-aarch64-unknown-linux-gnu
// RUN: %libomptarget-compile-run-and-check-powerpc64-ibm-linux-gnu
// RUN: %libomptarget-compile-run-and-check-powerpc64le-ibm-linux-gnu
// RUN: %libomptarget-compile-run-and-check-x86_64-pc-linux-gnu
#include <stdio.h>
#include <omp.h>
int main(void) {
int isHost = -1;
#pragma omp target map(from: isHost)
{ isHost = omp_is_initial_device(); }
if (isHost < 0) {
printf("Runtime error, isHost=%d\n", isHost);
}
// CHECK: Target region executed on the device
printf("Target region executed on the %s\n", isHost ? "host" : "device");
return isHost;
}
@@ -0,0 +1,23 @@
// RUN: %libomptarget-compilexx-run-and-check-aarch64-unknown-linux-gnu
// RUN: %libomptarget-compilexx-run-and-check-powerpc64-ibm-linux-gnu
// RUN: %libomptarget-compilexx-run-and-check-powerpc64le-ibm-linux-gnu
// RUN: %libomptarget-compilexx-run-and-check-x86_64-pc-linux-gnu
#include <stdio.h>
#include <omp.h>
int main(void) {
int isHost = 0;
#pragma omp target map(from: isHost)
{ isHost = omp_is_initial_device(); }
if (isHost < 0) {
printf("Runtime error, isHost=%d\n", isHost);
}
// CHECK: Target region executed on the device
printf("Target region executed on the %s\n", isHost ? "host" : "device");
return isHost;
}
+1 -1
View File
@@ -1141,7 +1141,7 @@ HTML_COLORSTYLE_GAMMA = 80
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = YES
HTML_TIMESTAMP = NO
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
+5
View File
@@ -0,0 +1,5 @@
---
BasedOnStyle: LLVM
AlignTrailingComments: false
SortIncludes: false
...
-229
View File
@@ -1,229 +0,0 @@
#
#//===----------------------------------------------------------------------===//
#//
#// 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.
#//
#//===----------------------------------------------------------------------===//
#
==========================================================
How to Build the LLVM* OpenMP* Runtime Library using CMake
==========================================================
==== Version of CMake required: v2.8.0 or above ====
============================================
How to call cmake initially, then repeatedly
============================================
- When calling cmake for the first time, all needed compiler options
must be specified on the command line. After this initial call to
cmake, the compiler definitions must not be included for further calls
to cmake. Other options can be specified on the command line multiple
times including all definitions in the Build options section below.
- Example of configuring, building, reconfiguring, rebuilding:
$ mkdir build
$ cd build
$ cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DLIBOMP_ARCH=i386 .. # Initial configuration
$ make
...
$ make clean
$ cmake -DLIBOMP_ARCH=x86_64 -DCMAKE_BUILD_TYPE=Debug .. # Second configuration
$ make
...
$ rm -rf *
$ cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DLIBOMP_ARCH=x86_64 .. # Third configuration
$ make
- Notice in the example how the compiler definitions are only specified
for an empty build directory, but other Build options are used at any time.
- The file CMakeCache.txt which is created after the first call to cmake
is a configuration file which holds all the values for the Build options.
These configuration values can be changed using a text editor to modify
CMakeCache.txt as opposed to using definitions on the command line.
- To have cmake create a particular type of build generator file simply
inlude the -G <Generator name> option:
$ cmake -G "Unix Makefiles" ...
You can see a list of generators cmake supports by executing cmake with
no arguments and a list will be printed.
=====================
Instructions to Build
=====================
$ cd libomp_top_level/ [ directory with src/ , exports/ , tools/ , etc. ]
$ mkdir build
$ cd build
[ Unix* Libraries ]
$ cmake -DCMAKE_C_COMPILER=<C Compiler> -DCMAKE_CXX_COMPILER=<C++ Compiler> ..
[ Intel(R) Many Integrated Core Library (Intel(R) MIC Library) ]
$ cmake -DCMAKE_C_COMPILER=<C Compiler> -DCMAKE_CXX_COMPILER=<C++ Compiler> -DLIBOMP_ARCH=mic ..
[ Windows Libraries ]
$ cmake -G <Generator Type> -DCMAKE_C_COMPILER=<C Compiler> -DCMAKE_CXX_COMPILER=<C++ Compiler> -DCMAKE_ASM_MASM_COMPILER=[ml | ml64] -DCMAKE_BUILD_TYPE=Release ..
$ make
$ make install
==================
Mac* Fat Libraries
==================
On OS X* machines, it is possible to build universal (or fat) libraries which
include both i386 and x86_64 architecture objects in a
single archive.
$ cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_OSX_ARCHITECTURES='i386;x86_64' ..
$ make
There is also an option -DLIBOMP_OSX_ARCHITECTURES which can be set in case
this is an LLVM source tree build which will only set the libomp library
to a universal fat library and prevent having the entire llvm/clang build
produce universal binaries.
===========
Micro tests
===========
After the library has been built, there are five optional microtests that
can be performed. Some will be skipped based upon the platform.
To run the tests,
$ make libomp-micro-tests
=============
CMake options
=============
-DCMAKE_C_COMPILER=<C compiler name>
Specify the C compiler
-DCMAKE_CXX_COMPILER=<C++ compiler name>
Specify the C++ compiler
-DCMAKE_Fortran_COMPILER=<Fortran compiler name>
This option is only needed when -DLIBOMP_FORTRAN_MODULES is on.
So typically, a Fortran compiler is not needed during the build.
Specify the Fortran compiler
-DCMAKE_ASM_MASM_COMPILER=[ml | ml64 ]
This option is Windows* Only
-DLIBOMP_ARCH=i386|x86_64|arm|ppc64|ppc64le|aarch64|mic
The default for the option is chosen based on the probing the compiler for
architecture macros (e.g., is __x86_64__ predefined by compiler?).
==== First values listed are the default value ====
-DLIBOMP_LIB_TYPE=normal|profile|stubs
Library type can be normal, profile, or stubs.
-DCMAKE_BUILD_TYPE=Release|Debug|RelWithDebInfo
Build type can be Release, Debug, or RelWithDebInfo.
-DLIBOMP_OMP_VERSION=45|40|30
OpenMP version can be either 45, 40 or 30.
-DLIBOMP_MIC_ARCH=knc|knf
This value is ignored if LIBOMP_ARCH != mic
Intel(R) MIC Architecture, can be knf or knc.
-DLIBOMP_FORTRAN_MODULES=off|on
Should the Fortran modules be created (requires Fortran compiler)
-DLIBOMP_USE_ADAPTIVE_LOCKS=on|off
Should adaptive (TSX-based) locks be included?
These are x86 specific. This feature is turned on by default
for i386 and x86_64. Otherwise, it is turned off.
-DLIBOMP_USE_INTERNODE_ALIGNMENT=off|on
Should 4096-byte alignment be used for certain data structures?
This option is useful on multinode systems where a small CACHE_LINE
setting leads to false sharing. This option is off by default.
-DLIBOMP_USE_VERSION_SYMBOLS=on|off
Should versioned symbols be used for building the library?
This option only makes sense for ELF based libraries where version
symbols are supported (Linux, some BSD* variants). It is off
by default for Windows and Mac, but on for other Unix based operating
systems.
-DLIBOMP_ENABLE_SHARED=on|off
Shared library instead of static library? (Note: static libraries are not
supported on Windows). If LIBOMP_ENABLE_SHARED is off, then static OpenMP
libraries will be built instead of dynamic ones.
-DLIBOMP_OMPT_SUPPORT=off|on
Should OMPT support be included in the build? (Not supported on Windows)
If LIBOMP_OMPT_SUPPORT is off, then both ompt_blame and ompt_trace are ignored.
-DLIBOMP_OMPT_BLAME=on|off
Should OMPT blame functionality be included in the build?
-DLIBOMP_OMPT_TRACE=on|off
Should OMPT trace functionality be included in the build?
-DLIBOMP_STATS=off|on
Should include stats-gathering code be included in the build?
-DLIBOMP_USE_DEBUGGER=off|on
Should the friendly debugger interface be included in the build?
-DLIBOMP_USE_HWLOC=off|on
Should the Hwloc library be used for affinity?
This option is not supported on Windows.
http://www.open-mpi.org/projects/hwloc
-DLIBOMP_HWLOC_INSTALL_DIR=/path/to/hwloc/install/dir
Default: /usr/local
This option is only used if LIBOMP_USE_HWLOC is on.
Specifies install location of Hwloc. The configuration system will look for
hwloc.h in ${LIBOMP_HWLOC_INSTALL_DIR}/include and the library in
${LIBOMP_HWLOC_INSTALL_DIR}/lib.
-DLIBOMP_LLVM_LIT_EXECUTABLE=/path/to/llvm-lit
Default: search in PATH
Specifiy full path to llvm-lit executable for running tests.
-DOPENMP_LLVM_TOOLS_DIR=/path/to/built/llvm/tools
Default: search for tools in path
Additional path to search for LLVM tools needed by tests.
================================
How to append flags to the build
================================
- These flags are *appended*. They do not
overwrite any of the preset flags.
-DLIBOMP_CPPFLAGS=<space-separated flags> -- Additional C preprocessor flags
-DLIBOMP_CFLAGS=<space-separated flags> -- Additional C compiler flags
-DLIBOMP_CXXFLAGS=<space-separated flags> -- Additional C++ compiler flags
-DLIBOMP_ASMFLAGS=<space-separated flags> -- Additional assembly flags
-DLIBOMP_LDFLAGS=<space-separated flags> -- Additional linker flags
-DLIBOMP_LIBFLAGS=<space-separated flags> -- Additional libraries to link
-DLIBOMP_FFLAGS=<space-separated flags> -- Additional Fortran compiler flags
=======================
Example usages of CMake
=======================
---- Typical usage ----
cmake -DCMAKE_C_COMPILER=icc -DCMAKE_CXX_COMPILER=icpc ..
cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ ..
cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ ..
---- With Various Options ----
- Build the i386 Linux library using GCC*
cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DLIBOMP_ARCH=i386 ..
- Build the x86_64 debug Mac library using Clang*
cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DLIBOMP_ARCH=x86_64 -DCMAKE_BUILD_TYPE=Debug ..
- Build the library (architecture determined by probing compiler) using the
Intel(R) C Compiler and the Intel(R) C++ Compiler. Also, create the fortran modules using
the Intel(R) Fortran Compiler.
cmake -DCMAKE_C_COMPILER=icc -DCMAKE_CXX_COMPILER=icpc -DCMAKE_Fortran_COMPILER=ifort -DLIBOMP_FORTRAN_MODULES=on ..
- Have CMake Find the C/C++ compiler, and specify additional flags for the C compiler, preprocessor, and C++ compiler.
cmake -DLIBOMP_CFLAGS='-specific-flag' -DLIBOMP_CPPFLAGS='-DNEW_FEATURE=1 -DOLD_FEATURE=0' -DLIBOMP_CXXFLAGS='--one-specific-flag --two-specific-flag' ..
---- Build the stubs library ----
cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DLIBOMP_LIB_TYPE=stubs ..
=========
Footnotes
=========
[*] Other names and brands may be claimed as the property of others.
+66 -48
View File
@@ -9,20 +9,13 @@
#//===----------------------------------------------------------------------===//
#
# CMAKE libomp
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
message(FATAL_ERROR "Direct configuration not supported, please use parent directory!")
endif()
# Add cmake directory to search for custom cmake functions
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
# Standalone build or part of LLVM?
set(LIBOMP_STANDALONE_BUILD FALSE)
if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}" OR
"${CMAKE_SOURCE_DIR}/runtime" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
project(libomp C CXX)
set(LIBOMP_STANDALONE_BUILD TRUE)
endif()
# Set libomp version
set(LIBOMP_VERSION_MAJOR 5)
set(LIBOMP_VERSION_MINOR 0)
@@ -34,23 +27,14 @@ include(LibompHandleFlags)
include(LibompDefinitions)
# Determine the target architecture
if(${LIBOMP_STANDALONE_BUILD})
if(${OPENMP_STANDALONE_BUILD})
# If adding a new architecture, take a look at cmake/LibompGetArchitecture.cmake
libomp_get_architecture(LIBOMP_DETECTED_ARCH)
set(LIBOMP_ARCH ${LIBOMP_DETECTED_ARCH} CACHE STRING
"The architecture to build for (x86_64/i386/arm/ppc64/ppc64le/aarch64/mic).")
# Allow user to choose a suffix for the installation directory.
set(LIBOMP_LIBDIR_SUFFIX "" CACHE STRING
"suffix of lib installation directory e.g., 64 => lib64")
"The architecture to build for (x86_64/i386/arm/ppc64/ppc64le/aarch64/mic/mips/mips64).")
# Should assertions be enabled? They are on by default.
set(LIBOMP_ENABLE_ASSERTIONS TRUE CACHE BOOL
"enable assertions?")
set(LIBOMP_ENABLE_WERROR FALSE CACHE BOOL
"Enable -Werror flags to turn warnings into errors for supporting compilers.")
# CMAKE_BUILD_TYPE was not defined, set default to Release
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
else() # Part of LLVM build
# Determine the native architecture from LLVM.
string(TOLOWER "${LLVM_TARGET_ARCH}" LIBOMP_NATIVE_ARCH)
@@ -65,6 +49,8 @@ else() # Part of LLVM build
set(LIBOMP_ARCH x86_64)
elseif(LIBOMP_NATIVE_ARCH STREQUAL "x86_64")
set(LIBOMP_ARCH x86_64)
elseif(LIBOMP_NATIVE_ARCH MATCHES "powerpc64le")
set(LIBOMP_ARCH ppc64le)
elseif(LIBOMP_NATIVE_ARCH MATCHES "powerpc")
set(LIBOMP_ARCH ppc64)
elseif(LIBOMP_NATIVE_ARCH MATCHES "aarch64")
@@ -77,24 +63,22 @@ else() # Part of LLVM build
# last ditch effort
libomp_get_architecture(LIBOMP_ARCH)
endif ()
set(LIBOMP_LIBDIR_SUFFIX ${LLVM_LIBDIR_SUFFIX})
set(LIBOMP_ENABLE_ASSERTIONS ${LLVM_ENABLE_ASSERTIONS})
set(LIBOMP_ENABLE_WERROR ${LLVM_ENABLE_WERROR})
endif()
libomp_check_variable(LIBOMP_ARCH 32e x86_64 32 i386 arm ppc64 ppc64le aarch64 mic)
libomp_check_variable(LIBOMP_ARCH 32e x86_64 32 i386 arm ppc64 ppc64le aarch64 mic mips mips64)
set(LIBOMP_LIB_TYPE normal CACHE STRING
"Performance,Profiling,Stubs library (normal/profile/stubs)")
libomp_check_variable(LIBOMP_LIB_TYPE normal profile stubs)
set(LIBOMP_OMP_VERSION 45 CACHE STRING
"The OpenMP version (45/40/30)")
if(LIBOMP_OMP_VERSION EQUAL 41)
libomp_warning_say("LIBOMP_OMP_VERSION=41 is deprecated and will be removed in a later version. Please use 45.")
set(LIBOMP_OMP_VERSION 45)
endif()
libomp_check_variable(LIBOMP_OMP_VERSION 45 40 30)
set(LIBOMP_OMP_VERSION 50 CACHE STRING
"The OpenMP version (50/45/40/30)")
libomp_check_variable(LIBOMP_OMP_VERSION 50 45 40 30)
# Set the OpenMP Year and Month assiociated with version
if(${LIBOMP_OMP_VERSION} GREATER 40 OR ${LIBOMP_OMP_VERSION} EQUAL 40)
if(${LIBOMP_OMP_VERSION} GREATER 50 OR ${LIBOMP_OMP_VERSION} EQUAL 50)
set(LIBOMP_OMP_YEAR_MONTH 201611)
elseif(${LIBOMP_OMP_VERSION} GREATER 45 OR ${LIBOMP_OMP_VERSION} EQUAL 45)
set(LIBOMP_OMP_YEAR_MONTH 201511)
elseif(${LIBOMP_OMP_VERSION} GREATER 40 OR ${LIBOMP_OMP_VERSION} EQUAL 40)
set(LIBOMP_OMP_YEAR_MONTH 201307)
elseif(${LIBOMP_OMP_VERSION} GREATER 30 OR ${LIBOMP_OMP_VERSION} EQUAL 30)
set(LIBOMP_OMP_YEAR_MONTH 201107)
@@ -153,7 +137,7 @@ set(LIBOMP_USE_HWLOC FALSE CACHE BOOL
set(LIBOMP_HWLOC_INSTALL_DIR /usr/local CACHE PATH
"Install path for hwloc library")
# Get the build number from kmp_version.c
# Get the build number from kmp_version.cpp
libomp_get_build_number("${CMAKE_CURRENT_SOURCE_DIR}" LIBOMP_VERSION_BUILD)
math(EXPR LIBOMP_VERSION_BUILD_YEAR "${LIBOMP_VERSION_BUILD}/10000")
math(EXPR LIBOMP_VERSION_BUILD_MONTH_DAY "${LIBOMP_VERSION_BUILD}%10000")
@@ -170,6 +154,8 @@ set(PPC64BE FALSE)
set(PPC64LE FALSE)
set(PPC64 FALSE)
set(MIC FALSE)
set(MIPS64 FALSE)
set(MIPS FALSE)
if("${LIBOMP_ARCH}" STREQUAL "i386" OR "${LIBOMP_ARCH}" STREQUAL "32") # IA-32 architecture
set(IA32 TRUE)
elseif("${LIBOMP_ARCH}" STREQUAL "x86_64" OR "${LIBOMP_ARCH}" STREQUAL "32e") # Intel(R) 64 architecture
@@ -186,6 +172,10 @@ elseif("${LIBOMP_ARCH}" STREQUAL "aarch64") # AARCH64 architecture
set(AARCH64 TRUE)
elseif("${LIBOMP_ARCH}" STREQUAL "mic") # Intel(R) Many Integrated Core Architecture
set(MIC TRUE)
elseif("${LIBOMP_ARCH}" STREQUAL "mips") # MIPS architecture
set(MIPS TRUE)
elseif("${LIBOMP_ARCH}" STREQUAL "mips64") # MIPS64 architecture
set(MIPS64 TRUE)
endif()
# Set some flags based on build_type
@@ -270,12 +260,13 @@ set(LIBOMP_USE_DEBUGGER FALSE CACHE BOOL
set(LIBOMP_USE_STDCPPLIB FALSE CACHE BOOL
"Should we link to C++ library?")
# TSX (x86) based locks have __asm code which can be troublesome for some compilers.
# Intel(R) Transactional Synchronization Extensions (Intel(R) TSX) based locks have
# __asm code which can be troublesome for some compilers. This feature is also x86 specific.
# TODO: Make this a real feature check
set(LIBOMP_USE_ADAPTIVE_LOCKS "${LIBOMP_HAVE_ADAPTIVE_LOCKS}" CACHE BOOL
"Should TSX-based lock be compiled (adaptive lock in kmp_lock.cpp). These are x86 specific.")
"Should Intel(R) TSX lock be compiled (adaptive lock in kmp_lock.cpp). These are x86 specific.")
if(LIBOMP_USE_ADAPTIVE_LOCKS AND (NOT LIBOMP_HAVE_ADAPTIVE_LOCKS))
libomp_error_say("Adaptive locks (TSX) functionality requested but not available")
libomp_error_say("Adaptive locks (Intel(R) TSX) functionality is only supported on x86 Architecture")
endif()
# - stats-gathering enables OpenMP stats where things like the number of
@@ -298,17 +289,41 @@ if(WIN32 AND NOT LIBOMP_ENABLE_SHARED)
libomp_error_say("Static libraries requested but not available on Windows")
endif()
# OMPT-support
if(LIBOMP_USE_ITT_NOTIFY AND NOT LIBOMP_ENABLE_SHARED)
message(STATUS "ITT Notify not supported for static libraries - forcing ITT Notify off")
set(LIBOMP_USE_ITT_NOTIFY FALSE)
endif()
if(LIBOMP_USE_VERSION_SYMBOLS AND (NOT LIBOMP_ENABLE_SHARED) )
message(STATUS "Version symbols not supported for static libraries - forcing Version symbols functionality off")
set (LIBOMP_USE_VERSION_SYMBOLS FALSE)
endif()
# OMPT-support defaults to ON for OpenMP 5.0+ and if the requirements in
# cmake/config-ix.cmake are fulfilled.
set(OMPT_DEFAULT FALSE)
if ((${LIBOMP_OMP_VERSION} GREATER 49) AND (LIBOMP_HAVE_OMPT_SUPPORT))
set(OMPT_DEFAULT TRUE)
endif()
set(LIBOMP_OMPT_SUPPORT ${OMPT_DEFAULT} CACHE BOOL
"OMPT-support?")
set(LIBOMP_OMPT_DEBUG FALSE CACHE BOOL
"Trace OMPT initialization?")
set(LIBOMP_OMPT_SUPPORT FALSE CACHE BOOL
"OMPT-support?")
set(LIBOMP_OMPT_BLAME TRUE CACHE BOOL
"OMPT-blame?")
set(LIBOMP_OMPT_TRACE TRUE CACHE BOOL
"OMPT-trace?")
set(LIBOMP_OMPT_OPTIONAL TRUE CACHE BOOL
"OMPT-optional?")
if(LIBOMP_OMPT_SUPPORT AND (NOT LIBOMP_HAVE_OMPT_SUPPORT))
libomp_error_say("OpenMP Tools Interface requested but not available")
libomp_error_say("OpenMP Tools Interface requested but not available in this implementation")
endif()
if(LIBOMP_OMPT_SUPPORT AND (${LIBOMP_OMP_VERSION} LESS 50))
libomp_error_say("OpenMP Tools Interface only available with OpenMP 5.0, LIBOMP_OMP_VERSION is ${LIBOMP_OMP_VERSION}")
endif()
# TSAN-support
set(LIBOMP_TSAN_SUPPORT FALSE CACHE BOOL
"TSAN-support?")
if(LIBOMP_TSAN_SUPPORT AND (NOT LIBOMP_HAVE_TSAN_SUPPORT))
libomp_error_say("TSAN functionality requested but not available")
endif()
# Error check hwloc support after config-ix has run
@@ -338,8 +353,12 @@ endif()
set(LIBOMP_LIB_FILE ${LIBOMP_LIB_NAME}${LIBOMP_LIBRARY_SUFFIX})
# Optional backwards compatibility aliases.
set(LIBOMP_INSTALL_ALIASES TRUE CACHE BOOL
"Install libgomp and libiomp5 library aliases for backwards compatibility")
# Print configuration after all variables are set.
if(${LIBOMP_STANDALONE_BUILD})
if(${OPENMP_STANDALONE_BUILD})
libomp_say("Operating System -- ${CMAKE_SYSTEM_NAME}")
libomp_say("Target Architecture -- ${LIBOMP_ARCH}")
if(${MIC})
@@ -362,14 +381,13 @@ if(${LIBOMP_STANDALONE_BUILD})
libomp_say("Use ITT notify -- ${LIBOMP_USE_ITT_NOTIFY}")
libomp_say("Use OMPT-support -- ${LIBOMP_OMPT_SUPPORT}")
if(${LIBOMP_OMPT_SUPPORT})
libomp_say("Use OMPT-blame -- ${LIBOMP_OMPT_BLAME}")
libomp_say("Use OMPT-trace -- ${LIBOMP_OMPT_TRACE}")
libomp_say("Use OMPT-optional -- ${LIBOMP_OMPT_OPTIONAL}")
endif()
libomp_say("Use Adaptive locks -- ${LIBOMP_USE_ADAPTIVE_LOCKS}")
libomp_say("Use quad precision -- ${LIBOMP_USE_QUAD_PRECISION}")
libomp_say("Use TSAN-support -- ${LIBOMP_TSAN_SUPPORT}")
libomp_say("Use Hwloc library -- ${LIBOMP_USE_HWLOC}")
endif()
add_subdirectory(src)
add_subdirectory(test)
+2 -1
View File
@@ -41,7 +41,7 @@ $ mkdir build && cd build
$ cmake path/to/openmp -DCMAKE_C_COMPILER=<C compiler> -DCMAKE_CXX_COMPILER=<C++ compiler>
$ make
For details about building, please look at Build_With_CMake.txt
For details about building, please look at README.rst in the parent directory.
Architectures Supported
=======================
@@ -52,6 +52,7 @@ Architectures Supported
* Aarch64 (64-bit ARM) architecture
* IBM(R) Power architecture (big endian)
* IBM(R) Power architecture (little endian)
* MIPS and MIPS64 architecture
Supported RTL Build Configurations
==================================
+4 -3
View File
@@ -27,8 +27,7 @@ endif()
libomp_append(libomp_suffix .s1 LIBOMP_STATS)
libomp_append(libomp_suffix .ompt LIBOMP_OMPT_SUPPORT)
if(${LIBOMP_OMPT_SUPPORT})
libomp_append(libomp_suffix .no-ompt-blame IF_FALSE LIBOMP_OMPT_BLAME)
libomp_append(libomp_suffix .no-ompt-trace IF_FALSE LIBOMP_OMPT_TRACE)
libomp_append(libomp_suffix .optional LIBOMP_OMPT_OPTIONAL)
endif()
string(REPLACE ";" "" libomp_suffix "${libomp_suffix}")
@@ -64,10 +63,12 @@ endif()
if(${LIBOMP_FORTRAN_MODULES})
add_custom_command(TARGET libomp-mod POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory ${LIBOMP_EXPORTS_MOD_DIR}
COMMAND ${CMAKE_COMMAND} -E copy omp_lib.h ${LIBOMP_EXPORTS_CMN_DIR}
COMMAND ${CMAKE_COMMAND} -E copy omp_lib.mod ${LIBOMP_EXPORTS_MOD_DIR}
COMMAND ${CMAKE_COMMAND} -E copy omp_lib_kinds.mod ${LIBOMP_EXPORTS_MOD_DIR}
)
add_custom_command(TARGET omp POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy omp_lib.h ${LIBOMP_EXPORTS_CMN_DIR}
)
endif()
# Copy OpenMP library into exports/ directory post build
@@ -42,6 +42,10 @@ function(libomp_get_architecture return_arch)
#error ARCHITECTURE=ppc64le
#elif defined(__powerpc64__)
#error ARCHITECTURE=ppc64
#elif defined(__mips__) && defined(__mips64)
#error ARCHITECTURE=mips64
#elif defined(__mips__) && !defined(__mips64)
#error ARCHITECTURE=mips
#else
#error ARCHITECTURE=UnknownArchitecture
#endif
+4 -4
View File
@@ -26,11 +26,8 @@ endmacro()
# Gets flags common to both the C and C++ compiler
function(libomp_get_c_and_cxxflags_common flags)
set(flags_local)
libomp_append(flags_local -std=c++11 LIBOMP_HAVE_STD_CPP11_FLAG)
libomp_append(flags_local -fno-exceptions LIBOMP_HAVE_FNO_EXCEPTIONS_FLAG)
if(${LIBOMP_ENABLE_WERROR})
libomp_append(flags_local -Werror LIBOMP_HAVE_WERROR_FLAG)
endif()
libomp_append(flags_local -fno-rtti LIBOMP_HAVE_FNO_RTTI_FLAG)
libomp_append(flags_local -Wno-sign-compare LIBOMP_HAVE_WNO_SIGN_COMPARE_FLAG)
libomp_append(flags_local -Wno-unused-function LIBOMP_HAVE_WNO_UNUSED_FUNCTION_FLAG)
libomp_append(flags_local -Wno-unused-local-typedef LIBOMP_HAVE_WNO_UNUSED_LOCAL_TYPEDEF_FLAG)
@@ -191,6 +188,9 @@ function(libomp_get_gdflags gdflags)
libomp_append(gdflags_local "-D stub" STUBS_LIBRARY)
libomp_append(gdflags_local "-D HAVE_QUAD" LIBOMP_USE_QUAD_PRECISION)
libomp_append(gdflags_local "-D USE_DEBUGGER" LIBOMP_USE_DEBUGGER)
if(${LIBOMP_OMP_VERSION} GREATER 50 OR ${LIBOMP_OMP_VERSION} EQUAL 50)
libomp_append(gdflags_local "-D OMP_50")
endif()
if(${LIBOMP_OMP_VERSION} GREATER 45 OR ${LIBOMP_OMP_VERSION} EQUAL 45)
libomp_append(gdflags_local "-D OMP_45")
endif()
+3
View File
@@ -206,6 +206,9 @@ else()
elseif(${PPC64})
libomp_append(libomp_expected_library_deps libc.so.6)
libomp_append(libomp_expected_library_deps ld64.so.1)
elseif(${MIPS} OR ${MIPS64})
libomp_append(libomp_expected_library_deps libc.so.6)
libomp_append(libomp_expected_library_deps ld.so.1)
endif()
libomp_append(libomp_expected_library_deps libpthread.so.0 IF_FALSE STUBS_LIBRARY)
libomp_append(libomp_expected_library_deps libhwloc.so.5 LIBOMP_USE_HWLOC)
+8 -4
View File
@@ -102,6 +102,10 @@ function(libomp_get_legal_arch return_arch_string)
set(${return_arch_string} "PPC64LE" PARENT_SCOPE)
elseif(${AARCH64})
set(${return_arch_string} "AARCH64" PARENT_SCOPE)
elseif(${MIPS})
set(${return_arch_string} "MIPS" PARENT_SCOPE)
elseif(${MIPS64})
set(${return_arch_string} "MIPS64" PARENT_SCOPE)
else()
set(${return_arch_string} "${LIBOMP_ARCH}" PARENT_SCOPE)
libomp_warning_say("libomp_get_legal_arch(): Warning: Unknown architecture: Using ${LIBOMP_ARCH}")
@@ -129,12 +133,12 @@ function(libomp_check_variable var)
endfunction()
# void libomp_get_build_number(string src_dir, string* return_build_number);
# - grab the eight digit build number (or 00000000) from kmp_version.c
# - grab the eight digit build number (or 00000000) from kmp_version.cpp
function(libomp_get_build_number src_dir return_build_number)
# sets file_lines_list to a list of all lines in kmp_version.c
file(STRINGS "${src_dir}/src/kmp_version.c" file_lines_list)
# sets file_lines_list to a list of all lines in kmp_version.cpp
file(STRINGS "${src_dir}/src/kmp_version.cpp" file_lines_list)
# runs through each line in kmp_version.c
# runs through each line in kmp_version.cpp
foreach(line IN LISTS file_lines_list)
# if the line begins with "#define KMP_VERSION_BUILD" then we take not of the build number
string(REGEX MATCH "^[ \t]*#define[ \t]+KMP_VERSION_BUILD" valid "${line}")
+17 -4
View File
@@ -47,10 +47,9 @@ function(libomp_check_architecture_flag flag retval)
endfunction()
# Checking C, CXX, Linker Flags
check_cxx_compiler_flag(-std=c++11 LIBOMP_HAVE_STD_CPP11_FLAG)
check_cxx_compiler_flag(-fno-exceptions LIBOMP_HAVE_FNO_EXCEPTIONS_FLAG)
check_cxx_compiler_flag(-fno-rtti LIBOMP_HAVE_FNO_RTTI_FLAG)
check_c_compiler_flag("-x c++" LIBOMP_HAVE_X_CPP_FLAG)
check_c_compiler_flag(-Werror LIBOMP_HAVE_WERROR_FLAG)
check_c_compiler_flag(-Wunused-function LIBOMP_HAVE_WNO_UNUSED_FUNCTION_FLAG)
check_c_compiler_flag(-Wunused-local-typedef LIBOMP_HAVE_WNO_UNUSED_LOCAL_TYPEDEF_FLAG)
check_c_compiler_flag(-Wunused-value LIBOMP_HAVE_WNO_UNUSED_VALUE_FLAG)
@@ -222,7 +221,7 @@ endif()
# Check if OMPT support is available
# Currently, __builtin_frame_address() is required for OMPT
# Weak attribute is required for Unices, LIBPSAPI is used for Windows
# Weak attribute is required for Unices (except Darwin), LIBPSAPI is used for Windows
check_c_source_compiles("int main(int argc, char** argv) {
void* p = __builtin_frame_address(0);
return 0;}" LIBOMP_HAVE___BUILTIN_FRAME_ADDRESS)
@@ -237,7 +236,15 @@ endif()
if(NOT LIBOMP_HAVE___BUILTIN_FRAME_ADDRESS)
set(LIBOMP_HAVE_OMPT_SUPPORT FALSE)
else()
if(LIBOMP_HAVE_WEAK_ATTRIBUTE OR LIBOMP_HAVE_PSAPI)
if( # hardware architecture supported?
((LIBOMP_ARCH STREQUAL x86_64) OR
(LIBOMP_ARCH STREQUAL i386) OR
# (LIBOMP_ARCH STREQUAL arm) OR
(LIBOMP_ARCH STREQUAL aarch64) OR
(LIBOMP_ARCH STREQUAL ppc64le) OR
(LIBOMP_ARCH STREQUAL ppc64))
AND # OS supported?
((WIN32 AND LIBOMP_HAVE_PSAPI) OR APPLE OR (NOT WIN32 AND LIBOMP_HAVE_WEAK_ATTRIBUTE)))
set(LIBOMP_HAVE_OMPT_SUPPORT TRUE)
else()
set(LIBOMP_HAVE_OMPT_SUPPORT FALSE)
@@ -265,3 +272,9 @@ if(${LIBOMP_USE_HWLOC})
endif()
endif()
# Check if ThreadSanitizer support is available
if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux" AND ${INTEL64})
set(LIBOMP_HAVE_TSAN_SUPPORT TRUE)
else()
set(LIBOMP_HAVE_TSAN_SUPPORT FALSE)
endif()
+1 -1
View File
@@ -969,7 +969,7 @@ HTML_COLORSTYLE_GAMMA = 80
# page will contain the date and time when the page was generated. Setting
# this to NO can help when comparing the output of multiple runs.
HTML_TIMESTAMP = YES
HTML_TIMESTAMP = NO
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
+322 -323
View File
@@ -1,6 +1,6 @@
// This file does not contain any code; it just contains additional text and formatting
// for doxygen.
// This file does not contain any code; it just contains additional text and formatting
// for doxygen.
//===----------------------------------------------------------------------===//
//
@@ -11,323 +11,322 @@
//
//===----------------------------------------------------------------------===//
/*! @mainpage LLVM&nbsp; OpenMP* Runtime Library Interface
@section sec_intro Introduction
This document describes the interface provided by the
LLVM &nbsp;OpenMP\other runtime library to the compiler.
Routines that are directly called as simple functions by user code are
not currently described here, since their definition is in the OpenMP
specification available from http://openmp.org
The aim here is to explain the interface from the compiler to the runtime.
The overall design is described, and each function in the interface
has its own description. (At least, that's the ambition, we may not be there yet).
@section sec_building Quickly Building the Runtime
For the impatient, we cover building the runtime as the first topic here.
CMake is used to build the OpenMP runtime. For details and a full list of options for the CMake build system,
see <tt>Build_With_CMake.txt</tt> inside the <tt>runtime/</tt> subdirectory. These
instructions will provide the most typical build.
In-LLVM-tree build:.
@code
$ cd where-you-want-to-live
Check out openmp into llvm/projects
$ cd where-you-want-to-build
$ mkdir build && cd build
$ cmake path/to/llvm -DCMAKE_C_COMPILER=<C compiler> -DCMAKE_CXX_COMPILER=<C++ compiler>
$ make omp
@endcode
Out-of-LLVM-tree build:
@code
$ cd where-you-want-to-live
Check out openmp
$ cd where-you-want-to-live/openmp/runtime
$ mkdir build && cd build
$ cmake path/to/openmp -DCMAKE_C_COMPILER=<C compiler> -DCMAKE_CXX_COMPILER=<C++ compiler>
$ make
@endcode
@section sec_supported Supported RTL Build Configurations
The architectures supported are IA-32 architecture, Intel&reg;&nbsp; 64, and
Intel&reg;&nbsp; Many Integrated Core Architecture. The build configurations
supported are shown in the table below.
<table border=1>
<tr><th> <th>icc/icl<th>gcc<th>clang
<tr><td>Linux\other OS<td>Yes(1,5)<td>Yes(2,4)<td>Yes(4,6,7)
<tr><td>FreeBSD\other<td>Yes(1,5)<td>Yes(2,4)<td>Yes(4,6,7,8)
<tr><td>OS X\other<td>Yes(1,3,4)<td>No<td>Yes(4,6,7)
<tr><td>Windows\other OS<td>Yes(1,4)<td>No<td>No
</table>
(1) On IA-32 architecture and Intel&reg;&nbsp; 64, icc/icl versions 12.x
are supported (12.1 is recommended).<br>
(2) gcc version 4.7 is supported.<br>
(3) For icc on OS X\other, OS X\other version 10.5.8 is supported.<br>
(4) Intel&reg;&nbsp; Many Integrated Core Architecture not supported.<br>
(5) On Intel&reg;&nbsp; Many Integrated Core Architecture, icc/icl versions 13.0 or later are required.<br>
(6) Clang\other version 3.3 is supported.<br>
(7) Clang\other currently does not offer a software-implemented 128 bit extended
precision type. Thus, all entry points reliant on this type are removed
from the library and cannot be called in the user program. The following
functions are not available:
@code
__kmpc_atomic_cmplx16_*
__kmpc_atomic_float16_*
__kmpc_atomic_*_fp
@endcode
(8) Community contribution provided AS IS, not tested by Intel.
Supported Architectures: IBM(R) Power 7 and Power 8
<table border=1>
<tr><th> <th>gcc<th>clang
<tr><td>Linux\other OS<td>Yes(1,2)<td>Yes(3,4)
</table>
(1) On Power 7, gcc version 4.8.2 is supported.<br>
(2) On Power 8, gcc version 4.8.2 is supported.<br>
(3) On Power 7, clang version 3.7 is supported.<br>
(4) On Power 8, clang version 3.7 is supported.<br>
@section sec_frontend Front-end Compilers that work with this RTL
The following compilers are known to do compatible code generation for
this RTL: icc/icl, gcc. Code generation is discussed in more detail
later in this document.
@section sec_outlining Outlining
The runtime interface is based on the idea that the compiler
"outlines" sections of code that are to run in parallel into separate
functions that can then be invoked in multiple threads. For instance,
simple code like this
@code
void foo()
{
#pragma omp parallel
{
... do something ...
}
}
@endcode
is converted into something that looks conceptually like this (where
the names used are merely illustrative; the real library function
names will be used later after we've discussed some more issues...)
@code
static void outlinedFooBody()
{
... do something ...
}
void foo()
{
__OMP_runtime_fork(outlinedFooBody, (void*)0); // Not the real function name!
}
@endcode
@subsection SEC_SHAREDVARS Addressing shared variables
In real uses of the OpenMP\other API there are normally references
from the outlined code to shared variables that are in scope in the containing function.
Therefore the containing function must be able to address
these variables. The runtime supports two alternate ways of doing
this.
@subsubsection SEC_SEC_OT Current Technique
The technique currently supported by the runtime library is to receive
a separate pointer to each shared variable that can be accessed from
the outlined function. This is what is shown in the example below.
We hope soon to provide an alternative interface to support the
alternate implementation described in the next section. The
alternative implementation has performance advantages for small
parallel regions that have many shared variables.
@subsubsection SEC_SEC_PT Future Technique
The idea is to treat the outlined function as though it
were a lexically nested function, and pass it a single argument which
is the pointer to the parent's stack frame. Provided that the compiler
knows the layout of the parent frame when it is generating the outlined
function it can then access the up-level variables at appropriate
offsets from the parent frame. This is a classical compiler technique
from the 1960s to support languages like Algol (and its descendants)
that support lexically nested functions.
The main benefit of this technique is that there is no code required
at the fork point to marshal the arguments to the outlined function.
Since the runtime knows statically how many arguments must be passed to the
outlined function, it can easily copy them to the thread's stack
frame. Therefore the performance of the fork code is independent of
the number of shared variables that are accessed by the outlined
function.
If it is hard to determine the stack layout of the parent while generating the
outlined code, it is still possible to use this approach by collecting all of
the variables in the parent that are accessed from outlined functions into
a single `struct` which is placed on the stack, and whose address is passed
to the outlined functions. In this way the offsets of the shared variables
are known (since they are inside the struct) without needing to know
the complete layout of the parent stack-frame. From the point of view
of the runtime either of these techniques is equivalent, since in either
case it only has to pass a single argument to the outlined function to allow
it to access shared variables.
A scheme like this is how gcc\other generates outlined functions.
@section SEC_INTERFACES Library Interfaces
The library functions used for specific parts of the OpenMP\other language implementation
are documented in different modules.
- @ref BASIC_TYPES fundamental types used by the runtime in many places
- @ref DEPRECATED functions that are in the library but are no longer required
- @ref STARTUP_SHUTDOWN functions for initializing and finalizing the runtime
- @ref PARALLEL functions for implementing `omp parallel`
- @ref THREAD_STATES functions for supporting thread state inquiries
- @ref WORK_SHARING functions for work sharing constructs such as `omp for`, `omp sections`
- @ref THREADPRIVATE functions to support thread private data, copyin etc
- @ref SYNCHRONIZATION functions to support `omp critical`, `omp barrier`, `omp master`, reductions etc
- @ref ATOMIC_OPS functions to support atomic operations
- @ref STATS_GATHERING macros to support developer profiling of libomp
- Documentation on tasking has still to be written...
@section SEC_EXAMPLES Examples
@subsection SEC_WORKSHARING_EXAMPLE Work Sharing Example
This example shows the code generated for a parallel for with reduction and dynamic scheduling.
@code
extern float foo( void );
int main () {
int i;
float r = 0.0;
#pragma omp parallel for schedule(dynamic) reduction(+:r)
for ( i = 0; i < 10; i ++ ) {
r += foo();
}
}
@endcode
The transformed code looks like this.
@code
extern float foo( void );
int main () {
static int zero = 0;
auto int gtid;
auto float r = 0.0;
__kmpc_begin( & loc3, 0 );
// The gtid is not actually required in this example so could be omitted;
// We show its initialization here because it is often required for calls into
// the runtime and should be locally cached like this.
gtid = __kmpc_global thread num( & loc3 );
__kmpc_fork call( & loc7, 1, main_7_parallel_3, & r );
__kmpc_end( & loc0 );
return 0;
}
struct main_10_reduction_t_5 { float r_10_rpr; };
static kmp_critical_name lck = { 0 };
static ident_t loc10; // loc10.flags should contain KMP_IDENT_ATOMIC_REDUCE bit set
// if compiler has generated an atomic reduction.
void main_7_parallel_3( int *gtid, int *btid, float *r_7_shp ) {
auto int i_7_pr;
auto int lower, upper, liter, incr;
auto struct main_10_reduction_t_5 reduce;
reduce.r_10_rpr = 0.F;
liter = 0;
__kmpc_dispatch_init_4( & loc7,*gtid, 35, 0, 9, 1, 1 );
while ( __kmpc_dispatch_next_4( & loc7, *gtid, & liter, & lower, & upper, & incr ) ) {
for( i_7_pr = lower; upper >= i_7_pr; i_7_pr ++ )
reduce.r_10_rpr += foo();
}
switch( __kmpc_reduce_nowait( & loc10, *gtid, 1, 4, & reduce, main_10_reduce_5, & lck ) ) {
case 1:
*r_7_shp += reduce.r_10_rpr;
__kmpc_end_reduce_nowait( & loc10, *gtid, & lck );
break;
case 2:
__kmpc_atomic_float4_add( & loc10, *gtid, r_7_shp, reduce.r_10_rpr );
break;
default:;
}
}
void main_10_reduce_5( struct main_10_reduction_t_5 *reduce_lhs,
struct main_10_reduction_t_5 *reduce_rhs )
{
reduce_lhs->r_10_rpr += reduce_rhs->r_10_rpr;
}
@endcode
@defgroup BASIC_TYPES Basic Types
Types that are used throughout the runtime.
@defgroup DEPRECATED Deprecated Functions
Functions in this group are for backwards compatibility only, and
should not be used in new code.
@defgroup STARTUP_SHUTDOWN Startup and Shutdown
These functions are for library initialization and shutdown.
@defgroup PARALLEL Parallel (fork/join)
These functions are used for implementing <tt>\#pragma omp parallel</tt>.
@defgroup THREAD_STATES Thread Information
These functions return information about the currently executing thread.
@defgroup WORK_SHARING Work Sharing
These functions are used for implementing
<tt>\#pragma omp for</tt>, <tt>\#pragma omp sections</tt>, <tt>\#pragma omp single</tt> and
<tt>\#pragma omp master</tt> constructs.
When handling loops, there are different functions for each of the signed and unsigned 32 and 64 bit integer types
which have the name suffixes `_4`, `_4u`, `_8` and `_8u`. The semantics of each of the functions is the same,
so they are only described once.
Static loop scheduling is handled by @ref __kmpc_for_static_init_4 and friends. Only a single call is needed,
since the iterations to be executed by any give thread can be determined as soon as the loop parameters are known.
Dynamic scheduling is handled by the @ref __kmpc_dispatch_init_4 and @ref __kmpc_dispatch_next_4 functions.
The init function is called once in each thread outside the loop, while the next function is called each
time that the previous chunk of work has been exhausted.
@defgroup SYNCHRONIZATION Synchronization
These functions are used for implementing barriers.
@defgroup THREADPRIVATE Thread private data support
These functions support copyin/out and thread private data.
@defgroup STATS_GATHERING Statistics Gathering from OMPTB
These macros support profiling the libomp library. Use --stats=on when building with build.pl to enable
and then use the KMP_* macros to profile (through counts or clock ticks) libomp during execution of an OpenMP program.
@section sec_stats_env_vars Environment Variables
This section describes the environment variables relevant to stats-gathering in libomp
@code
KMP_STATS_FILE
@endcode
This environment variable is set to an output filename that will be appended *NOT OVERWRITTEN* if it exists. If this environment variable is undefined, the statistics will be output to stderr
@code
KMP_STATS_THREADS
@endcode
This environment variable indicates to print thread-specific statistics as well as aggregate statistics. Each thread's statistics will be shown as well as the collective sum of all threads. The values "true", "on", "1", "yes" will all indicate to print per thread statistics.
@defgroup TASKING Tasking support
These functions support tasking constructs.
@defgroup USER User visible functions
These functions can be called directly by the user, but are runtime library specific, rather than being OpenMP interfaces.
*/
/*! @mainpage LLVM&nbsp; OpenMP* Runtime Library Interface
@section sec_intro Introduction
This document describes the interface provided by the
LLVM &nbsp;OpenMP\other runtime library to the compiler.
Routines that are directly called as simple functions by user code are
not currently described here, since their definition is in the OpenMP
specification available from http://openmp.org
The aim here is to explain the interface from the compiler to the runtime.
The overall design is described, and each function in the interface
has its own description. (At least, that's the ambition, we may not be there yet).
@section sec_building Quickly Building the Runtime
For the impatient, we cover building the runtime as the first topic here.
CMake is used to build the OpenMP runtime. For details and a full list of options for the CMake build system,
see <tt>README.rst</tt> in the source code repository. These instructions will provide the most typical build.
In-LLVM-tree build:.
@code
$ cd where-you-want-to-live
Check out openmp into llvm/projects
$ cd where-you-want-to-build
$ mkdir build && cd build
$ cmake path/to/llvm -DCMAKE_C_COMPILER=<C compiler> -DCMAKE_CXX_COMPILER=<C++ compiler>
$ make omp
@endcode
Out-of-LLVM-tree build:
@code
$ cd where-you-want-to-live
Check out openmp
$ cd where-you-want-to-live/openmp
$ mkdir build && cd build
$ cmake path/to/openmp -DCMAKE_C_COMPILER=<C compiler> -DCMAKE_CXX_COMPILER=<C++ compiler>
$ make
@endcode
@section sec_supported Supported RTL Build Configurations
The architectures supported are IA-32 architecture, Intel&reg;&nbsp; 64, and
Intel&reg;&nbsp; Many Integrated Core Architecture. The build configurations
supported are shown in the table below.
<table border=1>
<tr><th> <th>icc/icl<th>gcc<th>clang
<tr><td>Linux\other OS<td>Yes(1,5)<td>Yes(2,4)<td>Yes(4,6,7)
<tr><td>FreeBSD\other<td>Yes(1,5)<td>Yes(2,4)<td>Yes(4,6,7,8)
<tr><td>OS X\other<td>Yes(1,3,4)<td>No<td>Yes(4,6,7)
<tr><td>Windows\other OS<td>Yes(1,4)<td>No<td>No
</table>
(1) On IA-32 architecture and Intel&reg;&nbsp; 64, icc/icl versions 12.x
are supported (12.1 is recommended).<br>
(2) gcc version 4.7 is supported.<br>
(3) For icc on OS X\other, OS X\other version 10.5.8 is supported.<br>
(4) Intel&reg;&nbsp; Many Integrated Core Architecture not supported.<br>
(5) On Intel&reg;&nbsp; Many Integrated Core Architecture, icc/icl versions 13.0 or later are required.<br>
(6) Clang\other version 3.3 is supported.<br>
(7) Clang\other currently does not offer a software-implemented 128 bit extended
precision type. Thus, all entry points reliant on this type are removed
from the library and cannot be called in the user program. The following
functions are not available:
@code
__kmpc_atomic_cmplx16_*
__kmpc_atomic_float16_*
__kmpc_atomic_*_fp
@endcode
(8) Community contribution provided AS IS, not tested by Intel.
Supported Architectures: IBM(R) Power 7 and Power 8
<table border=1>
<tr><th> <th>gcc<th>clang
<tr><td>Linux\other OS<td>Yes(1,2)<td>Yes(3,4)
</table>
(1) On Power 7, gcc version 4.8.2 is supported.<br>
(2) On Power 8, gcc version 4.8.2 is supported.<br>
(3) On Power 7, clang version 3.7 is supported.<br>
(4) On Power 8, clang version 3.7 is supported.<br>
@section sec_frontend Front-end Compilers that work with this RTL
The following compilers are known to do compatible code generation for
this RTL: icc/icl, gcc. Code generation is discussed in more detail
later in this document.
@section sec_outlining Outlining
The runtime interface is based on the idea that the compiler
"outlines" sections of code that are to run in parallel into separate
functions that can then be invoked in multiple threads. For instance,
simple code like this
@code
void foo()
{
#pragma omp parallel
{
... do something ...
}
}
@endcode
is converted into something that looks conceptually like this (where
the names used are merely illustrative; the real library function
names will be used later after we've discussed some more issues...)
@code
static void outlinedFooBody()
{
... do something ...
}
void foo()
{
__OMP_runtime_fork(outlinedFooBody, (void*)0); // Not the real function name!
}
@endcode
@subsection SEC_SHAREDVARS Addressing shared variables
In real uses of the OpenMP\other API there are normally references
from the outlined code to shared variables that are in scope in the containing function.
Therefore the containing function must be able to address
these variables. The runtime supports two alternate ways of doing
this.
@subsubsection SEC_SEC_OT Current Technique
The technique currently supported by the runtime library is to receive
a separate pointer to each shared variable that can be accessed from
the outlined function. This is what is shown in the example below.
We hope soon to provide an alternative interface to support the
alternate implementation described in the next section. The
alternative implementation has performance advantages for small
parallel regions that have many shared variables.
@subsubsection SEC_SEC_PT Future Technique
The idea is to treat the outlined function as though it
were a lexically nested function, and pass it a single argument which
is the pointer to the parent's stack frame. Provided that the compiler
knows the layout of the parent frame when it is generating the outlined
function it can then access the up-level variables at appropriate
offsets from the parent frame. This is a classical compiler technique
from the 1960s to support languages like Algol (and its descendants)
that support lexically nested functions.
The main benefit of this technique is that there is no code required
at the fork point to marshal the arguments to the outlined function.
Since the runtime knows statically how many arguments must be passed to the
outlined function, it can easily copy them to the thread's stack
frame. Therefore the performance of the fork code is independent of
the number of shared variables that are accessed by the outlined
function.
If it is hard to determine the stack layout of the parent while generating the
outlined code, it is still possible to use this approach by collecting all of
the variables in the parent that are accessed from outlined functions into
a single `struct` which is placed on the stack, and whose address is passed
to the outlined functions. In this way the offsets of the shared variables
are known (since they are inside the struct) without needing to know
the complete layout of the parent stack-frame. From the point of view
of the runtime either of these techniques is equivalent, since in either
case it only has to pass a single argument to the outlined function to allow
it to access shared variables.
A scheme like this is how gcc\other generates outlined functions.
@section SEC_INTERFACES Library Interfaces
The library functions used for specific parts of the OpenMP\other language implementation
are documented in different modules.
- @ref BASIC_TYPES fundamental types used by the runtime in many places
- @ref DEPRECATED functions that are in the library but are no longer required
- @ref STARTUP_SHUTDOWN functions for initializing and finalizing the runtime
- @ref PARALLEL functions for implementing `omp parallel`
- @ref THREAD_STATES functions for supporting thread state inquiries
- @ref WORK_SHARING functions for work sharing constructs such as `omp for`, `omp sections`
- @ref THREADPRIVATE functions to support thread private data, copyin etc
- @ref SYNCHRONIZATION functions to support `omp critical`, `omp barrier`, `omp master`, reductions etc
- @ref ATOMIC_OPS functions to support atomic operations
- @ref STATS_GATHERING macros to support developer profiling of libomp
- Documentation on tasking has still to be written...
@section SEC_EXAMPLES Examples
@subsection SEC_WORKSHARING_EXAMPLE Work Sharing Example
This example shows the code generated for a parallel for with reduction and dynamic scheduling.
@code
extern float foo( void );
int main () {
int i;
float r = 0.0;
#pragma omp parallel for schedule(dynamic) reduction(+:r)
for ( i = 0; i < 10; i ++ ) {
r += foo();
}
}
@endcode
The transformed code looks like this.
@code
extern float foo( void );
int main () {
static int zero = 0;
auto int gtid;
auto float r = 0.0;
__kmpc_begin( & loc3, 0 );
// The gtid is not actually required in this example so could be omitted;
// We show its initialization here because it is often required for calls into
// the runtime and should be locally cached like this.
gtid = __kmpc_global thread num( & loc3 );
__kmpc_fork call( & loc7, 1, main_7_parallel_3, & r );
__kmpc_end( & loc0 );
return 0;
}
struct main_10_reduction_t_5 { float r_10_rpr; };
static kmp_critical_name lck = { 0 };
static ident_t loc10; // loc10.flags should contain KMP_IDENT_ATOMIC_REDUCE bit set
// if compiler has generated an atomic reduction.
void main_7_parallel_3( int *gtid, int *btid, float *r_7_shp ) {
auto int i_7_pr;
auto int lower, upper, liter, incr;
auto struct main_10_reduction_t_5 reduce;
reduce.r_10_rpr = 0.F;
liter = 0;
__kmpc_dispatch_init_4( & loc7,*gtid, 35, 0, 9, 1, 1 );
while ( __kmpc_dispatch_next_4( & loc7, *gtid, & liter, & lower, & upper, & incr ) ) {
for( i_7_pr = lower; upper >= i_7_pr; i_7_pr ++ )
reduce.r_10_rpr += foo();
}
switch( __kmpc_reduce_nowait( & loc10, *gtid, 1, 4, & reduce, main_10_reduce_5, & lck ) ) {
case 1:
*r_7_shp += reduce.r_10_rpr;
__kmpc_end_reduce_nowait( & loc10, *gtid, & lck );
break;
case 2:
__kmpc_atomic_float4_add( & loc10, *gtid, r_7_shp, reduce.r_10_rpr );
break;
default:;
}
}
void main_10_reduce_5( struct main_10_reduction_t_5 *reduce_lhs,
struct main_10_reduction_t_5 *reduce_rhs )
{
reduce_lhs->r_10_rpr += reduce_rhs->r_10_rpr;
}
@endcode
@defgroup BASIC_TYPES Basic Types
Types that are used throughout the runtime.
@defgroup DEPRECATED Deprecated Functions
Functions in this group are for backwards compatibility only, and
should not be used in new code.
@defgroup STARTUP_SHUTDOWN Startup and Shutdown
These functions are for library initialization and shutdown.
@defgroup PARALLEL Parallel (fork/join)
These functions are used for implementing <tt>\#pragma omp parallel</tt>.
@defgroup THREAD_STATES Thread Information
These functions return information about the currently executing thread.
@defgroup WORK_SHARING Work Sharing
These functions are used for implementing
<tt>\#pragma omp for</tt>, <tt>\#pragma omp sections</tt>, <tt>\#pragma omp single</tt> and
<tt>\#pragma omp master</tt> constructs.
When handling loops, there are different functions for each of the signed and unsigned 32 and 64 bit integer types
which have the name suffixes `_4`, `_4u`, `_8` and `_8u`. The semantics of each of the functions is the same,
so they are only described once.
Static loop scheduling is handled by @ref __kmpc_for_static_init_4 and friends. Only a single call is needed,
since the iterations to be executed by any give thread can be determined as soon as the loop parameters are known.
Dynamic scheduling is handled by the @ref __kmpc_dispatch_init_4 and @ref __kmpc_dispatch_next_4 functions.
The init function is called once in each thread outside the loop, while the next function is called each
time that the previous chunk of work has been exhausted.
@defgroup SYNCHRONIZATION Synchronization
These functions are used for implementing barriers.
@defgroup THREADPRIVATE Thread private data support
These functions support copyin/out and thread private data.
@defgroup STATS_GATHERING Statistics Gathering from OMPTB
These macros support profiling the libomp library. Use --stats=on when building with build.pl to enable
and then use the KMP_* macros to profile (through counts or clock ticks) libomp during execution of an OpenMP program.
@section sec_stats_env_vars Environment Variables
This section describes the environment variables relevant to stats-gathering in libomp
@code
KMP_STATS_FILE
@endcode
This environment variable is set to an output filename that will be appended *NOT OVERWRITTEN* if it exists. If this environment variable is undefined, the statistics will be output to stderr
@code
KMP_STATS_THREADS
@endcode
This environment variable indicates to print thread-specific statistics as well as aggregate statistics. Each thread's statistics will be shown as well as the collective sum of all threads. The values "true", "on", "1", "yes" will all indicate to print per thread statistics.
@defgroup TASKING Tasking support
These functions support tasking constructs.
@defgroup USER User visible functions
These functions can be called directly by the user, but are runtime library specific, rather than being OpenMP interfaces.
*/
+54 -54
View File
@@ -56,43 +56,27 @@ set(LIBOMP_CFILES)
set(LIBOMP_CXXFILES)
set(LIBOMP_ASMFILES)
if(${STUBS_LIBRARY})
set(LIBOMP_CFILES kmp_stub.c)
set(LIBOMP_CFILES kmp_stub.cpp)
else()
# Get C files
set(LIBOMP_CFILES
kmp_alloc.c
kmp_atomic.c
kmp_csupport.c
kmp_debug.c
kmp_itt.c
kmp_environment.c
kmp_error.c
kmp_global.c
kmp_i18n.c
kmp_io.c
kmp_runtime.c
kmp_settings.c
kmp_str.c
kmp_tasking.c
kmp_taskq.c
kmp_threadprivate.c
kmp_utility.c
)
if(WIN32)
# Windows specific files
libomp_append(LIBOMP_CFILES z_Windows_NT_util.c)
libomp_append(LIBOMP_CFILES z_Windows_NT-586_util.c)
libomp_append(LIBOMP_ASMFILES z_Windows_NT-586_asm.asm) # Windows assembly file
else()
# Unix specific files
libomp_append(LIBOMP_CFILES z_Linux_util.c)
libomp_append(LIBOMP_CFILES kmp_gsupport.c)
libomp_append(LIBOMP_ASMFILES z_Linux_asm.s) # Unix assembly file
endif()
libomp_append(LIBOMP_CFILES thirdparty/ittnotify/ittnotify_static.c LIBOMP_USE_ITT_NOTIFY)
libomp_append(LIBOMP_CFILES kmp_debugger.c LIBOMP_USE_DEBUGGER)
# Get C++ files
set(LIBOMP_CXXFILES
kmp_alloc.cpp
kmp_atomic.cpp
kmp_csupport.cpp
kmp_debug.cpp
kmp_itt.cpp
kmp_environment.cpp
kmp_error.cpp
kmp_global.cpp
kmp_i18n.cpp
kmp_io.cpp
kmp_runtime.cpp
kmp_settings.cpp
kmp_str.cpp
kmp_tasking.cpp
kmp_taskq.cpp
kmp_threadprivate.cpp
kmp_utility.cpp
kmp_barrier.cpp
kmp_wait_release.cpp
kmp_affinity.cpp
@@ -100,6 +84,19 @@ else()
kmp_lock.cpp
kmp_sched.cpp
)
if(WIN32)
# Windows specific files
libomp_append(LIBOMP_CXXFILES z_Windows_NT_util.cpp)
libomp_append(LIBOMP_CXXFILES z_Windows_NT-586_util.cpp)
libomp_append(LIBOMP_ASMFILES z_Windows_NT-586_asm.asm) # Windows assembly file
else()
# Unix specific files
libomp_append(LIBOMP_CXXFILES z_Linux_util.cpp)
libomp_append(LIBOMP_CXXFILES kmp_gsupport.cpp)
libomp_append(LIBOMP_ASMFILES z_Linux_asm.S) # Unix assembly file
endif()
libomp_append(LIBOMP_CFILES thirdparty/ittnotify/ittnotify_static.c LIBOMP_USE_ITT_NOTIFY)
libomp_append(LIBOMP_CXXFILES kmp_debugger.cpp LIBOMP_USE_DEBUGGER)
libomp_append(LIBOMP_CXXFILES kmp_stats.cpp LIBOMP_STATS)
libomp_append(LIBOMP_CXXFILES kmp_stats_timing.cpp LIBOMP_STATS)
if(${LIBOMP_OMP_VERSION} GREATER 40 OR ${LIBOMP_OMP_VERSION} EQUAL 40)
@@ -108,10 +105,11 @@ else()
endif()
endif()
# Files common to stubs and normal library
libomp_append(LIBOMP_CFILES kmp_ftn_cdecl.c)
libomp_append(LIBOMP_CFILES kmp_ftn_extra.c)
libomp_append(LIBOMP_CFILES kmp_version.c)
libomp_append(LIBOMP_CFILES ompt-general.c IF_TRUE LIBOMP_OMPT_SUPPORT)
libomp_append(LIBOMP_CXXFILES kmp_ftn_cdecl.cpp)
libomp_append(LIBOMP_CXXFILES kmp_ftn_extra.cpp)
libomp_append(LIBOMP_CXXFILES kmp_version.cpp)
libomp_append(LIBOMP_CXXFILES ompt-general.cpp IF_TRUE LIBOMP_OMPT_SUPPORT)
libomp_append(LIBOMP_CXXFILES tsan_annotations.cpp IF_TRUE LIBOMP_TSAN_SUPPORT)
set(LIBOMP_SOURCE_FILES ${LIBOMP_CFILES} ${LIBOMP_CXXFILES} ${LIBOMP_ASMFILES})
# For Windows, there is a resource file (.rc -> .res) that is also compiled
@@ -200,9 +198,9 @@ if(WIN32)
set_source_files_properties(thirdparty/ittnotify/ittnotify_static.c PROPERTIES COMPILE_DEFINITIONS "UNICODE")
# Create Windows import library
# the import library is "re-linked" to include kmp_import.c which prevents
# the import library is "re-linked" to include kmp_import.cpp which prevents
# linking of both Visual Studio OpenMP and newly built OpenMP
set_source_files_properties(kmp_import.c PROPERTIES COMPILE_FLAGS "${LIBOMP_CONFIGURED_CFLAGS}")
set_source_files_properties(kmp_import.cpp PROPERTIES COMPILE_FLAGS "${LIBOMP_CONFIGURED_CFLAGS}")
set(LIBOMP_IMP_LIB_FILE ${LIBOMP_LIB_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX})
set(LIBOMP_GENERATED_IMP_LIB_FILENAME ${LIBOMP_LIB_FILE}${CMAKE_STATIC_LIBRARY_SUFFIX})
set_target_properties(omp PROPERTIES
@@ -218,8 +216,8 @@ if(WIN32)
set(LIBOMP_GENERATED_IMP_LIB ${CMAKE_CURRENT_BINARY_DIR}/${LIBOMP_GENERATED_IMP_LIB_FILENAME})
endif()
set_source_files_properties(${LIBOMP_GENERATED_IMP_LIB} PROPERTIES GENERATED TRUE EXTERNAL_OBJECT TRUE)
# Create new import library that is just the previously created one + kmp_import.c
add_library(ompimp STATIC ${LIBOMP_GENERATED_IMP_LIB} kmp_import.c)
# Create new import library that is just the previously created one + kmp_import.cpp
add_library(ompimp STATIC ${LIBOMP_GENERATED_IMP_LIB} kmp_import.cpp)
set_target_properties(ompimp PROPERTIES
PREFIX "" SUFFIX "" OUTPUT_NAME "${LIBOMP_IMP_LIB_FILE}"
LINKER_LANGUAGE C
@@ -284,34 +282,36 @@ add_dependencies(libomp-micro-tests libomp-test-deps)
# Install rules
# We want to install libomp in DESTDIR/CMAKE_INSTALL_PREFIX/lib
# We want to install headers in DESTDIR/CMAKE_INSTALL_PREFIX/include
if(${LIBOMP_STANDALONE_BUILD})
if(${OPENMP_STANDALONE_BUILD})
set(LIBOMP_HEADERS_INSTALL_PATH include)
else()
string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CLANG_VERSION ${PACKAGE_VERSION})
set(LIBOMP_HEADERS_INSTALL_PATH lib${LIBOMP_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}/include)
set(LIBOMP_HEADERS_INSTALL_PATH lib${OPENMP_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}/include)
endif()
if(WIN32)
install(TARGETS omp RUNTIME DESTINATION bin)
install(TARGETS ompimp ARCHIVE DESTINATION lib${LIBOMP_LIBDIR_SUFFIX})
install(TARGETS ompimp ARCHIVE DESTINATION lib${OPENMP_LIBDIR_SUFFIX})
# Create aliases (regular copies) of the library for backwards compatibility
set(LIBOMP_ALIASES "libiomp5md")
foreach(alias IN LISTS LIBOMP_ALIASES)
install(CODE "execute_process(COMMAND \"\${CMAKE_COMMAND}\" -E copy \"${LIBOMP_LIB_FILE}\"
\"${alias}${LIBOMP_LIBRARY_SUFFIX}\" WORKING_DIRECTORY \${CMAKE_INSTALL_PREFIX}/bin)")
install(CODE "execute_process(COMMAND \"\${CMAKE_COMMAND}\" -E copy \"${LIBOMP_IMP_LIB_FILE}\"
\"${alias}${LIBOMP_LIBRARY_SUFFIX}\" WORKING_DIRECTORY \${CMAKE_INSTALL_PREFIX}/lib${LIBOMP_LIBDIR_SUFFIX})")
\"${alias}${LIBOMP_LIBRARY_SUFFIX}\" WORKING_DIRECTORY \${CMAKE_INSTALL_PREFIX}/lib${OPENMP_LIBDIR_SUFFIX})")
endforeach()
else()
install(TARGETS omp ${LIBOMP_INSTALL_KIND} DESTINATION lib${LIBOMP_LIBDIR_SUFFIX})
install(TARGETS omp ${LIBOMP_INSTALL_KIND} DESTINATION lib${OPENMP_LIBDIR_SUFFIX})
# Create aliases (symlinks) of the library for backwards compatibility
set(LIBOMP_ALIASES "libgomp;libiomp5")
foreach(alias IN LISTS LIBOMP_ALIASES)
install(CODE "execute_process(COMMAND \"\${CMAKE_COMMAND}\" -E create_symlink \"${LIBOMP_LIB_FILE}\"
\"${alias}${LIBOMP_LIBRARY_SUFFIX}\" WORKING_DIRECTORY
\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/lib${LIBOMP_LIBDIR_SUFFIX})")
endforeach()
if(${LIBOMP_INSTALL_ALIASES})
# Create aliases (symlinks) of the library for backwards compatibility
set(LIBOMP_ALIASES "libgomp;libiomp5")
foreach(alias IN LISTS LIBOMP_ALIASES)
install(CODE "execute_process(COMMAND \"\${CMAKE_COMMAND}\" -E create_symlink \"${LIBOMP_LIB_FILE}\"
\"${alias}${LIBOMP_LIBRARY_SUFFIX}\" WORKING_DIRECTORY
\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/lib${OPENMP_LIBDIR_SUFFIX})")
endforeach()
endif()
endif()
install(
FILES
+181 -4
View File
@@ -162,9 +162,11 @@
__kmp_wait_yield_4
__kmp_fork_call
__kmp_invoke_microtask
%ifdef KMP_USE_MONITOR
__kmp_launch_monitor
__kmp_launch_worker
__kmp_reap_monitor
%endif
__kmp_launch_worker
__kmp_reap_worker
__kmp_acquire_tas_lock
__kmp_acquire_nested_tas_lock
@@ -349,7 +351,7 @@ kmpc_set_defaults 224
%ifdef OMP_30
__kmpc_omp_taskyield 235
%endif # OMP_30
__kmpc_place_threads 236
# __kmpc_place_threads 236
%endif
# OpenMP 4.0 entry points
@@ -395,6 +397,15 @@ kmpc_set_defaults 224
kmpc_aligned_malloc 265
kmpc_set_disp_num_buffers 267
# OpenMP 5.0 entry points
# TODO: change to OMP_50 once it is implemented
%ifndef stub
%ifdef OMP_45
__kmpc_task_reduction_init 268
__kmpc_task_reduction_get_th_data 269
%endif
%endif
# User API entry points that have both lower- and upper- case versions for Fortran.
# Number for lowercase version is indicated. Number for uppercase is obtained by adding 1000.
# User API entry points are entry points that start with 'kmp_' or 'omp_'.
@@ -494,9 +505,9 @@ kmp_set_warnings_off 780
omp_get_cancellation 867
kmp_get_cancellation_status 868
omp_is_initial_device 869
omp_set_default_device 879
omp_get_default_device 880
%ifdef stub
omp_set_default_device 879
omp_get_default_device 880
omp_get_num_devices 881
%endif
%endif # OMP_40
@@ -922,6 +933,59 @@ kmp_set_disp_num_buffers 890
__kmpc_atomic_start 2410
__kmpc_atomic_end 2411
%ifdef HAVE_QUAD
__kmpc_atomic_fixed1_add_cpt_fp
__kmpc_atomic_fixed1_sub_cpt_fp
__kmpc_atomic_fixed1_mul_cpt_fp
__kmpc_atomic_fixed1_div_cpt_fp
__kmpc_atomic_fixed1u_add_cpt_fp
__kmpc_atomic_fixed1u_sub_cpt_fp
__kmpc_atomic_fixed1u_mul_cpt_fp
__kmpc_atomic_fixed1u_div_cpt_fp
__kmpc_atomic_fixed2_add_cpt_fp
__kmpc_atomic_fixed2_sub_cpt_fp
__kmpc_atomic_fixed2_mul_cpt_fp
__kmpc_atomic_fixed2_div_cpt_fp
__kmpc_atomic_fixed2u_add_cpt_fp
__kmpc_atomic_fixed2u_sub_cpt_fp
__kmpc_atomic_fixed2u_mul_cpt_fp
__kmpc_atomic_fixed2u_div_cpt_fp
__kmpc_atomic_fixed4_add_cpt_fp
__kmpc_atomic_fixed4_sub_cpt_fp
__kmpc_atomic_fixed4_mul_cpt_fp
__kmpc_atomic_fixed4_div_cpt_fp
__kmpc_atomic_fixed4u_add_cpt_fp
__kmpc_atomic_fixed4u_sub_cpt_fp
__kmpc_atomic_fixed4u_mul_cpt_fp
__kmpc_atomic_fixed4u_div_cpt_fp
__kmpc_atomic_fixed8_add_cpt_fp
__kmpc_atomic_fixed8_sub_cpt_fp
__kmpc_atomic_fixed8_mul_cpt_fp
__kmpc_atomic_fixed8_div_cpt_fp
__kmpc_atomic_fixed8u_add_cpt_fp
__kmpc_atomic_fixed8u_sub_cpt_fp
__kmpc_atomic_fixed8u_mul_cpt_fp
__kmpc_atomic_fixed8u_div_cpt_fp
__kmpc_atomic_float4_add_cpt_fp
__kmpc_atomic_float4_sub_cpt_fp
__kmpc_atomic_float4_mul_cpt_fp
__kmpc_atomic_float4_div_cpt_fp
__kmpc_atomic_float8_add_cpt_fp
__kmpc_atomic_float8_sub_cpt_fp
__kmpc_atomic_float8_mul_cpt_fp
__kmpc_atomic_float8_div_cpt_fp
__kmpc_atomic_float10_add_cpt_fp
__kmpc_atomic_float10_sub_cpt_fp
__kmpc_atomic_float10_mul_cpt_fp
__kmpc_atomic_float10_div_cpt_fp
%endif
%ifdef OMP_40
# ATOMIC extensions for OpenMP 4.0 spec (x86 and x64 only)
@@ -1000,11 +1064,124 @@ kmp_set_disp_num_buffers 890
%endif
%endif
__kmpc_atomic_fixed1_sub_rev 2470
__kmpc_atomic_fixed1_div_rev 2471
__kmpc_atomic_fixed1u_div_rev 2472
__kmpc_atomic_fixed1_shl_rev 2473
__kmpc_atomic_fixed1_shr_rev 2474
__kmpc_atomic_fixed1u_shr_rev 2475
__kmpc_atomic_fixed2_sub_rev 2476
__kmpc_atomic_fixed2_div_rev 2477
__kmpc_atomic_fixed2u_div_rev 2478
__kmpc_atomic_fixed2_shl_rev 2479
__kmpc_atomic_fixed2_shr_rev 2480
__kmpc_atomic_fixed2u_shr_rev 2481
__kmpc_atomic_fixed4_sub_rev 2482
__kmpc_atomic_fixed4_div_rev 2483
__kmpc_atomic_fixed4u_div_rev 2484
__kmpc_atomic_fixed4_shl_rev 2485
__kmpc_atomic_fixed4_shr_rev 2486
__kmpc_atomic_fixed4u_shr_rev 2487
__kmpc_atomic_fixed8_sub_rev 2488
__kmpc_atomic_fixed8_div_rev 2489
__kmpc_atomic_fixed8u_div_rev 2490
__kmpc_atomic_fixed8_shl_rev 2491
__kmpc_atomic_fixed8_shr_rev 2492
__kmpc_atomic_fixed8u_shr_rev 2493
__kmpc_atomic_float4_sub_rev 2494
__kmpc_atomic_float4_div_rev 2495
__kmpc_atomic_float8_sub_rev 2496
__kmpc_atomic_float8_div_rev 2497
__kmpc_atomic_float10_sub_rev 2498
__kmpc_atomic_float10_div_rev 2499
%ifdef HAVE_QUAD
__kmpc_atomic_float16_sub_rev 2500
__kmpc_atomic_float16_div_rev 2501
%endif
__kmpc_atomic_cmplx4_sub_rev 2502
__kmpc_atomic_cmplx4_div_rev 2503
__kmpc_atomic_cmplx8_sub_rev 2504
__kmpc_atomic_cmplx8_div_rev 2505
__kmpc_atomic_cmplx10_sub_rev 2506
__kmpc_atomic_cmplx10_div_rev 2507
%ifdef HAVE_QUAD
__kmpc_atomic_cmplx16_sub_rev 2508
__kmpc_atomic_cmplx16_div_rev 2509
%ifdef arch_32
__kmpc_atomic_float16_sub_a16_rev 2510
__kmpc_atomic_float16_div_a16_rev 2511
__kmpc_atomic_cmplx16_sub_a16_rev 2512
__kmpc_atomic_cmplx16_div_a16_rev 2513
%endif
%endif
%ifdef HAVE_QUAD
__kmpc_atomic_fixed1_sub_rev_fp
__kmpc_atomic_fixed1u_sub_rev_fp
__kmpc_atomic_fixed1_div_rev_fp
__kmpc_atomic_fixed1u_div_rev_fp
__kmpc_atomic_fixed2_sub_rev_fp
__kmpc_atomic_fixed2u_sub_rev_fp
__kmpc_atomic_fixed2_div_rev_fp
__kmpc_atomic_fixed2u_div_rev_fp
__kmpc_atomic_fixed4_sub_rev_fp
__kmpc_atomic_fixed4u_sub_rev_fp
__kmpc_atomic_fixed4_div_rev_fp
__kmpc_atomic_fixed4u_div_rev_fp
__kmpc_atomic_fixed8_sub_rev_fp
__kmpc_atomic_fixed8u_sub_rev_fp
__kmpc_atomic_fixed8_div_rev_fp
__kmpc_atomic_fixed8u_div_rev_fp
__kmpc_atomic_float4_sub_rev_fp
__kmpc_atomic_float4_div_rev_fp
__kmpc_atomic_float8_sub_rev_fp
__kmpc_atomic_float8_div_rev_fp
__kmpc_atomic_float10_sub_rev_fp
__kmpc_atomic_float10_div_rev_fp
__kmpc_atomic_fixed1_sub_cpt_rev_fp
__kmpc_atomic_fixed1u_sub_cpt_rev_fp
__kmpc_atomic_fixed1_div_cpt_rev_fp
__kmpc_atomic_fixed1u_div_cpt_rev_fp
__kmpc_atomic_fixed2_sub_cpt_rev_fp
__kmpc_atomic_fixed2u_sub_cpt_rev_fp
__kmpc_atomic_fixed2_div_cpt_rev_fp
__kmpc_atomic_fixed2u_div_cpt_rev_fp
__kmpc_atomic_fixed4_sub_cpt_rev_fp
__kmpc_atomic_fixed4u_sub_cpt_rev_fp
__kmpc_atomic_fixed4_div_cpt_rev_fp
__kmpc_atomic_fixed4u_div_cpt_rev_fp
__kmpc_atomic_fixed8_sub_cpt_rev_fp
__kmpc_atomic_fixed8u_sub_cpt_rev_fp
__kmpc_atomic_fixed8_div_cpt_rev_fp
__kmpc_atomic_fixed8u_div_cpt_rev_fp
__kmpc_atomic_float4_sub_cpt_rev_fp
__kmpc_atomic_float4_div_cpt_rev_fp
__kmpc_atomic_float8_sub_cpt_rev_fp
__kmpc_atomic_float8_div_cpt_rev_fp
__kmpc_atomic_float10_sub_cpt_rev_fp
__kmpc_atomic_float10_div_cpt_rev_fp
%endif
%endif # OMP_40
%endif # arch_64
%ifdef HAVE_QUAD
__kmpc_atomic_fixed1u_add_fp
__kmpc_atomic_fixed1u_sub_fp
__kmpc_atomic_fixed1u_mul_fp
__kmpc_atomic_fixed2u_add_fp
__kmpc_atomic_fixed2u_sub_fp
__kmpc_atomic_fixed2u_mul_fp
__kmpc_atomic_fixed4u_add_fp
__kmpc_atomic_fixed4u_sub_fp
__kmpc_atomic_fixed4u_mul_fp
__kmpc_atomic_fixed8u_add_fp
__kmpc_atomic_fixed8u_sub_fp
__kmpc_atomic_fixed8u_mul_fp
%endif
%endif
# end of file #
+6 -14
View File
@@ -25,17 +25,10 @@ VERSION {
#
# OMPT API
#
ompt_tool; # OMPT initialization interface
ompt_control; # OMPT control interface
ompt_start_tool; # OMPT start interface
#
# OMPT state placeholders
#
ompt_idle;
ompt_overhead;
ompt_barrier_wait;
ompt_task_wait;
ompt_mutex_wait;
# icc drops weak attribute at linking step without the following line:
Annotate*; # TSAN annotation
ompc_*; # omp.h renames some standard functions to ompc_*.
kmp_*; # Intel extensions.
@@ -81,13 +74,12 @@ VERSION {
__kmp_acquire_tas_lock;
__kmp_acquire_ticket_lock;
__kmp_fork_call;
__kmp_get_reduce_method;
__kmp_invoke_microtask;
__kmp_itt_fini_ittlib;
__kmp_itt_init_ittlib;
#if KMP_USE_MONITOR
__kmp_launch_monitor;
__kmp_launch_worker;
__kmp_reap_monitor;
#endif
__kmp_launch_worker;
__kmp_reap_worker;
__kmp_release_64;
__kmp_wait_64;
+390 -403
View File
@@ -2,7 +2,6 @@
* extractExternal.cpp
*/
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
@@ -12,14 +11,13 @@
//
//===----------------------------------------------------------------------===//
#include <stdlib.h>
#include <iostream>
#include <strstream>
#include <fstream>
#include <string>
#include <set>
#include <iostream>
#include <map>
#include <set>
#include <stdlib.h>
#include <string>
#include <strstream>
/* Given a set of n object files h ('external' object files) and a set of m
object files o ('internal' object files),
@@ -30,468 +28,457 @@
Usage:
hide.exe <n> <filenames for h> <filenames for o>
Thus, the prefixed symbols become hidden in the sense that they now have a special
prefix.
Thus, the prefixed symbols become hidden in the sense that they now have a
special prefix.
*/
using namespace std;
void stop(char* errorMsg) {
printf("%s\n", errorMsg);
exit(1);
void stop(char *errorMsg) {
printf("%s\n", errorMsg);
exit(1);
}
// an entry in the symbol table of a .OBJ file
class Symbol {
public:
__int64 name;
unsigned value;
unsigned short sectionNum, type;
char storageClass, nAux;
__int64 name;
unsigned value;
unsigned short sectionNum, type;
char storageClass, nAux;
};
class _rstream : public istrstream {
private:
const char *buf;
const char *buf;
protected:
_rstream(pair<const char*, streamsize> p):istrstream(p.first,p.second),buf(p.first){}
~_rstream() {
delete[]buf;
}
_rstream(pair<const char *, streamsize> p)
: istrstream(p.first, p.second), buf(p.first) {}
~_rstream() { delete[] buf; }
};
/* A stream encapuslating the content of a file or the content of a string, overriding the
>> operator to read various integer types in binary form, as well as a symbol table
entry.
*/
// A stream encapuslating the content of a file or the content of a string,
// overriding the >> operator to read various integer types in binary form,
// as well as a symbol table entry.
class rstream : public _rstream {
private:
template<class T>
inline rstream& doRead(T &x) {
read((char*)&x, sizeof(T));
return *this;
}
static pair<const char*, streamsize> getBuf(const char *fileName) {
ifstream raw(fileName,ios::binary | ios::in);
if(!raw.is_open())
stop("rstream.getBuf: Error opening file");
raw.seekg(0,ios::end);
streampos fileSize = raw.tellg();
if(fileSize < 0)
stop("rstream.getBuf: Error reading file");
char *buf = new char[fileSize];
raw.seekg(0,ios::beg);
raw.read(buf, fileSize);
return pair<const char*, streamsize>(buf,fileSize);
}
template <class T> inline rstream &doRead(T &x) {
read((char *)&x, sizeof(T));
return *this;
}
static pair<const char *, streamsize> getBuf(const char *fileName) {
ifstream raw(fileName, ios::binary | ios::in);
if (!raw.is_open())
stop("rstream.getBuf: Error opening file");
raw.seekg(0, ios::end);
streampos fileSize = raw.tellg();
if (fileSize < 0)
stop("rstream.getBuf: Error reading file");
char *buf = new char[fileSize];
raw.seekg(0, ios::beg);
raw.read(buf, fileSize);
return pair<const char *, streamsize>(buf, fileSize);
}
public:
// construct from a string
rstream(const char *buf,streamsize size):_rstream(pair<const char*,streamsize>(buf, size)){}
/* construct from a file whole content is fully read once to initialize the content of
this stream
*/
rstream(const char *fileName):_rstream(getBuf(fileName)){}
rstream& operator>>(int &x) {
return doRead(x);
}
rstream& operator>>(unsigned &x) {
return doRead(x);
}
rstream& operator>>(short &x) {
return doRead(x);
}
rstream& operator>>(unsigned short &x) {
return doRead(x);
}
rstream& operator>>(Symbol &e) {
read((char*)&e, 18);
return *this;
}
// construct from a string
rstream(const char *buf, streamsize size)
: _rstream(pair<const char *, streamsize>(buf, size)) {}
// construct from a file whole content is fully read once to initialize the
// content of this stream
rstream(const char *fileName) : _rstream(getBuf(fileName)) {}
rstream &operator>>(int &x) { return doRead(x); }
rstream &operator>>(unsigned &x) { return doRead(x); }
rstream &operator>>(short &x) { return doRead(x); }
rstream &operator>>(unsigned short &x) { return doRead(x); }
rstream &operator>>(Symbol &e) {
read((char *)&e, 18);
return *this;
}
};
// string table in a .OBJ file
class StringTable {
private:
map<string, unsigned> directory;
size_t length;
char *data;
map<string, unsigned> directory;
size_t length;
char *data;
// make <directory> from <length> bytes in <data>
void makeDirectory(void) {
unsigned i = 4;
while(i < length) {
string s = string(data + i);
directory.insert(make_pair(s, i));
i += s.size() + 1;
}
// make <directory> from <length> bytes in <data>
void makeDirectory(void) {
unsigned i = 4;
while (i < length) {
string s = string(data + i);
directory.insert(make_pair(s, i));
i += s.size() + 1;
}
// initialize <length> and <data> with contents specified by the arguments
void init(const char *_data) {
unsigned _length = *(unsigned*)_data;
}
// initialize <length> and <data> with contents specified by the arguments
void init(const char *_data) {
unsigned _length = *(unsigned *)_data;
if(_length < sizeof(unsigned) || _length != *(unsigned*)_data)
stop("StringTable.init: Invalid symbol table");
if(_data[_length - 1]) {
// to prevent runaway strings, make sure the data ends with a zero
data = new char[length = _length + 1];
data[_length] = 0;
} else {
data = new char[length = _length];
}
*(unsigned*)data = length;
KMP_MEMCPY(data + sizeof(unsigned), _data + sizeof(unsigned),
length - sizeof(unsigned));
makeDirectory();
if (_length < sizeof(unsigned) || _length != *(unsigned *)_data)
stop("StringTable.init: Invalid symbol table");
if (_data[_length - 1]) {
// to prevent runaway strings, make sure the data ends with a zero
data = new char[length = _length + 1];
data[_length] = 0;
} else {
data = new char[length = _length];
}
*(unsigned *)data = length;
KMP_MEMCPY(data + sizeof(unsigned), _data + sizeof(unsigned),
length - sizeof(unsigned));
makeDirectory();
}
public:
StringTable(rstream &f) {
/* Construct string table by reading from f.
*/
streampos s;
unsigned strSize;
char *strData;
StringTable(rstream &f) {
// Construct string table by reading from f.
streampos s;
unsigned strSize;
char *strData;
s = f.tellg();
f>>strSize;
if(strSize < sizeof(unsigned))
stop("StringTable: Invalid string table");
strData = new char[strSize];
*(unsigned*)strData = strSize;
// read the raw data into <strData>
f.read(strData + sizeof(unsigned), strSize - sizeof(unsigned));
s = f.tellg() - s;
if(s < strSize)
stop("StringTable: Unexpected EOF");
init(strData);
delete[]strData;
}
StringTable(const set<string> &strings) {
/* Construct string table from given strings.
*/
char *p;
set<string>::const_iterator it;
size_t s;
s = f.tellg();
f >> strSize;
if (strSize < sizeof(unsigned))
stop("StringTable: Invalid string table");
strData = new char[strSize];
*(unsigned *)strData = strSize;
// read the raw data into <strData>
f.read(strData + sizeof(unsigned), strSize - sizeof(unsigned));
s = f.tellg() - s;
if (s < strSize)
stop("StringTable: Unexpected EOF");
init(strData);
delete[] strData;
}
StringTable(const set<string> &strings) {
// Construct string table from given strings.
char *p;
set<string>::const_iterator it;
size_t s;
// count required size for data
for(length = sizeof(unsigned), it = strings.begin(); it != strings.end(); ++it) {
size_t l = (*it).size();
// count required size for data
for (length = sizeof(unsigned), it = strings.begin(); it != strings.end();
++it) {
size_t l = (*it).size();
if(l > (unsigned) 0xFFFFFFFF)
stop("StringTable: String too long");
if(l > 8) {
length += l + 1;
if(length > (unsigned) 0xFFFFFFFF)
stop("StringTable: Symbol table too long");
}
}
data = new char[length];
*(unsigned*)data = length;
// populate data and directory
for(p = data + sizeof(unsigned), it = strings.begin(); it != strings.end(); ++it) {
const string &str = *it;
size_t l = str.size();
if(l > 8) {
directory.insert(make_pair(str, p - data));
KMP_MEMCPY(p, str.c_str(), l);
p[l] = 0;
p += l + 1;
}
}
if (l > (unsigned)0xFFFFFFFF)
stop("StringTable: String too long");
if (l > 8) {
length += l + 1;
if (length > (unsigned)0xFFFFFFFF)
stop("StringTable: Symbol table too long");
}
}
~StringTable() {
delete[] data;
data = new char[length];
*(unsigned *)data = length;
// populate data and directory
for (p = data + sizeof(unsigned), it = strings.begin(); it != strings.end();
++it) {
const string &str = *it;
size_t l = str.size();
if (l > 8) {
directory.insert(make_pair(str, p - data));
KMP_MEMCPY(p, str.c_str(), l);
p[l] = 0;
p += l + 1;
}
}
/* Returns encoding for given string based on this string table.
Error if string length is greater than 8 but string is not in
the string table--returns 0.
*/
__int64 encode(const string &str) {
__int64 r;
}
~StringTable() { delete[] data; }
// Returns encoding for given string based on this string table. Error if
// string length is greater than 8 but string is not in the string table
// -- returns 0.
__int64 encode(const string &str) {
__int64 r;
if(str.size() <= 8) {
// encoded directly
((char*)&r)[7] = 0;
KMP_STRNCPY_S((char*)&r, sizeof(r), str.c_str(), 8);
return r;
} else {
// represented as index into table
map<string,unsigned>::const_iterator it = directory.find(str);
if(it == directory.end())
stop("StringTable::encode: String now found in string table");
((unsigned*)&r)[0] = 0;
((unsigned*)&r)[1] = (*it).second;
return r;
}
if (str.size() <= 8) {
// encoded directly
((char *)&r)[7] = 0;
KMP_STRNCPY_S((char *)&r, sizeof(r), str.c_str(), 8);
return r;
} else {
// represented as index into table
map<string, unsigned>::const_iterator it = directory.find(str);
if (it == directory.end())
stop("StringTable::encode: String now found in string table");
((unsigned *)&r)[0] = 0;
((unsigned *)&r)[1] = (*it).second;
return r;
}
/* Returns string represented by x based on this string table.
Error if x references an invalid position in the table--returns
the empty string.
*/
string decode(__int64 x) const {
if(*(unsigned*)&x == 0) {
// represented as index into table
unsigned &p = ((unsigned*)&x)[1];
if(p >= length)
stop("StringTable::decode: Invalid string table lookup");
return string(data + p);
} else {
// encoded directly
char *p = (char*)&x;
int i;
}
// Returns string represented by x based on this string table. Error if x
// references an invalid position in the table--returns the empty string.
string decode(__int64 x) const {
if (*(unsigned *)&x == 0) {
// represented as index into table
unsigned &p = ((unsigned *)&x)[1];
if (p >= length)
stop("StringTable::decode: Invalid string table lookup");
return string(data + p);
} else {
// encoded directly
char *p = (char *)&x;
int i;
for(i = 0; i < 8 && p[i]; ++i);
return string(p, i);
}
}
void write(ostream &os) {
os.write(data, length);
for (i = 0; i < 8 && p[i]; ++i)
;
return string(p, i);
}
}
void write(ostream &os) { os.write(data, length); }
};
/* for the named object file, determines the set of defined symbols and the set of undefined external symbols
and writes them to <defined> and <undefined> respectively
*/
void computeExternalSymbols(const char *fileName, set<string> *defined, set<string> *undefined){
streampos fileSize;
size_t strTabStart;
unsigned symTabStart, symNEntries;
rstream f(fileName);
// for the named object file, determines the set of defined symbols and the set
// of undefined external symbols and writes them to <defined> and <undefined>
// respectively
void computeExternalSymbols(const char *fileName, set<string> *defined,
set<string> *undefined) {
streampos fileSize;
size_t strTabStart;
unsigned symTabStart, symNEntries;
rstream f(fileName);
f.seekg(0,ios::end);
fileSize = f.tellg();
f.seekg(0, ios::end);
fileSize = f.tellg();
f.seekg(8);
f >> symTabStart >> symNEntries;
// seek to the string table
f.seekg(strTabStart = symTabStart + 18 * (size_t)symNEntries);
if(f.eof()) {
printf("computeExternalSymbols: fileName='%s', fileSize = %lu, symTabStart = %u, symNEntries = %u\n",
fileName, (unsigned long) fileSize, symTabStart, symNEntries);
stop("computeExternalSymbols: Unexpected EOF 1");
}
StringTable stringTable(f); // read the string table
if(f.tellg() != fileSize)
stop("computeExternalSymbols: Unexpected data after string table");
f.clear();
f.seekg(symTabStart); // seek to the symbol table
defined->clear(); undefined->clear();
for(int i = 0; i < symNEntries; ++i) {
// process each entry
Symbol e;
if(f.eof())
stop("computeExternalSymbols: Unexpected EOF 2");
f>>e;
if(f.fail())
stop("computeExternalSymbols: File read error");
if(e.nAux) { // auxiliary entry: skip
f.seekg(e.nAux * 18, ios::cur);
i += e.nAux;
}
// if symbol is extern and defined in the current file, insert it
if(e.storageClass == 2)
if(e.sectionNum)
defined->insert(stringTable.decode(e.name));
else
undefined->insert(stringTable.decode(e.name));
f.seekg(8);
f >> symTabStart >> symNEntries;
// seek to the string table
f.seekg(strTabStart = symTabStart + 18 * (size_t)symNEntries);
if (f.eof()) {
printf("computeExternalSymbols: fileName='%s', fileSize = %lu, symTabStart "
"= %u, symNEntries = %u\n",
fileName, (unsigned long)fileSize, symTabStart, symNEntries);
stop("computeExternalSymbols: Unexpected EOF 1");
}
StringTable stringTable(f); // read the string table
if (f.tellg() != fileSize)
stop("computeExternalSymbols: Unexpected data after string table");
f.clear();
f.seekg(symTabStart); // seek to the symbol table
defined->clear();
undefined->clear();
for (int i = 0; i < symNEntries; ++i) {
// process each entry
Symbol e;
if (f.eof())
stop("computeExternalSymbols: Unexpected EOF 2");
f >> e;
if (f.fail())
stop("computeExternalSymbols: File read error");
if (e.nAux) { // auxiliary entry: skip
f.seekg(e.nAux * 18, ios::cur);
i += e.nAux;
}
// if symbol is extern and defined in the current file, insert it
if (e.storageClass == 2)
if (e.sectionNum)
defined->insert(stringTable.decode(e.name));
else
undefined->insert(stringTable.decode(e.name));
}
}
/* For each occurrence of an external symbol in the object file named by
by <fileName> that is a member of <hide>, renames it by prefixing
with "__kmp_external_", writing back the file in-place
*/
// For each occurrence of an external symbol in the object file named by
// by <fileName> that is a member of <hide>, renames it by prefixing
// with "__kmp_external_", writing back the file in-place
void hideSymbols(char *fileName, const set<string> &hide) {
static const string prefix("__kmp_external_");
set<string> strings; // set of all occurring symbols, appropriately prefixed
streampos fileSize;
size_t strTabStart;
unsigned symTabStart, symNEntries;
int i;
rstream in(fileName);
static const string prefix("__kmp_external_");
set<string> strings; // set of all occurring symbols, appropriately prefixed
streampos fileSize;
size_t strTabStart;
unsigned symTabStart, symNEntries;
int i;
rstream in(fileName);
in.seekg(0,ios::end);
fileSize = in.tellg();
in.seekg(0, ios::end);
fileSize = in.tellg();
in.seekg(8);
in >> symTabStart >> symNEntries;
in.seekg(strTabStart = symTabStart + 18 * (size_t)symNEntries);
if(in.eof())
stop("hideSymbols: Unexpected EOF");
StringTable stringTableOld(in); // read original string table
in.seekg(8);
in >> symTabStart >> symNEntries;
in.seekg(strTabStart = symTabStart + 18 * (size_t)symNEntries);
if (in.eof())
stop("hideSymbols: Unexpected EOF");
StringTable stringTableOld(in); // read original string table
if(in.tellg() != fileSize)
stop("hideSymbols: Unexpected data after string table");
if (in.tellg() != fileSize)
stop("hideSymbols: Unexpected data after string table");
// compute set of occurring strings with prefix added
for(i = 0; i < symNEntries; ++i) {
Symbol e;
// compute set of occurring strings with prefix added
for (i = 0; i < symNEntries; ++i) {
Symbol e;
in.seekg(symTabStart + i * 18);
if(in.eof())
stop("hideSymbols: Unexpected EOF");
in >> e;
if(in.fail())
stop("hideSymbols: File read error");
if(e.nAux)
i += e.nAux;
const string &s = stringTableOld.decode(e.name);
// if symbol is extern and found in <hide>, prefix and insert into strings,
// otherwise, just insert into strings without prefix
strings.insert( (e.storageClass == 2 && hide.find(s) != hide.end()) ?
prefix + s : s);
in.seekg(symTabStart + i * 18);
if (in.eof())
stop("hideSymbols: Unexpected EOF");
in >> e;
if (in.fail())
stop("hideSymbols: File read error");
if (e.nAux)
i += e.nAux;
const string &s = stringTableOld.decode(e.name);
// if symbol is extern and found in <hide>, prefix and insert into strings,
// otherwise, just insert into strings without prefix
strings.insert(
(e.storageClass == 2 && hide.find(s) != hide.end()) ? prefix + s : s);
}
ofstream out(fileName, ios::trunc | ios::out | ios::binary);
if (!out.is_open())
stop("hideSymbols: Error opening output file");
// make new string table from string set
StringTable stringTableNew = StringTable(strings);
// copy input file to output file up to just before the symbol table
in.seekg(0);
char *buf = new char[symTabStart];
in.read(buf, symTabStart);
out.write(buf, symTabStart);
delete[] buf;
// copy input symbol table to output symbol table with name translation
for (i = 0; i < symNEntries; ++i) {
Symbol e;
in.seekg(symTabStart + i * 18);
if (in.eof())
stop("hideSymbols: Unexpected EOF");
in >> e;
if (in.fail())
stop("hideSymbols: File read error");
const string &s = stringTableOld.decode(e.name);
out.seekp(symTabStart + i * 18);
e.name = stringTableNew.encode(
(e.storageClass == 2 && hide.find(s) != hide.end()) ? prefix + s : s);
out.write((char *)&e, 18);
if (out.fail())
stop("hideSymbols: File write error");
if (e.nAux) {
// copy auxiliary symbol table entries
int nAux = e.nAux;
for (int j = 1; j <= nAux; ++j) {
in >> e;
out.seekp(symTabStart + (i + j) * 18);
out.write((char *)&e, 18);
}
i += nAux;
}
ofstream out(fileName, ios::trunc | ios::out | ios::binary);
if(!out.is_open())
stop("hideSymbols: Error opening output file");
// make new string table from string set
StringTable stringTableNew = StringTable(strings);
// copy input file to output file up to just before the symbol table
in.seekg(0);
char *buf = new char[symTabStart];
in.read(buf, symTabStart);
out.write(buf, symTabStart);
delete []buf;
// copy input symbol table to output symbol table with name translation
for(i = 0; i < symNEntries; ++i) {
Symbol e;
in.seekg(symTabStart + i*18);
if(in.eof())
stop("hideSymbols: Unexpected EOF");
in >> e;
if(in.fail())
stop("hideSymbols: File read error");
const string &s = stringTableOld.decode(e.name);
out.seekp(symTabStart + i*18);
e.name = stringTableNew.encode( (e.storageClass == 2 && hide.find(s) != hide.end()) ?
prefix + s : s);
out.write((char*)&e, 18);
if(out.fail())
stop("hideSymbols: File write error");
if(e.nAux) {
// copy auxiliary symbol table entries
int nAux = e.nAux;
for(int j = 1; j <= nAux; ++j) {
in >> e;
out.seekp(symTabStart + (i + j) * 18);
out.write((char*)&e, 18);
}
i += nAux;
}
}
// output string table
stringTableNew.write(out);
}
// output string table
stringTableNew.write(out);
}
// returns true iff <a> and <b> have no common element
template <class T>
bool isDisjoint(const set<T> &a, const set<T> &b) {
set<T>::const_iterator ita, itb;
template <class T> bool isDisjoint(const set<T> &a, const set<T> &b) {
set<T>::const_iterator ita, itb;
for(ita = a.begin(), itb = b.begin(); ita != a.end() && itb != b.end();) {
const T &ta = *ita, &tb = *itb;
if(ta < tb)
++ita;
else if (tb < ta)
++itb;
else
return false;
}
return true;
for (ita = a.begin(), itb = b.begin(); ita != a.end() && itb != b.end();) {
const T &ta = *ita, &tb = *itb;
if (ta < tb)
++ita;
else if (tb < ta)
++itb;
else
return false;
}
return true;
}
/* precondition: <defined> and <undefined> are arrays with <nTotal> elements where
<nTotal> >= <nExternal>. The first <nExternal> elements correspond to the external object
files and the rest correspond to the internal object files.
postcondition: file x is said to depend on file y if undefined[x] and defined[y] are not
disjoint. Returns the transitive closure of the set of internal object files, as a set of
file indexes, under the 'depends on' relation, minus the set of internal object files.
*/
set<int> *findRequiredExternal(int nExternal, int nTotal, set<string> *defined, set<string> *undefined) {
set<int> *required = new set<int>;
set<int> fresh[2];
int i, cur = 0;
bool changed;
// PRE: <defined> and <undefined> are arrays with <nTotal> elements where
// <nTotal> >= <nExternal>. The first <nExternal> elements correspond to the
// external object files and the rest correspond to the internal object files.
// POST: file x is said to depend on file y if undefined[x] and defined[y] are
// not disjoint. Returns the transitive closure of the set of internal object
// files, as a set of file indexes, under the 'depends on' relation, minus the
// set of internal object files.
set<int> *findRequiredExternal(int nExternal, int nTotal, set<string> *defined,
set<string> *undefined) {
set<int> *required = new set<int>;
set<int> fresh[2];
int i, cur = 0;
bool changed;
for(i = nTotal - 1; i >= nExternal; --i)
fresh[cur].insert(i);
do {
changed = false;
for(set<int>::iterator it = fresh[cur].begin(); it != fresh[cur].end(); ++it) {
set<string> &s = undefined[*it];
for (i = nTotal - 1; i >= nExternal; --i)
fresh[cur].insert(i);
do {
changed = false;
for (set<int>::iterator it = fresh[cur].begin(); it != fresh[cur].end();
++it) {
set<string> &s = undefined[*it];
for(i = 0; i < nExternal; ++i) {
if(required->find(i) == required->end()) {
if(!isDisjoint(defined[i], s)) {
// found a new qualifying element
required->insert(i);
fresh[1 - cur].insert(i);
changed = true;
}
}
}
}
fresh[cur].clear();
cur = 1 - cur;
} while(changed);
return required;
for (i = 0; i < nExternal; ++i) {
if (required->find(i) == required->end()) {
if (!isDisjoint(defined[i], s)) {
// found a new qualifying element
required->insert(i);
fresh[1 - cur].insert(i);
changed = true;
}
}
}
}
fresh[cur].clear();
cur = 1 - cur;
} while (changed);
return required;
}
int main(int argc, char **argv) {
int nExternal, nInternal, i;
set<string> *defined, *undefined;
set<int>::iterator it;
int nExternal, nInternal, i;
set<string> *defined, *undefined;
set<int>::iterator it;
if(argc < 3)
stop("Please specify a positive integer followed by a list of object filenames");
nExternal = atoi(argv[1]);
if(nExternal <= 0)
stop("Please specify a positive integer followed by a list of object filenames");
if(nExternal + 2 > argc)
stop("Too few external objects");
nInternal = argc - nExternal - 2;
defined = new set<string>[argc - 2];
undefined = new set<string>[argc - 2];
if (argc < 3)
stop("Please specify a positive integer followed by a list of object "
"filenames");
nExternal = atoi(argv[1]);
if (nExternal <= 0)
stop("Please specify a positive integer followed by a list of object "
"filenames");
if (nExternal + 2 > argc)
stop("Too few external objects");
nInternal = argc - nExternal - 2;
defined = new set<string>[argc - 2];
undefined = new set<string>[argc - 2];
// determine the set of defined and undefined external symbols
for(i = 2; i < argc; ++i)
computeExternalSymbols(argv[i], defined + i - 2, undefined + i - 2);
// determine the set of defined and undefined external symbols
for (i = 2; i < argc; ++i)
computeExternalSymbols(argv[i], defined + i - 2, undefined + i - 2);
// determine the set of required external files
set<int> *requiredExternal = findRequiredExternal(nExternal, argc - 2, defined, undefined);
set<string> hide;
// determine the set of required external files
set<int> *requiredExternal =
findRequiredExternal(nExternal, argc - 2, defined, undefined);
set<string> hide;
/* determine the set of symbols to hide--namely defined external symbols of the
required external files
*/
for(it = requiredExternal->begin(); it != requiredExternal->end(); ++it) {
int idx = *it;
set<string>::iterator it2;
/* We have to insert one element at a time instead of inserting a range because
the insert member function taking a range doesn't exist on Windows* OS, at least
at the time of this writing.
*/
for(it2 = defined[idx].begin(); it2 != defined[idx].end(); ++it2)
hide.insert(*it2);
}
// determine the set of symbols to hide--namely defined external symbols of
// the required external files
for (it = requiredExternal->begin(); it != requiredExternal->end(); ++it) {
int idx = *it;
set<string>::iterator it2;
// We have to insert one element at a time instead of inserting a range
// because the insert member function taking a range doesn't exist on
// Windows* OS, at least at the time of this writing.
for (it2 = defined[idx].begin(); it2 != defined[idx].end(); ++it2)
hide.insert(*it2);
}
/* process the external files--removing those that are not required and hiding
the appropriate symbols in the others
*/
for(i = 0; i < nExternal; ++i)
if(requiredExternal->find(i) != requiredExternal->end())
hideSymbols(argv[2 + i], hide);
else
remove(argv[2 + i]);
// hide the appropriate symbols in the internal files
for(i = nExternal + 2; i < argc; ++i)
hideSymbols(argv[i], hide);
return 0;
// process the external files--removing those that are not required and hiding
// the appropriate symbols in the others
for (i = 0; i < nExternal; ++i)
if (requiredExternal->find(i) != requiredExternal->end())
hideSymbols(argv[2 + i], hide);
else
remove(argv[2 + i]);
// hide the appropriate symbols in the internal files
for (i = nExternal + 2; i < argc; ++i)
hideSymbols(argv[i], hide);
return 0;
}
+21 -8
View File
@@ -38,7 +38,7 @@ Language "English"
Country "USA"
LangId "1033"
Version "2"
Revision "20160405"
Revision "20170523"
@@ -103,6 +103,7 @@ DisplayEnvBegin "OPENMP DISPLAY ENVIRONMENT BEGIN"
DisplayEnvEnd "OPENMP DISPLAY ENVIRONMENT END"
Device "[device]"
Host "[host]"
Tile "tile"
@@ -114,7 +115,7 @@ Info "OMP: Info #%1$d: %2$s\n"
Warning "OMP: Warning #%1$d: %2$s\n"
Fatal "OMP: Error #%1$d: %2$s\n"
SysErr "OMP: System error #%1$d: %2$s\n"
Hint "OMP: Hint: %2$s\n"
Hint "OMP: Hint %1$s\n"
Pragma "%1$s pragma (at %2$s:%3$s():%4$s)"
# %1 is pragma name (like "parallel" or "master",
@@ -325,6 +326,13 @@ StgIgnored "%1$s: ignored because %2$s has been defined"
# %1, -- name of ignored variable, %2 -- name of variable with higher priority.
OBSOLETE "%1$s: overrides %3$s specified before"
# %1, %2 -- name and value of the overriding variable, %3 -- name of overriden variable.
AffTilesNoHWLOC "%1$s: Tiles are only supported if KMP_TOPOLOGY_METHOD=hwloc, using granularity=package instead"
AffTilesNoTiles "%1$s: Tiles requested but were not detected on this HW, using granularity=package instead"
TopologyExtraTile "%1$s: %2$d packages x %3$d tiles/pkg x %4$d cores/tile x %5$d threads/core (%6$d total cores)"
TopologyExtraNode "%1$s: %2$d packages x %3$d nodes/pkg x %4$d cores/node x %5$d threads/core (%6$d total cores)"
TopologyExtraNoTi "%1$s: %2$d packages x %3$d nodes/pkg x %4$d tiles/node x %5$d cores/tile x %6$d threads/core (%7$d total cores)"
OmptOutdatedWorkshare "OMPT: Cannot determine workshare type; using the default (loop) instead. "
"This issue is fixed in an up-to-date compiler."
# --- OpenMP errors detected at runtime ---
#
@@ -388,15 +396,15 @@ OBSOLETE "%1$s: granularity=core will be used."
EnvLockWarn "%1$s must be set prior to first OMP lock call or critical section; ignored."
FutexNotSupported "futex system call not supported; %1$s=%2$s ignored."
AffGranUsing "%1$s: granularity=%2$s will be used."
AffHWSubsetInvalid "%1$s: invalid value \"%2$s\", valid format is \"Ns[@N],Nc[@N],Nt "
"(nSockets@offset, nCores@offset, nTthreads per core)\"."
AffHWSubsetInvalid "%1$s: invalid value \"%2$s\", valid format is \"N<item>[@N][,...][,Nt] "
"(<item> can be S, N, L2, C, T for Socket, NUMA Node, L2 Cache, Core, Thread)\"."
AffHWSubsetUnsupported "KMP_HW_SUBSET ignored: unsupported architecture."
AffHWSubsetManyCores "KMP_HW_SUBSET ignored: too many cores requested."
SyntaxErrorUsing "%1$s: syntax error, using %2$s."
AdaptiveNotSupported "%1$s: Adaptive locks are not supported; using queuing."
EnvSyntaxError "%1$s: Invalid symbols found. Check the value \"%2$s\"."
EnvSpacesNotAllowed "%1$s: Spaces between digits are not allowed \"%2$s\"."
BoundToOSProcSet "%1$s: pid %2$d thread %3$d bound to OS proc set %4$s"
BoundToOSProcSet "%1$s: pid %2$d tid %3$d thread %4$d bound to OS proc set %5$s"
CnsLoopIncrIllegal "%1$s error: parallel loop increment and condition are inconsistent."
NoGompCancellation "libgomp cancellation is not currently supported."
AffHWSubsetNonUniform "KMP_HW_SUBSET ignored: non-uniform topology."
@@ -410,6 +418,11 @@ AffIgnoringHwloc "%1$s: Ignoring hwloc mechanism."
AffHwlocErrorOccurred "%1$s: Hwloc failed in %2$s. Relying on internal affinity mechanisms."
EnvSerialWarn "%1$s must be set prior to OpenMP runtime library initialization; ignored."
EnvVarDeprecated "%1$s variable deprecated, please use %2$s instead."
RedMethodNotSupported "KMP_FORCE_REDUCTION: %1$s method is not supported; using critical."
AffHWSubsetNoHWLOC "KMP_HW_SUBSET ignored: unsupported item requested for non-HWLOC topology method (KMP_TOPOLOGY_METHOD)"
AffHWSubsetManyNodes "KMP_HW_SUBSET ignored: too many NUMA Nodes requested."
AffHWSubsetManyTiles "KMP_HW_SUBSET ignored: too many L2 Caches requested."
AffHWSubsetManyProcs "KMP_HW_SUBSET ignored: too many Procs requested."
# --------------------------------------------------------------------------------------------------
@@ -424,11 +437,11 @@ SubmitBugReport "Please submit a bug report with this message, comp
"compiler and operating system versions. Faster response will be "
"obtained by including all program sources. For information on "
"submitting this issue, please see "
"http://www.intel.com/software/products/support/."
"https://bugs.llvm.org/."
OBSOLETE "Check NLSPATH environment variable, its value is \"%1$s\"."
ChangeStackLimit "Please try changing the shell stack limit or adjusting the "
"OMP_STACKSIZE environment variable."
Unset_ALL_THREADS "Consider unsetting KMP_ALL_THREADS and OMP_THREAD_LIMIT (if either is set)."
Unset_ALL_THREADS "Consider unsetting KMP_DEVICE_THREAD_LIMIT (KMP_ALL_THREADS), KMP_TEAMS_THREAD_LIMIT, and OMP_THREAD_LIMIT (if any are set)."
Set_ALL_THREADPRIVATE "Consider setting KMP_ALL_THREADPRIVATE to a value larger than %1$d."
PossibleSystemLimitOnThreads "This could also be due to a system-related limit on the number of threads."
DuplicateLibrary "This means that multiple copies of the OpenMP runtime have been "
@@ -440,7 +453,7 @@ DuplicateLibrary "This means that multiple copies of the OpenMP runt
"you can set the environment variable KMP_DUPLICATE_LIB_OK=TRUE to allow "
"the program to continue to execute, but that may cause crashes or "
"silently produce incorrect results. "
"For more information, please see http://www.intel.com/software/products/support/."
"For more information, please see http://openmp.llvm.org/"
NameComesFrom_CPUINFO_FILE "This name is specified in environment variable KMP_CPUINFO_FILE."
NotEnoughMemory "Seems application required too much memory."
ValidBoolValues "Use \"0\", \"FALSE\". \".F.\", \"off\", \"no\" as false values, "
-488
View File
@@ -1,488 +0,0 @@
/*
* include/30/ompt.h.var
*/
#ifndef __OMPT__
#define __OMPT__
/*****************************************************************************
* system include files
*****************************************************************************/
#include <stdint.h>
/*****************************************************************************
* iteration macros
*****************************************************************************/
#define FOREACH_OMPT_INQUIRY_FN(macro) \
macro (ompt_enumerate_state) \
\
macro (ompt_set_callback) \
macro (ompt_get_callback) \
\
macro (ompt_get_idle_frame) \
macro (ompt_get_task_frame) \
\
macro (ompt_get_state) \
\
macro (ompt_get_parallel_id) \
macro (ompt_get_parallel_team_size) \
macro (ompt_get_task_id) \
macro (ompt_get_thread_id)
#define FOREACH_OMPT_PLACEHOLDER_FN(macro) \
macro (ompt_idle) \
macro (ompt_overhead) \
macro (ompt_barrier_wait) \
macro (ompt_task_wait) \
macro (ompt_mutex_wait)
#define FOREACH_OMPT_STATE(macro) \
\
/* first */ \
macro (ompt_state_first, 0x71) /* initial enumeration state */ \
\
/* work states (0..15) */ \
macro (ompt_state_work_serial, 0x00) /* working outside parallel */ \
macro (ompt_state_work_parallel, 0x01) /* working within parallel */ \
macro (ompt_state_work_reduction, 0x02) /* performing a reduction */ \
\
/* idle (16..31) */ \
macro (ompt_state_idle, 0x10) /* waiting for work */ \
\
/* overhead states (32..63) */ \
macro (ompt_state_overhead, 0x20) /* overhead excluding wait states */ \
\
/* barrier wait states (64..79) */ \
macro (ompt_state_wait_barrier, 0x40) /* waiting at a barrier */ \
macro (ompt_state_wait_barrier_implicit, 0x41) /* implicit barrier */ \
macro (ompt_state_wait_barrier_explicit, 0x42) /* explicit barrier */ \
\
/* task wait states (80..95) */ \
macro (ompt_state_wait_taskwait, 0x50) /* waiting at a taskwait */ \
macro (ompt_state_wait_taskgroup, 0x51) /* waiting at a taskgroup */ \
\
/* mutex wait states (96..111) */ \
macro (ompt_state_wait_lock, 0x60) /* waiting for lock */ \
macro (ompt_state_wait_nest_lock, 0x61) /* waiting for nest lock */ \
macro (ompt_state_wait_critical, 0x62) /* waiting for critical */ \
macro (ompt_state_wait_atomic, 0x63) /* waiting for atomic */ \
macro (ompt_state_wait_ordered, 0x64) /* waiting for ordered */ \
macro (ompt_state_wait_single, 0x6F) /* waiting for single region (non-standard!) */ \
\
/* misc (112..127) */ \
macro (ompt_state_undefined, 0x70) /* undefined thread state */
#define FOREACH_OMPT_EVENT(macro) \
\
/*--- Mandatory Events ---*/ \
macro (ompt_event_parallel_begin, ompt_new_parallel_callback_t, 1) /* parallel begin */ \
macro (ompt_event_parallel_end, ompt_end_parallel_callback_t, 2) /* parallel end */ \
\
macro (ompt_event_task_begin, ompt_new_task_callback_t, 3) /* task begin */ \
macro (ompt_event_task_end, ompt_task_callback_t, 4) /* task destroy */ \
\
macro (ompt_event_thread_begin, ompt_thread_type_callback_t, 5) /* thread begin */ \
macro (ompt_event_thread_end, ompt_thread_type_callback_t, 6) /* thread end */ \
\
macro (ompt_event_control, ompt_control_callback_t, 7) /* support control calls */ \
\
macro (ompt_event_runtime_shutdown, ompt_callback_t, 8) /* runtime shutdown */ \
\
/*--- Optional Events (blame shifting, ompt_event_unimplemented) ---*/ \
macro (ompt_event_idle_begin, ompt_thread_callback_t, 9) /* begin idle state */ \
macro (ompt_event_idle_end, ompt_thread_callback_t, 10) /* end idle state */ \
\
macro (ompt_event_wait_barrier_begin, ompt_parallel_callback_t, 11) /* begin wait at barrier */ \
macro (ompt_event_wait_barrier_end, ompt_parallel_callback_t, 12) /* end wait at barrier */ \
\
macro (ompt_event_wait_taskwait_begin, ompt_parallel_callback_t, 13) /* begin wait at taskwait */ \
macro (ompt_event_wait_taskwait_end, ompt_parallel_callback_t, 14) /* end wait at taskwait */ \
\
macro (ompt_event_wait_taskgroup_begin, ompt_parallel_callback_t, 15) /* begin wait at taskgroup */\
macro (ompt_event_wait_taskgroup_end, ompt_parallel_callback_t, 16) /* end wait at taskgroup */ \
\
macro (ompt_event_release_lock, ompt_wait_callback_t, 17) /* lock release */ \
macro (ompt_event_release_nest_lock_last, ompt_wait_callback_t, 18) /* last nest lock release */ \
macro (ompt_event_release_critical, ompt_wait_callback_t, 19) /* critical release */ \
\
macro (ompt_event_release_atomic, ompt_wait_callback_t, 20) /* atomic release */ \
\
macro (ompt_event_release_ordered, ompt_wait_callback_t, 21) /* ordered release */ \
\
/*--- Optional Events (synchronous events, ompt_event_unimplemented) --- */ \
macro (ompt_event_implicit_task_begin, ompt_parallel_callback_t, 22) /* implicit task begin */ \
macro (ompt_event_implicit_task_end, ompt_parallel_callback_t, 23) /* implicit task end */ \
\
macro (ompt_event_initial_task_begin, ompt_parallel_callback_t, 24) /* initial task begin */ \
macro (ompt_event_initial_task_end, ompt_parallel_callback_t, 25) /* initial task end */ \
\
macro (ompt_event_task_switch, ompt_task_pair_callback_t, 26) /* task switch */ \
\
macro (ompt_event_loop_begin, ompt_new_workshare_callback_t, 27) /* task at loop begin */ \
macro (ompt_event_loop_end, ompt_parallel_callback_t, 28) /* task at loop end */ \
\
macro (ompt_event_sections_begin, ompt_new_workshare_callback_t, 29) /* task at sections begin */\
macro (ompt_event_sections_end, ompt_parallel_callback_t, 30) /* task at sections end */ \
\
macro (ompt_event_single_in_block_begin, ompt_new_workshare_callback_t, 31) /* task at single begin*/ \
macro (ompt_event_single_in_block_end, ompt_parallel_callback_t, 32) /* task at single end */ \
\
macro (ompt_event_single_others_begin, ompt_parallel_callback_t, 33) /* task at single begin */ \
macro (ompt_event_single_others_end, ompt_parallel_callback_t, 34) /* task at single end */ \
\
macro (ompt_event_workshare_begin, ompt_new_workshare_callback_t, 35) /* task at workshare begin */\
macro (ompt_event_workshare_end, ompt_parallel_callback_t, 36) /* task at workshare end */ \
\
macro (ompt_event_master_begin, ompt_parallel_callback_t, 37) /* task at master begin */ \
macro (ompt_event_master_end, ompt_parallel_callback_t, 38) /* task at master end */ \
\
macro (ompt_event_barrier_begin, ompt_parallel_callback_t, 39) /* task at barrier begin */ \
macro (ompt_event_barrier_end, ompt_parallel_callback_t, 40) /* task at barrier end */ \
\
macro (ompt_event_taskwait_begin, ompt_parallel_callback_t, 41) /* task at taskwait begin */ \
macro (ompt_event_taskwait_end, ompt_parallel_callback_t, 42) /* task at task wait end */ \
\
macro (ompt_event_taskgroup_begin, ompt_parallel_callback_t, 43) /* task at taskgroup begin */\
macro (ompt_event_taskgroup_end, ompt_parallel_callback_t, 44) /* task at taskgroup end */ \
\
macro (ompt_event_release_nest_lock_prev, ompt_wait_callback_t, 45) /* prev nest lock release */ \
\
macro (ompt_event_wait_lock, ompt_wait_callback_t, 46) /* lock wait */ \
macro (ompt_event_wait_nest_lock, ompt_wait_callback_t, 47) /* nest lock wait */ \
macro (ompt_event_wait_critical, ompt_wait_callback_t, 48) /* critical wait */ \
macro (ompt_event_wait_atomic, ompt_wait_callback_t, 49) /* atomic wait */ \
macro (ompt_event_wait_ordered, ompt_wait_callback_t, 50) /* ordered wait */ \
\
macro (ompt_event_acquired_lock, ompt_wait_callback_t, 51) /* lock acquired */ \
macro (ompt_event_acquired_nest_lock_first, ompt_wait_callback_t, 52) /* 1st nest lock acquired */ \
macro (ompt_event_acquired_nest_lock_next, ompt_wait_callback_t, 53) /* next nest lock acquired*/ \
macro (ompt_event_acquired_critical, ompt_wait_callback_t, 54) /* critical acquired */ \
macro (ompt_event_acquired_atomic, ompt_wait_callback_t, 55) /* atomic acquired */ \
macro (ompt_event_acquired_ordered, ompt_wait_callback_t, 56) /* ordered acquired */ \
\
macro (ompt_event_init_lock, ompt_wait_callback_t, 57) /* lock init */ \
macro (ompt_event_init_nest_lock, ompt_wait_callback_t, 58) /* nest lock init */ \
\
macro (ompt_event_destroy_lock, ompt_wait_callback_t, 59) /* lock destruction */ \
macro (ompt_event_destroy_nest_lock, ompt_wait_callback_t, 60) /* nest lock destruction */ \
\
macro (ompt_event_flush, ompt_callback_t, 61) /* after executing flush */
/*****************************************************************************
* data types
*****************************************************************************/
/*---------------------
* identifiers
*---------------------*/
typedef uint64_t ompt_thread_id_t;
#define ompt_thread_id_none ((ompt_thread_id_t) 0) /* non-standard */
typedef uint64_t ompt_task_id_t;
#define ompt_task_id_none ((ompt_task_id_t) 0) /* non-standard */
typedef uint64_t ompt_parallel_id_t;
#define ompt_parallel_id_none ((ompt_parallel_id_t) 0) /* non-standard */
typedef uint64_t ompt_wait_id_t;
#define ompt_wait_id_none ((ompt_wait_id_t) 0) /* non-standard */
/*---------------------
* ompt_frame_t
*---------------------*/
typedef struct ompt_frame_s {
void *exit_runtime_frame; /* next frame is user code */
void *reenter_runtime_frame; /* previous frame is user code */
} ompt_frame_t;
/*****************************************************************************
* enumerations for thread states and runtime events
*****************************************************************************/
/*---------------------
* runtime states
*---------------------*/
typedef enum {
#define ompt_state_macro(state, code) state = code,
FOREACH_OMPT_STATE(ompt_state_macro)
#undef ompt_state_macro
} ompt_state_t;
/*---------------------
* runtime events
*---------------------*/
typedef enum {
#define ompt_event_macro(event, callback, eventid) event = eventid,
FOREACH_OMPT_EVENT(ompt_event_macro)
#undef ompt_event_macro
} ompt_event_t;
/*---------------------
* set callback results
*---------------------*/
typedef enum {
ompt_set_result_registration_error = 0,
ompt_set_result_event_may_occur_no_callback = 1,
ompt_set_result_event_never_occurs = 2,
ompt_set_result_event_may_occur_callback_some = 3,
ompt_set_result_event_may_occur_callback_always = 4,
} ompt_set_result_t;
/*****************************************************************************
* callback signatures
*****************************************************************************/
/* initialization */
typedef void (*ompt_interface_fn_t)(void);
typedef ompt_interface_fn_t (*ompt_function_lookup_t)(
const char * /* entry point to look up */
);
/* threads */
typedef void (*ompt_thread_callback_t) (
ompt_thread_id_t thread_id /* ID of thread */
);
typedef enum {
ompt_thread_initial = 1, // start the enumeration at 1
ompt_thread_worker = 2,
ompt_thread_other = 3
} ompt_thread_type_t;
typedef enum {
ompt_invoker_program = 0, /* program invokes master task */
ompt_invoker_runtime = 1 /* runtime invokes master task */
} ompt_invoker_t;
typedef void (*ompt_thread_type_callback_t) (
ompt_thread_type_t thread_type, /* type of thread */
ompt_thread_id_t thread_id /* ID of thread */
);
typedef void (*ompt_wait_callback_t) (
ompt_wait_id_t wait_id /* wait id */
);
/* parallel and workshares */
typedef void (*ompt_parallel_callback_t) (
ompt_parallel_id_t parallel_id, /* id of parallel region */
ompt_task_id_t task_id /* id of task */
);
typedef void (*ompt_new_workshare_callback_t) (
ompt_parallel_id_t parallel_id, /* id of parallel region */
ompt_task_id_t parent_task_id, /* id of parent task */
void *workshare_function /* pointer to outlined function */
);
typedef void (*ompt_new_parallel_callback_t) (
ompt_task_id_t parent_task_id, /* id of parent task */
ompt_frame_t *parent_task_frame, /* frame data of parent task */
ompt_parallel_id_t parallel_id, /* id of parallel region */
uint32_t requested_team_size, /* number of threads in team */
void *parallel_function, /* pointer to outlined function */
ompt_invoker_t invoker /* who invokes master task? */
);
typedef void (*ompt_end_parallel_callback_t) (
ompt_parallel_id_t parallel_id, /* id of parallel region */
ompt_task_id_t task_id, /* id of task */
ompt_invoker_t invoker /* who invokes master task? */
);
/* tasks */
typedef void (*ompt_task_callback_t) (
ompt_task_id_t task_id /* id of task */
);
typedef void (*ompt_task_pair_callback_t) (
ompt_task_id_t first_task_id,
ompt_task_id_t second_task_id
);
typedef void (*ompt_new_task_callback_t) (
ompt_task_id_t parent_task_id, /* id of parent task */
ompt_frame_t *parent_task_frame, /* frame data for parent task */
ompt_task_id_t new_task_id, /* id of created task */
void *task_function /* pointer to outlined function */
);
/* program */
typedef void (*ompt_control_callback_t) (
uint64_t command, /* command of control call */
uint64_t modifier /* modifier of control call */
);
typedef void (*ompt_callback_t)(void);
/****************************************************************************
* ompt API
***************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
#define OMPT_API_FNTYPE(fn) fn##_t
#define OMPT_API_FUNCTION(return_type, fn, args) \
typedef return_type (*OMPT_API_FNTYPE(fn)) args
/****************************************************************************
* INQUIRY FUNCTIONS
***************************************************************************/
/* state */
OMPT_API_FUNCTION(ompt_state_t, ompt_get_state, (
ompt_wait_id_t *ompt_wait_id
));
/* thread */
OMPT_API_FUNCTION(ompt_thread_id_t, ompt_get_thread_id, (void));
OMPT_API_FUNCTION(void *, ompt_get_idle_frame, (void));
/* parallel region */
OMPT_API_FUNCTION(ompt_parallel_id_t, ompt_get_parallel_id, (
int ancestor_level
));
OMPT_API_FUNCTION(int, ompt_get_parallel_team_size, (
int ancestor_level
));
/* task */
OMPT_API_FUNCTION(ompt_task_id_t, ompt_get_task_id, (
int depth
));
OMPT_API_FUNCTION(ompt_frame_t *, ompt_get_task_frame, (
int depth
));
/****************************************************************************
* PLACEHOLDERS FOR PERFORMANCE REPORTING
***************************************************************************/
/* idle */
OMPT_API_FUNCTION(void, ompt_idle, (
void
));
/* overhead */
OMPT_API_FUNCTION(void, ompt_overhead, (
void
));
/* barrier wait */
OMPT_API_FUNCTION(void, ompt_barrier_wait, (
void
));
/* task wait */
OMPT_API_FUNCTION(void, ompt_task_wait, (
void
));
/* mutex wait */
OMPT_API_FUNCTION(void, ompt_mutex_wait, (
void
));
/****************************************************************************
* INITIALIZATION FUNCTIONS
***************************************************************************/
OMPT_API_FUNCTION(void, ompt_initialize, (
ompt_function_lookup_t ompt_fn_lookup,
const char *runtime_version,
unsigned int ompt_version
));
/* initialization interface to be defined by tool */
ompt_initialize_t ompt_tool(void);
typedef enum opt_init_mode_e {
ompt_init_mode_never = 0,
ompt_init_mode_false = 1,
ompt_init_mode_true = 2,
ompt_init_mode_always = 3
} ompt_init_mode_t;
OMPT_API_FUNCTION(int, ompt_set_callback, (
ompt_event_t event,
ompt_callback_t callback
));
typedef enum ompt_set_callback_rc_e { /* non-standard */
ompt_set_callback_error = 0,
ompt_has_event_no_callback = 1,
ompt_no_event_no_callback = 2,
ompt_has_event_may_callback = 3,
ompt_has_event_must_callback = 4,
} ompt_set_callback_rc_t;
OMPT_API_FUNCTION(int, ompt_get_callback, (
ompt_event_t event,
ompt_callback_t *callback
));
/****************************************************************************
* MISCELLANEOUS FUNCTIONS
***************************************************************************/
/* control */
// FIXME: remove workaround for clang
#if !defined(__clang__) && defined(_OPENMP) && (_OPENMP >= 201307)
#pragma omp declare target
#endif
void ompt_control(
uint64_t command,
uint64_t modifier
);
#if !defined(__clang__) && defined(_OPENMP) && (_OPENMP >= 201307)
#pragma omp end declare target
#endif
/* state enumeration */
OMPT_API_FUNCTION(int, ompt_enumerate_state, (
int current_state,
int *next_state,
const char **next_state_name
));
#ifdef __cplusplus
};
#endif
#endif
+37 -32
View File
@@ -66,19 +66,19 @@
! *** omp_* entry points
! ***
subroutine omp_set_num_threads(nthreads)
subroutine omp_set_num_threads(num_threads)
use omp_lib_kinds
integer (kind=omp_integer_kind) nthreads
integer (kind=omp_integer_kind) num_threads
end subroutine omp_set_num_threads
subroutine omp_set_dynamic(enable)
subroutine omp_set_dynamic(dynamic_threads)
use omp_lib_kinds
logical (kind=omp_logical_kind) enable
logical (kind=omp_logical_kind) dynamic_threads
end subroutine omp_set_dynamic
subroutine omp_set_nested(enable)
subroutine omp_set_nested(nested)
use omp_lib_kinds
logical (kind=omp_logical_kind) enable
logical (kind=omp_logical_kind) nested
end subroutine omp_set_nested
function omp_get_num_threads()
@@ -106,6 +106,11 @@
logical (kind=omp_logical_kind) omp_in_parallel
end function omp_in_parallel
function omp_in_final()
use omp_lib_kinds
logical (kind=omp_logical_kind) omp_in_final
end function omp_in_final
function omp_get_dynamic()
use omp_lib_kinds
logical (kind=omp_logical_kind) omp_get_dynamic
@@ -153,16 +158,16 @@
integer (kind=omp_integer_kind) omp_get_team_size
end function omp_get_team_size
subroutine omp_set_schedule(kind, modifier)
subroutine omp_set_schedule(kind, chunk_size)
use omp_lib_kinds
integer (kind=omp_sched_kind) kind
integer (kind=omp_integer_kind) modifier
integer (kind=omp_integer_kind) chunk_size
end subroutine omp_set_schedule
subroutine omp_get_schedule(kind, modifier)
subroutine omp_get_schedule(kind, chunk_size)
use omp_lib_kinds
integer (kind=omp_sched_kind) kind
integer (kind=omp_integer_kind) modifier
integer (kind=omp_integer_kind) chunk_size
end subroutine omp_get_schedule
function omp_get_proc_bind()
@@ -183,9 +188,9 @@
integer (kind=omp_integer_kind) omp_get_default_device
end function omp_get_default_device
subroutine omp_set_default_device(dflt_device)
subroutine omp_set_default_device(device_num)
use omp_lib_kinds
integer (kind=omp_integer_kind) dflt_device
integer (kind=omp_integer_kind) device_num
end subroutine omp_set_default_device
function omp_get_num_devices()
@@ -213,86 +218,86 @@
logical (kind=omp_logical_kind) omp_is_initial_device
end function omp_is_initial_device
subroutine omp_init_lock(lockvar)
subroutine omp_init_lock(svar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_init_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_lock_kind) lockvar
integer (kind=omp_lock_kind) svar
end subroutine omp_init_lock
subroutine omp_destroy_lock(lockvar)
subroutine omp_destroy_lock(svar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_destroy_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_lock_kind) lockvar
integer (kind=omp_lock_kind) svar
end subroutine omp_destroy_lock
subroutine omp_set_lock(lockvar)
subroutine omp_set_lock(svar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_set_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_lock_kind) lockvar
integer (kind=omp_lock_kind) svar
end subroutine omp_set_lock
subroutine omp_unset_lock(lockvar)
subroutine omp_unset_lock(svar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_unset_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_lock_kind) lockvar
integer (kind=omp_lock_kind) svar
end subroutine omp_unset_lock
function omp_test_lock(lockvar)
function omp_test_lock(svar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_test_lock
!DIR$ ENDIF
use omp_lib_kinds
logical (kind=omp_logical_kind) omp_test_lock
integer (kind=omp_lock_kind) lockvar
integer (kind=omp_lock_kind) svar
end function omp_test_lock
subroutine omp_init_nest_lock(lockvar)
subroutine omp_init_nest_lock(nvar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_init_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) lockvar
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_init_nest_lock
subroutine omp_destroy_nest_lock(lockvar)
subroutine omp_destroy_nest_lock(nvar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_destroy_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) lockvar
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_destroy_nest_lock
subroutine omp_set_nest_lock(lockvar)
subroutine omp_set_nest_lock(nvar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_set_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) lockvar
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_set_nest_lock
subroutine omp_unset_nest_lock(lockvar)
subroutine omp_unset_nest_lock(nvar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_unset_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) lockvar
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_unset_nest_lock
function omp_test_nest_lock(lockvar)
function omp_test_nest_lock(nvar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_test_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_test_nest_lock
integer (kind=omp_nest_lock_kind) lockvar
integer (kind=omp_nest_lock_kind) nvar
end function omp_test_nest_lock
! ***
+32 -32
View File
@@ -64,19 +64,19 @@
! *** omp_* entry points
! ***
subroutine omp_set_num_threads(nthreads) bind(c)
subroutine omp_set_num_threads(num_threads) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind), value :: nthreads
integer (kind=omp_integer_kind), value :: num_threads
end subroutine omp_set_num_threads
subroutine omp_set_dynamic(enable) bind(c)
subroutine omp_set_dynamic(dynamic_threads) bind(c)
use omp_lib_kinds
logical (kind=omp_logical_kind), value :: enable
logical (kind=omp_logical_kind), value :: dynamic_threads
end subroutine omp_set_dynamic
subroutine omp_set_nested(enable) bind(c)
subroutine omp_set_nested(nested) bind(c)
use omp_lib_kinds
logical (kind=omp_logical_kind), value :: enable
logical (kind=omp_logical_kind), value :: nested
end subroutine omp_set_nested
function omp_get_num_threads() bind(c)
@@ -156,16 +156,16 @@
integer (kind=omp_integer_kind), value :: level
end function omp_get_team_size
subroutine omp_set_schedule(kind, modifier) bind(c)
subroutine omp_set_schedule(kind, chunk_size) bind(c)
use omp_lib_kinds
integer (kind=omp_sched_kind), value :: kind
integer (kind=omp_integer_kind), value :: modifier
integer (kind=omp_integer_kind), value :: chunk_size
end subroutine omp_set_schedule
subroutine omp_get_schedule(kind, modifier) bind(c)
subroutine omp_get_schedule(kind, chunk_size) bind(c)
use omp_lib_kinds
integer (kind=omp_sched_kind) kind
integer (kind=omp_integer_kind) modifier
integer (kind=omp_integer_kind) chunk_size
end subroutine omp_get_schedule
function omp_get_proc_bind() bind(c)
@@ -188,9 +188,9 @@
integer (kind=omp_integer_kind) omp_get_default_device
end function omp_get_default_device
subroutine omp_set_default_device(dflt_device) bind(c)
subroutine omp_set_default_device(device_num) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind), value :: dflt_device
integer (kind=omp_integer_kind), value :: device_num
end subroutine omp_set_default_device
function omp_get_num_devices() bind(c)
@@ -218,86 +218,86 @@
logical (kind=omp_logical_kind) omp_is_initial_device
end function omp_is_initial_device
subroutine omp_init_lock(lockvar) bind(c)
subroutine omp_init_lock(svar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_init_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_lock_kind) lockvar
integer (kind=omp_lock_kind) svar
end subroutine omp_init_lock
subroutine omp_destroy_lock(lockvar) bind(c)
subroutine omp_destroy_lock(svar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_destroy_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_lock_kind) lockvar
integer (kind=omp_lock_kind) svar
end subroutine omp_destroy_lock
subroutine omp_set_lock(lockvar) bind(c)
subroutine omp_set_lock(svar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_set_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_lock_kind) lockvar
integer (kind=omp_lock_kind) svar
end subroutine omp_set_lock
subroutine omp_unset_lock(lockvar) bind(c)
subroutine omp_unset_lock(svar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_unset_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_lock_kind) lockvar
integer (kind=omp_lock_kind) svar
end subroutine omp_unset_lock
function omp_test_lock(lockvar) bind(c)
function omp_test_lock(svar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_test_lock
!DIR$ ENDIF
use omp_lib_kinds
logical (kind=omp_logical_kind) omp_test_lock
integer (kind=omp_lock_kind) lockvar
integer (kind=omp_lock_kind) svar
end function omp_test_lock
subroutine omp_init_nest_lock(lockvar) bind(c)
subroutine omp_init_nest_lock(nvar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_init_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) lockvar
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_init_nest_lock
subroutine omp_destroy_nest_lock(lockvar) bind(c)
subroutine omp_destroy_nest_lock(nvar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_destroy_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) lockvar
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_destroy_nest_lock
subroutine omp_set_nest_lock(lockvar) bind(c)
subroutine omp_set_nest_lock(nvar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_set_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) lockvar
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_set_nest_lock
subroutine omp_unset_nest_lock(lockvar) bind(c)
subroutine omp_unset_nest_lock(nvar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_unset_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) lockvar
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_unset_nest_lock
function omp_test_nest_lock(lockvar) bind(c)
function omp_test_nest_lock(nvar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_test_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_test_nest_lock
integer (kind=omp_nest_lock_kind) lockvar
integer (kind=omp_nest_lock_kind) nvar
end function omp_test_nest_lock
! ***
+32 -32
View File
@@ -53,19 +53,19 @@
! *** omp_* entry points
! ***
subroutine omp_set_num_threads(nthreads) bind(c)
subroutine omp_set_num_threads(num_threads) bind(c)
import
integer (kind=omp_integer_kind), value :: nthreads
integer (kind=omp_integer_kind), value :: num_threads
end subroutine omp_set_num_threads
subroutine omp_set_dynamic(enable) bind(c)
subroutine omp_set_dynamic(dynamic_threads) bind(c)
import
logical (kind=omp_logical_kind), value :: enable
logical (kind=omp_logical_kind), value :: dynamic_threads
end subroutine omp_set_dynamic
subroutine omp_set_nested(enable) bind(c)
subroutine omp_set_nested(nested) bind(c)
import
logical (kind=omp_logical_kind), value :: enable
logical (kind=omp_logical_kind), value :: nested
end subroutine omp_set_nested
function omp_get_num_threads() bind(c)
@@ -145,16 +145,16 @@
integer (kind=omp_integer_kind), value :: level
end function omp_get_team_size
subroutine omp_set_schedule(kind, modifier) bind(c)
subroutine omp_set_schedule(kind, chunk_size) bind(c)
import
integer (kind=omp_sched_kind), value :: kind
integer (kind=omp_integer_kind), value :: modifier
integer (kind=omp_integer_kind), value :: chunk_size
end subroutine omp_set_schedule
subroutine omp_get_schedule(kind, modifier) bind(c)
subroutine omp_get_schedule(kind, chunk_size) bind(c)
import
integer (kind=omp_sched_kind) kind
integer (kind=omp_integer_kind) modifier
integer (kind=omp_integer_kind) chunk_size
end subroutine omp_get_schedule
function omp_get_proc_bind() bind(c)
@@ -175,9 +175,9 @@
integer (kind=omp_integer_kind) omp_get_default_device
end function omp_get_default_device
subroutine omp_set_default_device(dflt_device) bind(c)
subroutine omp_set_default_device(device_num) bind(c)
import
integer (kind=omp_integer_kind), value :: dflt_device
integer (kind=omp_integer_kind), value :: device_num
end subroutine omp_set_default_device
function omp_get_num_devices() bind(c)
@@ -200,86 +200,86 @@
logical (kind=omp_logical_kind) omp_is_initial_device
end function omp_is_initial_device
subroutine omp_init_lock(lockvar) bind(c)
subroutine omp_init_lock(svar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_init_lock
!DIR$ ENDIF
import
integer (kind=omp_lock_kind) lockvar
integer (kind=omp_lock_kind) svar
end subroutine omp_init_lock
subroutine omp_destroy_lock(lockvar) bind(c)
subroutine omp_destroy_lock(svar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_destroy_lock
!DIR$ ENDIF
import
integer (kind=omp_lock_kind) lockvar
integer (kind=omp_lock_kind) svar
end subroutine omp_destroy_lock
subroutine omp_set_lock(lockvar) bind(c)
subroutine omp_set_lock(svar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_set_lock
!DIR$ ENDIF
import
integer (kind=omp_lock_kind) lockvar
integer (kind=omp_lock_kind) svar
end subroutine omp_set_lock
subroutine omp_unset_lock(lockvar) bind(c)
subroutine omp_unset_lock(svar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_unset_lock
!DIR$ ENDIF
import
integer (kind=omp_lock_kind) lockvar
integer (kind=omp_lock_kind) svar
end subroutine omp_unset_lock
function omp_test_lock(lockvar) bind(c)
function omp_test_lock(svar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_test_lock
!DIR$ ENDIF
import
logical (kind=omp_logical_kind) omp_test_lock
integer (kind=omp_lock_kind) lockvar
integer (kind=omp_lock_kind) svar
end function omp_test_lock
subroutine omp_init_nest_lock(lockvar) bind(c)
subroutine omp_init_nest_lock(nvar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_init_nest_lock
!DIR$ ENDIF
import
integer (kind=omp_nest_lock_kind) lockvar
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_init_nest_lock
subroutine omp_destroy_nest_lock(lockvar) bind(c)
subroutine omp_destroy_nest_lock(nvar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_destroy_nest_lock
!DIR$ ENDIF
import
integer (kind=omp_nest_lock_kind) lockvar
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_destroy_nest_lock
subroutine omp_set_nest_lock(lockvar) bind(c)
subroutine omp_set_nest_lock(nvar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_set_nest_lock
!DIR$ ENDIF
import
integer (kind=omp_nest_lock_kind) lockvar
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_set_nest_lock
subroutine omp_unset_nest_lock(lockvar) bind(c)
subroutine omp_unset_nest_lock(nvar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_unset_nest_lock
!DIR$ ENDIF
import
integer (kind=omp_nest_lock_kind) lockvar
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_unset_nest_lock
function omp_test_nest_lock(lockvar) bind(c)
function omp_test_nest_lock(nvar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_test_nest_lock
!DIR$ ENDIF
import
integer (kind=omp_integer_kind) omp_test_nest_lock
integer (kind=omp_nest_lock_kind) lockvar
integer (kind=omp_nest_lock_kind) nvar
end function omp_test_nest_lock
! ***
-515
View File
@@ -1,515 +0,0 @@
/*
* include/40/ompt.h.var
*/
#ifndef __OMPT__
#define __OMPT__
/*****************************************************************************
* system include files
*****************************************************************************/
#include <stdint.h>
/*****************************************************************************
* iteration macros
*****************************************************************************/
#define FOREACH_OMPT_INQUIRY_FN(macro) \
macro (ompt_enumerate_state) \
\
macro (ompt_set_callback) \
macro (ompt_get_callback) \
\
macro (ompt_get_idle_frame) \
macro (ompt_get_task_frame) \
\
macro (ompt_get_state) \
\
macro (ompt_get_parallel_id) \
macro (ompt_get_parallel_team_size) \
macro (ompt_get_task_id) \
macro (ompt_get_thread_id)
#define FOREACH_OMPT_PLACEHOLDER_FN(macro) \
macro (ompt_idle) \
macro (ompt_overhead) \
macro (ompt_barrier_wait) \
macro (ompt_task_wait) \
macro (ompt_mutex_wait)
#define FOREACH_OMPT_STATE(macro) \
\
/* first */ \
macro (ompt_state_first, 0x71) /* initial enumeration state */ \
\
/* work states (0..15) */ \
macro (ompt_state_work_serial, 0x00) /* working outside parallel */ \
macro (ompt_state_work_parallel, 0x01) /* working within parallel */ \
macro (ompt_state_work_reduction, 0x02) /* performing a reduction */ \
\
/* idle (16..31) */ \
macro (ompt_state_idle, 0x10) /* waiting for work */ \
\
/* overhead states (32..63) */ \
macro (ompt_state_overhead, 0x20) /* overhead excluding wait states */ \
\
/* barrier wait states (64..79) */ \
macro (ompt_state_wait_barrier, 0x40) /* waiting at a barrier */ \
macro (ompt_state_wait_barrier_implicit, 0x41) /* implicit barrier */ \
macro (ompt_state_wait_barrier_explicit, 0x42) /* explicit barrier */ \
\
/* task wait states (80..95) */ \
macro (ompt_state_wait_taskwait, 0x50) /* waiting at a taskwait */ \
macro (ompt_state_wait_taskgroup, 0x51) /* waiting at a taskgroup */ \
\
/* mutex wait states (96..111) */ \
macro (ompt_state_wait_lock, 0x60) /* waiting for lock */ \
macro (ompt_state_wait_nest_lock, 0x61) /* waiting for nest lock */ \
macro (ompt_state_wait_critical, 0x62) /* waiting for critical */ \
macro (ompt_state_wait_atomic, 0x63) /* waiting for atomic */ \
macro (ompt_state_wait_ordered, 0x64) /* waiting for ordered */ \
macro (ompt_state_wait_single, 0x6F) /* waiting for single region (non-standard!) */ \
\
/* misc (112..127) */ \
macro (ompt_state_undefined, 0x70) /* undefined thread state */
#define FOREACH_OMPT_EVENT(macro) \
\
/*--- Mandatory Events ---*/ \
macro (ompt_event_parallel_begin, ompt_new_parallel_callback_t, 1) /* parallel begin */ \
macro (ompt_event_parallel_end, ompt_end_parallel_callback_t, 2) /* parallel end */ \
\
macro (ompt_event_task_begin, ompt_new_task_callback_t, 3) /* task begin */ \
macro (ompt_event_task_end, ompt_task_callback_t, 4) /* task destroy */ \
\
macro (ompt_event_thread_begin, ompt_thread_type_callback_t, 5) /* thread begin */ \
macro (ompt_event_thread_end, ompt_thread_type_callback_t, 6) /* thread end */ \
\
macro (ompt_event_control, ompt_control_callback_t, 7) /* support control calls */ \
\
macro (ompt_event_runtime_shutdown, ompt_callback_t, 8) /* runtime shutdown */ \
\
/*--- Optional Events (blame shifting, ompt_event_unimplemented) ---*/ \
macro (ompt_event_idle_begin, ompt_thread_callback_t, 9) /* begin idle state */ \
macro (ompt_event_idle_end, ompt_thread_callback_t, 10) /* end idle state */ \
\
macro (ompt_event_wait_barrier_begin, ompt_parallel_callback_t, 11) /* begin wait at barrier */ \
macro (ompt_event_wait_barrier_end, ompt_parallel_callback_t, 12) /* end wait at barrier */ \
\
macro (ompt_event_wait_taskwait_begin, ompt_parallel_callback_t, 13) /* begin wait at taskwait */ \
macro (ompt_event_wait_taskwait_end, ompt_parallel_callback_t, 14) /* end wait at taskwait */ \
\
macro (ompt_event_wait_taskgroup_begin, ompt_parallel_callback_t, 15) /* begin wait at taskgroup */\
macro (ompt_event_wait_taskgroup_end, ompt_parallel_callback_t, 16) /* end wait at taskgroup */ \
\
macro (ompt_event_release_lock, ompt_wait_callback_t, 17) /* lock release */ \
macro (ompt_event_release_nest_lock_last, ompt_wait_callback_t, 18) /* last nest lock release */ \
macro (ompt_event_release_critical, ompt_wait_callback_t, 19) /* critical release */ \
\
macro (ompt_event_release_atomic, ompt_wait_callback_t, 20) /* atomic release */ \
\
macro (ompt_event_release_ordered, ompt_wait_callback_t, 21) /* ordered release */ \
\
/*--- Optional Events (synchronous events, ompt_event_unimplemented) --- */ \
macro (ompt_event_implicit_task_begin, ompt_parallel_callback_t, 22) /* implicit task begin */ \
macro (ompt_event_implicit_task_end, ompt_parallel_callback_t, 23) /* implicit task end */ \
\
macro (ompt_event_initial_task_begin, ompt_parallel_callback_t, 24) /* initial task begin */ \
macro (ompt_event_initial_task_end, ompt_parallel_callback_t, 25) /* initial task end */ \
\
macro (ompt_event_task_switch, ompt_task_pair_callback_t, 26) /* task switch */ \
\
macro (ompt_event_loop_begin, ompt_new_workshare_callback_t, 27) /* task at loop begin */ \
macro (ompt_event_loop_end, ompt_parallel_callback_t, 28) /* task at loop end */ \
\
macro (ompt_event_sections_begin, ompt_new_workshare_callback_t, 29) /* task at sections begin */\
macro (ompt_event_sections_end, ompt_parallel_callback_t, 30) /* task at sections end */ \
\
macro (ompt_event_single_in_block_begin, ompt_new_workshare_callback_t, 31) /* task at single begin*/ \
macro (ompt_event_single_in_block_end, ompt_parallel_callback_t, 32) /* task at single end */ \
\
macro (ompt_event_single_others_begin, ompt_parallel_callback_t, 33) /* task at single begin */ \
macro (ompt_event_single_others_end, ompt_parallel_callback_t, 34) /* task at single end */ \
\
macro (ompt_event_workshare_begin, ompt_new_workshare_callback_t, 35) /* task at workshare begin */\
macro (ompt_event_workshare_end, ompt_parallel_callback_t, 36) /* task at workshare end */ \
\
macro (ompt_event_master_begin, ompt_parallel_callback_t, 37) /* task at master begin */ \
macro (ompt_event_master_end, ompt_parallel_callback_t, 38) /* task at master end */ \
\
macro (ompt_event_barrier_begin, ompt_parallel_callback_t, 39) /* task at barrier begin */ \
macro (ompt_event_barrier_end, ompt_parallel_callback_t, 40) /* task at barrier end */ \
\
macro (ompt_event_taskwait_begin, ompt_parallel_callback_t, 41) /* task at taskwait begin */ \
macro (ompt_event_taskwait_end, ompt_parallel_callback_t, 42) /* task at task wait end */ \
\
macro (ompt_event_taskgroup_begin, ompt_parallel_callback_t, 43) /* task at taskgroup begin */\
macro (ompt_event_taskgroup_end, ompt_parallel_callback_t, 44) /* task at taskgroup end */ \
\
macro (ompt_event_release_nest_lock_prev, ompt_wait_callback_t, 45) /* prev nest lock release */ \
\
macro (ompt_event_wait_lock, ompt_wait_callback_t, 46) /* lock wait */ \
macro (ompt_event_wait_nest_lock, ompt_wait_callback_t, 47) /* nest lock wait */ \
macro (ompt_event_wait_critical, ompt_wait_callback_t, 48) /* critical wait */ \
macro (ompt_event_wait_atomic, ompt_wait_callback_t, 49) /* atomic wait */ \
macro (ompt_event_wait_ordered, ompt_wait_callback_t, 50) /* ordered wait */ \
\
macro (ompt_event_acquired_lock, ompt_wait_callback_t, 51) /* lock acquired */ \
macro (ompt_event_acquired_nest_lock_first, ompt_wait_callback_t, 52) /* 1st nest lock acquired */ \
macro (ompt_event_acquired_nest_lock_next, ompt_wait_callback_t, 53) /* next nest lock acquired*/ \
macro (ompt_event_acquired_critical, ompt_wait_callback_t, 54) /* critical acquired */ \
macro (ompt_event_acquired_atomic, ompt_wait_callback_t, 55) /* atomic acquired */ \
macro (ompt_event_acquired_ordered, ompt_wait_callback_t, 56) /* ordered acquired */ \
\
macro (ompt_event_init_lock, ompt_wait_callback_t, 57) /* lock init */ \
macro (ompt_event_init_nest_lock, ompt_wait_callback_t, 58) /* nest lock init */ \
\
macro (ompt_event_destroy_lock, ompt_wait_callback_t, 59) /* lock destruction */ \
macro (ompt_event_destroy_nest_lock, ompt_wait_callback_t, 60) /* nest lock destruction */ \
\
macro (ompt_event_flush, ompt_callback_t, 61) /* after executing flush */ \
\
macro (ompt_event_task_dependences, ompt_task_dependences_callback_t, 69) /* report task dependences */\
macro (ompt_event_task_dependence_pair, ompt_task_pair_callback_t, 70) /* report task dependence pair */
/*****************************************************************************
* data types
*****************************************************************************/
/*---------------------
* identifiers
*---------------------*/
typedef uint64_t ompt_thread_id_t;
#define ompt_thread_id_none ((ompt_thread_id_t) 0) /* non-standard */
typedef uint64_t ompt_task_id_t;
#define ompt_task_id_none ((ompt_task_id_t) 0) /* non-standard */
typedef uint64_t ompt_parallel_id_t;
#define ompt_parallel_id_none ((ompt_parallel_id_t) 0) /* non-standard */
typedef uint64_t ompt_wait_id_t;
#define ompt_wait_id_none ((ompt_wait_id_t) 0) /* non-standard */
/*---------------------
* ompt_frame_t
*---------------------*/
typedef struct ompt_frame_s {
void *exit_runtime_frame; /* next frame is user code */
void *reenter_runtime_frame; /* previous frame is user code */
} ompt_frame_t;
/*---------------------
* dependences types
*---------------------*/
typedef enum ompt_task_dependence_flag_e {
// a two bit field for the dependence type
ompt_task_dependence_type_out = 1,
ompt_task_dependence_type_in = 2,
ompt_task_dependence_type_inout = 3,
} ompt_task_dependence_flag_t;
typedef struct ompt_task_dependence_s {
void *variable_addr;
uint32_t dependence_flags;
} ompt_task_dependence_t;
/*****************************************************************************
* enumerations for thread states and runtime events
*****************************************************************************/
/*---------------------
* runtime states
*---------------------*/
typedef enum {
#define ompt_state_macro(state, code) state = code,
FOREACH_OMPT_STATE(ompt_state_macro)
#undef ompt_state_macro
} ompt_state_t;
/*---------------------
* runtime events
*---------------------*/
typedef enum {
#define ompt_event_macro(event, callback, eventid) event = eventid,
FOREACH_OMPT_EVENT(ompt_event_macro)
#undef ompt_event_macro
} ompt_event_t;
/*---------------------
* set callback results
*---------------------*/
typedef enum {
ompt_set_result_registration_error = 0,
ompt_set_result_event_may_occur_no_callback = 1,
ompt_set_result_event_never_occurs = 2,
ompt_set_result_event_may_occur_callback_some = 3,
ompt_set_result_event_may_occur_callback_always = 4,
} ompt_set_result_t;
/*****************************************************************************
* callback signatures
*****************************************************************************/
/* initialization */
typedef void (*ompt_interface_fn_t)(void);
typedef ompt_interface_fn_t (*ompt_function_lookup_t)(
const char * /* entry point to look up */
);
/* threads */
typedef void (*ompt_thread_callback_t) (
ompt_thread_id_t thread_id /* ID of thread */
);
typedef enum {
ompt_thread_initial = 1, // start the enumeration at 1
ompt_thread_worker = 2,
ompt_thread_other = 3
} ompt_thread_type_t;
typedef enum {
ompt_invoker_program = 0, /* program invokes master task */
ompt_invoker_runtime = 1 /* runtime invokes master task */
} ompt_invoker_t;
typedef void (*ompt_thread_type_callback_t) (
ompt_thread_type_t thread_type, /* type of thread */
ompt_thread_id_t thread_id /* ID of thread */
);
typedef void (*ompt_wait_callback_t) (
ompt_wait_id_t wait_id /* wait id */
);
/* parallel and workshares */
typedef void (*ompt_parallel_callback_t) (
ompt_parallel_id_t parallel_id, /* id of parallel region */
ompt_task_id_t task_id /* id of task */
);
typedef void (*ompt_new_workshare_callback_t) (
ompt_parallel_id_t parallel_id, /* id of parallel region */
ompt_task_id_t parent_task_id, /* id of parent task */
void *workshare_function /* pointer to outlined function */
);
typedef void (*ompt_new_parallel_callback_t) (
ompt_task_id_t parent_task_id, /* id of parent task */
ompt_frame_t *parent_task_frame, /* frame data of parent task */
ompt_parallel_id_t parallel_id, /* id of parallel region */
uint32_t requested_team_size, /* number of threads in team */
void *parallel_function, /* pointer to outlined function */
ompt_invoker_t invoker /* who invokes master task? */
);
typedef void (*ompt_end_parallel_callback_t) (
ompt_parallel_id_t parallel_id, /* id of parallel region */
ompt_task_id_t task_id, /* id of task */
ompt_invoker_t invoker /* who invokes master task? */
);
/* tasks */
typedef void (*ompt_task_callback_t) (
ompt_task_id_t task_id /* id of task */
);
typedef void (*ompt_task_pair_callback_t) (
ompt_task_id_t first_task_id,
ompt_task_id_t second_task_id
);
typedef void (*ompt_new_task_callback_t) (
ompt_task_id_t parent_task_id, /* id of parent task */
ompt_frame_t *parent_task_frame, /* frame data for parent task */
ompt_task_id_t new_task_id, /* id of created task */
void *task_function /* pointer to outlined function */
);
/* task dependences */
typedef void (*ompt_task_dependences_callback_t) (
ompt_task_id_t task_id, /* ID of task with dependences */
const ompt_task_dependence_t *deps,/* vector of task dependences */
int ndeps /* number of dependences */
);
/* program */
typedef void (*ompt_control_callback_t) (
uint64_t command, /* command of control call */
uint64_t modifier /* modifier of control call */
);
typedef void (*ompt_callback_t)(void);
/****************************************************************************
* ompt API
***************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
#define OMPT_API_FNTYPE(fn) fn##_t
#define OMPT_API_FUNCTION(return_type, fn, args) \
typedef return_type (*OMPT_API_FNTYPE(fn)) args
/****************************************************************************
* INQUIRY FUNCTIONS
***************************************************************************/
/* state */
OMPT_API_FUNCTION(ompt_state_t, ompt_get_state, (
ompt_wait_id_t *ompt_wait_id
));
/* thread */
OMPT_API_FUNCTION(ompt_thread_id_t, ompt_get_thread_id, (void));
OMPT_API_FUNCTION(void *, ompt_get_idle_frame, (void));
/* parallel region */
OMPT_API_FUNCTION(ompt_parallel_id_t, ompt_get_parallel_id, (
int ancestor_level
));
OMPT_API_FUNCTION(int, ompt_get_parallel_team_size, (
int ancestor_level
));
/* task */
OMPT_API_FUNCTION(ompt_task_id_t, ompt_get_task_id, (
int depth
));
OMPT_API_FUNCTION(ompt_frame_t *, ompt_get_task_frame, (
int depth
));
/****************************************************************************
* PLACEHOLDERS FOR PERFORMANCE REPORTING
***************************************************************************/
/* idle */
OMPT_API_FUNCTION(void, ompt_idle, (
void
));
/* overhead */
OMPT_API_FUNCTION(void, ompt_overhead, (
void
));
/* barrier wait */
OMPT_API_FUNCTION(void, ompt_barrier_wait, (
void
));
/* task wait */
OMPT_API_FUNCTION(void, ompt_task_wait, (
void
));
/* mutex wait */
OMPT_API_FUNCTION(void, ompt_mutex_wait, (
void
));
/****************************************************************************
* INITIALIZATION FUNCTIONS
***************************************************************************/
OMPT_API_FUNCTION(void, ompt_initialize, (
ompt_function_lookup_t ompt_fn_lookup,
const char *runtime_version,
unsigned int ompt_version
));
/* initialization interface to be defined by tool */
ompt_initialize_t ompt_tool(void);
typedef enum opt_init_mode_e {
ompt_init_mode_never = 0,
ompt_init_mode_false = 1,
ompt_init_mode_true = 2,
ompt_init_mode_always = 3
} ompt_init_mode_t;
OMPT_API_FUNCTION(int, ompt_set_callback, (
ompt_event_t event,
ompt_callback_t callback
));
typedef enum ompt_set_callback_rc_e { /* non-standard */
ompt_set_callback_error = 0,
ompt_has_event_no_callback = 1,
ompt_no_event_no_callback = 2,
ompt_has_event_may_callback = 3,
ompt_has_event_must_callback = 4,
} ompt_set_callback_rc_t;
OMPT_API_FUNCTION(int, ompt_get_callback, (
ompt_event_t event,
ompt_callback_t *callback
));
/****************************************************************************
* MISCELLANEOUS FUNCTIONS
***************************************************************************/
/* control */
// FIXME: remove workaround for clang
#if !defined(__clang__) && defined(_OPENMP) && (_OPENMP >= 201307)
#pragma omp declare target
#endif
void ompt_control(
uint64_t command,
uint64_t modifier
);
#if !defined(__clang__) && defined(_OPENMP) && (_OPENMP >= 201307)
#pragma omp end declare target
#endif
/* state enumeration */
OMPT_API_FUNCTION(int, ompt_enumerate_state, (
int current_state,
int *next_state,
const char **next_state_name
));
#ifdef __cplusplus
};
#endif
#endif
+57 -42
View File
@@ -76,19 +76,19 @@
! *** omp_* entry points
! ***
subroutine omp_set_num_threads(nthreads)
subroutine omp_set_num_threads(num_threads)
use omp_lib_kinds
integer (kind=omp_integer_kind) nthreads
integer (kind=omp_integer_kind) num_threads
end subroutine omp_set_num_threads
subroutine omp_set_dynamic(enable)
subroutine omp_set_dynamic(dynamic_threads)
use omp_lib_kinds
logical (kind=omp_logical_kind) enable
logical (kind=omp_logical_kind) dynamic_threads
end subroutine omp_set_dynamic
subroutine omp_set_nested(enable)
subroutine omp_set_nested(nested)
use omp_lib_kinds
logical (kind=omp_logical_kind) enable
logical (kind=omp_logical_kind) nested
end subroutine omp_set_nested
function omp_get_num_threads()
@@ -116,6 +116,11 @@
logical (kind=omp_logical_kind) omp_in_parallel
end function omp_in_parallel
function omp_in_final()
use omp_lib_kinds
logical (kind=omp_logical_kind) omp_in_final
end function omp_in_final
function omp_get_dynamic()
use omp_lib_kinds
logical (kind=omp_logical_kind) omp_get_dynamic
@@ -163,16 +168,16 @@
integer (kind=omp_integer_kind) omp_get_team_size
end function omp_get_team_size
subroutine omp_set_schedule(kind, modifier)
subroutine omp_set_schedule(kind, chunk_size)
use omp_lib_kinds
integer (kind=omp_sched_kind) kind
integer (kind=omp_integer_kind) modifier
integer (kind=omp_integer_kind) chunk_size
end subroutine omp_set_schedule
subroutine omp_get_schedule(kind, modifier)
subroutine omp_get_schedule(kind, chunk_size)
use omp_lib_kinds
integer (kind=omp_sched_kind) kind
integer (kind=omp_integer_kind) modifier
integer (kind=omp_integer_kind) chunk_size
end subroutine omp_get_schedule
function omp_get_proc_bind()
@@ -194,7 +199,7 @@
subroutine omp_get_place_proc_ids(place_num, ids)
use omp_lib_kinds
integer (kind=omp_integer_kind) place_num
integer (kind=kmp_pointer_kind) ids
integer (kind=omp_integer_kind) ids(*)
end subroutine omp_get_place_proc_ids
function omp_get_place_num()
@@ -209,7 +214,7 @@
subroutine omp_get_partition_place_nums(place_nums)
use omp_lib_kinds
integer (kind=kmp_pointer_kind) place_nums
integer (kind=omp_integer_kind) place_nums(*)
end subroutine omp_get_partition_place_nums
function omp_get_wtime()
@@ -225,9 +230,9 @@
integer (kind=omp_integer_kind) omp_get_default_device
end function omp_get_default_device
subroutine omp_set_default_device(dflt_device)
subroutine omp_set_default_device(device_num)
use omp_lib_kinds
integer (kind=omp_integer_kind) dflt_device
integer (kind=omp_integer_kind) device_num
end subroutine omp_set_default_device
function omp_get_num_devices()
@@ -255,86 +260,91 @@
logical (kind=omp_logical_kind) omp_is_initial_device
end function omp_is_initial_device
subroutine omp_init_lock(lockvar)
function omp_get_initial_device()
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_initial_device
end function omp_get_initial_device
subroutine omp_init_lock(svar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_init_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_lock_kind) lockvar
integer (kind=omp_lock_kind) svar
end subroutine omp_init_lock
subroutine omp_destroy_lock(lockvar)
subroutine omp_destroy_lock(svar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_destroy_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_lock_kind) lockvar
integer (kind=omp_lock_kind) svar
end subroutine omp_destroy_lock
subroutine omp_set_lock(lockvar)
subroutine omp_set_lock(svar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_set_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_lock_kind) lockvar
integer (kind=omp_lock_kind) svar
end subroutine omp_set_lock
subroutine omp_unset_lock(lockvar)
subroutine omp_unset_lock(svar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_unset_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_lock_kind) lockvar
integer (kind=omp_lock_kind) svar
end subroutine omp_unset_lock
function omp_test_lock(lockvar)
function omp_test_lock(svar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_test_lock
!DIR$ ENDIF
use omp_lib_kinds
logical (kind=omp_logical_kind) omp_test_lock
integer (kind=omp_lock_kind) lockvar
integer (kind=omp_lock_kind) svar
end function omp_test_lock
subroutine omp_init_nest_lock(lockvar)
subroutine omp_init_nest_lock(nvar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_init_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) lockvar
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_init_nest_lock
subroutine omp_destroy_nest_lock(lockvar)
subroutine omp_destroy_nest_lock(nvar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_destroy_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) lockvar
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_destroy_nest_lock
subroutine omp_set_nest_lock(lockvar)
subroutine omp_set_nest_lock(nvar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_set_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) lockvar
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_set_nest_lock
subroutine omp_unset_nest_lock(lockvar)
subroutine omp_unset_nest_lock(nvar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_unset_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) lockvar
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_unset_nest_lock
function omp_test_nest_lock(lockvar)
function omp_test_nest_lock(nvar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_test_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_test_nest_lock
integer (kind=omp_nest_lock_kind) lockvar
integer (kind=omp_nest_lock_kind) nvar
end function omp_test_nest_lock
function omp_get_max_task_priority()
@@ -399,6 +409,11 @@
integer (kind=omp_integer_kind) kmp_get_library
end function kmp_get_library
subroutine kmp_set_disp_num_buffers(num)
use omp_lib_kinds
integer (kind=omp_integer_kind) num
end subroutine kmp_set_disp_num_buffers
function kmp_set_affinity(mask)
use omp_lib_kinds
integer (kind=omp_integer_kind) kmp_set_affinity
@@ -491,17 +506,17 @@
logical (kind=omp_logical_kind) kmp_get_cancellation_status
end function kmp_get_cancellation_status
subroutine kmp_init_lock_with_hint(lockvar, lockhint)
subroutine omp_init_lock_with_hint(svar, hint)
use omp_lib_kinds
integer (kind=omp_lock_kind) lockvar
integer (kind=omp_lock_hint_kind) lockhint
end subroutine kmp_init_lock_with_hint
integer (kind=omp_lock_kind) svar
integer (kind=omp_lock_hint_kind) hint
end subroutine omp_init_lock_with_hint
subroutine kmp_init_nest_lock_with_hint(lockvar, lockhint)
subroutine omp_init_nest_lock_with_hint(nvar, hint)
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) lockvar
integer (kind=omp_lock_hint_kind) lockhint
end subroutine kmp_init_nest_lock_with_hint
integer (kind=omp_nest_lock_kind) nvar
integer (kind=omp_lock_hint_kind) hint
end subroutine omp_init_nest_lock_with_hint
end interface
+2 -2
View File
@@ -197,7 +197,7 @@
subroutine omp_get_place_proc_ids(place_num, ids) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind), value :: place_num
integer (kind=kmp_pointer_kind) ids(*)
integer (kind=omp_integer_kind) ids(*)
end subroutine omp_get_place_proc_ids
function omp_get_place_num() bind(c)
@@ -212,7 +212,7 @@
subroutine omp_get_partition_place_nums(place_nums) bind(c)
use omp_lib_kinds
integer (kind=kmp_pointer_kind) place_nums(*)
integer (kind=omp_integer_kind) place_nums(*)
end subroutine omp_get_partition_place_nums
function omp_get_wtime() bind(c)
+2 -2
View File
@@ -186,7 +186,7 @@
subroutine omp_get_place_proc_ids(place_num, ids) bind(c)
import
integer (kind=omp_integer_kind), value :: place_num
integer (kind=kmp_pointer_kind) ids(*)
integer (kind=omp_integer_kind) ids(*)
end subroutine omp_get_place_proc_ids
function omp_get_place_num() bind(c)
@@ -201,7 +201,7 @@
subroutine omp_get_partition_place_nums(place_nums) bind(c)
import
integer (kind=kmp_pointer_kind) place_nums(*)
integer (kind=omp_integer_kind) place_nums(*)
end subroutine omp_get_partition_place_nums
function omp_get_wtime() bind(c)
-515
View File
@@ -1,515 +0,0 @@
/*
* include/45/ompt.h.var
*/
#ifndef __OMPT__
#define __OMPT__
/*****************************************************************************
* system include files
*****************************************************************************/
#include <stdint.h>
/*****************************************************************************
* iteration macros
*****************************************************************************/
#define FOREACH_OMPT_INQUIRY_FN(macro) \
macro (ompt_enumerate_state) \
\
macro (ompt_set_callback) \
macro (ompt_get_callback) \
\
macro (ompt_get_idle_frame) \
macro (ompt_get_task_frame) \
\
macro (ompt_get_state) \
\
macro (ompt_get_parallel_id) \
macro (ompt_get_parallel_team_size) \
macro (ompt_get_task_id) \
macro (ompt_get_thread_id)
#define FOREACH_OMPT_PLACEHOLDER_FN(macro) \
macro (ompt_idle) \
macro (ompt_overhead) \
macro (ompt_barrier_wait) \
macro (ompt_task_wait) \
macro (ompt_mutex_wait)
#define FOREACH_OMPT_STATE(macro) \
\
/* first */ \
macro (ompt_state_first, 0x71) /* initial enumeration state */ \
\
/* work states (0..15) */ \
macro (ompt_state_work_serial, 0x00) /* working outside parallel */ \
macro (ompt_state_work_parallel, 0x01) /* working within parallel */ \
macro (ompt_state_work_reduction, 0x02) /* performing a reduction */ \
\
/* idle (16..31) */ \
macro (ompt_state_idle, 0x10) /* waiting for work */ \
\
/* overhead states (32..63) */ \
macro (ompt_state_overhead, 0x20) /* overhead excluding wait states */ \
\
/* barrier wait states (64..79) */ \
macro (ompt_state_wait_barrier, 0x40) /* waiting at a barrier */ \
macro (ompt_state_wait_barrier_implicit, 0x41) /* implicit barrier */ \
macro (ompt_state_wait_barrier_explicit, 0x42) /* explicit barrier */ \
\
/* task wait states (80..95) */ \
macro (ompt_state_wait_taskwait, 0x50) /* waiting at a taskwait */ \
macro (ompt_state_wait_taskgroup, 0x51) /* waiting at a taskgroup */ \
\
/* mutex wait states (96..111) */ \
macro (ompt_state_wait_lock, 0x60) /* waiting for lock */ \
macro (ompt_state_wait_nest_lock, 0x61) /* waiting for nest lock */ \
macro (ompt_state_wait_critical, 0x62) /* waiting for critical */ \
macro (ompt_state_wait_atomic, 0x63) /* waiting for atomic */ \
macro (ompt_state_wait_ordered, 0x64) /* waiting for ordered */ \
macro (ompt_state_wait_single, 0x6F) /* waiting for single region (non-standard!) */ \
\
/* misc (112..127) */ \
macro (ompt_state_undefined, 0x70) /* undefined thread state */
#define FOREACH_OMPT_EVENT(macro) \
\
/*--- Mandatory Events ---*/ \
macro (ompt_event_parallel_begin, ompt_new_parallel_callback_t, 1) /* parallel begin */ \
macro (ompt_event_parallel_end, ompt_end_parallel_callback_t, 2) /* parallel end */ \
\
macro (ompt_event_task_begin, ompt_new_task_callback_t, 3) /* task begin */ \
macro (ompt_event_task_end, ompt_task_callback_t, 4) /* task destroy */ \
\
macro (ompt_event_thread_begin, ompt_thread_type_callback_t, 5) /* thread begin */ \
macro (ompt_event_thread_end, ompt_thread_type_callback_t, 6) /* thread end */ \
\
macro (ompt_event_control, ompt_control_callback_t, 7) /* support control calls */ \
\
macro (ompt_event_runtime_shutdown, ompt_callback_t, 8) /* runtime shutdown */ \
\
/*--- Optional Events (blame shifting, ompt_event_unimplemented) ---*/ \
macro (ompt_event_idle_begin, ompt_thread_callback_t, 9) /* begin idle state */ \
macro (ompt_event_idle_end, ompt_thread_callback_t, 10) /* end idle state */ \
\
macro (ompt_event_wait_barrier_begin, ompt_parallel_callback_t, 11) /* begin wait at barrier */ \
macro (ompt_event_wait_barrier_end, ompt_parallel_callback_t, 12) /* end wait at barrier */ \
\
macro (ompt_event_wait_taskwait_begin, ompt_parallel_callback_t, 13) /* begin wait at taskwait */ \
macro (ompt_event_wait_taskwait_end, ompt_parallel_callback_t, 14) /* end wait at taskwait */ \
\
macro (ompt_event_wait_taskgroup_begin, ompt_parallel_callback_t, 15) /* begin wait at taskgroup */\
macro (ompt_event_wait_taskgroup_end, ompt_parallel_callback_t, 16) /* end wait at taskgroup */ \
\
macro (ompt_event_release_lock, ompt_wait_callback_t, 17) /* lock release */ \
macro (ompt_event_release_nest_lock_last, ompt_wait_callback_t, 18) /* last nest lock release */ \
macro (ompt_event_release_critical, ompt_wait_callback_t, 19) /* critical release */ \
\
macro (ompt_event_release_atomic, ompt_wait_callback_t, 20) /* atomic release */ \
\
macro (ompt_event_release_ordered, ompt_wait_callback_t, 21) /* ordered release */ \
\
/*--- Optional Events (synchronous events, ompt_event_unimplemented) --- */ \
macro (ompt_event_implicit_task_begin, ompt_parallel_callback_t, 22) /* implicit task begin */ \
macro (ompt_event_implicit_task_end, ompt_parallel_callback_t, 23) /* implicit task end */ \
\
macro (ompt_event_initial_task_begin, ompt_parallel_callback_t, 24) /* initial task begin */ \
macro (ompt_event_initial_task_end, ompt_parallel_callback_t, 25) /* initial task end */ \
\
macro (ompt_event_task_switch, ompt_task_pair_callback_t, 26) /* task switch */ \
\
macro (ompt_event_loop_begin, ompt_new_workshare_callback_t, 27) /* task at loop begin */ \
macro (ompt_event_loop_end, ompt_parallel_callback_t, 28) /* task at loop end */ \
\
macro (ompt_event_sections_begin, ompt_new_workshare_callback_t, 29) /* task at sections begin */\
macro (ompt_event_sections_end, ompt_parallel_callback_t, 30) /* task at sections end */ \
\
macro (ompt_event_single_in_block_begin, ompt_new_workshare_callback_t, 31) /* task at single begin*/ \
macro (ompt_event_single_in_block_end, ompt_parallel_callback_t, 32) /* task at single end */ \
\
macro (ompt_event_single_others_begin, ompt_parallel_callback_t, 33) /* task at single begin */ \
macro (ompt_event_single_others_end, ompt_parallel_callback_t, 34) /* task at single end */ \
\
macro (ompt_event_workshare_begin, ompt_new_workshare_callback_t, 35) /* task at workshare begin */\
macro (ompt_event_workshare_end, ompt_parallel_callback_t, 36) /* task at workshare end */ \
\
macro (ompt_event_master_begin, ompt_parallel_callback_t, 37) /* task at master begin */ \
macro (ompt_event_master_end, ompt_parallel_callback_t, 38) /* task at master end */ \
\
macro (ompt_event_barrier_begin, ompt_parallel_callback_t, 39) /* task at barrier begin */ \
macro (ompt_event_barrier_end, ompt_parallel_callback_t, 40) /* task at barrier end */ \
\
macro (ompt_event_taskwait_begin, ompt_parallel_callback_t, 41) /* task at taskwait begin */ \
macro (ompt_event_taskwait_end, ompt_parallel_callback_t, 42) /* task at task wait end */ \
\
macro (ompt_event_taskgroup_begin, ompt_parallel_callback_t, 43) /* task at taskgroup begin */\
macro (ompt_event_taskgroup_end, ompt_parallel_callback_t, 44) /* task at taskgroup end */ \
\
macro (ompt_event_release_nest_lock_prev, ompt_wait_callback_t, 45) /* prev nest lock release */ \
\
macro (ompt_event_wait_lock, ompt_wait_callback_t, 46) /* lock wait */ \
macro (ompt_event_wait_nest_lock, ompt_wait_callback_t, 47) /* nest lock wait */ \
macro (ompt_event_wait_critical, ompt_wait_callback_t, 48) /* critical wait */ \
macro (ompt_event_wait_atomic, ompt_wait_callback_t, 49) /* atomic wait */ \
macro (ompt_event_wait_ordered, ompt_wait_callback_t, 50) /* ordered wait */ \
\
macro (ompt_event_acquired_lock, ompt_wait_callback_t, 51) /* lock acquired */ \
macro (ompt_event_acquired_nest_lock_first, ompt_wait_callback_t, 52) /* 1st nest lock acquired */ \
macro (ompt_event_acquired_nest_lock_next, ompt_wait_callback_t, 53) /* next nest lock acquired*/ \
macro (ompt_event_acquired_critical, ompt_wait_callback_t, 54) /* critical acquired */ \
macro (ompt_event_acquired_atomic, ompt_wait_callback_t, 55) /* atomic acquired */ \
macro (ompt_event_acquired_ordered, ompt_wait_callback_t, 56) /* ordered acquired */ \
\
macro (ompt_event_init_lock, ompt_wait_callback_t, 57) /* lock init */ \
macro (ompt_event_init_nest_lock, ompt_wait_callback_t, 58) /* nest lock init */ \
\
macro (ompt_event_destroy_lock, ompt_wait_callback_t, 59) /* lock destruction */ \
macro (ompt_event_destroy_nest_lock, ompt_wait_callback_t, 60) /* nest lock destruction */ \
\
macro (ompt_event_flush, ompt_callback_t, 61) /* after executing flush */ \
\
macro (ompt_event_task_dependences, ompt_task_dependences_callback_t, 69) /* report task dependences */\
macro (ompt_event_task_dependence_pair, ompt_task_pair_callback_t, 70) /* report task dependence pair */
/*****************************************************************************
* data types
*****************************************************************************/
/*---------------------
* identifiers
*---------------------*/
typedef uint64_t ompt_thread_id_t;
#define ompt_thread_id_none ((ompt_thread_id_t) 0) /* non-standard */
typedef uint64_t ompt_task_id_t;
#define ompt_task_id_none ((ompt_task_id_t) 0) /* non-standard */
typedef uint64_t ompt_parallel_id_t;
#define ompt_parallel_id_none ((ompt_parallel_id_t) 0) /* non-standard */
typedef uint64_t ompt_wait_id_t;
#define ompt_wait_id_none ((ompt_wait_id_t) 0) /* non-standard */
/*---------------------
* ompt_frame_t
*---------------------*/
typedef struct ompt_frame_s {
void *exit_runtime_frame; /* next frame is user code */
void *reenter_runtime_frame; /* previous frame is user code */
} ompt_frame_t;
/*---------------------
* dependences types
*---------------------*/
typedef enum ompt_task_dependence_flag_e {
// a two bit field for the dependence type
ompt_task_dependence_type_out = 1,
ompt_task_dependence_type_in = 2,
ompt_task_dependence_type_inout = 3,
} ompt_task_dependence_flag_t;
typedef struct ompt_task_dependence_s {
void *variable_addr;
uint32_t dependence_flags;
} ompt_task_dependence_t;
/*****************************************************************************
* enumerations for thread states and runtime events
*****************************************************************************/
/*---------------------
* runtime states
*---------------------*/
typedef enum {
#define ompt_state_macro(state, code) state = code,
FOREACH_OMPT_STATE(ompt_state_macro)
#undef ompt_state_macro
} ompt_state_t;
/*---------------------
* runtime events
*---------------------*/
typedef enum {
#define ompt_event_macro(event, callback, eventid) event = eventid,
FOREACH_OMPT_EVENT(ompt_event_macro)
#undef ompt_event_macro
} ompt_event_t;
/*---------------------
* set callback results
*---------------------*/
typedef enum {
ompt_set_result_registration_error = 0,
ompt_set_result_event_may_occur_no_callback = 1,
ompt_set_result_event_never_occurs = 2,
ompt_set_result_event_may_occur_callback_some = 3,
ompt_set_result_event_may_occur_callback_always = 4,
} ompt_set_result_t;
/*****************************************************************************
* callback signatures
*****************************************************************************/
/* initialization */
typedef void (*ompt_interface_fn_t)(void);
typedef ompt_interface_fn_t (*ompt_function_lookup_t)(
const char * /* entry point to look up */
);
/* threads */
typedef void (*ompt_thread_callback_t) (
ompt_thread_id_t thread_id /* ID of thread */
);
typedef enum {
ompt_thread_initial = 1, // start the enumeration at 1
ompt_thread_worker = 2,
ompt_thread_other = 3
} ompt_thread_type_t;
typedef enum {
ompt_invoker_program = 0, /* program invokes master task */
ompt_invoker_runtime = 1 /* runtime invokes master task */
} ompt_invoker_t;
typedef void (*ompt_thread_type_callback_t) (
ompt_thread_type_t thread_type, /* type of thread */
ompt_thread_id_t thread_id /* ID of thread */
);
typedef void (*ompt_wait_callback_t) (
ompt_wait_id_t wait_id /* wait id */
);
/* parallel and workshares */
typedef void (*ompt_parallel_callback_t) (
ompt_parallel_id_t parallel_id, /* id of parallel region */
ompt_task_id_t task_id /* id of task */
);
typedef void (*ompt_new_workshare_callback_t) (
ompt_parallel_id_t parallel_id, /* id of parallel region */
ompt_task_id_t parent_task_id, /* id of parent task */
void *workshare_function /* pointer to outlined function */
);
typedef void (*ompt_new_parallel_callback_t) (
ompt_task_id_t parent_task_id, /* id of parent task */
ompt_frame_t *parent_task_frame, /* frame data of parent task */
ompt_parallel_id_t parallel_id, /* id of parallel region */
uint32_t requested_team_size, /* number of threads in team */
void *parallel_function, /* pointer to outlined function */
ompt_invoker_t invoker /* who invokes master task? */
);
typedef void (*ompt_end_parallel_callback_t) (
ompt_parallel_id_t parallel_id, /* id of parallel region */
ompt_task_id_t task_id, /* id of task */
ompt_invoker_t invoker /* who invokes master task? */
);
/* tasks */
typedef void (*ompt_task_callback_t) (
ompt_task_id_t task_id /* id of task */
);
typedef void (*ompt_task_pair_callback_t) (
ompt_task_id_t first_task_id,
ompt_task_id_t second_task_id
);
typedef void (*ompt_new_task_callback_t) (
ompt_task_id_t parent_task_id, /* id of parent task */
ompt_frame_t *parent_task_frame, /* frame data for parent task */
ompt_task_id_t new_task_id, /* id of created task */
void *task_function /* pointer to outlined function */
);
/* task dependences */
typedef void (*ompt_task_dependences_callback_t) (
ompt_task_id_t task_id, /* ID of task with dependences */
const ompt_task_dependence_t *deps,/* vector of task dependences */
int ndeps /* number of dependences */
);
/* program */
typedef void (*ompt_control_callback_t) (
uint64_t command, /* command of control call */
uint64_t modifier /* modifier of control call */
);
typedef void (*ompt_callback_t)(void);
/****************************************************************************
* ompt API
***************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
#define OMPT_API_FNTYPE(fn) fn##_t
#define OMPT_API_FUNCTION(return_type, fn, args) \
typedef return_type (*OMPT_API_FNTYPE(fn)) args
/****************************************************************************
* INQUIRY FUNCTIONS
***************************************************************************/
/* state */
OMPT_API_FUNCTION(ompt_state_t, ompt_get_state, (
ompt_wait_id_t *ompt_wait_id
));
/* thread */
OMPT_API_FUNCTION(ompt_thread_id_t, ompt_get_thread_id, (void));
OMPT_API_FUNCTION(void *, ompt_get_idle_frame, (void));
/* parallel region */
OMPT_API_FUNCTION(ompt_parallel_id_t, ompt_get_parallel_id, (
int ancestor_level
));
OMPT_API_FUNCTION(int, ompt_get_parallel_team_size, (
int ancestor_level
));
/* task */
OMPT_API_FUNCTION(ompt_task_id_t, ompt_get_task_id, (
int depth
));
OMPT_API_FUNCTION(ompt_frame_t *, ompt_get_task_frame, (
int depth
));
/****************************************************************************
* PLACEHOLDERS FOR PERFORMANCE REPORTING
***************************************************************************/
/* idle */
OMPT_API_FUNCTION(void, ompt_idle, (
void
));
/* overhead */
OMPT_API_FUNCTION(void, ompt_overhead, (
void
));
/* barrier wait */
OMPT_API_FUNCTION(void, ompt_barrier_wait, (
void
));
/* task wait */
OMPT_API_FUNCTION(void, ompt_task_wait, (
void
));
/* mutex wait */
OMPT_API_FUNCTION(void, ompt_mutex_wait, (
void
));
/****************************************************************************
* INITIALIZATION FUNCTIONS
***************************************************************************/
OMPT_API_FUNCTION(void, ompt_initialize, (
ompt_function_lookup_t ompt_fn_lookup,
const char *runtime_version,
unsigned int ompt_version
));
/* initialization interface to be defined by tool */
ompt_initialize_t ompt_tool(void);
typedef enum opt_init_mode_e {
ompt_init_mode_never = 0,
ompt_init_mode_false = 1,
ompt_init_mode_true = 2,
ompt_init_mode_always = 3
} ompt_init_mode_t;
OMPT_API_FUNCTION(int, ompt_set_callback, (
ompt_event_t event,
ompt_callback_t callback
));
typedef enum ompt_set_callback_rc_e { /* non-standard */
ompt_set_callback_error = 0,
ompt_has_event_no_callback = 1,
ompt_no_event_no_callback = 2,
ompt_has_event_may_callback = 3,
ompt_has_event_must_callback = 4,
} ompt_set_callback_rc_t;
OMPT_API_FUNCTION(int, ompt_get_callback, (
ompt_event_t event,
ompt_callback_t *callback
));
/****************************************************************************
* MISCELLANEOUS FUNCTIONS
***************************************************************************/
/* control */
// FIXME: remove workaround for clang
#if !defined(__clang__) && defined(_OPENMP) && (_OPENMP >= 201307)
#pragma omp declare target
#endif
void ompt_control(
uint64_t command,
uint64_t modifier
);
#if !defined(__clang__) && defined(_OPENMP) && (_OPENMP >= 201307)
#pragma omp end declare target
#endif
/* state enumeration */
OMPT_API_FUNCTION(int, ompt_enumerate_state, (
int current_state,
int *next_state,
const char **next_state_name
));
#ifdef __cplusplus
};
#endif
#endif
+215
View File
@@ -0,0 +1,215 @@
/*
* include/50/omp.h.var
*/
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
#ifndef __OMP_H
# define __OMP_H
# define KMP_VERSION_MAJOR @LIBOMP_VERSION_MAJOR@
# define KMP_VERSION_MINOR @LIBOMP_VERSION_MINOR@
# define KMP_VERSION_BUILD @LIBOMP_VERSION_BUILD@
# define KMP_BUILD_DATE "@LIBOMP_BUILD_DATE@"
# ifdef __cplusplus
extern "C" {
# endif
# if defined(_WIN32)
# define __KAI_KMPC_CONVENTION __cdecl
# else
# define __KAI_KMPC_CONVENTION
# endif
/* schedule kind constants */
typedef enum omp_sched_t {
omp_sched_static = 1,
omp_sched_dynamic = 2,
omp_sched_guided = 3,
omp_sched_auto = 4
} omp_sched_t;
/* set API functions */
extern void __KAI_KMPC_CONVENTION omp_set_num_threads (int);
extern void __KAI_KMPC_CONVENTION omp_set_dynamic (int);
extern void __KAI_KMPC_CONVENTION omp_set_nested (int);
extern void __KAI_KMPC_CONVENTION omp_set_max_active_levels (int);
extern void __KAI_KMPC_CONVENTION omp_set_schedule (omp_sched_t, int);
/* query API functions */
extern int __KAI_KMPC_CONVENTION omp_get_num_threads (void);
extern int __KAI_KMPC_CONVENTION omp_get_dynamic (void);
extern int __KAI_KMPC_CONVENTION omp_get_nested (void);
extern int __KAI_KMPC_CONVENTION omp_get_max_threads (void);
extern int __KAI_KMPC_CONVENTION omp_get_thread_num (void);
extern int __KAI_KMPC_CONVENTION omp_get_num_procs (void);
extern int __KAI_KMPC_CONVENTION omp_in_parallel (void);
extern int __KAI_KMPC_CONVENTION omp_in_final (void);
extern int __KAI_KMPC_CONVENTION omp_get_active_level (void);
extern int __KAI_KMPC_CONVENTION omp_get_level (void);
extern int __KAI_KMPC_CONVENTION omp_get_ancestor_thread_num (int);
extern int __KAI_KMPC_CONVENTION omp_get_team_size (int);
extern int __KAI_KMPC_CONVENTION omp_get_thread_limit (void);
extern int __KAI_KMPC_CONVENTION omp_get_max_active_levels (void);
extern void __KAI_KMPC_CONVENTION omp_get_schedule (omp_sched_t *, int *);
extern int __KAI_KMPC_CONVENTION omp_get_max_task_priority (void);
/* lock API functions */
typedef struct omp_lock_t {
void * _lk;
} omp_lock_t;
extern void __KAI_KMPC_CONVENTION omp_init_lock (omp_lock_t *);
extern void __KAI_KMPC_CONVENTION omp_set_lock (omp_lock_t *);
extern void __KAI_KMPC_CONVENTION omp_unset_lock (omp_lock_t *);
extern void __KAI_KMPC_CONVENTION omp_destroy_lock (omp_lock_t *);
extern int __KAI_KMPC_CONVENTION omp_test_lock (omp_lock_t *);
/* nested lock API functions */
typedef struct omp_nest_lock_t {
void * _lk;
} omp_nest_lock_t;
extern void __KAI_KMPC_CONVENTION omp_init_nest_lock (omp_nest_lock_t *);
extern void __KAI_KMPC_CONVENTION omp_set_nest_lock (omp_nest_lock_t *);
extern void __KAI_KMPC_CONVENTION omp_unset_nest_lock (omp_nest_lock_t *);
extern void __KAI_KMPC_CONVENTION omp_destroy_nest_lock (omp_nest_lock_t *);
extern int __KAI_KMPC_CONVENTION omp_test_nest_lock (omp_nest_lock_t *);
/* lock hint type for dynamic user lock */
typedef enum omp_lock_hint_t {
omp_lock_hint_none = 0,
omp_lock_hint_uncontended = 1,
omp_lock_hint_contended = (1<<1 ),
omp_lock_hint_nonspeculative = (1<<2 ),
omp_lock_hint_speculative = (1<<3 ),
kmp_lock_hint_hle = (1<<16),
kmp_lock_hint_rtm = (1<<17),
kmp_lock_hint_adaptive = (1<<18)
} omp_lock_hint_t;
/* hinted lock initializers */
extern void __KAI_KMPC_CONVENTION omp_init_lock_with_hint(omp_lock_t *, omp_lock_hint_t);
extern void __KAI_KMPC_CONVENTION omp_init_nest_lock_with_hint(omp_nest_lock_t *, omp_lock_hint_t);
/* time API functions */
extern double __KAI_KMPC_CONVENTION omp_get_wtime (void);
extern double __KAI_KMPC_CONVENTION omp_get_wtick (void);
/* OpenMP 4.0 */
extern int __KAI_KMPC_CONVENTION omp_get_default_device (void);
extern void __KAI_KMPC_CONVENTION omp_set_default_device (int);
extern int __KAI_KMPC_CONVENTION omp_is_initial_device (void);
extern int __KAI_KMPC_CONVENTION omp_get_num_devices (void);
extern int __KAI_KMPC_CONVENTION omp_get_num_teams (void);
extern int __KAI_KMPC_CONVENTION omp_get_team_num (void);
extern int __KAI_KMPC_CONVENTION omp_get_cancellation (void);
# include <stdlib.h>
/* OpenMP 4.5 */
extern int __KAI_KMPC_CONVENTION omp_get_initial_device (void);
extern void* __KAI_KMPC_CONVENTION omp_target_alloc(size_t, int);
extern void __KAI_KMPC_CONVENTION omp_target_free(void *, int);
extern int __KAI_KMPC_CONVENTION omp_target_is_present(void *, int);
extern int __KAI_KMPC_CONVENTION omp_target_memcpy(void *, void *, size_t, size_t, size_t, int, int);
extern int __KAI_KMPC_CONVENTION omp_target_memcpy_rect(void *, void *, size_t, int, const size_t *,
const size_t *, const size_t *, const size_t *, const size_t *, int, int);
extern int __KAI_KMPC_CONVENTION omp_target_associate_ptr(void *, void *, size_t, size_t, int);
extern int __KAI_KMPC_CONVENTION omp_target_disassociate_ptr(void *, int);
/* kmp API functions */
extern int __KAI_KMPC_CONVENTION kmp_get_stacksize (void);
extern void __KAI_KMPC_CONVENTION kmp_set_stacksize (int);
extern size_t __KAI_KMPC_CONVENTION kmp_get_stacksize_s (void);
extern void __KAI_KMPC_CONVENTION kmp_set_stacksize_s (size_t);
extern int __KAI_KMPC_CONVENTION kmp_get_blocktime (void);
extern int __KAI_KMPC_CONVENTION kmp_get_library (void);
extern void __KAI_KMPC_CONVENTION kmp_set_blocktime (int);
extern void __KAI_KMPC_CONVENTION kmp_set_library (int);
extern void __KAI_KMPC_CONVENTION kmp_set_library_serial (void);
extern void __KAI_KMPC_CONVENTION kmp_set_library_turnaround (void);
extern void __KAI_KMPC_CONVENTION kmp_set_library_throughput (void);
extern void __KAI_KMPC_CONVENTION kmp_set_defaults (char const *);
extern void __KAI_KMPC_CONVENTION kmp_set_disp_num_buffers (int);
/* Intel affinity API */
typedef void * kmp_affinity_mask_t;
extern int __KAI_KMPC_CONVENTION kmp_set_affinity (kmp_affinity_mask_t *);
extern int __KAI_KMPC_CONVENTION kmp_get_affinity (kmp_affinity_mask_t *);
extern int __KAI_KMPC_CONVENTION kmp_get_affinity_max_proc (void);
extern void __KAI_KMPC_CONVENTION kmp_create_affinity_mask (kmp_affinity_mask_t *);
extern void __KAI_KMPC_CONVENTION kmp_destroy_affinity_mask (kmp_affinity_mask_t *);
extern int __KAI_KMPC_CONVENTION kmp_set_affinity_mask_proc (int, kmp_affinity_mask_t *);
extern int __KAI_KMPC_CONVENTION kmp_unset_affinity_mask_proc (int, kmp_affinity_mask_t *);
extern int __KAI_KMPC_CONVENTION kmp_get_affinity_mask_proc (int, kmp_affinity_mask_t *);
/* OpenMP 4.0 affinity API */
typedef enum omp_proc_bind_t {
omp_proc_bind_false = 0,
omp_proc_bind_true = 1,
omp_proc_bind_master = 2,
omp_proc_bind_close = 3,
omp_proc_bind_spread = 4
} omp_proc_bind_t;
extern omp_proc_bind_t __KAI_KMPC_CONVENTION omp_get_proc_bind (void);
/* OpenMP 4.5 affinity API */
extern int __KAI_KMPC_CONVENTION omp_get_num_places (void);
extern int __KAI_KMPC_CONVENTION omp_get_place_num_procs (int);
extern void __KAI_KMPC_CONVENTION omp_get_place_proc_ids (int, int *);
extern int __KAI_KMPC_CONVENTION omp_get_place_num (void);
extern int __KAI_KMPC_CONVENTION omp_get_partition_num_places (void);
extern void __KAI_KMPC_CONVENTION omp_get_partition_place_nums (int *);
extern void * __KAI_KMPC_CONVENTION kmp_malloc (size_t);
extern void * __KAI_KMPC_CONVENTION kmp_aligned_malloc (size_t, size_t);
extern void * __KAI_KMPC_CONVENTION kmp_calloc (size_t, size_t);
extern void * __KAI_KMPC_CONVENTION kmp_realloc (void *, size_t);
extern void __KAI_KMPC_CONVENTION kmp_free (void *);
extern void __KAI_KMPC_CONVENTION kmp_set_warnings_on(void);
extern void __KAI_KMPC_CONVENTION kmp_set_warnings_off(void);
/* OpenMP 5.0 Tool Control */
typedef enum omp_control_tool_result_t {
omp_control_tool_notool = -2,
omp_control_tool_nocallback = -1,
omp_control_tool_success = 0,
omp_control_tool_ignored = 1
} omp_control_tool_result_t;
typedef enum omp_control_tool_t {
omp_control_tool_start = 1,
omp_control_tool_pause = 2,
omp_control_tool_flush = 3,
omp_control_tool_end = 4
} omp_control_tool_t;
extern int __KAI_KMPC_CONVENTION omp_control_tool(int, int, void*);
# undef __KAI_KMPC_CONVENTION
/* Warning:
The following typedefs are not standard, deprecated and will be removed in a future release.
*/
typedef int omp_int_t;
typedef double omp_wtime_t;
# ifdef __cplusplus
}
# endif
#endif /* __OMP_H */
+868
View File
@@ -0,0 +1,868 @@
! include/50/omp_lib.f.var
!
!//===----------------------------------------------------------------------===//
!//
!// 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.
!//
!//===----------------------------------------------------------------------===//
!
!***
!*** Some of the directives for the following routine extend past column 72,
!*** so process this file in 132-column mode.
!***
!dec$ fixedformlinesize:132
module omp_lib_kinds
integer, parameter :: omp_integer_kind = 4
integer, parameter :: omp_logical_kind = 4
integer, parameter :: omp_real_kind = 4
integer, parameter :: omp_lock_kind = int_ptr_kind()
integer, parameter :: omp_nest_lock_kind = int_ptr_kind()
integer, parameter :: omp_sched_kind = omp_integer_kind
integer, parameter :: omp_proc_bind_kind = omp_integer_kind
integer, parameter :: kmp_pointer_kind = int_ptr_kind()
integer, parameter :: kmp_size_t_kind = int_ptr_kind()
integer, parameter :: kmp_affinity_mask_kind = int_ptr_kind()
integer, parameter :: kmp_cancel_kind = omp_integer_kind
integer, parameter :: omp_lock_hint_kind = omp_integer_kind
integer, parameter :: omp_control_tool_kind = omp_integer_kind
integer, parameter :: omp_control_tool_result_kind = omp_integer_kind
end module omp_lib_kinds
module omp_lib
use omp_lib_kinds
integer (kind=omp_integer_kind), parameter :: kmp_version_major = @LIBOMP_VERSION_MAJOR@
integer (kind=omp_integer_kind), parameter :: kmp_version_minor = @LIBOMP_VERSION_MINOR@
integer (kind=omp_integer_kind), parameter :: kmp_version_build = @LIBOMP_VERSION_BUILD@
character(*), parameter :: kmp_build_date = '@LIBOMP_BUILD_DATE@'
integer (kind=omp_integer_kind), parameter :: openmp_version = @LIBOMP_OMP_YEAR_MONTH@
integer(kind=omp_sched_kind), parameter :: omp_sched_static = 1
integer(kind=omp_sched_kind), parameter :: omp_sched_dynamic = 2
integer(kind=omp_sched_kind), parameter :: omp_sched_guided = 3
integer(kind=omp_sched_kind), parameter :: omp_sched_auto = 4
integer (kind=omp_proc_bind_kind), parameter :: omp_proc_bind_false = 0
integer (kind=omp_proc_bind_kind), parameter :: omp_proc_bind_true = 1
integer (kind=omp_proc_bind_kind), parameter :: omp_proc_bind_master = 2
integer (kind=omp_proc_bind_kind), parameter :: omp_proc_bind_close = 3
integer (kind=omp_proc_bind_kind), parameter :: omp_proc_bind_spread = 4
integer (kind=kmp_cancel_kind), parameter :: kmp_cancel_parallel = 1
integer (kind=kmp_cancel_kind), parameter :: kmp_cancel_loop = 2
integer (kind=kmp_cancel_kind), parameter :: kmp_cancel_sections = 3
integer (kind=kmp_cancel_kind), parameter :: kmp_cancel_taskgroup = 4
integer (kind=omp_lock_hint_kind), parameter :: omp_lock_hint_none = 0
integer (kind=omp_lock_hint_kind), parameter :: omp_lock_hint_uncontended = 1
integer (kind=omp_lock_hint_kind), parameter :: omp_lock_hint_contended = 2
integer (kind=omp_lock_hint_kind), parameter :: omp_lock_hint_nonspeculative = 4
integer (kind=omp_lock_hint_kind), parameter :: omp_lock_hint_speculative = 8
integer (kind=omp_lock_hint_kind), parameter :: kmp_lock_hint_hle = 65536
integer (kind=omp_lock_hint_kind), parameter :: kmp_lock_hint_rtm = 131072
integer (kind=omp_lock_hint_kind), parameter :: kmp_lock_hint_adaptive = 262144
interface
! ***
! *** omp_* entry points
! ***
subroutine omp_set_num_threads(num_threads)
use omp_lib_kinds
integer (kind=omp_integer_kind) num_threads
end subroutine omp_set_num_threads
subroutine omp_set_dynamic(dynamic_threads)
use omp_lib_kinds
logical (kind=omp_logical_kind) dynamic_threads
end subroutine omp_set_dynamic
subroutine omp_set_nested(nested)
use omp_lib_kinds
logical (kind=omp_logical_kind) nested
end subroutine omp_set_nested
function omp_get_num_threads()
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_num_threads
end function omp_get_num_threads
function omp_get_max_threads()
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_max_threads
end function omp_get_max_threads
function omp_get_thread_num()
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_thread_num
end function omp_get_thread_num
function omp_get_num_procs()
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_num_procs
end function omp_get_num_procs
function omp_in_parallel()
use omp_lib_kinds
logical (kind=omp_logical_kind) omp_in_parallel
end function omp_in_parallel
function omp_in_final()
use omp_lib_kinds
logical (kind=omp_logical_kind) omp_in_final
end function omp_in_final
function omp_get_dynamic()
use omp_lib_kinds
logical (kind=omp_logical_kind) omp_get_dynamic
end function omp_get_dynamic
function omp_get_nested()
use omp_lib_kinds
logical (kind=omp_logical_kind) omp_get_nested
end function omp_get_nested
function omp_get_thread_limit()
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_thread_limit
end function omp_get_thread_limit
subroutine omp_set_max_active_levels(max_levels)
use omp_lib_kinds
integer (kind=omp_integer_kind) max_levels
end subroutine omp_set_max_active_levels
function omp_get_max_active_levels()
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_max_active_levels
end function omp_get_max_active_levels
function omp_get_level()
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_level
end function omp_get_level
function omp_get_active_level()
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_active_level
end function omp_get_active_level
function omp_get_ancestor_thread_num(level)
use omp_lib_kinds
integer (kind=omp_integer_kind) level
integer (kind=omp_integer_kind) omp_get_ancestor_thread_num
end function omp_get_ancestor_thread_num
function omp_get_team_size(level)
use omp_lib_kinds
integer (kind=omp_integer_kind) level
integer (kind=omp_integer_kind) omp_get_team_size
end function omp_get_team_size
subroutine omp_set_schedule(kind, chunk_size)
use omp_lib_kinds
integer (kind=omp_sched_kind) kind
integer (kind=omp_integer_kind) chunk_size
end subroutine omp_set_schedule
subroutine omp_get_schedule(kind, chunk_size)
use omp_lib_kinds
integer (kind=omp_sched_kind) kind
integer (kind=omp_integer_kind) chunk_size
end subroutine omp_get_schedule
function omp_get_proc_bind()
use omp_lib_kinds
integer (kind=omp_proc_bind_kind) omp_get_proc_bind
end function omp_get_proc_bind
function omp_get_num_places()
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_num_places
end function omp_get_num_places
function omp_get_place_num_procs(place_num)
use omp_lib_kinds
integer (kind=omp_integer_kind) place_num
integer (kind=omp_integer_kind) omp_get_place_num_procs
end function omp_get_place_num_procs
subroutine omp_get_place_proc_ids(place_num, ids)
use omp_lib_kinds
integer (kind=omp_integer_kind) place_num
integer (kind=omp_integer_kind) ids(*)
end subroutine omp_get_place_proc_ids
function omp_get_place_num()
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_place_num
end function omp_get_place_num
function omp_get_partition_num_places()
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_partition_num_places
end function omp_get_partition_num_places
subroutine omp_get_partition_place_nums(place_nums)
use omp_lib_kinds
integer (kind=omp_integer_kind) place_nums(*)
end subroutine omp_get_partition_place_nums
function omp_get_wtime()
double precision omp_get_wtime
end function omp_get_wtime
function omp_get_wtick ()
double precision omp_get_wtick
end function omp_get_wtick
function omp_get_default_device()
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_default_device
end function omp_get_default_device
subroutine omp_set_default_device(device_num)
use omp_lib_kinds
integer (kind=omp_integer_kind) device_num
end subroutine omp_set_default_device
function omp_get_num_devices()
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_num_devices
end function omp_get_num_devices
function omp_get_num_teams()
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_num_teams
end function omp_get_num_teams
function omp_get_team_num()
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_team_num
end function omp_get_team_num
function omp_get_cancellation()
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_cancellation
end function omp_get_cancellation
function omp_is_initial_device()
use omp_lib_kinds
logical (kind=omp_logical_kind) omp_is_initial_device
end function omp_is_initial_device
function omp_get_initial_device()
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_initial_device
end function omp_get_initial_device
subroutine omp_init_lock(svar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_init_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_lock_kind) svar
end subroutine omp_init_lock
subroutine omp_destroy_lock(svar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_destroy_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_lock_kind) svar
end subroutine omp_destroy_lock
subroutine omp_set_lock(svar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_set_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_lock_kind) svar
end subroutine omp_set_lock
subroutine omp_unset_lock(svar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_unset_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_lock_kind) svar
end subroutine omp_unset_lock
function omp_test_lock(svar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_test_lock
!DIR$ ENDIF
use omp_lib_kinds
logical (kind=omp_logical_kind) omp_test_lock
integer (kind=omp_lock_kind) svar
end function omp_test_lock
subroutine omp_init_nest_lock(nvar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_init_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_init_nest_lock
subroutine omp_destroy_nest_lock(nvar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_destroy_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_destroy_nest_lock
subroutine omp_set_nest_lock(nvar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_set_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_set_nest_lock
subroutine omp_unset_nest_lock(nvar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_unset_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_unset_nest_lock
function omp_test_nest_lock(nvar)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_test_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_test_nest_lock
integer (kind=omp_nest_lock_kind) nvar
end function omp_test_nest_lock
function omp_get_max_task_priority()
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_max_task_priority
end function omp_get_max_task_priority
! ***
! *** kmp_* entry points
! ***
subroutine kmp_set_stacksize(size)
use omp_lib_kinds
integer (kind=omp_integer_kind) size
end subroutine kmp_set_stacksize
subroutine kmp_set_stacksize_s(size)
use omp_lib_kinds
integer (kind=kmp_size_t_kind) size
end subroutine kmp_set_stacksize_s
subroutine kmp_set_blocktime(msec)
use omp_lib_kinds
integer (kind=omp_integer_kind) msec
end subroutine kmp_set_blocktime
subroutine kmp_set_library_serial()
end subroutine kmp_set_library_serial
subroutine kmp_set_library_turnaround()
end subroutine kmp_set_library_turnaround
subroutine kmp_set_library_throughput()
end subroutine kmp_set_library_throughput
subroutine kmp_set_library(libnum)
use omp_lib_kinds
integer (kind=omp_integer_kind) libnum
end subroutine kmp_set_library
subroutine kmp_set_defaults(string)
character*(*) string
end subroutine kmp_set_defaults
function kmp_get_stacksize()
use omp_lib_kinds
integer (kind=omp_integer_kind) kmp_get_stacksize
end function kmp_get_stacksize
function kmp_get_stacksize_s()
use omp_lib_kinds
integer (kind=kmp_size_t_kind) kmp_get_stacksize_s
end function kmp_get_stacksize_s
function kmp_get_blocktime()
use omp_lib_kinds
integer (kind=omp_integer_kind) kmp_get_blocktime
end function kmp_get_blocktime
function kmp_get_library()
use omp_lib_kinds
integer (kind=omp_integer_kind) kmp_get_library
end function kmp_get_library
subroutine kmp_set_disp_num_buffers(num)
use omp_lib_kinds
integer (kind=omp_integer_kind) num
end subroutine kmp_set_disp_num_buffers
function kmp_set_affinity(mask)
use omp_lib_kinds
integer (kind=omp_integer_kind) kmp_set_affinity
integer (kind=kmp_affinity_mask_kind) mask
end function kmp_set_affinity
function kmp_get_affinity(mask)
use omp_lib_kinds
integer (kind=omp_integer_kind) kmp_get_affinity
integer (kind=kmp_affinity_mask_kind) mask
end function kmp_get_affinity
function kmp_get_affinity_max_proc()
use omp_lib_kinds
integer (kind=omp_integer_kind) kmp_get_affinity_max_proc
end function kmp_get_affinity_max_proc
subroutine kmp_create_affinity_mask(mask)
use omp_lib_kinds
integer (kind=kmp_affinity_mask_kind) mask
end subroutine kmp_create_affinity_mask
subroutine kmp_destroy_affinity_mask(mask)
use omp_lib_kinds
integer (kind=kmp_affinity_mask_kind) mask
end subroutine kmp_destroy_affinity_mask
function kmp_set_affinity_mask_proc(proc, mask)
use omp_lib_kinds
integer (kind=omp_integer_kind) kmp_set_affinity_mask_proc
integer (kind=omp_integer_kind) proc
integer (kind=kmp_affinity_mask_kind) mask
end function kmp_set_affinity_mask_proc
function kmp_unset_affinity_mask_proc(proc, mask)
use omp_lib_kinds
integer (kind=omp_integer_kind) kmp_unset_affinity_mask_proc
integer (kind=omp_integer_kind) proc
integer (kind=kmp_affinity_mask_kind) mask
end function kmp_unset_affinity_mask_proc
function kmp_get_affinity_mask_proc(proc, mask)
use omp_lib_kinds
integer (kind=omp_integer_kind) kmp_get_affinity_mask_proc
integer (kind=omp_integer_kind) proc
integer (kind=kmp_affinity_mask_kind) mask
end function kmp_get_affinity_mask_proc
function kmp_malloc(size)
use omp_lib_kinds
integer (kind=kmp_pointer_kind) kmp_malloc
integer (kind=kmp_size_t_kind) size
end function kmp_malloc
function kmp_aligned_malloc(size, alignment)
use omp_lib_kinds
integer (kind=kmp_pointer_kind) kmp_aligned_malloc
integer (kind=kmp_size_t_kind) size
integer (kind=kmp_size_t_kind) alignment
end function kmp_aligned_malloc
function kmp_calloc(nelem, elsize)
use omp_lib_kinds
integer (kind=kmp_pointer_kind) kmp_calloc
integer (kind=kmp_size_t_kind) nelem
integer (kind=kmp_size_t_kind) elsize
end function kmp_calloc
function kmp_realloc(ptr, size)
use omp_lib_kinds
integer (kind=kmp_pointer_kind) kmp_realloc
integer (kind=kmp_pointer_kind) ptr
integer (kind=kmp_size_t_kind) size
end function kmp_realloc
subroutine kmp_free(ptr)
use omp_lib_kinds
integer (kind=kmp_pointer_kind) ptr
end subroutine kmp_free
subroutine kmp_set_warnings_on()
end subroutine kmp_set_warnings_on
subroutine kmp_set_warnings_off()
end subroutine kmp_set_warnings_off
function kmp_get_cancellation_status(cancelkind)
use omp_lib_kinds
integer (kind=kmp_cancel_kind) cancelkind
logical (kind=omp_logical_kind) kmp_get_cancellation_status
end function kmp_get_cancellation_status
subroutine omp_init_lock_with_hint(svar, hint)
use omp_lib_kinds
integer (kind=omp_lock_kind) svar
integer (kind=omp_lock_hint_kind) hint
end subroutine omp_init_lock_with_hint
subroutine omp_init_nest_lock_with_hint(nvar, hint)
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) nvar
integer (kind=omp_lock_hint_kind) hint
end subroutine omp_init_nest_lock_with_hint
function omp_control_tool(command, modifier)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_control_tool
integer (kind=omp_control_tool_kind) command
integer (kind=omp_control_tool_kind) modifier
end function omp_control_tool
end interface
!dec$ if defined(_WIN32)
!dec$ if defined(_WIN64) .or. defined(_M_AMD64)
!***
!*** The Fortran entry points must be in uppercase, even if the /Qlowercase
!*** option is specified. The alias attribute ensures that the specified
!*** string is used as the entry point.
!***
!*** On the Windows* OS IA-32 architecture, the Fortran entry points have an
!*** underscore prepended. On the Windows* OS Intel(R) 64
!*** architecture, no underscore is prepended.
!***
!dec$ attributes alias:'OMP_SET_NUM_THREADS' :: omp_set_num_threads
!dec$ attributes alias:'OMP_SET_DYNAMIC' :: omp_set_dynamic
!dec$ attributes alias:'OMP_SET_NESTED' :: omp_set_nested
!dec$ attributes alias:'OMP_GET_NUM_THREADS' :: omp_get_num_threads
!dec$ attributes alias:'OMP_GET_MAX_THREADS' :: omp_get_max_threads
!dec$ attributes alias:'OMP_GET_THREAD_NUM' :: omp_get_thread_num
!dec$ attributes alias:'OMP_GET_NUM_PROCS' :: omp_get_num_procs
!dec$ attributes alias:'OMP_IN_PARALLEL' :: omp_in_parallel
!dec$ attributes alias:'OMP_GET_DYNAMIC' :: omp_get_dynamic
!dec$ attributes alias:'OMP_GET_NESTED' :: omp_get_nested
!dec$ attributes alias:'OMP_GET_THREAD_LIMIT' :: omp_get_thread_limit
!dec$ attributes alias:'OMP_SET_MAX_ACTIVE_LEVELS' :: omp_set_max_active_levels
!dec$ attributes alias:'OMP_GET_MAX_ACTIVE_LEVELS' :: omp_get_max_active_levels
!dec$ attributes alias:'OMP_GET_LEVEL' :: omp_get_level
!dec$ attributes alias:'OMP_GET_ACTIVE_LEVEL' :: omp_get_active_level
!dec$ attributes alias:'OMP_GET_ANCESTOR_THREAD_NUM' :: omp_get_ancestor_thread_num
!dec$ attributes alias:'OMP_GET_TEAM_SIZE' :: omp_get_team_size
!dec$ attributes alias:'OMP_SET_SCHEDULE' :: omp_set_schedule
!dec$ attributes alias:'OMP_GET_SCHEDULE' :: omp_get_schedule
!dec$ attributes alias:'OMP_GET_PROC_BIND' :: omp_get_proc_bind
!dec$ attributes alias:'OMP_GET_WTIME' :: omp_get_wtime
!dec$ attributes alias:'OMP_GET_WTICK' :: omp_get_wtick
!dec$ attributes alias:'OMP_GET_DEFAULT_DEVICE' :: omp_get_default_device
!dec$ attributes alias:'OMP_SET_DEFAULT_DEVICE' :: omp_set_default_device
!dec$ attributes alias:'OMP_GET_NUM_DEVICES' :: omp_get_num_devices
!dec$ attributes alias:'OMP_GET_NUM_TEAMS' :: omp_get_num_teams
!dec$ attributes alias:'OMP_GET_TEAM_NUM' :: omp_get_team_num
!dec$ attributes alias:'OMP_GET_CANCELLATION' :: omp_get_cancellation
!dec$ attributes alias:'OMP_IS_INITIAL_DEVICE' :: omp_is_initial_device
!dec$ attributes alias:'OMP_GET_MAX_TASK_PRIORITY' :: omp_get_max_task_priority
!dec$ attributes alias:'OMP_CONTROL_TOOL' :: omp_control_tool
!dec$ attributes alias:'omp_init_lock' :: omp_init_lock
!dec$ attributes alias:'omp_init_lock_with_hint' :: omp_init_lock_with_hint
!dec$ attributes alias:'omp_destroy_lock' :: omp_destroy_lock
!dec$ attributes alias:'omp_set_lock' :: omp_set_lock
!dec$ attributes alias:'omp_unset_lock' :: omp_unset_lock
!dec$ attributes alias:'omp_test_lock' :: omp_test_lock
!dec$ attributes alias:'omp_init_nest_lock' :: omp_init_nest_lock
!dec$ attributes alias:'omp_init_nest_lock_with_hint' :: omp_init_nest_lock_with_hint
!dec$ attributes alias:'omp_destroy_nest_lock' :: omp_destroy_nest_lock
!dec$ attributes alias:'omp_set_nest_lock' :: omp_set_nest_lock
!dec$ attributes alias:'omp_unset_nest_lock' :: omp_unset_nest_lock
!dec$ attributes alias:'omp_test_nest_lock' :: omp_test_nest_lock
!dec$ attributes alias:'KMP_SET_STACKSIZE'::kmp_set_stacksize
!dec$ attributes alias:'KMP_SET_STACKSIZE_S'::kmp_set_stacksize_s
!dec$ attributes alias:'KMP_SET_BLOCKTIME'::kmp_set_blocktime
!dec$ attributes alias:'KMP_SET_LIBRARY_SERIAL'::kmp_set_library_serial
!dec$ attributes alias:'KMP_SET_LIBRARY_TURNAROUND'::kmp_set_library_turnaround
!dec$ attributes alias:'KMP_SET_LIBRARY_THROUGHPUT'::kmp_set_library_throughput
!dec$ attributes alias:'KMP_SET_LIBRARY'::kmp_set_library
!dec$ attributes alias:'KMP_GET_STACKSIZE'::kmp_get_stacksize
!dec$ attributes alias:'KMP_GET_STACKSIZE_S'::kmp_get_stacksize_s
!dec$ attributes alias:'KMP_GET_BLOCKTIME'::kmp_get_blocktime
!dec$ attributes alias:'KMP_GET_LIBRARY'::kmp_get_library
!dec$ attributes alias:'KMP_SET_AFFINITY'::kmp_set_affinity
!dec$ attributes alias:'KMP_GET_AFFINITY'::kmp_get_affinity
!dec$ attributes alias:'KMP_GET_AFFINITY_MAX_PROC'::kmp_get_affinity_max_proc
!dec$ attributes alias:'KMP_CREATE_AFFINITY_MASK'::kmp_create_affinity_mask
!dec$ attributes alias:'KMP_DESTROY_AFFINITY_MASK'::kmp_destroy_affinity_mask
!dec$ attributes alias:'KMP_SET_AFFINITY_MASK_PROC'::kmp_set_affinity_mask_proc
!dec$ attributes alias:'KMP_UNSET_AFFINITY_MASK_PROC'::kmp_unset_affinity_mask_proc
!dec$ attributes alias:'KMP_GET_AFFINITY_MASK_PROC'::kmp_get_affinity_mask_proc
!dec$ attributes alias:'KMP_MALLOC'::kmp_malloc
!dec$ attributes alias:'KMP_ALIGNED_MALLOC'::kmp_aligned_malloc
!dec$ attributes alias:'KMP_CALLOC'::kmp_calloc
!dec$ attributes alias:'KMP_REALLOC'::kmp_realloc
!dec$ attributes alias:'KMP_FREE'::kmp_free
!dec$ attributes alias:'KMP_SET_WARNINGS_ON'::kmp_set_warnings_on
!dec$ attributes alias:'KMP_SET_WARNINGS_OFF'::kmp_set_warnings_off
!dec$ attributes alias:'KMP_GET_CANCELLATION_STATUS' :: kmp_get_cancellation_status
!dec$ else
!***
!*** On Windows* OS IA-32 architecture, the Fortran entry points have an underscore prepended.
!***
!dec$ attributes alias:'_OMP_SET_NUM_THREADS' :: omp_set_num_threads
!dec$ attributes alias:'_OMP_SET_DYNAMIC' :: omp_set_dynamic
!dec$ attributes alias:'_OMP_SET_NESTED' :: omp_set_nested
!dec$ attributes alias:'_OMP_GET_NUM_THREADS' :: omp_get_num_threads
!dec$ attributes alias:'_OMP_GET_MAX_THREADS' :: omp_get_max_threads
!dec$ attributes alias:'_OMP_GET_THREAD_NUM' :: omp_get_thread_num
!dec$ attributes alias:'_OMP_GET_NUM_PROCS' :: omp_get_num_procs
!dec$ attributes alias:'_OMP_IN_PARALLEL' :: omp_in_parallel
!dec$ attributes alias:'_OMP_GET_DYNAMIC' :: omp_get_dynamic
!dec$ attributes alias:'_OMP_GET_NESTED' :: omp_get_nested
!dec$ attributes alias:'_OMP_GET_THREAD_LIMIT' :: omp_get_thread_limit
!dec$ attributes alias:'_OMP_SET_MAX_ACTIVE_LEVELS' :: omp_set_max_active_levels
!dec$ attributes alias:'_OMP_GET_MAX_ACTIVE_LEVELS' :: omp_get_max_active_levels
!dec$ attributes alias:'_OMP_GET_LEVEL' :: omp_get_level
!dec$ attributes alias:'_OMP_GET_ACTIVE_LEVEL' :: omp_get_active_level
!dec$ attributes alias:'_OMP_GET_ANCESTOR_THREAD_NUM' :: omp_get_ancestor_thread_num
!dec$ attributes alias:'_OMP_GET_TEAM_SIZE' :: omp_get_team_size
!dec$ attributes alias:'_OMP_SET_SCHEDULE' :: omp_set_schedule
!dec$ attributes alias:'_OMP_GET_SCHEDULE' :: omp_get_schedule
!dec$ attributes alias:'_OMP_GET_PROC_BIND' :: omp_get_proc_bind
!dec$ attributes alias:'_OMP_GET_WTIME' :: omp_get_wtime
!dec$ attributes alias:'_OMP_GET_WTICK' :: omp_get_wtick
!dec$ attributes alias:'_OMP_GET_DEFAULT_DEVICE' :: omp_get_default_device
!dec$ attributes alias:'_OMP_SET_DEFAULT_DEVICE' :: omp_set_default_device
!dec$ attributes alias:'_OMP_GET_NUM_DEVICES' :: omp_get_num_devices
!dec$ attributes alias:'_OMP_GET_NUM_TEAMS' :: omp_get_num_teams
!dec$ attributes alias:'_OMP_GET_TEAM_NUM' :: omp_get_team_num
!dec$ attributes alias:'_OMP_GET_CANCELLATION' :: omp_get_cancellation
!dec$ attributes alias:'_OMP_IS_INITIAL_DEVICE' :: omp_is_initial_device
!dec$ attributes alias:'_OMP_GET_MAX_TASK_PRIORTY' :: omp_get_max_task_priority
!dec$ attributes alias:'_OMP_CONTROL_TOOL' :: omp_control_tool
!dec$ attributes alias:'_omp_init_lock' :: omp_init_lock
!dec$ attributes alias:'_omp_init_lock_with_hint' :: omp_init_lock_with_hint
!dec$ attributes alias:'_omp_destroy_lock' :: omp_destroy_lock
!dec$ attributes alias:'_omp_set_lock' :: omp_set_lock
!dec$ attributes alias:'_omp_unset_lock' :: omp_unset_lock
!dec$ attributes alias:'_omp_test_lock' :: omp_test_lock
!dec$ attributes alias:'_omp_init_nest_lock' :: omp_init_nest_lock
!dec$ attributes alias:'_omp_init_nest_lock_with_hint' :: omp_init_nest_lock_with_hint
!dec$ attributes alias:'_omp_destroy_nest_lock' :: omp_destroy_nest_lock
!dec$ attributes alias:'_omp_set_nest_lock' :: omp_set_nest_lock
!dec$ attributes alias:'_omp_unset_nest_lock' :: omp_unset_nest_lock
!dec$ attributes alias:'_omp_test_nest_lock' :: omp_test_nest_lock
!dec$ attributes alias:'_KMP_SET_STACKSIZE'::kmp_set_stacksize
!dec$ attributes alias:'_KMP_SET_STACKSIZE_S'::kmp_set_stacksize_s
!dec$ attributes alias:'_KMP_SET_BLOCKTIME'::kmp_set_blocktime
!dec$ attributes alias:'_KMP_SET_LIBRARY_SERIAL'::kmp_set_library_serial
!dec$ attributes alias:'_KMP_SET_LIBRARY_TURNAROUND'::kmp_set_library_turnaround
!dec$ attributes alias:'_KMP_SET_LIBRARY_THROUGHPUT'::kmp_set_library_throughput
!dec$ attributes alias:'_KMP_SET_LIBRARY'::kmp_set_library
!dec$ attributes alias:'_KMP_GET_STACKSIZE'::kmp_get_stacksize
!dec$ attributes alias:'_KMP_GET_STACKSIZE_S'::kmp_get_stacksize_s
!dec$ attributes alias:'_KMP_GET_BLOCKTIME'::kmp_get_blocktime
!dec$ attributes alias:'_KMP_GET_LIBRARY'::kmp_get_library
!dec$ attributes alias:'_KMP_SET_AFFINITY'::kmp_set_affinity
!dec$ attributes alias:'_KMP_GET_AFFINITY'::kmp_get_affinity
!dec$ attributes alias:'_KMP_GET_AFFINITY_MAX_PROC'::kmp_get_affinity_max_proc
!dec$ attributes alias:'_KMP_CREATE_AFFINITY_MASK'::kmp_create_affinity_mask
!dec$ attributes alias:'_KMP_DESTROY_AFFINITY_MASK'::kmp_destroy_affinity_mask
!dec$ attributes alias:'_KMP_SET_AFFINITY_MASK_PROC'::kmp_set_affinity_mask_proc
!dec$ attributes alias:'_KMP_UNSET_AFFINITY_MASK_PROC'::kmp_unset_affinity_mask_proc
!dec$ attributes alias:'_KMP_GET_AFFINITY_MASK_PROC'::kmp_get_affinity_mask_proc
!dec$ attributes alias:'_KMP_MALLOC'::kmp_malloc
!dec$ attributes alias:'_KMP_ALIGNED_MALLOC'::kmp_aligned_malloc
!dec$ attributes alias:'_KMP_CALLOC'::kmp_calloc
!dec$ attributes alias:'_KMP_REALLOC'::kmp_realloc
!dec$ attributes alias:'_KMP_FREE'::kmp_free
!dec$ attributes alias:'_KMP_SET_WARNINGS_ON'::kmp_set_warnings_on
!dec$ attributes alias:'_KMP_SET_WARNINGS_OFF'::kmp_set_warnings_off
!dec$ attributes alias:'_KMP_GET_CANCELLATION_STATUS' :: kmp_get_cancellation_status
!dec$ endif
!dec$ endif
!dec$ if defined(__linux)
!***
!*** The Linux* OS entry points are in lowercase, with an underscore appended.
!***
!dec$ attributes alias:'omp_set_num_threads_'::omp_set_num_threads
!dec$ attributes alias:'omp_set_dynamic_'::omp_set_dynamic
!dec$ attributes alias:'omp_set_nested_'::omp_set_nested
!dec$ attributes alias:'omp_get_num_threads_'::omp_get_num_threads
!dec$ attributes alias:'omp_get_max_threads_'::omp_get_max_threads
!dec$ attributes alias:'omp_get_thread_num_'::omp_get_thread_num
!dec$ attributes alias:'omp_get_num_procs_'::omp_get_num_procs
!dec$ attributes alias:'omp_in_parallel_'::omp_in_parallel
!dec$ attributes alias:'omp_get_dynamic_'::omp_get_dynamic
!dec$ attributes alias:'omp_get_nested_'::omp_get_nested
!dec$ attributes alias:'omp_get_thread_limit_'::omp_get_thread_limit
!dec$ attributes alias:'omp_set_max_active_levels_'::omp_set_max_active_levels
!dec$ attributes alias:'omp_get_max_active_levels_'::omp_get_max_active_levels
!dec$ attributes alias:'omp_get_level_'::omp_get_level
!dec$ attributes alias:'omp_get_active_level_'::omp_get_active_level
!dec$ attributes alias:'omp_get_ancestor_thread_num_'::omp_get_ancestor_thread_num
!dec$ attributes alias:'omp_get_team_size_'::omp_get_team_size
!dec$ attributes alias:'omp_set_schedule_'::omp_set_schedule
!dec$ attributes alias:'omp_get_schedule_'::omp_get_schedule
!dec$ attributes alias:'omp_get_proc_bind_' :: omp_get_proc_bind
!dec$ attributes alias:'omp_get_wtime_'::omp_get_wtime
!dec$ attributes alias:'omp_get_wtick_'::omp_get_wtick
!dec$ attributes alias:'omp_get_default_device_'::omp_get_default_device
!dec$ attributes alias:'omp_set_default_device_'::omp_set_default_device
!dec$ attributes alias:'omp_get_num_devices_'::omp_get_num_devices
!dec$ attributes alias:'omp_get_num_teams_'::omp_get_num_teams
!dec$ attributes alias:'omp_get_team_num_'::omp_get_team_num
!dec$ attributes alias:'omp_get_cancellation_'::omp_get_cancellation
!dec$ attributes alias:'omp_is_initial_device_'::omp_is_initial_device
!dec$ attributes alias:'omp_get_max_task_priority_'::omp_get_max_task_priority
!dec$ attributes alias:'omp_init_lock_'::omp_init_lock
!dec$ attributes alias:'omp_init_lock_with_hint_'::omp_init_lock_with_hint
!dec$ attributes alias:'omp_destroy_lock_'::omp_destroy_lock
!dec$ attributes alias:'omp_set_lock_'::omp_set_lock
!dec$ attributes alias:'omp_unset_lock_'::omp_unset_lock
!dec$ attributes alias:'omp_test_lock_'::omp_test_lock
!dec$ attributes alias:'omp_init_nest_lock_'::omp_init_nest_lock
!dec$ attributes alias:'omp_init_nest_lock_with_hint_'::omp_init_nest_lock_with_hint
!dec$ attributes alias:'omp_destroy_nest_lock_'::omp_destroy_nest_lock
!dec$ attributes alias:'omp_set_nest_lock_'::omp_set_nest_lock
!dec$ attributes alias:'omp_unset_nest_lock_'::omp_unset_nest_lock
!dec$ attributes alias:'omp_test_nest_lock_'::omp_test_nest_lock
!dec$ attributes alias:'omp_control_tool_'::omp_control_tool
!dec$ attributes alias:'kmp_set_stacksize_'::kmp_set_stacksize
!dec$ attributes alias:'kmp_set_stacksize_s_'::kmp_set_stacksize_s
!dec$ attributes alias:'kmp_set_blocktime_'::kmp_set_blocktime
!dec$ attributes alias:'kmp_set_library_serial_'::kmp_set_library_serial
!dec$ attributes alias:'kmp_set_library_turnaround_'::kmp_set_library_turnaround
!dec$ attributes alias:'kmp_set_library_throughput_'::kmp_set_library_throughput
!dec$ attributes alias:'kmp_set_library_'::kmp_set_library
!dec$ attributes alias:'kmp_get_stacksize_'::kmp_get_stacksize
!dec$ attributes alias:'kmp_get_stacksize_s_'::kmp_get_stacksize_s
!dec$ attributes alias:'kmp_get_blocktime_'::kmp_get_blocktime
!dec$ attributes alias:'kmp_get_library_'::kmp_get_library
!dec$ attributes alias:'kmp_set_affinity_'::kmp_set_affinity
!dec$ attributes alias:'kmp_get_affinity_'::kmp_get_affinity
!dec$ attributes alias:'kmp_get_affinity_max_proc_'::kmp_get_affinity_max_proc
!dec$ attributes alias:'kmp_create_affinity_mask_'::kmp_create_affinity_mask
!dec$ attributes alias:'kmp_destroy_affinity_mask_'::kmp_destroy_affinity_mask
!dec$ attributes alias:'kmp_set_affinity_mask_proc_'::kmp_set_affinity_mask_proc
!dec$ attributes alias:'kmp_unset_affinity_mask_proc_'::kmp_unset_affinity_mask_proc
!dec$ attributes alias:'kmp_get_affinity_mask_proc_'::kmp_get_affinity_mask_proc
!dec$ attributes alias:'kmp_malloc_'::kmp_malloc
!dec$ attributes alias:'kmp_aligned_malloc_'::kmp_aligned_malloc
!dec$ attributes alias:'kmp_calloc_'::kmp_calloc
!dec$ attributes alias:'kmp_realloc_'::kmp_realloc
!dec$ attributes alias:'kmp_free_'::kmp_free
!dec$ attributes alias:'kmp_set_warnings_on_'::kmp_set_warnings_on
!dec$ attributes alias:'kmp_set_warnings_off_'::kmp_set_warnings_off
!dec$ attributes alias:'kmp_get_cancellation_status_'::kmp_get_cancellation_status
!dec$ endif
!dec$ if defined(__APPLE__)
!***
!*** The Mac entry points are in lowercase, with an both an underscore
!*** appended and an underscore prepended.
!***
!dec$ attributes alias:'_omp_set_num_threads_'::omp_set_num_threads
!dec$ attributes alias:'_omp_set_dynamic_'::omp_set_dynamic
!dec$ attributes alias:'_omp_set_nested_'::omp_set_nested
!dec$ attributes alias:'_omp_get_num_threads_'::omp_get_num_threads
!dec$ attributes alias:'_omp_get_max_threads_'::omp_get_max_threads
!dec$ attributes alias:'_omp_get_thread_num_'::omp_get_thread_num
!dec$ attributes alias:'_omp_get_num_procs_'::omp_get_num_procs
!dec$ attributes alias:'_omp_in_parallel_'::omp_in_parallel
!dec$ attributes alias:'_omp_get_dynamic_'::omp_get_dynamic
!dec$ attributes alias:'_omp_get_nested_'::omp_get_nested
!dec$ attributes alias:'_omp_get_thread_limit_'::omp_get_thread_limit
!dec$ attributes alias:'_omp_set_max_active_levels_'::omp_set_max_active_levels
!dec$ attributes alias:'_omp_get_max_active_levels_'::omp_get_max_active_levels
!dec$ attributes alias:'_omp_get_level_'::omp_get_level
!dec$ attributes alias:'_omp_get_active_level_'::omp_get_active_level
!dec$ attributes alias:'_omp_get_ancestor_thread_num_'::omp_get_ancestor_thread_num
!dec$ attributes alias:'_omp_get_team_size_'::omp_get_team_size
!dec$ attributes alias:'_omp_set_schedule_'::omp_set_schedule
!dec$ attributes alias:'_omp_get_schedule_'::omp_get_schedule
!dec$ attributes alias:'_omp_get_proc_bind_' :: omp_get_proc_bind
!dec$ attributes alias:'_omp_get_wtime_'::omp_get_wtime
!dec$ attributes alias:'_omp_get_wtick_'::omp_get_wtick
!dec$ attributes alias:'_omp_get_num_teams_'::omp_get_num_teams
!dec$ attributes alias:'_omp_get_team_num_'::omp_get_team_num
!dec$ attributes alias:'_omp_get_cancellation_'::omp_get_cancellation
!dec$ attributes alias:'_omp_is_initial_device_'::omp_is_initial_device
!dec$ attributes alias:'_omp_get_max_task_priorty_'::omp_get_max_task_priority
!dec$ attributes alias:'_omp_init_lock_'::omp_init_lock
!dec$ attributes alias:'_omp_init_lock_with_hint_'::omp_init_lock_with_hint
!dec$ attributes alias:'_omp_destroy_lock_'::omp_destroy_lock
!dec$ attributes alias:'_omp_set_lock_'::omp_set_lock
!dec$ attributes alias:'_omp_unset_lock_'::omp_unset_lock
!dec$ attributes alias:'_omp_test_lock_'::omp_test_lock
!dec$ attributes alias:'_omp_init_nest_lock_'::omp_init_nest_lock
!dec$ attributes alias:'_omp_init_nest_lock_with_hint_'::omp_init_nest_lock_with_hint
!dec$ attributes alias:'_omp_destroy_nest_lock_'::omp_destroy_nest_lock
!dec$ attributes alias:'_omp_set_nest_lock_'::omp_set_nest_lock
!dec$ attributes alias:'_omp_unset_nest_lock_'::omp_unset_nest_lock
!dec$ attributes alias:'_omp_test_nest_lock_'::omp_test_nest_lock
!dec$ attributes alias:'_omp_control_tool_'::omp_control_tool
!dec$ attributes alias:'_kmp_set_stacksize_'::kmp_set_stacksize
!dec$ attributes alias:'_kmp_set_stacksize_s_'::kmp_set_stacksize_s
!dec$ attributes alias:'_kmp_set_blocktime_'::kmp_set_blocktime
!dec$ attributes alias:'_kmp_set_library_serial_'::kmp_set_library_serial
!dec$ attributes alias:'_kmp_set_library_turnaround_'::kmp_set_library_turnaround
!dec$ attributes alias:'_kmp_set_library_throughput_'::kmp_set_library_throughput
!dec$ attributes alias:'_kmp_set_library_'::kmp_set_library
!dec$ attributes alias:'_kmp_get_stacksize_'::kmp_get_stacksize
!dec$ attributes alias:'_kmp_get_stacksize_s_'::kmp_get_stacksize_s
!dec$ attributes alias:'_kmp_get_blocktime_'::kmp_get_blocktime
!dec$ attributes alias:'_kmp_get_library_'::kmp_get_library
!dec$ attributes alias:'_kmp_set_affinity_'::kmp_set_affinity
!dec$ attributes alias:'_kmp_get_affinity_'::kmp_get_affinity
!dec$ attributes alias:'_kmp_get_affinity_max_proc_'::kmp_get_affinity_max_proc
!dec$ attributes alias:'_kmp_create_affinity_mask_'::kmp_create_affinity_mask
!dec$ attributes alias:'_kmp_destroy_affinity_mask_'::kmp_destroy_affinity_mask
!dec$ attributes alias:'_kmp_set_affinity_mask_proc_'::kmp_set_affinity_mask_proc
!dec$ attributes alias:'_kmp_unset_affinity_mask_proc_'::kmp_unset_affinity_mask_proc
!dec$ attributes alias:'_kmp_get_affinity_mask_proc_'::kmp_get_affinity_mask_proc
!dec$ attributes alias:'_kmp_malloc_'::kmp_malloc
!dec$ attributes alias:'_kmp_aligned_malloc_'::kmp_aligned_malloc
!dec$ attributes alias:'_kmp_calloc_'::kmp_calloc
!dec$ attributes alias:'_kmp_realloc_'::kmp_realloc
!dec$ attributes alias:'_kmp_free_'::kmp_free
!dec$ attributes alias:'_kmp_set_warnings_on_'::kmp_set_warnings_on
!dec$ attributes alias:'_kmp_set_warnings_off_'::kmp_set_warnings_off
!dec$ attributes alias:'_kmp_get_cancellation_status_'::kmp_get_cancellation_status
!dec$ endif
end module omp_lib
+543
View File
@@ -0,0 +1,543 @@
! include/50/omp_lib.f90.var
!
!//===----------------------------------------------------------------------===//
!//
!// 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.
!//
!//===----------------------------------------------------------------------===//
!
module omp_lib_kinds
use, intrinsic :: iso_c_binding
integer, parameter :: omp_integer_kind = c_int
integer, parameter :: omp_logical_kind = 4
integer, parameter :: omp_real_kind = c_float
integer, parameter :: kmp_double_kind = c_double
integer, parameter :: omp_lock_kind = c_intptr_t
integer, parameter :: omp_nest_lock_kind = c_intptr_t
integer, parameter :: omp_sched_kind = omp_integer_kind
integer, parameter :: omp_proc_bind_kind = omp_integer_kind
integer, parameter :: kmp_pointer_kind = c_intptr_t
integer, parameter :: kmp_size_t_kind = c_size_t
integer, parameter :: kmp_affinity_mask_kind = c_intptr_t
integer, parameter :: kmp_cancel_kind = omp_integer_kind
integer, parameter :: omp_lock_hint_kind = omp_integer_kind
integer, parameter :: omp_control_tool_kind = omp_integer_kind
integer, parameter :: omp_control_tool_result_kind = omp_integer_kind
end module omp_lib_kinds
module omp_lib
use omp_lib_kinds
integer (kind=omp_integer_kind), parameter :: openmp_version = @LIBOMP_OMP_YEAR_MONTH@
integer (kind=omp_integer_kind), parameter :: kmp_version_major = @LIBOMP_VERSION_MAJOR@
integer (kind=omp_integer_kind), parameter :: kmp_version_minor = @LIBOMP_VERSION_MINOR@
integer (kind=omp_integer_kind), parameter :: kmp_version_build = @LIBOMP_VERSION_BUILD@
character(*) kmp_build_date
parameter( kmp_build_date = '@LIBOMP_BUILD_DATE@' )
integer(kind=omp_sched_kind), parameter :: omp_sched_static = 1
integer(kind=omp_sched_kind), parameter :: omp_sched_dynamic = 2
integer(kind=omp_sched_kind), parameter :: omp_sched_guided = 3
integer(kind=omp_sched_kind), parameter :: omp_sched_auto = 4
integer (kind=omp_proc_bind_kind), parameter :: omp_proc_bind_false = 0
integer (kind=omp_proc_bind_kind), parameter :: omp_proc_bind_true = 1
integer (kind=omp_proc_bind_kind), parameter :: omp_proc_bind_master = 2
integer (kind=omp_proc_bind_kind), parameter :: omp_proc_bind_close = 3
integer (kind=omp_proc_bind_kind), parameter :: omp_proc_bind_spread = 4
integer (kind=kmp_cancel_kind), parameter :: kmp_cancel_parallel = 1
integer (kind=kmp_cancel_kind), parameter :: kmp_cancel_loop = 2
integer (kind=kmp_cancel_kind), parameter :: kmp_cancel_sections = 3
integer (kind=kmp_cancel_kind), parameter :: kmp_cancel_taskgroup = 4
integer (kind=omp_lock_hint_kind), parameter :: omp_lock_hint_none = 0
integer (kind=omp_lock_hint_kind), parameter :: omp_lock_hint_uncontended = 1
integer (kind=omp_lock_hint_kind), parameter :: omp_lock_hint_contended = 2
integer (kind=omp_lock_hint_kind), parameter :: omp_lock_hint_nonspeculative = 4
integer (kind=omp_lock_hint_kind), parameter :: omp_lock_hint_speculative = 8
integer (kind=omp_lock_hint_kind), parameter :: kmp_lock_hint_hle = 65536
integer (kind=omp_lock_hint_kind), parameter :: kmp_lock_hint_rtm = 131072
integer (kind=omp_lock_hint_kind), parameter :: kmp_lock_hint_adaptive = 262144
integer (kind=omp_control_tool_kind), parameter :: omp_control_tool_start = 1
integer (kind=omp_control_tool_kind), parameter :: omp_control_tool_pause = 2
integer (kind=omp_control_tool_kind), parameter :: omp_control_tool_flush = 3
integer (kind=omp_control_tool_kind), parameter :: omp_control_tool_end = 4
integer (kind=omp_control_tool_result_kind), parameter :: omp_control_tool_notool = -2
integer (kind=omp_control_tool_result_kind), parameter :: omp_control_tool_nocallback = -1
integer (kind=omp_control_tool_result_kind), parameter :: omp_control_tool_success = 0
integer (kind=omp_control_tool_result_kind), parameter :: omp_control_tool_ignored = 1
interface
! ***
! *** omp_* entry points
! ***
subroutine omp_set_num_threads(num_threads) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind), value :: num_threads
end subroutine omp_set_num_threads
subroutine omp_set_dynamic(dynamic_threads) bind(c)
use omp_lib_kinds
logical (kind=omp_logical_kind), value :: dynamic_threads
end subroutine omp_set_dynamic
subroutine omp_set_nested(nested) bind(c)
use omp_lib_kinds
logical (kind=omp_logical_kind), value :: nested
end subroutine omp_set_nested
function omp_get_num_threads() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_num_threads
end function omp_get_num_threads
function omp_get_max_threads() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_max_threads
end function omp_get_max_threads
function omp_get_thread_num() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_thread_num
end function omp_get_thread_num
function omp_get_num_procs() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_num_procs
end function omp_get_num_procs
function omp_in_parallel() bind(c)
use omp_lib_kinds
logical (kind=omp_logical_kind) omp_in_parallel
end function omp_in_parallel
function omp_in_final() bind(c)
use omp_lib_kinds
logical (kind=omp_logical_kind) omp_in_final
end function omp_in_final
function omp_get_dynamic() bind(c)
use omp_lib_kinds
logical (kind=omp_logical_kind) omp_get_dynamic
end function omp_get_dynamic
function omp_get_nested() bind(c)
use omp_lib_kinds
logical (kind=omp_logical_kind) omp_get_nested
end function omp_get_nested
function omp_get_thread_limit() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_thread_limit
end function omp_get_thread_limit
subroutine omp_set_max_active_levels(max_levels) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind), value :: max_levels
end subroutine omp_set_max_active_levels
function omp_get_max_active_levels() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_max_active_levels
end function omp_get_max_active_levels
function omp_get_level() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_level
end function omp_get_level
function omp_get_active_level() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_active_level
end function omp_get_active_level
function omp_get_ancestor_thread_num(level) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_ancestor_thread_num
integer (kind=omp_integer_kind), value :: level
end function omp_get_ancestor_thread_num
function omp_get_team_size(level) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_team_size
integer (kind=omp_integer_kind), value :: level
end function omp_get_team_size
subroutine omp_set_schedule(kind, chunk_size) bind(c)
use omp_lib_kinds
integer (kind=omp_sched_kind), value :: kind
integer (kind=omp_integer_kind), value :: chunk_size
end subroutine omp_set_schedule
subroutine omp_get_schedule(kind, chunk_size) bind(c)
use omp_lib_kinds
integer (kind=omp_sched_kind) kind
integer (kind=omp_integer_kind) chunk_size
end subroutine omp_get_schedule
function omp_get_proc_bind() bind(c)
use omp_lib_kinds
integer (kind=omp_proc_bind_kind) omp_get_proc_bind
end function omp_get_proc_bind
function omp_get_num_places() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_num_places
end function omp_get_num_places
function omp_get_place_num_procs(place_num) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind), value :: place_num
integer (kind=omp_integer_kind) omp_get_place_num_procs
end function omp_get_place_num_procs
subroutine omp_get_place_proc_ids(place_num, ids) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind), value :: place_num
integer (kind=omp_integer_kind) ids(*)
end subroutine omp_get_place_proc_ids
function omp_get_place_num() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_place_num
end function omp_get_place_num
function omp_get_partition_num_places() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_partition_num_places
end function omp_get_partition_num_places
subroutine omp_get_partition_place_nums(place_nums) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) place_nums(*)
end subroutine omp_get_partition_place_nums
function omp_get_wtime() bind(c)
use omp_lib_kinds
real (kind=kmp_double_kind) omp_get_wtime
end function omp_get_wtime
function omp_get_wtick() bind(c)
use omp_lib_kinds
real (kind=kmp_double_kind) omp_get_wtick
end function omp_get_wtick
function omp_get_default_device() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_default_device
end function omp_get_default_device
subroutine omp_set_default_device(device_num) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind), value :: device_num
end subroutine omp_set_default_device
function omp_get_num_devices() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_num_devices
end function omp_get_num_devices
function omp_get_num_teams() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_num_teams
end function omp_get_num_teams
function omp_get_team_num() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_team_num
end function omp_get_team_num
function omp_get_cancellation() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_cancellation
end function omp_get_cancellation
function omp_is_initial_device() bind(c)
use omp_lib_kinds
logical (kind=omp_logical_kind) omp_is_initial_device
end function omp_is_initial_device
function omp_get_initial_device() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_initial_device
end function omp_get_initial_device
subroutine omp_init_lock(svar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_init_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_lock_kind) svar
end subroutine omp_init_lock
subroutine omp_destroy_lock(svar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_destroy_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_lock_kind) svar
end subroutine omp_destroy_lock
subroutine omp_set_lock(svar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_set_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_lock_kind) svar
end subroutine omp_set_lock
subroutine omp_unset_lock(svar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_unset_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_lock_kind) svar
end subroutine omp_unset_lock
function omp_test_lock(svar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_test_lock
!DIR$ ENDIF
use omp_lib_kinds
logical (kind=omp_logical_kind) omp_test_lock
integer (kind=omp_lock_kind) svar
end function omp_test_lock
subroutine omp_init_nest_lock(nvar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_init_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_init_nest_lock
subroutine omp_destroy_nest_lock(nvar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_destroy_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_destroy_nest_lock
subroutine omp_set_nest_lock(nvar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_set_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_set_nest_lock
subroutine omp_unset_nest_lock(nvar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_unset_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_unset_nest_lock
function omp_test_nest_lock(nvar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_test_nest_lock
!DIR$ ENDIF
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_test_nest_lock
integer (kind=omp_nest_lock_kind) nvar
end function omp_test_nest_lock
function omp_get_max_task_priority() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_get_max_task_priority
end function omp_get_max_task_priority
! ***
! *** kmp_* entry points
! ***
subroutine kmp_set_stacksize(size) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind), value :: size
end subroutine kmp_set_stacksize
subroutine kmp_set_stacksize_s(size) bind(c)
use omp_lib_kinds
integer (kind=kmp_size_t_kind), value :: size
end subroutine kmp_set_stacksize_s
subroutine kmp_set_blocktime(msec) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind), value :: msec
end subroutine kmp_set_blocktime
subroutine kmp_set_library_serial() bind(c)
end subroutine kmp_set_library_serial
subroutine kmp_set_library_turnaround() bind(c)
end subroutine kmp_set_library_turnaround
subroutine kmp_set_library_throughput() bind(c)
end subroutine kmp_set_library_throughput
subroutine kmp_set_library(libnum) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind), value :: libnum
end subroutine kmp_set_library
subroutine kmp_set_defaults(string) bind(c)
use, intrinsic :: iso_c_binding
character (kind=c_char) :: string(*)
end subroutine kmp_set_defaults
function kmp_get_stacksize() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) kmp_get_stacksize
end function kmp_get_stacksize
function kmp_get_stacksize_s() bind(c)
use omp_lib_kinds
integer (kind=kmp_size_t_kind) kmp_get_stacksize_s
end function kmp_get_stacksize_s
function kmp_get_blocktime() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) kmp_get_blocktime
end function kmp_get_blocktime
function kmp_get_library() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) kmp_get_library
end function kmp_get_library
subroutine kmp_set_disp_num_buffers(num) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind), value :: num
end subroutine kmp_set_disp_num_buffers
function kmp_set_affinity(mask) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) kmp_set_affinity
integer (kind=kmp_affinity_mask_kind) mask
end function kmp_set_affinity
function kmp_get_affinity(mask) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) kmp_get_affinity
integer (kind=kmp_affinity_mask_kind) mask
end function kmp_get_affinity
function kmp_get_affinity_max_proc() bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) kmp_get_affinity_max_proc
end function kmp_get_affinity_max_proc
subroutine kmp_create_affinity_mask(mask) bind(c)
use omp_lib_kinds
integer (kind=kmp_affinity_mask_kind) mask
end subroutine kmp_create_affinity_mask
subroutine kmp_destroy_affinity_mask(mask) bind(c)
use omp_lib_kinds
integer (kind=kmp_affinity_mask_kind) mask
end subroutine kmp_destroy_affinity_mask
function kmp_set_affinity_mask_proc(proc, mask) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) kmp_set_affinity_mask_proc
integer (kind=omp_integer_kind), value :: proc
integer (kind=kmp_affinity_mask_kind) mask
end function kmp_set_affinity_mask_proc
function kmp_unset_affinity_mask_proc(proc, mask) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) kmp_unset_affinity_mask_proc
integer (kind=omp_integer_kind), value :: proc
integer (kind=kmp_affinity_mask_kind) mask
end function kmp_unset_affinity_mask_proc
function kmp_get_affinity_mask_proc(proc, mask) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) kmp_get_affinity_mask_proc
integer (kind=omp_integer_kind), value :: proc
integer (kind=kmp_affinity_mask_kind) mask
end function kmp_get_affinity_mask_proc
function kmp_malloc(size) bind(c)
use omp_lib_kinds
integer (kind=kmp_pointer_kind) kmp_malloc
integer (kind=kmp_size_t_kind), value :: size
end function kmp_malloc
function kmp_aligned_malloc(size, alignment) bind(c)
use omp_lib_kinds
integer (kind=kmp_pointer_kind) kmp_aligned_malloc
integer (kind=kmp_size_t_kind), value :: size
integer (kind=kmp_size_t_kind), value :: alignment
end function kmp_aligned_malloc
function kmp_calloc(nelem, elsize) bind(c)
use omp_lib_kinds
integer (kind=kmp_pointer_kind) kmp_calloc
integer (kind=kmp_size_t_kind), value :: nelem
integer (kind=kmp_size_t_kind), value :: elsize
end function kmp_calloc
function kmp_realloc(ptr, size) bind(c)
use omp_lib_kinds
integer (kind=kmp_pointer_kind) kmp_realloc
integer (kind=kmp_pointer_kind), value :: ptr
integer (kind=kmp_size_t_kind), value :: size
end function kmp_realloc
subroutine kmp_free(ptr) bind(c)
use omp_lib_kinds
integer (kind=kmp_pointer_kind), value :: ptr
end subroutine kmp_free
subroutine kmp_set_warnings_on() bind(c)
end subroutine kmp_set_warnings_on
subroutine kmp_set_warnings_off() bind(c)
end subroutine kmp_set_warnings_off
function kmp_get_cancellation_status(cancelkind) bind(c)
use omp_lib_kinds
integer (kind=kmp_cancel_kind), value :: cancelkind
logical (kind=omp_logical_kind) kmp_get_cancellation_status
end function kmp_get_cancellation_status
subroutine omp_init_lock_with_hint(svar, hint) bind(c)
use omp_lib_kinds
integer (kind=omp_lock_kind) svar
integer (kind=omp_lock_hint_kind), value :: hint
end subroutine omp_init_lock_with_hint
subroutine omp_init_nest_lock_with_hint(nvar, hint) bind(c)
use omp_lib_kinds
integer (kind=omp_nest_lock_kind) nvar
integer (kind=omp_lock_hint_kind), value :: hint
end subroutine omp_init_nest_lock_with_hint
function omp_control_tool(command, modifier) bind(c)
use omp_lib_kinds
integer (kind=omp_integer_kind) omp_control_tool
integer (kind=omp_control_tool_kind), value :: command
integer (kind=omp_control_tool_kind), value :: modifier
end function omp_control_tool
end interface
end module omp_lib
+663
View File
@@ -0,0 +1,663 @@
! include/50/omp_lib.h.var
!
!//===----------------------------------------------------------------------===//
!//
!// 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.
!//
!//===----------------------------------------------------------------------===//
!
!***
!*** Some of the directives for the following routine extend past column 72,
!*** so process this file in 132-column mode.
!***
!DIR$ fixedformlinesize:132
integer, parameter :: omp_integer_kind = 4
integer, parameter :: omp_logical_kind = 4
integer, parameter :: omp_real_kind = 4
integer, parameter :: omp_lock_kind = int_ptr_kind()
integer, parameter :: omp_nest_lock_kind = int_ptr_kind()
integer, parameter :: omp_sched_kind = omp_integer_kind
integer, parameter :: omp_proc_bind_kind = omp_integer_kind
integer, parameter :: kmp_pointer_kind = int_ptr_kind()
integer, parameter :: kmp_size_t_kind = int_ptr_kind()
integer, parameter :: kmp_affinity_mask_kind = int_ptr_kind()
integer, parameter :: omp_lock_hint_kind = omp_integer_kind
integer, parameter :: omp_control_tool_kind = omp_integer_kind
integer, parameter :: omp_control_tool_result_kind = omp_integer_kind
integer (kind=omp_integer_kind), parameter :: openmp_version = @LIBOMP_OMP_YEAR_MONTH@
integer (kind=omp_integer_kind), parameter :: kmp_version_major = @LIBOMP_VERSION_MAJOR@
integer (kind=omp_integer_kind), parameter :: kmp_version_minor = @LIBOMP_VERSION_MINOR@
integer (kind=omp_integer_kind), parameter :: kmp_version_build = @LIBOMP_VERSION_BUILD@
character(*) kmp_build_date
parameter( kmp_build_date = '@LIBOMP_BUILD_DATE@' )
integer(kind=omp_sched_kind), parameter :: omp_sched_static = 1
integer(kind=omp_sched_kind), parameter :: omp_sched_dynamic = 2
integer(kind=omp_sched_kind), parameter :: omp_sched_guided = 3
integer(kind=omp_sched_kind), parameter :: omp_sched_auto = 4
integer (kind=omp_proc_bind_kind), parameter :: omp_proc_bind_false = 0
integer (kind=omp_proc_bind_kind), parameter :: omp_proc_bind_true = 1
integer (kind=omp_proc_bind_kind), parameter :: omp_proc_bind_master = 2
integer (kind=omp_proc_bind_kind), parameter :: omp_proc_bind_close = 3
integer (kind=omp_proc_bind_kind), parameter :: omp_proc_bind_spread = 4
integer (kind=omp_lock_hint_kind), parameter :: omp_lock_hint_none = 0
integer (kind=omp_lock_hint_kind), parameter :: omp_lock_hint_uncontended = 1
integer (kind=omp_lock_hint_kind), parameter :: omp_lock_hint_contended = 2
integer (kind=omp_lock_hint_kind), parameter :: omp_lock_hint_nonspeculative = 4
integer (kind=omp_lock_hint_kind), parameter :: omp_lock_hint_speculative = 8
integer (kind=omp_lock_hint_kind), parameter :: kmp_lock_hint_hle = 65536
integer (kind=omp_lock_hint_kind), parameter :: kmp_lock_hint_rtm = 131072
integer (kind=omp_lock_hint_kind), parameter :: kmp_lock_hint_adaptive = 262144
integer (kind=omp_control_tool_kind), parameter :: omp_control_tool_start = 1
integer (kind=omp_control_tool_kind), parameter :: omp_control_tool_pause = 2
integer (kind=omp_control_tool_kind), parameter :: omp_control_tool_flush = 3
integer (kind=omp_control_tool_kind), parameter :: omp_control_tool_end = 4
integer (kind=omp_control_tool_result_kind), parameter :: omp_control_tool_notool = -2
integer (kind=omp_control_tool_result_kind), parameter :: omp_control_tool_nocallback = -1
integer (kind=omp_control_tool_result_kind), parameter :: omp_control_tool_success = 0
integer (kind=omp_control_tool_result_kind), parameter :: omp_control_tool_ignored = 1
interface
! ***
! *** omp_* entry points
! ***
subroutine omp_set_num_threads(num_threads) bind(c)
import
integer (kind=omp_integer_kind), value :: num_threads
end subroutine omp_set_num_threads
subroutine omp_set_dynamic(dynamic_threads) bind(c)
import
logical (kind=omp_logical_kind), value :: dynamic_threads
end subroutine omp_set_dynamic
subroutine omp_set_nested(nested) bind(c)
import
logical (kind=omp_logical_kind), value :: nested
end subroutine omp_set_nested
function omp_get_num_threads() bind(c)
import
integer (kind=omp_integer_kind) omp_get_num_threads
end function omp_get_num_threads
function omp_get_max_threads() bind(c)
import
integer (kind=omp_integer_kind) omp_get_max_threads
end function omp_get_max_threads
function omp_get_thread_num() bind(c)
import
integer (kind=omp_integer_kind) omp_get_thread_num
end function omp_get_thread_num
function omp_get_num_procs() bind(c)
import
integer (kind=omp_integer_kind) omp_get_num_procs
end function omp_get_num_procs
function omp_in_parallel() bind(c)
import
logical (kind=omp_logical_kind) omp_in_parallel
end function omp_in_parallel
function omp_in_final() bind(c)
import
logical (kind=omp_logical_kind) omp_in_final
end function omp_in_final
function omp_get_dynamic() bind(c)
import
logical (kind=omp_logical_kind) omp_get_dynamic
end function omp_get_dynamic
function omp_get_nested() bind(c)
import
logical (kind=omp_logical_kind) omp_get_nested
end function omp_get_nested
function omp_get_thread_limit() bind(c)
import
integer (kind=omp_integer_kind) omp_get_thread_limit
end function omp_get_thread_limit
subroutine omp_set_max_active_levels(max_levels) bind(c)
import
integer (kind=omp_integer_kind), value :: max_levels
end subroutine omp_set_max_active_levels
function omp_get_max_active_levels() bind(c)
import
integer (kind=omp_integer_kind) omp_get_max_active_levels
end function omp_get_max_active_levels
function omp_get_level() bind(c)
import
integer (kind=omp_integer_kind) omp_get_level
end function omp_get_level
function omp_get_active_level() bind(c)
import
integer (kind=omp_integer_kind) omp_get_active_level
end function omp_get_active_level
function omp_get_ancestor_thread_num(level) bind(c)
import
integer (kind=omp_integer_kind) omp_get_ancestor_thread_num
integer (kind=omp_integer_kind), value :: level
end function omp_get_ancestor_thread_num
function omp_get_team_size(level) bind(c)
import
integer (kind=omp_integer_kind) omp_get_team_size
integer (kind=omp_integer_kind), value :: level
end function omp_get_team_size
subroutine omp_set_schedule(kind, chunk_size) bind(c)
import
integer (kind=omp_sched_kind), value :: kind
integer (kind=omp_integer_kind), value :: chunk_size
end subroutine omp_set_schedule
subroutine omp_get_schedule(kind, chunk_size) bind(c)
import
integer (kind=omp_sched_kind) kind
integer (kind=omp_integer_kind) chunk_size
end subroutine omp_get_schedule
function omp_get_proc_bind() bind(c)
import
integer (kind=omp_proc_bind_kind) omp_get_proc_bind
end function omp_get_proc_bind
function omp_get_num_places() bind(c)
import
integer (kind=omp_integer_kind) omp_get_num_places
end function omp_get_num_places
function omp_get_place_num_procs(place_num) bind(c)
import
integer (kind=omp_integer_kind), value :: place_num
integer (kind=omp_integer_kind) omp_get_place_num_procs
end function omp_get_place_num_procs
subroutine omp_get_place_proc_ids(place_num, ids) bind(c)
import
integer (kind=omp_integer_kind), value :: place_num
integer (kind=omp_integer_kind) ids(*)
end subroutine omp_get_place_proc_ids
function omp_get_place_num() bind(c)
import
integer (kind=omp_integer_kind) omp_get_place_num
end function omp_get_place_num
function omp_get_partition_num_places() bind(c)
import
integer (kind=omp_integer_kind) omp_get_partition_num_places
end function omp_get_partition_num_places
subroutine omp_get_partition_place_nums(place_nums) bind(c)
import
integer (kind=omp_integer_kind) place_nums(*)
end subroutine omp_get_partition_place_nums
function omp_get_wtime() bind(c)
double precision omp_get_wtime
end function omp_get_wtime
function omp_get_wtick() bind(c)
double precision omp_get_wtick
end function omp_get_wtick
function omp_get_default_device() bind(c)
import
integer (kind=omp_integer_kind) omp_get_default_device
end function omp_get_default_device
subroutine omp_set_default_device(device_num) bind(c)
import
integer (kind=omp_integer_kind), value :: device_num
end subroutine omp_set_default_device
function omp_get_num_devices() bind(c)
import
integer (kind=omp_integer_kind) omp_get_num_devices
end function omp_get_num_devices
function omp_get_num_teams() bind(c)
import
integer (kind=omp_integer_kind) omp_get_num_teams
end function omp_get_num_teams
function omp_get_team_num() bind(c)
import
integer (kind=omp_integer_kind) omp_get_team_num
end function omp_get_team_num
function omp_is_initial_device() bind(c)
import
logical (kind=omp_logical_kind) omp_is_initial_device
end function omp_is_initial_device
function omp_get_initial_device() bind(c)
import
integer (kind=omp_integer_kind) omp_get_initial_device
end function omp_get_initial_device
subroutine omp_init_lock(svar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_init_lock
!DIR$ ENDIF
import
integer (kind=omp_lock_kind) svar
end subroutine omp_init_lock
subroutine omp_destroy_lock(svar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_destroy_lock
!DIR$ ENDIF
import
integer (kind=omp_lock_kind) svar
end subroutine omp_destroy_lock
subroutine omp_set_lock(svar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_set_lock
!DIR$ ENDIF
import
integer (kind=omp_lock_kind) svar
end subroutine omp_set_lock
subroutine omp_unset_lock(svar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_unset_lock
!DIR$ ENDIF
import
integer (kind=omp_lock_kind) svar
end subroutine omp_unset_lock
function omp_test_lock(svar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_test_lock
!DIR$ ENDIF
import
logical (kind=omp_logical_kind) omp_test_lock
integer (kind=omp_lock_kind) svar
end function omp_test_lock
subroutine omp_init_nest_lock(nvar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_init_nest_lock
!DIR$ ENDIF
import
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_init_nest_lock
subroutine omp_destroy_nest_lock(nvar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_destroy_nest_lock
!DIR$ ENDIF
import
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_destroy_nest_lock
subroutine omp_set_nest_lock(nvar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_set_nest_lock
!DIR$ ENDIF
import
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_set_nest_lock
subroutine omp_unset_nest_lock(nvar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_unset_nest_lock
!DIR$ ENDIF
import
integer (kind=omp_nest_lock_kind) nvar
end subroutine omp_unset_nest_lock
function omp_test_nest_lock(nvar) bind(c)
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!DIR$ attributes known_intrinsic :: omp_test_nest_lock
!DIR$ ENDIF
import
integer (kind=omp_integer_kind) omp_test_nest_lock
integer (kind=omp_nest_lock_kind) nvar
end function omp_test_nest_lock
function omp_get_max_task_priority() bind(c)
import
integer (kind=omp_integer_kind) omp_get_max_task_priority
end function omp_get_max_task_priority
! ***
! *** kmp_* entry points
! ***
subroutine kmp_set_stacksize(size) bind(c)
import
integer (kind=omp_integer_kind), value :: size
end subroutine kmp_set_stacksize
subroutine kmp_set_stacksize_s(size) bind(c)
import
integer (kind=kmp_size_t_kind), value :: size
end subroutine kmp_set_stacksize_s
subroutine kmp_set_blocktime(msec) bind(c)
import
integer (kind=omp_integer_kind), value :: msec
end subroutine kmp_set_blocktime
subroutine kmp_set_library_serial() bind(c)
end subroutine kmp_set_library_serial
subroutine kmp_set_library_turnaround() bind(c)
end subroutine kmp_set_library_turnaround
subroutine kmp_set_library_throughput() bind(c)
end subroutine kmp_set_library_throughput
subroutine kmp_set_library(libnum) bind(c)
import
integer (kind=omp_integer_kind), value :: libnum
end subroutine kmp_set_library
subroutine kmp_set_defaults(string) bind(c)
character string(*)
end subroutine kmp_set_defaults
function kmp_get_stacksize() bind(c)
import
integer (kind=omp_integer_kind) kmp_get_stacksize
end function kmp_get_stacksize
function kmp_get_stacksize_s() bind(c)
import
integer (kind=kmp_size_t_kind) kmp_get_stacksize_s
end function kmp_get_stacksize_s
function kmp_get_blocktime() bind(c)
import
integer (kind=omp_integer_kind) kmp_get_blocktime
end function kmp_get_blocktime
function kmp_get_library() bind(c)
import
integer (kind=omp_integer_kind) kmp_get_library
end function kmp_get_library
subroutine kmp_set_disp_num_buffers(num) bind(c)
import
integer (kind=omp_integer_kind), value :: num
end subroutine kmp_set_disp_num_buffers
function kmp_set_affinity(mask) bind(c)
import
integer (kind=omp_integer_kind) kmp_set_affinity
integer (kind=kmp_affinity_mask_kind) mask
end function kmp_set_affinity
function kmp_get_affinity(mask) bind(c)
import
integer (kind=omp_integer_kind) kmp_get_affinity
integer (kind=kmp_affinity_mask_kind) mask
end function kmp_get_affinity
function kmp_get_affinity_max_proc() bind(c)
import
integer (kind=omp_integer_kind) kmp_get_affinity_max_proc
end function kmp_get_affinity_max_proc
subroutine kmp_create_affinity_mask(mask) bind(c)
import
integer (kind=kmp_affinity_mask_kind) mask
end subroutine kmp_create_affinity_mask
subroutine kmp_destroy_affinity_mask(mask) bind(c)
import
integer (kind=kmp_affinity_mask_kind) mask
end subroutine kmp_destroy_affinity_mask
function kmp_set_affinity_mask_proc(proc, mask) bind(c)
import
integer (kind=omp_integer_kind) kmp_set_affinity_mask_proc
integer (kind=omp_integer_kind), value :: proc
integer (kind=kmp_affinity_mask_kind) mask
end function kmp_set_affinity_mask_proc
function kmp_unset_affinity_mask_proc(proc, mask) bind(c)
import
integer (kind=omp_integer_kind) kmp_unset_affinity_mask_proc
integer (kind=omp_integer_kind), value :: proc
integer (kind=kmp_affinity_mask_kind) mask
end function kmp_unset_affinity_mask_proc
function kmp_get_affinity_mask_proc(proc, mask) bind(c)
import
integer (kind=omp_integer_kind) kmp_get_affinity_mask_proc
integer (kind=omp_integer_kind), value :: proc
integer (kind=kmp_affinity_mask_kind) mask
end function kmp_get_affinity_mask_proc
function kmp_malloc(size) bind(c)
import
integer (kind=kmp_pointer_kind) kmp_malloc
integer (kind=kmp_size_t_kind), value :: size
end function kmp_malloc
function kmp_aligned_malloc(size, alignment) bind(c)
import
integer (kind=kmp_pointer_kind) kmp_aligned_malloc
integer (kind=kmp_size_t_kind), value :: size
integer (kind=kmp_size_t_kind), value :: alignment
end function kmp_aligned_malloc
function kmp_calloc(nelem, elsize) bind(c)
import
integer (kind=kmp_pointer_kind) kmp_calloc
integer (kind=kmp_size_t_kind), value :: nelem
integer (kind=kmp_size_t_kind), value :: elsize
end function kmp_calloc
function kmp_realloc(ptr, size) bind(c)
import
integer (kind=kmp_pointer_kind) kmp_realloc
integer (kind=kmp_pointer_kind), value :: ptr
integer (kind=kmp_size_t_kind), value :: size
end function kmp_realloc
subroutine kmp_free(ptr) bind(c)
import
integer (kind=kmp_pointer_kind), value :: ptr
end subroutine kmp_free
subroutine kmp_set_warnings_on() bind(c)
end subroutine kmp_set_warnings_on
subroutine kmp_set_warnings_off() bind(c)
end subroutine kmp_set_warnings_off
subroutine omp_init_lock_with_hint(svar, hint) bind(c)
import
integer (kind=omp_lock_kind) svar
integer (kind=omp_lock_hint_kind), value :: hint
end subroutine omp_init_lock_with_hint
subroutine omp_init_nest_lock_with_hint(nvar, hint) bind(c)
import
integer (kind=omp_nest_lock_kind) nvar
integer (kind=omp_lock_hint_kind), value :: hint
end subroutine omp_init_nest_lock_with_hint
function omp_control_tool(command, modifier) bind(c)
import
integer (kind=omp_integer_kind) omp_control_tool
integer (kind=omp_control_tool_kind), value :: command
integer (kind=omp_control_tool_kind), value :: modifier
end function omp_control_tool
end interface
!DIR$ IF DEFINED (__INTEL_OFFLOAD)
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_set_num_threads
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_set_dynamic
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_set_nested
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_num_threads
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_max_threads
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_thread_num
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_num_procs
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_in_parallel
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_in_final
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_dynamic
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_nested
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_thread_limit
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_set_max_active_levels
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_max_active_levels
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_level
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_active_level
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_ancestor_thread_num
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_team_size
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_set_schedule
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_schedule
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_proc_bind
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_wtime
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_wtick
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_default_device
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_set_default_device
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_is_initial_device
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_num_devices
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_num_teams
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_team_num
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_init_lock
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_destroy_lock
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_set_lock
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_unset_lock
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_test_lock
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_init_nest_lock
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_destroy_nest_lock
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_set_nest_lock
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_unset_nest_lock
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_test_nest_lock
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_max_task_priority
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_set_stacksize
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_set_stacksize_s
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_set_blocktime
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_set_library_serial
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_set_library_turnaround
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_set_library_throughput
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_set_library
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_set_defaults
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_get_stacksize
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_get_stacksize_s
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_get_blocktime
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_get_library
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_set_disp_num_buffers
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_set_affinity
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_get_affinity
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_get_affinity_max_proc
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_create_affinity_mask
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_destroy_affinity_mask
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_set_affinity_mask_proc
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_unset_affinity_mask_proc
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_get_affinity_mask_proc
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_malloc
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_aligned_malloc
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_calloc
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_realloc
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_free
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_set_warnings_on
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_set_warnings_off
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_init_lock_with_hint
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_init_nest_lock_with_hint
!DIR$ IF(__INTEL_COMPILER.GE.1400)
!$omp declare target(omp_set_num_threads )
!$omp declare target(omp_set_dynamic )
!$omp declare target(omp_set_nested )
!$omp declare target(omp_get_num_threads )
!$omp declare target(omp_get_max_threads )
!$omp declare target(omp_get_thread_num )
!$omp declare target(omp_get_num_procs )
!$omp declare target(omp_in_parallel )
!$omp declare target(omp_in_final )
!$omp declare target(omp_get_dynamic )
!$omp declare target(omp_get_nested )
!$omp declare target(omp_get_thread_limit )
!$omp declare target(omp_set_max_active_levels )
!$omp declare target(omp_get_max_active_levels )
!$omp declare target(omp_get_level )
!$omp declare target(omp_get_active_level )
!$omp declare target(omp_get_ancestor_thread_num )
!$omp declare target(omp_get_team_size )
!$omp declare target(omp_set_schedule )
!$omp declare target(omp_get_schedule )
!$omp declare target(omp_get_proc_bind )
!$omp declare target(omp_get_wtime )
!$omp declare target(omp_get_wtick )
!$omp declare target(omp_get_default_device )
!$omp declare target(omp_set_default_device )
!$omp declare target(omp_is_initial_device )
!$omp declare target(omp_get_num_devices )
!$omp declare target(omp_get_num_teams )
!$omp declare target(omp_get_team_num )
!$omp declare target(omp_init_lock )
!$omp declare target(omp_destroy_lock )
!$omp declare target(omp_set_lock )
!$omp declare target(omp_unset_lock )
!$omp declare target(omp_test_lock )
!$omp declare target(omp_init_nest_lock )
!$omp declare target(omp_destroy_nest_lock )
!$omp declare target(omp_set_nest_lock )
!$omp declare target(omp_unset_nest_lock )
!$omp declare target(omp_test_nest_lock )
!$omp declare target(omp_get_max_task_priority )
!$omp declare target(kmp_set_stacksize )
!$omp declare target(kmp_set_stacksize_s )
!$omp declare target(kmp_set_blocktime )
!$omp declare target(kmp_set_library_serial )
!$omp declare target(kmp_set_library_turnaround )
!$omp declare target(kmp_set_library_throughput )
!$omp declare target(kmp_set_library )
!$omp declare target(kmp_set_defaults )
!$omp declare target(kmp_get_stacksize )
!$omp declare target(kmp_get_stacksize_s )
!$omp declare target(kmp_get_blocktime )
!$omp declare target(kmp_get_library )
!$omp declare target(kmp_set_disp_num_buffers )
!$omp declare target(kmp_set_affinity )
!$omp declare target(kmp_get_affinity )
!$omp declare target(kmp_get_affinity_max_proc )
!$omp declare target(kmp_create_affinity_mask )
!$omp declare target(kmp_destroy_affinity_mask )
!$omp declare target(kmp_set_affinity_mask_proc )
!$omp declare target(kmp_unset_affinity_mask_proc )
!$omp declare target(kmp_get_affinity_mask_proc )
!$omp declare target(kmp_malloc )
!$omp declare target(kmp_aligned_malloc )
!$omp declare target(kmp_calloc )
!$omp declare target(kmp_realloc )
!$omp declare target(kmp_free )
!$omp declare target(kmp_set_warnings_on )
!$omp declare target(kmp_set_warnings_off )
!$omp declare target(omp_init_lock_with_hint )
!$omp declare target(omp_init_nest_lock_with_hint )
!DIR$ ENDIF
!DIR$ ENDIF
+688
View File
@@ -0,0 +1,688 @@
/*
* include/50/ompt.h.var
*/
#ifndef __OMPT__
#define __OMPT__
/*****************************************************************************
* system include files
*****************************************************************************/
#include <stdint.h>
#include <stddef.h>
/*****************************************************************************
* iteration macros
*****************************************************************************/
#define FOREACH_OMPT_INQUIRY_FN(macro) \
macro (ompt_enumerate_states) \
macro (ompt_enumerate_mutex_impls) \
\
macro (ompt_set_callback) \
macro (ompt_get_callback) \
\
macro (ompt_get_state) \
\
macro (ompt_get_parallel_info) \
macro (ompt_get_task_info) \
macro (ompt_get_thread_data) \
macro (ompt_get_unique_id) \
\
macro(ompt_get_num_procs) \
macro(ompt_get_num_places) \
macro(ompt_get_place_proc_ids) \
macro(ompt_get_place_num) \
macro(ompt_get_partition_place_nums) \
macro(ompt_get_proc_id) \
\
macro(ompt_get_target_info) \
macro(ompt_get_num_devices)
#define FOREACH_OMP_STATE(macro) \
\
/* first available state */ \
macro (omp_state_undefined, 0x102) /* undefined thread state */ \
\
/* work states (0..15) */ \
macro (omp_state_work_serial, 0x000) /* working outside parallel */ \
macro (omp_state_work_parallel, 0x001) /* working within parallel */ \
macro (omp_state_work_reduction, 0x002) /* performing a reduction */ \
\
/* barrier wait states (16..31) */ \
macro (omp_state_wait_barrier, 0x010) /* waiting at a barrier */ \
macro (omp_state_wait_barrier_implicit_parallel, 0x011) \
/* implicit barrier at the end of parallel region */\
macro (omp_state_wait_barrier_implicit_workshare, 0x012) \
/* implicit barrier at the end of worksharing */ \
macro (omp_state_wait_barrier_implicit, 0x013) /* implicit barrier */ \
macro (omp_state_wait_barrier_explicit, 0x014) /* explicit barrier */ \
\
/* task wait states (32..63) */ \
macro (omp_state_wait_taskwait, 0x020) /* waiting at a taskwait */ \
macro (omp_state_wait_taskgroup, 0x021) /* waiting at a taskgroup */ \
\
/* mutex wait states (64..127) */ \
macro (omp_state_wait_mutex, 0x040) \
macro (omp_state_wait_lock, 0x041) /* waiting for lock */ \
macro (omp_state_wait_critical, 0x042) /* waiting for critical */ \
macro (omp_state_wait_atomic, 0x043) /* waiting for atomic */ \
macro (omp_state_wait_ordered, 0x044) /* waiting for ordered */ \
\
/* target wait states (128..255) */ \
macro (omp_state_wait_target, 0x080) /* waiting for target region */ \
macro (omp_state_wait_target_map, 0x081) /* waiting for target data mapping operation */ \
macro (omp_state_wait_target_update, 0x082) /* waiting for target update operation */ \
\
/* misc (256..511) */ \
macro (omp_state_idle, 0x100) /* waiting for work */ \
macro (omp_state_overhead, 0x101) /* overhead excluding wait states */ \
\
/* implementation-specific states (512..) */
#define FOREACH_OMPT_MUTEX_IMPL(macro) \
macro (ompt_mutex_impl_unknown, 0) /* unknown implementatin */ \
macro (ompt_mutex_impl_spin, 1) /* based on spin */ \
macro (ompt_mutex_impl_queuing, 2) /* based on some fair policy */ \
macro (ompt_mutex_impl_speculative, 3) /* based on HW-supported speculation */
#define FOREACH_OMPT_EVENT(macro) \
\
/*--- Mandatory Events ---*/ \
macro (ompt_callback_thread_begin, ompt_callback_thread_begin_t, 1) /* thread begin */ \
macro (ompt_callback_thread_end, ompt_callback_thread_end_t, 2) /* thread end */ \
\
macro (ompt_callback_parallel_begin, ompt_callback_parallel_begin_t, 3) /* parallel begin */ \
macro (ompt_callback_parallel_end, ompt_callback_parallel_end_t, 4) /* parallel end */ \
\
macro (ompt_callback_task_create, ompt_callback_task_create_t, 5) /* task begin */ \
macro (ompt_callback_task_schedule, ompt_callback_task_schedule_t, 6) /* task schedule */ \
macro (ompt_callback_implicit_task, ompt_callback_implicit_task_t, 7) /* implicit task */ \
\
macro (ompt_callback_target, ompt_callback_target_t, 8) /* target */ \
macro (ompt_callback_target_data_op, ompt_callback_target_data_op_t, 9) /* target data op */ \
macro (ompt_callback_target_submit, ompt_callback_target_submit_t, 10) /* target submit */ \
\
macro (ompt_callback_control_tool, ompt_callback_control_tool_t, 11) /* control tool */ \
\
macro (ompt_callback_device_initialize, ompt_callback_device_initialize_t, 12) /* device initialize */ \
macro (ompt_callback_device_finalize, ompt_callback_device_finalize_t, 13) /* device finalize */ \
\
macro (ompt_callback_device_load, ompt_callback_device_load_t, 14) /* device load */ \
macro (ompt_callback_device_unload, ompt_callback_device_unload_t, 15) /* device unload */ \
\
/* Optional Events */ \
macro (ompt_callback_sync_region_wait, ompt_callback_sync_region_t, 16) /* sync region wait begin or end */ \
\
macro (ompt_callback_mutex_released, ompt_callback_mutex_t, 17) /* mutex released */ \
\
macro (ompt_callback_task_dependences, ompt_callback_task_dependences_t, 18) /* report task dependences */ \
macro (ompt_callback_task_dependence, ompt_callback_task_dependence_t, 19) /* report task dependence */ \
\
macro (ompt_callback_work, ompt_callback_work_t, 20) /* task at work begin or end */ \
\
macro (ompt_callback_master, ompt_callback_master_t, 21) /* task at master begin or end */ \
\
macro (ompt_callback_target_map, ompt_callback_target_map_t, 22) /* target map */ \
\
macro (ompt_callback_sync_region, ompt_callback_sync_region_t, 23) /* sync region begin or end */ \
\
macro (ompt_callback_lock_init, ompt_callback_mutex_acquire_t, 24) /* lock init */ \
macro (ompt_callback_lock_destroy, ompt_callback_mutex_t, 25) /* lock destroy */ \
\
macro (ompt_callback_mutex_acquire, ompt_callback_mutex_acquire_t, 26) /* mutex acquire */ \
macro (ompt_callback_mutex_acquired, ompt_callback_mutex_t, 27) /* mutex acquired */ \
\
macro (ompt_callback_nest_lock, ompt_callback_nest_lock_t, 28) /* nest lock */ \
\
macro (ompt_callback_flush, ompt_callback_flush_t, 29) /* after executing flush */ \
\
macro (ompt_callback_cancel, ompt_callback_cancel_t, 30) /* cancel innermost binding region */ \
macro (ompt_callback_idle, ompt_callback_idle_t, 31) /* begin or end idle state */
/*****************************************************************************
* data types
*****************************************************************************/
/*---------------------
* identifiers
*---------------------*/
typedef uint64_t ompt_id_t;
#define ompt_id_none 0
typedef union ompt_data_t {
uint64_t value; /* data initialized by runtime to unique id */
void *ptr; /* pointer under tool control */
} ompt_data_t;
static const ompt_data_t ompt_data_none = {0};
typedef uint64_t ompt_wait_id_t;
static const ompt_wait_id_t ompt_wait_id_none = 0;
typedef void ompt_device_t;
/*---------------------
* ompt_frame_t
*---------------------*/
typedef struct ompt_frame_t {
void *exit_frame; /* next frame is user code */
void *enter_frame; /* previous frame is user code */
} ompt_frame_t;
/*---------------------
* dependences types
*---------------------*/
typedef enum ompt_task_dependence_flag_t {
// a two bit field for the dependence type
ompt_task_dependence_type_out = 1,
ompt_task_dependence_type_in = 2,
ompt_task_dependence_type_inout = 3,
} ompt_task_dependence_flag_t;
typedef struct ompt_task_dependence_t {
void *variable_addr;
unsigned int dependence_flags;
} ompt_task_dependence_t;
/*****************************************************************************
* enumerations for thread states and runtime events
*****************************************************************************/
/*---------------------
* runtime states
*---------------------*/
typedef enum {
#define omp_state_macro(state, code) state = code,
FOREACH_OMP_STATE(omp_state_macro)
#undef omp_state_macro
} omp_state_t;
/*---------------------
* runtime events
*---------------------*/
typedef enum ompt_callbacks_e{
#define ompt_event_macro(event, callback, eventid) event = eventid,
FOREACH_OMPT_EVENT(ompt_event_macro)
#undef ompt_event_macro
} ompt_callbacks_t;
/*---------------------
* set callback results
*---------------------*/
typedef enum ompt_set_result_t {
ompt_set_error = 0,
ompt_set_never = 1,
ompt_set_sometimes = 2,
ompt_set_sometimes_paired = 3,
ompt_set_always = 4
} ompt_set_result_t;
/*----------------------
* mutex implementations
*----------------------*/
typedef enum ompt_mutex_impl_t {
#define ompt_mutex_impl_macro(impl, code) impl = code,
FOREACH_OMPT_MUTEX_IMPL(ompt_mutex_impl_macro)
#undef ompt_mutex_impl_macro
} ompt_mutex_impl_t;
/*****************************************************************************
* callback signatures
*****************************************************************************/
/* initialization */
typedef void (*ompt_interface_fn_t)(void);
typedef ompt_interface_fn_t (*ompt_function_lookup_t)(
const char * /* entry point to look up */
);
/* threads */
typedef enum ompt_thread_type_t {
ompt_thread_initial = 1, // start the enumeration at 1
ompt_thread_worker = 2,
ompt_thread_other = 3,
ompt_thread_unknown = 4
} ompt_thread_type_t;
typedef enum ompt_invoker_t {
ompt_invoker_program = 1, /* program invokes master task */
ompt_invoker_runtime = 2 /* runtime invokes master task */
} ompt_invoker_t;
typedef void (*ompt_callback_thread_begin_t) (
ompt_thread_type_t thread_type, /* type of thread */
ompt_data_t *thread_data /* data of thread */
);
typedef void (*ompt_callback_thread_end_t) (
ompt_data_t *thread_data /* data of thread */
);
typedef void (*ompt_wait_callback_t) (
ompt_wait_id_t wait_id /* wait data */
);
/* parallel and workshares */
typedef enum ompt_scope_endpoint_t {
ompt_scope_begin = 1,
ompt_scope_end = 2
} ompt_scope_endpoint_t;
/* implicit task */
typedef void (*ompt_callback_implicit_task_t) (
ompt_scope_endpoint_t endpoint, /* endpoint of implicit task */
ompt_data_t *parallel_data, /* data of parallel region */
ompt_data_t *task_data, /* data of implicit task */
unsigned int team_size, /* team size */
unsigned int thread_num /* thread number of calling thread */
);
typedef void (*ompt_callback_parallel_begin_t) (
ompt_data_t *encountering_task_data, /* data of encountering task */
const ompt_frame_t *encountering_task_frame, /* frame data of encountering task */
ompt_data_t *parallel_data, /* data of parallel region */
unsigned int requested_team_size, /* requested number of threads in team */
ompt_invoker_t invoker, /* invoker of master task */
const void *codeptr_ra /* return address of runtime call */
);
typedef void (*ompt_callback_parallel_end_t) (
ompt_data_t *parallel_data, /* data of parallel region */
ompt_data_t *encountering_task_data, /* data of encountering task */
ompt_invoker_t invoker, /* invoker of master task */
const void *codeptr_ra /* return address of runtime call */
);
/* tasks */
typedef enum ompt_task_type_t {
ompt_task_initial = 0x1,
ompt_task_implicit = 0x2,
ompt_task_explicit = 0x4,
ompt_task_target = 0x8,
ompt_task_undeferred = 0x8000000,
ompt_task_untied = 0x10000000,
ompt_task_final = 0x20000000,
ompt_task_mergeable = 0x40000000,
ompt_task_merged = 0x80000000
} ompt_task_type_t;
typedef enum ompt_task_status_t {
ompt_task_complete = 1,
ompt_task_yield = 2,
ompt_task_cancel = 3,
ompt_task_others = 4
} ompt_task_status_t;
typedef void (*ompt_callback_task_schedule_t) (
ompt_data_t *prior_task_data, /* data of prior task */
ompt_task_status_t prior_task_status, /* status of prior task */
ompt_data_t *next_task_data /* data of next task */
);
typedef void (*ompt_callback_task_create_t) (
ompt_data_t *encountering_task_data, /* data of parent task */
const ompt_frame_t *encountering_task_frame, /* frame data for parent task */
ompt_data_t *new_task_data, /* data of created task */
int type, /* type of created task */
int has_dependences, /* created task has dependences */
const void *codeptr_ra /* return address of runtime call */
);
/* task dependences */
typedef void (*ompt_callback_task_dependences_t) (
ompt_data_t *task_data, /* data of task */
const ompt_task_dependence_t *deps, /* dependences of task */
int ndeps /* dependences count of task */
);
typedef void (*ompt_callback_task_dependence_t) (
ompt_data_t *src_task_data, /* data of source task */
ompt_data_t *sink_task_data /* data of sink task */
);
/* target and device */
typedef enum ompt_target_type_t {
ompt_target = 1,
ompt_target_enter_data = 2,
ompt_target_exit_data = 3,
ompt_target_update = 4
} ompt_target_type_t;
typedef void (*ompt_callback_target_t) (
ompt_target_type_t kind,
ompt_scope_endpoint_t endpoint,
uint64_t device_num,
ompt_data_t *task_data,
ompt_id_t target_id,
const void *codeptr_ra
);
typedef enum ompt_target_data_op_t {
ompt_target_data_alloc = 1,
ompt_target_data_transfer_to_dev = 2,
ompt_target_data_transfer_from_dev = 3,
ompt_target_data_delete = 4
} ompt_target_data_op_t;
typedef void (*ompt_callback_target_data_op_t) (
ompt_id_t target_id,
ompt_id_t host_op_id,
ompt_target_data_op_t optype,
void *host_addr,
void *device_addr,
size_t bytes
);
typedef void (*ompt_callback_target_submit_t) (
ompt_id_t target_id,
ompt_id_t host_op_id
);
typedef void (*ompt_callback_target_map_t) (
ompt_id_t target_id,
unsigned int nitems,
void **host_addr,
void **device_addr,
size_t *bytes,
unsigned int *mapping_flags
);
typedef void (*ompt_callback_device_initialize_t) (
uint64_t device_num,
const char *type,
ompt_device_t *device,
ompt_function_lookup_t lookup,
const char *documentation
);
typedef void (*ompt_callback_device_finalize_t) (
uint64_t device_num
);
typedef void (*ompt_callback_device_load_t) (
uint64_t device_num,
const char * filename,
int64_t offset_in_file,
void * vma_in_file,
size_t bytes,
void * host_addr,
void * device_addr,
uint64_t module_id
);
#define ompt_addr_unknown ((void *) ~0)
typedef void (*ompt_callback_device_unload_t) (
uint64_t device_num,
uint64_t module_id
);
/* control_tool */
typedef int (*ompt_callback_control_tool_t) (
uint64_t command, /* command of control call */
uint64_t modifier, /* modifier of control call */
void *arg, /* argument of control call */
const void *codeptr_ra /* return address of runtime call */
);
typedef enum ompt_mutex_kind_t {
ompt_mutex = 0x10,
ompt_mutex_lock = 0x11,
ompt_mutex_nest_lock = 0x12,
ompt_mutex_critical = 0x13,
ompt_mutex_atomic = 0x14,
ompt_mutex_ordered = 0x20
} ompt_mutex_kind_t;
typedef void (*ompt_callback_mutex_acquire_t) (
ompt_mutex_kind_t kind, /* mutex kind */
unsigned int hint, /* mutex hint */
unsigned int impl, /* mutex implementation */
ompt_wait_id_t wait_id, /* id of object being awaited */
const void *codeptr_ra /* return address of runtime call */
);
typedef void (*ompt_callback_mutex_t) (
ompt_mutex_kind_t kind, /* mutex kind */
ompt_wait_id_t wait_id, /* id of object being awaited */
const void *codeptr_ra /* return address of runtime call */
);
typedef void (*ompt_callback_nest_lock_t) (
ompt_scope_endpoint_t endpoint, /* endpoint of nested lock */
ompt_wait_id_t wait_id, /* id of object being awaited */
const void *codeptr_ra /* return address of runtime call */
);
typedef void (*ompt_callback_master_t) (
ompt_scope_endpoint_t endpoint, /* endpoint of master region */
ompt_data_t *parallel_data, /* data of parallel region */
ompt_data_t *task_data, /* data of task */
const void *codeptr_ra /* return address of runtime call */
);
typedef void (*ompt_callback_idle_t) (
ompt_scope_endpoint_t endpoint /* endpoint of idle time */
);
typedef enum ompt_work_type_t {
ompt_work_loop = 1,
ompt_work_sections = 2,
ompt_work_single_executor = 3,
ompt_work_single_other = 4,
ompt_work_workshare = 5,
ompt_work_distribute = 6,
ompt_work_taskloop = 7
} ompt_work_type_t;
typedef void (*ompt_callback_work_t) (
ompt_work_type_t wstype, /* type of work region */
ompt_scope_endpoint_t endpoint, /* endpoint of work region */
ompt_data_t *parallel_data, /* data of parallel region */
ompt_data_t *task_data, /* data of task */
uint64_t count, /* quantity of work */
const void *codeptr_ra /* return address of runtime call */
);
typedef enum ompt_sync_region_kind_t {
ompt_sync_region_barrier = 1,
ompt_sync_region_taskwait = 2,
ompt_sync_region_taskgroup = 3
} ompt_sync_region_kind_t;
typedef void (*ompt_callback_sync_region_t) (
ompt_sync_region_kind_t kind, /* kind of sync region */
ompt_scope_endpoint_t endpoint, /* endpoint of sync region */
ompt_data_t *parallel_data, /* data of parallel region */
ompt_data_t *task_data, /* data of task */
const void *codeptr_ra /* return address of runtime call */
);
typedef enum ompt_cancel_flag_t {
ompt_cancel_parallel = 0x1,
ompt_cancel_sections = 0x2,
ompt_cancel_do = 0x4,
ompt_cancel_taskgroup = 0x8,
ompt_cancel_activated = 0x10,
ompt_cancel_detected = 0x20,
ompt_cancel_discarded_task = 0x40
} ompt_cancel_flag_t;
typedef void (*ompt_callback_cancel_t) (
ompt_data_t *task_data, /* data of task */
int flags, /* cancel flags */
const void *codeptr_ra /* return address of runtime call */
);
typedef void (*ompt_callback_flush_t) (
ompt_data_t *thread_data, /* data of thread */
const void *codeptr_ra /* return address of runtime call */
);
/****************************************************************************
* ompt API
***************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
#define OMPT_API_FNTYPE(fn) fn##_t
#define OMPT_API_FUNCTION(return_type, fn, args) \
typedef return_type (*OMPT_API_FNTYPE(fn)) args
/****************************************************************************
* INQUIRY FUNCTIONS
***************************************************************************/
/* state */
OMPT_API_FUNCTION(omp_state_t, ompt_get_state, (
ompt_wait_id_t *wait_id
));
/* thread */
OMPT_API_FUNCTION(ompt_data_t*, ompt_get_thread_data, (void));
/* parallel region */
OMPT_API_FUNCTION(int, ompt_get_parallel_info, (
int ancestor_level,
ompt_data_t **parallel_data,
int *team_size
));
/* task */
OMPT_API_FUNCTION(int, ompt_get_task_info, (
int ancestor_level,
int *type,
ompt_data_t **task_data,
ompt_frame_t **task_frame,
ompt_data_t **parallel_data,
int *thread_num
));
/* procs */
OMPT_API_FUNCTION(int, ompt_get_num_procs, (void));
/* places */
OMPT_API_FUNCTION(int, ompt_get_num_places, (void));
OMPT_API_FUNCTION(int, ompt_get_place_proc_ids, (
int place_num,
int ids_size,
int *ids
));
OMPT_API_FUNCTION(int, ompt_get_place_num, (void));
OMPT_API_FUNCTION(int, ompt_get_partition_place_nums, (
int place_nums_size,
int *place_nums
));
/* proc_id */
OMPT_API_FUNCTION(int, ompt_get_proc_id, (void));
/****************************************************************************
* INITIALIZATION FUNCTIONS
***************************************************************************/
OMPT_API_FUNCTION(int, ompt_initialize, (
ompt_function_lookup_t ompt_fn_lookup,
ompt_data_t *tool_data
));
OMPT_API_FUNCTION(void, ompt_finalize, (
ompt_data_t *tool_data
));
typedef struct ompt_start_tool_result_t {
ompt_initialize_t initialize;
ompt_finalize_t finalize;
ompt_data_t tool_data;
} ompt_start_tool_result_t;
/* initialization interface to be defined by tool */
#ifdef _WIN32
__declspec(dllexport)
#endif
ompt_start_tool_result_t * ompt_start_tool(
unsigned int omp_version,
const char * runtime_version
);
typedef void (*ompt_callback_t)(void);
OMPT_API_FUNCTION(int, ompt_set_callback, (
ompt_callbacks_t which,
ompt_callback_t callback
));
OMPT_API_FUNCTION(int, ompt_get_callback, (
ompt_callbacks_t which,
ompt_callback_t *callback
));
/****************************************************************************
* MISCELLANEOUS FUNCTIONS
***************************************************************************/
/* state enumeration */
OMPT_API_FUNCTION(int, ompt_enumerate_states, (
int current_state,
int *next_state,
const char **next_state_name
));
/* mutex implementation enumeration */
OMPT_API_FUNCTION(int, ompt_enumerate_mutex_impls, (
int current_impl,
int *next_impl,
const char **next_impl_name
));
/* get_unique_id */
OMPT_API_FUNCTION(uint64_t, ompt_get_unique_id, (void));
#ifdef __cplusplus
};
#endif
/****************************************************************************
* TARGET
***************************************************************************/
OMPT_API_FUNCTION(int, ompt_get_target_info, (
uint64_t *device_num,
ompt_id_t *target_id,
ompt_id_t *host_op_id
));
OMPT_API_FUNCTION(int, ompt_get_num_devices, (void));
#endif /* __OMPT__ */
+2452 -2302
View File
File diff suppressed because it is too large Load Diff
+4754 -4348
View File
File diff suppressed because it is too large Load Diff
+787 -277
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1517 -786
View File
File diff suppressed because it is too large Load Diff
+1776 -1492
View File
File diff suppressed because it is too large Load Diff
+248 -194
View File
@@ -8,11 +8,13 @@
//
//===----------------------------------------------------------------------===//
#include "kmp.h"
#include "kmp_i18n.h"
#include "kmp_io.h"
#include "kmp_str.h"
#if OMPT_SUPPORT
#include "ompt-specific.h"
#endif
#if OMP_40_ENABLED
@@ -22,76 +24,104 @@
@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.
@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 ];
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) );
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);
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 */);
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) {
// we do not have a cancellation request in this team or we do have
// one that matches the current request -> cancel
#if OMPT_SUPPORT && OMPT_OPTIONAL
if (ompt_enabled.ompt_callback_cancel) {
ompt_data_t *task_data;
__ompt_get_task_info_internal(0, NULL, &task_data, NULL, NULL,
NULL);
ompt_cancel_flag_t type = ompt_cancel_parallel;
if (cncl_kind == cancel_parallel)
type = ompt_cancel_parallel;
else if (cncl_kind == cancel_loop)
type = ompt_cancel_do;
else if (cncl_kind == cancel_sections)
type = ompt_cancel_sections;
ompt_callbacks.ompt_callback(ompt_callback_cancel)(
task_data, type | ompt_cancel_activated,
OMPT_GET_RETURN_ADDRESS(0));
}
#endif
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;
// ICV OMP_CANCELLATION=false, so we ignored this cancel request
KMP_DEBUG_ASSERT(!__kmp_omp_cancellation);
return 0 /* false */;
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
#if OMPT_SUPPORT && OMPT_OPTIONAL
if (ompt_enabled.ompt_callback_cancel) {
ompt_data_t *task_data;
__ompt_get_task_info_internal(0, NULL, &task_data, NULL, NULL,
NULL);
ompt_callbacks.ompt_callback(ompt_callback_cancel)(
task_data, ompt_cancel_taskgroup | ompt_cancel_activated,
OMPT_GET_RETURN_ADDRESS(0));
}
#endif
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 */;
}
/*!
@@ -100,77 +130,105 @@ kmp_int32 __kmpc_cancel(ident_t* loc_ref, kmp_int32 gtid, kmp_int32 cncl_kind) {
@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..
@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 ];
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) );
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);
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;
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
#if OMPT_SUPPORT && OMPT_OPTIONAL
if (ompt_enabled.ompt_callback_cancel) {
ompt_data_t *task_data;
__ompt_get_task_info_internal(0, NULL, &task_data, NULL, NULL,
NULL);
ompt_cancel_flag_t type = ompt_cancel_parallel;
if (cncl_kind == cancel_parallel)
type = ompt_cancel_parallel;
else if (cncl_kind == cancel_loop)
type = ompt_cancel_do;
else if (cncl_kind == cancel_sections)
type = ompt_cancel_sections;
ompt_callbacks.ompt_callback(ompt_callback_cancel)(
task_data, type | ompt_cancel_detected,
OMPT_GET_RETURN_ADDRESS(0));
}
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 */);
#endif
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;
// ICV OMP_CANCELLATION=false, so we ignore the cancellation point
KMP_DEBUG_ASSERT(!__kmp_omp_cancellation);
return 0 /* false */;
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
#if OMPT_SUPPORT && OMPT_OPTIONAL
if (ompt_enabled.ompt_callback_cancel &&
!!taskgroup->cancel_request) {
ompt_data_t *task_data;
__ompt_get_task_info_internal(0, NULL, &task_data, NULL, NULL,
NULL);
ompt_callbacks.ompt_callback(ompt_callback_cancel)(
task_data, ompt_cancel_taskgroup | ompt_cancel_detected,
OMPT_GET_RETURN_ADDRESS(0));
}
#endif
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 */;
}
/*!
@@ -178,63 +236,61 @@ kmp_int32 __kmpc_cancellationpoint(ident_t* loc_ref, kmp_int32 gtid, kmp_int32 c
@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..
@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_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);
KMP_DEBUG_ASSERT(__kmp_get_gtid() == gtid);
// call into the standard barrier
__kmpc_barrier(loc, 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 */);
}
// 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;
return ret;
}
/*!
@@ -242,8 +298,8 @@ __kmpc_cancel_barrier(ident_t *loc, kmp_int32 gtid) {
@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..
@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:
@@ -254,29 +310,27 @@ if (kmp_get_cancellation_status(kmp_cancel_parallel)) {
}
*/
int __kmp_get_cancellation_status(int cancel_kind) {
if (__kmp_omp_cancellation) {
kmp_info_t *this_thr = __kmp_entry_thread();
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;
}
}
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 */;
return 0 /* false */;
}
#endif
+6 -4
View File
@@ -45,10 +45,8 @@
#define OMPT_DEBUG LIBOMP_OMPT_DEBUG
#cmakedefine01 LIBOMP_OMPT_SUPPORT
#define OMPT_SUPPORT LIBOMP_OMPT_SUPPORT
#cmakedefine01 LIBOMP_OMPT_BLAME
#define OMPT_BLAME LIBOMP_OMPT_BLAME
#cmakedefine01 LIBOMP_OMPT_TRACE
#define OMPT_TRACE LIBOMP_OMPT_TRACE
#cmakedefine01 LIBOMP_OMPT_OPTIONAL
#define OMPT_OPTIONAL LIBOMP_OMPT_OPTIONAL
#cmakedefine01 LIBOMP_USE_ADAPTIVE_LOCKS
#define KMP_USE_ADAPTIVE_LOCKS LIBOMP_USE_ADAPTIVE_LOCKS
#define KMP_DEBUG_ADAPTIVE_LOCKS 0
@@ -68,6 +66,10 @@
#define OMP_45_ENABLED (LIBOMP_OMP_VERSION >= 45)
#define OMP_40_ENABLED (LIBOMP_OMP_VERSION >= 40)
#define OMP_30_ENABLED (LIBOMP_OMP_VERSION >= 30)
#cmakedefine01 LIBOMP_TSAN_SUPPORT
#if LIBOMP_TSAN_SUPPORT
#define TSAN_SUPPORT
#endif
// Configured cache line based on architecture
#if KMP_ARCH_PPC64
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-142
View File
@@ -1,142 +0,0 @@
/*
* kmp_debug.c -- debug utilities for the Guide library
*/
//===----------------------------------------------------------------------===//
//
// 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_debug.h" /* really necessary? */
#include "kmp_i18n.h"
#include "kmp_io.h"
#ifdef KMP_DEBUG
void
__kmp_debug_printf_stdout( char const * format, ... )
{
va_list ap;
va_start( ap, format );
__kmp_vprintf( kmp_out, format, ap );
va_end(ap);
}
#endif
void
__kmp_debug_printf( char const * format, ... )
{
va_list ap;
va_start( ap, format );
__kmp_vprintf( kmp_err, format, ap );
va_end( ap );
}
#ifdef KMP_USE_ASSERT
int
__kmp_debug_assert(
char const * msg,
char const * file,
int line
) {
if ( file == NULL ) {
file = KMP_I18N_STR( UnknownFile );
} else {
// Remove directories from path, leave only file name. File name is enough, there is no need
// in bothering developers and customers with full paths.
char const * slash = strrchr( file, '/' );
if ( slash != NULL ) {
file = slash + 1;
}; // if
}; // if
#ifdef KMP_DEBUG
__kmp_acquire_bootstrap_lock( & __kmp_stdio_lock );
__kmp_debug_printf( "Assertion failure at %s(%d): %s.\n", file, line, msg );
__kmp_release_bootstrap_lock( & __kmp_stdio_lock );
#ifdef USE_ASSERT_BREAK
#if KMP_OS_WINDOWS
DebugBreak();
#endif
#endif // USE_ASSERT_BREAK
#ifdef USE_ASSERT_STALL
/* __kmp_infinite_loop(); */
for(;;);
#endif // USE_ASSERT_STALL
#ifdef USE_ASSERT_SEG
{
int volatile * ZERO = (int*) 0;
++ (*ZERO);
}
#endif // USE_ASSERT_SEG
#endif
__kmp_msg(
kmp_ms_fatal,
KMP_MSG( AssertionFailure, file, line ),
KMP_HNT( SubmitBugReport ),
__kmp_msg_null
);
return 0;
} // __kmp_debug_assert
#endif // KMP_USE_ASSERT
/* Dump debugging buffer to stderr */
void
__kmp_dump_debug_buffer( void )
{
if ( __kmp_debug_buffer != NULL ) {
int i;
int dc = __kmp_debug_count;
char *db = & __kmp_debug_buffer[ (dc % __kmp_debug_buf_lines) * __kmp_debug_buf_chars ];
char *db_end = & __kmp_debug_buffer[ __kmp_debug_buf_lines * __kmp_debug_buf_chars ];
char *db2;
__kmp_acquire_bootstrap_lock( & __kmp_stdio_lock );
__kmp_printf_no_lock( "\nStart dump of debugging buffer (entry=%d):\n",
dc % __kmp_debug_buf_lines );
for ( i = 0; i < __kmp_debug_buf_lines; i++ ) {
if ( *db != '\0' ) {
/* Fix up where no carriage return before string termination char */
for ( db2 = db + 1; db2 < db + __kmp_debug_buf_chars - 1; db2 ++) {
if ( *db2 == '\0' ) {
if ( *(db2-1) != '\n' ) { *db2 = '\n'; *(db2+1) = '\0'; }
break;
}
}
/* Handle case at end by shortening the printed message by one char if necessary */
if ( db2 == db + __kmp_debug_buf_chars - 1 &&
*db2 == '\0' && *(db2-1) != '\n' ) {
*(db2-1) = '\n';
}
__kmp_printf_no_lock( "%4d: %.*s", i, __kmp_debug_buf_chars, db );
*db = '\0'; /* only let it print once! */
}
db += __kmp_debug_buf_chars;
if ( db >= db_end )
db = __kmp_debug_buffer;
}
__kmp_printf_no_lock( "End dump of debugging buffer (entry=%d).\n\n",
( dc+i-1 ) % __kmp_debug_buf_lines );
__kmp_release_bootstrap_lock( & __kmp_stdio_lock );
}
}
+132
View File
@@ -0,0 +1,132 @@
/*
* kmp_debug.cpp -- debug utilities for the Guide library
*/
//===----------------------------------------------------------------------===//
//
// 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_debug.h" /* really necessary? */
#include "kmp_i18n.h"
#include "kmp_io.h"
#ifdef KMP_DEBUG
void __kmp_debug_printf_stdout(char const *format, ...) {
va_list ap;
va_start(ap, format);
__kmp_vprintf(kmp_out, format, ap);
va_end(ap);
}
#endif
void __kmp_debug_printf(char const *format, ...) {
va_list ap;
va_start(ap, format);
__kmp_vprintf(kmp_err, format, ap);
va_end(ap);
}
#ifdef KMP_USE_ASSERT
int __kmp_debug_assert(char const *msg, char const *file, int line) {
if (file == NULL) {
file = KMP_I18N_STR(UnknownFile);
} else {
// Remove directories from path, leave only file name. File name is enough,
// there is no need in bothering developers and customers with full paths.
char const *slash = strrchr(file, '/');
if (slash != NULL) {
file = slash + 1;
}
}
#ifdef KMP_DEBUG
__kmp_acquire_bootstrap_lock(&__kmp_stdio_lock);
__kmp_debug_printf("Assertion failure at %s(%d): %s.\n", file, line, msg);
__kmp_release_bootstrap_lock(&__kmp_stdio_lock);
#ifdef USE_ASSERT_BREAK
#if KMP_OS_WINDOWS
DebugBreak();
#endif
#endif // USE_ASSERT_BREAK
#ifdef USE_ASSERT_STALL
/* __kmp_infinite_loop(); */
for (;;)
;
#endif // USE_ASSERT_STALL
#ifdef USE_ASSERT_SEG
{
int volatile *ZERO = (int *)0;
++(*ZERO);
}
#endif // USE_ASSERT_SEG
#endif
__kmp_fatal(KMP_MSG(AssertionFailure, file, line), KMP_HNT(SubmitBugReport),
__kmp_msg_null);
return 0;
} // __kmp_debug_assert
#endif // KMP_USE_ASSERT
/* Dump debugging buffer to stderr */
void __kmp_dump_debug_buffer(void) {
if (__kmp_debug_buffer != NULL) {
int i;
int dc = __kmp_debug_count;
char *db = &__kmp_debug_buffer[(dc % __kmp_debug_buf_lines) *
__kmp_debug_buf_chars];
char *db_end =
&__kmp_debug_buffer[__kmp_debug_buf_lines * __kmp_debug_buf_chars];
char *db2;
__kmp_acquire_bootstrap_lock(&__kmp_stdio_lock);
__kmp_printf_no_lock("\nStart dump of debugging buffer (entry=%d):\n",
dc % __kmp_debug_buf_lines);
for (i = 0; i < __kmp_debug_buf_lines; i++) {
if (*db != '\0') {
/* Fix up where no carriage return before string termination char */
for (db2 = db + 1; db2 < db + __kmp_debug_buf_chars - 1; db2++) {
if (*db2 == '\0') {
if (*(db2 - 1) != '\n') {
*db2 = '\n';
*(db2 + 1) = '\0';
}
break;
}
}
/* Handle case at end by shortening the printed message by one char if
* necessary */
if (db2 == db + __kmp_debug_buf_chars - 1 && *db2 == '\0' &&
*(db2 - 1) != '\n') {
*(db2 - 1) = '\n';
}
__kmp_printf_no_lock("%4d: %.*s", i, __kmp_debug_buf_chars, db);
*db = '\0'; /* only let it print once! */
}
db += __kmp_debug_buf_chars;
if (db >= db_end)
db = __kmp_debug_buffer;
}
__kmp_printf_no_lock("End dump of debugging buffer (entry=%d).\n\n",
(dc + i - 1) % __kmp_debug_buf_lines);
__kmp_release_bootstrap_lock(&__kmp_stdio_lock);
}
}
+122 -82
View File
@@ -2,7 +2,6 @@
* kmp_debug.h -- debug / assertion code for Assure library
*/
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
@@ -12,120 +11,161 @@
//
//===----------------------------------------------------------------------===//
#ifndef KMP_DEBUG_H
#define KMP_DEBUG_H
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
extern "C" {
#endif // __cplusplus
// -------------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// Build-time assertion.
// -------------------------------------------------------------------------------------------------
/*
Build-time assertion can do compile-time checking of data structure sizes, etc. This works by
declaring a negative-length array if the conditional expression evaluates to false. In that
case, the compiler issues a syntax error and stops the compilation. If the expression is
true, we get an extraneous static single character array in the scope of the macro.
// New C++11 style build assert
#define KMP_BUILD_ASSERT(expr) static_assert(expr, "Build condition error")
Usage:
KMP_BUILD_ASSERT( sizeof( some_t ) <= 32 );
KMP_BUILD_ASSERT( offsetof( some_t, field ) % 8 == 0 );
Do not use _KMP_BUILD_ASSERT and __KMP_BUILD_ASSERT directly, it is working guts.
*/
#define __KMP_BUILD_ASSERT( expr, suffix ) typedef char __kmp_build_check_##suffix[ (expr) ? 1 : -1 ]
#define _KMP_BUILD_ASSERT( expr, suffix ) __KMP_BUILD_ASSERT( (expr), suffix )
#ifdef KMP_USE_ASSERT
#define KMP_BUILD_ASSERT( expr ) _KMP_BUILD_ASSERT( (expr), __LINE__ )
#else
#define KMP_BUILD_ASSERT( expr ) /* nothing to do */
#endif
// -------------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// Run-time assertions.
// -------------------------------------------------------------------------------------------------
extern void __kmp_dump_debug_buffer( void );
extern void __kmp_dump_debug_buffer(void);
#ifdef KMP_USE_ASSERT
extern int __kmp_debug_assert( char const * expr, char const * file, int line );
#ifdef KMP_DEBUG
#define KMP_ASSERT( cond ) ( (cond) ? 0 : __kmp_debug_assert( #cond, __FILE__, __LINE__ ) )
#define KMP_ASSERT2( cond, msg ) ( (cond) ? 0 : __kmp_debug_assert( (msg), __FILE__, __LINE__ ) )
#define KMP_DEBUG_ASSERT( cond ) KMP_ASSERT( cond )
#define KMP_DEBUG_ASSERT2( cond, msg ) KMP_ASSERT2( cond, msg )
#else
// Do not expose condition in release build. Use "assertion failure".
#define KMP_ASSERT( cond ) ( (cond) ? 0 : __kmp_debug_assert( "assertion failure", __FILE__, __LINE__ ) )
#define KMP_ASSERT2( cond, msg ) KMP_ASSERT( cond )
#define KMP_DEBUG_ASSERT( cond ) 0
#define KMP_DEBUG_ASSERT2( cond, msg ) 0
#endif // KMP_DEBUG
extern int __kmp_debug_assert(char const *expr, char const *file, int line);
#ifdef KMP_DEBUG
#define KMP_ASSERT(cond) \
((cond) ? 0 : __kmp_debug_assert(#cond, __FILE__, __LINE__))
#define KMP_ASSERT2(cond, msg) \
((cond) ? 0 : __kmp_debug_assert((msg), __FILE__, __LINE__))
#define KMP_DEBUG_ASSERT(cond) KMP_ASSERT(cond)
#define KMP_DEBUG_ASSERT2(cond, msg) KMP_ASSERT2(cond, msg)
#else
#define KMP_ASSERT( cond ) 0
#define KMP_ASSERT2( cond, msg ) 0
#define KMP_DEBUG_ASSERT( cond ) 0
#define KMP_DEBUG_ASSERT2( cond, msg ) 0
// Do not expose condition in release build. Use "assertion failure".
#define KMP_ASSERT(cond) \
((cond) ? 0 : __kmp_debug_assert("assertion failure", __FILE__, __LINE__))
#define KMP_ASSERT2(cond, msg) KMP_ASSERT(cond)
#define KMP_DEBUG_ASSERT(cond) 0
#define KMP_DEBUG_ASSERT2(cond, msg) 0
#endif // KMP_DEBUG
#else
#define KMP_ASSERT(cond) 0
#define KMP_ASSERT2(cond, msg) 0
#define KMP_DEBUG_ASSERT(cond) 0
#define KMP_DEBUG_ASSERT2(cond, msg) 0
#endif // KMP_USE_ASSERT
#ifdef KMP_DEBUG
extern void __kmp_debug_printf_stdout( char const * format, ... );
extern void __kmp_debug_printf_stdout(char const *format, ...);
#endif
extern void __kmp_debug_printf( char const * format, ... );
extern void __kmp_debug_printf(char const *format, ...);
#ifdef KMP_DEBUG
extern int kmp_a_debug;
extern int kmp_b_debug;
extern int kmp_c_debug;
extern int kmp_d_debug;
extern int kmp_e_debug;
extern int kmp_f_debug;
extern int kmp_diag;
extern int kmp_a_debug;
extern int kmp_b_debug;
extern int kmp_c_debug;
extern int kmp_d_debug;
extern int kmp_e_debug;
extern int kmp_f_debug;
extern int kmp_diag;
#define KA_TRACE(d,x) if (kmp_a_debug >= d) { __kmp_debug_printf x ; }
#define KB_TRACE(d,x) if (kmp_b_debug >= d) { __kmp_debug_printf x ; }
#define KC_TRACE(d,x) if (kmp_c_debug >= d) { __kmp_debug_printf x ; }
#define KD_TRACE(d,x) if (kmp_d_debug >= d) { __kmp_debug_printf x ; }
#define KE_TRACE(d,x) if (kmp_e_debug >= d) { __kmp_debug_printf x ; }
#define KF_TRACE(d,x) if (kmp_f_debug >= d) { __kmp_debug_printf x ; }
#define K_DIAG(d,x) {if (kmp_diag == d) { __kmp_debug_printf_stdout x ; } }
#define KA_TRACE(d, x) \
if (kmp_a_debug >= d) { \
__kmp_debug_printf x; \
}
#define KB_TRACE(d, x) \
if (kmp_b_debug >= d) { \
__kmp_debug_printf x; \
}
#define KC_TRACE(d, x) \
if (kmp_c_debug >= d) { \
__kmp_debug_printf x; \
}
#define KD_TRACE(d, x) \
if (kmp_d_debug >= d) { \
__kmp_debug_printf x; \
}
#define KE_TRACE(d, x) \
if (kmp_e_debug >= d) { \
__kmp_debug_printf x; \
}
#define KF_TRACE(d, x) \
if (kmp_f_debug >= d) { \
__kmp_debug_printf x; \
}
#define K_DIAG(d, x) \
{ \
if (kmp_diag == d) { \
__kmp_debug_printf_stdout x; \
} \
}
#define KA_DUMP(d,x) if (kmp_a_debug >= d) { int ks; __kmp_disable(&ks); (x) ; __kmp_enable(ks); }
#define KB_DUMP(d,x) if (kmp_b_debug >= d) { int ks; __kmp_disable(&ks); (x) ; __kmp_enable(ks); }
#define KC_DUMP(d,x) if (kmp_c_debug >= d) { int ks; __kmp_disable(&ks); (x) ; __kmp_enable(ks); }
#define KD_DUMP(d,x) if (kmp_d_debug >= d) { int ks; __kmp_disable(&ks); (x) ; __kmp_enable(ks); }
#define KE_DUMP(d,x) if (kmp_e_debug >= d) { int ks; __kmp_disable(&ks); (x) ; __kmp_enable(ks); }
#define KF_DUMP(d,x) if (kmp_f_debug >= d) { int ks; __kmp_disable(&ks); (x) ; __kmp_enable(ks); }
#define KA_DUMP(d, x) \
if (kmp_a_debug >= d) { \
int ks; \
__kmp_disable(&ks); \
(x); \
__kmp_enable(ks); \
}
#define KB_DUMP(d, x) \
if (kmp_b_debug >= d) { \
int ks; \
__kmp_disable(&ks); \
(x); \
__kmp_enable(ks); \
}
#define KC_DUMP(d, x) \
if (kmp_c_debug >= d) { \
int ks; \
__kmp_disable(&ks); \
(x); \
__kmp_enable(ks); \
}
#define KD_DUMP(d, x) \
if (kmp_d_debug >= d) { \
int ks; \
__kmp_disable(&ks); \
(x); \
__kmp_enable(ks); \
}
#define KE_DUMP(d, x) \
if (kmp_e_debug >= d) { \
int ks; \
__kmp_disable(&ks); \
(x); \
__kmp_enable(ks); \
}
#define KF_DUMP(d, x) \
if (kmp_f_debug >= d) { \
int ks; \
__kmp_disable(&ks); \
(x); \
__kmp_enable(ks); \
}
#else
#define KA_TRACE(d,x) /* nothing to do */
#define KB_TRACE(d,x) /* nothing to do */
#define KC_TRACE(d,x) /* nothing to do */
#define KD_TRACE(d,x) /* nothing to do */
#define KE_TRACE(d,x) /* nothing to do */
#define KF_TRACE(d,x) /* nothing to do */
#define K_DIAG(d,x) {}/* nothing to do */
#define KA_TRACE(d, x) /* nothing to do */
#define KB_TRACE(d, x) /* nothing to do */
#define KC_TRACE(d, x) /* nothing to do */
#define KD_TRACE(d, x) /* nothing to do */
#define KE_TRACE(d, x) /* nothing to do */
#define KF_TRACE(d, x) /* nothing to do */
#define K_DIAG(d, x) \
{} /* nothing to do */
#define KA_DUMP(d,x) /* nothing to do */
#define KB_DUMP(d,x) /* nothing to do */
#define KC_DUMP(d,x) /* nothing to do */
#define KD_DUMP(d,x) /* nothing to do */
#define KE_DUMP(d,x) /* nothing to do */
#define KF_DUMP(d,x) /* nothing to do */
#define KA_DUMP(d, x) /* nothing to do */
#define KB_DUMP(d, x) /* nothing to do */
#define KC_DUMP(d, x) /* nothing to do */
#define KD_DUMP(d, x) /* nothing to do */
#define KE_DUMP(d, x) /* nothing to do */
#define KF_DUMP(d, x) /* nothing to do */
#endif // KMP_DEBUG
#ifdef __cplusplus
} // extern "C"
} // extern "C"
#endif // __cplusplus
#endif /* KMP_DEBUG_H */
-315
View File
@@ -1,315 +0,0 @@
#if USE_DEBUGGER
/*
* kmp_debugger.c -- debugger support.
*/
//===----------------------------------------------------------------------===//
//
// 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_lock.h"
#include "kmp_omp.h"
#include "kmp_str.h"
/*
NOTE: All variable names are known to the debugger, do not change!
*/
#ifdef __cplusplus
extern "C" {
extern kmp_omp_struct_info_t __kmp_omp_debug_struct_info;
} // extern "C"
#endif // __cplusplus
int __kmp_debugging = FALSE; // Boolean whether currently debugging OpenMP RTL.
#define offset_and_size_of( structure, field ) \
{ \
offsetof( structure, field ), \
sizeof( ( (structure *) NULL)->field ) \
}
#define offset_and_size_not_available \
{ -1, -1 }
#define addr_and_size_of( var ) \
{ \
(kmp_uint64)( & var ), \
sizeof( var ) \
}
#define nthr_buffer_size 1024
static kmp_int32
kmp_omp_nthr_info_buffer[ nthr_buffer_size ] =
{ nthr_buffer_size * sizeof( kmp_int32 ) };
/* TODO: Check punctuation for various platforms here */
static char func_microtask[] = "__kmp_invoke_microtask";
static char func_fork[] = "__kmpc_fork_call";
static char func_fork_teams[] = "__kmpc_fork_teams";
// Various info about runtime structures: addresses, field offsets, sizes, etc.
kmp_omp_struct_info_t
__kmp_omp_debug_struct_info = {
/* Change this only if you make a fundamental data structure change here */
KMP_OMP_VERSION,
/* sanity check. Only should be checked if versions are identical
* This is also used for backward compatibility to get the runtime
* structure size if it the runtime is older than the interface */
sizeof( kmp_omp_struct_info_t ),
/* OpenMP RTL version info. */
addr_and_size_of( __kmp_version_major ),
addr_and_size_of( __kmp_version_minor ),
addr_and_size_of( __kmp_version_build ),
addr_and_size_of( __kmp_openmp_version ),
{ (kmp_uint64)( __kmp_copyright ) + KMP_VERSION_MAGIC_LEN, 0 }, // Skip magic prefix.
/* Various globals. */
addr_and_size_of( __kmp_threads ),
addr_and_size_of( __kmp_root ),
addr_and_size_of( __kmp_threads_capacity ),
addr_and_size_of( __kmp_monitor ),
#if ! KMP_USE_DYNAMIC_LOCK
addr_and_size_of( __kmp_user_lock_table ),
#endif
addr_and_size_of( func_microtask ),
addr_and_size_of( func_fork ),
addr_and_size_of( func_fork_teams ),
addr_and_size_of( __kmp_team_counter ),
addr_and_size_of( __kmp_task_counter ),
addr_and_size_of( kmp_omp_nthr_info_buffer ),
sizeof( void * ),
OMP_LOCK_T_SIZE < sizeof(void *),
bs_last_barrier,
INITIAL_TASK_DEQUE_SIZE,
// thread structure information
sizeof( kmp_base_info_t ),
offset_and_size_of( kmp_base_info_t, th_info ),
offset_and_size_of( kmp_base_info_t, th_team ),
offset_and_size_of( kmp_base_info_t, th_root ),
offset_and_size_of( kmp_base_info_t, th_serial_team ),
offset_and_size_of( kmp_base_info_t, th_ident ),
offset_and_size_of( kmp_base_info_t, th_spin_here ),
offset_and_size_of( kmp_base_info_t, th_next_waiting ),
offset_and_size_of( kmp_base_info_t, th_task_team ),
offset_and_size_of( kmp_base_info_t, th_current_task ),
offset_and_size_of( kmp_base_info_t, th_task_state ),
offset_and_size_of( kmp_base_info_t, th_bar ),
offset_and_size_of( kmp_bstate_t, b_worker_arrived ),
#if OMP_40_ENABLED
// teams information
offset_and_size_of( kmp_base_info_t, th_teams_microtask),
offset_and_size_of( kmp_base_info_t, th_teams_level),
offset_and_size_of( kmp_teams_size_t, nteams ),
offset_and_size_of( kmp_teams_size_t, nth ),
#endif
// kmp_desc structure (for info field above)
sizeof( kmp_desc_base_t ),
offset_and_size_of( kmp_desc_base_t, ds_tid ),
offset_and_size_of( kmp_desc_base_t, ds_gtid ),
// On Windows* OS, ds_thread contains a thread /handle/, which is not usable, while thread /id/
// is in ds_thread_id.
#if KMP_OS_WINDOWS
offset_and_size_of( kmp_desc_base_t, ds_thread_id),
#else
offset_and_size_of( kmp_desc_base_t, ds_thread),
#endif
// team structure information
sizeof( kmp_base_team_t ),
offset_and_size_of( kmp_base_team_t, t_master_tid ),
offset_and_size_of( kmp_base_team_t, t_ident ),
offset_and_size_of( kmp_base_team_t, t_parent ),
offset_and_size_of( kmp_base_team_t, t_nproc ),
offset_and_size_of( kmp_base_team_t, t_threads ),
offset_and_size_of( kmp_base_team_t, t_serialized ),
offset_and_size_of( kmp_base_team_t, t_id ),
offset_and_size_of( kmp_base_team_t, t_pkfn ),
offset_and_size_of( kmp_base_team_t, t_task_team ),
offset_and_size_of( kmp_base_team_t, t_implicit_task_taskdata ),
#if OMP_40_ENABLED
offset_and_size_of( kmp_base_team_t, t_cancel_request ),
#endif
offset_and_size_of( kmp_base_team_t, t_bar ),
offset_and_size_of( kmp_balign_team_t, b_master_arrived ),
offset_and_size_of( kmp_balign_team_t, b_team_arrived ),
// root structure information
sizeof( kmp_base_root_t ),
offset_and_size_of( kmp_base_root_t, r_root_team ),
offset_and_size_of( kmp_base_root_t, r_hot_team ),
offset_and_size_of( kmp_base_root_t, r_uber_thread ),
offset_and_size_not_available,
// ident structure information
sizeof( ident_t ),
offset_and_size_of( ident_t, psource ),
offset_and_size_of( ident_t, flags ),
// lock structure information
sizeof( kmp_base_queuing_lock_t ),
offset_and_size_of( kmp_base_queuing_lock_t, initialized ),
offset_and_size_of( kmp_base_queuing_lock_t, location ),
offset_and_size_of( kmp_base_queuing_lock_t, tail_id ),
offset_and_size_of( kmp_base_queuing_lock_t, head_id ),
offset_and_size_of( kmp_base_queuing_lock_t, next_ticket ),
offset_and_size_of( kmp_base_queuing_lock_t, now_serving ),
offset_and_size_of( kmp_base_queuing_lock_t, owner_id ),
offset_and_size_of( kmp_base_queuing_lock_t, depth_locked ),
offset_and_size_of( kmp_base_queuing_lock_t, flags ),
#if ! KMP_USE_DYNAMIC_LOCK
/* Lock table. */
sizeof( kmp_lock_table_t ),
offset_and_size_of( kmp_lock_table_t, used ),
offset_and_size_of( kmp_lock_table_t, allocated ),
offset_and_size_of( kmp_lock_table_t, table ),
#endif
// Task team structure information.
sizeof( kmp_base_task_team_t ),
offset_and_size_of( kmp_base_task_team_t, tt_threads_data ),
offset_and_size_of( kmp_base_task_team_t, tt_found_tasks ),
offset_and_size_of( kmp_base_task_team_t, tt_nproc ),
offset_and_size_of( kmp_base_task_team_t, tt_unfinished_threads ),
offset_and_size_of( kmp_base_task_team_t, tt_active ),
// task_data_t.
sizeof( kmp_taskdata_t ),
offset_and_size_of( kmp_taskdata_t, td_task_id ),
offset_and_size_of( kmp_taskdata_t, td_flags ),
offset_and_size_of( kmp_taskdata_t, td_team ),
offset_and_size_of( kmp_taskdata_t, td_parent ),
offset_and_size_of( kmp_taskdata_t, td_level ),
offset_and_size_of( kmp_taskdata_t, td_ident ),
offset_and_size_of( kmp_taskdata_t, td_allocated_child_tasks ),
offset_and_size_of( kmp_taskdata_t, td_incomplete_child_tasks ),
offset_and_size_of( kmp_taskdata_t, td_taskwait_ident ),
offset_and_size_of( kmp_taskdata_t, td_taskwait_counter ),
offset_and_size_of( kmp_taskdata_t, td_taskwait_thread ),
#if OMP_40_ENABLED
offset_and_size_of( kmp_taskdata_t, td_taskgroup ),
offset_and_size_of( kmp_taskgroup_t, count ),
offset_and_size_of( kmp_taskgroup_t, cancel_request ),
offset_and_size_of( kmp_taskdata_t, td_depnode ),
offset_and_size_of( kmp_depnode_list_t, node ),
offset_and_size_of( kmp_depnode_list_t, next ),
offset_and_size_of( kmp_base_depnode_t, successors ),
offset_and_size_of( kmp_base_depnode_t, task ),
offset_and_size_of( kmp_base_depnode_t, npredecessors ),
offset_and_size_of( kmp_base_depnode_t, nrefs ),
#endif
offset_and_size_of( kmp_task_t, routine ),
// thread_data_t.
sizeof( kmp_thread_data_t ),
offset_and_size_of( kmp_base_thread_data_t, td_deque ),
offset_and_size_of( kmp_base_thread_data_t, td_deque_size ),
offset_and_size_of( kmp_base_thread_data_t, td_deque_head ),
offset_and_size_of( kmp_base_thread_data_t, td_deque_tail ),
offset_and_size_of( kmp_base_thread_data_t, td_deque_ntasks ),
offset_and_size_of( kmp_base_thread_data_t, td_deque_last_stolen ),
// The last field.
KMP_OMP_VERSION,
}; // __kmp_omp_debug_struct_info
#undef offset_and_size_of
#undef addr_and_size_of
/*
Intel compiler on IA-32 architecture issues a warning "conversion
from "unsigned long long" to "char *" may lose significant bits"
when 64-bit value is assigned to 32-bit pointer. Use this function
to suppress the warning.
*/
static inline
void *
__kmp_convert_to_ptr(
kmp_uint64 addr
) {
#if KMP_COMPILER_ICC
#pragma warning( push )
#pragma warning( disable: 810 ) // conversion from "unsigned long long" to "char *" may lose significant bits
#pragma warning( disable: 1195 ) // conversion from integer to smaller pointer
#endif // KMP_COMPILER_ICC
return (void *) addr;
#if KMP_COMPILER_ICC
#pragma warning( pop )
#endif // KMP_COMPILER_ICC
} // __kmp_convert_to_ptr
static int
kmp_location_match(
kmp_str_loc_t * loc,
kmp_omp_nthr_item_t * item
) {
int file_match = 0;
int func_match = 0;
int line_match = 0;
char * file = (char *) __kmp_convert_to_ptr( item->file );
char * func = (char *) __kmp_convert_to_ptr( item->func );
file_match = __kmp_str_fname_match( & loc->fname, file );
func_match =
item->func == 0 // If item->func is NULL, it allows any func name.
||
strcmp( func, "*" ) == 0
||
( loc->func != NULL && strcmp( loc->func, func ) == 0 );
line_match =
item->begin <= loc->line
&&
( item->end <= 0 || loc->line <= item->end ); // if item->end <= 0, it means "end of file".
return ( file_match && func_match && line_match );
} // kmp_location_match
int
__kmp_omp_num_threads(
ident_t const * ident
) {
int num_threads = 0;
kmp_omp_nthr_info_t * info =
(kmp_omp_nthr_info_t *) __kmp_convert_to_ptr( __kmp_omp_debug_struct_info.nthr_info.addr );
if ( info->num > 0 && info->array != 0 ) {
kmp_omp_nthr_item_t * items = (kmp_omp_nthr_item_t *) __kmp_convert_to_ptr( info->array );
kmp_str_loc_t loc = __kmp_str_loc_init( ident->psource, 1 );
int i;
for ( i = 0; i < info->num; ++ i ) {
if ( kmp_location_match( & loc, & items[ i ] ) ) {
num_threads = items[ i ].num_threads;
}; // if
}; // for
__kmp_str_loc_free( & loc );
}; // if
return num_threads;;
} // __kmp_omp_num_threads
#endif /* USE_DEBUGGER */
+289
View File
@@ -0,0 +1,289 @@
#if USE_DEBUGGER
/*
* kmp_debugger.cpp -- debugger support.
*/
//===----------------------------------------------------------------------===//
//
// 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_lock.h"
#include "kmp_omp.h"
#include "kmp_str.h"
// NOTE: All variable names are known to the debugger, do not change!
#ifdef __cplusplus
extern "C" {
extern kmp_omp_struct_info_t __kmp_omp_debug_struct_info;
} // extern "C"
#endif // __cplusplus
int __kmp_debugging = FALSE; // Boolean whether currently debugging OpenMP RTL.
#define offset_and_size_of(structure, field) \
{ offsetof(structure, field), sizeof(((structure *)NULL)->field) }
#define offset_and_size_not_available \
{ -1, -1 }
#define addr_and_size_of(var) \
{ (kmp_uint64)(&var), sizeof(var) }
#define nthr_buffer_size 1024
static kmp_int32 kmp_omp_nthr_info_buffer[nthr_buffer_size] = {
nthr_buffer_size * sizeof(kmp_int32)};
/* TODO: Check punctuation for various platforms here */
static char func_microtask[] = "__kmp_invoke_microtask";
static char func_fork[] = "__kmpc_fork_call";
static char func_fork_teams[] = "__kmpc_fork_teams";
// Various info about runtime structures: addresses, field offsets, sizes, etc.
kmp_omp_struct_info_t __kmp_omp_debug_struct_info = {
/* Change this only if you make a fundamental data structure change here */
KMP_OMP_VERSION,
/* sanity check. Only should be checked if versions are identical
* This is also used for backward compatibility to get the runtime
* structure size if it the runtime is older than the interface */
sizeof(kmp_omp_struct_info_t),
/* OpenMP RTL version info. */
addr_and_size_of(__kmp_version_major),
addr_and_size_of(__kmp_version_minor),
addr_and_size_of(__kmp_version_build),
addr_and_size_of(__kmp_openmp_version),
{(kmp_uint64)(__kmp_copyright) + KMP_VERSION_MAGIC_LEN,
0}, // Skip magic prefix.
/* Various globals. */
addr_and_size_of(__kmp_threads),
addr_and_size_of(__kmp_root),
addr_and_size_of(__kmp_threads_capacity),
addr_and_size_of(__kmp_monitor),
#if !KMP_USE_DYNAMIC_LOCK
addr_and_size_of(__kmp_user_lock_table),
#endif
addr_and_size_of(func_microtask),
addr_and_size_of(func_fork),
addr_and_size_of(func_fork_teams),
addr_and_size_of(__kmp_team_counter),
addr_and_size_of(__kmp_task_counter),
addr_and_size_of(kmp_omp_nthr_info_buffer),
sizeof(void *),
OMP_LOCK_T_SIZE < sizeof(void *),
bs_last_barrier,
INITIAL_TASK_DEQUE_SIZE,
// thread structure information
sizeof(kmp_base_info_t),
offset_and_size_of(kmp_base_info_t, th_info),
offset_and_size_of(kmp_base_info_t, th_team),
offset_and_size_of(kmp_base_info_t, th_root),
offset_and_size_of(kmp_base_info_t, th_serial_team),
offset_and_size_of(kmp_base_info_t, th_ident),
offset_and_size_of(kmp_base_info_t, th_spin_here),
offset_and_size_of(kmp_base_info_t, th_next_waiting),
offset_and_size_of(kmp_base_info_t, th_task_team),
offset_and_size_of(kmp_base_info_t, th_current_task),
offset_and_size_of(kmp_base_info_t, th_task_state),
offset_and_size_of(kmp_base_info_t, th_bar),
offset_and_size_of(kmp_bstate_t, b_worker_arrived),
#if OMP_40_ENABLED
// teams information
offset_and_size_of(kmp_base_info_t, th_teams_microtask),
offset_and_size_of(kmp_base_info_t, th_teams_level),
offset_and_size_of(kmp_teams_size_t, nteams),
offset_and_size_of(kmp_teams_size_t, nth),
#endif
// kmp_desc structure (for info field above)
sizeof(kmp_desc_base_t),
offset_and_size_of(kmp_desc_base_t, ds_tid),
offset_and_size_of(kmp_desc_base_t, ds_gtid),
// On Windows* OS, ds_thread contains a thread /handle/, which is not usable,
// while thread /id/ is in ds_thread_id.
#if KMP_OS_WINDOWS
offset_and_size_of(kmp_desc_base_t, ds_thread_id),
#else
offset_and_size_of(kmp_desc_base_t, ds_thread),
#endif
// team structure information
sizeof(kmp_base_team_t),
offset_and_size_of(kmp_base_team_t, t_master_tid),
offset_and_size_of(kmp_base_team_t, t_ident),
offset_and_size_of(kmp_base_team_t, t_parent),
offset_and_size_of(kmp_base_team_t, t_nproc),
offset_and_size_of(kmp_base_team_t, t_threads),
offset_and_size_of(kmp_base_team_t, t_serialized),
offset_and_size_of(kmp_base_team_t, t_id),
offset_and_size_of(kmp_base_team_t, t_pkfn),
offset_and_size_of(kmp_base_team_t, t_task_team),
offset_and_size_of(kmp_base_team_t, t_implicit_task_taskdata),
#if OMP_40_ENABLED
offset_and_size_of(kmp_base_team_t, t_cancel_request),
#endif
offset_and_size_of(kmp_base_team_t, t_bar),
offset_and_size_of(kmp_balign_team_t, b_master_arrived),
offset_and_size_of(kmp_balign_team_t, b_team_arrived),
// root structure information
sizeof(kmp_base_root_t),
offset_and_size_of(kmp_base_root_t, r_root_team),
offset_and_size_of(kmp_base_root_t, r_hot_team),
offset_and_size_of(kmp_base_root_t, r_uber_thread),
offset_and_size_not_available,
// ident structure information
sizeof(ident_t),
offset_and_size_of(ident_t, psource),
offset_and_size_of(ident_t, flags),
// lock structure information
sizeof(kmp_base_queuing_lock_t),
offset_and_size_of(kmp_base_queuing_lock_t, initialized),
offset_and_size_of(kmp_base_queuing_lock_t, location),
offset_and_size_of(kmp_base_queuing_lock_t, tail_id),
offset_and_size_of(kmp_base_queuing_lock_t, head_id),
offset_and_size_of(kmp_base_queuing_lock_t, next_ticket),
offset_and_size_of(kmp_base_queuing_lock_t, now_serving),
offset_and_size_of(kmp_base_queuing_lock_t, owner_id),
offset_and_size_of(kmp_base_queuing_lock_t, depth_locked),
offset_and_size_of(kmp_base_queuing_lock_t, flags),
#if !KMP_USE_DYNAMIC_LOCK
/* Lock table. */
sizeof(kmp_lock_table_t),
offset_and_size_of(kmp_lock_table_t, used),
offset_and_size_of(kmp_lock_table_t, allocated),
offset_and_size_of(kmp_lock_table_t, table),
#endif
// Task team structure information.
sizeof(kmp_base_task_team_t),
offset_and_size_of(kmp_base_task_team_t, tt_threads_data),
offset_and_size_of(kmp_base_task_team_t, tt_found_tasks),
offset_and_size_of(kmp_base_task_team_t, tt_nproc),
offset_and_size_of(kmp_base_task_team_t, tt_unfinished_threads),
offset_and_size_of(kmp_base_task_team_t, tt_active),
// task_data_t.
sizeof(kmp_taskdata_t),
offset_and_size_of(kmp_taskdata_t, td_task_id),
offset_and_size_of(kmp_taskdata_t, td_flags),
offset_and_size_of(kmp_taskdata_t, td_team),
offset_and_size_of(kmp_taskdata_t, td_parent),
offset_and_size_of(kmp_taskdata_t, td_level),
offset_and_size_of(kmp_taskdata_t, td_ident),
offset_and_size_of(kmp_taskdata_t, td_allocated_child_tasks),
offset_and_size_of(kmp_taskdata_t, td_incomplete_child_tasks),
offset_and_size_of(kmp_taskdata_t, td_taskwait_ident),
offset_and_size_of(kmp_taskdata_t, td_taskwait_counter),
offset_and_size_of(kmp_taskdata_t, td_taskwait_thread),
#if OMP_40_ENABLED
offset_and_size_of(kmp_taskdata_t, td_taskgroup),
offset_and_size_of(kmp_taskgroup_t, count),
offset_and_size_of(kmp_taskgroup_t, cancel_request),
offset_and_size_of(kmp_taskdata_t, td_depnode),
offset_and_size_of(kmp_depnode_list_t, node),
offset_and_size_of(kmp_depnode_list_t, next),
offset_and_size_of(kmp_base_depnode_t, successors),
offset_and_size_of(kmp_base_depnode_t, task),
offset_and_size_of(kmp_base_depnode_t, npredecessors),
offset_and_size_of(kmp_base_depnode_t, nrefs),
#endif
offset_and_size_of(kmp_task_t, routine),
// thread_data_t.
sizeof(kmp_thread_data_t),
offset_and_size_of(kmp_base_thread_data_t, td_deque),
offset_and_size_of(kmp_base_thread_data_t, td_deque_size),
offset_and_size_of(kmp_base_thread_data_t, td_deque_head),
offset_and_size_of(kmp_base_thread_data_t, td_deque_tail),
offset_and_size_of(kmp_base_thread_data_t, td_deque_ntasks),
offset_and_size_of(kmp_base_thread_data_t, td_deque_last_stolen),
// The last field.
KMP_OMP_VERSION,
}; // __kmp_omp_debug_struct_info
#undef offset_and_size_of
#undef addr_and_size_of
/* Intel compiler on IA-32 architecture issues a warning "conversion
from "unsigned long long" to "char *" may lose significant bits"
when 64-bit value is assigned to 32-bit pointer. Use this function
to suppress the warning. */
static inline void *__kmp_convert_to_ptr(kmp_uint64 addr) {
#if KMP_COMPILER_ICC
#pragma warning(push)
#pragma warning(disable : 810) // conversion from "unsigned long long" to "char
// *" may lose significant bits
#pragma warning(disable : 1195) // conversion from integer to smaller pointer
#endif // KMP_COMPILER_ICC
return (void *)addr;
#if KMP_COMPILER_ICC
#pragma warning(pop)
#endif // KMP_COMPILER_ICC
} // __kmp_convert_to_ptr
static int kmp_location_match(kmp_str_loc_t *loc, kmp_omp_nthr_item_t *item) {
int file_match = 0;
int func_match = 0;
int line_match = 0;
char *file = (char *)__kmp_convert_to_ptr(item->file);
char *func = (char *)__kmp_convert_to_ptr(item->func);
file_match = __kmp_str_fname_match(&loc->fname, file);
func_match =
item->func == 0 // If item->func is NULL, it allows any func name.
|| strcmp(func, "*") == 0 ||
(loc->func != NULL && strcmp(loc->func, func) == 0);
line_match =
item->begin <= loc->line &&
(item->end <= 0 ||
loc->line <= item->end); // if item->end <= 0, it means "end of file".
return (file_match && func_match && line_match);
} // kmp_location_match
int __kmp_omp_num_threads(ident_t const *ident) {
int num_threads = 0;
kmp_omp_nthr_info_t *info = (kmp_omp_nthr_info_t *)__kmp_convert_to_ptr(
__kmp_omp_debug_struct_info.nthr_info.addr);
if (info->num > 0 && info->array != 0) {
kmp_omp_nthr_item_t *items =
(kmp_omp_nthr_item_t *)__kmp_convert_to_ptr(info->array);
kmp_str_loc_t loc = __kmp_str_loc_init(ident->psource, 1);
int i;
for (i = 0; i < info->num; ++i) {
if (kmp_location_match(&loc, &items[i])) {
num_threads = items[i].num_threads;
}
}
__kmp_str_loc_free(&loc);
}
return num_threads;
;
} // __kmp_omp_num_threads
#endif /* USE_DEBUGGER */
+21 -23
View File
@@ -3,7 +3,6 @@
* kmp_debugger.h -- debugger support.
*/
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
@@ -13,39 +12,38 @@
//
//===----------------------------------------------------------------------===//
#ifndef KMP_DEBUGGER_H
#define KMP_DEBUGGER_H
#ifdef __cplusplus
extern "C" {
extern "C" {
#endif // __cplusplus
/* * This external variable can be set by any debugger to flag to the runtime that we
are currently executing inside a debugger. This will allow the debugger to override
the number of threads spawned in a parallel region by using __kmp_omp_num_threads() (below).
* When __kmp_debugging is TRUE, each team and each task gets a unique integer identifier
that can be used by debugger to conveniently identify teams and tasks.
* The debugger has access to __kmp_omp_debug_struct_info which contains information
about the OpenMP library's important internal structures. This access will allow the debugger
to read detailed information from the typical OpenMP constructs (teams, threads, tasking, etc. )
during a debugging session and offer detailed and useful information which the user can probe
about the OpenMP portion of their code.
*/
extern int __kmp_debugging; /* Boolean whether currently debugging OpenMP RTL */
/* This external variable can be set by any debugger to flag to the runtime
that we are currently executing inside a debugger. This will allow the
debugger to override the number of threads spawned in a parallel region by
using __kmp_omp_num_threads() (below).
* When __kmp_debugging is TRUE, each team and each task gets a unique integer
identifier that can be used by debugger to conveniently identify teams and
tasks.
* The debugger has access to __kmp_omp_debug_struct_info which contains
information about the OpenMP library's important internal structures. This
access will allow the debugger to read detailed information from the typical
OpenMP constructs (teams, threads, tasking, etc. ) during a debugging
session and offer detailed and useful information which the user can probe
about the OpenMP portion of their code. */
extern int __kmp_debugging; /* Boolean whether currently debugging OpenMP RTL */
// Return number of threads specified by the debugger for given parallel region.
/* The ident field, which represents a source file location, is used to check if the
debugger has changed the number of threads for the parallel region at source file
location ident. This way, specific parallel regions' number of threads can be changed
at the debugger's request.
*/
int __kmp_omp_num_threads( ident_t const * ident );
/* The ident field, which represents a source file location, is used to check if
the debugger has changed the number of threads for the parallel region at
source file location ident. This way, specific parallel regions' number of
threads can be changed at the debugger's request. */
int __kmp_omp_num_threads(ident_t const *ident);
#ifdef __cplusplus
} // extern "C"
} // extern "C"
#endif // __cplusplus
#endif // KMP_DEBUGGER_H
#endif // USE_DEBUGGER
+2529 -2419
View File
File diff suppressed because it is too large Load Diff
-596
View File
@@ -1,596 +0,0 @@
/*
* kmp_environment.c -- Handle environment variables OS-independently.
*/
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
/*
------------------------------------------------------------------------------------------------
We use GetEnvironmentVariable for Windows* OS instead of getenv because the act of
loading a DLL on Windows* OS makes any user-set environment variables (i.e. with putenv())
unavailable. getenv() apparently gets a clean copy of the env variables as they existed
at the start of the run.
JH 12/23/2002
------------------------------------------------------------------------------------------------
On Windows* OS, there are two environments (at least, see below):
1. Environment maintained by Windows* OS on IA-32 architecture.
Accessible through GetEnvironmentVariable(),
SetEnvironmentVariable(), and GetEnvironmentStrings().
2. Environment maintained by C RTL. Accessible through getenv(), putenv().
putenv() function updates both C and Windows* OS on IA-32 architecture. getenv() function
search for variables in C RTL environment only. Windows* OS on IA-32 architecture functions work *only*
with Windows* OS on IA-32 architecture.
Windows* OS on IA-32 architecture maintained by OS, so there is always only one Windows* OS on
IA-32 architecture per process. Changes in Windows* OS on IA-32 architecture are process-visible.
C environment maintained by C RTL. Multiple copies of C RTL may be present in the process, and
each C RTL maintains its own environment. :-(
Thus, proper way to work with environment on Windows* OS is:
1. Set variables with putenv() function -- both C and Windows* OS on
IA-32 architecture are being updated. Windows* OS on
IA-32 architecture may be considered as primary target,
while updating C RTL environment is a free bonus.
2. Get variables with GetEnvironmentVariable() -- getenv() does not
search Windows* OS on IA-32 architecture, and can not see variables
set with SetEnvironmentVariable().
2007-04-05 -- lev
------------------------------------------------------------------------------------------------
*/
#include "kmp_environment.h"
#include "kmp_os.h" // KMP_OS_*.
#include "kmp.h" //
#include "kmp_str.h" // __kmp_str_*().
#include "kmp_i18n.h"
#if KMP_OS_UNIX
#include <stdlib.h> // getenv, setenv, unsetenv.
#include <string.h> // strlen, strcpy.
#if KMP_OS_DARWIN
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#else
extern char * * environ;
#endif
#elif KMP_OS_WINDOWS
#include <windows.h> // GetEnvironmentVariable, SetEnvironmentVariable, GetLastError.
#else
#error Unknown or unsupported OS.
#endif
// TODO: Eliminate direct memory allocations, use string operations instead.
static inline
void *
allocate(
size_t size
) {
void * ptr = KMP_INTERNAL_MALLOC( size );
if ( ptr == NULL ) {
KMP_FATAL( MemoryAllocFailed );
}; // if
return ptr;
} // allocate
char *
__kmp_env_get( char const * name ) {
char * result = NULL;
#if KMP_OS_UNIX
char const * value = getenv( name );
if ( value != NULL ) {
size_t len = KMP_STRLEN( value ) + 1;
result = (char *) KMP_INTERNAL_MALLOC( len );
if ( result == NULL ) {
KMP_FATAL( MemoryAllocFailed );
}; // if
KMP_STRNCPY_S( result, len, value, len );
}; // if
#elif KMP_OS_WINDOWS
/*
We use GetEnvironmentVariable for Windows* OS instead of getenv because the act of
loading a DLL on Windows* OS makes any user-set environment variables (i.e. with putenv())
unavailable. getenv() apparently gets a clean copy of the env variables as they existed
at the start of the run.
JH 12/23/2002
*/
DWORD rc;
rc = GetEnvironmentVariable( name, NULL, 0 );
if ( ! rc ) {
DWORD error = GetLastError();
if ( error != ERROR_ENVVAR_NOT_FOUND ) {
__kmp_msg(
kmp_ms_fatal,
KMP_MSG( CantGetEnvVar, name ),
KMP_ERR( error ),
__kmp_msg_null
);
}; // if
// Variable is not found, it's ok, just continue.
} else {
DWORD len = rc;
result = (char *) KMP_INTERNAL_MALLOC( len );
if ( result == NULL ) {
KMP_FATAL( MemoryAllocFailed );
}; // if
rc = GetEnvironmentVariable( name, result, len );
if ( ! rc ) {
// GetEnvironmentVariable() may return 0 if variable is empty.
// In such a case GetLastError() returns ERROR_SUCCESS.
DWORD error = GetLastError();
if ( error != ERROR_SUCCESS ) {
// Unexpected error. The variable should be in the environment,
// and buffer should be large enough.
__kmp_msg(
kmp_ms_fatal,
KMP_MSG( CantGetEnvVar, name ),
KMP_ERR( error ),
__kmp_msg_null
);
KMP_INTERNAL_FREE( (void *) result );
result = NULL;
}; // if
}; // if
}; // if
#else
#error Unknown or unsupported OS.
#endif
return result;
} // func __kmp_env_get
// TODO: Find and replace all regular free() with __kmp_env_free().
void
__kmp_env_free( char const * * value ) {
KMP_DEBUG_ASSERT( value != NULL );
KMP_INTERNAL_FREE( (void *) * value );
* value = NULL;
} // func __kmp_env_free
int
__kmp_env_exists( char const * name ) {
#if KMP_OS_UNIX
char const * value = getenv( name );
return ( ( value == NULL ) ? ( 0 ) : ( 1 ) );
#elif KMP_OS_WINDOWS
DWORD rc;
rc = GetEnvironmentVariable( name, NULL, 0 );
if ( rc == 0 ) {
DWORD error = GetLastError();
if ( error != ERROR_ENVVAR_NOT_FOUND ) {
__kmp_msg(
kmp_ms_fatal,
KMP_MSG( CantGetEnvVar, name ),
KMP_ERR( error ),
__kmp_msg_null
);
}; // if
return 0;
}; // if
return 1;
#else
#error Unknown or unsupported OS.
#endif
} // func __kmp_env_exists
void
__kmp_env_set( char const * name, char const * value, int overwrite ) {
#if KMP_OS_UNIX
int rc = setenv( name, value, overwrite );
if ( rc != 0 ) {
// Dead code. I tried to put too many variables into Linux* OS
// environment on IA-32 architecture. When application consumes
// more than ~2.5 GB of memory, entire system feels bad. Sometimes
// application is killed (by OS?), sometimes system stops
// responding... But this error message never appears. --ln
__kmp_msg(
kmp_ms_fatal,
KMP_MSG( CantSetEnvVar, name ),
KMP_HNT( NotEnoughMemory ),
__kmp_msg_null
);
}; // if
#elif KMP_OS_WINDOWS
BOOL rc;
if ( ! overwrite ) {
rc = GetEnvironmentVariable( name, NULL, 0 );
if ( rc ) {
// Variable exists, do not overwrite.
return;
}; // if
DWORD error = GetLastError();
if ( error != ERROR_ENVVAR_NOT_FOUND ) {
__kmp_msg(
kmp_ms_fatal,
KMP_MSG( CantGetEnvVar, name ),
KMP_ERR( error ),
__kmp_msg_null
);
}; // if
}; // if
rc = SetEnvironmentVariable( name, value );
if ( ! rc ) {
DWORD error = GetLastError();
__kmp_msg(
kmp_ms_fatal,
KMP_MSG( CantSetEnvVar, name ),
KMP_ERR( error ),
__kmp_msg_null
);
}; // if
#else
#error Unknown or unsupported OS.
#endif
} // func __kmp_env_set
void
__kmp_env_unset( char const * name ) {
#if KMP_OS_UNIX
unsetenv( name );
#elif KMP_OS_WINDOWS
BOOL rc = SetEnvironmentVariable( name, NULL );
if ( ! rc ) {
DWORD error = GetLastError();
__kmp_msg(
kmp_ms_fatal,
KMP_MSG( CantSetEnvVar, name ),
KMP_ERR( error ),
__kmp_msg_null
);
}; // if
#else
#error Unknown or unsupported OS.
#endif
} // func __kmp_env_unset
// -------------------------------------------------------------------------------------------------
/*
Intel OpenMP RTL string representation of environment: just a string of characters, variables
are separated with vertical bars, e. g.:
"KMP_WARNINGS=0|KMP_AFFINITY=compact|"
Empty variables are allowed and ignored:
"||KMP_WARNINGS=1||"
*/
static
void
___kmp_env_blk_parse_string(
kmp_env_blk_t * block, // M: Env block to fill.
char const * env // I: String to parse.
) {
char const chr_delimiter = '|';
char const str_delimiter[] = { chr_delimiter, 0 };
char * bulk = NULL;
kmp_env_var_t * vars = NULL;
int count = 0; // Number of used elements in vars array.
int delimiters = 0; // Number of delimiters in input string.
// Copy original string, we will modify the copy.
bulk = __kmp_str_format( "%s", env );
// Loop thru all the vars in environment block. Count delimiters (maximum number of variables
// is number of delimiters plus one).
{
char const * ptr = bulk;
for ( ; ; ) {
ptr = strchr( ptr, chr_delimiter );
if ( ptr == NULL ) {
break;
}; // if
++ delimiters;
ptr += 1;
}; // forever
}
// Allocate vars array.
vars = (kmp_env_var_t *) allocate( ( delimiters + 1 ) * sizeof( kmp_env_var_t ) );
// Loop thru all the variables.
{
char * var; // Pointer to variable (both name and value).
char * name; // Pointer to name of variable.
char * value; // Pointer to value.
char * buf; // Buffer for __kmp_str_token() function.
var = __kmp_str_token( bulk, str_delimiter, & buf ); // Get the first var.
while ( var != NULL ) {
// Save found variable in vars array.
__kmp_str_split( var, '=', & name, & value );
KMP_DEBUG_ASSERT( count < delimiters + 1 );
vars[ count ].name = name;
vars[ count ].value = value;
++ count;
// Get the next var.
var = __kmp_str_token( NULL, str_delimiter, & buf );
}; // while
}
// Fill out result.
block->bulk = bulk;
block->vars = vars;
block->count = count;
}; // ___kmp_env_blk_parse_string
/*
Windows* OS (actually, DOS) environment block is a piece of memory with environment variables. Each
variable is terminated with zero byte, entire block is terminated with one extra zero byte, so
we have two zero bytes at the end of environment block, e. g.:
"HOME=C:\\users\\lev\x00OS=Windows_NT\x00\x00"
It is not clear how empty environment is represented. "\x00\x00"?
*/
#if KMP_OS_WINDOWS
static
void
___kmp_env_blk_parse_windows(
kmp_env_blk_t * block, // M: Env block to fill.
char const * env // I: Pointer to Windows* OS (DOS) environment block.
) {
char * bulk = NULL;
kmp_env_var_t * vars = NULL;
int count = 0; // Number of used elements in vars array.
int size = 0; // Size of bulk.
char * name; // Pointer to name of variable.
char * value; // Pointer to value.
if ( env != NULL ) {
// Loop thru all the vars in environment block. Count variables, find size of block.
{
char const * var; // Pointer to beginning of var.
int len; // Length of variable.
count = 0;
var = env; // The first variable starts and beginning of environment block.
len = KMP_STRLEN( var );
while ( len != 0 ) {
++ count;
size = size + len + 1;
var = var + len + 1; // Move pointer to the beginning of the next variable.
len = KMP_STRLEN( var );
}; // while
size = size + 1; // Total size of env block, including terminating zero byte.
}
// Copy original block to bulk, we will modify bulk, not original block.
bulk = (char *) allocate( size );
KMP_MEMCPY_S( bulk, size, env, size );
// Allocate vars array.
vars = (kmp_env_var_t *) allocate( count * sizeof( kmp_env_var_t ) );
// Loop thru all the vars, now in bulk.
{
char * var; // Pointer to beginning of var.
int len; // Length of variable.
count = 0;
var = bulk;
len = KMP_STRLEN( var );
while ( len != 0 ) {
// Save variable in vars array.
__kmp_str_split( var, '=', & name, & value );
vars[ count ].name = name;
vars[ count ].value = value;
++ count;
// Get the next var.
var = var + len + 1;
len = KMP_STRLEN( var );
}; // while
}
}; // if
// Fill out result.
block->bulk = bulk;
block->vars = vars;
block->count = count;
}; // ___kmp_env_blk_parse_windows
#endif
/*
Unix environment block is a array of pointers to variables, last pointer in array is NULL:
{ "HOME=/home/lev", "TERM=xterm", NULL }
*/
static
void
___kmp_env_blk_parse_unix(
kmp_env_blk_t * block, // M: Env block to fill.
char * * env // I: Unix environment to parse.
) {
char * bulk = NULL;
kmp_env_var_t * vars = NULL;
int count = 0;
int size = 0; // Size of bulk.
// Count number of variables and length of required bulk.
{
count = 0;
size = 0;
while ( env[ count ] != NULL ) {
size += KMP_STRLEN( env[ count ] ) + 1;
++ count;
}; // while
}
// Allocate memory.
bulk = (char *) allocate( size );
vars = (kmp_env_var_t *) allocate( count * sizeof( kmp_env_var_t ) );
// Loop thru all the vars.
{
char * var; // Pointer to beginning of var.
char * name; // Pointer to name of variable.
char * value; // Pointer to value.
int len; // Length of variable.
int i;
var = bulk;
for ( i = 0; i < count; ++ i ) {
// Copy variable to bulk.
len = KMP_STRLEN( env[ i ] );
KMP_MEMCPY_S( var, size, env[ i ], len + 1 );
// Save found variable in vars array.
__kmp_str_split( var, '=', & name, & value );
vars[ i ].name = name;
vars[ i ].value = value;
// Move pointer.
var += len + 1;
}; // for
}
// Fill out result.
block->bulk = bulk;
block->vars = vars;
block->count = count;
}; // ___kmp_env_blk_parse_unix
void
__kmp_env_blk_init(
kmp_env_blk_t * block, // M: Block to initialize.
char const * bulk // I: Initialization string, or NULL.
) {
if ( bulk != NULL ) {
___kmp_env_blk_parse_string( block, bulk );
} else {
#if KMP_OS_UNIX
___kmp_env_blk_parse_unix( block, environ );
#elif KMP_OS_WINDOWS
{
char * mem = GetEnvironmentStrings();
if ( mem == NULL ) {
DWORD error = GetLastError();
__kmp_msg(
kmp_ms_fatal,
KMP_MSG( CantGetEnvironment ),
KMP_ERR( error ),
__kmp_msg_null
);
}; // if
___kmp_env_blk_parse_windows( block, mem );
FreeEnvironmentStrings( mem );
}
#else
#error Unknown or unsupported OS.
#endif
}; // if
} // __kmp_env_blk_init
static
int
___kmp_env_var_cmp( // Comparison function for qsort().
kmp_env_var_t const * lhs,
kmp_env_var_t const * rhs
) {
return strcmp( lhs->name, rhs->name );
}
void
__kmp_env_blk_sort(
kmp_env_blk_t * block // M: Block of environment variables to sort.
) {
qsort(
(void *) block->vars,
block->count,
sizeof( kmp_env_var_t ),
( int ( * )( void const *, void const * ) ) & ___kmp_env_var_cmp
);
} // __kmp_env_block_sort
void
__kmp_env_blk_free(
kmp_env_blk_t * block // M: Block of environment variables to free.
) {
KMP_INTERNAL_FREE( (void *) block->vars );
KMP_INTERNAL_FREE( (void *) block->bulk );
block->count = 0;
block->vars = NULL;
block->bulk = NULL;
} // __kmp_env_blk_free
char const * // R: Value of variable or NULL if variable does not exist.
__kmp_env_blk_var(
kmp_env_blk_t * block, // I: Block of environment variables.
char const * name // I: Name of variable to find.
) {
int i;
for ( i = 0; i < block->count; ++ i ) {
if ( strcmp( block->vars[ i ].name, name ) == 0 ) {
return block->vars[ i ].value;
}; // if
}; // for
return NULL;
} // __kmp_env_block_var
// end of file //
+501
View File
@@ -0,0 +1,501 @@
/*
* kmp_environment.cpp -- Handle environment variables OS-independently.
*/
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
/* We use GetEnvironmentVariable for Windows* OS instead of getenv because the
act of loading a DLL on Windows* OS makes any user-set environment variables
(i.e. with putenv()) unavailable. getenv() apparently gets a clean copy of
the env variables as they existed at the start of the run. JH 12/23/2002
On Windows* OS, there are two environments (at least, see below):
1. Environment maintained by Windows* OS on IA-32 architecture. Accessible
through GetEnvironmentVariable(), SetEnvironmentVariable(), and
GetEnvironmentStrings().
2. Environment maintained by C RTL. Accessible through getenv(), putenv().
putenv() function updates both C and Windows* OS on IA-32 architecture.
getenv() function search for variables in C RTL environment only.
Windows* OS on IA-32 architecture functions work *only* with Windows* OS on
IA-32 architecture.
Windows* OS on IA-32 architecture maintained by OS, so there is always only
one Windows* OS on IA-32 architecture per process. Changes in Windows* OS on
IA-32 architecture are process-visible.
C environment maintained by C RTL. Multiple copies of C RTL may be present
in the process, and each C RTL maintains its own environment. :-(
Thus, proper way to work with environment on Windows* OS is:
1. Set variables with putenv() function -- both C and Windows* OS on IA-32
architecture are being updated. Windows* OS on IA-32 architecture may be
considered primary target, while updating C RTL environment is free bonus.
2. Get variables with GetEnvironmentVariable() -- getenv() does not
search Windows* OS on IA-32 architecture, and can not see variables
set with SetEnvironmentVariable().
2007-04-05 -- lev
*/
#include "kmp_environment.h"
#include "kmp.h" //
#include "kmp_i18n.h"
#include "kmp_os.h" // KMP_OS_*.
#include "kmp_str.h" // __kmp_str_*().
#if KMP_OS_UNIX
#include <stdlib.h> // getenv, setenv, unsetenv.
#include <string.h> // strlen, strcpy.
#if KMP_OS_DARWIN
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#else
extern char **environ;
#endif
#elif KMP_OS_WINDOWS
#include <windows.h> // GetEnvironmentVariable, SetEnvironmentVariable,
// GetLastError.
#else
#error Unknown or unsupported OS.
#endif
// TODO: Eliminate direct memory allocations, use string operations instead.
static inline void *allocate(size_t size) {
void *ptr = KMP_INTERNAL_MALLOC(size);
if (ptr == NULL) {
KMP_FATAL(MemoryAllocFailed);
}
return ptr;
} // allocate
char *__kmp_env_get(char const *name) {
char *result = NULL;
#if KMP_OS_UNIX
char const *value = getenv(name);
if (value != NULL) {
size_t len = KMP_STRLEN(value) + 1;
result = (char *)KMP_INTERNAL_MALLOC(len);
if (result == NULL) {
KMP_FATAL(MemoryAllocFailed);
}
KMP_STRNCPY_S(result, len, value, len);
}
#elif KMP_OS_WINDOWS
/* We use GetEnvironmentVariable for Windows* OS instead of getenv because the
act of loading a DLL on Windows* OS makes any user-set environment
variables (i.e. with putenv()) unavailable. getenv() apparently gets a
clean copy of the env variables as they existed at the start of the run.
JH 12/23/2002 */
DWORD rc;
rc = GetEnvironmentVariable(name, NULL, 0);
if (!rc) {
DWORD error = GetLastError();
if (error != ERROR_ENVVAR_NOT_FOUND) {
__kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
}
// Variable is not found, it's ok, just continue.
} else {
DWORD len = rc;
result = (char *)KMP_INTERNAL_MALLOC(len);
if (result == NULL) {
KMP_FATAL(MemoryAllocFailed);
}
rc = GetEnvironmentVariable(name, result, len);
if (!rc) {
// GetEnvironmentVariable() may return 0 if variable is empty.
// In such a case GetLastError() returns ERROR_SUCCESS.
DWORD error = GetLastError();
if (error != ERROR_SUCCESS) {
// Unexpected error. The variable should be in the environment,
// and buffer should be large enough.
__kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error),
__kmp_msg_null);
KMP_INTERNAL_FREE((void *)result);
result = NULL;
}
}
}
#else
#error Unknown or unsupported OS.
#endif
return result;
} // func __kmp_env_get
// TODO: Find and replace all regular free() with __kmp_env_free().
void __kmp_env_free(char const **value) {
KMP_DEBUG_ASSERT(value != NULL);
KMP_INTERNAL_FREE(CCAST(char *, *value));
*value = NULL;
} // func __kmp_env_free
int __kmp_env_exists(char const *name) {
#if KMP_OS_UNIX
char const *value = getenv(name);
return ((value == NULL) ? (0) : (1));
#elif KMP_OS_WINDOWS
DWORD rc;
rc = GetEnvironmentVariable(name, NULL, 0);
if (rc == 0) {
DWORD error = GetLastError();
if (error != ERROR_ENVVAR_NOT_FOUND) {
__kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
}
return 0;
}
return 1;
#else
#error Unknown or unsupported OS.
#endif
} // func __kmp_env_exists
void __kmp_env_set(char const *name, char const *value, int overwrite) {
#if KMP_OS_UNIX
int rc = setenv(name, value, overwrite);
if (rc != 0) {
// Dead code. I tried to put too many variables into Linux* OS
// environment on IA-32 architecture. When application consumes
// more than ~2.5 GB of memory, entire system feels bad. Sometimes
// application is killed (by OS?), sometimes system stops
// responding... But this error message never appears. --ln
__kmp_fatal(KMP_MSG(CantSetEnvVar, name), KMP_HNT(NotEnoughMemory),
__kmp_msg_null);
}
#elif KMP_OS_WINDOWS
BOOL rc;
if (!overwrite) {
rc = GetEnvironmentVariable(name, NULL, 0);
if (rc) {
// Variable exists, do not overwrite.
return;
}
DWORD error = GetLastError();
if (error != ERROR_ENVVAR_NOT_FOUND) {
__kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
}
}
rc = SetEnvironmentVariable(name, value);
if (!rc) {
DWORD error = GetLastError();
__kmp_fatal(KMP_MSG(CantSetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
}
#else
#error Unknown or unsupported OS.
#endif
} // func __kmp_env_set
void __kmp_env_unset(char const *name) {
#if KMP_OS_UNIX
unsetenv(name);
#elif KMP_OS_WINDOWS
BOOL rc = SetEnvironmentVariable(name, NULL);
if (!rc) {
DWORD error = GetLastError();
__kmp_fatal(KMP_MSG(CantSetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
}
#else
#error Unknown or unsupported OS.
#endif
} // func __kmp_env_unset
/* Intel OpenMP RTL string representation of environment: just a string of
characters, variables are separated with vertical bars, e. g.:
"KMP_WARNINGS=0|KMP_AFFINITY=compact|"
Empty variables are allowed and ignored:
"||KMP_WARNINGS=1||"
*/
static void
___kmp_env_blk_parse_string(kmp_env_blk_t *block, // M: Env block to fill.
char const *env // I: String to parse.
) {
char const chr_delimiter = '|';
char const str_delimiter[] = {chr_delimiter, 0};
char *bulk = NULL;
kmp_env_var_t *vars = NULL;
int count = 0; // Number of used elements in vars array.
int delimiters = 0; // Number of delimiters in input string.
// Copy original string, we will modify the copy.
bulk = __kmp_str_format("%s", env);
// Loop thru all the vars in environment block. Count delimiters (maximum
// number of variables is number of delimiters plus one).
{
char const *ptr = bulk;
for (;;) {
ptr = strchr(ptr, chr_delimiter);
if (ptr == NULL) {
break;
}
++delimiters;
ptr += 1;
}
}
// Allocate vars array.
vars = (kmp_env_var_t *)allocate((delimiters + 1) * sizeof(kmp_env_var_t));
// Loop thru all the variables.
{
char *var; // Pointer to variable (both name and value).
char *name; // Pointer to name of variable.
char *value; // Pointer to value.
char *buf; // Buffer for __kmp_str_token() function.
var = __kmp_str_token(bulk, str_delimiter, &buf); // Get the first var.
while (var != NULL) {
// Save found variable in vars array.
__kmp_str_split(var, '=', &name, &value);
KMP_DEBUG_ASSERT(count < delimiters + 1);
vars[count].name = name;
vars[count].value = value;
++count;
// Get the next var.
var = __kmp_str_token(NULL, str_delimiter, &buf);
}
}
// Fill out result.
block->bulk = bulk;
block->vars = vars;
block->count = count;
}
/* Windows* OS (actually, DOS) environment block is a piece of memory with
environment variables. Each variable is terminated with zero byte, entire
block is terminated with one extra zero byte, so we have two zero bytes at
the end of environment block, e. g.:
"HOME=C:\\users\\lev\x00OS=Windows_NT\x00\x00"
It is not clear how empty environment is represented. "\x00\x00"?
*/
#if KMP_OS_WINDOWS
static void ___kmp_env_blk_parse_windows(
kmp_env_blk_t *block, // M: Env block to fill.
char const *env // I: Pointer to Windows* OS (DOS) environment block.
) {
char *bulk = NULL;
kmp_env_var_t *vars = NULL;
int count = 0; // Number of used elements in vars array.
int size = 0; // Size of bulk.
char *name; // Pointer to name of variable.
char *value; // Pointer to value.
if (env != NULL) {
// Loop thru all the vars in environment block. Count variables, find size
// of block.
{
char const *var; // Pointer to beginning of var.
int len; // Length of variable.
count = 0;
var =
env; // The first variable starts and beginning of environment block.
len = KMP_STRLEN(var);
while (len != 0) {
++count;
size = size + len + 1;
var = var + len +
1; // Move pointer to the beginning of the next variable.
len = KMP_STRLEN(var);
}
size =
size + 1; // Total size of env block, including terminating zero byte.
}
// Copy original block to bulk, we will modify bulk, not original block.
bulk = (char *)allocate(size);
KMP_MEMCPY_S(bulk, size, env, size);
// Allocate vars array.
vars = (kmp_env_var_t *)allocate(count * sizeof(kmp_env_var_t));
// Loop thru all the vars, now in bulk.
{
char *var; // Pointer to beginning of var.
int len; // Length of variable.
count = 0;
var = bulk;
len = KMP_STRLEN(var);
while (len != 0) {
// Save variable in vars array.
__kmp_str_split(var, '=', &name, &value);
vars[count].name = name;
vars[count].value = value;
++count;
// Get the next var.
var = var + len + 1;
len = KMP_STRLEN(var);
}
}
}
// Fill out result.
block->bulk = bulk;
block->vars = vars;
block->count = count;
}
#endif
/* Unix environment block is a array of pointers to variables, last pointer in
array is NULL:
{ "HOME=/home/lev", "TERM=xterm", NULL }
*/
static void
___kmp_env_blk_parse_unix(kmp_env_blk_t *block, // M: Env block to fill.
char **env // I: Unix environment to parse.
) {
char *bulk = NULL;
kmp_env_var_t *vars = NULL;
int count = 0;
int size = 0; // Size of bulk.
// Count number of variables and length of required bulk.
{
count = 0;
size = 0;
while (env[count] != NULL) {
size += KMP_STRLEN(env[count]) + 1;
++count;
}
}
// Allocate memory.
bulk = (char *)allocate(size);
vars = (kmp_env_var_t *)allocate(count * sizeof(kmp_env_var_t));
// Loop thru all the vars.
{
char *var; // Pointer to beginning of var.
char *name; // Pointer to name of variable.
char *value; // Pointer to value.
int len; // Length of variable.
int i;
var = bulk;
for (i = 0; i < count; ++i) {
// Copy variable to bulk.
len = KMP_STRLEN(env[i]);
KMP_MEMCPY_S(var, size, env[i], len + 1);
// Save found variable in vars array.
__kmp_str_split(var, '=', &name, &value);
vars[i].name = name;
vars[i].value = value;
// Move pointer.
var += len + 1;
}
}
// Fill out result.
block->bulk = bulk;
block->vars = vars;
block->count = count;
}
void __kmp_env_blk_init(kmp_env_blk_t *block, // M: Block to initialize.
char const *bulk // I: Initialization string, or NULL.
) {
if (bulk != NULL) {
___kmp_env_blk_parse_string(block, bulk);
} else {
#if KMP_OS_UNIX
___kmp_env_blk_parse_unix(block, environ);
#elif KMP_OS_WINDOWS
{
char *mem = GetEnvironmentStrings();
if (mem == NULL) {
DWORD error = GetLastError();
__kmp_fatal(KMP_MSG(CantGetEnvironment), KMP_ERR(error),
__kmp_msg_null);
}
___kmp_env_blk_parse_windows(block, mem);
FreeEnvironmentStrings(mem);
}
#else
#error Unknown or unsupported OS.
#endif
}
} // __kmp_env_blk_init
static int ___kmp_env_var_cmp( // Comparison function for qsort().
kmp_env_var_t const *lhs, kmp_env_var_t const *rhs) {
return strcmp(lhs->name, rhs->name);
}
void __kmp_env_blk_sort(
kmp_env_blk_t *block // M: Block of environment variables to sort.
) {
qsort(CCAST(kmp_env_var_t *, block->vars), block->count,
sizeof(kmp_env_var_t),
(int (*)(void const *, void const *)) & ___kmp_env_var_cmp);
} // __kmp_env_block_sort
void __kmp_env_blk_free(
kmp_env_blk_t *block // M: Block of environment variables to free.
) {
KMP_INTERNAL_FREE(CCAST(kmp_env_var_t *, block->vars));
__kmp_str_free(&(block->bulk));
block->count = 0;
block->vars = NULL;
} // __kmp_env_blk_free
char const * // R: Value of variable or NULL if variable does not exist.
__kmp_env_blk_var(
kmp_env_blk_t *block, // I: Block of environment variables.
char const *name // I: Name of variable to find.
) {
int i;
for (i = 0; i < block->count; ++i) {
if (strcmp(block->vars[i].name, name) == 0) {
return block->vars[i].value;
}
}
return NULL;
} // __kmp_env_block_var
// end of file //
+29 -32
View File
@@ -2,7 +2,6 @@
* kmp_environment.h -- Handle environment varoiables OS-independently.
*/
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
@@ -12,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
#ifndef KMP_ENVIRONMENT_H
#define KMP_ENVIRONMENT_H
@@ -20,56 +18,56 @@
extern "C" {
#endif
// Return a copy of the value of environment variable or NULL if the variable does not exist.
// Return a copy of the value of environment variable or NULL if the variable
// does not exist.
// *Note*: Returned pointed *must* be freed after use with __kmp_env_free().
char * __kmp_env_get( char const * name );
void __kmp_env_free( char const * * value );
char *__kmp_env_get(char const *name);
void __kmp_env_free(char const **value);
// Return 1 if the environment variable exists or 0 if does not exist.
int __kmp_env_exists( char const * name );
int __kmp_env_exists(char const *name);
// Set the environment variable.
void __kmp_env_set( char const * name, char const * value, int overwrite );
void __kmp_env_set(char const *name, char const *value, int overwrite);
// Unset (remove) environment variable.
void __kmp_env_unset( char const * name );
void __kmp_env_unset(char const *name);
// -------------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// Working with environment blocks.
// -------------------------------------------------------------------------------------------------
/*
kmp_env_blk_t is read-only collection of environment variables (or environment-like). Usage:
/* kmp_env_blk_t is read-only collection of environment variables (or
environment-like). Usage:
kmp_env_blk_t block;
__kmp_env_blk_init( & block, NULL ); // Initialize block from process environment.
// or
__kmp_env_blk_init( & block, "KMP_WARNING=1|KMP_AFFINITY=none" ); // from string.
__kmp_env_blk_sort( & block ); // Optionally, sort list.
for ( i = 0; i < block.count; ++ i ) {
// Process block.vars[ i ].name and block.vars[ i ].value...
}; // for i
__kmp_env_block_free( & block );
kmp_env_blk_t block;
__kmp_env_blk_init( & block, NULL ); // Initialize block from process
// environment.
// or
__kmp_env_blk_init( & block, "KMP_WARNING=1|KMP_AFFINITY=none" ); // from string
__kmp_env_blk_sort( & block ); // Optionally, sort list.
for ( i = 0; i < block.count; ++ i ) {
// Process block.vars[ i ].name and block.vars[ i ].value...
}
__kmp_env_block_free( & block );
*/
struct __kmp_env_var {
char const * name;
char const * value;
char *name;
char *value;
};
typedef struct __kmp_env_var kmp_env_var_t;
struct __kmp_env_blk {
char const * bulk;
kmp_env_var_t const * vars;
int count;
char *bulk;
kmp_env_var_t *vars;
int count;
};
typedef struct __kmp_env_blk kmp_env_blk_t;
void __kmp_env_blk_init( kmp_env_blk_t * block, char const * bulk );
void __kmp_env_blk_free( kmp_env_blk_t * block );
void __kmp_env_blk_sort( kmp_env_blk_t * block );
char const * __kmp_env_blk_var( kmp_env_blk_t * block, char const * name );
void __kmp_env_blk_init(kmp_env_blk_t *block, char const *bulk);
void __kmp_env_blk_free(kmp_env_blk_t *block);
void __kmp_env_blk_sort(kmp_env_blk_t *block);
char const *__kmp_env_blk_var(kmp_env_blk_t *block, char const *name);
#ifdef __cplusplus
}
@@ -78,4 +76,3 @@ char const * __kmp_env_blk_var( kmp_env_blk_t * block, char const * name );
#endif // KMP_ENVIRONMENT_H
// end of file //
-523
View File
@@ -1,523 +0,0 @@
/*
* kmp_error.c -- KPTS functions for error checking at runtime
*/
//===----------------------------------------------------------------------===//
//
// 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_str.h"
#include "kmp_error.h"
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
#define MIN_STACK 100
static char const * cons_text_c[] = {
"(none)",
"\"parallel\"",
"work-sharing", /* this is not called "for" because of lowering of "sections" pragmas */
"\"ordered\" work-sharing", /* this is not called "for ordered" because of lowering of "sections" pragmas */
"\"sections\"",
"work-sharing", /* this is not called "single" because of lowering of "sections" pragmas */
"\"taskq\"",
"\"taskq\"",
"\"taskq ordered\"",
"\"critical\"",
"\"ordered\"", /* in PARALLEL */
"\"ordered\"", /* in PDO */
"\"ordered\"", /* in TASKQ */
"\"master\"",
"\"reduce\"",
"\"barrier\""
};
#define get_src( ident ) ( (ident) == NULL ? NULL : (ident)->psource )
#define PUSH_MSG( ct, ident ) \
"\tpushing on stack: %s (%s)\n", cons_text_c[ (ct) ], get_src( (ident) )
#define POP_MSG( p ) \
"\tpopping off stack: %s (%s)\n", \
cons_text_c[ (p)->stack_data[ tos ].type ], \
get_src( (p)->stack_data[ tos ].ident )
static int const cons_text_c_num = sizeof( cons_text_c ) / sizeof( char const * );
/* ------------------------------------------------------------------------ */
/* --------------- START OF STATIC LOCAL ROUTINES ------------------------- */
/* ------------------------------------------------------------------------ */
static void
__kmp_check_null_func( void )
{
/* nothing to do */
}
static void
__kmp_expand_cons_stack( int gtid, struct cons_header *p )
{
int i;
struct cons_data *d;
/* TODO for monitor perhaps? */
if (gtid < 0)
__kmp_check_null_func();
KE_TRACE( 10, ("expand cons_stack (%d %d)\n", gtid, __kmp_get_gtid() ) );
d = p->stack_data;
p->stack_size = (p->stack_size * 2) + 100;
/* TODO free the old data */
p->stack_data = (struct cons_data *) __kmp_allocate( sizeof( struct cons_data ) * (p->stack_size+1) );
for (i = p->stack_top; i >= 0; --i)
p->stack_data[i] = d[i];
/* NOTE: we do not free the old stack_data */
}
// NOTE: Function returns allocated memory, caller must free it!
static char const *
__kmp_pragma(
int ct,
ident_t const * ident
) {
char const * cons = NULL; // Construct name.
char * file = NULL; // File name.
char * func = NULL; // Function (routine) name.
char * line = NULL; // Line number.
kmp_str_buf_t buffer;
kmp_msg_t prgm;
__kmp_str_buf_init( & buffer );
if ( 0 < ct && ct < cons_text_c_num ) {
cons = cons_text_c[ ct ];
} else {
KMP_DEBUG_ASSERT( 0 );
};
if ( ident != NULL && ident->psource != NULL ) {
char * tail = NULL;
__kmp_str_buf_print( & buffer, "%s", ident->psource ); // Copy source to buffer.
// Split string in buffer to file, func, and line.
tail = buffer.str;
__kmp_str_split( tail, ';', NULL, & tail );
__kmp_str_split( tail, ';', & file, & tail );
__kmp_str_split( tail, ';', & func, & tail );
__kmp_str_split( tail, ';', & line, & tail );
}; // if
prgm = __kmp_msg_format( kmp_i18n_fmt_Pragma, cons, file, func, line );
__kmp_str_buf_free( & buffer );
return prgm.str;
} // __kmp_pragma
/* ------------------------------------------------------------------------ */
/* ----------------- END OF STATIC LOCAL ROUTINES ------------------------- */
/* ------------------------------------------------------------------------ */
void
__kmp_error_construct(
kmp_i18n_id_t id, // Message identifier.
enum cons_type ct, // Construct type.
ident_t const * ident // Construct ident.
) {
char const * construct = __kmp_pragma( ct, ident );
__kmp_msg( kmp_ms_fatal, __kmp_msg_format( id, construct ), __kmp_msg_null );
KMP_INTERNAL_FREE( (void *) construct );
}
void
__kmp_error_construct2(
kmp_i18n_id_t id, // Message identifier.
enum cons_type ct, // First construct type.
ident_t const * ident, // First construct ident.
struct cons_data const * cons // Second construct.
) {
char const * construct1 = __kmp_pragma( ct, ident );
char const * construct2 = __kmp_pragma( cons->type, cons->ident );
__kmp_msg( kmp_ms_fatal, __kmp_msg_format( id, construct1, construct2 ), __kmp_msg_null );
KMP_INTERNAL_FREE( (void *) construct1 );
KMP_INTERNAL_FREE( (void *) construct2 );
}
struct cons_header *
__kmp_allocate_cons_stack( int gtid )
{
struct cons_header *p;
/* TODO for monitor perhaps? */
if ( gtid < 0 ) {
__kmp_check_null_func();
}; // if
KE_TRACE( 10, ("allocate cons_stack (%d)\n", gtid ) );
p = (struct cons_header *) __kmp_allocate( sizeof( struct cons_header ) );
p->p_top = p->w_top = p->s_top = 0;
p->stack_data = (struct cons_data *) __kmp_allocate( sizeof( struct cons_data ) * (MIN_STACK+1) );
p->stack_size = MIN_STACK;
p->stack_top = 0;
p->stack_data[ 0 ].type = ct_none;
p->stack_data[ 0 ].prev = 0;
p->stack_data[ 0 ].ident = NULL;
return p;
}
void
__kmp_free_cons_stack( void * ptr ) {
struct cons_header * p = (struct cons_header *) ptr;
if ( p != NULL ) {
if ( p->stack_data != NULL ) {
__kmp_free( p->stack_data );
p->stack_data = NULL;
}; // if
__kmp_free( p );
}; // if
}
#if KMP_DEBUG
static void
dump_cons_stack( int gtid, struct cons_header * p ) {
int i;
int tos = p->stack_top;
kmp_str_buf_t buffer;
__kmp_str_buf_init( & buffer );
__kmp_str_buf_print( & buffer, "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-\n" );
__kmp_str_buf_print( & buffer, "Begin construct stack with %d items for thread %d\n", tos, gtid );
__kmp_str_buf_print( & buffer, " stack_top=%d { P=%d, W=%d, S=%d }\n", tos, p->p_top, p->w_top, p->s_top );
for ( i = tos; i > 0; i-- ) {
struct cons_data * c = & ( p->stack_data[ i ] );
__kmp_str_buf_print( & buffer, " stack_data[%2d] = { %s (%s) %d %p }\n", i, cons_text_c[ c->type ], get_src( c->ident ), c->prev, c->name );
}; // for i
__kmp_str_buf_print( & buffer, "End construct stack for thread %d\n", gtid );
__kmp_str_buf_print( & buffer, "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-\n" );
__kmp_debug_printf( "%s", buffer.str );
__kmp_str_buf_free( & buffer );
}
#endif
void
__kmp_push_parallel( int gtid, ident_t const * ident )
{
int tos;
struct cons_header *p = __kmp_threads[ gtid ]->th.th_cons;
KMP_DEBUG_ASSERT( __kmp_threads[ gtid ]-> th.th_cons );
KE_TRACE( 10, ("__kmp_push_parallel (%d %d)\n", gtid, __kmp_get_gtid() ) );
KE_TRACE( 100, ( PUSH_MSG( ct_parallel, ident ) ) );
if ( p->stack_top >= p->stack_size ) {
__kmp_expand_cons_stack( gtid, p );
}; // if
tos = ++p->stack_top;
p->stack_data[ tos ].type = ct_parallel;
p->stack_data[ tos ].prev = p->p_top;
p->stack_data[ tos ].ident = ident;
p->stack_data[ tos ].name = NULL;
p->p_top = tos;
KE_DUMP( 1000, dump_cons_stack( gtid, p ) );
}
void
__kmp_check_workshare( int gtid, enum cons_type ct, ident_t const * ident )
{
struct cons_header *p = __kmp_threads[ gtid ]->th.th_cons;
KMP_DEBUG_ASSERT( __kmp_threads[ gtid ]-> th.th_cons );
KE_TRACE( 10, ("__kmp_check_workshare (%d %d)\n", gtid, __kmp_get_gtid() ) );
if ( p->stack_top >= p->stack_size ) {
__kmp_expand_cons_stack( gtid, p );
}; // if
if ( p->w_top > p->p_top &&
!(IS_CONS_TYPE_TASKQ(p->stack_data[ p->w_top ].type) && IS_CONS_TYPE_TASKQ(ct))) {
// We are already in a WORKSHARE construct for this PARALLEL region.
__kmp_error_construct2( kmp_i18n_msg_CnsInvalidNesting, ct, ident, & p->stack_data[ p->w_top ] );
}; // if
if ( p->s_top > p->p_top ) {
// We are already in a SYNC construct for this PARALLEL region.
__kmp_error_construct2( kmp_i18n_msg_CnsInvalidNesting, ct, ident, & p->stack_data[ p->s_top ] );
}; // if
}
void
__kmp_push_workshare( int gtid, enum cons_type ct, ident_t const * ident )
{
int tos;
struct cons_header *p = __kmp_threads[ gtid ]->th.th_cons;
KE_TRACE( 10, ("__kmp_push_workshare (%d %d)\n", gtid, __kmp_get_gtid() ) );
__kmp_check_workshare( gtid, ct, ident );
KE_TRACE( 100, ( PUSH_MSG( ct, ident ) ) );
tos = ++p->stack_top;
p->stack_data[ tos ].type = ct;
p->stack_data[ tos ].prev = p->w_top;
p->stack_data[ tos ].ident = ident;
p->stack_data[ tos ].name = NULL;
p->w_top = tos;
KE_DUMP( 1000, dump_cons_stack( gtid, p ) );
}
void
#if KMP_USE_DYNAMIC_LOCK
__kmp_check_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck, kmp_uint32 seq )
#else
__kmp_check_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck )
#endif
{
struct cons_header *p = __kmp_threads[ gtid ]->th.th_cons;
KE_TRACE( 10, ("__kmp_check_sync (gtid=%d)\n", __kmp_get_gtid() ) );
if (p->stack_top >= p->stack_size)
__kmp_expand_cons_stack( gtid, p );
if (ct == ct_ordered_in_parallel || ct == ct_ordered_in_pdo || ct == ct_ordered_in_taskq ) {
if (p->w_top <= p->p_top) {
/* we are not in a worksharing construct */
#ifdef BUILD_PARALLEL_ORDERED
/* do not report error messages for PARALLEL ORDERED */
KMP_ASSERT( ct == ct_ordered_in_parallel );
#else
__kmp_error_construct( kmp_i18n_msg_CnsBoundToWorksharing, ct, ident );
#endif /* BUILD_PARALLEL_ORDERED */
} else {
/* inside a WORKSHARING construct for this PARALLEL region */
if (!IS_CONS_TYPE_ORDERED(p->stack_data[ p->w_top ].type)) {
if (p->stack_data[ p->w_top ].type == ct_taskq) {
__kmp_error_construct2(
kmp_i18n_msg_CnsNotInTaskConstruct,
ct, ident,
& p->stack_data[ p->w_top ]
);
} else {
__kmp_error_construct2(
kmp_i18n_msg_CnsNoOrderedClause,
ct, ident,
& p->stack_data[ p->w_top ]
);
}
}
}
if (p->s_top > p->p_top && p->s_top > p->w_top) {
/* inside a sync construct which is inside a worksharing construct */
int index = p->s_top;
enum cons_type stack_type;
stack_type = p->stack_data[ index ].type;
if (stack_type == ct_critical ||
( ( stack_type == ct_ordered_in_parallel ||
stack_type == ct_ordered_in_pdo ||
stack_type == ct_ordered_in_taskq ) && /* C doesn't allow named ordered; ordered in ordered gets error */
p->stack_data[ index ].ident != NULL &&
(p->stack_data[ index ].ident->flags & KMP_IDENT_KMPC ))) {
/* we are in ORDERED which is inside an ORDERED or CRITICAL construct */
__kmp_error_construct2(
kmp_i18n_msg_CnsInvalidNesting,
ct, ident,
& p->stack_data[ index ]
);
}
}
} else if ( ct == ct_critical ) {
#if KMP_USE_DYNAMIC_LOCK
if ( lck != NULL && __kmp_get_user_lock_owner( lck, seq ) == gtid ) { /* this same thread already has lock for this critical section */
#else
if ( lck != NULL && __kmp_get_user_lock_owner( lck ) == gtid ) { /* this same thread already has lock for this critical section */
#endif
int index = p->s_top;
struct cons_data cons = { NULL, ct_critical, 0, NULL };
/* walk up construct stack and try to find critical with matching name */
while ( index != 0 && p->stack_data[ index ].name != lck ) {
index = p->stack_data[ index ].prev;
}
if ( index != 0 ) {
/* found match on the stack (may not always because of interleaved critical for Fortran) */
cons = p->stack_data[ index ];
}
/* we are in CRITICAL which is inside a CRITICAL construct of the same name */
__kmp_error_construct2( kmp_i18n_msg_CnsNestingSameName, ct, ident, & cons );
}
} else if ( ct == ct_master || ct == ct_reduce ) {
if (p->w_top > p->p_top) {
/* inside a WORKSHARING construct for this PARALLEL region */
__kmp_error_construct2(
kmp_i18n_msg_CnsInvalidNesting,
ct, ident,
& p->stack_data[ p->w_top ]
);
}
if (ct == ct_reduce && p->s_top > p->p_top) {
/* inside a another SYNC construct for this PARALLEL region */
__kmp_error_construct2(
kmp_i18n_msg_CnsInvalidNesting,
ct, ident,
& p->stack_data[ p->s_top ]
);
}; // if
}; // if
}
void
#if KMP_USE_DYNAMIC_LOCK
__kmp_push_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck, kmp_uint32 seq )
#else
__kmp_push_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck )
#endif
{
int tos;
struct cons_header *p = __kmp_threads[ gtid ]->th.th_cons;
KMP_ASSERT( gtid == __kmp_get_gtid() );
KE_TRACE( 10, ("__kmp_push_sync (gtid=%d)\n", gtid ) );
#if KMP_USE_DYNAMIC_LOCK
__kmp_check_sync( gtid, ct, ident, lck, seq );
#else
__kmp_check_sync( gtid, ct, ident, lck );
#endif
KE_TRACE( 100, ( PUSH_MSG( ct, ident ) ) );
tos = ++ p->stack_top;
p->stack_data[ tos ].type = ct;
p->stack_data[ tos ].prev = p->s_top;
p->stack_data[ tos ].ident = ident;
p->stack_data[ tos ].name = lck;
p->s_top = tos;
KE_DUMP( 1000, dump_cons_stack( gtid, p ) );
}
/* ------------------------------------------------------------------------ */
void
__kmp_pop_parallel( int gtid, ident_t const * ident )
{
int tos;
struct cons_header *p = __kmp_threads[ gtid ]->th.th_cons;
tos = p->stack_top;
KE_TRACE( 10, ("__kmp_pop_parallel (%d %d)\n", gtid, __kmp_get_gtid() ) );
if ( tos == 0 || p->p_top == 0 ) {
__kmp_error_construct( kmp_i18n_msg_CnsDetectedEnd, ct_parallel, ident );
}
if ( tos != p->p_top || p->stack_data[ tos ].type != ct_parallel ) {
__kmp_error_construct2(
kmp_i18n_msg_CnsExpectedEnd,
ct_parallel, ident,
& p->stack_data[ tos ]
);
}
KE_TRACE( 100, ( POP_MSG( p ) ) );
p->p_top = p->stack_data[ tos ].prev;
p->stack_data[ tos ].type = ct_none;
p->stack_data[ tos ].ident = NULL;
p->stack_top = tos - 1;
KE_DUMP( 1000, dump_cons_stack( gtid, p ) );
}
enum cons_type
__kmp_pop_workshare( int gtid, enum cons_type ct, ident_t const * ident )
{
int tos;
struct cons_header *p = __kmp_threads[ gtid ]->th.th_cons;
tos = p->stack_top;
KE_TRACE( 10, ("__kmp_pop_workshare (%d %d)\n", gtid, __kmp_get_gtid() ) );
if ( tos == 0 || p->w_top == 0 ) {
__kmp_error_construct( kmp_i18n_msg_CnsDetectedEnd, ct, ident );
}
if ( tos != p->w_top ||
( p->stack_data[ tos ].type != ct &&
/* below are two exceptions to the rule that construct types must match */
! ( p->stack_data[ tos ].type == ct_pdo_ordered && ct == ct_pdo ) &&
! ( p->stack_data[ tos ].type == ct_task_ordered && ct == ct_task )
)
) {
__kmp_check_null_func();
__kmp_error_construct2(
kmp_i18n_msg_CnsExpectedEnd,
ct, ident,
& p->stack_data[ tos ]
);
}
KE_TRACE( 100, ( POP_MSG( p ) ) );
p->w_top = p->stack_data[ tos ].prev;
p->stack_data[ tos ].type = ct_none;
p->stack_data[ tos ].ident = NULL;
p->stack_top = tos - 1;
KE_DUMP( 1000, dump_cons_stack( gtid, p ) );
return p->stack_data[ p->w_top ].type;
}
void
__kmp_pop_sync( int gtid, enum cons_type ct, ident_t const * ident )
{
int tos;
struct cons_header *p = __kmp_threads[ gtid ]->th.th_cons;
tos = p->stack_top;
KE_TRACE( 10, ("__kmp_pop_sync (%d %d)\n", gtid, __kmp_get_gtid() ) );
if ( tos == 0 || p->s_top == 0 ) {
__kmp_error_construct( kmp_i18n_msg_CnsDetectedEnd, ct, ident );
};
if ( tos != p->s_top || p->stack_data[ tos ].type != ct ) {
__kmp_check_null_func();
__kmp_error_construct2(
kmp_i18n_msg_CnsExpectedEnd,
ct, ident,
& p->stack_data[ tos ]
);
};
if ( gtid < 0 ) {
__kmp_check_null_func();
};
KE_TRACE( 100, ( POP_MSG( p ) ) );
p->s_top = p->stack_data[ tos ].prev;
p->stack_data[ tos ].type = ct_none;
p->stack_data[ tos ].ident = NULL;
p->stack_top = tos - 1;
KE_DUMP( 1000, dump_cons_stack( gtid, p ) );
}
/* ------------------------------------------------------------------------ */
void
__kmp_check_barrier( int gtid, enum cons_type ct, ident_t const * ident )
{
struct cons_header *p = __kmp_threads[ gtid ]->th.th_cons;
KE_TRACE( 10, ("__kmp_check_barrier (loc: %p, gtid: %d %d)\n", ident, gtid, __kmp_get_gtid() ) );
if ( ident != 0 ) {
__kmp_check_null_func();
}
if ( p->w_top > p->p_top ) {
/* we are already in a WORKSHARING construct for this PARALLEL region */
__kmp_error_construct2(
kmp_i18n_msg_CnsInvalidNesting,
ct, ident,
& p->stack_data[ p->w_top ]
);
}
if (p->s_top > p->p_top) {
/* we are already in a SYNC construct for this PARALLEL region */
__kmp_error_construct2(
kmp_i18n_msg_CnsInvalidNesting,
ct, ident,
& p->stack_data[ p->s_top ]
);
}
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
+462
View File
@@ -0,0 +1,462 @@
/*
* kmp_error.cpp -- KPTS functions for error checking at runtime
*/
//===----------------------------------------------------------------------===//
//
// 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_error.h"
#include "kmp_i18n.h"
#include "kmp_str.h"
/* ------------------------------------------------------------------------ */
#define MIN_STACK 100
static char const *cons_text_c[] = {
"(none)", "\"parallel\"", "work-sharing", /* this is not called "for"
because of lowering of
"sections" pragmas */
"\"ordered\" work-sharing", /* this is not called "for ordered" because of
lowering of "sections" pragmas */
"\"sections\"",
"work-sharing", /* this is not called "single" because of lowering of
"sections" pragmas */
"\"taskq\"", "\"taskq\"", "\"taskq ordered\"", "\"critical\"",
"\"ordered\"", /* in PARALLEL */
"\"ordered\"", /* in PDO */
"\"ordered\"", /* in TASKQ */
"\"master\"", "\"reduce\"", "\"barrier\""};
#define get_src(ident) ((ident) == NULL ? NULL : (ident)->psource)
#define PUSH_MSG(ct, ident) \
"\tpushing on stack: %s (%s)\n", cons_text_c[(ct)], get_src((ident))
#define POP_MSG(p) \
"\tpopping off stack: %s (%s)\n", cons_text_c[(p)->stack_data[tos].type], \
get_src((p)->stack_data[tos].ident)
static int const cons_text_c_num = sizeof(cons_text_c) / sizeof(char const *);
/* --------------- START OF STATIC LOCAL ROUTINES ------------------------- */
static void __kmp_check_null_func(void) { /* nothing to do */
}
static void __kmp_expand_cons_stack(int gtid, struct cons_header *p) {
int i;
struct cons_data *d;
/* TODO for monitor perhaps? */
if (gtid < 0)
__kmp_check_null_func();
KE_TRACE(10, ("expand cons_stack (%d %d)\n", gtid, __kmp_get_gtid()));
d = p->stack_data;
p->stack_size = (p->stack_size * 2) + 100;
/* TODO free the old data */
p->stack_data = (struct cons_data *)__kmp_allocate(sizeof(struct cons_data) *
(p->stack_size + 1));
for (i = p->stack_top; i >= 0; --i)
p->stack_data[i] = d[i];
/* NOTE: we do not free the old stack_data */
}
// NOTE: Function returns allocated memory, caller must free it!
static char *__kmp_pragma(int ct, ident_t const *ident) {
char const *cons = NULL; // Construct name.
char *file = NULL; // File name.
char *func = NULL; // Function (routine) name.
char *line = NULL; // Line number.
kmp_str_buf_t buffer;
kmp_msg_t prgm;
__kmp_str_buf_init(&buffer);
if (0 < ct && ct < cons_text_c_num) {
cons = cons_text_c[ct];
} else {
KMP_DEBUG_ASSERT(0);
}
if (ident != NULL && ident->psource != NULL) {
char *tail = NULL;
__kmp_str_buf_print(&buffer, "%s",
ident->psource); // Copy source to buffer.
// Split string in buffer to file, func, and line.
tail = buffer.str;
__kmp_str_split(tail, ';', NULL, &tail);
__kmp_str_split(tail, ';', &file, &tail);
__kmp_str_split(tail, ';', &func, &tail);
__kmp_str_split(tail, ';', &line, &tail);
}
prgm = __kmp_msg_format(kmp_i18n_fmt_Pragma, cons, file, func, line);
__kmp_str_buf_free(&buffer);
return prgm.str;
} // __kmp_pragma
/* ----------------- END OF STATIC LOCAL ROUTINES ------------------------- */
void __kmp_error_construct(kmp_i18n_id_t id, // Message identifier.
enum cons_type ct, // Construct type.
ident_t const *ident // Construct ident.
) {
char *construct = __kmp_pragma(ct, ident);
__kmp_fatal(__kmp_msg_format(id, construct), __kmp_msg_null);
KMP_INTERNAL_FREE(construct);
}
void __kmp_error_construct2(kmp_i18n_id_t id, // Message identifier.
enum cons_type ct, // First construct type.
ident_t const *ident, // First construct ident.
struct cons_data const *cons // Second construct.
) {
char *construct1 = __kmp_pragma(ct, ident);
char *construct2 = __kmp_pragma(cons->type, cons->ident);
__kmp_fatal(__kmp_msg_format(id, construct1, construct2), __kmp_msg_null);
KMP_INTERNAL_FREE(construct1);
KMP_INTERNAL_FREE(construct2);
}
struct cons_header *__kmp_allocate_cons_stack(int gtid) {
struct cons_header *p;
/* TODO for monitor perhaps? */
if (gtid < 0) {
__kmp_check_null_func();
}
KE_TRACE(10, ("allocate cons_stack (%d)\n", gtid));
p = (struct cons_header *)__kmp_allocate(sizeof(struct cons_header));
p->p_top = p->w_top = p->s_top = 0;
p->stack_data = (struct cons_data *)__kmp_allocate(sizeof(struct cons_data) *
(MIN_STACK + 1));
p->stack_size = MIN_STACK;
p->stack_top = 0;
p->stack_data[0].type = ct_none;
p->stack_data[0].prev = 0;
p->stack_data[0].ident = NULL;
return p;
}
void __kmp_free_cons_stack(void *ptr) {
struct cons_header *p = (struct cons_header *)ptr;
if (p != NULL) {
if (p->stack_data != NULL) {
__kmp_free(p->stack_data);
p->stack_data = NULL;
}
__kmp_free(p);
}
}
#if KMP_DEBUG
static void dump_cons_stack(int gtid, struct cons_header *p) {
int i;
int tos = p->stack_top;
kmp_str_buf_t buffer;
__kmp_str_buf_init(&buffer);
__kmp_str_buf_print(
&buffer,
"+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-\n");
__kmp_str_buf_print(&buffer,
"Begin construct stack with %d items for thread %d\n",
tos, gtid);
__kmp_str_buf_print(&buffer, " stack_top=%d { P=%d, W=%d, S=%d }\n", tos,
p->p_top, p->w_top, p->s_top);
for (i = tos; i > 0; i--) {
struct cons_data *c = &(p->stack_data[i]);
__kmp_str_buf_print(
&buffer, " stack_data[%2d] = { %s (%s) %d %p }\n", i,
cons_text_c[c->type], get_src(c->ident), c->prev, c->name);
}
__kmp_str_buf_print(&buffer, "End construct stack for thread %d\n", gtid);
__kmp_str_buf_print(
&buffer,
"+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-\n");
__kmp_debug_printf("%s", buffer.str);
__kmp_str_buf_free(&buffer);
}
#endif
void __kmp_push_parallel(int gtid, ident_t const *ident) {
int tos;
struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
KMP_DEBUG_ASSERT(__kmp_threads[gtid]->th.th_cons);
KE_TRACE(10, ("__kmp_push_parallel (%d %d)\n", gtid, __kmp_get_gtid()));
KE_TRACE(100, (PUSH_MSG(ct_parallel, ident)));
if (p->stack_top >= p->stack_size) {
__kmp_expand_cons_stack(gtid, p);
}
tos = ++p->stack_top;
p->stack_data[tos].type = ct_parallel;
p->stack_data[tos].prev = p->p_top;
p->stack_data[tos].ident = ident;
p->stack_data[tos].name = NULL;
p->p_top = tos;
KE_DUMP(1000, dump_cons_stack(gtid, p));
}
void __kmp_check_workshare(int gtid, enum cons_type ct, ident_t const *ident) {
struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
KMP_DEBUG_ASSERT(__kmp_threads[gtid]->th.th_cons);
KE_TRACE(10, ("__kmp_check_workshare (%d %d)\n", gtid, __kmp_get_gtid()));
if (p->stack_top >= p->stack_size) {
__kmp_expand_cons_stack(gtid, p);
}
if (p->w_top > p->p_top &&
!(IS_CONS_TYPE_TASKQ(p->stack_data[p->w_top].type) &&
IS_CONS_TYPE_TASKQ(ct))) {
// We are already in a WORKSHARE construct for this PARALLEL region.
__kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
&p->stack_data[p->w_top]);
}
if (p->s_top > p->p_top) {
// We are already in a SYNC construct for this PARALLEL region.
__kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
&p->stack_data[p->s_top]);
}
}
void __kmp_push_workshare(int gtid, enum cons_type ct, ident_t const *ident) {
int tos;
struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
KE_TRACE(10, ("__kmp_push_workshare (%d %d)\n", gtid, __kmp_get_gtid()));
__kmp_check_workshare(gtid, ct, ident);
KE_TRACE(100, (PUSH_MSG(ct, ident)));
tos = ++p->stack_top;
p->stack_data[tos].type = ct;
p->stack_data[tos].prev = p->w_top;
p->stack_data[tos].ident = ident;
p->stack_data[tos].name = NULL;
p->w_top = tos;
KE_DUMP(1000, dump_cons_stack(gtid, p));
}
void
#if KMP_USE_DYNAMIC_LOCK
__kmp_check_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck, kmp_uint32 seq )
#else
__kmp_check_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck )
#endif
{
struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
KE_TRACE(10, ("__kmp_check_sync (gtid=%d)\n", __kmp_get_gtid()));
if (p->stack_top >= p->stack_size)
__kmp_expand_cons_stack(gtid, p);
if (ct == ct_ordered_in_parallel || ct == ct_ordered_in_pdo ||
ct == ct_ordered_in_taskq) {
if (p->w_top <= p->p_top) {
/* we are not in a worksharing construct */
#ifdef BUILD_PARALLEL_ORDERED
/* do not report error messages for PARALLEL ORDERED */
KMP_ASSERT(ct == ct_ordered_in_parallel);
#else
__kmp_error_construct(kmp_i18n_msg_CnsBoundToWorksharing, ct, ident);
#endif /* BUILD_PARALLEL_ORDERED */
} else {
/* inside a WORKSHARING construct for this PARALLEL region */
if (!IS_CONS_TYPE_ORDERED(p->stack_data[p->w_top].type)) {
if (p->stack_data[p->w_top].type == ct_taskq) {
__kmp_error_construct2(kmp_i18n_msg_CnsNotInTaskConstruct, ct, ident,
&p->stack_data[p->w_top]);
} else {
__kmp_error_construct2(kmp_i18n_msg_CnsNoOrderedClause, ct, ident,
&p->stack_data[p->w_top]);
}
}
}
if (p->s_top > p->p_top && p->s_top > p->w_top) {
/* inside a sync construct which is inside a worksharing construct */
int index = p->s_top;
enum cons_type stack_type;
stack_type = p->stack_data[index].type;
if (stack_type == ct_critical ||
((stack_type == ct_ordered_in_parallel ||
stack_type == ct_ordered_in_pdo ||
stack_type ==
ct_ordered_in_taskq) && /* C doesn't allow named ordered;
ordered in ordered gets error */
p->stack_data[index].ident != NULL &&
(p->stack_data[index].ident->flags & KMP_IDENT_KMPC))) {
/* we are in ORDERED which is inside an ORDERED or CRITICAL construct */
__kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
&p->stack_data[index]);
}
}
} else if (ct == ct_critical) {
#if KMP_USE_DYNAMIC_LOCK
if (lck != NULL &&
__kmp_get_user_lock_owner(lck, seq) ==
gtid) { /* this thread already has lock for this critical section */
#else
if (lck != NULL &&
__kmp_get_user_lock_owner(lck) ==
gtid) { /* this thread already has lock for this critical section */
#endif
int index = p->s_top;
struct cons_data cons = {NULL, ct_critical, 0, NULL};
/* walk up construct stack and try to find critical with matching name */
while (index != 0 && p->stack_data[index].name != lck) {
index = p->stack_data[index].prev;
}
if (index != 0) {
/* found match on the stack (may not always because of interleaved
* critical for Fortran) */
cons = p->stack_data[index];
}
/* we are in CRITICAL which is inside a CRITICAL construct of same name */
__kmp_error_construct2(kmp_i18n_msg_CnsNestingSameName, ct, ident, &cons);
}
} else if (ct == ct_master || ct == ct_reduce) {
if (p->w_top > p->p_top) {
/* inside a WORKSHARING construct for this PARALLEL region */
__kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
&p->stack_data[p->w_top]);
}
if (ct == ct_reduce && p->s_top > p->p_top) {
/* inside a another SYNC construct for this PARALLEL region */
__kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
&p->stack_data[p->s_top]);
}
}
}
void
#if KMP_USE_DYNAMIC_LOCK
__kmp_push_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck, kmp_uint32 seq )
#else
__kmp_push_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck )
#endif
{
int tos;
struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
KMP_ASSERT(gtid == __kmp_get_gtid());
KE_TRACE(10, ("__kmp_push_sync (gtid=%d)\n", gtid));
#if KMP_USE_DYNAMIC_LOCK
__kmp_check_sync(gtid, ct, ident, lck, seq);
#else
__kmp_check_sync(gtid, ct, ident, lck);
#endif
KE_TRACE(100, (PUSH_MSG(ct, ident)));
tos = ++p->stack_top;
p->stack_data[tos].type = ct;
p->stack_data[tos].prev = p->s_top;
p->stack_data[tos].ident = ident;
p->stack_data[tos].name = lck;
p->s_top = tos;
KE_DUMP(1000, dump_cons_stack(gtid, p));
}
/* ------------------------------------------------------------------------ */
void __kmp_pop_parallel(int gtid, ident_t const *ident) {
int tos;
struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
tos = p->stack_top;
KE_TRACE(10, ("__kmp_pop_parallel (%d %d)\n", gtid, __kmp_get_gtid()));
if (tos == 0 || p->p_top == 0) {
__kmp_error_construct(kmp_i18n_msg_CnsDetectedEnd, ct_parallel, ident);
}
if (tos != p->p_top || p->stack_data[tos].type != ct_parallel) {
__kmp_error_construct2(kmp_i18n_msg_CnsExpectedEnd, ct_parallel, ident,
&p->stack_data[tos]);
}
KE_TRACE(100, (POP_MSG(p)));
p->p_top = p->stack_data[tos].prev;
p->stack_data[tos].type = ct_none;
p->stack_data[tos].ident = NULL;
p->stack_top = tos - 1;
KE_DUMP(1000, dump_cons_stack(gtid, p));
}
enum cons_type __kmp_pop_workshare(int gtid, enum cons_type ct,
ident_t const *ident) {
int tos;
struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
tos = p->stack_top;
KE_TRACE(10, ("__kmp_pop_workshare (%d %d)\n", gtid, __kmp_get_gtid()));
if (tos == 0 || p->w_top == 0) {
__kmp_error_construct(kmp_i18n_msg_CnsDetectedEnd, ct, ident);
}
if (tos != p->w_top ||
(p->stack_data[tos].type != ct &&
// below are two exceptions to the rule that construct types must match
!(p->stack_data[tos].type == ct_pdo_ordered && ct == ct_pdo) &&
!(p->stack_data[tos].type == ct_task_ordered && ct == ct_task))) {
__kmp_check_null_func();
__kmp_error_construct2(kmp_i18n_msg_CnsExpectedEnd, ct, ident,
&p->stack_data[tos]);
}
KE_TRACE(100, (POP_MSG(p)));
p->w_top = p->stack_data[tos].prev;
p->stack_data[tos].type = ct_none;
p->stack_data[tos].ident = NULL;
p->stack_top = tos - 1;
KE_DUMP(1000, dump_cons_stack(gtid, p));
return p->stack_data[p->w_top].type;
}
void __kmp_pop_sync(int gtid, enum cons_type ct, ident_t const *ident) {
int tos;
struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
tos = p->stack_top;
KE_TRACE(10, ("__kmp_pop_sync (%d %d)\n", gtid, __kmp_get_gtid()));
if (tos == 0 || p->s_top == 0) {
__kmp_error_construct(kmp_i18n_msg_CnsDetectedEnd, ct, ident);
}
if (tos != p->s_top || p->stack_data[tos].type != ct) {
__kmp_check_null_func();
__kmp_error_construct2(kmp_i18n_msg_CnsExpectedEnd, ct, ident,
&p->stack_data[tos]);
}
if (gtid < 0) {
__kmp_check_null_func();
}
KE_TRACE(100, (POP_MSG(p)));
p->s_top = p->stack_data[tos].prev;
p->stack_data[tos].type = ct_none;
p->stack_data[tos].ident = NULL;
p->stack_top = tos - 1;
KE_DUMP(1000, dump_cons_stack(gtid, p));
}
/* ------------------------------------------------------------------------ */
void __kmp_check_barrier(int gtid, enum cons_type ct, ident_t const *ident) {
struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
KE_TRACE(10, ("__kmp_check_barrier (loc: %p, gtid: %d %d)\n", ident, gtid,
__kmp_get_gtid()));
if (ident != 0) {
__kmp_check_null_func();
}
if (p->w_top > p->p_top) {
/* we are already in a WORKSHARING construct for this PARALLEL region */
__kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
&p->stack_data[p->w_top]);
}
if (p->s_top > p->p_top) {
/* we are already in a SYNC construct for this PARALLEL region */
__kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
&p->stack_data[p->s_top]);
}
}
+24 -20
View File
@@ -2,7 +2,6 @@
* kmp_error.h -- PTS functions for error checking at runtime.
*/
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
@@ -12,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
#ifndef KMP_ERROR_H
#define KMP_ERROR_H
@@ -20,38 +18,44 @@
/* ------------------------------------------------------------------------ */
#ifdef __cplusplus
extern "C" {
extern "C" {
#endif
void __kmp_error_construct( kmp_i18n_id_t id, enum cons_type ct, ident_t const * ident );
void __kmp_error_construct2( kmp_i18n_id_t id, enum cons_type ct, ident_t const * ident, struct cons_data const * cons );
void __kmp_error_construct(kmp_i18n_id_t id, enum cons_type ct,
ident_t const *ident);
void __kmp_error_construct2(kmp_i18n_id_t id, enum cons_type ct,
ident_t const *ident, struct cons_data const *cons);
struct cons_header * __kmp_allocate_cons_stack( int gtid );
void __kmp_free_cons_stack( void * ptr );
struct cons_header *__kmp_allocate_cons_stack(int gtid);
void __kmp_free_cons_stack(void *ptr);
void __kmp_push_parallel( int gtid, ident_t const * ident );
void __kmp_push_workshare( int gtid, enum cons_type ct, ident_t const * ident );
void __kmp_push_parallel(int gtid, ident_t const *ident);
void __kmp_push_workshare(int gtid, enum cons_type ct, ident_t const *ident);
#if KMP_USE_DYNAMIC_LOCK
void __kmp_push_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p name, kmp_uint32 );
void __kmp_push_sync(int gtid, enum cons_type ct, ident_t const *ident,
kmp_user_lock_p name, kmp_uint32);
#else
void __kmp_push_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p name );
void __kmp_push_sync(int gtid, enum cons_type ct, ident_t const *ident,
kmp_user_lock_p name);
#endif
void __kmp_check_workshare( int gtid, enum cons_type ct, ident_t const * ident );
void __kmp_check_workshare(int gtid, enum cons_type ct, ident_t const *ident);
#if KMP_USE_DYNAMIC_LOCK
void __kmp_check_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p name, kmp_uint32 );
void __kmp_check_sync(int gtid, enum cons_type ct, ident_t const *ident,
kmp_user_lock_p name, kmp_uint32);
#else
void __kmp_check_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p name );
void __kmp_check_sync(int gtid, enum cons_type ct, ident_t const *ident,
kmp_user_lock_p name);
#endif
void __kmp_pop_parallel( int gtid, ident_t const * ident );
enum cons_type __kmp_pop_workshare( int gtid, enum cons_type ct, ident_t const * ident );
void __kmp_pop_sync( int gtid, enum cons_type ct, ident_t const * ident );
void __kmp_check_barrier( int gtid, enum cons_type ct, ident_t const * ident );
void __kmp_pop_parallel(int gtid, ident_t const *ident);
enum cons_type __kmp_pop_workshare(int gtid, enum cons_type ct,
ident_t const *ident);
void __kmp_pop_sync(int gtid, enum cons_type ct, ident_t const *ident);
void __kmp_check_barrier(int gtid, enum cons_type ct, ident_t const *ident);
#ifdef __cplusplus
} // extern "C"
} // extern "C"
#endif
#endif // KMP_ERROR_H
@@ -1,8 +1,7 @@
/*
* kmp_ftn_cdecl.c -- Fortran __cdecl linkage support for OpenMP.
* kmp_ftn_cdecl.cpp -- Fortran __cdecl linkage support for OpenMP.
*/
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
@@ -12,24 +11,25 @@
//
//===----------------------------------------------------------------------===//
#include "kmp.h"
#include "kmp_affinity.h"
#if KMP_OS_WINDOWS
# if defined KMP_WIN_CDECL || !defined KMP_DYNAMIC_LIB
# define KMP_FTN_ENTRIES KMP_FTN_UPPER
# endif
#if defined KMP_WIN_CDECL || !defined KMP_DYNAMIC_LIB
#define KMP_FTN_ENTRIES KMP_FTN_UPPER
#endif
#elif KMP_OS_UNIX
# define KMP_FTN_ENTRIES KMP_FTN_PLAIN
#define KMP_FTN_ENTRIES KMP_FTN_PLAIN
#endif
// Note: This string is not printed when KMP_VERSION=1.
char const __kmp_version_ftncdecl[] = KMP_VERSION_PREFIX "Fortran __cdecl OMP support: "
char const __kmp_version_ftncdecl[] =
KMP_VERSION_PREFIX "Fortran __cdecl OMP support: "
#ifdef KMP_FTN_ENTRIES
"yes";
# define FTN_STDCALL /* no stdcall */
# include "kmp_ftn_os.h"
# include "kmp_ftn_entry.h"
"yes";
#define FTN_STDCALL /* no stdcall */
#include "kmp_ftn_os.h"
#include "kmp_ftn_entry.h"
#else
"no";
"no";
#endif /* KMP_FTN_ENTRIES */

Some files were not shown because too many files have changed in this diff Show More