Merge branch 'charm' of charmgit:charm into charm
authorPritish Jetley <pjetley2@illinois.edu>
Tue, 16 Feb 2010 16:54:57 +0000 (10:54 -0600)
committerPritish Jetley <pjetley2@illinois.edu>
Tue, 16 Feb 2010 16:54:57 +0000 (10:54 -0600)
168 files changed:
.cproject
.gitignore
CHANGES
build
doc/charm++/controlpoints.tex [new file with mode: 0644]
doc/charm++/entry.tex
doc/charm++/manual.tex
doc/charm++/python.tex
doc/faq/install.tex
doc/faq/manual.tex
doc/faq/overview.tex
examples/Makefile
examples/ampi/pingpong/Makefile
examples/charm++/cell/md/main.C
examples/charm++/cell/md/md_config.h
examples/charm++/cell/md/pairCompute.C
examples/charm++/cell/md/pairCompute.ci
examples/charm++/cell/md/pairCompute.h
examples/charm++/cell/md/patch.C
examples/charm++/cell/md/patch.ci
examples/charm++/cell/md/patch.h
examples/charm++/cell/md/selfCompute.C
examples/charm++/cell/md/selfCompute.ci
examples/charm++/cell/md/selfCompute.h
smart-build.pl
src/arch/bluegenel/bglmachine.C
src/arch/bluegenel/machine.c
src/arch/bluegenep/machine.c
src/arch/common/conv-mach-bigsim.h
src/arch/common/conv-mach-gfortran.sh
src/arch/elan/machine.c
src/arch/lapi/charmrun
src/arch/lapi/conv-common.h
src/arch/lapi/conv-mach.sh
src/arch/lapi/machine.c [changed mode: 0644->0755]
src/arch/mpi-crayxt/conv-mach-smp.h
src/arch/mpi-crayxt/conv-mach.sh
src/arch/mpi-crayxt3/conv-mach-smp.h
src/arch/mpi-darwin-ppc/conv-mach-smp.h
src/arch/mpi-linux-mips64/conv-mach-smp.h
src/arch/mpi-linux-x86_64/cc-mpicxx.sh
src/arch/mpi-linux-x86_64/conv-mach-smp.h
src/arch/mpi-linux/conv-mach-smp.h
src/arch/mpi-linux/conv-mach-vmi.h
src/arch/mpi/machine.c
src/arch/multicore-darwin-x86/conv-mach.h
src/arch/multicore-darwin-x86_64/conv-mach.h
src/arch/net-darwin-x86/conv-mach-smp.h
src/arch/net-linux-x86_64/conv-mach.h
src/arch/net-linux/conv-mach-smp.h
src/arch/net-linux/conv-mach.h
src/arch/net-linux/conv-mach.sh
src/arch/net/machine-ibverbs.c
src/arch/portals-crayxt3/machine.c
src/arch/util/machine-smp.c
src/ck-com/ComlibManager.C
src/ck-com/ComlibStats.C
src/ck-core/charm++.h
src/ck-core/charm.h
src/ck-core/ck.C
src/ck-core/ck.h
src/ck-core/ckarray.C
src/ck-core/ckcallback.C
src/ck-core/ckcallback.h
src/ck-core/ckcheckpoint.C
src/ck-core/ckcheckpoint.h
src/ck-core/ckmemcheckpoint.C
src/ck-core/ckobjQ.C
src/ck-core/ckobjQ.h
src/ck-core/ckreduction.C
src/ck-core/ckreduction.h
src/ck-core/debug-charm.C
src/ck-core/envelope.h
src/ck-core/init.C
src/ck-core/init.h
src/ck-core/middle-conv.h
src/ck-core/msgalloc.C
src/ck-core/qd.C
src/ck-cp/API-generator/cp_effects.C
src/ck-cp/API-generator/cp_effects.h
src/ck-cp/API-generator/cp_effects.pl
src/ck-cp/API-generator/cp_effects.txt
src/ck-cp/controlPoints.C
src/ck-cp/controlPoints.ci
src/ck-cp/controlPoints.h
src/ck-ldb/CentralLB.C
src/ck-ldb/HybridBaseLB.C
src/ck-ldb/HybridBaseLB.ci
src/ck-ldb/HybridBaseLB.h
src/ck-ldb/HybridLBMsg.h
src/ck-ldb/LButil.C
src/ck-ldb/NullLB.C
src/ck-ldb/lbdb.h
src/ck-perf/trace-controlPoints.C
src/ck-perf/trace-controlPoints.h
src/ck-perf/trace-converse.c
src/ck-perf/trace-recordreplay.C [deleted file]
src/ck-perf/trace-recordreplay.h [deleted file]
src/conv-ccs/conv-ccs.c
src/conv-core/conv-config.h
src/conv-core/convcore.c
src/conv-core/converse.h
src/conv-core/debug-conv.c
src/conv-core/debug-conv.h
src/conv-core/global-elfgot.C
src/conv-core/memory-charmdebug.c
src/conv-core/memory.c
src/conv-core/quiescence.c
src/conv-core/threads.c
src/libs/ck-libs/ParFUM-Iterators/Makefile
src/libs/ck-libs/ParFUM-Iterators/ParFUM_Iterators.cc
src/libs/ck-libs/ParFUM-Iterators/ParFUM_Iterators.h
src/libs/ck-libs/ampi/ampi.C
src/libs/ck-libs/ampi/ampif.C
src/libs/ck-libs/ampi/ampiimpl.h
src/libs/ck-libs/armci/armci.h
src/libs/ck-libs/armci/armci_api.C
src/libs/ck-libs/armci/armci_impl.h
src/libs/ck-libs/armci/armci_vp.C
src/libs/ck-libs/pythonCCS/PythonCCS.C
src/libs/ck-libs/tcharm/tcharm.C
src/scripts/Make.depends
src/scripts/Makefile
src/scripts/charmc
src/scripts/configure
src/scripts/configure.in
src/util/CrayNid.c
src/util/ckhashtable.C
src/util/ckhashtable.h
src/util/cklists.h
src/util/simd.h
src/util/treeStrategy_nodeAware_minGens.h
tests/ampi/Makefile
tests/ampi/migration/Makefile [new file with mode: 0644]
tests/ampi/migration/test.C [new file with mode: 0644]
tests/ampi/mpich-test/Makefile
tests/ampi/mpich-test/coll/Makefile
tests/ampi/mpich-test/coll/runtests
tests/ampi/mpich-test/command/runtests
tests/ampi/mpich-test/context/Makefile
tests/ampi/mpich-test/context/runtests
tests/ampi/mpich-test/env/Makefile
tests/ampi/mpich-test/env/runtests
tests/ampi/mpich-test/profile/Makefile
tests/ampi/mpich-test/profile/runtests
tests/ampi/mpich-test/pt2pt/Makefile
tests/ampi/mpich-test/pt2pt/dtypes.h [new file with mode: 0644]
tests/ampi/mpich-test/pt2pt/gcomm.h [new file with mode: 0644]
tests/ampi/mpich-test/pt2pt/runtests
tests/ampi/mpich-test/pt2pt/test.h [new file with mode: 0644]
tests/ampi/mpich-test/runbase
tests/ampi/mpich-test/topol/Makefile
tests/ampi/mpich-test/topol/runtests
tests/charm++/chkpt/hello.C
tests/charm++/chkpt/hello.ci
tests/charm++/loadbalancing/lb_test/Makefile
tests/charm++/megatest/Make.depends
tests/charm++/megatest/Makefile
tests/charm++/megatest/bitvector.C
tests/charm++/megatest/inlineem.C [new file with mode: 0644]
tests/charm++/megatest/inlineem.ci [new file with mode: 0644]
tests/charm++/simplearrayhello-crosscorruption/Makefile [new file with mode: 0644]
tests/charm++/simplearrayhello-crosscorruption/hello.C [new file with mode: 0644]
tests/charm++/simplearrayhello-crosscorruption/hello.ci [new file with mode: 0644]
tests/util/Makefile
tests/util/headerpad.C [new file with mode: 0644]
tests/util/headerpad.ci [new file with mode: 0644]
tests/util/headerpad.h [new file with mode: 0644]

index e0da74e754d16e243e28d37b17c673ddba2c28bf..3dbb439aa86e5245be9ce7b193d37c9392026893 100644 (file)
--- a/.cproject
+++ b/.cproject
@@ -31,7 +31,7 @@
 <listOptionValue builtIn="false" value="&quot;${workspace_loc:/charm/net-linux-amd64/tmp}&quot;"/>
 <listOptionValue builtIn="false" value="&quot;${workspace_loc:/charm/net-linux-amd64/tmp/libs/ck-libs/pythonCCS}&quot;"/>
 </option>
-<option id="gnu.cpp.compiler.option.preprocessor.def.1120432124" superClass="gnu.cpp.compiler.option.preprocessor.def" valueType="definedSymbols">
+<option id="gnu.cpp.compiler.option.preprocessor.def.1120432124" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" valueType="definedSymbols">
 <listOptionValue builtIn="false" value="CMK_SEPARATE_PATH=1"/>
 <listOptionValue builtIn="false" value="CMK_USE_BACKTRACE=1"/>
 <listOptionValue builtIn="false" value="CMK_CCS_AVAILABLE"/>
@@ -44,7 +44,7 @@
 <option id="gnu.c.compiler.option.include.paths.783568532" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
 <listOptionValue builtIn="false" value="&quot;${workspace_loc:/charm/net-linux-amd64/tmp}&quot;"/>
 </option>
-<option id="gnu.c.compiler.option.preprocessor.def.symbols.2106822378" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
+<option id="gnu.c.compiler.option.preprocessor.def.symbols.2106822378" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
 <listOptionValue builtIn="false" value="CMK_SEPARATE_PATH=1"/>
 <listOptionValue builtIn="false" value="CMK_USE_BACKTRACE=1"/>
 <listOptionValue builtIn="false" value="CMK_CCS_AVAILABLE"/>
@@ -64,6 +64,9 @@
 </tool>
 </toolChain>
 </folderInfo>
+<sourceEntries>
+<entry excluding="bin/|include/|lib/|lib_so/|tmp/|net-**" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/>
+</sourceEntries>
 </configuration>
 </storageModule>
 <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
index a0b906d8e8d5ffbcbb93964e0e2a05e174c74fc7..b82a4655bbfa3f9eec49ce03cbbbb3de384354c9 100644 (file)
@@ -22,6 +22,7 @@ mpi-*
 lapi*
 vmi-*
 multicore-*
+uth-*
 
 # Ignore cruft that would result from compiling charm example/test code
 # Note this is negated inside src/arch to permit addition of new charmrun files in there
diff --git a/CHANGES b/CHANGES
index 82a64c0ebfa05edd8baa488144bdbac31ccb3626..c430db772a326a024808278392cbdffa1970bba6 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,109 @@
+This file describes the most significant changes. For more detail, use
+'git log' on a clone of the charm repository.
+
+================================================================================
+What's new in Charm++ 6.2.0 (since 6.1)
+================================================================================
+
+--------------------------------------------------------------------------------
+New Supported Platforms:
+--------------------------------------------------------------------------------
+
+64-bit MIPS, such as SiCortex, using mpi-linux-mips64
+
+Windows HPC cluster, using mpi-win32/mpi-win64
+
+--------------------------------------------------------------------------------
+General Changes
+--------------------------------------------------------------------------------
+
+Runtime support
+ - Smarter build/configure scripts
+ - A new interface for model-based load balancing
+ - new CPU topology API
+ - a general implementation of CmiMemoryUsage()
+ - Bug fix: Quiescence detection (QD) works with immediate messages
+ - New reduction functions implemented in Converse
+ - CCS (Converse Client-Server) can deliver message to more than one processor
+
+Charm++
+ - Cross-array and cross-group sections
+ - Structured Dagger (SDAG): Support templated arguments properly
+ - Plain chares support checkpoint/restart (both in-memory and disk-based)
+ - Conditional packing of messages and parameters in SMP scenario
+
+Adaptive MPI (AMPI)
+ - Compilers renamed to avoid collision with host MPI (ampicc, ampiCC,
+   ampif77, ampif90)
+ - Improved MPI standard conformance, and documentation of non-conformance
+   * Bug fixes in: MPI_Ssend, MPI_Cart_shift, MPI_Get_count
+   * Support MPI_IN_PLACE in MPI_(All)Reduce
+   * Define various missing constants
+ - Return the received message's tag in response to a non-blocking
+   wildcard receive, to support SuperLU
+ - Improved tracing for BigSim
+
+Multiphase Shared Arrays (MSA)
+ - Typed handles to enforce phases
+ - Split-phase synchronization to enable message-driven execution
+ - 3D arrays
+
+TCharm
+ - Automatic tracing of API calls for simulation and analysis.
+
+Debugging
+ - Wider support for architectures other than net- (in particular MPI layers)
+ - Improved support for large scale debugging (better scalability)
+ - Enhanced record/replay stability to handle various events, and to signal unexpected messages
+ - New detailed record/replay: The full content of messages can be recorded, and a single processor can be re-executed outside of the parallel application
+
+Performance analysis
+ - Tracing of nested entry methods
+
+BigSim
+ - Out-of-core support, with prefetching capability
+ - Detailed tracing of MPI calls
+ - Detailed record/replay support at emulation time, capable of replaying any emulated processor after obtained recorded logs.
+
+--------------------------------------------------------------------------------
+Architecture-specific changes
+--------------------------------------------------------------------------------
+
+Net-Linux
+ - New charmrun option ++no-va-randomization to disable address space
+   randomization (ASLR). This is most useful for running AMPI with
+   isomalloc
+
+MPI
+ - Default to using ampicxx instead of mpiCC
+
+MPI-SMP
+ - The +p option now has the same semantics as in other smp builds
+
+Power 7
+ - Support for VSX in SIMD abstraction API
+
+Blue Gene/L
+ - Compilers and options have been updated to the latest ones
+
+Cray XT
+ - cputopology information is now available on XT3/4/5
+
+Infiniband (ibverbs)
+ - Bug fix: plug memory leaks that caused failures in long runs
+
+LAPI
+ - Support for SMP
+
+
+================================================================================
+Note that changes from 5.9, 6.0, and 6.1 are not documented here. A partial list
+can be found on the charm download page, or by reading through version control
+logs.
+
+================================================================================
 What's New since Charm++ 5.4 release 1
-========================================
+================================================================================
 
 --------------------------------------------------------------------------------
 New Supported Platforms:
@@ -44,8 +148,9 @@ Summary of Changes:
                 *******   Old Change histories *******
 
 
+================================================================================
 What's New in Charm++ 5.4 release 1 since 5.0
-===============================================================
+================================================================================
 
 --------------------------------------------------------------------------------
 New Supported Platforms:
diff --git a/build b/build
index c5b045617bde68200deb4a49b256b43a41dcc371..1841beed8afab03b9a5a1d129e4f9bc34517e8e4 100755 (executable)
--- a/build
+++ b/build
@@ -89,6 +89,7 @@ syntax() {
   echo '  --basedir=DIR             shortcut for the above two - DIR/include and DIR/lib'
   echo '  -j[N]              parallel make, N is the number of paralle make jobs'
   echo "  --with-romio       build AMPI with ROMIO library"
+  echo "  --with-production  build Charm++ with all optimizations for maximum performance"
   echo "  --destination=DIR  build Charm++ inside DIR, by default the destination is <version>"
   echo "  --suffix=DIR       append DIR to the destination directory of the Charm++ build"
   echo "  --tau-makefile=FILE Specify which TAU stub makefile to use"
@@ -207,6 +208,7 @@ INCDIR=
 ARCH=
 BUILD_SHARED=
 WITH_ROMIO=
+WITH_PRODUCTION=
 BUILD_EMULATOR=0
 DESTINATION=""
 DESTINATION_SUFFIX=""
@@ -294,6 +296,10 @@ do
     --with-romio)
                WITH_ROMIO="true"; shift
                ;;
+    --with-production)
+               WITH_PRODUCTION="true" 
+               shift
+               ;;
     --build-shared|-bs)
                # obsolete, do nothing
                shift
@@ -520,6 +526,11 @@ then
     echo "CMK_AMPI_WITH_ROMIO=\"true\"" >> $ConvSh
 fi
 
+if test -n "$WITH_PRODUCTION"
+then
+    echo '#define CMK_OPTIMIZE' >> $ConvHeader
+    echo '#define CMK_REPLAYSYSTEM  0' >> $ConvHeader
+fi
 
 # build with Tau
 WITH_TAU=0
@@ -571,6 +582,8 @@ printError()
        exit $MAKEEXIT
 }
 
+echo 'BUILDOPTS="'$OPTS'"'  >> $ConvSh
+
 Echo "Performing '$MAKE $MAKEOPTS basics OPTS="$OPTS" QUIET="$QUIET"' in $VERSION/tmp"
 cd $DESTINATION/tmp 
 $MAKE $MAKEOPTS basics OPTS="$OPTS $BUILD_SHARED" QUIET="$QUIET"
@@ -585,7 +598,7 @@ then
        Echo "-------------------------------------------------"
        Echo "$PROGRAM built successfully."
        Echo "Next, try out a sample program like" \
-            "tests/charm++/simplearrayhello"
+            "$DESTINATION/tests/charm++/simplearrayhello"
 else
         printError
 fi
diff --git a/doc/charm++/controlpoints.tex b/doc/charm++/controlpoints.tex
new file mode 100644 (file)
index 0000000..a70d7b6
--- /dev/null
@@ -0,0 +1,128 @@
+\section{Control Point Automatic Tuning Framework}
+
+\index{Control Point Automatic Tuning Framework}
+\label{sec:controlpoint}
+
+
+\charmpp{} currently includes an experimental automatic tuning
+framework that can dynamically adapt a program at runtime to improve
+its performance. The program provides a set of tunable knobs that are
+adjusted automatically by the tuning framework. The user program also
+provides information about the control points so that intelligent
+tuning choices can be made. This information will be used to steer the
+program instead of requiring the tuning framework to blindly search
+the possible program configurations.
+
+\textbf{Warning: this is still an experimental feature not meant for production applications}
+
+\subsection{Exposing Control Points in a Charm++ Program}
+The program should include a header file before any of its \texttt{*.decl.h} files:
+
+\begin{alltt} 
+    #include <controlPoints.h> 
+\end{alltt} 
+
+The control point framework initializes itself, so no changes need to be made at startup in the program.
+
+The program will request the values for each control point on PE 0. Control point values are non-negative integers:
+
+\begin{alltt} 
+    my_var = controlPoint("any_name", 5, 10);
+    my_var2 = controlPoint("another_name", 100,101);
+\end{alltt} 
+
+To specify information about the effects of each control point, make calls such as these once on PE 0 before accessing any control point values:
+
+\begin{alltt} 
+    ControlPoint::EffectDecrease::Granularity("num_chare_rows");
+    ControlPoint::EffectDecrease::Granularity("num_chare_cols");
+    ControlPoint::EffectIncrease::NumMessages("num_chare_rows");
+    ControlPoint::EffectIncrease::NumMessages("num_chare_cols");
+    ControlPoint::EffectDecrease::MessageSizes("num_chare_rows");
+    ControlPoint::EffectDecrease::MessageSizes("num_chare_cols");
+    ControlPoint::EffectIncrease::Concurrency("num_chare_rows");
+    ControlPoint::EffectIncrease::Concurrency("num_chare_cols");
+    ControlPoint::EffectIncrease::NumComputeObjects("num_chare_rows");
+    ControlPoint::EffectIncrease::NumComputeObjects("num_chare_cols");
+\end{alltt} 
+
+For a complete list of these functions, see \texttt{cp\_effects.h} in \texttt{charm/include}.
+
+
+The program, of course, has to adapt its behavior to use these new control point values. There are two ways for a the control point values to change over time. The program can request that a new phase (with its own control point values) be used whenever it wants, or the control point framework can automatically advance to a new phase periodically. The structure of the program will be slightly different in these to cases. Sections \ref{frameworkAdvancesPhases} and \ref{programAdvancesPhases} describe the additional changes to the program that should be made for each case.
+
+\subsubsection{Control Point Framework Advances Phases}
+\label{frameworkAdvancesPhases}
+
+The program provides a callback to the control point framework in a manner such as this:
+
+\begin{alltt} 
+    // Once early on in program, create a callback, and register it 
+    CkCallback cb(CkIndex_Main::granularityChange(NULL),thisProxy); 
+    registerCPChangeCallback(cb, true);
+\end{alltt} 
+
+In the callback or after the callback has executed, the program should request the new control point values on PE 0, and adapt its behavior appropriately.
+
+Alternatively, the program can specify that it wants to call \texttt{gotoNextPhase();} itself when it is ready. Perhaps the program wishes to delay its adaptation for a while. To do this, it specifies \texttt{false} as the final parameter to \texttt{registerCPChangeCallback} as follows:
+
+\begin{alltt} 
+   registerCPChangeCallback(cb, false);
+\end{alltt} 
+
+
+\subsubsection{Program Advances Phases}
+\label{programAdvancesPhases}
+
+\begin{alltt} 
+     registerControlPointTiming(duration); // called after each program iteration on PE 0
+     gotoNextPhase(); // called after some number of iterations on PE 0
+    // Then request new control point values
+\end{alltt} 
+
+
+
+\subsection{Linking With The Control Point Framework}
+
+The program should be linked with the following options to compile in the control point framework:
+
+\texttt{-module ControlPoints -tracemode controlPoints}
+
+The \texttt{ControlPoint} module contains the framework code responsible for recording information about the running program as well as adjust the control point values. The trace module will enable measurements to be gathered including information about utilization, idle time, and memory usage. 
+
+\subsection{Runtime Command Line Arguments}
+
+Various following command line arguments will affect the behavior of the program when running with the control point framework. As this is an experimental framework, these are subject to change.
+
+The scheme used for tuning can be selected at runtime by the use of one of the following options:
+\begin{alltt} 
+    +CPSchemeRandom            Randomly Select Control Point Values
+ +CPExhaustiveSearch            Exhaustive Search of Control Point Values
+      +CPSimulAnneal            Simulated Annealing Search of Control Point Values
+ +CPCriticalPathPrio            Use Critical Path to adapt Control Point Values
+        +CPBestKnown            Use BestKnown Timing for Control Point Values
+         +CPSteering            Use Steering to adjust Control Point Values
+      +CPMemoryAware            Adjust control points to approach available memory
+\end{alltt} 
+
+To intelligently tune or steer an application's performance, performance measurements ought to be used. Some of the schemes above require that memory footprint statistics and utilization statistics be gathered. The following flags enable the gathering of such measurements.
+\begin{alltt} 
+       +CPGatherAll            Gather all types of measurements for each phase
++CPGatherMemoryUsage            Gather memory usage after each phase
++CPGatherUtilization            Gather utilization & Idle time after each phase
+\end{alltt} 
+
+
+The control point framework will periodically adapt the control point values. The following command line flag determines the frequency at which the control point framework will attempt to adjust things.
+\begin{alltt} 
+     +CPSamplePeriod     number The time between Control Point Framework samples (in seconds)
+\end{alltt} 
+
+The data from one run of the program can be saved and used in subsequent runs. The following command line arguments specify that a file named \texttt{controlPointData.txt} should be created or loaded. This file contains measurements for each phase as well as the control point values used in each phase. 
+\begin{alltt} 
+        +CPSaveData            Save Control Point timings & configurations at completion
+         +CPLoadData            Load Control Point timings & configurations at startup
+\end{alltt} 
+
+It might be useful for example, to run once with \texttt{+CPSimulAnneal +CPSaveData} to try to find a good configuration for the program, and then use  \texttt{+CPBestKnown +CPLoadData} for all subsequent production runs.
+
index dc5fcb480b8dffe3f4f894f24e57d46fd537915a..fd16eaf092613a1ca079405c00bba9a9b0b77f40 100644 (file)
@@ -114,6 +114,6 @@ a pointer.
 \index{python}\item[python] entry methods are methods which are enabled to be
 called from python scripts running as explained in section~\ref{python}. In
 order to work, the object owning the method must also be declared with the
-keywork \kw{python}.
+keyword \kw{python}.
 
 \end{description}
index b39e0d583a0cff320c64fde01223bcc80b043260..e55a5655b32581178e68e99fdbdb6dbda6a8d267 100644 (file)
@@ -2,60 +2,64 @@
 
 \usepackage{../pplmanual} \input{../pplmanual} \usepackage{html}
 \title{The\\ \charmpp\\ Programming Language\\ Manual} \version{6.0
-(Release 1)} \credits{ {\small The Charm software was developed as a
-group effort.  The earliest prototype, Chare Kernel(1.0), was
-developed by Wennie Shu and Kevin Nomura working with Laxmikant Kale.
-The second prototype, Chare Kernel(2.0), a complete re-write with
-major design changes, was developed by a team consisting of Wayne
-Fenton, Balkrishna Ramkumar, Vikram Saletore, Amitabh B. Sinha and
-Laxmikant Kale. The translator for Chare Kernel(2.0) was written by
-Manish Gupta.  Charm(3.0), with significant design changes, was
-developed by a team consisting of Attila Gursoy, Balkrishna Ramkumar,
-Amitabh B.  Sinha and Laxmikant Kale, with a new translator written by
-Nimish Shah.  The \charmpp\ implementation was done by Sanjeev
-Krishnan.  Charm(4.0) included \charmpp\ and was released in fall
-1993.  Charm(4.5) was developed by Attila Gursoy, Sanjeev Krishnan,
-Milind Bhandarkar, Joshua Yelon, Narain Jagathesan and Laxmikant Kale.
-Charm(4.8), developed by the same team included Converse, a parallel
-runtime system that allows interoperability among modules written
-using different paradigms within a single application. \charmpp\
-runtime system was re-targetted at Converse. Syntactic extensions in
-\charmpp\ were dropped, and a simple interface translator was
-developed (by Sanjeev Krishnan and Jay DeSouza) that, along with the
-\charmpp\ runtime, became the \charmpp\ language.  Charm (5.4R1)
-included the following: a complete rewrite of the \charmpp\ runtime
-system (using \CC) and the interface translator (done by Milind
-Bhandarkar), several new features such as Chare Arrays (developed by
-Robert Brunner and Orion Lawlor), various libraries (written by Terry
-Wilmarth, Gengbin Zheng, Laxmikant Kale, Zehra Sura, Milind
-Bhandarkar, Robert Brunner, and Krishnan Varadarajan.) A coordination
-language ``Structured Dagger'' was been implemented on top of
-\charmpp\ (Milind Bhandarkar), dynamic seed-based load balancing
-(Terry Wilmarth and Joshua Yelon), a client-server interface for
-Converse programs, and debugging support by Parthasarathy
-Ramachandran, Jeff Wright, and Milind Bhandarkar, Projections, the
-performance visualization and analysis tool, was redesigned and
-rewritten using Java by Michael Denardo. The test suite for \charmpp\
-was developed by Michael Lang, Jackie Wang, and Fang Hu. Converse was
-been ported to ASCI Red (Joshua Yelon), Cray T3E (Robert Brunner), and
-SGI Origin2000 (Milind Bhandarkar). For the current version Charm 6.0
-(R1), Converse has been ported to new platforms including
-BlueGene/[LP] (Kumar, Huang, Bhatele), Cray XT3/4 (Zheng), Apple G5,
-Myrinet (Zheng), and Infiniband (Chakravorty).  Charm 6.0 introduces a
-dedicated no network SMP multicore Converse layer for stand-alone
-workstation experimenters (Zheng, Chakravorty, Kale, Jetley).  Charm
-6.0 also includes cross platform network topology aware chare
-placement for 3D tori and mesh networks (Kumar, Huang, Bhatele,
-Bohm). The test suite was extended for automated testing on all
-supported platforms by Gengbin Zheng.  The Projection tool was
-substantially improved by Chee Wai Lee and Isaac Dooley. Debugging
-support was enhanced with memory inspection features by Filippo
-Gioachin. The Charisma orchestration language was implemented on top
-of Charm++ by Chao Huang and Sanjay Kale.  Sanjay Kale, Orion Lawlor,
-Gengbin Zheng, Terry Wilmarth, Filippo Gioachin, Sayantan Chakravorty,
-Chao Huang, David Kunzman, Isaac Dooley, Eric Bohm, Sameer Kumar, Chao
-Mei, Pritish Jetley, and Abhinav Bhatele, have been responsible for
-the changes to the system since the last release.  } }
+  (Release 1)} \credits{ {\small The Charm software was developed as a
+    group effort.  The earliest prototype, Chare Kernel(1.0), was
+    developed by Wennie Shu and Kevin Nomura working with Laxmikant
+    Kale.  The second prototype, Chare Kernel(2.0), a complete
+    re-write with major design changes, was developed by a team
+    consisting of Wayne Fenton, Balkrishna Ramkumar, Vikram Saletore,
+    Amitabh B. Sinha and Laxmikant Kale. The translator for Chare
+    Kernel(2.0) was written by Manish Gupta.  Charm(3.0), with
+    significant design changes, was developed by a team consisting of
+    Attila Gursoy, Balkrishna Ramkumar, Amitabh B.  Sinha and
+    Laxmikant Kale, with a new translator written by Nimish Shah.  The
+    \charmpp\ implementation was done by Sanjeev Krishnan.  Charm(4.0)
+    included \charmpp\ and was released in fall 1993.  Charm(4.5) was
+    developed by Attila Gursoy, Sanjeev Krishnan, Milind Bhandarkar,
+    Joshua Yelon, Narain Jagathesan and Laxmikant Kale.  Charm(4.8),
+    developed by the same team included Converse, a parallel runtime
+    system that allows interoperability among modules written using
+    different paradigms within a single application. \charmpp\ runtime
+    system was re-targetted at Converse. Syntactic extensions in
+    \charmpp\ were dropped, and a simple interface translator was
+    developed (by Sanjeev Krishnan and Jay DeSouza) that, along with
+    the \charmpp\ runtime, became the \charmpp\ language.  Charm
+    (5.4R1) included the following: a complete rewrite of the
+    \charmpp\ runtime system (using \CC) and the interface translator
+    (done by Milind Bhandarkar), several new features such as Chare
+    Arrays (developed by Robert Brunner and Orion Lawlor), various
+    libraries (written by Terry Wilmarth, Gengbin Zheng, Laxmikant
+    Kale, Zehra Sura, Milind Bhandarkar, Robert Brunner, and Krishnan
+    Varadarajan.) A coordination language ``Structured Dagger'' was
+    been implemented on top of \charmpp\ (Milind Bhandarkar), dynamic
+    seed-based load balancing (Terry Wilmarth and Joshua Yelon), a
+    client-server interface for Converse programs, and debugging
+    support by Parthasarathy Ramachandran, Jeff Wright, and Milind
+    Bhandarkar, Projections, the performance visualization and
+    analysis tool, was redesigned and rewritten using Java by Michael
+    Denardo. The test suite for \charmpp\ was developed by Michael
+    Lang, Jackie Wang, and Fang Hu. Converse was been ported to ASCI
+    Red (Joshua Yelon), Cray T3E (Robert Brunner), and SGI Origin2000
+    (Milind Bhandarkar). For the current version Charm 6.0 (R1),
+    Converse has been ported to new platforms including BlueGene/[LP]
+    (Kumar, Huang, Bhatele), Cray XT3/4 (Zheng), Apple G5, Myrinet
+    (Zheng), and Infiniband (Chakravorty).  Charm 6.0 introduces a
+    dedicated no network SMP multicore Converse layer for stand-alone
+    workstation experimenters (Zheng, Chakravorty, Kale, Jetley).
+    Charm 6.0 also includes cross platform network topology aware
+    chare placement for 3D tori and mesh networks (Kumar, Huang,
+    Bhatele, Bohm). The test suite was extended for automated testing
+    on all supported platforms by Gengbin Zheng.  The Projection tool
+    was substantially improved by Chee Wai Lee and Isaac Dooley. The
+    Control Point performance tuning framework was created by Isaac
+    Dooley. Debugging support was enhanced with memory inspection
+    features by Filippo Gioachin. The Charisma orchestration language
+    was implemented on top of Charm++ by Chao Huang and Sanjay Kale.
+    Sanjay Kale, Orion Lawlor, Gengbin Zheng, Terry Wilmarth, Filippo
+    Gioachin, Sayantan Chakravorty, Chao Huang, David Kunzman, Isaac
+    Dooley, Eric Bohm, Sameer Kumar, Chao Mei, Pritish Jetley, and
+    Abhinav Bhatele, have been responsible for the changes to the
+    system since the last release.  } }
 
 \begin{document}
 
@@ -90,6 +94,9 @@ the changes to the system since the last release.  } }
 
 \input{checkpoint}
 
+\input{controlpoints}
+
+
 \appendix
 
 \input{sdag}
index 9757f0880db54c42fa10fdb546209091d655c06a..defad4afeb7c69253134fd5a0fc851550c2d83e0 100644 (file)
@@ -119,7 +119,7 @@ later in this subsection).
 
 \item[high level]
 In order to have the ability to call high level \charmpp{} functions (available
-through the keywork \kw{python}) this flag must be set to true. If it is false,
+through the keyword \kw{python}) this flag must be set to true. If it is false,
 the entire module ``charm'' will not be present, but the startup of the script
 will be faster.
 
index 7ffbf1a3cea438eae6de62af017b0bff76761029..e23a99fedc673bbb8662303baaf0ed73bb0eadd6 100644 (file)
@@ -13,7 +13,7 @@ will likely contain bug fixes not found in the releases.
 \subsubsection{How do I compile Charm++?}
 
 Run the interactive build script {\tt ./build} with no extra arguments If this fails,
-email \htmladdnormallink{ppl@cs.uiuc.edu}{mailto:ppl@cs.uiuc.edu} with the
+email \htmladdnormallink{charm AT cs.uiuc.edu}{mailto:charm AT cs.uiuc.edu} with the
 problem. Include the build line used (this is saved automatically in
 {\tt smart-build.log})
 
@@ -22,7 +22,7 @@ If you have a very unusual machine configuration, you will have to run
 architecture, and then you may have to modify the associated conf-mach.sh and
 conv-mach.h files in src/arch to point to your desired compilers and options. If
 you develop a significantly different platform, send the modified files to
-\htmladdnormallink{ppl@cs.uiuc.edu}{mailto:ppl@cs.uiuc.edu} so we can include it
+\htmladdnormallink{charm AT cs.uiuc.edu}{mailto:charm AT cs.uiuc.edu} so we can include it
 in the distribution.
 
 \subsubsection{How do I compile AMPI?}
index 9ade097a9f5763e1e9fecd33adbdc0ed84d8b896..2444960b5cf0f70b6cf971068962ecf41134dc50 100644 (file)
@@ -4,14 +4,15 @@
 \usepackage{html}
 
 \title{\charmpp{}\\Frequently Asked Questions}
-\version{5.9 (Release 1)}
+\version{6.2 pre-release}
 \credits{empty}
 
 \begin{document}
 
 \maketitle
 
-For answers to questions not on this list, please contact us at \htmladdnormallink{ppl@cs.uiuc.edu}{mailto:ppl@cs.uiuc.edu}
+For answers to questions not on this list, please contact us at
+\htmladdnormallink{charm AT cs.uiuc.edu}{mailto:charm AT cs.uiuc.edu}
 
 \input{overview}
 \input{install}
index 4ac624e810171b71086257215af9a39f6d9df1c7..ed665c12167f8b6efcfcb836172498b93f46858d 100644 (file)
@@ -92,5 +92,6 @@ The actual, legal license is included with Charm++ (in charm/LICENSE).
 \subsubsection{I have a suggestion/feature request/bug report. Who should I send
 it to?}
 
-Our mailing list is \htmladdnormallink{ppl@cs.uiuc.edu}{mailto:ppl@cs.uiuc.edu} and our Wiki is \htmladdnormallink{CharmWiki}{http://charm.cs.uiuc.edu/xTwiki/bin/view}.
+Our mailing list is \htmladdnormallink{charm AT
+  cs.uiuc.edu}{mailto:charm AT cs.uiuc.edu}.
 We're always glad to get feedback on our software.
index 8bc9b7d94abbd89a84cb661a305c9f4fbfcb312b..e9fd298308f88e2ba3a23efa8f13837d9e04384c 100644 (file)
@@ -1,4 +1,4 @@
-DIRS=charm++ converse ampi fem armci bigsim ParFUM
+DIRS=charm++ converse ampi fem ParFUM armci bigsim
 
 
 all:
index e80f043b515ef9bf6c0436294254012f4475ea5b..2ef8a5ceb279508aa8723a230fd39ff8746eda46 100644 (file)
@@ -3,7 +3,7 @@ CHARMC=../../../bin/charmc -language ampi $(OPTS)
 MPICC=mpicc $(OPTS)
 
 #all : pingpong-2way.c
-#      $(CHARMC) pingpong-2wayc -o pgm
+#      $(CHARMC) pingpong-2way.c -o pgm
 #      $(MPICC) pingpong-2way.c -o pgm-mpi
 
 all : pingpong-1way.c
index 5a99b3631ad1e462c8b1ac11e59c189be3f6dd41..1384684babc7a37056f66175b5e01182cb66b5da 100644 (file)
@@ -76,7 +76,12 @@ Main::Main(CkArgMsg* msg) {
            numStepsRemaining,
            STEPS_PER_PRINT
          );
-
+  if(sizeof(MD_FLOAT)==4)
+    CkPrintf("Single Precision\n");
+  else  if(sizeof(MD_FLOAT)==8)
+    CkPrintf("Double Precision\n");
+  else 
+    CkPrintf("Precision %d bytes\n",sizeof(MD_FLOAT));
   // DMK - DEBUG
   #if ENABLE_USER_EVENTS != 0
     traceRegisterUserEvent("Patch::forceCheckIn_callback()", PROJ_USER_EVENT_PATCH_FORCECHECKIN_CALLBACK);
@@ -144,7 +149,7 @@ Main::Main(CkArgMsg* msg) {
     int numPairComputes = 0;
     for (int i = 0; i < numPEs; i++) { numPairComputes += peStats[i]; }
     for (int i = 0; i < numPEs; i++) {
-      CkPrintf("[STATS] :: peStats[%d] = %6d (%5.2f%%)\n", i, peStats[i], ((float)peStats[i]) / ((float)numPairComputes) * 100.0f);
+      CkPrintf("[STATS] :: peStats[%d] = %6d (%5.2f%%)\n", i, peStats[i], ((float)peStats[i]) / ((float)numPairComputes) * 10zero);
     }
   #endif
 
index ca6521fff8337c5268240c99512eeef87779490d..c5b13c8a0e2a5fd1692b5d8bf0e0dc3077a65d15 100644 (file)
@@ -5,6 +5,45 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Default Simulation Parameters
 
+
+// convenience typedefs and consts to facilitate float vs double usage
+#define USE_DOUBLE 0
+#if USE_DOUBLE
+typedef double  MD_FLOAT;
+#define  MD_VEC veclf
+const double zero=0.0;
+const double one=1.0;
+const double two=2.0;
+#define myvec_numElems veclf_numElems;
+#define vextract_MDF vextractlf
+#define vsub_MDF vsublf
+#define vadd_MDF vaddlf
+#define vmadd_MDF vmaddlf
+#define vmul_MDF vmullf
+#define vspread_MDF vspreadlf
+#define vrecip_MDF vreciplf
+#define vsqrt_MDF vsqrtlf
+#define visfinite_MDF visfinitelf
+#else
+typedef float  MD_FLOAT;
+#define  MD_VEC vecf
+#define myvec_numElems vecf_numElems;
+const float zero=0.0f;
+const float one=1.0f;
+const float two=2.0f;
+
+#define vextract_MDF vextractf
+#define vsub_MDF vsubf
+#define vadd_MDF vaddf
+#define vmadd_MDF vmaddf
+#define vmul_MDF vmulf
+#define vspread_MDF vspreadf
+#define vrecip_MDF vrecipf
+#define vsqrt_MDF vsqrtf
+#define visfinite_MDF visfinitef
+#endif
+
+
 #define DEFAULT_NUM_PARTICLES_PER_PATCH  (128)
 
 #define DEFAULT_NUM_PATCHES_X              (2)
 ////////////////////////////////////////////////////////////////////////////////
 // Physics Constants
 
+#if USE_DOUBLE
+#define TIME_PER_STEP       (1.0e-15)           // Unit: s
+#define SIM_BOX_SIDE_LEN    (1.0e-7)            // Unit: m (NOTE: 1 nm = 10A)
+#define COULOMBS_CONSTANT   (8.987551787e-9)    // Unit: N*(m^2)*(C^-2)
+#define ELECTRON_CHARGE     (-1.602176487e-19)  // Unit: C
+#define ELECTRON_MASS       (9.109382154e-31)   // Unit: kg
+#else
 #define TIME_PER_STEP       (1.0e-15f)           // Unit: s
 #define SIM_BOX_SIDE_LEN    (1.0e-7f)            // Unit: m (NOTE: 1 nm = 10A)
 #define COULOMBS_CONSTANT   (8.987551787e-9f)    // Unit: N*(m^2)*(C^-2)
 #define ELECTRON_CHARGE     (-1.602176487e-19f)  // Unit: C
 #define ELECTRON_MASS       (9.109382154e-31f)   // Unit: kg
-
+#endif
 
 ////////////////////////////////////////////////////////////////////////////////
 // Misc. Helper Macros
@@ -50,6 +96,9 @@
 // DMK - DEBUG
 #define COUNT_FLOPS                      (0)
 
+// EJB - SANITY CHECK
+#define SANITY_CHECK                     (0)
+
 // DMK - DEBUG
 #define ENABLE_USER_EVENTS               (0)
 #define PROJ_USER_EVENT_PATCH_FORCECHECKIN_CALLBACK  (1120)
index 903681e7412c36c0fd286f0910a1852a1c938522..662f20c9417dc56157087f52f2d7e06aae2fe836 100644 (file)
@@ -47,21 +47,21 @@ void PairCompute::init(int numParticlesPerPatch) {
   // Initialize the arrays
   numParticles = numParticlesPerPatch;
   #if USE_PROXY_PATCHES == 0
-    particleX[0] = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-    particleX[1] = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-    particleY[0] = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-    particleY[1] = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-    particleZ[0] = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-    particleZ[1] = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-    particleQ[0] = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-    particleQ[1] = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
+    particleX[0] = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+    particleX[1] = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+    particleY[0] = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+    particleY[1] = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+    particleZ[0] = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+    particleZ[1] = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+    particleQ[0] = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+    particleQ[1] = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
   #endif
-  forceX[0] = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  forceX[1] = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  forceY[0] = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  forceY[1] = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  forceZ[0] = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  forceZ[1] = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
+  forceX[0] = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  forceX[1] = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  forceY[0] = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  forceY[1] = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  forceZ[0] = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  forceZ[1] = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
   patchDataCount = 0;
 
   // Check in with the main chare
@@ -69,14 +69,14 @@ void PairCompute::init(int numParticlesPerPatch) {
 }
 
 
-void PairCompute::patchData(int numParticles, float* particleX, float* particleY, float* particleZ, float* particleQ, int fromPatch, CProxy_ProxyPatch proxyPatchProxy) {
+void PairCompute::patchData(int numParticles, MD_FLOAT* particleX, MD_FLOAT* particleY, MD_FLOAT* particleZ, MD_FLOAT* particleQ, int fromPatch, CProxy_ProxyPatch proxyPatchProxy) {
   #if USE_PROXY_PATCHES != 0
     this->proxyPatchProxy[fromPatch] = proxyPatchProxy;
   #endif
   patchData(numParticles, particleX, particleY, particleZ, particleQ, fromPatch);
 }
 
-void PairCompute::patchData(int numParticles, float* particleX, float* particleY, float* particleZ, float* particleQ, int fromPatch) {
+void PairCompute::patchData(int numParticles, MD_FLOAT* particleX, MD_FLOAT* particleY, MD_FLOAT* particleZ, MD_FLOAT* particleQ, int fromPatch) {
 
   // Copy the data from the parameters
   #if USE_PROXY_PATCHES != 0
@@ -85,10 +85,10 @@ void PairCompute::patchData(int numParticles, float* particleX, float* particleY
     this->particleZ[fromPatch] = particleZ;
     this->particleQ[fromPatch] = particleQ;
   #else
-    memcpy(this->particleX[fromPatch], particleX, numParticles * sizeof(float));
-    memcpy(this->particleY[fromPatch], particleY, numParticles * sizeof(float));
-    memcpy(this->particleZ[fromPatch], particleZ, numParticles * sizeof(float));
-    memcpy(this->particleQ[fromPatch], particleQ, numParticles * sizeof(float));
+    memcpy(this->particleX[fromPatch], particleX, numParticles * sizeof(MD_FLOAT));
+    memcpy(this->particleY[fromPatch], particleY, numParticles * sizeof(MD_FLOAT));
+    memcpy(this->particleZ[fromPatch], particleZ, numParticles * sizeof(MD_FLOAT));
+    memcpy(this->particleQ[fromPatch], particleQ, numParticles * sizeof(MD_FLOAT));
   #endif
 
   // Increment the patch count and initiate the calculation of both patches have
index 3b414390955d607682c63e255f00d290da627b97..0d60813b23b7798549634c50d4827ea340111ef9 100644 (file)
@@ -10,30 +10,30 @@ module pairCompute {
     entry void init(int numParticlesPerPatch);
 
     entry void patchData(int numParticles,
-                         float particleX[numParticles],
-                         float particleY[numParticles],
-                         float particleZ[numParticles],
-                         float particleQ[numParticles],
+                         MD_FLOAT particleX[numParticles],
+                         MD_FLOAT particleY[numParticles],
+                         MD_FLOAT particleZ[numParticles],
+                         MD_FLOAT particleQ[numParticles],
                          int fromPatch
                         );
 
     entry [accel] void doCalc()[  readonly : int numParticles <impl_obj->numParticles>,
                                   readonly : int thisIndex_x <impl_obj->thisIndex.x>,
                                   readonly : int thisIndex_y <impl_obj->thisIndex.y>,
-                                  readonly : float p0_x[numParticles] <impl_obj->particleX[0]>,
-                                  readonly : float p1_x[numParticles] <impl_obj->particleX[1]>,
-                                  readonly : float p0_y[numParticles] <impl_obj->particleY[0]>,
-                                  readonly : float p1_y[numParticles] <impl_obj->particleY[1]>,
-                                  readonly : float p0_z[numParticles] <impl_obj->particleZ[0]>,
-                                  readonly : float p1_z[numParticles] <impl_obj->particleZ[1]>,
-                                  readonly : float p0_q[numParticles] <impl_obj->particleQ[0]>,
-                                  readonly : float p1_q[numParticles] <impl_obj->particleQ[1]>,
-                                 writeonly : float f0_x[numParticles] <impl_obj->forceX[0]>,
-                                 writeonly : float f1_x[numParticles] <impl_obj->forceX[1]>,
-                                 writeonly : float f0_y[numParticles] <impl_obj->forceY[0]>,
-                                 writeonly : float f1_y[numParticles] <impl_obj->forceY[1]>,
-                                 writeonly : float f0_z[numParticles] <impl_obj->forceZ[0]>,
-                                 writeonly : float f1_z[numParticles] <impl_obj->forceZ[1]>,
+                                  readonly : MD_FLOAT p0_x[numParticles] <impl_obj->particleX[0]>,
+                                  readonly : MD_FLOAT p1_x[numParticles] <impl_obj->particleX[1]>,
+                                  readonly : MD_FLOAT p0_y[numParticles] <impl_obj->particleY[0]>,
+                                  readonly : MD_FLOAT p1_y[numParticles] <impl_obj->particleY[1]>,
+                                  readonly : MD_FLOAT p0_z[numParticles] <impl_obj->particleZ[0]>,
+                                  readonly : MD_FLOAT p1_z[numParticles] <impl_obj->particleZ[1]>,
+                                  readonly : MD_FLOAT p0_q[numParticles] <impl_obj->particleQ[0]>,
+                                  readonly : MD_FLOAT p1_q[numParticles] <impl_obj->particleQ[1]>,
+                                 writeonly : MD_FLOAT f0_x[numParticles] <impl_obj->forceX[0]>,
+                                 writeonly : MD_FLOAT f1_x[numParticles] <impl_obj->forceX[1]>,
+                                 writeonly : MD_FLOAT f0_y[numParticles] <impl_obj->forceY[0]>,
+                                 writeonly : MD_FLOAT f1_y[numParticles] <impl_obj->forceY[1]>,
+                                 writeonly : MD_FLOAT f0_z[numParticles] <impl_obj->forceZ[0]>,
+                                 writeonly : MD_FLOAT f1_z[numParticles] <impl_obj->forceZ[1]>,
                                  writeonly : unsigned int localFlopCount <impl_obj->localFlopCount>
                                ] {
 
@@ -51,20 +51,20 @@ module pairCompute {
         localFlopCount = 0;
       #endif
 
-      register vecf* p1_x_vec = (vecf*)p1_x;
-      register vecf* p1_y_vec = (vecf*)p1_y;
-      register vecf* p1_z_vec = (vecf*)p1_z;
-      register vecf* p1_q_vec = (vecf*)p1_q;
-      register vecf* f1_x_vec = (vecf*)f1_x;
-      register vecf* f1_y_vec = (vecf*)f1_y;
-      register vecf* f1_z_vec = (vecf*)f1_z;
+      register MD_VEC* p1_x_vec = (MD_VEC*)p1_x;
+      register MD_VEC* p1_y_vec = (MD_VEC*)p1_y;
+      register MD_VEC* p1_z_vec = (MD_VEC*)p1_z;
+      register MD_VEC* p1_q_vec = (MD_VEC*)p1_q;
+      register MD_VEC* f1_x_vec = (MD_VEC*)f1_x;
+      register MD_VEC* f1_y_vec = (MD_VEC*)f1_y;
+      register MD_VEC* f1_z_vec = (MD_VEC*)f1_z;
       register int i;
       register int j;
-      register const int numParticlesByVecSize = numParticles / vecf_numElems;
+      register const int numParticlesByVecSize = numParticles / myvec_numElems;
 
       // Zero out the force array for p1 (p0's force array will be zero'ed for each
       //   particle in the outer loop)
-      vecf zero_vec = vspreadf(0.0f);
+      MD_VEC zero_vec = vspread_MDF(zero);
       for (j = 0; j < numParticlesByVecSize; j++) {
         f1_x_vec[j] = zero_vec;
         f1_y_vec[j] = zero_vec;
@@ -72,19 +72,19 @@ module pairCompute {
       }
 
       // Spread coulumb's constant across a vector
-      vecf coulomb_vec = vspreadf(COULOMBS_CONSTANT);
+      MD_VEC coulomb_vec = vspread_MDF(COULOMBS_CONSTANT);
 
       // Outer-loop (p0)
       for (i = 0; i < numParticles; i++) {
 
         // Spread this particle's values out over vectors
-        vecf p0_x_i_vec = vspreadf(p0_x[i]);
-        vecf p0_y_i_vec = vspreadf(p0_y[i]);
-        vecf p0_z_i_vec = vspreadf(p0_z[i]);
-        vecf p0_q_i_vec = vspreadf(p0_q[i]);
-        vecf f0_x_i_vec = vspreadf(0.0f);
-        vecf f0_y_i_vec = vspreadf(0.0f);
-        vecf f0_z_i_vec = vspreadf(0.0f);
+        MD_VEC p0_x_i_vec = vspread_MDF(p0_x[i]);
+        MD_VEC p0_y_i_vec = vspread_MDF(p0_y[i]);
+        MD_VEC p0_z_i_vec = vspread_MDF(p0_z[i]);
+        MD_VEC p0_q_i_vec = vspread_MDF(p0_q[i]);
+        MD_VEC f0_x_i_vec = vspread_MDF(zero);
+        MD_VEC f0_y_i_vec = vspread_MDF(zero);
+        MD_VEC f0_z_i_vec = vspread_MDF(zero);
 
         #if 1
 
@@ -97,22 +97,21 @@ module pairCompute {
         /// Loop Preamble ///
 
         const int loopUpper = numParticlesByVecSize - 3;
-
         // Setup Input for Stage 2 - Initially for j+2
         const int jPlus2 = 2;
-        vecf p1_x_j_vec = p1_x_vec[jPlus2];
-        vecf p1_y_j_vec = p1_y_vec[jPlus2];
-        vecf p1_z_j_vec = p1_z_vec[jPlus2];
-        vecf p1_q_j_vec = p1_q_vec[jPlus2];
+        MD_VEC p1_x_j_vec = p1_x_vec[jPlus2];
+        MD_VEC p1_y_j_vec = p1_y_vec[jPlus2];
+        MD_VEC p1_z_j_vec = p1_z_vec[jPlus2];
+        MD_VEC p1_q_j_vec = p1_q_vec[jPlus2];
 
         // Setup Input for Stage 3 - Initial for j+1
         const int jPlus1 = 1;
-        vecf p_x_diff_vec = p0_x_i_vec - p1_x_vec[jPlus1];
-        vecf p_y_diff_vec = p0_y_i_vec - p1_y_vec[jPlus1];
-        vecf p_z_diff_vec = p0_z_i_vec - p1_z_vec[jPlus1];
-        vecf p1_q_j_vec_s2 = p1_q_vec[jPlus1];
-        vecf r_2_vec = (p_x_diff_vec * p_x_diff_vec) + (p_y_diff_vec * p_y_diff_vec) + (p_z_diff_vec * p_z_diff_vec);
-        vecf r_vec = vsqrtf(r_2_vec);
+        MD_VEC p_x_diff_vec = p0_x_i_vec - p1_x_vec[jPlus1];
+        MD_VEC p_y_diff_vec = p0_y_i_vec - p1_y_vec[jPlus1];
+        MD_VEC p_z_diff_vec = p0_z_i_vec - p1_z_vec[jPlus1];
+        MD_VEC p1_q_j_vec_s2 = p1_q_vec[jPlus1];
+        MD_VEC r_2_vec = (p_x_diff_vec * p_x_diff_vec) + (p_y_diff_vec * p_y_diff_vec) + (p_z_diff_vec * p_z_diff_vec);
+        MD_VEC r_vec = vsqrt_MDF(r_2_vec);
 
         // DMK - DEBUG
         #if COUNT_FLOPS != 0
@@ -121,21 +120,21 @@ module pairCompute {
 
         // Setup Input for Stage 4 - Initially for j+0
         const int jPlus0 = 0;
-        vecf f_x_vec;
-        vecf f_y_vec;
-        vecf f_z_vec;
+        MD_VEC f_x_vec;
+        MD_VEC f_y_vec;
+        MD_VEC f_z_vec;
         {
-          vecf p_x_diff_vec = p0_x_i_vec - p1_x_vec[jPlus0];
-          vecf p_y_diff_vec = p0_y_i_vec - p1_y_vec[jPlus0];
-          vecf p_z_diff_vec = p0_z_i_vec - p1_z_vec[jPlus0];
-          vecf r_2_vec = (p_x_diff_vec * p_x_diff_vec) + (p_y_diff_vec * p_y_diff_vec) + (p_z_diff_vec * p_z_diff_vec);
-          vecf r_vec = vsqrtf(r_2_vec);
-          vecf r_recip_vec = vrecipf(r_vec);
-          vecf r_2_recip_vec = vrecipf(r_2_vec);
-          vecf p_x_diff_norm_vec = p_x_diff_vec * r_recip_vec;
-          vecf p_y_diff_norm_vec = p_y_diff_vec * r_recip_vec;
-          vecf p_z_diff_norm_vec = p_z_diff_vec * r_recip_vec;
-          vecf f_mag_vec = coulomb_vec * ((p0_q_i_vec * p1_q_vec[jPlus0]) * r_2_recip_vec);
+          MD_VEC p_x_diff_vec = p0_x_i_vec - p1_x_vec[jPlus0];
+          MD_VEC p_y_diff_vec = p0_y_i_vec - p1_y_vec[jPlus0];
+          MD_VEC p_z_diff_vec = p0_z_i_vec - p1_z_vec[jPlus0];
+          MD_VEC r_2_vec = (p_x_diff_vec * p_x_diff_vec) + (p_y_diff_vec * p_y_diff_vec) + (p_z_diff_vec * p_z_diff_vec);
+          MD_VEC r_vec = vsqrt_MDF(r_2_vec);
+          MD_VEC r_recip_vec = vrecip_MDF(r_vec);
+          MD_VEC r_2_recip_vec = vrecip_MDF(r_2_vec);
+          MD_VEC p_x_diff_norm_vec = p_x_diff_vec * r_recip_vec;
+          MD_VEC p_y_diff_norm_vec = p_y_diff_vec * r_recip_vec;
+          MD_VEC p_z_diff_norm_vec = p_z_diff_vec * r_recip_vec;
+          MD_VEC f_mag_vec = coulomb_vec * ((p0_q_i_vec * p1_q_vec[jPlus0]) * r_2_recip_vec);
           f_x_vec = p_x_diff_norm_vec * f_mag_vec;
           f_y_vec = p_y_diff_norm_vec * f_mag_vec;
           f_z_vec = p_z_diff_norm_vec * f_mag_vec;
@@ -153,31 +152,31 @@ module pairCompute {
           #if 1
 
           // Stage 4 - Apply force vector
-          f0_x_i_vec = vaddf(f0_x_i_vec, f_x_vec);
-          f0_y_i_vec = vaddf(f0_y_i_vec, f_y_vec);
-          f0_z_i_vec = vaddf(f0_z_i_vec, f_z_vec);
-          f1_x_vec[j] = vsubf(f1_x_vec[j], f_x_vec);
-          f1_y_vec[j] = vsubf(f1_y_vec[j], f_y_vec);
-          f1_z_vec[j] = vsubf(f1_z_vec[j], f_z_vec);
+          f0_x_i_vec = vadd_MDF(f0_x_i_vec, f_x_vec);
+          f0_y_i_vec = vadd_MDF(f0_y_i_vec, f_y_vec);
+          f0_z_i_vec = vadd_MDF(f0_z_i_vec, f_z_vec);
+          f1_x_vec[j] = vsub_MDF(f1_x_vec[j], f_x_vec);
+          f1_y_vec[j] = vsub_MDF(f1_y_vec[j], f_y_vec);
+          f1_z_vec[j] = vsub_MDF(f1_z_vec[j], f_z_vec);
 
           // Stage 3 - Calculate force vector
-          vecf r_recip_vec = vrecipf(r_vec);
-          vecf r_2_recip_vec = vrecipf(r_2_vec);
-          vecf p_z_diff_norm_vec = vmulf(p_z_diff_vec, r_recip_vec);
-          vecf p_y_diff_norm_vec = vmulf(p_y_diff_vec, r_recip_vec);
-          vecf p_x_diff_norm_vec = vmulf(p_x_diff_vec, r_recip_vec);
-          vecf f_mag_vec = vmulf(vmulf(coulomb_vec, p0_q_i_vec), vmulf(p1_q_j_vec_s2, r_2_recip_vec));
-          f_x_vec = vmulf(p_x_diff_norm_vec, f_mag_vec);
-          f_y_vec = vmulf(p_y_diff_norm_vec, f_mag_vec);
-          f_z_vec = vmulf(p_z_diff_norm_vec, f_mag_vec);
+          MD_VEC r_recip_vec = vrecip_MDF(r_vec);
+          MD_VEC r_2_recip_vec = vrecip_MDF(r_2_vec);
+          MD_VEC p_z_diff_norm_vec = vmul_MDF(p_z_diff_vec, r_recip_vec);
+          MD_VEC p_y_diff_norm_vec = vmul_MDF(p_y_diff_vec, r_recip_vec);
+          MD_VEC p_x_diff_norm_vec = vmul_MDF(p_x_diff_vec, r_recip_vec);
+          MD_VEC f_mag_vec = vmul_MDF(vmul_MDF(coulomb_vec, p0_q_i_vec), vmul_MDF(p1_q_j_vec_s2, r_2_recip_vec));
+          f_x_vec = vmul_MDF(p_x_diff_norm_vec, f_mag_vec);
+          f_y_vec = vmul_MDF(p_y_diff_norm_vec, f_mag_vec);
+          f_z_vec = vmul_MDF(p_z_diff_norm_vec, f_mag_vec);
 
           // Stage 2 - Calculate radius
           p1_q_j_vec_s2 = p1_q_j_vec;
-          p_x_diff_vec = vsubf(p0_x_i_vec, p1_x_j_vec);
-          p_y_diff_vec = vsubf(p0_y_i_vec, p1_y_j_vec);
-          p_z_diff_vec = vsubf(p0_z_i_vec, p1_z_j_vec);
-          r_2_vec = vmaddf(p_x_diff_vec, p_x_diff_vec, vmaddf(p_y_diff_vec, p_y_diff_vec, vmulf(p_z_diff_vec, p_z_diff_vec)));
-          r_vec = vsqrtf(r_2_vec);
+          p_x_diff_vec = vsub_MDF(p0_x_i_vec, p1_x_j_vec);
+          p_y_diff_vec = vsub_MDF(p0_y_i_vec, p1_y_j_vec);
+          p_z_diff_vec = vsub_MDF(p0_z_i_vec, p1_z_j_vec);
+          r_2_vec = vmadd_MDF(p_x_diff_vec, p_x_diff_vec, vmadd_MDF(p_y_diff_vec, p_y_diff_vec, vmul_MDF(p_z_diff_vec, p_z_diff_vec)));
+          r_vec = vsqrt_MDF(r_2_vec);
 
           // Stage 1 - Load particle data
           const int jIndexToLoad = j + 3;
@@ -197,12 +196,12 @@ module pairCompute {
           f1_z_vec[j] -= f_z_vec;
 
           // Stage 3 - Calculate force vector
-          vecf r_recip_vec = vrecipf(r_vec);
-          vecf r_2_recip_vec = vrecipf(r_2_vec);
-          vecf p_x_diff_norm_vec = p_x_diff_vec * r_recip_vec;
-          vecf p_y_diff_norm_vec = p_y_diff_vec * r_recip_vec;
-          vecf p_z_diff_norm_vec = p_z_diff_vec * r_recip_vec;
-          vecf f_mag_vec = coulomb_vec * p0_q_i_vec * p1_q_j_vec_s2 * r_2_recip_vec;  // Calc force magnitude
+          MD_VEC r_recip_vec = vrecip_MDF(r_vec);
+          MD_VEC r_2_recip_vec = vrecip_MDF(r_2_vec);
+          MD_VEC p_x_diff_norm_vec = p_x_diff_vec * r_recip_vec;
+          MD_VEC p_y_diff_norm_vec = p_y_diff_vec * r_recip_vec;
+          MD_VEC p_z_diff_norm_vec = p_z_diff_vec * r_recip_vec;
+          MD_VEC f_mag_vec = coulomb_vec * p0_q_i_vec * p1_q_j_vec_s2 * r_2_recip_vec;  // Calc force magnitude
           f_x_vec = p_x_diff_norm_vec * f_mag_vec;  // Multiply normalized vector by force magnitude
           f_y_vec = p_y_diff_norm_vec * f_mag_vec;
           f_z_vec = p_z_diff_norm_vec * f_mag_vec;
@@ -213,7 +212,7 @@ module pairCompute {
           p_y_diff_vec = p0_y_i_vec - p1_y_j_vec;
           p_z_diff_vec = p0_z_i_vec - p1_z_j_vec;
           r_2_vec = (p_x_diff_vec * p_x_diff_vec) + (p_y_diff_vec * p_y_diff_vec) + (p_z_diff_vec * p_z_diff_vec);
-          r_vec = vsqrtf(r_2_vec);
+          r_vec = vsqrt_MDF(r_2_vec);
 
           // Stage 1 - Load particle data
           const int jIndexToLoad = j + 3;
@@ -249,15 +248,15 @@ module pairCompute {
 
         // Complete Calc for Stage 2 Data - Calculate Force Vector, Apply Force Vector
         {
-          vecf r_recip_vec = vrecipf(r_vec);
-          vecf r_2_recip_vec = vrecipf(r_2_vec);
-          vecf p_x_diff_norm_vec = p_x_diff_vec * r_recip_vec;
-          vecf p_y_diff_norm_vec = p_y_diff_vec * r_recip_vec;
-          vecf p_z_diff_norm_vec = p_z_diff_vec * r_recip_vec;
-          vecf f_mag_vec = coulomb_vec * ((p0_q_i_vec * p1_q_j_vec_s2) * r_2_recip_vec);
-          vecf f_x_vec = p_x_diff_norm_vec * f_mag_vec;
-          vecf f_y_vec = p_y_diff_norm_vec * f_mag_vec;
-          vecf f_z_vec = p_z_diff_norm_vec * f_mag_vec;
+          MD_VEC r_recip_vec = vrecip_MDF(r_vec);
+          MD_VEC r_2_recip_vec = vrecip_MDF(r_2_vec);
+          MD_VEC p_x_diff_norm_vec = p_x_diff_vec * r_recip_vec;
+          MD_VEC p_y_diff_norm_vec = p_y_diff_vec * r_recip_vec;
+          MD_VEC p_z_diff_norm_vec = p_z_diff_vec * r_recip_vec;
+          MD_VEC f_mag_vec = coulomb_vec * ((p0_q_i_vec * p1_q_j_vec_s2) * r_2_recip_vec);
+          MD_VEC f_x_vec = p_x_diff_norm_vec * f_mag_vec;
+          MD_VEC f_y_vec = p_y_diff_norm_vec * f_mag_vec;
+          MD_VEC f_z_vec = p_z_diff_norm_vec * f_mag_vec;
           f0_x_i_vec += f_x_vec;
           f0_y_i_vec += f_y_vec;
           f0_z_i_vec += f_z_vec;
@@ -273,20 +272,20 @@ module pairCompute {
 
         // Complete Calc for Stage 1 Data - Calculate Radius, Calculate Force Vector, Apply Force Vector
         {
-          vecf p_x_diff_vec = p0_x_i_vec - p1_x_j_vec;
-          vecf p_y_diff_vec = p0_y_i_vec - p1_y_j_vec;
-          vecf p_z_diff_vec = p0_z_i_vec - p1_z_j_vec;
-          vecf r_2_vec = (p_x_diff_vec * p_x_diff_vec) + (p_y_diff_vec * p_y_diff_vec) + (p_z_diff_vec * p_z_diff_vec);
-          vecf r_vec = vsqrtf(r_2_vec);
-          vecf r_recip_vec = vrecipf(r_vec);
-          vecf r_2_recip_vec = vrecipf(r_2_vec);
-          vecf p_x_diff_norm_vec = p_x_diff_vec * r_recip_vec;
-          vecf p_y_diff_norm_vec = p_y_diff_vec * r_recip_vec;
-          vecf p_z_diff_norm_vec = p_z_diff_vec * r_recip_vec;
-          vecf f_mag_vec = coulomb_vec * ((p0_q_i_vec * p1_q_j_vec) * r_2_recip_vec);
-          vecf f_x_vec = p_x_diff_norm_vec * f_mag_vec;
-          vecf f_y_vec = p_y_diff_norm_vec * f_mag_vec;
-          vecf f_z_vec = p_z_diff_norm_vec * f_mag_vec;
+          MD_VEC p_x_diff_vec = p0_x_i_vec - p1_x_j_vec;
+          MD_VEC p_y_diff_vec = p0_y_i_vec - p1_y_j_vec;
+          MD_VEC p_z_diff_vec = p0_z_i_vec - p1_z_j_vec;
+          MD_VEC r_2_vec = (p_x_diff_vec * p_x_diff_vec) + (p_y_diff_vec * p_y_diff_vec) + (p_z_diff_vec * p_z_diff_vec);
+          MD_VEC r_vec = vsqrt_MDF(r_2_vec);
+          MD_VEC r_recip_vec = vrecip_MDF(r_vec);
+          MD_VEC r_2_recip_vec = vrecip_MDF(r_2_vec);
+          MD_VEC p_x_diff_norm_vec = p_x_diff_vec * r_recip_vec;
+          MD_VEC p_y_diff_norm_vec = p_y_diff_vec * r_recip_vec;
+          MD_VEC p_z_diff_norm_vec = p_z_diff_vec * r_recip_vec;
+          MD_VEC f_mag_vec = coulomb_vec * ((p0_q_i_vec * p1_q_j_vec) * r_2_recip_vec);
+          MD_VEC f_x_vec = p_x_diff_norm_vec * f_mag_vec;
+          MD_VEC f_y_vec = p_y_diff_norm_vec * f_mag_vec;
+          MD_VEC f_z_vec = p_z_diff_norm_vec * f_mag_vec;
           f0_x_i_vec += f_x_vec;
           f0_y_i_vec += f_y_vec;
           f0_z_i_vec += f_z_vec;
@@ -306,36 +305,36 @@ module pairCompute {
         for (j = 0; j < numParticlesByVecSize; j++) {
 
           // Load the particles' data
-          vecf p1_x_j_vec = p1_x_vec[j];
-          vecf p1_y_j_vec = p1_y_vec[j];
-          vecf p1_z_j_vec = p1_z_vec[j];
-          vecf p1_q_j_vec = p1_q_vec[j];
+          MD_VEC p1_x_j_vec = p1_x_vec[j];
+          MD_VEC p1_y_j_vec = p1_y_vec[j];
+          MD_VEC p1_z_j_vec = p1_z_vec[j];
+          MD_VEC p1_q_j_vec = p1_q_vec[j];
 
           // Calculate the vector between the particles
-          vecf p_x_diff_vec = p0_x_i_vec - p1_x_j_vec;
-          vecf p_y_diff_vec = p0_y_i_vec - p1_y_j_vec;
-          vecf p_z_diff_vec = p0_z_i_vec - p1_z_j_vec;
+          MD_VEC p_x_diff_vec = p0_x_i_vec - p1_x_j_vec;
+          MD_VEC p_y_diff_vec = p0_y_i_vec - p1_y_j_vec;
+          MD_VEC p_z_diff_vec = p0_z_i_vec - p1_z_j_vec;
 
           // Calculate r and r^2 between the particles
-          vecf p_x_diff_2_vec = p_x_diff_vec * p_x_diff_vec;
-          vecf p_y_diff_2_vec = p_y_diff_vec * p_y_diff_vec;
-          vecf p_z_diff_2_vec = p_z_diff_vec * p_z_diff_vec;
-          vecf r_2_vec = p_x_diff_2_vec + p_y_diff_2_vec + p_z_diff_2_vec;
-          vecf r_vec = vsqrtf(r_2_vec);
+          MD_VEC p_x_diff_2_vec = p_x_diff_vec * p_x_diff_vec;
+          MD_VEC p_y_diff_2_vec = p_y_diff_vec * p_y_diff_vec;
+          MD_VEC p_z_diff_2_vec = p_z_diff_vec * p_z_diff_vec;
+          MD_VEC r_2_vec = p_x_diff_2_vec + p_y_diff_2_vec + p_z_diff_2_vec;
+          MD_VEC r_vec = vsqrt_MDF(r_2_vec);
 
           // Normalize the vector between the particles
-          vecf p_x_diff_norm_vec = p_x_diff_vec / r_vec;
-          vecf p_y_diff_norm_vec = p_y_diff_vec / r_vec;
-          vecf p_z_diff_norm_vec = p_z_diff_vec / r_vec;
+          MD_VEC p_x_diff_norm_vec = p_x_diff_vec / r_vec;
+          MD_VEC p_y_diff_norm_vec = p_y_diff_vec / r_vec;
+          MD_VEC p_z_diff_norm_vec = p_z_diff_vec / r_vec;
 
           // Calculate the magnitude of the electrostatic force between the particles
-          vecf f_mag_vec = coulomb_vec * ((p0_q_i_vec * p1_q_j_vec) / r_2_vec);
+          MD_VEC f_mag_vec = coulomb_vec * ((p0_q_i_vec * p1_q_j_vec) / r_2_vec);
 
           // Multiply the magnitude by the normalized postition difference vector to
           //   create the force vector
-          vecf f_x_vec = p_x_diff_norm_vec * f_mag_vec;
-          vecf f_y_vec = p_y_diff_norm_vec * f_mag_vec;
-          vecf f_z_vec = p_z_diff_norm_vec * f_mag_vec;
+          MD_VEC f_x_vec = p_x_diff_norm_vec * f_mag_vec;
+          MD_VEC f_y_vec = p_y_diff_norm_vec * f_mag_vec;
+          MD_VEC f_z_vec = p_z_diff_norm_vec * f_mag_vec;
 
           // Add the force to the outer-loop particle and subtract it from the inner-loop particles
           f0_x_i_vec += f_x_vec;
@@ -353,11 +352,23 @@ module pairCompute {
         }
 
         #endif
-
         // Write force values for the outer-loop particle back to memory
-        f0_x[i] = vextractf(f0_x_i_vec, 0) + vextractf(f0_x_i_vec, 1) + vextractf(f0_x_i_vec, 2) + vextractf(f0_x_i_vec, 3);
-        f0_y[i] = vextractf(f0_y_i_vec, 0) + vextractf(f0_y_i_vec, 1) + vextractf(f0_y_i_vec, 2) + vextractf(f0_y_i_vec, 3);
-        f0_z[i] = vextractf(f0_z_i_vec, 0) + vextractf(f0_z_i_vec, 1) + vextractf(f0_z_i_vec, 2) + vextractf(f0_z_i_vec, 3);
+#ifdef USE_DOUBLE
+        f0_x[i] = vextract_MDF(f0_x_i_vec, 0) + vextract_MDF(f0_x_i_vec, 1);
+        f0_y[i] = vextract_MDF(f0_y_i_vec, 0) + vextract_MDF(f0_y_i_vec, 1);
+        f0_z[i] = vextract_MDF(f0_z_i_vec, 0) + vextract_MDF(f0_z_i_vec, 1);
+#else
+
+        f0_x[i] = vextract_MDF(f0_x_i_vec, 0) + vextract_MDF(f0_x_i_vec, 1) + vextract_MDF(f0_x_i_vec, 2) + vextract_MDF(f0_x_i_vec, 3);
+        f0_y[i] = vextract_MDF(f0_y_i_vec, 0) + vextract_MDF(f0_y_i_vec, 1) + vextract_MDF(f0_y_i_vec, 2) + vextract_MDF(f0_y_i_vec, 3);
+        f0_z[i] = vextract_MDF(f0_z_i_vec, 0) + vextract_MDF(f0_z_i_vec, 1) + vextract_MDF(f0_z_i_vec, 2) + vextract_MDF(f0_z_i_vec, 3);
+#endif
+#if SANITY_CHECK
+       CkAssert(finite(f0_x[i]));
+       CkAssert(finite(f0_y[i]));
+       CkAssert(finite(f0_z[i]));
+
+#endif 
       }
 
       // DMK - DEBUG
@@ -369,7 +380,7 @@ module pairCompute {
           CkPrintf("[DEBUG] :: PairCompute[%d,%d]::doCalc() - Took %lf ms to execute... numParticles:%d\n"
                    "             p0[0] = { %e, %e, %e : %e }, p1[0] = { %e, %e, %e : %e }...\n"
                    "             f0[0] = { %e, %e, %e }, f1[0] = { %e, %e, %e }...\n",
-                   thisIndex_x, thisIndex_y, deltaTime * 1000.0f, numParticles,
+                   thisIndex_x, thisIndex_y, deltaTime * 100zero, numParticles,
                    p0_x[0], p0_y[0], p0_z[0], p0_q[0], p1_x[0], p1_y[0], p1_z[0], p1_q[0],
                    f0_x[0], f0_y[0], f0_z[0], f1_x[0], f1_y[0], f1_z[0]
                   );
index b6f3729640b08354d16a0e10d8da67f473ee1885..0dc8371dff54fb8c97e59b25a05da8fc03d6240c 100644 (file)
@@ -19,15 +19,15 @@ class PairCompute : public CBase_PairCompute {
     int patchDataCount;
 
     /// Particle Buffers ///
-    float* particleX[2];
-    float* particleY[2];
-    float* particleZ[2];
-    float* particleQ[2];
+    MD_FLOAT* particleX[2];
+    MD_FLOAT* particleY[2];
+    MD_FLOAT* particleZ[2];
+    MD_FLOAT* particleQ[2];
 
     /// Force Buffers ///
-    float* forceX[2];
-    float* forceY[2];
-    float* forceZ[2];
+    MD_FLOAT* forceX[2];
+    MD_FLOAT* forceY[2];
+    MD_FLOAT* forceZ[2];
 
     #if USE_PROXY_PATCHES != 0
       CProxy_ProxyPatch proxyPatchProxy[2];
@@ -45,8 +45,8 @@ class PairCompute : public CBase_PairCompute {
 
     /// Entry Methods ///
     void init(int numParticlesPerPatch);
-    void patchData(int numParticles, float* particleX, float* particleY, float* particleZ, float* particleQ, int fromPatch, CProxy_ProxyPatch proxyPatchProxy);
-    void patchData(int numParticles, float* particleX, float* particleY, float* particleZ, float* particleQ, int fromPatch);
+    void patchData(int numParticles, MD_FLOAT* particleX, MD_FLOAT* particleY, MD_FLOAT* particleZ, MD_FLOAT* particleQ, int fromPatch, CProxy_ProxyPatch proxyPatchProxy);
+    void patchData(int numParticles, MD_FLOAT* particleX, MD_FLOAT* particleY, MD_FLOAT* particleZ, MD_FLOAT* particleQ, int fromPatch);
     void doCalc_callback();
 
 };
index 195d7a8ecd25dfd17fae6be9c6d774ebb1ffa2a6..97fa43e8a53bddc5da9c9229421281267fea31e5 100644 (file)
@@ -8,14 +8,14 @@ void Patch::randomizeParticles() {
 
   // Fill in a box with electrons that initially have no velocity
   for (int i = 0; i < numParticles; i++) {
-    particleX[i] = (randf() * SIM_BOX_SIDE_LEN) - (SIM_BOX_SIDE_LEN / 2.0f);
-    particleY[i] = (randf() * SIM_BOX_SIDE_LEN) - (SIM_BOX_SIDE_LEN / 2.0f);
-    particleZ[i] = (randf() * SIM_BOX_SIDE_LEN) - (SIM_BOX_SIDE_LEN / 2.0f);
+    particleX[i] = (randf() * SIM_BOX_SIDE_LEN) - (SIM_BOX_SIDE_LEN / two);
+    particleY[i] = (randf() * SIM_BOX_SIDE_LEN) - (SIM_BOX_SIDE_LEN / two);
+    particleZ[i] = (randf() * SIM_BOX_SIDE_LEN) - (SIM_BOX_SIDE_LEN / two);
     particleQ[i] = ELECTRON_CHARGE;
     particleM[i] = ELECTRON_MASS;
-    velocityX[i] = 0.0f;
-    velocityY[i] = 0.0f;
-    velocityZ[i] = 0.0f;
+    velocityX[i] = zero;
+    velocityY[i] = zero;
+    velocityZ[i] = zero;
 
     // DMK - DEBUG
     #if DUMP_INITIAL_PARTICLE_DATA != 0
@@ -26,13 +26,24 @@ void Patch::randomizeParticles() {
                velocityX[i], velocityY[i], velocityZ[i]
               );
     #endif
+      //EJB DEBUG
+    #if SANITY_CHECK
+      CkAssert(finite(particleX[i]));
+      CkAssert(finite(particleY[i]));
+      CkAssert(finite(particleZ[i]));
+      CkAssert(finite(velocityX[i]));
+      CkAssert(finite(velocityY[i]));
+      CkAssert(finite(velocityZ[i]));
+    #endif 
+
   }
 }
 
 
-float Patch::randf() {
+MD_FLOAT Patch::randf() {
   const int mask = 0x7FFFFFFF;
-  return (((float)(rand() % mask)) / ((float)(mask)));
+  return (((MD_FLOAT)(rand() % mask)) / ((MD_FLOAT)(mask)));
+
 }
 
 
@@ -81,17 +92,17 @@ void Patch::init_common(int numParticles) {
 
   // Allocate memory for the particles
   this->numParticles = numParticles;
-  particleX = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  particleY = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  particleZ = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  particleQ = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  particleM = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  forceSumX = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  forceSumY = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  forceSumZ = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  velocityX = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  velocityY = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  velocityZ = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
+  particleX = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  particleY = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  particleZ = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  particleQ = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  particleM = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  forceSumX = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  forceSumY = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  forceSumZ = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  velocityX = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  velocityY = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  velocityZ = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
 
   // Initialize the particles
   randomizeParticles();
@@ -138,15 +149,15 @@ void Patch::startIteration_common(int numIters) {
 
   // Clear the force sum arrays
   #if 1
-    memset(forceSumX, 0, sizeof(float) * numParticles);
-    memset(forceSumY, 0, sizeof(float) * numParticles);
-    memset(forceSumZ, 0, sizeof(float) * numParticles);
+    memset(forceSumX, 0, sizeof(MD_FLOAT) * numParticles);
+    memset(forceSumY, 0, sizeof(MD_FLOAT) * numParticles);
+    memset(forceSumZ, 0, sizeof(MD_FLOAT) * numParticles);
   #else
-    register vecf* fsx = (vecf*)forceSumX;
-    register vecf* fsy = (vecf*)forceSumY;
-    register vecf* fsz = (vecf*)forceSumZ;
-    const vecf zero_vec = vspreadf(0.0f);
-    register const int numParticles_vec = numParticles / vecf_numElems;
+    register MD_VEC* fsx = (MD_VEC*)forceSumX;
+    register MD_VEC* fsy = (MD_VEC*)forceSumY;
+    register MD_VEC* fsz = (MD_VEC*)forceSumZ;
+    const MD_VEC zero_vec = vspread_MDF(zero);
+    register const int numParticles_vec = numParticles / myvec_numElems;
     for (int i = 0; i < numParticles_vec; i++) {
       fsx[i] = zero_vec;
       fsy[i] = zero_vec;
@@ -200,28 +211,33 @@ void Patch::startIteration_common(int numIters) {
 }
 
 
-void Patch::forceCheckIn(int numParticles, float* forceX, float* forceY, float* forceZ) {
+void Patch::forceCheckIn(int numParticles, MD_FLOAT* forceX, MD_FLOAT* forceY, MD_FLOAT* forceZ) {
   forceCheckIn(numParticles, forceX, forceY, forceZ, 1);
 }
-void Patch::forceCheckIn(int numParticles, float* forceX, float* forceY, float* forceZ, int numForceCheckIns) {
+void Patch::forceCheckIn(int numParticles, MD_FLOAT* forceX, MD_FLOAT* forceY, MD_FLOAT* forceZ, int numForceCheckIns) {
 
   // Accumulate the force data
   #if 0
-    register vecf* fsx = (vecf*)forceSumX;
-    register vecf* fsy = (vecf*)forceSumY;
-    register vecf* fsz = (vecf*)forceSumZ;
-    register vecf* fx = (vecf*)forceX;
-    register vecf* fy = (vecf*)forceY;
-    register vecf* fz = (vecf*)forceZ;
-    register const int numParticles_vec = numParticles / vecf_numElems;
+    register MD_VEC* fsx = (MD_VEC*)forceSumX;
+    register MD_VEC* fsy = (MD_VEC*)forceSumY;
+    register MD_VEC* fsz = (MD_VEC*)forceSumZ;
+    register MD_VEC* fx = (MD_VEC*)forceX;
+    register MD_VEC* fy = (MD_VEC*)forceY;
+    register MD_VEC* fz = (MD_VEC*)forceZ;
+    register const int numParticles_vec = numParticles / myvec_numElems;
     register int i;
     for (i = 0; i < numParticles_vec; i++) {
-      fsx[i] = vaddf(fsx[i], fx[i]);
-      fsy[i] = vaddf(fsy[i], fy[i]);
-      fsz[i] = vaddf(fsz[i], fz[i]);
+      fsx[i] = vadd_MDF(fsx[i], fx[i]);
+      fsy[i] = vadd_MDF(fsy[i], fy[i]);
+      fsz[i] = vadd_MDF(fsz[i], fz[i]);
     }
   #else
     for (int i = 0; i < numParticles; i++) {
+#if SANITY_CHECK
+      CkAssert(finite(forceX[i]));
+      CkAssert(finite(forceY[i]));
+      CkAssert(finite(forceZ[i]));
+#endif 
       forceSumX[i] += forceX[i];
       forceSumY[i] += forceY[i];
       forceSumZ[i] += forceZ[i];
@@ -300,31 +316,31 @@ void ProxyPatch::init(int numParticles) {
 
   // Allocate memory for the particles
   this->numParticles = numParticles;
-  particleX = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  particleY = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  particleZ = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  particleQ = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  forceSumX = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  forceSumY = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  forceSumZ = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
+  particleX = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  particleY = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  particleZ = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  particleQ = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  forceSumX = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  forceSumY = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  forceSumZ = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
 
   // Check in with the main proxy
   mainProxy.initCheckIn();
 }
 
 
-void ProxyPatch::patchData(int numParticles, float* particleX, float* particleY, float* particleZ, float* particleQ) {
+void ProxyPatch::patchData(int numParticles, MD_FLOAT* particleX, MD_FLOAT* particleY, MD_FLOAT* particleZ, MD_FLOAT* particleQ) {
 
   // Copy in the updated particle data
-  memcpy(this->particleX, particleX, numParticles * sizeof(float));
-  memcpy(this->particleY, particleY, numParticles * sizeof(float));
-  memcpy(this->particleZ, particleZ, numParticles * sizeof(float));
-  memcpy(this->particleQ, particleQ, numParticles * sizeof(float));
+  memcpy(this->particleX, particleX, numParticles * sizeof(MD_FLOAT));
+  memcpy(this->particleY, particleY, numParticles * sizeof(MD_FLOAT));
+  memcpy(this->particleZ, particleZ, numParticles * sizeof(MD_FLOAT));
+  memcpy(this->particleQ, particleQ, numParticles * sizeof(MD_FLOAT));
 
   // Clear out the force arrays
-  memset(this->forceSumX, 0, numParticles * sizeof(float));
-  memset(this->forceSumY, 0, numParticles * sizeof(float));
-  memset(this->forceSumZ, 0, numParticles * sizeof(float));
+  memset(this->forceSumX, 0, numParticles * sizeof(MD_FLOAT));
+  memset(this->forceSumY, 0, numParticles * sizeof(MD_FLOAT));
+  memset(this->forceSumZ, 0, numParticles * sizeof(MD_FLOAT));
 
   // Reset the patch checkin counters
   checkInCount = 0;
@@ -361,17 +377,17 @@ void ProxyPatch::patchData(int numParticles, float* particleX, float* particleY,
 }
 
 
-void ProxyPatch::forceCheckIn(int numParticles, float* forceX, float* forceY, float* forceZ) {
+void ProxyPatch::forceCheckIn(int numParticles, MD_FLOAT* forceX, MD_FLOAT* forceY, MD_FLOAT* forceZ) {
 
   // Accumulate the force data
   #if USE_PROXY_PATCHES != 0  // Calls will be local and pointers will be aligned, so take advantage and vectorize the code
-    register vecf* forceX_vec = (vecf*)forceX;
-    register vecf* forceY_vec = (vecf*)forceY;
-    register vecf* forceZ_vec = (vecf*)forceZ;
-    register vecf* forceSumX_vec = (vecf*)forceSumX;
-    register vecf* forceSumY_vec = (vecf*)forceSumY;
-    register vecf* forceSumZ_vec = (vecf*)forceSumZ;
-    const int numParticles_vec = numParticles / vecf_numElems;
+    register MD_VEC* forceX_vec = (MD_VEC*)forceX;
+    register MD_VEC* forceY_vec = (MD_VEC*)forceY;
+    register MD_VEC* forceZ_vec = (MD_VEC*)forceZ;
+    register MD_VEC* forceSumX_vec = (MD_VEC*)forceSumX;
+    register MD_VEC* forceSumY_vec = (MD_VEC*)forceSumY;
+    register MD_VEC* forceSumZ_vec = (MD_VEC*)forceSumZ;
+    const int numParticles_vec = numParticles / myvec_numElems;
     for (int i = 0; i < numParticles_vec; i++) {
       forceSumX_vec[i] += forceX_vec[i];
       forceSumY_vec[i] += forceY_vec[i];
index 5b23bf45c40db73703b737643a3be8ccf79f3a48..4ac7d72918c32c30b94a54e0db438a4048118652 100644 (file)
@@ -5,21 +5,21 @@ module patch {
   accelblock {
 
     void accumForce(int numParticles,
-                    float* forceSumX, float* forceSumY, float* forceSumZ,
-                    float* forceX, float* forceY, float* forceZ
+                    MD_FLOAT* forceSumX, MD_FLOAT* forceSumY, MD_FLOAT* forceSumZ,
+                    MD_FLOAT* forceX, MD_FLOAT* forceY, MD_FLOAT* forceZ
                    ) {
-      register vecf* fsx = (vecf*)forceSumX;
-      register vecf* fsy = (vecf*)forceSumY;
-      register vecf* fsz = (vecf*)forceSumZ;
-      register vecf* fx = (vecf*)forceX;
-      register vecf* fy = (vecf*)forceY;
-      register vecf* fz = (vecf*)forceZ;
-      register const int numParticles_vec = numParticles / vecf_numElems;
+      register MD_VEC* fsx = (MD_VEC*)forceSumX;
+      register MD_VEC* fsy = (MD_VEC*)forceSumY;
+      register MD_VEC* fsz = (MD_VEC*)forceSumZ;
+      register MD_VEC* fx = (MD_VEC*)forceX;
+      register MD_VEC* fy = (MD_VEC*)forceY;
+      register MD_VEC* fz = (MD_VEC*)forceZ;
+      register const int numParticles_vec = numParticles / myvec_numElems;
       register int i;
       for (i = 0; i < numParticles_vec; i++) {
-        fsx[i] = vaddf(fsx[i], fx[i]);
-        fsy[i] = vaddf(fsy[i], fy[i]);
-        fsz[i] = vaddf(fsz[i], fz[i]);
+        fsx[i] = vadd_MDF(fsx[i], fx[i]);
+        fsy[i] = vadd_MDF(fsy[i], fy[i]);
+        fsz[i] = vadd_MDF(fsz[i], fz[i]);
       }
     }
   };
@@ -31,16 +31,16 @@ module patch {
     entry void init(int numParticles);
 
     entry void patchData(int numParticles,
-                         float particleX[numParticles],
-                         float particleY[numParticles],
-                         float particleZ[numParticles],
-                         float particleQ[numParticles]
+                         MD_FLOAT particleX[numParticles],
+                         MD_FLOAT particleY[numParticles],
+                         MD_FLOAT particleZ[numParticles],
+                         MD_FLOAT particleQ[numParticles]
                         );
 
     entry void forceCheckIn(int numParticles,
-                            float forceX[numParticles],
-                            float forceY[numParticles],
-                            float forceZ[numParticles]
+                            MD_FLOAT forceX[numParticles],
+                            MD_FLOAT forceY[numParticles],
+                            MD_FLOAT forceZ[numParticles]
                            );
   };
 
@@ -55,14 +55,14 @@ module patch {
     entry void startIterations(int numIters);
 
     entry void forceCheckIn(int numParticles,
-                            float forceX[numParticles],
-                            float forceY[numParticles],
-                            float forceZ[numParticles]
+                            MD_FLOAT forceX[numParticles],
+                            MD_FLOAT forceY[numParticles],
+                            MD_FLOAT forceZ[numParticles]
                            );
     entry void forceCheckIn(int numParticles,
-                            float forceX[numParticles],
-                            float forceY[numParticles],
-                            float forceZ[numParticles],
+                            MD_FLOAT forceX[numParticles],
+                            MD_FLOAT forceY[numParticles],
+                            MD_FLOAT forceZ[numParticles],
                             int numForceCheckIns
                            );
 
@@ -70,16 +70,16 @@ module patch {
                                     readonly : int thisIndex_x <impl_obj->thisIndex.x>,
                                     readonly : int thisIndex_y <impl_obj->thisIndex.y>,
                                     readonly : int thisIndex_z <impl_obj->thisIndex.z>,
-                                   readwrite : float p_x[numParticles] <impl_obj->particleX>,
-                                   readwrite : float p_y[numParticles] <impl_obj->particleY>,
-                                   readwrite : float p_z[numParticles] <impl_obj->particleZ>,
-                                    readonly : float p_m[numParticles] <impl_obj->particleM>,
-                                    readonly : float f_x[numParticles] <impl_obj->forceSumX>,
-                                    readonly : float f_y[numParticles] <impl_obj->forceSumY>,
-                                    readonly : float f_z[numParticles] <impl_obj->forceSumZ>,
-                                   readwrite : float v_x[numParticles] <impl_obj->velocityX>,
-                                   readwrite : float v_y[numParticles] <impl_obj->velocityY>,
-                                   readwrite : float v_z[numParticles] <impl_obj->velocityZ>,
+                                   readwrite : MD_FLOAT p_x[numParticles] <impl_obj->particleX>,
+                                   readwrite : MD_FLOAT p_y[numParticles] <impl_obj->particleY>,
+                                   readwrite : MD_FLOAT p_z[numParticles] <impl_obj->particleZ>,
+                                    readonly : MD_FLOAT p_m[numParticles] <impl_obj->particleM>,
+                                    readonly : MD_FLOAT f_x[numParticles] <impl_obj->forceSumX>,
+                                    readonly : MD_FLOAT f_y[numParticles] <impl_obj->forceSumY>,
+                                    readonly : MD_FLOAT f_z[numParticles] <impl_obj->forceSumZ>,
+                                   readwrite : MD_FLOAT v_x[numParticles] <impl_obj->velocityX>,
+                                   readwrite : MD_FLOAT v_y[numParticles] <impl_obj->velocityY>,
+                                   readwrite : MD_FLOAT v_z[numParticles] <impl_obj->velocityZ>,
                                    writeonly : unsigned int localFlopCount <impl_obj->localFlopCount>
                                   ] {
 
@@ -88,28 +88,28 @@ module patch {
         localFlopCount = 0;
       #endif
 
-      register vecf* p_x_vec = (vecf*)p_x;
-      register vecf* p_y_vec = (vecf*)p_y;
-      register vecf* p_z_vec = (vecf*)p_z;
-      register vecf* p_m_vec = (vecf*)p_m;
-      register vecf* f_x_vec = (vecf*)f_x;
-      register vecf* f_y_vec = (vecf*)f_y;
-      register vecf* f_z_vec = (vecf*)f_z;
-      register vecf* v_x_vec = (vecf*)v_x;
-      register vecf* v_y_vec = (vecf*)v_y;
-      register vecf* v_z_vec = (vecf*)v_z;
+      register MD_VEC* p_x_vec = (MD_VEC*)p_x;
+      register MD_VEC* p_y_vec = (MD_VEC*)p_y;
+      register MD_VEC* p_z_vec = (MD_VEC*)p_z;
+      register MD_VEC* p_m_vec = (MD_VEC*)p_m;
+      register MD_VEC* f_x_vec = (MD_VEC*)f_x;
+      register MD_VEC* f_y_vec = (MD_VEC*)f_y;
+      register MD_VEC* f_z_vec = (MD_VEC*)f_z;
+      register MD_VEC* v_x_vec = (MD_VEC*)v_x;
+      register MD_VEC* v_y_vec = (MD_VEC*)v_y;
+      register MD_VEC* v_z_vec = (MD_VEC*)v_z;
       register int i;
-      register const int numParticles_vec = numParticles / vecf_numElems;
+      register const int numParticles_vec = numParticles / myvec_numElems;
 
-      vecf delta_time_vec = vspreadf(TIME_PER_STEP);
+      MD_VEC delta_time_vec = vspread_MDF(TIME_PER_STEP);
 
       // Add the acceleration to the velocity and add the update velocity to the position
       for (i = 0; i < numParticles_vec; i++) {
 
         // Update the velocity : v_new = v_old + (F/m)dt
-        vecf new_v_x_vec = v_x_vec[i] + (delta_time_vec * (f_x_vec[i] / p_m_vec[i]));
-        vecf new_v_y_vec = v_y_vec[i] + (delta_time_vec * (f_y_vec[i] / p_m_vec[i]));
-        vecf new_v_z_vec = v_z_vec[i] + (delta_time_vec * (f_z_vec[i] / p_m_vec[i]));
+        MD_VEC new_v_x_vec = v_x_vec[i] + (delta_time_vec * (f_x_vec[i] / p_m_vec[i]));
+        MD_VEC new_v_y_vec = v_y_vec[i] + (delta_time_vec * (f_y_vec[i] / p_m_vec[i]));
+        MD_VEC new_v_z_vec = v_z_vec[i] + (delta_time_vec * (f_z_vec[i] / p_m_vec[i]));
         v_x_vec[i] = new_v_x_vec;
         v_y_vec[i] = new_v_y_vec;
         v_z_vec[i] = new_v_z_vec;
index eb8ed11028bc30397ffc3e31f001fba78b846958..71f982456a862a20652e9fb2644d235aad858f53 100644 (file)
@@ -20,17 +20,17 @@ class Patch : public CBase_Patch {
     int remainingIterations;
 
     int numParticles;
-    float* particleX;  // x-coordinate
-    float* particleY;  // y-coordinate
-    float* particleZ;  // z-coordinate
-    float* particleQ;  // charge
-    float* particleM;  // mass
-    float* velocityX;  // velocity x-component
-    float* velocityY;  // velocity y-component
-    float* velocityZ;  // velocity z-component
-    float* forceSumX;  // Buffer to sum of force x components from computes
-    float* forceSumY;  // Buffer to sum of force y components from computes
-    float* forceSumZ;  // Buffer to sum of force z components from computes
+    MD_FLOAT* particleX;  // x-coordinate
+    MD_FLOAT* particleY;  // y-coordinate
+    MD_FLOAT* particleZ;  // z-coordinate
+    MD_FLOAT* particleQ;  // charge
+    MD_FLOAT* particleM;  // mass
+    MD_FLOAT* velocityX;  // velocity x-component
+    MD_FLOAT* velocityY;  // velocity y-component
+    MD_FLOAT* velocityZ;  // velocity z-component
+    MD_FLOAT* forceSumX;  // Buffer to sum of force x components from computes
+    MD_FLOAT* forceSumY;  // Buffer to sum of force y components from computes
+    MD_FLOAT* forceSumZ;  // Buffer to sum of force z components from computes
 
     #if USE_ARRAY_SECTIONS != 0
       CProxySection_PairCompute pairComputeArraySection_lower;
@@ -49,7 +49,7 @@ class Patch : public CBase_Patch {
 
     /// Member Functions ///
     void randomizeParticles();
-    float randf();
+    MD_FLOAT randf();
     void startIteration_common(int numIters);
 
   public:
@@ -65,8 +65,8 @@ class Patch : public CBase_Patch {
     void init_common(int numParticles);
     void startIteration();
     void startIterations(int numIters);
-    void forceCheckIn(int numParticles, float* forceX, float* forceY, float* forceZ);
-    void forceCheckIn(int numParticles, float* forceX, float* forceY, float* forceZ, int numForceCheckIns);
+    void forceCheckIn(int numParticles, MD_FLOAT* forceX, MD_FLOAT* forceY, MD_FLOAT* forceZ);
+    void forceCheckIn(int numParticles, MD_FLOAT* forceX, MD_FLOAT* forceY, MD_FLOAT* forceZ, int numForceCheckIns);
     void integrate_callback();
 
 };
@@ -82,13 +82,13 @@ class ProxyPatch : public CBase_ProxyPatch {
 
     /// Member Variables ///
     int numParticles;
-    float* particleX;
-    float* particleY;
-    float* particleZ;
-    float* particleQ;
-    float* forceSumX;
-    float* forceSumY;
-    float* forceSumZ;
+    MD_FLOAT* particleX;
+    MD_FLOAT* particleY;
+    MD_FLOAT* particleZ;
+    MD_FLOAT* particleQ;
+    MD_FLOAT* forceSumX;
+    MD_FLOAT* forceSumY;
+    MD_FLOAT* forceSumZ;
 
     int patchIndex;
 
@@ -104,8 +104,8 @@ class ProxyPatch : public CBase_ProxyPatch {
 
     /// Entry Methods ///
     void init(int numParticles);
-    void patchData(int numParticles, float* particleX, float* particleY, float* particleZ, float* particleQ);
-    void forceCheckIn(int numParticles, float* forceX, float* forceY, float* forceZ);
+    void patchData(int numParticles, MD_FLOAT* particleX, MD_FLOAT* particleY, MD_FLOAT* particleZ, MD_FLOAT* particleQ);
+    void forceCheckIn(int numParticles, MD_FLOAT* forceX, MD_FLOAT* forceY, MD_FLOAT* forceZ);
 
 };
 
index 8322638d29f6d83c70d0a246bbc1631bf6deef6e..950396ae6cf04bf21fe308ab6df60afb7b1ef34c 100644 (file)
@@ -38,28 +38,28 @@ void SelfCompute::init(int numParticlesPerPatch) {
   // Allocate buffers for force data
   numParticles = numParticlesPerPatch;
   #if USE_PROXY_PATCHES == 0
-    particleX = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-    particleY = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-    particleZ = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-    particleQ = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
+    particleX = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+    particleY = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+    particleZ = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+    particleQ = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
   #endif
-  forceX = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  forceY = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
-  forceZ = (float*)(CmiMallocAligned(numParticles * sizeof(float), 128));
+  forceX = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  forceY = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
+  forceZ = (MD_FLOAT*)(CmiMallocAligned(numParticles * sizeof(MD_FLOAT), 128));
 
   // Check in with the main chare
   mainProxy.initCheckIn();
 }
 
 
-void SelfCompute::patchData(int numParticles, float* particleX, float* particleY, float* particleZ, float* particleQ, CProxy_ProxyPatch proxyPatchProxy) {
+void SelfCompute::patchData(int numParticles, MD_FLOAT* particleX, MD_FLOAT* particleY, MD_FLOAT* particleZ, MD_FLOAT* particleQ, CProxy_ProxyPatch proxyPatchProxy) {
   #if USE_PROXY_PATCHES != 0
     this->proxyPatchProxy = proxyPatchProxy;
   #endif
   patchData(numParticles, particleX, particleY, particleZ, particleQ);
 }
 
-void SelfCompute::patchData(int numParticles, float* particleX, float* particleY, float* particleZ, float* particleQ) {
+void SelfCompute::patchData(int numParticles, MD_FLOAT* particleX, MD_FLOAT* particleY, MD_FLOAT* particleZ, MD_FLOAT* particleQ) {
 
   // Copy the data from the parameters
   #if USE_PROXY_PATCHES != 0
@@ -68,10 +68,10 @@ void SelfCompute::patchData(int numParticles, float* particleX, float* particleY
     this->particleZ = particleZ;
     this->particleQ = particleQ;
   #else
-    memcpy(this->particleX, particleX, numParticles * sizeof(float));
-    memcpy(this->particleY, particleY, numParticles * sizeof(float));
-    memcpy(this->particleZ, particleZ, numParticles * sizeof(float));
-    memcpy(this->particleQ, particleQ, numParticles * sizeof(float));
+    memcpy(this->particleX, particleX, numParticles * sizeof(MD_FLOAT));
+    memcpy(this->particleY, particleY, numParticles * sizeof(MD_FLOAT));
+    memcpy(this->particleZ, particleZ, numParticles * sizeof(MD_FLOAT));
+    memcpy(this->particleQ, particleQ, numParticles * sizeof(MD_FLOAT));
   #endif
 
   // Initiate the calculation for this compute
index e0c30d60f2195ee5564e51ece4131ea1f0626bff..5cb62ba2c85ecb82fe7b9d89690a4157772e4cbe 100644 (file)
@@ -10,23 +10,23 @@ module selfCompute {
     entry void init(int numParticlesPerPatch);
 
     entry void patchData(int numParticles,
-                         float particleX[numParticles],
-                         float particleY[numParticles],
-                         float particleZ[numParticles],
-                         float particleQ[numParticles]
+                         MD_FLOAT particleX[numParticles],
+                         MD_FLOAT particleY[numParticles],
+                         MD_FLOAT particleZ[numParticles],
+                         MD_FLOAT particleQ[numParticles]
                         );
 
     entry [accel] void doCalc()[
                                  readonly : int numParticles <impl_obj->numParticles>,
                                  readonly : int thisIndex_x <impl_obj->thisIndex.x>,
                                  readonly : int thisIndex_y <impl_obj->thisIndex.y>,
-                                 readonly : float particleX[numParticles] <impl_obj->particleX>,
-                                 readonly : float particleY[numParticles] <impl_obj->particleY>,
-                                 readonly : float particleZ[numParticles] <impl_obj->particleZ>,
-                                 readonly : float particleQ[numParticles] <impl_obj->particleQ>,
-                                writeonly : float f0_x[numParticles] <impl_obj->forceX>,
-                                writeonly : float f0_y[numParticles] <impl_obj->forceY>,
-                                writeonly : float f0_z[numParticles] <impl_obj->forceZ>,
+                                 readonly : MD_FLOAT particleX[numParticles] <impl_obj->particleX>,
+                                 readonly : MD_FLOAT particleY[numParticles] <impl_obj->particleY>,
+                                 readonly : MD_FLOAT particleZ[numParticles] <impl_obj->particleZ>,
+                                 readonly : MD_FLOAT particleQ[numParticles] <impl_obj->particleQ>,
+                                writeonly : MD_FLOAT f0_x[numParticles] <impl_obj->forceX>,
+                                writeonly : MD_FLOAT f0_y[numParticles] <impl_obj->forceY>,
+                                writeonly : MD_FLOAT f0_z[numParticles] <impl_obj->forceZ>,
                                 writeonly : unsigned int localFlopCount <impl_obj->localFlopCount>
                                ] {
 
@@ -42,20 +42,22 @@ module selfCompute {
       #if COUNT_FLOPS != 0
         localFlopCount = 0;
       #endif
-
-      register vecf* p0_x_vec = (vecf*)particleX;
-      register vecf* p0_y_vec = (vecf*)particleY;
-      register vecf* p0_z_vec = (vecf*)particleZ;
-      register vecf* p0_q_vec = (vecf*)particleQ;
-      register vecf* f0_x_vec = (vecf*)f0_x;
-      register vecf* f0_y_vec = (vecf*)f0_y;
-      register vecf* f0_z_vec = (vecf*)f0_z;
+      const int vec_numElems= myvec_numElems;
+      const int VEC_MASK= vec_numElems-1;
+      const int shifter= sizeof(MD_FLOAT)==4 ? 2 :1;
+      register MD_VEC* p0_x_vec = (MD_VEC*)particleX;
+      register MD_VEC* p0_y_vec = (MD_VEC*)particleY;
+      register MD_VEC* p0_z_vec = (MD_VEC*)particleZ;
+      register MD_VEC* p0_q_vec = (MD_VEC*)particleQ;
+      register MD_VEC* f0_x_vec = (MD_VEC*)f0_x;
+      register MD_VEC* f0_y_vec = (MD_VEC*)f0_y;
+      register MD_VEC* f0_z_vec = (MD_VEC*)f0_z;
       register int i;
       register int j;
-      register const int numParticlesByVecSize = numParticles / vecf_numElems;
+      register const int numParticlesByVecSize = numParticles / myvec_numElems;
 
       // Zero out the force output
-      vecf zero_vec = vspreadf(0.0f);
+      MD_VEC zero_vec = vspread_MDF(zero);
       for (j = 0; j < numParticlesByVecSize; j++) {
         f0_x_vec[j] = zero_vec;
         f0_y_vec[j] = zero_vec;
@@ -63,30 +65,30 @@ module selfCompute {
       }
 
       // Spread coulumb's constant across a vector
-      vecf coulomb_vec = vspreadf(COULOMBS_CONSTANT);
+      MD_VEC coulomb_vec = vspread_MDF(COULOMBS_CONSTANT);
 
       // Outer-loop
       for (i = 0; i < numParticles; i++) {
 
         // Interact with all particles (one-by-one) until the vector boundary
-        for (j = i + 1; ((j & 0x3) != 0x0) && (j < numParticles); j++) {
+        for (j = i + 1; ((j & VEC_MASK) != 0x0) && (j < numParticles); j++) {
 
-          float p_x_diff = particleX[i] - particleX[j];
-          float p_y_diff = particleY[i] - particleY[j];
-          float p_z_diff = particleZ[i] - particleZ[j];
-          float r_2 = (p_x_diff * p_x_diff) + (p_y_diff * p_y_diff) + (p_z_diff * p_z_diff);
-          float r = sqrt(r_2);
+          MD_FLOAT p_x_diff = particleX[i] - particleX[j];
+          MD_FLOAT p_y_diff = particleY[i] - particleY[j];
+          MD_FLOAT p_z_diff = particleZ[i] - particleZ[j];
+          MD_FLOAT r_2 = (p_x_diff * p_x_diff) + (p_y_diff * p_y_diff) + (p_z_diff * p_z_diff);
+          MD_FLOAT r = sqrt(r_2);
 
-          float p_x_diff_norm = p_x_diff / r;
-          float p_y_diff_norm = p_y_diff / r;
-          float p_z_diff_norm = p_z_diff / r;
+          MD_FLOAT p_x_diff_norm = p_x_diff / r;
+          MD_FLOAT p_y_diff_norm = p_y_diff / r;
+          MD_FLOAT p_z_diff_norm = p_z_diff / r;
 
-          float p_q_prod = particleQ[i] * particleQ[j];
-          float f_mag = COULOMBS_CONSTANT * (p_q_prod / r_2);
+          MD_FLOAT p_q_prod = particleQ[i] * particleQ[j];
+          MD_FLOAT f_mag = COULOMBS_CONSTANT * (p_q_prod / r_2);
 
-          float f_x = f_mag * p_x_diff_norm;
-          float f_y = f_mag * p_y_diff_norm;
-          float f_z = f_mag * p_z_diff_norm;
+          MD_FLOAT f_x = f_mag * p_x_diff_norm;
+          MD_FLOAT f_y = f_mag * p_y_diff_norm;
+          MD_FLOAT f_z = f_mag * p_z_diff_norm;
 
           f0_x[i] += f_x;
           f0_y[i] += f_y;
@@ -102,45 +104,55 @@ module selfCompute {
         }
 
         // Spread this particle's (p0[i]) values out over vectors
-        vecf p0_x_i_vec = vspreadf(particleX[i]);
-        vecf p0_y_i_vec = vspreadf(particleY[i]);
-        vecf p0_z_i_vec = vspreadf(particleZ[i]);
-        vecf p0_q_i_vec = vspreadf(particleQ[i]);
-        vecf f0_x_i_vec = vspreadf(0.0f);
-        vecf f0_y_i_vec = vspreadf(0.0f);
-        vecf f0_z_i_vec = vspreadf(0.0f);
+        MD_VEC p0_x_i_vec = vspread_MDF(particleX[i]);
+        MD_VEC p0_y_i_vec = vspread_MDF(particleY[i]);
+        MD_VEC p0_z_i_vec = vspread_MDF(particleZ[i]);
+        MD_VEC p0_q_i_vec = vspread_MDF(particleQ[i]);
+        MD_VEC f0_x_i_vec = vspread_MDF(zero);
+        MD_VEC f0_y_i_vec = vspread_MDF(zero);
+        MD_VEC f0_z_i_vec = vspread_MDF(zero);
 
         // Switch to vectorized loop for the remaining elements in the particle array
-        for (j = j >> 2; j < numParticlesByVecSize; j++) {
+       
+        for (j = j >>shifter; j < numParticlesByVecSize; j++) {
 
           // Load the particles' data
-          vecf p0_x_j_vec = p0_x_vec[j];
-          vecf p0_y_j_vec = p0_y_vec[j];
-          vecf p0_z_j_vec = p0_z_vec[j];
-          vecf p0_q_j_vec = p0_q_vec[j];
+          MD_VEC p0_x_j_vec = p0_x_vec[j];
+          MD_VEC p0_y_j_vec = p0_y_vec[j];
+          MD_VEC p0_z_j_vec = p0_z_vec[j];
+          MD_VEC p0_q_j_vec = p0_q_vec[j];
 
           // Calculate the vector between the particles
-          vecf p_x_diff_vec = p0_x_i_vec - p0_x_j_vec;
-          vecf p_y_diff_vec = p0_y_i_vec - p0_y_j_vec;
-          vecf p_z_diff_vec = p0_z_i_vec - p0_z_j_vec;
-
+          MD_VEC p_x_diff_vec = p0_x_i_vec - p0_x_j_vec;
+          MD_VEC p_y_diff_vec = p0_y_i_vec - p0_y_j_vec;
+          MD_VEC p_z_diff_vec = p0_z_i_vec - p0_z_j_vec;
           // Calculate r and r^2 between the particles
-          vecf r_2_vec = (p_x_diff_vec * p_x_diff_vec) + (p_y_diff_vec * p_y_diff_vec) + (p_z_diff_vec * p_z_diff_vec);
-          vecf r_vec = vsqrtf(r_2_vec);
+          MD_VEC r_2_vec = (p_x_diff_vec * p_x_diff_vec) + (p_y_diff_vec * p_y_diff_vec) + (p_z_diff_vec * p_z_diff_vec);
+          MD_VEC r_vec = vsqrt_MDF(r_2_vec);
 
           // Normalize the vector between the particles
-          vecf r_recip_vec = vrecipf(r_vec);
-          vecf r_2_recip_vec = vrecipf(r_2_vec);
-          vecf p_x_diff_norm_vec = p_x_diff_vec * r_recip_vec;
-          vecf p_y_diff_norm_vec = p_y_diff_vec * r_recip_vec;
-          vecf p_z_diff_norm_vec = p_z_diff_vec * r_recip_vec;
-          vecf f_mag_vec = coulomb_vec * p0_q_i_vec * p0_q_j_vec * r_2_recip_vec;  // Calc force magnitude
+          MD_VEC r_recip_vec = vrecip_MDF(r_vec);
+          MD_VEC r_2_recip_vec = vrecip_MDF(r_2_vec);
+#if SANITY_CHECK
+         CkAssert(visfinite_MDF(r_2_vec));
+         CkAssert(visfinite_MDF(r_vec));
+#endif
+//             CkAssert(&p0_x_vec !=);
+/*
+       { // how the hell does this not flake out?
+               CkPrintf("i %d j %d px_i %+6e px_j %+6e py_i %+6e py_j %+6e pz_i %+6e pz_j%+6e\n",i,j,vextract_MDF(p0_x_i_vec,0),vextract_MDF(p0_x_j_vec,0),vextract_MDF(p0_y_i_vec,0),vextract_MDF(p0_y_j_vec,0),vextract_MDF(p0_z_i_vec,0),vextract_MDF(p0_z_j_vec,0));
+       }
+*/
+          MD_VEC p_x_diff_norm_vec = p_x_diff_vec * r_recip_vec;
+          MD_VEC p_y_diff_norm_vec = p_y_diff_vec * r_recip_vec;
+          MD_VEC p_z_diff_norm_vec = p_z_diff_vec * r_recip_vec;
+          MD_VEC f_mag_vec = coulomb_vec * p0_q_i_vec * p0_q_j_vec * r_2_recip_vec;  // Calc force magnitude
 
           // Multiply the magnitude by the normalized postition difference vector to
           //   create the force vector
-          vecf f_x_vec = p_x_diff_norm_vec * f_mag_vec;
-          vecf f_y_vec = p_y_diff_norm_vec * f_mag_vec;
-          vecf f_z_vec = p_z_diff_norm_vec * f_mag_vec;
+          MD_VEC f_x_vec = p_x_diff_norm_vec * f_mag_vec;
+          MD_VEC f_y_vec = p_y_diff_norm_vec * f_mag_vec;
+          MD_VEC f_z_vec = p_z_diff_norm_vec * f_mag_vec;
 
           // Add the force to the outer-loop particle and subtract it from the inner-loop particles
           f0_x_i_vec += f_x_vec;
@@ -157,9 +169,9 @@ module selfCompute {
         }
 
         // Add force values for p0[i] into f0
-        f0_x[i] += vextractf(f0_x_i_vec, 0) + vextractf(f0_x_i_vec, 1) + vextractf(f0_x_i_vec, 2) + vextractf(f0_x_i_vec, 3);
-        f0_y[i] += vextractf(f0_y_i_vec, 0) + vextractf(f0_y_i_vec, 1) + vextractf(f0_y_i_vec, 2) + vextractf(f0_y_i_vec, 3);
-        f0_z[i] += vextractf(f0_z_i_vec, 0) + vextractf(f0_z_i_vec, 1) + vextractf(f0_z_i_vec, 2) + vextractf(f0_z_i_vec, 3);
+        f0_x[i] += vextract_MDF(f0_x_i_vec, 0) + vextract_MDF(f0_x_i_vec, 1) + vextract_MDF(f0_x_i_vec, 2) + vextract_MDF(f0_x_i_vec, 3);
+        f0_y[i] += vextract_MDF(f0_y_i_vec, 0) + vextract_MDF(f0_y_i_vec, 1) + vextract_MDF(f0_y_i_vec, 2) + vextract_MDF(f0_y_i_vec, 3);
+        f0_z[i] += vextract_MDF(f0_z_i_vec, 0) + vextract_MDF(f0_z_i_vec, 1) + vextract_MDF(f0_z_i_vec, 2) + vextract_MDF(f0_z_i_vec, 3);
       }
 
       // DMK - DEBUG
index bea380921b69010e21cbee0ea639a7c4fa7e5926..2da8fbbda7ad9ba78f1aa0c597219e6db65773d8 100644 (file)
@@ -17,13 +17,13 @@ class SelfCompute : public CBase_SelfCompute {
 
     /// Member Variables ///
     int numParticles;
-    float* particleX;
-    float* particleY;
-    float* particleZ;
-    float* particleQ;
-    float* forceX;
-    float* forceY;
-    float* forceZ;
+    MD_FLOAT* particleX;
+    MD_FLOAT* particleY;
+    MD_FLOAT* particleZ;
+    MD_FLOAT* particleQ;
+    MD_FLOAT* forceX;
+    MD_FLOAT* forceY;
+    MD_FLOAT* forceZ;
 
     CProxy_ProxyPatch proxyPatchProxy;
 
@@ -41,8 +41,8 @@ class SelfCompute : public CBase_SelfCompute {
 
     /// Entry Methods ///
     void init(int numParticlesPerPatch);
-    void patchData(int numParticles, float* particleX, float* particleY, float* particleZ, float* particleQ, CProxy_ProxyPatch proxyPatchProxy);
-    void patchData(int numParticles, float* particleX, float* particleY, float* particleZ, float* particleQ);
+    void patchData(int numParticles, MD_FLOAT* particleX, MD_FLOAT* particleY, MD_FLOAT* particleZ, MD_FLOAT* particleQ, CProxy_ProxyPatch proxyPatchProxy);
+    void patchData(int numParticles, MD_FLOAT* particleX, MD_FLOAT* particleY, MD_FLOAT* particleZ, MD_FLOAT* particleQ);
     void doCalc_callback();
 
 };
index 181f0e0265e59f0538c687b7058fd79859fec5a4..360a948c8358c53a0c8779b16e340499ed17439e 100755 (executable)
@@ -93,31 +93,6 @@ if($cpu =~ m/i[0-9]86/){
 $converse_network_type = "net";
 
 
-print << "EOF";
-How do you want to handle SMP/Multicore: [1-4]
-         1) single-threaded [default]
-         2) multicore(single node only)
-         3) SMP
-         4) POSIX Shared Memory
-
-EOF
-
-while($line = <>){
-       chomp $line;
-       if($line eq "1" || $line eq ""){
-           last;
-       } elsif($line eq "2"){
-           $converse_network_type = "multicore";
-           last;
-       } elsif($line eq "3"){
-           $options = "$options smp ";
-           last;
-       } elsif($line eq "4"){
-           $options = "$options pxshm ";
-           last;
-       }
-}
-
 # check for MPI
 
 $skip_choosing = "false";
@@ -249,6 +224,60 @@ if($arch eq "net-darwin"){
 
 
 
+#================ Choose SMP/PXSHM =================================
+
+# find what options are available
+$opts = `./build charm++ $arch help 2>&1 | grep "Supported options"`;
+$opts =~ m/Supported options: (.*)/;
+$opts = $1;
+
+
+#always provide multicore and single-threaded versions
+print << "EOF";
+How do you want to handle SMP/Multicore: [1-4]
+         1) single-threaded [default]
+         2) multicore(single node only)
+EOF
+
+# only add the smp or pxshm options if they are available
+$counter = 3; # the next index used in the list
+
+$smpIndex = -1;
+if($opts =~ m/smp/){
+  print "         $counter) SMP\n";
+  $smpIndex = $counter; 
+  $counter ++;
+}
+
+$pxshmIndex = -1;
+if($opts =~ m/pxshm/){
+  print "         $counter) POSIX Shared Memory\n";
+  $pxshmIndex = $counter; 
+  $counter ++;
+}
+
+while($line = <>){
+       chomp $line;
+       if($line eq "1" || $line eq ""){
+           last;
+       } elsif($line eq "2"){
+           $converse_network_type = "multicore";
+           last;
+       } elsif($line eq $smpIndex){
+           $options = "$options smp ";
+           last;
+       } elsif($line eq $pxshmIndex){
+           $options = "$options pxshm ";
+           last;
+       }
+}
+
+
+
+
+
+
+
 #================ Choose Compiler =================================
 
 # Lookup list of compilers
@@ -289,6 +318,7 @@ if ($numc > 0) {
 
 
 
+
 #================ Choose Options =================================
 
 #Create a hash table containing descriptions of various options
@@ -385,6 +415,12 @@ $explanations{"mlogft"} = "Use message logging fault tolerance support";
 
 
 
+
+
+
+
+
+
 # Choose compiler flags
 print << "EOF";
        
index 6f98d13788954289ff0643c750586a24e124dc03..4de1adf4f3b8dda13e8f751121f65542c4cc8032 100644 (file)
@@ -155,7 +155,7 @@ static void CmiStartThreads(char **argv)
 int received_immediate = 0;
 
 /*Add a message to this processor's receive queue, pe is a rank */
-static void CmiPushPE(int pe,void *msg)
+void CmiPushPE(int pe,void *msg)
 {
   CmiState cs = CmiGetStateN(pe);
   MACHSTATE2(3,"Pushing message into rank %d's queue %p{",pe, cs->recv);
index fd50117c5456643de3ba1e47d60ad10f3bd6887c..e92b163922d2567fd83ba9b768bc6e28e7be2194 100644 (file)
@@ -351,7 +351,7 @@ static void CmiStartThreads(char **argv)
 #endif /* non smp */
 
 /*Add a message to this processor's receive queue, pe is a rank */
-static void CmiPushPE(int pe,void *msg)
+void CmiPushPE(int pe,void *msg)
 {
   CmiState cs = CmiGetStateN(pe);
   MACHSTATE2(3,"Pushing message into rank %d's queue %p{",pe, cs->recv);
index 26f4ec466ba9515a4477573348f4396342843ae3..d42eafd6a26531c85f56d1fb6cdc89ce3ad0a0b5 100644 (file)
@@ -165,7 +165,7 @@ static void CmiStartThreads(char **argv) {
 //int received_broadcast;
 
 /*Add a message to this processor's receive queue, pe is a rank */
-static void CmiPushPE(int pe,void *msg) {
+void CmiPushPE(int pe,void *msg) {
     CmiState cs = CmiGetStateN(pe);
     MACHSTATE2(3,"Pushing message into rank %d's queue %p{",pe, cs->recv);
 #if CMK_IMMEDIATE_MSG
index e55a4c8b1f227830cc93909dad5b461105d1bba7..cfb0dfaaf06c55a0afe3fe962263650572b97826 100644 (file)
@@ -14,3 +14,6 @@
 
 #define BIGSIM_OUT_OF_CORE                                 0
 #define BIGSIM_OOC_PREFETCH                                0
+
+
+#define CMK_CHARE_USE_PTR                                  1
index b6fa0417d91dd33134aa6b6ef89f1a87cb46371f..86dee635a2b36db045415053c39582eb1e168241 100644 (file)
@@ -6,16 +6,18 @@ CMK_CXX="$CMK_CXX -DCMK_GFORTRAN"
 if test -n "$CMK_MACOSX64"
 then
 CMK_F90FLAGS="$CMK_F90FLAGS -m64"
+CMK_F77FLAGS="$CMK_F90FLAGS -m64"
 fi
 
 if test -n "$CMK_MACOSX"
 then
 CMK_F90FLAGS="$CMK_F90FLAGS -fno-common"
+CMK_F77FLAGS="$CMK_F90FLAGS -fno-common"
 fi
 
-CMK_CF77="g77 "
-CMK_CF90=`which gfortran 2>/dev/null`
 CMK_FPP="/lib/cpp -P -CC"
+
+CMK_CF90=`which gfortran 2>/dev/null`
 CMK_CF90="$CMK_CF90 $CMK_F90FLAGS -fPIC -fno-second-underscore -fdollar-ok" 
 CMK_CF90_FIXED="$CMK_CF90 -ffixed-form "
 # find f90 library:
@@ -42,6 +44,9 @@ else
 fi
 test -n "$F90LIBDIR" && CMK_F90LIBS="-L$F90LIBDIR -lgfortran -lgcc_eh"
 
+CMK_CF77=$CMK_CF90
+CMK_F77LIBS=$CMK_F90LIBS
+
 CMK_MOD_NAME_ALLCAPS=
 CMK_MOD_EXT="mod"
 CMK_F90_USE_MODDIR=1
index 28a581850aaf091d1319b6bcb363286a2b1b1a65..d115164ed60ee128aca4ad7113f3b2f177ce32ea 100644 (file)
@@ -270,7 +270,7 @@ static void CmiStartThreads(char **argv)
 }      
 
 /*Add a message to this processor's receive queue */
-static void CmiPushPE(int pe,void *msg)
+void CmiPushPE(int pe,void *msg)
 {
   CmiState cs=CmiGetStateN(pe);
   MACHSTATE1(2,"Pushing message into %d's queue",pe);
index 452a1c6920c626e90a03ad90a7d3edd112b206c5..e9d8389968e15625204cf03ea237687eaedb7d3c 100755 (executable)
@@ -99,6 +99,8 @@ if [ -z "$llfile" ]
     then
     echo "No load leveler template specified. Either use the flag \"+ll <llfile>\" or create"
     echo "a file called \"charmrun.ll\" in the current directory on in your home directory."
+    echo "An example of the template can be found at src/arch/lapi/charmrun.ll, this may"
+    echo "require tuning for the specific machine (for example account_no or class)."
     echo
     exit
 fi
@@ -169,7 +171,7 @@ cat > $filename <<EOF
 #@ network.LAPI = csss,,US
 #@ total_tasks = $total_tasks
 $nodes
-$tasks_per_node
+$tasks_per_node
 
 # User settings
 EOF
index 9c036f368578c8a98d900454f1bb8ae7ba03846f..05ffd2f11fc783ebcba535ef3a597ac3c3d9e13e 100644 (file)
@@ -3,7 +3,8 @@
 
 #define CMK_CMIPRINTF_IS_A_BUILTIN                         0
 
-#define CMK_MSG_HEADER_FIELDS CmiUInt2 rank,root,hdl,xhdl,info,stratid,size,redID;
+#define CMK_MSG_HEADER_FIELDS CmiUInt2 rank,hdl,xhdl,info,stratid,redID; int root, size, srcpe, seqno;
+
 #define CMK_MSG_HEADER_BASIC  CMK_MSG_HEADER_EXT
 #define CMK_MSG_HEADER_EXT    { CMK_MSG_HEADER_FIELDS }
 #define CMK_MSG_HEADER_BLUEGENE    { CMK_MSG_HEADER_FIELDS CMK_BLUEGENE_FIELDS }
index 6629d3dbcc195ffb53c476c60873622c8be26409..d88d40f85af26cf393042d423418d8bd810ac9d9 100644 (file)
@@ -1,31 +1,33 @@
+COMMENT="Enable 32-bit mode (-q32)"
+
 CMK_CPP_CHARM='/usr/lib/cpp -P -D_NO_PROTO '
 CMK_CPP_C='/usr/lib/cpp -P -D_NO_PROTO '
 CMK_LDRO='ld -r -o '
 CMK_LDRO_WORKS=0
-CMK_CC='mpcc_r -qcpluscmt '
-CMK_CXX='mpCC_r -qstaticinline '
-CMK_CXXPP='xlC -E '
-CMK_LD="mpcc_r -brtl "
-CMK_LDXX="mpCC_r -brtl "
-CMK_CF77='mpxlf_r'
-CMK_CF90='mpxlf90_r -qsuffix=f=f90'
-CMK_CF90_FIXED='mpxlf90_r '
+CMK_CC='mpcc_r -q32 -qcpluscmt '
+CMK_CXX='mpCC_r -q32 -qstaticinline '
+CMK_CXXPP='xlC -q32 -E '
+CMK_LD="mpcc_r -q32 -brtl "
+CMK_LDXX="mpCC_r -q32 -brtl "
+CMK_CF77='mpxlf_r -q32 '
+CMK_CF90='mpxlf90_r -q32 -qsuffix=f=f90'
+CMK_CF90_FIXED='mpxlf90_r -q32 '
 CMK_C_OPTIMIZE='-O3 -qstrict -Q  '
 CMK_CXX_OPTIMIZE='-O3 -qstrict -Q '
-CMK_AR='ar cq'
+CMK_AR='ar -X 32 cq'
 CMK_RANLIB='true'
 CMK_LIBS="-lckqt -lhC -llapi_r"
 CMK_LD_SHARED='-G'
 CMK_SEQ_LIBS=''
-CMK_SEQ_CC='xlc_r'
-CMK_SEQ_LD='xlc_r'
-CMK_SEQ_CXX='xlC_r -qstaticinline '
-CMK_SEQ_LDXX='xlC_r'
-CMK_NATIVE_CC='xlc_r'
-CMK_NATIVE_LD='xlc_r'
-CMK_NATIVE_CXX='xlC_r -qstaticinline '
-CMK_NATIVE_LDXX='xlC_r'
-CMK_NM='/bin/nm'
+CMK_SEQ_CC='xlc_r -q32 '
+CMK_SEQ_LD='xlc_r -q32 '
+CMK_SEQ_CXX='xlC_r -q32 -qstaticinline '
+CMK_SEQ_LDXX='xlC_r -q32 '
+CMK_NATIVE_CC='xlc_r -q32 '
+CMK_NATIVE_LD='xlc_r -q32 '
+CMK_NATIVE_CXX='xlC_r -q32 -qstaticinline '
+CMK_NATIVE_LDXX='xlC_r -q32 '
+CMK_NM='/bin/nm -X 32'
 CMK_NM_FILTER="grep ^_CK_ | cut -f 1 -d ' '"
 CMK_QT='aix'
 CMK_XIOPTS=''
old mode 100644 (file)
new mode 100755 (executable)
index a097219..fa7d4cb
@@ -2,20 +2,15 @@
 LAPI version of machine layer
 Based on the template machine layer
 
-Developed by 
+Developed by
 Filippo Gioachin   03/23/05
+Chao Mei 01/28/2010
 ************************************************************************/
 
 #include <lapi.h>
 
 #include "converse.h"
 
-/*
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-*/
 #include <assert.h>
 #include <errno.h>
 
@@ -24,45 +19,208 @@ Filippo Gioachin   03/23/05
 #include <stdlib.h> /*For sleep()*/
 
 #include "machine.h"
+
+#if CMK_SMP
+#define CMK_PCQUEUE_LOCK 1
+#else
+/** 
+ *  In non-smp case: the LAPI completion handler thread will
+ *  also access the proc's recv queue (a PCQueue), so the queue
+ *  needs to be protected. The number of producers equals the
+ *  #completion handler threads, while there's only one consumer
+ *  for the queue. Right now, the #completion handler threads is
+ *  set to 1, so the atomic operation for PCQueue should be
+ *  achieved via memory fence. --Chao Mei
+ */
+
+/* Redefine CmiNodeLocks only for PCQueue data structure */
+#define CmiNodeLock CmiNodeLock_nonsmp
+#undef CmiCreateLock()
+#undef CmiLock(lock)
+#undef CmiUnlock(lock)
+#undef CmiTryLock(lock)
+#undef CmiDestroyLock(lock)
+typedef pthread_mutex_t *CmiNodeLock_nonsmp;
+CmiNodeLock CmiCreateLock(){
+  CmiNodeLock lk = (CmiNodeLock)malloc(sizeof(pthread_mutex_t));  
+  pthread_mutex_init(lk,(pthread_mutexattr_t *)0);
+  return lk;
+}
+#define CmiLock(lock) (pthread_mutex_lock(lock))
+#define CmiUnlock(lock) (pthread_mutex_unlock(lock))
+#define CmiTryLock(lock) (pthread_mutex_trylock(lock))
+void CmiDestroyLock(CmiNodeLock lock){
+    pthread_mutex_destroy(lock);
+    free(lock);
+}
+#define CMK_PCQUEUE_LOCK 1
+#endif
 #include "pcqueue.h"
 
-/* #define MAX_QLEN 200 */
+/** 
+ *  The converse qd is rarely used in current charm apps, so the
+ *  counter for converse qd could be disabled for max
+ *  performance. --Chao Mei
+ */
+#define ENABLE_CONVERSE_QD 1
 
+#if CMK_SMP
+/** 
+ *  The macro defines whether to have a comm thd to offload some
+ *  work such as processing immdiate messages, forwarding
+ *  broadcast messages etc. This macro should be defined before
+ *  including "machine-smp.c".
+ *  --Chao Mei
+ */
+#define CMK_SMP_NO_COMMTHD 1
+#if CMK_SMP_NO_COMMTHD
+int Cmi_commthread = 0;
+#endif
+
+#endif
+
+/** 
+ * #####REGARDING IN-ORDER MESSAGE DELIVERY BETWEEN A PAIR OF 
+ * PROCESSORS#####: 
+ *  
+ * Since the lapi doesn't guarantee the order of msg delivery 
+ * (via network) between a pair of processors, we need to ensure 
+ * this order via msg seq no and a window sliding based msg 
+ * receiving scheme. So two extra fields are added to the basic 
+ * msg header: srcPe and seqno. For node messages, we process it 
+ * like a msg to be delivered to the first proc (rank=0) of that 
+ * node. 
+ *  
+ * BTW: The in-order delivery between two processors in the same
+ * node is guaranteed in the SMP mode as the msg transfer 
+ * doesn't go through LAPI. 
+ *  
+ * The msg transferred through LAPI (via network) is always 
+ * delivered to the first proc (whose rank is 0) on that node! 
+ *  
+ * --Chao Mei 
+ */
+#define ENSURE_MSG_PAIRORDER 1
+#define MAX_MSG_SEQNO 65535
+#define MAX_WINDOW_SIZE 8
+
+#if ENSURE_MSG_PAIRORDER
+/* Variables used on recver side */
+/** 
+ *  expectedMsgSeqNo is an int array of size "#procs". It tracks
+ *  the expected seqno recved from other procs to this proc.
+ */
+CpvDeclare(int *, expectedMsgSeqNo);
+/** 
+ * oosMsgBuffer is an array of sizeof(void **)*(#procs), each 
+ * element (created on demand) points to a window (array) size 
+ * of MAX_WINDOW_SIZE which buffers the out-of-order incoming 
+ * messages (a (void *) array) 
+ */   
+CpvDeclare(void ***, oooMsgBuffer);
+/** 
+ * Indicates the maximum offset of the ooo msg ahead of the 
+ * expected msg. The offset begins with 1, i.e., (offset-1) is 
+ * the index of the ooo msg in the window (oooMsgBuffer)
+ */
+CpvDeclare(unsigned char*, oooMaxOffset);
+
+
+/* Variables used on sender side */
+/** 
+ *  nextMsgSeqNo is an int array of size "#procs". It tracks
+ *  the next seqno of the msg to be sent from this proc to other
+ *  procs.
+ */
+CpvDeclare(int *, nextMsgSeqNo);
+
+
+/** 
+ *  expectedMsgSeqNo is an int array of size "#procs". It tracks
+ *  the expected seqno recved from other procs to this proc.
+ *  
+ *  nextMsgSeqNo is an int array of size "#procs". It tracks
+ *  the next seqno of the msg to be sent from this proc to other
+ *  procs.
+ *  
+ *  Those two arrays also have corresponding locks to ensure the
+ *  atomicity increase of seq no. As the seq no could possible
+ *  be increased by multiple threads (the normal lapi execution
+ *  thread, and the lapi thread that handles msg completion
+ *  handler) --Chao Mei
+ */
 /*
-    To reduce the buffer used in broadcast and distribute the load from 
-  broadcasting node, define CMK_BROADCAST_SPANNING_TREE enforce the use of 
+typedef struct MsgOrderInfoStruct{
+    int *expectedMsgSeqNo;
+    CmiNodeLock *expectedLocks;
+
+    int *nextMsgSeqNo;
+    CmiNodeLock *nextLocks;
+}MsgOrderInfo;
+
+CpvDeclare(MsgOrderInfo, msgSeqInfo);
+*/
+#endif
+
+/*
+    To reduce the buffer used in broadcast and distribute the load from
+  broadcasting node, define CMK_BROADCAST_SPANNING_TREE enforce the use of
   spanning tree broadcast algorithm.
     This will use the fourth short in message as an indicator of spanning tree
   root.
 */
 
-#define BROADCAST_SPANNING_FACTOR        CMK_SPANTREE_MAXSPAN
+#undef CMK_BROADCAST_SPANNING_TREE
+#define CMK_BROADCAST_SPANNING_TREE 0
+
+/*#define BROADCAST_SPANNING_FACTOR        CMK_SPANTREE_MAXSPAN*/
+#define BROADCAST_SPANNING_FACTOR   2
+
+#undef CMK_BROADCAST_HYPERCUBE
+#define CMK_BROADCAST_HYPERCUBE     1
 
+/**
+ * The broadcast root of a msg. 
+ * 0: indicate a non-broadcast msg 
+ *  
+ * >0: indicate a proc-level broadcast msg ("root-1" indicates 
+ * the proc that starts a broadcast)
+ *  
+ * <0: indicate a node-level broadcast msg ("-root-1" indicates 
+ * the node that starts a broadcast) 
+ *  
+ * On BG/P, we have a separate broadcast queue on each 
+ * processor. This will allow us to use the separate thread 
+ * (comm thread) to offload the broadcast operation from worker 
+ * threads --Chao Mei 
+ */
 #define CMI_BROADCAST_ROOT(msg)          ((CmiMsgHeaderBasic *)msg)->root
 #define CMI_DEST_RANK(msg)               ((CmiMsgHeaderBasic *)msg)->rank
+/* The actual msg size including the msg header */
+#define CMI_MSG_SIZE(msg)                ((CmiMsgHeaderBasic *)msg)->size
+
+#define CMI_MSG_SRCPE(msg)               ((CmiMsgHeaderBasic *)msg)->srcpe
+#define CMI_MSG_SEQNO(msg)               ((CmiMsgHeaderBasic *)msg)->seqno
 
 CpvDeclare(unsigned , networkProgressCount);
-int networkProgressPeriod;
 
+int networkProgressPeriod;
 static int lapiDebugMode=0;
-/* static int lapiInterruptMode=0; */
-
 CsvDeclare(int, lapiInterruptMode);
 
-/* static int SHORT_MESSAGE_SIZE=512; */
-
 static void ConverseRunPE(int everReturn);
 static void PerrorExit(const char *msg);
-static int Cmi_nodestart;   /* First processor in this node - stupid need due to
-                              machine-smp.h that uses it!!  */
+
+static int Cmi_nodestart;   /* First processor in this node - stupid need due to machine-smp.h that uses it!!  */
 
 #include "machine-smp.c"
 
 
 /* Variables describing the processor ID */
 
+/* non-smp mode */
 #if CMK_SHARED_VARS_UNAVAILABLE
-
+/* Should the non-smp also needs the concept of node which equals to processor -Chao Mei */
 int _Cmi_mype;
 int _Cmi_numpes;
 int _Cmi_myrank;
@@ -75,7 +233,9 @@ static struct CmiStateStruct Cmi_state;
 #define CmiGetState() (&Cmi_state)
 #define CmiGetStateN(n) (&Cmi_state)
 
-void CmiYield() { sleep(0); }
+void CmiYield() {
+    sleep(0);
+}
 
 #elif CMK_SHARED_VARS_POSIX_THREADS_SMP
 
@@ -84,97 +244,123 @@ int _Cmi_mynodesize;
 int _Cmi_mynode;
 int _Cmi_numnodes;
 
-int CmiMyPe(void) { return CmiGetState()->pe; }
-
-int CmiMyRank(void) { return CmiGetState()->rank; }
+int CmiMyPe(void) {
+    return CmiGetState()->pe;
+}
 
-int CmiNodeFirst(int node) { return node*_Cmi_mynodesize; }
-int CmiNodeSize(int node)  { return _Cmi_mynodesize; }
+int CmiMyRank(void) {
+    return CmiGetState()->rank;
+}
 
-int CmiNodeOf(int pe)      { return (pe/_Cmi_mynodesize); }
-int CmiRankOf(int pe)      { return pe-(CmiNodeOf(pe)*_Cmi_mynodesize); }
+int CmiNodeFirst(int node) {
+    return node*_Cmi_mynodesize;
+}
+int CmiNodeSize(int node)  {
+    return _Cmi_mynodesize;
+}
 
+int CmiNodeOf(int pe)      {
+    return (pe / _Cmi_mynodesize);
+}
+int CmiRankOf(int pe)      {
+    return (pe % _Cmi_mynodesize);
+}
 #endif
 
 CpvDeclare(void*, CmiLocalQueue);
 
-#define DGRAM_NODEMESSAGE   (0xFB)
-
 #if CMK_NODE_QUEUE_AVAILABLE
+#define DGRAM_NODEMESSAGE   (0x7EFB)
 #define NODE_BROADCAST_OTHERS (-1)
 #define NODE_BROADCAST_ALL    (-2)
 #endif
 
+/* The way to read this macro
+ * "routine args" becomes a function call inside the parameters of check_lapi_err,
+ * and it returns a int as returnCode;
+ * "#routine" turns the "routine" as a string
+ * __LINE__ is the line number in the source file
+ * -Chao Mei
+ */
 #define check_lapi(routine,args) \
         check_lapi_err(routine args, #routine, __LINE__);
 
 static void check_lapi_err(int returnCode,const char *routine,int line) {
-        if (returnCode!=LAPI_SUCCESS) {
-                char errMsg[LAPI_MAX_ERR_STRING];
-                LAPI_Msg_string(returnCode,errMsg);
-                fprintf(stderr,"Fatal LAPI error while executing %s at %s:%d\n"
-                        "  Description: %s\n", routine, __FILE__, line, errMsg);
-                CmiAbort("Fatal LAPI error");
-        }
+    if (returnCode!=LAPI_SUCCESS) {
+        char errMsg[LAPI_MAX_ERR_STRING];
+        LAPI_Msg_string(returnCode,errMsg);
+        fprintf(stderr,"Fatal LAPI error while executing %s at %s:%d\n"
+                "  Description: %s\n", routine, __FILE__, line, errMsg);
+        CmiAbort("Fatal LAPI error");
+    }
 }
 
-/*
-static void CommunicationServer(int sleepTime);
-static void CommunicationServerThread(int sleepTime);
-
-typedef struct msg_list {
-  char *msg;
-  struct msg_list *next;
-  int size, destpe;
-  
-  // LAPI Stuff Here 
-  lapi_cntr_t lapiSendCounter;
-  
-} SMSG_LIST;
-
-static int MsgQueueLen=0;
-static int request_max;
-
-static SMSG_LIST *sent_msgs=0;
-static SMSG_LIST *end_sent=0;
-*/
-
-/* static int no_outstanding_sends=0; */
-/*FLAG: consume outstanding Isends in scheduler loop*/
+static void lapi_err_hndlr(lapi_handle_t *hndl, int *error_code, 
+                            lapi_err_t *err_type, int *task_ID, int *src){
+    char errstr[LAPI_MAX_ERR_STRING];
+    LAPI_Msg_string(*error_code, errstr);
+    fprintf(stderr, "ERROR IN LAPI: %s for task %d at src %d\n", errstr, *task_ID, *src);
+    LAPI_Term(*hndl);
+    exit(1);
+}
 
+/**
+ * The lapiContext stands for the lapi context for a single lapi 
+ * task. And inside one lapi task, only one lapi context could 
+ * be created via lapi_init. In SMP mode, this context is 
+ * created by proc of rank 0, and then it is shared among all 
+ * cores on a node (threads) --Chao Mei 
+ * 
+ */
 static lapi_handle_t lapiContext;
 static lapi_long_t lapiHeaderHandler = 1;
 
-/* double starttimer; */
-
-/* void CmiAbort(const char *message); */
-
+/**
+ * Note on broadcast functions: 
+ * The converse QD may be wrong if using spanning tree or 
+ * hypercube schemes to send messages --Chao Mei 
+ */
+void SendMsgToPeers(int size, char *msg, int includeSelf);
+#if ENSURE_MSG_PAIRORDER
+void SendSpanningChildren(int size, char *msg, int srcPe, int *seqNoArr);
+void SendHypercube(int size, char *msg, int srcPe, int *seqNoArr);
+#else
 void SendSpanningChildren(int size, char *msg);
 void SendHypercube(int size, char *msg);
+#endif
+
+#if CMK_NODE_QUEUE_AVAILABLE
+/** 
+ *  The sending schemes of the following two functions are very
+ *  similar to its corresponding proc-level functions
+ */
+void SendSpanningChildrenNode(int size, char *msg);
+void SendHypercubeNode(int size, char *msg);
+#endif
 
+/**
+ * There is a function "CkCopyMsg" in the charm++ level, which
+ * considers more than mere memcpy as there could be var size msg
+ * --Chao Mei
+ */
 char *CopyMsg(char *msg, int len) {
-  char *copy = (char *)CmiAlloc(len);
-  if (!copy)
-      fprintf(stderr, "Out of memory\n");
-  memcpy(copy, msg, len);
-  return copy;
+    char *copy = (char *)CmiAlloc(len);
+    if (!copy)
+        fprintf(stderr, "Out of memory\n");
+    memcpy(copy, msg, len);
+    return copy;
 }
 
+/* I don't think it is required here for guarding the recv queue on each proc -Chao Mei */
+#if 0
+/* If ProcState is that simple, then we don't need a struct for it --Chao Mei*/
 typedef struct ProcState {
-  CmiNodeLock  recvLock;                   /* for cs->recv */
+    CmiNodeLock  recvLock;                 /* for cs->recv */
 } ProcState;
-
 static ProcState  *procState;
-
-/*
-#if CMK_SMP
-
-static PCQueue sendMsgBuf;
-static CmiNodeLock  sendMsgBufLock = NULL;        // for sendMsgBuf 
-
 #endif
-*/
-
 #if CMK_NODE_QUEUE_AVAILABLE
 CsvDeclare(CmiNodeState, NodeState);
 #endif
@@ -183,1038 +369,1201 @@ CsvDeclare(CmiNodeState, NodeState);
 #include "immediate.c"
 #endif
 
-#if CMK_SHARED_VARS_UNAVAILABLE
+static void AdvanceCommunication(){
+    if(!CsvAccess(lapiInterruptMode)) check_lapi(LAPI_Probe,(lapiContext));
+#if CMK_SMP && CMK_IMMEDIATE_MSG
+    /** 
+     * Immediate msgs are handled in CmiPushNode and 
+     * CmiSendNodeSelf, CmiPushPe and CmiSendSelf in the non-SMP 
+     * case, but in SMP case, those four functions could be called 
+     * in the completition handler where "CmiMyPe(), CmiMyRank()" 
+     * will be wrong as the "CmiGetState()" will not return a right 
+     * proc-specific CmiState!! So immediate messages are handled 
+     * when proc is idle. This may cause a big delay for processing 
+     * immdiate messages in SMP mode if there's not a dedicated 
+     * communication thread. 
+     * --Chao Mei 
+     */
+    MACHSTATE1(2, "[%p] Handling Immediate Message begin{",CmiGetState());
+    CmiHandleImmediate();
+    MACHSTATE1(2, "[%p] Handling Immediate Message end}",CmiGetState());
+#endif
+}
 
+/* non-smp CmiStartThreads. -Chao Mei */
+#if CMK_SHARED_VARS_UNAVAILABLE
 /* To conform with the call made in SMP mode */
 static void CmiStartThreads(char **argv) {
-  CmiStateInit(Cmi_nodestart, 0, &Cmi_state);
-  /* _Cmi_mype = Cmi_nodestart; // already set! 
-  */
-  _Cmi_myrank = 0;
+    CmiStateInit(Cmi_nodestart, 0, &Cmi_state);
+    /* _Cmi_mype = Cmi_nodestart; // already set! */
+    _Cmi_myrank = 0;
+}
+#endif
+
+/* ===== Beginging of functions regarding ensure in-order msg delivery ===== */
+#if ENSURE_MSG_PAIRORDER
+
+/**
+ * "setNextMsgSeqNo" actually sets the current seqno, the 
+ * "getNextMsgSeqNo" will increment the seqno, i.e., 
+ * "getNextMgSeqNo" returns the next seqno based on the previous 
+ * seqno stored in the seqno array. 
+ * --Chao Mei 
+ */
+static int getNextMsgSeqNo(int *seqNoArr, int destPe){
+    int ret = seqNoArr[destPe];
+    if(ret == MAX_MSG_SEQNO) 
+        ret = 0;
+    else
+        ret++;
+
+    return ret;
 }
+static void setNextMsgSeqNo(int *seqNoArr, int destPe, int val){
+    seqNoArr[destPe] = val;
+}
+
+#define getNextExpectedMsgSeqNo(seqNoArr,srcPe) getNextMsgSeqNo(seqNoArr, srcPe)
+#define setNextExpectedMsgSeqNo(seqNoArr,srcPe,val) setNextMsgSeqNo(seqNoArr, srcPe, val)
+
 #endif
+/* ===== End of functions regarding ensure in-order msg delivery ===== */
 
+/* ===========CmiPushPe and CmiPushNode============*/
 /* Add a message to this processor's receive queue, pe is a rank */
 void CmiPushPE(int pe,void *msg) {
-  CmiState cs = CmiGetStateN(pe);
-  MACHSTATE3(3,"[%p] Pushing message into rank %d's queue %p {",CmiGetState(),pe, cs->recv);
+    CmiState cs = CmiGetStateN(pe);
+    MACHSTATE3(3,"Pushing message(%p) into rank %d's queue %p {",msg,pe,(cs->recv));
 
 #if CMK_IMMEDIATE_MSG
-  if (CmiIsImmediate(msg)) {
-    MACHSTATE1(3, "[%p] Handling Immediate Message",CmiGetState());
-    CMI_DEST_RANK(msg) = pe;
-    CmiPushImmediateMsg(msg);
-    CmiHandleImmediate();
-    return;
-  }
-#endif
-
-#if CMK_SMP
-  CmiLock(procState[pe].recvLock);
+    if (CmiIsImmediate(msg)) {
+        MACHSTATE1(3, "[%p] Push Immediate Message begin{",CmiGetState());
+        CMI_DEST_RANK(msg) = pe;
+        CmiPushImmediateMsg(msg);
+        MACHSTATE1(3, "[%p] Push Immediate Message end }",CmiGetState());
+        #if !CMK_SMP
+        CmiHandleImmediate();        
+        #endif
+        return;
+    }
 #endif
 
-  PCQueuePush(cs->recv,msg);
+    /* Note atomicity is guaranteed inside pcqueue data structure --Chao Mei */
+    PCQueuePush(cs->recv,msg);
 
-#if CMK_SMP
-  CmiUnlock(procState[pe].recvLock);
-#endif
-  CmiIdleLock_addMessage(&cs->idle); 
-  MACHSTATE1(3,"} Pushing message into rank %d's queue done",pe);
+    CmiIdleLock_addMessage(&cs->idle);
+    MACHSTATE1(3,"} Pushing message into rank %d's queue done",pe);
 }
 
 #if CMK_NODE_QUEUE_AVAILABLE
 /*Add a message to this processor's receive queue */
-static void CmiPushNode(void *msg) {
-  MACHSTATE1(3,"[%p] Pushing message into NodeRecv queue",CmiGetState());
+/*Note: CmiPushNode is essentially same with CimSendNodeSelf */
+static void CmiPushNode(void *msg) {    
+    MACHSTATE1(3,"[%p] Pushing message into NodeRecv queue",CmiGetState());
 
 #if CMK_IMMEDIATE_MSG
-  if (CmiIsImmediate(msg)) {
-    MACHSTATE1(3, "[%p] Handling Immediate Message",CmiGetState());
-    CMI_DEST_RANK(msg) = 0;
-    CmiPushImmediateMsg(msg);
-    CmiHandleImmediate();
-    return;
-  }
+    if (CmiIsImmediate(msg)) {
+        MACHSTATE1(3, "[%p] Push Immediate Message begin {",CmiGetState());
+        CMI_DEST_RANK(msg) = 0;
+        CmiPushImmediateMsg(msg);
+        MACHSTATE1(3, "[%p] Push Immediate Message end }",CmiGetState());
+        #if !CMK_SMP
+        CmiHandleImmediate();
+        #endif
+        return;
+    }
 #endif
-  
-  CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
-  PCQueuePush(CsvAccess(NodeState).NodeRecv,msg);
-  CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
-  {
-  CmiState cs=CmiGetStateN(0);
-  CmiIdleLock_addMessage(&cs->idle);
-  }
+    /* CmiNodeRecvLock may not be needed  --Chao Mei*/
+    CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
+    PCQueuePush(CsvAccess(NodeState).NodeRecv,msg);
+    CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
 
-  MACHSTATE(3,"Pushing message into NodeRecv queue {");
+    CmiState cs=CmiGetStateN(0);
+    CmiIdleLock_addMessage(&cs->idle);
+
+    MACHSTATE(3,"Pushing message into NodeRecv queue {");
 }
 #endif
 
-/*
-Functions to release the space used by sent messages. This is handled by the
-sender completion handler.
-
-static int CmiAllAsyncMsgsSent(void) {
-   SMSG_LIST *msg_tmp = sent_msgs;
-   
-   int done;
-     
-   while(msg_tmp!=0) {
-    done = 0;
-
-    check_lapi(LAPI_Getcntr,(lapiContext, &msg_tmp->lapiSendCounter, &done));
-
-    if(!done)
-      return 0;
-    
-    msg_tmp = msg_tmp->next;
-   }
-   return 1;
+/* ======Beginning of helper functions for processing an incoming (network) message ======*/
+/* Process a proc-level broadcast message */
+static void ProcessBroadcastMsg(char *msg){
+    int nbytes = CMI_MSG_SIZE(msg);    
+#if ENSURE_MSG_PAIRORDER
+    MACHSTATE3(2,"[%p] the broadcast msg is from pe=%d with seq no=%d", CmiGetState(), CMI_MSG_SRCPE(msg), CMI_MSG_SEQNO(msg));
+    #if CMK_BROADCAST_SPANNING_TREE
+    SendSpanningChildren(nbytes, msg, CmiNodeFirst(CmiMyNode()), CpvAccessOther(nextMsgSeqNo, 0));
+    #elif CMK_BROADCAST_HYPERCUBE
+    SendHypercube(nbytes, msg, CmiNodeFirst(CmiMyNode()), CpvAccessOther(nextMsgSeqNo, 0));
+    #endif
+#else
+    #if CMK_BROADCAST_SPANNING_TREE
+    SendSpanningChildren(nbytes, msg);
+    #elif CMK_BROADCAST_HYPERCUBE
+    SendHypercube(nbytes, msg);
+    #endif
+#endif                     
+#if CMK_SMP
+    SendMsgToPeers(nbytes, msg, 1);                   
+    CmiFree(msg);
+#else
+    /* nonsmp case */
+    CmiPushPE(0, msg);
+#endif
 }
 
-int CmiAsyncMsgSent(CmiCommHandle c) {
-     
-  SMSG_LIST *msg_tmp = sent_msgs;
-  int done;
+#if ENSURE_MSG_PAIRORDER
+/* return 1 if this msg is an out-of-order incoming message */
 
-  while ((msg_tmp) && ((CmiCommHandle)(msg_tmp) != c))
-    msg_tmp = msg_tmp->next;
-  if(msg_tmp) {
-    done = 0;
+/** 
+ * !!!! 
+ * TODO: data race for seqno is possible here if forwarding 
+ * broadcast msgs is performed in completion handler  
+ * --Chao Mei
+ */
 
-    check_lapi(LAPI_Getcntr,(lapiContext, &msg_tmp->lapiSendCounter, &done));
+/**
+ * Returns 1 if this "msg" is an out-of-order message, or 
+ * this "msg" is a late message which triggers the process 
+ * of all buffered ooo msgs. 
+ * --Chao Mei 
+ */
+static int CheckMsgInOrder(char *msg){
+    int srcpe, destrank; 
+    int incomingSeqNo, expectedSeqNo;
+    int curOffset, maxOffset;
+    int i;
+    void **destMsgBuffer = NULL;    
+
+    /* Only checks the proc-level messages */
+    if(CMI_BROADCAST_ROOT(msg)<0) return 0;
+#if CMK_NODE_QUEUE_AVAILABLE
+    if(CMI_DEST_RANK(msg)==DGRAM_NODEMESSAGE) return 0;
+#endif
+    srcpe = CMI_MSG_SRCPE(msg);
+    destrank = CMI_DEST_RANK(msg);  
+    incomingSeqNo = CMI_MSG_SEQNO(msg);
+    expectedSeqNo = getNextExpectedMsgSeqNo(CpvAccessOther(expectedMsgSeqNo, destrank), srcpe);
+    if(expectedSeqNo == incomingSeqNo){
+        /* Two cases: has ooo msg buffered or not */
+        maxOffset = CpvAccessOther(oooMaxOffset, destrank)[srcpe];
+        if(maxOffset>0) {
+            MACHSTATE1(4, "Processing all buffered ooo msgs (maxOffset=%d) including the just recved begin {", maxOffset);
+            /* process the msg just recved */
+            if(CMI_BROADCAST_ROOT(msg)>0) {
+                ProcessBroadcastMsg(msg);
+            }else{
+                CmiPushPE(CMI_DEST_RANK(msg), msg);
+            }
+            /* process the buffered ooo msg until the first empty slot in the window */
+            destMsgBuffer = CpvAccessOther(oooMsgBuffer, destrank)[srcpe];                       
+            for(curOffset=0; curOffset<maxOffset; curOffset++) {
+                char *curMsg = destMsgBuffer[curOffset];
+                if(curMsg == NULL){
+                    assert(curOffset!=(maxOffset-1));                                        
+                    break;
+                }
+                if(CMI_BROADCAST_ROOT(curMsg)>0) {
+                    ProcessBroadcastMsg(curMsg);
+                }else{
+                    CmiPushPE(CMI_DEST_RANK(curMsg), curMsg);
+                }
+                destMsgBuffer[curOffset] = NULL;
+            }            
+            /* Update expected seqno, maxOffset and slide the window */
+            if(curOffset < maxOffset) {
+                int i;
+                /** 
+                 * now, the seqno of the next to-be-recved msg should be 
+                 * "expectedSeqNo+curOffset+1" as the seqno of the just 
+                 * processed msg is "expectedSeqNo+curOffset. We need to slide 
+                 * the msg buffer window from "curOffset+1" because the first 
+                 * element of the buffer window should always points to the ooo 
+                 * msg that's 1 in terms of seqno ahead of the next to-be-recved 
+                 * msg. --Chao Mei 
+                 */                
+                
+                /* moving [curOffset+1, maxOffset) to [0, maxOffset-curOffset-1) in the window */
+                /* The following two loops could be combined --Chao Mei */
+                for(i=0; i<maxOffset-curOffset-1; i++){
+                    destMsgBuffer[i] = destMsgBuffer[curOffset+i+1];
+                }
+                for(i=maxOffset-curOffset-1; i<maxOffset; i++) {
+                    destMsgBuffer[i] = NULL;
+                }
+                CpvAccessOther(oooMaxOffset, destrank)[srcpe] = maxOffset-curOffset-1;
+                setNextExpectedMsgSeqNo(CpvAccessOther(expectedMsgSeqNo, destrank), srcpe, expectedSeqNo+curOffset);
+            }else{
+                /* there's no remaining buffered ooo msgs */
+                CpvAccessOther(oooMaxOffset, destrank)[srcpe] = 0;
+                setNextExpectedMsgSeqNo(CpvAccessOther(expectedMsgSeqNo, destrank), srcpe, expectedSeqNo+maxOffset);
+            }
+            MACHSTATE1(4, "Processing all buffered ooo msgs (actually processed %d) end }", curOffset);
+            /** 
+             * Since we have processed all buffered ooo msgs including 
+             * this just recved one, 1 should be returned so that this 
+             * msg no longer needs processing 
+             */
+            return 1;
+        }else{
+            /* An expected msg recved without any ooo msg buffered */
+            setNextExpectedMsgSeqNo(CpvAccessOther(expectedMsgSeqNo, destrank), srcpe, expectedSeqNo);
+            return 0;
+        }        
+    }
 
-    return ((done)?1:0);
-  } else {
+    MACHSTATE2(4, "Receiving an out-of-order msg with seqno=%d, but expect seqno=%d\n", incomingSeqNo, expectedSeqNo);
+    if(CpvAccessOther(oooMsgBuffer, destrank)[srcpe]==NULL) {
+        CpvAccessOther(oooMsgBuffer, destrank)[srcpe] = malloc(MAX_WINDOW_SIZE*sizeof(void *));
+        memset(CpvAccessOther(oooMsgBuffer, destrank)[srcpe], 0, MAX_WINDOW_SIZE*sizeof(void *));
+    }
+    destMsgBuffer = CpvAccessOther(oooMsgBuffer, destrank)[srcpe];
+    curOffset = incomingSeqNo - expectedSeqNo;
+    maxOffset = CpvAccessOther(oooMaxOffset, destrank)[srcpe];
+    assert(curOffset>0 && curOffset<=MAX_WINDOW_SIZE);
+    assert(destMsgBuffer[curOffset-1] == NULL);
+    destMsgBuffer[curOffset-1] = msg;
+    if(curOffset > maxOffset) CpvAccessOther(oooMaxOffset, destrank)[srcpe] = curOffset;
     return 1;
-  }
 }
-
-static void CmiReleaseSentMessages(void) {
-  SMSG_LIST *msg_tmp=sent_msgs;
-  SMSG_LIST *prev=0;
-  SMSG_LIST *temp;
-  int done;
-     
-  MACHSTATE1(2,"CmiReleaseSentMessages begin on %d {", CmiMyPe());
-
-  while(msg_tmp!=0) {
-    done =0;
-    
-    check_lapi(LAPI_Getcntr,(lapiContext, &msg_tmp->lapiSendCounter, &done));
-
-    if(done) {
-      MACHSTATE2(3,"CmiReleaseSentMessages release one %d to %d", CmiMyPe(), msg_tmp->destpe);
-      MsgQueueLen--;
-      
-      // Release the message
-      temp = msg_tmp->next;
-      if(prev==0)  // first message
-        sent_msgs = temp;
-      else
-        prev->next = temp;
-      CmiFree(msg_tmp->msg);
-      CmiFree(msg_tmp);
-      msg_tmp = temp;
-    } else {
-      prev = msg_tmp;
-      msg_tmp = msg_tmp->next;
+#endif
+/* ======End of helper functions for processing an incoming (network) message ======*/
+
+/* ======Begining of lapi callbacks such as the completion handler on the sender and recver side ======*/
+/** 
+  * lapi completion handler on the recv side. It's responsible to push messages 
+  * to the destination proc or relay broadcast messages. --Chao Mei 
+  *  
+  * Note: The completion handler could be executed on any cores within a node ??? 
+  * So in SMP mode when there's a comm thread, the completion handler should be carefully 
+  * dealt with. 
+  *  
+  * Given lapi also provides an internal lapi thread to deal with network progress which 
+  * will call this function (???), we should be careful with the following situations: 
+  * 1) non SMP mode, with interrupt (lapi internal completion thread) 
+  * 2) non SMP mode, with polling (machine layer is responsible for network progress) 
+  * 3) SMP mode, no comm thread, with polling 
+  * 4) SMP mode, no comm thread, with interrupt 
+  * 5) SMP mode, with comm thread, with polling (not yet implemented, comm server is empty right now)
+  * 6) SMP mode, with comm thread, with interrupt?? 
+  *  
+  * Currently, SMP mode without comm thread is undergoing implementation. 
+  *  
+  * This function is executed by LAPI internal threads. It seems that the number of internal 
+  * completion handler threads could vary during the program. LAPI adaptively creates more 
+  * threads if there are more outstanding messages!!!! This means pcqueue needs protection 
+  * even in the nonsmp case!!!!
+  *  
+  * --Chao Mei 
+  */
+static void PumpMsgsComplete(lapi_handle_t *myLapiContext, void *am_info) {
+    int i;
+    char *msg = am_info;
+
+    int nbytes = CMI_MSG_SIZE(msg);
+
+    MACHSTATE3(2,"[%p] PumpMsgsComplete with msg %p (isImm=%d) begin {",CmiGetState(), msg, CmiIsImmediate(msg));
+
+    /**
+     * First, we check if the msg is a broadcast msg via spanning 
+     * tree. If it is, it needs to call SendSpanningChildren to 
+     * relay the broadcast, and then send the msg to every cores on 
+     * this node.
+     *  
+     * After the first check, we deal with normal messages. 
+     * --Chao Mei
+     */
+/* It's the right place to relay the broadcast message */
+    /**
+     * 1. For in-order delivery, because this is the handler for 
+     * receiving a message, and we assume the cross-network msgs are 
+     * always delivered to the first proc (rank 0) of this node, we 
+     * select the srcpe of the bcast msgs and the next msg seq no 
+     * correspondingly. 
+     *  
+     * 2. TODO: checking the in-order delivery of p2p msgs!! 
+     *  
+     * --Chao Mei 
+     */
+#if ENSURE_MSG_PAIRORDER
+    /* Check whether the incoming message is in-order and buffer if necessary */
+    if(CheckMsgInOrder(msg)) return;    
+#endif    
+
+#if CMK_BROADCAST_SPANNING_TREE || CMK_BROADCAST_HYPERCUBE
+    if (CMI_BROADCAST_ROOT(msg)>0) {
+        MACHSTATE1(2,"[%p] Recved a proc-level broadcast msg",CmiGetState());     
+        ProcessBroadcastMsg(msg);
+        MACHSTATE(2,"} PumpMsgsComplete end ");
+        return;
     }
-  }
-  end_sent = prev;
-  MACHSTATE(2,"} CmiReleaseSentMessages end");
-}
-*/
 
-/* lapi completion handler */
-static void PumpMsgsComplete(lapi_handle_t *myLapiContext, void *am_info) {
-  int i;
-  char *msg = am_info;
-  
-  int nbytes = ((CmiMsgHeaderBasic *)msg)->size;
-  
-  MACHSTATE1(2,"[%p] PumpMsgsComplete begin {",CmiGetState());
-  
 #if CMK_NODE_QUEUE_AVAILABLE
-  if (CMI_DEST_RANK(msg)==DGRAM_NODEMESSAGE)
-    CmiPushNode(msg);
-  else
+    if(CMI_BROADCAST_ROOT(msg) < 0) {
+        MACHSTATE1(2,"[%p] Recved a node-level broadcast msg",CmiGetState());  
+        #if CMK_BROADCAST_SPANNING_TREE
+        SendSpanningChildrenNode(nbytes, msg);
+        #elif CMK_BROADCAST_HYPERCUBE
+        SendHypercubeNode(nbytes, msg);
+        #endif            
+        CmiPushNode(msg);
+        MACHSTATE(2,"} PumpMsgsComplete end ");
+        return;
+    }
 #endif
-    CmiPushPE(CMI_DEST_RANK(msg), msg);
-
-  /*
-  if(!myLapiContext)
-    return;
-  */
 
-#if CMK_BROADCAST_SPANNING_TREE
-  if (CMI_BROADCAST_ROOT(msg)) {
-    SendSpanningChildren(nbytes, msg);
-  }
-  
-#elif CMK_BROADCAST_HYPERCUBE
-  if (CMI_BROADCAST_ROOT(msg)) {
-    SendHypercube(nbytes, msg);
-  }
 #endif
 
-#if CMK_SMP
-  if (CMI_BROADCAST_ROOT(msg) && CMI_DEST_RANK(msg)!=DGRAM_NODEMESSAGE) {
-    assert(CMI_DEST_RANK(msg)==0);
-    for (i=1; i<CmiMyNodeSize(); ++i) {
-      CmiPushPE(i, msg);
+#if CMK_NODE_QUEUE_AVAILABLE
+    if (CMI_DEST_RANK(msg)==DGRAM_NODEMESSAGE)
+        CmiPushNode(msg);
+    else{
+        MACHSTATE3(2,"[%p] Recv a p2p msg from pe=%d with seq no=%d", CmiGetState(), CMI_MSG_SRCPE(msg), CMI_MSG_SEQNO(msg));
+        CmiPushPE(CMI_DEST_RANK(msg), msg);
     }
-  }
+#else
+    CmiPushPE(CMI_DEST_RANK(msg), msg);
 #endif
 
-  MACHSTATE(2,"} PumpMsgsComplete end ");
-  return;
+    MACHSTATE(2,"} PumpMsgsComplete end ");
+    return;
 }
 
-/* lapi header handler */
+/** lapi header handler: executed on the recv side, when the
+ *  first packet of the recving msg arrives, it is called to
+ *  prepare the memory buffer in the user space for recving the
+ *  data --Chao Mei
+ */
 static void* PumpMsgsBegin(lapi_handle_t *myLapiContext,
-                          void *hdr, uint *uhdr_len,
-                          lapi_return_info_t *msg_info,
-                          compl_hndlr_t **comp_h, void **comp_am_info) {
-  void *msg_buf;
-  MACHSTATE1(2,"[%p] PumpMsgsBegin begin {",CmiGetState());
-  /*
-  if(msg_info->udata_one_pkt_ptr != NULL) {
-    // it means that all the data has already arrived
-    msg_buf = CopyMsg(msg_info->udata_one_pkt_ptr, msg_info->msg_len);
-    PumpMsgsComplete(myLapiContext, msg_buf);
-
-    *comp_h = NULL;
-    *comp_am_info = NULL;
-    MACHSTATE(2,"} PumpMsgsBegin end single message");
-    return NULL;
-  } else {
-  */
+                           void *hdr, uint *uhdr_len,
+                           lapi_return_info_t *msg_info,
+                           compl_hndlr_t **comp_h, void **comp_am_info) {
+    void *msg_buf;
+    MACHSTATE1(2,"[%p] PumpMsgsBegin begin {",CmiGetState());
     /* prepare the space for receiving the data, set the completion handler to
        be executed inline */
     msg_buf = (void *)CmiAlloc(msg_info->msg_len);
-    
+
     msg_info->ret_flags = LAPI_SEND_REPLY;
     *comp_h = PumpMsgsComplete;
     *comp_am_info = msg_buf;
     MACHSTATE(2,"} PumpMsgsBegin end");
     return msg_buf;
-    /*}*/
+
 }
 
-/* lapi sender handlers*/
+/* The following two are lapi sender handlers */
 static void ReleaseMsg(lapi_handle_t *myLapiContext, void *msg, lapi_sh_info_t *info) {
-  MACHSTATE2(2,"[%p] ReleaseMsg begin %p {",CmiGetState(),msg);
-  check_lapi_err(info->reason, "ReleaseMsg", __LINE__);
-  CmiFree(msg);
-  MACHSTATE(2,"} ReleaseMsg end");
+    MACHSTATE2(2,"[%p] ReleaseMsg begin %p {",CmiGetState(),msg);
+    check_lapi_err(info->reason, "ReleaseMsg", __LINE__);
+    CmiFree(msg);
+    MACHSTATE(2,"} ReleaseMsg end");
 }
 
 static void DeliveredMsg(lapi_handle_t *myLapiContext, void *msg, lapi_sh_info_t *info) {
-  MACHSTATE1(2,"[%p] DeliveredMsg begin {",CmiGetState());
-  check_lapi_err(info->reason, "DeliveredMsg", __LINE__);
-  *((int *)msg) = *((int *)msg) - 1;
-  MACHSTATE(2,"} DeliveredMsg end");
+    MACHSTATE1(2,"[%p] DeliveredMsg begin {",CmiGetState());
+    check_lapi_err(info->reason, "DeliveredMsg", __LINE__);
+    *((int *)msg) = *((int *)msg) - 1;
+    MACHSTATE(2,"} DeliveredMsg end");
 }
+/* ======End of lapi callbacks such as the completion handler on the sender and recver side ======*/
 
-/*
-#if CMK_SMP
-
-static int inexit = 0;
-
-static int MsgQueueEmpty() {
-  int i;
-#if 0
-  for (i=0; i<_Cmi_mynodesize; i++)
-    if (!PCQueueEmpty(procState[i].sendMsgBuf)) return 0;
-#else
-  return PCQueueEmpty(sendMsgBuf);
-#endif
-  return 1;
-}
-
-static int SendMsgBuf();
-
-// test if all processors recv queues are empty
-static int RecvQueueEmpty() {
-  int i;
-  for (i=0; i<_Cmi_mynodesize; i++) {
-    CmiState cs=CmiGetStateN(i);
-    if (!PCQueueEmpty(cs->recv)) return 0;
-  }
-  return 1;
-}
-*/
 
 /**
-CommunicationServer calls MPI to send messages in the queues and probe message from network.
-*/
-/*
-static void CommunicationServer(int sleepTime) {
-  // PumpMsgs();
-  CmiReleaseSentMessages();
-  SendMsgBuf(); 
-
-  if (inexit == CmiMyNodeSize()) {
-    MACHSTATE(2, "CommunicationServer exiting {");
-#if 0
-    while(!MsgQueueEmpty() || !CmiAllAsyncMsgsSent() || !RecvQueueEmpty()) {
-#endif
-    while(!MsgQueueEmpty() || !CmiAllAsyncMsgsSent()) {
-      CmiReleaseSentMessages();
-      SendMsgBuf(); 
-      // PumpMsgs();
-    }
-
-    MACHSTATE(2, "CommunicationServer barrier begin {");
+ * TODO!!! CommunicationServer/CommunicationServerThread missing
+ * for smp Should refer to the BG/P smp layer for 
+ * commserver/commserverthd 
+ * --Chao Mei
+ */
 
-    check_lapi(LAPI_Gfence,(lapiContext));
-
-    MACHSTATE(2, "} CommunicationServer barrier end");
-#if (CMK_DEBUG_MODE || CMK_WEB_MODE || NODE_0_IS_CONVHOST)
-    if (CmiMyNode() == 0){
-      CmiPrintf("End of program\n");
+#if CMK_NODE_QUEUE_AVAILABLE
+char *CmiGetNonLocalNodeQ(void) {
+    CmiState cs = CmiGetState();
+    char *result = 0;
+    CmiIdleLock_checkMessage(&cs->idle);
+    if (!PCQueueEmpty(CsvAccess(NodeState).NodeRecv)) {
+        MACHSTATE2(3,"[%p] CmiGetNonLocalNodeQ begin %d {",CmiGetState(),CmiMyPe());
+        CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
+        result = (char *) PCQueuePop(CsvAccess(NodeState).NodeRecv);
+        CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
+        MACHSTATE1(3,"} CmiGetNonLocalNodeQ end %d ", CmiMyPe());
     }
-#endif
-    MACHSTATE(2, "} CommunicationServer EXIT");
-    check_lapi(LAPI_Term,(lapiContext));
-    exit(0);   
-  }
+    return result;
 }
 #endif
-*/
 
-/*
-static void CommunicationServerThread(int sleepTime) {
-#if CMK_SMP
-  CommunicationServer(sleepTime);
-#endif
-#if CMK_IMMEDIATE_MSG
-  CmiHandleImmediate();
-#endif
-}
-*/
-
-#if CMK_NODE_QUEUE_AVAILABLE
-char *CmiGetNonLocalNodeQ(void) {
-  CmiState cs = CmiGetState();
-  char *result = 0;
-  CmiIdleLock_checkMessage(&cs->idle);
-  if(!PCQueueEmpty(CsvAccess(NodeState).NodeRecv)) {
-    MACHSTATE2(3,"[%p] CmiGetNonLocalNodeQ begin %d {",CmiGetState(),CmiMyPe());
-    CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
-    result = (char *) PCQueuePop(CsvAccess(NodeState).NodeRecv);
-    CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
-    MACHSTATE1(3,"} CmiGetNonLocalNodeQ end %d ", CmiMyPe());
-  }
-  return result;
-}
-#endif
-
-void *CmiGetNonLocal(void) {
-  CmiState cs = CmiGetState();
-  CmiIdleLock_checkMessage(&cs->idle);
-  MACHSTATE2(3,"[%p] CmiGetNonLocal %d",CmiGetState(),CmiMyPe());
-  return PCQueuePop(cs->recv);
-  /*
-  static int count=0;
-  CmiState cs = CmiGetState();
-  void *msg;
-  CmiIdleLock_checkMessage(&cs->idle);
-
-  // un-necessary locking since only one processor pulls the queue, and the queue is lock safe
-
-  //CmiLock(procState[cs->rank].recvLock);
-  msg =  PCQueuePop(cs->recv); 
-  //CmiUnlock(procState[cs->rank].recvLock);
-
-#if ! CMK_SMP
-  if (no_outstanding_sends) {
-    while (MsgQueueLen>0) {
-      CmiReleaseSentMessages();
-      // PumpMsgs() ??
-    }
-  }
+void *CmiGetNonLocal(void) {    
+    CmiState cs = CmiGetState();
+    MACHSTATE2(3, "[%p] CmiGetNonLocal begin %d{", cs, CmiMyPe());
+    CmiIdleLock_checkMessage(&cs->idle);    
+    void *msg = PCQueuePop(cs->recv);
+    MACHSTATE3(3,"[%p] CmiGetNonLocal from queue %p with msg %p end }",CmiGetState(),(cs->recv), msg);    
+    return msg;
 
-  if(!msg) {
-    CmiReleaseSentMessages();
-    // Potentially put a flag here!!
-    return  PCQueuePop(cs->recv);
-  }
-#endif
-  return msg;
-*/
 }
 
-void CmiNotifyIdle(void) {
-  /* CmiReleaseSentMessages(); */
-  LAPI_Probe(lapiContext);
-  CmiYield();
-}
+/**
+ * TODO: What will be the effects if calling LAPI_Probe in the 
+ * interrupt mode??? --Chao Mei 
+ */
+
 /* user call to handle immediate message, since there is no ServerThread polling
    messages (lapi does all the polling) every thread is authorized to process
    immediate messages. If we are not in lapiInterruptMode check for progress.
 */
 #if CMK_IMMEDIATE_MSG
 void CmiMachineProgressImpl() {
-  MACHSTATE1(2,"[%p] Probing Immediate Messages",CmiGetState());
-  if (!CsvAccess(lapiInterruptMode)) LAPI_Probe(lapiContext);
-  MACHSTATE1(3, "[%p] Handling Immediate Message",CmiGetState());
-  CmiHandleImmediate();
+    /**
+     * I don't understand why imm msgs need to be processed inside 
+     * machine progress implementation.?????? --Chao Mei 
+     */
+    MACHSTATE1(2,"[%p] Probing Immediate Messages",CmiGetState());
+    if (!CsvAccess(lapiInterruptMode)) check_lapi(LAPI_Probe,(lapiContext));
+
+    MACHSTATE1(2, "[%p] Handling Immediate Message begin{",CmiGetState());
+    CmiHandleImmediate();
+    MACHSTATE1(2, "[%p] Handling Immediate Message end }",CmiGetState());
+}
+#else
+void CmiMachineProgressImpl(){
+    if (!CsvAccess(lapiInterruptMode)) check_lapi(LAPI_Probe,(lapiContext));
 }
 #endif
 
+/*TODO: does lapi provide any Barrrier related functions as DCMF provides??? --Chao Mei */
+/* Barrier needs to be implemented!!! -Chao Mei */
 /* These two barriers are only needed by CmiTimerInit to synchronize all the
    threads. They do not need to provide a general barrier. */
-int CmiBarrier() {return 0;}
-int CmiBarrierZero() {return 0;}
+int CmiBarrier() {
+    return 0;
+}
+int CmiBarrierZero() {
+    return 0;
+}
 
 /********************* MESSAGE SEND FUNCTIONS ******************/
 
-static void CmiSendSelf(char *msg) {
-  MACHSTATE1(3,"[%p] Sending itself a message {",CmiGetState());
+/** 
+ * "deliverable": used to know if the message can be encoded 
+ * into the destPE queue withtout duplication (for usage of 
+ * SMP). If it has already been duplicated (and therefore is 
+ * deliverable), we do not want to copy it again, while if it 
+ * has been copied we must do it before enqueuing it. 
+ *  
+ * The general send function for all Cmi send functions.
+ */
+void lapiSendFn(int destPE, int size, char *msg, scompl_hndlr_t *shdlr, void *sinfo, int deliverable) {
+    /* CmiState cs = CmiGetState(); */
+    CmiUInt2  rank, node;
+    lapi_xfer_t xfer_cmd;
 
-#if CMK_IMMEDIATE_MSG
-  if (CmiIsImmediate(msg)) {
-    MACHSTATE1(3, "[%p] Handling Immediate Message",CmiGetState());
-    /* CmiBecomeNonImmediate(msg); */
-    CmiPushImmediateMsg(msg);
-    CmiHandleImmediate();
-    return;
-  }
+    MACHSTATE3(2,"lapiSendFn to destPE=%d with msg %p (isImm=%d) begin {",destPE,msg, CmiIsImmediate(msg));
+    MACHSTATE3(2, "inside lapiSendFn 1: size=%d, sinfo=%p, deliverable=%d", size, sinfo, deliverable);
+    
+#if ENSURE_MSG_PAIRORDER
+    MACHSTATE3(2, "inside lapiSendFn 2: msg src->dest (%d->%d), seqno=%d", CMI_MSG_SRCPE(msg), destPE, CMI_MSG_SEQNO(msg));
 #endif
-  CQdCreate(CpvAccess(cQdState), 1);
-  CdsFifo_Enqueue(CmiGetState()->localqueue,msg);
 
-  MACHSTATE(3,"} Sending itself a message");
-}
-
-/* the field deliverable is used to know if the message can be encoded into the
-   destPE queue without duplication (for usage of SMP). If it has already been
-   duplicated (and therefore is deliverable), we do not want to copy it again,
-   while if it has not been copied we must do it before enqueuing it. */
-void lapiSendFn(int destPE, int size, char *msg, scompl_hndlr_t *shdlr, void *sinfo, int deliverable) {
-  /* CmiState cs = CmiGetState(); */
-  CmiUInt2  rank, node;
-  lapi_xfer_t xfer_cmd;
-     
-  MACHSTATE1(2,"[%p] lapiSendFn begin {",CmiGetState());
-  CQdCreate(CpvAccess(cQdState), 1);
-  node = CmiNodeOf(destPE);
+    node = CmiNodeOf(destPE);
+    /** 
+     *  The rank of the msg should be set before calling
+     *  lapiSendFn!!
+     *  The rank could be DGRAM_NODEMESSAGE which indicates
+     *  a node-level message.
+     */
 #if CMK_SMP
-  rank = CmiRankOf(destPE);
-  
-  if (node == CmiMyNode())  {
-    if (deliverable) {
-      CmiPushPE(rank, msg);
-      /* the acknowledge of delivery must not be called */
-    } else {
-      CmiPushPE(rank, CopyMsg(msg, size));
-      /* acknowledge that the message has been delivered */
-      lapi_sh_info_t lapiInfo;
-      lapiInfo.src = node;
-      lapiInfo.reason = LAPI_SUCCESS;
-      (*shdlr)(&lapiContext, sinfo, &lapiInfo);
+    /*CMI_DEST_RANK(msg) = rank;*/
+    if (node == CmiMyNode())  {
+        rank = CmiRankOf(destPE);
+        MACHSTATE2(2,"[%p] inside lapiSendFn for intra-node message (%p)",CmiGetState(), msg);
+        if (deliverable) {
+            CmiPushPE(rank, msg);
+            /* the acknowledge of delivery must not be called */
+        } else {
+            CmiPushPE(rank, CopyMsg(msg, size));
+            /* acknowledge that the message has been delivered */
+            lapi_sh_info_t lapiInfo;
+            lapiInfo.src = node;
+            lapiInfo.reason = LAPI_SUCCESS;
+            (*shdlr)(&lapiContext, sinfo, &lapiInfo);
+        }
+        return;
     }
-    return;
-  }
-  /*
-  CMI_DEST_RANK(msg) = rank;
-#else
-  // non smp
-  CMI_DEST_RANK(msg) = 0;      // rank is always 0
-  */
 #endif
-  /* The rank is now set by the caller function! */
-
-  /* send the message out of the processor */
-
-  /*
-  msg_tmp = (SMSG_LIST *) CmiAlloc(sizeof(SMSG_LIST));
-  msg_tmp->msg = msg;
-  msg_tmp->next = 0;
-  while (MsgQueueLen > request_max) {
-    //printf("Waiting for %d messages to be sent\n", MsgQueueLen);
-    CmiReleaseSentMessages();
-  }
-
-  check_lapi(LAPI_Setcntr, (*my_context, &msg_tmp->lapiSendCounter, 0));
-  */
-  if (CMI_DEST_RANK(msg) > 10) MACHSTATE2(5, "Error!! in lapiSendFn! destPe=%d, destRank=%d",destPE,CMI_DEST_RANK(msg));
-
-  xfer_cmd.Am.Xfer_type = LAPI_AM_XFER;
-  xfer_cmd.Am.flags     = 0;
-  xfer_cmd.Am.tgt       = node;
-  xfer_cmd.Am.hdr_hdl   = lapiHeaderHandler;
-  xfer_cmd.Am.uhdr_len  = 0;
-  xfer_cmd.Am.uhdr      = NULL;
-  xfer_cmd.Am.udata     = msg;
-  xfer_cmd.Am.udata_len = size;
-  xfer_cmd.Am.shdlr     = shdlr;
-  xfer_cmd.Am.sinfo     = sinfo;
-  xfer_cmd.Am.tgt_cntr  = NULL;
-  xfer_cmd.Am.org_cntr  = NULL;
-  xfer_cmd.Am.cmpl_cntr = NULL;
-
-  check_lapi(LAPI_Xfer,(lapiContext, &xfer_cmd));
-
-  MACHSTATE(2,"} lapiSendFn end");
-  /*
-  if(size < SHORT_MESSAGE_SIZE && my_context != NULL) {
-    check_lapi(LAPI_Amsend,(*my_context, node, (void *)PumpMsgsBegin, 
-                           msg, size, 0, 0, NULL, NULL,
-                           &msg_tmp->lapiSendCounter));      
-  }
-  else {
-
-    if(my_context == NULL)
-      my_context = &lapiContext;
     
-    check_lapi(LAPI_Amsend,(*my_context, destPE,
-                           (void *)PumpMsgsBegin, 0, 0, msg, size,
-                           NULL, NULL, &msg_tmp->lapiSendCounter));
-  }
-  */
-  /*
-  MsgQueueLen++;
-  if(sent_msgs==0)
-    sent_msgs = msg_tmp;
-  else
-    end_sent->next = msg_tmp;
-  end_sent = msg_tmp;
-  return (CmiCommHandle) msg_tmp;
-  */
-}
+    MACHSTATE2(2, "Ready to call LAPI_Xfer with destPe=%d, destRank=%d",destPE,CMI_DEST_RANK(msg));
 
-void CmiSyncSendFn(int destPE, int size, char *msg) {
-  CmiState cs = CmiGetState();
-  /*char *dupmsg = (char *) CmiAlloc(size);
-    memcpy(dupmsg, msg, size); */
-  char *dupmsg = CopyMsg(msg, size);
+    xfer_cmd.Am.Xfer_type = LAPI_AM_XFER;
+    xfer_cmd.Am.flags     = 0;
+    xfer_cmd.Am.tgt       = node;
+    xfer_cmd.Am.hdr_hdl   = lapiHeaderHandler;
+    xfer_cmd.Am.uhdr_len  = 0;
+    xfer_cmd.Am.uhdr      = NULL;
+    xfer_cmd.Am.udata     = msg;
+    xfer_cmd.Am.udata_len = size;
+    xfer_cmd.Am.shdlr     = shdlr;
+    xfer_cmd.Am.sinfo     = sinfo;
+    xfer_cmd.Am.tgt_cntr  = NULL;
+    xfer_cmd.Am.org_cntr  = NULL;
+    xfer_cmd.Am.cmpl_cntr = NULL;
 
-  MACHSTATE1(3,"[%p] Sending sync message begin {",CmiGetState());
-  CMI_BROADCAST_ROOT(dupmsg) = 0;
-  CMI_DEST_RANK(dupmsg) = CmiRankOf(destPE);
+    check_lapi(LAPI_Xfer,(lapiContext, &xfer_cmd));
 
-  if (cs->pe==destPE) {
-    CmiSendSelf(dupmsg);
-  } else {
-    lapiSendFn(destPE, size, dupmsg, ReleaseMsg, dupmsg, 1);
-    /*CmiAsyncSendFn(destPE, size, dupmsg); */
-  }
-  MACHSTATE(3,"} Sending sync message end");
+    MACHSTATE(2,"} lapiSendFn end");
 }
 
-/*
-#if CMK_SMP
-
-// called by communication thread in SMP
-static int SendMsgBuf() {
-  SMSG_LIST *msg_tmp;
-  char *msg;
-  int node, rank, size;
-  int i;
-  int sent = 0;
-
-  MACHSTATE(2,"SendMsgBuf begin {");
-
-  // single message sending queue
-  CmiLock(sendMsgBufLock);
-  msg_tmp = (SMSG_LIST *)PCQueuePop(sendMsgBuf);
-  CmiUnlock(sendMsgBufLock);
-  while (NULL != msg_tmp)
-    {
+static void CmiSendSelf(char *msg) {
+    MACHSTATE1(3,"[%p] Sending itself a message {",CmiGetState());
 
-      node = msg_tmp->destpe;
-      size = msg_tmp->size;
-      msg = msg_tmp->msg;
-      msg_tmp->next = 0;
-      while (MsgQueueLen > request_max) {
-       CmiReleaseSentMessages();
-       // PumpMsgs();
-      }
-      
-      MACHSTATE2(3,"LAPI_Amsend to node %d rank: %d{", node,CMI_DEST_RANK(msg));
-      
-      check_lapi(LAPI_Setcntr, (lapiContext, &msg_tmp->lapiSendCounter, 0));
-
-      if(size < SHORT_MESSAGE_SIZE) 
-       check_lapi(LAPI_Amsend,(lapiContext, node,
-                               (void *)PumpMsgsBegin, msg, size, 0, 0
-                               NULL, &msg_tmp->lapiSendCounter, NULL));      
-      else
-       check_lapi(LAPI_Amsend,(lapiContext, node,
-                               (void *)PumpMsgsBegin, 0,0, msg, size,
-                               NULL, &msg_tmp->lapiSendCounter, NULL));
-
-      MACHSTATE(3,"}LAPI_Amsend end");
-      MsgQueueLen++;
-      if(sent_msgs==0)
-        sent_msgs = msg_tmp;
-      else
-        end_sent->next = msg_tmp;
-      end_sent = msg_tmp;
-      sent=1;
-      CmiLock(sendMsgBufLock);
-      msg_tmp = (SMSG_LIST *)PCQueuePop(sendMsgBuf);
-      CmiUnlock(sendMsgBufLock);
+#if CMK_IMMEDIATE_MSG
+    if (CmiIsImmediate(msg)) {
+        MACHSTATE1(3, "[%p] Push Immediate Message begin {",CmiGetState());        
+        CmiPushImmediateMsg(msg);
+        MACHSTATE1(3, "[%p] Push Immediate Message end }",CmiGetState());        
+        #if !CMK_SMP
+        /* Immdiate msgs have to be handled differently in SMP. See more in AdvanceCommunication() */
+        CmiHandleImmediate();
+        #endif
+        return;
     }
-  MACHSTATE(2,"}SendMsgBuf end ");
-  return sent;
-}
+#endif
+    CQdCreate(CpvAccess(cQdState), 1);
+    CdsFifo_Enqueue(CmiGetState()->localqueue,msg);
 
-void EnqueueMsg(void *m, int size, int node) {
-  SMSG_LIST *msg_tmp = (SMSG_LIST *) CmiAlloc(sizeof(SMSG_LIST));
-  MACHSTATE1(3,"EnqueueMsg to node %d {{ ", node);
-  msg_tmp->msg = m;
-  msg_tmp->size = size;        
-  msg_tmp->destpe = node;      
-  CmiLock(sendMsgBufLock);
-  PCQueuePush(sendMsgBuf,(char *)msg_tmp);
-  CmiUnlock(sendMsgBufLock);
-  MACHSTATE3(3,"}} EnqueueMsg to %d finish with queue %p len: %d", node, sendMsgBuf, PCQueueLength(sendMsgBuf));
+    MACHSTATE(3,"} Sending itself a message");
 }
 
-#endif
-*/
-
-/*
-CmiCommHandle lapiSendFn(lapi_handle_t *my_context, int destPE, 
-                            int size, char *msg) {
-  CmiState cs = CmiGetState();
-  SMSG_LIST *msg_tmp;
-  CmiUInt2  rank, node;
-     
-  if(destPE == cs->pe) {
-    char *dupmsg = (char *) CmiAlloc(size);
-    memcpy(dupmsg, msg, size);
-    CmiSendSelf(dupmsg);
-    return 0;
-  }
-  CQdCreate(CpvAccess(cQdState), 1);
-#if CMK_SMP
-  node = CmiNodeOf(destPE);
-  rank = CmiRankOf(destPE);
-  
-  if (node == CmiMyNode())  {
-    CmiPushPE(rank, msg);
-    return 0;
-  }
-  CMI_DEST_RANK(msg) = rank;
-  EnqueueMsg(msg, size, node);
-  return 0;
+void CmiSyncSendFn(int destPE, int size, char *msg) {
+    CmiState cs = CmiGetState();
+    char *dupmsg = CopyMsg(msg, size);
 
-#else
-  
-  // non smp
-  CMI_DEST_RANK(msg) = 0;      // rank is always 0
-  msg_tmp = (SMSG_LIST *) CmiAlloc(sizeof(SMSG_LIST));
-  msg_tmp->msg = msg;
-  msg_tmp->next = 0;
-  while (MsgQueueLen > request_max) {
-    //printf("Waiting for %d messages to be sent\n", MsgQueueLen);
-    CmiReleaseSentMessages();
-  }
-
-  check_lapi(LAPI_Setcntr, (*my_context, &msg_tmp->lapiSendCounter, 0));
-
-  if(size < SHORT_MESSAGE_SIZE && my_context != NULL) {
-    check_lapi(LAPI_Amsend,(*my_context, node, (void *)PumpMsgsBegin, 
-                           msg, size, 0, 0, NULL, NULL,
-                           &msg_tmp->lapiSendCounter));      
-  }
-  else {
-
-    if(my_context == NULL)
-      my_context = &lapiContext;
-    
-    check_lapi(LAPI_Amsend,(*my_context, destPE,
-                           (void *)PumpMsgsBegin, 0, 0, msg, size,
-                           NULL, NULL, &msg_tmp->lapiSendCounter));
-  }
+    MACHSTATE1(3,"[%p] Sending sync message begin {",CmiGetState());
+    CMI_BROADCAST_ROOT(dupmsg) = 0;
+    CMI_DEST_RANK(dupmsg) = CmiRankOf(destPE);
 
-  MsgQueueLen++;
-  if(sent_msgs==0)
-    sent_msgs = msg_tmp;
-  else
-    end_sent->next = msg_tmp;
-  end_sent = msg_tmp;
-  return (CmiCommHandle) msg_tmp;
-#endif
+    if (cs->pe==destPE) {
+        CmiSendSelf(dupmsg);
+    } else {
+    #if ENSURE_MSG_PAIRORDER
+        CMI_MSG_SRCPE(dupmsg) = CmiMyPe();
+        CMI_MSG_SEQNO(dupmsg) = getNextMsgSeqNo(CpvAccess(nextMsgSeqNo), destPE);
+        setNextMsgSeqNo(CpvAccess(nextMsgSeqNo), destPE, CMI_MSG_SEQNO(dupmsg));
+    #endif
+
+    #if ENABLE_CONVERSE_QD
+        CQdCreate(CpvAccess(cQdState), 1);
+    #endif
+        lapiSendFn(destPE, size, dupmsg, ReleaseMsg, dupmsg, 1);
+    }
+    MACHSTATE(3,"} Sending sync message end");
 }
-*/
 
 int CmiAsyncMsgSent(CmiCommHandle handle) {
-  return (*((int *)handle) == 0)?1:0;
+    return (*((int *)handle) == 0)?1:0;
 }
 
 void CmiReleaseCommHandle(CmiCommHandle handle) {
 #ifndef CMK_OPTIMIZE
-  if (*((int *)handle) != 0) CmiAbort("Released a CmiCommHandle not free!");
+    if (*((int *)handle) != 0) CmiAbort("Released a CmiCommHandle not free!");
 #endif
-  free(handle);
+    free(handle);
 }
 
 /* the CmiCommHandle returned is a pointer to the location of an int. When it is
    set to 1 the message is available. */
 CmiCommHandle CmiAsyncSendFn(int destPE, int size, char *msg) {
-  MACHSTATE1(3,"[%p] Sending async message begin {",CmiGetState());
-  void *handle;
-  CmiState cs = CmiGetState();
-  CMI_BROADCAST_ROOT(msg) = 0;
-  CMI_DEST_RANK(msg) = CmiRankOf(destPE);
-
-  /* if we are the destination, send ourself a copy of the message */
-  if (cs->pe==destPE) {
-    CmiSendSelf(CopyMsg(msg, size));
-    MACHSTATE(3,"} Sending async message end");
-    return 0;
-  }
+    MACHSTATE1(3,"[%p] Sending async message begin {",CmiGetState());
+    void *handle;
+    CmiState cs = CmiGetState();
+    CMI_BROADCAST_ROOT(msg) = 0;
+    CMI_DEST_RANK(msg) = CmiRankOf(destPE);
+
+    /* if we are the destination, send ourself a copy of the message */
+    if (cs->pe==destPE) {
+        CmiSendSelf(CopyMsg(msg, size));
+        MACHSTATE(3,"} Sending async message end");
+        return 0;
+    }
 
-  handle = malloc(sizeof(int));
-  *((int *)handle) = 1;
-  lapiSendFn(destPE, size, msg, DeliveredMsg, handle, 0);
-  /* the message may have been duplicated and already delivered if we are in SMP
-     mode and the destination is on the same node, but there is no optimized
-     check for that. */
-  MACHSTATE(3,"} Sending async message end");
-  return handle;
+    handle = malloc(sizeof(int));
+    *((int *)handle) = 1;
+
+#if ENSURE_MSG_PAIRORDER
+    CMI_MSG_SRCPE(msg) = CmiMyPe();
+    CMI_MSG_SEQNO(msg) = getNextMsgSeqNo(CpvAccess(nextMsgSeqNo), destPE);
+    setNextMsgSeqNo(CpvAccess(nextMsgSeqNo), destPE, CMI_MSG_SEQNO(msg));
+#endif
+
+#if ENABLE_CONVERSE_QD
+    CQdCreate(CpvAccess(cQdState), 1);
+#endif
+    lapiSendFn(destPE, size, msg, DeliveredMsg, handle, 0);
+    /* the message may have been duplicated and already delivered if we are in SMP
+       mode and the destination is on the same node, but there is no optimized
+       check for that. */
+    MACHSTATE(3,"} Sending async message end");
+    return handle;
 }
 
 void CmiFreeSendFn(int destPE, int size, char *msg) {
-  MACHSTATE1(3,"[%p] Sending sync free message begin {",CmiGetState());
-  CmiState cs = CmiGetState();
-  CMI_BROADCAST_ROOT(msg) = 0;
-  CMI_DEST_RANK(msg) = CmiRankOf(destPE);
+    MACHSTATE1(3,"[%p] Sending sync free message begin {",CmiGetState());
+    CmiState cs = CmiGetState();
+    CMI_BROADCAST_ROOT(msg) = 0;
+    CMI_DEST_RANK(msg) = CmiRankOf(destPE);
 
-  if (cs->pe==destPE) {
-    CmiSendSelf(msg);
-  } else {
-    lapiSendFn(destPE, size, msg, ReleaseMsg, msg, 1);
-    /*CmiAsyncSendFn(destPE, size, msg);*/
-  }
-  MACHSTATE(3,"} Sending sync free message end");
+    if (cs->pe==destPE) {
+        CmiSendSelf(msg);
+    } else {
+    #if ENSURE_MSG_PAIRORDER
+        CMI_MSG_SRCPE(msg) = CmiMyPe();
+        CMI_MSG_SEQNO(msg) = getNextMsgSeqNo(CpvAccess(nextMsgSeqNo), destPE);
+        setNextMsgSeqNo(CpvAccess(nextMsgSeqNo), destPE, CMI_MSG_SEQNO(msg));
+    #endif
+    #if ENABLE_CONVERSE_QD
+        CQdCreate(CpvAccess(cQdState), 1);
+    #endif        
+        lapiSendFn(destPE, size, msg, ReleaseMsg, msg, 1);
+        /*CmiAsyncSendFn(destPE, size, msg);*/
+    }
+    MACHSTATE(3,"} Sending sync free message end");
 }
 
+/* ===========Node level p2p send functions============= */
 #if CMK_NODE_QUEUE_AVAILABLE
-
 static void CmiSendNodeSelf(char *msg) {
-  CmiState cs;
-  MACHSTATE1(3,"[%p] Sending itself a node message {",CmiGetState());
+    CmiState cs;
+    MACHSTATE1(3,"[%p] Sending itself a node message {",CmiGetState());
 
 #if CMK_IMMEDIATE_MSG
-  if (CmiIsImmediate(msg)) {
-    MACHSTATE1(3, "[%p] Handling Immediate Message {",CmiGetState());
-    CMI_DEST_RANK(msg) = 0;
-    CmiPushImmediateMsg(msg);
-    CmiHandleImmediate();
-    MACHSTATE(3, "} Handling Immediate Message end");
-    return;
-  }
+    if (CmiIsImmediate(msg)) {
+        MACHSTATE1(3, "[%p] Push Immediate Message {",CmiGetState());
+        CMI_DEST_RANK(msg) = 0;
+        CmiPushImmediateMsg(msg);
+        MACHSTATE(3, "} Push Immediate Message end");
+        #if !CMK_SMP
+        CmiHandleImmediate();
+        #endif     
+        return;
+    }
 #endif
-  CQdCreate(CpvAccess(cQdState), 1);
-  CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
-  PCQueuePush(CsvAccess(NodeState).NodeRecv, msg);
-  CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
+    CQdCreate(CpvAccess(cQdState), 1);
+    CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
+    PCQueuePush(CsvAccess(NodeState).NodeRecv, msg);
+    CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
 
-  cs=CmiGetStateN(0);
-  CmiIdleLock_addMessage(&cs->idle);
+    cs=CmiGetStateN(0);
+    CmiIdleLock_addMessage(&cs->idle);
 
-  MACHSTATE(3,"} Sending itself a node message");
+    MACHSTATE(3,"} Sending itself a node message");
 }
 
+/*TODO: not sure whether the in-order delivery affects for node messages?? --Chao Mei */
 void CmiSyncNodeSendFn(int destNode, int size, char *msg) {
-  char *dupmsg = CopyMsg(msg, size);
+    char *dupmsg = CopyMsg(msg, size);
 
-  MACHSTATE1(3,"[%p] Sending sync node message begin {",CmiGetState());
-  CMI_BROADCAST_ROOT(dupmsg) = 0;
-  CMI_DEST_RANK(dupmsg) = DGRAM_NODEMESSAGE;
+    MACHSTATE1(3,"[%p] Sending sync node message begin {",CmiGetState());
+    CMI_BROADCAST_ROOT(dupmsg) = 0;
+    CMI_DEST_RANK(dupmsg) = DGRAM_NODEMESSAGE;
 
-  if (CmiMyNode()==destNode) {
-    CmiSendNodeSelf(dupmsg);
-  } else {
-    lapiSendFn(CmiNodeFirst(destNode), size, dupmsg, ReleaseMsg, dupmsg, 1);
-  }
-  MACHSTATE(3,"} Sending sync node message end");
+    if (CmiMyNode()==destNode) {
+        CmiSendNodeSelf(dupmsg);
+    } else {
+    #if ENABLE_CONVERSE_QD
+        CQdCreate(CpvAccess(cQdState), 1);
+    #endif
+        lapiSendFn(CmiNodeFirst(destNode), size, dupmsg, ReleaseMsg, dupmsg, 1);
+    }
+    MACHSTATE(3,"} Sending sync node message end");
 }
 
 CmiCommHandle CmiAsyncNodeSendFn(int destNode, int size, char *msg) {
-  void *handle;
-  CMI_BROADCAST_ROOT(msg) = 0;
-  CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;
+    void *handle;
+    CMI_BROADCAST_ROOT(msg) = 0;
+    CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;
+
+    MACHSTATE1(3,"[%p] Sending async node message begin {",CmiGetState());
+    /* if we are the destination, send ourself a copy of the message */
+    if (CmiMyNode()==destNode) {
+        CmiSendNodeSelf(CopyMsg(msg, size));
+        MACHSTATE(3,"} Sending async node message end");
+        return 0;
+    }
 
-  MACHSTATE1(3,"[%p] Sending async node message begin {",CmiGetState());
-  /* if we are the destination, send ourself a copy of the message */
-  if (CmiMyNode()==destNode) {
-    CmiSendNodeSelf(CopyMsg(msg, size));
+    handle = malloc(sizeof(int));
+    *((int *)handle) = 1;
+
+#if ENABLE_CONVERSE_QD
+    CQdCreate(CpvAccess(cQdState), 1);
+#endif
+    lapiSendFn(CmiNodeFirst(destNode), size, msg, DeliveredMsg, handle, 0);
+    /* the message may have been duplicated and already delivered if we are in SMP
+       mode and the destination is on the same node, but there is no optimized
+       check for that. */
     MACHSTATE(3,"} Sending async node message end");
-    return 0;
-  }
-
-  handle = malloc(sizeof(int));
-  *((int *)handle) = 1;
-  lapiSendFn(CmiNodeFirst(destNode), size, msg, DeliveredMsg, handle, 0);
-  /* the message may have been duplicated and already delivered if we are in SMP
-     mode and the destination is on the same node, but there is no optimized
-     check for that. */
-  MACHSTATE(3,"} Sending async node message end");
-  return handle;
-
-  /*
-  int i;
-  SMSG_LIST *msg_tmp;
-  char *dupmsg;
-     
-  CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;
-  switch (dstNode) {
-  case NODE_BROADCAST_ALL:
-    CmiSendNodeSelf((char *)CopyMsg(msg,size));
-  case NODE_BROADCAST_OTHERS:
-    CQdCreate(CpvAccess(cQdState), _Cmi_numnodes-1);
-    for (i=0; i<_Cmi_numnodes; i++)
-      if (i!=_Cmi_mynode) {
-        EnqueueMsg((char *)CopyMsg(msg,size), size, i);
-      }
-    break;
-  default:
-    dupmsg = (char *)CopyMsg(msg,size);
-    if(dstNode == _Cmi_mynode) {
-      CmiSendNodeSelf(dupmsg);
-    }
-    else {
-      CQdCreate(CpvAccess(cQdState), 1);
-      EnqueueMsg(dupmsg, size, dstNode);
-    }
-  }
-  return 0;
-  */
+    return handle;
+
 }
 
 void CmiFreeNodeSendFn(int destNode, int size, char *msg) {
-  CMI_BROADCAST_ROOT(msg) = 0;
-  CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;
+    CMI_BROADCAST_ROOT(msg) = 0;
+    CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;
 
-  MACHSTATE1(3,"[%p] Sending sync free node message begin {",CmiGetState());
-  if (CmiMyNode()==destNode) {
-    CmiSendNodeSelf(msg);
-  } else {
-    lapiSendFn(CmiNodeFirst(destNode), size, msg, ReleaseMsg, msg, 1);
-  }
-  MACHSTATE(3,"} Sending sync free node message end");
+    MACHSTATE1(3,"[%p] Sending sync free node message begin {",CmiGetState());
+    if (CmiMyNode()==destNode) {
+        CmiSendNodeSelf(msg);
+    } else {
+    #if ENABLE_CONVERSE_QD
+        CQdCreate(CpvAccess(cQdState), 1);
+    #endif
+        lapiSendFn(CmiNodeFirst(destNode), size, msg, ReleaseMsg, msg, 1);
+    }
+    MACHSTATE(3,"} Sending sync free node message end");
 }
-
 #endif
 
 /*********************** BROADCAST FUNCTIONS **********************/
+#if CMK_SMP
+/** 
+  * Sending msgs to cores in the same node 
+  * "includeSelf" indicates whether the msg should be sent to 
+  * the proc of rank CMI_DEST_RANK(msg) 
+  * --Chao mei 
+  *  
+  */
+void SendMsgToPeers(int size, char *msg, int includeSelf){
+    if(includeSelf) {
+        int i;
+        for(i=0; i<CmiMyNodeSize(); i++) {
+            char *dupmsg = CopyMsg(msg,size);
+            CmiPushPE(i,dupmsg);
+        }
+    }else{
+        int i;
+        int excludeRank = CMI_DEST_RANK(msg);
+        for(i=excludeRank+1; i<CmiMyNodeSize(); i++) {
+            char *dupmsg = CopyMsg(msg,size);
+            CmiPushPE(i,dupmsg);
+        }
+        for(i=0; i<excludeRank; i++) {
+            char *dupmsg = CopyMsg(msg,size);
+            CmiPushPE(i,dupmsg);
+        }
+    }
+}
+#endif
 
-/* send msg to its spanning children in broadcast. G. Zheng */
+/** 
+ * SendSpanningChildren only sends inter-node messages. The 
+ * intra-node messages are delivered via SendMsgToPeers if it is 
+ * in SMP mode. 
+ */
+#if ENSURE_MSG_PAIRORDER
+void SendSpanningChildren(int size, char *msg, int srcPe, int *seqNoArr){
+#else
 void SendSpanningChildren(int size, char *msg) {
-  int startnode = CMI_BROADCAST_ROOT(msg)-1;
-  int i;
-  char *dupmsg;
-
-  assert(startnode>=0 && startnode<CmiNumNodes());
-
-  for (i=1; i<=BROADCAST_SPANNING_FACTOR; i++) {
-    int p = CmiMyNode() - startnode;
-    if (p<0) p+=CmiNumNodes();
-    p = BROADCAST_SPANNING_FACTOR*p + i;
-    if (p > CmiNumNodes() - 1) break;
-    p += startnode;
-    p = p%CmiNumNodes();
-    assert(p>=0 && p<CmiNumNodes() && p!=CmiMyNode());
+#endif
+    int startproc = CMI_BROADCAST_ROOT(msg)-1;
+    int startnode = CmiNodeOf(startproc);
+    int i, rp;
+    char *dupmsg;
+
+    assert(startnode>=0 && startnode<CmiNumNodes());
+    
+    MACHSTATE3(3, "[%p] SendSpanningChildren on proc=%d with start proc %d begin {",CmiGetState(), CmiMyPe(), startproc);  
+    /* rp is the relative node id from start node */  
+    rp = CmiMyNode() - startnode;
+    if(rp<0) rp += CmiNumNodes();
+    for (i=1; i<=BROADCAST_SPANNING_FACTOR; i++) {
+        int p = BROADCAST_SPANNING_FACTOR*rp + i;
+        if (p > CmiNumNodes() - 1) break;
+        p += startnode;
+        p = p%CmiNumNodes();
+        
 #if CMK_BROADCAST_USE_CMIREFERENCE
-    CmiReference(msg);
-    lapiSendFn(CmiNodeFirst(p), size, msg, ReleaseMsg, msg, 0);
+        CmiReference(msg);
+        lapiSendFn(CmiNodeFirst(p), size, msg, ReleaseMsg, msg, 0);
 #else
-    dupmsg = CopyMsg(msg, size);
-    lapiSendFn(CmiNodeFirst(p), size, dupmsg, ReleaseMsg, dupmsg, 1);
+        dupmsg = CopyMsg(msg, size);
+    #if ENSURE_MSG_PAIRORDER
+        CMI_MSG_SRCPE(dupmsg) = srcPe;
+        CMI_MSG_SEQNO(dupmsg) = getNextMsgSeqNo(seqNoArr, CmiNodeFirst(p));
+        setNextMsgSeqNo(seqNoArr, CmiNodeFirst(p), CMI_MSG_SEQNO(dupmsg));
+    #endif
+        lapiSendFn(CmiNodeFirst(p), size, dupmsg, ReleaseMsg, dupmsg, 1);
 #endif
-    /*CmiSyncSendFn1(p, size, msg); */
-  }
+    }    
+
+    MACHSTATE3(3, "[%p] SendSpanningChildren on proc=%d with start proc %d end }",CmiGetState(), CmiMyPe(), startproc);    
 }
 
-int Cmi_log_of_2 (int i) {
-  int m;
-  for (m=0; i>(1<<m); ++m);
-  return m;
+/* Return the smallest integer that is larger than or equal to log2(i), e.g CmiLog2(14) = 4*/
+static int CmiLog2 (int i) {
+    int m;
+    for (m=0; i>(1<<m); ++m);
+    return m;
 }
 
-/* send msg along the hypercube in broadcast. (Filippo Gioachin) */
-void SendHypercube(int size, char *msg) {
-  int srcPeNumber, tmp, k, num_pes, *dest_pes;
-
-  srcPeNumber = CMI_BROADCAST_ROOT(msg);
-  tmp = srcPeNumber ^ CmiMyPe();
-  k = Cmi_log_of_2(CmiNumPes()) + 2;
-  if (tmp) {
-    do {--k;} while (!(tmp>>k));
-  }
-
-  /* now 'k' is the last dimension in the hypercube used for exchange */
-  CMI_BROADCAST_ROOT(msg) = CmiMyPe();  /* where the message is coming from */
-  dest_pes = (int *)malloc(k*sizeof(int));
-  --k;  /* next dimension in the cube to be used */
-  num_pes = HypercubeGetBcastDestinations(CmiMyPe(), CmiNumPes(), k, dest_pes);
-  for (k=0; k<num_pes; ++k) {
-#if CMI_BROADCAST_USE_CMIREFERENCE
-    CmiReference(msg);
-    CmiSyncSendAndFree(dest_pes[k], size, msg);
+/* send msg along the hypercube in broadcast. (Chao Mei) */
+#if ENSURE_MSG_PAIRORDER
+void SendHypercube(int size, char *msg, int srcPe, int *seqNoArr){
 #else
-    CmiSyncSend(dest_pes[k], size, msg);
+void SendHypercube(int size, char *msg) {
 #endif
-  }
-  free(dest_pes);
+    int i, dist;   
+    char *dupmsg;
+    int dims = CmiLog2(CmiNumNodes());
+    int startproc = CMI_BROADCAST_ROOT(msg)-1;
+    int startnode = CmiNodeOf(startproc);
+    /* relative proc id to startnode */
+    int rp = CmiMyNode() - startnode;    
+    if(rp < 0) rp += CmiNumNodes();
+    dist = rp;
+
+    MACHSTATE3(3, "[%p] SendHypercube on proc=%d with start proc %d begin {",CmiGetState(), CmiMyPe(), startproc);    
+    for(i=0; i<dims; i++) { 
+        if((dist & 1) == 1) break;
+
+        /* destnode is still the relative node id from startnode */
+        int destnode = rp + (1<<i);
+        if(destnode > CmiNumNodes()-1) break; 
+        
+        destnode += startnode;
+        destnode = destnode % CmiNumNodes();
+
+        assert(destnode != CmiMyNode());
+               
+#if CMK_BROADCAST_USE_CMIREFERENCE
+        CmiReference(msg);
+        lapiSendFn(CmiNodeFirst(destnode), size, msg, ReleaseMsg, msg, 0);
+#else
+        dupmsg = CopyMsg(msg, size);
+    #if ENSURE_MSG_PAIRORDER
+        CMI_MSG_SRCPE(dupmsg) = srcPe;
+        CMI_MSG_SEQNO(dupmsg) = getNextMsgSeqNo(seqNoArr, CmiNodeFirst(destnode));
+        setNextMsgSeqNo(seqNoArr, CmiNodeFirst(destnode), CMI_MSG_SEQNO(dupmsg));
+    #endif
+        lapiSendFn(CmiNodeFirst(destnode), size, dupmsg, ReleaseMsg, dupmsg, 1);
+#endif        
+        dist = dist >> 1;    
+    }    
+    MACHSTATE3(3, "[%p] SendHypercube on proc=%d with start proc %d end }",CmiGetState(), CmiMyPe(), startproc);    
 }
 
 void CmiSyncBroadcastGeneralFn(int size, char *msg) {    /* ALL_EXCEPT_ME  */
-  int i, rank;
-  MACHSTATE1(3,"[%p] Sending sync broadcast message begin {",CmiGetState());
+    int i, rank;
+    MACHSTATE3(3,"[%p] Sending sync broadcast message %p with size %d begin {",CmiGetState(), msg, size);
+
+#if ENABLE_CONVERSE_QD
+    CQdCreate(CpvAccess(cQdState), CmiNumPes()-1);
+#endif
+
 #if CMK_BROADCAST_SPANNING_TREE
-  CMI_BROADCAST_ROOT(msg) = CmiMyPe()+1;
-  SendSpanningChildren(size, msg);
-  
-#elif CMK_BROADCAST_HYPERCUBE
-  CMI_BROADCAST_ROOT(msg) = CmiMyPe()+1;
-  SendHypercube(size, msg);
-    
+    CMI_BROADCAST_ROOT(msg) = CmiMyPe()+1;
+    /** 
+     * since the broadcast msg will be relayed separately on 
+     * remote procs by SendSpanningChildren, the actual msg size 
+     * needs to be recorded in the header for proper memory 
+     * allocation. E.g. the bcast msg is relayed in PumpMsgComplete.
+     * But at that time, the actual msg size is not known if the 
+     * filed inside the msg header is not set. The unknown actual 
+     * msg size will cause the relay of msg fail because CopyMsg 
+     * doesn't have a correct msg size input!! -Chao Mei 
+     */
+    CMI_MSG_SIZE(msg) = size;
+    /* node-aware spanning tree, so bcast msg is always delivered to the first core on each node */
+    CMI_DEST_RANK(msg) = 0;
+#if ENSURE_MSG_PAIRORDER
+    SendSpanningChildren(size, msg, CmiMyPe(), CpvAccess(nextMsgSeqNo));
 #else
-  CmiState cs = CmiGetState();
-  char *dupmsg;
+    SendSpanningChildren(size, msg);
+#endif
+        
+#if CMK_SMP
+    CMI_DEST_RANK(msg) = CmiMyRank();
+    SendMsgToPeers(size, msg, 0);
+#endif
 
-  CMI_BROADCAST_ROOT(msg) = 0;
-#if CMK_BROADCAST_USE_CMIREFERENCE
-  for (i=cs->pe+1; i<CmiNumPes(); i++) {
-    CmiReference(msg);
-    lapiSendFn(i, size, msg, ReleaseMsg, msg, 0);
-    /*CmiSyncSendFn(i, size, msg) ;*/
-  }
-  for (i=0; i<cs->pe; i++) {
-    CmiReference(msg);
-    lapiSendFn(i, size, msg, ReleaseMsg, msg, 0);
-    /*CmiSyncSendFn(i, size,msg) ;*/
-  }
+#elif CMK_BROADCAST_HYPERCUBE 
+   
+    CMI_BROADCAST_ROOT(msg) = CmiMyPe()+1;
+    CMI_MSG_SIZE(msg) = size;
+    CMI_DEST_RANK(msg) = 0;    
+
+#if ENSURE_MSG_PAIRORDER
+    SendHypercube(size, msg, CmiMyPe(), CpvAccess(nextMsgSeqNo));
 #else
-  for (i=cs->pe+1; i<CmiNumPes(); i++) {
-    dupmsg = CopyMsg(msg, size);
-    lapiSendFn(i, size, dupmsg, ReleaseMsg, dupmsg, 1);
-    /*CmiSyncSendFn(i, size, msg) ;*/
-  }
-  for (i=0; i<cs->pe; i++) {
-    dupmsg = CopyMsg(msg, size);
-    lapiSendFn(i, size, dupmsg, ReleaseMsg, dupmsg, 1);
-    /*CmiSyncSendFn(i, size,msg) ;*/
-  }
+    SendHypercube(size, msg);
 #endif
+      
+#if CMK_SMP
+    CMI_DEST_RANK(msg) = CmiMyRank();
+    SendMsgToPeers(size, msg, 0);
 #endif
 
-#if CMK_SMP
-  /* deliver local node messages */
-  if (CMI_DEST_RANK(msg)!=DGRAM_NODEMESSAGE) {
-    rank = CmiMyRank();
-    for (i=0; i<CmiMyNodeSize(); ++i) {
-      if (i != rank) CmiPushPE(i, CopyMsg(msg, size));
+#else
+    CmiState cs = CmiGetState();
+    char *dupmsg;
+
+    CMI_BROADCAST_ROOT(msg) = 0;
+#if CMK_BROADCAST_USE_CMIREFERENCE
+    for (i=cs->pe+1; i<CmiNumPes(); i++) {
+        CmiReference(msg);
+        lapiSendFn(i, size, msg, ReleaseMsg, msg, 0);
+        /*CmiSyncSendFn(i, size, msg) ;*/
+    }
+    for (i=0; i<cs->pe; i++) {
+        CmiReference(msg);
+        lapiSendFn(i, size, msg, ReleaseMsg, msg, 0);
+        /*CmiSyncSendFn(i, size,msg) ;*/
+    }
+#else
+#if ENSURE_MSG_PAIRORDER
+    CMI_MSG_SRCPE(msg) = CmiMyPe();
+#endif
+    for (i=cs->pe+1; i<CmiNumPes(); i++) {
+        dupmsg = CopyMsg(msg, size);
+        CMI_DEST_RANK(dupmsg) = CmiRankOf(i);
+    #if ENSURE_MSG_PAIRORDER
+        CMI_MSG_SEQNO(dupmsg) = getNextMsgSeqNo(CpvAccess(nextMsgSeqNo), i);
+        setNextMsgSeqNo(CpvAccess(nextMsgSeqNo), i, CMI_MSG_SEQNO(dupmsg));
+    #endif
+        lapiSendFn(i, size, dupmsg, ReleaseMsg, dupmsg, 1);        
+    }
+    for (i=0; i<cs->pe; i++) {
+        dupmsg = CopyMsg(msg, size);
+    #if ENSURE_MSG_PAIRORDER
+        CMI_MSG_SEQNO(dupmsg) = getNextMsgSeqNo(CpvAccess(nextMsgSeqNo), i);
+        setNextMsgSeqNo(CpvAccess(nextMsgSeqNo), i, CMI_MSG_SEQNO(dupmsg));
+    #endif
+        CMI_DEST_RANK(dupmsg) = CmiRankOf(i);
+        lapiSendFn(i, size, dupmsg, ReleaseMsg, dupmsg, 1);        
     }
-  }
 #endif
-  MACHSTATE(3,"} Sending sync broadcast message end");
+#endif
+
+    MACHSTATE(3,"} Sending sync broadcast message end");
 }
 
 CmiCommHandle CmiAsyncBroadcastGeneralFn(int size, char *msg) {
-  CmiState cs = CmiGetState();
-  int i, rank;
-
-  MACHSTATE1(3,"[%p] Sending async broadcast message from {",CmiGetState());
-  CMI_BROADCAST_ROOT(msg) = 0;
-  void *handle = malloc(sizeof(int));
-  *((int *)handle) = CmiNumPes()-1;
-  for (i=cs->pe+1; i<CmiNumPes(); i++) {
-    lapiSendFn(i, size, msg, DeliveredMsg, handle, 0);
-  }
-  for (i=0; i<cs->pe; i++) {
-    lapiSendFn(i, size, msg, DeliveredMsg, handle, 0);
-  }
-#if CMK_SMP
-  /* deliver local node messages */
-  if (CMI_DEST_RANK(msg)!=DGRAM_NODEMESSAGE) {
-    rank = CmiMyRank();
-    for (i=0; i<CmiMyNodeSize(); ++i) {
-      if (i != rank) CmiPushPE(i, CopyMsg(msg, size));
+#if ENSURE_MSG_PAIRORDER
+    /* Not sure how to add the msg seq no for async broadcast messages --Chao Mei */
+    /* so abort here ! */
+    assert(0);
+    return 0;
+#else
+    CmiState cs = CmiGetState();
+    int i, rank;
+#if ENABLE_CONVERSE_QD
+    CQdCreate(CpvAccess(cQdState), CmiNumPes()-1);
+#endif
+    MACHSTATE1(3,"[%p] Sending async broadcast message from {",CmiGetState());
+    CMI_BROADCAST_ROOT(msg) = 0;
+    void *handle = malloc(sizeof(int));
+    *((int *)handle) = CmiNumPes()-1;
+
+    for (i=cs->pe+1; i<CmiNumPes(); i++) {
+        CMI_DEST_RANK(msg) = CmiRankOf(i);
+        lapiSendFn(i, size, msg, DeliveredMsg, handle, 0);
     }
-  }
+    for (i=0; i<cs->pe; i++) {
+        CMI_DEST_RANK(msg) = CmiRankOf(i);
+        lapiSendFn(i, size, msg, DeliveredMsg, handle, 0);
+    }
+
+    MACHSTATE(3,"} Sending async broadcast message end");
+    return handle;
 #endif
-  MACHSTATE(3,"} Sending async broadcast message end");
-  return handle;
 }
 
 void CmiSyncBroadcastFn(int size, char *msg) {
-  CMI_DEST_RANK(msg) = 0;
-  CmiSyncBroadcastGeneralFn(size, msg);
+    /*CMI_DEST_RANK(msg) = 0;*/
+    CmiSyncBroadcastGeneralFn(size, msg);
 }
 
 CmiCommHandle CmiAsyncBroadcastFn(int size, char *msg) {
-  CMI_DEST_RANK(msg) = 0;
-  return CmiAsyncBroadcastGeneralFn(size, msg);
+    /*CMI_DEST_RANK(msg) = 0;*/
+    return CmiAsyncBroadcastGeneralFn(size, msg);
 }
 
 void CmiFreeBroadcastFn(int size, char *msg) {
-   CmiSyncBroadcastFn(size,msg);
-   CmiFree(msg);
+    CmiSyncBroadcastFn(size,msg);
+    CmiFree(msg);
 }
 
 void CmiSyncBroadcastAllFn(int size, char *msg) {       /* All including me */
-  CmiSendSelf(CopyMsg(msg, size));
-  CmiSyncBroadcastFn(size, msg);
+    CmiSendSelf(CopyMsg(msg, size));
+    CmiSyncBroadcastFn(size, msg);
 }
 
 CmiCommHandle CmiAsyncBroadcastAllFn(int size, char *msg) {
-  CmiSendSelf(CopyMsg(msg, size));
-  return CmiAsyncBroadcastFn(size, msg);
+    CmiSendSelf(CopyMsg(msg, size));
+    return CmiAsyncBroadcastFn(size, msg);
 }
 
 void CmiFreeBroadcastAllFn(int size, char *msg) {       /* All including me */
-  CmiSendSelf(CopyMsg(msg, size));
-  CmiSyncBroadcastFn(size, msg);
-  CmiFree(msg);
+    CmiSendSelf(CopyMsg(msg, size));
+    CmiSyncBroadcastFn(size, msg);
+    CmiFree(msg);
 }
 
 #if CMK_NODE_QUEUE_AVAILABLE
+void SendSpanningChildrenNode(int size, char *msg){    
+    int startnode = -CMI_BROADCAST_ROOT(msg)-1;    
+    int i, rp;
+    char *dupmsg;
+
+    MACHSTATE3(2, "[%p] SendSpanningChildrenNode on node %d with startnode %d", CmiGetState(), CmiMyNode(), startnode);
+    assert(startnode>=0 && startnode<CmiNumNodes());
+        
+    rp = CmiMyNode() - startnode;
+    if (rp<0) rp+=CmiNumNodes();        
+    for (i=1; i<=BROADCAST_SPANNING_FACTOR; i++) {
+        int p = BROADCAST_SPANNING_FACTOR*rp + i;
+        if (p > CmiNumNodes() - 1) break;
+        p += startnode;
+        p = p%CmiNumNodes();
+        
+#if CMK_BROADCAST_USE_CMIREFERENCE
+        CmiReference(msg);
+        lapiSendFn(CmiNodeFirst(p), size, msg, ReleaseMsg, msg, 0);
+#else
+        dupmsg = CopyMsg(msg, size);
+        lapiSendFn(CmiNodeFirst(p), size, dupmsg, ReleaseMsg, dupmsg, 1);
+#endif
+    }
+    MACHSTATE3(3, "[%p] SendSpanningChildrenNode on node=%d with start node %d end }",CmiGetState(), CmiMyNode(), startnode);
+}
+
+/* send msg along the hypercube in broadcast. (Chao Mei) */
+void SendHypercubeNode(int size, char *msg) {
+    int i, dist;   
+    char *dupmsg;
+    int dims = CmiLog2(CmiNumNodes());
+    int startnode = -CMI_BROADCAST_ROOT(msg)-1;
+    int rp = CmiMyNode() - startnode;    
+    if(rp < 0) rp += CmiNumNodes();
+    dist = rp;
+
+    MACHSTATE3(3, "[%p] SendHypercubeNode on node=%d with start node %d begin {",CmiGetState(), CmiMyNode(), startnode);
+    for(i=0; i<dims; i++) { 
+        if((dist & 1) == 1) break;
+        
+        int destnode = rp + (1<<i);
+        if(destnode > CmiNumNodes()-1) break;
+        
+        destnode += startnode;
+        destnode = destnode % CmiNumNodes();        
+                        
+        assert(destnode != CmiMyNode());
+
+#if CMK_BROADCAST_USE_CMIREFERENCE
+        CmiReference(msg);
+        lapiSendFn(CmiNodeFirst(destnode), size, msg, ReleaseMsg, msg, 0);
+#else
+        dupmsg = CopyMsg(msg, size);
+        lapiSendFn(CmiNodeFirst(destnode), size, dupmsg, ReleaseMsg, dupmsg, 1);
+#endif        
+        dist = dist >> 1;    
+    }
+    MACHSTATE3(3, "[%p] SendHypercubeNode on node=%d with start node %d end }",CmiGetState(), CmiMyNode(), startnode);  
+}
+
+void CmiSyncNodeBroadcastGeneralFn(int size, char *msg) {    /* ALL_EXCEPT_THIS_NODE  */     
+#if ENABLE_CONVERSE_QD
+    CQdCreate(CpvAccess(cQdState), CmiNumNodes()-1);
+#endif
+#if CMK_BROADCAST_SPANNING_TREE
+
+    MACHSTATE1(3,"[%p] Sending sync node broadcast message (use spanning tree) begin {",CmiGetState());
+    CMI_BROADCAST_ROOT(msg) = -(CmiMyNode()+1);
+    CMI_MSG_SIZE(msg) = size;
+    CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;    
+    SendSpanningChildrenNode(size, msg);
+    
+#elif CMK_BROADCAST_HYPERCUBE
+
+    MACHSTATE1(3,"[%p] Sending sync node broadcast message (use Hypercube) begin {",CmiGetState());
+    CMI_BROADCAST_ROOT(msg) = -(CmiMyNode()+1);
+    CMI_MSG_SIZE(msg) = size;
+    CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;    
+    SendHypercubeNode(size, msg);
+    
+#else      
+    char *dupmsg;
+    int i;
+    MACHSTATE1(3,"[%p] Sending sync node broadcast message (use p2p) begin {",CmiGetState());
+
+    CMI_BROADCAST_ROOT(msg) = 0;
+    CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;
+    for (i=CmiMyNode()+1; i<CmiNumNodes(); i++) {
+        dupmsg = CopyMsg(msg, size);        
+        lapiSendFn(CmiNodeFirst(i), size, dupmsg, ReleaseMsg, dupmsg, 1);        
+    }
+    for (i=0; i<CmiMyNode(); i++) {
+        dupmsg = CopyMsg(msg, size);        
+        lapiSendFn(CmiNodeFirst(i), size, dupmsg, ReleaseMsg, dupmsg, 1);        
+    }
+#endif
+    MACHSTATE(3,"} Sending sync node broadcast message end");
+}
+
+CmiCommHandle CmiAsyncNodeBroadcastGeneralFn(int size, char *msg) {
+    int i;
+
+#if ENABLE_CONVERSE_QD
+    CQdCreate(CpvAccess(cQdState), CmiNumNodes()-1);
+#endif
+
+    MACHSTATE1(3,"[%p] Sending async node broadcast message from {",CmiGetState());
+    CMI_BROADCAST_ROOT(msg) = 0;
+    CMI_DEST_RANK(msg) =DGRAM_NODEMESSAGE;
+    void *handle = malloc(sizeof(int));
+    *((int *)handle) = CmiNumNodes()-1;
+    for (i=CmiMyNode()+1; i<CmiNumNodes(); i++) {        
+        lapiSendFn(CmiNodeFirst(i), size, msg, DeliveredMsg, handle, 0);
+    }
+    for (i=0; i<CmiMyNode(); i++) {        
+        lapiSendFn(CmiNodeFirst(i), size, msg, DeliveredMsg, handle, 0);
+    }
+
+    MACHSTATE(3,"} Sending async broadcast message end");
+    return handle;
+}
 
 void CmiSyncNodeBroadcastFn(int size, char *msg) {
-  CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;
-  CmiSyncBroadcastGeneralFn(size, msg);
+    /*CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;*/
+    CmiSyncNodeBroadcastGeneralFn(size, msg);
 }
 
 CmiCommHandle CmiAsyncNodeBroadcastFn(int size, char *msg) {
-   CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;
-   CmiAsyncBroadcastGeneralFn(size, msg);
+    /*CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;*/
+    return CmiAsyncNodeBroadcastGeneralFn(size, msg);
 }
 
 void CmiFreeNodeBroadcastFn(int size, char *msg) {
-  CmiSyncNodeBroadcastFn(size, msg);
-  CmiFree(msg);
+    CmiSyncNodeBroadcastFn(size, msg);
+    CmiFree(msg);
 }
 
 void CmiSyncNodeBroadcastAllFn(int size, char *msg) {
-  CmiSendNodeSelf(msg);
-  CmiSyncNodeBroadcastFn(size, msg);
+    CmiSendNodeSelf(CopyMsg(msg, size));
+    CmiSyncNodeBroadcastFn(size, msg);
 }
 
 CmiCommHandle CmiAsyncNodeBroadcastAllFn(int size, char *msg) {
-  CmiSendNodeSelf(msg);
-  return CmiAsyncNodeBroadcastFn(size, msg);
+    CmiSendNodeSelf(CopyMsg(msg, size));
+    return CmiAsyncNodeBroadcastFn(size, msg);
 }
 
 void CmiFreeNodeBroadcastAllFn(int size, char *msg) {
-  CmiSendNodeSelf(CopyMsg(msg, size));
-  CmiSyncNodeBroadcastFn(size, msg);
-  CmiFree(msg);
+    CmiSendNodeSelf(CopyMsg(msg, size));
+    CmiSyncNodeBroadcastFn(size, msg);
+    CmiFree(msg);
 }
-
 #endif
 
 #if ! CMK_MULTICAST_LIST_USE_COMMON_CODE
-
 void CmiSyncListSendFn(int, int *, int, char*) {
 
 }
@@ -1226,11 +1575,9 @@ CmiCommHandle CmiAsyncListSendFn(int, int *, int, char*) {
 void CmiFreeListSendFn(int, int *, int, char*) {
 
 }
-
 #endif
 
 #if ! CMK_VECTOR_SEND_USES_COMMON_CODE
-
 void CmiSyncVectorSend(int, int, int *, char **) {
 
 }
@@ -1242,249 +1589,359 @@ CmiCommHandle CmiAsyncVectorSend(int, int, int *, char **) {
 void CmiSyncVectorSendAndFree(int, int, int *, char **) {
 
 }
-
 #endif
 
 
-/************************** MAIN ***********************************/
-
-static volatile int inexit = 0;
+/************************** MAIN (non comm related functions) ***********************************/
 
 void ConverseExit(void) {
-  MACHSTATE2(2, "[%d-%p] entering ConverseExit",CmiMyPe(),CmiGetState());
-#if CMK_SMP
-  if (CmiMyRank() != 0) {
-    CmiCommLock();
-    inexit++;
-    CmiCommUnlock();
-
-    /* By leaving this function to return, the caller function (ConverseRunPE)
-       will also terminate and return. Since that functions was called by the
-       thread constructor (call_startfn of machine-smp.c), the thread will be
-       terminated. */
-  } else {
-    /* processor 0 */
-    CmiState cs = CmiGetState();
-    MACHSTATE2(2, "waiting for inexit (%d) to be %d",inexit,CmiMyNodeSize()-1);
-    while (inexit != CmiMyNodeSize()-1) {
-      CmiIdleLock_sleep(&cs->idle,10);
-    }
-    /* ok, all threads synchronized! */
-#endif
-    check_lapi(LAPI_Gfence, (lapiContext));
+    MACHSTATE2(2, "[%d-%p] entering ConverseExit begin {",CmiMyPe(),CmiGetState());
+    
+    /* TODO: Is it necessary to drive the network progress here?? -Chao Mei */
+
+    /* A barrier excluding the comm thread if present */
+    CmiNodeBarrier();
 
     ConverseCommonExit();
-    check_lapi(LAPI_Term, (lapiContext));
 
 #if (CMK_DEBUG_MODE || CMK_WEB_MODE || NODE_0_IS_CONVHOST)
     if (CmiMyPe() == 0) CmiPrintf("End of program\n");
 #endif
 
-    exit(0);
+    /* TODO: signal the comm thread to exit now!! -Chao Mei */
+
+    CmiNodeBarrier();
+
+    MACHSTATE2(2, "[%d-%p] ConverseExit end }",CmiMyPe(),CmiGetState());
 #if CMK_SMP
-  }
+    if(CmiMyRank()==0) {
+        check_lapi(LAPI_Gfence, (lapiContext));
+        check_lapi(LAPI_Term, (lapiContext));
+        exit(EXIT_SUCCESS);
+    }else{
+        pthread_exit(NULL);
+    }
+#else
+    check_lapi(LAPI_Gfence, (lapiContext));      
+    check_lapi(LAPI_Term, (lapiContext));
+    exit(EXIT_SUCCESS);
 #endif
 }
 
+/* Those be Cpved?? --Chao Mei */
 static char     **Cmi_argv;
 static CmiStartFn Cmi_startfn;   /* The start function */
 static int        Cmi_usrsched;  /* Continue after start function finishes? */
 
+/** 
+ *  CmiNotifyIdle is used in non-SMP mode when the proc is idle.
+ *  When the proc is idle, the LAPI_Probe is called to make
+ *  network progress.
+ *  
+ *  While in SMP mode, CmiNotifyStillIdle and CmiNotifyBeginIdle
+ *  are used. Particularly, when idle, the frequency of calling
+ *  lapi_probe (network progress) is given by "sleepMs"
+ */
+void CmiNotifyIdle(void) {    
+    AdvanceCommunication();
+    CmiYield();
+}
+
 typedef struct {
-  int sleepMs; /*Milliseconds to sleep while idle*/
-  int nIdles; /*Number of times we've been idle in a row*/
-  CmiState cs; /*Machine state*/
+    int sleepMs; /*Milliseconds to sleep while idle*/
+    int nIdles; /*Number of times we've been idle in a row*/
+    CmiState cs; /*Machine state*/
 } CmiIdleState;
 
 static CmiIdleState *CmiNotifyGetState(void) {
-  CmiIdleState *s=(CmiIdleState *)malloc(sizeof(CmiIdleState));
-  s->sleepMs=0;
-  s->nIdles=0;
-  s->cs=CmiGetState();
-  return s;
+    CmiIdleState *s=(CmiIdleState *)malloc(sizeof(CmiIdleState));
+    s->sleepMs=0;
+    s->nIdles=0;
+    s->cs=CmiGetState();
+    return s;
 }
 
 static void CmiNotifyBeginIdle(CmiIdleState *s) {
-  s->sleepMs=0;
-  s->nIdles=0;
+    s->sleepMs=0;
+    s->nIdles=0;
 }
 
 #define SPINS_BEFORE_SLEEP     20
-    
+
 static void CmiNotifyStillIdle(CmiIdleState *s) {
-  MACHSTATE2(2,"[%p] still idle (%d) begin {",CmiGetState(),CmiMyPe());
-  s->nIdles++;
-  if (s->nIdles>SPINS_BEFORE_SLEEP) { /*Start giving some time back to the OS*/
-    s->sleepMs+=2;
-    if (s->sleepMs>10) s->sleepMs=10;
-  }
-  if (s->sleepMs>0) {
-    MACHSTATE1(2,"idle sleep (%d) {",CmiMyPe());
-    CmiIdleLock_sleep(&s->cs->idle,s->sleepMs);
-    MACHSTATE1(2,"} idle sleep (%d)",CmiMyPe());
-  }       
-  LAPI_Probe(lapiContext);
-  MACHSTATE1(2,"still idle (%d) end {",CmiMyPe());
+    MACHSTATE2(2,"[%p] still idle (%d) begin {",CmiGetState(),CmiMyPe());
+    s->nIdles++;
+    if (s->nIdles>SPINS_BEFORE_SLEEP) { /*Start giving some time back to the OS*/
+        s->sleepMs+=2;
+        if (s->sleepMs>10) s->sleepMs=10;
+    }
+    if (s->sleepMs>0) {
+        MACHSTATE1(2,"idle sleep (%d) {",CmiMyPe());
+        CmiIdleLock_sleep(&s->cs->idle,s->sleepMs);
+        MACHSTATE1(2,"} idle sleep (%d)",CmiMyPe());
+    }
+
+    AdvanceCommunication();
+    
+    MACHSTATE1(2,"still idle (%d) end }",CmiMyPe());
 }
 
+#if MACHINE_DEBUG_LOG
+CpvDeclare(FILE *, debugLog);
+#endif
+
 static void ConverseRunPE(int everReturn) {
-  CmiIdleState *s;
-  char** CmiMyArgv;
-  CpvInitialize(void *,CmiLocalQueue);
+    CmiIdleState *s;
+    char** CmiMyArgv;
+    int i;
+    CpvInitialize(void *,CmiLocalQueue);
+    CpvInitialize(unsigned, networkProgressCount);
+
+#if ENSURE_MSG_PAIRORDER
+    CpvInitialize(int *, nextMsgSeqNo);
+    CpvAccess(nextMsgSeqNo) = malloc(CmiNumPes()*sizeof(int));
+    memset(CpvAccess(nextMsgSeqNo), 0, CmiNumPes()*sizeof(int));
+    CpvInitialize(int *, expectedMsgSeqNo);
+    CpvAccess(expectedMsgSeqNo) = malloc(CmiNumPes()*sizeof(int));
+    memset(CpvAccess(expectedMsgSeqNo), 0, CmiNumPes()*sizeof(int));
+
+    CpvInitialize(void ***, oooMsgBuffer);
+    CpvAccess(oooMsgBuffer) = malloc(CmiNumPes()*sizeof(void **));
+    memset(CpvAccess(oooMsgBuffer), 0, CmiNumPes()*sizeof(void **));
+
+    CpvInitialize(unsigned char *, oooMaxOffset);
+    CpvAccess(oooMaxOffset) = malloc(CmiNumPes()*sizeof(unsigned char));
+    memset(CpvAccess(oooMaxOffset), 0, CmiNumPes()*sizeof(unsigned char));
 
-  MACHSTATE2(2, "[%d] ConverseRunPE (thread %p)",CmiMyRank(),CmiGetState());
-  /* No communication thread */
-  s=CmiNotifyGetState();
-  /*CmiState cs;*/
-  CmiNodeBarrier();
-  /*cs = CmiGetState();*/
+/*
+    CpvInitialize(MsgOrderInfo, msgSeqInfo);
+    CpvAccess(msgSeqInfo).expectedMsgSeqNo = malloc(CmiNumPes()*sizeof(int));
+    memset(CpvAccess(msgSeqInfo).expectedMsgSeqNo, 0, CmiNumPes()*sizeof(int));
+    CpvAccess(msgSeqInfo).nextMsgSeqNo = malloc(CmiNumPes()*sizeof(int));
+    memset(CpvAccess(msgSeqInfo).nextMsgSeqNo, 0, CmiNumPes()*sizeof(int));
+    for(i=0; i<CmiNumPes(); i++) {
+        CpvAccess(msgSeqInfo).
+    }
+*/
 
-  CpvAccess(CmiLocalQueue) = CmiGetState()->localqueue;
+#endif
 
-  CmiMyArgv=CmiCopyArgs(Cmi_argv);
-    
-  CthInit(CmiMyArgv);
+#if MACHINE_DEBUG_LOG
+    {
+        char ln[200];
+        sprintf(ln,"debugLog.%d",CmiMyPe());
+        CpvInitialize(FILE *, debugLog);
+        CpvAccess(debugLog)=fopen(ln,"w");
+    }
+#endif
 
-  ConverseCommonInit(CmiMyArgv);
+    /* To make sure cpvaccess is correct? -Chao Mei */
+    CmiNodeAllBarrier();
 
+    /* Added by Chao Mei */
 #if CMK_SMP
-  CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,(CcdVoidFn)CmiNotifyBeginIdle,(void *)s);
-  CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyStillIdle,(void *)s);
+    if(CmiMyRank()) {
+        /* The master core of this node is already initialized */
+        lapi_info_t info;
+        int testnode, testnumnodes;
+        memset(&info,0,sizeof(info));
+        /*CpvInitialize(lapi_handle_t *, lapiContext);
+        CpvAccess(lapiContext) = CpvAccessOther(lapiContext, 0)+CmiMyRank();
+        CpvAccess(lapiContext) = CpvAccessOther(lapiContext, 0);
+        */       
+        MACHSTATE2(2, "My rank id=%d, lapicontext=%p", CmiMyRank(), &lapiContext);
+
+        check_lapi(LAPI_Qenv,(lapiContext, TASK_ID, &testnode));
+        check_lapi(LAPI_Qenv,(lapiContext, NUM_TASKS, &testnumnodes));
+
+        MACHSTATE3(2, "My rank id=%d, Task id=%d, Num tasks=%d", CmiMyRank(), testnode, testnumnodes);
+    }
+#endif
+
+
+    MACHSTATE2(2, "[%d] ConverseRunPE (thread %p)",CmiMyRank(),CmiGetState());
+       
+    CmiNodeAllBarrier();
+
+    MACHSTATE(2, "After NodeBarrier in ConverseRunPE");
+    
+    CpvAccess(CmiLocalQueue) = CmiGetState()->localqueue;
+
+    CmiMyArgv=CmiCopyArgs(Cmi_argv);
+
+    CthInit(CmiMyArgv);
+
+    MACHSTATE(2, "After CthInit in ConverseRunPE");
+
+    ConverseCommonInit(CmiMyArgv);
+
+    MACHSTATE(2, "After ConverseCommonInit in ConverseRunPE");
+
+   /**
+     * In SMP, the machine layer usually has one comm thd, and it is 
+     * designed to be responsible for all network communication. So 
+     * if there's no dedicated processor for the comm thread, it has 
+     * to share a proc with a worker thread. In this scenario, 
+     * the worker thread needs to yield for some time to give CPU 
+     * time to comm thread. However, in current configuration, we 
+     * will always dedicate one proc for the comm thd, therefore, 
+     * such yielding scheme is not necessary.  Besides, avoiding 
+     * this yielding scheme improves performance because worker 
+     * thread doesn't need to yield and will be more responsive to 
+     * incoming messages. So, we will always use CmiNotifyIdle 
+     * instead. 
+     *  
+     * --Chao Mei
+     */
+#if 0 && CMK_SMP
+    s=CmiNotifyGetState();
+    CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,(CcdVoidFn)CmiNotifyBeginIdle,(void *)s);
+    CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyStillIdle,(void *)s);
 #else
-  CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyIdle,NULL);
+    CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyIdle,NULL);
+#if !CMK_SMP || CMK_SMP_NO_COMMTHD
+    /* If there's comm thread, then comm thd is responsible for advancing comm */
+    CcdCallOnConditionKeep(CcdPERIODIC_10ms, (CcdVoidFn)AdvanceCommunication, NULL);
+#endif
 #endif
 
 #if CMK_IMMEDIATE_MSG
-  /* Converse initialization finishes, immediate messages can be processed.
-     node barrier previously should take care of the node synchronization */
-  _immediateReady = 1;
-#endif
-
-  /*if (CmiMyRank() == CmiMyNodeSize()) return;*/
-  /* communication thread */
-  if (CmiMyRank() == CmiMyNodeSize()) {
-    Cmi_startfn(CmiGetArgc(CmiMyArgv), CmiMyArgv);
-    while (1) sleep(1); /*CommunicationServerThread(5);*/
-  }
-  else {  /* worker thread */
-  if (!everReturn) {
-    Cmi_startfn(CmiGetArgc(CmiMyArgv), CmiMyArgv);
-    if (Cmi_usrsched==0) CsdScheduler(-1);
-    ConverseExit();
-  }
-  }
-}
-
-void ConverseInit(int argc, char **argv, CmiStartFn fn, int usched, int initret)
-{
-  int n,i;
-#if MACHINE_DEBUG
-  debugLog=NULL;
-#endif
-
-  lapi_info_t info;
-  /*int LAPI_Init_rc;*/
-  memset(&info,0,sizeof(info));
-  check_lapi(LAPI_Init,(&lapiContext, &info));
-  /*
-  info.err_hndlr=NULL;
-  LAPI_Init_rc = LAPI_Init(&lapiContext, &info);
-  if (LAPI_Init_rc == LAPI_ERR_BAD_PARAMETER) {
-    printf("Error during LAPI_Init.  This normally indicates that \n"
-          " your environment is not properly configured for LAPI--\n"
-          "     MP_MSG_API = %s (should be lapi or mpi,lapi)\n"
-          "     MP_EUILIB = %s (should be us or ip)\n",
-          getenv("MP_MSG_API"),
-          getenv("MP_EULIB"));
-  }
-  check_lapi(LAPI_Init_rc,);
-  */
-  
-  /* It's a good idea to start with a fence,
-     because packets recv'd before a LAPI_Init are just dropped. */
-  check_lapi(LAPI_Gfence,(lapiContext));
-  
-  CsvAccess(lapiInterruptMode) = 0;
-  CsvAccess(lapiInterruptMode) = CmiGetArgFlag(argv,"+poll")?0:1;
-  CsvAccess(lapiInterruptMode) = CmiGetArgFlag(argv,"+nopoll")?1:0;
-
-  check_lapi(LAPI_Senv,(lapiContext, ERROR_CHK, lapiDebugMode));
-  check_lapi(LAPI_Senv,(lapiContext, INTERRUPT_SET, CsvAccess(lapiInterruptMode)));
-  
-  check_lapi(LAPI_Qenv,(lapiContext, TASK_ID, &CmiMyNode()));
-  check_lapi(LAPI_Qenv,(lapiContext, NUM_TASKS, &CmiNumNodes()));
-
-  check_lapi(LAPI_Addr_set,(lapiContext,(void *)PumpMsgsBegin,lapiHeaderHandler));
-
-  /* processor per node */
+    /* Converse initialization finishes, immediate messages can be processed.
+       node barrier previously should take care of the node synchronization */
+    _immediateReady = 1;
+#endif
+
+    /* communication thread */
+    if (CmiMyRank() == CmiMyNodeSize()) {
+        Cmi_startfn(CmiGetArgc(CmiMyArgv), CmiMyArgv);
+        MACHSTATE2(3, "[%p]: Comm thread on node %d is going to be a communication server", CmiGetState(), CmiMyNode());    
+        while (1) sleep(1); /*CommunicationServerThread(5);*/
+    } else { /* worker thread */
+        if (!everReturn) {
+            Cmi_startfn(CmiGetArgc(CmiMyArgv), CmiMyArgv);
+            MACHSTATE1(3, "[%p]: Worker thread is going to work", CmiGetState());
+            if (Cmi_usrsched==0) CsdScheduler(-1);
+            ConverseExit();
+        }
+    }
+}
+
+void ConverseInit(int argc, char **argv, CmiStartFn fn, int usched, int initret) {
+    int n,i;
+
+    lapi_info_t info;
+
+    /* processor per node */
+    /** 
+     *  We have to determin the ppn at this point in order to create
+     *  the corresponding number of lapiContext instances.
+     */
 #if CMK_SMP
-  CmiMyNodeSize() = 1;
-  CmiGetArgInt(argv,"+ppn", &CmiMyNodeSize());
+    CmiMyNodeSize() = 1;
+    CmiGetArgInt(argv,"+ppn", &CmiMyNodeSize());
 #else
-  if (CmiGetArgFlag(argv,"+ppn")) {
-    CmiAbort("+ppn cannot be used in non SMP version!\n");
-  }
+    if (CmiGetArgFlag(argv,"+ppn")) {
+        CmiAbort("+ppn cannot be used in non SMP version!\n");
+    }
 #endif
 
-  /*
-#if CMK_NO_OUTSTANDING_SENDS
-  no_outstanding_sends=1;
-#endif
-  if (CmiGetArgInt(argv,"+no_outstanding_sends",&no_outstanding_sends) && _Cmi_mynode == 0) {
-     CmiPrintf("Charm++: Will%s consume outstanding sends in scheduler loop\n",
-       no_outstanding_sends?"":" not");
-  }
-  */
-  CmiNumPes() = CmiNumNodes() * CmiMyNodeSize();
-  Cmi_nodestart = CmiMyNode() * CmiMyNodeSize();
-  /*Cmi_argvcopy = CmiCopyArgs(argv);*/
-  Cmi_argv = argv;
-  Cmi_startfn = fn;
-  Cmi_usrsched = usched;
- /* CmiSpanTreeInit();*/
-  /*
-  request_max=MAX_QLEN;
-  CmiGetArgInt(argv,"+requestmax",&request_max);
-  */
-  /*printf("request max=%d\n", request_max);*/
-  if (CmiGetArgFlag(argv,"++debug"))
-  {   /*Pause so user has a chance to start and attach debugger*/
-    printf("CHARMDEBUG> Processor %d has PID %d\n",CmiMyNode(),getpid());
-    if (!CmiGetArgFlag(argv,"++debug-no-pause"))
-      sleep(10);
-  }
+    memset(&info,0,sizeof(info));
 
-  /*CmiTimerInit();*/
 
-#if CMK_NODE_QUEUE_AVAILABLE
-  CsvInitialize(CmiNodeState, NodeState);
-  CmiNodeStateInit(&CsvAccess(NodeState));
+/* instance_no has beed disabled, and no longer effective in LAPI --Chao Mei */
+#if 0 && CMK_SMP
+#if CMK_SMP_NO_COMMTHD    
+    info.instance_no = CmiMyNodeSize();
+#else
+    /*create the additional lapi context instance for the comm thread in SMP mode -Chao Mei*/
+    info.instance_no = CmiMyNodeSize()+1;
+#endif
+    if(info.instance_no > 16) {
+        if(CmiMyPe()==0) CmiPrintf("WARNING: Only a maximum of 16 LAPI instances in a LAPI task could be created!\n");
+        info.instance_no = 16;
+    }
 #endif
+    
+    /* Register error handler (redundant?) -- added by Chao Mei*/
+    info.err_hndlr = (LAPI_err_hndlr *)lapi_err_hndlr;
+
+    /* Indicates the number of completion handler threads to create */
+    /* The number of completion hndlr thds will affect the atomic PCQueue operations!! */
+    /* info.num_compl_hndlr_thr = 1; */
+
+    check_lapi(LAPI_Init,(&lapiContext, &info));
+    
+    /* It's a good idea to start with a fence,
+       because packets recv'd before a LAPI_Init are just dropped. */
+    check_lapi(LAPI_Gfence,(lapiContext));
+
+    check_lapi(LAPI_Qenv,(lapiContext, TASK_ID, &CmiMyNode()));
+    check_lapi(LAPI_Qenv,(lapiContext, NUM_TASKS, &CmiNumNodes()));
 
-  procState = (ProcState *)malloc((CmiMyNodeSize()) * sizeof(ProcState));
-  for (i=0; i<CmiMyNodeSize(); i++) {
-/*    procState[i].sendMsgBuf = PCQueueCreate();   */
-    procState[i].recvLock = CmiCreateLock();
-  }
-  /*
 #if CMK_SMP
-  sendMsgBuf = PCQueueCreate();
-  sendMsgBufLock = CmiCreateLock();
+    CsvAccess(lapiInterruptMode) = 0;
+    if(CmiGetArgFlag(argv,"+poll")) CsvAccess(lapiInterruptMode) = 0;
+    if(CmiGetArgFlag(argv,"+nopoll")) CsvAccess(lapiInterruptMode) = 1;    
+#else
+    /* To make the interrupt mode as default in the non-smp case -NOT QUITE STABLE YET!! */
+    CsvAccess(lapiInterruptMode) = 0;    
+    if(CmiGetArgFlag(argv,"+poll")) CsvAccess(lapiInterruptMode) = 0;
+    if(CmiGetArgFlag(argv,"+nopoll")) CsvAccess(lapiInterruptMode) = 1;  
+
+    if(CmiNumNodes()==1) {
+        /** 
+         *  There's a bug in LAPI with interrupt mode with only one
+         *  LAPI task, so turning off the interrupt mode. --Chao Mei
+         */
+        CsvAccess(lapiInterruptMode) = 0;
+    }
 #endif
-  */
 
-#if MACHINE_DEBUG_LOG
-  {
-    char ln[200];
-    sprintf(ln,"debugLog.%d",CmiMyNode());
-    debugLog=fopen(ln,"w");
-  }
+    check_lapi(LAPI_Senv,(lapiContext, ERROR_CHK, lapiDebugMode));
+    check_lapi(LAPI_Senv,(lapiContext, INTERRUPT_SET, CsvAccess(lapiInterruptMode)));
+
+    if(CmiMyNode()==0) {
+        printf("Running lapi in interrupt mode: %d\n", CsvAccess(lapiInterruptMode));
+        printf("Running lapi with %d completion handler threads.\n", info.num_compl_hndlr_thr);
+    }
+
+    /** 
+     *  Associate PumpMsgsBegin with var "lapiHeaderHandler". Then inside Xfer calls,
+     *  lapiHeaderHandler could be used to indicate the callback
+     *  instead of PumpMsgsBegin --Chao Mei
+     */
+    check_lapi(LAPI_Addr_set,(lapiContext,(void *)PumpMsgsBegin,lapiHeaderHandler));
+
+    CmiNumPes() = CmiNumNodes() * CmiMyNodeSize();
+    Cmi_nodestart = CmiMyNode() * CmiMyNodeSize();
+
+    /*Cmi_argvcopy = CmiCopyArgs(argv);  Not needed?? --Chao Mei*/
+
+    Cmi_argv = argv;
+    Cmi_startfn = fn;
+    Cmi_usrsched = usched;
+
+    if (CmiGetArgFlag(argv,"++debug")) {  /*Pause so user has a chance to start and attach debugger*/
+        printf("CHARMDEBUG> Processor %d has PID %d\n",CmiMyNode(),getpid());
+        if (!CmiGetArgFlag(argv,"++debug-no-pause"))
+            sleep(10);
+    }
+
+#if CMK_NODE_QUEUE_AVAILABLE
+    CsvInitialize(CmiNodeState, NodeState);
+    CmiNodeStateInit(&CsvAccess(NodeState));
 #endif
-  for (i=0; i<10; ++i) MACHSTATE2(2, "Rankof(%d) = %d",i,CmiRankOf(i));
 
-  MACHSTATE(2, "Starting threads");
-  CmiStartThreads(argv);
-  ConverseRunPE(initret);
+#if 0
+    procState = (ProcState *)malloc((CmiMyNodeSize()) * sizeof(ProcState));
+    for (i=0; i<CmiMyNodeSize(); i++) {
+        procState[i].recvLock = CmiCreateLock();
+    }
+#endif
+
+    CmiStartThreads(argv);
+
+    ConverseRunPE(initret);
 }
 
 /***********************************************************************
@@ -1494,14 +1951,14 @@ void ConverseInit(int argc, char **argv, CmiStartFn fn, int usched, int initret)
  ************************************************************************/
 
 void CmiAbort(const char *message) {
-  CmiError(message);
-  check_lapi(LAPI_Term,(lapiContext));
-  exit(1);
+    CmiError(message);
+    check_lapi(LAPI_Term,(lapiContext));
+    exit(1);
 }
 
 static void PerrorExit(const char *msg) {
-  perror(msg);
-  check_lapi(LAPI_Term,(lapiContext));
-  exit(1);
+    perror(msg);
+    check_lapi(LAPI_Term, (lapiContext));
+    exit(1);
 }
 
index 03de8fac024fd5e37a430c33c61fecc694d1f028..c561708cd719b98e5d6cd4e7b9cb01b577979e65 100644 (file)
@@ -7,5 +7,3 @@
 #undef CMK_SHARED_VARS_POSIX_THREADS_SMP
 #define CMK_SHARED_VARS_UNAVAILABLE                        0
 #define CMK_SHARED_VARS_POSIX_THREADS_SMP                  1
-
-#define CMK_LINUX_PTHREAD_HACK                             0
index 8437e44a1c480f8170d8fbde3c979cabbee29348..e803164c23e28190485ab4df7262bd4b136d7e54 100644 (file)
@@ -17,8 +17,10 @@ CMK_LD_LIBRARY_PATH="-Wl,-rpath,$CHARMLIBSO/"
 # compiler for compiling sequential programs
 if test -n "$PGCC"
 then
+CMK_CC="cc $CMK_DEFS -DCMK_CC_PGCC=1 "
+CMK_CXX="CC  $CMK_DEFS -DCMK_CC_PGCC=1 "
 # gcc is needed for building QT
-CMK_SEQ_CC="gcc -fPIC"
+CMK_SEQ_CC="gcc -fPIC "
 CMK_SEQ_CXX="pgCC -fPIC "
 else
 CMK_SEQ_CC="gcc -fPIC"
index 13a1e6c98b57d955c0b909c32547aba691bba9ee..397c743dd43c99b60f0026020753b142b578e567 100644 (file)
@@ -8,5 +8,3 @@
 #undef CMK_SHARED_VARS_POSIX_THREADS_SMP
 #define CMK_SHARED_VARS_UNAVAILABLE                        0
 #define CMK_SHARED_VARS_POSIX_THREADS_SMP                  1
-
-#define CMK_LINUX_PTHREAD_HACK                             1
index 767aa5652dff89359618e2cf2a092b1a4a25d848..f06e2a96ab19418ecd55c03da29eea1b981674eb 100644 (file)
@@ -1,10 +1,3 @@
-/*****************************************************************************
- * $Source$
- * $Author$
- * $Date$
- * $Revision$
- *****************************************************************************/
-
 #define CMK_SMP                                                   1
 
 #undef CMK_MALLOC_USE_GNU_MALLOC
@@ -23,8 +16,6 @@
 #define CMK_SHARED_VARS_UNAVAILABLE                        0
 #define CMK_SHARED_VARS_POSIX_THREADS_SMP                  1
 
-#define CMK_LINUX_PTHREAD_HACK                             1
-
 #undef CMK_SYNCHRONIZE_ON_TCP_CLOSE
 #define CMK_SYNCHRONIZE_ON_TCP_CLOSE                       1
 
index 767aa5652dff89359618e2cf2a092b1a4a25d848..f06e2a96ab19418ecd55c03da29eea1b981674eb 100644 (file)
@@ -1,10 +1,3 @@
-/*****************************************************************************
- * $Source$
- * $Author$
- * $Date$
- * $Revision$
- *****************************************************************************/
-
 #define CMK_SMP                                                   1
 
 #undef CMK_MALLOC_USE_GNU_MALLOC
@@ -23,8 +16,6 @@
 #define CMK_SHARED_VARS_UNAVAILABLE                        0
 #define CMK_SHARED_VARS_POSIX_THREADS_SMP                  1
 
-#define CMK_LINUX_PTHREAD_HACK                             1
-
 #undef CMK_SYNCHRONIZE_ON_TCP_CLOSE
 #define CMK_SYNCHRONIZE_ON_TCP_CLOSE                       1
 
index 60745844fd8c62d02e98b9fa9d918a51c26f68bd..f49ef1f89dad345c3251480f000b1917e43f1568 100644 (file)
@@ -18,6 +18,7 @@ CMK_REAL_COMPILER=`$MPICXX -show 2>/dev/null | cut -d' ' -f1 `
 case "$CMK_REAL_COMPILER" in
 g++)   CMK_AMD64="-m64 -fPIC" ;;
 icpc)  CMK_AMD64="-m64";;
+pgCC)  CMK_AMD64="-DCMK_CC_PGCC=1" ;;
 esac
 
 CMK_CPP_CHARM="/lib/cpp -P"
index e7cf1e84bae47831d008fdd09754517d7f8cee35..d151c6de355011430d9fd2abde8603243d35ef2b 100644 (file)
@@ -1,10 +1,3 @@
-/*****************************************************************************
- * $Source$
- * $Author$
- * $Date$
- * $Revision$
- *****************************************************************************/
-
 #define CMK_SMP                                                   1
 
 #undef CMK_NODE_QUEUE_AVAILABLE
@@ -15,8 +8,6 @@
 #define CMK_SHARED_VARS_UNAVAILABLE                        0
 #define CMK_SHARED_VARS_POSIX_THREADS_SMP                  1
 
-#define CMK_LINUX_PTHREAD_HACK                             0
-
 #undef CMK_TIMER_USE_GETRUSAGE
 #undef CMK_TIMER_USE_SPECIAL
 #define CMK_TIMER_USE_GETRUSAGE                            1
index 767aa5652dff89359618e2cf2a092b1a4a25d848..f06e2a96ab19418ecd55c03da29eea1b981674eb 100644 (file)
@@ -1,10 +1,3 @@
-/*****************************************************************************
- * $Source$
- * $Author$
- * $Date$
- * $Revision$
- *****************************************************************************/
-
 #define CMK_SMP                                                   1
 
 #undef CMK_MALLOC_USE_GNU_MALLOC
@@ -23,8 +16,6 @@
 #define CMK_SHARED_VARS_UNAVAILABLE                        0
 #define CMK_SHARED_VARS_POSIX_THREADS_SMP                  1
 
-#define CMK_LINUX_PTHREAD_HACK                             1
-
 #undef CMK_SYNCHRONIZE_ON_TCP_CLOSE
 #define CMK_SYNCHRONIZE_ON_TCP_CLOSE                       1
 
index f88be75e5e2857a7b1141db5fbff721e1e8bd2e2..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1 +0,0 @@
-#define CMK_LINUX_PTHREAD_HACK                             1
index 9c7bd873c11bb426f56c084074f5aadac81e5d31..27dfaaab60e0c360e22971fea030c87672f8daf7 100644 (file)
@@ -793,7 +793,7 @@ int PumpMsgs(void)
   }
 
   
-  #if CMK_IMMEDIATE_MSG && !CMK_SMP
+#if CMK_IMMEDIATE_MSG && !CMK_SMP
   CmiHandleImmediate();
 #endif
   
@@ -1014,6 +1014,11 @@ void *CmiGetNonLocal(void)
   static int count=0;
   CmiState cs = CmiGetState();
   void *msg;
+
+#if ! CMK_SMP
+  if (CmiNumPes() == 1) return NULL;
+#endif
+
   CmiIdleLock_checkMessage(&cs->idle);
   /* although it seems that lock is not needed, I found it crashes very often
      on mpi-smp without lock */
index 88e217b2e555932d690794682334c1ca3fa85c6b..2535cc964fbaf40b2ecd2381013a675d446f7344 100644 (file)
@@ -1,10 +1,3 @@
-/*****************************************************************************
- * $Source$
- * $Author$
- * $Date$
- * $Revision$
- *****************************************************************************/
-
 #ifndef _CONV_MACH_H
 #define _CONV_MACH_H
 
@@ -76,8 +69,6 @@
 */
 #define CMK_USE_KQUEUE                                     1
 
-#define CMK_MACOSX_PTHREAD_HACK                            1
-
 #if !CMK_GCC_X86_ASM || !CMK_GCC_X86_ASM_ATOMICINCREMENT
 #define CMK_PCQUEUE_LOCK                                   1
 #endif
index 43bd6fe473141f3272a43e6e9492356cbf8f31bd..0855967be332d7659e60e25cf866744497cee32b 100644 (file)
@@ -1,10 +1,3 @@
-/*****************************************************************************
- * $Source$
- * $Author$
- * $Date$
- * $Revision$
- *****************************************************************************/
-
 #ifndef _CONV_MACH_H
 #define _CONV_MACH_H
 
@@ -77,8 +70,6 @@
 */
 #define CMK_USE_KQUEUE                                     1
 
-#define CMK_MACOSX_PTHREAD_HACK                            1
-
 #if !CMK_GCC_X86_ASM || !CMK_GCC_X86_ASM_ATOMICINCREMENT
 #define CMK_PCQUEUE_LOCK                                   1
 #endif
index c02f35b821e757bbe333cd9f097786e026b2a12f..024c04001a7ec9cb00638efd3e39ab124224d534 100644 (file)
@@ -9,8 +9,6 @@
 #define CMK_SHARED_VARS_UNAVAILABLE                        0
 #define CMK_SHARED_VARS_POSIX_THREADS_SMP                  1
 
-#define CMK_MACOSX_PTHREAD_HACK                            1
-
 #if !CMK_GCC_X86_ASM || !CMK_GCC_X86_ASM_ATOMICINCREMENT
 #define CMK_PCQUEUE_LOCK                                   1
 #endif
index 36d6b51789e492b7e4746c47d0116381433c948d..50bb8e366bf9e2ed6bd23d53d26d60918f261e3b 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef _CONV_MACH_H
 #define _CONV_MACH_H
 
+#define CMK_NETPOLL         1
+
 #define CMK_AMD64                                         1
 
 #define CMK_ASYNC_NOT_NEEDED                               0
@@ -40,8 +42,8 @@
 #define CMK_THREADS_ARE_WIN32_FIBERS                       0
 
 #define CMK_SIGNAL_NOT_NEEDED                              0
-#define CMK_SIGNAL_USE_SIGACTION                           1
-#define CMK_SIGNAL_USE_SIGACTION_WITH_RESTART              0
+#define CMK_SIGNAL_USE_SIGACTION                           0
+#define CMK_SIGNAL_USE_SIGACTION_WITH_RESTART              1
 
 #define CMK_THREADS_REQUIRE_NO_CPV                         0
 #define CMK_THREADS_COPY_STACK                             0
index 13a1e6c98b57d955c0b909c32547aba691bba9ee..397c743dd43c99b60f0026020753b142b578e567 100644 (file)
@@ -8,5 +8,3 @@
 #undef CMK_SHARED_VARS_POSIX_THREADS_SMP
 #define CMK_SHARED_VARS_UNAVAILABLE                        0
 #define CMK_SHARED_VARS_POSIX_THREADS_SMP                  1
-
-#define CMK_LINUX_PTHREAD_HACK                             1
index 2f64cbb8daaad80c5fb81e19f9cf164dd23b2ab7..953cabd39334897587392107789cdc49c42c4fb5 100644 (file)
@@ -8,6 +8,7 @@
 #ifndef _CONV_MACH_H
 #define _CONV_MACH_H
 
+#define CMK_NETPOLL         1
 
 #define CMK_ASYNC_NOT_NEEDED                               0
 #define CMK_ASYNC_USE_FIOASYNC_AND_FIOSETOWN               0
index aae592bf8d1cbc6f406a999bf8a579cc1b05f787..493d13fd27e99163dd2e865725f49e9eba9e78c2 100644 (file)
@@ -14,9 +14,23 @@ CMK_LD_LIBRARY_PATH="-Wl,-rpath,$CHARMLIBSO/"
 CMK_XIOPTS=""
 CMK_QT="i386-gcc"
 
-# fortran compiler Absoft or gnu f95
-CMK_CF77="g77 "
-CMK_F77LIBS="-lg2c "
+CMK_CF90=`which f95 2>/dev/null`
+if test -n "$CMK_CF90"
+then
+    . $CHARMINC/conv-mach-gfortran.sh
+else
+
+# fortran compiler f77 or gnu f95
+CMK_CF77=`which g77 2>/dev/null`
+if test -z "$CMK_CF77"
+then
+  CMK_CF77=`which f77 2>/dev/null`
+fi
+if test -n "$CMK_CF77"
+then
+  CMK_F77LIBS="-lg2c "
+fi
+
 CMK_CF90=`which f90 2>/dev/null`
 if test -n "$CMK_CF90"
 then
@@ -38,3 +52,5 @@ else
     CMK_F90_MODINC="-I"
   fi
 fi
+
+fi
index 31ecd3dc8108c45cf515c5792a48e40011b75d28..e904585fad46a9e049e5f8802b73863bf0b98c2e 100644 (file)
@@ -933,7 +933,7 @@ void postInitialRecvs(struct infiBufferPool *recvBufferPool,int numRecvs,int siz
 
 static inline void CommunicationServer_nolock(int toBuffer); //if buffer ==1 recvd messages are buffered but not processed
 
-static void CmiMachineExit()
+void CmiMachineExit()
 {
 #if CMK_IBVERBS_STATS  
        printf("[%d] numReg %d numUnReg %d numCurReg %d msgCount %d pktCount %d packetSize %d total Time %.6lf s processBufferedCount %d processBufferedTime %.6lf s maxTokens %d tokensLeft %d \n",_Cmi_mynode,numReg, numUnReg, numCurReg, msgCount,pktCount,packetSize,CmiTimer(),processBufferedCount,processBufferedTime,maxTokens,context->tokensLeft);
index 86a3bf5b170c0bd7102a1d4b99067093827769ee..7154ac75624b067bef0d40329595cf0c32f33c44 100644 (file)
@@ -254,7 +254,7 @@ static void CmiStartThreads(char **argv)
 #endif /* non smp */
 
 /*Add a message to this processor's receive queue, pe is a rank */
-static void CmiPushPE(int pe,void *msg)
+void CmiPushPE(int pe,void *msg)
 {
   CmiState cs = CmiGetStateN(pe);
   MACHSTATE2(3,"Pushing message into rank %d's queue %p{",pe, cs->recv);
index a0fc27985ac635f9e0aa4d1782813225108c5977..94e5c783a86e48926bc45f543282835125150a81 100644 (file)
@@ -230,7 +230,7 @@ static void CmiStartThreads(char **argv)
 /*  CmiStateInit(-1,_Cmi_mynodesize,CmiGetStateN(_Cmi_mynodesize)); */
   CmiStateInit(_Cmi_mynode+CmiNumPes(),_Cmi_mynodesize,CmiGetStateN(_Cmi_mynodesize));
   
-#if CMK_MULTICORE
+#if CMK_MULTICORE || CMK_SMP_NO_COMMTHD
   if (!Cmi_commthread)
     tocreate = _Cmi_mynodesize-1;
   else
@@ -445,7 +445,7 @@ static void CmiStartThreads(char **argv)
 #endif
 #endif
 
-#if CMK_MULTICORE
+#if CMK_MULTICORE || CMK_SMP_NO_COMMTHD
   if (!Cmi_commthread)
     tocreate = _Cmi_mynodesize-1;
   else
@@ -492,7 +492,7 @@ void  CmiNodeBarrier(void) {
 /* unfortunately this could also be called in a seemingly non smp version
    net-win32, which actually is implemented as smp with comm. thread */
 void CmiNodeAllBarrier(void) {
-#if CMK_MULTICORE
+#if CMK_MULTICORE || CMK_SMP_NO_COMMTHD
   if (!Cmi_commthread)
   CmiNodeBarrierCount(CmiMyNodeSize());
   else
index 135eb2921b3af300074dbe7d5f92cf3482c0ab8a..0848f460b0fb2ef89971ddadc6b95fcdd7aacd6c 100644 (file)
@@ -115,6 +115,7 @@ void ComlibManager::init(){
        CkpvAccess(RecvmsgHandle) =CkRegisterHandler((CmiHandler)recv_array_msg);
 
        bcast_pelist = new int [CkNumPes()];
+       _MEMCHECK(bcast_pelist);
        for(int brcount = 0; brcount < CkNumPes(); brcount++)
                bcast_pelist[brcount] = brcount;
 
@@ -861,16 +862,16 @@ void ComlibManager::printPeList(const char* note, int *count)
        for(int i=0;i<CkNumPes();i++){
                switch (count[i]){
                case 0:
-                       sprintf(buf+strlen(buf), " %d:no ", i, count[i]);
+                       sprintf(buf+strlen(buf), " %d:no ", i);
                        break;
                case 1:
-                       sprintf(buf+strlen(buf), " %d:source ", i, count[i]);
+                       sprintf(buf+strlen(buf), " %d:source ", i);
                        break;
                case 2:
-                       sprintf(buf+strlen(buf), " %d:dest ", i, count[i]);
+                       sprintf(buf+strlen(buf), " %d:dest ", i);
                        break;
                case 3:
-                       sprintf(buf+strlen(buf), " %d:both ", i, count[i]);
+                       sprintf(buf+strlen(buf), " %d:both ", i);
                        break;
                }
        }
@@ -878,6 +879,7 @@ void ComlibManager::printPeList(const char* note, int *count)
        sprintf(buf+strlen(buf), ", all source objects discovered =  %d, all destination objects discovered = %d",  count[CkNumPes()] ,  count[CkNumPes()+1] );
                
        ComlibPrintf("%s\n", buf);
+       free(buf);
 }
 
 /***************************************************************************
index 22f83582aad88c81386b505241a841884bd0cf89..759f284c2899173ad792c5b0d1e39f4a88fe1fdb 100644 (file)
@@ -9,6 +9,7 @@
 
 ComlibGlobalStats::ComlibGlobalStats() {
     statsArr = new ComlibLocalStats[CkNumPes()];
+    _MEMCHECK(statsArr);
 }
 
 void ComlibGlobalStats::updateStats(ComlibLocalStats &stats, int p) {
index 3f19838279293b281c05998d9fc96ec6c5729677..1e4fe06133af67442f987e2e7dfc73a78eaaaeb1 100644 (file)
 #include <stdlib.h>
 #include <memory.h>
 
+#include "charm.h"
+#include "middle.h"
+
 #if CMK_HAS_STRINGS_H
   #include <strings.h>            /* defines bzero */
 #else
   #define bzero(s,n)   memset(s,0,n)
 #endif
 
-#include "charm.h"
-#include "middle.h"
-
 class CMessage_CkArgMsg {
 public: static int __idx;
 };
@@ -101,9 +101,10 @@ class CkEntryOptions : public CkNoncopyable {
        typedef unsigned int prio_t; //Datatype used to represent priorities
        prio_t *prioPtr; //Points to message priority values
        prio_t prioStore; //For short priorities, stores the priority value
+       CkGroupID  depGroupID;  // group dependence
 public:
        CkEntryOptions(void): queueingtype(CK_QUEUEING_FIFO), prioBits(0), 
-                              prioPtr(NULL), prioStore(0) {}
+                              prioPtr(NULL), prioStore(0) { depGroupID.setZero(); }
 
        ~CkEntryOptions() {
                if ( prioPtr != NULL && queueingtype != CK_QUEUEING_IFIFO ) {
@@ -152,11 +153,13 @@ public:
        }
        
        inline void setQueueing(int queueingtype_) {queueingtype=queueingtype_;}
+       inline void setGroupDepID(CkGroupID &gid) { depGroupID = gid; }
 
        ///These are used by CkAllocateMarshallMsg, below:
        inline int getQueueing(void) const {return queueingtype;}
        inline int getPriorityBits(void) const {return prioBits;}
        inline const prio_t *getPriorityPtr(void) const {return prioPtr;}
+       inline const CkGroupID getGroupDepID() const { return depGroupID; }
 };
 
 #include "CkMarshall.decl.h"
@@ -418,7 +421,7 @@ class Chare {
     CkObjectMsgQ objQ;                // object message queue
 #endif
   public:
-#if CMK_FT_CHARE
+#ifndef CMK_CHARE_USE_PTR
     int chareIdx;                  // index in the chare obj table (chare_objs)
 #endif
 #ifdef _FAULT_MLOG_
@@ -726,7 +729,7 @@ class CProxy_Chare : public CProxy {
     }
 #ifndef CMK_OPTIMIZE
     inline void ckCheck(void) const  {   //Make sure this proxy has a value
-#if !CMK_FT_CHARE
+#ifdef CMK_CHARE_USE_PTR
        if (_ck_cid.objPtr==0)
                CkAbort("Error! This chare proxy has not been initialized!");
 #endif
index 84abd118902212ec2bce0450d92326f73fe52a17..ae36f867a1bbd1a87288e5ea1a5b0af4ce03a3dc 100644 (file)
@@ -186,12 +186,15 @@ typedef struct {
 typedef struct _ckGroupID{
   int idx;             /* pe(processor number) is removed from the structure */
 #ifdef __cplusplus
-  void pup(PUP::er &p) {  p|idx; }
-  int isZero(void) const { return (idx==0); }
-  void setZero(void) { idx=0; }
-  int operator==(const struct _ckGroupID& gid) const {
+  inline void pup(PUP::er &p) {  p|idx; }
+  inline int isZero(void) const { return (idx==0); }
+  inline void setZero(void) { idx=0; }
+  inline int operator==(const struct _ckGroupID& gid) const {
     return (gid.idx==idx);
   }
+  inline int operator<(const struct _ckGroupID& gid) const {
+    return (gid.idx<idx);
+  }
 #endif
 } CkGroupID;
 
index 40a5f279aab29a135e9623b28b46b30e2f4c32fc..cc93822e0475bb635145acdb1bd70c6226209545 100644 (file)
@@ -25,8 +25,9 @@ void automaticallySetMessagePriority(envelope *env); // in control point framewo
 #include "LBDatabase.h"
 #endif // CMK_LBDB_ON
 
-#if CMK_FT_CHARE
+#ifndef CMK_CHARE_USE_PTR
 CpvDeclare(CkVec<void *>, chare_objs);
+CpvDeclare(CkVec<int>, chare_types);
 CpvDeclare(CkVec<VidBlock *>, vidblocks);
 #endif
 
@@ -46,8 +47,8 @@ extern int _defaultObjectQ;
 Chare::Chare(void) {
   thishandle.onPE=CkMyPe();
   thishandle.objPtr=this;
-#if CMK_FT_CHARE
-     // for plain chare, objPtr is actually the index to chare table
+#ifndef CMK_CHARE_USE_PTR
+     // for plain chare, objPtr is actually the index to chare obj table
   if (chareIdx >= 0) thishandle.objPtr=(void*)chareIdx;
 #endif
 #ifdef _FAULT_MLOG_
@@ -82,7 +83,7 @@ void Chare::pup(PUP::er &p)
 {
   p(thishandle.onPE);
   thishandle.objPtr=(void *)this;
-#if CMK_FT_CHARE
+#ifndef CMK_CHARE_USE_PTR
   p(chareIdx);
   if (chareIdx != -1) thishandle.objPtr=(void*)chareIdx;
 #endif
@@ -551,7 +552,7 @@ void CkCreateChare(int cIdx, int eIdx, void *msg, CkChareID *pCid, int destPE)
     _MEMCHECK(pCid->objPtr);
     env->setMsgtype(NewVChareMsg);
     env->setVidPtr(pCid->objPtr);
-#if CMK_FT_CHARE
+#ifndef CMK_CHARE_USE_PTR
     CpvAccess(vidblocks).push_back((VidBlock*)pCid->objPtr);
     int idx = CpvAccess(vidblocks).size()-1;
     pCid->objPtr = (void *)idx;
@@ -569,7 +570,7 @@ void CkCreateChare(int cIdx, int eIdx, void *msg, CkChareID *pCid, int destPE)
     env->setForAnyPE(1);
   else
     env->setForAnyPE(0);
-  CldEnqueue(destPE, env, _infoIdx);
+  _CldEnqueue(destPE, env, _infoIdx);
   _TRACE_CREATION_DONE(1);
 }
 
@@ -587,7 +588,7 @@ void CkCreateLocalGroup(CkGroupID groupID, int epIdx, envelope *env)
   if(ptrq) {
     void *pending;
     while((pending=ptrq->deq())!=0)
-      CldEnqueue(CkMyPe(), pending, _infoIdx);
+      _CldEnqueue(CkMyPe(), pending, _infoIdx);
 //    delete ptrq;
       CkpvAccess(_groupTable)->find(groupID).clearPending();
   }
@@ -595,7 +596,7 @@ void CkCreateLocalGroup(CkGroupID groupID, int epIdx, envelope *env)
 
   CkpvAccess(_currentGroup) = groupID;
   CkpvAccess(_currentGroupRednMgr) = env->getRednMgr();
-#if CMK_FT_CHARE
+#ifndef CMK_CHARE_USE_PTR
   ((Chare *)obj)->chareIdx = -1;
 #endif
   _invokeEntryNoTrace(epIdx,env,obj); /* can't trace groups: would cause nested begin's */
@@ -618,7 +619,7 @@ void CkCreateLocalNodeGroup(CkGroupID groupID, int epIdx, envelope *env)
 // User may call CkLocalNodeBranch() inside the nodegroup constructor
 //  store nodegroup into _currentNodeGroupObj
   CkpvAccess(_currentNodeGroupObj) = obj;
-#if CMK_FT_CHARE
+#ifndef CMK_CHARE_USE_PTR
   ((Chare *)obj)->chareIdx = -1;
 #endif
   _invokeEntryNoTrace(epIdx,env,obj);
@@ -634,7 +635,7 @@ void CkCreateLocalNodeGroup(CkGroupID groupID, int epIdx, envelope *env)
   if(ptrq) {
     void *pending;
     while((pending=ptrq->deq())!=0)
-      CldNodeEnqueue(CkMyNode(), pending, _infoIdx);
+      _CldNodeEnqueue(CkMyNode(), pending, _infoIdx);
 //    delete ptrq;
       CksvAccess(_nodeGroupTable)->find(groupID).clearPending();
   }
@@ -684,7 +685,7 @@ void _createNodeGroup(CkGroupID groupID, envelope *env)
     CkPackMessage(&env);
     CmiSetHandler(env, _bocHandlerIdx);
     _numInitMsgs++;
-    CksvAccess(_numInitNodeMsgs)++;
+    if (CkpvAccess(_charmEpoch)==0) CksvAccess(_numInitNodeMsgs)++;
     CmiSyncNodeBroadcast(env->getTotalsize(), (char *)env);
     CpvAccess(_qd)->create(CkNumNodes()-1);
     CkUnpackMessage(&env);
@@ -774,11 +775,12 @@ static inline void *_allocNewChare(envelope *env, int &idx)
 {
   int chareIdx = _entryTable[env->getEpIdx()]->chareIdx;
   void *tmp=malloc(_chareTable[chareIdx]->size);
-#if CMK_FT_CHARE
+  _MEMCHECK(tmp);
+#ifndef CMK_CHARE_USE_PTR
   CpvAccess(chare_objs).push_back(tmp);
+  CpvAccess(chare_types).push_back(chareIdx);
   idx = CpvAccess(chare_objs).size()-1;
 #endif
-  _MEMCHECK(tmp);
   setMemoryTypeChare(tmp);
   return tmp;
 }
@@ -787,12 +789,18 @@ static void _processNewChareMsg(CkCoreState *ck,envelope *env)
 {
   int idx;
   register void *obj = _allocNewChare(env, idx);
-#if CMK_FT_CHARE
+#ifndef CMK_CHARE_USE_PTR
   ((Chare *)obj)->chareIdx = idx;
 #endif
   _invokeEntry(env->getEpIdx(),env,obj);
 }
 
+void CkCreateLocalChare(int epIdx, envelope *env)
+{
+  env->setEpIdx(epIdx);
+  _processNewChareMsg(NULL, env);
+}
+
 static void _processNewVChareMsg(CkCoreState *ck,envelope *env)
 {
   int idx;
@@ -800,7 +808,7 @@ static void _processNewVChareMsg(CkCoreState *ck,envelope *env)
   register CkChareID *pCid = (CkChareID *)
       _allocMsg(FillVidMsg, sizeof(CkChareID));
   pCid->onPE = CkMyPe();
-#if CMK_FT_CHARE
+#ifndef CMK_CHARE_USE_PTR
   pCid->objPtr = (void*)idx;
 #else
   pCid->objPtr = obj;
@@ -813,7 +821,7 @@ static void _processNewVChareMsg(CkCoreState *ck,envelope *env)
   CmiSetHandler(ret, _charmHandlerIdx);
   CmiSyncSendAndFree(srcPe, ret->getTotalsize(), (char *)ret);
   CpvAccess(_qd)->create();
-#if CMK_FT_CHARE
+#ifndef CMK_CHARE_USE_PTR
   ((Chare *)obj)->chareIdx = idx;
 #endif
   _invokeEntry(env->getEpIdx(),env,obj);
@@ -826,12 +834,12 @@ static inline void _processForPlainChareMsg(CkCoreState *ck,envelope *env)
   register int epIdx = env->getEpIdx();
   register int mainIdx = _chareTable[_entryTable[epIdx]->chareIdx]->mainChareType();
   register void *obj;
-  if (mainIdx != -1)  {
+  if (mainIdx != -1)  {           // mainchare
     CmiAssert(CkMyPe()==0);
     obj = _mainTable[mainIdx]->getObj();
   }
   else {
-#if CMK_FT_CHARE
+#ifndef CMK_CHARE_USE_PTR
     if (_chareTable[_entryTable[epIdx]->chareIdx]->chareType == TypeChare)
       obj = CpvAccess(chare_objs)[(CmiIntPtr)env->getObjPtr()];
     else
@@ -852,7 +860,7 @@ static inline void _processForChareMsg(CkCoreState *ck,envelope *env)
 
 static inline void _processFillVidMsg(CkCoreState *ck,envelope *env)
 {
-#if CMK_FT_CHARE
+#ifndef CMK_CHARE_USE_PTR
   register VidBlock *vptr = CpvAccess(vidblocks)[(CmiIntPtr)env->getVidPtr()];
 #else
   register VidBlock *vptr = (VidBlock *) env->getVidPtr();
@@ -866,7 +874,7 @@ static inline void _processFillVidMsg(CkCoreState *ck,envelope *env)
 
 static inline void _processForVidMsg(CkCoreState *ck,envelope *env)
 {
-#if CMK_FT_CHARE
+#ifndef CMK_CHARE_USE_PTR
   register VidBlock *vptr = CpvAccess(vidblocks)[(CmiIntPtr)env->getVidPtr()];
 #else
   VidBlock *vptr = (VidBlock *) env->getVidPtr();
@@ -879,11 +887,15 @@ static inline void _processForVidMsg(CkCoreState *ck,envelope *env)
 /************** Receive: Groups ****************/
 
 /**
- This message is sent to this groupID--prepare to
- handle this message by looking up the group,
- and possibly stashing the message.
+ Return a pointer to the local BOC of "groupID".
+ The message "env" passed in has some known dependency on this groupID
+ (either it is to be delivered to this BOC, or it depends on this BOC being there).
+ Therefore, if the return value is NULL, this function buffers the massage so that
+ it will be re-sent (by CkCreateLocalBranch) when this groupID is eventually constructed.
+ The message passed in must have its handlers correctly set so that it can be
+ scheduled again.
 */
-IrrGroup *_lookupGroup(CkCoreState *ck,envelope *env,const CkGroupID &groupID)
+static inline IrrGroup *_lookupGroupAndBufferIfNotThere(CkCoreState *ck,envelope *env,const CkGroupID &groupID)
 {
 
        CmiImmediateLock(CkpvAccess(_groupTableImmLock));
@@ -920,7 +932,7 @@ static inline void _deliverForBocMsg(CkCoreState *ck,int epIdx,envelope *env,Irr
 static inline void _processForBocMsg(CkCoreState *ck,envelope *env)
 {
   register CkGroupID groupID =  env->getGroupNum();
-  register IrrGroup *obj = _lookupGroup(ck,env,env->getGroupNum());
+  register IrrGroup *obj = _lookupGroupAndBufferIfNotThere(ck,env,env->getGroupNum());
   if(obj) {
     _deliverForBocMsg(ck,env->getEpIdx(),env,obj);
   }
@@ -972,6 +984,13 @@ void _processBocInitMsg(CkCoreState *ck,envelope *env)
 {
   register CkGroupID groupID = env->getGroupNum();
   register int epIdx = env->getEpIdx();
+  if (!env->getGroupDep().isZero()) {      // dependence
+    CkGroupID dep = env->getGroupDep();
+    IrrGroup *obj = _lookupGroupAndBufferIfNotThere(ck,env,dep);
+    if (obj == NULL) return;
+  }
+  else
+    ck->process();
   CkCreateLocalGroup(groupID, epIdx, env);
 }
 
@@ -985,14 +1004,14 @@ void _processNodeBocInitMsg(CkCoreState *ck,envelope *env)
 /************** Receive: Arrays *************/
 
 static void _processArrayEltInitMsg(CkCoreState *ck,envelope *env) {
-  CkArray *mgr=(CkArray *)_lookupGroup(ck,env,env->getsetArrayMgr());
+  CkArray *mgr=(CkArray *)_lookupGroupAndBufferIfNotThere(ck,env,env->getsetArrayMgr());
   if (mgr) {
     _SET_USED(env, 0);
     mgr->insertElement((CkMessage *)EnvToUsr(env));
   }
 }
 static void _processArrayEltMsg(CkCoreState *ck,envelope *env) {
-  CkArray *mgr=(CkArray *)_lookupGroup(ck,env,env->getsetArrayMgr());
+  CkArray *mgr=(CkArray *)_lookupGroupAndBufferIfNotThere(ck,env,env->getsetArrayMgr());
   if (mgr) {
     _SET_USED(env, 0);
     mgr->getLocMgr()->deliverInline((CkMessage *)EnvToUsr(env));
@@ -1042,7 +1061,9 @@ void _processHandler(void *converseMsg,CkCoreState *ck)
 // Group support
     case BocInitMsg :
       TELLMSGTYPE(CkPrintf("proc[%d]: _processHandler with msg type: BocInitMsg\n", CkMyPe());)
-      ck->process(); if(env->isPacked()) CkUnpackMessage(&env);
+      // QD processing moved inside _processBocInitMsg because it is conditional
+      //ck->process(); 
+      if(env->isPacked()) CkUnpackMessage(&env);
       _processBocInitMsg(ck,env);
       break;
     case NodeBocInitMsg :
@@ -1172,7 +1193,7 @@ void CkUnpackMessage(envelope **pEnv)
 // the PE can never be CLD_ANYWHERE; wasting _infoFn calls.
 // Thus these accellerated versions of the Cld calls.
 
-int index_objectQHandler;
+static int index_objectQHandler;
 int index_tokenHandler;
 static int index_skipCldHandler;
 
@@ -1202,6 +1223,12 @@ static void _skipCldHandler(void *converseMsg)
 // Made non-static to be used by ckmessagelogging
 void _skipCldEnqueue(int pe,envelope *env, int infoFn)
 {
+#if CMK_REPLAYSYSTEM
+  if (replaySystem) {
+    CmiFree(env);
+    return;
+  }
+#endif
   if(pe == CkMyPe() ){
     if(!CmiNodeAlive(CkMyPe())){
        printf("[%d] Invalid processor sending itself a message \n",CkMyPe());
@@ -1257,12 +1284,18 @@ void _skipCldEnqueue(int pe,envelope *env, int infoFn)
 }
 
 #if CMK_BLUEGENE_CHARM
-#   define  _skipCldEnqueue   CldEnqueue
+#   define  _skipCldEnqueue   _CldEnqueue
 #endif
 
 // by pass Charm++ priority queue, send as Converse message
 static void _noCldEnqueueMulti(int npes, int *pes, envelope *env)
 {
+#if CMK_REPLAYSYSTEM
+  if (replaySystem) {
+    CmiFree(env);
+    return;
+  }
+#endif
   CkPackMessage(&env);
   int len=env->getTotalsize();
   CmiSyncListSendAndFree(npes, pes, len, (char *)env);
@@ -1275,6 +1308,12 @@ static void _noCldEnqueue(int pe, envelope *env)
     CmiHandleMessage(env);
   } else
 */
+#if CMK_REPLAYSYSTEM
+  if (replaySystem) {
+    CmiFree(env);
+    return;
+  }
+#endif
   CkPackMessage(&env);
   int len=env->getTotalsize();
   if (pe==CLD_BROADCAST) { CmiSyncBroadcastAndFree(len, (char *)env); }
@@ -1291,6 +1330,12 @@ void _noCldNodeEnqueue(int node, envelope *env)
     CmiHandleMessage(env);
   } else {
 */
+#if CMK_REPLAYSYSTEM
+  if (replaySystem) {
+    CmiFree(env);
+    return;
+  }
+#endif
   CkPackMessage(&env);
   int len=env->getTotalsize();
   if (node==CLD_BROADCAST) { 
@@ -1340,7 +1385,7 @@ static inline int _prepareMsg(int eIdx,void *msg,const CkChareID *pCid)
   if (pCid->onPE < 0) { //Virtual chare ID (VID)
     register int pe = -(pCid->onPE+1);
     if(pe==CkMyPe()) {
-#if CMK_FT_CHARE
+#ifndef CMK_CHARE_USE_PTR
       VidBlock *vblk = CpvAccess(vidblocks)[(CmiIntPtr)pCid->objPtr];
 #else
       VidBlock *vblk = (VidBlock *) pCid->objPtr;
@@ -1395,15 +1440,19 @@ void CkSendMsg(int entryIdx, void *msg,const CkChareID *pCid, int opts)
 #endif
   register envelope *env = UsrToEnv(msg);
   int destPE=_prepareMsg(entryIdx,msg,pCid);
+  // Before it traced the creation only if destPE!=-1 (i.e it did not when the
+  // VidBlock was not yet filled). The problem is that the creation was never
+  // traced later when the VidBlock was filled. One solution is to trace the
+  // creation here, the other to trace it in VidBlock->msgDeliver().
+  _TRACE_CREATION_1(env);
   if (destPE!=-1) {
-    _TRACE_CREATION_1(env);
     CpvAccess(_qd)->create();
     if (opts & CK_MSG_SKIP_OR_IMM)
       _noCldEnqueue(destPE, env);
     else
-      CldEnqueue(destPE, env, _infoIdx);
-    _TRACE_CREATION_DONE(1);
+      _CldEnqueue(destPE, env, _infoIdx);
   }
+  _TRACE_CREATION_DONE(1);
 }
 
 extern "C"
@@ -1426,19 +1475,24 @@ void CkSendMsgInline(int entryIndex, void *msg, const CkChareID *pCid, int opts)
   }
   else {
     //No way to inline a cross-processor message:
-    CkSendMsg(entryIndex,msg,pCid,opts&!CK_MSG_INLINE);
+    CkSendMsg(entryIndex, msg, pCid, opts & (~CK_MSG_INLINE));
   }
 }
 
 static inline envelope *_prepareMsgBranch(int eIdx,void *msg,CkGroupID gID,int type)
 {
   register envelope *env = UsrToEnv(msg);
+  CkNodeGroupID nodeRedMgr;
   _CHECK_USED(env);
   _SET_USED(env, 1);
   env->setMsgtype(type);
   env->setEpIdx(eIdx);
   env->setGroupNum(gID);
   env->setSrcPe(CkMyPe());
+#ifndef CMK_OPTIMIZE
+  nodeRedMgr.setZero();
+  env->setRednMgr(nodeRedMgr);
+#endif
 #ifdef USE_CRITICAL_PATH_HEADER_ARRAY
   criticalPath_send(env);
   automaticallySetMessagePriority(env);
@@ -1484,7 +1538,7 @@ static inline void _sendMsgBranchMulti(int eIdx, void *msg, CkGroupID gID,
 {
   register envelope *env = _prepareMsgBranch(eIdx,msg,gID,ForBocMsg);
   _TRACE_CREATION_MULTICAST(env, npes, pes);
-  CldEnqueueMulti(npes, pes, env, _infoIdx);
+  _CldEnqueueMulti(npes, pes, env, _infoIdx);
   _TRACE_CREATION_DONE(1);     // since it only creates one creation event.
 }
 
@@ -1534,7 +1588,7 @@ void CkSendMsgBranchInline(int eIdx, void *msg, int destPE, CkGroupID gID, int o
     }
   }
   //Can't inline-- send the usual way, clear CK_MSG_INLINE
-  CkSendMsgBranch(eIdx,msg,destPE,gID,opts&!CK_MSG_INLINE);
+  CkSendMsgBranch(eIdx, msg, destPE, gID, opts & (~CK_MSG_INLINE));
 }
 
 extern "C"
@@ -1607,7 +1661,7 @@ static inline void _sendMsgNodeBranch(int eIdx, void *msg, CkGroupID gID,
     }
   }
   else
-    CldNodeEnqueue(node, env, _infoIdx);
+    _CldNodeEnqueue(node, env, _infoIdx);
   _TRACE_CREATION_DONE(1);
 #endif
 }
@@ -1618,7 +1672,7 @@ static inline void _sendMsgNodeBranchMulti(int eIdx, void *msg, CkGroupID gID,
   register envelope *env = _prepareMsgBranch(eIdx,msg,gID,ForNodeBocMsg);
   _TRACE_CREATION_N(env, npes);
   for (int i=0; i<npes; i++) {
-    CldNodeEnqueue(nodes[i], env, _infoIdx);
+    _CldNodeEnqueue(nodes[i], env, _infoIdx);
   }
   _TRACE_CREATION_DONE(1);  // since it only creates one creation event.
 }
@@ -1669,7 +1723,7 @@ void CkSendMsgNodeBranchInline(int eIdx, void *msg, int node, CkGroupID gID, int
     }
   }
   //Can't inline-- send the usual way
-  CkSendMsgNodeBranch(eIdx,msg,node,gID,opts&!CK_MSG_INLINE);
+  CkSendMsgNodeBranch(eIdx, msg, node, gID, opts & ~(CK_MSG_INLINE));
 }
 
 extern "C"
@@ -1765,7 +1819,7 @@ void CkArrayManagerInsert(int pe,void *msg,CkGroupID aID) {
   register envelope *env = UsrToEnv(msg);
   env->getsetArrayMgr()=aID;
   _prepareOutgoingArrayMsg(env,ArrayEltInitMsg);
-  CldEnqueue(pe, env, _infoIdx);
+  _CldEnqueue(pe, env, _infoIdx);
 }
 
 extern "C"
@@ -1832,24 +1886,36 @@ printf("[%d] DELETE!\n", CkMyPe());
 //------------------- Message Watcher (record/replay) ----------------
 
 #include "crc32.h"
+
+CkpvDeclare(int, envelopeEventID);
+
 CkMessageWatcher::~CkMessageWatcher() {}
 
 class CkMessageRecorder : public CkMessageWatcher {
 public:
   CkMessageRecorder(FILE *f_) { f=f_; }
   ~CkMessageRecorder() {
-    fprintf(f,"-1 -1 -1");
+    fprintf(f,"-1 -1 -1 ");
     fclose(f);
   }
 
 private:
   virtual CmiBool process(envelope *env,CkCoreState *ck) {
     if (env->getEvent()) {
-      unsigned int crc = crc32_initial(((unsigned char*)env)+CmiMsgHeaderSizeBytes, env->getTotalsize()-CmiMsgHeaderSizeBytes);
-      fprintf(f,"%d %d %d %d %x\n",env->getSrcPe(),env->getTotalsize(),env->getEvent(), env->getMsgtype()==NodeBocInitMsg || env->getMsgtype()==ForNodeBocMsg, crc);
+      bool wasPacked = env->isPacked();
+      if (!wasPacked) CkPackMessage(&env);
+      //unsigned int crc = crc32_initial(((unsigned char*)env)+CmiMsgHeaderSizeBytes, env->getTotalsize()-CmiMsgHeaderSizeBytes);
+      unsigned int crc1 = crc32_initial(((unsigned char*)env)+CmiMsgHeaderSizeBytes, sizeof(*env)-CmiMsgHeaderSizeBytes);
+      unsigned int crc2 = crc32_initial(((unsigned char*)env)+sizeof(*env), env->getTotalsize()-sizeof(*env));
+      fprintf(f,"%d %d %d %hhd %x %x\n",env->getSrcPe(),env->getTotalsize(),env->getEvent(), env->getMsgtype()==NodeBocInitMsg || env->getMsgtype()==ForNodeBocMsg, crc1, crc2);
+      if (!wasPacked) CkUnpackMessage(&env);
     }
     return CmiTrue;
   }
+  virtual int process(CthThreadToken *token,CkCoreState *ck) {
+    fprintf(f, "%d %d %d\n",CkMyPe(), -2, token->serialNo);
+    return 1;
+  }
 };
 
 class CkMessageDetailRecorder : public CkMessageWatcher {
@@ -1865,9 +1931,12 @@ public:
   ~CkMessageDetailRecorder() {fclose(f);}
 private:
   virtual CmiBool process(envelope *env, CkCoreState *ck) {
+    bool wasPacked = env->isPacked();
+    if (!wasPacked) CkPackMessage(&env);
     CmiUInt4 size = env->getTotalsize();
     fwrite(&size, 4, 1, f);
     fwrite(env, env->getTotalsize(), 1, f);
+    if (!wasPacked) CkUnpackMessage(&env);
     return CmiTrue;
   }
 };
@@ -1875,64 +1944,118 @@ private:
 //#define REPLAYDEBUG(args) ckout<<"["<<CkMyPe()<<"] "<< args <<endl;
 #define REPLAYDEBUG(args) /* empty */
 
+extern "C" void CkMessageReplayQuiescence(void *rep, double time);
+extern "C" void CkMessageDetailReplayDone(void *rep, double time);
+
 class CkMessageReplay : public CkMessageWatcher {
+  int counter;
        int nextPE, nextSize, nextEvent, nexttype; //Properties of next message we need:
-       unsigned int crc;
+       unsigned int crc1, crc2;
        /// Read the next message we need from the file:
        void getNext(void) {
-               if (5!=fscanf(f,"%d%d%d%d%x", &nextPE,&nextSize,&nextEvent,&nexttype,&crc)) {
-                       // CkAbort("CkMessageReplay> Syntax error reading replay file");
+         if (3!=fscanf(f,"%d%d%d", &nextPE,&nextSize,&nextEvent)) CkAbort("CkMessageReplay> Syntax error reading replay file");
+         if (nextSize > 0) {
+           // We are reading a regular message
+           if (3!=fscanf(f,"%d%x%x", &nexttype,&crc1,&crc2)) {
+             CkAbort("CkMessageReplay> Syntax error reading replay file");
+           }
+         } else if (nextSize == -2) {
+           // We are reading a special message (right now only thread awaken)
+           // Nothing to do since we have already read all info
+         } else if (nextPE!=-1 || nextSize!=-1 || nextEvent!=-1) {
+           CkPrintf("Read from file item %d %d %d\n",nextPE,nextSize,nextEvent);
+           CkAbort("CkMessageReplay> Unrecognized input");
+         }
+           /*
+               if (6!=fscanf(f,"%d%d%d%d%x%x", &nextPE,&nextSize,&nextEvent,&nexttype,&crc1,&crc2)) {
+                       CkAbort("CkMessageReplay> Syntax error reading replay file");
                        nextPE=nextSize=nextEvent=nexttype=-1; //No destructor->record file just ends in the middle!
                }
+               */
+               counter++;
        }
        /// If this is the next message we need, advance and return CmiTrue.
        CmiBool isNext(envelope *env) {
                if (nextPE!=env->getSrcPe()) return CmiFalse;
                if (nextEvent!=env->getEvent()) return CmiFalse;
+               if (nextSize<0) return CmiFalse; // not waiting for a regular message
                if (nextSize!=env->getTotalsize())
                 {
                        CkPrintf("CkMessageReplay> Message size changed during replay org: [%d %d %d] got: [%d %d %d]\n", nextPE, nextEvent, nextSize, env->getSrcPe(), env->getEvent(), env->getTotalsize());
                         return CmiFalse;
                 }
-               unsigned int crcnew = crc32_initial(((unsigned char*)env)+CmiMsgHeaderSizeBytes, env->getTotalsize()-CmiMsgHeaderSizeBytes);
-               if (crcnew != crc) {
-                 CkPrintf("CkMessageReplay> Message CRC changed during replay org: [0x%x] got: [0x%x]\n",crc,crcnew);
+               bool wasPacked = env->isPacked();
+               if (!wasPacked) CkPackMessage(&env);
+               //unsigned int crcnew = crc32_initial(((unsigned char*)env)+CmiMsgHeaderSizeBytes, env->getTotalsize()-CmiMsgHeaderSizeBytes);
+               unsigned int crcnew1 = crc32_initial(((unsigned char*)env)+CmiMsgHeaderSizeBytes, sizeof(*env)-CmiMsgHeaderSizeBytes);
+               unsigned int crcnew2 = crc32_initial(((unsigned char*)env)+sizeof(*env), env->getTotalsize()-sizeof(*env));
+               if (crcnew1 != crc1) {
+                 CkPrintf("CkMessageReplay %d> Envelope CRC changed during replay org: [0x%x] got: [0x%x]\n",CkMyPe(),crc1,crcnew1);
                }
+        if (crcnew2 != crc2) {
+          CkPrintf("CkMessageReplay %d> Message CRC changed during replay org: [0x%x] got: [0x%x]\n",CkMyPe(),crc2,crcnew2);
+        }
+        if (!wasPacked) CkUnpackMessage(&env);
                return CmiTrue;
        }
+       CmiBool isNext(CthThreadToken *token) {
+         if (nextPE==CkMyPe() && nextSize==-2 && nextEvent==token->serialNo) return CmiTrue;
+         return CmiFalse;
+       }
 
        /// This is a (short) list of messages we aren't yet ready for:
-       CkQ<envelope *> delayed;
+       CkQ<envelope *> delayedMessages;
+       /// This is a (short) list of tokens (i.e messages that awake user-threads) we aren't yet ready for:
+       CkQ<CthThreadToken *> delayedTokens;
 
        /// Try to flush out any delayed messages
        void flush(void) {
-               int len=delayed.length();
+         if (nextSize>0) {
+               int len=delayedMessages.length();
                for (int i=0;i<len;i++) {
-                       envelope *env=delayed.deq();
+                       envelope *env=delayedMessages.deq();
                        if (isNext(env)) { /* this is the next message: process it */
                                REPLAYDEBUG("Dequeueing message: "<<env->getSrcPe()<<" "<<env->getTotalsize()<<" "<<env->getEvent())
-                               CmiSyncSendAndFree(CkMyPe(),env->getTotalsize(),(char *)env);
+                               //CmiSyncSendAndFree(CkMyPe(),env->getTotalsize(),(char *)env);
+                               CsdEnqueueLifo((void*)env); // Make it at the beginning since this is the one we want next
                                return;
                        }
                        else /* Not ready yet-- put it back in the
                                queue */
                          {
                                REPLAYDEBUG("requeueing delayed message: "<<env->getSrcPe()<<" "<<env->getTotalsize()<<" "<<env->getEvent())
-                               delayed.enq(env);
+                               delayedMessages.enq(env);
                          }
                }
+         } else if (nextSize==-2) {
+           int len=delayedTokens.length();
+           for (int i=0;i<len;++i) {
+             CthThreadToken *token=delayedTokens.deq();
+             if (isNext(token)) {
+            REPLAYDEBUG("Dequeueing token: "<<token->serialNo)
+               CsdEnqueueLifo((void*)token);
+               return;
+             } else {
+            REPLAYDEBUG("requeueing delayed token: "<<token->serialNo)
+               delayedTokens.enq(token);
+             }
+           }
+         }
        }
 
 public:
        CkMessageReplay(FILE *f_) {
+         counter=0;
          f=f_;
          getNext();
          REPLAYDEBUG("Constructing ckMessageReplay: "<< nextPE <<" "<< nextSize <<" "<<nextEvent);
+         if (CkMyPe()==0) CmiStartQD(CkMessageReplayQuiescence, this);
        }
        ~CkMessageReplay() {fclose(f);}
 
 private:
        virtual CmiBool process(envelope *env,CkCoreState *ck) {
+         //CkAssert(*(int*)env == 0x34567890);
          REPLAYDEBUG("ProcessMessage message: "<<env->getSrcPe()<<" "<<env->getTotalsize()<<" "<<env->getEvent() <<" " <<env->getMsgtype() <<" " <<env->getMsgIdx());
                 if (env->getEvent() == 0) return CmiTrue;
                if (isNext(env)) { /* This is the message we were expecting */
@@ -1955,13 +2078,108 @@ private:
                else /*!isNext(env) */ {
                        REPLAYDEBUG("Queueing message: "<<env->getSrcPe()<<" "<<env->getTotalsize()<<" "<<env->getEvent()
                                <<" because we wanted "<<nextPE<<" "<<nextSize<<" "<<nextEvent)
-                       delayed.enq(env);
+                       delayedMessages.enq(env);
                         flush();
                        return CmiFalse;
                }
        }
+       virtual int process(CthThreadToken *token, CkCoreState *ck) {
+      REPLAYDEBUG("ProcessToken token: "<<token->serialNo);
+         if (isNext(token)) {
+        REPLAYDEBUG("Executing token: "<<token->serialNo)
+           getNext();
+           flush();
+           return 1;
+         } else {
+        REPLAYDEBUG("Queueing token: "<<token->serialNo
+            <<" because we wanted "<<nextPE<<" "<<nextSize<<" "<<nextEvent)
+           delayedTokens.enq(token);
+           return 0;
+         }
+       }
+};
+
+class CkMessageDetailReplay : public CkMessageWatcher {
+  void *getNext() {
+    CmiUInt4 size; size_t nread;
+    if ((nread=fread(&size, 4, 1, f)) < 1) {
+      if (feof(f)) return NULL;
+      CkPrintf("Broken record file (metadata) got %d\n",nread);
+      CkAbort("");
+    }
+    void *env = CmiAlloc(size);
+    long tell = ftell(f);
+    if ((nread=fread(env, size, 1, f)) < 1) {
+      CkPrintf("Broken record file (data) expecting %d, got %d (file position %lld)\n",size,nread,tell);
+      CkAbort("");
+    }
+    //*(int*)env = 0x34567890; // set first integer as magic
+    return env;
+  }
+public:
+  CkMessageDetailReplay(FILE *f_) {
+    f=f_;
+    /* This must match what CkMessageDetailRecorder did */
+    CmiUInt2 little;
+    fread(&little, 2, 1, f);
+    if (little != sizeof(void*)) {
+      CkAbort("Replaying on a different architecture from which recording was done!");
+    }
+
+    CsdEnqueue(getNext());
+
+    CcdCallOnCondition(CcdPROCESSOR_STILL_IDLE, (CcdVoidFn)CkMessageDetailReplayDone, (void*)this);
+  }
+  virtual CmiBool process(envelope *env,CkCoreState *ck) {
+    void *msg = getNext();
+    if (msg != NULL) CsdEnqueue(msg);
+    return CmiTrue;
+  }
 };
 
+extern "C" void CkMessageReplayQuiescence(void *rep, double time) {
+  CkPrintf("[%d] Quiescence detected\n",CkMyPe());
+  CkMessageReplay *replay = (CkMessageReplay*)rep;
+  //CmiStartQD(CkMessageReplayQuiescence, replay);
+}
+
+extern "C" void CkMessageDetailReplayDone(void *rep, double time) {
+  CkPrintf("[%d] Detailed replay finished. Exiting.\n",CkMyPe());
+  ConverseExit();
+}
+
+static int CpdExecuteThreadResume(CthThreadToken *token) {
+  CkCoreState *ck = CkpvAccess(_coreState);
+  if (ck->watcher!=NULL) {
+    return ck->watcher->processThread(token,ck);
+  }
+  return 1;
+}
+
+CpvCExtern(int, CthResumeNormalThreadIdx);
+extern "C" void CthResumeNormalThreadDebug(CthThreadToken* token)
+{
+  CthThread t = token->thread;
+
+  if(t == NULL){
+    free(token);
+    return;
+  }
+#ifndef CMK_OPTIMIZE
+#if ! CMK_TRACE_IN_CHARM
+  if(CpvAccess(traceOn))
+    CthTraceResume(t);
+/*    if(CpvAccess(_traceCoreOn)) 
+            resumeTraceCore();*/
+#endif
+#endif
+  
+  /* For Record/Replay debugging: need to notify the upper layer that we are resuming a thread */
+  if (CpdExecuteThreadResume(token)) {
+    CthResume(t);
+  }
+}
+
 #include "trace-common.h" /* For traceRoot and traceRootBaseLength */
 
 static FILE *openReplayFile(const char *prefix, const char *suffix, const char *permissions) {
@@ -1982,23 +2200,42 @@ static FILE *openReplayFile(const char *prefix, const char *suffix, const char *
 
 #include "ckliststring.h"
 void CkMessageWatcherInit(char **argv,CkCoreState *ck) {
+    CmiBool forceReplay = CmiFalse;
     char *procs = NULL;
-       REPLAYDEBUG("CkMessageWaterInit ");
+    replaySystem = 0;
+       REPLAYDEBUG("CkMessageWatcherInit ");
     if (CmiGetArgStringDesc(argv,"+record-detail",&procs,"Record full message content for the specified processors")) {
         CkListString list(procs);
         if (list.includes(CkMyPe())) {
+          CpdSetInitializeMemory(1);
           ck->addWatcher(new CkMessageDetailRecorder(openReplayFile("ckreplay_",".detail","w")));
         }
     }
        if (CmiGetArgFlagDesc(argv,"+record","Record message processing order")) {
+           CpdSetInitializeMemory(1);
+        CmiNumberHandler(CpvAccess(CthResumeNormalThreadIdx), (CmiHandler)CthResumeNormalThreadDebug);
                ck->addWatcher(new CkMessageRecorder(openReplayFile("ckreplay_",".log","w")));
        }
-       if (CmiGetArgFlagDesc(argv,"+replay","Re-play recorded message stream")) {
-               ck->addWatcher(new CkMessageReplay(openReplayFile("ckreplay_",".log","r")));
-       }
-       if (CmiGetArgStringDesc(argv,"+replay-detail",&procs,"Re-play the specified processors from recorded message content")) {
-         /*Nothing yet*/
+       if (CmiGetArgStringDesc(argv,"+replay-detail",&procs,"Replay the specified processors from recorded message content")) {
+           forceReplay = CmiTrue;
+           CpdSetInitializeMemory(1);
+           // Set the parameters of the processor
+#if CMK_SHARED_VARS_UNAVAILABLE
+           _Cmi_mype = atoi(procs);
+           while (procs[0]!='/') procs++;
+           procs++;
+           _Cmi_numpes = atoi(procs);
+#else
+           CkAbort("+replay-detail available only for non-SMP build");
+#endif
+           replaySystem = 1;
+           ck->addWatcher(new CkMessageDetailReplay(openReplayFile("ckreplay_",".detail","r")));
        }
+    if (CmiGetArgFlagDesc(argv,"+replay","Replay recorded message stream") || forceReplay) {
+        CpdSetInitializeMemory(1);
+        CmiNumberHandler(CpvAccess(CthResumeNormalThreadIdx), (CmiHandler)CthResumeNormalThreadDebug);
+        ck->addWatcher(new CkMessageReplay(openReplayFile("ckreplay_",".log","r")));
+    }
 }
 
 extern "C"
index f33cf43973180ba597dffe0993a4d550254867f4..39d92fba181e525d5e5fade8642d5ada6b75a617 100644 (file)
 #define _CHECK_VALID(p, msg) do { } while(0)
 #endif
 
+// Flag that tells the system if we are replaying using Record/Replay
+extern int replaySystem;
+
+#if CMK_REPLAYSYSTEM
+inline void _CldEnqueue(int pe, void *msg, int infofn) {
+  if (replaySystem) {
+    CmiFree(msg);
+    return;
+  }
+  CldEnqueue(pe, msg, infofn);
+}
+inline void _CldEnqueueMulti(int npes, int *pes, void *msg, int infofn) {
+  if (replaySystem) {
+    CmiFree(msg);
+    return;
+  }
+  CldEnqueueMulti(npes, pes, msg, infofn);
+}
+inline void _CldNodeEnqueue(int node, void *msg, int infofn) {
+  if (replaySystem) {
+    CmiFree(msg);
+    return;
+  }
+  CldNodeEnqueue(node, msg, infofn);
+}
+#else
+#define _CldEnqueue       CldEnqueue
+#define _CldEnqueueMulti  CldEnqueueMulti
+#define _CldNodeEnqueue   CldNodeEnqueue
+#endif
+
 /// A set of "Virtual ChareID"'s
 class VidBlock {
     enum VidState {FILLED, UNFILLED};
@@ -32,10 +63,11 @@ class VidBlock {
     PtrQ *msgQ;
     CkChareID actualID;
     void msgDeliver(envelope *env) {
-        env->setSrcPe(CkMyPe());
+        // This was causing sync entry methods not to return properly in some cases
+        //env->setSrcPe(CkMyPe());
         env->setMsgtype(ForChareMsg);
         env->setObjPtr(actualID.objPtr);
-        CldEnqueue(actualID.onPE, env, _infoIdx);
+        _CldEnqueue(actualID.onPE, env, _infoIdx);
         CpvAccess(_qd)->create();      
     }
   public:
@@ -63,7 +95,7 @@ class VidBlock {
       return NULL;
     }
     void pup(PUP::er &p) {
-#if CMK_FT_CHARE
+#ifndef CMK_CHARE_USE_PTR
       int s;
       if (!p.isUnpacking()) s = state-FILLED;
       p|s;
@@ -91,12 +123,21 @@ public:
         * up to the outermost
         */
        inline CmiBool processMessage(envelope *env,CkCoreState *ck) {
-         if (next != NULL) next->processMessage(env, ck);
-         return process(env, ck);
+         CmiBool result = CmiTrue;
+         if (next != NULL) result &= next->processMessage(env, ck);
+         result &= process(env, ck);
+         return result;
+       }
+       inline int processThread(CthThreadToken *token, CkCoreState *ck) {
+          int result = 1;
+          if (next != NULL) result &= next->processThread(token, ck);
+          result &= process(token, ck);
+          return result;
        }
 protected:
-    /** This is used internally by this class to call the correct subclass method */
+    /** These are used internally by this class to call the correct subclass method */
        virtual CmiBool process(envelope *env,CkCoreState *ck) =0;
+       virtual int process(CthThreadToken *token, CkCoreState *ck) {return 1;}
 public:
     inline void setNext(CkMessageWatcher *w) { next = w; }
 };
index 3d3735fec56f7f7f20a4f834e2d1b2ef83a0527b..fb6455fffddee86de3e18eb78c853fb9db867525 100644 (file)
@@ -419,28 +419,31 @@ CkArrayID CProxy_ArrayBase::ckCreateArray(CkArrayMessage *m,int ctor,
                                          const CkArrayOptions &opts_)
 {
   CkArrayOptions opts(opts_);
-  if (opts.getLocationManager().isZero())
+  CkGroupID locMgr = opts.getLocationManager();
+  if (locMgr.isZero())
   { //Create a new location manager
 #if !CMK_LBDB_ON
     CkGroupID _lbdb;
 #endif
-    opts.setLocationManager(CProxy_CkLocMgr::ckNew(
-      opts.getMap(),_lbdb,opts.getNumInitial()
-      ));
+    locMgr = CProxy_CkLocMgr::ckNew(opts.getMap(),_lbdb,opts.getNumInitial());
+    opts.setLocationManager(locMgr);
   }
   //Create the array manager
   m->array_ep()=ctor;
   CkMarshalledMessage marsh(m);
+  CkEntryOptions  e_opts;
+  e_opts.setGroupDepID(locMgr);       // group creation dependence
 #if !GROUP_LEVEL_REDUCTION
   CProxy_CkArrayReductionMgr nodereductionProxy = CProxy_CkArrayReductionMgr::ckNew();
-  CkGroupID ag=CProxy_CkArray::ckNew(opts,marsh,nodereductionProxy);
+  CkGroupID ag=CProxy_CkArray::ckNew(opts,marsh,nodereductionProxy,&e_opts);
   nodereductionProxy.setAttachedGroup(ag);
 #else
   CkNodeGroupID dummyid;
-  CkGroupID ag=CProxy_CkArray::ckNew(opts,marsh,dummyid);
+  CkGroupID ag=CProxy_CkArray::ckNew(opts,marsh,dummyid,&e_opts);
 #endif
   return (CkArrayID)ag;
 }
+
 CkArrayID CProxy_ArrayBase::ckCreateEmptyArray(void)
 {
   return ckCreateArray((CkArrayMessage *)CkAllocSysMsg(),0,CkArrayOptions());
@@ -768,10 +771,16 @@ void CProxyElement_ArrayBase::ckSend(CkArrayMessage *msg, int ep, int opts) cons
          ckDelegatedTo()->ArraySend(ckDelegatedPtr(),ep,msg,_idx,ckGetArrayID());
        else 
        { //Usual case: a direct send
-         if (opts & CK_MSG_INLINE)
-           ckLocalBranch()->deliver(msg, CkDeliver_inline, opts&!CK_MSG_INLINE);
-         else
-           ckLocalBranch()->deliver(msg, CkDeliver_queue, opts);
+         CkArray *localbranch = ckLocalBranch();
+         if (localbranch == NULL) {             // array not created yet
+           CkArrayManagerDeliver(CkMyPe(), msg, 0);
+          }
+         else {
+           if (opts & CK_MSG_INLINE)
+             localbranch->deliver(msg, CkDeliver_inline, opts & (~CK_MSG_INLINE));
+           else
+             localbranch->deliver(msg, CkDeliver_queue, opts);
+         }
        }
 }
 
@@ -809,7 +818,10 @@ void CkSendMsgArray(int entryIndex, void *msg, CkArrayID aID, const CkArrayIndex
   m->array_index()=idx;
   msg_prepareSend(m,entryIndex,aID);
   CkArray *a=(CkArray *)_localBranch(aID);
-  a->deliver(m,CkDeliver_queue,opts);
+  if (a == NULL)
+    CkArrayManagerDeliver(CkMyPe(), msg, 0);
+  else
+    a->deliver(m,CkDeliver_queue,opts);
 }
 
 void CkSendMsgArrayInline(int entryIndex, void *msg, CkArrayID aID, const CkArrayIndex &idx, int opts)
index 884095414e846c84d41f983ad7ca694a5ec56805..0b0aa7f5da6aa64a61106eb344f8caa843686ee0 100644 (file)
@@ -16,6 +16,10 @@ Initial version by Orion Sky Lawlor, olawlor@acm.org, 2/8/2002
 
 /*readonly*/ CProxy_ckcallback_group _ckcallbackgroup;
 
+typedef CkHashtableT<CkHashtableAdaptorT<unsigned int>, CkCallback*> threadCB_t;
+CpvStaticDeclare(threadCB_t, threadCBs);
+CpvStaticDeclare(unsigned int, nextThreadCB);
+
 //This main chare is only used to create the callback forwarding group
 class ckcallback_main : public CBase_ckcallback_main {
 public:
@@ -41,10 +45,17 @@ public:
 //Initialize the callback's thread fields before sending it off:
 void CkCallback::impl_thread_init(void)
 {
-       d.thread.onPE=CkMyPe();
-       d.thread.cb=this; //<- so we can find this structure later
+    int exist;
+    CkCallback **cb;
+    d.thread.onPE=CkMyPe();
+       do {
+         if (CpvAccess(nextThreadCB)==0) CpvAccess(nextThreadCB)=1;
+         d.thread.cb=CpvAccess(nextThreadCB)++;
+         cb = &CpvAccess(threadCBs).put(d.thread.cb, &exist);
+       } while (exist==1);
+       *cb = this; //<- so we can find this structure later
        d.thread.th=NULL; //<- thread isn't suspended yet
-       d.thread.ret=NULL;//<- no data to return yet
+       d.thread.ret=(void*)-1;//<- no data to return yet
 }
 
 //Actually suspend this thread
@@ -57,12 +68,14 @@ void *CkCallback::impl_thread_delay(void) const
        
        //Find the original callback object:
        CkCallback *dest=(CkCallback *)this;
-       if (d.thread.cb!=NULL) dest=d.thread.cb;
-       if (dest->d.thread.cb!=NULL) 
+       if (d.thread.cb!=0) dest=CpvAccess(threadCBs).get(d.thread.cb);
+       if (dest==0)
+           CkAbort("Called thread_delay on an already deleted callback");
+       if (dest->d.thread.ret==(void*)-1) 
        {  //We need to sleep for the result:
                dest->d.thread.th=CthSelf(); //<- so we know a thread is waiting
                CthSuspend();
-               if (dest->d.thread.cb!=NULL
+               if (dest->d.thread.ret==(void*)-1
                        CkAbort("thread resumed, but callback data is still empty");
        }
        return dest->d.thread.ret;
@@ -72,54 +85,70 @@ void *CkCallback::impl_thread_delay(void) const
 /*These can't be defined in the .h file like the other constructors
  * because we need CkCallback before CProxyElement* are defined.
  */
-CkCallback::CkCallback(Chare *p, int ep, CmiBool doInline)
-               :type(doInline?isendChare:sendChare)
-{
+CkCallback::CkCallback(Chare *p, int ep, CmiBool doInline) {
+#ifndef CMK_OPTIMIZE
+      bzero(this, sizeof(CkCallback));
+#endif
+      type=doInline?isendChare:sendChare;
        d.chare.ep=ep; 
        d.chare.id=p->ckGetChareID();
 }
-CkCallback::CkCallback(Group *p, int ep, CmiBool doInline)
-               :type(doInline?isendGroup:sendGroup)
-{
+CkCallback::CkCallback(Group *p, int ep, CmiBool doInline) {
+#ifndef CMK_OPTIMIZE
+      bzero(this, sizeof(CkCallback));
+#endif
+      type=doInline?isendGroup:sendGroup;
        d.group.ep=ep; d.group.id=p->ckGetGroupID(); d.group.onPE=CkMyPe();
 }
-CkCallback::CkCallback(NodeGroup *p, int ep, CmiBool doInline)
-               :type(doInline?isendNodeGroup:sendNodeGroup)
-{
+CkCallback::CkCallback(NodeGroup *p, int ep, CmiBool doInline) {
+#ifndef CMK_OPTIMIZE
+      bzero(this, sizeof(CkCallback));
+#endif
+      type=doInline?isendNodeGroup:sendNodeGroup;
        d.group.ep=ep; d.group.id=p->ckGetGroupID(); d.group.onPE=CkMyNode();
 }
 
-CkCallback::CkCallback(int ep,const CProxy_NodeGroup &ngp)
-               :type(bcastNodeGroup) 
-{
+CkCallback::CkCallback(int ep,const CProxy_NodeGroup &ngp) {
+#ifndef CMK_OPTIMIZE
+      bzero(this, sizeof(CkCallback));
+#endif
+      type=bcastNodeGroup;
        d.group.ep=ep; d.group.id=ngp.ckGetGroupID();
 }
 
-CkCallback::CkCallback(int ep,int onPE,const CProxy_NodeGroup &ngp,CmiBool doInline)
-       :type(doInline?isendNodeGroup:sendNodeGroup) 
-{
+CkCallback::CkCallback(int ep,int onPE,const CProxy_NodeGroup &ngp,CmiBool doInline) {
+#ifndef CMK_OPTIMIZE
+      bzero(this, sizeof(CkCallback));
+#endif
+      type=doInline?isendNodeGroup:sendNodeGroup;
        d.group.ep=ep; d.group.id=ngp.ckGetGroupID(); d.group.onPE=onPE;
 }
 
-CkCallback::CkCallback(int ep,const CProxyElement_Group &grpElt,CmiBool doInline) 
-       :type(doInline?isendGroup:sendGroup) 
-{
+CkCallback::CkCallback(int ep,const CProxyElement_Group &grpElt,CmiBool doInline) {
+#ifndef CMK_OPTIMIZE
+      bzero(this, sizeof(CkCallback));
+#endif
+      type=doInline?isendGroup:sendGroup;
        d.group.ep=ep; 
        d.group.id=grpElt.ckGetGroupID(); 
        d.group.onPE=grpElt.ckGetGroupPe();
 }
-CkCallback::CkCallback(int ep,const CProxyElement_ArrayBase &arrElt,CmiBool doInline)
-       :type(doInline?isendArray:sendArray) 
-{
+CkCallback::CkCallback(int ep,const CProxyElement_ArrayBase &arrElt,CmiBool doInline) {
+#ifndef CMK_OPTIMIZE
+      bzero(this, sizeof(CkCallback));
+#endif
+      type=doInline?isendArray:sendArray;
        d.array.ep=ep; 
        d.array.id=arrElt.ckGetArrayID(); 
        d.array.idx.asMax()=arrElt.ckGetIndex();
 }
 
-CkCallback::CkCallback(ArrayElement *p, int ep,CmiBool doInline)
-       :type(doInline?isendArray:sendArray) 
-{
-        d.array.ep=ep; 
+CkCallback::CkCallback(ArrayElement *p, int ep,CmiBool doInline) {
+#ifndef CMK_OPTIMIZE
+      bzero(this, sizeof(CkCallback));
+#endif
+      type=doInline?isendArray:sendArray;
+    d.array.ep=ep; 
        d.array.id=p->ckGetArrayID(); 
        d.array.idx.asMax()=p->ckGetArrayIndex();
 }
@@ -145,11 +174,10 @@ void CkCallback::send(void *msg) const
                break;
        case resumeThread: //Resume a waiting thread
                if (d.thread.onPE==CkMyPe()) {
-                       CkCallback *dest=d.thread.cb;
-                       if (dest==NULL)
+                       CkCallback *dest=CpvAccess(threadCBs).get(d.thread.cb);
+                       if (dest==0 || dest->d.thread.ret!=(void*)-1)
                                CkAbort("Already sent a value to this callback!\n");
                        dest->d.thread.ret=msg; //<- return data
-                       dest->d.thread.cb=NULL; //<- mark callback as finished
                        if (dest->d.thread.th!=NULL)
                                CthAwaken(dest->d.thread.th);
                } 
@@ -230,6 +258,68 @@ void CkCallback::send(void *msg) const
        };
 }
 
+void CkCallback::pup(PUP::er &p) {
+  //p((char*)this, sizeof(CkCallback));
+  int t = (int)type;
+  p|t;
+  type = (callbackType)t;
+  switch (type) {
+  case resumeThread:
+    p|d.thread.onPE;
+    p|d.thread.cb;
+    break;
+  case isendChare:
+  case sendChare:
+    p|d.chare.ep;
+    p|d.chare.id;
+    break;
+  case isendGroup:
+  case sendGroup:
+  case isendNodeGroup:
+  case sendNodeGroup:
+    p|d.group.onPE;
+  case bcastNodeGroup:
+  case bcastGroup:
+    p|d.group.ep;
+    p|d.group.id;
+    break;
+  case isendArray:
+  case sendArray:
+    p|d.array.idx;
+  case bcastArray:
+    p|d.array.ep;
+    p|d.array.id;
+    break;
+  case replyCCS:
+    p((char*)&d.ccsReply.reply, sizeof(d.ccsReply.reply));
+    break;
+  case call1Fn:
+    p((char*)&d.c1fn, sizeof(d.c1fn));
+    break;
+  case callCFn:
+    p((char*)&d.cfn, sizeof(d.cfn));
+    break;
+  case ignore:
+  case ckExit:
+  case invalid:
+    break;
+  default:
+    CkAbort("Inconsistent CkCallback type");
+  }
+}
+
+void CkCallback::thread_destroy() const {
+  if (type==resumeThread && CpvAccess(threadCBs).get(d.thread.cb)==this) {
+    CpvAccess(threadCBs).remove(d.thread.cb);
+  }
+}
+
+CkCallbackResumeThread::~CkCallbackResumeThread() {
+  void * res = thread_delay(); //<- block thread here if it hasn't already
+  if (result != NULL) *result = res;
+  else CkFreeMsg(res);
+  thread_destroy();
+}
 
 /****** Callback-from-CCS ******/
 
@@ -272,5 +362,11 @@ void CkDataMsg::check(void)
                CkAbort("CkDataMsg corrupted-- bad tag.");
 }
 
+void CkCallbackInit() {
+  CpvInitialize(threadCB_t, threadCBs);
+  CpvInitialize(unsigned int, nextThreadCB);
+  CpvAccess(nextThreadCB)=1;
+}
+
 #include "CkCallback.def.h"
 
index e7e755f9bfa035daba75e530739ad3cc87e9246b..79f387cd56490b5a03883f5fcd6b29707577fb6c 100644 (file)
@@ -53,7 +53,7 @@ private:
        union callbackData {
        struct s_thread { //resumeThread
                int onPE; //Thread is waiting on this PE
-               CkCallback *cb; //The suspending callback (NULL if already done)
+               int cb; //The suspending callback (0 if already done)
                CthThread th; //Thread to resume (NULL if none waiting)
                void *ret; //Place to put the returned message
        } thread;
@@ -84,60 +84,98 @@ private:
        } ccsReply;
        };
 public:        
-       callbackType type; 
+       callbackType type;
        callbackData d;
        
        void impl_thread_init(void);
        void *impl_thread_delay(void) const;
 public:
-       CkCallback(void) :type(invalid) {}
+       CkCallback(void) {
+#ifndef CMK_OPTIMIZE
+      bzero(this, sizeof(CkCallback));
+#endif
+      type=invalid;
+       }
        //This is how you create ignore, ckExit, and resumeThreads:
-       CkCallback(callbackType t) 
-               :type(t) { if (t==resumeThread) impl_thread_init(); }
+       CkCallback(callbackType t) {
+#ifndef CMK_OPTIMIZE
+         bzero(this, sizeof(CkCallback));
+#endif
+         if (t==resumeThread) impl_thread_init();
+         type=t;
+       }
 
     // Call a C function on the current PE
-       CkCallback(Ck1CallbackFn fn)
-               :type(call1Fn)
-               {d.c1fn.fn=fn;}
+       CkCallback(Ck1CallbackFn fn) {
+#ifndef CMK_OPTIMIZE
+      bzero(this, sizeof(CkCallback));
+#endif
+      type=call1Fn;
+         d.c1fn.fn=fn;
+       }
 
     // Call a C function on the current PE
-       CkCallback(CkCallbackFn fn,void *param)
-               :type(callCFn) 
-               {d.cfn.onPE=CkMyPe(); d.cfn.fn=fn; d.cfn.param=param;}
+       CkCallback(CkCallbackFn fn,void *param) {
+#ifndef CMK_OPTIMIZE
+      bzero(this, sizeof(CkCallback));
+#endif
+      type=callCFn;
+         d.cfn.onPE=CkMyPe(); d.cfn.fn=fn; d.cfn.param=param;
+       }
 
     // Call a chare entry method
-       CkCallback(int ep,const CkChareID &id,CmiBool doInline=CmiFalse)
-               :type(doInline?isendChare:sendChare) 
-               {d.chare.ep=ep; d.chare.id=id;}
+       CkCallback(int ep,const CkChareID &id,CmiBool doInline=CmiFalse) {
+#ifndef CMK_OPTIMIZE
+      bzero(this, sizeof(CkCallback));
+#endif
+      type=doInline?isendChare:sendChare;
+         d.chare.ep=ep; d.chare.id=id;
+       }
 
     // Bcast to nodegroup
        CkCallback(int ep,const CProxy_NodeGroup &ngp);
 
     // Bcast to a group or nodegroup
-       CkCallback(int ep,const CkGroupID &id, int isNodeGroup=0)
-               :type(isNodeGroup?bcastNodeGroup:bcastGroup) 
-               {d.group.ep=ep; d.group.id=id;}
+       CkCallback(int ep,const CkGroupID &id, int isNodeGroup=0) {
+#ifndef CMK_OPTIMIZE
+      bzero(this, sizeof(CkCallback));
+#endif
+      type=isNodeGroup?bcastNodeGroup:bcastGroup;
+         d.group.ep=ep; d.group.id=id;
+       }
 
     // Send to nodegroup element
        CkCallback(int ep,int onPE,const CProxy_NodeGroup &ngp,CmiBool doInline=CmiFalse);
 
     // Send to group/nodegroup element
-       CkCallback(int ep,int onPE,const CkGroupID &id,CmiBool doInline=CmiFalse, int isNodeGroup=0)
-               :type(doInline?(isNodeGroup?isendNodeGroup:isendGroup):(isNodeGroup?sendNodeGroup:sendGroup)) 
-               {d.group.ep=ep; d.group.id=id; d.group.onPE=onPE;}
+       CkCallback(int ep,int onPE,const CkGroupID &id,CmiBool doInline=CmiFalse, int isNodeGroup=0) {
+#ifndef CMK_OPTIMIZE
+      bzero(this, sizeof(CkCallback));
+#endif
+      type=doInline?(isNodeGroup?isendNodeGroup:isendGroup):(isNodeGroup?sendNodeGroup:sendGroup); 
+      d.group.ep=ep; d.group.id=id; d.group.onPE=onPE;
+       }
 
     // Send to specified group element
        CkCallback(int ep,const CProxyElement_Group &grpElt,CmiBool doInline=CmiFalse);
        
     // Bcast to array
-       CkCallback(int ep,const CkArrayID &id)
-               :type(bcastArray) 
-               {d.array.ep=ep; d.array.id=id;}
+       CkCallback(int ep,const CkArrayID &id) {
+#ifndef CMK_OPTIMIZE
+      bzero(this, sizeof(CkCallback));
+#endif
+      type=bcastArray;
+         d.array.ep=ep; d.array.id=id;
+       }
 
     // Send to array element
-       CkCallback(int ep,const CkArrayIndex &idx,const CkArrayID &id,CmiBool doInline=CmiFalse)
-               :type(doInline?isendArray:sendArray) 
-               {d.array.ep=ep; d.array.id=id; d.array.idx.asMax()=*(CkArrayIndexMax*)&idx;}
+       CkCallback(int ep,const CkArrayIndex &idx,const CkArrayID &id,CmiBool doInline=CmiFalse) {
+#ifndef CMK_OPTIMIZE
+      bzero(this, sizeof(CkCallback));
+#endif
+      type=doInline?isendArray:sendArray;
+         d.array.ep=ep; d.array.id=id; d.array.idx.asMax()=*(CkArrayIndexMax*)&idx;
+       }
 
     // Bcast to array
        CkCallback(int ep,const CProxyElement_ArrayBase &arrElt,CmiBool doInline=CmiFalse);
@@ -154,9 +192,18 @@ public:
     // Send to specified array element 
        CkCallback(ArrayElement *p, int ep,CmiBool doInline=CmiFalse);
 
-       CkCallback(const CcsDelayedReply &reply) 
-               :type(replyCCS) {d.ccsReply.reply=reply;}
+       CkCallback(const CcsDelayedReply &reply) {
+#ifndef CMK_OPTIMIZE
+      bzero(this, sizeof(CkCallback));
+#endif
+      type=replyCCS;
+         d.ccsReply.reply=reply;
+       }
 
+       ~CkCallback() {
+         thread_destroy();
+       }
+       
        int isInvalid(void) const {return type==invalid;}
 
 /**
@@ -171,6 +218,8 @@ public:
                return NULL;
        }
 
+       void thread_destroy() const;
+       
 /**
  * Send this message back to the caller.
  *
@@ -184,8 +233,10 @@ public:
  * Send this data, formatted as a CkDataMsg, back to the caller.
  */
        void send(int length,const void *data) const;
+       
+       void pup(PUP::er &p);
 };
-PUPbytes(CkCallback) //FIXME: write a real pup routine
<