Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e62ab1ab82 | ||
|
|
57d5483742 | ||
|
|
fc80b280f9 |
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"repository.callsign" : "OMP",
|
||||
"conduit_uri" : "https://reviews.llvm.org/"
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
#==============================================================================#
|
||||
# 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
|
||||
+1
-77
@@ -1,81 +1,5 @@
|
||||
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
|
||||
|
||||
# Add cmake directory to search for custom cmake functions.
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
|
||||
set(OPENMP_LLVM_TOOLS_DIR "" CACHE PATH "Path to LLVM tools for testing")
|
||||
|
||||
# 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()
|
||||
|
||||
+4
-8
@@ -8,18 +8,10 @@ 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
|
||||
|
||||
@@ -59,3 +51,7 @@ 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
@@ -1,307 +0,0 @@
|
||||
========================================
|
||||
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.
|
||||
@@ -1,39 +0,0 @@
|
||||
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)
|
||||
@@ -1,16 +0,0 @@
|
||||
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)
|
||||
@@ -1,178 +0,0 @@
|
||||
# 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()
|
||||
@@ -1,6 +0,0 @@
|
||||
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)
|
||||
@@ -1,72 +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.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
#
|
||||
# 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)
|
||||
@@ -1,73 +0,0 @@
|
||||
|
||||
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.
|
||||
@@ -1,124 +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.
|
||||
#//
|
||||
#//===----------------------------------------------------------------------===//
|
||||
#
|
||||
|
||||
# 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)
|
||||
@@ -1,28 +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.
|
||||
#//
|
||||
#//===----------------------------------------------------------------------===//
|
||||
#
|
||||
|
||||
# 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()
|
||||
@@ -1,237 +0,0 @@
|
||||
//===-------- 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_
|
||||
@@ -1,92 +0,0 @@
|
||||
//===-- 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_
|
||||
@@ -1,72 +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.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
#
|
||||
# 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)
|
||||
|
||||
@@ -1,18 +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.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
#
|
||||
# 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()
|
||||
@@ -1,73 +0,0 @@
|
||||
//===-- 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;
|
||||
}
|
||||
@@ -1,50 +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.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
#
|
||||
# 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)
|
||||
@@ -1,711 +0,0 @@
|
||||
//===----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
|
||||
@@ -1,15 +0,0 @@
|
||||
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:
|
||||
*;
|
||||
};
|
||||
@@ -1,339 +0,0 @@
|
||||
//===-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
|
||||
@@ -1,18 +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.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
#
|
||||
# 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()
|
||||
@@ -1,18 +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.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
#
|
||||
# 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()
|
||||
@@ -1,18 +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.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
#
|
||||
# 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()
|
||||
@@ -1,31 +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.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
#
|
||||
# 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})
|
||||
@@ -1,283 +0,0 @@
|
||||
//===----------- 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;
|
||||
}
|
||||
@@ -1,365 +0,0 @@
|
||||
//===--------- 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;
|
||||
}
|
||||
@@ -1,167 +0,0 @@
|
||||
//===----------- 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
|
||||
@@ -1,28 +0,0 @@
|
||||
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:
|
||||
*;
|
||||
};
|
||||
|
||||
@@ -1,502 +0,0 @@
|
||||
//===-------- 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;
|
||||
}
|
||||
@@ -1,648 +0,0 @@
|
||||
//===------ 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;
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
//===---------- 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
|
||||
@@ -1,368 +0,0 @@
|
||||
//===----------- 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");
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
//===------------ 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
|
||||
@@ -1,28 +0,0 @@
|
||||
# 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
@@ -1,20 +0,0 @@
|
||||
// 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
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
# -*- 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))
|
||||
@@ -1,18 +0,0 @@
|
||||
@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")
|
||||
@@ -1,23 +0,0 @@
|
||||
// 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;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
// 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;
|
||||
}
|
||||
@@ -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 = NO
|
||||
HTML_TIMESTAMP = YES
|
||||
|
||||
# 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
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
BasedOnStyle: LLVM
|
||||
AlignTrailingComments: false
|
||||
SortIncludes: false
|
||||
...
|
||||
@@ -0,0 +1,229 @@
|
||||
#
|
||||
#//===----------------------------------------------------------------------===//
|
||||
#//
|
||||
#// 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.
|
||||
+45
-41
@@ -9,13 +9,21 @@
|
||||
#//===----------------------------------------------------------------------===//
|
||||
#
|
||||
|
||||
if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
message(FATAL_ERROR "Direct configuration not supported, please use parent directory!")
|
||||
endif()
|
||||
# CMAKE libomp
|
||||
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
|
||||
|
||||
# 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(OPENMP_STANDALONE_BUILD OR
|
||||
"${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)
|
||||
@@ -27,14 +35,23 @@ include(LibompHandleFlags)
|
||||
include(LibompDefinitions)
|
||||
|
||||
# Determine the target architecture
|
||||
if(${OPENMP_STANDALONE_BUILD})
|
||||
if(${LIBOMP_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/mips/mips64).")
|
||||
# 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")
|
||||
# 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)
|
||||
@@ -63,20 +80,24 @@ 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 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 50 CACHE STRING
|
||||
"The OpenMP version (50/45/40/30)")
|
||||
libomp_check_variable(LIBOMP_OMP_VERSION 50 45 40 30)
|
||||
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 the OpenMP Year and Month assiociated with version
|
||||
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)
|
||||
if(${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)
|
||||
@@ -260,13 +281,12 @@ set(LIBOMP_USE_DEBUGGER FALSE CACHE BOOL
|
||||
set(LIBOMP_USE_STDCPPLIB FALSE CACHE BOOL
|
||||
"Should we link to C++ library?")
|
||||
|
||||
# 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.
|
||||
# TSX (x86) based locks have __asm code which can be troublesome for some compilers.
|
||||
# TODO: Make this a real feature check
|
||||
set(LIBOMP_USE_ADAPTIVE_LOCKS "${LIBOMP_HAVE_ADAPTIVE_LOCKS}" CACHE BOOL
|
||||
"Should Intel(R) TSX lock be compiled (adaptive lock in kmp_lock.cpp). These are x86 specific.")
|
||||
"Should TSX-based 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 (Intel(R) TSX) functionality is only supported on x86 Architecture")
|
||||
libomp_error_say("Adaptive locks (TSX) functionality requested but not available")
|
||||
endif()
|
||||
|
||||
# - stats-gathering enables OpenMP stats where things like the number of
|
||||
@@ -289,34 +309,17 @@ if(WIN32 AND NOT LIBOMP_ENABLE_SHARED)
|
||||
libomp_error_say("Static libraries requested but not available on Windows")
|
||||
endif()
|
||||
|
||||
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?")
|
||||
|
||||
# OMPT-support
|
||||
set(LIBOMP_OMPT_DEBUG FALSE CACHE BOOL
|
||||
"Trace OMPT initialization?")
|
||||
set(LIBOMP_OMPT_OPTIONAL TRUE CACHE BOOL
|
||||
"OMPT-optional?")
|
||||
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?")
|
||||
if(LIBOMP_OMPT_SUPPORT AND (NOT LIBOMP_HAVE_OMPT_SUPPORT))
|
||||
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}")
|
||||
libomp_error_say("OpenMP Tools Interface requested but not available")
|
||||
endif()
|
||||
|
||||
# TSAN-support
|
||||
@@ -358,7 +361,7 @@ set(LIBOMP_INSTALL_ALIASES TRUE CACHE BOOL
|
||||
"Install libgomp and libiomp5 library aliases for backwards compatibility")
|
||||
|
||||
# Print configuration after all variables are set.
|
||||
if(${OPENMP_STANDALONE_BUILD})
|
||||
if(${LIBOMP_STANDALONE_BUILD})
|
||||
libomp_say("Operating System -- ${CMAKE_SYSTEM_NAME}")
|
||||
libomp_say("Target Architecture -- ${LIBOMP_ARCH}")
|
||||
if(${MIC})
|
||||
@@ -381,7 +384,8 @@ if(${OPENMP_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-optional -- ${LIBOMP_OMPT_OPTIONAL}")
|
||||
libomp_say("Use OMPT-blame -- ${LIBOMP_OMPT_BLAME}")
|
||||
libomp_say("Use OMPT-trace -- ${LIBOMP_OMPT_TRACE}")
|
||||
endif()
|
||||
libomp_say("Use Adaptive locks -- ${LIBOMP_USE_ADAPTIVE_LOCKS}")
|
||||
libomp_say("Use quad precision -- ${LIBOMP_USE_QUAD_PRECISION}")
|
||||
|
||||
+1
-1
@@ -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 README.rst in the parent directory.
|
||||
For details about building, please look at Build_With_CMake.txt
|
||||
|
||||
Architectures Supported
|
||||
=======================
|
||||
|
||||
@@ -27,7 +27,8 @@ endif()
|
||||
libomp_append(libomp_suffix .s1 LIBOMP_STATS)
|
||||
libomp_append(libomp_suffix .ompt LIBOMP_OMPT_SUPPORT)
|
||||
if(${LIBOMP_OMPT_SUPPORT})
|
||||
libomp_append(libomp_suffix .optional LIBOMP_OMPT_OPTIONAL)
|
||||
libomp_append(libomp_suffix .no-ompt-blame IF_FALSE LIBOMP_OMPT_BLAME)
|
||||
libomp_append(libomp_suffix .no-ompt-trace IF_FALSE LIBOMP_OMPT_TRACE)
|
||||
endif()
|
||||
string(REPLACE ";" "" libomp_suffix "${libomp_suffix}")
|
||||
|
||||
|
||||
@@ -26,8 +26,12 @@ 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)
|
||||
libomp_append(flags_local -fno-rtti LIBOMP_HAVE_FNO_RTTI_FLAG)
|
||||
if(${LIBOMP_ENABLE_WERROR})
|
||||
libomp_append(flags_local -Werror LIBOMP_HAVE_WERROR_FLAG)
|
||||
endif()
|
||||
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)
|
||||
@@ -188,9 +192,6 @@ 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()
|
||||
|
||||
@@ -47,9 +47,11 @@ 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)
|
||||
@@ -221,7 +223,7 @@ endif()
|
||||
|
||||
# Check if OMPT support is available
|
||||
# Currently, __builtin_frame_address() is required for OMPT
|
||||
# Weak attribute is required for Unices (except Darwin), LIBPSAPI is used for Windows
|
||||
# Weak attribute is required for Unices, 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)
|
||||
@@ -236,15 +238,7 @@ endif()
|
||||
if(NOT LIBOMP_HAVE___BUILTIN_FRAME_ADDRESS)
|
||||
set(LIBOMP_HAVE_OMPT_SUPPORT FALSE)
|
||||
else()
|
||||
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)))
|
||||
if(LIBOMP_HAVE_WEAK_ATTRIBUTE OR LIBOMP_HAVE_PSAPI)
|
||||
set(LIBOMP_HAVE_OMPT_SUPPORT TRUE)
|
||||
else()
|
||||
set(LIBOMP_HAVE_OMPT_SUPPORT FALSE)
|
||||
|
||||
@@ -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 = NO
|
||||
HTML_TIMESTAMP = YES
|
||||
|
||||
# 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
|
||||
|
||||
@@ -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,322 +11,323 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
/*! @mainpage LLVM OpenMP* Runtime Library Interface
|
||||
@section sec_intro Introduction
|
||||
|
||||
This document describes the interface provided by the
|
||||
LLVM 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® 64, and
|
||||
Intel® 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® 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® Many Integrated Core Architecture not supported.<br>
|
||||
(5) On Intel® 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 OpenMP* Runtime Library Interface
|
||||
@section sec_intro Introduction
|
||||
|
||||
This document describes the interface provided by the
|
||||
LLVM 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® 64, and
|
||||
Intel® 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® 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® Many Integrated Core Architecture not supported.<br>
|
||||
(5) On Intel® 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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ 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
|
||||
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)
|
||||
@@ -282,26 +282,26 @@ 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(${OPENMP_STANDALONE_BUILD})
|
||||
if(${LIBOMP_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${OPENMP_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}/include)
|
||||
set(LIBOMP_HEADERS_INSTALL_PATH lib${LIBOMP_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}/include)
|
||||
endif()
|
||||
if(WIN32)
|
||||
install(TARGETS omp RUNTIME DESTINATION bin)
|
||||
install(TARGETS ompimp ARCHIVE DESTINATION lib${OPENMP_LIBDIR_SUFFIX})
|
||||
install(TARGETS ompimp ARCHIVE DESTINATION lib${LIBOMP_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${OPENMP_LIBDIR_SUFFIX})")
|
||||
\"${alias}${LIBOMP_LIBRARY_SUFFIX}\" WORKING_DIRECTORY \${CMAKE_INSTALL_PREFIX}/lib${LIBOMP_LIBDIR_SUFFIX})")
|
||||
endforeach()
|
||||
else()
|
||||
|
||||
install(TARGETS omp ${LIBOMP_INSTALL_KIND} DESTINATION lib${OPENMP_LIBDIR_SUFFIX})
|
||||
install(TARGETS omp ${LIBOMP_INSTALL_KIND} DESTINATION lib${LIBOMP_LIBDIR_SUFFIX})
|
||||
|
||||
if(${LIBOMP_INSTALL_ALIASES})
|
||||
# Create aliases (symlinks) of the library for backwards compatibility
|
||||
@@ -309,7 +309,7 @@ else()
|
||||
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})")
|
||||
\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/lib${LIBOMP_LIBDIR_SUFFIX})")
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
+1
-14
@@ -351,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
|
||||
@@ -397,15 +397,6 @@ 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_'.
|
||||
@@ -1117,19 +1108,15 @@ kmp_set_disp_num_buffers 890
|
||||
|
||||
%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
|
||||
|
||||
@@ -25,11 +25,21 @@ VERSION {
|
||||
#
|
||||
# OMPT API
|
||||
#
|
||||
ompt_start_tool; # OMPT start interface
|
||||
ompt_tool; # OMPT initialization interface
|
||||
ompt_control; # OMPT control interface
|
||||
|
||||
# icc drops weak attribute at linking step without the following line:
|
||||
Annotate*; # TSAN annotation
|
||||
|
||||
#
|
||||
# OMPT state placeholders
|
||||
#
|
||||
ompt_idle;
|
||||
ompt_overhead;
|
||||
ompt_barrier_wait;
|
||||
ompt_task_wait;
|
||||
ompt_mutex_wait;
|
||||
|
||||
ompc_*; # omp.h renames some standard functions to ompc_*.
|
||||
kmp_*; # Intel extensions.
|
||||
kmpc_*; # Intel extensions.
|
||||
@@ -74,7 +84,10 @@ 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_reap_monitor;
|
||||
|
||||
+407
-394
@@ -2,6 +2,7 @@
|
||||
* extractExternal.cpp
|
||||
*/
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@@ -11,13 +12,14 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <strstream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
/* Given a set of n object files h ('external' object files) and a set of m
|
||||
object files o ('internal' object files),
|
||||
@@ -28,457 +30,468 @@
|
||||
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];
|
||||
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();
|
||||
}
|
||||
*(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;
|
||||
|
||||
// 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");
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
~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;
|
||||
StringTable(const set<string> &strings) {
|
||||
/* Construct string table from given strings.
|
||||
*/
|
||||
char *p;
|
||||
set<string>::const_iterator it;
|
||||
size_t s;
|
||||
|
||||
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;
|
||||
// count required size for data
|
||||
for(length = sizeof(unsigned), it = strings.begin(); it != strings.end(); ++it) {
|
||||
size_t l = (*it).size();
|
||||
|
||||
for (i = 0; i < 8 && p[i]; ++i)
|
||||
;
|
||||
return string(p, i);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
~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;
|
||||
}
|
||||
}
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
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));
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
// output string table
|
||||
stringTableNew.write(out);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ Language "English"
|
||||
Country "USA"
|
||||
LangId "1033"
|
||||
Version "2"
|
||||
Revision "20170523"
|
||||
Revision "20160714"
|
||||
|
||||
|
||||
|
||||
@@ -103,7 +103,6 @@ DisplayEnvBegin "OPENMP DISPLAY ENVIRONMENT BEGIN"
|
||||
DisplayEnvEnd "OPENMP DISPLAY ENVIRONMENT END"
|
||||
Device "[device]"
|
||||
Host "[host]"
|
||||
Tile "tile"
|
||||
|
||||
|
||||
|
||||
@@ -115,7 +114,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 %1$s\n"
|
||||
Hint "OMP: Hint: %2$s\n"
|
||||
|
||||
Pragma "%1$s pragma (at %2$s:%3$s():%4$s)"
|
||||
# %1 is pragma name (like "parallel" or "master",
|
||||
@@ -326,13 +325,6 @@ 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 ---
|
||||
#
|
||||
@@ -396,15 +388,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 \"N<item>[@N][,...][,Nt] "
|
||||
"(<item> can be S, N, L2, C, T for Socket, NUMA Node, L2 Cache, Core, Thread)\"."
|
||||
AffHWSubsetInvalid "%1$s: invalid value \"%2$s\", valid format is \"Ns[@N],Nc[@N],Nt "
|
||||
"(nSockets@offset, nCores@offset, nTthreads per core)\"."
|
||||
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 tid %3$d thread %4$d bound to OS proc set %5$s"
|
||||
BoundToOSProcSet "%1$s: pid %2$d thread %3$d bound to OS proc set %4$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."
|
||||
@@ -419,10 +411,6 @@ AffHwlocErrorOccurred "%1$s: Hwloc failed in %2$s. Relying on internal af
|
||||
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."
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------------
|
||||
@@ -437,11 +425,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 "
|
||||
"https://bugs.llvm.org/."
|
||||
"http://www.intel.com/software/products/support/."
|
||||
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_DEVICE_THREAD_LIMIT (KMP_ALL_THREADS), KMP_TEAMS_THREAD_LIMIT, and OMP_THREAD_LIMIT (if any are set)."
|
||||
Unset_ALL_THREADS "Consider unsetting KMP_ALL_THREADS and OMP_THREAD_LIMIT (if either is 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 "
|
||||
@@ -453,7 +441,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://openmp.llvm.org/"
|
||||
"For more information, please see http://www.intel.com/software/products/support/."
|
||||
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, "
|
||||
|
||||
@@ -0,0 +1,488 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
@@ -0,0 +1,515 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
@@ -199,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=omp_integer_kind) ids(*)
|
||||
integer (kind=kmp_pointer_kind) ids(*)
|
||||
end subroutine omp_get_place_proc_ids
|
||||
|
||||
function omp_get_place_num()
|
||||
@@ -214,7 +214,7 @@
|
||||
|
||||
subroutine omp_get_partition_place_nums(place_nums)
|
||||
use omp_lib_kinds
|
||||
integer (kind=omp_integer_kind) place_nums(*)
|
||||
integer (kind=kmp_pointer_kind) place_nums(*)
|
||||
end subroutine omp_get_partition_place_nums
|
||||
|
||||
function omp_get_wtime()
|
||||
|
||||
@@ -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=omp_integer_kind) ids(*)
|
||||
integer (kind=kmp_pointer_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=omp_integer_kind) place_nums(*)
|
||||
integer (kind=kmp_pointer_kind) place_nums(*)
|
||||
end subroutine omp_get_partition_place_nums
|
||||
|
||||
function omp_get_wtime() bind(c)
|
||||
|
||||
@@ -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=omp_integer_kind) ids(*)
|
||||
integer (kind=kmp_pointer_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=omp_integer_kind) place_nums(*)
|
||||
integer (kind=kmp_pointer_kind) place_nums(*)
|
||||
end subroutine omp_get_partition_place_nums
|
||||
|
||||
function omp_get_wtime() bind(c)
|
||||
|
||||
@@ -0,0 +1,515 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
@@ -1,215 +0,0 @@
|
||||
/*
|
||||
* 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 */
|
||||
|
||||
@@ -1,868 +0,0 @@
|
||||
! 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
|
||||
|
||||
@@ -1,543 +0,0 @@
|
||||
! 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
|
||||
@@ -1,663 +0,0 @@
|
||||
! 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
|
||||
|
||||
@@ -1,688 +0,0 @@
|
||||
/*
|
||||
* 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__ */
|
||||
+2098
-2370
File diff suppressed because it is too large
Load Diff
+4356
-4666
File diff suppressed because it is too large
Load Diff
+697
-750
File diff suppressed because it is too large
Load Diff
+1580
-1403
File diff suppressed because it is too large
Load Diff
+1756
-2268
File diff suppressed because it is too large
Load Diff
+882
-1501
File diff suppressed because it is too large
Load Diff
+1569
-1820
File diff suppressed because it is too large
Load Diff
+191
-245
@@ -8,13 +8,11 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#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
|
||||
|
||||
@@ -24,104 +22,76 @@
|
||||
@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) {
|
||||
// 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;
|
||||
|
||||
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));
|
||||
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;
|
||||
}
|
||||
#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 */);
|
||||
}
|
||||
}
|
||||
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
|
||||
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 */;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -130,105 +100,77 @@ 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
|
||||
#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));
|
||||
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;
|
||||
}
|
||||
#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;
|
||||
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);
|
||||
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 */;
|
||||
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 */);
|
||||
}
|
||||
}
|
||||
default:
|
||||
KMP_ASSERT(0 /* false */);
|
||||
}
|
||||
}
|
||||
|
||||
// ICV OMP_CANCELLATION=false, so we ignore the cancellation point
|
||||
KMP_DEBUG_ASSERT(!__kmp_omp_cancellation);
|
||||
return 0 /* false */;
|
||||
// ICV OMP_CANCELLATION=false, so we ignore the cancellation point
|
||||
KMP_DEBUG_ASSERT(!__kmp_omp_cancellation);
|
||||
return 0 /* false */;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -236,61 +178,63 @@ kmp_int32 __kmpc_cancellationpoint(ident_t *loc_ref, 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..
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -298,8 +242,8 @@ kmp_int32 __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:
|
||||
@@ -310,27 +254,29 @@ 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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
@@ -45,8 +45,10 @@
|
||||
#define OMPT_DEBUG LIBOMP_OMPT_DEBUG
|
||||
#cmakedefine01 LIBOMP_OMPT_SUPPORT
|
||||
#define OMPT_SUPPORT LIBOMP_OMPT_SUPPORT
|
||||
#cmakedefine01 LIBOMP_OMPT_OPTIONAL
|
||||
#define OMPT_OPTIONAL LIBOMP_OMPT_OPTIONAL
|
||||
#cmakedefine01 LIBOMP_OMPT_BLAME
|
||||
#define OMPT_BLAME LIBOMP_OMPT_BLAME
|
||||
#cmakedefine01 LIBOMP_OMPT_TRACE
|
||||
#define OMPT_TRACE LIBOMP_OMPT_TRACE
|
||||
#cmakedefine01 LIBOMP_USE_ADAPTIVE_LOCKS
|
||||
#define KMP_USE_ADAPTIVE_LOCKS LIBOMP_USE_ADAPTIVE_LOCKS
|
||||
#define KMP_DEBUG_ADAPTIVE_LOCKS 0
|
||||
|
||||
+2189
-2919
File diff suppressed because it is too large
Load Diff
+96
-86
@@ -2,6 +2,7 @@
|
||||
* kmp_debug.cpp -- debug utilities for the Guide library
|
||||
*/
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@@ -11,122 +12,131 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#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);
|
||||
void
|
||||
__kmp_debug_printf_stdout( char const * format, ... )
|
||||
{
|
||||
va_list ap;
|
||||
va_start( ap, format );
|
||||
|
||||
__kmp_vprintf(kmp_out, format, ap);
|
||||
__kmp_vprintf( kmp_out, format, ap );
|
||||
|
||||
va_end(ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
|
||||
void __kmp_debug_printf(char const *format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
void
|
||||
__kmp_debug_printf( char const * format, ... )
|
||||
{
|
||||
va_list ap;
|
||||
va_start( ap, format );
|
||||
|
||||
__kmp_vprintf(kmp_err, format, ap);
|
||||
__kmp_vprintf( kmp_err, format, ap );
|
||||
|
||||
va_end(ap);
|
||||
va_end( ap );
|
||||
}
|
||||
|
||||
#ifdef KMP_USE_ASSERT
|
||||
int __kmp_debug_assert(char const *msg, char const *file, int line) {
|
||||
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 ( 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
|
||||
#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);
|
||||
__kmp_msg(
|
||||
kmp_ms_fatal,
|
||||
KMP_MSG( AssertionFailure, file, line ),
|
||||
KMP_HNT( SubmitBugReport ),
|
||||
__kmp_msg_null
|
||||
);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
} // __kmp_debug_assert
|
||||
} // __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;
|
||||
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);
|
||||
__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++) {
|
||||
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';
|
||||
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! */
|
||||
}
|
||||
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';
|
||||
|
||||
db += __kmp_debug_buf_chars;
|
||||
if ( db >= db_end )
|
||||
db = __kmp_debug_buffer;
|
||||
}
|
||||
|
||||
__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 );
|
||||
}
|
||||
|
||||
__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);
|
||||
}
|
||||
}
|
||||
|
||||
+82
-122
@@ -2,6 +2,7 @@
|
||||
* kmp_debug.h -- debug / assertion code for Assure library
|
||||
*/
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@@ -11,161 +12,120 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#ifndef KMP_DEBUG_H
|
||||
#define KMP_DEBUG_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
// Build-time assertion.
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
// New C++11 style build assert
|
||||
#define KMP_BUILD_ASSERT(expr) static_assert(expr, "Build condition error")
|
||||
/*
|
||||
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.
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
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)
|
||||
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
|
||||
#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
|
||||
#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
|
||||
#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 */
|
||||
|
||||
+211
-185
@@ -1,8 +1,9 @@
|
||||
#if USE_DEBUGGER
|
||||
/*
|
||||
* kmp_debugger.cpp -- debugger support.
|
||||
* kmp_debugger.c -- debugger support.
|
||||
*/
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@@ -12,41 +13,53 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#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!
|
||||
/*
|
||||
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"
|
||||
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.
|
||||
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_of( structure, field ) \
|
||||
{ \
|
||||
offsetof( structure, field ), \
|
||||
sizeof( ( (structure *) NULL)->field ) \
|
||||
}
|
||||
|
||||
#define offset_and_size_not_available \
|
||||
{ -1, -1 }
|
||||
#define offset_and_size_not_available \
|
||||
{ -1, -1 }
|
||||
|
||||
#define addr_and_size_of(var) \
|
||||
{ (kmp_uint64)(&var), sizeof(var) }
|
||||
#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)};
|
||||
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";
|
||||
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 = {
|
||||
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,
|
||||
@@ -54,167 +67,166 @@ kmp_omp_struct_info_t __kmp_omp_debug_struct_info = {
|
||||
/* 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),
|
||||
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.
|
||||
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),
|
||||
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 *),
|
||||
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),
|
||||
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),
|
||||
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
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
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
|
||||
#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),
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
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_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),
|
||||
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),
|
||||
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),
|
||||
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,
|
||||
@@ -224,66 +236,80 @@ kmp_omp_struct_info_t __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
|
||||
/*
|
||||
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
|
||||
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;
|
||||
static int
|
||||
kmp_location_match(
|
||||
kmp_str_loc_t * loc,
|
||||
kmp_omp_nthr_item_t * item
|
||||
) {
|
||||
|
||||
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".
|
||||
int file_match = 0;
|
||||
int func_match = 0;
|
||||
int line_match = 0;
|
||||
|
||||
return (file_match && func_match && line_match);
|
||||
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;
|
||||
int
|
||||
__kmp_omp_num_threads(
|
||||
ident_t const * ident
|
||||
) {
|
||||
|
||||
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);
|
||||
}
|
||||
int num_threads = 0;
|
||||
|
||||
return num_threads;
|
||||
;
|
||||
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 */
|
||||
|
||||
+23
-21
@@ -3,6 +3,7 @@
|
||||
* kmp_debugger.h -- debugger support.
|
||||
*/
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@@ -12,38 +13,39 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#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
|
||||
|
||||
+2380
-2490
File diff suppressed because it is too large
Load Diff
+472
-378
@@ -2,6 +2,7 @@
|
||||
* kmp_environment.cpp -- Handle environment variables OS-independently.
|
||||
*/
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@@ -11,291 +12,356 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* 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):
|
||||
/*
|
||||
------------------------------------------------------------------------------------------------
|
||||
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().
|
||||
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().
|
||||
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.
|
||||
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.
|
||||
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. :-(
|
||||
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:
|
||||
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.
|
||||
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().
|
||||
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
|
||||
2007-04-05 -- lev
|
||||
------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "kmp_environment.h"
|
||||
|
||||
#include "kmp.h" //
|
||||
#include "kmp_os.h" // KMP_OS_*.
|
||||
#include "kmp.h" //
|
||||
#include "kmp_str.h" // __kmp_str_*().
|
||||
#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
|
||||
#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.
|
||||
#include <windows.h> // GetEnvironmentVariable, SetEnvironmentVariable, GetLastError.
|
||||
#else
|
||||
#error Unknown or unsupported OS.
|
||||
#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;
|
||||
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;
|
||||
char *
|
||||
__kmp_env_get( char const * name ) {
|
||||
|
||||
#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
|
||||
char * result = NULL;
|
||||
|
||||
return result;
|
||||
#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) {
|
||||
void
|
||||
__kmp_env_free( char const * * value ) {
|
||||
|
||||
KMP_DEBUG_ASSERT(value != NULL);
|
||||
KMP_INTERNAL_FREE(CCAST(char *, *value));
|
||||
*value = NULL;
|
||||
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_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
#else
|
||||
#error Unknown or unsupported OS.
|
||||
#endif
|
||||
|
||||
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_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
|
||||
|
||||
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_fatal(KMP_MSG(CantSetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
|
||||
}
|
||||
#else
|
||||
#error Unknown or unsupported OS.
|
||||
#endif
|
||||
|
||||
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.:
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
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.
|
||||
) {
|
||||
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 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.
|
||||
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);
|
||||
// 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;
|
||||
// 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));
|
||||
// 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);
|
||||
// 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;
|
||||
}
|
||||
// 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.:
|
||||
}; // ___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"
|
||||
|
||||
@@ -303,199 +369,227 @@ ___kmp_env_blk_parse_string(kmp_env_blk_t *block, // M: Env block to fill.
|
||||
*/
|
||||
|
||||
#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.
|
||||
) {
|
||||
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 * 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.
|
||||
char * name; // Pointer to name of variable.
|
||||
char * value; // Pointer to value.
|
||||
|
||||
if (env != NULL) {
|
||||
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.
|
||||
}
|
||||
// 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));
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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
|
||||
}
|
||||
|
||||
// Fill out result.
|
||||
block->bulk = bulk;
|
||||
block->vars = vars;
|
||||
block->count = count;
|
||||
}
|
||||
}; // 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:
|
||||
|
||||
/*
|
||||
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.
|
||||
) {
|
||||
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.
|
||||
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
|
||||
// Count number of variables and length of required bulk.
|
||||
{
|
||||
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);
|
||||
count = 0;
|
||||
size = 0;
|
||||
while ( env[ count ] != NULL ) {
|
||||
size += KMP_STRLEN( env[ count ] ) + 1;
|
||||
++ count;
|
||||
}; // while
|
||||
}
|
||||
#else
|
||||
#error Unknown or unsupported OS.
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
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.
|
||||
) {
|
||||
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);
|
||||
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(CCAST(kmp_env_var_t *, block->vars));
|
||||
__kmp_str_free(&(block->bulk));
|
||||
|
||||
block->count = 0;
|
||||
block->vars = NULL;
|
||||
void
|
||||
__kmp_env_blk_free(
|
||||
kmp_env_blk_t * block // M: Block of environment variables to free.
|
||||
) {
|
||||
|
||||
KMP_INTERNAL_FREE( (void *) 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;
|
||||
|
||||
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 //
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* kmp_environment.h -- Handle environment varoiables OS-independently.
|
||||
*/
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@@ -11,6 +12,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#ifndef KMP_ENVIRONMENT_H
|
||||
#define KMP_ENVIRONMENT_H
|
||||
|
||||
@@ -18,56 +20,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...
|
||||
}
|
||||
__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...
|
||||
}; // for i
|
||||
__kmp_env_block_free( & block );
|
||||
*/
|
||||
|
||||
struct __kmp_env_var {
|
||||
char *name;
|
||||
char *value;
|
||||
char const * name;
|
||||
char const * value;
|
||||
};
|
||||
typedef struct __kmp_env_var kmp_env_var_t;
|
||||
|
||||
struct __kmp_env_blk {
|
||||
char *bulk;
|
||||
kmp_env_var_t *vars;
|
||||
int count;
|
||||
char const * bulk;
|
||||
kmp_env_var_t const * 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
|
||||
}
|
||||
@@ -76,3 +78,4 @@ char const *__kmp_env_blk_var(kmp_env_blk_t *block, char const *name);
|
||||
#endif // KMP_ENVIRONMENT_H
|
||||
|
||||
// end of file //
|
||||
|
||||
|
||||
+413
-352
@@ -2,6 +2,7 @@
|
||||
* kmp_error.cpp -- KPTS functions for error checking at runtime
|
||||
*/
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@@ -11,237 +12,261 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#include "kmp.h"
|
||||
#include "kmp_error.h"
|
||||
#include "kmp_i18n.h"
|
||||
#include "kmp_str.h"
|
||||
#include "kmp_error.h"
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#define MIN_STACK 100
|
||||
#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 */
|
||||
|
||||
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\""};
|
||||
"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 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)
|
||||
#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 *);
|
||||
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_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;
|
||||
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();
|
||||
/* TODO for monitor perhaps? */
|
||||
if (gtid < 0)
|
||||
__kmp_check_null_func();
|
||||
|
||||
KE_TRACE(10, ("expand cons_stack (%d %d)\n", gtid, __kmp_get_gtid()));
|
||||
KE_TRACE( 10, ("expand cons_stack (%d %d)\n", gtid, __kmp_get_gtid() ) );
|
||||
|
||||
d = p->stack_data;
|
||||
d = p->stack_data;
|
||||
|
||||
p->stack_size = (p->stack_size * 2) + 100;
|
||||
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));
|
||||
/* 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];
|
||||
for (i = p->stack_top; i >= 0; --i)
|
||||
p->stack_data[i] = d[i];
|
||||
|
||||
/* NOTE: we do not free the old stack_data */
|
||||
/* 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;
|
||||
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 *construct = __kmp_pragma(ct, ident);
|
||||
__kmp_fatal(__kmp_msg_format(id, construct), __kmp_msg_null);
|
||||
KMP_INTERNAL_FREE(construct);
|
||||
|
||||
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 *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);
|
||||
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();
|
||||
}
|
||||
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;
|
||||
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;
|
||||
}
|
||||
__kmp_free(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);
|
||||
}
|
||||
__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);
|
||||
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;
|
||||
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));
|
||||
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;
|
||||
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()));
|
||||
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]);
|
||||
}
|
||||
|
||||
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
|
||||
__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
|
||||
@@ -251,91 +276,98 @@ __kmp_check_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_l
|
||||
__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;
|
||||
struct cons_header *p = __kmp_threads[ gtid ]->th.th_cons;
|
||||
|
||||
KE_TRACE(10, ("__kmp_check_sync (gtid=%d)\n", __kmp_get_gtid()));
|
||||
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 (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]);
|
||||
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 {
|
||||
__kmp_error_construct2(kmp_i18n_msg_CnsNoOrderedClause, ct, ident,
|
||||
&p->stack_data[p->w_top]);
|
||||
/* 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;
|
||||
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;
|
||||
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 (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 */
|
||||
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 thread already has lock for this critical section */
|
||||
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 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]);
|
||||
}
|
||||
}
|
||||
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
|
||||
@@ -345,118 +377,147 @@ __kmp_push_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lo
|
||||
__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;
|
||||
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));
|
||||
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);
|
||||
__kmp_check_sync( gtid, ct, ident, lck, seq );
|
||||
#else
|
||||
__kmp_check_sync(gtid, ct, ident, lck);
|
||||
__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));
|
||||
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));
|
||||
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;
|
||||
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);
|
||||
}
|
||||
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;
|
||||
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_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]);
|
||||
}
|
||||
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 ]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
+20
-24
@@ -2,6 +2,7 @@
|
||||
* kmp_error.h -- PTS functions for error checking at runtime.
|
||||
*/
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@@ -11,6 +12,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#ifndef KMP_ERROR_H
|
||||
#define KMP_ERROR_H
|
||||
|
||||
@@ -18,44 +20,38 @@
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
#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
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* kmp_ftn_cdecl.cpp -- Fortran __cdecl linkage support for OpenMP.
|
||||
*/
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@@ -11,25 +12,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 */
|
||||
|
||||
+1218
-1026
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,7 @@
|
||||
* kmp_ftn_extra.cpp -- Fortran 'extra' linkage support for OpenMP.
|
||||
*/
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@@ -11,23 +12,23 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#include "kmp.h"
|
||||
#include "kmp_affinity.h"
|
||||
|
||||
#if KMP_OS_WINDOWS
|
||||
#define KMP_FTN_ENTRIES KMP_FTN_PLAIN
|
||||
# define KMP_FTN_ENTRIES KMP_FTN_PLAIN
|
||||
#elif KMP_OS_UNIX
|
||||
#define KMP_FTN_ENTRIES KMP_FTN_APPEND
|
||||
# define KMP_FTN_ENTRIES KMP_FTN_APPEND
|
||||
#endif
|
||||
|
||||
// Note: This string is not printed when KMP_VERSION=1.
|
||||
char const __kmp_version_ftnextra[] =
|
||||
KMP_VERSION_PREFIX "Fortran \"extra\" OMP support: "
|
||||
char const __kmp_version_ftnextra[] = KMP_VERSION_PREFIX "Fortran \"extra\" OMP support: "
|
||||
#ifdef KMP_FTN_ENTRIES
|
||||
"yes";
|
||||
#define FTN_STDCALL /* nothing to do */
|
||||
#include "kmp_ftn_os.h"
|
||||
#include "kmp_ftn_entry.h"
|
||||
"yes";
|
||||
# define FTN_STDCALL /* nothing to do */
|
||||
# include "kmp_ftn_os.h"
|
||||
# include "kmp_ftn_entry.h"
|
||||
#else
|
||||
"no";
|
||||
"no";
|
||||
#endif /* KMP_FTN_ENTRIES */
|
||||
|
||||
+476
-472
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,7 @@
|
||||
* kmp_ftn_stdcall.cpp -- Fortran __stdcall linkage support for OpenMP.
|
||||
*/
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@@ -11,23 +12,24 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#include "kmp.h"
|
||||
|
||||
// Note: This string is not printed when KMP_VERSION=1.
|
||||
char const __kmp_version_ftnstdcall[] =
|
||||
KMP_VERSION_PREFIX "Fortran __stdcall OMP support: "
|
||||
char const __kmp_version_ftnstdcall[] = KMP_VERSION_PREFIX "Fortran __stdcall OMP support: "
|
||||
#ifdef USE_FTN_STDCALL
|
||||
"yes";
|
||||
"yes";
|
||||
#else
|
||||
"no";
|
||||
"no";
|
||||
#endif
|
||||
|
||||
#ifdef USE_FTN_STDCALL
|
||||
|
||||
#define FTN_STDCALL KMP_STDCALL
|
||||
#define KMP_FTN_ENTRIES USE_FTN_STDCALL
|
||||
#define FTN_STDCALL KMP_STDCALL
|
||||
#define KMP_FTN_ENTRIES USE_FTN_STDCALL
|
||||
|
||||
#include "kmp_ftn_entry.h"
|
||||
#include "kmp_ftn_os.h"
|
||||
#include "kmp_ftn_entry.h"
|
||||
|
||||
#endif /* USE_FTN_STDCALL */
|
||||
|
||||
|
||||
+272
-280
@@ -2,6 +2,7 @@
|
||||
* kmp_global.cpp -- KPTS global variables for runtime support library
|
||||
*/
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@@ -11,13 +12,14 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#include "kmp.h"
|
||||
#include "kmp_affinity.h"
|
||||
|
||||
kmp_key_t __kmp_gtid_threadprivate_key;
|
||||
|
||||
#if KMP_ARCH_X86 || KMP_ARCH_X86_64
|
||||
kmp_cpuinfo_t __kmp_cpuinfo = {0}; // Not initialized
|
||||
kmp_cpuinfo_t __kmp_cpuinfo = { 0 }; // Not initialized
|
||||
#endif
|
||||
|
||||
#if KMP_STATS_ENABLED
|
||||
@@ -25,12 +27,11 @@ kmp_cpuinfo_t __kmp_cpuinfo = {0}; // Not initialized
|
||||
// lock for modifying the global __kmp_stats_list
|
||||
kmp_tas_lock_t __kmp_stats_lock;
|
||||
|
||||
// global list of per thread stats, the head is a sentinel node which
|
||||
// accumulates all stats produced before __kmp_create_worker is called.
|
||||
kmp_stats_list *__kmp_stats_list;
|
||||
// global list of per thread stats, the head is a sentinel node which accumulates all stats produced before __kmp_create_worker is called.
|
||||
kmp_stats_list* __kmp_stats_list;
|
||||
|
||||
// thread local pointer to stats node within list
|
||||
KMP_THREAD_LOCAL kmp_stats_list *__kmp_stats_thread_ptr = NULL;
|
||||
__thread kmp_stats_list* __kmp_stats_thread_ptr = NULL;
|
||||
|
||||
// gives reference tick for all events (considered the 0 tick)
|
||||
tsc_tick_count __kmp_stats_start_time;
|
||||
@@ -39,183 +40,176 @@ tsc_tick_count __kmp_stats_start_time;
|
||||
/* ----------------------------------------------------- */
|
||||
/* INITIALIZATION VARIABLES */
|
||||
/* they are syncronized to write during init, but read anytime */
|
||||
volatile int __kmp_init_serial = FALSE;
|
||||
volatile int __kmp_init_gtid = FALSE;
|
||||
volatile int __kmp_init_common = FALSE;
|
||||
volatile int __kmp_init_middle = FALSE;
|
||||
volatile int __kmp_init_parallel = FALSE;
|
||||
volatile int __kmp_init_serial = FALSE;
|
||||
volatile int __kmp_init_gtid = FALSE;
|
||||
volatile int __kmp_init_common = FALSE;
|
||||
volatile int __kmp_init_middle = FALSE;
|
||||
volatile int __kmp_init_parallel = FALSE;
|
||||
#if KMP_USE_MONITOR
|
||||
volatile int __kmp_init_monitor =
|
||||
0; /* 1 - launched, 2 - actually started (Windows* OS only) */
|
||||
volatile int __kmp_init_monitor = 0; /* 1 - launched, 2 - actually started (Windows* OS only) */
|
||||
#endif
|
||||
volatile int __kmp_init_user_locks = FALSE;
|
||||
volatile int __kmp_init_user_locks = FALSE;
|
||||
|
||||
/* list of address of allocated caches for commons */
|
||||
kmp_cached_addr_t *__kmp_threadpriv_cache_list = NULL;
|
||||
kmp_cached_addr_t *__kmp_threadpriv_cache_list = NULL;
|
||||
|
||||
int __kmp_init_counter = 0;
|
||||
int __kmp_root_counter = 0;
|
||||
int __kmp_version = 0;
|
||||
int __kmp_init_counter = 0;
|
||||
int __kmp_root_counter = 0;
|
||||
int __kmp_version = 0;
|
||||
|
||||
volatile kmp_uint32 __kmp_team_counter = 0;
|
||||
volatile kmp_uint32 __kmp_task_counter = 0;
|
||||
volatile kmp_uint32 __kmp_team_counter = 0;
|
||||
volatile kmp_uint32 __kmp_task_counter = 0;
|
||||
|
||||
unsigned int __kmp_init_wait =
|
||||
KMP_DEFAULT_INIT_WAIT; /* initial number of spin-tests */
|
||||
unsigned int __kmp_next_wait =
|
||||
KMP_DEFAULT_NEXT_WAIT; /* susequent number of spin-tests */
|
||||
unsigned int __kmp_init_wait = KMP_DEFAULT_INIT_WAIT; /* initial number of spin-tests */
|
||||
unsigned int __kmp_next_wait = KMP_DEFAULT_NEXT_WAIT; /* susequent number of spin-tests */
|
||||
|
||||
size_t __kmp_stksize = KMP_DEFAULT_STKSIZE;
|
||||
size_t __kmp_stksize = KMP_DEFAULT_STKSIZE;
|
||||
#if KMP_USE_MONITOR
|
||||
size_t __kmp_monitor_stksize = 0; // auto adjust
|
||||
size_t __kmp_monitor_stksize = 0; // auto adjust
|
||||
#endif
|
||||
size_t __kmp_stkoffset = KMP_DEFAULT_STKOFFSET;
|
||||
int __kmp_stkpadding = KMP_MIN_STKPADDING;
|
||||
size_t __kmp_stkoffset = KMP_DEFAULT_STKOFFSET;
|
||||
int __kmp_stkpadding = KMP_MIN_STKPADDING;
|
||||
|
||||
size_t __kmp_malloc_pool_incr = KMP_DEFAULT_MALLOC_POOL_INCR;
|
||||
size_t __kmp_malloc_pool_incr = KMP_DEFAULT_MALLOC_POOL_INCR;
|
||||
|
||||
// Barrier method defaults, settings, and strings.
|
||||
// branch factor = 2^branch_bits (only relevant for tree & hyper barrier types)
|
||||
kmp_uint32 __kmp_barrier_gather_bb_dflt = 2;
|
||||
/* branch_factor = 4 */ /* hyper2: C78980 */
|
||||
kmp_uint32 __kmp_barrier_release_bb_dflt = 2;
|
||||
/* branch_factor = 4 */ /* hyper2: C78980 */
|
||||
/* Barrier method defaults, settings, and strings */
|
||||
/* branch factor = 2^branch_bits (only relevant for tree and hyper barrier types) */
|
||||
#if KMP_ARCH_X86_64
|
||||
kmp_uint32 __kmp_barrier_gather_bb_dflt = 2; /* branch_factor = 4 */ /* hyper2: C78980 */
|
||||
kmp_uint32 __kmp_barrier_release_bb_dflt = 2; /* branch_factor = 4 */ /* hyper2: C78980 */
|
||||
#else
|
||||
kmp_uint32 __kmp_barrier_gather_bb_dflt = 2; /* branch_factor = 4 */ /* communication in core for MIC */
|
||||
kmp_uint32 __kmp_barrier_release_bb_dflt = 2; /* branch_factor = 4 */ /* communication in core for MIC */
|
||||
#endif // KMP_ARCH_X86_64
|
||||
#if KMP_ARCH_X86_64
|
||||
kmp_bar_pat_e __kmp_barrier_gather_pat_dflt = bp_hyper_bar; /* hyper2: C78980 */
|
||||
kmp_bar_pat_e __kmp_barrier_release_pat_dflt = bp_hyper_bar; /* hyper2: C78980 */
|
||||
#else
|
||||
kmp_bar_pat_e __kmp_barrier_gather_pat_dflt = bp_linear_bar;
|
||||
kmp_bar_pat_e __kmp_barrier_release_pat_dflt = bp_linear_bar;
|
||||
#endif
|
||||
kmp_uint32 __kmp_barrier_gather_branch_bits [ bs_last_barrier ] = { 0 };
|
||||
kmp_uint32 __kmp_barrier_release_branch_bits [ bs_last_barrier ] = { 0 };
|
||||
kmp_bar_pat_e __kmp_barrier_gather_pattern [ bs_last_barrier ] = { bp_linear_bar };
|
||||
kmp_bar_pat_e __kmp_barrier_release_pattern [ bs_last_barrier ] = { bp_linear_bar };
|
||||
char const *__kmp_barrier_branch_bit_env_name [ bs_last_barrier ] =
|
||||
{ "KMP_PLAIN_BARRIER", "KMP_FORKJOIN_BARRIER"
|
||||
#if KMP_FAST_REDUCTION_BARRIER
|
||||
, "KMP_REDUCTION_BARRIER"
|
||||
#endif // KMP_FAST_REDUCTION_BARRIER
|
||||
};
|
||||
char const *__kmp_barrier_pattern_env_name [ bs_last_barrier ] =
|
||||
{ "KMP_PLAIN_BARRIER_PATTERN", "KMP_FORKJOIN_BARRIER_PATTERN"
|
||||
#if KMP_FAST_REDUCTION_BARRIER
|
||||
, "KMP_REDUCTION_BARRIER_PATTERN"
|
||||
#endif // KMP_FAST_REDUCTION_BARRIER
|
||||
};
|
||||
char const *__kmp_barrier_type_name [ bs_last_barrier ] =
|
||||
{ "plain", "forkjoin"
|
||||
#if KMP_FAST_REDUCTION_BARRIER
|
||||
, "reduction"
|
||||
#endif // KMP_FAST_REDUCTION_BARRIER
|
||||
};
|
||||
char const *__kmp_barrier_pattern_name[bp_last_bar] = {"linear","tree","hyper","hierarchical"};
|
||||
|
||||
kmp_bar_pat_e __kmp_barrier_gather_pat_dflt = bp_hyper_bar;
|
||||
/* hyper2: C78980 */
|
||||
kmp_bar_pat_e __kmp_barrier_release_pat_dflt = bp_hyper_bar;
|
||||
/* hyper2: C78980 */
|
||||
int __kmp_allThreadsSpecified = 0;
|
||||
size_t __kmp_align_alloc = CACHE_LINE;
|
||||
|
||||
kmp_uint32 __kmp_barrier_gather_branch_bits[bs_last_barrier] = {0};
|
||||
kmp_uint32 __kmp_barrier_release_branch_bits[bs_last_barrier] = {0};
|
||||
kmp_bar_pat_e __kmp_barrier_gather_pattern[bs_last_barrier] = {bp_linear_bar};
|
||||
kmp_bar_pat_e __kmp_barrier_release_pattern[bs_last_barrier] = {bp_linear_bar};
|
||||
char const *__kmp_barrier_branch_bit_env_name[bs_last_barrier] = {
|
||||
"KMP_PLAIN_BARRIER", "KMP_FORKJOIN_BARRIER"
|
||||
#if KMP_FAST_REDUCTION_BARRIER
|
||||
,
|
||||
"KMP_REDUCTION_BARRIER"
|
||||
#endif // KMP_FAST_REDUCTION_BARRIER
|
||||
};
|
||||
char const *__kmp_barrier_pattern_env_name[bs_last_barrier] = {
|
||||
"KMP_PLAIN_BARRIER_PATTERN", "KMP_FORKJOIN_BARRIER_PATTERN"
|
||||
#if KMP_FAST_REDUCTION_BARRIER
|
||||
,
|
||||
"KMP_REDUCTION_BARRIER_PATTERN"
|
||||
#endif // KMP_FAST_REDUCTION_BARRIER
|
||||
};
|
||||
char const *__kmp_barrier_type_name[bs_last_barrier] = {"plain", "forkjoin"
|
||||
#if KMP_FAST_REDUCTION_BARRIER
|
||||
,
|
||||
"reduction"
|
||||
#endif // KMP_FAST_REDUCTION_BARRIER
|
||||
};
|
||||
char const *__kmp_barrier_pattern_name[bp_last_bar] = {"linear", "tree",
|
||||
"hyper", "hierarchical"};
|
||||
|
||||
int __kmp_allThreadsSpecified = 0;
|
||||
size_t __kmp_align_alloc = CACHE_LINE;
|
||||
|
||||
int __kmp_generate_warnings = kmp_warnings_low;
|
||||
int __kmp_reserve_warn = 0;
|
||||
int __kmp_xproc = 0;
|
||||
int __kmp_avail_proc = 0;
|
||||
size_t __kmp_sys_min_stksize = KMP_MIN_STKSIZE;
|
||||
int __kmp_sys_max_nth = KMP_MAX_NTH;
|
||||
int __kmp_max_nth = 0;
|
||||
int __kmp_cg_max_nth = 0;
|
||||
int __kmp_teams_max_nth = 0;
|
||||
int __kmp_threads_capacity = 0;
|
||||
int __kmp_dflt_team_nth = 0;
|
||||
int __kmp_dflt_team_nth_ub = 0;
|
||||
int __kmp_tp_capacity = 0;
|
||||
int __kmp_tp_cached = 0;
|
||||
int __kmp_dflt_nested = FALSE;
|
||||
int __kmp_dispatch_num_buffers = KMP_DFLT_DISP_NUM_BUFF;
|
||||
int __kmp_dflt_max_active_levels =
|
||||
KMP_MAX_ACTIVE_LEVELS_LIMIT; /* max_active_levels limit */
|
||||
int __kmp_generate_warnings = kmp_warnings_low;
|
||||
int __kmp_reserve_warn = 0;
|
||||
int __kmp_xproc = 0;
|
||||
int __kmp_avail_proc = 0;
|
||||
size_t __kmp_sys_min_stksize = KMP_MIN_STKSIZE;
|
||||
int __kmp_sys_max_nth = KMP_MAX_NTH;
|
||||
int __kmp_max_nth = 0;
|
||||
int __kmp_threads_capacity = 0;
|
||||
int __kmp_dflt_team_nth = 0;
|
||||
int __kmp_dflt_team_nth_ub = 0;
|
||||
int __kmp_tp_capacity = 0;
|
||||
int __kmp_tp_cached = 0;
|
||||
int __kmp_dflt_nested = FALSE;
|
||||
int __kmp_dispatch_num_buffers = KMP_DFLT_DISP_NUM_BUFF;
|
||||
int __kmp_dflt_max_active_levels = KMP_MAX_ACTIVE_LEVELS_LIMIT; /* max_active_levels limit */
|
||||
#if KMP_NESTED_HOT_TEAMS
|
||||
int __kmp_hot_teams_mode = 0; /* 0 - free extra threads when reduced */
|
||||
/* 1 - keep extra threads when reduced */
|
||||
int __kmp_hot_teams_max_level = 1; /* nesting level of hot teams */
|
||||
int __kmp_hot_teams_mode = 0; /* 0 - free extra threads when reduced */
|
||||
/* 1 - keep extra threads when reduced */
|
||||
int __kmp_hot_teams_max_level = 1; /* nesting level of hot teams */
|
||||
#endif
|
||||
enum library_type __kmp_library = library_none;
|
||||
enum sched_type __kmp_sched =
|
||||
kmp_sch_default; /* scheduling method for runtime scheduling */
|
||||
enum sched_type __kmp_static =
|
||||
kmp_sch_static_greedy; /* default static scheduling method */
|
||||
enum sched_type __kmp_guided =
|
||||
kmp_sch_guided_iterative_chunked; /* default guided scheduling method */
|
||||
enum sched_type __kmp_auto =
|
||||
kmp_sch_guided_analytical_chunked; /* default auto scheduling method */
|
||||
int __kmp_dflt_blocktime = KMP_DEFAULT_BLOCKTIME;
|
||||
enum sched_type __kmp_sched = kmp_sch_default; /* scheduling method for runtime scheduling */
|
||||
enum sched_type __kmp_static = kmp_sch_static_greedy; /* default static scheduling method */
|
||||
enum sched_type __kmp_guided = kmp_sch_guided_iterative_chunked; /* default guided scheduling method */
|
||||
enum sched_type __kmp_auto = kmp_sch_guided_analytical_chunked; /* default auto scheduling method */
|
||||
int __kmp_dflt_blocktime = KMP_DEFAULT_BLOCKTIME;
|
||||
#if KMP_USE_MONITOR
|
||||
int __kmp_monitor_wakeups = KMP_MIN_MONITOR_WAKEUPS;
|
||||
int __kmp_bt_intervals = KMP_INTERVALS_FROM_BLOCKTIME(KMP_DEFAULT_BLOCKTIME,
|
||||
KMP_MIN_MONITOR_WAKEUPS);
|
||||
int __kmp_monitor_wakeups = KMP_MIN_MONITOR_WAKEUPS;
|
||||
int __kmp_bt_intervals = KMP_INTERVALS_FROM_BLOCKTIME( KMP_DEFAULT_BLOCKTIME, KMP_MIN_MONITOR_WAKEUPS );
|
||||
#endif
|
||||
#ifdef KMP_ADJUST_BLOCKTIME
|
||||
int __kmp_zero_bt = FALSE;
|
||||
int __kmp_zero_bt = FALSE;
|
||||
#endif /* KMP_ADJUST_BLOCKTIME */
|
||||
#ifdef KMP_DFLT_NTH_CORES
|
||||
int __kmp_ncores = 0;
|
||||
int __kmp_ncores = 0;
|
||||
#endif
|
||||
int __kmp_chunk = 0;
|
||||
int __kmp_abort_delay = 0;
|
||||
int __kmp_chunk = 0;
|
||||
int __kmp_abort_delay = 0;
|
||||
#if KMP_OS_LINUX && defined(KMP_TDATA_GTID)
|
||||
int __kmp_gtid_mode = 3; /* use __declspec(thread) TLS to store gtid */
|
||||
int __kmp_adjust_gtid_mode = FALSE;
|
||||
int __kmp_gtid_mode = 3; /* use __declspec(thread) TLS to store gtid */
|
||||
int __kmp_adjust_gtid_mode = FALSE;
|
||||
#elif KMP_OS_WINDOWS
|
||||
int __kmp_gtid_mode = 2; /* use TLS functions to store gtid */
|
||||
int __kmp_adjust_gtid_mode = FALSE;
|
||||
int __kmp_gtid_mode = 2; /* use TLS functions to store gtid */
|
||||
int __kmp_adjust_gtid_mode = FALSE;
|
||||
#else
|
||||
int __kmp_gtid_mode = 0; /* select method to get gtid based on #threads */
|
||||
int __kmp_adjust_gtid_mode = TRUE;
|
||||
int __kmp_gtid_mode = 0; /* select method to get gtid based on #threads */
|
||||
int __kmp_adjust_gtid_mode = TRUE;
|
||||
#endif /* KMP_OS_LINUX && defined(KMP_TDATA_GTID) */
|
||||
#ifdef KMP_TDATA_GTID
|
||||
KMP_THREAD_LOCAL int __kmp_gtid = KMP_GTID_DNE;
|
||||
#if KMP_OS_WINDOWS
|
||||
__declspec(thread) int __kmp_gtid = KMP_GTID_DNE;
|
||||
#else
|
||||
__thread int __kmp_gtid = KMP_GTID_DNE;
|
||||
#endif /* KMP_OS_WINDOWS - workaround because Intel(R) Many Integrated Core compiler 20110316 doesn't accept __declspec */
|
||||
#endif /* KMP_TDATA_GTID */
|
||||
int __kmp_tls_gtid_min = INT_MAX;
|
||||
int __kmp_foreign_tp = TRUE;
|
||||
int __kmp_tls_gtid_min = INT_MAX;
|
||||
int __kmp_foreign_tp = TRUE;
|
||||
#if KMP_ARCH_X86 || KMP_ARCH_X86_64
|
||||
int __kmp_inherit_fp_control = TRUE;
|
||||
kmp_int16 __kmp_init_x87_fpu_control_word = 0;
|
||||
kmp_uint32 __kmp_init_mxcsr = 0;
|
||||
int __kmp_inherit_fp_control = TRUE;
|
||||
kmp_int16 __kmp_init_x87_fpu_control_word = 0;
|
||||
kmp_uint32 __kmp_init_mxcsr = 0;
|
||||
#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
|
||||
|
||||
#ifdef USE_LOAD_BALANCE
|
||||
double __kmp_load_balance_interval = 1.0;
|
||||
double __kmp_load_balance_interval = 1.0;
|
||||
#endif /* USE_LOAD_BALANCE */
|
||||
|
||||
kmp_nested_nthreads_t __kmp_nested_nth = {NULL, 0, 0};
|
||||
kmp_nested_nthreads_t __kmp_nested_nth = { NULL, 0, 0 };
|
||||
|
||||
#if KMP_USE_ADAPTIVE_LOCKS
|
||||
|
||||
kmp_adaptive_backoff_params_t __kmp_adaptive_backoff_params = {
|
||||
1, 1024}; // TODO: tune it!
|
||||
kmp_adaptive_backoff_params_t __kmp_adaptive_backoff_params = { 1, 1024 }; // TODO: tune it!
|
||||
|
||||
#if KMP_DEBUG_ADAPTIVE_LOCKS
|
||||
char *__kmp_speculative_statsfile = "-";
|
||||
char * __kmp_speculative_statsfile = "-";
|
||||
#endif
|
||||
|
||||
#endif // KMP_USE_ADAPTIVE_LOCKS
|
||||
|
||||
#if OMP_40_ENABLED
|
||||
int __kmp_display_env = FALSE;
|
||||
int __kmp_display_env_verbose = FALSE;
|
||||
int __kmp_omp_cancellation = FALSE;
|
||||
int __kmp_display_env = FALSE;
|
||||
int __kmp_display_env_verbose = FALSE;
|
||||
int __kmp_omp_cancellation = FALSE;
|
||||
#endif
|
||||
|
||||
/* map OMP 3.0 schedule types with our internal schedule types */
|
||||
enum sched_type __kmp_sch_map[kmp_sched_upper - kmp_sched_lower_ext +
|
||||
kmp_sched_upper_std - kmp_sched_lower - 2] = {
|
||||
kmp_sch_static_chunked, // ==> kmp_sched_static = 1
|
||||
kmp_sch_dynamic_chunked, // ==> kmp_sched_dynamic = 2
|
||||
kmp_sch_guided_chunked, // ==> kmp_sched_guided = 3
|
||||
kmp_sch_auto, // ==> kmp_sched_auto = 4
|
||||
kmp_sch_trapezoidal // ==> kmp_sched_trapezoidal = 101
|
||||
// will likely not be used, introduced here just to debug the code
|
||||
// of public intel extension schedules
|
||||
enum sched_type __kmp_sch_map[ kmp_sched_upper - kmp_sched_lower_ext + kmp_sched_upper_std - kmp_sched_lower - 2 ] = {
|
||||
kmp_sch_static_chunked, // ==> kmp_sched_static = 1
|
||||
kmp_sch_dynamic_chunked, // ==> kmp_sched_dynamic = 2
|
||||
kmp_sch_guided_chunked, // ==> kmp_sched_guided = 3
|
||||
kmp_sch_auto, // ==> kmp_sched_auto = 4
|
||||
kmp_sch_trapezoidal // ==> kmp_sched_trapezoidal = 101
|
||||
// will likely not used, introduced here just to debug the code
|
||||
// of public intel extension schedules
|
||||
};
|
||||
|
||||
#if KMP_OS_LINUX
|
||||
@@ -223,63 +217,58 @@ enum clock_function_type __kmp_clock_function;
|
||||
int __kmp_clock_function_param;
|
||||
#endif /* KMP_OS_LINUX */
|
||||
|
||||
#if KMP_MIC_SUPPORTED
|
||||
#if KMP_ARCH_X86_64 && (KMP_OS_LINUX || KMP_OS_WINDOWS)
|
||||
enum mic_type __kmp_mic_type = non_mic;
|
||||
#endif
|
||||
|
||||
#if KMP_AFFINITY_SUPPORTED
|
||||
|
||||
KMPAffinity *__kmp_affinity_dispatch = NULL;
|
||||
KMPAffinity* __kmp_affinity_dispatch = NULL;
|
||||
|
||||
#if KMP_USE_HWLOC
|
||||
# if KMP_USE_HWLOC
|
||||
int __kmp_hwloc_error = FALSE;
|
||||
hwloc_topology_t __kmp_hwloc_topology = NULL;
|
||||
int __kmp_numa_detected = FALSE;
|
||||
int __kmp_tile_depth = 0;
|
||||
#endif
|
||||
# endif
|
||||
|
||||
#if KMP_OS_WINDOWS
|
||||
#if KMP_GROUP_AFFINITY
|
||||
# if KMP_OS_WINDOWS
|
||||
# if KMP_GROUP_AFFINITY
|
||||
int __kmp_num_proc_groups = 1;
|
||||
#endif /* KMP_GROUP_AFFINITY */
|
||||
# endif /* KMP_GROUP_AFFINITY */
|
||||
kmp_GetActiveProcessorCount_t __kmp_GetActiveProcessorCount = NULL;
|
||||
kmp_GetActiveProcessorGroupCount_t __kmp_GetActiveProcessorGroupCount = NULL;
|
||||
kmp_GetThreadGroupAffinity_t __kmp_GetThreadGroupAffinity = NULL;
|
||||
kmp_SetThreadGroupAffinity_t __kmp_SetThreadGroupAffinity = NULL;
|
||||
#endif /* KMP_OS_WINDOWS */
|
||||
# endif /* KMP_OS_WINDOWS */
|
||||
|
||||
size_t __kmp_affin_mask_size = 0;
|
||||
size_t __kmp_affin_mask_size = 0;
|
||||
enum affinity_type __kmp_affinity_type = affinity_default;
|
||||
enum affinity_gran __kmp_affinity_gran = affinity_gran_default;
|
||||
int __kmp_affinity_gran_levels = -1;
|
||||
int __kmp_affinity_gran_levels = -1;
|
||||
int __kmp_affinity_dups = TRUE;
|
||||
enum affinity_top_method __kmp_affinity_top_method =
|
||||
affinity_top_method_default;
|
||||
int __kmp_affinity_compact = 0;
|
||||
int __kmp_affinity_offset = 0;
|
||||
int __kmp_affinity_verbose = FALSE;
|
||||
int __kmp_affinity_warnings = TRUE;
|
||||
int __kmp_affinity_respect_mask = affinity_respect_mask_default;
|
||||
char *__kmp_affinity_proclist = NULL;
|
||||
enum affinity_top_method __kmp_affinity_top_method = affinity_top_method_default;
|
||||
int __kmp_affinity_compact = 0;
|
||||
int __kmp_affinity_offset = 0;
|
||||
int __kmp_affinity_verbose = FALSE;
|
||||
int __kmp_affinity_warnings = TRUE;
|
||||
int __kmp_affinity_respect_mask = affinity_respect_mask_default;
|
||||
char * __kmp_affinity_proclist = NULL;
|
||||
kmp_affin_mask_t *__kmp_affinity_masks = NULL;
|
||||
unsigned __kmp_affinity_num_masks = 0;
|
||||
unsigned __kmp_affinity_num_masks = 0;
|
||||
|
||||
char *__kmp_cpuinfo_file = NULL;
|
||||
char const * __kmp_cpuinfo_file = NULL;
|
||||
|
||||
#endif /* KMP_AFFINITY_SUPPORTED */
|
||||
|
||||
#if OMP_40_ENABLED
|
||||
kmp_nested_proc_bind_t __kmp_nested_proc_bind = {NULL, 0, 0};
|
||||
kmp_nested_proc_bind_t __kmp_nested_proc_bind = { NULL, 0, 0 };
|
||||
int __kmp_affinity_num_places = 0;
|
||||
#endif
|
||||
|
||||
kmp_hws_item_t __kmp_hws_socket = {0, 0};
|
||||
kmp_hws_item_t __kmp_hws_node = {0, 0};
|
||||
kmp_hws_item_t __kmp_hws_tile = {0, 0};
|
||||
kmp_hws_item_t __kmp_hws_core = {0, 0};
|
||||
kmp_hws_item_t __kmp_hws_proc = {0, 0};
|
||||
int __kmp_hws_requested = 0;
|
||||
int __kmp_hws_abs_flag = 0; // absolute or per-item number requested
|
||||
int __kmp_place_num_sockets = 0;
|
||||
int __kmp_place_socket_offset = 0;
|
||||
int __kmp_place_num_cores = 0;
|
||||
int __kmp_place_core_offset = 0;
|
||||
int __kmp_place_num_threads_per_core = 0;
|
||||
|
||||
#if OMP_40_ENABLED
|
||||
kmp_int32 __kmp_default_device = 0;
|
||||
@@ -288,126 +277,123 @@ kmp_int32 __kmp_default_device = 0;
|
||||
kmp_tasking_mode_t __kmp_tasking_mode = tskm_task_teams;
|
||||
#if OMP_45_ENABLED
|
||||
kmp_int32 __kmp_max_task_priority = 0;
|
||||
kmp_uint64 __kmp_taskloop_min_tasks = 0;
|
||||
#endif
|
||||
|
||||
/* This check ensures that the compiler is passing the correct data type for the
|
||||
flags formal parameter of the function kmpc_omp_task_alloc(). If the type is
|
||||
not a 4-byte type, then give an error message about a non-positive length
|
||||
array pointing here. If that happens, the kmp_tasking_flags_t structure must
|
||||
be redefined to have exactly 32 bits. */
|
||||
KMP_BUILD_ASSERT(sizeof(kmp_tasking_flags_t) == 4);
|
||||
/* This check ensures that the compiler is passing the correct data type
|
||||
* for the flags formal parameter of the function kmpc_omp_task_alloc().
|
||||
* If the type is not a 4-byte type, then give an error message about
|
||||
* a non-positive length array pointing here. If that happens, the
|
||||
* kmp_tasking_flags_t structure must be redefined to have exactly 32 bits.
|
||||
*/
|
||||
KMP_BUILD_ASSERT( sizeof(kmp_tasking_flags_t) == 4 );
|
||||
|
||||
int __kmp_task_stealing_constraint = 1; /* Constrain task stealing by default */
|
||||
kmp_int32 __kmp_task_stealing_constraint = 1; /* Constrain task stealing by default */
|
||||
|
||||
#ifdef DEBUG_SUSPEND
|
||||
int __kmp_suspend_count = 0;
|
||||
int __kmp_suspend_count = 0;
|
||||
#endif
|
||||
|
||||
int __kmp_settings = FALSE;
|
||||
int __kmp_duplicate_library_ok = 0;
|
||||
int __kmp_settings = FALSE;
|
||||
int __kmp_duplicate_library_ok = 0;
|
||||
#if USE_ITT_BUILD
|
||||
int __kmp_forkjoin_frames = 1;
|
||||
int __kmp_forkjoin_frames_mode = 3;
|
||||
int __kmp_forkjoin_frames = 1;
|
||||
int __kmp_forkjoin_frames_mode = 3;
|
||||
#endif
|
||||
PACKED_REDUCTION_METHOD_T __kmp_force_reduction_method =
|
||||
reduction_method_not_defined;
|
||||
int __kmp_determ_red = FALSE;
|
||||
PACKED_REDUCTION_METHOD_T __kmp_force_reduction_method = reduction_method_not_defined;
|
||||
int __kmp_determ_red = FALSE;
|
||||
|
||||
#ifdef KMP_DEBUG
|
||||
int kmp_a_debug = 0;
|
||||
int kmp_b_debug = 0;
|
||||
int kmp_c_debug = 0;
|
||||
int kmp_d_debug = 0;
|
||||
int kmp_e_debug = 0;
|
||||
int kmp_f_debug = 0;
|
||||
int kmp_diag = 0;
|
||||
int kmp_a_debug = 0;
|
||||
int kmp_b_debug = 0;
|
||||
int kmp_c_debug = 0;
|
||||
int kmp_d_debug = 0;
|
||||
int kmp_e_debug = 0;
|
||||
int kmp_f_debug = 0;
|
||||
int kmp_diag = 0;
|
||||
#endif
|
||||
|
||||
/* For debug information logging using rotating buffer */
|
||||
int __kmp_debug_buf =
|
||||
FALSE; /* TRUE means use buffer, FALSE means print to stderr */
|
||||
int __kmp_debug_buf_lines =
|
||||
KMP_DEBUG_BUF_LINES_INIT; /* Lines of debug stored in buffer */
|
||||
int __kmp_debug_buf_chars =
|
||||
KMP_DEBUG_BUF_CHARS_INIT; /* Characters allowed per line in buffer */
|
||||
int __kmp_debug_buf_atomic =
|
||||
FALSE; /* TRUE means use atomic update of buffer entry pointer */
|
||||
int __kmp_debug_buf = FALSE; /* TRUE means use buffer, FALSE means print to stderr */
|
||||
int __kmp_debug_buf_lines = KMP_DEBUG_BUF_LINES_INIT; /* Lines of debug stored in buffer */
|
||||
int __kmp_debug_buf_chars = KMP_DEBUG_BUF_CHARS_INIT; /* Characters allowed per line in buffer */
|
||||
int __kmp_debug_buf_atomic = FALSE; /* TRUE means use atomic update of buffer entry pointer */
|
||||
|
||||
char *__kmp_debug_buffer = NULL; /* Debug buffer itself */
|
||||
int __kmp_debug_count =
|
||||
0; /* Counter for number of lines printed in buffer so far */
|
||||
int __kmp_debug_buf_warn_chars =
|
||||
0; /* Keep track of char increase recommended in warnings */
|
||||
char *__kmp_debug_buffer = NULL; /* Debug buffer itself */
|
||||
int __kmp_debug_count = 0; /* Counter for number of lines printed in buffer so far */
|
||||
int __kmp_debug_buf_warn_chars = 0; /* Keep track of char increase recommended in warnings */
|
||||
/* end rotating debug buffer */
|
||||
|
||||
#ifdef KMP_DEBUG
|
||||
int __kmp_par_range; /* +1 => only go par for constructs in range */
|
||||
/* -1 => only go par for constructs outside range */
|
||||
char __kmp_par_range_routine[KMP_PAR_RANGE_ROUTINE_LEN] = {'\0'};
|
||||
char __kmp_par_range_filename[KMP_PAR_RANGE_FILENAME_LEN] = {'\0'};
|
||||
int __kmp_par_range_lb = 0;
|
||||
int __kmp_par_range_ub = INT_MAX;
|
||||
int __kmp_par_range; /* +1 => only go par for constructs in range */
|
||||
/* -1 => only go par for constructs outside range */
|
||||
char __kmp_par_range_routine[KMP_PAR_RANGE_ROUTINE_LEN] = { '\0' };
|
||||
char __kmp_par_range_filename[KMP_PAR_RANGE_FILENAME_LEN] = { '\0' };
|
||||
int __kmp_par_range_lb = 0;
|
||||
int __kmp_par_range_ub = INT_MAX;
|
||||
#endif /* KMP_DEBUG */
|
||||
|
||||
/* For printing out dynamic storage map for threads and teams */
|
||||
int __kmp_storage_map =
|
||||
FALSE; /* True means print storage map for threads and teams */
|
||||
int __kmp_storage_map_verbose =
|
||||
FALSE; /* True means storage map includes placement info */
|
||||
int __kmp_storage_map_verbose_specified = FALSE;
|
||||
/* Initialize the library data structures when we fork a child process, defaults
|
||||
* to TRUE */
|
||||
int __kmp_need_register_atfork =
|
||||
TRUE; /* At initialization, call pthread_atfork to install fork handler */
|
||||
int __kmp_need_register_atfork_specified = TRUE;
|
||||
int __kmp_storage_map = FALSE; /* True means print storage map for threads and teams */
|
||||
int __kmp_storage_map_verbose = FALSE; /* True means storage map includes placement info */
|
||||
int __kmp_storage_map_verbose_specified = FALSE;
|
||||
/* Initialize the library data structures when we fork a child process, defaults to TRUE */
|
||||
int __kmp_need_register_atfork = TRUE; /* At initialization, call pthread_atfork to install fork handler */
|
||||
int __kmp_need_register_atfork_specified = TRUE;
|
||||
|
||||
int __kmp_env_stksize = FALSE; /* KMP_STACKSIZE specified? */
|
||||
int __kmp_env_blocktime = FALSE; /* KMP_BLOCKTIME specified? */
|
||||
int __kmp_env_checks = FALSE; /* KMP_CHECKS specified? */
|
||||
int __kmp_env_consistency_check = FALSE; /* KMP_CONSISTENCY_CHECK specified? */
|
||||
int __kmp_env_chunk = FALSE; /* KMP_CHUNK specified? */
|
||||
int __kmp_env_stksize = FALSE; /* KMP_STACKSIZE specified? */
|
||||
int __kmp_env_omp_stksize = FALSE; /* OMP_STACKSIZE specified? */
|
||||
int __kmp_env_all_threads = FALSE;/* KMP_ALL_THREADS or KMP_MAX_THREADS specified? */
|
||||
int __kmp_env_omp_all_threads = FALSE;/* OMP_THREAD_LIMIT specified? */
|
||||
int __kmp_env_blocktime = FALSE; /* KMP_BLOCKTIME specified? */
|
||||
int __kmp_env_checks = FALSE; /* KMP_CHECKS specified? */
|
||||
int __kmp_env_consistency_check = FALSE; /* KMP_CONSISTENCY_CHECK specified? */
|
||||
|
||||
kmp_uint32 __kmp_yield_init = KMP_INIT_WAIT;
|
||||
kmp_uint32 __kmp_yield_next = KMP_NEXT_WAIT;
|
||||
|
||||
#if KMP_USE_MONITOR
|
||||
kmp_uint32 __kmp_yielding_on = 1;
|
||||
#endif
|
||||
#if KMP_OS_CNK
|
||||
kmp_uint32 __kmp_yield_cycle = 0;
|
||||
#else
|
||||
kmp_uint32 __kmp_yield_cycle = 1; /* Yield-cycle is on by default */
|
||||
kmp_uint32 __kmp_yield_cycle = 1; /* Yield-cycle is on by default */
|
||||
#endif
|
||||
kmp_int32 __kmp_yield_on_count =
|
||||
10; /* By default, yielding is on for 10 monitor periods. */
|
||||
kmp_int32 __kmp_yield_off_count =
|
||||
1; /* By default, yielding is off for 1 monitor periods. */
|
||||
kmp_int32 __kmp_yield_on_count = 10; /* By default, yielding is on for 10 monitor periods. */
|
||||
kmp_int32 __kmp_yield_off_count = 1; /* By default, yielding is off for 1 monitor periods. */
|
||||
#endif
|
||||
/* ----------------------------------------------------- */
|
||||
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
/* STATE mostly syncronized with global lock */
|
||||
/* data written to rarely by masters, read often by workers */
|
||||
/* TODO: None of this global padding stuff works consistently because the order
|
||||
of declaration is not necessarily correlated to storage order. To fix this,
|
||||
all the important globals must be put in a big structure instead. */
|
||||
/*
|
||||
* SHALL WE EDIT THE COMMENT BELOW IN SOME WAY?
|
||||
* TODO: None of this global padding stuff works consistently because
|
||||
* the order of declaration is not necessarily correlated to storage order.
|
||||
* To fix this, all the important globals must be put in a big structure
|
||||
* instead.
|
||||
*/
|
||||
KMP_ALIGN_CACHE
|
||||
kmp_info_t **__kmp_threads = NULL;
|
||||
kmp_root_t **__kmp_root = NULL;
|
||||
kmp_info_t **__kmp_threads = NULL;
|
||||
kmp_root_t **__kmp_root = NULL;
|
||||
|
||||
/* data read/written to often by masters */
|
||||
KMP_ALIGN_CACHE
|
||||
volatile int __kmp_nth = 0;
|
||||
volatile int __kmp_all_nth = 0;
|
||||
int __kmp_thread_pool_nth = 0;
|
||||
volatile kmp_info_t *__kmp_thread_pool = NULL;
|
||||
volatile kmp_team_t *__kmp_team_pool = NULL;
|
||||
volatile int __kmp_nth = 0;
|
||||
volatile int __kmp_all_nth = 0;
|
||||
int __kmp_thread_pool_nth = 0;
|
||||
volatile kmp_info_t *__kmp_thread_pool = NULL;
|
||||
volatile kmp_team_t *__kmp_team_pool = NULL;
|
||||
|
||||
KMP_ALIGN_CACHE
|
||||
volatile int __kmp_thread_pool_active_nth = 0;
|
||||
volatile int __kmp_thread_pool_active_nth = 0;
|
||||
|
||||
/* -------------------------------------------------
|
||||
* GLOBAL/ROOT STATE */
|
||||
KMP_ALIGN_CACHE
|
||||
kmp_global_t __kmp_global = {{0}};
|
||||
kmp_global_t __kmp_global = {{ 0 }};
|
||||
|
||||
/* ----------------------------------------------- */
|
||||
/* GLOBAL SYNCHRONIZATION LOCKS */
|
||||
@@ -418,88 +404,94 @@ kmp_global_t __kmp_global = {{0}};
|
||||
* false sharing if the alignment is not large enough for these locks */
|
||||
KMP_ALIGN_CACHE_INTERNODE
|
||||
|
||||
kmp_bootstrap_lock_t __kmp_initz_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER(
|
||||
__kmp_initz_lock); /* Control initializations */
|
||||
kmp_bootstrap_lock_t __kmp_initz_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER( __kmp_initz_lock ); /* Control initializations */
|
||||
KMP_ALIGN_CACHE_INTERNODE
|
||||
kmp_bootstrap_lock_t __kmp_forkjoin_lock; /* control fork/join access */
|
||||
KMP_ALIGN_CACHE_INTERNODE
|
||||
kmp_bootstrap_lock_t __kmp_exit_lock; /* exit() is not always thread-safe */
|
||||
kmp_bootstrap_lock_t __kmp_exit_lock; /* exit() is not always thread-safe */
|
||||
#if KMP_USE_MONITOR
|
||||
KMP_ALIGN_CACHE_INTERNODE
|
||||
kmp_bootstrap_lock_t __kmp_monitor_lock; /* control monitor thread creation */
|
||||
#endif
|
||||
/* used for the hack to allow threadprivate cache and __kmp_threads expansion
|
||||
to co-exist */
|
||||
KMP_ALIGN_CACHE_INTERNODE
|
||||
kmp_bootstrap_lock_t __kmp_tp_cached_lock;
|
||||
kmp_bootstrap_lock_t __kmp_tp_cached_lock; /* used for the hack to allow threadprivate cache and __kmp_threads expansion to co-exist */
|
||||
|
||||
KMP_ALIGN_CACHE_INTERNODE
|
||||
kmp_lock_t __kmp_global_lock; /* Control OS/global access */
|
||||
kmp_lock_t __kmp_global_lock; /* Control OS/global access */
|
||||
KMP_ALIGN_CACHE_INTERNODE
|
||||
kmp_queuing_lock_t __kmp_dispatch_lock; /* Control dispatch access */
|
||||
kmp_queuing_lock_t __kmp_dispatch_lock; /* Control dispatch access */
|
||||
KMP_ALIGN_CACHE_INTERNODE
|
||||
kmp_lock_t __kmp_debug_lock; /* Control I/O access for KMP_DEBUG */
|
||||
kmp_lock_t __kmp_debug_lock; /* Control I/O access for KMP_DEBUG */
|
||||
#else
|
||||
KMP_ALIGN_CACHE
|
||||
|
||||
kmp_bootstrap_lock_t __kmp_initz_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER(
|
||||
__kmp_initz_lock); /* Control initializations */
|
||||
kmp_bootstrap_lock_t __kmp_initz_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER( __kmp_initz_lock ); /* Control initializations */
|
||||
kmp_bootstrap_lock_t __kmp_forkjoin_lock; /* control fork/join access */
|
||||
kmp_bootstrap_lock_t __kmp_exit_lock; /* exit() is not always thread-safe */
|
||||
kmp_bootstrap_lock_t __kmp_exit_lock; /* exit() is not always thread-safe */
|
||||
#if KMP_USE_MONITOR
|
||||
kmp_bootstrap_lock_t __kmp_monitor_lock; /* control monitor thread creation */
|
||||
#endif
|
||||
/* used for the hack to allow threadprivate cache and __kmp_threads expansion
|
||||
to co-exist */
|
||||
kmp_bootstrap_lock_t __kmp_tp_cached_lock;
|
||||
kmp_bootstrap_lock_t __kmp_tp_cached_lock; /* used for the hack to allow threadprivate cache and __kmp_threads expansion to co-exist */
|
||||
|
||||
KMP_ALIGN(128)
|
||||
kmp_lock_t __kmp_global_lock; /* Control OS/global access */
|
||||
kmp_lock_t __kmp_global_lock; /* Control OS/global access */
|
||||
KMP_ALIGN(128)
|
||||
kmp_queuing_lock_t __kmp_dispatch_lock; /* Control dispatch access */
|
||||
kmp_queuing_lock_t __kmp_dispatch_lock; /* Control dispatch access */
|
||||
KMP_ALIGN(128)
|
||||
kmp_lock_t __kmp_debug_lock; /* Control I/O access for KMP_DEBUG */
|
||||
kmp_lock_t __kmp_debug_lock; /* Control I/O access for KMP_DEBUG */
|
||||
#endif
|
||||
|
||||
/* ----------------------------------------------- */
|
||||
|
||||
#if KMP_HANDLE_SIGNALS
|
||||
/* Signal handling is disabled by default, because it confuses users: In case of
|
||||
sigsegv (or other trouble) in user code signal handler catches the signal,
|
||||
which then "appears" in the monitor thread (when the monitor executes raise()
|
||||
function). Users see signal in the monitor thread and blame OpenMP RTL.
|
||||
/*
|
||||
Signal handling is disabled by default, because it confuses users: In case of sigsegv
|
||||
(or other trouble) in user code signal handler catches the signal, which then "appears" in
|
||||
the monitor thread (when the monitor executes raise() function). Users see signal in the
|
||||
monitor thread and blame OpenMP RTL.
|
||||
|
||||
Grant said signal handling required on some older OSes (Irix?) supported by
|
||||
KAI, because bad applications hung but not aborted. Currently it is not a
|
||||
problem for Linux* OS, OS X* and Windows* OS.
|
||||
Grant said signal handling required on some older OSes (Irix?) supported by KAI, because
|
||||
bad applications hung but not aborted. Currently it is not a problem for Linux* OS, OS X* and
|
||||
Windows* OS.
|
||||
|
||||
Grant: Found new hangs for EL4, EL5, and a Fedora Core machine. So I'm
|
||||
putting the default back for now to see if that fixes hangs on those
|
||||
machines.
|
||||
Grant: Found new hangs for EL4, EL5, and a Fedora Core machine. So I'm putting
|
||||
the default back for now to see if that fixes hangs on those machines.
|
||||
|
||||
2010-04013 Lev: It was a bug in Fortran RTL. Fortran RTL prints a kind of
|
||||
stack backtrace when program is aborting, but the code is not signal-safe.
|
||||
When multiple signals raised at the same time (which occurs in dynamic
|
||||
negative tests because all the worker threads detects the same error),
|
||||
Fortran RTL may hang. The bug finally fixed in Fortran RTL library provided
|
||||
by Steve R., and will be available soon. */
|
||||
int __kmp_handle_signals = FALSE;
|
||||
2010-04013 Lev: It was a bug in Fortran RTL. Fortran RTL prints a kind of stack backtrace
|
||||
when program is aborting, but the code is not signal-safe. When multiple signals raised at
|
||||
the same time (which occurs in dynamic negative tests because all the worker threads detects
|
||||
the same error), Fortran RTL may hang. The bug finally fixed in Fortran RTL library provided
|
||||
by Steve R., and will be available soon.
|
||||
*/
|
||||
int __kmp_handle_signals = FALSE;
|
||||
#endif
|
||||
|
||||
/* ----------------------------------------------- */
|
||||
#ifdef BUILD_TV
|
||||
kmp_key_t __kmp_tv_key = 0;
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#ifdef DEBUG_SUSPEND
|
||||
int get_suspend_count_(void) {
|
||||
int count = __kmp_suspend_count;
|
||||
__kmp_suspend_count = 0;
|
||||
return count;
|
||||
int
|
||||
get_suspend_count_( void ) {
|
||||
int count = __kmp_suspend_count;
|
||||
__kmp_suspend_count = 0;
|
||||
return count;
|
||||
}
|
||||
void
|
||||
set_suspend_count_( int * value ) {
|
||||
__kmp_suspend_count = *value;
|
||||
}
|
||||
void set_suspend_count_(int *value) { __kmp_suspend_count = *value; }
|
||||
#endif
|
||||
|
||||
// Symbols for MS mutual detection.
|
||||
int _You_must_link_with_exactly_one_OpenMP_library = 1;
|
||||
int _You_must_link_with_Intel_OpenMP_library = 1;
|
||||
#if KMP_OS_WINDOWS && (KMP_VERSION_MAJOR > 4)
|
||||
int _You_must_link_with_Microsoft_OpenMP_library = 1;
|
||||
int _You_must_link_with_Intel_OpenMP_library = 1;
|
||||
#if KMP_OS_WINDOWS && ( KMP_VERSION_MAJOR > 4 )
|
||||
int _You_must_link_with_Microsoft_OpenMP_library = 1;
|
||||
#endif
|
||||
|
||||
// end of file //
|
||||
|
||||
+1295
-1202
File diff suppressed because it is too large
Load Diff
+810
-686
File diff suppressed because it is too large
Load Diff
+122
-108
@@ -2,6 +2,7 @@
|
||||
* kmp_i18n.h
|
||||
*/
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@@ -11,167 +12,180 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#ifndef KMP_I18N_H
|
||||
#define KMP_I18N_H
|
||||
|
||||
#include "kmp_str.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
/* kmp_i18n_id.inc defines kmp_i18n_id_t type. It is an enumeration with
|
||||
identifiers of all the messages in the catalog. There is one special
|
||||
identifier: kmp_i18n_null, which denotes absence of message. */
|
||||
/*
|
||||
kmp_i18n_id.inc defines kmp_i18n_id_t type. It is an enumeration with identifiers of all the
|
||||
messages in the catalog. There is one special identifier: kmp_i18n_null, which denotes absence
|
||||
of message.
|
||||
*/
|
||||
#include "kmp_i18n_id.inc" // Generated file. Do not edit it manually.
|
||||
|
||||
/* Low-level functions handling message catalog. __kmp_i18n_open() opens message
|
||||
catalog, __kmp_i18n_closes() it. Explicit opening is not required: if message
|
||||
catalog is not yet open, __kmp_i18n_catgets() will open it implicitly.
|
||||
However, catalog should be explicitly closed, otherwise resources (mamory,
|
||||
handles) may leak.
|
||||
/*
|
||||
Low-level functions handling message catalog. __kmp_i18n_open() opens message catalog,
|
||||
__kmp_i18n_closes() it. Explicit opening is not required: if message catalog is not yet open,
|
||||
__kmp_i18n_catgets() will open it implicitly. However, catalog should be explicitly closed,
|
||||
otherwise resources (mamory, handles) may leak.
|
||||
|
||||
__kmp_i18n_catgets() returns read-only string. It should not be freed.
|
||||
__kmp_i18n_catgets() returns read-only string. It should not be freed.
|
||||
|
||||
KMP_I18N_STR macro simplifies acces to strings in message catalog a bit.
|
||||
Following two lines are equivalent:
|
||||
KMP_I18N_STR macro simplifies acces to strings in message catalog a bit. Following two lines are
|
||||
equivalent:
|
||||
|
||||
__kmp_i18n_catgets( kmp_i18n_str_Warning )
|
||||
KMP_I18N_STR( Warning )
|
||||
__kmp_i18n_catgets( kmp_i18n_str_Warning )
|
||||
KMP_I18N_STR( Warning )
|
||||
*/
|
||||
|
||||
void __kmp_i18n_catopen();
|
||||
void __kmp_i18n_catclose();
|
||||
char const *__kmp_i18n_catgets(kmp_i18n_id_t id);
|
||||
void __kmp_i18n_catopen();
|
||||
void __kmp_i18n_catclose();
|
||||
char const * __kmp_i18n_catgets( kmp_i18n_id_t id );
|
||||
|
||||
#define KMP_I18N_STR(id) __kmp_i18n_catgets(kmp_i18n_str_##id)
|
||||
#define KMP_I18N_STR( id ) __kmp_i18n_catgets( kmp_i18n_str_ ## id )
|
||||
|
||||
/* High-level interface for printing strings targeted to the user.
|
||||
|
||||
All the strings are divided into 3 types:
|
||||
* messages,
|
||||
* hints,
|
||||
* system errors.
|
||||
/*
|
||||
------------------------------------------------------------------------------------------------
|
||||
|
||||
There are 3 kind of message severities:
|
||||
* informational messages,
|
||||
* warnings (non-fatal errors),
|
||||
* fatal errors.
|
||||
High-level interface for printing strings targeted to the user.
|
||||
|
||||
For example:
|
||||
OMP: Warning #2: Cannot open message catalog "libguide.cat": (1)
|
||||
OMP: System error #2: No such file or directory (2)
|
||||
OMP: Hint: Please check NLSPATH environment variable. (3)
|
||||
OMP: Info #3: Default messages will be used. (4)
|
||||
All the strings are divided into 3 types:
|
||||
|
||||
where
|
||||
(1) is a message of warning severity,
|
||||
(2) is a system error caused the previous warning,
|
||||
(3) is a hint for the user how to fix the problem,
|
||||
(4) is a message of informational severity.
|
||||
* messages,
|
||||
* hints,
|
||||
* system errors.
|
||||
|
||||
There are 3 kind of message severities:
|
||||
|
||||
* informational messages,
|
||||
* warnings (non-fatal errors),
|
||||
* fatal errors.
|
||||
|
||||
For example:
|
||||
|
||||
OMP: Warning #2: Cannot open message catalog "libguide.cat": (1)
|
||||
OMP: System error #2: No such file or directory (2)
|
||||
OMP: Hint: Please check NLSPATH environment variable. (3)
|
||||
OMP: Info #3: Default messages will be used. (4)
|
||||
|
||||
where
|
||||
|
||||
(1) is a message of warning severity,
|
||||
(2) is a system error caused the previous warning,
|
||||
(3) is a hint for the user how to fix the problem,
|
||||
(4) is a message of informational severity.
|
||||
|
||||
Usage in complex cases (message is accompanied with hints and system errors):
|
||||
|
||||
int error = errno; // We need save errno immediately, because it may
|
||||
// be changed.
|
||||
__kmp_msg(
|
||||
kmp_ms_warning, // Severity
|
||||
KMP_MSG( CantOpenMessageCatalog, name ), // Primary message
|
||||
KMP_ERR( error ), // System error
|
||||
KMP_HNT( CheckNLSPATH ), // Hint
|
||||
__kmp_msg_null // Variadic argument list finisher
|
||||
);
|
||||
int error = errno; // We need save errno immediately, because it may be changed.
|
||||
__kmp_msg(
|
||||
kmp_ms_warning, // Severity
|
||||
KMP_MSG( CantOpenMessageCatalog, name ), // Primary message
|
||||
KMP_ERR( error ), // System error
|
||||
KMP_HNT( CheckNLSPATH ), // Hint
|
||||
__kmp_msg_null // Variadic argument list finisher
|
||||
);
|
||||
|
||||
Usage in simple cases (just a message, no system errors or hints):
|
||||
KMP_INFORM( WillUseDefaultMessages );
|
||||
KMP_WARNING( CantOpenMessageCatalog, name );
|
||||
KMP_FATAL( StackOverlap );
|
||||
KMP_SYSFAIL( "pthread_create", status );
|
||||
KMP_CHECK_SYSFAIL( "pthread_create", status );
|
||||
KMP_CHECK_SYSFAIL_ERRNO( "gettimeofday", status );
|
||||
Usage in simple cases (just a message, no system errors or hints):
|
||||
|
||||
KMP_INFORM( WillUseDefaultMessages );
|
||||
KMP_WARNING( CantOpenMessageCatalog, name );
|
||||
KMP_FATAL( StackOverlap );
|
||||
KMP_SYSFAIL( "pthread_create", status );
|
||||
KMP_CHECK_SYSFAIL( "pthread_create", status );
|
||||
KMP_CHECK_SYSFAIL_ERRNO( "gettimeofday", status );
|
||||
|
||||
------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
enum kmp_msg_type {
|
||||
kmp_mt_dummy = 0, // Special type for internal purposes.
|
||||
kmp_mt_mesg =
|
||||
4, // Primary OpenMP message, could be information, warning, or fatal.
|
||||
kmp_mt_hint = 5, // Hint to the user.
|
||||
kmp_mt_syserr = -1 // System error message.
|
||||
kmp_mt_dummy = 0, // Special type for internal purposes.
|
||||
kmp_mt_mesg = 4, // Primary OpenMP message, could be information, warning, or fatal.
|
||||
kmp_mt_hint = 5, // Hint to the user.
|
||||
kmp_mt_syserr = -1 // System error message.
|
||||
}; // enum kmp_msg_type
|
||||
typedef enum kmp_msg_type kmp_msg_type_t;
|
||||
typedef enum kmp_msg_type kmp_msg_type_t;
|
||||
|
||||
struct kmp_msg {
|
||||
kmp_msg_type_t type;
|
||||
int num;
|
||||
char *str;
|
||||
int len;
|
||||
kmp_msg_type_t type;
|
||||
int num;
|
||||
char const * str;
|
||||
int len;
|
||||
}; // struct kmp_message
|
||||
typedef struct kmp_msg kmp_msg_t;
|
||||
typedef struct kmp_msg kmp_msg_t;
|
||||
|
||||
// Special message to denote the end of variadic list of arguments.
|
||||
extern kmp_msg_t __kmp_msg_null;
|
||||
// Two special messages.
|
||||
extern kmp_msg_t __kmp_msg_empty; // Can be used in place where message is required syntactically.
|
||||
extern kmp_msg_t __kmp_msg_null; // Denotes the end of variadic list of arguments.
|
||||
|
||||
// Helper functions. Creates messages either from message catalog or from
|
||||
// system. Note: these functions allocate memory. You should pass created
|
||||
// messages to __kmp_msg() function, it will print messages and destroy them.
|
||||
kmp_msg_t __kmp_msg_format(unsigned id_arg, ...);
|
||||
kmp_msg_t __kmp_msg_error_code(int code);
|
||||
kmp_msg_t __kmp_msg_error_mesg(char const *mesg);
|
||||
// Helper functions. Creates messages either from message catalog or from system. Note: these
|
||||
// functions allocate memory. You should pass created messages to __kmp_msg() function, it will
|
||||
// print messages and destroy them.
|
||||
kmp_msg_t __kmp_msg_format( unsigned id_arg, ... );
|
||||
kmp_msg_t __kmp_msg_error_code( int code );
|
||||
kmp_msg_t __kmp_msg_error_mesg( char const * mesg );
|
||||
|
||||
// Helper macros to make calls shorter.
|
||||
#define KMP_MSG(...) __kmp_msg_format(kmp_i18n_msg_##__VA_ARGS__)
|
||||
#define KMP_HNT(...) __kmp_msg_format(kmp_i18n_hnt_##__VA_ARGS__)
|
||||
#define KMP_SYSERRCODE(code) __kmp_msg_error_code(code)
|
||||
#define KMP_SYSERRMESG(mesg) __kmp_msg_error_mesg(mesg)
|
||||
#define KMP_MSG( ... ) __kmp_msg_format( kmp_i18n_msg_ ## __VA_ARGS__ )
|
||||
#define KMP_HNT( ... ) __kmp_msg_format( kmp_i18n_hnt_ ## __VA_ARGS__ )
|
||||
#define KMP_SYSERRCODE( code ) __kmp_msg_error_code( code )
|
||||
#define KMP_SYSERRMESG( mesg ) __kmp_msg_error_mesg( mesg )
|
||||
#define KMP_ERR KMP_SYSERRCODE
|
||||
|
||||
// Message severity.
|
||||
enum kmp_msg_severity {
|
||||
kmp_ms_inform, // Just information for the user.
|
||||
kmp_ms_warning, // Non-fatal error, execution continues.
|
||||
kmp_ms_fatal // Fatal error, program aborts.
|
||||
kmp_ms_inform, // Just information for the user.
|
||||
kmp_ms_warning, // Non-fatal error, execution continues.
|
||||
kmp_ms_fatal // Fatal error, program aborts.
|
||||
}; // enum kmp_msg_severity
|
||||
typedef enum kmp_msg_severity kmp_msg_severity_t;
|
||||
typedef enum kmp_msg_severity kmp_msg_severity_t;
|
||||
|
||||
// Primary function for printing messages for the user. The first message is
|
||||
// mandatory. Any number of system errors and hints may be specified. Argument
|
||||
// list must be finished with __kmp_msg_null.
|
||||
void __kmp_msg(kmp_msg_severity_t severity, kmp_msg_t message, ...);
|
||||
KMP_NORETURN void __kmp_fatal(kmp_msg_t message, ...);
|
||||
// Primary function for printing messages for the user. The first message is mandatory. Any number
|
||||
// of system errors and hints may be specified. Argument list must be finished with __kmp_msg_null.
|
||||
void __kmp_msg( kmp_msg_severity_t severity, kmp_msg_t message, ... );
|
||||
|
||||
// Helper macros to make calls shorter in simple cases.
|
||||
#define KMP_INFORM(...) \
|
||||
__kmp_msg(kmp_ms_inform, KMP_MSG(__VA_ARGS__), __kmp_msg_null)
|
||||
#define KMP_WARNING(...) \
|
||||
__kmp_msg(kmp_ms_warning, KMP_MSG(__VA_ARGS__), __kmp_msg_null)
|
||||
#define KMP_FATAL(...) __kmp_fatal(KMP_MSG(__VA_ARGS__), __kmp_msg_null)
|
||||
#define KMP_SYSFAIL(func, error) \
|
||||
__kmp_fatal(KMP_MSG(FunctionError, func), KMP_SYSERRCODE(error), \
|
||||
__kmp_msg_null)
|
||||
#define KMP_INFORM( ... ) __kmp_msg( kmp_ms_inform, KMP_MSG( __VA_ARGS__ ), __kmp_msg_null )
|
||||
#define KMP_WARNING( ... ) __kmp_msg( kmp_ms_warning, KMP_MSG( __VA_ARGS__ ), __kmp_msg_null )
|
||||
#define KMP_FATAL( ... ) __kmp_msg( kmp_ms_fatal, KMP_MSG( __VA_ARGS__ ), __kmp_msg_null )
|
||||
#define KMP_SYSFAIL( func, error ) \
|
||||
__kmp_msg( \
|
||||
kmp_ms_fatal, \
|
||||
KMP_MSG( FunctionError, func ), \
|
||||
KMP_SYSERRCODE( error ), \
|
||||
__kmp_msg_null \
|
||||
)
|
||||
|
||||
// Check error, if not zero, generate fatal error message.
|
||||
#define KMP_CHECK_SYSFAIL(func, error) \
|
||||
{ \
|
||||
if (error) { \
|
||||
KMP_SYSFAIL(func, error); \
|
||||
} \
|
||||
}
|
||||
#define KMP_CHECK_SYSFAIL( func, error ) \
|
||||
{ \
|
||||
if ( error ) { \
|
||||
KMP_SYSFAIL( func, error ); \
|
||||
}; \
|
||||
}
|
||||
|
||||
// Check status, if not zero, generate fatal error message using errno.
|
||||
#define KMP_CHECK_SYSFAIL_ERRNO(func, status) \
|
||||
{ \
|
||||
if (status != 0) { \
|
||||
int error = errno; \
|
||||
KMP_SYSFAIL(func, error); \
|
||||
} \
|
||||
}
|
||||
#define KMP_CHECK_SYSFAIL_ERRNO( func, status ) \
|
||||
{ \
|
||||
if ( status != 0 ) { \
|
||||
int error = errno; \
|
||||
KMP_SYSFAIL( func, error ); \
|
||||
}; \
|
||||
}
|
||||
|
||||
#ifdef KMP_DEBUG
|
||||
void __kmp_i18n_dump_catalog(kmp_str_buf_t *buffer);
|
||||
void __kmp_i18n_dump_catalog( kmp_str_buf_t * buffer );
|
||||
#endif // KMP_DEBUG
|
||||
|
||||
#ifdef __cplusplus
|
||||
}; // extern "C"
|
||||
}; // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // KMP_I18N_H
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* kmp_import.cpp
|
||||
*/
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@@ -11,20 +12,27 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Object generated from this source file is linked to Windows* OS DLL import
|
||||
library (libompmd.lib) only! It is not a part of regular static or dynamic
|
||||
OpenMP RTL. Any code that just needs to go in the libompmd.lib (but not in
|
||||
libompmt.lib and libompmd.dll) should be placed in this file. */
|
||||
|
||||
/*
|
||||
------------------------------------------------------------------------------------------------
|
||||
Object generated from this source file is linked to Windows* OS DLL import library (libompmd.lib)
|
||||
only! It is not a part of regular static or dynamic OpenMP RTL. Any code that just needs to go
|
||||
in the libompmd.lib (but not in libompmt.lib and libompmd.dll) should be placed in this
|
||||
file.
|
||||
------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*These symbols are required for mutual exclusion with Microsoft OpenMP RTL
|
||||
(and compatibility with MS Compiler). */
|
||||
/*
|
||||
These symbols are required for mutual exclusion with Microsoft OpenMP RTL (and compatibility
|
||||
with MS Compiler).
|
||||
*/
|
||||
|
||||
int _You_must_link_with_exactly_one_OpenMP_library = 1;
|
||||
int _You_must_link_with_Intel_OpenMP_library = 1;
|
||||
int _You_must_link_with_Intel_OpenMP_library = 1;
|
||||
int _You_must_link_with_Microsoft_OpenMP_library = 1;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
+196
-176
@@ -2,6 +2,7 @@
|
||||
* kmp_io.cpp -- RTL IO
|
||||
*/
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@@ -11,218 +12,237 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#ifndef __ABSOFT_WIN
|
||||
#include <sys/types.h>
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "kmp.h" // KMP_GTID_DNE, __kmp_debug_buf, etc
|
||||
#include "kmp_io.h"
|
||||
#include "kmp_lock.h"
|
||||
#include "kmp_os.h"
|
||||
#include "kmp_lock.h"
|
||||
#include "kmp_str.h"
|
||||
#include "kmp_io.h"
|
||||
#include "kmp.h" // KMP_GTID_DNE, __kmp_debug_buf, etc
|
||||
|
||||
#if KMP_OS_WINDOWS
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 271 310)
|
||||
#include <windows.h>
|
||||
#pragma warning(pop)
|
||||
# pragma warning( push )
|
||||
# pragma warning( disable: 271 310 )
|
||||
# include <windows.h>
|
||||
# pragma warning( pop )
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
kmp_bootstrap_lock_t __kmp_stdio_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER(
|
||||
__kmp_stdio_lock); /* Control stdio functions */
|
||||
kmp_bootstrap_lock_t __kmp_console_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER(
|
||||
__kmp_console_lock); /* Control console initialization */
|
||||
kmp_bootstrap_lock_t __kmp_stdio_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER( __kmp_stdio_lock ); /* Control stdio functions */
|
||||
kmp_bootstrap_lock_t __kmp_console_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER( __kmp_console_lock ); /* Control console initialization */
|
||||
|
||||
#if KMP_OS_WINDOWS
|
||||
|
||||
#ifdef KMP_DEBUG
|
||||
/* __kmp_stdout is used only for dev build */
|
||||
static HANDLE __kmp_stdout = NULL;
|
||||
#endif
|
||||
static HANDLE __kmp_stderr = NULL;
|
||||
static int __kmp_console_exists = FALSE;
|
||||
static kmp_str_buf_t __kmp_console_buf;
|
||||
# ifdef KMP_DEBUG
|
||||
/* __kmp_stdout is used only for dev build */
|
||||
static HANDLE __kmp_stdout = NULL;
|
||||
# endif
|
||||
static HANDLE __kmp_stderr = NULL;
|
||||
static int __kmp_console_exists = FALSE;
|
||||
static kmp_str_buf_t __kmp_console_buf;
|
||||
|
||||
static int is_console(void) {
|
||||
char buffer[128];
|
||||
DWORD rc = 0;
|
||||
DWORD err = 0;
|
||||
// Try to get console title.
|
||||
SetLastError(0);
|
||||
// GetConsoleTitle does not reset last error in case of success or short
|
||||
// buffer, so we need to clear it explicitly.
|
||||
rc = GetConsoleTitle(buffer, sizeof(buffer));
|
||||
if (rc == 0) {
|
||||
// rc == 0 means getting console title failed. Let us find out why.
|
||||
err = GetLastError();
|
||||
// err == 0 means buffer too short (we suppose console exists).
|
||||
// In Window applications we usually have err == 6 (invalid handle).
|
||||
}
|
||||
return rc > 0 || err == 0;
|
||||
}
|
||||
|
||||
void __kmp_close_console(void) {
|
||||
/* wait until user presses return before closing window */
|
||||
/* TODO only close if a window was opened */
|
||||
if (__kmp_console_exists) {
|
||||
#ifdef KMP_DEBUG
|
||||
/* standard out is used only in dev build */
|
||||
__kmp_stdout = NULL;
|
||||
#endif
|
||||
__kmp_stderr = NULL;
|
||||
__kmp_str_buf_free(&__kmp_console_buf);
|
||||
__kmp_console_exists = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* For windows, call this before stdout, stderr, or stdin are used.
|
||||
It opens a console window and starts processing */
|
||||
static void __kmp_redirect_output(void) {
|
||||
__kmp_acquire_bootstrap_lock(&__kmp_console_lock);
|
||||
|
||||
if (!__kmp_console_exists) {
|
||||
#ifdef KMP_DEBUG
|
||||
/* standard out is used only in dev build */
|
||||
HANDLE ho;
|
||||
#endif
|
||||
HANDLE he;
|
||||
|
||||
__kmp_str_buf_init(&__kmp_console_buf);
|
||||
|
||||
AllocConsole();
|
||||
// We do not check the result of AllocConsole because
|
||||
// 1. the call is harmless
|
||||
// 2. it is not clear how to communicate failue
|
||||
// 3. we will detect failure later when we get handle(s)
|
||||
|
||||
#ifdef KMP_DEBUG
|
||||
ho = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (ho == INVALID_HANDLE_VALUE || ho == NULL) {
|
||||
|
||||
DWORD err = GetLastError();
|
||||
// TODO: output error somehow (maybe message box)
|
||||
__kmp_stdout = NULL;
|
||||
|
||||
} else {
|
||||
|
||||
__kmp_stdout = ho; // temporary code, need new global for ho
|
||||
static int
|
||||
is_console( void )
|
||||
{
|
||||
char buffer[ 128 ];
|
||||
DWORD rc = 0;
|
||||
DWORD err = 0;
|
||||
// Try to get console title.
|
||||
SetLastError( 0 );
|
||||
// GetConsoleTitle does not reset last error in case of success or short buffer,
|
||||
// so we need to clear it explicitly.
|
||||
rc = GetConsoleTitle( buffer, sizeof( buffer ) );
|
||||
if ( rc == 0 ) {
|
||||
// rc == 0 means getting console title failed. Let us find out why.
|
||||
err = GetLastError();
|
||||
// err == 0 means buffer too short (we suppose console exists).
|
||||
// In Window applications we usually have err == 6 (invalid handle).
|
||||
}; // if
|
||||
return rc > 0 || err == 0;
|
||||
}
|
||||
#endif
|
||||
he = GetStdHandle(STD_ERROR_HANDLE);
|
||||
if (he == INVALID_HANDLE_VALUE || he == NULL) {
|
||||
|
||||
DWORD err = GetLastError();
|
||||
// TODO: output error somehow (maybe message box)
|
||||
__kmp_stderr = NULL;
|
||||
|
||||
} else {
|
||||
|
||||
__kmp_stderr = he; // temporary code, need new global
|
||||
void
|
||||
__kmp_close_console( void )
|
||||
{
|
||||
/* wait until user presses return before closing window */
|
||||
/* TODO only close if a window was opened */
|
||||
if( __kmp_console_exists ) {
|
||||
#ifdef KMP_DEBUG
|
||||
/* standard out is used only in dev build */
|
||||
__kmp_stdout = NULL;
|
||||
#endif
|
||||
__kmp_stderr = NULL;
|
||||
__kmp_str_buf_free( &__kmp_console_buf );
|
||||
__kmp_console_exists = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* For windows, call this before stdout, stderr, or stdin are used.
|
||||
* It opens a console window and starts processing */
|
||||
static void
|
||||
__kmp_redirect_output( void )
|
||||
{
|
||||
__kmp_acquire_bootstrap_lock( &__kmp_console_lock );
|
||||
|
||||
if( ! __kmp_console_exists ) {
|
||||
#ifdef KMP_DEBUG
|
||||
/* standard out is used only in dev build */
|
||||
HANDLE ho;
|
||||
#endif
|
||||
HANDLE he;
|
||||
|
||||
__kmp_str_buf_init( &__kmp_console_buf );
|
||||
|
||||
AllocConsole();
|
||||
// We do not check the result of AllocConsole because
|
||||
// 1. the call is harmless
|
||||
// 2. it is not clear how to communicate failue
|
||||
// 3. we will detect failure later when we get handle(s)
|
||||
|
||||
#ifdef KMP_DEBUG
|
||||
ho = GetStdHandle( STD_OUTPUT_HANDLE );
|
||||
if ( ho == INVALID_HANDLE_VALUE || ho == NULL ) {
|
||||
|
||||
DWORD err = GetLastError();
|
||||
// TODO: output error somehow (maybe message box)
|
||||
__kmp_stdout = NULL;
|
||||
|
||||
} else {
|
||||
|
||||
__kmp_stdout = ho; // temporary code, need new global for ho
|
||||
|
||||
}
|
||||
#endif
|
||||
he = GetStdHandle( STD_ERROR_HANDLE );
|
||||
if ( he == INVALID_HANDLE_VALUE || he == NULL ) {
|
||||
|
||||
DWORD err = GetLastError();
|
||||
// TODO: output error somehow (maybe message box)
|
||||
__kmp_stderr = NULL;
|
||||
|
||||
} else {
|
||||
|
||||
__kmp_stderr = he; // temporary code, need new global
|
||||
}
|
||||
__kmp_console_exists = TRUE;
|
||||
}
|
||||
__kmp_release_bootstrap_lock( &__kmp_console_lock );
|
||||
}
|
||||
__kmp_console_exists = TRUE;
|
||||
}
|
||||
__kmp_release_bootstrap_lock(&__kmp_console_lock);
|
||||
}
|
||||
|
||||
#else
|
||||
#define __kmp_stderr (stderr)
|
||||
#define __kmp_stderr (stderr)
|
||||
#endif /* KMP_OS_WINDOWS */
|
||||
|
||||
void __kmp_vprintf(enum kmp_io __kmp_io, char const *format, va_list ap) {
|
||||
#if KMP_OS_WINDOWS
|
||||
if (!__kmp_console_exists) {
|
||||
__kmp_redirect_output();
|
||||
}
|
||||
if (!__kmp_stderr && __kmp_io == kmp_err) {
|
||||
return;
|
||||
}
|
||||
#ifdef KMP_DEBUG
|
||||
if (!__kmp_stdout && __kmp_io == kmp_out) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#endif /* KMP_OS_WINDOWS */
|
||||
void
|
||||
__kmp_vprintf( enum kmp_io __kmp_io, char const * format, va_list ap )
|
||||
{
|
||||
#if KMP_OS_WINDOWS
|
||||
if( !__kmp_console_exists ) {
|
||||
__kmp_redirect_output();
|
||||
}
|
||||
if( ! __kmp_stderr && __kmp_io == kmp_err ) {
|
||||
return;
|
||||
}
|
||||
#ifdef KMP_DEBUG
|
||||
if( ! __kmp_stdout && __kmp_io == kmp_out ) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#endif /* KMP_OS_WINDOWS */
|
||||
|
||||
if (__kmp_debug_buf && __kmp_debug_buffer != NULL) {
|
||||
if ( __kmp_debug_buf && __kmp_debug_buffer != NULL ) {
|
||||
|
||||
int dc = (__kmp_debug_buf_atomic ? KMP_TEST_THEN_INC32(&__kmp_debug_count)
|
||||
: __kmp_debug_count++) %
|
||||
__kmp_debug_buf_lines;
|
||||
char *db = &__kmp_debug_buffer[dc * __kmp_debug_buf_chars];
|
||||
int chars = 0;
|
||||
int dc = ( __kmp_debug_buf_atomic ?
|
||||
KMP_TEST_THEN_INC32( & __kmp_debug_count) : __kmp_debug_count++ )
|
||||
% __kmp_debug_buf_lines;
|
||||
char *db = & __kmp_debug_buffer[ dc * __kmp_debug_buf_chars ];
|
||||
int chars = 0;
|
||||
|
||||
#ifdef KMP_DEBUG_PIDS
|
||||
chars = KMP_SNPRINTF(db, __kmp_debug_buf_chars, "pid=%d: ",
|
||||
(kmp_int32)getpid());
|
||||
#endif
|
||||
chars += KMP_VSNPRINTF(db, __kmp_debug_buf_chars, format, ap);
|
||||
#ifdef KMP_DEBUG_PIDS
|
||||
chars = KMP_SNPRINTF( db, __kmp_debug_buf_chars, "pid=%d: ", (kmp_int32)getpid() );
|
||||
#endif
|
||||
chars += KMP_VSNPRINTF( db, __kmp_debug_buf_chars, format, ap );
|
||||
|
||||
if (chars + 1 > __kmp_debug_buf_chars) {
|
||||
if (chars + 1 > __kmp_debug_buf_warn_chars) {
|
||||
#if KMP_OS_WINDOWS
|
||||
DWORD count;
|
||||
__kmp_str_buf_print(&__kmp_console_buf, "OMP warning: Debugging buffer "
|
||||
"overflow; increase "
|
||||
"KMP_DEBUG_BUF_CHARS to %d\n",
|
||||
chars + 1);
|
||||
WriteFile(__kmp_stderr, __kmp_console_buf.str, __kmp_console_buf.used,
|
||||
&count, NULL);
|
||||
__kmp_str_buf_clear(&__kmp_console_buf);
|
||||
#else
|
||||
fprintf(__kmp_stderr, "OMP warning: Debugging buffer overflow; "
|
||||
"increase KMP_DEBUG_BUF_CHARS to %d\n",
|
||||
chars + 1);
|
||||
fflush(__kmp_stderr);
|
||||
#endif
|
||||
__kmp_debug_buf_warn_chars = chars + 1;
|
||||
}
|
||||
/* terminate string if overflow occurred */
|
||||
db[__kmp_debug_buf_chars - 2] = '\n';
|
||||
db[__kmp_debug_buf_chars - 1] = '\0';
|
||||
if ( chars + 1 > __kmp_debug_buf_chars ) {
|
||||
if ( chars + 1 > __kmp_debug_buf_warn_chars ) {
|
||||
#if KMP_OS_WINDOWS
|
||||
DWORD count;
|
||||
__kmp_str_buf_print( &__kmp_console_buf,
|
||||
"OMP warning: Debugging buffer overflow; increase KMP_DEBUG_BUF_CHARS to %d\n",
|
||||
chars + 1 );
|
||||
WriteFile( __kmp_stderr, __kmp_console_buf.str, __kmp_console_buf.used, &count, NULL );
|
||||
__kmp_str_buf_clear( &__kmp_console_buf );
|
||||
#else
|
||||
fprintf( __kmp_stderr,
|
||||
"OMP warning: Debugging buffer overflow; increase KMP_DEBUG_BUF_CHARS to %d\n",
|
||||
chars + 1 );
|
||||
fflush( __kmp_stderr );
|
||||
#endif
|
||||
__kmp_debug_buf_warn_chars = chars + 1;
|
||||
}
|
||||
/* terminate string if overflow occurred */
|
||||
db[ __kmp_debug_buf_chars - 2 ] = '\n';
|
||||
db[ __kmp_debug_buf_chars - 1 ] = '\0';
|
||||
}
|
||||
} else {
|
||||
#if KMP_OS_WINDOWS
|
||||
DWORD count;
|
||||
#ifdef KMP_DEBUG_PIDS
|
||||
__kmp_str_buf_print( &__kmp_console_buf, "pid=%d: ",
|
||||
(kmp_int32)getpid() );
|
||||
#endif
|
||||
__kmp_str_buf_vprint( &__kmp_console_buf, format, ap );
|
||||
WriteFile(
|
||||
__kmp_stderr,
|
||||
__kmp_console_buf.str,
|
||||
__kmp_console_buf.used,
|
||||
&count,
|
||||
NULL
|
||||
);
|
||||
__kmp_str_buf_clear( &__kmp_console_buf );
|
||||
#else
|
||||
#ifdef KMP_DEBUG_PIDS
|
||||
fprintf( __kmp_stderr, "pid=%d: ", (kmp_int32)getpid() );
|
||||
#endif
|
||||
vfprintf( __kmp_stderr, format, ap );
|
||||
fflush( __kmp_stderr );
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
#if KMP_OS_WINDOWS
|
||||
DWORD count;
|
||||
#ifdef KMP_DEBUG_PIDS
|
||||
__kmp_str_buf_print(&__kmp_console_buf, "pid=%d: ", (kmp_int32)getpid());
|
||||
#endif
|
||||
__kmp_str_buf_vprint(&__kmp_console_buf, format, ap);
|
||||
WriteFile(__kmp_stderr, __kmp_console_buf.str, __kmp_console_buf.used,
|
||||
&count, NULL);
|
||||
__kmp_str_buf_clear(&__kmp_console_buf);
|
||||
#else
|
||||
#ifdef KMP_DEBUG_PIDS
|
||||
fprintf(__kmp_stderr, "pid=%d: ", (kmp_int32)getpid());
|
||||
#endif
|
||||
vfprintf(__kmp_stderr, format, ap);
|
||||
fflush(__kmp_stderr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void __kmp_printf(char const *format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
void
|
||||
__kmp_printf( char const * format, ... )
|
||||
{
|
||||
va_list ap;
|
||||
va_start( ap, format );
|
||||
|
||||
__kmp_acquire_bootstrap_lock(&__kmp_stdio_lock);
|
||||
__kmp_vprintf(kmp_err, format, ap);
|
||||
__kmp_release_bootstrap_lock(&__kmp_stdio_lock);
|
||||
__kmp_acquire_bootstrap_lock( & __kmp_stdio_lock );
|
||||
__kmp_vprintf( kmp_err, format, ap );
|
||||
__kmp_release_bootstrap_lock( & __kmp_stdio_lock );
|
||||
|
||||
va_end(ap);
|
||||
va_end( ap );
|
||||
}
|
||||
|
||||
void __kmp_printf_no_lock(char const *format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
void
|
||||
__kmp_printf_no_lock( char const * format, ... )
|
||||
{
|
||||
va_list ap;
|
||||
va_start( ap, format );
|
||||
|
||||
__kmp_vprintf(kmp_err, format, ap);
|
||||
__kmp_vprintf( kmp_err, format, ap );
|
||||
|
||||
va_end(ap);
|
||||
va_end( ap );
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
+14
-8
@@ -2,6 +2,7 @@
|
||||
* kmp_io.h -- RTL IO header file.
|
||||
*/
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@@ -11,6 +12,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#ifndef KMP_IO_H
|
||||
#define KMP_IO_H
|
||||
|
||||
@@ -18,21 +20,25 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
enum kmp_io { kmp_out = 0, kmp_err };
|
||||
enum kmp_io {
|
||||
kmp_out = 0,
|
||||
kmp_err
|
||||
};
|
||||
|
||||
extern kmp_bootstrap_lock_t __kmp_stdio_lock; /* Control stdio functions */
|
||||
extern kmp_bootstrap_lock_t
|
||||
__kmp_console_lock; /* Control console initialization */
|
||||
extern kmp_bootstrap_lock_t __kmp_stdio_lock; /* Control stdio functions */
|
||||
extern kmp_bootstrap_lock_t __kmp_console_lock; /* Control console initialization */
|
||||
|
||||
extern void __kmp_vprintf(enum kmp_io __kmp_io, char const *format, va_list ap);
|
||||
extern void __kmp_printf(char const *format, ...);
|
||||
extern void __kmp_printf_no_lock(char const *format, ...);
|
||||
extern void __kmp_close_console(void);
|
||||
extern void __kmp_vprintf( enum kmp_io __kmp_io, char const * format, va_list ap );
|
||||
extern void __kmp_printf( char const * format, ... );
|
||||
extern void __kmp_printf_no_lock( char const * format, ... );
|
||||
extern void __kmp_close_console( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* KMP_IO_H */
|
||||
|
||||
|
||||
+116
-102
@@ -5,6 +5,7 @@
|
||||
* kmp_itt.cpp -- ITT Notify interface.
|
||||
*/
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@@ -14,136 +15,149 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#include "kmp_itt.h"
|
||||
|
||||
#if KMP_DEBUG
|
||||
#include "kmp_itt.inl"
|
||||
#include "kmp_itt.inl"
|
||||
#endif
|
||||
|
||||
|
||||
#if USE_ITT_NOTIFY
|
||||
|
||||
kmp_int32 __kmp_barrier_domain_count;
|
||||
kmp_int32 __kmp_region_domain_count;
|
||||
__itt_domain *__kmp_itt_barrier_domains[KMP_MAX_FRAME_DOMAINS];
|
||||
__itt_domain *__kmp_itt_region_domains[KMP_MAX_FRAME_DOMAINS];
|
||||
__itt_domain *__kmp_itt_imbalance_domains[KMP_MAX_FRAME_DOMAINS];
|
||||
kmp_int32 __kmp_itt_region_team_size[KMP_MAX_FRAME_DOMAINS];
|
||||
__itt_domain *metadata_domain = NULL;
|
||||
__itt_string_handle *string_handle_imbl = NULL;
|
||||
__itt_string_handle *string_handle_loop = NULL;
|
||||
__itt_string_handle *string_handle_sngl = NULL;
|
||||
kmp_int32 __kmp_barrier_domain_count;
|
||||
kmp_int32 __kmp_region_domain_count;
|
||||
__itt_domain* __kmp_itt_barrier_domains[KMP_MAX_FRAME_DOMAINS];
|
||||
__itt_domain* __kmp_itt_region_domains[KMP_MAX_FRAME_DOMAINS];
|
||||
__itt_domain* __kmp_itt_imbalance_domains[KMP_MAX_FRAME_DOMAINS];
|
||||
kmp_int32 __kmp_itt_region_team_size[KMP_MAX_FRAME_DOMAINS];
|
||||
__itt_domain * metadata_domain = NULL;
|
||||
__itt_string_handle * string_handle_imbl = NULL;
|
||||
__itt_string_handle * string_handle_loop = NULL;
|
||||
__itt_string_handle * string_handle_sngl = NULL;
|
||||
|
||||
#include "kmp_i18n.h"
|
||||
#include "kmp_str.h"
|
||||
#include "kmp_version.h"
|
||||
#include "kmp_version.h"
|
||||
#include "kmp_i18n.h"
|
||||
#include "kmp_str.h"
|
||||
|
||||
KMP_BUILD_ASSERT(sizeof(kmp_itt_mark_t) == sizeof(__itt_mark_type));
|
||||
KMP_BUILD_ASSERT( sizeof( kmp_itt_mark_t ) == sizeof( __itt_mark_type ) );
|
||||
|
||||
/* Previously used warnings:
|
||||
/*
|
||||
Previously used warnings:
|
||||
|
||||
KMP_WARNING( IttAllNotifDisabled );
|
||||
KMP_WARNING( IttObjNotifDisabled );
|
||||
KMP_WARNING( IttMarkNotifDisabled );
|
||||
KMP_WARNING( IttUnloadLibFailed, libittnotify );
|
||||
*/
|
||||
KMP_WARNING( IttAllNotifDisabled );
|
||||
KMP_WARNING( IttObjNotifDisabled );
|
||||
KMP_WARNING( IttMarkNotifDisabled );
|
||||
KMP_WARNING( IttUnloadLibFailed, libittnotify );
|
||||
*/
|
||||
|
||||
kmp_int32 __kmp_itt_prepare_delay = 0;
|
||||
kmp_bootstrap_lock_t __kmp_itt_debug_lock =
|
||||
KMP_BOOTSTRAP_LOCK_INITIALIZER(__kmp_itt_debug_lock);
|
||||
|
||||
kmp_int32 __kmp_itt_prepare_delay = 0;
|
||||
kmp_bootstrap_lock_t __kmp_itt_debug_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER( __kmp_itt_debug_lock );
|
||||
|
||||
#endif // USE_ITT_NOTIFY
|
||||
|
||||
void __kmp_itt_initialize() {
|
||||
|
||||
// ITTNotify library is loaded and initialized at first call to any ittnotify
|
||||
// function, so we do not need to explicitly load it any more. Just report OMP
|
||||
// RTL version to ITTNotify.
|
||||
// ITTNotify library is loaded and initialized at first call to any ittnotify function,
|
||||
// so we do not need to explicitly load it any more.
|
||||
// Jusr report OMP RTL version to ITTNotify.
|
||||
|
||||
#if USE_ITT_NOTIFY
|
||||
// Report OpenMP RTL version.
|
||||
kmp_str_buf_t buf;
|
||||
__itt_mark_type version;
|
||||
__kmp_str_buf_init(&buf);
|
||||
__kmp_str_buf_print(&buf, "OMP RTL Version %d.%d.%d", __kmp_version_major,
|
||||
__kmp_version_minor, __kmp_version_build);
|
||||
if (__itt_api_version_ptr != NULL) {
|
||||
__kmp_str_buf_print(&buf, ":%s", __itt_api_version());
|
||||
}
|
||||
version = __itt_mark_create(buf.str);
|
||||
__itt_mark(version, NULL);
|
||||
__kmp_str_buf_free(&buf);
|
||||
#endif
|
||||
#if USE_ITT_NOTIFY
|
||||
// Report OpenMP RTL version.
|
||||
kmp_str_buf_t buf;
|
||||
__itt_mark_type version;
|
||||
__kmp_str_buf_init( & buf );
|
||||
__kmp_str_buf_print(
|
||||
& buf,
|
||||
"OMP RTL Version %d.%d.%d",
|
||||
__kmp_version_major,
|
||||
__kmp_version_minor,
|
||||
__kmp_version_build
|
||||
);
|
||||
if ( __itt_api_version_ptr != NULL ) {
|
||||
__kmp_str_buf_print( & buf, ":%s", __itt_api_version() );
|
||||
}; // if
|
||||
version = __itt_mark_create( buf.str );
|
||||
__itt_mark( version, NULL );
|
||||
__kmp_str_buf_free( & buf );
|
||||
#endif
|
||||
|
||||
} // __kmp_itt_initialize
|
||||
|
||||
|
||||
void __kmp_itt_destroy() {
|
||||
#if USE_ITT_NOTIFY
|
||||
__kmp_itt_fini_ittlib();
|
||||
#endif
|
||||
#if USE_ITT_NOTIFY
|
||||
__kmp_itt_fini_ittlib();
|
||||
#endif
|
||||
} // __kmp_itt_destroy
|
||||
|
||||
extern "C" void __itt_error_handler(__itt_error_code err, va_list args) {
|
||||
|
||||
switch (err) {
|
||||
case __itt_error_no_module: {
|
||||
char const *library = va_arg(args, char const *);
|
||||
extern "C"
|
||||
void
|
||||
__itt_error_handler(
|
||||
__itt_error_code err,
|
||||
va_list args
|
||||
) {
|
||||
|
||||
switch ( err ) {
|
||||
case __itt_error_no_module : {
|
||||
char const * library = va_arg( args, char const * );
|
||||
#if KMP_OS_WINDOWS
|
||||
int sys_err = va_arg(args, int);
|
||||
kmp_msg_t err_code = KMP_SYSERRCODE(sys_err);
|
||||
__kmp_msg(kmp_ms_warning, KMP_MSG(IttLoadLibFailed, library), err_code,
|
||||
__kmp_msg_null);
|
||||
if (__kmp_generate_warnings == kmp_warnings_off) {
|
||||
__kmp_str_free(&err_code.str);
|
||||
}
|
||||
int sys_err = va_arg( args, int );
|
||||
kmp_msg_t err_code = KMP_SYSERRCODE( sys_err );
|
||||
__kmp_msg( kmp_ms_warning, KMP_MSG( IttLoadLibFailed, library ), err_code, __kmp_msg_null );
|
||||
if (__kmp_generate_warnings == kmp_warnings_off) {
|
||||
__kmp_str_free(&err_code.str);
|
||||
}
|
||||
#else
|
||||
char const *sys_err = va_arg(args, char const *);
|
||||
kmp_msg_t err_code = KMP_SYSERRMESG(sys_err);
|
||||
__kmp_msg(kmp_ms_warning, KMP_MSG(IttLoadLibFailed, library), err_code,
|
||||
__kmp_msg_null);
|
||||
if (__kmp_generate_warnings == kmp_warnings_off) {
|
||||
__kmp_str_free(&err_code.str);
|
||||
}
|
||||
char const * sys_err = va_arg( args, char const * );
|
||||
kmp_msg_t err_code = KMP_SYSERRMESG( sys_err );
|
||||
__kmp_msg( kmp_ms_warning, KMP_MSG( IttLoadLibFailed, library ), err_code, __kmp_msg_null );
|
||||
if (__kmp_generate_warnings == kmp_warnings_off) {
|
||||
__kmp_str_free(&err_code.str);
|
||||
}
|
||||
#endif
|
||||
} break;
|
||||
case __itt_error_no_symbol: {
|
||||
char const *library = va_arg(args, char const *);
|
||||
char const *symbol = va_arg(args, char const *);
|
||||
KMP_WARNING(IttLookupFailed, symbol, library);
|
||||
} break;
|
||||
case __itt_error_unknown_group: {
|
||||
char const *var = va_arg(args, char const *);
|
||||
char const *group = va_arg(args, char const *);
|
||||
KMP_WARNING(IttUnknownGroup, var, group);
|
||||
} break;
|
||||
case __itt_error_env_too_long: {
|
||||
char const *var = va_arg(args, char const *);
|
||||
size_t act_len = va_arg(args, size_t);
|
||||
size_t max_len = va_arg(args, size_t);
|
||||
KMP_WARNING(IttEnvVarTooLong, var, (unsigned long)act_len,
|
||||
(unsigned long)max_len);
|
||||
} break;
|
||||
case __itt_error_cant_read_env: {
|
||||
char const *var = va_arg(args, char const *);
|
||||
int sys_err = va_arg(args, int);
|
||||
kmp_msg_t err_code = KMP_ERR(sys_err);
|
||||
__kmp_msg(kmp_ms_warning, KMP_MSG(CantGetEnvVar, var), err_code,
|
||||
__kmp_msg_null);
|
||||
if (__kmp_generate_warnings == kmp_warnings_off) {
|
||||
__kmp_str_free(&err_code.str);
|
||||
}
|
||||
} break;
|
||||
case __itt_error_system: {
|
||||
char const *func = va_arg(args, char const *);
|
||||
int sys_err = va_arg(args, int);
|
||||
kmp_msg_t err_code = KMP_SYSERRCODE(sys_err);
|
||||
__kmp_msg(kmp_ms_warning, KMP_MSG(IttFunctionError, func), err_code,
|
||||
__kmp_msg_null);
|
||||
if (__kmp_generate_warnings == kmp_warnings_off) {
|
||||
__kmp_str_free(&err_code.str);
|
||||
}
|
||||
} break;
|
||||
default: { KMP_WARNING(IttUnknownError, err); }
|
||||
}
|
||||
} break;
|
||||
case __itt_error_no_symbol : {
|
||||
char const * library = va_arg( args, char const * );
|
||||
char const * symbol = va_arg( args, char const * );
|
||||
KMP_WARNING( IttLookupFailed, symbol, library );
|
||||
} break;
|
||||
case __itt_error_unknown_group : {
|
||||
char const * var = va_arg( args, char const * );
|
||||
char const * group = va_arg( args, char const * );
|
||||
KMP_WARNING( IttUnknownGroup, var, group );
|
||||
} break;
|
||||
case __itt_error_env_too_long : {
|
||||
char const * var = va_arg( args, char const * );
|
||||
size_t act_len = va_arg( args, size_t );
|
||||
size_t max_len = va_arg( args, size_t );
|
||||
KMP_WARNING( IttEnvVarTooLong, var, (unsigned long) act_len, (unsigned long) max_len );
|
||||
} break;
|
||||
case __itt_error_cant_read_env : {
|
||||
char const * var = va_arg( args, char const * );
|
||||
int sys_err = va_arg( args, int );
|
||||
kmp_msg_t err_code = KMP_ERR( sys_err );
|
||||
__kmp_msg( kmp_ms_warning, KMP_MSG( CantGetEnvVar, var ), err_code, __kmp_msg_null );
|
||||
if (__kmp_generate_warnings == kmp_warnings_off) {
|
||||
__kmp_str_free(&err_code.str);
|
||||
}
|
||||
} break;
|
||||
case __itt_error_system : {
|
||||
char const * func = va_arg( args, char const * );
|
||||
int sys_err = va_arg( args, int );
|
||||
kmp_msg_t err_code = KMP_SYSERRCODE( sys_err );
|
||||
__kmp_msg( kmp_ms_warning, KMP_MSG( IttFunctionError, func ), err_code, __kmp_msg_null );
|
||||
if (__kmp_generate_warnings == kmp_warnings_off) {
|
||||
__kmp_str_free(&err_code.str);
|
||||
}
|
||||
} break;
|
||||
default : {
|
||||
KMP_WARNING( IttUnknownError, err );
|
||||
};
|
||||
}; // switch
|
||||
|
||||
} // __itt_error_handler
|
||||
|
||||
#endif /* USE_ITT_BUILD */
|
||||
|
||||
+196
-216
@@ -3,6 +3,7 @@
|
||||
* kmp_itt.h -- ITT Notify interface.
|
||||
*/
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@@ -12,6 +13,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#ifndef KMP_ITT_H
|
||||
#define KMP_ITT_H
|
||||
|
||||
@@ -22,121 +24,104 @@
|
||||
#include "legacy/ittnotify.h"
|
||||
|
||||
#if KMP_DEBUG
|
||||
#define __kmp_inline // Turn off inlining in debug mode.
|
||||
#define __kmp_inline // Turn off inlining in debug mode.
|
||||
#else
|
||||
#define __kmp_inline static inline
|
||||
#define __kmp_inline static inline
|
||||
#endif
|
||||
|
||||
#if USE_ITT_NOTIFY
|
||||
extern kmp_int32 __kmp_itt_prepare_delay;
|
||||
#ifdef __cplusplus
|
||||
extern "C" void __kmp_itt_fini_ittlib(void);
|
||||
#else
|
||||
extern void __kmp_itt_fini_ittlib(void);
|
||||
#endif
|
||||
extern kmp_int32 __kmp_itt_prepare_delay;
|
||||
# ifdef __cplusplus
|
||||
extern "C" void __kmp_itt_fini_ittlib(void);
|
||||
# else
|
||||
extern void __kmp_itt_fini_ittlib(void);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Simplify the handling of an argument that is only required when USE_ITT_BUILD
|
||||
// is enabled.
|
||||
#define USE_ITT_BUILD_ARG(x) , x
|
||||
// Simplify the handling of an argument that is only required when USE_ITT_BUILD is enabled.
|
||||
#define USE_ITT_BUILD_ARG(x) ,x
|
||||
|
||||
void __kmp_itt_initialize();
|
||||
void __kmp_itt_destroy();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
// New stuff for reporting high-level constructs.
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
// Note the naming convention:
|
||||
// __kmp_itt_xxxing() function should be called before action, while
|
||||
// __kmp_itt_xxxed() function should be called after action.
|
||||
|
||||
// --- Parallel region reporting ---
|
||||
__kmp_inline void
|
||||
__kmp_itt_region_forking(int gtid, int team_size,
|
||||
int barriers); // Master only, before forking threads.
|
||||
__kmp_inline void
|
||||
__kmp_itt_region_joined(int gtid); // Master only, after joining threads.
|
||||
// (*) Note: A thread may execute tasks after this point, though.
|
||||
__kmp_inline void __kmp_itt_region_forking( int gtid, int team_size, int barriers ); // Master only, before forking threads.
|
||||
__kmp_inline void __kmp_itt_region_joined( int gtid ); // Master only, after joining threads.
|
||||
// (*) Note: A thread may execute tasks after this point, though.
|
||||
|
||||
// --- Frame reporting ---
|
||||
// region=0: no regions, region=1: parallel, region=2: serialized parallel
|
||||
__kmp_inline void __kmp_itt_frame_submit(int gtid, __itt_timestamp begin,
|
||||
__itt_timestamp end, int imbalance,
|
||||
ident_t *loc, int team_size,
|
||||
int region = 0);
|
||||
// region = 0 - no regions, region = 1 - parallel, region = 2 - serialized parallel
|
||||
__kmp_inline void __kmp_itt_frame_submit( int gtid, __itt_timestamp begin, __itt_timestamp end, int imbalance, ident_t *loc, int team_size, int region = 0 );
|
||||
|
||||
// --- Metadata reporting ---
|
||||
// begin/end - begin/end timestamps of a barrier frame, imbalance - aggregated
|
||||
// wait time value, reduction -if this is a reduction barrier
|
||||
__kmp_inline void __kmp_itt_metadata_imbalance(int gtid, kmp_uint64 begin,
|
||||
kmp_uint64 end,
|
||||
kmp_uint64 imbalance,
|
||||
kmp_uint64 reduction);
|
||||
// sched_type: 0 - static, 1 - dynamic, 2 - guided, 3 - custom (all others);
|
||||
// iterations - loop trip count, chunk - chunk size
|
||||
__kmp_inline void __kmp_itt_metadata_loop(ident_t *loc, kmp_uint64 sched_type,
|
||||
kmp_uint64 iterations,
|
||||
kmp_uint64 chunk);
|
||||
__kmp_inline void __kmp_itt_metadata_single(ident_t *loc);
|
||||
// begin/end - begin/end timestamps of a barrier frame, imbalance - aggregated wait time value, reduction -if this is a reduction barrier
|
||||
__kmp_inline void __kmp_itt_metadata_imbalance( int gtid, kmp_uint64 begin, kmp_uint64 end, kmp_uint64 imbalance, kmp_uint64 reduction );
|
||||
// sched_type: 0 - static, 1 - dynamic, 2 - guided, 3 - custom (all others); iterations - loop trip count, chunk - chunk size
|
||||
__kmp_inline void __kmp_itt_metadata_loop( ident_t * loc, kmp_uint64 sched_type, kmp_uint64 iterations, kmp_uint64 chunk );
|
||||
__kmp_inline void __kmp_itt_metadata_single( ident_t * loc );
|
||||
|
||||
// --- Barrier reporting ---
|
||||
__kmp_inline void *__kmp_itt_barrier_object(int gtid, int bt, int set_name = 0,
|
||||
int delta = 0);
|
||||
__kmp_inline void __kmp_itt_barrier_starting(int gtid, void *object);
|
||||
__kmp_inline void __kmp_itt_barrier_middle(int gtid, void *object);
|
||||
__kmp_inline void __kmp_itt_barrier_finished(int gtid, void *object);
|
||||
__kmp_inline void * __kmp_itt_barrier_object( int gtid, int bt, int set_name = 0, int delta = 0 );
|
||||
__kmp_inline void __kmp_itt_barrier_starting( int gtid, void * object );
|
||||
__kmp_inline void __kmp_itt_barrier_middle( int gtid, void * object );
|
||||
__kmp_inline void __kmp_itt_barrier_finished( int gtid, void * object );
|
||||
|
||||
// --- Taskwait reporting ---
|
||||
__kmp_inline void *__kmp_itt_taskwait_object(int gtid);
|
||||
__kmp_inline void __kmp_itt_taskwait_starting(int gtid, void *object);
|
||||
__kmp_inline void __kmp_itt_taskwait_finished(int gtid, void *object);
|
||||
__kmp_inline void * __kmp_itt_taskwait_object( int gtid );
|
||||
__kmp_inline void __kmp_itt_taskwait_starting( int gtid, void * object );
|
||||
__kmp_inline void __kmp_itt_taskwait_finished( int gtid, void * object );
|
||||
|
||||
// --- Task reporting ---
|
||||
__kmp_inline void __kmp_itt_task_starting(void *object);
|
||||
__kmp_inline void __kmp_itt_task_finished(void *object);
|
||||
__kmp_inline void __kmp_itt_task_starting( void * object );
|
||||
__kmp_inline void __kmp_itt_task_finished( void * object );
|
||||
|
||||
// --- Lock reporting ---
|
||||
#if KMP_USE_DYNAMIC_LOCK
|
||||
__kmp_inline void __kmp_itt_lock_creating(kmp_user_lock_p lock,
|
||||
const ident_t *);
|
||||
__kmp_inline void __kmp_itt_lock_creating( kmp_user_lock_p lock, const ident_t * );
|
||||
#else
|
||||
__kmp_inline void __kmp_itt_lock_creating(kmp_user_lock_p lock);
|
||||
__kmp_inline void __kmp_itt_lock_creating( kmp_user_lock_p lock );
|
||||
#endif
|
||||
__kmp_inline void __kmp_itt_lock_acquiring(kmp_user_lock_p lock);
|
||||
__kmp_inline void __kmp_itt_lock_acquired(kmp_user_lock_p lock);
|
||||
__kmp_inline void __kmp_itt_lock_releasing(kmp_user_lock_p lock);
|
||||
__kmp_inline void __kmp_itt_lock_cancelled(kmp_user_lock_p lock);
|
||||
__kmp_inline void __kmp_itt_lock_destroyed(kmp_user_lock_p lock);
|
||||
__kmp_inline void __kmp_itt_lock_acquiring( kmp_user_lock_p lock );
|
||||
__kmp_inline void __kmp_itt_lock_acquired( kmp_user_lock_p lock );
|
||||
__kmp_inline void __kmp_itt_lock_releasing( kmp_user_lock_p lock );
|
||||
__kmp_inline void __kmp_itt_lock_cancelled( kmp_user_lock_p lock );
|
||||
__kmp_inline void __kmp_itt_lock_destroyed( kmp_user_lock_p lock );
|
||||
|
||||
// --- Critical reporting ---
|
||||
#if KMP_USE_DYNAMIC_LOCK
|
||||
__kmp_inline void __kmp_itt_critical_creating(kmp_user_lock_p lock,
|
||||
const ident_t *);
|
||||
__kmp_inline void __kmp_itt_critical_creating( kmp_user_lock_p lock, const ident_t * );
|
||||
#else
|
||||
__kmp_inline void __kmp_itt_critical_creating(kmp_user_lock_p lock);
|
||||
__kmp_inline void __kmp_itt_critical_creating( kmp_user_lock_p lock );
|
||||
#endif
|
||||
__kmp_inline void __kmp_itt_critical_acquiring(kmp_user_lock_p lock);
|
||||
__kmp_inline void __kmp_itt_critical_acquired(kmp_user_lock_p lock);
|
||||
__kmp_inline void __kmp_itt_critical_releasing(kmp_user_lock_p lock);
|
||||
__kmp_inline void __kmp_itt_critical_destroyed(kmp_user_lock_p lock);
|
||||
__kmp_inline void __kmp_itt_critical_acquiring( kmp_user_lock_p lock );
|
||||
__kmp_inline void __kmp_itt_critical_acquired( kmp_user_lock_p lock );
|
||||
__kmp_inline void __kmp_itt_critical_releasing( kmp_user_lock_p lock );
|
||||
__kmp_inline void __kmp_itt_critical_destroyed( kmp_user_lock_p lock );
|
||||
|
||||
// --- Single reporting ---
|
||||
__kmp_inline void __kmp_itt_single_start(int gtid);
|
||||
__kmp_inline void __kmp_itt_single_end(int gtid);
|
||||
__kmp_inline void __kmp_itt_single_start( int gtid );
|
||||
__kmp_inline void __kmp_itt_single_end( int gtid );
|
||||
|
||||
// --- Ordered reporting ---
|
||||
__kmp_inline void __kmp_itt_ordered_init(int gtid);
|
||||
__kmp_inline void __kmp_itt_ordered_prep(int gtid);
|
||||
__kmp_inline void __kmp_itt_ordered_start(int gtid);
|
||||
__kmp_inline void __kmp_itt_ordered_end(int gtid);
|
||||
__kmp_inline void __kmp_itt_ordered_init( int gtid );
|
||||
__kmp_inline void __kmp_itt_ordered_prep( int gtid );
|
||||
__kmp_inline void __kmp_itt_ordered_start( int gtid );
|
||||
__kmp_inline void __kmp_itt_ordered_end( int gtid );
|
||||
|
||||
// --- Threads reporting ---
|
||||
__kmp_inline void __kmp_itt_thread_ignore();
|
||||
__kmp_inline void __kmp_itt_thread_name(int gtid);
|
||||
__kmp_inline void __kmp_itt_thread_ignore();
|
||||
__kmp_inline void __kmp_itt_thread_name( int gtid );
|
||||
|
||||
// --- System objects ---
|
||||
__kmp_inline void __kmp_itt_system_object_created(void *object,
|
||||
char const *name);
|
||||
__kmp_inline void __kmp_itt_system_object_created( void * object, char const * name );
|
||||
|
||||
// --- Stack stitching ---
|
||||
__kmp_inline __itt_caller __kmp_itt_stack_caller_create(void);
|
||||
@@ -144,189 +129,184 @@ __kmp_inline void __kmp_itt_stack_caller_destroy(__itt_caller);
|
||||
__kmp_inline void __kmp_itt_stack_callee_enter(__itt_caller);
|
||||
__kmp_inline void __kmp_itt_stack_callee_leave(__itt_caller);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
// Old stuff for reporting low-level internal synchronization.
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
#if USE_ITT_NOTIFY
|
||||
|
||||
/* Support for SSC marks, which are used by SDE
|
||||
http://software.intel.com/en-us/articles/intel-software-development-emulator
|
||||
to mark points in instruction traces that represent spin-loops and are
|
||||
therefore uninteresting when collecting traces for architecture simulation.
|
||||
*/
|
||||
#ifndef INCLUDE_SSC_MARKS
|
||||
#define INCLUDE_SSC_MARKS (KMP_OS_LINUX && KMP_ARCH_X86_64)
|
||||
#endif
|
||||
/*
|
||||
* Support for SSC marks, which are used by SDE
|
||||
* http://software.intel.com/en-us/articles/intel-software-development-emulator
|
||||
* to mark points in instruction traces that represent spin-loops and are
|
||||
* therefore uninteresting when collecting traces for architecture simulation.
|
||||
*/
|
||||
#ifndef INCLUDE_SSC_MARKS
|
||||
# define INCLUDE_SSC_MARKS (KMP_OS_LINUX && KMP_ARCH_X86_64)
|
||||
#endif
|
||||
|
||||
/* Linux 64 only for now */
|
||||
#if (INCLUDE_SSC_MARKS && KMP_OS_LINUX && KMP_ARCH_X86_64)
|
||||
// Portable (at least for gcc and icc) code to insert the necessary instructions
|
||||
// to set %ebx and execute the unlikely no-op.
|
||||
#if defined(__INTEL_COMPILER)
|
||||
#define INSERT_SSC_MARK(tag) __SSC_MARK(tag)
|
||||
#else
|
||||
#define INSERT_SSC_MARK(tag) \
|
||||
__asm__ __volatile__("movl %0, %%ebx; .byte 0x64, 0x67, 0x90 " ::"i"(tag) \
|
||||
: "%ebx")
|
||||
#endif
|
||||
#else
|
||||
#define INSERT_SSC_MARK(tag) ((void)0)
|
||||
#endif
|
||||
/* Linux 64 only for now */
|
||||
#if (INCLUDE_SSC_MARKS && KMP_OS_LINUX && KMP_ARCH_X86_64)
|
||||
// Portable (at least for gcc and icc) code to insert the necessary instructions
|
||||
// to set %ebx and execute the unlikely no-op.
|
||||
#if defined( __INTEL_COMPILER )
|
||||
# define INSERT_SSC_MARK(tag) __SSC_MARK(tag)
|
||||
#else
|
||||
# define INSERT_SSC_MARK(tag) \
|
||||
__asm__ __volatile__ ("movl %0, %%ebx; .byte 0x64, 0x67, 0x90 " ::"i"(tag):"%ebx")
|
||||
#endif
|
||||
#else
|
||||
# define INSERT_SSC_MARK(tag) ((void)0)
|
||||
#endif
|
||||
|
||||
/* Markers for the start and end of regions that represent polling and are
|
||||
therefore uninteresting to architectural simulations 0x4376 and 0x4377 are
|
||||
arbitrary numbers that should be unique in the space of SSC tags, but there
|
||||
is no central issuing authority rather randomness is expected to work. */
|
||||
#define SSC_MARK_SPIN_START() INSERT_SSC_MARK(0x4376)
|
||||
#define SSC_MARK_SPIN_END() INSERT_SSC_MARK(0x4377)
|
||||
/* Markers for the start and end of regions that represent polling and
|
||||
* are therefore uninteresting to architectural simulations 0x4376 and
|
||||
* 0x4377 are arbitrary numbers that should be unique in the space of
|
||||
* SSC tags, but there is no central issuing authority rather
|
||||
* randomness is expected to work.
|
||||
*/
|
||||
#define SSC_MARK_SPIN_START() INSERT_SSC_MARK(0x4376)
|
||||
#define SSC_MARK_SPIN_END() INSERT_SSC_MARK(0x4377)
|
||||
|
||||
// Markers for architecture simulation.
|
||||
// FORKING : Before the master thread forks.
|
||||
// JOINING : At the start of the join.
|
||||
// INVOKING : Before the threads invoke microtasks.
|
||||
// DISPATCH_INIT: At the start of dynamically scheduled loop.
|
||||
// DISPATCH_NEXT: After claming next iteration of dynamically scheduled loop.
|
||||
#define SSC_MARK_FORKING() INSERT_SSC_MARK(0xd693)
|
||||
#define SSC_MARK_JOINING() INSERT_SSC_MARK(0xd694)
|
||||
#define SSC_MARK_INVOKING() INSERT_SSC_MARK(0xd695)
|
||||
#define SSC_MARK_DISPATCH_INIT() INSERT_SSC_MARK(0xd696)
|
||||
#define SSC_MARK_DISPATCH_NEXT() INSERT_SSC_MARK(0xd697)
|
||||
// Markers for architecture simulation.
|
||||
// FORKING : Before the master thread forks.
|
||||
// JOINING : At the start of the join.
|
||||
// INVOKING : Before the threads invoke microtasks.
|
||||
// DISPATCH_INIT: At the start of dynamically scheduled loop.
|
||||
// DISPATCH_NEXT: After claming next iteration of dynamically scheduled loop.
|
||||
#define SSC_MARK_FORKING() INSERT_SSC_MARK(0xd693)
|
||||
#define SSC_MARK_JOINING() INSERT_SSC_MARK(0xd694)
|
||||
#define SSC_MARK_INVOKING() INSERT_SSC_MARK(0xd695)
|
||||
#define SSC_MARK_DISPATCH_INIT() INSERT_SSC_MARK(0xd696)
|
||||
#define SSC_MARK_DISPATCH_NEXT() INSERT_SSC_MARK(0xd697)
|
||||
|
||||
// The object is an address that associates a specific set of the prepare,
|
||||
// acquire, release, and cancel operations.
|
||||
// The object is an address that associates a specific set of the prepare, acquire, release,
|
||||
// and cancel operations.
|
||||
|
||||
/* Sync prepare indicates a thread is going to start waiting for another thread
|
||||
to send a release event. This operation should be done just before the
|
||||
thread begins checking for the existence of the release event */
|
||||
/* Sync prepare indicates a thread is going to start waiting for another thread
|
||||
to send a release event. This operation should be done just before the thread
|
||||
begins checking for the existence of the release event */
|
||||
|
||||
/* Sync cancel indicates a thread is cancelling a wait on another thread and
|
||||
continuing execution without waiting for the other thread to release it */
|
||||
/* Sync cancel indicates a thread is cancelling a wait on another thread anc
|
||||
continuing execution without waiting for the other thread to release it */
|
||||
|
||||
/* Sync acquired indicates a thread has received a release event from another
|
||||
thread and has stopped waiting. This operation must occur only after the
|
||||
release event is received. */
|
||||
/* Sync acquired indicates a thread has received a release event from another
|
||||
thread and has stopped waiting. This operation must occur only after the release
|
||||
event is received. */
|
||||
|
||||
/* Sync release indicates a thread is going to send a release event to another
|
||||
thread so it will stop waiting and continue execution. This operation must
|
||||
just happen before the release event. */
|
||||
/* Sync release indicates a thread is going to send a release event to another thread
|
||||
so it will stop waiting and continue execution. This operation must just happen before
|
||||
the release event. */
|
||||
|
||||
#define KMP_FSYNC_PREPARE(obj) __itt_fsync_prepare((void *)(obj))
|
||||
#define KMP_FSYNC_CANCEL(obj) __itt_fsync_cancel((void *)(obj))
|
||||
#define KMP_FSYNC_ACQUIRED(obj) __itt_fsync_acquired((void *)(obj))
|
||||
#define KMP_FSYNC_RELEASING(obj) __itt_fsync_releasing((void *)(obj))
|
||||
#define KMP_FSYNC_PREPARE( obj ) __itt_fsync_prepare( (void *)( obj ) )
|
||||
#define KMP_FSYNC_CANCEL( obj ) __itt_fsync_cancel( (void *)( obj ) )
|
||||
#define KMP_FSYNC_ACQUIRED( obj ) __itt_fsync_acquired( (void *)( obj ) )
|
||||
#define KMP_FSYNC_RELEASING( obj ) __itt_fsync_releasing( (void *)( obj ) )
|
||||
|
||||
/* In case of waiting in a spin loop, ITT wants KMP_FSYNC_PREPARE() to be called
|
||||
with a delay (and not called at all if waiting time is small). So, in spin
|
||||
loops, do not use KMP_FSYNC_PREPARE(), but use KMP_FSYNC_SPIN_INIT() (before
|
||||
spin loop), KMP_FSYNC_SPIN_PREPARE() (whithin the spin loop), and
|
||||
KMP_FSYNC_SPIN_ACQUIRED(). See KMP_WAIT_YIELD() for example. */
|
||||
/*
|
||||
In case of waiting in a spin loop, ITT wants KMP_FSYNC_PREPARE() to be called with a delay
|
||||
(and not called at all if waiting time is small). So, in spin loops, do not use
|
||||
KMP_FSYNC_PREPARE(), but use KMP_FSYNC_SPIN_INIT() (before spin loop),
|
||||
KMP_FSYNC_SPIN_PREPARE() (whithin the spin loop), and KMP_FSYNC_SPIN_ACQUIRED().
|
||||
See KMP_WAIT_YIELD() for example.
|
||||
*/
|
||||
|
||||
#undef KMP_FSYNC_SPIN_INIT
|
||||
#define KMP_FSYNC_SPIN_INIT(obj, spin) \
|
||||
int sync_iters = 0; \
|
||||
if (__itt_fsync_prepare_ptr) { \
|
||||
if (obj == NULL) { \
|
||||
obj = spin; \
|
||||
} /* if */ \
|
||||
} /* if */ \
|
||||
SSC_MARK_SPIN_START()
|
||||
#undef KMP_FSYNC_SPIN_INIT
|
||||
#define KMP_FSYNC_SPIN_INIT( obj, spin ) \
|
||||
int sync_iters = 0; \
|
||||
if ( __itt_fsync_prepare_ptr ) { \
|
||||
if ( obj == NULL ) { \
|
||||
obj = spin; \
|
||||
} /* if */ \
|
||||
} /* if */ \
|
||||
SSC_MARK_SPIN_START()
|
||||
|
||||
#undef KMP_FSYNC_SPIN_PREPARE
|
||||
#define KMP_FSYNC_SPIN_PREPARE(obj) \
|
||||
do { \
|
||||
if (__itt_fsync_prepare_ptr && sync_iters < __kmp_itt_prepare_delay) { \
|
||||
++sync_iters; \
|
||||
if (sync_iters >= __kmp_itt_prepare_delay) { \
|
||||
KMP_FSYNC_PREPARE((void *)obj); \
|
||||
} /* if */ \
|
||||
} /* if */ \
|
||||
} while (0)
|
||||
#undef KMP_FSYNC_SPIN_ACQUIRED
|
||||
#define KMP_FSYNC_SPIN_ACQUIRED(obj) \
|
||||
do { \
|
||||
SSC_MARK_SPIN_END(); \
|
||||
if (sync_iters >= __kmp_itt_prepare_delay) { \
|
||||
KMP_FSYNC_ACQUIRED((void *)obj); \
|
||||
} /* if */ \
|
||||
} while (0)
|
||||
#undef KMP_FSYNC_SPIN_PREPARE
|
||||
#define KMP_FSYNC_SPIN_PREPARE( obj ) do { \
|
||||
if ( __itt_fsync_prepare_ptr && sync_iters < __kmp_itt_prepare_delay ) { \
|
||||
++ sync_iters; \
|
||||
if ( sync_iters >= __kmp_itt_prepare_delay ) { \
|
||||
KMP_FSYNC_PREPARE( (void*) obj ); \
|
||||
} /* if */ \
|
||||
} /* if */ \
|
||||
} while (0)
|
||||
#undef KMP_FSYNC_SPIN_ACQUIRED
|
||||
#define KMP_FSYNC_SPIN_ACQUIRED( obj ) do { \
|
||||
SSC_MARK_SPIN_END(); \
|
||||
if ( sync_iters >= __kmp_itt_prepare_delay ) { \
|
||||
KMP_FSYNC_ACQUIRED( (void*) obj ); \
|
||||
} /* if */ \
|
||||
} while (0)
|
||||
|
||||
/* ITT will not report objects created within KMP_ITT_IGNORE(), e. g.:
|
||||
KMP_ITT_IGNORE(
|
||||
ptr = malloc( size );
|
||||
);
|
||||
*/
|
||||
#define KMP_ITT_IGNORE(statement) \
|
||||
do { \
|
||||
__itt_state_t __itt_state_; \
|
||||
if (__itt_state_get_ptr) { \
|
||||
__itt_state_ = __itt_state_get(); \
|
||||
__itt_obj_mode_set(__itt_obj_prop_ignore, __itt_obj_state_set); \
|
||||
} /* if */ \
|
||||
{ statement } \
|
||||
if (__itt_state_get_ptr) { \
|
||||
__itt_state_set(__itt_state_); \
|
||||
} /* if */ \
|
||||
} while (0)
|
||||
/* ITT will not report objects created within KMP_ITT_IGNORE(), e. g.:
|
||||
KMP_ITT_IGNORE(
|
||||
ptr = malloc( size );
|
||||
);
|
||||
*/
|
||||
#define KMP_ITT_IGNORE( statement ) do { \
|
||||
__itt_state_t __itt_state_; \
|
||||
if ( __itt_state_get_ptr ) { \
|
||||
__itt_state_ = __itt_state_get(); \
|
||||
__itt_obj_mode_set( __itt_obj_prop_ignore, __itt_obj_state_set ); \
|
||||
} /* if */ \
|
||||
{ statement } \
|
||||
if ( __itt_state_get_ptr ) { \
|
||||
__itt_state_set( __itt_state_ ); \
|
||||
} /* if */ \
|
||||
} while (0)
|
||||
|
||||
const int KMP_MAX_FRAME_DOMAINS =
|
||||
512; // Maximum number of frame domains to use (maps to
|
||||
// different OpenMP regions in the user source code).
|
||||
extern kmp_int32 __kmp_barrier_domain_count;
|
||||
extern kmp_int32 __kmp_region_domain_count;
|
||||
extern __itt_domain *__kmp_itt_barrier_domains[KMP_MAX_FRAME_DOMAINS];
|
||||
extern __itt_domain *__kmp_itt_region_domains[KMP_MAX_FRAME_DOMAINS];
|
||||
extern __itt_domain *__kmp_itt_imbalance_domains[KMP_MAX_FRAME_DOMAINS];
|
||||
extern kmp_int32 __kmp_itt_region_team_size[KMP_MAX_FRAME_DOMAINS];
|
||||
extern __itt_domain *metadata_domain;
|
||||
extern __itt_string_handle *string_handle_imbl;
|
||||
extern __itt_string_handle *string_handle_loop;
|
||||
extern __itt_string_handle *string_handle_sngl;
|
||||
const int KMP_MAX_FRAME_DOMAINS = 512; // Maximum number of frame domains to use (maps to
|
||||
// different OpenMP regions in the user source code).
|
||||
extern kmp_int32 __kmp_barrier_domain_count;
|
||||
extern kmp_int32 __kmp_region_domain_count;
|
||||
extern __itt_domain* __kmp_itt_barrier_domains[KMP_MAX_FRAME_DOMAINS];
|
||||
extern __itt_domain* __kmp_itt_region_domains[KMP_MAX_FRAME_DOMAINS];
|
||||
extern __itt_domain* __kmp_itt_imbalance_domains[KMP_MAX_FRAME_DOMAINS];
|
||||
extern kmp_int32 __kmp_itt_region_team_size[KMP_MAX_FRAME_DOMAINS];
|
||||
extern __itt_domain * metadata_domain;
|
||||
extern __itt_string_handle * string_handle_imbl;
|
||||
extern __itt_string_handle * string_handle_loop;
|
||||
extern __itt_string_handle * string_handle_sngl;
|
||||
|
||||
#else
|
||||
|
||||
// Null definitions of the synchronization tracing functions.
|
||||
#define KMP_FSYNC_PREPARE(obj) ((void)0)
|
||||
#define KMP_FSYNC_CANCEL(obj) ((void)0)
|
||||
#define KMP_FSYNC_ACQUIRED(obj) ((void)0)
|
||||
#define KMP_FSYNC_RELEASING(obj) ((void)0)
|
||||
# define KMP_FSYNC_PREPARE( obj ) ((void)0)
|
||||
# define KMP_FSYNC_CANCEL( obj ) ((void)0)
|
||||
# define KMP_FSYNC_ACQUIRED( obj ) ((void)0)
|
||||
# define KMP_FSYNC_RELEASING( obj ) ((void)0)
|
||||
|
||||
#define KMP_FSYNC_SPIN_INIT(obj, spin) ((void)0)
|
||||
#define KMP_FSYNC_SPIN_PREPARE(obj) ((void)0)
|
||||
#define KMP_FSYNC_SPIN_ACQUIRED(obj) ((void)0)
|
||||
# define KMP_FSYNC_SPIN_INIT( obj, spin ) ((void)0)
|
||||
# define KMP_FSYNC_SPIN_PREPARE( obj ) ((void)0)
|
||||
# define KMP_FSYNC_SPIN_ACQUIRED( obj ) ((void)0)
|
||||
|
||||
#define KMP_ITT_IGNORE(stmt) \
|
||||
do { \
|
||||
stmt \
|
||||
} while (0)
|
||||
# define KMP_ITT_IGNORE(stmt ) do { stmt } while (0)
|
||||
|
||||
#endif // USE_ITT_NOTIFY
|
||||
|
||||
#if !KMP_DEBUG
|
||||
// In release mode include definitions of inline functions.
|
||||
#include "kmp_itt.inl"
|
||||
#if ! KMP_DEBUG
|
||||
// In release mode include definitions of inline functions.
|
||||
#include "kmp_itt.inl"
|
||||
#endif
|
||||
|
||||
#endif // KMP_ITT_H
|
||||
|
||||
#else /* USE_ITT_BUILD */
|
||||
#else /* USE_ITT_BUILD */
|
||||
|
||||
// Null definitions of the synchronization tracing functions.
|
||||
// If USE_ITT_BULID is not enabled, USE_ITT_NOTIFY cannot be either.
|
||||
// By defining these we avoid unpleasant ifdef tests in many places.
|
||||
#define KMP_FSYNC_PREPARE(obj) ((void)0)
|
||||
#define KMP_FSYNC_CANCEL(obj) ((void)0)
|
||||
#define KMP_FSYNC_ACQUIRED(obj) ((void)0)
|
||||
#define KMP_FSYNC_RELEASING(obj) ((void)0)
|
||||
# define KMP_FSYNC_PREPARE( obj ) ((void)0)
|
||||
# define KMP_FSYNC_CANCEL( obj ) ((void)0)
|
||||
# define KMP_FSYNC_ACQUIRED( obj ) ((void)0)
|
||||
# define KMP_FSYNC_RELEASING( obj ) ((void)0)
|
||||
|
||||
#define KMP_FSYNC_SPIN_INIT(obj, spin) ((void)0)
|
||||
#define KMP_FSYNC_SPIN_PREPARE(obj) ((void)0)
|
||||
#define KMP_FSYNC_SPIN_ACQUIRED(obj) ((void)0)
|
||||
# define KMP_FSYNC_SPIN_INIT( obj, spin ) ((void)0)
|
||||
# define KMP_FSYNC_SPIN_PREPARE( obj ) ((void)0)
|
||||
# define KMP_FSYNC_SPIN_ACQUIRED( obj ) ((void)0)
|
||||
|
||||
#define KMP_ITT_IGNORE(stmt) \
|
||||
do { \
|
||||
stmt \
|
||||
} while (0)
|
||||
# define KMP_ITT_IGNORE(stmt ) do { stmt } while (0)
|
||||
|
||||
#define USE_ITT_BUILD_ARG(x)
|
||||
# define USE_ITT_BUILD_ARG(x)
|
||||
|
||||
#endif /* USE_ITT_BUILD */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user