[MLton-commit] r6432

spoons at mlton.org spoons at mlton.org
Mon Mar 3 06:52:05 PST 2008


Added the Portable Linux Processor Affinity (PLPA) package

This is a subset of the PLPA package that is meant to be included in
other projects.

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

U   mlton/branches/shared-heap-multicore/bin/mlton-script
U   mlton/branches/shared-heap-multicore/runtime/Makefile
U   mlton/branches/shared-heap-multicore/runtime/cenv.h
A   mlton/branches/shared-heap-multicore/runtime/plpa/
A   mlton/branches/shared-heap-multicore/runtime/plpa/AUTHORS
A   mlton/branches/shared-heap-multicore/runtime/plpa/LICENSE
A   mlton/branches/shared-heap-multicore/runtime/plpa/Makefile
A   mlton/branches/shared-heap-multicore/runtime/plpa/NEWS
A   mlton/branches/shared-heap-multicore/runtime/plpa/README
A   mlton/branches/shared-heap-multicore/runtime/plpa/README.mlton
A   mlton/branches/shared-heap-multicore/runtime/plpa/VERSION
A   mlton/branches/shared-heap-multicore/runtime/plpa/plpa.h
A   mlton/branches/shared-heap-multicore/runtime/plpa/plpa_api_probe.c
A   mlton/branches/shared-heap-multicore/runtime/plpa/plpa_bottom.h
A   mlton/branches/shared-heap-multicore/runtime/plpa/plpa_dispatch.c
A   mlton/branches/shared-heap-multicore/runtime/plpa/plpa_internal.h

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

Modified: mlton/branches/shared-heap-multicore/bin/mlton-script
===================================================================
--- mlton/branches/shared-heap-multicore/bin/mlton-script	2008-03-03 14:42:04 UTC (rev 6431)
+++ mlton/branches/shared-heap-multicore/bin/mlton-script	2008-03-03 14:52:04 UTC (rev 6432)
@@ -82,7 +82,7 @@
         -cc-opt-quote "-I$lib/include"                           \
         -cc-opt '-O1'                                            \
         -cc-opt '-fno-strict-aliasing -fomit-frame-pointer -w'   \
-        -link-opt '-lgdtoa -lm -lgmp'                            \
+        -link-opt '-lgdtoa -lm -lgmp -lpthread -lplpa_included -lrt' \
         -mlb-path-map "$lib/mlb-path-map"                        \
         -target-as-opt amd64 '-m64 -mtune=opteron'               \
         -target-cc-opt amd64 '-m64 -mtune=opteron'               \

Modified: mlton/branches/shared-heap-multicore/runtime/Makefile
===================================================================
--- mlton/branches/shared-heap-multicore/runtime/Makefile	2008-03-03 14:42:04 UTC (rev 6431)
+++ mlton/branches/shared-heap-multicore/runtime/Makefile	2008-03-03 14:52:04 UTC (rev 6432)
@@ -107,7 +107,7 @@
 
 CC := gcc -std=gnu99
 CPPFLAGS := 
-CFLAGS := -I. -Iplatform $(FLAGS)
+CFLAGS := -I. -Iplatform -Iplpa $(FLAGS)
 OPTCFLAGS := $(CFLAGS) $(OPTFLAGS)
 DEBUGCFLAGS := $(CFLAGS) -DASSERT=1 $(DEBUGFLAGS)
 GCOPTCFLAGS = $(GCOPTFLAGS)
@@ -227,7 +227,7 @@
 	$(foreach f, $(basename $(BASISCFILES)), $(f)-gdb.o)
 endif
 
-ALL := libgdtoa.a libmlton.a libmlton-gdb.a
+ALL := libgdtoa.a libplpa_included.a libmlton.a libmlton-gdb.a
 ALL += gen/c-types.sml gen/basis-ffi.sml
 ifeq ($(OMIT_BYTECODE), yes)
 else
@@ -255,6 +255,13 @@
 gdtoa/arith.h: gdtoa/arithchk.out
 	cd gdtoa && ./arithchk.out >arith.h
 
+libplpa_included.a: plpa/plpa_api_probe.c plpa/plpa_dispatch.c
+	@rm -f $@
+	cd plpa && $(CC) $(OPTCFLAGS) -c plpa_api_probe.c 
+	cd plpa && $(CC) $(OPTCFLAGS) -c plpa_dispatch.c
+	$(AR) $@ plpa/*.o
+	$(RANLIB) $@
+
 libmlton.a: $(OBJS)
 	$(AR) libmlton.a $(OBJS)
 	$(RANLIB) libmlton.a

Modified: mlton/branches/shared-heap-multicore/runtime/cenv.h
===================================================================
--- mlton/branches/shared-heap-multicore/runtime/cenv.h	2008-03-03 14:42:04 UTC (rev 6431)
+++ mlton/branches/shared-heap-multicore/runtime/cenv.h	2008-03-03 14:52:04 UTC (rev 6432)
@@ -40,6 +40,7 @@
 #include <limits.h>
 // #include <locale.h>
 #include <math.h>
+#include <plpa.h>
 // #include <setjmp.h>
 #include <signal.h>
 #include <stdarg.h>

Added: mlton/branches/shared-heap-multicore/runtime/plpa/AUTHORS
===================================================================
--- mlton/branches/shared-heap-multicore/runtime/plpa/AUTHORS	2008-03-03 14:42:04 UTC (rev 6431)
+++ mlton/branches/shared-heap-multicore/runtime/plpa/AUTHORS	2008-03-03 14:52:04 UTC (rev 6432)
@@ -0,0 +1,13 @@
+PLPA Authors
+============
+
+The IDs in parenthesis are those used in Subversion commit notices.
+
+Current Authors
+---------------
+
+Indiana University:
+- Jeff Squyres (jsquyres)
+
+Lawrence Berkeley National Lab:
+- Paul Hargrove (phargrov)

Added: mlton/branches/shared-heap-multicore/runtime/plpa/LICENSE
===================================================================
--- mlton/branches/shared-heap-multicore/runtime/plpa/LICENSE	2008-03-03 14:42:04 UTC (rev 6431)
+++ mlton/branches/shared-heap-multicore/runtime/plpa/LICENSE	2008-03-03 14:52:04 UTC (rev 6432)
@@ -0,0 +1,54 @@
+Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana
+                        University Research and Technology
+                        Corporation.  All rights reserved.
+Copyright (c) 2004-2005 The Regents of the University of California.
+                        All rights reserved.
+
+Portions copyright:
+
+Copyright (c) 2004-2005 The University of Tennessee and The University
+                        of Tennessee Research Foundation.  All rights
+                        reserved.
+Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, 
+                        University of Stuttgart.  All rights reserved.
+
+$COPYRIGHT$
+
+Additional copyrights may follow
+
+$HEADER$
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+- Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer listed
+  in this license in the documentation and/or other materials
+  provided with the distribution.
+
+- Neither the name of the copyright holders nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+The copyright holders provide no reassurances that the source code
+provided does not infringe any patent, copyright, or any other
+intellectual property rights of third parties.  The copyright holders
+disclaim any liability to any recipient for claims brought against
+recipient by any third party for infringement of that parties
+intellectual property rights.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Added: mlton/branches/shared-heap-multicore/runtime/plpa/Makefile
===================================================================
--- mlton/branches/shared-heap-multicore/runtime/plpa/Makefile	2008-03-03 14:42:04 UTC (rev 6431)
+++ mlton/branches/shared-heap-multicore/runtime/plpa/Makefile	2008-03-03 14:52:04 UTC (rev 6432)
@@ -0,0 +1,10 @@
+
+SRC = plpa_api_probe.c plpa_dispatch.c
+OBJ = ${SRC:%.c=%.o}
+
+%.o : %.c
+	gcc -DHAVE_CONFIG_H -I. -g -c $<  -fPIC -DPIC -o $@;
+
+libplpa_included.a: ${OBJ}
+	ar cru $@ $<;
+	ranlib $@;

Added: mlton/branches/shared-heap-multicore/runtime/plpa/NEWS
===================================================================
--- mlton/branches/shared-heap-multicore/runtime/plpa/NEWS	2008-03-03 14:42:04 UTC (rev 6431)
+++ mlton/branches/shared-heap-multicore/runtime/plpa/NEWS	2008-03-03 14:52:04 UTC (rev 6432)
@@ -0,0 +1,59 @@
+Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana
+                        University Research and Technology
+                        Corporation.  All rights reserved.
+Copyright (c) 2004-2005 The Regents of the University of California.
+                        All rights reserved.
+$COPYRIGHT$
+
+Additional copyrights may follow
+
+$HEADER$
+
+===========================================================================
+
+This file contains the main features as well as overviews of specific
+bug fixes (and other actions) for each version of PLPA since
+version 1.0.
+
+1.0.3
+-----
+
+- Resolve some sizing / units ambiguities that mistakenly did not make
+  it into 1.0.1.  Thanks to Bert Wesarg for pointing these problems out.
+
+
+1.0.2
+-----
+
+- Ensure that plpa_sched_[set|get]affinity() returns 0 upon success.
+  Thanks to David Creasy for bringing this to our attention.
+
+
+1.0.1
+-----
+
+- Specify that cpusetsize should be in units of bytes and add some
+  missing "* 8"'s in plpa_dispatch.c.
+
+
+1.0
+---
+
+- Initial release.
+
+
+0.9a2
+-----
+
+- Change the back-end type of the plpa_bitmask_t to unsigned long
+  instead of unsigned char to avoid an endian problem.
+- No longer attempt to set the affinity in plpa_api_probe() to avoid a
+  possible race condition (setting it after getting it).
+- Fix PLPA_CPU_ZERO macro.  Thanks to Bogdan Costescu for pointing
+  this out.
+
+
+0.9a1
+-----
+
+Initial public release.

Added: mlton/branches/shared-heap-multicore/runtime/plpa/README
===================================================================
--- mlton/branches/shared-heap-multicore/runtime/plpa/README	2008-03-03 14:42:04 UTC (rev 6431)
+++ mlton/branches/shared-heap-multicore/runtime/plpa/README	2008-03-03 14:52:04 UTC (rev 6432)
@@ -0,0 +1,460 @@
+Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana
+                        University Research and Technology
+                        Corporation.  All rights reserved.
+Copyright (c) 2004-2005 The University of Tennessee and The University
+                        of Tennessee Research Foundation.  All rights
+                        reserved.
+Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, 
+                        University of Stuttgart.  All rights reserved.
+Copyright (c) 2004-2005 The Regents of the University of California.
+                        All rights reserved.
+$COPYRIGHT$
+
+Additional copyrights may follow
+
+$HEADER$
+
+===========================================================================
+
+This is the Portable Linux Processor Affinity (PLPA) package
+(pronounced "pli-pa").  It is intended for developers who wish to use
+Linux processor affinity via the sched_setaffinity() and
+sched_getaffinity() library calls, but don't want to wade through the
+morass of 3 different APIs that have been offered through the life of
+these calls in various Linux distributions and glibc versions.
+
+Specifically, to compile for any given Linux system, you need some
+complex compile-time tests to figure out which of the 3 APIs to use.
+And if you want your application to be binary portable across
+different Linux distributions, more complex run-time tests (and horrid
+compile-time trickery) are required to figure out which API the system
+you are running on uses.  
+
+These problems all stem from the fact that the same 2 symbols have had
+three different APIs (with different numbers and types of
+parameters) throughout their life in Linux.  Ick.
+
+The PLPA is an attempt to solve this problem by providing a single API
+that developers can write to.  It provides two things:
+
+1. A single API that developers can write to, regardless of what
+   back-end API the system you are compiling on has.
+2. A run-time test and dispatch that will invoke the Right back-end
+   API depending on what back-end API the system you are running on
+   has.
+
+This package is actually pretty small.  It does not attempt to have
+many extra bells and whistles.  Anyone could write it and package it.
+We did it simply because it appears that no one else has yet done
+this.  In a world where larger scale SMPs are [again] becoming more
+common, particularly where at least some of them are NUMA-based
+architectures, processor affinity is going to become more and more
+important.  Just because developers have not yet realized that they
+have this problem does not mean that they won't evenutally figure it
+out.  :-)
+
+Note that if you're looking into processor affinity, if you're on a
+NUMA machine, you probably also want to look into libnuma:
+
+    ftp://ftp.suse.com/pub/people/ak/numa/
+
+We hope that PLPA helps you.
+
+===========================================================================
+
+What, exactly, is the problem?
+------------------------------
+
+There are at least 3 different ways that sched_setaffinity is
+implemented in glibc (only one of which is documented in the
+sched_setaffinity(2) man page), and some corresponding changes
+to what the kernel considers to be valid arguments:
+
+1. int sched_setaffinity(pid_t pid, unsigned int len, unsigned
+                         long *mask);
+
+This originated in the time period of 2.5 kernels and some distros
+back-ported it to their 2.4 kernels and libraries.  It's unknown if
+this version was ever packaged with any 2.6 kernels.
+
+2. int sched_setaffinity (pid_t __pid, size_t __cpusetsize,
+                          const cpu_set_t *__cpuset);
+
+This appears to be in recent distors using 2.6 kernels.  We don't
+know exactly when #1 changed into #2.  However, this prototype is nice
+because the cpu_set_t type is accompanied by fdset-like CPU_ZERO(),
+CPU_SET(), CPU_ISSET(), etc. macros.
+
+3. int sched_setaffinity (pid_t __pid, const cpu_set_t *__mask);
+
+(note the missing len parameter) This is in at least some Linux
+distros (e.g., MDK 10.0 with a 2.6.3 kernel, and SGI Altix, even
+though the Altix uses a 2.4-based kernel and therefore likely
+back-ported the 2.5 work or originated it in the first place).
+Similar to #2, the cpu_set_t type is accompanied by fdset-like
+CPU_ZERO(), CPU_SET(), CPU_ISSET(), etc. macros.
+
+But wait, it gets worse.
+
+Remember that getting/setting processor affinity has to involve the
+kernel.  The sched_[sg]etaffinity() glibc functions typically do a
+little error checking and then make a syscall down into the kernel to
+actually do the work.  There are multiple possibilities for problems
+here as the amount of checking has changed:
+
+1. The glibc may support the affinity functions, but the kernel may
+   not (and vice versa).
+
+   This is typically only an issue with slightly older Linux distributions.
+   Mandrake 9.2 is an example of this.  PLPA can detect this at run-time
+   and turn its internal functions into no-ops and return appropriate error
+   codes (ENOSYS).
+
+2. The glibc affinity functions may be buggy (i.e., they pass bad data
+   down to the syscall).
+
+   This is fortunately restricted to some older versions of glibc, and
+   is relatively easy to check for at run-time.  PLPA reliably detects
+   this situation at run-time and returns appropriate error codes
+   (ENOSYS).
+
+   The original SuSE 9.1 version seems to have this problem, but it was
+   fixed it somewhere in the SuSE patching history (it is unknown exactly
+   when).  Specifically, updating to the latest SuSE 9.1 patch level
+   (as of Dec 2005) seems to fix the problem.
+
+3. The CPU_* macros for manipulating cpu_set_t bitmasks may not
+   compile because of typo bugs in system header files.
+
+   PLPA avoids this problem by providing its own PLPA_CPU_* macros for
+   manipulating CPU bitmasks.  See "How do I use PLPA?", below, for
+   more details.
+
+The PLPA avoids all the glibc issues by using syscall() to directly
+access the kernel set and get affinity functions.  This is described
+below.
+
+===========================================================================
+
+How does PLPA work?
+-------------------
+
+Jeff Squyres initially sent a mail to the Open MPI developer's mailing
+list explaining the Linux processor affinity problems and asking for
+help coming up with a solution (particularly for binary
+compatibility):
+
+    http://www.open-mpi.org/community/lists/devel/2005/11/0558.php
+
+Discussion on that thread and others eventually resulted in the
+run-time tests that form the heart of the PLPA.  Many thanks to Paul
+Hargrove and Bogdan Costescu for their time and effort to get these
+tests right.
+
+PLPA was written so that other developers who want to use processor
+affinity in Linux don't have to go through this mess.  The PLPA
+provides a single interface that can be used on any platform,
+regardless of which back-end API variant it has.  This includes both
+the sched_setaffinity() and sched_getaffinity() calls as well as the
+CPU_*() macros.
+
+The PLPA avoids glibc altogether -- although tests were developed that
+could *usually* figure out which glibc variant to use at run time,
+there were still some cases where it was either impossible to
+determine or the glibc interface itself was buggy.  Hence, it was
+decided that a simpler approach was simply to use syscall() to invoke
+the back-end kernel functions directly.
+
+The kernel functions have gone through a few changes as well, so the
+PLPA does a few run-time tests to determine which variant to use
+before actually invoking the back-end functions with the
+user-specified arguments.
+
+NOTE: The run-time tests that the PLPA performs involve getting the
+current affinity for the process in question and then attempting to
+set them back to the same value.  By definition, this introduces a
+race condition (there is no atomic get-and-set functionality for
+processor affinity).  The PLPA cannot guarantee consistent results if
+multiple entites (such as multiple threads or multiple processes) are
+setting the affinity for a process at the same time.  In a worst case
+scenario, the PLPA may actually determine that it cannot determine the
+kernel variant at run time if another entity modifies a process'
+affinity while PLPA is executing its run-time tests.
+
+===========================================================================
+
+Does PLPA make truly portable binaries?
+---------------------------------------
+
+As much as Linux binaries are portable, yes.  That is, if you have
+within your power to make a binary that is runnable on several
+different Linux distributions/versions/etc., then you may run into
+problems with the Linux processor affinity functions.  PLPA attempts
+to solve this problem for you by *also* making the Linux processor
+affinity calls be binary portable.
+
+Hence, you need to start with something that is already binary
+portable (perhaps linking everything statically) -- then PLPA will be
+of help to you.  Do not fall into the misconception that PLPA will
+magically make your executable be binary portable between different
+Linux variants.
+
+===========================================================================
+
+How do I use PLPA?
+------------------
+
+There are two main uses of the PLPA:
+
+1. Using the plpa_info executable to check if your system supports
+   processor affinity and the PLPA can determine which to use at run-time.
+2. Developers using the PLPA library to enable source and binary Linux
+   processor affinity portability.
+
+In more detail:
+
+1. The plpa_info executable is a simple call into the PLPA library
+   that checks which API variant the system it is running on has.  If
+   the kernel supports processor affinity and the PLPA is able to
+   figure out which API variant to use, it prints "PLPA_PROBE_OK".
+   Other responses indicate an error.
+
+   Since the PLPA library abstracts this kind of problem away, this is
+   more a diagnostic tool than anything else.  Note that plpa_info is
+   *only* compiled and installed if PLPA is installed as a standalone
+   package (see below).
+
+2. Developers can use this package by including the <plpa.h> header
+   file and using the following prototypes:
+
+   int plpa_sched_setaffinity(pid_t pid, size_t cpusetsize,
+                              const plpa_cpu_set_t *cpuset);
+
+   int plpa_sched_getaffinity(pid_t pid, size_t cpusetsize,
+                              const plpa_cpu_set_t *cpuset)
+
+   These functions perform run-time tests to determine which back-end
+   API variant exists on the system and then dispatch to it correctly.
+   The units of cpusetsize is number of bytes.  This should normally
+   just be sizeof(*cpuset), but is made available as a parameter to
+   allow for future expansion of the PLPA (stay tuned).
+
+   The observant reader will notice that this is remarkably similar to
+   the one of the Linux API's (the function names are different and
+   the CPU set type is different).  PLPA also provides several macros
+   for manipulating the plpa_cpu_set_t bitmask, quite similar to FDSET
+   macros (see "What, Exactly, Is the Problem?" above for a
+   description of problems with the native CPU_* macros):
+
+   - PLPA_CPU_ZERO(&cpuset): Sets all bits in a plpa_cpu_set_t to
+     zero.
+   - PLPA_CPU_SET(num, &cpuset): Sets bit <num> of <cpuset> to one.
+   - PLPA_CPU_CLR(num, &cpuset): Sets bit <num> of <cpuset> to zero.
+   - PLPA_CPU_ISSET(num, &cpuset): Returns one if bit <num> of
+     <cpuset> is one; returns zero otherwise.
+
+   Note that all four macros take a *pointer* to a plpa_cpu_set_t, as
+   denoted by "&cpuset" in the descriptions above.
+
+===========================================================================
+
+How do I compile / install the PLPA as a standalone package?
+------------------------------------------------------------
+
+The PLPA uses the standard GNU Autoconf/Automake/Libtool toolset to
+build and install itself.  This means that generally, the following
+works:
+
+shell$ ./configure --prefix=/where/you/want/to/install
+[...lots of output...]
+shell$ make all
+[...lots of output...]
+shell$ make install
+
+Depending on your --prefix, you may need to run the "make install"
+step as root or some other privileged user.
+
+"make install" will install the following:
+
+- <plpa.h> in $includedir (typically $prefix/include)
+- libplpa.la and libplpa.a and/or libplpa.so in $libdir (typically
+  $prefix/lib)
+- plpa_info executable in $bindir (typically $prefix/bin)
+
+Note that since PLPA builds itself with GNU Libtool, it can be built
+as a static or shared library (or both).  The default is to build a
+shared library.  You can enable building a static library by supplying
+the "--enable-static" argument to configure; you can disable building
+the shared library by supplying the "--enable-shared" argument to
+configure.  "make install" will install whichever library was built
+(or both).
+
+"make uninstall" will fully uninstall PLPA from the prefix directory
+(again, depending in filesystem permissions, you may need to run this
+as root or some privileged user).
+
+===========================================================================
+
+How do I include PLPA in my software package?
+---------------------------------------------
+
+It can be desirable to include PLPA in a larger software package
+(be sure to check out the LICENSE file) so that users don't have to
+separately download and install it before installing your software
+(after all, PLPA is a tiny little project -- why make users bother
+with it?).
+
+When used in "included" mode, PLPA will:
+
+- not install any header files
+- not build or install plpa_info
+- not build libplpa.* -- instead, it will build libplpa_included.*
+
+There are two ways to put PLPA into "included" mode.  From the
+configure command line:
+
+shell$ ./configure --enable-included-mode ...
+
+Or by directly integrating PLPA's m4 configure macro in your configure
+script and invoking a specific macro to enable the included mode.  
+
+Every project is different, and there are many different ways of
+integrating PLPA into yours.  What follows is *one* example of how to
+do it.
+
+Copy the PLPA directory in your source tree and include the plpa.m4
+file in your configure script -- perhaps with the following line in
+acinclude.m4 (assuming the use of Automake):
+
+m4_include(path/to/plpa.m4)
+
+The following macros can then be used from your configure script:
+
+- PLPA_INIT(action-upon-success, action-upon-failure)
+  Invoke the PLPA tests and setup the PLPA to build.  A traversal of
+  "make" into the PLPA directory should build everything (it is safe
+  to list the PLPA directory in the SUBDIRS of a higher-level
+  Makefile.am, for example).
+
+- PLPA_STANDALONE
+  Force the building of PLPA in standalone mode.  Overrides the
+  --enable-included-mode command line switch.
+
+- PLPA_INCLUDED
+  Force the building of PLPA in included mode.
+
+- PLPA_SET_SYMBOL_PREFIX(foo)
+  Tells the PLPA to prefix all types and public symbols with "foo"
+  instead of "plpa_".  This is recommended behavior if you are
+  including PLPA in a larger project -- it is possible that your
+  software will be combined with other software that also includes
+  PLPA.  If you both use different symbol prefixes, there will be no
+  type/symbol clashes, and everything will compile and link
+  successfully.  If you both include PLPA and do not change the symbol
+  prefix, it is likely that you will get multiple symbol definitions
+  when linking.
+
+Here's an example of integrating with a larger project named sandbox:
+
+shell$ cd sandbox
+shell$ cp -r /somewhere/else/plpa-1.0 .
+shell$ edit acinclude.m4
+...add the line "m4_include(plpa-1.0/config/plpa.m4)"...
+shell$ edit Makefile.am
+...add "plpa-1.0" to SUBDIRS...
+...add "$(top_builddir)/plpa-1.0/src/libplpa/libplpa_included.la" to
+   my executable's LDADD line...
+shell$ edit configure.ac
+...add "PLPA_INCLUDED" line...
+...add "PLPA_SET_SYMBOL_PREFIX(sandbox_plpa_)" line...
+...add "PLPA_INIT(plpa_happy=yes, plpa_happy=no)" line...
+...add error checking for plpa_happy=no case...
+shell$ edit src/my_program.c
+...add #include <plpa.h>...
+...add calls to plpa_sched_setaffinity()...
+shell$ aclocal
+shell$ autoconf
+shell$ libtoolize --automake
+shell$ automake -a
+shell$ ./configure
+...lots of output...
+shell$ make
+...lots of output...
+
+===========================================================================
+
+How can I tell if PLPA is working?
+----------------------------------
+
+Run plpa_info; if it says "PLPA_PROBE_OK", then PLPA is working
+properly.
+
+If you want to compile your own test program to verify it, try
+compiling and running the following:
+
+---------------------------------------------------------------------------
+#include <stdio.h>
+#include <plpa.h>
+
+int main(int argc, char* argv[]) {
+    if (PLPA_PROBE_OK == plpa_api_probe()) {
+        printf("All is good!\n");
+    }
+    return 0;
+}
+---------------------------------------------------------------------------
+
+You may need to supply appropriate -I and -L arguments to the
+compiler/linker, respectively, to tell it where to find the PLPA
+header and library files.  Also don't forget to supply -lplpa to link
+in the PLPA library itself.  For example, if you configured PLPA with:
+
+shell$ ./configure --prefix=$HOME/my-plpa-install
+
+Then you would compile the above program with:
+
+shell$ gcc my-plpa-test.c \
+       -I$HOME/my-plpa-install/include \
+       -L$HOME/my-plpa-install/lib -lplpa \
+       -o my-plpa-test
+shell$ ./my-plpa-test
+
+If it compiles, links, runs, and prints "All is good!", then all
+should be well.
+
+===========================================================================
+
+What license does PLPA use?
+---------------------------
+
+This package is distributed under the BSD license (see the LICENSE
+file in the top-level directory of a PLPA distribution).  The
+copyrights of several institutions appear throughout the code base
+because some of the code was directly derived from the Open MPI
+project (http://www.open-mpi.org/), which is also distributed under
+the BSD license.
+
+===========================================================================
+
+How do I get involved in PLPA?
+------------------------------
+
+Hopefully, PLPA is so simple that it won't need to be modified much
+after its first few releases.  However, it is possible that we'll need
+to modify the run-time test if new variants of the Linux processor
+affinity API emerge.
+
+The best way to report bugs, send comments, or ask questions is to
+sign up on the user's mailing list:
+
+        plpa-users at open-mpi.org
+
+Because of spam, only subscribers are allowed to post to this list
+(ensure that you subscribe with and post from exactly the same e-mail
+address -- joe at example.com is considered different than
+joe at mycomputer.example.com!).  Visit this page to subscribe to the
+list:
+
+     http://www.open-mpi.org/mailman/listinfo.cgi/plpa-users
+
+Thanks for your time.

Added: mlton/branches/shared-heap-multicore/runtime/plpa/README.mlton
===================================================================
--- mlton/branches/shared-heap-multicore/runtime/plpa/README.mlton	2008-03-03 14:42:04 UTC (rev 6431)
+++ mlton/branches/shared-heap-multicore/runtime/plpa/README.mlton	2008-03-03 14:52:04 UTC (rev 6432)
@@ -0,0 +1,3 @@
+
+XXX spoons add readme
+

Added: mlton/branches/shared-heap-multicore/runtime/plpa/VERSION
===================================================================
--- mlton/branches/shared-heap-multicore/runtime/plpa/VERSION	2008-03-03 14:42:04 UTC (rev 6431)
+++ mlton/branches/shared-heap-multicore/runtime/plpa/VERSION	2008-03-03 14:52:04 UTC (rev 6432)
@@ -0,0 +1,36 @@
+# This is the VERSION file for PLPA, describing the precise version of
+# PLPA in this distribution.  The various components of the version
+# number below are combined to form a single version number string.
+
+# major, minor, and release are generally combined in the form
+# <major>.<minor>.<release>.  If release is zero, then it is omitted.
+
+major=1
+minor=0
+release=3
+
+# greek is used for alpha or beta release tags.  If it is non-empty,
+# it will be appended to the version number.  It does not have to be
+# numeric.  Common examples include a1 (alpha release 1), b1 (beta
+# release 1), sc2005 (Super Computing 2005 release).  The only
+# requirement is that it must be entirely printable ASCII characters
+# and have no white space.
+
+greek=
+
+# If want_svn=1, then the SVN r number will be included in the overall
+# PLPA version number in some form.
+
+want_svn=0
+
+# If svn_r=-1, then the SVN r numbere will be obtained dynamically at
+# run time, either 1) via the "svnversion" command (if this is a
+# Subversion checkout) in the form "r<svn_r>", or b) with the date (if
+# this is not a Subversion checkout, and the svnversion command cannot
+# be used) in the form of "svn<date>".  Alternatively, if svn_r is not
+# -1, the value of svn_r will be directly appended to the version
+# string.  This happens during "make dist", for example: if the
+# distribution tarball is being made from an SVN checkout, the value
+# of svn_r in this file is replaced with the output of "svnversion".
+
+svn_r=r58

Added: mlton/branches/shared-heap-multicore/runtime/plpa/plpa.h
===================================================================
--- mlton/branches/shared-heap-multicore/runtime/plpa/plpa.h	2008-03-03 14:42:04 UTC (rev 6431)
+++ mlton/branches/shared-heap-multicore/runtime/plpa/plpa.h	2008-03-03 14:52:04 UTC (rev 6432)
@@ -0,0 +1,78 @@
+/* src/libplpa/plpa.h.  Generated by configure.  */
+/* src/libplpa/plpa.h.in.  Generated from configure.ac by autoheader.  */
+
+/* -*- c -*-
+ *
+ * Copyright (c) 2004-2005 The Trustees of Indiana University.
+ *                         All rights reserved.
+ * Copyright (c) 2004-2005 The Regents of the University of California.
+ *                         All rights reserved.
+ * $COPYRIGHT$
+ *
+ * Additional copyrights may follow
+ *
+ * $HEADER$
+ */
+
+#ifndef PLPA_H
+#define PLPA_H
+
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "http://www.open-mpi.org/community/help/"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "plpa"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "plpa 1.0.1a1"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "plpa"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.0.1a1"
+
+/* The PLPA symbol prefix */
+#define PLPA_SYM_PREFIX plpa_
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+
+#include "plpa_bottom.h"
+#endif /* PLPA_H */
+

Added: mlton/branches/shared-heap-multicore/runtime/plpa/plpa_api_probe.c
===================================================================
--- mlton/branches/shared-heap-multicore/runtime/plpa/plpa_api_probe.c	2008-03-03 14:42:04 UTC (rev 6431)
+++ mlton/branches/shared-heap-multicore/runtime/plpa/plpa_api_probe.c	2008-03-03 14:52:04 UTC (rev 6432)
@@ -0,0 +1,65 @@
+/* -*- c -*-
+ *
+ * Copyright (c) 2004-2005 The Trustees of Indiana University.
+ *                         All rights reserved.
+ * Copyright (c) 2004-2005 The Regents of the University of California.
+ *                         All rights reserved.
+ * $COPYRIGHT$
+ *
+ * Additional copyrights may follow
+ *
+ * $HEADER$
+ */
+
+#include <plpa.h>
+#include <errno.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+/* Cache, just to make things a little more efficient */
+static PLPA_NAME(api_type_t) cache = PLPA_PROBE_UNSET;
+
+/* The len value we find - not in public header, but used by the lib */
+size_t PLPA_NAME(len) = 0;
+
+PLPA_NAME(api_type_t) PLPA_NAME(api_probe)(void) 
+{
+    if (PLPA_PROBE_UNSET == cache) {
+        PLPA_NAME(cpu_set_t) mask;
+        int rc;
+        size_t len;
+
+        for (len = sizeof(mask); len != 0; len >>= 1) {
+            rc = syscall(__NR_sched_getaffinity, 0, len, &mask);
+            if (rc >= 0) {
+                /* OK, kernel is happy with a get().  Validate w/ a set(). */
+                /* Note that kernel may have told us the "proper" size */
+                size_t tmp = (0 != rc) ? ((size_t) rc) : len;
+                /* Pass mask=NULL, expect errno==EFAULT if tmp was OK as a length */
+                rc = syscall(__NR_sched_setaffinity, 0, tmp, NULL);
+                if ((rc < 0) && (errno == EFAULT)) {
+                    cache = PLPA_PROBE_OK;
+                    PLPA_NAME(len) = tmp;
+                    rc = 0;
+                    break;
+                }
+            }
+            if (errno == ENOSYS) {
+                break; /* No point in looping */
+            }
+        }
+        
+        if (rc >= 0) {
+            /* OK */
+        } else if (errno == ENOSYS) {
+            /* Kernel returns ENOSYS because there is no support for
+                processor affinity */
+            cache = PLPA_PROBE_NOT_SUPPORTED;
+        } else {
+            /* Unknown! */
+            cache = PLPA_PROBE_UNKNOWN;
+        }
+    }
+
+    return cache;
+}

Added: mlton/branches/shared-heap-multicore/runtime/plpa/plpa_bottom.h
===================================================================
--- mlton/branches/shared-heap-multicore/runtime/plpa/plpa_bottom.h	2008-03-03 14:42:04 UTC (rev 6431)
+++ mlton/branches/shared-heap-multicore/runtime/plpa/plpa_bottom.h	2008-03-03 14:52:04 UTC (rev 6432)
@@ -0,0 +1,96 @@
+/* -*- c -*-
+ *
+ * Copyright (c) 2004-2005 The Trustees of Indiana University.
+ *                         All rights reserved.
+ * Copyright (c) 2004-2005 The Regents of the University of California.
+ *                         All rights reserved.
+ * $COPYRIGHT$
+ *
+ * Additional copyrights may follow
+ *
+ * $HEADER$
+ */
+
+#ifndef PLPA_BOTTOM_H
+#define PLPA_BOTTOM_H
+
+/* Absolutely must not include <sched.h> here or it will generate
+   conflicts. */
+
+/* For memset() */
+#include <string.h>
+/* For pid_t and size_t */
+#include <sys/types.h>
+
+/***************************************************************************/
+
+/* Internal macro to munge names */
+
+/* Preprocessors are fun -- the double inderection is necessary.
+   Extra bonus points if you can figure out why! :p */
+#define PLPA_MUNGE_NAME(a, b) PLPA_MUNGE_NAME2(a, b)
+#define PLPA_MUNGE_NAME2(a, b) a ## b
+#define PLPA_NAME(name) PLPA_MUNGE_NAME(PLPA_SYM_PREFIX, name)
+
+/***************************************************************************/
+
+/* Values that can be returned from plpa_api_probe() */
+typedef enum {
+    /* Sentinel value */
+    PLPA_PROBE_UNSET,
+    /* sched_setaffinity syscall available */
+    PLPA_PROBE_OK,
+    /* syscall unavailable/unimplemented */
+    PLPA_PROBE_NOT_SUPPORTED,
+    /* we experienced some strange failure that the user should report */
+    PLPA_PROBE_UNKNOWN
+} PLPA_NAME(api_type_t);
+
+/* PLPA bitmask type */
+typedef unsigned long int PLPA_NAME(bitmask_t);
+#define PLPA_BITMASK_T_NUM_BITS (sizeof(PLPA_NAME(bitmask_t)) * 8)
+#define PLPA_BITMASK_CPU_MAX 1024
+#define PLPA_BITMASK_NUM_ELEMENTS (PLPA_BITMASK_CPU_MAX / PLPA_BITMASK_T_NUM_BITS)
+typedef struct { PLPA_NAME(bitmask_t) bitmask[PLPA_BITMASK_NUM_ELEMENTS]; } PLPA_NAME(cpu_set_t);
+
+/***************************************************************************/
+
+/* Internal macro for identifying the byte in a bitmask array */
+#define PLPA_CPU_BYTE(num) (num / PLPA_BITMASK_T_NUM_BITS)
+
+/* Internal macro for identifying the bit in a bitmask array */
+#define PLPA_CPU_BIT(num) (num % PLPA_BITMASK_T_NUM_BITS)
+
+/***************************************************************************/
+
+/* Public macro to zero out a PLPA cpu set */
+#define PLPA_CPU_ZERO(cpuset) \
+    memset(cpuset, 0, sizeof(PLPA_NAME(cpu_set_t)))
+
+/* Public macro to set a bit in a PLPA cpu set */
+#define PLPA_CPU_SET(num, cpuset) \
+    (cpuset)->bitmask[PLPA_CPU_BYTE(num)] |= (1 << PLPA_CPU_BIT(num))
+
+/* Public macro to clear a bit in a PLPA cpu set */
+#define PLPA_CPU_CLR(num, cpuset) \
+    (cpuset)->bitmask[PLPA_CPU_BYTE(num)] &= ~(1 << PLPA_CPU_BIT(num))
+
+/* Public macro to test if a bit is set in a PLPA cpu set */
+#define PLPA_CPU_ISSET(num, cpuset) \
+    (0 != ((cpuset)->bitmask[PLPA_CPU_BYTE(num)] & (1 << PLPA_CPU_BIT(num))))
+
+/***************************************************************************/
+
+/* Check what API is on this machine */
+PLPA_NAME(api_type_t) PLPA_NAME(api_probe)(void);
+
+/* Set processor affinity */
+int PLPA_NAME(sched_setaffinity)(pid_t pid, size_t cpusetsize,
+                                 const PLPA_NAME(cpu_set_t) *cpuset);
+
+/* Get processor affinity */
+int PLPA_NAME(sched_getaffinity)(pid_t pid, size_t cpusetsize,
+                                 PLPA_NAME(cpu_set_t) *cpuset);
+
+#endif /* PLPA_BOTTOM_H */
+

Added: mlton/branches/shared-heap-multicore/runtime/plpa/plpa_dispatch.c
===================================================================
--- mlton/branches/shared-heap-multicore/runtime/plpa/plpa_dispatch.c	2008-03-03 14:42:04 UTC (rev 6431)
+++ mlton/branches/shared-heap-multicore/runtime/plpa/plpa_dispatch.c	2008-03-03 14:52:04 UTC (rev 6432)
@@ -0,0 +1,171 @@
+/* -*- c -*-
+ *
+ * Copyright (c) 2004-2006 The Trustees of Indiana University.
+ *                         All rights reserved.
+ * Copyright (c) 2004-2005 The Regents of the University of California.
+ *                         All rights reserved.
+ * $COPYRIGHT$
+ *
+ * Additional copyrights may follow
+ *
+ * $HEADER$
+ */
+
+#include <errno.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <plpa.h>
+#include <plpa_internal.h>
+
+/*
+ * Call the kernel's setaffinity, massaging the user's input
+ * parameters as necessary
+ */
+int PLPA_NAME(sched_setaffinity)(pid_t pid, size_t cpusetsize,
+                                 const PLPA_NAME(cpu_set_t) *cpuset)
+{
+    int ret;
+    size_t i;
+    PLPA_NAME(cpu_set_t) tmp;
+
+    switch (PLPA_NAME(api_probe)()) {
+    case PLPA_PROBE_OK:
+        /* This shouldn't happen, but check anyway */
+        if (cpusetsize > sizeof(*cpuset)) {
+            return EINVAL;
+        }
+        if (NULL == cpuset) {
+            return EINVAL;
+        }
+
+        /* If the user-supplied bitmask is smaller than what the
+           kernel wants, zero out a temporary buffer of the size that
+           the kernel wants and copy the user-supplied bitmask to the
+           lower part of the temporary buffer.  This could be done
+           more efficiently, but we're looking for clarity/simplicity
+           of code here -- this is not intended to be
+           performance-critical. */
+        if (cpusetsize < PLPA_NAME(len)) {
+            memset(&tmp, 0, sizeof(tmp));
+            for (i = 0; i < cpusetsize * 8; ++i) {
+                if (PLPA_CPU_ISSET(i, cpuset)) {
+                    PLPA_CPU_SET(i, &tmp);
+                }
+            }
+        }
+
+        /* If the user-supplied bitmask is larger than what the kernel
+           will accept, scan it and see if there are any set bits in
+           the part larger than what the kernel will accept.  If so,
+           return EINVAL.  Otherwise, copy the part that the kernel
+           will accept into a temporary and use that.  Again,
+           efficinency is not the issue of this code -- clarity is. */
+        else if (cpusetsize > PLPA_NAME(len)) {
+            for (i = PLPA_NAME(len) * 8; i < cpusetsize * 8; ++i) {
+                if (PLPA_CPU_ISSET(i, cpuset)) {
+                    return EINVAL;
+                }
+            }
+            /* No upper-level bits are set, so now copy over the bits
+               that the kernel will look at */
+            memset(&tmp, 0, sizeof(tmp));
+            for (i = 0; i < PLPA_NAME(len) * 8; ++i) {
+                if (PLPA_CPU_ISSET(i, cpuset)) {
+                    PLPA_CPU_SET(i, &tmp);
+                }
+            }
+        }
+
+        /* Otherwise, the user supplied a buffer that is exactly the
+           right size.  Just for clarity of code, copy the user's
+           buffer into the temporary and use that. */
+        else {
+            memcpy(&tmp, cpuset, cpusetsize);
+        }
+
+        /* Now do the syscall */
+        ret = syscall(__NR_sched_setaffinity, 0, PLPA_NAME(len), &tmp);
+
+        /* Return 0 upon success.  According to
+           http://www.open-mpi.org/community/lists/plpa-users/2006/02/0016.php,
+           all the kernel implementations return >= 0 upon success. */
+        if (ret >= 0) {
+            return 0;
+        } else {
+            return ret;
+        }
+        break;
+
+    case PLPA_PROBE_NOT_SUPPORTED:
+        /* Process affinity not supported here */
+        return ENOSYS;
+        break;
+
+    default:
+        /* Something went wrong */
+        /* JMS: would be good to have something other than EINVAL here
+           -- suggestions? */
+        return EINVAL;
+        break;
+    }
+}
+
+
+/*
+ * Call the kernel's getaffinity, massaging the user's input
+ * parameters as necessary
+ */
+int PLPA_NAME(sched_getaffinity)(pid_t pid, size_t cpusetsize,
+                                PLPA_NAME(cpu_set_t) *cpuset)
+{
+    int ret;
+
+    switch (PLPA_NAME(api_probe)()) {
+    case PLPA_PROBE_OK:
+        /* This shouldn't happen, but check anyway */
+        if (PLPA_NAME(len) > sizeof(*cpuset)) {
+            return EINVAL;
+        }
+        if (NULL == cpuset) {
+            return EINVAL;
+        }
+
+        /* If the user supplied a buffer that is too small, then don't
+           even bother */
+        if (cpusetsize < PLPA_NAME(len)) {
+            return EINVAL;
+        }
+
+        /* Now we know that the user's buffer is >= the size required
+           by the kernel.  If it's >, then zero it out so that the
+           bits at the top are cleared (since they won't be set by the
+           kernel) */
+        if (cpusetsize > PLPA_NAME(len)) {
+            memset(cpuset, 0, sizeof(*cpuset));
+        }
+
+        /* Now do the syscall */
+        ret = syscall(__NR_sched_getaffinity, 0, PLPA_NAME(len), cpuset);
+
+        /* Return 0 upon success.  According to
+           http://www.open-mpi.org/community/lists/plpa-users/2006/02/0016.php,
+           all the kernel implementations return >= 0 upon success. */
+        if (ret >= 0) {
+            return 0;
+        } else {
+            return ret;
+        }
+        break;
+
+    case PLPA_PROBE_NOT_SUPPORTED:
+        /* Process affinity not supported here */
+        return ENOSYS;
+        break;
+
+    default:
+        /* Something went wrong */
+        return EINVAL;
+        break;
+    }
+}
+

Added: mlton/branches/shared-heap-multicore/runtime/plpa/plpa_internal.h
===================================================================
--- mlton/branches/shared-heap-multicore/runtime/plpa/plpa_internal.h	2008-03-03 14:42:04 UTC (rev 6431)
+++ mlton/branches/shared-heap-multicore/runtime/plpa/plpa_internal.h	2008-03-03 14:52:04 UTC (rev 6432)
@@ -0,0 +1,23 @@
+/* -*- c -*-
+ *
+ * Copyright (c) 2004-2005 The Trustees of Indiana University.
+ *                         All rights reserved.
+ * Copyright (c) 2004-2005 The Regents of the University of California.
+ *                         All rights reserved.
+ * $COPYRIGHT$
+ *
+ * Additional copyrights may follow
+ *
+ * $HEADER$
+ */
+
+#ifndef PLPA_INTERNAL_H
+#define PLPA_INTERNAL_H
+
+#include <plpa.h>
+
+/* Cached size of the affinity buffers that the kernel expects */
+extern size_t PLPA_NAME(len);
+
+#endif /* PLPA_INTERNAL_H */
+




More information about the MLton-commit mailing list