Imported libSDF into VOID tree

This commit is contained in:
Guilhem Lavaux 2013-02-27 13:27:23 -05:00
parent c6dd08bd7d
commit 2d09cb68df
55 changed files with 12667 additions and 0 deletions

106
external/libsdf/libmpmy/GNUmakefile vendored Normal file
View file

@ -0,0 +1,106 @@
# Make.$(ARCH) sets many of the variables used below including:
# CC, CFLAGS, AS, RANLIB, objdir, objsuf, asmdir
# This Makefile is 'non-standard' because we are trying to create a .o
# file in the '$(libdir)' directory. Furthermore, the name of the
# file we are creating can't be determined until after we have 'include'd
# the $(ARCH)-specific makefile (so we can use the default PAROS).
#
# The dependencies are even more unreliable than usual.
#
# It's amazing that it works at all...
treedir=..
treedir_sed=\.\.
appexcludes=
libname=NO_NAME
# This is here only to allow 'make depends' to work.
src=mpmy_seq.c mpmy_lsv.c mpmy_nx.c mpmy_vertex.c mpmy_sunmos.c mpmy_mpi.c mpmy_eui.c mpmy_pvm.c mpmy_craypvm.c
special_rule_for_all=YES
all: special
include $(treedir)/Make-common/Make.$(ARCH)
include $(treedir)/Make-common/Make.generic
override CFLAGS:=$(PAROSCFLAGS) $(CFLAGS)
# I think these should be handled with PAROSCFLAGS
# So sue me!
#ifeq ($(PAROS),eui)
#CFLAGS:=-I/usr/lpp/euih/eui $(CFLAGS)
#endif
#ifeq ($(PAROS),mpi)
#CFLAGS:=-I/usr/lpp/mpif $(CFLAGS)
#endif
#ifeq ($(PAROS),srv)
#CFLAGS:=-I$(SRVHOME)/include/cros3 $(CFLAGS)
#endif
#ifeq ($(PAROS),pvm)
#CFLAGS:=-I$(PVM_ROOT)/include $(CFLAGS)
#endif
# order is important here. We need to make $(libdir)
special: $(libdir)/mpmy_$(PAROS)$(objsuf)
$(libdir)/mpmy_$(PAROS)$(objsuf) : $(objdir)/mpmy_$(PAROS)$(objsuf) $(libdir)
cp $< $@
$(objdir)/mpmy_$(PAROS)$(objsuf) : $(objdir)
# If there's a default PAROS for this architecture, then we put
# mpmy_$(PAROS).o into libsw.a. To override it, it is
# necessary to list mpmy_$(alternative).o AHEAD of libsw.a in the
# link command. But if you just want the defaults (typically _seq), then
# the only thing to link against is libsw.a.
ifeq ($(PAROS),$(defaultPAROS))
special: $(libdir)/libsw$(libext)($(objdir)/mpmy_$(PAROS)$(objsuf))
$(RANLIB) $(libdir)/libsw$(libext)
$(libdir)/libsw$(libext)($(objdir)/mpmy_$(PAROS)$(objsuf)) : $(libdir)
endif
# DO NOT DELETE THIS LINE -- make depend depends on it.
$(objdir)/mpmy_seq$(objsuf):
$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/Msgs.h
$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/gccextensions.h $(treedir)/include/libsdf/mpmy.h
$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/timers.h
$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/Assert.h $(treedir)/include/libsdf/error.h
$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/mpmy_io.h $(treedir)/include/libsdf/mpmy_time.h
$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/mpmy_abnormal.h timers_hwclock.c
$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/Malloc.h
$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/chn.h mpmy_io.c
$(objdir)/mpmy_seq$(objsuf):
$(objdir)/mpmy_seq$(objsuf):
$(objdir)/mpmy_seq$(objsuf):
$(objdir)/mpmy_seq$(objsuf):
$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/protos.h iozero.h
$(objdir)/mpmy_seq$(objsuf): iozero.c io_generic.c mpmy_abnormal.c
$(objdir)/mpmy_seq$(objsuf):
$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/singlio.h
$(objdir)/mpmy_seq$(objsuf): mpmy_generic.c
$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/mpmy_abnormal.h
$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/gccextensions.h
$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/Malloc.h $(treedir)/include/libsdf/error.h
$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/chn.h $(treedir)/include/libsdf/Assert.h
$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/mpmy.h $(treedir)/include/libsdf/timers.h
$(objdir)/mpmy_mpi$(objsuf):
$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/Msgs.h $(treedir)/include/libsdf/memfile.h
$(objdir)/mpmy_mpi$(objsuf): timers_hwclock.c
$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/mpmy_time.h
$(objdir)/mpmy_mpi$(objsuf): mpmy_mpiio.c
$(objdir)/mpmy_mpi$(objsuf):
$(objdir)/mpmy_mpi$(objsuf):
$(objdir)/mpmy_mpi$(objsuf):
$(objdir)/mpmy_mpi$(objsuf):
$(objdir)/mpmy_mpi$(objsuf):
$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/protos.h
$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/mpmy_io.h io_generic.c mpmy_abnormal.c
$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/singlio.h
$(objdir)/mpmy_mpi$(objsuf): mpmy_generic.c

59
external/libsdf/libmpmy/io_generic.c vendored Normal file
View file

@ -0,0 +1,59 @@
/* Some i/o routines that are likely to be common... */
#ifndef HAVE_MPMY_FPRINTF
int MPMY_Fprintf(MPMYFile *fp, const char *fmt, ...){
int ret;
va_list ap;
va_start(ap, fmt);
ret = MPMY_Vfprintf(fp, fmt, ap);
va_end(ap);
return ret;
}
#endif
#ifndef HAVE_MPMY_VFPRINTF
#include <stdarg.h>
#include <stdio.h>
static char buf[1024];
int MPMY_Vfprintf(MPMYFile *fp, const char *fmt, va_list args){
/* What a pain. Sometimes sprintf returns a char* and sometimes
it returns an int. There's no good way to tell, but this
should do.*/
long ret = (long)vsprintf(buf, fmt, args);
/* Broken versions of sprintf return their first arg... */
if( ret == (long)buf )
ret = strlen(buf);
if( ret < 0 ){
return ret;
}
if( ret >= sizeof(buf) ){
/* This is serious. We've probably scribbled over memory.
Maybe we should just bail out now?
*/
static int recursion;
if( recursion++ == 0 )
Error("MPMY_Vfprintf overflow. Data corruption likely!\n");
recursion--;
}
if( MPMY_Fwrite(buf, 1, ret, fp) != ret ){
return -1;
}
return ret;
}
#endif
#ifndef HAVE_MPMY_FLUSH
/* This is here just for completeness... The higher levels all do
their I/O using unbuffered primitives (read/write/open/close), so
we don't have to do anything special to flush output */
int MPMY_Fflush(MPMYFile *fp){
return 0;
}
#endif

360
external/libsdf/libmpmy/iozero.c vendored Normal file
View file

@ -0,0 +1,360 @@
/* More include madness. This is such good stuff, that I can't resist */
/* just "#include"ing it into all the mpmy_??io.c files...*/
/* Try to use different tags for the different kinds of broadcasts... */
#define BCAST_CLOSE 0x3579
#define BCAST_OPEN 0x3779
#define BCAST_READ1 0x3979
#define BCAST_READ2 0x3b79
#define BCAST_WRITE 0x3d79
#define BCAST_LSEEK 0x3f79
#define BCAST_TELL 0x4179
#define BCAST_FLEN 0x4379
#define BCAST_MKDIR 0x4579
static int
open0(const char *path, int flags, int mode)
{
int ret;
/* paragon left the const out of the prototype */
Msgf(("open0(path=%s, flags=%#x, mode=%#x\n", path, flags, mode));
if (MPMY_Procnum() == 0){
ret = open((char *)path, flags, mode);
Msgf(("open returns %d on node 0\n", ret));
}
MPMY_BcastTag(&ret, 1, MPMY_INT, 0, BCAST_OPEN);
Msgf(("open0 returning %d\n", ret));
return ret;
}
static int
close0(int fd)
{
int ret;
if (MPMY_Procnum() == 0) ret = close(fd);
MPMY_BcastTag(&ret, 1, MPMY_INT, 0, BCAST_CLOSE);
return ret;
}
static long
read0(int fd, void *buf, unsigned long nbytes)
{
long ret;
if (MPMY_Procnum() == 0){
ret = read(fd, buf, nbytes);
Msgf(("read0: read(fd=%d, nbytes=%ld) returns %ld\n",
fd, nbytes, ret));
}
MPMY_BcastTag(&ret, 1, MPMY_LONG, 0, BCAST_READ1);
Msgf(("read0: after Bcast ret = %ld\n", ret));
if( ret > 0 )
MPMY_BcastTag(buf, ret, MPMY_CHAR, 0, BCAST_READ2);
if( Msg_test(__FILE__)){
int i;
int sum = 0;
char *cbuf = buf;
for(i=0; i<ret; i++){
sum ^= cbuf[i];
}
Msg_do("iozero: Fread(%ld), got %ld, sum=%d\n", nbytes, ret, sum);
}
return ret;
}
static long
write0(int fd, const void *buf, unsigned long nbytes)
{
long ret;
/* paragon left the const out of the prototype */
if (MPMY_Procnum() == 0) ret = write(fd, (void *)buf, nbytes);
MPMY_BcastTag(&ret, 1, MPMY_INT, 0, BCAST_WRITE);
return ret;
}
static off_t
lseek0(int fd, off_t offset, int whence)
{
off_t ret;
if (MPMY_Procnum() == 0) ret = lseek(fd, offset, whence);
MPMY_BcastTag(&ret, 1, MPMY_OFFT, 0, BCAST_LSEEK);
return ret;
}
static off_t
tell0(int fd)
{
off_t ret;
if (MPMY_Procnum() == 0) ret = lseek(fd, 0L, SEEK_CUR);
MPMY_BcastTag(&ret, 1, MPMY_OFFT, 0, BCAST_TELL);
return ret;
}
static off_t
flen(int fd)
{
off_t ret;
ret = lseek(fd, 0, SEEK_END);
Msg_do("lseek on %d returns %ld, errno is %d\n", fd, ret, errno);
return ret;
}
static off_t
flen0(int fd)
{
off_t ret;
if (MPMY_Procnum() == 0) {
ret = flen(fd);
Msgf(("flen0 of %d returns %ld\n", fd, (long)ret));
}
MPMY_BcastTag(&ret, 1, MPMY_OFFT, 0, BCAST_FLEN);
return ret;
}
static int
mkdir0(const char *path, int mode){
#if defined(__SUNMOS__) || defined(__AP1000__)
return -1;
#else
int ret;
if( MPMY_Procnum() == 0 ){
ret = mkdir(path, mode);
if( ret && errno == EEXIST ){
/* Let's just pretend we really made it... */
ret = 0;
}
}
MPMY_BcastTag(&ret, 1, MPMY_INT, 0, BCAST_MKDIR );
return ret;
#endif
}
static long
fseekrd0(int fd, off_t offset, int whence, void *buf, int reclen,
int nrecs)
{
int doseek;
int real_whence;
void *tmpbuf;
int i;
long nread;
off_t len;
struct {
off_t offset;
long whence;
long reclen;
long nrecs;
} parbuf, *allbuf;
Msgf(("fseekrd0: (fd=%d, offset=%ld, whence=%d, buf=%p, reclen=%d, nrecs=%d)\n",
fd, offset, whence, buf, reclen, nrecs));
parbuf.offset = offset;
parbuf.whence = whence;
parbuf.reclen = reclen;
parbuf.nrecs = nrecs;
if (MPMY_Procnum() == 0) {
allbuf = Malloc(sizeof(parbuf)*MPMY_Nproc());
MPMY_Gather(&parbuf, sizeof(parbuf), MPMY_CHAR, allbuf,0);
tmpbuf = Malloc(reclen*nrecs);
for (i = 0; i < MPMY_Nproc(); i++) {
offset = allbuf[i].offset;
whence = allbuf[i].whence;
reclen = allbuf[i].reclen;
nrecs = allbuf[i].nrecs;
if( whence == MPMY_SEEK_CUR ){
/* I'm not sure this is a well-defined operation */
doseek = (offset != 0);
}else if( whence == MPMY_SEEK_SET ){
off_t cur_off = lseek(fd, 0, SEEK_CUR);
if (cur_off < 0){
static int issued_seek_warning;
if( errno == ESPIPE ){
if( !issued_seek_warning ){
SeriousWarning("fseekrd: Can't seek on a pipe.\nAssuming the seek is a no-op. Good luck. You will not be warned again\n");
issued_seek_warning = 1;
}
}else{
Error("fseekrd: lseek(%d, 0, SEEK_CUR) failed, errno=%d\n",
fd, errno);
}
doseek = 0;
}else{
doseek = (offset != cur_off);
}
}else{
doseek = 1;
}
if( doseek ){
switch(whence){
case MPMY_SEEK_SET:
real_whence = SEEK_SET;
break;
case MPMY_SEEK_CUR:
real_whence = SEEK_CUR;
break;
case MPMY_SEEK_END:
real_whence = SEEK_END;
break;
default:
Error("Illegal value of whence (%d) in fseekrd\n", whence);
}
if (lseek(fd, offset, real_whence) == -1L) {
Error("fseekrd: cycle %d lseek(%d, %ld, %d) failed, errno=%d\n",
i, fd, offset, whence, errno);
}
}
len = 0;
while (len < reclen*nrecs) {
nread = read(fd, (char *)tmpbuf+len, reclen*nrecs-len);
if (nread == -1) {
Error("fseekrd: read(%d, %ld) failed, errno=%d\n",
fd, reclen*nrecs-len, errno);
} else if (nread == 0) {
Error("fseekrd: read(%d, %ld) got EOF\n",
fd, reclen*nrecs-len);
} else {
Msgf(("fseekrd: got %ld\n", nread));
len += nread;
}
}
if (len != reclen*nrecs) {
Error("fseekrd: Wrong amount of data\n");
}
if (i) {
MPMY_send(tmpbuf, reclen*nrecs, i, MPMY_IOTAG);
} else {
memcpy(buf, tmpbuf, reclen*nrecs);
}
}
Free(tmpbuf);
Free(allbuf);
} else {
MPMY_Gather(&parbuf, sizeof(parbuf)/sizeof(long), MPMY_LONG, NULL, 0);
MPMY_recvn(buf, reclen*nrecs, 0, MPMY_IOTAG);
}
return parbuf.nrecs;
}
#define MAX_IOBUF (64*1024*1024)
static long
write0_multi(int fd, const void *buf, off_t nbytes)
{
long ret;
off_t *sizes;
int i, n, sync;
char *tmpbuf = 0;
off_t total_bytes;
int nproc = MPMY_Nproc();
int procnum = MPMY_Procnum();
MPMY_Combine(&nbytes, &total_bytes, 1, MPMY_OFFT, MPMY_SUM);
Msgf(("write0_multi, nbytes is %ld, total_bytes is %ld\n", nbytes, total_bytes));
/* If the total is small enough, we might as well concat it on proc 0 */
if (total_bytes <= MAX_IOBUF) {
MPMY_NGather(buf, nbytes, MPMY_CHAR, (void **)&tmpbuf, 0);
if (procnum == 0) {
ret = write(fd, tmpbuf, total_bytes);
if (ret != total_bytes) Error("write failed, errno=%d\n", errno);
Msgf(("write0 %ld (one block)\n", ret));
Free(tmpbuf);
}
return nbytes;
} else if (procnum == 0) {
sizes = Malloc(sizeof(off_t)*nproc);
MPMY_Gather(&nbytes, 1, MPMY_OFFT, sizes, 0);
ret = 0;
while (nbytes > 0) {
off_t nwrite = (nbytes > MAX_IOBUF) ? MAX_IOBUF : nbytes;
off_t wrote;
wrote = write(fd, buf+ret, nwrite);
if (wrote != nwrite) Shout("write failed, errno=%d\n", errno);
ret += wrote;
nbytes -= wrote;
}
Msgf(("write0 %ld\n", ret));
if (nproc > 1) {
tmpbuf = Malloc(nbytes);
for (i = procnum+1; i < nproc; i++) {
/* This could be double-buffered */
tmpbuf = Realloc(tmpbuf, sizes[i]);
/* Avoid deluge of messages by sync */
MPMY_send(&sync, sizeof(int), i, MPMY_IOTAG);
MPMY_recvn(tmpbuf, sizes[i], i, MPMY_IOTAG);
n = write(fd, tmpbuf, sizes[i]);
if (n != sizes[i]) Shout("write failed, errno=%d\n", errno);
Msgf(("write%d %d\n", i, n));
/* should we send errno as well? */
MPMY_send(&n, sizeof(int), i, MPMY_IOTAG);
}
Free(tmpbuf);
}
Free(sizes);
} else {
MPMY_Gather(&nbytes, 1, MPMY_OFFT, NULL, 0);
MPMY_recvn(&sync, sizeof(int), 0, MPMY_IOTAG);
Msgf(("sending %ld bytes\n", nbytes));
MPMY_send(buf, nbytes, 0, MPMY_IOTAG);
MPMY_recvn(&ret, sizeof(int), 0, MPMY_IOTAG);
}
return ret;
}
static long
read0_multi(int fd, void *buf, off_t nbytes)
{
int ret;
off_t *sizes;
int i, n;
char *tmpbuf;
int nproc = MPMY_Nproc();
int procnum = MPMY_Procnum();
if (sizeof(off_t) != sizeof(long long)) {
Error("Type problem in write0_multi\n");
}
if (procnum == 0) {
sizes = Malloc(sizeof(off_t)*nproc);
MPMY_Gather(&nbytes, 1, MPMY_OFFT, sizes, 0);
ret = read(fd, buf, nbytes);
if (ret != nbytes) Shout("read failed, errno=%d\n", errno);
Msgf(("read0 %d\n", ret));
if (nproc > 1) {
tmpbuf = Malloc(nbytes);
for (i = procnum+1; i < nproc; i++) {
/* This could be double-buffered */
tmpbuf = Realloc(tmpbuf, sizes[i]);
n = read(fd, tmpbuf, sizes[i]);
MPMY_send(tmpbuf, n, i, MPMY_IOTAG);
if (n != sizes[i]) Shout("read failed, errno=%d\n", errno);
Msgf(("read%d %d\n", i, n));
}
Free(tmpbuf);
}
Free(sizes);
} else {
MPMY_Status stat;
MPMY_Comm_request req;
MPMY_Gather(&nbytes, 1, MPMY_OFFT, NULL, 0);
MPMY_Irecv(buf, nbytes, 0, MPMY_IOTAG, &req);
MPMY_Wait(req, &stat);
ret = MPMY_Count(&stat);
}
return ret;
}

20
external/libsdf/libmpmy/iozero.h vendored Normal file
View file

@ -0,0 +1,20 @@
#ifndef IOzeroDOTh
#define IOzeroDOTh
#define MPMY_IOTAG (0x183)
#define IoZero(fp) (fp->flags & MPMY_IOZERO)
static int open0(const char *path, int flags, int mode);
static int close0(int fd);
static int mkdir0(const char *path, int mode);
static long read0(int fd, void *buf, unsigned long nbytes);
static long write0(int fd, const void *buf, unsigned long nbytes);
static off_t lseek0(int fd, off_t offset, int whence);
static off_t tell0(int fd);
static off_t flen(int fd);
static off_t flen0(int fd);
static long fseekrd0(int fd, off_t offset, int whence, void *buf,
int reclen, int nrecs);
static long write0_multi(int fd, const void *buf, off_t nbytes);
static long read0_multi(int fd, void *buf, off_t nbytes);
#endif

View file

@ -0,0 +1,2 @@

259
external/libsdf/libmpmy/mpmy_abnormal.c vendored Normal file
View file

@ -0,0 +1,259 @@
/* Yet another attempt to rationalize the abnormal termination of
parallel programs.
Issues to consider:
- Do core files exist, and are they useful.
- Do we need to chdir before dumping a core file.
- Exactly how do we go about dumping a core file.
- Do we want to do anything else before quitting.
- Sometimes we get the most information when we just return
from a signal handler (delta).
- Parts will need to be over-ridden by mpmy_<paros>.c, but
duplication of code should be minimized.
- include files, values of signals, etc. are all wildly system
specific.
*/
#include <signal.h>
#include <stdlib.h>
#include "singlio.h"
#include "Msgs.h"
#include "mpmy_abnormal.h"
#ifndef MPMY_ABORT
void MPMY_Abort(void){
MPMY_RaiseAbnormal(SIGABRT);
MPMY_SystemAbort();
}
#endif
#ifdef _AIX
/* dje says AIX dumps core fine, but the debuggers are confused by
the signal handlers. Another way of achieving this might be
to set absiglist and MPMY_HAVE_ABSIGLIST in the mpmy_paros.c file. */
#define NO_SIGNALS
#endif
#if !defined( HAVE_ABSIG_LIST ) && !defined(NO_SIGNALS)
static int absiglist[]={
#if 0 && defined(SIGABRT) /* ANSI */
/* DO NOT TRAP SIGABRT! Just leave it completely alone. We studiously
avoid calling abort in our code, so we should just let SIGABRT do its
normal, unmodified thing. */
SIGABRT,
#endif
#ifdef SIGFPE /* ANSI */
SIGFPE,
#endif
#ifdef SIGIILL /* ANSI */
SIGILL,
#endif
#ifdef SIGIOT /* ANSI */
SIGIOT,
#endif
#ifdef SIGSEGV /* ANSI */
SIGSEGV,
#endif
#ifdef SIGQUIT
SIGQUIT,
#endif
#ifdef SIGTRAP
SIGTRAP,
#endif
#ifdef SIGEMT
SIGEMT,
#endif
#ifdef SIGKILL
SIGKILL, /* for form's sake */
#endif
#ifdef SIGBUS
SIGBUS,
#endif
#ifdef SIGSYS
SIGSYS,
#endif
#ifdef SIGPIPE
SIGPIPE,
#endif
/* Do we need to worry about a trailing comma?? */
};
#endif /* HAVE_ABSIGLIST */
#ifndef HAVE_SETUP_ABSIGS
void _MPMY_setup_absigs(void){
int i;
#if !defined(NO_SIGNALS)
for(i=0; i< sizeof(absiglist)/sizeof(*absiglist); i++){
signal(absiglist[i], MPMY_RaiseAbnormal);
}
#endif
}
#endif
#ifndef HAVE_ABNORMAL
#define MAXUSERFUNCS 64
static int nuserfuncs = 0;
static Abhndlr userfuncs[MAXUSERFUNCS];
/* Lots of functions are suitable for use as userfuncs to be called in
the event of abnormal termination. These might include:
malloc_print();
PrintMemfile();
PrintMPMYDiags();
Msg_flush();
MPMY_abchdir(); (with MPMY_abchdir_arg set beforehand)
MPMY_SystemAbort();
MPMY_SystemExit(); (with MPMY_exit_arg set beforehand)
MPMY_Abannounce();
They are called in the reverse chronological order, so later functions
might 'override' earlier ones. This isn't perfect, but it's better than
the monolithic handler we had before.
*/
void MPMY_OnAbnormal(Abhndlr hndlr){
if(nuserfuncs < MAXUSERFUNCS)
userfuncs[nuserfuncs++] = hndlr;
}
int MPMY_Abnormal_signum;
int MPMY_stop_abnormal_processing;
void MPMY_RaiseAbnormal(int sig){
int i;
MPMY_Abnormal_signum = sig;
MPMY_stop_abnormal_processing = 0;
/* Just cycle through the 'user' functions. */
for(i=nuserfuncs-1; i>=0 && !MPMY_stop_abnormal_processing; i--){
(*userfuncs[i])();
}
MPMY_Abnormal_signum = 0;
}
#endif
#ifndef HAVE_SYSTEM_ABORT
void MPMY_SystemAbort(void){
/* This should be unnecessary, since we didn't trap SIGABRT above. */
signal(SIGABRT, SIG_DFL);
abort();
}
#endif
#ifndef HAVE_SYSTEM_EXIT
int MPMY_exit_arg = 0;
void MPMY_SystemExit(void){
exit(MPMY_exit_arg);
}
#endif
#ifndef HAVE_MPMY_CHDIR
/* This is pretty generic, but if the system can't even link against
mkdir and chdir, then it will be necessary to override this with
a noop in the PAROS-specific file. */
#include <unistd.h>
#ifndef __INTEL_SSD__ /* Intel's headers aren't safe for multiple inclusion! */
#include <sys/stat.h>
#endif
#include <errno.h>
char MPMY_Abchdir_arg[128];
/* Suitable for use as a userfunc */
void MPMY_Abchdir(void){
if( strlen(MPMY_Abchdir_arg) ){
errno=0;
if( mkdir(MPMY_Abchdir_arg, 0777) && errno != EEXIST ){
Msg_do("Can't mkdir(\"%s\"): %d\n", MPMY_Abchdir_arg, errno);
}
errno = 0;
if( chdir(MPMY_Abchdir_arg) ){
Msg_do("Can't chdir(\"%s\"): %d\n", MPMY_Abchdir_arg, errno);
}else{
Msg_do("New directory: \"%s\"\n", MPMY_Abchdir_arg);
}
}
}
#endif
#ifndef HAVE_ABANNOUNCE
void MPMY_Abannounce(void){
static int announced;
/* Don't repeat yourself! */
if (!announced){
Msg_do("MPMY_ABNORMAL_SIGNUM: %d\n", MPMY_Abnormal_signum);
MPMY_Diagnostic(Msg_do);
}
Msg_flush();
announced = 1;
}
#endif
#ifndef HAVE_PRINTMPMY_DIAGS
void PrintMPMYDiags(void){
MPMY_Diagnostic(Msg_do);
}
#endif
#ifndef HAVE_MPMY_TIMEOUT
/* Aieeee!!! Some systems can link alarm, but when the execute it,
they die (cm5). Other systems can't even link it (sunmos, ap1000).
Others will crash mysteriously if they use alarm (lsv). This isn't
really a PAROS thing, and it's not really ARCH either. Aargh. */
#ifdef CANT_USE_ALARM
#define HAVE_MPMY_TIMEOUT
void
MPMY_TimeoutSet(int n){
SinglWarning("Can't use alarm(). Timeout not set!\n");
}
void
MPMY_TimeoutReset(int n){
return;
}
void
MPMY_TimeoutCancel(void){
return;
}
#else /* CANT_USE_ALARM */
static int nt;
static void
alrm_hndlr(int sig)
{
/* Should this be Shout followed by MPMY_RaiseAbnormal()?? */
Error("Exceeded timeout (%d sec)\n", nt);
}
void
MPMY_TimeoutSet(int n)
{
void (*prev_sig)(int);
prev_sig = signal(SIGALRM, alrm_hndlr);
if( prev_sig == SIG_DFL || prev_sig == NULL || prev_sig == SIG_IGN ){
singlPrintf("Setting timeout to %d seconds.\n", n);
alarm(n);
nt = n;
}else{
singlPrintf("There is already a handler for SIGALRM at %p\n",
prev_sig);
singlPrintf("NOT setting timeout!\n");
signal(SIGALRM, prev_sig);
}
}
void
MPMY_TimeoutReset(int n)
{
alarm(n);
nt = n;
}
void
MPMY_TimeoutCancel(void)
{
alarm(0);
signal(SIGALRM, SIG_DFL);
}
#endif /* CANT_USE_ALARM */
#endif /* HAVE_MPMY_TIMEOUT */

286
external/libsdf/libmpmy/mpmy_generic.c vendored Normal file
View file

@ -0,0 +1,286 @@
/* This file is included in most (all?) of the mpmy_PAROS files.
It defines several of the required mpmy functions in terms of a
more primitive set. In some cases, however, there will be a PAROS
specific way to achieve these results defined in the mpmy_PAROS file
When that happens, the mpmy_PAROS file will also
#define HAVE_MPMY_FUNCNAME
so we know that we shouldn't define it here. */
/* These are set to the "right" thing on a uniprocessor, where it is
most likely that we will neglect to call MPMY_Init, but where
we really can proceed without any problems. I tried
setting them to -1, but that just led to hard-to-understand
crashes. We really should test occasionally that MPMY_Init has
been called. But I'll leave that for another day... */
int _MPMY_procnum_ = 0;
int _MPMY_nproc_ = 1;
int _MPMY_procs_per_node_ = 1;
int _MPMY_initialized_ = 0;
Counter_t MPMYSendCnt;
Counter_t MPMYRecvCnt;
Counter_t MPMYDoneCnt;
#ifndef HAVE_MPMY_FLICK
int MPMY_Flick(void){return MPMY_SUCCESS;}
#endif /* HAVE_MPMY_FLICK */
#ifndef HAVE_MPMY_IRSEND
int MPMY_Irsend(const void *buf, int cnt, int dest, int tag, MPMY_Comm_request *req){
return MPMY_Isend(buf, cnt, dest, tag, req);
}
#endif /* HAVE_MPMY_IRSEND */
#ifndef HAVE_MPMY_SHIFT
/* An implementation of shift that just uses mpmy_isend/irecv */
/* Some systems will have a better option, but this should always work. */
#define SHIFT_TAG 0x1492
/* Because NX can't distinguish different sources when reading */
/* messages, we help it out by adding processor info to the tag. */
/* Is this really necessary for the "generic" implementation? */
int MPMY_Shift(int proc, void *recvbuf, int recvcnt,
const void *sendbuf, int sendcnt, MPMY_Status *stat){
MPMY_Comm_request inreq, outreq;
Msgf(("Starting MPMY_Shift(proc=%d, recvcnt=%d, sendcnt=%d:\n",
proc, recvcnt, sendcnt));
if (proc > _MPMY_procnum_) {
MPMY_Irecv(recvbuf, recvcnt, proc, SHIFT_TAG+proc, &inreq);
Msgf(("Irecv posted\n"));
MPMY_Wait(inreq, stat);
Msgf(("Irecv done\n"));
MPMY_Isend(sendbuf, sendcnt, proc, SHIFT_TAG+MPMY_Procnum(), &outreq);
Msgf(("Isend posted\n"));
MPMY_Wait(outreq, NULL);
Msgf(("Isend done\n"));
} else {
MPMY_Isend(sendbuf, sendcnt, proc, SHIFT_TAG+MPMY_Procnum(), &outreq);
Msgf(("Isend posted\n"));
MPMY_Wait(outreq, NULL);
Msgf(("Isend done\n"));
MPMY_Irecv(recvbuf, recvcnt, proc, SHIFT_TAG+proc, &inreq);
Msgf(("Irecv posted\n"));
MPMY_Wait(inreq, stat);
Msgf(("Irecv done\n"));
}
Msgf(("Finished MPMY_Shift\n"));
return MPMY_SUCCESS;
}
#endif /* HAVE_MPMY_SHIFT */
/*
This could be smarter. In particular, it could recover gracefully
from malloc failing to deliver.
*/
#ifndef HAVE_MPMY_SHIFT_OVERLAP
#include "Malloc.h"
#include <stdlib.h>
int MPMY_Shift_overlap(int proc, void *recvbuf, int recvcnt,
const void *sendbuf, int sendcnt, MPMY_Status *stat){
void *tmp = Malloc(sendcnt);
int ret;
if( tmp == NULL && sendcnt>0 )
return MPMY_FAILED;
memcpy(tmp, sendbuf, sendcnt);
ret = MPMY_Shift(proc, recvbuf, recvcnt, tmp, sendcnt, stat);
Free(tmp);
return ret;
}
#endif /* HAVE_MPMY_SHIFT_OVERLAP */
#ifndef HAVE_MPMY_SYNC
/* Implementation of MPMY_Sync in terms of the 'combine' functions. */
/* Some systems might provide a more useful interface. */
int MPMY_Sync(void){
int junk=0;
/* I'm sure this is overkill! */
return MPMY_Combine(&junk, &junk, 1, MPMY_INT, MPMY_BOR);
}
#endif
#ifndef HAVE_MPMY_FINALIZE
/* Any system specific stuff gets handled by a system-specific finalizer */
int MPMY_Finalize(void){
return MPMY_SUCCESS;
}
#endif
#ifndef HAVE_MPMY_WAIT
/* An implementation of mpmy_wait that just busy-waits on MPMY_Test. */
/* Some systems will have a better option, but this should always work. */
int MPMY_Wait(MPMY_Comm_request req, MPMY_Status *stat){
/* Should we do a 'MPMY_Flick'' ? */
int flag = 0;
int ret;
do{
MPMY_Flick();
ret = MPMY_Test(req, &flag, stat);
}while( ret == MPMY_SUCCESS && flag==0 );
return ret;
}
#endif /* HAVE_MPMY_WAIT */
#ifndef HAVE_MPMY_WAIT2
int MPMY_Wait2(MPMY_Comm_request req1, MPMY_Status *stat1,
MPMY_Comm_request req2, MPMY_Status *stat2){
/* Should we do a 'MPMY_Flick'' ? */
int done1, done2;
int ret;
done1 = done2 = 0;
do{ /* loop until at least one is finished */
MPMY_Flick();
ret = MPMY_Test(req1, &done1, stat1);
if( ret != MPMY_SUCCESS )
return ret;
ret = MPMY_Test(req2, &done2, stat2);
if( ret != MPMY_SUCCESS )
return ret;
}while( done1 == 0 && done2 == 0 );
/* Now there's only one left, so we can call MPMY_Wait */
if( !done1 ){
ret = MPMY_Wait(req1, stat1);
if( ret != MPMY_SUCCESS )
return ret;
}
if( !done2 ){
ret = MPMY_Wait(req2, stat2);
if( ret != MPMY_SUCCESS )
return ret;
}
return MPMY_SUCCESS;
}
#endif
#ifndef HAVE_MPMY_DIAGNOSTIC
void MPMY_Diagnostic(int (*printflike)(const char *, ...)){
(*printflike)("No Diagnostic info for this MPMY\n");
}
#endif
#ifndef HAVE_MPMY_INITIALIZED
int MPMY_Initialized(void){
return _MPMY_initialized_;
}
#endif
#ifndef HAVE_MPMY_PHYSNODE
const char *MPMY_Physnode(void){
return "?";
}
#endif
#ifndef HAVE_MPMY_TIMERS
/* This is a nightmare! Timers should really be ARCH dependent */
/* but because of the CM5's special closeness to ARCH=sun4, they */
/* are PAROS dependent, instead. That means that we would otherwise */
/* repeat this code block in lots of mpmy_PAROS.c files */
#ifdef _AIX
/* No longer working?? Nov 3 1994
# include "timers_readrtc.c" */
#if !defined(USE_HWCLOCK) && !defined(USE_GETTIME)
#include "timers_posix.c"
#endif
/* it's not inconceivable to compile sequentially for the intels */
/* However, we won't necessarily be linking against, e.g, hwclock
#elif defined(__INTEL_SSD__)
# include "timers_nx.c"
*/
#else
#if !defined(USE_HWCLOCK) && !defined(USE_GETTIME)
# include "timers_posix.c"
#endif
#endif /* _AIX */
#endif /* HAVE_MPMY_TIMERS */
static time_t job_start;
static time_t job_end;
static time_t checkpoint_last;
static time_t checkpoint_next;
static time_t checkpoint_interval;
static int checkpoint_setup;
void
MPMY_CheckpointSetup(int job_seconds, int interval_seconds, int step_seconds)
{
if (MPMY_Procnum() == 0) {
job_start = time(NULL);
if (job_seconds == -1) job_end = -1;
else job_end = job_start + job_seconds - step_seconds;
checkpoint_interval = interval_seconds - step_seconds;
checkpoint_last = job_start;
checkpoint_next = job_start + checkpoint_interval;
Msg_do("Checkpoint Setup interval %ld start %ld next %ld end %ld\n",
checkpoint_interval, job_start, checkpoint_next, job_end);
}
checkpoint_setup = 1;
}
int
MPMY_CheckpointDue(int next_output_seconds)
{
time_t t;
int retval = 0;
if (MPMY_Procnum() == 0) {
t = time(NULL);
if (t >= checkpoint_next) retval = 1;
if (next_output_seconds < checkpoint_interval/4) {
Msg_do("Postponing checkpoint since output expected in %d seconds\n",
next_output_seconds);
retval = 0;
}
if (job_end > 0 && t >= job_end) retval = 1;
}
if (retval) Msg_do("Checkpoint Due\n");
MPMY_Bcast(&retval, 1, MPMY_INT, 0);
return retval;
}
void
MPMY_CheckpointFinished(void)
{
time_t t;
if (MPMY_Procnum() == 0) {
t = time(NULL);
checkpoint_last = t;
checkpoint_next = t + checkpoint_interval;
if (job_end > 0 && checkpoint_next > job_end) checkpoint_next = job_end;
Msg_do("next checkpoint %ld (%ld from now)\n", checkpoint_next, checkpoint_next-t);
}
}
int
MPMY_JobDone(void)
{
time_t t;
int retval = 0;
if (MPMY_Procnum() == 0) {
t = time(NULL);
if (job_end > 0 && t >= job_end) {
retval = 1;
Msg_do("Job Done\n");
}
}
MPMY_Bcast(&retval, 1, MPMY_INT, 0);
return retval;
}
#ifndef HAVE_MPMY_JOBREMAINING
int
MPMY_JobRemaining(void)
{
return -1;
}
#endif

525
external/libsdf/libmpmy/mpmy_io.c vendored Normal file
View file

@ -0,0 +1,525 @@
/* The default I/O model here is that only proc 0 can read/write etc. */
/* There are two I/O modes for read and write, MULTI and SINGL */
/* All other functions do not have an I/O mode associated with them */
/* All calls must be loosely synchronous. There is a single file pointer */
/* This model works on all machines, but it may not be the most efficient */
/* MPMY_NFILE extends the mpmy_io model to include multiple file segments */
#include <stdarg.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "Assert.h"
#include "protos.h"
#include "mpmy.h"
#include "mpmy_io.h"
#include "Msgs.h"
#include "Malloc.h"
#include "iozero.h"
#ifndef EINVAL
/* just in case... */
#define EINVAL 0
#endif
#define NFILES 4096
static struct _File{
int fd;
int iomode;
int iotype;
} _files[NFILES];
#define DEFAULT_PERMS 0644
static int do_nfileio;
int
MPMY_Nfileio(int val){
int oldval = do_nfileio;
do_nfileio = val;
return oldval;
}
int
MPMY_SetIOMode(MPMYFile *Fp, int iomode)
{
struct _File *fp = (struct _File *)Fp;
fp->iomode = iomode;
return 0;
}
MPMYFile *
MPMY_Fopen(const char *path, int mpmy_flags)
{
int fd;
int flags = 0;
int iomode = MPMY_SINGL;
int iotype = 0;
Msgf(("Fopen %s\n", path));
if (mpmy_flags & MPMY_RDONLY) flags |= O_RDONLY;
if (mpmy_flags & MPMY_WRONLY) flags |= O_WRONLY;
if (mpmy_flags & MPMY_RDWR) flags |= O_RDWR;
if (mpmy_flags & MPMY_APPEND) flags |= O_APPEND;
if (mpmy_flags & MPMY_TRUNC) flags |= O_TRUNC;
if (mpmy_flags & MPMY_CREAT) flags |= O_CREAT;
if (mpmy_flags & MPMY_MULTI) iomode = MPMY_MULTI;
if (mpmy_flags & MPMY_SINGL) iomode = MPMY_SINGL;
/* This is a sub-mode which can work with either of the above */
if (mpmy_flags & MPMY_NFILE) iotype = MPMY_NFILE;
if (mpmy_flags & MPMY_INDEPENDENT) {
iotype = MPMY_INDEPENDENT;
iomode = MPMY_MULTI;
}
/* We need an external control for nfile mode */
if (do_nfileio) iotype = MPMY_NFILE;
if (iotype == MPMY_NFILE) {
char real_path[256];
sprintf(real_path, "%s.p%03d", path, MPMY_Procnum());
fd = open(real_path, flags, DEFAULT_PERMS);
} else if (iotype == MPMY_INDEPENDENT) {
fd = open(path, flags, DEFAULT_PERMS);
} else {
if( strcmp(path, "-") != 0 ){
fd = open0(path, flags, DEFAULT_PERMS);
}else{
/* Be very afraid. */
/* We made MPMY_RDONLY zero because O_RDONLY==0. But why
did 'they' do that?! */
if ( (mpmy_flags & MPMY_RDWR) )
Error("Can't open '-' RDWR\n");
#if MPMY_RDONLY != 0
# error Aargh.
#endif
if(mpmy_flags & MPMY_WRONLY )
fd = 1; /* stdout */
else /* we can't test for MPMY_RDONLY! */
fd = 0; /* stdout */
}
}
if (fd >= NFILES) Error("fd too large (%d)\n", fd);
if(fd >= 0){
_files[fd].iomode = iomode;
_files[fd].iotype = iotype;
_files[fd].fd = fd;
Msgf(("Fopen returns %d, iomode=%d, flags=0x%x\n", fd, iomode, flags));
return &(_files[fd]);
}else{
Msgf(("Fopen fails, errno=%d\n", errno));
return NULL;
}
}
int
MPMY_Fclose(MPMYFile *Fp)
{
struct _File *fp = (struct _File *)Fp;
int ret;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (fp->iotype & MPMY_NFILE || fp->iotype & MPMY_INDEPENDENT) {
ret = close(fp->fd);
} else {
ret = close0(fp->fd);
}
fp->fd = -1;
Msgf(("Close returns %d\n", ret));
return ret;
}
int
MPMY_Mkdir(const char *path, int mode){
return mkdir0(path, mode);
}
size_t
MPMY_Fread(void *ptr, size_t size, size_t nitems, MPMYFile *Fp)
{
struct _File *fp = (struct _File *)Fp;
ssize_t ret = -1;
Msgf(("Fread(ptr=%p, size=%ld, nitems=%ld, FILE=%p)\n",
ptr, size, nitems, Fp));
Msg_flush();
if( fp == NULL ){
errno = EINVAL;
return -1;
}
switch (fp->iomode) {
case MPMY_SINGL:
ret = read0(fp->fd, ptr, (long)size*nitems);
break;
case MPMY_MULTI:
if (fp->iotype & MPMY_NFILE || fp->iotype & MPMY_INDEPENDENT)
ret = read(fp->fd, ptr, (long)size*nitems);
else
ret = read0_multi(fp->fd, ptr, (long)size*nitems);
break;
default:
ret = -1;
break;
}
Msgf(("Fread returns %ld.\n", ret));
if( ret < 0 ){
Warning("MPMY_Fread: read returns %ld, errno=%d\n", ret, errno);
return -1;
}
if (ret % size)
Shout("MPMY_Fread has a problem, ret=%ld, size=%ld\n", ret, size);
return ret/size;
}
size_t
MPMY_Fwrite(const void *ptr, size_t size, size_t nitems, MPMYFile *Fp)
{
struct _File *fp = (struct _File *)Fp;
ssize_t ret = -1;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
switch (fp->iomode) {
case MPMY_SINGL:
ret = write0(fp->fd, ptr, size*nitems);
break;
case MPMY_MULTI:
if (fp->iotype & MPMY_NFILE || fp->iotype & MPMY_INDEPENDENT)
ret = write(fp->fd, ptr, size*nitems);
else
ret = write0_multi(fp->fd, ptr, size*nitems);
break;
default:
ret = -1;
Shout("Bad iomode in Fwrite\n");
}
Msgf(("Fwrite returns %ld.\n", ret));
if( ret < 0 ){
Warning("MPMY_Fwrite: write returns %ld, errno=%d\n", ret, errno);
return -1;
}
if (ret % size)
Shout("MPMY_Fwrite has a problem: ret=%ld, size=%ld\n", ret, size);
return ret/size;
}
off_t
MPMY_Fseek(MPMYFile *Fp, off_t offset, int whence)
{
struct _File *fp = (struct _File *)Fp;
off_t ret;
int real_whence = 0;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (whence == MPMY_SEEK_SET) real_whence = SEEK_SET;
if (whence == MPMY_SEEK_CUR) real_whence = SEEK_CUR;
if (whence == MPMY_SEEK_END) real_whence = SEEK_END;
if (fp->iotype == MPMY_INDEPENDENT) {
ret = lseek(fp->fd, offset, real_whence);
} else {
ret = lseek0(fp->fd, offset, real_whence);
}
if (ret != -1) ret = 0;
Msgf(("Fseek returns %ld\n", (long)ret));
return ret;
}
off_t
MPMY_Ftell(MPMYFile *Fp)
{
struct _File *fp = (struct _File *)Fp;
off_t ret;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (fp->iotype == MPMY_INDEPENDENT) {
ret = lseek(fp->fd, 0L, SEEK_CUR);
} else {
ret = tell0(fp->fd);
}
Msgf(("Ftell returns %ld\n", (long)ret));
return ret;
}
off_t
MPMY_Flen(MPMYFile *Fp)
{
struct _File *fp = (struct _File *)Fp;
off_t ret;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (fp->iotype & MPMY_NFILE) {
ret = flen(fp->fd);
Msgf(("flen segment %ld\n", (long)ret));
if (sizeof(ret) != sizeof(long)) {
Error("Bad types in MPMY_Flen\n");
}
MPMY_Combine(&ret, &ret, 1, MPMY_LONG, MPMY_SUM);
} else if (fp->iotype == MPMY_INDEPENDENT) {
ret = flen(fp->fd);
} else {
ret = flen0(fp->fd);
}
Msgf(("Flen returns %ld\n", (long)ret));
return ret;
}
#define MAXREQ 4
static int
fseekrd_nfile(int fd, off_t offset, int whence, void *buf, int reclen,
int nrecs)
{
off_t offend;
void *tmpbuf = 0; /* realloc null first time */
int i;
off_t nread;
long size;
struct {
off_t offset;
off_t flen;
off_t start;
long reclen;
long nrecs;
} parbuf, *allbuf;
MPMY_Status stat;
MPMY_Comm_request req[MAXREQ]; /* should be dynamic? */
int nreq = 0;
int procnum = MPMY_Procnum();
off_t my_start, my_size, my_end;
int nproc = MPMY_Nproc();
if (whence != MPMY_SEEK_SET)
Error("Fseekrd Nfiles must use SEEK_SET\n");
parbuf.offset = offset;
parbuf.reclen = reclen;
parbuf.nrecs = nrecs;
parbuf.flen = flen(fd);
allbuf = Malloc(sizeof(parbuf)*nproc);
MPMY_AllGather(&parbuf, sizeof(parbuf)/sizeof(long), MPMY_LONG, allbuf);
my_start = 0;
for (i = 0; i < nproc; i++) {
allbuf[i].start = my_start;
my_start += allbuf[i].flen;
}
offend = offset+nrecs*reclen;
my_start = allbuf[procnum].start;
my_size = allbuf[procnum].flen;
my_end = my_start+my_size;
Msgf(("reclen %d\n", reclen));
Msgf(("offset %ld\n", offset));
Msgf(("nrecs*reclen %d\n", nrecs*reclen));
Msgf(("my_start %ld\n", my_start));
Msgf(("my_size %ld\n", my_size));
Msgf(("my_end %ld\n", my_end));
/* post Irecvs for my data */
for (i = 0; i < nproc; i++) {
if (allbuf[i].start<=offset && offset<allbuf[i].start+allbuf[i].flen) {
size = allbuf[i].start+allbuf[i].flen-offset;
if (size > reclen*nrecs) size = reclen*nrecs;
Msgf(("irecv %ld from %d\n", size, i));
if (nreq >= MAXREQ) Error("Too many Irecvs in fseekrd\n");
MPMY_Irecv(buf, size, i, MPMY_IOTAG, &req[nreq]);
++nreq;
} else if (offset <= allbuf[i].start && offend > allbuf[i].start+allbuf[i].flen) {
size = allbuf[i].flen;
Msgf(("irecv %ld from %d\n", size, i));
if (nreq >= MAXREQ) Error("Too many Irecvs in fseekrd\n");
MPMY_Irecv((char *)buf+allbuf[i-1].start+allbuf[i-1].flen-offset,
size, i, MPMY_IOTAG+2, &req[nreq]);
++nreq;
} else if (allbuf[i].start<offend && offend<=allbuf[i].start+allbuf[i].flen) {
size = offend-allbuf[i].start;
Msgf(("irecv %ld from %d\n", size, i));
if (nreq >= MAXREQ) Error("Too many Irecvs in fseekrd\n");
MPMY_Irecv((char *)buf+reclen*nrecs-size, size, i,
MPMY_IOTAG+1, &req[nreq]);
++nreq;
}
}
for (i = 0; i < nproc; i++) {
offset = allbuf[i].offset;
reclen = allbuf[i].reclen;
nrecs = allbuf[i].nrecs;
offend = offset+reclen*nrecs;
if (my_start <= offset && offset < my_end) {
size = my_end-offset;
if (size > reclen*nrecs) size = reclen*nrecs;
lseek(fd, offset-my_start, SEEK_SET);
tmpbuf = Realloc(tmpbuf, size);
nread = read(fd, tmpbuf, size);
Msgf(("send %ld to %d\n", size, i));
MPMY_send(tmpbuf, size, i, MPMY_IOTAG);
} else if (offset <= my_start && offend > my_end) {
size = my_end-my_start;
lseek(fd, 0, SEEK_SET);
tmpbuf = Realloc(tmpbuf, size);
nread = read(fd, tmpbuf, size);
Msgf(("send %ld to %d\n", size, i));
MPMY_send(tmpbuf, size, i, MPMY_IOTAG+2);
} else if (my_start < offend && offend <= my_end) {
size = offend-my_start;
lseek(fd, 0, SEEK_SET);
tmpbuf = Realloc(tmpbuf, size);
nread = read(fd, tmpbuf, size);
Msgf(("send %ld to %d\n", size, i));
MPMY_send(tmpbuf, size, i, MPMY_IOTAG+1);
}
}
Free(tmpbuf);
Free(allbuf);
nread = 0;
Msg_flush();
#if 0
for (i = 0; i < nreq; i++) {
MPMY_Wait(req[i], &stat);
Msgf(("Got %d from %d\n", stat.count, stat.src));
nread += stat.count;
}
#else
i = 0;
while( nreq ){
int done;
/* Msgf(("Testing req[%d] = %p\n", i, req[i])); */
MPMY_Test(req[i], &done, &stat);
if( done ){
Msgf(("Got %d from %d\n", stat.count, stat.src));
nread += stat.count;
Msgf(("Moving req[%d] = req[%d] = ", i, nreq-1));
req[i] = req[--nreq];
Msgf(("%p\n", req[i]));
}else{
/* Msgf(("Req[%d] not done yet\n", i)); */
i++;
}
assert(i <= nreq );
if( i == nreq )
i = 0;
}
#endif
Msgf(("fseekrd_nfile returning = %ld\n", nread/reclen));
return nread/reclen;
}
/* This should be called from fseekrd0 instead of replicating code */
static int
fseekrd(int fd, off_t offset, int whence, void *buf, int reclen,
int nrecs)
{
int doseek;
int real_whence;
off_t nread = 0;
off_t len;
if( whence == SEEK_CUR ){
doseek = (offset != 0);
}else if( whence == SEEK_SET ){
/* don't worry about errors. If ftell returns -1, */
/* doseek will be turned on, and the fseek below will */
/* (probably) fail */
doseek = (lseek(fd, 0L, SEEK_CUR) != offset);
}else{
doseek = 1;
}
if( doseek ){
switch(whence){
case MPMY_SEEK_SET:
real_whence = SEEK_SET;
break;
case MPMY_SEEK_CUR:
real_whence = SEEK_CUR;
break;
case MPMY_SEEK_END:
real_whence = SEEK_END;
break;
default:
Shout("Illegal value of whence (%d) in fseekrd\n", whence);
return -1;
}
if (lseek(fd, offset, real_whence) == -1) {
Error("fseekrd: lseek(%d, %ld, %d) failed, errno=%d\n",
fd, (long)offset, whence, errno);
return -1;
}
}
len = 0;
while (len < reclen*nrecs) {
nread = read(fd, (char *)buf+len, reclen*nrecs-len);
if (nread == -1) {
Error("fseekrd: read(%d, %ld) failed, errno=%d\n",
fd, (long)reclen*nrecs-len, errno);
return -1;
} else if (nread == 0) {
Error("fseekrd: read(%d, %ld) got EOF\n",
fd, (long)reclen*nrecs-len);
return -1;
} else {
printf("%d fseekrd(%d): got %ld\n", fd, MPMY_Procnum(), (long)nread);
len += nread;
}
}
if (len != reclen*nrecs) Error("fseekrd: Wrong amount of data\n");
return nread/reclen;
}
size_t
MPMY_Fseekrd(MPMYFile *Fp, off_t offset, int whence, void *buf, size_t reclen,
size_t nrecs)
{
struct _File *fp = (struct _File *)Fp;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (fp->iotype & MPMY_NFILE) {
nrecs = fseekrd_nfile(fp->fd, offset, whence, buf, reclen, nrecs);
} else if (fp->iotype == MPMY_INDEPENDENT) {
nrecs = fseekrd(fp->fd, offset, whence, buf, reclen, nrecs);
} else {
nrecs = fseekrd0(fp->fd, offset, whence, buf, reclen, nrecs);
}
return nrecs;
}
#include "iozero.c"
#include "io_generic.c"

399
external/libsdf/libmpmy/mpmy_mpi.c vendored Normal file
View file

@ -0,0 +1,399 @@
#ifdef _SWAMPI
#include <swampi.h>
#else
#include <mpi.h>
#endif
#include "mpmy_abnormal.h"
#include "Malloc.h"
#include "chn.h"
#include "mpmy.h"
#include "Assert.h"
#include "timers.h"
#include "Msgs.h"
#include "error.h"
#include "memfile.h"
struct comm_s {
MPI_Request hndl;
int inout;
};
static Chn commchn;
#define NCOMM 2048
#define IN 1
#define OUT 2
int MPMY_Isend(const void *buf, int cnt, int dest, int tag,
MPMY_Comm_request *reqp) {
struct comm_s *comm = ChnAlloc(&commchn);
Msgf(("Isend: buf=%p, cnt=%d, dest=%d, tag=%d\n",
buf, cnt, dest, tag));
if (MPI_Isend((void *)buf, cnt, MPI_BYTE, dest, tag, MPI_COMM_WORLD,
&comm->hndl) != MPI_SUCCESS)
Error("MPMY_Isend MPI_Isend failed\n");
comm->inout = OUT;
Msgf(("Isend: hndl=%ld\n", (long) comm->hndl));
*reqp = comm;
return MPMY_SUCCESS;
}
#if 0
#define HAVE_MPMY_IRSEND
int MPMY_Irsend(const void *buf, int cnt, int dest, int tag,
MPMY_Comm_request *reqp) {
struct comm_s *comm = ChnAlloc(&commchn);
Msgf(("Irsend: buf=%p, dest=%d, tag=%d\n",
buf, dest, tag));
if (MPI_Irsend(buf, cnt, MPI_BYTE, dest, tag, MPI_COMM_WORLD,
&comm->hndl) != MPI_SUCCESS)
Error("MPMY_Isend MPI_Irsend failed\n");
comm->inout = OUT;
Msgf(("Irsend: hndl=%d\n", (int) comm->hndl));
*reqp = comm;
return MPMY_SUCCESS;
}
#endif /* 0 */
int MPMY_Irecv(void *buf, int cnt, int src, int tag, MPMY_Comm_request *reqp) {
struct comm_s *comm = ChnAlloc(&commchn);
if (tag == MPMY_TAG_ANY) tag = MPI_ANY_TAG;
if (src == MPMY_SOURCE_ANY) {
src = MPI_ANY_SOURCE;
} else if (src < 0 || src >= MPMY_Nproc()) {
Error("Bad src (%d) in Irecv\n", src);
}
Msgf(("Irecv: buf=%p, src=%d, tag=%d\n",
buf, src, tag));
if (MPI_Irecv(buf, cnt, MPI_BYTE, src, tag, MPI_COMM_WORLD,
&comm->hndl) != MPI_SUCCESS)
Error("MPMY_Irecv MPI_Irecv failed\n");
comm->inout = IN;
Msgf(("Irecv: hndl=%ld\n", (long) comm->hndl));
*reqp = comm;
return MPMY_SUCCESS;
}
int MPMY_Test(MPMY_Comm_request req, int *flag, MPMY_Status *stat) {
struct comm_s *comm = req;
MPI_Status status;
int cnt;
int ret = 0;
Msgf(("MPMY_Test hndl=%ld at %p\n", (long) comm->hndl, &comm->hndl));
if ((ret = MPI_Test(&comm->hndl, flag, &status)) != MPI_SUCCESS) {
Error("MPMY_Test MPI_Test failed (%d), MPI_ERROR %d, hndl=%ld at %p, flag=%p, status=%p\n",
ret, status.MPI_ERROR, (long)comm->hndl, &comm->hndl, flag, &status);
}
Msgf(("Tested (%s), %d\n",
(comm->inout==IN)?"in":"out", *flag));
if (*flag) {
if(comm->inout == IN) {
MPI_Get_count(&status, MPI_BYTE, &cnt);
Msgf(("Recvd(T) from %d, tag %d, count: %d\n",
status.MPI_SOURCE, status.MPI_TAG, cnt));
if (stat) {
stat->src = status.MPI_SOURCE;
stat->tag = status.MPI_TAG;
stat->count = cnt;
}
}
ChnFree(&commchn, comm);
}
return MPMY_SUCCESS;
}
#define HAVE_MPMY_WAIT
int MPMY_Wait(MPMY_Comm_request req, MPMY_Status *stat) {
struct comm_s *comm = req;
MPI_Status status;
int cnt;
Msgf(("Wait for %ld\n", (long) comm->hndl));
if (MPI_Wait(&comm->hndl, &status) != MPI_SUCCESS)
Error("MPMY_Wait MPI_Wait failed\n");
Msgf(("Waited for (%s), deallocated\n",
(comm->inout==IN)?"in":"out"));
if(comm->inout == IN) {
MPI_Get_count(&status, MPI_BYTE, &cnt);
Msgf(("Recvd(W) from %d, tag %d, count: %d\n",
status.MPI_SOURCE, status.MPI_TAG, cnt));
if (stat) {
stat->src = status.MPI_SOURCE;
stat->tag = status.MPI_TAG;
stat->count = cnt;
}
}
ChnFree(&commchn, comm);
return MPMY_SUCCESS;
}
#define HAVE_MPMY_SHIFT
#define SHIFT_TAG 0x1492
int MPMY_Shift(int proc, void *recvbuf, int recvcnt,
const void *sendbuf, int sendcnt, MPMY_Status *stat) {
MPI_Status status;
int count;
Msgf(("Starting MPMY_Shift(proc=%d, recvcnt=%d, sendcnt=%d, recvbuf=%p, sendbuf=%p\n",
proc, recvcnt, sendcnt, recvbuf, sendbuf));
if (MPI_Sendrecv((void *)sendbuf, sendcnt, MPI_BYTE, proc, SHIFT_TAG,
recvbuf, recvcnt, MPI_BYTE, proc, SHIFT_TAG,
MPI_COMM_WORLD, &status) != MPI_SUCCESS)
Error("MPMY_Shift MPI_Sendrecv failed\n");
MPI_Get_count(&status, MPI_BYTE, &count);
Msgf(("MPMY_Shift done, received=%d\n", count));
if (stat) {
stat->count = count;
stat->src = status.MPI_SOURCE;
stat->tag = status.MPI_TAG;
}
return MPMY_SUCCESS;
}
int
Native_MPMY_Alltoall(void *sendbuf, int sendcount, MPMY_Datatype sendtype,
void *recvbuf, int recvcount, MPMY_Datatype recvtype)
{
MPI_Datatype st, rt;
switch (sendtype){
case MPMY_FLOAT:
st = MPI_FLOAT;
break;
case MPMY_DOUBLE:
st = MPI_DOUBLE;
break;
case MPMY_INT:
st = MPI_INT;
break;
case MPMY_CHAR:
st = MPI_CHAR;
break;
default:
Error("No type match in alltoall\n");
}
switch (recvtype){
case MPMY_FLOAT:
rt = MPI_FLOAT;
break;
case MPMY_DOUBLE:
rt = MPI_DOUBLE;
break;
case MPMY_INT:
rt = MPI_INT;
break;
case MPMY_CHAR:
rt = MPI_CHAR;
break;
default:
Error("No type match in alltoall\n");
}
MPI_Alltoall(sendbuf, sendcount, st,
recvbuf, recvcount, rt, MPI_COMM_WORLD);
return MPMY_SUCCESS;
}
int
Native_MPMY_Alltoallv(void *sendbuf, int *sendcounts, int *sendoffsets, MPMY_Datatype sendtype,
void *recvbuf, int *recvcounts, int *recvoffsets, MPMY_Datatype recvtype)
{
MPI_Datatype st, rt;
switch (sendtype){
case MPMY_FLOAT:
st = MPI_FLOAT;
break;
case MPMY_DOUBLE:
st = MPI_DOUBLE;
break;
case MPMY_INT:
st = MPI_INT;
break;
case MPMY_CHAR:
st = MPI_CHAR;
break;
case MPMY_SHORT:
st = MPI_SHORT;
break;
case MPMY_LONG:
st = MPI_LONG;
break;
default:
Error("No type match in alltoallv\n");
}
switch (recvtype){
case MPMY_FLOAT:
rt = MPI_FLOAT;
break;
case MPMY_DOUBLE:
rt = MPI_DOUBLE;
break;
case MPMY_INT:
rt = MPI_INT;
break;
case MPMY_CHAR:
rt = MPI_CHAR;
break;
case MPMY_SHORT:
rt = MPI_SHORT;
break;
case MPMY_LONG:
rt = MPI_LONG;
break;
default:
Error("No type match in alltoallv\n");
}
MPI_Alltoallv(sendbuf, sendcounts, sendoffsets, st,
recvbuf, recvcounts, recvoffsets, rt, MPI_COMM_WORLD);
return MPMY_SUCCESS;
}
int
Native_MPMY_Allgather(void *sendbuf, int sendcount, MPMY_Datatype type, void *recvbuf)
{
MPI_Datatype st, rt;
int recvcount = sendcount;
switch (type){
case MPMY_FLOAT:
st = MPI_FLOAT;
break;
case MPMY_DOUBLE:
st = MPI_DOUBLE;
break;
case MPMY_INT:
st = MPI_INT;
break;
case MPMY_CHAR:
st = MPI_CHAR;
break;
case MPMY_SHORT:
st = MPI_SHORT;
break;
case MPMY_LONG:
st = MPI_LONG;
break;
default:
Error("No type match in allgather\n");
}
rt = st;
MPI_Allgather(sendbuf, sendcount, st,
recvbuf, recvcount, rt, MPI_COMM_WORLD);
return MPMY_SUCCESS;
}
int
Native_MPMY_Allgatherv(void *sendbuf, int sendcount, MPMY_Datatype type, void *recvbuf,
int *rcounts, int *roffsets)
{
MPI_Datatype st, rt;
switch (type){
case MPMY_FLOAT:
st = MPI_FLOAT;
break;
case MPMY_DOUBLE:
st = MPI_DOUBLE;
break;
case MPMY_INT:
st = MPI_INT;
break;
case MPMY_CHAR:
st = MPI_CHAR;
break;
case MPMY_SHORT:
st = MPI_SHORT;
break;
case MPMY_LONG:
st = MPI_LONG;
break;
default:
Error("No type match in allgather\n");
}
rt = st;
MPI_Allgatherv(sendbuf, sendcount, st,
recvbuf, rcounts, roffsets, rt, MPI_COMM_WORLD);
return MPMY_SUCCESS;
}
#define HAVE_MPMY_SYNC
int MPMY_Sync(void) {
MPI_Barrier(MPI_COMM_WORLD);
return MPMY_SUCCESS;
}
int MPMY_Init(int *argcp, char ***argvp) {
ChnInit(&commchn, sizeof(struct comm_s), NCOMM, Realloc_f);
ChnMoreMem(&commchn); /* alloc now to prevent heap fragmentation later */
if (MPI_Init(argcp, argvp) != MPI_SUCCESS)
Error("MPMY_Init MPI_Init failed\n");
if (MPI_Comm_size(MPI_COMM_WORLD, &_MPMY_nproc_) != MPI_SUCCESS)
Error("MPMY_Init MPI_Comm_size failed\n");
if (MPI_Comm_rank(MPI_COMM_WORLD, &_MPMY_procnum_) != MPI_SUCCESS)
Error("MPMY_Init MPI_Comm_rank failed\n");
#ifdef PROCS_PER_NODE
_MPMY_procs_per_node_ = PROCS_PER_NODE;
#else
_MPMY_procs_per_node_ = 1;
#endif
_MPMY_setup_absigs();
MPMY_OnAbnormal(MPMY_SystemAbort);
MPMY_OnAbnormal(MPMY_Abannounce);
MPMY_OnAbnormal(PrintMemfile);
_MPMY_initialized_ = 1;
return MPMY_SUCCESS;
}
#define HAVE_MPMY_FINALIZE
int MPMY_Finalize(void){
return (MPI_Finalize() == MPI_SUCCESS) ? MPMY_SUCCESS : MPMY_FAILED ;
}
#define HAVE_MPMY_FLICK
int MPMY_Flick(void){
return MPMY_SUCCESS;
}
#define HAVE_MPMY_JOBREMAINING
int
MPMY_JobRemaining(void)
{
/* returns -1 for failure, or if not a slurm job */
return -1;
}
#ifdef USE_HWCLOCK
#include "timers_hwclock.c"
#endif
#ifdef USE_GETTIME
#include "timers_gettime.c"
#endif
#if !defined(USE_HWCLOCK) && !defined(USE_GETTIME)
#define HAVE_MPMY_TIMERS
#include "timers_mpi.c"
#endif
#if defined(__CM5__) || defined(_AIX) || defined(__AP1000__)
#define CANT_USE_ALARM
#endif
#if defined(__CM5__) || defined(__INTEL_SSD__)
#include "mpmy_pario.c"
#else
#if defined(USE_MPIIO)
#include "mpmy_mpiio.c"
#else
#include "mpmy_io.c"
#endif
#endif
#include "mpmy_abnormal.c"
#include "mpmy_generic.c"

292
external/libsdf/libmpmy/mpmy_mpiio.1.c vendored Normal file
View file

@ -0,0 +1,292 @@
/* This file contains the parallel I/O suitable for CMMD and NX.
It wouldn't be hard to add cubix-syntax as well. Are there any
other options? Would they fit in this structure? The only
difference between CMMD and NX is in Fopen, where one
system calls gopen() and the other calls CMMD_set_io_mode().
We use a pre-processor symbol (__INTEL_SSD__) or (__CM5__) to decide
which one to use. __INTEL_SSD__ is set by the ARCH-specific Makefiles,
while __CM5__ is set by mpmy_cm5.c, which #includes this file.
*/
#include <stdarg.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mpi.h>
#ifndef OPEN_MPI
#include <mpio.h>
#endif
#include "protos.h"
#include "mpmy.h"
#include "mpmy_io.h"
#include "Msgs.h"
#ifndef EINVAL
/* just in case... */
#define EINVAL 0
#endif
#define NFILES 4096
static struct _File{
MPI_File fd;
int iomode;
} _files[NFILES];
static int files; /* need dynamic storage */
static int do_nfileio;
MPMYFile *
MPMY_Fopen(const char *path, int flags)
{
MPI_File fd;
MPI_Info info;
int iomode = MPMY_SINGL; /* default */
int real_flags = MPI_MODE_RDONLY; /* if no flags specified */
int ret;
Msgf(("Fopen %s, flags = 0x%x\n", path, flags));
if (flags & MPMY_RDONLY) real_flags = MPI_MODE_RDONLY;
if (flags & MPMY_WRONLY) real_flags = MPI_MODE_WRONLY;
if (flags & MPMY_RDWR) real_flags = MPI_MODE_RDWR;
if (flags & MPMY_APPEND) real_flags |= MPI_MODE_APPEND;
if (flags & MPMY_TRUNC && ((flags & MPMY_WRONLY) || (flags & MPMY_RDWR))) {
int fd;
if (MPMY_Procnum() == 0) {
fd = open(path, O_RDWR|O_TRUNC, 0644);
if (fd < 0) Msgf(("Fopen fails, errno=%d\n", errno));
else close(fd);
MPMY_Sync();
} else {
MPMY_Sync();
}
}
if (flags & MPMY_CREAT) real_flags |= MPI_MODE_CREATE;
/* Panasas optimizations */
real_flags |= MPI_MODE_UNIQUE_OPEN; /* dangerous? */
MPI_Info_create(&info);
MPI_Info_set(info, "panfs_concurrent_write", "1");
/* Should we make sure that only one of them is on?? */
if (flags & MPMY_MULTI) iomode = MPMY_MULTI;
if (flags & MPMY_SINGL) iomode = MPMY_SINGL;
if (flags & MPMY_NFILE) Error("MPMY_NFILE not supported\n");
if (flags & MPMY_IOZERO) Error("MPMY_IOZERO not supported\n");
if (flags & MPMY_INDEPENDENT) Error("MPMY_INDEPENDENT not supported\n");
if (flags & MPMY_SINGL) {
Msgf(("Fopen %s in SINGL mode\n", path));
} else {
Msgf(("Fopen %s in MULTI mode\n", path));
}
Msgf(("MPI_File_open %s with flags = 0x%x\n", path, real_flags));
ret = MPI_File_open(MPI_COMM_WORLD, (char *)path, real_flags, info, &fd);
if (files >= NFILES) Error("files too large\n");
if (ret == 0) {
_files[files].iomode = iomode;
_files[files].fd = fd;
Msgf(("Fopen returns fd %p, iomode=%d, flags=0x%x\n",
fd, iomode, flags));
return &(_files[files++]);
} else {
Msgf(("Fopen fails, errno=%d\n", errno));
return NULL;
}
}
int
MPMY_Nfileio(int val){
int oldval = do_nfileio;
do_nfileio = val;
return oldval;
}
int
MPMY_Fclose(MPMYFile *Fp)
{
struct _File *fp = (struct _File *)Fp;
int ret;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
Msgf(("Fclose %p\n", fp->fd));
ret = MPI_File_close(&fp->fd);
return ret;
}
int
MPMY_Mkdir(const char *path, int mode)
{
int ret;
if( MPMY_Procnum() == 0 ){
ret = mkdir(path, mode);
if( ret && errno == EEXIST ){
/* Let's just pretend we really made it... */
ret = 0;
}
}
MPMY_BcastTag(&ret, 1, MPMY_INT, 0, 0x4579 );
return ret;
}
size_t
MPMY_Fread(void *ptr, size_t size, size_t nitems, MPMYFile *Fp)
{
struct _File *fp = (struct _File *)Fp;
MPI_Status status;
int cnt;
size_t nread = size*nitems;
const char *p = ptr;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (fp->iomode == MPMY_SINGL) {
MPI_File_read_all(fp->fd, (void *)p, nread, MPI_CHAR, &status);
} else {
MPI_File_read_ordered(fp->fd, (void *)p, nread, MPI_CHAR, &status);
}
MPI_Get_count(&status, MPI_BYTE, &cnt);
if (cnt != nread) Error("MPMY_Fread has a problem\n");
Msgf(("MPI_File_read from %p returns %d\n", fp->fd, cnt));
return nitems;
}
size_t
MPMY_Fwrite(const void *ptr, size_t size, size_t nitems, MPMYFile *Fp)
{
struct _File *fp = (struct _File *)Fp;
MPI_Status status;
int cnt;
size_t nwrite = size*nitems;
const char *p = ptr;
Msgf(("MPMY_Fwrite %ld %ld\n", size, nitems));
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (fp->iomode == MPMY_SINGL) {
MPI_File_write_all(fp->fd, (void *)p, nwrite, MPI_CHAR, &status);
} else {
MPI_File_write_ordered(fp->fd, (void *)p, nwrite, MPI_CHAR, &status);
}
MPI_Get_count(&status, MPI_BYTE, &cnt);
if (cnt != nwrite) Error("MPMY_Fread has a problem\n");
Msgf(("MPI_File_write from %p returns %d\n", fp->fd, cnt));
return nitems;
}
int
MPMY_Fseek(MPMYFile *Fp, off_t offset, int whence)
{
struct _File *fp = (struct _File *)Fp;
int ret;
MPI_Offset mpi_offset;
int real_whence = 0;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (whence == MPMY_SEEK_SET) real_whence = MPI_SEEK_SET;
if (whence == MPMY_SEEK_CUR) real_whence = MPI_SEEK_CUR;
if (whence == MPMY_SEEK_END) real_whence = MPI_SEEK_END;
mpi_offset = offset; /* potential conversion problem */
if (fp->iomode == MPMY_SINGL) {
ret = MPI_File_seek_shared(fp->fd, mpi_offset, real_whence);
} else {
ret = MPI_File_seek(fp->fd, mpi_offset, real_whence);
}
if (ret != -1) ret = 0;
Msgf(("Fseek to %ld returns %d\n", (long)mpi_offset, ret));
return ret;
}
off_t
MPMY_Ftell(MPMYFile *Fp)
{
struct _File *fp = (struct _File *)Fp;
MPI_Offset mpi_offset;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (fp->iomode == MPMY_SINGL) {
MPI_File_get_position_shared(fp->fd, &mpi_offset);
} else {
MPI_File_get_position(fp->fd, &mpi_offset);
}
Msgf(("Ftell returns %ld\n", (long)mpi_offset));
return mpi_offset;
}
off_t
MPMY_Flen(MPMYFile *Fp)
{
struct _File *fp = (struct _File *)Fp;
MPI_Offset mpi_offset_current, mpi_offset_end;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (fp->iomode == MPMY_SINGL) {
MPI_File_get_position_shared(fp->fd, &mpi_offset_current);
MPI_File_seek_shared(fp->fd, mpi_offset_current, MPI_SEEK_END);
MPI_File_get_position_shared(fp->fd, &mpi_offset_end);
MPI_File_seek_shared(fp->fd, mpi_offset_current, MPI_SEEK_SET);
} else {
MPI_File_get_position(fp->fd, &mpi_offset_current);
MPI_File_seek(fp->fd, mpi_offset_current, MPI_SEEK_END);
MPI_File_get_position(fp->fd, &mpi_offset_end);
MPI_File_seek(fp->fd, mpi_offset_current, MPI_SEEK_SET);
}
Msgf(("Flen returns %ld\n", (long)mpi_offset_end));
return mpi_offset_end;
}
size_t
MPMY_Fseekrd(MPMYFile *Fp, off_t offset, int whence, void *buf, size_t reclen,
size_t nrecs)
{
struct _File *fp = (struct _File *)Fp;
MPI_Offset mpi_offset;
MPI_Status status;
int cnt;
size_t nread = reclen*nrecs;
const char *p = buf;
Msgf(("Fseekrd %ld at %ld\n", (size_t)reclen*nrecs, offset));
mpi_offset = offset;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (fp->iomode == MPMY_SINGL) {
MPI_File_read_at_all(fp->fd, mpi_offset, (void *)p, nread, MPI_BYTE, &status);
} else {
MPI_File_read_at(fp->fd, mpi_offset, (void *)p, nread, MPI_BYTE, &status);
}
MPI_Get_count(&status, MPI_BYTE, &cnt);
if (cnt != nread) Error("MPMY_Fseekrd has a problem, got %d expected %ld\n",
cnt, nread);
return nrecs;
}
#include "io_generic.c"

346
external/libsdf/libmpmy/mpmy_mpiio.c vendored Normal file
View file

@ -0,0 +1,346 @@
/* This file contains the parallel I/O suitable for CMMD and NX.
It wouldn't be hard to add cubix-syntax as well. Are there any
other options? Would they fit in this structure? The only
difference between CMMD and NX is in Fopen, where one
system calls gopen() and the other calls CMMD_set_io_mode().
We use a pre-processor symbol (__INTEL_SSD__) or (__CM5__) to decide
which one to use. __INTEL_SSD__ is set by the ARCH-specific Makefiles,
while __CM5__ is set by mpmy_cm5.c, which #includes this file.
*/
#include <stdarg.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mpi.h>
#ifndef OPEN_MPI
#include <mpio.h>
#endif
#include "protos.h"
#include "mpmy.h"
#include "mpmy_io.h"
#include "Msgs.h"
#ifndef EINVAL
/* just in case... */
#define EINVAL 0
#endif
#define NFILES 4096
/* MPI only allows 2GB buffer sizes, and MPI_Get_Count uses an int */
#define MAXIOSIZE (256*1024*1024)
static struct _File{
MPI_File fd;
int iomode;
} _files[NFILES];
static int files; /* need dynamic storage */
static int do_nfileio;
MPMYFile *
MPMY_Fopen(const char *path, int flags)
{
MPI_File fd;
MPI_Info info;
int iomode = MPMY_SINGL; /* default */
int real_flags = MPI_MODE_RDONLY; /* if no flags specified */
int ret;
Msgf(("Fopen %s, flags = 0x%x\n", path, flags));
if (flags & MPMY_RDONLY) real_flags = MPI_MODE_RDONLY;
if (flags & MPMY_WRONLY) real_flags = MPI_MODE_WRONLY;
if (flags & MPMY_RDWR) real_flags = MPI_MODE_RDWR;
if (flags & MPMY_APPEND) real_flags |= MPI_MODE_APPEND;
if (flags & MPMY_TRUNC && ((flags & MPMY_WRONLY) || (flags & MPMY_RDWR))) {
int fd;
if (MPMY_Procnum() == 0) {
fd = open(path, O_RDWR|O_TRUNC, 0644);
if (fd < 0) Msgf(("Fopen fails, errno=%d\n", errno));
else close(fd);
MPMY_Sync();
} else {
MPMY_Sync();
}
}
if (flags & MPMY_CREAT) real_flags |= MPI_MODE_CREATE;
/* Panasas optimizations */
if (!(flags & MPMY_RDONLY))
real_flags |= MPI_MODE_UNIQUE_OPEN; /* dangerous? */
MPI_Info_create(&info);
MPI_Info_set(info, "panfs_concurrent_write", "1");
/* Should we make sure that only one of them is on?? */
if (flags & MPMY_MULTI) iomode = MPMY_MULTI;
if (flags & MPMY_SINGL) iomode = MPMY_SINGL;
if (flags & MPMY_NFILE) Error("MPMY_NFILE not supported\n");
if (flags & MPMY_IOZERO) Error("MPMY_IOZERO not supported\n");
if (flags & MPMY_INDEPENDENT) Error("MPMY_INDEPENDENT not supported\n");
if (flags & MPMY_SINGL) {
Msgf(("Fopen %s in SINGL mode\n", path));
} else {
Msgf(("Fopen %s in MULTI mode\n", path));
}
Msgf(("MPI_File_open %s with flags = 0x%x\n", path, real_flags));
ret = MPI_File_open(MPI_COMM_WORLD, (char *)path, real_flags, info, &fd);
if (files >= NFILES) Error("files too large\n");
if (ret == 0) {
_files[files].iomode = iomode;
_files[files].fd = fd;
Msgf(("Fopen returns fd %p, iomode=%d, flags=0x%x\n",
fd, iomode, flags));
return &(_files[files++]);
} else {
Msgf(("Fopen fails, errno=%d\n", errno));
return NULL;
}
}
int
MPMY_Nfileio(int val){
int oldval = do_nfileio;
do_nfileio = val;
return oldval;
}
int
MPMY_Fclose(MPMYFile *Fp)
{
struct _File *fp = (struct _File *)Fp;
int ret;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
Msgf(("Fclose %p\n", fp->fd));
ret = MPI_File_close(&fp->fd);
return ret;
}
int
MPMY_Mkdir(const char *path, int mode)
{
int ret;
if( MPMY_Procnum() == 0 ){
ret = mkdir(path, mode);
if( ret && errno == EEXIST ){
/* Let's just pretend we really made it... */
ret = 0;
}
}
MPMY_BcastTag(&ret, 1, MPMY_INT, 0, 0x4579 );
return ret;
}
size_t
MPMY_Fread(void *ptr, size_t size, size_t nitems, MPMYFile *Fp)
{
struct _File *fp = (struct _File *)Fp;
MPI_Status status;
int cnt;
size_t nread = size*nitems;
const char *p = ptr;
Msgf(("MPMY_Fread %ld %ld\n", size, nitems));
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (fp->iomode == MPMY_SINGL) {
if (nread >= (1 << 31)) Error("MPMY_SINGL does not yet support large reads\n");
MPI_File_read_all(fp->fd, (void *)p, nread, MPI_CHAR, &status);
MPI_Get_count(&status, MPI_CHAR, &cnt);
} else {
MPI_Offset mpi_offset;
size_t left, *sizes;
int i;
assert(sizeof(size_t) == MPMY_Datasize[MPMY_LONG]);
sizes = Malloc(sizeof(size_t)*MPMY_Nproc());
/* Use scan instead? */
Native_MPMY_Allgather(&nread, 1, MPMY_LONG, sizes);
MPI_File_get_position(fp->fd, &mpi_offset);
Msgf(("Starting offset in MPMY_Fread is %lld\n", mpi_offset));
for (i = 0; i < MPMY_Procnum(); i++) {
mpi_offset += sizes[i];
}
Msgf(("My offset in MPMY_Fread is %lld\n", mpi_offset));
Free(sizes);
left = nread;
while (left > 0) {
nread = (left < MAXIOSIZE) ? left : MAXIOSIZE;
Msgf(("read %ld at %lld\n", nread, mpi_offset));
Msg_flush();
MPI_File_read_at(fp->fd, mpi_offset, (void *)p, nread, MPI_CHAR, &status);
left -= nread;
p += nread;
mpi_offset += nread;
MPI_Get_count(&status, MPI_CHAR, &cnt);
}
}
return cnt/size;
}
size_t
MPMY_Fwrite(const void *ptr, size_t size, size_t nitems, MPMYFile *Fp)
{
struct _File *fp = (struct _File *)Fp;
MPI_Status status;
int cnt;
size_t nwrite = size*nitems;
const char *p = ptr;
Msgf(("MPMY_Fwrite %ld %ld\n", size, nitems));
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (fp->iomode == MPMY_SINGL) {
if (nwrite >= (1 << 31)) Error("MPMY_SINGL does not yet support large writes\n");
MPI_File_write_all(fp->fd, (void *)p, nwrite, MPI_CHAR, &status);
MPI_Get_count(&status, MPI_CHAR, &cnt);
if (cnt != nwrite) Error("MPMY_Fwrite has a problem, wrote %d of %ld\n",
cnt, nwrite);
} else {
MPI_Offset mpi_offset;
size_t left, *sizes;
int i;
assert(sizeof(size_t) == MPMY_Datasize[MPMY_LONG]);
sizes = Malloc(sizeof(size_t)*MPMY_Nproc());
Native_MPMY_Allgather(&nwrite, 1, MPMY_LONG, sizes);
MPI_File_get_position(fp->fd, &mpi_offset);
Msgf(("Starting offset in MPMY_Fwrite is %lld\n", mpi_offset));
for (i = 0; i < MPMY_Procnum(); i++) {
mpi_offset += sizes[i];
}
Msgf(("My offset in MPMY_Fwrite is %lld\n", mpi_offset));
Free(sizes);
left = nwrite;
while (left > 0) {
nwrite = (left < MAXIOSIZE) ? left : MAXIOSIZE;
Msgf(("write %ld at %lld\n", nwrite, mpi_offset));
Msg_flush();
MPI_File_write_at(fp->fd, mpi_offset, (void *)p, nwrite, MPI_CHAR, &status);
left -= nwrite;
p += nwrite;
mpi_offset += nwrite;
MPI_Get_count(&status, MPI_CHAR, &cnt);
if (cnt != nwrite) Error("MPMY_Fwrite has a problem, wrote %d of %ld\n",
cnt, nwrite);
}
}
return nitems;
}
off_t
MPMY_Fseek(MPMYFile *Fp, off_t offset, int whence)
{
struct _File *fp = (struct _File *)Fp;
int ret;
MPI_Offset mpi_offset;
int real_whence = 0;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (whence == MPMY_SEEK_SET) real_whence = MPI_SEEK_SET;
if (whence == MPMY_SEEK_CUR) real_whence = MPI_SEEK_CUR;
if (whence == MPMY_SEEK_END) real_whence = MPI_SEEK_END;
mpi_offset = offset; /* potential conversion problem */
if (fp->iomode == MPMY_SINGL) {
ret = MPI_File_seek_shared(fp->fd, mpi_offset, real_whence);
} else {
ret = MPI_File_seek(fp->fd, mpi_offset, real_whence);
}
if (ret != -1) ret = 0;
Msgf(("Fseek to %ld returns %d\n", (long)mpi_offset, ret));
return ret;
}
off_t
MPMY_Ftell(MPMYFile *Fp)
{
struct _File *fp = (struct _File *)Fp;
MPI_Offset mpi_offset;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (fp->iomode == MPMY_SINGL) {
MPI_File_get_position_shared(fp->fd, &mpi_offset);
} else {
MPI_File_get_position(fp->fd, &mpi_offset);
}
Msgf(("Ftell returns %ld\n", (long)mpi_offset));
return mpi_offset;
}
off_t
MPMY_Flen(MPMYFile *Fp)
{
struct _File *fp = (struct _File *)Fp;
MPI_Offset mpi_offset_current, mpi_offset_end;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (fp->iomode == MPMY_SINGL) {
MPI_File_get_position_shared(fp->fd, &mpi_offset_current);
MPI_File_seek_shared(fp->fd, mpi_offset_current, MPI_SEEK_END);
MPI_File_get_position_shared(fp->fd, &mpi_offset_end);
MPI_File_seek_shared(fp->fd, mpi_offset_current, MPI_SEEK_SET);
} else {
MPI_File_get_position(fp->fd, &mpi_offset_current);
MPI_File_seek(fp->fd, mpi_offset_current, MPI_SEEK_END);
MPI_File_get_position(fp->fd, &mpi_offset_end);
MPI_File_seek(fp->fd, mpi_offset_current, MPI_SEEK_SET);
}
Msgf(("Flen returns %ld\n", (long)mpi_offset_end));
return mpi_offset_end;
}
size_t
MPMY_Fseekrd(MPMYFile *Fp, off_t offset, int whence, void *buf, size_t reclen,
size_t nrecs)
{
struct _File *fp = (struct _File *)Fp;
MPI_Offset mpi_offset;
MPI_Status status;
int cnt;
size_t nread = reclen*nrecs;
const char *p = buf;
Msgf(("Fseekrd %ld at %ld\n", (size_t)reclen*nrecs, offset));
mpi_offset = offset;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (fp->iomode == MPMY_SINGL) {
MPI_File_read_at_all(fp->fd, mpi_offset, (void *)p, nread, MPI_BYTE, &status);
} else {
MPI_File_read_at(fp->fd, mpi_offset, (void *)p, nread, MPI_BYTE, &status);
}
MPI_Get_count(&status, MPI_BYTE, &cnt);
if (cnt != nread) Error("MPMY_Fseekrd has a problem, got %d expected %ld\n",
cnt, nread);
return nrecs;
}
#include "io_generic.c"

1
external/libsdf/libmpmy/mpmy_mvapich2.c vendored Symbolic link
View file

@ -0,0 +1 @@
mpmy_mpi.c

281
external/libsdf/libmpmy/mpmy_panio.c vendored Normal file
View file

@ -0,0 +1,281 @@
/* This file contains the parallel I/O suitable for CMMD and NX.
It wouldn't be hard to add cubix-syntax as well. Are there any
other options? Would they fit in this structure? The only
difference between CMMD and NX is in Fopen, where one
system calls gopen() and the other calls CMMD_set_io_mode().
We use a pre-processor symbol (__INTEL_SSD__) or (__CM5__) to decide
which one to use. __INTEL_SSD__ is set by the ARCH-specific Makefiles,
while __CM5__ is set by mpmy_cm5.c, which #includes this file.
*/
#include <stdarg.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include "protos.h"
#include "mpmy.h"
#include "mpmy_io.h"
#include "Msgs.h"
#include "iozero.h"
#ifndef EINVAL
/* just in case... */
#define EINVAL 0
#endif
#define NFILES 4096
static struct _File{
int fd;
int iomode;
int iotype;
int flags;
} _files[NFILES];
static int do_nfileio;
MPMYFile *
MPMY_Fopen(const char *path, int flags)
{
int fd;
int mode = 0644;
int iomode = MPMY_SINGL; /* default */
int iotype = 0;
int real_flags = 0;
Msgf(("Fopen %s\n", path));
if (flags & MPMY_RDONLY) real_flags |= O_RDONLY;
if (flags & MPMY_WRONLY) real_flags |= O_WRONLY;
if (flags & MPMY_RDWR) real_flags |= O_RDWR;
if (flags & MPMY_APPEND) real_flags |= O_APPEND;
if (flags & MPMY_TRUNC) real_flags |= O_TRUNC;
if (flags & MPMY_CREAT) real_flags |= O_CREAT;
/* Should we make sure that only one of them is on?? */
if (flags & MPMY_MULTI) iomode = MPMY_MULTI;
if (flags & MPMY_SINGL) iomode = MPMY_SINGL;
if (flags & MPMY_NFILE) iotype = MPMY_NFILE;
if (flags & MPMY_IOZERO) Error("MPMY_IOZERO not supported\n");
if (flags & MPMY_INDEPENDENT) Error("MPMY_INDEPENDENT not supported\n");
if (iotype == MPMY_NFILE) {
char real_path[256];
sprintf(real_path, "%s.p%03d", path, MPMY_Procnum());
Msgf(("Fopen %s in NFILE mode\n", path));
fd = open(real_path, real_flags, mode);
} else if (flags & MPMY_SINGL) {
Msgf(("Fopen %s in SINGL mode\n", path));
fd = open(path, real_flags, mode);
} else {
Msgf(("Fopen %s in MULTI mode\n", path));
fd = open(path, real_flags, mode);
}
if (fd >= NFILES) Error("fd too large (%d)\n", fd);
if( fd >= 0 ){
_files[fd].iomode = iomode;
_files[fd].iotype = iotype;
Msgf(("Fopen returns %d, iomode=%d, flags=0x%x\n", fd, iomode, flags));
return &(_files[fd]);
}else{
Msgf(("Fopen fails, errno=%d\n", errno));
return NULL;
}
}
int
MPMY_Nfileio(int val){
int oldval = do_nfileio;
do_nfileio = val;
return oldval;
}
int
MPMY_Fclose(MPMYFile *Fp)
{
struct _File *fp = (struct _File *)Fp;
int ret;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (fp->iomode == MPMY_SINGL) ret = close0(fp->fd);
else ret = close(fp->fd);
Msgf(("Fclose of %d returns %d\n", fp->fd, ret));
return ret;
}
int
MPMY_Mkdir(const char *path, int mode){
return mkdir0(path, mode);
}
int
MPMY_Fread(void *ptr, int size, int nitems, MPMYFile *Fp)
{
struct _File *fp = (struct _File *)Fp;
int ret;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (fp->iomode == MPMY_SINGL) ret = read0(fp->fd, ptr, size*nitems);
else ret = read(fp->fd, ptr, size*nitems);
Msgf(("Fread from %d returns %d\n", fp->fd, ret));
if (ret % size) Error("MPMY_Fread has a problem\n");
return ret/size;
}
int
MPMY_Fwrite(const void *ptr, int size, int nitems, MPMYFile *Fp)
{
struct _File *fp = (struct _File *)Fp;
int ret;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (fp->iomode == MPMY_SINGL) ret= write0(fp->fd, ptr, size*nitems);
else ret = write(fp->fd, ptr, size*nitems);
/* Msgf(("Fwrite to %d returns %d.\n", fp->fd, ret)); */
if (ret % size) Error("MPMY_Fwrite has a problem\n");
return ret/size;
}
int
MPMY_Fseek(MPMYFile *Fp, off_t offset, int whence)
{
struct _File *fp = (struct _File *)Fp;
off_t ret;
int real_whence = 0;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (whence == MPMY_SEEK_SET) real_whence = SEEK_SET;
if (whence == MPMY_SEEK_CUR) real_whence = SEEK_CUR;
if (whence == MPMY_SEEK_END) real_whence = SEEK_END;
if (fp->iotype == MPMY_SINGL) {
ret = lseek0(fp->fd, offset, real_whence);
} else {
ret = lseek(fp->fd, offset, real_whence);
}
if (ret != -1) ret = 0;
Msgf(("Fseek returns %ld\n", (long)ret));
return ret;
}
int
MPMY_Ftell(MPMYFile *Fp)
{
struct _File *fp = (struct _File *)Fp;
off_t ret;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (fp->iotype == MPMY_SINGL) {
ret = tell0(fp->fd);
} else {
ret = lseek(fp->fd, 0L, SEEK_CUR);
}
Msgf(("Ftell returns %ld\n", (long)ret));
return ret;
}
off_t
MPMY_Flen(MPMYFile *Fp)
{
struct _File *fp = (struct _File *)Fp;
off_t ret;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (fp->iotype & MPMY_NFILE) {
ret = flen(fp->fd);
Msgf(("flen segment %ld\n", (long)ret));
if (sizeof(ret) != sizeof(long)) {
Error("Bad types in MPMY_Flen\n");
}
MPMY_Combine(&ret, &ret, 1, MPMY_LONG, MPMY_SUM);
} else if (fp->iotype == MPMY_SINGL) {
ret = flen0(fp->fd);
} else {
ret = flen(fp->fd);
}
Msgf(("Flen returns %ld\n", (long)ret));
return ret;
}
int
MPMY_Fseekrd(MPMYFile *Fp, off_t offset, int whence, void *buf, int reclen,
int nrecs)
{
struct _File *fp = (struct _File *)Fp;
int doseek;
if( fp == NULL ){
errno = EINVAL;
return -1;
}
if (fp->iomode == MPMY_SINGL) {
nrecs = fseekrd0(fp->fd, offset, whence, buf, reclen, nrecs);
return nrecs;
}
if( whence == MPMY_SEEK_CUR ){
doseek = (offset != 0);
}else if( whence == MPMY_SEEK_SET ){
/* don't worry about errors. If ftell returns -1, */
/* doseek will be turned on, and the fseek below will */
/* (probably) fail */
doseek = (MPMY_Ftell(Fp) != offset);
}else{
doseek = 1;
}
if( doseek ){
if( MPMY_Fseek(Fp, offset, whence) ){
if( whence == MPMY_SEEK_CUR && offset > 0 ){
/* Make a final heroic effort to seek by reading forward! */
char junk[BUFSIZ];
int nleft = offset;
while( nleft ){
int ntry = ( nleft > sizeof(junk) ) ? sizeof(junk) : nleft;
if( MPMY_Fread(junk, ntry, 1, Fp) != 1 ){
Error("fseekrd: incremental fread(%#lx, %d, 1, %#lx) failed, errno=%d\n",
(unsigned long)junk, ntry,
(unsigned long)fp, errno);
return -1;
}
nleft -= ntry;
}
}else{
Error("fseekrd: fseek(%#lx, %lld, %d) failed, errno=%d\n",
(unsigned long)fp, offset, whence, errno);
return -1;
}
}
}
if( MPMY_Fread(buf, reclen, nrecs, Fp) != nrecs ){
Error("fseekrd: fread(%#lx, %d, %d, %#lx) failed, errno=%d\n",
(unsigned long)buf, reclen, nrecs, (unsigned long)fp, errno);
return -1;
}
return nrecs;
}
#include "iozero.c"
#include "io_generic.c"

262
external/libsdf/libmpmy/mpmy_seq.c vendored Normal file
View file

@ -0,0 +1,262 @@
/*
Not-so-trivial implementation of the mpmy interface for a single process(or)
that handles messages sent to itself.
This is not designed for speed. In fact, it's not designed at all. It's
just meant to limp along. I think it's a bad idea to be sending a lot
of messages to yourself.
*/
#include <string.h>
#include "Msgs.h"
#include "mpmy.h"
#include "Assert.h"
#include "mpmy_io.h"
#include "mpmy_time.h"
#include "mpmy_abnormal.h"
#define IN 1
#define OUT 2
#ifdef __SUN4__
/* ARCH=sun4 code may have been compiled and linked with __CM5VU__, which
means that if we're not careful we'll hit some illegal instructions when
we try to call do_grav. This variable sidesteps those Vector-Unit
calls at run-time. It's twisted, but it's the price we pay for using
ARCH=sun4 for the CM5. */
int have_vu = 0;
void *VUHeap;
int VUaux_allocated;
#if 0
void *aux_alloc_heap(int n){
Error("aux_alloc_heap: You shouldn't reach this on a non-cm5 processor!\n");
}
#endif
#endif
struct comm_s{
int cnt;
int tag;
void *buf;
int inout;
int finished;
};
/* These do a little more than mpmy_alloc_generic. It lets us search */
/* the list of allocated requests too. Unfortunately, it takes O(Nreq) */
/* time to do a Dealloc or a Match. I'm sure there's something simpler than */
/* hashing that would do better, but I'm being dense. */
#define MAXCOMM 200
static struct comm_s _comms[MAXCOMM];
static int freecomm[MAXCOMM];
static int usedcomm[MAXCOMM];
static int mpmy_nfree = 0;
static int mpmy_nused = 0;
static void CommInit(void){
int i;
for(i=0; i<MAXCOMM; i++){
freecomm[i] = i;
}
mpmy_nfree = MAXCOMM;
mpmy_nused = 0;
}
static int CommAlloc(void){
int ret;
if( mpmy_nfree >= 0 ){
ret = freecomm[--mpmy_nfree];
usedcomm[mpmy_nused++] = ret;
return ret;
}else
return -1;
}
static void CommDealloc(int req){
int i;
assert(mpmy_nfree < MAXCOMM);
for(i=0; i<mpmy_nused; i++){
if( usedcomm[i] == req ){
usedcomm[i] = usedcomm[--mpmy_nused];
break;
}
}
freecomm[mpmy_nfree++] = req;
}
static int find_match(int inout, int tag){
int i, ui;
struct comm_s *comm;
for(i=0; i<mpmy_nused; i++){
ui = usedcomm[i];
comm = &_comms[ui];
if( !comm->finished
&& (comm->tag == tag || tag == MPMY_TAG_ANY || comm->tag == MPMY_TAG_ANY)
&& comm->inout == inout )
return ui;
}
return -1;
}
int MPMY_Isend(const void *buf, int cnt, int dest, int tag, MPMY_Comm_request *reqp){
struct comm_s *comm;
int req;
if( dest != 0 )
return MPMY_FAILED;
req = CommAlloc();
if( req < 0 )
return MPMY_FAILED;
comm = &_comms[req];
comm->inout = OUT;
comm->cnt = cnt;
comm->tag = tag;
comm->buf = (void *)buf; /* drop const. modifier */
comm->finished = 0;
*reqp = comm;
IncrCounter(&MPMYSendCnt);
return MPMY_SUCCESS;
}
int MPMY_Irecv(void *buf, int cnt, int src, int tag, MPMY_Comm_request *reqp){
struct comm_s *comm;
int req;
if( src != 0 && src != MPMY_SOURCE_ANY )
return MPMY_FAILED;
req = CommAlloc();
if( req < 0 )
return MPMY_FAILED;
comm = &_comms[req];
comm->inout = IN;
comm->cnt = cnt;
comm->tag = tag;
comm->buf = buf;
comm->finished = 0;
*reqp = comm;
IncrCounter(&MPMYRecvCnt);
return MPMY_SUCCESS;
}
int MPMY_Test(MPMY_Comm_request req, int *flag, MPMY_Status *stat){
struct comm_s *comm = req;
struct comm_s *mcomm;
int match;
int ireq = comm - _comms;
if( comm->finished ){
*flag = 1;
if( comm->inout == IN && stat ){
stat->count = comm->cnt;
stat->tag = comm->tag;
stat->src = 0;
}
CommDealloc(ireq);
IncrCounter(&MPMYDoneCnt);
return MPMY_SUCCESS;
}
if( comm->inout == IN ){
match = find_match(OUT, comm->tag);
if( match >= 0 ){
mcomm = &_comms[match];
if( mcomm->cnt > comm->cnt ){
SeriousWarning("MPMY_Test message too long\n");
CommDealloc(ireq);
return MPMY_FAILED;
}
memcpy(comm->buf, mcomm->buf, mcomm->cnt);
if( stat ){
stat->count = mcomm->cnt;
stat->tag = mcomm->tag;
stat->src = 0;
}
mcomm->finished = 1;
*flag = 1;
IncrCounter(&MPMYDoneCnt);
CommDealloc(ireq);
return MPMY_SUCCESS;
}else{
*flag = 0;
return MPMY_SUCCESS;
}
}else{
match = find_match(IN, comm->tag);
if( match >= 0 ){
mcomm = &_comms[match];
if( comm->cnt > mcomm->cnt ){
SeriousWarning("MPMY_Test message too long\n");
CommDealloc(ireq);
return MPMY_FAILED;
}
memcpy(mcomm->buf, comm->buf, comm->cnt);
mcomm->cnt = comm->cnt;
mcomm->tag = comm->tag;
mcomm->finished = 1;
*flag = 1;
IncrCounter(&MPMYDoneCnt);
CommDealloc(ireq);
return MPMY_SUCCESS;
}else{
*flag = 0;
return MPMY_SUCCESS;
}
}
}
int
Native_MPMY_Alltoall(void *sendbuf, int sendcount, MPMY_Datatype sendtype,
void *recvbuf, int recvcount, MPMY_Datatype recvtype)
{
memcpy(recvbuf, sendbuf, sendcount*MPMY_Datasize[sendtype]);
return MPMY_SUCCESS;
}
int
Native_MPMY_Allgather(void *sendbuf, int sendcount, MPMY_Datatype type, void *recvbuf)
{
memcpy(recvbuf, sendbuf, sendcount*MPMY_Datasize[type]);
return MPMY_SUCCESS;
}
int
Native_MPMY_Allgatherv(void *sendbuf, int sendcount, MPMY_Datatype type, void *recvbuf,
int *rcounts, int *roffsets)
{
memcpy(recvbuf, sendbuf, sendcount*MPMY_Datasize[type]);
return MPMY_SUCCESS;
}
int MPMY_Init(int *argcp, char ***argvp){
CommInit();
_MPMY_nproc_ = 1;
_MPMY_procnum_ = 0;
_MPMY_initialized_ = 1;
/* There should really be a better way to opt out of MPMY abnormal
signal handling. For now, this will work for programs that might
use SDF, but which have their own carefully crafted signal handlers,
e.g., SM */
if( argcp )
_MPMY_setup_absigs();
MPMY_OnAbnormal(MPMY_SystemAbort);
MPMY_OnAbnormal(MPMY_Abannounce);
return MPMY_SUCCESS;
}
#ifdef USE_GETTIME
#include "timers_gettime.c"
#endif
#ifdef USE_HWCLOCK
#include "timers_hwclock.c"
#endif
#include "mpmy_io.c"
#include "mpmy_abnormal.c"
#include "mpmy_generic.c"

View file

@ -0,0 +1,85 @@
#include <time.h>
#include "mpmy_time.h"
#include "Malloc.h"
#include "chn.h"
static Chn timer_chn;
static int initialized;
typedef struct {
int type;
struct timespec cpu_start;
double cpu_accum;
struct timespec wc_start;
double wc_accum;
} MPMY_Timer;
void *MPMY_CreateTimer(int type){
MPMY_Timer *ret;
if( initialized == 0 ){
ChnInit(&timer_chn, sizeof(MPMY_Timer), 40, Realloc_f);
initialized = 1;
}
ret = ChnAlloc(&timer_chn);
ret->type = type;
MPMY_ClearTimer(ret);
return (void *)ret;
}
int MPMY_DestroyTimer(void *p){
ChnFree(&timer_chn, p);
return MPMY_SUCCESS;
}
int MPMY_StartTimer(void *p){
MPMY_Timer *t = p;
switch(t->type){
case MPMY_CPU_TIME:
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t->cpu_start);
break;
case MPMY_WC_TIME:
clock_gettime(CLOCK_REALTIME, &t->wc_start);
break;
}
return MPMY_SUCCESS;
}
int MPMY_StopTimer(void *p){
MPMY_Timer *t = p;
struct timespec tnow;
switch(t->type){
case MPMY_CPU_TIME:
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tnow);
t->cpu_accum += (tnow.tv_sec - t->cpu_start.tv_sec) + (tnow.tv_nsec - t->cpu_start.tv_nsec) * 1e-9;
break;
case MPMY_WC_TIME:
clock_gettime(CLOCK_REALTIME, &tnow);
t->wc_accum += (tnow.tv_sec - t->wc_start.tv_sec) + (tnow.tv_nsec - t->wc_start.tv_nsec) * 1e-9;
break;
}
return MPMY_SUCCESS;
}
int MPMY_ClearTimer(void *p){
MPMY_Timer *t = p;
t->cpu_accum = 0.0;
t->wc_accum = 0.0;
return MPMY_SUCCESS;
}
double MPMY_ReadTimer(void *p){
MPMY_Timer *t = p;
switch(t->type){
case MPMY_CPU_TIME:
return t->cpu_accum;
case MPMY_WC_TIME:
return t->wc_accum;
}
return -1.0;
}

106
external/libsdf/libmpmy/timers_hwclock.c vendored Normal file
View file

@ -0,0 +1,106 @@
#include <time.h>
#include "mpmy_time.h"
#include "Malloc.h"
#include "chn.h"
static Chn timer_chn;
static int initialized;
typedef struct {
unsigned long long start;
unsigned long long accum;
struct timespec wc_start;
double wc_accum;
int type;
} MPMY_Timer;
#ifdef AMD6100
#define DEFAULT_MHZ 2300.0e6
#else
#define DEFAULT_MHZ 2668.0e6
#endif
static __inline__ unsigned long long rdtsc(void)
{
unsigned hi, lo;
__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}
void *MPMY_CreateTimer(int type){
MPMY_Timer *ret;
if( initialized == 0 ){
ChnInit(&timer_chn, sizeof(MPMY_Timer), 40, Realloc_f);
initialized = 1;
}
ret = ChnAlloc(&timer_chn);
ret->type = type;
MPMY_ClearTimer(ret);
return (void *)ret;
}
int MPMY_DestroyTimer(void *p){
ChnFree(&timer_chn, p);
return MPMY_SUCCESS;
}
int MPMY_CopyTimer(void *p, void *q)
{
MPMY_Timer *t = p;
MPMY_Timer *u = q;
*u = *t;
return MPMY_SUCCESS;
}
int MPMY_StartTimer(void *p){
MPMY_Timer *t = p;
switch(t->type){
case MPMY_CPU_TIME:
t->start = rdtsc();
break;
case MPMY_WC_TIME:
clock_gettime(CLOCK_REALTIME, &t->wc_start);
break;
}
return MPMY_SUCCESS;
}
int MPMY_StopTimer(void *p){
MPMY_Timer *t = p;
struct timespec tnow;
switch(t->type){
case MPMY_CPU_TIME:
t->accum += rdtsc()-t->start;
break;
case MPMY_WC_TIME:
clock_gettime(CLOCK_REALTIME, &tnow);
t->wc_accum += (tnow.tv_sec - t->wc_start.tv_sec) + (tnow.tv_nsec - t->wc_start.tv_nsec) * 1e-9;
break;
}
return MPMY_SUCCESS;
}
int MPMY_ClearTimer(void *p){
MPMY_Timer *t = p;
t->accum = 0;
t->wc_accum = 0.0;
return MPMY_SUCCESS;
}
double MPMY_ReadTimer(void *p){
MPMY_Timer *t = p;
switch(t->type){
case MPMY_CPU_TIME:
return t->accum/DEFAULT_MHZ;
case MPMY_WC_TIME:
return t->wc_accum;
}
return -1.0;
}

59
external/libsdf/libmpmy/timers_mpi.c vendored Normal file
View file

@ -0,0 +1,59 @@
/* This file tries to use only MPI-approved timer constructs. */
/* time.h should define CLOCKS_PER_SECOND and prototype clock() and time()
and it should have typedefs for time_t and clock_t. */
#include "mpmy_time.h"
#include "chn.h"
static Chn timer_chn;
static int initialized;
typedef struct {
int type;
double wc_start, wc_accum;
} MPMY_Timer;
void *MPMY_CreateTimer(int type){
MPMY_Timer *ret;
if( initialized == 0 ){
ChnInit(&timer_chn, sizeof(MPMY_Timer), 40, Realloc_f);
initialized = 1;
}
ret = ChnAlloc(&timer_chn);
ret->type = type;
return (void *)ret;
}
int MPMY_DestroyTimer(void *p){
ChnFree(&timer_chn, p);
return MPMY_SUCCESS;
}
int MPMY_StartTimer(void *p){
MPMY_Timer *t = p;
t->wc_start = MPI_Wtime();
return MPMY_SUCCESS;
}
int MPMY_StopTimer(void *p){
MPMY_Timer *t = p;
t->wc_accum += MPI_Wtime() - t->wc_start;
return MPMY_SUCCESS;
}
int MPMY_ClearTimer(void *p){
MPMY_Timer *t = p;
t->wc_accum = 0.;
return MPMY_SUCCESS;
}
double MPMY_ReadTimer(void *p){
MPMY_Timer *t = p;
return (double)t->wc_accum;
}

139
external/libsdf/libmpmy/timers_posix.c vendored Normal file
View file

@ -0,0 +1,139 @@
/* This file tries to use only ANSI/POSIX-approved timer constructs. */
/* It should compile correctly everywhere (Ha!) */
/* time.h should define CLOCKS_PER_SECOND and prototype clock() and time()
and it should have typedefs for time_t and clock_t. */
#include <time.h>
#include "mpmy_time.h"
#include "chn.h"
#include "Malloc.h"
#ifndef CLOCKS_PER_SECOND
/* We've got a non-standard time.h. At least we have a time.h...*/
#ifdef CLOCKS_PER_SEC /* This works for linux */
#define CLOCKS_PER_SECOND CLOCKS_PER_SEC
#else
#define CLOCKS_PER_SECOND 1000000 /* this is just a wild guess!! */
#endif
#endif
/* POSIX only guarantees 'time', which returns a time_t. The option
is available for the 'implementor' to make time_t a double. Does
the friendly implementor at Sun do this? Nooooo. If we want more
precision we have to use gettimeofday, which is a non-POSIX BSD-ism.
Better still, gettimeofday has mutually incompatible definitions in
SVr4 (one argument) and XSH4.2 (two arguments). Sigh...
*/
#if defined(sun) || defined(__INTEL_SSD__) || defined(_AIX) || defined(__x86_64__)
# define USE_GETTIMEOFDAY
# include <sys/time.h>
#else /* don't use gettimeofday. use time() instead */
extern time_t time(time_t *);
#endif
/* This ought to be in one of the system headers... */
extern clock_t clock(void);
static Chn timer_chn;
static int initialized;
typedef struct {
int type;
clock_t cpu_start, cpu_accum;
#ifdef USE_GETTIMEOFDAY
struct timeval wc_start;
struct timeval wc_accum;
#else
time_t wc_start, wc_accum;
#endif
} MPMY_Timer;
void *MPMY_CreateTimer(int type){
MPMY_Timer *ret;
if( initialized == 0 ){
ChnInit(&timer_chn, sizeof(MPMY_Timer), 40, Realloc_f);
initialized = 1;
}
ret = ChnAlloc(&timer_chn);
ret->type = type;
MPMY_ClearTimer(ret);
return (void *)ret;
}
int MPMY_DestroyTimer(void *p){
ChnFree(&timer_chn, p);
return MPMY_SUCCESS;
}
int MPMY_StartTimer(void *p){
MPMY_Timer *t = p;
switch(t->type){
case MPMY_WC_TIME:
#ifdef USE_GETTIMEOFDAY
gettimeofday(&t->wc_start, 0);
#else
t->wc_start = time(0);
#endif
break;
case MPMY_CPU_TIME:
t->cpu_start = clock();
break;
}
return MPMY_SUCCESS;
}
int MPMY_StopTimer(void *p){
MPMY_Timer *t = p;
switch(t->type){
case MPMY_WC_TIME:
#ifdef USE_GETTIMEOFDAY
{
struct timeval tnow;
gettimeofday(&tnow, 0);
t->wc_accum.tv_sec += tnow.tv_sec - t->wc_start.tv_sec;
t->wc_accum.tv_usec += tnow.tv_usec - t->wc_start.tv_usec;
}
#else
t->wc_accum += time(0) - t->wc_start;
#endif
break;
case MPMY_CPU_TIME:
t->cpu_accum += clock() - t->cpu_start;
break;
}
return MPMY_SUCCESS;
}
int MPMY_ClearTimer(void *p){
MPMY_Timer *t = p;
#ifdef USE_GETTIMEOFDAY
t->wc_accum.tv_sec = 0;
t->wc_accum.tv_usec = 0;
#else
t->wc_accum = 0;
#endif
t->cpu_accum = 0;
return MPMY_SUCCESS;
}
double MPMY_ReadTimer(void *p){
MPMY_Timer *t = p;
switch(t->type){
case MPMY_WC_TIME:
#ifdef USE_GETTIMEOFDAY
return (double)t->wc_accum.tv_sec + (double)t->wc_accum.tv_usec*1.0e-6;
#else
return (double)t->wc_accum;
#endif
case MPMY_CPU_TIME:
return (double)t->cpu_accum * (1.0/CLOCKS_PER_SECOND);
}
return -1.0;
}