AMPI: Add fsglobals (filesystem) and pipglobals (Process-in-Process) privatization... 88/4788/36
authorEvan Ramos <evan@hpccharm.com>
Tue, 6 Nov 2018 22:34:37 +0000 (16:34 -0600)
committerEvan Ramos <evan@hpccharm.com>
Wed, 8 May 2019 02:03:01 +0000 (21:03 -0500)
Thanks to the authors of the following publication for providing the
insight that dlmopen(LM_ID_NEWLM, ...) in combination with a PIE binary
results in privatized global variables, implemented here as pipglobals.

Atsushi Hori, Min Si, Balazs Gerofi, Masamichi Takagi, Jai Dayal, Pavan
Balaji, and Yutaka Ishikawa. 2018. Process-in-process: techniques for
practical address-space sharing.  In Proceedings of the 27th
International Symposium on High-Performance Parallel and Distributed
Computing (HPDC '18). ACM, New York, NY, USA,  131-143. DOI:
https://doi.org/10.1145/3208040.3208045

Change-Id: Ie7ef57a9ea6ae03f458f0c87ed88624bd2f1f676

22 files changed:
doc/ampi/manual.rst
src/arch/common/cc-clang.sh
src/arch/common/cc-gcc.sh
src/arch/common/conv-mach-darwin.sh
src/arch/mpi-darwin-x86_64/conv-mach.sh
src/libs/ck-libs/ampi/Makefile
src/libs/ck-libs/ampi/ampi.C
src/libs/ck-libs/ampi/ampi.h
src/libs/ck-libs/ampi/ampiCC
src/libs/ck-libs/ampi/ampi_funcptr.h [new file with mode: 0644]
src/libs/ck-libs/ampi/ampi_funcptr_fsglobals.C [new file with mode: 0644]
src/libs/ck-libs/ampi/ampi_funcptr_loader.C [new file with mode: 0644]
src/libs/ck-libs/ampi/ampi_funcptr_loader.h [new file with mode: 0644]
src/libs/ck-libs/ampi/ampi_funcptr_pipglobals.C [new file with mode: 0644]
src/libs/ck-libs/ampi/ampi_funcptr_shim.C [new file with mode: 0644]
src/libs/ck-libs/ampi/ampiimpl.h
src/libs/ck-libs/ampi/compat_ampicm.C
src/scripts/charmc
src/scripts/configure.ac
src/scripts/conv-config.sh
tests/ampi/privatization/Makefile
tests/ampi/privatization/test.C

index 64774c91d1c32411181db205695755e463041b9f..543fc4a4d0b4abd1a46892d9d8bddbfd605da3d4 100644 (file)
@@ -422,6 +422,115 @@ compile and link time:
 
    $ ampicxx -o example example.C -tlsglobals
 
+Automatic Process-in-Process Runtime Linking Privatization
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Process-in-Process (PiP) [PiP2018]_ Globals allows fully automatic
+privatization of global variables on GNU/Linux systems without
+modification of user code. All languages (C, C++, Fortran, etc.) are
+supported. This method currently lacks support for checkpointing and
+migration, which are necessary for load balancing and fault tolerance.
+Additionally, overdecomposition is limited to approximately 12 virtual
+ranks per logical node, though this can be resolved by building a
+patched version of glibc.
+
+This method works by combining a specific method of building binaries
+with a GNU extension to the dynamic linker. First, AMPI's toolchain
+wrapper compiles your user program as a Position Independent Executable
+(PIE) and links it against a special shim of function pointers instead
+of the normal AMPI runtime. It then builds a small loader utility that
+links directly against AMPI. For each rank, this loader calls the
+glibc-specific function ``dlmopen`` on the PIE binary with a unique
+namespace index. The loader uses ``dlsym`` to populate the PIE binary's
+function pointers and then it calls the entry point. This ``dlmopen``
+and ``dlsym`` process repeats for each rank. As soon as execution jumps
+into the PIE binary, any global variables referenced within will appear
+privatized. This is because PIE binaries locate the global data segment
+immediately after the code segment so that PIE global variables are
+accessed relative to the instruction pointer, and because ``dlmopen``
+creates a separate copy of these segments in memory for each unique
+namespace index.
+
+Optionally, the first step in using PiP-Globals is to build PiP-glibc to
+overcome the limitation on rank count per process. Use the instructions
+at https://github.com/RIKEN-SysSoft/PiP/blob/pip-1/INSTALL to download
+an installable PiP package or build PiP-glibc from source by following
+the ``Patched GLIBC`` section. AMPI may be able to automatically detect
+PiP's location if installed as a package, but otherwise set and export
+the environment variable ``PIP_GLIBC_INSTALL_DIR`` to the value of
+``<GLIBC_INSTALL_DIR>`` as used in the above instructions. For example:
+
+.. code-block:: bash
+
+   $ export PIP_GLIBC_INSTALL_DIR=~/pip
+
+To use PiP-Globals in your AMPI program (with or without PiP-glibc),
+compile and link with the ``-pipglobals`` parameter:
+
+.. code-block:: bash
+
+   $ ampicxx -o example.o -c example.cpp -pipglobals
+   $ ampicxx -o example example.o -pipglobals
+
+No further effort is needed. Global variables in ``example.cpp`` will be
+automatically privatized when the program is run. Any libraries and
+shared objects compiled as PIE will also be privatized. However, if
+these objects call MPI functions, it will be necessary to build them
+with the AMPI toolchain wrappers, ``-pipglobals``, and potentially also
+the ``-standalone`` parameter in the case of shared objects. It is
+recommended to do this in any case so that AMPI can ensure everything is
+built as PIE.
+
+Potential future support for checkpointing and migration will require
+modification of the ``ld-linux.so`` runtime loader to intercept mmap
+allocations of the previously mentioned segments and redirect them
+through Isomalloc. The present lack of support for these features mean
+PiP-Globals is best suited for testing AMPI during exploratory phases
+of development, and for production jobs not requiring load balancing or
+fault tolerance.
+
+Automatic Filesystem-Based Runtime Linking Privatization
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Filesystem Globals (FS-Globals) was discovered during the development of
+PiP-Globals and the two are highly similar. Like PiP-Globals, it
+requires no modification of user code and works with any language.
+It also currently lacks support for checkpointing and migration,
+preventing use of load balancing and fault tolerance. Unlike PiP-Globals,
+it is portable beyond GNU/Linux and has no limits to overdecomposition
+beyond available disk space.
+
+FS-Globals works in the same way as PiP-Globals except that instead of
+specifying namespaces using ``dlmopen``, which is a GNU/Linux-specific
+feature, this method creates copies of the user's PIE binary on the
+filesystem for each rank and calls the POSIX-standard ``dlopen``.
+
+To use FS-Globals, compile and link with the ``-fsglobals`` parameter:
+
+.. code-block:: bash
+
+   $ ampicxx -o example.o -c example.cpp -fsglobals
+   $ ampicxx -o example example.o -fsglobals
+
+No additional steps are required. Global variables in ``example.cpp``
+will be automatically privatized when the program is run. Variables in
+statically linked libraries will also be privatized if compiled as PIE.
+It is recommended to achieve this by building with the AMPI toolchain
+wrappers and ``-fsglobals``, and this is necessary if the libraries call
+MPI functions. Shared objects are currently not supported by FS-Globals
+due to the extra overhead of iterating through all dependencies and
+copying each one per rank while avoiding system components, plus the
+complexity of ensuring each rank's program binary sees the proper set of
+objects.
+
+This method's use of the filesystem is a drawback in that it is slow
+during startup and can be considered wasteful. Additionally, support for
+load balancing and fault tolerance would require further development in
+the future, using the same infrastructure as what PiP-Globals would
+require. For these reasons FS-Globals is best suited for the R&D phase
+of AMPI program development and for small jobs, and it may be less
+suitable for large production environments.
+
 Automatic Global Offset Table Swapping
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -634,6 +743,8 @@ different schemes.
    Transformation       Yes Yes    Yes    Yes  Yes     Yes   Yes
    GOT-Globals          Yes Yes    No     No   No      Yes   Yes
    TLS-Globals          Yes Yes    Yes    No   Maybe   Maybe Maybe
+   PiP-Globals          Yes Yes    No     No   No      Yes   Yes
+   FS-Globals           Yes Yes    Yes    No   Maybe   Yes   Yes
    ==================== === ====== ====== ==== ======= ===== =====
 
 Extensions for Migrations
@@ -2030,3 +2141,11 @@ set the following environment variable to see program output to stdout:
    Currently, we assume that the interface code, which does mapping and
    interpolation among the boundary values of Fluids and Solids domain,
    is integrated with one of Fluids and Solids.
+
+.. [PiP2018]
+   Atsushi Hori, Min Si, Balazs Gerofi, Masamichi Takagi, Jai Dayal, Pavan
+   Balaji, and Yutaka Ishikawa. 2018. Process-in-process: techniques for
+   practical address-space sharing.  In Proceedings of the 27th
+   International Symposium on High-Performance Parallel and Distributed
+   Computing (HPDC '18). ACM, New York, NY, USA,  131-143. DOI:
+   https://doi.org/10.1145/3208040.3208045
index 3892c3063107e71be74df57fe9c31214b312f798..1adb245b434f23f74b32ba02aeca8ae8d4d57419 100644 (file)
@@ -19,5 +19,7 @@ if [ "$CMK_COMPILER" = "msvc" ]; then
   CMK_NATIVE_LDXX="$CMK_LDXX"
 fi
 
+CMK_PIE='-fPIE'
+
 CMK_COMPILER='clang'
 CMK_WARNINGS_ARE_ERRORS="-Werror"
index 92f2e437515631f6fe7a2adc57b000964fc18030..4dc5783ff3c3b5607acaf845ee82dad105967c45 100644 (file)
@@ -28,8 +28,8 @@ if [ "$CMK_MACOSX" ]; then
 
       CMK_CC_FLAGS="-fPIC"
       CMK_CXX_FLAGS="-fPIC -Wno-deprecated"
-      CMK_LD_FLAGS="-fPIC -Wl,-no_pie "
-      CMK_LDXX_FLAGS="-fPIC -multiply_defined suppress -Wl,-no_pie"
+      CMK_LD_FLAGS="-fPIC"
+      CMK_LDXX_FLAGS="-fPIC -multiply_defined suppress"
       found=1
       break
     fi
index 8c5f8ac6b47bac4e370567603b2a396f853d220f..6cd78445a651197abf1a9ecab59fb518ebd97d8e 100644 (file)
@@ -6,9 +6,8 @@ CMK_QT='generic64-light'
 CMK_XIOPTS=''
 
 CMK_CC_FLAGS="$CMK_CC_FLAGS -fPIC -dynamic -fno-common "
-CMK_LD_FLAGS="$CMK_LD_FLAGS -Wl,-no_pie "
 CMK_CXX_FLAGS="$CMK_CXX_FLAGS -fPIC -dynamic -fno-common -stdlib=libc++ "
-CMK_LDXX_FLAGS="$CMK_LDXX_FLAGS -multiply_defined suppress -Wl,-no_pie -stdlib=libc++ "
+CMK_LDXX_FLAGS="$CMK_LDXX_FLAGS -multiply_defined suppress -stdlib=libc++ "
 
 # setting for shared lib
 CMK_SHARED_SUF="dylib"
index e2750681398de208a4ba94dac7bced5b940e691b..c8750befca56a3d20b8de23e2061c88e929f96d5 100644 (file)
@@ -34,9 +34,9 @@ CMK_NATIVE_LDXX='clang++'
 CMK_NATIVE_LIBS=""
 
 CMK_NATIVE_CC_FLAGS="$CMK_GCC64"
-CMK_NATIVE_LD_FLAGS="-Wl,-no_pie $CMK_GCC64"
+CMK_NATIVE_LD_FLAGS="$CMK_GCC64"
 CMK_NATIVE_CXX_FLAGS="$CMK_GCC64 -stdlib=libc++"
-CMK_NATIVE_LDXX_FLAGS="-Wl,-no_pie $CMK_GCC64 -stdlib=libc++"
+CMK_NATIVE_LDXX_FLAGS="$CMK_GCC64 -stdlib=libc++"
 
 CMK_CF90=`which f95 2>/dev/null`
 if test -n "$CMK_CF90"
index 9e840373556c2f4aa7a29ff76d3269535f6f1db7..f3f4170075d1f9b63bce0d8ec61cc92e1c67e2bd 100644 (file)
@@ -20,6 +20,25 @@ DESTF=$(AMPI_LIBDIR)/$(AMPI_LIB)f.a
 COMPATLIB=$(AMPI_LIBDIR)/libampi-compat.a
 ROMIOLIB=$(AMPI_LIBDIR)/libampiromio
 
+AMPIFIMPL_OBJ=$(AMPI_LIBDIR)/ampifimpl.o
+AMPIMOD_OBJ=$(AMPI_LIBDIR)/ampimod.o
+
+FUNCPTR_SHIM_OBJ=$(AMPI_LIBDIR)/ampi_funcptr_shim.o
+FUNCPTR_FORTRAN_OBJ=$(AMPI_LIBDIR)/ampi_funcptr_fortran.o
+FUNCPTR_LOADER_OBJ=$(AMPI_LIBDIR)/ampi_funcptr_loader.o
+FUNCPTR_PIPGLOBALS_OBJ=$(AMPI_LIBDIR)/ampi_funcptr_pipglobals.o
+FUNCPTR_FSGLOBALS_OBJ=$(AMPI_LIBDIR)/ampi_funcptr_fsglobals.o
+
+AMPI_TARGET = $(DEST) $(FUNCPTR_SHIM_OBJ) $(FUNCPTR_LOADER_OBJ)
+AMPIF_TARGET = $(DESTF) $(FUNCPTR_FORTRAN_OBJ)
+
+ifeq (1,$(CMK_SUPPORTS_PIPGLOBALS))
+  AMPI_TARGET += $(FUNCPTR_PIPGLOBALS_OBJ)
+endif
+ifeq (1,$(CMK_SUPPORTS_FSGLOBALS))
+  AMPI_TARGET += $(FUNCPTR_FSGLOBALS_OBJ)
+endif
+
 ifeq ($(CMK_NO_BUILD_SHARED),false)
        ROMIOLIBSHARED=$(CDIR)/lib_so/libampiromio.$(CMK_SHARED_SUF)
 endif
@@ -60,10 +79,10 @@ $(ROMIO): | AMPI AMPIF
        fi
        @echo "ROMIO built successfully"
 
-AMPI: $(DEST)
+AMPI: $(AMPI_TARGET)
        @echo "AMPI built successfully"
 
-AMPIF: $(DESTF)
+AMPIF: $(AMPIF_TARGET)
        @echo "AMPIF built successfully"
 
 $(DEST): $(OBJS) headers
@@ -71,10 +90,10 @@ $(DEST): $(OBJS) headers
        cp $(AMPI_LIB).dep $(AMPI_LIBDIR)/$(AMPI_LIB).dep
 
 $(DESTF): $(OBJS) headers
-       -$(CHARMC) -c ampifimpl.f90
-       -$(CHARMC) -c ampimod.f90
+       -$(CHARMC) -c ampifimpl.f90 -o $(AMPIFIMPL_OBJ)
+       -$(CHARMC) -c ampimod.f90 -o $(AMPIMOD_OBJ)
        -$(CHARMC) -cpmod ../../../../include mpi.M
-       -$(CHARMC) $(OBJS) ampifimpl.o ampimod.o -o $@
+       -$(CHARMC) $(OBJS) $(AMPIFIMPL_OBJ) $(AMPIMOD_OBJ) -o $@
        -cp $(AMPI_LIB)f.dep $(AMPI_LIBDIR)/$(AMPI_LIB)f.dep
 
 $(COMPATLIB): $(COMPAT)
@@ -140,6 +159,21 @@ ampi.decl.h ampi.def.h: ampi.ci
 
 ddt.o: ddt.C ddt.h $(HEADDEP)
 
+$(FUNCPTR_SHIM_OBJ): ampi_funcptr_shim.C $(HEADDEP)
+       $(CHARMC) -ampi-funcptr-shim -c $< -o $@
+
+$(FUNCPTR_FORTRAN_OBJ): ampif.C $(HEADDEP)
+       -$(CHARMC) -ampi-funcptr-shim -c $< -o $@
+
+$(FUNCPTR_LOADER_OBJ): ampi_funcptr_loader.C $(HEADDEP)
+       $(CHARMC) -c $< -o $@
+
+$(FUNCPTR_FSGLOBALS_OBJ): ampi_funcptr_fsglobals.C $(HEADDEP)
+       $(CHARMC) -c $< -o $@
+
+$(FUNCPTR_PIPGLOBALS_OBJ): ampi_funcptr_pipglobals.C $(HEADDEP)
+       $(CHARMC) -c $< -o $@
+
 clean:
        rm -fr *.o *~ *.decl.h *.def.h gmon.out $(DEST) $(DESTF) $(COMPATLIB) conv-host charmrun headers *.mod
        - cd romio && $(MAKE) clean
index ffb8d8ee0e7e8028ef648d70535f123c4ef2bb40..51c1973dd71652e59c36f00b62f7528e72ad0e33 100644 (file)
@@ -904,8 +904,94 @@ static constexpr std::array<MPI_User_function*, AMPI_MAX_PREDEFINED_OP+1> ampiPr
   MPI_NO_OP_USER_FN
 }};
 
+#if defined _WIN32
+# ifndef WIN32_LEAN_AND_MEAN
+#  define WIN32_LEAN_AND_MEAN
+# endif
+# ifndef NOMINMAX
+#  define NOMINMAX
+# endif
+# include <windows.h>
+#elif defined __APPLE__
+# include <unistd.h>
+# include <libproc.h>
+#elif CMK_HAS_REALPATH || CMK_HAS_READLINK
+# ifndef _GNU_SOURCE
+#  define _GNU_SOURCE
+# endif
+# ifndef __USE_GNU
+#  define __USE_GNU
+# endif
+# include <unistd.h>
+#endif
+
+char * ampi_binary_path;
+
+static void getAmpiBinaryPath() noexcept
+{
+#if defined _WIN32
+  ssize_t bufsize = MAX_PATH;
+  DWORD n;
+  do
+  {
+    ampi_binary_path = (char *)realloc(ampi_binary_path, bufsize);
+    SetLastError(0);
+    n = GetModuleFileName(NULL, ampi_binary_path, bufsize);
+    bufsize *= 2;
+  }
+  while (n == bufsize || GetLastError() == ERROR_INSUFFICIENT_BUFFER);
+
+  if (n == 0)
+  {
+    CkError("ERROR> GetModuleFileName(): %d\n", (int)GetLastError());
+    free(ampi_binary_path);
+    ampi_binary_path = nullptr;
+  }
+#elif defined __APPLE__
+  ampi_binary_path = (char *)malloc(PROC_PIDPATHINFO_MAXSIZE);
+  pid_t pid = getpid();
+  int n = proc_pidpath(pid, ampi_binary_path, PROC_PIDPATHINFO_MAXSIZE);
+
+  if (n == 0)
+  {
+    CkError("ERROR> proc_pidpath(): %s\n", strerror(errno));
+    free(ampi_binary_path);
+    ampi_binary_path = nullptr;
+  }
+#elif CMK_HAS_REALPATH
+  ampi_binary_path = realpath("/proc/self/exe", nullptr);
+  if (ampi_binary_path == nullptr)
+    CkError("ERROR> realpath(): %s\n", strerror(errno));
+#elif CMK_HAS_READLINK
+  ssize_t bufsize = 256;
+  ssize_t n;
+  do
+  {
+    ampi_binary_path = (char *)realloc(ampi_binary_path, bufsize);
+    n = readlink("/proc/self/exe", ampi_binary_path, bufsize-1);
+    bufsize *= 2;
+  }
+  while (n == bufsize-1);
+
+  if (n == -1)
+  {
+    CkError("ERROR> readlink(): %s\n", strerror(errno));
+    free(ampi_binary_path);
+    ampi_binary_path = nullptr;
+  }
+  else
+  {
+    ampi_binary_path[n] = '\0';
+  }
+#else
+  CkAbort("Could not get path to current binary!");
+#endif
+}
+
 static void ampiNodeInit() noexcept
 {
+  getAmpiBinaryPath();
+
 #if CMK_TRACE_ENABLED
   TCharm::nodeInit(); // make sure tcharm_funcmap is set up
   int funclength = sizeof(funclist)/sizeof(char*);
index ee7a16cc889e33c799d857f61b5da2939ae8e1e5..a69e0d48a513f572c728a86618d3fea5f56f7f56 100644 (file)
 
 /* Macros to define the AMPI'fied name of an MPI function, plus the AMPI'fied
  * PMPI name. */
+#ifdef AMPI_USE_FUNCPTR
+  #define AMPI_FUNCPTR(x) (* x)
+#else
+  #define AMPI_FUNCPTR(x) x
+#endif
+
 #define AMPI_CUSTOM_API_DEF(return_type, function_name, ...) \
-  extern return_type function_name(__VA_ARGS__);
+  extern return_type AMPI_FUNCPTR(function_name)(__VA_ARGS__);
 #if AMPI_HAVE_PMPI
   #define AMPI_API_DEF(return_type, function_name, ...) \
-    extern return_type function_name(__VA_ARGS__);             \
-    extern return_type P##function_name(__VA_ARGS__);
+    extern return_type AMPI_FUNCPTR(function_name)(__VA_ARGS__);             \
+    extern return_type AMPI_FUNCPTR(P##function_name)(__VA_ARGS__);
 #else
   #define AMPI_API_DEF AMPI_CUSTOM_API_DEF
 #endif
@@ -70,7 +76,7 @@ instead of as an actual "main".
 */
 #ifdef __cplusplus /* C++ version-- rename "main" as "AMPI_Main_cpp" */
 #  define main AMPI_Main_cpp
-int AMPI_Main_cpp(int argc,char **argv); /* prototype for C++ main routine */
+CLINKAGE int AMPI_Main_cpp(int argc,char **argv); /* prototype for C++ main routine */
 int AMPI_Main_cpp(void); /* prototype for C++ main routines without args, as in autoconf tests */
 
 extern "C" {
index 2944e1150532e2f497e53f14ebf52c1f6dafbd63..f6a94b15043dcb9f6e2d9f681910d0dcbd06d283 100755 (executable)
@@ -1,12 +1,20 @@
 #!/bin/sh
 CHARMBIN=`dirname $0`
+CHARMLIB="$CHARMBIN/../lib"
+CHARMINC="$CHARMBIN/../include"
+. "$CHARMINC/conv-mach-opt.sh"
 
 [ -z "$AMPICC_MODE" ] && AMPICC_MODE='ampi'
 STANDALONE=''
 ROMIO_CONFIGURE=''
 MPITEST=''
+FSGLOBALS=''
+PIPGLOBALS=''
+EXPLICIT_COMPILATION=''
+BUILD_SHARE=''
 
 ARGS=''
+OBJECT=''
 
 processArgs() {
 while [ ! $# -eq 0 ]
@@ -32,6 +40,25 @@ do
      MPITEST='true'
      ;;
 
+  -fsglobals)
+     FSGLOBALS='true'
+     ;;
+  -pipglobals)
+     PIPGLOBALS='true'
+     ;;
+
+  -c)
+     EXPLICIT_COMPILATION='true'
+     ARGS="$ARGS \"$arg\""
+     ;;
+  -shared|-G)
+     BUILD_SHARE='true'
+     ARGS="$ARGS \"$arg\""
+     ;;
+  -o)
+     shift
+     OBJECT="$1"
+     ;;
   *)
      ARGS="$ARGS \"$arg\""
      ;;
@@ -42,13 +69,77 @@ done
 
 eval processArgs "$@"
 
+if [ -n "$FSGLOBALS" ]
+then
+  if [ "$CMK_SUPPORTS_FSGLOBALS" != '1' ]
+  then
+    echo "Error: Prerequisites for -fsglobals support were not detected."
+    exit 1
+  fi
+fi
+
+if [ -n "$PIPGLOBALS" ]
+then
+  if [ "$CMK_SUPPORTS_PIPGLOBALS" != '1' ]
+  then
+    echo "Error: Prerequisites for -pipglobals support were not detected."
+    exit 1
+  fi
+fi
+
+AMPICC_POST_OPTS=''
+
 [ -n "$ROMIO_CONFIGURE" -a -z "$MPITEST" ] && STANDALONE='true'
 
 [ -n "$STANDALONE" ] && ARGS="$ARGS -standalone"
 
 [ -f $CHARMBIN/../lib/libampiromio.a -a -z "$STANDALONE" -a -z "$ROMIO_CONFIGURE" ] && ROMIO='-lampiromio'
 
-$CHARMBIN/charmc -language $AMPICC_MODE -default-to-aout $ARGS $ROMIO
+FUNCPTR_SHIM_SUFFIX='.user'
+
+if [ -n "$FSGLOBALS" -o -n "$PIPGLOBALS" ]
+then
+  if [ -z "$EXPLICIT_COMPILATION" -a -z "$BUILD_SHARE" -a -z "$STANDALONE" ] # if linking an AMPI executable
+  then
+    # link the user program against the shim
+    [ -z "$OBJECT" ] && USEROBJECT="a.out$FUNCPTR_SHIM_SUFFIX" || USEROBJECT="$OBJECT$FUNCPTR_SHIM_SUFFIX"
+    SHIM_OBJS="\"$CHARMLIB/ampi_funcptr_shim.o\""
+    [ "$AMPICC_MODE" = 'ampif' ] && SHIM_OBJS="$SHIM_OBJS \"$CHARMLIB/ampi_funcptr_fortran.o\" \"$CHARMLIB/ampifimpl.o\" \"$CHARMLIB/ampimod.o\""
+    $CHARMBIN/charmc $ARGS $AMPICC_POST_OPTS $SHIM_OBJS -standalone -ampi-funcptr-shim -o "$USEROBJECT"
+
+    # set up linking the loader against the runtime
+    AMPICC_POST_OPTS="$AMPICC_POST_OPTS -clear-input \"$CHARMLIB/ampi_funcptr_loader.o\""
+    if [ -n "$FSGLOBALS" ]
+    then
+      AMPICC_POST_OPTS="$AMPICC_POST_OPTS \"$CHARMLIB/ampi_funcptr_fsglobals.o\""
+    elif [ -n "$PIPGLOBALS" ]
+    then
+      AMPICC_POST_OPTS="$AMPICC_POST_OPTS \"$CHARMLIB/ampi_funcptr_pipglobals.o\""
+
+      # look for PiP-glibc
+      [ -z "$PIP_GLIBC_INSTALL_DIR" ] && PIP_GLIBC_INSTALL_DIR='/opt/pip'
+      pipldquery="$PIP_GLIBC_INSTALL_DIR/lib/ld-*.so"
+      set -- $pipldquery
+      pipld="$1"
+      if [ "$pipld" = "$pipldquery" ]
+      then
+        echo 'Note: PiP-glibc not found. Maximum virtualization count will be limited.'
+        echo '      Please set and export $PIP_GLIBC_INSTALL_DIR appropriately.'
+      else
+        AMPICC_POST_OPTS="$AMPICC_POST_OPTS -Wl,--dynamic-linker=$pipld"
+      fi
+    fi
+  else
+    AMPICC_POST_OPTS="$AMPICC_POST_OPTS -ampi-funcptr-shim"
+  fi
+fi
+
+if [ -n "$OBJECT" ]
+then
+  AMPICC_POST_OPTS="$AMPICC_POST_OPTS -o \"$OBJECT\""
+fi
+
+$CHARMBIN/charmc -language $AMPICC_MODE -default-to-aout $ARGS $AMPICC_POST_OPTS $ROMIO
 status=$?
 
 # Copy ampirun, but do not overwrite it if it already exists.
diff --git a/src/libs/ck-libs/ampi/ampi_funcptr.h b/src/libs/ck-libs/ampi/ampi_funcptr.h
new file mode 100644 (file)
index 0000000..d1bc6fa
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef AMPI_FUNCPTR_H_
+#define AMPI_FUNCPTR_H_
+
+#include "ampi.h"
+
+
+#define AMPI_CUSTOM_FUNCPTR_DEF(return_type, function_name, ...) \
+  return_type (* function_name)(__VA_ARGS__);
+#if AMPI_HAVE_PMPI
+  #define AMPI_FUNCPTR_DEF(return_type, function_name, ...) \
+    return_type (* function_name)(__VA_ARGS__);             \
+    return_type (* P##function_name)(__VA_ARGS__);
+#else
+  #define AMPI_FUNCPTR_DEF AMPI_CUSTOM_FUNCPTR_DEF
+#endif
+
+
+struct AMPI_FuncPtr_Transport
+{
+#define AMPI_FUNC AMPI_FUNCPTR_DEF
+#define AMPI_FUNC_NOIMPL AMPI_FUNC
+#define AMPI_CUSTOM_FUNC AMPI_CUSTOM_FUNCPTR_DEF
+
+#include "ampi_functions.h"
+
+#undef AMPI_FUNC
+#undef AMPI_FUNC_NOIMPL
+#undef AMPI_CUSTOM_FUNC
+};
+
+
+#endif /* AMPI_FUNCPTR_H_ */
diff --git a/src/libs/ck-libs/ampi/ampi_funcptr_fsglobals.C b/src/libs/ck-libs/ampi/ampi_funcptr_fsglobals.C
new file mode 100644 (file)
index 0000000..bf9ff91
--- /dev/null
@@ -0,0 +1,100 @@
+
+#include "ampi_funcptr_loader.h"
+
+#if defined _WIN32
+# ifndef WIN32_LEAN_AND_MEAN
+#  define WIN32_LEAN_AND_MEAN
+# endif
+# ifndef NOMINMAX
+#  define NOMINMAX
+# endif
+# include <windows.h>
+# include <io.h>
+# define access _access
+#elif defined __APPLE__
+# include <unistd.h>
+# include <copyfile.h>
+# include <errno.h>
+#else
+# include <unistd.h>
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <errno.h>
+#endif
+
+#include <string>
+#include <atomic>
+
+static void fs_copy(const char * src, const char * dst)
+{
+  static const char abortmsg[] = "Could not copy fsglobals user program!";
+
+#if defined _WIN32
+  BOOL ret = CopyFile(src, dst, true);
+  if (ret == 0)
+  {
+    CkError("ERROR> CopyFile(): %d\n", (int)GetLastError());
+    CkAbort(abortmsg);
+  }
+#elif defined __APPLE__
+  int ret = copyfile(src, dst, 0, COPYFILE_ALL);
+  if (ret < 0)
+  {
+    CkError("ERROR> copyfile(): %d %s\n", ret, strerror(errno));
+    CkAbort(abortmsg);
+  }
+#else
+  pid_t pid = fork();
+  if (pid == 0)
+  {
+    execl("/bin/cp", "/bin/cp", src, dst, NULL);
+    CkError("ERROR> execl(): %s\n", strerror(errno));
+    CkAbort(abortmsg);
+  }
+  else if (pid < 0)
+  {
+    CkError("ERROR> fork(): %s\n", strerror(errno));
+    CkAbort(abortmsg);
+  }
+  else
+  {
+    int status;
+    pid_t ws = waitpid(pid, &status, 0);
+    if (ws == -1)
+      CkError("ERROR> waitpid(): %s\n", strerror(errno));
+  }
+#endif
+}
+
+static std::atomic<size_t> rank_count{};
+
+int main(int argc, char ** argv)
+{
+  SharedObject myexe;
+
+  // copy the user binary for this rank on the filesystem and open it
+  {
+    static const char FUNCPTR_SHIM_SUFFIX[] = ".user";
+
+    std::string src{ampi_binary_path};
+    src += FUNCPTR_SHIM_SUFFIX;
+
+    std::string dst{src};
+    dst += '.';
+    dst += std::to_string(rank_count++);
+    const char * dststr = dst.c_str();
+
+    if (access(dststr, R_OK) != 0)
+      fs_copy(src.c_str(), dststr);
+
+    myexe = dlopen(dststr, RTLD_NOW|RTLD_LOCAL);
+  }
+
+  if (myexe == nullptr)
+  {
+    CkError("dlopen error: %s\n", dlerror());
+    CkAbort("Could not open fsglobals user program!");
+  }
+
+  return AMPI_FuncPtr_Loader(myexe, argc, argv);
+}
diff --git a/src/libs/ck-libs/ampi/ampi_funcptr_loader.C b/src/libs/ck-libs/ampi/ampi_funcptr_loader.C
new file mode 100644 (file)
index 0000000..f7b5c04
--- /dev/null
@@ -0,0 +1,84 @@
+
+#include "ampi_funcptr_loader.h"
+
+#include <stdio.h>
+#include <string.h>
+
+
+static void AMPI_FuncPtr_Pack(struct AMPI_FuncPtr_Transport * x)
+{
+#define AMPI_CUSTOM_FUNC(return_type, function_name, ...) \
+    x->function_name = function_name;
+#if AMPI_HAVE_PMPI
+  #define AMPI_FUNC(return_type, function_name, ...) \
+      x->function_name = function_name; \
+      x->P##function_name = P##function_name;
+#else
+  #define AMPI_FUNC AMPI_CUSTOM_FUNC
+#endif
+#define AMPI_FUNC_NOIMPL AMPI_FUNC
+
+#include "ampi_functions.h"
+
+#undef AMPI_FUNC
+#undef AMPI_FUNC_NOIMPL
+#undef AMPI_CUSTOM_FUNC
+}
+
+static void AMPI_FuncPtr_Unpack_Dispatch(SharedObject myexe, struct AMPI_FuncPtr_Transport * x)
+{
+  typedef int (*myPtrUnpackType)(struct AMPI_FuncPtr_Transport *);
+  auto myPtrUnpack = (myPtrUnpackType)dlsym(myexe, "AMPI_FuncPtr_Unpack");
+
+  if (myPtrUnpack == nullptr)
+  {
+    CkError("dlsym error: %s\n", dlerror());
+    CkAbort("Could not complete AMPI_FuncPtr_Unpack!");
+  }
+
+  myPtrUnpack(x);
+}
+
+
+static int AMPI_Main_Dispatch(SharedObject myexe, int argc, char ** argv)
+{
+  typedef int (*maintype)(int, char **);
+  typedef void (*fmpimaintype)(void);
+
+  auto AMPI_Main_cpp_ptr = (maintype)dlsym(myexe, "AMPI_Main_cpp");
+  if (AMPI_Main_cpp_ptr)
+    return AMPI_Main_cpp_ptr(argc, argv);
+
+  auto AMPI_Main_c_ptr = (maintype)dlsym(myexe, "AMPI_Main_c");
+  if (AMPI_Main_c_ptr)
+    return AMPI_Main_c_ptr(argc, argv);
+
+  auto AMPI_Main_ptr = (maintype)dlsym(myexe, "AMPI_Main");
+  if (AMPI_Main_ptr)
+    return AMPI_Main_ptr(argc, argv);
+
+  auto fmpi_main_ptr = (fmpimaintype)dlsym(myexe, STRINGIZE(FTN_NAME(MPI_MAIN,mpi_main)));
+  if (fmpi_main_ptr)
+  {
+    fmpi_main_ptr();
+    return 0;
+  }
+
+  CkAbort("Could not find any AMPI entry points!");
+
+  return 1;
+}
+
+
+int AMPI_FuncPtr_Loader(SharedObject myexe, int argc, char ** argv)
+{
+  // populate the user binary's function pointer shim
+  {
+    AMPI_FuncPtr_Transport x;
+    AMPI_FuncPtr_Pack(&x);
+    AMPI_FuncPtr_Unpack_Dispatch(myexe, &x);
+  }
+
+  // jump to the user binary
+  return AMPI_Main_Dispatch(myexe, argc, argv);
+}
diff --git a/src/libs/ck-libs/ampi/ampi_funcptr_loader.h b/src/libs/ck-libs/ampi/ampi_funcptr_loader.h
new file mode 100644 (file)
index 0000000..f715713
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef AMPI_FUNCPTR_LOADER_H_
+#define AMPI_FUNCPTR_LOADER_H_
+
+#ifndef __STDC_FORMAT_MACROS
+# define __STDC_FORMAT_MACROS
+#endif
+#ifndef __STDC_LIMIT_MACROS
+# define __STDC_LIMIT_MACROS
+#endif
+#include <inttypes.h>
+#include <limits.h>
+
+#include "ampiimpl.h"
+#include "ampi_funcptr.h"
+
+#define STRINGIZE_INTERNAL(x) #x
+#define STRINGIZE(x) STRINGIZE_INTERNAL(x)
+
+
+#ifdef _WIN32
+
+#ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#ifndef NOMINMAX
+# define NOMINMAX
+#endif
+#include <windows.h>
+
+typedef HMODULE SharedObject;
+
+#define dlopen(name, flags) LoadLibrary(name)
+#define dlsym(handle, name) GetProcAddress((handle), (name))
+#define dlclose(handle) FreeLibrary(handle)
+
+#else
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+#ifndef __USE_GNU
+# define __USE_GNU
+#endif
+#include <dlfcn.h>
+
+typedef void * SharedObject;
+
+#endif
+
+
+int AMPI_FuncPtr_Loader(SharedObject, int, char **);
+
+#endif /* AMPI_FUNCPTR_LOADER_H_ */
diff --git a/src/libs/ck-libs/ampi/ampi_funcptr_pipglobals.C b/src/libs/ck-libs/ampi/ampi_funcptr_pipglobals.C
new file mode 100644 (file)
index 0000000..88df868
--- /dev/null
@@ -0,0 +1,31 @@
+
+#include "ampi_funcptr_loader.h"
+
+#include <string>
+#include <atomic>
+
+static std::atomic<size_t> rank_count{};
+
+int main(int argc, char ** argv)
+{
+  SharedObject myexe;
+
+  // open the user binary for this rank in a unique namespace
+  {
+    static const char FUNCPTR_SHIM_SUFFIX[] = ".user";
+
+    std::string binary_path{ampi_binary_path};
+    binary_path += FUNCPTR_SHIM_SUFFIX;
+
+    const Lmid_t lmid = rank_count++ == 0 ? LM_ID_BASE : LM_ID_NEWLM;
+    myexe = dlmopen(lmid, binary_path.c_str(), RTLD_NOW|RTLD_LOCAL);
+  }
+
+  if (myexe == nullptr)
+  {
+    CkError("dlmopen error: %s\n", dlerror());
+    CkAbort("Could not open pipglobals user program!");
+  }
+
+  return AMPI_FuncPtr_Loader(myexe, argc, argv);
+}
diff --git a/src/libs/ck-libs/ampi/ampi_funcptr_shim.C b/src/libs/ck-libs/ampi/ampi_funcptr_shim.C
new file mode 100644 (file)
index 0000000..4ae63b7
--- /dev/null
@@ -0,0 +1,56 @@
+// This object can be linked to AMPI binaries in place of the RTS.
+
+#ifndef AMPI_USE_FUNCPTR
+# error This file requires -ampi-funcptr-shim.
+#endif
+#include "ampi_funcptr.h"
+
+
+// Provide the definitions of function pointers corresponding to the entire AMPI API.
+
+#define AMPI_FUNC AMPI_FUNCPTR_DEF
+#define AMPI_FUNC_NOIMPL AMPI_FUNC
+#define AMPI_CUSTOM_FUNC AMPI_CUSTOM_FUNCPTR_DEF
+
+#include "ampi_functions.h"
+
+#undef AMPI_FUNC
+#undef AMPI_FUNC_NOIMPL
+#undef AMPI_CUSTOM_FUNC
+
+
+// Provide an interface to link the function pointers at runtime.
+
+extern "C" void AMPI_FuncPtr_Unpack(struct AMPI_FuncPtr_Transport * x)
+{
+#define AMPI_CUSTOM_FUNC(return_type, function_name, ...) \
+  function_name = x->function_name;
+#if AMPI_HAVE_PMPI
+  #define AMPI_FUNC(return_type, function_name, ...) \
+    function_name = x->function_name; \
+    P##function_name = x->P##function_name;
+#else
+  #define AMPI_FUNC AMPI_CUSTOM_FUNC
+#endif
+#define AMPI_FUNC_NOIMPL AMPI_FUNC
+
+#include "ampi_functions.h"
+
+#undef AMPI_FUNC
+#undef AMPI_FUNC_NOIMPL
+#undef AMPI_CUSTOM_FUNC
+}
+
+
+// Provide a stub entry point so the program will link without any special effort.
+
+#include <stdio.h>
+
+#ifdef main
+# undef main
+#endif
+int main()
+{
+  fprintf(stderr, "Do not run this binary directly!\n");
+  return 1;
+}
index 1cedf8b582983eaf014c4c4b41dffbf22ed78131..ef65724d615978cf6b361cc71e1464dd96b9ed9c 100644 (file)
@@ -40,6 +40,8 @@ using std::vector;
     ret name(__VA_ARGS__)
 #endif
 
+extern char * ampi_binary_path;
+
 #if AMPIMSGLOG
 #include "ckliststring.h"
 static CkListString msgLogRanks;
index c5319ab46094785940b9e84bc9f256a9a9e15494..2d5e86819a69dc27615a38a8f75c731b5d337ef3 100644 (file)
@@ -1,4 +1,4 @@
-int AMPI_Main_cpp(int argc,char **argv)
+extern "C" int AMPI_Main_cpp(int argc,char **argv)
 {
        (void)argc; (void)argv;
        return 0;
index e2cf23adf2a6a9e4b0f4e96b8613983ca34c67cc..2913c33039618e2df1cf75c6ab63ca1f1bf1fc7f 100755 (executable)
@@ -51,8 +51,8 @@ OPTS_CC_GENCPM=""
 OPTS_CXX="" 
 OPTS_F90=""
 OPTS_LD=""  
-OPTS_PIC=""
 USE_PIC="0"
+USE_PIE='0'
 
 CHARMDEBUG=""
 LINK_PYTHON=""
@@ -99,6 +99,7 @@ BUILD_SHARE="0"
 SWAPGLOBALS="0"
 TLSGLOBALS="0"
 ROSE_OMP_TLS_GLOBALS="no"
+AMPI_FUNCPTR_SHIM='0'
 PRINT_BUILDING_BLOCKS=""
 NOABORT=""
 
@@ -533,6 +534,11 @@ do
                ROSE_OMP_TLS_GLOBALS="yes"
                ;;
 
+       "-ampi-funcptr-shim")
+               AMPI_FUNCPTR_SHIM='1'
+               USE_PIE='1'
+               ;;
+
        "-verbose")
                echo "Verbose mode set"
                VERBOSE=true
@@ -864,6 +870,13 @@ do
                NOABORT="yes"
                ;;
 
+       -clear-input)
+               INPUT_GIVEN=''
+               FILES=''
+               PRE_LIBRARIES=''
+               POST_LIBRARIES=''
+               ;;
+
        -*|+*)
 #              Warning "passing unrecognized option $arg to all compilers and linkers"
                OPTS="$OPTS  $arg"
@@ -1026,6 +1039,12 @@ then
     OPTS_F90="$OPTS_F90 $TLSGLOBALS_OPTS"
 fi
 
+if [ "$AMPI_FUNCPTR_SHIM" = '1' ]
+then
+    OPTS_CC="$OPTS_CC -DAMPI_USE_FUNCPTR"
+    OPTS_CXX="$OPTS_CXX -DAMPI_USE_FUNCPTR"
+fi
+
 # Look up and add the dependencies for module $1
 findModuleDep() {
        M=$1
@@ -1092,13 +1111,20 @@ then
        USE_PIC="1"
 fi
 
-OPTS_PIC="$CMK_PIC"
 if [ "$USE_PIC" = "1" ]
 then
-       OPTS_CC="$OPTS_CC $OPTS_PIC"
-       OPTS_CXX="$OPTS_CXX $OPTS_PIC"
-       OPTS_F90="$OPTS_F90 $OPTS_PIC"
-       OPTS_LD="$OPTS_LD $OPTS_PIC"
+       OPTS_CC="$OPTS_CC $CMK_PIC"
+       OPTS_CXX="$OPTS_CXX $CMK_PIC"
+       OPTS_F90="$OPTS_F90 $CMK_PIC"
+       OPTS_LD="$OPTS_LD $CMK_PIC"
+fi
+
+if [ "$USE_PIE" = "1" ]
+then
+       OPTS_CC="$OPTS_CC $CMK_PIE"
+       OPTS_CXX="$OPTS_CXX $CMK_PIE"
+       OPTS_F90="$OPTS_F90 $CMK_PIE"
+       OPTS_LD="$OPTS_LD $CMK_PIE"
 fi
 
 if [ "$BUILD_SHARE" = "1" ]
index 2bea8515d6ec14f1ffe323dc449875011a521f6e..977eb1e92515c38003182a97474456d56994f5aa 100644 (file)
@@ -2035,6 +2035,7 @@ fi
 
 if test $pass -eq 1 -o $noldl -eq 1
 then
+       CMK_HAS_DLOPEN='1'
 # One version or another of dlopen worked: compile it in
        AC_DEFINE_UNQUOTED(CMK_DLL_USE_DLOPEN, 1, [dlopen])
 fi
@@ -2073,6 +2074,89 @@ EOT
 test_cc "whether has RTLD_NEXT" "yes" "no" ""
 AC_DEFINE_UNQUOTED(CMK_HAS_RTLD_NEXT, $pass, [whether has RTLD_NEXT])
 
+cat > $tc <<EOT
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+#ifndef __USE_GNU
+# define __USE_GNU
+#endif
+#include <dlfcn.h>
+#include <stddef.h>
+int main()
+{
+  return dlmopen(LM_ID_NEWLM, "foo.so", 0) == NULL;
+}
+EOT
+test_cc "whether has dlmopen" "yes" "no" ""
+AC_DEFINE_UNQUOTED(CMK_HAS_DLMOPEN, $pass, [whether has dlmopen])
+CMK_HAS_DLMOPEN="$pass"
+
+cat > $tc <<EOT
+#include <unistd.h>
+int main()
+{
+  char exe[[1024]];
+  return readlink("/proc/self/exe", exe, sizeof(exe)-1) == -1;
+}
+EOT
+test_cc "whether has readlink" "yes" "no" ""
+AC_DEFINE_UNQUOTED(CMK_HAS_READLINK, $pass, [whether has readlink])
+CMK_HAS_READLINK="$pass"
+
+cat > $tc <<EOT
+#include <limits.h>
+#include <stdlib.h>
+int main()
+{
+  return realpath("/proc/self/exe", NULL) == NULL;
+}
+EOT
+test_cc "whether has realpath" "yes" "no" ""
+AC_DEFINE_UNQUOTED(CMK_HAS_REALPATH, $pass, [whether has realpath])
+CMK_HAS_REALPATH="$pass"
+
+case "$CMK_VDIR" in
+  *-win-*|*-win64)
+    CMK_CAN_GET_BINARY_PATH='1'
+    CMK_CAN_OPEN_SHARED_OBJECTS_DYNAMICALLY='1'
+    ;;
+  *-darwin*)
+    CMK_CAN_GET_BINARY_PATH='1'
+    CMK_CAN_OPEN_SHARED_OBJECTS_DYNAMICALLY="$CMK_HAS_DLOPEN"
+    ;;
+  *)
+    if test "$CMK_HAS_READLINK" = '1' -o "$CMK_HAS_REALPATH" = '1'
+    then
+      CMK_CAN_GET_BINARY_PATH='1'
+    else
+      CMK_CAN_GET_BINARY_PATH='0'
+    fi
+    CMK_CAN_OPEN_SHARED_OBJECTS_DYNAMICALLY="$CMK_HAS_DLOPEN"
+    ;;
+esac
+
+if test "$CMK_CAN_OPEN_SHARED_OBJECTS_DYNAMICALLY" = '1' -a "$CMK_CAN_GET_BINARY_PATH" = '1'
+then
+  CMK_SUPPORTS_FSGLOBALS='1'
+else
+  CMK_SUPPORTS_FSGLOBALS='0'
+fi
+AC_DEFINE_UNQUOTED(CMK_SUPPORTS_FSGLOBALS, $CMK_SUPPORTS_FSGLOBALS, [whether supports filesystem globals])
+add_flag "CMK_SUPPORTS_FSGLOBALS=$CMK_SUPPORTS_FSGLOBALS" 'filesystem globals'
+add_make_flag "CMK_SUPPORTS_FSGLOBALS:=$CMK_SUPPORTS_FSGLOBALS" 'filesystem globals'
+
+if test "$CMK_HAS_DLMOPEN" = '1' -a "$CMK_CAN_GET_BINARY_PATH" = '1'
+then
+  CMK_SUPPORTS_PIPGLOBALS='1'
+else
+  CMK_SUPPORTS_PIPGLOBALS='0'
+fi
+AC_DEFINE_UNQUOTED(CMK_SUPPORTS_PIPGLOBALS, $CMK_SUPPORTS_PIPGLOBALS, [whether supports PiP globals])
+add_flag "CMK_SUPPORTS_PIPGLOBALS=$CMK_SUPPORTS_PIPGLOBALS" 'PiP globals'
+add_make_flag "CMK_SUPPORTS_PIPGLOBALS:=$CMK_SUPPORTS_PIPGLOBALS" 'PiP globals'
+
+
 ### test gethostname ####
 cat > $tc <<EOT
 #ifdef _WIN32
index 0db9bd7e9e016092fd2fef5ea654c3c6bdedf83c..3478ecca29db4eeaa3e68d747c0398b2a1d24e2e 100644 (file)
@@ -84,6 +84,7 @@ OPTS_CXX="$OPTS_CXX $USER_OPTS_CXX"
 OPTS_LD="$OPTS_LD $USER_OPTS_LD"
 
 [ -z "$CMK_PIC" ] && CMK_PIC='-fpic'
+[ -z "$CMK_PIE" ] && CMK_PIE='-pie -fPIE'
 
 [ -z "$CMK_SEQ_CC" ] && CMK_SEQ_CC="$CMK_CC"
 [ -z "$CMK_SEQ_CXX" ] && CMK_SEQ_CXX="$CMK_CXX"
index 696310614dd443ff9bd32adfc6e25acb95d73e90..4815750a519d05ccdc5cfa2d4f0ba283a38d204c 100644 (file)
@@ -1,4 +1,5 @@
 -include ../../common.mk
+-include ../../../include/conv-mach-opt.mak
 AMPICC=../../../bin/ampicxx $(OPTS)
 AMPIF90=../../../bin/ampif90 $(OPTS)
 
@@ -14,6 +15,8 @@ VARIANTS := \
   swapglobals \
   tlsglobals \
   roseomptlsglobals \
+  fsglobals \
+  pipglobals \
 
 
 # for determining `all`, `test` rules
@@ -21,6 +24,13 @@ CANDIDATES := \
   swapglobals \
   tlsglobals \
 
+ifeq (1,$(CMK_SUPPORTS_FSGLOBALS))
+  CANDIDATES += fsglobals
+endif
+ifeq (1,$(CMK_SUPPORTS_PIPGLOBALS))
+  CANDIDATES += pipglobals
+endif
+
 
 # Define what options to pass to charmc for each method.
 $(foreach i,$(VARIANTS),$(foreach j,$(LANGUAGES),$(eval OPTS_$j_$i := -$i)))
@@ -29,10 +39,12 @@ OPTS_f90_control :=
 OPTS_f90_tlsglobals += -fopenmp
 
 # Define the features that each privatization method supports.
-FEATURES_cxx_control := staticvars sharedlib dynamiclib
-FEATURES_cxx_swapglobals :=
-FEATURES_cxx_tlsglobals := staticvars sharedlib
-FEATURES_cxx_roseomptlsglobals := staticvars sharedlib
+FEATURES_cxx_control := migration staticvars sharedlib dynamiclib
+FEATURES_cxx_swapglobals := migration
+FEATURES_cxx_tlsglobals := migration staticvars sharedlib
+FEATURES_cxx_roseomptlsglobals := migration staticvars sharedlib
+FEATURES_cxx_fsglobals := staticvars
+FEATURES_cxx_pipglobals := staticvars sharedlib
 
 
 # Determine which methods to test in the current environment and target.
@@ -125,8 +137,10 @@ tlsglobals-test-f90.o: test-f90-tlsglobals.f90
        $(AMPIF90) -o $@ $(OPTS_f90_tlsglobals) -c $<
 
 
+FUNCPTR_SHIM_SUFFIX := .user
+
 clean:
-       rm -f *.o *.a *.so *.mod $(foreach i,$(VARIANTS),$(foreach j,$(LANGUAGES),$j-$i)) charmrun ampirun
+       rm -f *.o *.a *.so *.mod $(foreach i,$(VARIANTS),$(foreach j,$(LANGUAGES),$(strip $j-$i $(wildcard $j-$i$(FUNCPTR_SHIM_SUFFIX)*)))) charmrun ampirun
 
 .SUFFIXES:
 .PHONY: all test everything test-everything $(foreach i,$(VARIANTS),$(foreach j,$(LANGUAGES),test-$j-$i) test-$i $i)
index b7b1d1603fde63ce3770491139dbc7158de716ed..a800b462574004ecd9176ef0fb07703ffe865184 100644 (file)
@@ -56,8 +56,10 @@ void privatization_test_framework(void)
   int failed_before = 0;
   perform_test_batch(failed_before, rank, my_wth);
 
+#if defined test_migration
   if (rank == 0) printf("Requesting migration.\n");
   AMPI_Migrate(AMPI_INFO_LB_SYNC);
+#endif
 
   int failed_after = 0;
   perform_test_batch(failed_after, rank, my_wth);