Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of git+ssh://scm.gforge.inria.fr//gitroot/simgrid/simgrid
authorPierre Veyre <pierre.veyre@cc.in2p3.fr>
Tue, 25 Mar 2014 10:39:44 +0000 (11:39 +0100)
committerPierre Veyre <pierre.veyre@cc.in2p3.fr>
Tue, 25 Mar 2014 10:39:44 +0000 (11:39 +0100)
21 files changed:
buildtools/Cmake/AddTests.cmake
buildtools/Cmake/DefinePackages.cmake
buildtools/Cmake/MakeExe.cmake
buildtools/jenkins/run.sh
buildtools/pipol/Experimental_bindings.sh
buildtools/pipol/MemCheck.sh
buildtools/pipol/Nightly_memCheck.sh
buildtools/pipol/Nightly_simgrid.sh
examples/java/reservationSurfPlugin/CMakeLists.txt [new file with mode: 0644]
examples/java/reservationSurfPlugin/Receiver.java [new file with mode: 0644]
examples/java/reservationSurfPlugin/ReservationPlugin.java [new file with mode: 0644]
examples/java/reservationSurfPlugin/Sender.java [new file with mode: 0644]
examples/java/reservationSurfPlugin/TestPlugin.java [new file with mode: 0644]
examples/java/reservationSurfPlugin/reservationSurfPluginDeployment.xml [new file with mode: 0644]
examples/java/reservationSurfPlugin/reservationSurfPluginPlatform.xml [new file with mode: 0644]
examples/java/reservationSurfPlugin/reservation_surf_plugin.tesh [new file with mode: 0644]
src/bindings/java/surf.i
src/bindings/java/surf_swig.cpp
src/bindings/java/surf_swig.hpp
teshsuite/smpi/mpich3-test/CMakeLists.txt
teshsuite/smpi/mpich3-test/util/mtest_manual.c [new file with mode: 0644]

index a3330e3..03ad3a8 100644 (file)
@@ -30,10 +30,10 @@ endif()
 
 #some tests may take forever on non futexes systems, using busy_wait with n cores < n workers
 # default to posix for these tests if futexes are not supported
-if(NOT HAVE_FUTEX_H) 
+if(NOT HAVE_FUTEX_H)
 SET(CONTEXTS_SYNCHRO --cfg contexts/synchro:posix)
 endif()
+
 
 INCLUDE(CTest)
 ENABLE_TESTING()
@@ -199,7 +199,7 @@ if(NOT enable_memcheck)
   ADD_TEST(msg-masterslave-vivaldi-thread       ${TESH_COMMAND} ${TESH_OPTION} --cfg contexts/factory:thread --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/masterslave/masterslave_vivaldi.tesh)
 
   ADD_TEST(msg-cloud-two-tasks-vm-thread ${TESH_COMMAND} ${TESH_OPTION} --cfg contexts/factory:thread --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/cloud/ --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg/cloud/ --cd ${CMAKE_BINARY_DIR}/examples/msg/cloud/ ${CMAKE_HOME_DIRECTORY}/examples/msg/cloud/two_tasks_vm.tesh)
-  
+
   ADD_TEST(msg-cloud-simple-vm-thread ${TESH_COMMAND} ${TESH_OPTION} --cfg contexts/factory:thread --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/cloud/ --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg/cloud/ --cd ${CMAKE_BINARY_DIR}/examples/msg/cloud/ ${CMAKE_HOME_DIRECTORY}/examples/msg/cloud/simple_vm.tesh)
 
   if(CONTEXT_UCONTEXT)
@@ -624,6 +624,7 @@ if(NOT enable_memcheck)
     ADD_TEST(java-mutualExclusion               ${TESH_COMMAND} ${TESH_OPTION} --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/java --setenv classpath=${TESH_CLASSPATH} --cd ${CMAKE_BINARY_DIR}/examples/java ${CMAKE_HOME_DIRECTORY}/examples/java/mutualExclusion/mutualexclusion.tesh)
     ADD_TEST(java-pingPong                      ${TESH_COMMAND} ${TESH_OPTION} --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/java --setenv classpath=${TESH_CLASSPATH} --cd ${CMAKE_BINARY_DIR}/examples/java ${CMAKE_HOME_DIRECTORY}/examples/java/pingPong/pingpong.tesh)
     ADD_TEST(java-priority                      ${TESH_COMMAND} ${TESH_OPTION} --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/java --setenv classpath=${TESH_CLASSPATH} --cd ${CMAKE_BINARY_DIR}/examples/java ${CMAKE_HOME_DIRECTORY}/examples/java/priority/priority.tesh)
+    ADD_TEST(java-reservation-surf-plugin       ${TESH_COMMAND} ${TESH_OPTION} --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/java --setenv classpath=${TESH_CLASSPATH} --cd ${CMAKE_BINARY_DIR}/examples/java ${CMAKE_HOME_DIRECTORY}/examples/java/reservationSurfPlugin/reservation_surf_plugin.tesh)
     ADD_TEST(java-startKillTime                 ${TESH_COMMAND} ${TESH_OPTION} --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/java --setenv classpath=${TESH_CLASSPATH} --cd ${CMAKE_BINARY_DIR}/examples/java ${CMAKE_HOME_DIRECTORY}/examples/java/startKillTime/startKillTime.tesh)
     ADD_TEST(java-surf-plugin                   ${TESH_COMMAND} ${TESH_OPTION} --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/java --setenv classpath=${TESH_CLASSPATH} --cd ${CMAKE_BINARY_DIR}/examples/java ${CMAKE_HOME_DIRECTORY}/examples/java/surfPlugin/surf_plugin.tesh)
     ADD_TEST(java-suspend                       ${TESH_COMMAND} ${TESH_OPTION} --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/java --setenv classpath=${TESH_CLASSPATH} --cd ${CMAKE_BINARY_DIR}/examples/java ${CMAKE_HOME_DIRECTORY}/examples/java/suspend/suspend.tesh)
index a441a88..2c0e140 100644 (file)
@@ -158,7 +158,7 @@ set(SMPI_SRC
   src/smpi/colls/allgather-smp-simple.c
   src/smpi/colls/allgather-spreading-simple.c
   src/smpi/colls/allgather-ompi-neighborexchange.c
-  src/smpi/colls/allgatherv-GB.c  
+  src/smpi/colls/allgatherv-GB.c
   src/smpi/colls/allgatherv-pair.c
   src/smpi/colls/allgatherv-ring.c
   src/smpi/colls/allgatherv-ompi-neighborexchange.c
@@ -190,10 +190,10 @@ set(SMPI_SRC
   src/smpi/colls/alltoall-ring-light-barrier.c
   src/smpi/colls/alltoall-ring-mpi-barrier.c
   src/smpi/colls/alltoall-ring-one-barrier.c
-  src/smpi/colls/alltoallv-pair.c   
+  src/smpi/colls/alltoallv-pair.c
   src/smpi/colls/alltoallv-pair-light-barrier.c
   src/smpi/colls/alltoallv-pair-mpi-barrier.c
-  src/smpi/colls/alltoallv-pair-one-barrier.c 
+  src/smpi/colls/alltoallv-pair-one-barrier.c
   src/smpi/colls/alltoallv-ring.c
   src/smpi/colls/alltoallv-ring-light-barrier.c
   src/smpi/colls/alltoallv-ring-mpi-barrier.c
@@ -319,7 +319,7 @@ set(SURF_SRC
   src/surf/maxmin.cpp
   src/surf/network_interface.cpp
   src/surf/network_cm02.cpp
-  src/surf/network_smpi.cpp  
+  src/surf/network_smpi.cpp
   src/surf/network_constant.cpp
   src/surf/platf_generator.c
   src/surf/random_mgr.c
@@ -328,7 +328,7 @@ set(SURF_SRC
   src/surf/storage_n11.cpp
   src/surf/surf_interface.cpp
   src/surf/surf_c_bindings.cpp
-  src/surf/surf_routing.cpp  
+  src/surf/surf_routing.cpp
   src/surf/surf_routing_cluster.cpp
   src/surf/surf_routing_cluster_torus.cpp
   src/surf/surf_routing_dijkstra.cpp
@@ -461,9 +461,8 @@ set(JMSG_C_SRC
 
 set(JMSG_JAVA_SRC
   src/bindings/java/org/simgrid/NativeLib.java
-  #src/bindings/java/org/simgrid/NativeException.java
 
-  src/bindings/java/org/simgrid/msg/As.java    
+  src/bindings/java/org/simgrid/msg/As.java
   src/bindings/java/org/simgrid/msg/Comm.java
   src/bindings/java/org/simgrid/msg/File.java
   src/bindings/java/org/simgrid/msg/Host.java
@@ -473,7 +472,7 @@ set(JMSG_JAVA_SRC
   src/bindings/java/org/simgrid/msg/Msg.java
   src/bindings/java/org/simgrid/msg/MsgException.java
   src/bindings/java/org/simgrid/msg/Mutex.java
-  src/bindings/java/org/simgrid/msg/NativeException.java    
+  src/bindings/java/org/simgrid/msg/NativeException.java
   src/bindings/java/org/simgrid/msg/Process.java
   src/bindings/java/org/simgrid/msg/ProcessKilledError.java
   src/bindings/java/org/simgrid/msg/ProcessNotFoundException.java
@@ -500,15 +499,15 @@ set(JSURF_JAVA_GENERATED_SRC
   ${CMAKE_BINARY_DIR}/src/bindings/java/org/simgrid/surf/Plugin.java
   ${CMAKE_BINARY_DIR}/src/bindings/java/org/simgrid/surf/Model.java
   ${CMAKE_BINARY_DIR}/src/bindings/java/org/simgrid/surf/Resource.java
-  ${CMAKE_BINARY_DIR}/src/bindings/java/org/simgrid/surf/Action.java  
+  ${CMAKE_BINARY_DIR}/src/bindings/java/org/simgrid/surf/Action.java
   ${CMAKE_BINARY_DIR}/src/bindings/java/org/simgrid/surf/Cpu.java
-  ${CMAKE_BINARY_DIR}/src/bindings/java/org/simgrid/surf/CpuAction.java  
-  ${CMAKE_BINARY_DIR}/src/bindings/java/org/simgrid/surf/NetworkLink.java  
-  ${CMAKE_BINARY_DIR}/src/bindings/java/org/simgrid/surf/NetworkAction.java  
+  ${CMAKE_BINARY_DIR}/src/bindings/java/org/simgrid/surf/CpuAction.java
+  ${CMAKE_BINARY_DIR}/src/bindings/java/org/simgrid/surf/NetworkLink.java
+  ${CMAKE_BINARY_DIR}/src/bindings/java/org/simgrid/surf/NetworkAction.java
 
-  ${CMAKE_BINARY_DIR}/src/bindings/java/org/simgrid/surf/LmmConstraint.java  
+  ${CMAKE_BINARY_DIR}/src/bindings/java/org/simgrid/surf/LmmConstraint.java
   ${CMAKE_BINARY_DIR}/src/bindings/java/org/simgrid/surf/XbtDict.java
-) 
+)
 
 set(JTRACE_C_SRC
   src/bindings/java/jtrace.c
@@ -832,7 +831,7 @@ set(DOC_SOURCES
   doc/msg-tuto-src/platforms/griffon.xml
   doc/msg-tuto-src/platforms/peers.xml
   doc/msg-tuto-src/platforms/platform.xml
-  
+
   CITATION.bib
   )
 
@@ -908,7 +907,6 @@ set(EXAMPLES_CMAKEFILES_TXT
   examples/java/cloud/CMakeLists.txt
   examples/java/cloud/migration/CMakeLists.txt
   examples/java/commTime/CMakeLists.txt
-  examples/java/surfPlugin/CMakeLists.txt
   examples/java/io/CMakeLists.txt
   examples/java/kademlia/CMakeLists.txt
   examples/java/master_slave_bypass/CMakeLists.txt
@@ -918,7 +916,9 @@ set(EXAMPLES_CMAKEFILES_TXT
   examples/java/mutualExclusion/CMakeLists.txt
   examples/java/pingPong/CMakeLists.txt
   examples/java/priority/CMakeLists.txt
+  examples/java/reservationSurfPlugin/CMakeLists.txt
   examples/java/startKillTime/CMakeLists.txt
+  examples/java/surfPlugin/CMakeLists.txt
   examples/java/suspend/CMakeLists.txt
   examples/java/tracing/CMakeLists.txt
   examples/lua/CMakeLists.txt
index 299103e..a5a5819 100644 (file)
@@ -18,6 +18,7 @@ add_subdirectory(${CMAKE_HOME_DIRECTORY}/examples/java/migration)
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/examples/java/mutualExclusion)
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/examples/java/pingPong)
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/examples/java/priority)
+add_subdirectory(${CMAKE_HOME_DIRECTORY}/examples/java/reservationSurfPlugin)
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/examples/java/startKillTime)
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/examples/java/surfPlugin)
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/examples/java/suspend)
index 96f8afb..c95277c 100755 (executable)
@@ -12,6 +12,8 @@ die () {
   exit $status
 }
 
+ulimit -c 0
+
 rm -rf $WORKSPACE/build
 
 mkdir $WORKSPACE/build
index 7cb21a9..8e7f0ea 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+ulimit -c 0
+
 if [ -e ./pipol ] ; then
        rm -rf ./pipol/$PIPOL_HOST
        mkdir ./pipol/$PIPOL_HOST
index 3247bbc..c696420 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+ulimit -c 0
+
 if [ -e ./pipol ] ; then
        rm -rf ./pipol/$PIPOL_HOST
        mkdir ./pipol/$PIPOL_HOST
index 00ff108..a1720c6 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+ulimit -c 0
+
 #PIPOL esn amd64_2010-linux-ubuntu-maverick.dd.gz none 02:00 --user --silent
 
 if [ -e ./pipol ] ; then
@@ -45,4 +47,4 @@ ctest -D NightlyStart
 ctest -D NightlyConfigure
 ctest -D NightlyBuild
 ctest -D NightlyMemCheck
-ctest -D NightlySubmit
\ No newline at end of file
+ctest -D NightlySubmit
index a19e890..b556483 100755 (executable)
@@ -42,6 +42,8 @@
 #___________________________________________________________________________________________________
 #MacOS Snow Leopard 10.6____________________________________________________________________________
 
+ulimit -c 0
+
 if [ -e ./pipol ] ; then
         rm -rf ./pipol/$PIPOL_HOST
         mkdir ./pipol/$PIPOL_HOST
diff --git a/examples/java/reservationSurfPlugin/CMakeLists.txt b/examples/java/reservationSurfPlugin/CMakeLists.txt
new file mode 100644 (file)
index 0000000..bef5627
--- /dev/null
@@ -0,0 +1,47 @@
+cmake_minimum_required(VERSION 2.6)
+
+set(example java_reservation_surf_plugin)
+set(sources
+   ${CMAKE_CURRENT_SOURCE_DIR}/TestPlugin.java
+   ${CMAKE_CURRENT_SOURCE_DIR}/ReservationPlugin.java
+   ${CMAKE_CURRENT_SOURCE_DIR}/Sender.java
+   ${CMAKE_CURRENT_SOURCE_DIR}/Receiver.java
+  )
+
+if(enable_java)
+  add_custom_command(
+    COMMENT "Building ${example}..."
+    OUTPUT ${example}_compiled
+    DEPENDS ${sources} simgrid-java_jar ${SIMGRID_JAR}
+    COMMAND ${JAVA_COMPILE} -classpath ${SIMGRID_JAR}
+                             -d ${CMAKE_CURRENT_BINARY_DIR}/.. ${sources}
+    COMMAND ${CMAKE_COMMAND} -E remove ${example}_compiled
+    COMMAND ${CMAKE_COMMAND} -E touch ${example}_compiled
+  )
+  add_custom_target(${example} ALL DEPENDS ${example}_compiled)
+endif()
+
+set(tesh_files
+  ${tesh_files}
+  ${CMAKE_CURRENT_SOURCE_DIR}/reservation_surf_plugin.tesh
+  PARENT_SCOPE
+  )
+set(xml_files
+  ${xml_files}
+  ${CMAKE_CURRENT_SOURCE_DIR}/reservationSurfPluginPlatform.xml
+  ${CMAKE_CURRENT_SOURCE_DIR}/reservationSurfPluginDeployment.xml
+  PARENT_SCOPE
+  )
+set(examples_src
+  ${examples_src}
+  ${sources}
+  PARENT_SCOPE
+  )
+set(bin_files
+  ${bin_files}
+  PARENT_SCOPE
+  )
+set(txt_files
+  ${txt_files}
+  PARENT_SCOPE
+  )
diff --git a/examples/java/reservationSurfPlugin/Receiver.java b/examples/java/reservationSurfPlugin/Receiver.java
new file mode 100644 (file)
index 0000000..cd66bb4
--- /dev/null
@@ -0,0 +1,36 @@
+/* Copyright (c) 2006-2014. The SimGrid Team.
+ * All rights reserved.                                                     */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+package reservationSurfPlugin;
+import org.simgrid.msg.Host;
+import org.simgrid.msg.Msg;
+import org.simgrid.msg.MsgException;
+import org.simgrid.msg.Task;
+import org.simgrid.msg.Process;
+
+public class Receiver extends Process {
+   public Receiver(Host host, String name, String[]args) {
+               super(host,name,args);
+   }
+   final double commSizeLat = 1;
+   final double commSizeBw = 100000000;
+
+   public void main(String[] args) throws MsgException {
+
+      Msg.info("helloo!");
+      double communicationTime=0;
+
+      Msg.info("try to get a task");
+
+      Task task = Task.receive(getHost().getName());
+      double timeGot = Msg.getClock();
+
+      Msg.info("Got at time "+ timeGot);
+      task.execute();
+
+      Msg.info("goodbye!");
+    }
+}
diff --git a/examples/java/reservationSurfPlugin/ReservationPlugin.java b/examples/java/reservationSurfPlugin/ReservationPlugin.java
new file mode 100644 (file)
index 0000000..0bd91aa
--- /dev/null
@@ -0,0 +1,61 @@
+package reservationSurfPlugin;
+
+import org.simgrid.surf.*;
+import org.simgrid.msg.Msg;
+import java.util.HashMap;
+
+public class ReservationPlugin extends Plugin {
+
+  public ReservationPlugin() {
+    activateCpuCreatedCallback();
+    activateCpuDestructedCallback();
+    activateCpuStateChangedCallback();
+    activateCpuActionStateChangedCallback();
+
+    activateNetworkLinkCreatedCallback();
+    activateNetworkLinkDestructedCallback();
+    activateNetworkLinkStateChangedCallback();
+    activateNetworkActionStateChangedCallback();
+
+  }
+
+  public void init() {
+    NetworkLink[] route = Surf.getRoute("Jacquelin", "Boivin");
+    Msg.info("RouteLength:"+route.length);
+    Msg.info("RouteName0:"+route[0].getName());
+    Msg.info("RouteName1:"+route[1].getName());
+  }
+
+  public void cpuCreatedCallback(Cpu cpu) {
+    Msg.info("Trace: Cpu created "+cpu.getName());
+  }
+
+  public void cpuDestructedCallback(Cpu cpu) {
+    Msg.info("Trace: Cpu destructed "+cpu.getName());
+  }
+
+  public void cpuStateChangedCallback(Cpu cpu){
+    Msg.info("Trace: Cpu state changed "+cpu.getName());
+  }
+
+  public void cpuActionStateChangedCallback(CpuAction action){
+    Msg.info("Trace: CpuAction state changed "+action.getModel().getName());
+  }
+
+  public void networkLinkCreatedCallback(NetworkLink link) {
+    Msg.info("Trace: NetworkLink created "+link.getName());
+  }
+
+  public void networkLinkDestructedCallback(NetworkLink link) {
+    Msg.info("Trace: NetworkLink destructed "+link.getName());
+  }
+
+  public void networkLinkStateChangedCallback(NetworkLink link){
+    Msg.info("Trace: NetworkLink state changed "+link.getName());
+  }
+
+  public void networkActionStateChangedCallback(NetworkAction action){
+    Msg.info("Trace: NetworkAction state changed "+action.getModel().getName());
+  }
+
+}
diff --git a/examples/java/reservationSurfPlugin/Sender.java b/examples/java/reservationSurfPlugin/Sender.java
new file mode 100644 (file)
index 0000000..6f5ccf4
--- /dev/null
@@ -0,0 +1,55 @@
+/* Copyright (c) 2006-2014. The SimGrid Team.
+ * All rights reserved.                                                     */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+package reservationSurfPlugin;
+import org.simgrid.msg.Host;
+import org.simgrid.msg.HostNotFoundException;
+import org.simgrid.msg.Msg;
+import org.simgrid.msg.MsgException;
+import org.simgrid.msg.Process;
+import org.simgrid.msg.Task;
+
+public class Sender extends Process {
+       public Sender(Host host, String name, String[] args) {
+               super(host,name,args);
+       }
+    private final double commSizeLat = 1;
+    final double commSizeBw = 100000000;
+
+    public void main(String[] args) throws MsgException {
+
+       Msg.info("helloo!");
+
+       int hostCount = args.length;
+
+       Msg.info("host count: " + hostCount);
+       String mailboxes[] = new String[hostCount];
+       double time;
+       double computeDuration = 10000;
+       Task task;
+
+       for(int pos = 0; pos < args.length ; pos++) {
+         try {
+            mailboxes[pos] = Host.getByName(args[pos]).getName();
+         } catch (HostNotFoundException e) {
+            Msg.info("Invalid deployment file: " + e.toString());
+            System.exit(1);
+         }
+        }
+
+        for (int pos = 0; pos < hostCount; pos++) {
+          time = Msg.getClock();
+
+          Msg.info("sender time: " + time);
+
+          task = new Task("no name",computeDuration,commSizeLat);
+
+          task.send(mailboxes[pos]);
+        }
+
+        Msg.info("goodbye!");
+    }
+}
diff --git a/examples/java/reservationSurfPlugin/TestPlugin.java b/examples/java/reservationSurfPlugin/TestPlugin.java
new file mode 100644 (file)
index 0000000..cedbb04
--- /dev/null
@@ -0,0 +1,38 @@
+/* Copyright (c) 2006-2014. The SimGrid Team.
+ * All rights reserved.                                                     */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+package reservationSurfPlugin;
+import org.simgrid.msg.Msg;
+import org.simgrid.msg.NativeException;
+import org.simgrid.surf.Surf;
+import org.simgrid.surf.Cpu;
+
+public class TestPlugin {
+
+  /* This only contains the launcher. If you do nothing more than than you can run
+  *   java simgrid.msg.Msg
+  * which also contains such a launcher
+  */
+  static ReservationPlugin tp = new ReservationPlugin();
+
+  public static void main(String[] args) throws NativeException {
+    /* initialize the MSG simulation. Must be done before anything else (even logging). */
+    Msg.init(args);
+    if(args.length < 2) {
+      Msg.info("Usage   : TestPlugin platform_file deployment_file");
+      Msg.info("example : TestPlugin ping_pong_platform.xml ping_pong_deployment.xml");
+      System.exit(1);
+    }
+    /* construct the platform and deploy the application */
+    Msg.createEnvironment(args[0]);
+    Msg.deployApplication(args[1]);
+    tp.init();
+
+    // getName());
+    /*  execute the simulation. */
+    Msg.run();
+  }
+}
diff --git a/examples/java/reservationSurfPlugin/reservationSurfPluginDeployment.xml b/examples/java/reservationSurfPlugin/reservationSurfPluginDeployment.xml
new file mode 100644 (file)
index 0000000..9101480
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version='1.0'?>
+<!DOCTYPE platform SYSTEM "http://simgrid.gforge.inria.fr/simgrid.dtd">
+<platform version="3">
+  <process host="Jacquelin" function="surfPlugin.Sender">
+      <argument value="Boivin"/>
+  </process>
+<process host="Boivin" function="surfPlugin.Receiver"/>
+</platform>
diff --git a/examples/java/reservationSurfPlugin/reservationSurfPluginPlatform.xml b/examples/java/reservationSurfPlugin/reservationSurfPluginPlatform.xml
new file mode 100644 (file)
index 0000000..2712607
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version='1.0'?>
+ <!DOCTYPE platform SYSTEM "http://simgrid.gforge.inria.fr/simgrid.dtd">
+ <platform version="3">
+ <AS  id="AS0"  routing="Full">
+   <host id="Jacquelin" power="137.333Mf"/>
+   <host id="Boivin" power="98.095Mf"/>
+   <host id="TeX" power="68.667Mf"/>
+   <link id="link0" bandwidth="1MBps" latency="100ms"/>
+   <link id="link1" bandwidth="1MBps" latency="100ms"/>
+   <link id="link2" bandwidth="1MBps" latency="100ms"/>
+   <route src="Jacquelin" dst="Boivin">
+     <link_ctn id="link0"/>
+     <link_ctn id="link1"/>
+   </route>
+   <route src="Jacquelin" dst="TeX">
+     <link_ctn id="link0"/>
+     <link_ctn id="link2"/>
+   </route>
+
+ </AS>
+ </platform>
diff --git a/examples/java/reservationSurfPlugin/reservation_surf_plugin.tesh b/examples/java/reservationSurfPlugin/reservation_surf_plugin.tesh
new file mode 100644 (file)
index 0000000..012094f
--- /dev/null
@@ -0,0 +1,27 @@
+#! tesh
+
+$ java -classpath ${classpath:=.} reservationSurfPlugin/TestPlugin ${srcdir:=.}/reservationSurfPlugin/reservationSurfPluginPlatform.xml ${srcdir:=.}/reservationSurfPlugin/reservationSurfPluginDeployment.xml
+> [0.000000] [jmsg/INFO] Using regular java threads. Coroutines could speed your simulation up.
+> [0.000000] [jmsg/INFO] Trace: NetworkLink created __loopback__
+> [0.000000] [jmsg/INFO] Trace: NetworkLink state changed __loopback__
+> [0.000000] [jmsg/INFO] Trace: Cpu created Jacquelin
+> [0.000000] [jmsg/INFO] Trace: Cpu state changed Jacquelin
+> [0.000000] [jmsg/INFO] Trace: Cpu created Boivin
+> [0.000000] [jmsg/INFO] Trace: Cpu state changed Boivin
+> [0.000000] [jmsg/INFO] Trace: NetworkLink created link
+> [0.000000] [jmsg/INFO] Trace: NetworkLink state changed link
+> [Jacquelin:surfPlugin.Sender:(1) 0.000000] [jmsg/INFO] helloo!
+> [Jacquelin:surfPlugin.Sender:(1) 0.000000] [jmsg/INFO] host count: 1
+> [Jacquelin:surfPlugin.Sender:(1) 0.000000] [jmsg/INFO] sender time: 0.0
+> [Boivin:surfPlugin.Receiver:(2) 0.000000] [jmsg/INFO] helloo!
+> [Boivin:surfPlugin.Receiver:(2) 0.000000] [jmsg/INFO] try to get a task
+> [1.301001] [jmsg/INFO] Trace: NetworkAction state changed network
+> [Boivin:surfPlugin.Receiver:(2) 1.301001] [jmsg/INFO] Got at time 1.3010010824742269
+> [Jacquelin:surfPlugin.Sender:(1) 1.301001] [jmsg/INFO] goodbye!
+> [1.301103] [jmsg/INFO] Trace: CpuAction state changed cpu
+> [Boivin:surfPlugin.Receiver:(2) 1.301103] [jmsg/INFO] goodbye!
+> [1.301103] [jmsg/INFO] MSG_main finished; Cleaning up the simulation...
+> [1.301103] [jmsg/INFO] Trace: Cpu destructed Jacquelin
+> [1.301103] [jmsg/INFO] Trace: Cpu destructed Boivin
+> [1.301103] [jmsg/INFO] Trace: NetworkLink destructed link
+> [1.301103] [jmsg/INFO] Trace: NetworkLink destructed __loopback__
index 3fc9033..d860b98 100644 (file)
@@ -1,9 +1,10 @@
 /* File : example.i */
 %module(directors="1") Surf
 
+%include "arrays_java.i"
+
 %pragma(java) jniclassimports=%{
 import org.simgrid.NativeLib;
-
 %}
 %pragma(java) jniclasscode=%{
   static {
@@ -27,6 +28,24 @@ import org.simgrid.NativeLib;
 typedef struct lmm_constraint *lmm_constraint_t;
 %}
 
+/* Handle xbt_dynar_t of NetworkLink */
+JAVA_ARRAYSOFCLASSES(NetworkLink);
+%apply NetworkLink[] {NetworkLinkDynar};
+%typemap(jstype) NetworkLinkDynar "NetworkLink[]"
+%typemap(javain) NetworkLinkDynar "NetworkLink.cArrayUnwrap($javainput)"
+
+%typemap(javaout) NetworkLinkDynar {
+     return NetworkLink.cArrayWrap($jnicall, $owner);
+}
+%typemap(out) NetworkLinkDynar {
+  long l = xbt_dynar_length($1);
+  $result = jenv->NewLongArray(l);
+  NetworkLink **lout = (NetworkLink **)xbt_dynar_to_array($1);
+  jenv->SetLongArrayRegion($result, 0, l, (const jlong*)lout);
+  free(lout);
+}
+
+/* Allow to subclass Plugin and send java object to C++ code */
 %feature("director") Plugin;
 
 %include "src/bindings/java/surf_swig.hpp"
@@ -79,7 +98,6 @@ public:
 }
 };
 
-
 %rename lmm_constraint LmmConstraint;
 struct lmm_constraint {
 %extend {
@@ -93,4 +111,3 @@ struct s_xbt_dict {
   char *getValue(char *key) {return (char*)xbt_dict_get_or_null($self, key);}
 }
 };
-
index b5a376f..32f557f 100644 (file)
@@ -12,6 +12,24 @@ void clean() {
   SIMIX_clean();
 }
 
+/*NetworkModel *getNetworkModel()
+{
+  return surf_network_model;
+}*/
+
+NetworkLinkDynar getRoute(char *srcName, char *dstName) {
+  RoutingEdge *src = (RoutingEdge*)xbt_lib_get_or_null(host_lib, srcName, ROUTING_HOST_LEVEL);
+  RoutingEdge *dst = (RoutingEdge*)xbt_lib_get_or_null(host_lib, dstName, ROUTING_HOST_LEVEL);
+  if (src==NULL)
+    xbt_die("TOTO");
+  if (dst==NULL)
+    xbt_die("TOTO");
+  printf("src: %s\ndst: %s\n", src->getName(), dst->getName());
+  xbt_dynar_t route = xbt_dynar_new(sizeof(RoutingEdgePtr), NULL);
+  routing_platf->getRouteAndLatency(src, dst, &route, NULL);
+  return route;
+}
+
 void Plugin::activateCpuCreatedCallback(){
   surf_callback_connect(cpuCreatedCallbacks, boost::bind(&Plugin::cpuCreatedCallback, this, _1));
 }
index 39eb67d..1c51c7b 100644 (file)
@@ -4,15 +4,13 @@
 #include "src/surf/network_interface.hpp"
 #include "src/surf/maxmin_private.hpp"
 
+typedef xbt_dynar_t NetworkLinkDynar;
+
 double getClock();
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 void clean();
-#ifdef __cplusplus
-}
-#endif
+
+NetworkLinkDynar getRoute(char *srcName, char *dstName);
 
 class Plugin {
 public:
index f8b8f8e..153598d 100644 (file)
@@ -40,6 +40,7 @@ set(txt_files
   ${CMAKE_CURRENT_SOURCE_DIR}/hostfile
   ${CMAKE_CURRENT_SOURCE_DIR}/checktests
   ${CMAKE_CURRENT_SOURCE_DIR}/util/mtest.c
+  ${CMAKE_CURRENT_SOURCE_DIR}/util/mtest_manual.c
   ${CMAKE_CURRENT_SOURCE_DIR}/f77/testlist
   ${CMAKE_CURRENT_SOURCE_DIR}/f90/testlist
   ${CMAKE_CURRENT_SOURCE_DIR}/include/mpitestconf.h
@@ -59,8 +60,10 @@ set(EXECUTABLE_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}")
 include_directories("${CMAKE_HOME_DIRECTORY}/include/smpi")
 include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include/")
 
-#C version
+#C version - use automatic privatization if mmap is supported, manual through SMPI macros if not
+if(HAVE_MMAP)
 add_library(mtest_c STATIC util/mtest.c)
-
-
+else()
+add_library(mtest_c STATIC util/mtest_manual.c)
+endif()
 
diff --git a/teshsuite/smpi/mpich3-test/util/mtest_manual.c b/teshsuite/smpi/mpich3-test/util/mtest_manual.c
new file mode 100644 (file)
index 0000000..e922072
--- /dev/null
@@ -0,0 +1,1716 @@
+/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
+/*
+ *
+ *  (C) 2001 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+#include "mpi.h"
+#include "mpitestconf.h"
+#include "mpitest.h"
+#include "smpi_cocci.h"
+#if defined(HAVE_STDIO_H) || defined(STDC_HEADERS)
+#include <stdio.h>
+#endif
+#if defined(HAVE_STDLIB_H) || defined(STDC_HEADERS)
+#include <stdlib.h>
+#endif
+#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
+#include <string.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+/* The following two includes permit the collection of resource usage
+   data in the tests
+ */
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+#include <errno.h>
+
+
+/*
+ * Utility routines for writing MPI tests.
+ *
+ * We check the return codes on all MPI routines (other than INIT)
+ * to allow the program that uses these routines to select MPI_ERRORS_RETURN
+ * as the error handler.  We do *not* set MPI_ERRORS_RETURN because
+ * the code that makes use of these routines may not check return
+ * codes.
+ * 
+ */
+
+static void MTestRMACleanup( void );
+static void MTestResourceSummary( FILE * );
+
+/* Here is where we could put the includes and definitions to enable
+   memory testing */
+
+SMPI_VARINIT_GLOBAL_AND_SET(dbgflag, int, 0); /* Flag used for debugging */
+SMPI_VARINIT_GLOBAL_AND_SET(wrank, int, -1);  /* World rank */
+SMPI_VARINIT_GLOBAL_AND_SET(verbose, int, 0); /* Message level (0 is none) */
+SMPI_VARINIT_GLOBAL_AND_SET(returnWithVal, int, 0); /* Allow programs to return
+                                  with a non-zero if there was an error (may
+                                  cause problems with some runtime systems) */
+SMPI_VARINIT_GLOBAL_AND_SET(usageOutput, int, 0); /* */
+
+/* Provide backward portability to MPI 1 */
+#ifndef MPI_VERSION
+#define MPI_VERSION 1
+#endif
+#if MPI_VERSION < 2
+#define MPI_THREAD_SINGLE 0
+#endif
+
+/* 
+ * Initialize and Finalize MTest
+ */
+
+/*
+   Initialize MTest, initializing MPI if necessary.  
+
+ Environment Variables:
++ MPITEST_DEBUG - If set (to any value), turns on debugging output
+. MPITEST_THREADLEVEL_DEFAULT - If set, use as the default "provided"
+                                level of thread support.  Applies to 
+                                MTest_Init but not MTest_Init_thread.
+- MPITEST_VERBOSE - If set to a numeric value, turns on that level of
+  verbose output.  This is used by the routine 'MTestPrintfMsg'
+
+*/
+void MTest_Init_thread( int *argc, char ***argv, int required, int *provided )
+{
+    int flag;
+    char *envval = 0;
+
+    MPI_Initialized( &flag );
+    if (!flag) {
+       /* Permit an MPI that claims only MPI 1 but includes the 
+          MPI_Init_thread routine (e.g., IBM MPI) */
+#if MPI_VERSION >= 2 || defined(HAVE_MPI_INIT_THREAD)
+       MPI_Init_thread( argc, argv, required, provided );
+#else
+       MPI_Init( argc, argv );
+       *provided = -1;
+#endif
+    }
+    /* Check for debugging control */
+    if (getenv( "MPITEST_DEBUG" )) {
+       SMPI_VARGET_GLOBAL(dbgflag) = 1;
+       MPI_Comm_rank( MPI_COMM_WORLD, &SMPI_VARGET_GLOBAL(wrank) );
+    }
+
+    /* Check for verbose control */
+    envval = getenv( "MPITEST_VERBOSE" );
+    if (envval) {
+       char *s;
+       long val = strtol( envval, &s, 0 );
+       if (s == envval) {
+           /* This is the error case for strtol */
+           fprintf( stderr, "Warning: %s not valid for MPITEST_VERBOSE\n", 
+                    envval );
+           fflush( stderr );
+       }
+       else {
+           if (val >= 0) {
+               SMPI_VARGET_GLOBAL(verbose) = val;
+           }
+           else {
+               fprintf( stderr, "Warning: %s not valid for MPITEST_VERBOSE\n", 
+                        envval );
+               fflush( stderr );
+           }
+       }
+    }
+    /* Check for option to return success/failure in the return value of main */
+    envval = getenv( "MPITEST_RETURN_WITH_CODE" );
+    if (envval) {
+       if (strcmp( envval, "yes" ) == 0 ||
+           strcmp( envval, "YES" ) == 0 ||
+           strcmp( envval, "true" ) == 0 ||
+           strcmp( envval, "TRUE" ) == 0) {
+           SMPI_VARGET_GLOBAL(returnWithVal) = 1;
+       }
+       else if (strcmp( envval, "no" ) == 0 ||
+           strcmp( envval, "NO" ) == 0 ||
+           strcmp( envval, "false" ) == 0 ||
+           strcmp( envval, "FALSE" ) == 0) {
+           SMPI_VARGET_GLOBAL(returnWithVal) = 0;
+       }
+       else {
+           fprintf( stderr, 
+                    "Warning: %s not valid for MPITEST_RETURN_WITH_CODE\n", 
+                    envval );
+           fflush( stderr );
+       }
+    }
+    
+    /* Print rusage data if set */
+    if (getenv( "MPITEST_RUSAGE" )) {
+       SMPI_VARGET_GLOBAL(usageOutput) = 1;
+    }
+}
+/* 
+ * Initialize the tests, using an MPI-1 style init.  Supports 
+ * MTEST_THREADLEVEL_DEFAULT to test with user-specified thread level
+ */
+void MTest_Init( int *argc, char ***argv )
+{
+    int provided;
+#if MPI_VERSION >= 2 || defined(HAVE_MPI_INIT_THREAD)
+    const char *str = 0;
+    int        threadLevel;
+
+    threadLevel = MPI_THREAD_SINGLE;
+    str = getenv( "MTEST_THREADLEVEL_DEFAULT" );
+    if (!str) str = getenv( "MPITEST_THREADLEVEL_DEFAULT" );
+    if (str && *str) {
+       if (strcmp(str,"MULTIPLE") == 0 || strcmp(str,"multiple") == 0) {
+           threadLevel = MPI_THREAD_MULTIPLE;
+       }
+       else if (strcmp(str,"SERIALIZED") == 0 || 
+                strcmp(str,"serialized") == 0) {
+           threadLevel = MPI_THREAD_SERIALIZED;
+       }
+       else if (strcmp(str,"FUNNELED") == 0 || strcmp(str,"funneled") == 0) {
+           threadLevel = MPI_THREAD_FUNNELED;
+       }
+       else if (strcmp(str,"SINGLE") == 0 || strcmp(str,"single") == 0) {
+           threadLevel = MPI_THREAD_SINGLE;
+       }
+       else {
+           fprintf( stderr, "Unrecognized thread level %s\n", str );
+           /* Use exit since MPI_Init/Init_thread has not been called. */
+           exit(1);
+       }
+    }
+    MTest_Init_thread( argc, argv, threadLevel, &provided );
+#else
+    /* If the MPI_VERSION is 1, there is no MPI_THREAD_xxx defined */
+    MTest_Init_thread( argc, argv, 0, &provided );
+#endif    
+}
+
+/*
+  Finalize MTest.  errs is the number of errors on the calling process; 
+  this routine will write the total number of errors over all of MPI_COMM_WORLD
+  to the process with rank zero, or " No Errors".
+  It does *not* finalize MPI.
+ */
+void MTest_Finalize( int errs )
+{
+    int rank, toterrs, merr;
+
+    merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+    if (merr) MTestPrintError( merr );
+
+    merr = MPI_Reduce( &errs, &toterrs, 1, MPI_INT, MPI_SUM, 
+                     0, MPI_COMM_WORLD );
+    if (merr) MTestPrintError( merr );
+    if (rank == 0) {
+       if (toterrs) {
+           printf( " Found %d errors\n", toterrs );
+       }
+       else {
+           printf( " No Errors\n" );
+       }
+       fflush( stdout );
+    }
+    
+    if (SMPI_VARGET_GLOBAL(usageOutput))
+       MTestResourceSummary( stdout );
+
+
+    /* Clean up any persistent objects that we allocated */
+    MTestRMACleanup();
+}
+/* ------------------------------------------------------------------------ */
+/* This routine may be used instead of "return 0;" at the end of main; 
+   it allows the program to use the return value to signal success or failure. 
+ */
+int MTestReturnValue( int errors )
+{
+    if (SMPI_VARGET_GLOBAL(returnWithVal)) return errors ? 1 : 0;
+    return 0;
+}
+/* ------------------------------------------------------------------------ */
+
+/*
+ * Miscellaneous utilities, particularly to eliminate OS dependencies
+ * from the tests.
+ * MTestSleep( seconds )
+ */
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+void MTestSleep( int sec )
+{
+    Sleep( 1000 * sec );
+}
+#else
+#include <unistd.h>
+void MTestSleep( int sec )
+{
+    sleep( sec );
+}
+#endif
+
+/*
+ * Datatypes
+ *
+ * Eventually, this could read a description of a file.  For now, we hard 
+ * code the choices.
+ *
+ * Each kind of datatype has the following functions:
+ *    MTestTypeXXXInit     - Initialize a send buffer for that type
+ *    MTestTypeXXXInitRecv - Initialize a receive buffer for that type
+ *    MTestTypeXXXFree     - Free any buffers associate with that type
+ *    MTestTypeXXXCheckbuf - Check that the buffer contains the expected data
+ * These routines work with (nearly) any datatype that is of type XXX, 
+ * allowing the test codes to create a variety of contiguous, vector, and
+ * indexed types, then test them by calling these routines.
+ *
+ * Available types (for the XXX) are
+ *    Contig   - Simple contiguous buffers
+ *    Vector   - Simple strided "vector" type
+ *    Indexed  - Indexed datatype.  Only for a count of 1 instance of the 
+ *               datatype
+ */
+SMPI_VARINIT_GLOBAL_AND_SET(datatype_index, int, 0);
+
+/* ------------------------------------------------------------------------ */
+/* Datatype routines for contiguous datatypes                               */
+/* ------------------------------------------------------------------------ */
+/* 
+ * Setup contiguous buffers of n copies of a datatype.
+ */
+static void *MTestTypeContigInit( MTestDatatype *mtype )
+{
+    MPI_Aint size;
+    int merr;
+
+    if (mtype->count > 0) {
+       signed char *p;
+       int  i, totsize;
+       merr = MPI_Type_extent( mtype->datatype, &size );
+       if (merr) MTestPrintError( merr );
+       totsize = size * mtype->count;
+       if (!mtype->buf) {
+           mtype->buf = (void *) malloc( totsize );
+       }
+       p = (signed char *)(mtype->buf);
+       if (!p) {
+           /* Error - out of memory */
+           MTestError( "Out of memory in type buffer init" );
+       }
+       for (i=0; i<totsize; i++) {
+           p[i] = 0xff ^ (i & 0xff);
+       }
+    }
+    else {
+       if (mtype->buf) {
+           free( mtype->buf );
+       }
+       mtype->buf = 0;
+    }
+    return mtype->buf;
+}
+
+/* 
+ * Setup contiguous buffers of n copies of a datatype.  Initialize for
+ * reception (e.g., set initial data to detect failure)
+ */
+static void *MTestTypeContigInitRecv( MTestDatatype *mtype )
+{
+    MPI_Aint size;
+    int      merr;
+
+    if (mtype->count > 0) {
+       signed char *p;
+       int  i, totsize;
+       merr = MPI_Type_extent( mtype->datatype, &size );
+       if (merr) MTestPrintError( merr );
+       totsize = size * mtype->count;
+       if (!mtype->buf) {
+           mtype->buf = (void *) malloc( totsize );
+       }
+       p = (signed char *)(mtype->buf);
+       if (!p) {
+           /* Error - out of memory */
+           MTestError( "Out of memory in type buffer init" );
+       }
+       for (i=0; i<totsize; i++) {
+           p[i] = 0xff;
+       }
+    }
+    else {
+       if (mtype->buf) {
+           free( mtype->buf );
+       }
+       mtype->buf = 0;
+    }
+    return mtype->buf;
+}
+static void *MTestTypeContigFree( MTestDatatype *mtype )
+{
+    if (mtype->buf) {
+       free( mtype->buf );
+       mtype->buf = 0;
+    }
+    return 0;
+}
+static int MTestTypeContigCheckbuf( MTestDatatype *mtype )
+{
+    unsigned char *p;
+    unsigned char expected;
+    int  i, totsize, err = 0, merr;
+    MPI_Aint size;
+
+    p = (unsigned char *)mtype->buf;
+    if (p) {
+       merr = MPI_Type_extent( mtype->datatype, &size );
+       if (merr) MTestPrintError( merr );
+       totsize = size * mtype->count;
+       for (i=0; i<totsize; i++) {
+           expected = (0xff ^ (i & 0xff));
+           if (p[i] != expected) {
+               err++;
+               if (mtype->printErrors && err < 10) {
+                   printf( "Data expected = %x but got p[%d] = %x\n",
+                           expected, i, p[i] );
+                   fflush( stdout );
+               }
+           }
+       }
+    }
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+/* Datatype routines for vector datatypes                                   */
+/* ------------------------------------------------------------------------ */
+
+static void *MTestTypeVectorInit( MTestDatatype *mtype )
+{
+    MPI_Aint size;
+    int      merr;
+
+    if (mtype->count > 0) {
+       unsigned char *p;
+       int  i, j, k, nc, totsize;
+
+       merr = MPI_Type_extent( mtype->datatype, &size );
+       if (merr) MTestPrintError( merr );
+       totsize    = mtype->count * size;
+       if (!mtype->buf) {
+           mtype->buf = (void *) malloc( totsize );
+       }
+       p          = (unsigned char *)(mtype->buf);
+       if (!p) {
+           /* Error - out of memory */
+           MTestError( "Out of memory in type buffer init" );
+       }
+
+       /* First, set to -1 */
+       for (i=0; i<totsize; i++) p[i] = 0xff;
+
+       /* Now, set the actual elements to the successive values.
+          To do this, we need to run 3 loops */
+       nc = 0;
+       /* count is usually one for a vector type */
+       for (k=0; k<mtype->count; k++) {
+           /* For each element (block) */
+           for (i=0; i<mtype->nelm; i++) {
+               /* For each value */
+               for (j=0; j<mtype->blksize; j++) {
+                   p[j] = (0xff ^ (nc & 0xff));
+                   nc++;
+               }
+               p += mtype->stride;
+           }
+       }
+    }
+    else {
+       mtype->buf = 0;
+    }
+    return mtype->buf;
+}
+
+static void *MTestTypeVectorFree( MTestDatatype *mtype )
+{
+    if (mtype->buf) {
+       free( mtype->buf );
+       mtype->buf = 0;
+    }
+    return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+/* Datatype routines for indexed block datatypes                            */
+/* ------------------------------------------------------------------------ */
+
+/* 
+ * Setup a buffer for one copy of an indexed datatype. 
+ */
+static void *MTestTypeIndexedInit( MTestDatatype *mtype )
+{
+    MPI_Aint totsize;
+    int      merr;
+    
+    if (mtype->count > 1) {
+       MTestError( "This datatype is supported only for a single count" );
+    }
+    if (mtype->count == 1) {
+       signed char *p;
+       int  i, k, offset, j;
+
+       /* Allocate the send/recv buffer */
+       merr = MPI_Type_extent( mtype->datatype, &totsize );
+       if (merr) MTestPrintError( merr );
+       if (!mtype->buf) {
+           mtype->buf = (void *) malloc( totsize );
+       }
+       p = (signed char *)(mtype->buf);
+       if (!p) {
+           MTestError( "Out of memory in type buffer init\n" );
+       }
+       /* Initialize the elements */
+       /* First, set to -1 */
+       for (i=0; i<totsize; i++) p[i] = 0xff;
+
+       /* Now, set the actual elements to the successive values.
+          We require that the base type is a contiguous type */
+       k = 0;
+       for (i=0; i<mtype->nelm; i++) {
+           int b;
+           /* Compute the offset: */
+           offset = mtype->displs[i] * mtype->basesize;
+           /* For each element in the block */
+           for (b=0; b<mtype->index[i]; b++) {
+               for (j=0; j<mtype->basesize; j++) {
+                   p[offset+j] = 0xff ^ (k++ & 0xff);
+               }
+               offset += mtype->basesize;
+           }
+       }
+    }
+    else {
+       /* count == 0 */
+       if (mtype->buf) {
+           free( mtype->buf );
+       }
+       mtype->buf = 0;
+    }
+    return mtype->buf;
+}
+
+/* 
+ * Setup indexed buffers for 1 copy of a datatype.  Initialize for
+ * reception (e.g., set initial data to detect failure)
+ */
+static void *MTestTypeIndexedInitRecv( MTestDatatype *mtype )
+{
+    MPI_Aint totsize;
+    int      merr;
+
+    if (mtype->count > 1) {
+       MTestError( "This datatype is supported only for a single count" );
+    }
+    if (mtype->count == 1) {
+       signed char *p;
+       int  i;
+       merr = MPI_Type_extent( mtype->datatype, &totsize );
+       if (merr) MTestPrintError( merr );
+       if (!mtype->buf) {
+           mtype->buf = (void *) malloc( totsize );
+       }
+       p = (signed char *)(mtype->buf);
+       if (!p) {
+           /* Error - out of memory */
+           MTestError( "Out of memory in type buffer init\n" );
+       }
+       for (i=0; i<totsize; i++) {
+           p[i] = 0xff;
+       }
+    }
+    else {
+       /* count == 0 */
+       if (mtype->buf) {
+           free( mtype->buf );
+       }
+       mtype->buf = 0;
+    }
+    return mtype->buf;
+}
+
+static void *MTestTypeIndexedFree( MTestDatatype *mtype )
+{
+    if (mtype->buf) {
+       free( mtype->buf );
+       free( mtype->displs );
+       free( mtype->index );
+       mtype->buf    = 0;
+       mtype->displs = 0;
+       mtype->index  = 0;
+    }
+    return 0;
+}
+
+static int MTestTypeIndexedCheckbuf( MTestDatatype *mtype )
+{
+    unsigned char *p;
+    unsigned char expected;
+    int  i, err = 0, merr;
+    MPI_Aint totsize;
+
+    p = (unsigned char *)mtype->buf;
+    if (p) {
+       int j, k, offset;
+       merr = MPI_Type_extent( mtype->datatype, &totsize );
+       if (merr) MTestPrintError( merr );
+       
+       k = 0;
+       for (i=0; i<mtype->nelm; i++) {
+           int b;
+           /* Compute the offset: */
+           offset = mtype->displs[i] * mtype->basesize;
+           for (b=0; b<mtype->index[i]; b++) {
+               for (j=0; j<mtype->basesize; j++) {
+                   expected = (0xff ^ (k & 0xff));
+                   if (p[offset+j] != expected) {
+                       err++;
+                       if (mtype->printErrors && err < 10) {
+                           printf( "Data expected = %x but got p[%d,%d] = %x\n",
+                                   expected, i,j, p[offset+j] );
+                           fflush( stdout );
+                       }
+                   }
+                   k++;
+               }
+               offset += mtype->basesize;
+           }
+       }
+    }
+    return err;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Routines to select a datatype and associated buffer create/fill/check    */
+/* routines                                                                 */
+/* ------------------------------------------------------------------------ */
+
+/* 
+   Create a range of datatypes with a given count elements.
+   This uses a selection of types, rather than an exhaustive collection.
+   It allocates both send and receive types so that they can have the same
+   type signature (collection of basic types) but different type maps (layouts
+   in memory) 
+ */
+int MTestGetDatatypes( MTestDatatype *sendtype, MTestDatatype *recvtype,
+                      int count )
+{
+    int merr;
+    int i;
+
+    sendtype->InitBuf    = 0;
+    sendtype->FreeBuf    = 0;
+    sendtype->CheckBuf   = 0;
+    sendtype->datatype   = 0;
+    sendtype->isBasic    = 0;
+    sendtype->printErrors = 0;
+    recvtype->InitBuf    = 0;
+    recvtype->FreeBuf    = 0;
+
+    recvtype->CheckBuf   = 0;
+    recvtype->datatype   = 0;
+    recvtype->isBasic    = 0;
+    recvtype->printErrors = 0;
+
+    sendtype->buf        = 0;
+    recvtype->buf        = 0;
+
+    /* Set the defaults for the message lengths */
+    sendtype->count      = count;
+    recvtype->count      = count;
+    /* Use datatype_index to choose a datatype to use.  If at the end of the
+       list, return 0 */
+    switch (SMPI_VARGET_GLOBAL(datatype_index)) {
+    case 0:
+       sendtype->datatype = MPI_INT;
+       sendtype->isBasic  = 1;
+       recvtype->datatype = MPI_INT;
+       recvtype->isBasic  = 1;
+       break;
+    case 1:
+       sendtype->datatype = MPI_DOUBLE;
+       sendtype->isBasic  = 1;
+       recvtype->datatype = MPI_DOUBLE;
+       recvtype->isBasic  = 1;
+       break;
+    case 2:
+       sendtype->datatype = MPI_FLOAT_INT;
+       sendtype->isBasic  = 1;
+       recvtype->datatype = MPI_FLOAT_INT;
+       recvtype->isBasic  = 1;
+       break;
+    case 3:
+       merr = MPI_Type_dup( MPI_INT, &sendtype->datatype );
+       if (merr) MTestPrintError( merr );
+       merr = MPI_Type_set_name( sendtype->datatype,
+                                  (char*)"dup of MPI_INT" );
+       if (merr) MTestPrintError( merr );
+       merr = MPI_Type_dup( MPI_INT, &recvtype->datatype );
+       if (merr) MTestPrintError( merr );
+       merr = MPI_Type_set_name( recvtype->datatype,
+                                  (char*)"dup of MPI_INT" );
+       if (merr) MTestPrintError( merr );
+       /* dup'ed types are already committed if the original type 
+          was committed (MPI-2, section 8.8) */
+       break;
+    case 4:
+       /* vector send type and contiguous receive type */
+       /* These sizes are in bytes (see the VectorInit code) */
+       sendtype->stride   = 3 * sizeof(int);
+       sendtype->blksize  = sizeof(int);
+       sendtype->nelm     = recvtype->count;
+
+       merr = MPI_Type_vector( recvtype->count, 1, 3, MPI_INT, 
+                               &sendtype->datatype );
+       if (merr) MTestPrintError( merr );
+        merr = MPI_Type_commit( &sendtype->datatype );
+       if (merr) MTestPrintError( merr );
+       merr = MPI_Type_set_name( sendtype->datatype,
+                                  (char*)"int-vector" );
+       if (merr) MTestPrintError( merr );
+       sendtype->count    = 1;
+       recvtype->datatype = MPI_INT;
+       recvtype->isBasic  = 1;
+       sendtype->InitBuf  = MTestTypeVectorInit;
+       recvtype->InitBuf  = MTestTypeContigInitRecv;
+       sendtype->FreeBuf  = MTestTypeVectorFree;
+       recvtype->FreeBuf  = MTestTypeContigFree;
+       sendtype->CheckBuf = 0;
+       recvtype->CheckBuf = MTestTypeContigCheckbuf;
+       break;
+
+    case 5:
+       /* Indexed send using many small blocks and contig receive */
+       sendtype->blksize  = sizeof(int);
+       sendtype->nelm     = recvtype->count;
+       sendtype->basesize = sizeof(int);
+       sendtype->displs   = (int *)malloc( sendtype->nelm * sizeof(int) );
+       sendtype->index    = (int *)malloc( sendtype->nelm * sizeof(int) );
+       if (!sendtype->displs || !sendtype->index) {
+           MTestError( "Out of memory in type init\n" );
+       }
+       /* Make the sizes larger (4 ints) to help push the total
+          size to over 256k in some cases, as the MPICH code as of
+          10/1/06 used large internal buffers for packing non-contiguous
+          messages */
+       for (i=0; i<sendtype->nelm; i++) {
+           sendtype->index[i]   = 4;
+           sendtype->displs[i]  = 5*i;
+       }
+       merr = MPI_Type_indexed( sendtype->nelm,
+                                sendtype->index, sendtype->displs, 
+                                MPI_INT, &sendtype->datatype );
+       if (merr) MTestPrintError( merr );
+        merr = MPI_Type_commit( &sendtype->datatype );
+       if (merr) MTestPrintError( merr );
+       merr = MPI_Type_set_name( sendtype->datatype,
+                                  (char*)"int-indexed(4-int)" );
+       if (merr) MTestPrintError( merr );
+       sendtype->count    = 1;
+       sendtype->InitBuf  = MTestTypeIndexedInit;
+       sendtype->FreeBuf  = MTestTypeIndexedFree;
+       sendtype->CheckBuf = 0;
+
+       recvtype->datatype = MPI_INT;
+       recvtype->isBasic  = 1;
+       recvtype->count    = count * 4;
+       recvtype->InitBuf  = MTestTypeContigInitRecv;
+       recvtype->FreeBuf  = MTestTypeContigFree;
+       recvtype->CheckBuf = MTestTypeContigCheckbuf;
+       break;
+
+    case 6:
+       /* Indexed send using 2 large blocks and contig receive */
+       sendtype->blksize  = sizeof(int);
+       sendtype->nelm     = 2;
+       sendtype->basesize = sizeof(int);
+       sendtype->displs   = (int *)malloc( sendtype->nelm * sizeof(int) );
+       sendtype->index    = (int *)malloc( sendtype->nelm * sizeof(int) );
+       if (!sendtype->displs || !sendtype->index) {
+           MTestError( "Out of memory in type init\n" );
+       }
+       /* index -> block size */
+       sendtype->index[0]   = (recvtype->count + 1) / 2;
+       sendtype->displs[0]  = 0;
+       sendtype->index[1]   = recvtype->count - sendtype->index[0];
+       sendtype->displs[1]  = sendtype->index[0] + 1; 
+       /* There is a deliberate gap here */
+
+       merr = MPI_Type_indexed( sendtype->nelm,
+                                sendtype->index, sendtype->displs, 
+                                MPI_INT, &sendtype->datatype );
+       if (merr) MTestPrintError( merr );
+        merr = MPI_Type_commit( &sendtype->datatype );
+       if (merr) MTestPrintError( merr );
+       merr = MPI_Type_set_name( sendtype->datatype,
+                                  (char*)"int-indexed(2 blocks)" );
+       if (merr) MTestPrintError( merr );
+       sendtype->count    = 1;
+       sendtype->InitBuf  = MTestTypeIndexedInit;
+       sendtype->FreeBuf  = MTestTypeIndexedFree;
+       sendtype->CheckBuf = 0;
+
+       recvtype->datatype = MPI_INT;
+       recvtype->isBasic  = 1;
+       recvtype->count    = sendtype->index[0] + sendtype->index[1];
+       recvtype->InitBuf  = MTestTypeContigInitRecv;
+       recvtype->FreeBuf  = MTestTypeContigFree;
+       recvtype->CheckBuf = MTestTypeContigCheckbuf;
+       break;
+
+    case 7:
+       /* Indexed receive using many small blocks and contig send */
+       recvtype->blksize  = sizeof(int);
+       recvtype->nelm     = recvtype->count;
+       recvtype->basesize = sizeof(int);
+       recvtype->displs   = (int *)malloc( recvtype->nelm * sizeof(int) );
+       recvtype->index    = (int *)malloc( recvtype->nelm * sizeof(int) );
+       if (!recvtype->displs || !recvtype->index) {
+           MTestError( "Out of memory in type recv init\n" );
+       }
+       /* Make the sizes larger (4 ints) to help push the total
+          size to over 256k in some cases, as the MPICH code as of
+          10/1/06 used large internal buffers for packing non-contiguous
+          messages */
+       /* Note that there are gaps in the indexed type */
+       for (i=0; i<recvtype->nelm; i++) {
+           recvtype->index[i]   = 4;
+           recvtype->displs[i]  = 5*i;
+       }
+       merr = MPI_Type_indexed( recvtype->nelm,
+                                recvtype->index, recvtype->displs, 
+                                MPI_INT, &recvtype->datatype );
+       if (merr) MTestPrintError( merr );
+        merr = MPI_Type_commit( &recvtype->datatype );
+       if (merr) MTestPrintError( merr );
+       merr = MPI_Type_set_name( recvtype->datatype,
+                                  (char*)"recv-int-indexed(4-int)" );
+       if (merr) MTestPrintError( merr );
+       recvtype->count    = 1;
+       recvtype->InitBuf  = MTestTypeIndexedInitRecv;
+       recvtype->FreeBuf  = MTestTypeIndexedFree;
+       recvtype->CheckBuf = MTestTypeIndexedCheckbuf;
+
+       sendtype->datatype = MPI_INT;
+       sendtype->isBasic  = 1;
+       sendtype->count    = count * 4;
+       sendtype->InitBuf  = MTestTypeContigInit;
+       sendtype->FreeBuf  = MTestTypeContigFree;
+       sendtype->CheckBuf = 0;
+       break;
+
+       /* Less commonly used but still simple types */
+    case 8:
+       sendtype->datatype = MPI_SHORT;
+       sendtype->isBasic  = 1;
+       recvtype->datatype = MPI_SHORT;
+       recvtype->isBasic  = 1;
+       break;
+    case 9:
+       sendtype->datatype = MPI_LONG;
+       sendtype->isBasic  = 1;
+       recvtype->datatype = MPI_LONG;
+       recvtype->isBasic  = 1;
+       break;
+    case 10:
+       sendtype->datatype = MPI_CHAR;
+       sendtype->isBasic  = 1;
+       recvtype->datatype = MPI_CHAR;
+       recvtype->isBasic  = 1;
+       break;
+    case 11:
+       sendtype->datatype = MPI_UINT64_T;
+       sendtype->isBasic  = 1;
+       recvtype->datatype = MPI_UINT64_T;
+       recvtype->isBasic  = 1;
+       break;
+    case 12:
+       sendtype->datatype = MPI_FLOAT;
+       sendtype->isBasic  = 1;
+       recvtype->datatype = MPI_FLOAT;
+       recvtype->isBasic  = 1;
+       break;
+
+#ifndef USE_STRICT_MPI
+       /* MPI_BYTE may only be used with MPI_BYTE in strict MPI */
+    case 13:
+       sendtype->datatype = MPI_INT;
+       sendtype->isBasic  = 1;
+       recvtype->datatype = MPI_BYTE;
+       recvtype->isBasic  = 1;
+       recvtype->count    *= sizeof(int);
+       break;
+#endif
+    default:
+       SMPI_VARGET_GLOBAL(datatype_index) = -1;
+    }
+
+    if (!sendtype->InitBuf) {
+       sendtype->InitBuf  = MTestTypeContigInit;
+       recvtype->InitBuf  = MTestTypeContigInitRecv;
+       sendtype->FreeBuf  = MTestTypeContigFree;
+       recvtype->FreeBuf  = MTestTypeContigFree;
+       sendtype->CheckBuf = MTestTypeContigCheckbuf;
+       recvtype->CheckBuf = MTestTypeContigCheckbuf;
+    }
+    SMPI_VARGET_GLOBAL(datatype_index)++;
+
+    if (SMPI_VARGET_GLOBAL(dbgflag) && SMPI_VARGET_GLOBAL(datatype_index) > 0) {
+       int typesize;
+       fprintf( stderr, "%d: sendtype is %s\n", SMPI_VARGET_GLOBAL(wrank), MTestGetDatatypeName( sendtype ) );
+       merr = MPI_Type_size( sendtype->datatype, &typesize );
+       if (merr) MTestPrintError( merr );
+       fprintf( stderr, "%d: sendtype size = %d\n", SMPI_VARGET_GLOBAL(wrank), typesize );
+       fprintf( stderr, "%d: recvtype is %s\n", SMPI_VARGET_GLOBAL(wrank), MTestGetDatatypeName( recvtype ) );
+       merr = MPI_Type_size( recvtype->datatype, &typesize );
+       if (merr) MTestPrintError( merr );
+       fprintf( stderr, "%d: recvtype size = %d\n", SMPI_VARGET_GLOBAL(wrank), typesize );
+       fflush( stderr );
+       
+    }
+    else if (SMPI_VARGET_GLOBAL(verbose) && SMPI_VARGET_GLOBAL(datatype_index) > 0) {
+       printf( "Get new datatypes: send = %s, recv = %s\n", 
+               MTestGetDatatypeName( sendtype ), 
+               MTestGetDatatypeName( recvtype ) );
+       fflush( stdout );
+    }
+
+    return SMPI_VARGET_GLOBAL(datatype_index);
+}
+
+/* Reset the datatype index (start from the initial data type.
+   Note: This routine is rarely needed; MTestGetDatatypes automatically
+   starts over after the last available datatype is used.
+*/
+void MTestResetDatatypes( void )
+{
+    SMPI_VARGET_GLOBAL(datatype_index) = 0;
+}
+/* Return the index of the current datatype.  This is rarely needed and
+   is provided mostly to enable debugging of the MTest package itself */
+int MTestGetDatatypeIndex( void )
+{
+    return SMPI_VARGET_GLOBAL(datatype_index);
+}
+
+/* Free the storage associated with a datatype */
+void MTestFreeDatatype( MTestDatatype *mtype )
+{
+    int merr;
+    /* Invoke a datatype-specific free function to handle
+       both the datatype and the send/receive buffers */
+    if (mtype->FreeBuf) {
+       (mtype->FreeBuf)( mtype );
+    }
+    /* Free the datatype itself if it was created */
+    if (!mtype->isBasic) {
+       merr = MPI_Type_free( &mtype->datatype );
+       if (merr) MTestPrintError( merr );
+    }
+}
+
+/* Check that a message was received correctly.  Returns the number of
+   errors detected.  Status may be NULL or MPI_STATUS_IGNORE */
+int MTestCheckRecv( MPI_Status *status, MTestDatatype *recvtype )
+{
+    int count;
+    int errs = 0, merr;
+
+    if (status && status != MPI_STATUS_IGNORE) {
+       merr = MPI_Get_count( status, recvtype->datatype, &count );
+       if (merr) MTestPrintError( merr );
+       
+       /* Check count against expected count */
+       if (count != recvtype->count) {
+           errs ++;
+       }
+    }
+
+    /* Check received data */
+    if (!errs && recvtype->CheckBuf( recvtype )) {
+       errs++;
+    }
+    return errs;
+}
+
+/* This next routine uses a circular buffer of static name arrays just to
+   simplify the use of the routine */
+const char *MTestGetDatatypeName( MTestDatatype *dtype )
+{
+    typedef char name_type[4][MPI_MAX_OBJECT_NAME];
+    SMPI_VARINIT_STATIC(name, name_type);
+    SMPI_VARINIT_STATIC_AND_SET(sp, int, 0);
+    int rlen, merr;
+
+    if (SMPI_VARGET_STATIC(sp) >= 4) SMPI_VARGET_STATIC(sp) = 0;
+    merr = MPI_Type_get_name( dtype->datatype, SMPI_VARGET_STATIC(name)[SMPI_VARGET_STATIC(sp)], &rlen );
+    if (merr) MTestPrintError( merr );
+    return (const char *)SMPI_VARGET_STATIC(name)[SMPI_VARGET_STATIC(sp)++];
+}
+/* ----------------------------------------------------------------------- */
+
+/* 
+ * Create communicators.  Use separate routines for inter and intra
+ * communicators (there is a routine to give both)
+ * Note that the routines may return MPI_COMM_NULL, so code should test for
+ * that return value as well.
+ * 
+ */
+SMPI_VARINIT_GLOBAL_AND_SET(interCommIdx, int, 0);
+SMPI_VARINIT_GLOBAL_AND_SET(intraCommIdx, int, 0);
+SMPI_VARINIT_GLOBAL_AND_SET(intraCommName, const char *, 0);
+SMPI_VARINIT_GLOBAL_AND_SET(interCommName, const char *, 0);
+
+/* 
+ * Get an intracommunicator with at least min_size members.  If "allowSmaller"
+ * is true, allow the communicator to be smaller than MPI_COMM_WORLD and
+ * for this routine to return MPI_COMM_NULL for some values.  Returns 0 if
+ * no more communicators are available.
+ */
+int MTestGetIntracommGeneral( MPI_Comm *comm, int min_size, int allowSmaller )
+{
+    int size, rank, merr;
+    int done2, done=0;
+    int isBasic = 0;
+
+    /* The while loop allows us to skip communicators that are too small.
+       MPI_COMM_NULL is always considered large enough */
+    while (!done) {
+       isBasic = 0;
+       SMPI_VARGET_GLOBAL(intraCommName) = "";
+       switch (SMPI_VARGET_GLOBAL(intraCommIdx)) {
+       case 0:
+           *comm = MPI_COMM_WORLD;
+           isBasic = 1;
+           SMPI_VARGET_GLOBAL(intraCommName) = "MPI_COMM_WORLD";
+           break;
+       case 1:
+           /* dup of world */
+           merr = MPI_Comm_dup(MPI_COMM_WORLD, comm );
+           if (merr) MTestPrintError( merr );
+           SMPI_VARGET_GLOBAL(intraCommName) = "Dup of MPI_COMM_WORLD";
+           break;
+       case 2:
+           /* reverse ranks */
+           merr = MPI_Comm_size( MPI_COMM_WORLD, &size );
+           if (merr) MTestPrintError( merr );
+           merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+           if (merr) MTestPrintError( merr );
+           merr = MPI_Comm_split( MPI_COMM_WORLD, 0, size-rank, comm );
+           if (merr) MTestPrintError( merr );
+           SMPI_VARGET_GLOBAL(intraCommName) = "Rank reverse of MPI_COMM_WORLD";
+           break;
+       case 3:
+           /* subset of world, with reversed ranks */
+           merr = MPI_Comm_size( MPI_COMM_WORLD, &size );
+           if (merr) MTestPrintError( merr );
+           merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+           if (merr) MTestPrintError( merr );
+           merr = MPI_Comm_split( MPI_COMM_WORLD, ((rank < size/2) ? 1 : MPI_UNDEFINED),
+                                  size-rank, comm );
+           if (merr) MTestPrintError( merr );
+           SMPI_VARGET_GLOBAL(intraCommName) = "Rank reverse of half of MPI_COMM_WORLD";
+           break;
+       case 4:
+           *comm = MPI_COMM_SELF;
+           isBasic = 1;
+           SMPI_VARGET_GLOBAL(intraCommName) = "MPI_COMM_SELF";
+           break;
+
+           /* These next cases are communicators that include some
+              but not all of the processes */
+       case 5:
+       case 6:
+       case 7:
+       case 8:
+       {
+           int newsize;
+           merr = MPI_Comm_size( MPI_COMM_WORLD, &size );
+           if (merr) MTestPrintError( merr );
+           newsize = size - (SMPI_VARGET_GLOBAL(intraCommIdx) - 4);
+           
+           if (allowSmaller && newsize >= min_size) {
+               merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+               if (merr) MTestPrintError( merr );
+               merr = MPI_Comm_split( MPI_COMM_WORLD, rank < newsize, rank, 
+                                      comm );
+               if (merr) MTestPrintError( merr );
+               if (rank >= newsize) {
+                   merr = MPI_Comm_free( comm );
+                   if (merr) MTestPrintError( merr );
+                   *comm = MPI_COMM_NULL;
+               }
+               else {
+                   SMPI_VARGET_GLOBAL(intraCommName) = "Split of WORLD";
+               }
+           }
+           else {
+               /* Act like default */
+               *comm = MPI_COMM_NULL;
+               SMPI_VARGET_GLOBAL(intraCommIdx) = -1;
+           }
+       }
+       break;
+           
+           /* Other ideas: dup of self, cart comm, graph comm */
+       default:
+           *comm = MPI_COMM_NULL;
+           SMPI_VARGET_GLOBAL(intraCommIdx) = -1;
+           break;
+       }
+
+       if (*comm != MPI_COMM_NULL) {
+           merr = MPI_Comm_size( *comm, &size );
+           if (merr) MTestPrintError( merr );
+           if (size >= min_size)
+               done = 1;
+       }
+        else {
+            SMPI_VARGET_GLOBAL(intraCommName) = "MPI_COMM_NULL";
+            isBasic = 1;
+            done = 1;
+        }
+done2=done;
+        /* we are only done if all processes are done */
+        MPI_Allreduce(&done2, &done, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
+
+        /* Advance the comm index whether we are done or not, otherwise we could
+         * spin forever trying to allocate a too-small communicator over and
+         * over again. */
+        SMPI_VARGET_GLOBAL(intraCommIdx)++;
+
+        if (!done && !isBasic && *comm != MPI_COMM_NULL) {
+            /* avoid leaking communicators */
+            merr = MPI_Comm_free(comm);
+            if (merr) MTestPrintError(merr);
+        }
+    }
+
+    return SMPI_VARGET_GLOBAL(intraCommIdx);
+}
+
+/* 
+ * Get an intracommunicator with at least min_size members.
+ */
+int MTestGetIntracomm( MPI_Comm *comm, int min_size ) 
+{
+    return MTestGetIntracommGeneral( comm, min_size, 0 );
+}
+
+/* Return the name of an intra communicator */
+const char *MTestGetIntracommName( void )
+{
+    return SMPI_VARGET_GLOBAL(intraCommName);
+}
+
+/* 
+ * Return an intercomm; set isLeftGroup to 1 if the calling process is 
+ * a member of the "left" group.
+ */
+int MTestGetIntercomm( MPI_Comm *comm, int *isLeftGroup, int min_size )
+{
+    int size, rank, remsize, merr;
+    int done=0;
+    MPI_Comm mcomm  = MPI_COMM_NULL;
+    MPI_Comm mcomm2 = MPI_COMM_NULL;
+    int rleader;
+
+    /* The while loop allows us to skip communicators that are too small.
+       MPI_COMM_NULL is always considered large enough.  The size is
+       the sum of the sizes of the local and remote groups */
+    while (!done) {
+        *comm = MPI_COMM_NULL;
+        *isLeftGroup = 0;
+        SMPI_VARGET_GLOBAL(interCommName) = "MPI_COMM_NULL";
+
+       switch (SMPI_VARGET_GLOBAL(interCommIdx)) {
+       case 0:
+           /* Split comm world in half */
+           merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+           if (merr) MTestPrintError( merr );
+           merr = MPI_Comm_size( MPI_COMM_WORLD, &size );
+           if (merr) MTestPrintError( merr );
+           if (size > 1) {
+               merr = MPI_Comm_split( MPI_COMM_WORLD, (rank < size/2), rank, 
+                                      &mcomm );
+               if (merr) MTestPrintError( merr );
+               if (rank == 0) {
+                   rleader = size/2;
+               }
+               else if (rank == size/2) {
+                   rleader = 0;
+               }
+               else {
+                   /* Remote leader is signficant only for the processes
+                      designated local leaders */
+                   rleader = -1;
+               }
+               *isLeftGroup = rank < size/2;
+               merr = MPI_Intercomm_create( mcomm, 0, MPI_COMM_WORLD, rleader,
+                                            12345, comm );
+               if (merr) MTestPrintError( merr );
+               SMPI_VARGET_GLOBAL(interCommName) = "Intercomm by splitting MPI_COMM_WORLD";
+           }
+           else 
+               *comm = MPI_COMM_NULL;
+           break;
+       case 1:
+           /* Split comm world in to 1 and the rest */
+           merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+           if (merr) MTestPrintError( merr );
+           merr = MPI_Comm_size( MPI_COMM_WORLD, &size );
+           if (merr) MTestPrintError( merr );
+           if (size > 1) {
+               merr = MPI_Comm_split( MPI_COMM_WORLD, rank == 0, rank, 
+                                      &mcomm );
+               if (merr) MTestPrintError( merr );
+               if (rank == 0) {
+                   rleader = 1;
+               }
+               else if (rank == 1) {
+                   rleader = 0;
+               }
+               else {
+                   /* Remote leader is signficant only for the processes
+                      designated local leaders */
+                   rleader = -1;
+               }
+               *isLeftGroup = rank == 0;
+               merr = MPI_Intercomm_create( mcomm, 0, MPI_COMM_WORLD, 
+                                            rleader, 12346, comm );
+               if (merr) MTestPrintError( merr );
+               SMPI_VARGET_GLOBAL(interCommName) = "Intercomm by splitting MPI_COMM_WORLD into 1, rest";
+           }
+           else
+               *comm = MPI_COMM_NULL;
+           break;
+
+       case 2:
+           /* Split comm world in to 2 and the rest */
+           merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+           if (merr) MTestPrintError( merr );
+           merr = MPI_Comm_size( MPI_COMM_WORLD, &size );
+           if (merr) MTestPrintError( merr );
+           if (size > 3) {
+               merr = MPI_Comm_split( MPI_COMM_WORLD, rank < 2, rank, 
+                                      &mcomm );
+               if (merr) MTestPrintError( merr );
+               if (rank == 0) {
+                   rleader = 2;
+               }
+               else if (rank == 2) {
+                   rleader = 0;
+               }
+               else {
+                   /* Remote leader is signficant only for the processes
+                      designated local leaders */
+                   rleader = -1;
+               }
+               *isLeftGroup = rank < 2;
+               merr = MPI_Intercomm_create( mcomm, 0, MPI_COMM_WORLD, 
+                                            rleader, 12347, comm );
+               if (merr) MTestPrintError( merr );
+               SMPI_VARGET_GLOBAL(interCommName) = "Intercomm by splitting MPI_COMM_WORLD into 2, rest";
+           }
+           else 
+               *comm = MPI_COMM_NULL;
+           break;
+
+       case 3:
+           /* Split comm world in half, then dup */
+           merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+           if (merr) MTestPrintError( merr );
+           merr = MPI_Comm_size( MPI_COMM_WORLD, &size );
+           if (merr) MTestPrintError( merr );
+           if (size > 1) {
+               merr = MPI_Comm_split( MPI_COMM_WORLD, (rank < size/2), rank, 
+                                      &mcomm );
+               if (merr) MTestPrintError( merr );
+               if (rank == 0) {
+                   rleader = size/2;
+               }
+               else if (rank == size/2) {
+                   rleader = 0;
+               }
+               else {
+                   /* Remote leader is signficant only for the processes
+                      designated local leaders */
+                   rleader = -1;
+               }
+               *isLeftGroup = rank < size/2;
+               merr = MPI_Intercomm_create( mcomm, 0, MPI_COMM_WORLD, rleader,
+                                            12345, comm );
+               if (merr) MTestPrintError( merr );
+                /* avoid leaking after assignment below */
+               merr = MPI_Comm_free( &mcomm );
+               if (merr) MTestPrintError( merr );
+
+               /* now dup, some bugs only occur for dup's of intercomms */
+               mcomm = *comm;
+               merr = MPI_Comm_dup(mcomm, comm);
+               if (merr) MTestPrintError( merr );
+               SMPI_VARGET_GLOBAL(interCommName) = "Intercomm by splitting MPI_COMM_WORLD then dup'ing";
+           }
+           else 
+               *comm = MPI_COMM_NULL;
+           break;
+
+       case 4:
+           /* Split comm world in half, form intercomm, then split that intercomm */
+           merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+           if (merr) MTestPrintError( merr );
+           merr = MPI_Comm_size( MPI_COMM_WORLD, &size );
+           if (merr) MTestPrintError( merr );
+           if (size > 1) {
+               merr = MPI_Comm_split( MPI_COMM_WORLD, (rank < size/2), rank, 
+                                      &mcomm );
+               if (merr) MTestPrintError( merr );
+               if (rank == 0) {
+                   rleader = size/2;
+               }
+               else if (rank == size/2) {
+                   rleader = 0;
+               }
+               else {
+                   /* Remote leader is signficant only for the processes
+                      designated local leaders */
+                   rleader = -1;
+               }
+               *isLeftGroup = rank < size/2;
+               merr = MPI_Intercomm_create( mcomm, 0, MPI_COMM_WORLD, rleader,
+                                            12345, comm );
+               if (merr) MTestPrintError( merr );
+                /* avoid leaking after assignment below */
+               merr = MPI_Comm_free( &mcomm );
+               if (merr) MTestPrintError( merr );
+
+               /* now split, some bugs only occur for splits of intercomms */
+               mcomm = *comm;
+               rank = MPI_Comm_rank(mcomm, &rank);
+               if (merr) MTestPrintError( merr );
+               /* this split is effectively a dup but tests the split code paths */
+               merr = MPI_Comm_split(mcomm, 0, rank, comm);
+               if (merr) MTestPrintError( merr );
+               SMPI_VARGET_GLOBAL(interCommName) = "Intercomm by splitting MPI_COMM_WORLD then then splitting again";
+           }
+           else
+               *comm = MPI_COMM_NULL;
+           break;
+
+       case 5:
+            /* split comm world in half discarding rank 0 on the "left"
+             * communicator, then form them into an intercommunicator */
+           merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+           if (merr) MTestPrintError( merr );
+           merr = MPI_Comm_size( MPI_COMM_WORLD, &size );
+           if (merr) MTestPrintError( merr );
+           if (size >= 4) {
+                int color = (rank < size/2 ? 0 : 1);
+                if (rank == 0)
+                    color = MPI_UNDEFINED;
+
+               merr = MPI_Comm_split( MPI_COMM_WORLD, color, rank, &mcomm );
+               if (merr) MTestPrintError( merr );
+
+               if (rank == 1) {
+                   rleader = size/2;
+               }
+               else if (rank == (size/2)) {
+                   rleader = 1;
+               }
+               else {
+                   /* Remote leader is signficant only for the processes
+                      designated local leaders */
+                   rleader = -1;
+               }
+               *isLeftGroup = rank < size/2;
+                if (rank != 0) { /* 0's mcomm is MPI_COMM_NULL */
+                    merr = MPI_Intercomm_create( mcomm, 0, MPI_COMM_WORLD, rleader, 12345, comm );
+                    if (merr) MTestPrintError( merr );
+                }
+                SMPI_VARGET_GLOBAL(interCommName) = "Intercomm by splitting MPI_COMM_WORLD (discarding rank 0 in the left group) then MPI_Intercomm_create'ing";
+            }
+            else {
+                *comm = MPI_COMM_NULL;
+            }
+            break;
+
+        case 6:
+            /* Split comm world in half then form them into an
+             * intercommunicator.  Then discard rank 0 from each group of the
+             * intercomm via MPI_Comm_create. */
+           merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+           if (merr) MTestPrintError( merr );
+           merr = MPI_Comm_size( MPI_COMM_WORLD, &size );
+           if (merr) MTestPrintError( merr );
+           if (size >= 4) {
+                MPI_Group oldgroup, newgroup;
+                int ranks[1];
+                int color = (rank < size/2 ? 0 : 1);
+
+               merr = MPI_Comm_split( MPI_COMM_WORLD, color, rank, &mcomm );
+               if (merr) MTestPrintError( merr );
+
+               if (rank == 0) {
+                   rleader = size/2;
+               }
+               else if (rank == (size/2)) {
+                   rleader = 0;
+               }
+               else {
+                   /* Remote leader is signficant only for the processes
+                      designated local leaders */
+                   rleader = -1;
+               }
+               *isLeftGroup = rank < size/2;
+                merr = MPI_Intercomm_create( mcomm, 0, MPI_COMM_WORLD, rleader, 12345, &mcomm2 );
+                if (merr) MTestPrintError( merr );
+
+                /* We have an intercomm between the two halves of comm world. Now create
+                 * a new intercomm that removes rank 0 on each side. */
+                merr = MPI_Comm_group(mcomm2, &oldgroup);
+                if (merr) MTestPrintError( merr );
+                ranks[0] = 0;
+                merr = MPI_Group_excl(oldgroup, 1, ranks, &newgroup);
+                if (merr) MTestPrintError( merr );
+                merr = MPI_Comm_create(mcomm2, newgroup, comm);
+                if (merr) MTestPrintError( merr );
+
+                merr = MPI_Group_free(&oldgroup);
+                if (merr) MTestPrintError( merr );
+                merr = MPI_Group_free(&newgroup);
+                if (merr) MTestPrintError( merr );
+
+                SMPI_VARGET_GLOBAL(interCommName) = "Intercomm by splitting MPI_COMM_WORLD then discarding 0 ranks with MPI_Comm_create";
+            }
+            else {
+                *comm = MPI_COMM_NULL;
+            }
+            break;
+
+       default:
+           *comm = MPI_COMM_NULL;
+           SMPI_VARGET_GLOBAL(interCommIdx) = -1;
+           break;
+       }
+
+       if (*comm != MPI_COMM_NULL) {
+           merr = MPI_Comm_size( *comm, &size );
+           if (merr) MTestPrintError( merr );
+           merr = MPI_Comm_remote_size( *comm, &remsize );
+           if (merr) MTestPrintError( merr );
+           if (size + remsize >= min_size) done = 1;
+       }
+       else {
+           SMPI_VARGET_GLOBAL(interCommName) = "MPI_COMM_NULL";
+           done = 1;
+        }
+
+        /* we are only done if all processes are done */
+        MPI_Allreduce(MPI_IN_PLACE, &done, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
+
+        /* Advance the comm index whether we are done or not, otherwise we could
+         * spin forever trying to allocate a too-small communicator over and
+         * over again. */
+        SMPI_VARGET_GLOBAL(interCommIdx)++;
+
+        if (!done && *comm != MPI_COMM_NULL) {
+            /* avoid leaking communicators */
+            merr = MPI_Comm_free(comm);
+            if (merr) MTestPrintError(merr);
+        }
+
+        /* cleanup for common temp objects */
+        if (mcomm != MPI_COMM_NULL) {
+            merr = MPI_Comm_free(&mcomm);
+            if (merr) MTestPrintError( merr );
+        }
+        if (mcomm2 != MPI_COMM_NULL) {
+            merr = MPI_Comm_free(&mcomm2);
+            if (merr) MTestPrintError( merr );
+        }
+    }
+
+    return SMPI_VARGET_GLOBAL(interCommIdx);
+}
+/* Return the name of an intercommunicator */
+const char *MTestGetIntercommName( void )
+{
+    return SMPI_VARGET_GLOBAL(interCommName);
+}
+
+/* Get a communicator of a given minimum size.  Both intra and inter 
+   communicators are provided */
+int MTestGetComm( MPI_Comm *comm, int min_size )
+{
+    int idx=0;
+    SMPI_VARINIT_STATIC_AND_SET(getinter, int, 0);
+
+    if (!SMPI_VARGET_STATIC(getinter)) {
+       idx = MTestGetIntracomm( comm, min_size );
+       if (idx == 0) {
+           SMPI_VARGET_STATIC(getinter) = 1;
+       }
+    }
+    if (SMPI_VARGET_STATIC(getinter)) {
+       int isLeft;
+       idx = MTestGetIntercomm( comm, &isLeft, min_size );
+       if (idx == 0) {
+           SMPI_VARGET_STATIC(getinter) = 0;
+       }
+    }
+
+    return idx;
+}
+
+/* Free a communicator.  It may be called with a predefined communicator
+ or MPI_COMM_NULL */
+void MTestFreeComm( MPI_Comm *comm )
+{
+    int merr;
+    if (*comm != MPI_COMM_WORLD &&
+       *comm != MPI_COMM_SELF &&
+       *comm != MPI_COMM_NULL) {
+       merr = MPI_Comm_free( comm );
+       if (merr) MTestPrintError( merr );
+    }
+}
+
+/* ------------------------------------------------------------------------ */
+void MTestPrintError( int errcode )
+{
+    int errclass, slen;
+    char string[MPI_MAX_ERROR_STRING];
+    
+    MPI_Error_class( errcode, &errclass );
+    MPI_Error_string( errcode, string, &slen );
+    printf( "Error class %d (%s)\n", errclass, string );
+    fflush( stdout );
+}
+void MTestPrintErrorMsg( const char msg[], int errcode )
+{
+    int errclass, slen;
+    char string[MPI_MAX_ERROR_STRING];
+    
+    MPI_Error_class( errcode, &errclass );
+    MPI_Error_string( errcode, string, &slen );
+    printf( "%s: Error class %d (%s)\n", msg, errclass, string ); 
+    fflush( stdout );
+}
+/* ------------------------------------------------------------------------ */
+/* 
+ If verbose output is selected and the level is at least that of the
+ value of the verbose flag, then perform printf( format, ... );
+ */
+void MTestPrintfMsg( int level, const char format[], ... )
+{
+    va_list list;
+
+    if (SMPI_VARGET_GLOBAL(verbose) && level >= SMPI_VARGET_GLOBAL(verbose)) {
+       va_start(list,format);
+       vprintf( format, list );
+       va_end(list);
+       fflush(stdout);
+    }
+}
+/* Fatal error.  Report and exit */
+void MTestError( const char *msg )
+{
+    fprintf( stderr, "%s\n", msg );
+    fflush( stderr );
+    MPI_Abort( MPI_COMM_WORLD, 1 );
+    exit(1);
+}
+/* ------------------------------------------------------------------------ */
+static void MTestResourceSummary( FILE *fp )
+{
+#ifdef HAVE_GETRUSAGE
+    struct rusage ru;
+    SMPI_VARINIT_STATIC_AND_SET(pfThreshold, int, -2);
+    int doOutput = 1;
+    if (getrusage( RUSAGE_SELF, &ru ) == 0) {
+       /* There is an option to generate output only when a resource
+          exceeds a threshold.  To date, only page faults supported. */
+       if (SMPI_VARGET_STATIC(pfThreshold) == -2) {
+           char *p = getenv("MPITEST_RUSAGE_PF");
+           SMPI_VARGET_STATIC(pfThreshold) = -1;
+           if (p) {
+               SMPI_VARGET_STATIC(pfThreshold) = strtol( p, 0, 0 );
+           }
+       }
+       if (SMPI_VARGET_STATIC(pfThreshold) > 0) {
+           doOutput = ru.ru_minflt > SMPI_VARGET_STATIC(pfThreshold);
+       }
+       if (doOutput) {
+           /* Cast values to long in case some system has defined them
+              as another integer type */
+           fprintf( fp, "RUSAGE: max resident set = %ldKB\n", 
+                    (long)ru.ru_maxrss );
+           fprintf( fp, "RUSAGE: page faults = %ld : %ld\n", 
+                    (long)ru.ru_minflt, (long)ru.ru_majflt );
+           /* Not every Unix provides useful information for the xxrss fields */
+           fprintf( fp, "RUSAGE: memory in text/data/stack = %ld : %ld : %ld\n", 
+                    (long)ru.ru_ixrss, (long)ru.ru_idrss, (long)ru.ru_isrss );
+           fprintf( fp, "RUSAGE: I/O in and out = %ld : %ld\n", 
+                    (long)ru.ru_inblock, (long)ru.ru_oublock );
+           fprintf( fp, "RUSAGE: context switch = %ld : %ld\n", 
+                    (long)ru.ru_nvcsw, (long)ru.ru_nivcsw );
+       }
+    }
+    else {
+       fprintf( fp, "RUSAGE: return error %d\n", errno );
+    }
+#endif
+}
+/* ------------------------------------------------------------------------ */
+#ifdef HAVE_MPI_WIN_CREATE
+/*
+ * Create MPI Windows
+ */
+SMPI_VARINIT_GLOBAL_AND_SET(win_index, int, 0);
+SMPI_VARINIT_GLOBAL(winName, const char *);
+/* Use an attribute to remember the type of memory allocation (static,
+   malloc, or MPI_Alloc_mem) */
+SMPI_VARINIT_GLOBAL_AND_SET(mem_keyval, int, MPI_KEYVAL_INVALID);
+int MTestGetWin( MPI_Win *win, int mustBePassive )
+{
+    typedef char actbuf_type[1024];
+    SMPI_VARINIT_STATIC(actbuf, actbuf_type);
+    SMPI_VARINIT_STATIC(pasbuf, char *);
+    char        *buf;
+    int         n, rank, merr;
+    MPI_Info    info;
+
+    if (SMPI_VARGET_GLOBAL(mem_keyval) == MPI_KEYVAL_INVALID) {
+       /* Create the keyval */
+       merr = MPI_Win_create_keyval( MPI_WIN_NULL_COPY_FN, 
+                                     MPI_WIN_NULL_DELETE_FN, 
+                                     &SMPI_VARGET_GLOBAL(mem_keyval), 0 );
+       if (merr) MTestPrintError( merr );
+
+    }
+
+    switch (SMPI_VARGET_GLOBAL(win_index)) {
+    case 0:
+       /* Active target window */
+       merr = MPI_Win_create( SMPI_VARGET_STATIC(actbuf), 1024, 1, MPI_INFO_NULL, MPI_COMM_WORLD,
+                              win );
+       if (merr) MTestPrintError( merr );
+       SMPI_VARGET_GLOBAL(winName) = "active-window";
+       merr = MPI_Win_set_attr( *win, SMPI_VARGET_GLOBAL(mem_keyval), (void *)0 );
+       if (merr) MTestPrintError( merr );
+       break;
+    case 1:
+       /* Passive target window */
+       merr = MPI_Alloc_mem( 1024, MPI_INFO_NULL, &SMPI_VARGET_STATIC(pasbuf) );
+       if (merr) MTestPrintError( merr );
+       merr = MPI_Win_create( SMPI_VARGET_STATIC(pasbuf), 1024, 1, MPI_INFO_NULL, MPI_COMM_WORLD,
+                              win );
+       if (merr) MTestPrintError( merr );
+       SMPI_VARGET_GLOBAL(winName) = "passive-window";
+       merr = MPI_Win_set_attr( *win, SMPI_VARGET_GLOBAL(mem_keyval), (void *)2 );
+       if (merr) MTestPrintError( merr );
+       break;
+    case 2:
+       /* Active target; all windows different sizes */
+       merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+       if (merr) MTestPrintError( merr );
+       n = rank * 64;
+       if (n) 
+           buf = (char *)malloc( n );
+       else
+           buf = 0;
+       merr = MPI_Win_create( buf, n, 1, MPI_INFO_NULL, MPI_COMM_WORLD, 
+                              win );
+       if (merr) MTestPrintError( merr );
+       SMPI_VARGET_GLOBAL(winName) = "active-all-different-win";
+       merr = MPI_Win_set_attr( *win, SMPI_VARGET_GLOBAL(mem_keyval), (void *)1 );
+       if (merr) MTestPrintError( merr );
+       break;
+    case 3:
+       /* Active target, no locks set */
+       merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+       if (merr) MTestPrintError( merr );
+       n = rank * 64;
+       if (n) 
+           buf = (char *)malloc( n );
+       else
+           buf = 0;
+       merr = MPI_Info_create( &info );
+       if (merr) MTestPrintError( merr );
+       merr = MPI_Info_set( info, (char*)"nolocks", (char*)"true" );
+       if (merr) MTestPrintError( merr );
+       merr = MPI_Win_create( buf, n, 1, info, MPI_COMM_WORLD, win );
+       if (merr) MTestPrintError( merr );
+       merr = MPI_Info_free( &info );
+       if (merr) MTestPrintError( merr );
+       SMPI_VARGET_GLOBAL(winName) = "active-nolocks-all-different-win";
+       merr = MPI_Win_set_attr( *win, SMPI_VARGET_GLOBAL(mem_keyval), (void *)1 );
+       if (merr) MTestPrintError( merr );
+       break;
+    default:
+       SMPI_VARGET_GLOBAL(win_index) = -1;
+    }
+    SMPI_VARGET_GLOBAL(win_index)++;
+    return SMPI_VARGET_GLOBAL(win_index);
+}
+/* Return a pointer to the name associated with a window object */
+const char *MTestGetWinName( void )
+{
+    return SMPI_VARGET_GLOBAL(winName);
+}
+/* Free the storage associated with a window object */
+void MTestFreeWin( MPI_Win *win )
+{
+    void *addr;
+    int  flag, merr;
+
+    merr = MPI_Win_get_attr( *win, MPI_WIN_BASE, &addr, &flag );
+    if (merr) MTestPrintError( merr );
+    if (!flag) {
+       MTestError( "Could not get WIN_BASE from window" );
+    }
+    if (addr) {
+       void *val;
+       merr = MPI_Win_get_attr( *win, SMPI_VARGET_GLOBAL(mem_keyval), &val, &flag );
+       if (merr) MTestPrintError( merr );
+       if (flag) {
+           if (val == (void *)1) {
+               free( addr );
+           }
+           else if (val == (void *)2) {
+               merr = MPI_Free_mem( addr );
+               if (merr) MTestPrintError( merr );
+           }
+           /* if val == (void *)0, then static data that must not be freed */
+       }
+    }
+    merr = MPI_Win_free(win);
+    if (merr) MTestPrintError( merr );
+}
+static void MTestRMACleanup( void )
+{
+    if (SMPI_VARGET_GLOBAL(mem_keyval) != MPI_KEYVAL_INVALID) {
+       MPI_Win_free_keyval( &SMPI_VARGET_GLOBAL(mem_keyval) );
+    }
+}
+#else 
+static void MTestRMACleanup( void ) {}
+#endif