./pvm3/0042755007401100000360000000000010117676455011121 5ustar kohlgopher./pvm3/bin/0042755007401100000360000000000010117676455011671 5ustar kohlgopher./pvm3/Makefile0100644007401100000360000000111406373621767012556 0ustar kohlgopher# # $Id: Makefile,v 1.8 1997/08/11 14:38:47 pvmsrc Exp $ # # top-level PVM3 makefile # SHELL = /bin/sh AIMKSTR = -here -f ./conf/`./lib/pvmtmparch`.def -f ./Makefile.aimk default: ./lib/aimk $(AIMKSTR) default install: ./lib/aimk $(AIMKSTR) install all: ./lib/aimk $(AIMKSTR) all clean: ./lib/aimk $(AIMKSTR) clean s: ./lib/aimk $(AIMKSTR) s c: ./lib/aimk $(AIMKSTR) c f: ./lib/aimk $(AIMKSTR) f g: ./lib/aimk $(AIMKSTR) g e: ./lib/aimk $(AIMKSTR) e m: ./lib/aimk $(AIMKSTR) m t: ./lib/aimk $(AIMKSTR) t x: ./lib/aimk $(AIMKSTR) x r: ./lib/aimk $(AIMKSTR) r ./pvm3/Makefile.aimk0100644007401100000360000000450307641112240013457 0ustar kohlgopher# # $Id: Makefile.aimk,v 1.6 2003/03/28 18:29:52 pvmsrc Exp $ # # top-level PVM3 aimk makefile # # targets: # s: src - pvmd3, libpvm3.a # c: console - pvm # f: fortran lib - libfpvm3.a # g: groups - pvmgs, libgpvm3.a # e: examples # t: tracer # m: xep example # x: xpvm # r: srm # SHELL = /bin/sh # # Override with Any User Defaults # # (*** Must Add To PVMOPTS List To Pass Down ***) # #CC = cc #CFLOPTS = -g #F77 = f77 #FFLOPTS = -g #PVMDIR = ../.. # # Pass Options Down # PVMOPTS = CC="$(CC)" \ F77="$(F77)" # CFLOPTS="$(CFLOPTS)" # FFLOPTS="$(FFLOPTS)" # PVMDIR=$(PVMDIR) # # Targets # default: s c f g install: default all: s c f g e m t x r c: s t g: s e: s f g m: s t: s x: s r: c clean: - cd src; ../lib/aimk $(PVMOPTS) clean - cd console; ../lib/aimk $(PVMOPTS) clean - cd libfpvm; ../lib/aimk $(PVMOPTS) clean - cd pvmgs; ../lib/aimk $(PVMOPTS) clean - cd examples; ../lib/aimk $(PVMOPTS) clean - cd gexamples; ../lib/aimk $(PVMOPTS) clean - cd tracer; ../lib/aimk $(PVMOPTS) clean - cd xep; ../lib/aimk $(PVMOPTS) clean - cd xpvm; ../lib/aimk $(PVMOPTS) clean - cd rm; ../lib/aimk $(PVMOPTS) clean ## build pvmd, libpvm ## s: @ echo "building in src" cd src; ../lib/aimk $(PVMOPTS) install @ echo "done building in src" ## build libfpvm ## f: @ echo "building libfpvm" cd libfpvm; ../lib/aimk $(PVMOPTS) install @ echo "done building libfpvm" ## build groups ## g: @ echo "building group server and library" cd pvmgs; ../lib/aimk $(PVMOPTS) install @ echo "done building group server and library" ## build pvm console ## c: @ echo "building console" cd console; ../lib/aimk $(PVMOPTS) install @ echo "done building console" ## build xep example ## m: @ echo "building xep example" - cd xep; ../lib/aimk $(PVMOPTS) @ echo "done building xep example" ## build example programs ## e: @ echo "building examples" - cd examples; ../lib/aimk $(PVMOPTS) all - cd gexamples; ../lib/aimk $(PVMOPTS) all @ echo "done building examples" ## build tracer ## t: @ echo "building tracer" - cd tracer; ../lib/aimk $(PVMOPTS) install @ echo "done building tracer" ## build xpvm ## x: @ echo "building XPVM" - cd xpvm; ../lib/aimk $(PVMOPTS) install @ echo "done building XPVM" ## build srm ## r: @ echo "building srm" - cd rm; ../lib/aimk $(PVMOPTS) install @ echo "done building srm" ./pvm3/make.bat0100644007401100000360000001624706673522114012525 0ustar kohlgopherrem rem $Id: make.bat,v 1.15 1999/03/16 18:34:52 pvmsrc Exp $ rem rem echo on @echo off cls rem Script File for PVM for WIN32 rem 06/24/1997 Markus Fischer rem 10/--/1998 Stephen L. Scott -- revised edition rem 01/16/1999 Stephen L. Scott -- resolve some NT, Win95/98 issues rem 02/17/1999 Stephen L. Scott -- DevStudio C/Fortran V6 vs V5 differences rem rem OS is used to decide if batch file has to do any work rem to initialize C or Fortran setup. NT does not require rem any setup while 95/98 has some interesting twists... rem if "%OS%" == "Windows_NT" goto BEGIN rem skip 95/98 tests if have already been through once if "%PVMVCF%" == "YES" goto BEGIN rem *********** rem * FORTRAN * rem *********** rem check if dfvars.bat has been executed rem DF_TOOLS is defined as MSVC in dfvars.bat, so test for it... rem if found - dfvars.bat already initialized VC rem so skip VC stuff below too if "%DF_TOOLS%" == "MSVC" goto BEGIN rem dfvars.bat not executed, determine if fortran is installed rem decide which based on explicit path to fortran location. rem if find here, then execute dfvars.bat and skip C stuff below. if exist "%PVM_FBIN%\dfvars.bat" goto HASFORTRAN echo. echo Fortran compiler not found. echo. rem ****** rem * VC * rem ****** rem check if vcvars32.bat has been executed rem MSVCDIR is defined in vcvars.bat, so test for it... rem if found - vcvars32.bat already initialized VC rem so skip VC stuff below if exist "%MSVCDIR%\bin\vcvars32.bat" goto BEGIN rem either vcvars32.bat not executed OR VC not installed rem decide which based on explicit path to VC location. rem if find here, then execute vcvars32.bat if exist "%PVM_CBIN%\vcvars32.bat" goto HASC echo. echo C compiler not found. echo. goto INTRO :HASFORTRAN CALL %PVM_FBIN%\dfvars.bat rem this does VC also - so skip VC stuff... goto BEGIN :HASC CALL %PVM_CBIN%\vcvars32.bat goto BEGIN :BEGIN set PVMVCF=YES if "%1" == "" goto INTRO goto SWITCH :INTRO echo This is a script for (re)compiling the PVM code and examples. echo Type one of the following at the DOS command line. echo. echo make pvm -- will compile and install the PVM code by echo compiling libpvm, daemon, hoster, groupserver echo and console echo. echo make ec -- will compile the C examples echo. echo make ef -- will compile the Fortran examples echo. echo make gec -- will compile the C group examples echo. echo make gef -- will compile the Fortran group examples echo. echo make all -- will compile the items above echo. echo make clean -- will erase all object files (.obj) echo. echo make tidy -- will erase the object, dll, and executables echo (.obj .dll .ilk .pdb .exe) echo. echo make tec -- perform a "tidy" for C examples echo. echo make tef -- perform a "tidy" for Fortran examples echo. echo make tgec -- perform a "tidy" for C group examples echo. echo make tgef -- perform a "tidy" for Fortran group examples echo. echo. goto ENDE :SWITCH if "%1" == "pvm" goto PVM if "%1" == "all" goto PVMEX if "%1" == "clean" goto CLEAN if "%1" == "tidy" goto TIDY if "%1" == "ec" goto CEXAMPLES if "%1" == "ef" goto FEXAMPLES if "%1" == "gec" goto CGEXAMPLES if "%1" == "gef" goto FGEXAMPLES if "%1" == "tec" goto TEC if "%1" == "tef" goto TEF if "%1" == "tgec" goto TGEC if "%1" == "tgef" goto TGEF echo Your make "option" specification did not match. RETRY... echo. goto INTRO :PVM :PVMEX echo. echo Compiling and installing library (C,Fortran), daemon, tracer, echo console, hoster and groupserver echo ------------------------------------------------------------- cd %PVM_ROOT%\src\ nmake /f makefile.mak cd %PVM_ROOT% echo. echo Compiling and installing tracer echo ------------------------------- cd %PVM_ROOT%\tracer\ nmake /f makefile.mak cd %PVM_ROOT% echo. echo Compiling and installing pvm echo ---------------------------- cd %PVM_ROOT%\console\ nmake /f makefile.mak cd %PVM_ROOT% echo. echo Compiling and installing hoster echo ------------------------------- cd %PVM_ROOT%\hoster\ nmake /f makefile.mak cd %PVM_ROOT% echo. echo Compiling and installing pvmgs echo ------------------------------ cd %PVM_ROOT%\pvmgs\ nmake /f makefile.mak cd %PVM_ROOT% echo. echo Compiling and installing libfpvm echo -------------------------------- cd %PVM_ROOT%\libfpvm\ nmake /f makefile.mak cd %PVM_ROOT% echo. echo More Information in Readme.win32 echo. if "%1" == "pvm" goto ENDE :CEXAMPLES cd %PVM_ROOT%\examples echo. echo Building C examples echo ------------------- nmake /f makefile.mak c-all cd %PVM_ROOT% if "%1" == "ec" goto ENDE :FEXAMPLES echo. echo Building Fortran examples echo ------------------------- cd %PVM_ROOT%\examples nmake /f makefile.mak f-all cd %PVM_ROOT% if "%1" == "ef" goto ENDE :CGEXAMPLES cd %PVM_ROOT%\gexamples echo. echo Building C group examples echo ------------------------- nmake /f makefile.mak c-all cd %PVM_ROOT% if "%1" == "gec" goto ENDE :FGEXAMPLES echo. echo Building Fortran group examples echo ------------------------------- rem skipout here if doing "all" as there is a known rem problem with the fortran group example code if "%1" == "all" goto ENDE rem feel free to let it fail if you really want to try it... cd %PVM_ROOT%\gexamples nmake /f makefile.mak f-all cd %PVM_ROOT% if "%1" == "gef" goto ENDE goto ENDE :TIDY echo. echo Cleaning Execs and Libs ... echo --------------------------- cd %PVM_ROOT%\bin\%PVM_ARCH%\ erase *.exe cd %PVM_ROOT%\tracer\%PVM_ARCH%\ erase *.exe erase *.lib cd %PVM_ROOT%\lib\%PVM_ARCH%\ erase *.lib erase *.exe erase *.dll cd %PVM_ROOT%\libfpvm\%PVM_ARCH%\ erase *.lib erase *.dll cd %PVM_ROOT% :CLEAN echo. echo Cleaning Objects ... echo -------------------- cd %PVM_ROOT%\src\%PVM_ARCH%\ erase *.obj echo. echo Cleaning libfpvm objects ... echo ---------------------------- cd %PVM_ROOT%\libfpvm\%PVM_ARCH% erase *.obj echo. echo Cleaning console objects ... echo ---------------------------- cd %PVM_ROOT%\console\%PVM_ARCH% erase *.obj echo. echo Cleaning hoster objects ... echo --------------------------- cd %PVM_ROOT%\hoster\%PVM_ARCH%\ erase *.obj echo. echo Cleaning pvmgs objects ... echo -------------------------- cd %PVM_ROOT%\pvmgs\%PVM_ARCH%\ erase *.obj echo. echo Cleaning tracer objects ... echo --------------------------- cd %PVM_ROOT%\tracer\%PVM_ARCH%\ erase *.obj echo. echo Cleaning example objects ... echo ---------------------------- cd %PVM_ROOT%\examples\%PVM_ARCH%\ erase *.obj cd %PVM_ROOT%\libfpvm\%PVM_ARCH%\ erase *.ilk erase *.pdb echo. echo Cleaning group example objects ... echo ---------------------------------- cd %PVM_ROOT%\gexamples\%PVM_ARCH%\ erase *.obj cd %PVM_ROOT% goto ENDE :TEC echo. echo Tidy the C examples echo ------------------- cd %PVM_ROOT%\examples nmake /f makefile.mak tidy-c cd %PVM_ROOT% goto ENDE :TEF echo. echo Tidy the Fortran examples echo ------------------------- cd %PVM_ROOT%\examples nmake /f makefile.mak tidy-f cd %PVM_ROOT% goto ENDE :TGEC echo. echo Tidy the C group examples echo ------------------------- cd %PVM_ROOT%\gexamples nmake /f makefile.mak tidy-c cd %PVM_ROOT% goto ENDE :TGEF echo. echo Tidy the Fortran group examples echo ------------------------- cd %PVM_ROOT%\gexamples nmake /f makefile.mak tidy-f cd %PVM_ROOT% goto ENDE :ENDE ./pvm3/maclOs2.cmd0100644007401100000360000000046506401301612013063 0ustar kohlgophercd src\os2 make clean cd ..\..\console\os2 make clean cd ..\..\pvmgs\os2 make clean cd ..\..\examples\os2 make clean cd ..\..\gexamples\os2 make clean cd ..\..\hoster\os2 make clean cd ..\..\libfpvm\os2 make clean cd ..\..\rm\os2 make clean cd ..\..\tracer\os2 make clean cd ..\..\xep\os2 make clean cd ..\.. ./pvm3/makeOs2.cmd0100644007401100000360000000047106401305505013066 0ustar kohlgophercd src\os2 make install cd ..\..\tracer\os2 make install cd ..\..\console\os2 make install cd ..\..\pvmgs\os2 make install cd ..\..\hoster\os2 make all cd ..\..\examples\os2 make all cd ..\..\gexamples\os2 make all cd ..\..\libfpvm\os2 make install cd ..\..\rm\os2 make install cd ..\..\xep\os2 make all cd ..\.. ./pvm3/Readme0100644007401100000360000004437707521531031012234 0ustar kohlgopher PVM version 3.4: Parallel Virtual Machine System University of Tennessee, Knoxville TN. Oak Ridge National Laboratory, Oak Ridge TN. Emory University, Atlanta GA. Authors: J. J. Dongarra, G. E. Fagg, G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam (C) 1997 All Rights Reserved NOTICE Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted provided that the above copyright notice appear in all copies and that both the copyright notice and this permission notice appear in supporting documentation. Neither the Institutions (Emory University, Oak Ridge National Laboratory, and University of Tennessee) nor the Authors make any representations about the suitability of this software for any purpose. This software is provided ``as is'' without express or implied warranty. PVM version 3 was funded in part by the U.S. Department of Energy, the National Science Foundation and the State of Tennessee. ________________________________________________________________________ WHAT IS PVM? PVM is a software system that enables a collection of heterogeneous computers to be used as a coherent and flexible concurrent computational resource, or a "parallel virtual machine". The individual computers may be shared- or local-memory multiprocessors, vector supercomputers, specialized graphics engines, or scalar workstations and PCs, that may be interconnected by a variety of networks, such as Ethernet or FDDI. PVM consists of a run-time environment and library for message-passing, task and resource management, and fault notification. While PVM will not automatically make a commerical software package run faster, it *does* provide a powerful set of functions for manually parallelizing an existing source program, or for writing new parallel / distributed programs. The PVM software must be specifically installed on every machine that is to be used in your "virtual machine". There is no "automatic" installation of executables onto remote machines in PVM, although simply copying the pvm3/lib and pvm3/bin directories to another *similar* machine (and setting $PVM_ROOT and $PVM_ARCH - see below) is sufficient for running PVM programs. Compiling or building PVM programs requires the full PVM installation. User programs written in C, C++ or Fortran can access PVM through provided library routines. ________________________________________________________________________ UNPACKING This distribution contains source code, some simple examples, and run-time support for PVM version 3. The documentation for PVM can be obtained separately from Netlib. To get a list of available subsets, send e-mail to "netlib@ORNL.GOV" with the subject: "send index from pvm3". The files in the source distribution unpack into a "pvm3" directory. The pvm3 directory can reside in either a private or shared disk area. Installations for multiple machine architectures can coexist in the same shared filesystem because compiled files are placed in different subdirectories named for each architecture ($PVM_ARCH). Some of the more important directories are: Directory Contains --------------------------------------------------------------- bin/$PVM_ARCH/ PVM user program executables (examples & your programs) conf/ Make configuration files for all PVM architectures console/ Source for the pvm console doc/ Miscellaneous documentation examples/ Example PVM programs source files gexamples/ More example PVM programs - for group library hoster/ An example "hoster" program include/ Header files for PVM programs lib/ Generic system executables (scripts, rc file stubs) lib/$PVM_ARCH/ System executables (pvmd, console, etc.) libfpvm/ Source for the libfpvm Fortran library man/man[13]/ Online manual pages (nroff format) misc/ Some miscellaneous PVM examples and utilities patches/ Patch files and instructions, as they are released pvmgs/ Source for the libgpvm library and group nameserver rm/ An example resource manager for PVM shmd/ A special daemon for shared memory systems (*MP) src/ Source for the libpvm library and pvmd daemon src/$PVM_ARCH/ Additional source code for specific machines tasker/ An example "tasker" program for PVM tracer/ An example "tracer" program for PVM xep/ An example interactive X-Window program BUILDING AND INSTALLING To build the full PVM software, you will need to have a "make" utility, a C or C++ compiler, and a Fortran compiler installed on your system. Before building or running PVM, you must set the environment variable "PVM_ROOT" to the path where PVM resides, i.e. the path of the directory with this "Readme" file. This can be in a private area, for example $HOME/pvm3, or a public one, such as /usr/local/pvm3. If your shell is csh, add a line such as: setenv PVM_ROOT $HOME/pvm3 to your .cshrc file. If you use a shell that reads .profile, such as sh or ksh, or .bashrc for bash, add the following lines to that file: PVM_ROOT=$HOME/pvm3 export PVM_ROOT The use of this variable and others is explained more fully in the pvm_intro man page. You can also include an appropriate shell startup file stub to set other PVM environment variables and to add PVM directories to your execution path. Inert the matching stub file, pvm3/lib/cshrc.stub, pvm3/lib/kshrc.stub or pvm3/lib/bashrc.stub, after your declaration of PVM_ROOT in your shell startup file. To build PVM for your system, type "make" in this directory. Make will use the "aimk" in the pvm3/lib directory to build the daemon executable (pvmd3), the C library (libpvm3.a), the Fortran library (libfpvm3.a) and the console client program (pvm). The libraries and executables are installed in $PVM_ROOT/lib/$PVM_ARCH, where $PVM_ARCH is the host architecture name, e.g. "CRAY" or "LINUX". If you have problems compiling PVM on your system, check the architecture-specific configuration file: $PVM_ROOT/conf/$PVM_ARCH.def for comments regarding alternative configurations for your system. The provided scripts $PVM_ROOT/lib/pvm and $PVM_ROOT/lib/pvmd are used to start the PVM console and the PVM daemon, respectively. They determine the machine architecture and run the actual programs in the $PVM_ROOT/lib/$PVM_ARCH directory. You can either copy these scripts to your bin directory or add $PVM_ROOT/lib to your shell search path (using the above *.stub files). You may wish to add $PVM_ROOT/man to your MANPATH environment variable, if it's supported on your system. This will allow you to easily read the online manual pages. ALTERNATIVES TO RSH To use "ssh" instead of "rsh" on your system, you can either: 1. Modify the $PVM_ROOT/conf/$PVM_ARCH.def file to change the absolute path specified for RSHCOMMAND in the ARCHCFLAGS define. Replace the path to rsh with the absolute path to "ssh" on your system and then recompile PVM and your applications. Or, 2. Set the "PVM_RSH" environment variable to point to the absolute path to "ssh" on your system. This does not require re-compilation but must be done in every shell from which PVM is executed. The "PVM_RSH" environment variable can be set in your $HOME/.cshrc or equivalent shell startup file to take affect in all new shells. Once either of these approaches has been applied, the $HOME/.rhosts file is then no longer necessary for PVM, thereby eliminating a fundamental security concern. Now, to add PVM hosts (using ssh), you can either manually enter your password each time you add a host, or else you can set up an ssh-agent session. (You can always just use a $HOME/.shosts file, but then you're not much more secure than with standard rsh...) When manually entering your password, you will not receive a prompt from PVM or ssh - the text prompts normally returned by ssh are automatically captured and written to the local /tmp/pvml. log file. However, simply typing your password from inside the "pvm" console or when running the "pvmd" script will work. You can bypass this manual password entry for a given session by executing the following commands (example is for bash, could use for any shell): $ ssh-agent bash $ ssh-add $ pvm $ pvm> add host2 . . . For this to work, you must have run "ssh-keygen" on each host to create a private/public key pair for your login id. These keys are typically stored in the $HOME/.ssh directory on each system. The $HOME/.ssh/identity.pub public key must be copied to each remote host and added as a line in the $HOME/.ssh/authorized_keys file on the remote system. When this has been set up, any PVM hosts can be added without password or passphrase entry using the above ssh-agent session. STARTING AND STOPPING PVM To start PVM, run $PVM_ROOT/lib/pvm. This starts the console task, which in turn starts a pvmd if one is not already running. More hosts can be started and added to your "virtual machine" by using the console "add" command. To start the pvmd without starting the console, you can also run the $PVM_ROOT/lib/pvmd directly. A number of hosts can all be started at once by supplying the pvmd with a host file, as in: $PVM_ROOT/lib/pvmd my_hosts where "my_hosts" contains the names of the hosts you wish to add, one host per line. See the pvmd man page for other host file options. To stop PVM, use the PVM console command "halt". From within your user programs, you can use the pvm_halt() function. You can also kill the pvmd3 process (always use a catchable signal such as SIGTERM). But, if you do kill the pvmd, or if it fails for some other reason, always be sure to remove any leftover /tmp/pvmd. pvmd socket files, where is your numerical user id. These files will make PVM think a pvmd is running, and can cause the dreaded "Can't Start Pvmd" message. For more information about the console commands, see the console "help" function or the console man page. TROUBLESHOOTING If you ever have trouble starting PVM or adding a new host to your virtual machine, verify that there are no leftover /tmp/pvmd. daemon socket files on the machines where you are trying to start PVM (as described above) and then check the local /tmp/pvml. log file for any error messages which may help you to determine the problem. A common problem is caused by restricted access to a remote machine via "rsh". PVM uses "rsh" to start the pvmd on a remote host. If you cannot do this: % rsh remote_host 'echo $PVM_ROOT' and successfully get back the correct value of $PVM_ROOT on that remote host, without typing your password, then that is the problem. You will need to set up permissions on the remote host to allow rsh access without a password. On Unix systems, this is accomplished by creating a $HOME/.rhosts file on the *remote* machine that provides access to your *local* machine. (Note: the $HOME/.rhosts file is *NOT* a PVM host file...) The format of a $HOME/.rhosts file is as follows: your_host_1 your_login_on_host_1 your_host_2 your_login_on_host_2 your_host_3 your_login_on_host_3 . . . If you get really stuck, try checking the online FAQ off of the PVM Home Page: http://www.netlib.org/pvm3/book/node23.html#SECTION00450000000000000000 Master Host IP Address is Loopback! ----------------------------------- *** If you see "Master Host IP Address is Loopback!" or get the PvmIPLoopback error when adding hosts, this means that the networking on your Master PVM host (the one you initially started PVM on) is not set up correctly for networking to multiple, remote hosts in your virtual machine. By default, especially on many Linux systems, your system's host name alias is appended to the 127.0.0.1 loopback, or localhost, IP address in the /etc/hosts file. This is very useful for PCs running in stand-alone mode without networking, however this alias must be removed for interaction with remote hosts in PVM. The bottom line is that you need to assign a "real" IP address to your machine's host name in /etc/hosts. By default, most Linux systems create an entry like this: 127.0.0.1 localhost.localdomain localhost foo where "foo" is your system's host name. The problem here is that PVM uses the host name "foo" to look up the IP address for your system, so PVM gets the localhost "loopback" IP address (127.0.0.1) by mistake. You need to create a separate line in /etc/hosts that associates your host name with its externally recognized IP address: 127.0.0.1 localhost.localdomain localhost 123.45.67.89 foo.your.domain foo Make sure that you remove any references to your host name / alias from the 127.0.0.1 line, or else put the new hard-coded IP address line *before* the localhost line in /etc/hosts... If you don't want to manually change your /etc/hosts file in this way, then please see the Linux Networking HOWTO for information on automatically handling this scenario (via ifup-local and ifdown-local scripts). Also keep in mind that you can start PVM using the '-n' flag to select a specific host name & corresponding IP address, as in: $ pvm -nfoo Note that there is no space between the '-n' and your desired host name. Clusters with Internal and External Networks -------------------------------------------- If you have a cluster system with an internal network that can't be seen from outside the cluster, then you may have problems adding cluster nodes to a virtual machine that was started on the head cluster node. The problem is likely related to a mixing of your cluster's internal versus external networking setup. Your front-end head cluster node likely has *two* IP addresses, one for the external network, and one for the internal network. This is a common scenario where the front-end node that can see both the external network and also the internal cluster network, but the internal cluster nodes cannot see the external network. When you start PVM on the master node, by default it uses the system host name to look up the network interface and corresponding IP address (using gethostbyname()). In most cases, this will be the IP address for the externally visible network interface. So, when you try to add an internal cluster node from the master, PVM will initiate the connection using this external IP address, which the cluster node can't see from inside its private, internal network. Then PVM will in fact double-check the source IP address of incoming message packets at the internal cluster nodes, and if the IP's don't match, it drops the packets (for security reasons). Therefore, the replies from the cluster nodes' PVM daemons will never reach the master PVM daemon. The solution is to start PVM using the *internal* network interface (and corresponding IP address) on the master node, so that the internal cluster nodes will correctly recognize the front-end node's IP address and network packets. This can be accomplished using the '-n' argument to the "pvm" console, as in: pvm -nfoo where "foo" is the master's host name on the internal network. (Note: there is no space between the '-n' and the 'foo'... :-) Clearly, for this to work, your front-end master cluster node must have 2 entries in its /etc/hosts file, one mapping the external IP address to some externally recognized host name, and there must be another line with the internal network IP address and a distinct internal network host name. You should be aware that running PVM on the master node using the internal network interface, to enable the internal cluster nodes to see the master, precludes adding hosts from the external network to your virtual machine. The master node does *not* act as a gateway between the internal and external networks in PVM. Instead, if you really need to include nodes on an external network in the same PVM virtual machine with your cluster nodes, then you should use the BEOLIN port of PVM, which uses a single PVM daemon on the master node and treats the cluster as one computational resource. (See the pvm3/Readme.Beolin file for information and usage.) Hope this helps! Linux / GCC Warnings -------------------- In Linux, with the latest version of gcc, if you get the warning: "the use of `tmpnam' is dangerous, better use `mkstemp'" from gcc, you may safely ignore it. PVM cannot use the mkstemp() function to create a temporary file for binding to its sockets, as the mkstemp() function actually opens the given file & returns a file pointer. The mktemp() function (without the "s") could be used in place of tmpnam(), but this function *also* produces the same gcc warning. It's all quite annoying really, as tmpnam() works just fine for our purposes... Hrmph. APPLICATION PROGRAMS C, C++ and Fortran programs must be linked with the main PVM library, $PVM_ROOT/lib/$PVM_ARCH/libpvm3.a, and Fortran programs must also be linked with the $PVM_ROOT/lib/$PVM_ARCH/libfpvm3.a library file. User program source files should include the $PVM_ROOT/include/pvm3.h header file for C/C++ programs, to define PVM constants and function prototypes. The corresponding Fortran header file is $PVM_ROOT/include/fpvm3.h. Executables should be installed in $PVM_ROOT/bin/$PVM_ARCH for a user installation (where the $PVM_ROOT directory is somewhere in a user-writable area), and in $HOME/pvm3/bin/$PVM_ARCH for a system-wide PVM installation (such as /usr/local/pvm3, where the user may not be able to write to the $PVM_ROOT/bin/$PVM_ARCH directory). The default execution path can be changed; see the "ep=" option on the pvmd man page. When user programs are spawned by PVM, by default they execute in the $HOME directory of the user. Any input or data files should therefore reside in or be linked to $HOME. This default working directory can be changed; see the "wd=" option on the pvmd man page. CONTACT The PVM web home page is at http://www.csm.ornl.gov/pvm/pvm_home.html . A newsgroup, comp.parallel.pvm, exists for discussions about PVM and help with specific problems. Please direct any e-mail (questions, bugs, bug fixes, etc.) to: pvm@msr.CSM.ORNL.GOV. To report bugs or problems with PVM, please see the file $PVM_ROOT/doc/bugreport . ________________________________________________________________________ Sincerely, The PVM research group ./pvm3/Readme.Beolin0100644007401100000360000001253007053271023013427 0ustar kohlgopher This readme file describes the BEOLIN (Beowulf LINUX) port of PVM. PURPOSE: Some Beowulf clusters are designed so that not all nodes are visible to the external world. In these cases, there is often a "front end" node which connects to the world, and the rest of the nodes are on an internal network. This has the disadvantage for PVM users running on an outside computer who want to add the Beowulf computer to their configuration: the PVM code on their computer will be unable to communicate with the Beowulf nodes on the internal network. The BEOLIN port of PVM solves this problem by making the parallelism of the Beowulf computer transparent to the user. This is done in a way similar to the MPP ports of PVM for parallel computers such as the IBM SP2, Cray T3D and others. ARCHITECTURE: This port generates a single copy of the PVM daemon (pvmd). The daemon spawns tasks onto other processors which are selected based on the contents of the PROC_LIST environment variable (see below), with each task going onto a separate processor. Initially each task communicates with the PVM daemon using what is assumed to be a shared files system, in the /tmps directory. Each task then sets up sockets to communicate with the daemon and with each other. To avoid communication bottlenecks through the daemon, it is strongly recommended that the PvmRoute option be set to PvmRouteDirect in your PVM applications using the pvm_setopt() library call (see the man page for pvm_setopt). It should be noted that this single daemon approach works equally well on a cluster where nodes do have externally visible IP addresses. This would be useful on any group of machines where only a single copy of the pvmd is desired. For each task the daemon initiates, it forks a process which in turn executes an rsh to initiate the task on a cluster host. Each forked process shows up in the task list, as .host. The forked process takes care of certain communications to and from the task, such as standard I/O. If a group server is started by a Beowulf task, it will be run on the same master node which is running the Beowulf PVM daemon. INSTALLATION NOTES: To select this Beowulf port when compiling PVM, the PVM_ARCH flag should first be manually set to "BEOLIN" in your $HOME/.cshrc (or equivalent) shell startup file. The /tmps directory must be a shared file system among all the Beowulf processors which will be involved in running PVM tasks. If a different shared directory is desired, this can be set using the new PVM_TMP environment variable, as is now possible with all standard PVM architectures. This distribution is shipped by default with the compile flag -DNOPROT added to the ARCHCFLAGS define in the pvm3/conf/BEOLIN.def configuration file. This turns off security checking between the pvmd and a task when the task initiates the connection process. It has been turned off because of NFS performance problems over a shared file system. If you want to turn authentication protection back on, and don't mind the wait (approximately 15 seconds per check), then the -DNOPROT flag should be removed from the ARCHCFLAGS define and PVM should be recompiled. The front-end node of a Beowulf system which provides access to the internal network will have two IP addresses: one registered address visible to the outside world and one internal address visible only to the other nodes in the cluster. The gethostname() function, when run on this front-end node, must return the host name which is recognized by the other nodes in the cluster, in order for them to communicate with the pvmd daemon on the front end. External hosts wishing to add the Beowulf cluster to a virtual machine will use the host name that maps to the registered external IP address. (PVM resolves multiple network (IP) addresses using the host names associated with each address on a given system, as typically specified in the /etc/hosts file.) RUNNING: The desired processors on the internal network should appear in the environment variable PROC_LIST, as a list of host names separated by colons. For example, on our internal network, the processors are named beginning with the letter 'h' followed by the processor number. So in my $HOME/.cshrc file I might have the statement: setenv PROC_LIST h11:h12:h13:h14 This would allow PVM tasks to be spawned onto h11-14, a total of 4 processors. Any additional spawns beyond the first 4 would result in an error message, unless the earlier tasks completed before the new spawns occurred. Remember, when you use this version of PVM you don't add the nodes individually--just do a spawn, and PVM will automatically spawn to the nodes in your PROC_LIST variable. KNOWN BUGS: Signals don't seem to propagate from the daemon to a task. LINUX claims that signals will be communicated across an rsh connection, but this doesn't work for me. SUPPORT: There is no formal support for this product, but if you find a bug or have a question about it, I'll do what I can. Send email to Paul Springer at the Jet Propulsion Laboratory, Paul.Springer@jpl.nasa.gov. DISCLAIMER: I don't know why the following has to be in all caps, but you know lawyers. THIS IS A DEMONSTRATION RELEASE. THE AUTHOR MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY OTHER PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESSED OR IMPLIED WARRANTY. THIS NOTICE MUST BE MAINTAINED IN ALL DISTRIBUTED VERSIONS. ./pvm3/Readme.Beoscyld0100644007401100000360000001143107354706706014001 0ustar kohlgopher This readme file describes the BEOSCYLD (Scyld Beowulf) port of PVM. DESCRIPTION: The purpose of this port is to implement a version of PVM for use with the Scyld Beowulf cluster operating system. Since the slave nodes in a Scyld Beowulf cluster do not by default contain a full installation, the primary changes for this port were to provide the mechanisms for getting jobs out to the slave nodes. There were two major problems to solve. Number one, how do we get PVM slave daemons out to the slave nodes? And number two, how can a slave daemon spawn a job when there typically aren't any binaries on the slave node? The first problem is typically solved using 'rsh' or 'ssh'. However since Scyld slave nodes don't contain a full Linux installation, these tools couldn't be used. The solution was to use 'bpsh'. The bproc shell facility is used to migrate PVM slave daemons from the master node to the appropriate slave nodes. The solution to the second problem was implemented through the magic of bproc. The traditional fork/exec sequence could not be used on a slave node because in all likelihood the desired binary would not be available locally. When a PVM slave daemon performs a task spawn, the following sequence occurs: 1) fork is called to create a new process; 2) using bproc, the new process is moved back to the master node; 3) the binary is located on the master by searching the DEFBINDIR path; 4) once located, bproc is again used to execmove the process back to the slave node from which it came. The master PVM daemon can be started on the master node using the PVM console. You can use the console's add command to add slave nodes to your virtual machine. The syntax for the command would be as follows: "add .#", replacing the '#' character with the node's assigned number in the cluster (as listed in beosetup). Alternately, you can start the PVM console by specifying a hostfile name on the command line. This file should contain the .# names of the slave nodes you want as part of the virtual machine. As with standard PVM, this method automatically spawns PVM slave daemons to the appropriate slave nodes in the cluster. INSTALLATION & RUNTIME ISSUES: This section describes the installation and runtime issues associated with the RPM installation of the BEOSCYLD PVM port. If you're working from a tarball, with the BEOSCYLD patches applied, you need to define the following environment variables (as specified below) as explained in the general PVM Readme file: export PVM_ARCH=BEOSCYLD export PVM_RSH=`which bpsh` export PVM_ROOT= The use of these variables and others is explained in more detail in the pvm_intro man page. It's also probably a good idea to examine the build time configuration file: $PVM_ROOT/conf/BEOSCYLD.def. Assuming you're using the PVM tools from the RPM installation, the following build / runtime information may prove useful. 1) PVM_ARCH was set to BEOSCYLD when building the binaries. 2) PVM_ROOT was set to /usr/share/pvm3 when building the binaries. You can override this setting at runtime by creating a PVM_ROOT environment variable. 3) RSHCOMMAND was set to /usr/bin/bpsh when building the binaries. You can override this setting at runtime by creating a PVM_RSH environment variable. 4) PVMDPATH was set to /usr/sbin/pvmd3 when building the binaries. 5) The default binary directory search path, DEFBINDIR, was set to the following when building the binaries: /usr/bin:$PVM_ROOT/bin/$PVM_ARCH:$HOME/pvm3/bin/$PVM_ARCH PVM_ROOT and PVM_ARCH are as defined above and $HOME will of course be expanded appropriately at runtime. 6) All PVM tools and applications which make use of the PVM library, are statically linked against /usr/lib/libbproc.a. This alleviates the need to have the shared library version of libbproc out on the slave nodes to execute PVM binaries. KNOWN BUGS: This port was verified using the pvmtest33 "pvm test suite" tarball. All tests were executed and all tests passed. The only item worth mentioning is that if a PVM daemon running on a slave node crashes such that the file /tmp/pvmd.uid does not get deleted, the daemon will not restart on that slave node until the file is removed. This is not really a bug, but a result of PVM's implementation. It's mentioned merely because it is an easy thing to verify when things don't appear to be working properly with respect to slave nodes. Note that the PVM debugger was not tested. SUPPORT: For questions or comments about this PVM port, contact the author by sending an email to Joe Vitale at Scyld Computing Corporation, vitale@scyld.com, or by contacting the Scyld Technical Support Team directly at support@scyld.com. DISCLAIMER: THE AUTHOR MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESSED OR IMPLIED WARRANTY. ./pvm3/Readme.Cygwin0100644007401100000360000000410007240352763013462 0ustar kohlgopher#*****************************************************************************# # # READ_ME_PVMcygwin.txt 03/30/1999 # #*****************************************************************************# To install PVM 3.4.0 in the Cygwin environment: 1- Install the Cygwin version b20.1 package (http://sourceware.cygnus.com/cygwin/) 2- Install and configure the WRSHD-9X or WRSHD-NT package (http://www.uni-paderborn.de/cs/getin/download.htm) 3- Choose suitable locations for /tmp and /etc. These could be real directories or mount points. See the Cygwin documentation. 4- Create the passwd and group databases using Cygwin's mkpasswd and mkgroup utilities. 5- Unzip the pvm3_4_0_Xcygwin.ZIP archive in the directory of your choice. This directory will be the PVM root directory. 6- In the Control Panel, choose the System icon and select the environment tab. Add the following variables to the system variables (requires administraive privileges under NT): Variable Value PVM_ARCH Win32 PVM_ROOT Windows path to the PVM root directory (e.g., D:\pvm3_4_0) PVM_ROOT_U Unix path to the PVM root directory, using / instead of \, and a mount point if necessary (e.g., /disks/d/pvm3_4_0) 7- Add the directory containing the CYGWIN1.DLL file to the system PATH variable. If the path already includes some directory containing POSIX utilities from the NT resource kit, the directory containing the CYGWIN1.DLL file must be inserted before the one containing POSIX utilities. 8- If the locations chosen for /tmp and /etc are not direct subdirectories of C:\ or if the PVM root directory is not on the C: drive, you must create permanent mount points for them. In the registry editor, go to the key: \\HKEY_LOCAL_MACHINE\SOFTWARE\Cygnus Solutions\CYGWIN.DLL.setup\b15.0\mounts and, for each of the needed mount points, select the first empty subkey and add the following values: fbinary (REG_DWORD) 0 fsilent (REG_DWORD) 0 native (REG_SZ) windows path (e.g., C:\TEMP) unix (REG_SZ) unix path (e.g., /tmp) This may require administraive privileges under NT. 9- Reboot the system. ./pvm3/Readme.mp0100644007401100000360000006171506673540515012660 0ustar kohlgopherThis is a supplement to the main Readme file. The reader should consult that file for more information. Table of Contents ----------------- 1. MPP vs. Workstation Cluster 2. Usage 3. iPSC/860 4. Paragon 5. CM5 6. IBM SP2 AIX 3.x AIX 4.x 7. Shared-memory Systems (pvmd and internal) Solaris 2.X+ 8. Shared-memory Systems (separate daemon) ATT SysV shmop supported systems 1. Massively Parallel Systems vs. Workstation Cluster ----------------------------------------------------- In the workstation environment, there is usually one (or a few at the most) task(s) and one PVM Daemon (pvmd) on each host. On a MPP machine, however, only one pvmd runs on the front-end and it has to support all the tasks running on the back-end nodes. On an SP, the node on which PVM is started becomes the front-end. On a MPP machine tasks are always spawned on the back-end nodes. If you want to start a task on the front-end you have to run it as a Unix process, which then connects to the pvmd by calling pvm_mytid(). Tasks to be run on the front-end should be linked with the socket- based libpvm3.a (i.e., compiled with the option "-lpvm3"), while tasks to be spawned on the back-end must be linked with libpvm3pe.a (i.e., compiled with the option "-lpvm3pe"). On the Paragon, tasks running on the back-end communicate with one another directly, but packets going to another machine or to a task on the front-end must be relayed by pvmd. To get the best performance, the entire program should run on the back-end. If you must have a master task running on the front-end (to read input from the user terminal, for example), the master should avoid doing any compute-intensive work. On the CM5 and SP, each batch of tasks created by pvm_spawn() form a unit. Within the same unit, message are passed directly. For each unit, PVM spawns an additional task to relay messages to and from pvmd, because tasks in the unit cannot communicate with pvmd directly. Communication between different units must go through pvmd. To get the best performance, try to spawn all your tasks together. The system supports on nodes of some MPP machines are limited. For example if your program forks on a node, the behavior of the new process is machine-dependent. In any event it would not be allowed to become a new PVM task. Inter-host task-to-task direct routing via a TCP socket connection has not been implemented on the nodes. Setting the PvmRouteDirect option on a node has no effect. PVM message tags above 999999000 are reserved for internal use. You should not have to make any changes in your source code when you move your PVM program from a workstation cluster to a MPP, unless your program contains machine-dependent code. You do need to, however, modify the makefile to link in the approriate libraries. In the examples directory, you'll find a special makefile for each MPP architecture, hidden under the ARCH directory. On some MPP you must use a special compiler or loader to compile your program. 2. Usage -------- Once properly installed, PVM can be started on a MPP by simply typing pvm or pvmd&. Although a MPP has many nodes, it is treated as a single host in PVM, just like a workstation. PVM has access to all the nodes in the default partition. To run a program in parallel, the user spawns a number of tasks, which will be loaded onto different nodes by PVM. The user has no control of how the tasks are distributed among the nodes. So running a parallel program on a MPP is like running it on a very powerful uniprocessor machine with multitasking. For example, to run nntime program on the IBM SP, we first start PVM on the high performance switch, and then spawn 2 copies of nntime from the console: r25n15% pvm3/lib/pvm -nr25n15-hps pvm> conf 1 host, 1 data format HOST DTID ARCH SPEED r25n15-hps 40000 SP2MPI 1000 pvm> spawn -2 -> nntime [1] 2 successful t60000 t60001 pvm> [1:t60000] t60001: 100000 doubles received correctly [1:t60000] [1:t60000] [1:t60000] t60000: 100000 doubles received correctly [1:t60000] [1:t60000] [1:t60000] Node-to-node Send/Ack [1:t60000] [1:t60000] Roundtrip T = 90 (us) (0.0000 MB/s) Data size: 0 [1:t60000] Roundtrip T = 105 (us) (1.5238 MB/s) Data size: 80 [1:t60000] Roundtrip T = 207 (us) (7.7295 MB/s) Data size: 800 [1:t60000] Roundtrip T = 920 (us) (17.3913 MB/s) Data size: 8000 [1:t60000] Roundtrip T = 5802 (us) (27.5767 MB/s) Data size: 80000 [1:t60000] Roundtrip T = 47797 (us) (33.4749 MB/s) Data size: 800000 [1:t60001] EOF [1:t60000] EOF [1] finished pvm> halt r25n15% To run nntime from command line and not from the console you can use the starter program provided in the examples directory. r25n15% pvm3/lib/pvm -nr25n15-hps pvm> conf 1 host, 1 data format HOST DTID ARCH SPEED r25n15-hps 40000 SP2MPI 1000 pvm> quit r25n15% bin/SP2MPI/starter -n 2 nntime There is no need to "add" any nodes, "conf" showed only one host. We note that nntime is a true "hostless" (SPMD) program in the sense that it has no master task. The spmd example, on the other hand, has a master task which spawns other slave tasks. Hostless programs perform better than master-slave programs because all the tasks can be spawned together onto back-end nodes. PVM does not distinguish between a multiprocessor system and a uniprocessor system. While machine-specific information such as the number of processors and the power of individual processor would be useful for load-balancing purpose, PVM neither supplies nor makes use of such information. 3. iPSC/860 ----------- This port was developed on an iPSC/860 with 128 nodes, using an SRM as its front-end. Compiling and installing on a remote host may require extensive knowledge of Intel software. INSTALLATION Type "make" on the SRM front-end to build pvmd and libpvm3.a, and make PVM_ARCH=CUBE to build libpvm3pe.a on a machine (SRM or workstation) that has the icc/if77 i860 cross-compilers. To make the examples, repeat the above steps in the "examples" directory but use ../lib/aimk instead of make. (Note that aimk --- and pvmd, pvmgetarch, etc. --- is a sh script. You have to run them under sh instead of csh. The i386 frontend running sysV3.2 does not understand #!, so you have to put a blank line at the beginning of the scripts.) To build pvmd and libpvm3.a on a remote host (Sun/SGI) instead of the SRM, try make PVM_ARCH=I860 You may have to add a -L option to the definition of ARCHDLIB and a -I option to ARCHCFLAGS in conf/I860SUN4.def (or conf/I860SGI.def) to include the path of libhost.a and cube.h . APPLICATION PROGRAMS Host (master) programs should be linked with pvm3/lib/I860/libpvm3.a and the SRM system library libsocket.a, node (slave) programs with pvm3/lib/ARCH/libpvm3pe.a and libnode.a . Fortran programs should also be linked with pvm3/lib/I860/libfpvm3.a (host program) or pvm3/lib/I860/libfpvm3pe.a (node program). The programs in the gexamples directory have NOT been ported. The user must modify the makefiles to link to the appropriate libraries. BUGS AND TIPS a) On the SRM pvm is slow to start and it may sometimes time out and print out the message "can't start pvmd", while in fact pvmd has already been started. When this happens, just run pvm again and it'll connect to the pvmd. If you start the pvm console on another machine and add the I860 host to the configuration then this should not occur. b) To use PVM on a remote host you have to start "pvm3/lib/I860/pvmd" manually in the background, because PVM has no way of knowing that your workstation is being used as a front-end to the hypercube. PVM relies on the shell script "pvm3/lib/pvmd" to determine the architecture of your system, you can hack the script to make it do what you want. c) If PVM cannot obtain a cube of the size you specify because none is available, it will return the error "Out of resources". d) The function pvm_spawn() will NOT return until all spawned tasks check in with PVM. Therefore slave tasks should call pvm_mytid() before starting any heavy duty computation. e) The only signal that can be sent to tasks running on the cube is SIGKILL. Any other signals will be ignored. f) All spawned tasks should call pvm_exit() just before they exit. Pvmd will release the cube after all tasks loaded into the cube have called pvm_exit(). If any task attempts to continue execution after it called pvm_exit(), it'll be terminated when the cube is released. g) There is a constant TIMEOUT in the file "pvmmimd.h" that controls the frequency at which the PVM daemon probes for packets from node tasks. If you want it to respond more quickly you can reduce this value. Currently it is set to 10 millisecond. h) DO NOT use any native NX message passing calls in PVM or they may interfere with pvm_send()/pvm_recv(). i) Messages printed to "stderr" by node tasks do not end up in the log file "/tmp/pvml.uid". j) The "argv" argument to pvm_spawn() is quietly ignored. 4. Paragon ---------- This port has been tested on a Paragon XPS5 running R1.3. The support and information provided by Intel engineers are gratefully acknowledged. INSTALLATION Type "make" in this directory on the Paragon. To build on a cross- compiler machine, you need to type setenv PVM_ARCH PGON make -e The environmental variable PARAGON_XDEV must be set to the proper base directory in the later case. To make the examples, go to the "examples" directory and repeat the above procedure but use ../lib/aimk instead of make. STARTING THE PVMD WITH PEXEC Many Paragon sites use the program "pexec" to manage partitions for application programs. The pvmd startup script has been modified to use pexec, if it exists. The environment variable NX_DFLT_SIZE should be set in the user's .cshrc file and is the size (with a default of 1) of the partition that the pvmd will manage. The partition size can also be set by invoking the pvmd with the command % pvmd [pvmd options] -sz The "pexec" program should exist in /bin/pexec. If it exists in another location, modify the pvm3/lib/pvmd startup script to point at the site-specific location or have the system administrator make the appropriate link. If a PGON is the first ("master") host in the virtual machine, the pvmd should be started first, and then the console may be started: % pvmd -sz & % pvm Other hosts, including other Paragons, may then be added using the console. pvm> add other_pgon pvm> add my_workstation APPLICATION PROGRAMS Host (master) programs should be linked with pvm3/lib/PGON/libpvm3.a and the system library librpc.a, node (slave) programs with pvm3/lib/PGON/libpvm3pe.a, libnx.a, and librpc.a . Fortran programs should also be linked with pvm3/lib/PGON/libfpvm3.a . The programs in the gexamples directory have NOT been ported. The user must modify the makefiles to link to the appropriate libraries. NATIVE MODE COLLECTIVE OPERATIONS If possible, native mode collective operations such as gsync, gisum, and gdsum are used for group operations. The native operations will be used if all of following hold a) A native collective operation exists on the Paragon b) All the nodes in the paragon compute partition are participating in the collective operation (pvm_barrier, pvm_reduce, etc.) c) The group has been made static with pvm_freezegroup If all three conditions do not hold, the collective operation still functions correctly, but does not use native operations. If all the PGON nodes are part of a larger group, the native operations are used for the PGON part of the collective operation. BUGS AND CAVEATS a) Tasks spawned onto the Paragon run on the compute nodes by default. Host tasks run on the service nodes and should be started from a Unix prompt. b) By default PVM spawns tasks in your default partition. You can use the NX command-line options such as "-pn partition_name" to force it to run on a particular partition or "-sz number_of_nodes" to specify the number of nodes you want it to use. Setting the environmental variable NX_DFLT_SIZE would have the same effect. For example starting pvmd with the following command pvmd -pn pvm -sz 33 would force it to run on the partition "pvm" using only 33 nodes (there must be at least that many nodes in the partition). c) The current implementation only allows one task to be spawned on each node. d) There is a constant TIMEOUT in the file "pvmmimd.h" that controls the frequency at which the PVM daemon probes for packets from node tasks. If you want it to respond more quickly you can reduce this value. Currently it is set to 10 millisecond. e) DO NOT use any native NX message passing calls in PVM or they may interfere with pvm_send()/pvm_recv(). f) PVM programs compiled for versions earlier than 3.3.8 need to be recompiled. A small change in data passed to node tasks on startup will cause earlier programs to break. 5. CM5 ------ This port was developed on a 32-node CM5 running CMOST v7.2 and CMMD3.0. We gratefully acknowledge the supports and information provided by engineers of Thinking Machines Corp. INSTALLATION Type "make" in this directory. To make the examples, go to the "examples" directory and type ../lib/aimk default APPLICATION PROGRAMS Host (master) programs should be linked with pvm3/lib/CM5/libpvm3.a . Node (slave) programs need to be linked to pvm3/lib/CM5/libpvm3pe.a and joined with pvm3/lib/CM5/pvmhost.o and pvm3/lib/CM5/libpvm3.a using the CMMD loader "cmmd-ld". Fortran programs should also be linked with pvm3/lib/CM5/libfpvm3.a . The programs in the gexamples directory have NOT been ported. The user must modify the makefiles to link to the appropriate libraries. BUGS a) The function pvm_kill() does not behave like a Unix kill: it will delete the target task from PVM's task queue but doesn't actually kill the task. b) Signals sent by pvm_sendsig() are simply discarded, except for SIGTERM and SIGKILL, which are equivalent to calling pvm_kill(). c) You're not allowed to spawn more tasks than the number of nodes available in your partition in one call to pvm_spawn(). d) If you kill the node tasks from PVM (e.g., using pvm_kill), the node processes will dump core files into your HOME directory. I don't consider this to be a PVM bug. 6. IBM SP2 ---------- This implementation is built on top of MPI-F, IBM's version of the Message Passing Interface. Information provided by Hubertus Franke of IBM T. J. Watson Research Center is gratefully acknowledged. KEY FOR OPERATING SYSTEM VERSION Based on the AIX version on your SP2, insert one of the following architecture designations for "" in the discussion below. ^^^^^^^^^^ for AIX 3.x use SP2MPI for AIX 4.x use AIX4SP2 INSTALLATION Type "make PVM_ARCH=" in this directory. Make sure the mpicc compiler is in your path. To make the examples, go to the "examples" directory, and type setenv PVM_ARCH ; ../lib/aimk APPLICATION PROGRAMS Host (master) programs should be linked with: pvm3/lib//libpvm3.a . Node (slave) programs must be compiled with the mpicc compiler for a C program and mpixlf compiler for a FORTRAN program, and then linked with pvm3/lib//libpvm3pe.a . FORTRAN programs should also be linked with pvm3/lib//libfpvm3.a . The programs in the gexamples directory have NOT been ported. The user must modify the makefiles to link to the appropriate libraries. BUGS AND CAVEATS a) The user is required to set MP_PROCS and MP_RMPOOL environment variables or provide a node file (MP_HOSTFILE) for the SP that lists all the nodes the user intends to run PVM on. This is not to be confused with the PVM hostfile. Before starting PVM, the POE environment variable MP_HOSTFILE should be set to the path of the user's SP node file. For example I have the line "setenv MP_HOSTFILE ~/host.list" in my .cshrc file. My host.list file contains the names of the high-performance switches on all the parallel nodes. If you do not want to use the SP node file, then you can set MP_PROCS to the maximum number of nodes you will need plus one. The number listed here should be equal to the number of nodes you would have listed in the MP_HOSTFILE. So if you need a 5 task job then you will need to set MP_PROCS=6 and if you need spawned two 5 task jobs then you will need to set MP_PROCS=12. MP_RMPOOL is set to default value of "1" but you may need to change it depending how your administrator has allocated the SP nodes into different pools. You can run "/usr/bin/jm_status -P" to see what POOL id's and nodes are available. b) On a SP node only one process can use the switch (User Space) at any given time. If you want to share the switch between different users then you will need to run in IP mode over the switch. To do this, you must set "setenv MP_EUILIB ip" before starting PVM. The default value for "MP_EUILIB" is "us". These environment variables should be set before starting PVM and this configuration will last until PVM is halted. To run your program you need one node for each PVM task, plus one for the PVM host process that relays messages for pvmd. So if you want to spawn 8 PVM tasks, for instance, you'll need at least 9 node names in your SP node file. Remember there is a host process for each group of tasks spawned together. If you spawn 8 tasks in two batches, you'll need 10 nodes instead of 9. c) Signals sent by pvm_sendsig() are simply discarded, except for SIGTERM and SIGKILL, which are equivalent to calling pvm_kill(). d) If you kill one PVM task using pvm_kill(), all the tasks spawned together will also die in sympathy. e) To get the best performance for communications that involves pvmd, for example when you pass messages between two group of tasks spawned separately, use switch names in the node file instead of the host names, and start pvm with the -nswitchname option. This would force any socket communication to go over the high-performance switch rather than Ethernet. 7. Shared-memory Systems ------------------------ These ports achieve better performance by using shared memory instead of sockets to pass messages. They're fully compatible with the socket version. In addition, tasks linked to different PVM libraries can coexist and communicate with each other. (But these messages are routed through the PVM daemon instead of using shared memory.) On architectures that support shared memory operations, the default PVM architecture selection is still non-shmem, therefore to turn on selection of the appropriate *MP architecture the user must set the environment variable "PVM_SHMEM" to "ON", as in: % setenv PVM_SHMEM ON (Note that the old "$SGIMP" environment variable has been subsumed with the new "$PVM_SHMEM" environment variable.) The original socket library in PVM 3.4 is now (consistently) named libpvm3.a, whether on a shared memory (*MP) architecture or not. The new shared memory version of the PVM library is now named "libpvm3s.a", and users can link their programs with -lpvm3s if they would rather use shared memory for local communication. (Note that this naming convention is the *reverse* of the PVM 3.3 naming convention - sorry.) There is also now a new PVM shmd shared memory daemon, to control and monitor the use of shared memory. This alleviates a significant number of bugs as compared to the PVM 3.3 implementation. BUGS AND CAVEATS a) Messages are sent directly, pvm_setopt(PvmRoute, PvmRouteDirect) has no effect. The sender will block if the receiving buffer is full. This could lead to deadlocks. b) The buffer size used by PVM, SHMBUFSIZE, is defined in pvm3/src/pvmshmem.h, with a default of 1MBytes. You can change the buffer size by setting the environment variable PVMBUFSIZE before starting PVM. Note that the default system limit on shared-memory segment size (1 MB on Sun's) may have to be raised as well. c) PVM uses the last 10 bits of the Unix user ID as the base for the shared-memory keys. If there is a conflict with keys used by another user or application, you can set the environment variable PVMSHMIDBASE to a different value. d) If PVM crashes for any reason, you may have to remove the leftover shared-memory segments and/or semaphores manually. Use the Uhix command `ipcs` to list them and `ipcrm` to delete them. Or, use the script `ipcfree` in $PVM_ROOT/lib. e) For best performance, use psend/precv. If you must use the standard send/recv, the InPlace encoding should be used where appropiate. Solaris2.3+ ---------- APPLICATION PROGRAMS All PVM programs must be linked with the thread library (-lthread). Refer to the example Makefile (pvm3/examples/SUNMP/Makefile) for details. BUGS AND CAVEATS a) There is a system limit on the number of shared-memory segments a process can attach to. This in turn imposes a limit on the number of PVM tasks allowed on a single host. According to Sun Microsystem, the system parameter can be set by a system administrator. b) Some of the newer PVM shared memory systems prefer to use semaphores instead of mutex and conditional variables. Some of these systems also support the V8plus instruction set. The semaphore version has been made the default version at the request of Sun MicroSystems. For older systems that need to use the Mutex version, edit the pvm3/conf/SUNMP.def file and add the -DPVMUSEMUTEX flag to the ARCHFLAGS line and null out the PLOCKFILE line. 8. Shared-memory Systems (separate daemon) This version is an add-on that is used to speed up particular application classes at the expense of flexibility, while avoiding many of the un-welcome feature in the generic PVM shared memory system described above. The system is designed to allow programs that use the pvm_psend and pvm_precv calls to be accelerated through the use of a self monitoring shared memory daemon that takes the burden of resource handling away from the PVM host daemons (pvmds). In the generic version of shared memory all messages, even those received through forien pvmds were placed into shared memory, and each task handled its own memory, even though monitoring of processes was still via Unix pipes. This method had a number of know race conditions and other problems once the shared memory was full, or tasks forgot to cleanup their own resources when exiting. This new version hands all the management to a single daemon, and allows the task-daemon operations to continue via pipes/sockets in the time proven way. Uses: This version only uses shared memory for passing messages internal to a single SMP when using pvm_psend, pvm_precv, and NOT pvm_send / pvm_recv with any packed buffers. Messages off the machine (if enabled*) use sockets etc. *See readme in the shmd directory for more info. To use the new version: cd into the shmd directory and do an aimk. This should build two executables, the shared memory daemon (pvm_shmd) and a program to probe the daemon about its state (pvm_shmd_stat). The extra program is required as tickle from the PVM console only tickles the pvmd and not other pvm tasks. (The new program is much like pvm_gstat in the PVM group directory). One other file will have been built, libpvm3shmd.a This is the library file that replaces libpvm3.a when you want to use the shared memory versions of pvm_psend/pvm_precv. If you don't link to this you won't get any benefits. Running the system: Start the pvm_shmd, host% pvm_shmd & The pvm_shmd can be started automatically by calls to psend/precv in the libpvm3shmd.a, but this has to be enabled at compile time. This is currently off as you probably want to monitor how the pvm_shmd works so that you can tune it for your specific applications. Now that the pvm_shmd is running you can use the shared memory calls. More info on the daemon is in the manual pages under pvm_shmd(1PVM). Other options and restrictions are listed in the shmd directory readme file. Bugs: Only know bug to date appears on some linux boxes running RedHat. When *somestimes* first starting the pvm_shmd, no output appears and the shmd daemon spins, it appears that the kernel is creating the SysV resources and holding the daemon on a shmget() call. Just CTRL C the daemon, and start it again! Warnings: As mentioned in the pvm_shmd(1PVM) manual page, don't give all your virtual memory to the pvm_shmd for use in message passing, as you'll need some running actual applications. Under Solaris, this is usually very restricted (6-8 segments 1MB each). IRIX6 on the otherhand can be very very genereous.... and make all the VM shared memory for message passing! Supported Architectures: This system was made using only standard SysV calls. So it should work on *any* platform that supports these calls. (Pigs have been known to fly). The systems that shmd has been tested under include: SGI IRIX64 6.5 SGI IRIX64 origin 6.5 (Origin 2000) SunOS 5.5.1 sun4u sparc SUNW,Ultra-2 SunOS 5.6 sun4u sparc SUNW,Ultra-2 SunOS sol 5.5.1 sun4m sparc SUNW,SPARCstation-10 (4 processor Sun) IBM AIX 2 4 (SP2 4 processor high node) HP V-Class 2250 under HP-UX 11.0 Linux 2.2.2 #9 SMP Sun Feb 28 14:19:40 EST 1999 i686 unknown (Dell Dual PII Linux box) ./pvm3/Readme.Os20100644007401100000360000000320507331310241012654 0ustar kohlgopher================================================================== PVM 3.4.0 for OS2, Bohumir Horeni, horeni@login.cz, Sat Aug 9 1997 ================================================================== Port of Paralel Virtual Machine (PVM) v.3.4.beta3 (Netlib 22 July 1997) to OS2 platform. Mimimal cahanges in "unix" code, no extensive rewriting. tested: ======= PVM Test Engine version 2.0 (patched for gcc/i386) OS2<--->LINUX<--->HPPA used: ===== OS/2 version 4.0 ( v.3 Connect fixpack level 17 ) emx 0.9c (GNU C compiler 2.7.2.1) ftp://hobbes.nmsu.edu RPC for emx http://set.gmd.de/~veit/os2 (9) XF86 Support device driver http://set.gmd.de/~veit/os2 or XFree86 v.3.3 for OS/2 GNU Make (v.3.75) ftp://hobbes.nmsu.edu (*) Korn shell (OS/2 port of pdksh version 5) ftp://hobbes.nmsu.edu GNU file utilities (cp/mv/etc.) ftp://hobbes.nmsu.edu (f) GNU Fortran 0.5.20 for the OS/2 with emx ftp://hobbes.nmsu.edu (f) GNU m4 macro processor (1.4) ftp://hobbes.nmsu.edu (x) XFree86 v.3.3 ftp://hobbes.nmsu.edu (9) kill -9 feature for OS/2 (*) some other shells (bash) failed for -D\"IMA_OS2\" (f) libfpvm, *.f examples (x) xep config.sys (example) ========== ... DEVICE=C:\XFree86\lib\xf86sup.sys ... SET HOME=c:/home SET TMP=c:/tmp ... SET PVM_ROOT=c:/home/work/tools/pvm3 SET PVM_ARCH=OS2 ... # environment for emx, XFree86, ... ... build ===== makeOs2.cmd rebuild ======= maclOs2.cmd makeOs2.cmd PVM === http://www.csm.ornl.gov/pvm/pvm_home.html ./pvm3/Readme.Win320100644007401100000360000001317307331302537013131 0ustar kohlgopher PVM version 3.4: Parallel Virtual Machine System University of Tennessee, Knoxville TN. Oak Ridge National Laboratory, Oak Ridge TN. Emory University, Atlanta GA. Authors: J. J. Dongarra, G. E. Fagg, M. Fischer, G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam (C) 1997 All Rights Reserved NOTICE Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted provided that the above copyright notice appear in all copies and that both the copyright notice and this permission notice appear in supporting documentation. Neither the Institutions (Emory University, Oak Ridge National Laboratory, and University of Tennessee) nor the Authors make any representations about the suitability of this software for any purpose. This software is provided ``as is'' without express or implied warranty. PVM version 3 was funded in part by the U.S. Department of Energy, the National Science Foundation and the State of Tennessee. ________________________________________________________________________ This is a supplement to the main Readme file. The reader should consult that file for more information. Table of Contents ----------------- 0. What's new 1. Possible User Specifications - Different Compiler Dependencies 2. Installation, Environment Settings 3. Startup Differences compared to the Unix version 4. Additional Software for WIN32 5. Further, detailed information 6. Basic Testing 7. Fortran Problems ----------------- 0. What's new. What we are working on (in WIN32): - rshd for convenient startup: Currently users have to install a rshd or rexecd on their machines which is often Shareware. However some of them do not follow the BSD specification. Also it is required to specify the location of the daemon executable which may be installation dependent and different on other machines. We have a rshd in progress which is BSD compliant, but also converting the $VARIABLES to their corresponding values set in the registry. This way the daemon location is no longer needed. However this daemon is allowing only one connection at a time, but we are working on that. - XPVM: XPVM comes with beta6 but is crashing from time to time in its initialization. This is hard to debug since the SEGV is in the TK library. But probably someone can give us some hints. - GUI Console: We would like to integrate all the applications we provide in one GUI application. Changes: From Beta 6: (09/30/98) fortran make files updated to actually work win32 beta merged with unix beta into single source PVM version From Beta 5: (01/22/98) Bug fixes (tracer, console, daemon), Winhelp, XPVM, Static Lib and DLL From Beta 4: (09/23/97) First InstallShield Version, Use of Registry, Bug fixes. . . . 1. Unlike standardized compilers in the Unix world, different flags and libs are used for WIN32. Currently we distinguish between Borland 5.0 or VC++ 4.0 or higher. Thus, a dependency file in %PVM_ROOT/conf named WIN32.def can be modified to point to the INCLUDE and LIB directories of the installed Compiler. It also provides a compiler detection mechanism, which works with a normal compiler installation (checking for INCLUDE environment variables). 2. The installation is now wizard guided. Required information is stored in the registry. For manual installation, please see the documentation in PVM3.4\WIN32\Installation.doc. 3. PVM is started by invoking the console command "pvm" with an additional hostfile argument which identifies potential resources. The machine on which "pvm" is run for the first time (in a given session) is referred to as the "master daemon." If this machine crashes, your PVM virtual machine goes down (a single point of failure). The hostfile should be referenced by full path, e.g. pvm d:\hostfile. Manual adding of hosts is performed by the "add" command in the "pvm" console. Add commands must specify the location of the daemon executable, e.g. pvm> add "hostname dx=d:\pvm3\lib\win32\pvmd3.exe" 4. Rshd or rexecd are required for WINNT, Rshd for WIN95. This is additional (shareware) software that you will find on the WWW, as long as MS does not offer its own solution. Please note that the rshd is required to run remote processes under your account. If you find pvm{d,l}.System in your PVM_TMP directory, then the rshd is NOT working properly. 5. If you are new to PVM, please read the book on PVM or check out the user's guide. You will find it on the PVM homepage at: http://www.csm.ornl.gov/pvm 6. Before using PVM, you should test the functionality of the additional software, e.g. "rsh remotehost -l login dir | more" This should show the directory listing of the remote host. Piping to "more" additionally checks for buffered std{io,err}. 7. We are aware of Fortran problems when calling one of the pvm_pk* functions. This is currently an open question. ./pvm3/WIN32/0042755007401100000360000000000010117676455011723 5ustar kohlgopher./pvm3/WIN32/file.env0100644007401100000360000000003306672027642013342 0ustar kohlgopherPVM_ROOT=c:\PROGRA~1\PVM3.4./pvm3/WIN32/installation.doc0100644007401100000360000017100006673303673015106 0ustar kohlgopherÐÏࡱá>þÿ o[þÿÿÿpPÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿà…ŸòùOh«‘+'³Ù0˜,8P\p ˆ” ° ¼ È Ôàèðøä‰To install PVM on an NT system without using the installshield package requires that the human installer manually perform the same tasksqo iWestern Hemlockest Normal.dotlWestern Hemlock35tMicrosoft Word 8.0n@%@0Ɔùn¾@NÞb…g¾@òùn¾‰(To install PVM on an NT system without using the installshield package requires that the human installer manually perform the same tasks as installshield. These tasks are outlined below. All tasks should be assumed to be for both NT and Win 95/98 systems unless otherwise indicated as only (NT) or only (95/98). Where there are “parallel” task paths for NT versus 95/98 – there will be duplicate item numbers – take ONLY the appropriate path. 1. Unpack the PVM files to directory: C:\Program Files\PVM3.4 Install registry entries for (NT) or environment variables for (95/98): - (NT) Install registry entries. Based on your version of Visual C++ and optionally Digital Fortran, double click on both the pvm.reg and pvm_user_env.reg files in the appropriate directory. NOTE that every PVM user will have to install the pvm_user_env.reg entries for their personal account while pvm.reg need only be done once. - DevStudio 5: C:\Program Files\PVM3.4\WIN32\DevStudio5 - DevStudio 6: C:\Program Files\PVM3.4\WIN32\DevStudio6 (95/98) Install environment values into C:\Autoexec.bat file. Append to C:\Autoexec.bat the contents of C:\Program Files\PVM3.4\into-Autoexec.bat Edit C:\Program Files\PVM3.4\PVMVARS.BAT according to instructions in that file with respect to DevStudio 5 versus DevStudio 6 installations. Install your rshd package according to supplier instructions. (NT) Information provided here is for the Ataman package available at  HYPERLINK http://www.ataman.com http://www.ataman.com (this is a commercial package). In the future we will do additional testing on an internally developed rshd package. Look for information regarding that package in the near future. (NT) Set the environment file to: C:\Program Files\PVM3.4\WIN32\file.env Note that other rshd packages may (or not) require this “help” in setting the PVM_ROOT environment value. This is a result of Ataman’s package not using an individual’s environment settings (this is discussed in Ataman documentation.) Windows 95/98 does not exhibit this problem as it uses the settings in C:\Autoexec.bat to pickup the environment values. Copy the appropriate PVM compile shell (with icon) to your desktop. You will want to use this DOS window when compiling PVM. Perhaps more important, when others walk by your desktop – they will see that you are a proud PVM 3.4.0 user! - (NT) C:\Program Files\PVM3.4\WIN32\PVM NT Compile Shell - (95/98) C:\Program Files\PVM3.4\WIN32\PVM Compile Shell (95/98) If you run the PVM make.bat file and see “Out of environment space” – this indicates that you have too many environment variables set for your initial memory allocation. This can be resolved by: right click the “PVM Compile Shell” icon – select “properties” – choose “memory” tab – increase the “Initial environment” setting – click “OK”. Our initial setting is 2048. We required this value on Windows 95 and 98 machines with C++, Fortran, and PVM environment values installed. If you do more, expect to increase this value. Activate the new environment variables. - (NT) Logoff and the logon. Not as intrusive as “other” applications that require a reboot after every other step… This is necessary so that the new registry entries are recognized as environment variables. - (95/98) Reboot Just can’t be avoided. That is, unless you switch to NT. You are now ready to compile PVM on your machine. Double-click the desktop PVM compile shell icon. Type make.bat at the DOS command prompt to see makefile options. Go for it! To place PVM shortcuts in your START menu – two options: To install shortcuts so that all users have them: (NT) 1. Create directory PVM in C:\WINNT\Profiles\All Users\Start Menu\Programs 2. Create a shortcut for C:\Program Files\PVM3.4\lib\WIN32\pvm.exe Place shortcut in C:\WINNT\Profiles\All Users\Start Menu\Programs\PVM Rename shortcut “PVM Console” Create a shortcut for C:\Program Files\PVM3.4\lib\WIN32\pvmd3.exe Place shortcut in C:\WINNT\Profiles\All Users\Start Menu\Programs\PVM Rename shortcut “PVM Daemon” Create a shortcut for C:\Program Files\PVM3.4\man\WIN32\Pvmhelp.hlp Place shortcut in C:\WINNT\Profiles\All Users\Start Menu\Programs\PVM Rename shortcut “PVM Help” (95/98) 1. Create directory PVM in C:\WINDOWS\Start Menu\Programs 2. Create a shortcut for C:\Program Files\PVM3.4\lib\WIN32\pvm.exe 3. Place shortcut in C:\WINDOWS\Start Menu\Programs \PVM Rename shortcut “PVM Console” Create a shortcut for C:\Program Files\PVM3.4\lib\WIN32\pvmd3.exe Place shortcut in C:\WINDOWS\Start Menu\Programs \PVM Rename shortcut “PVM Daemon” Create a shortcut for C:\Program Files\PVM3.4\man\WIN32\Pvmhelp.hlp Place shortcut in C:\WINDOWS\Start Menu\Programs \PVM Rename shortcut “PVM Help” To install shortcuts so that only an individual has them: (NT) 1. Create directory PVM in C:\WINNT\Profiles\\Start Menu\Programs 2. Create a shortcut for C:\Program Files\PVM3.4\lib\WIN32\pvm.exe 3. Place shortcut in C:\WINNT\Profiles\\Start Menu\Programs \PVM 4. Rename shortcut “PVM Console” 5. Create a shortcut for C:\Program Files\PVM3.4\lib\WIN32\pvmd3.exe 6. Place shortcut in C:\WINNT\Profiles\\Start Menu\Programs \PVM 7. Rename shortcut “PVM Daemon” 8. Create a shortcut for C:\Program Files\PVM3.4\man\WIN32\Pvmhelp.hlp 9. Place shortcut in C:\WINNT\Profiles\\Start Menu\Programs \PVM 10. Rename shortcut “PVM Help” (95/98) option not available on 95/98 systems –operating system limitation IMPORTANT NOTES: ALPHA VS INTEL: Although both Intel and Alpha based machines can run NT, remember that these two systems require their own binary format. Thus, you must compile PVM codes for the target physical architecture. LATE BREAKING NT/95/98 NEWS:  HYPERLINK http://www.epm.ornl.gov/~sscott http://www.epm.ornl.gov/~sscott þÿÕÍÕœ.“—+,ù®DÕÍÕœ.“—+,ù®Ä€ hpŒ”œ¤ ¬´¼Ä Ì aäTsuga heterophylla+ Àj ‰To install PVM on an NT system without using the installshield package requires that the human installer manually perform the same tasks Title˜(RZ² _PID_GUI»¼½½¾ýþFG¢£ÛRS¬; < z { ± ýýýýýûýòìæýÝÝýØÔÏÆÀòÀÔ„„  & F Æ8 & F„ & F „Ð Æ8~ „Є˜þ„„ & F Æh»¼½½¾ýþFG¢£ÛRS¬; < z { ± ² û ü ç è a b c N O ‰ Ã Ä ÙÚ !ÔÕæç !ST…ÆÑÒ  >@—Ý#ýøööñýìåýÞýýýÙýýýýÒÌÆÃ½·±«ýý¦Ÿ                                    <± ² û ü ç è a b c N O ‰ Ã Ä ÙÚ !ÔÕæç ûòûûûûððçðããðãðÞðÚðÖðÚðքЄh & F„h & F Æh & F ÆÐ„ !ST…ÆÑÒ  >@—Ý#B„Êè,rýøòéééòøãÞØÏÁ³³³³³³³  & F„$ Æ 8¼$   & F„$ Æ h¼$  Æ ì¼$  Æì & F„h„˜þ & F Æh Æh & F#B„Êè,rŽØWv¸î P†¢£¤Þß5{Æè-x™à+KL™š›œ­®¾øñêãÜÕÎÌÌÌž·°©¢›•ÌŽ‰‚{‰tm‰fÌ                                                             (rŽØWv¸î P†¢£¤Þß5{Æè-ñíäààÔÔÔÔÔÔÔííÏÉä»»»»  & F„$ Æ h¼$ „h„˜þ & F  & F„$ ÆÐ$ „$  Æ ì¼$ „h  & F„$ Æ 8¼$ D _PID_HLINKSäAN{414A81DD-D329-11D2-B21A-0060088DC5E3}AÜ c( http://www.epm.ornl.gov/~sscott)$http://www.ataman.com/¾€ìíýÁ  ã ä å ú û žÉÊËêëí^:n<ˆ@BEÔIJJ@JDJpJ–LOXQbSzU‚WúòúïúúçúïúååH*jÏU0JjU jUÏDÐÉêyùºÎŒ‚ªK© http://www.ataman.comàÉêyùºÎŒ‚ªK© .http://www.ataman.com/õDÐÉêyùºÎŒ‚ªK©  http://www.epm.ornl.gov/~sscottàÉêyùºÎŒ‚ªK© @http://www.epm.ornl.gov/~sscottÁ  ã ä å ú û žÉÊËêëí^:n<ˆ@BEÔIJJ@JDJpJ–LOXQbSzU‚WXúòúïúúçúïúååH*jÏU0JjU jU <<B<@@@ @\@BB*B*8V@¢18FollowedHyperlink>*B* u:ÿÿÿÿµ·4Ê 8 P Q z { ™ š R o options: KNOWN PROBLEMS: There appears to be a  timeout problem related to ports on the NT/95/98 systems or with Ataman. One source suggested making all connections non-persistent. The symptom is that it takes some time before a reconnection to a droo options  1st for all users, 2nd for individual users:d as only (NT) or only (95/98).Append m Files\PVM3.4\into-Autoexec.bat to .(95/98) If you run the C:\Program Files\PVM3.4\ironment space , DOS shelln(A) for all users, (B) P · ¸ ê ì NOŠ‹j+,<ÏÐí<=>?]w˜€€ž€€˜€€ž€€˜ €€ž€€˜€€ž€€˜ €€š€€˜€€š€€˜€€š€€˜ €€˜€€˜ €€˜€€š€€˜€€˜ €€˜€€ž€€˜d as only (NT) or only (95/98).Append m Files\PVM3.4\into-Autoexec.bat to .(95/98) If you run the C:\Program Files\PVM3.4\ironment space , DOS shellnstep (A) for all users, (B) host can can3-15Filename: ockWestern Hemlock [$@ñÿ$NormalmH <A@òÿ¡<Default Paragraph Font<C@ò<Body Text Indent „´„Lÿ@R@@Body Text Indent 2 „h„˜þ<S@<Body Text Indent 3„Â(U@¢!( Hyperlink>*B*8V@¢18FollowedHyperlink>*B* r:ÿÿÿÿµ·4Ê 8 P Q z { ™ š R P · ¸ ê ì NOŠ‹j+,<ÏÐí<=>?Zt˜€€ž€€˜€€ž€€˜ €€ž€€˜€€ž€€˜ €€š€€˜€€š€€˜€€š€€˜ €€˜€€˜ €€˜€€š€€˜€€˜ €€˜€€ž€€˜€€˜€€˜€€˜€€˜€€ž€€˜€€˜€€˜€€˜€€˜€€˜€€X± r-<¨I#¾íÿÿUnknownWestern Hemlock5Xní:rXÿ€Xÿ€ÿÿ _Hlt445299731 _Hlt445319974 _Hlt445293227g,th -t1>†“?FQa¼Ìøÿ%T]Š”½Á×Û€„îöDJ  2 : )45B±¼½ÎXcdu  vƒðý‡”,Óà_lÄÑ•›]`x{š IYt o options: Filename: NT-installation.doc Last Updated: 3-6-1999 o options: KNOWN PROBLEMS: There appears to be a  timeout problem related to ports on the NT/95/98 systems or with Ataman. The symptom is that it takes some time before a reconnection to a dropped or deleted node is accepted. The error  can not connect€€˜€€˜€€˜€€˜€€ž€€˜€€˜€€˜€€˜€€˜€€˜€€‚W± r-<¨I#¾íÿÿUnknownWestern Hemlock5Xní:uXÿ€Xÿ€ÿÿ _Hlt445299731 _Hlt445319974 _Hlt445293227g,wh -w1>†“?FQa¼Ìøÿ%T]Š”½Á×Û€„îöDJ  2 : )45B±¼½ÎXcdu  vƒðý‡”,Óà_lÄÑ•›]`x{š ktwY]8F·¿Þã 'Ã Ï î õ ý =GO^™¡”œ«]twÿÿWestern Hemlock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestern Hemlock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestern Hemlock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestern Hemlock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestern Hemlock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestern Hemlock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestern Hemlock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestern Hemlock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestern Hemlock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestern Hemlock0C:\TEMP\AutoRecovery save of NT-installation.asd ÞÑ ÿÿÿÿÿÿÿÿÿBY ÿÿÿÿÿÿÿÿÿ?vƒ/ˆê*Sÿÿÿÿÿÿÿÿÿ±I38šd’šÿÿÿÿÿÿÿÿÿ²E×Kü¬ôÿÿÿÿÿÿÿÿÿL(crŸèTÿÿÿÿÿÿÿÿÿÜJn‡jaÿÿÿÿÿÿÿÿÿU¡nlJBÿÿÿÿÿÿÿÿÿ¢U} ÿÿÿÿÿÿÿÿÿ„h„˜þÆho(.„h„˜þÆho(.„h„˜þÆho(„Є˜þÆÐo(-„Є˜þÆÐo(.„Є˜þÆÐo(()„8„˜þÆ8o(.„Є˜þÆÐo(-„h„˜þÆho(. ¢U}U¡nBYÞѲE×K±I38ÜJn?vƒ/L(cÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ@€oolkÌok°C$EÆ€bÊ'ÿÿ & F & F ƈÈà & F ƈÈÃC$„ „hÆh„hˆY3ÊÑë 8 g ˆ ™ â ë Q R ‘ ö û P ~ ˆ ‰ Š ‹ Œ   ¡ ¶ · ¸ é ê NOP‰Š*+,<RZ—Ùà.2JNefgk‰¡ÎÏ;<=?\]jkotu1@0¾@1V0x @1>V1â@1LV1ŽV1¾@1”V0V@1–V1¾@1ôV1$@1W0è@1F0´@1(W00 @1*W0ú @1¤#@1J1J1J14W16W18W1:W1DJ1FJ0$@0F1$@0z$@0|$@0F-@ 1`W1H-@0º-@0¼-@0ü4@ 0F0F1*B*8V@¢18FollowedHyperlink>*B* t:ÿÿÿÿµ·4Ê 8 P Q z { ™ š R P · ¸ ê ì NOŠ‹j+,<ÏÐí<=>?]v˜€€ž€€˜€€ž€€˜ €€ž€€˜€€ž€€˜ €€š€€˜€€š€€˜€€š€€˜ €€˜€€˜ €€˜€€š€€˜€€˜ €€˜€€ž€€˜€€˜€€˜€€˜€€˜€€ž€€˜€€˜€€˜€€˜€€˜€€˜€€zU± r-<¨I#¾íÿÿUnknownWestern Hemlock5Xní:tXÿ€Xÿ€ÿÿ _Hlt445299731 _Hlt445319974 _Hlt445293227g,vh -v1>†“?FQa¼Ìøÿ%T]Š”½Á×Û€„îöDJ  2 : )45B±¼½ÎXcdu  vƒðý‡”,Óà_lÄÑ•›]`hnx{š vY]8F¥À´´€20ÊÿÿˆTo install PVM on an NT system without using the installshield package requires that the human installer manually perform the same tasksWester·¿Þã 'Ã Ï î õ ý =GO^™¡”œ«@ÎvÿÿWestern Hemlock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestern Hemlock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestern Hemlock1C:\Program Files\PVM3.4\WÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿIN32\NT-installation.docWestern Hemlock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestern Hemlock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestern Hemlock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestern Hemlock1C:\Program Files\ock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestern Hemlock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestern Hemlock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestern Hemlock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestPVM3.4\WIN32\NT-installation.docWestern Hemlock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestern Hemlock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestern Hemlock0C:\TEMP\AutoRecovery save of NT-installation.asd ÞÑ ÿÿÿÿÿÿÿÿÿBY ÿÿÿÿÿÿÿÿÿ?vƒ/ˆê*Sÿÿÿÿÿÿÿÿÿ±I38šd’šÿÿÿÿÿÿÿÿÿ²E×Kü¬ôÿÿÿÿÿÿÿÿÿL(crŸèTÿÿÿÿÿÿÿÿÿÜJn‡jaÿÿÿÿÿÿÿÿÿU¡nlJBÿÿÿÿÿÿÿÿÿ¢U} ÿÿÿÿÿÿÿÿÿ„h„˜þÆho(.„h„˜þÆho(.„h„˜þÆho(„Є˜þÆÐo(-„Є˜þÆÐo(.„Є˜þÆÐo(()„8„˜þÆ8o(.„Є˜þÆÐo(-„h„˜þÆho(. ¢U}U¡nBYÞѲE×K±I38ÜJn?vƒ/L(cÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ@€kklkÌkg°C$EÆ€ern Hemlock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestern Hemlock1C:\Program Files\PVM3.4\WIN32\NT-installation.docWestern Hemlock0C:\TEMP\AutoRecovery save of NT-installation.asdWestern Hemlock.C:\Program Files\PVM3.4\WIN32\installation.doc ÞÑ ÿÿÿÿÿÿÿÿÿBY ÿÿÿÿÿÿÿÿÿ?vƒ/ˆê*Sÿÿÿÿÿÿÿÿÿ±I38šd’šÿÿÿÿÿÿÿÿÿ²E×Kü¬ôÿÿÿÿÿÿÿÿÿL(crŸèTÿÿÿÿÿÿÿÿÿÜJn‡jaÿÿÿÿÿÿÿÿÿU¡nlJBÿÿÿÿÿÿÿÿÿ¢U} ÿÿÿÿÿÿÿÿÿ„h„˜þÆho(.„h„˜þÆho(.„h„˜þÆho(„Є˜þÆÐo(-„Є˜þÆÐo(.„Є˜þÆÐo(()„8„˜þÆ8o(.„Є˜þÆÐo(-„h„˜þÆho(. ¢U}U¡nBYÞѲE×K±I38ÜJn?vƒ/L(cÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ@€IIdËI?°C$EÆ€bÊ'ÿÿ & F & F ƈÈà & F ƈÈÃC$„ „hÆh„h|Y3ÊÑë 8 g ˆ ™ â ë Q R ‘ ö û P ~ ˆ ‰ Š ‹ Œ   ¡ ¶ · ¸ é ê NOP‰Š*+,<RZ—Ùà.2JNefgk‰¡ÎÏ;<=?\]jkst1@0¾@1T0x @1>T1â@1LTbÊ'ÿÿ & F & F ƈÈà & F ƈÈÃC$„ „hÆh„h”Y3ÊÑë 8 g ˆ ™ â ë Q R ‘ ö û P ~ ˆ ‰ Š ‹ Œ   ¡ ¶ · ¸ é ê NOP‰Š*+,<RZ—Ùà.2JNefgk‰¡ÎÏ;<=?IYZghlqþÿÿÿ þÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ1ŽT1¾@1”T0V@1–T1¾@1ôT1$@1U0è@1F0´@1(U00 @1*U0ú @1¤#@1J1J1J14U16U18U1:U1DJ1FJ0$@0F1$@0z$@0|$@0F-@ 1`U1H-@0º-@0¼-@0ü4@ 0F0F1V1â@1LV1ŽV1¾@1”V0V@1–V1¾@1ôV1$@1W0è@1F0´@1(W00 @1*W0ú @1¤#@1J1J1J14W16W18W1:W1DJ1FJ0$@0F1$@0z$@0|$@0F-@ 1`W1H-@0º-@0¼-@0ü4@ 0F0F1(@ABCDEFGHNÿÿÿÿKLMO_QýÿÿÿSÿÿÿÿTUYÿÿÿÿÿÿÿÿÿÿÿÿ\ÿÿÿÿþÿÿÿ`ÿÿÿÿÿÿÿÿþÿÿÿabþÿÿÿÿÿÿÿekýÿÿÿþÿÿÿjuhÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿvþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ0TableÿÿÿÿJ:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿ ÿÿÿÿ ÀFMicrosoft Word Document MSWordDocWord.Document.8ô9²qþÿÕÍÕœ.“—+,ù®DÕÍÕœ.“—+,ù®Ä€ hpŒ”œ¤ ¬´¼Ä Ì aäTsuga heterophylla+ Ãj ‰To install PVM on an NT system without using the installshield package requires that the human installer manually perform the same tasks Title˜(RZ² _PID_GUID _PID_HLINKSäAN{414A81DD-D329-11D2-B21A-0060088DC5E3}AÜ c( http://www.epm.ornl.gov/~sscott)$http://www.ataman.com/SummaryInformation PP(ÿÿÿÿÿÿÿÿÿÿÿÿèë0DocumentSummaryInformation8ÿÿÿÿÿÿÿÿhÊHZBˆD \CompObj7î ppÕHÿÿÿÿˆîjObjectPoolÿ ïpÖHÿÿÿÿÿÿÿÿÿÿÿÿ@à žg¾@à žg¾xxperform the same tasksWestern HemlockWestern HemlockÈÈ´´´´ož,žÊ þŸ¸´´oˆ€Ë ˜ùn¾ÈÎì²Wì¥ÁY Ü¿íbjbjóWóW Z‘=‘=rÿÿÿÿÿÿ]:´îîîîî 4f0¶š(ÂÂÂÂÂZ 8 £+¥+¥+¥+¥+¥+¥+$1ô3vÉ+îH ÂÂH H É+Ø"îîÂÂd6Ø"Ø"Ø"H ÞîÂî£+îîîîH £+Ø"&Ø"þ'þÓ*¸îî£+ÂH¥ún¾&"²‹+Root Entry—E¸ý¸hÊHXBÿÿÿÿÿÿÿÿ ÀFÙ¹×Ng¾X§ún¾t@DataÕHë¡«Hèë ÿÿÿÿÿÿÿÿÿÿÿÿ 0 ÿÿ1TableH 2ÿÿÿÿÿÿÿÿÿÿÿÿxx2FWordDocumentÿÿÿÿmZÿÿÿÿÿÿÿÿ &ÿÿÿÿ/ÿÿÿÿ0ÿÿÿÿ !"#$%þÿÿÿ=34+5-7ÿÿÿÿ1'6)*,?8þÿÿÿ:;<I>(@ABCDEFGHNRKLMO_QýÿÿÿSVTUYWXZ\]þÿÿÿ`^cþÿÿÿa9ÿÿÿÿlÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿqþÿÿÿnkýÿÿÿþÿÿÿsþÿÿÿwÿÿÿÿÿÿÿÿrÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ0TableÿÿÿÿJ†4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿà…ŸòùOh«‘+'³Ù0˜,8P\p ˆ” ° ¼ È Ôàèðøä‰To install PVM on an NT system without using the installshield package requires that the human installer manually perform the same tasksqo iWestern Hemlockest Normal.dotlWestern Hemlock35tMicrosoft Word 8.0n@%@0Ɔùn¾@NÞb…g¾@òùn¾‰(þÿ ÿÿÿÿ ÀFMicrosoft Word Document MSWordDocWord.Document.8ô9²qþÿÕÍÕœ.“—+,ù®DÕÍÕœ.“—+,ù®Ä€ hpŒ”œ¤ ¬´¼Ä Ì aäTsuga heterophylla+ Àj ‰To install PVM on an NT system without using the installshield package requires that the human instaþÿà…ŸòùOh«‘+'³Ù0˜,8P\p ˆ” ° ¼ È Ôàèðøä‰To install PVM on an NT system without using the installshield package requires that the human installer manually perform the same tasksqo iWestern Hemlockest Normal.dotlWestern Hemlock34tMicrosoft Word 8.0n@%@0Ɔùn¾@NÞb…g¾@0Ɔùn¾‰*ller manually perform the same tasks Title˜(RZ² _PID_GUID _PID_HLINKSäAN{414A81DD-D329-11D2-B21A-0060088DC5E3}AÜ c( http://www.epm.ornl.gov/~sscott)$http://www.ataman.com/./pvm3/WIN32/installation.ps0100644007401100000360000032601506673303705014767 0ustar kohlgopher%!PS-Adobe-3.0 %%Title: Microsoft Word - installation.doc %%Creator: Windows NT 4.0 %%CreationDate: 10:43 3/15/1999 %%Pages: (atend) %%BoundingBox: 13 13 599 780 %%LanguageLevel: 2 %%DocumentNeededFonts: (atend) %%DocumentSuppliedFonts: (atend) %%EndComments %%BeginProlog %%BeginResource: procset NTPSOct95 /NTPSOct95 100 dict dup begin/bd{bind def}bind def/ld{load def}bd/ed{exch def} bd/a{currentpoint}bd/c/curveto ld/d/dup ld/e/eofill ld/f/fill ld/tr/translate ld/gr/grestore ld/gs/gsave ld/j/setlinejoin ld/L/lineto ld/M/moveto ld/n /newpath ld/cp/closepath ld/rm/rmoveto ld/sl/setlinewidth ld/sd/setdash ld/g /setgray ld/r/setrgbcolor ld/s/stroke ld/t/show ld/aw/awidthshow ld/im /imagemask ld/MS{moveto show}bd/SF{findfont exch scalefont setfont}bd/SM{cmtx setmatrix}bd/MF{findfont exch makefont setfont}bd/CM{/cmtx matrix currentmatrix def}bd/B{M exch dup 0 rlt exch 0 exch rlt neg 0 rlt}bd/CB{B cp eoclip}bd/EA{1 index 0/G0 put 4 string 1 1 4 -1 roll{3 copy neg exch cvs dup 0 71 put cvn 3 -1 roll exch put}for pop}bd/rlt/rlineto ld/L2?/languagelevel where{pop languagelevel 2 ge}{false}ifelse def end def %%EndResource %%EndProlog %%BeginSetup [{0 /languagelevel where{pop languagelevel 2 ge}{false}ifelse {1 dict dup/JobTimeout 4 -1 roll put setuserparams} {statusdict/setjobtimeout get exec}ifelse }stopped cleartomark [{240 /languagelevel where{pop languagelevel 2 ge}{false}ifelse {1 dict dup/WaitTimeout 4 -1 roll put setuserparams} {statusdict/waittimeout 3 -1 roll put}ifelse }stopped cleartomark /#copies 1 def [{ %%BeginFeature: *PageSize Letter <> setpagedevice %%EndFeature } stopped cleartomark [{ %%BeginFeature: *Duplex None <> setpagedevice %%EndFeature } stopped cleartomark [{ %%BeginFeature: *Option1 False %%EndFeature } stopped cleartomark [{ %%BeginFeature: *Option2 False %%EndFeature } stopped cleartomark [{ %%BeginFeature: *Option3 False %%EndFeature } stopped cleartomark [{ %%BeginFeature: *Option4 6Meg %%EndFeature } stopped cleartomark %%EndSetup NTPSOct95 begin %%Page: 1 1 NTPSOct95 /PageSV save put 13.238 780.059 translate 72 600 div dup neg scale 0 0 transform .25 add round .25 sub exch .25 add round .25 sub exch itransform translate %%IncludeFont: Times-Roman [83 0 0 -83 0 0]/Times-Roman MF (T)442 576 MS (o)494 576 MS ( )535 576 MS (i)556 576 MS (n)579 576 MS (s)620 576 MS (t)652 576 MS (a)675 576 MS (l)712 576 MS (l)735 576 MS ( )758 576 MS (P)779 576 MS (V)826 576 MS (M)886 576 MS ( )960 576 MS (o)981 576 MS (n)1023 576 MS ( )1064 576 MS (a)1085 576 MS (n)1122 576 MS ( )1163 576 MS (N)1184 576 MS (T)1244 576 MS ( )1296 576 MS (s)1317 576 MS (y)1350 576 MS (s)1391 576 MS (t)1423 576 MS (e)1446 576 MS (m)1484 576 MS ( )1547 576 MS (w)1570 576 MS (i)1629 576 MS (t)1652 576 MS (h)1676 576 MS (o)1717 576 MS (u)1759 576 MS (t)1800 576 MS ( )1823 576 MS (u)1845 576 MS (s)1886 576 MS (i)1918 576 MS (n)1942 576 MS (g)1983 576 MS ( )2024 576 MS (t)2045 576 MS (h)2069 576 MS (e)2110 576 MS ( )2147 576 MS (i)2168 576 MS (n)2192 576 MS (s)2233 576 MS (t)2265 576 MS (a)2288 576 MS (l)2325 576 MS (l)2349 576 MS (s)2372 576 MS (h)2405 576 MS (i)2446 576 MS (e)2469 576 MS (l)2506 576 MS (d)2529 576 MS ( )2571 576 MS (p)2592 576 MS (a)2634 576 MS (c)2671 576 MS (k)2708 576 MS (a)2749 576 MS (g)2787 576 MS (e)2828 576 MS ( )2865 576 MS (r)2886 576 MS (e)2914 576 MS (q)2951 576 MS (u)2993 576 MS (i)3034 576 MS (r)3057 576 MS (e)3085 576 MS (s)3122 576 MS ( )3154 576 MS (t)3175 576 MS (h)3198 576 MS (a)3239 576 MS (t)3277 576 MS ( )3300 576 MS (t)3321 576 MS (h)3344 576 MS (e)3385 576 MS ( )3422 576 MS (i)3443 576 MS (n)3466 576 MS (s)3507 576 MS (t)3540 576 MS (a)3563 576 MS (l)3601 576 MS (l)3624 576 MS (e)3647 576 MS (r)3684 576 MS ( )3712 576 MS (m)3734 576 MS (a)3797 576 MS (n)3835 576 MS (u)3877 576 MS (a)3918 576 MS (l)3955 576 MS (l)3978 576 MS (y)4002 576 MS ( )4042 576 MS (p)4063 576 MS (e)4105 576 MS (r)4142 576 MS (f)4170 576 MS (o)4197 576 MS (r)4239 576 MS (m)4268 576 MS (t)442 672 MS (h)465 672 MS (e)506 672 MS ( )543 672 MS (s)564 672 MS (a)596 672 MS (m)634 672 MS (e)698 672 MS ( )735 672 MS (t)756 672 MS (a)779 672 MS (s)816 672 MS (k)849 672 MS (s)890 672 MS ( )922 672 MS (a)943 672 MS (s)981 672 MS ( )1013 672 MS (i)1034 672 MS (n)1057 672 MS (s)1099 672 MS (t)1131 672 MS (a)1154 672 MS (l)1191 672 MS (l)1214 672 MS (s)1238 672 MS (h)1270 672 MS (i)1311 672 MS (e)1334 672 MS (l)1372 672 MS (d)1395 672 MS (.)1437 672 MS ( )1458 672 MS (T)1479 672 MS (h)1531 672 MS (e)1572 672 MS (s)1609 672 MS (e)1641 672 MS ( )1678 672 MS (t)1699 672 MS (a)1722 672 MS (s)1759 672 MS (k)1791 672 MS (s)1832 672 MS ( )1864 672 MS (a)1885 672 MS (r)1922 672 MS (e)1950 672 MS ( )1987 672 MS (o)2008 672 MS (u)2050 672 MS (t)2091 672 MS (l)2115 672 MS (i)2138 672 MS (n)2161 672 MS (e)2202 672 MS (d)2239 672 MS ( )2281 672 MS (b)2302 672 MS (e)2344 672 MS (l)2381 672 MS (o)2404 672 MS (w)2446 672 MS (.)2505 672 MS (A)442 959 MS (l)501 959 MS (l)524 959 MS ( )547 959 MS (t)568 959 MS (a)591 959 MS (s)629 959 MS (k)662 959 MS (s)703 959 MS ( )735 959 MS (s)756 959 MS (h)789 959 MS (o)830 959 MS (u)872 959 MS (l)913 959 MS (d)936 959 MS ( )978 959 MS (b)999 959 MS (e)1041 959 MS ( )1078 959 MS (a)1099 959 MS (s)1136 959 MS (s)1168 959 MS (u)1201 959 MS (m)1243 959 MS (e)1307 959 MS (d)1344 959 MS ( )1386 959 MS (t)1407 959 MS (o)1430 959 MS ( )1472 959 MS (b)1493 959 MS (e)1535 959 MS ( )1572 959 MS (f)1593 959 MS (o)1620 959 MS (r)1662 959 MS ( )1690 959 MS (b)1711 959 MS (o)1753 959 MS (t)1795 959 MS (h)1818 959 MS ( )1859 959 MS (N)1880 959 MS (T)1940 959 MS ( )1991 959 MS (a)2012 959 MS (n)2049 959 MS (d)2090 959 MS ( )2132 959 MS (W)2153 959 MS (i)2232 959 MS (n)2255 959 MS ( )2296 959 MS (9)2317 959 MS (5)2359 959 MS (/)2401 959 MS (9)2424 959 MS (8)2466 959 MS ( )2508 959 MS (s)2529 959 MS (y)2561 959 MS (s)2601 959 MS (t)2633 959 MS (e)2656 959 MS (m)2694 959 MS (s)2758 959 MS ( )2790 959 MS (u)2811 959 MS (n)2853 959 MS (l)2895 959 MS (e)2918 959 MS (s)2955 959 MS (s)2988 959 MS ( )3020 959 MS (o)3041 959 MS (t)3083 959 MS (h)3106 959 MS (e)3147 959 MS (r)3184 959 MS (w)3213 959 MS (i)3272 959 MS (s)3295 959 MS (e)3327 959 MS ( )3364 959 MS (i)3385 959 MS (n)3409 959 MS (d)3450 959 MS (i)3492 959 MS (c)3515 959 MS (a)3552 959 MS (t)3589 959 MS (e)3612 959 MS (d)3649 959 MS ( )3691 959 MS (a)3712 959 MS (s)3749 959 MS ( )3781 959 MS (o)3802 959 MS (n)3844 959 MS (l)3885 959 MS (y)3909 959 MS ( )3950 959 MS (\()3971 959 MS (N)3999 959 MS (T)4059 959 MS (\))4111 959 MS ( )4139 959 MS (o)4160 959 MS (r)4202 959 MS ( )4230 959 MS (o)4250 959 MS (n)4292 959 MS (l)4333 959 MS (y)4357 959 MS (\()442 1055 MS (9)470 1055 MS (5)512 1055 MS (/)554 1055 MS (9)577 1055 MS (8)619 1055 MS (\))660 1055 MS (.)688 1055 MS (1)442 1247 MS (.)484 1247 MS (U)592 1247 MS (n)652 1247 MS (p)693 1247 MS (a)735 1247 MS (c)772 1247 MS (k)809 1247 MS ( )850 1247 MS (t)871 1247 MS (h)895 1247 MS (e)936 1247 MS ( )973 1247 MS (P)994 1247 MS (V)1041 1247 MS (M)1101 1247 MS ( )1175 1247 MS (f)1196 1247 MS (i)1223 1247 MS (l)1246 1247 MS (e)1269 1247 MS (s)1307 1247 MS ( )1339 1247 MS (t)1360 1247 MS (o)1383 1247 MS ( )1425 1247 MS (d)1446 1247 MS (i)1488 1247 MS (r)1511 1247 MS (e)1539 1247 MS (c)1576 1247 MS (t)1613 1247 MS (o)1636 1247 MS (r)1678 1247 MS (y)1706 1247 MS (:)1746 1247 MS ( )1769 1247 MS ( )1790 1247 MS (C)1811 1247 MS (:)1866 1247 MS (\\)1890 1247 MS (P)1912 1247 MS (r)1959 1247 MS (o)1987 1247 MS (g)2029 1247 MS (r)2070 1247 MS (a)2098 1247 MS (m)2136 1247 MS ( )2199 1247 MS (F)2221 1247 MS (i)2267 1247 MS (l)2290 1247 MS (e)2313 1247 MS (s)2351 1247 MS (\\)2384 1247 MS (P)2406 1247 MS (V)2453 1247 MS (M)2513 1247 MS (3)2587 1247 MS (.)2629 1247 MS (4)2650 1247 MS (2)442 1438 MS (.)484 1438 MS %%IncludeFont: Helvetica [83 0 0 -83 0 0]/Helvetica MF ( )505 1438 MS [83 0 0 -83 0 0]/Times-Roman MF (I)592 1438 MS (n)620 1438 MS (s)661 1438 MS (t)693 1438 MS (a)716 1438 MS (l)753 1438 MS (l)776 1438 MS ( )799 1438 MS (r)820 1438 MS (e)848 1438 MS (g)886 1438 MS (i)927 1438 MS (s)950 1438 MS (t)982 1438 MS (r)1005 1438 MS (y)1034 1438 MS ( )1075 1438 MS (e)1096 1438 MS (n)1133 1438 MS (t)1174 1438 MS (r)1197 1438 MS (i)1225 1438 MS (e)1248 1438 MS (s)1286 1438 MS ( )1318 1438 MS (f)1339 1438 MS (o)1366 1438 MS (r)1408 1438 MS ( )1436 1438 MS (\()1457 1438 MS (N)1485 1438 MS (T)1545 1438 MS (\))1597 1438 MS ( )1625 1438 MS (o)1646 1438 MS (r)1687 1438 MS ( )1715 1438 MS (e)1736 1438 MS (n)1773 1438 MS (v)1814 1438 MS (i)1855 1438 MS (r)1878 1438 MS (o)1906 1438 MS (n)1948 1438 MS (m)1990 1438 MS (e)2054 1438 MS (n)2091 1438 MS (t)2132 1438 MS ( )2155 1438 MS (v)2177 1438 MS (a)2218 1438 MS (r)2255 1438 MS (i)2283 1438 MS (a)2306 1438 MS (b)2343 1438 MS (l)2385 1438 MS (e)2408 1438 MS (s)2445 1438 MS ( )2477 1438 MS (f)2499 1438 MS (o)2526 1438 MS (r)2568 1438 MS ( )2596 1438 MS (\()2617 1438 MS (9)2645 1438 MS (5)2687 1438 MS (/)2729 1438 MS (9)2752 1438 MS (8)2794 1438 MS (\))2835 1438 MS (:)2863 1438 MS (-)592 1630 MS (\()742 1630 MS (N)770 1630 MS (T)830 1630 MS (\))882 1630 MS ( )909 1630 MS (I)930 1630 MS (n)958 1630 MS (s)999 1630 MS (t)1031 1630 MS (a)1054 1630 MS (l)1091 1630 MS (l)1114 1630 MS ( )1137 1630 MS (r)1158 1630 MS (e)1186 1630 MS (g)1223 1630 MS (i)1264 1630 MS (s)1288 1630 MS (t)1320 1630 MS (r)1343 1630 MS (y)1372 1630 MS ( )1412 1630 MS (e)1433 1630 MS (n)1471 1630 MS (t)1512 1630 MS (r)1535 1630 MS (i)1563 1630 MS (e)1586 1630 MS (s)1623 1630 MS (.)1655 1630 MS ( )1676 1630 MS (B)1697 1630 MS (a)1753 1630 MS (s)1790 1630 MS (e)1822 1630 MS (d)1859 1630 MS ( )1901 1630 MS (o)1922 1630 MS (n)1964 1630 MS ( )2005 1630 MS (y)2027 1630 MS (o)2067 1630 MS (u)2109 1630 MS (r)2150 1630 MS ( )2178 1630 MS (v)2200 1630 MS (e)2241 1630 MS (r)2278 1630 MS (s)2306 1630 MS (i)2338 1630 MS (o)2361 1630 MS (n)2403 1630 MS ( )2444 1630 MS (o)2465 1630 MS (f)2508 1630 MS ( )2535 1630 MS (V)2556 1630 MS (i)2616 1630 MS (s)2639 1630 MS (u)2672 1630 MS (a)2713 1630 MS (l)2750 1630 MS ( )2773 1630 MS (C)2795 1630 MS (+)2850 1630 MS (+)2897 1630 MS ( )2944 1630 MS (a)2965 1630 MS (n)3002 1630 MS (d)3043 1630 MS ( )3085 1630 MS (o)3106 1630 MS (p)3148 1630 MS (t)3190 1630 MS (i)3213 1630 MS (o)3236 1630 MS (n)3278 1630 MS (a)3319 1630 MS (l)3356 1630 MS (l)3379 1630 MS (y)3403 1630 MS ( )3443 1630 MS (D)3465 1630 MS (i)3525 1630 MS (g)3548 1630 MS (i)3589 1630 MS (t)3613 1630 MS (a)3636 1630 MS (l)3673 1630 MS ( )3696 1630 MS (F)3717 1630 MS (o)3763 1630 MS (r)3805 1630 MS (t)3833 1630 MS (r)3856 1630 MS (a)3884 1630 MS (n)3921 1630 MS (,)3962 1630 MS ( )3983 1630 MS (d)4004 1630 MS (o)4046 1630 MS (u)4088 1630 MS (b)4129 1630 MS (l)4171 1630 MS (e)4194 1630 MS ( )4231 1630 MS (c)4252 1630 MS (l)4289 1630 MS (i)4312 1630 MS (c)4335 1630 MS (k)4372 1630 MS (o)742 1726 MS (n)784 1726 MS ( )825 1726 MS (b)846 1726 MS (o)888 1726 MS (t)930 1726 MS (h)953 1726 MS ( )994 1726 MS (t)1015 1726 MS (h)1038 1726 MS (e)1079 1726 MS ( )1116 1726 MS ( )1137 1726 MS ( )1158 1726 MS ( )1179 1726 MS (p)1200 1726 MS (v)1242 1726 MS (m)1284 1726 MS (.)1347 1726 MS (r)1368 1726 MS (e)1396 1726 MS (g)1434 1726 MS ( )1475 1726 MS ( )1496 1726 MS ( )1517 1726 MS ( )1538 1726 MS (a)1559 1726 MS (n)1596 1726 MS (d)1637 1726 MS ( )1679 1726 MS ( )1700 1726 MS ( )1721 1726 MS ( )1742 1726 MS (p)1763 1726 MS (v)1805 1726 MS (m)1847 1726 MS (_)1910 1726 MS (u)1952 1726 MS (s)1994 1726 MS (e)2026 1726 MS (r)2063 1726 MS (_)2091 1726 MS (e)2133 1726 MS (n)2170 1726 MS (v)2211 1726 MS (.)2252 1726 MS (r)2273 1726 MS (e)2301 1726 MS (g)2339 1726 MS ( )2380 1726 MS ( )2401 1726 MS ( )2422 1726 MS ( )2443 1726 MS (f)2464 1726 MS (i)2491 1726 MS (l)2514 1726 MS (e)2537 1726 MS (s)2575 1726 MS ( )2607 1726 MS (i)2628 1726 MS (n)2651 1726 MS ( )2692 1726 MS (t)2713 1726 MS (h)2737 1726 MS (e)2778 1726 MS ( )2815 1726 MS (a)2836 1726 MS (p)2873 1726 MS (p)2915 1726 MS (r)2957 1726 MS (o)2985 1726 MS (p)3027 1726 MS (r)3069 1726 MS (i)3097 1726 MS (a)3120 1726 MS (t)3157 1726 MS (e)3180 1726 MS ( )3217 1726 MS (d)3238 1726 MS (i)3280 1726 MS (r)3303 1726 MS (e)3331 1726 MS (c)3368 1726 MS (t)3405 1726 MS (o)3427 1726 MS (r)3469 1726 MS (y)3497 1726 MS (.)3537 1726 MS ( )3558 1726 MS (N)3579 1726 MS (O)3639 1726 MS (T)3699 1726 MS (E)3751 1726 MS ( )3802 1726 MS (t)3823 1726 MS (h)3846 1726 MS (a)3887 1726 MS (t)3924 1726 MS ( )3947 1726 MS (e)3968 1726 MS (v)4005 1726 MS (e)4046 1726 MS (r)4083 1726 MS (y)4112 1726 MS ( )4152 1726 MS (P)4173 1726 MS (V)4220 1726 MS (M)4280 1726 MS (u)742 1822 MS (s)783 1822 MS (e)815 1822 MS (r)852 1822 MS ( )880 1822 MS (w)902 1822 MS (i)961 1822 MS (l)984 1822 MS (l)1007 1822 MS ( )1030 1822 MS (h)1052 1822 MS (a)1093 1822 MS (v)1130 1822 MS (e)1171 1822 MS ( )1208 1822 MS (t)1229 1822 MS (o)1252 1822 MS ( )1294 1822 MS (i)1315 1822 MS (n)1339 1822 MS (s)1380 1822 MS (t)1412 1822 MS (a)1435 1822 MS (l)1473 1822 MS (l)1496 1822 MS ( )1519 1822 MS (t)1540 1822 MS (h)1563 1822 MS (e)1604 1822 MS ( )1641 1822 MS ( )1662 1822 MS (p)1683 1822 MS (v)1725 1822 MS (m)1767 1822 MS (_)1831 1822 MS (u)1874 1822 MS (s)1915 1822 MS (e)1947 1822 MS (r)1984 1822 MS (_)2012 1822 MS (e)2054 1822 MS (n)2091 1822 MS (v)2133 1822 MS (.)2174 1822 MS (r)2195 1822 MS (e)2223 1822 MS (g)2260 1822 MS ( )2301 1822 MS ( )2322 1822 MS (e)2343 1822 MS (n)2380 1822 MS (t)2421 1822 MS (r)2444 1822 MS (i)2472 1822 MS (e)2495 1822 MS (s)2533 1822 MS ( )2565 1822 MS (f)2586 1822 MS (o)2613 1822 MS (r)2655 1822 MS ( )2683 1822 MS (t)2704 1822 MS (h)2727 1822 MS (e)2768 1822 MS (i)2806 1822 MS (r)2829 1822 MS ( )2857 1822 MS (p)2878 1822 MS (e)2920 1822 MS (r)2957 1822 MS (s)2985 1822 MS (o)3017 1822 MS (n)3059 1822 MS (a)3100 1822 MS (l)3137 1822 MS ( )3160 1822 MS (a)3181 1822 MS (c)3218 1822 MS (c)3255 1822 MS (o)3292 1822 MS (u)3334 1822 MS (n)3375 1822 MS (t)3416 1822 MS ( )3439 1822 MS (w)3461 1822 MS (h)3520 1822 MS (i)3562 1822 MS (l)3585 1822 MS (e)3608 1822 MS ( )3645 1822 MS ( )3666 1822 MS (p)3687 1822 MS (v)3729 1822 MS (m)3770 1822 MS (.)3834 1822 MS (r)3856 1822 MS (e)3884 1822 MS (g)3922 1822 MS ( )3963 1822 MS ( )3984 1822 MS (n)4005 1822 MS (e)4046 1822 MS (e)4083 1822 MS (d)4120 1822 MS ( )4162 1822 MS (o)4183 1822 MS (n)4225 1822 MS (l)4266 1822 MS (y)4290 1822 MS ( )4330 1822 MS (b)4351 1822 MS (e)4393 1822 MS (d)742 1917 MS (o)784 1917 MS (n)826 1917 MS (e)867 1917 MS ( )904 1917 MS (o)925 1917 MS (n)967 1917 MS (c)1008 1917 MS (e)1045 1917 MS (.)1082 1917 MS (-)742 2109 MS (D)892 2109 MS (e)952 2109 MS (v)989 2109 MS (S)1030 2109 MS (t)1076 2109 MS (u)1100 2109 MS (d)1141 2109 MS (i)1183 2109 MS (o)1206 2109 MS ( )1248 2109 MS (5)1269 2109 MS (:)1311 2109 MS (C)1455 2109 MS (:)1510 2109 MS (\\)1534 2109 MS (P)1556 2109 MS (r)1603 2109 MS (o)1631 2109 MS (g)1673 2109 MS (r)1714 2109 MS (a)1742 2109 MS (m)1780 2109 MS ( )1843 2109 MS (F)1864 2109 MS (i)1910 2109 MS (l)1933 2109 MS (e)1956 2109 MS (s)1994 2109 MS (\\)2027 2109 MS (P)2049 2109 MS (V)2096 2109 MS (M)2156 2109 MS (3)2230 2109 MS (.)2272 2109 MS (4)2293 2109 MS (\\)2335 2109 MS (W)2357 2109 MS (I)2436 2109 MS (N)2464 2109 MS (3)2524 2109 MS (2)2566 2109 MS (\\)2608 2109 MS (D)2630 2109 MS (e)2690 2109 MS (v)2727 2109 MS (S)2768 2109 MS (t)2814 2109 MS (u)2838 2109 MS (d)2879 2109 MS (i)2921 2109 MS (o)2944 2109 MS (5)2986 2109 MS (-)742 2205 MS (D)892 2205 MS (e)952 2205 MS (v)989 2205 MS (S)1030 2205 MS (t)1076 2205 MS (u)1100 2205 MS (d)1141 2205 MS (i)1183 2205 MS (o)1206 2205 MS ( )1248 2205 MS (6)1269 2205 MS (:)1311 2205 MS (C)1455 2205 MS (:)1510 2205 MS (\\)1534 2205 MS (P)1556 2205 MS (r)1603 2205 MS (o)1631 2205 MS (g)1673 2205 MS (r)1714 2205 MS (a)1742 2205 MS (m)1780 2205 MS ( )1843 2205 MS (F)1864 2205 MS (i)1910 2205 MS (l)1933 2205 MS (e)1956 2205 MS (s)1994 2205 MS (\\)2027 2205 MS (P)2049 2205 MS (V)2096 2205 MS (M)2156 2205 MS (3)2230 2205 MS (.)2272 2205 MS (4)2293 2205 MS (\\)2335 2205 MS (W)2357 2205 MS (I)2436 2205 MS (N)2464 2205 MS (3)2524 2205 MS (2)2566 2205 MS (\\)2608 2205 MS (D)2630 2205 MS (e)2690 2205 MS (v)2727 2205 MS (S)2768 2205 MS (t)2814 2205 MS (u)2838 2205 MS (d)2879 2205 MS (i)2921 2205 MS (o)2944 2205 MS (6)2986 2205 MS (-)592 2397 MS [83 0 0 -83 0 0]/Helvetica MF ( )619 2397 MS [83 0 0 -83 0 0]/Times-Roman MF (\()742 2397 MS (9)770 2397 MS (5)812 2397 MS (/)854 2397 MS (9)877 2397 MS (8)919 2397 MS (\))960 2397 MS ( )988 2397 MS (I)1009 2397 MS (n)1037 2397 MS (s)1078 2397 MS (t)1110 2397 MS (a)1133 2397 MS (l)1170 2397 MS (l)1193 2397 MS ( )1216 2397 MS (e)1237 2397 MS (n)1274 2397 MS (v)1316 2397 MS (i)1357 2397 MS (r)1380 2397 MS (o)1408 2397 MS (n)1450 2397 MS (m)1492 2397 MS (e)1556 2397 MS (n)1593 2397 MS (t)1635 2397 MS ( )1658 2397 MS (v)1679 2397 MS (a)1720 2397 MS (l)1757 2397 MS (u)1781 2397 MS (e)1822 2397 MS (s)1859 2397 MS ( )1891 2397 MS (i)1912 2397 MS (n)1936 2397 MS (t)1977 2397 MS (o)2000 2397 MS ( )2042 2397 MS (C)2063 2397 MS (:)2118 2397 MS (\\)2142 2397 MS (A)2165 2397 MS (u)2225 2397 MS (t)2267 2397 MS (o)2290 2397 MS (e)2332 2397 MS (x)2369 2397 MS (e)2410 2397 MS (c)2447 2397 MS (.)2484 2397 MS (b)2505 2397 MS (a)2547 2397 MS (t)2584 2397 MS ( )2607 2397 MS (f)2628 2397 MS (i)2655 2397 MS (l)2678 2397 MS (e)2701 2397 MS (.)2738 2397 MS (1)742 2588 MS (.)784 2588 MS [83 0 0 -83 0 0]/Helvetica MF ( )805 2588 MS [83 0 0 -83 0 0]/Times-Roman MF (A)892 2588 MS (p)951 2588 MS (p)993 2588 MS (e)1035 2588 MS (n)1072 2588 MS (d)1113 2588 MS ( )1155 2588 MS (t)1176 2588 MS (h)1200 2588 MS (e)1241 2588 MS ( )1278 2588 MS (c)1299 2588 MS (o)1336 2588 MS (n)1378 2588 MS (t)1419 2588 MS (e)1442 2588 MS (n)1479 2588 MS (t)1521 2588 MS (s)1544 2588 MS ( )1576 2588 MS (o)1597 2588 MS (f)1639 2588 MS ( )1666 2588 MS ( )1687 2588 MS (C)1709 2588 MS (:)1764 2588 MS (\\)1788 2588 MS (P)1810 2588 MS (r)1857 2588 MS (o)1885 2588 MS (g)1927 2588 MS (r)1968 2588 MS (a)1996 2588 MS (m)2033 2588 MS ( )2097 2588 MS (F)2118 2588 MS (i)2164 2588 MS (l)2187 2588 MS (e)2210 2588 MS (s)2248 2588 MS (\\)2281 2588 MS (P)2303 2588 MS (V)2350 2588 MS (M)2410 2588 MS (3)2484 2588 MS (.)2526 2588 MS (4)2547 2588 MS (\\)2589 2588 MS (i)2611 2588 MS (n)2635 2588 MS (t)2676 2588 MS (o)2699 2588 MS (-)2741 2588 MS (A)2768 2588 MS (u)2828 2588 MS (t)2870 2588 MS (o)2893 2588 MS (e)2935 2588 MS (x)2973 2588 MS (e)3014 2588 MS (c)3051 2588 MS (.)3088 2588 MS (b)3109 2588 MS (a)3151 2588 MS (t)3188 2588 MS ( )3211 2588 MS (t)3232 2588 MS (o)3255 2588 MS ( )3297 2588 MS (C)3318 2588 MS (:)3373 2588 MS (\\)3397 2588 MS (A)3420 2588 MS (u)3480 2588 MS (t)3521 2588 MS (o)3544 2588 MS (e)3586 2588 MS (x)3623 2588 MS (e)3664 2588 MS (c)3701 2588 MS (.)3738 2588 MS (b)3759 2588 MS (a)3801 2588 MS (t)3838 2588 MS (.)3861 2588 MS (2)742 2684 MS (.)784 2684 MS [83 0 0 -83 0 0]/Helvetica MF ( )805 2684 MS [83 0 0 -83 0 0]/Times-Roman MF (E)892 2684 MS (d)943 2684 MS (i)985 2684 MS (t)1008 2684 MS ( )1031 2684 MS ( )1052 2684 MS (C)1073 2684 MS (:)1128 2684 MS (\\)1151 2684 MS (P)1173 2684 MS (r)1220 2684 MS (o)1248 2684 MS (g)1290 2684 MS (r)1331 2684 MS (a)1359 2684 MS (m)1397 2684 MS ( )1460 2684 MS (F)1482 2684 MS (i)1528 2684 MS (l)1551 2684 MS (e)1574 2684 MS (s)1611 2684 MS (\\)1644 2684 MS (P)1666 2684 MS (V)1713 2684 MS (M)1773 2684 MS (3)1847 2684 MS (.)1889 2684 MS (4)1910 2684 MS (\\)1952 2684 MS (P)1974 2684 MS (V)2021 2684 MS (M)2081 2684 MS (V)2155 2684 MS (A)2216 2684 MS (R)2276 2684 MS (S)2331 2684 MS (.)2377 2684 MS (B)2398 2684 MS (A)2455 2684 MS (T)2514 2684 MS ( )2566 2684 MS (a)2587 2684 MS (c)2624 2684 MS (c)2661 2684 MS (o)2698 2684 MS (r)2740 2684 MS (d)2768 2684 MS (i)2810 2684 MS (n)2833 2684 MS (g)2874 2684 MS ( )2915 2684 MS (t)2936 2684 MS (o)2959 2684 MS ( )3001 2684 MS (i)3022 2684 MS (n)3045 2684 MS (s)3086 2684 MS (t)3118 2684 MS (r)3141 2684 MS (u)3170 2684 MS (c)3211 2684 MS (t)3248 2684 MS (i)3271 2684 MS (o)3294 2684 MS (n)3336 2684 MS (s)3378 2684 MS ( )3410 2684 MS (i)3431 2684 MS (n)3454 2684 MS ( )3495 2684 MS (t)3516 2684 MS (h)3540 2684 MS (a)3581 2684 MS (t)3618 2684 MS ( )3641 2684 MS (f)3663 2684 MS (i)3690 2684 MS (l)3713 2684 MS (e)3736 2684 MS ( )3773 2684 MS (w)3795 2684 MS (i)3854 2684 MS (t)3877 2684 MS (h)3900 2684 MS ( )3941 2684 MS (r)3962 2684 MS (e)3991 2684 MS (s)4028 2684 MS (p)4060 2684 MS (e)4102 2684 MS (c)4139 2684 MS (t)4176 2684 MS ( )4199 2684 MS (t)4220 2684 MS (o)4243 2684 MS (D)892 2780 MS (e)952 2780 MS (v)989 2780 MS (S)1030 2780 MS (t)1076 2780 MS (u)1100 2780 MS (d)1141 2780 MS (i)1183 2780 MS (o)1206 2780 MS ( )1248 2780 MS (5)1269 2780 MS ( )1311 2780 MS (v)1332 2780 MS (e)1373 2780 MS (r)1410 2780 MS (s)1438 2780 MS (u)1470 2780 MS (s)1512 2780 MS ( )1544 2780 MS (D)1565 2780 MS (e)1625 2780 MS (v)1662 2780 MS (S)1704 2780 MS (t)1750 2780 MS (u)1774 2780 MS (d)1815 2780 MS (i)1857 2780 MS (o)1880 2780 MS ( )1922 2780 MS (6)1943 2780 MS ( )1985 2780 MS (i)2006 2780 MS (n)2029 2780 MS (s)2070 2780 MS (t)2102 2780 MS (a)2125 2780 MS (l)2162 2780 MS (l)2185 2780 MS (a)2208 2780 MS (t)2245 2780 MS (i)2269 2780 MS (o)2292 2780 MS (n)2334 2780 MS (s)2375 2780 MS (.)2407 2780 MS (3)442 2971 MS (.)484 2971 MS [83 0 0 -83 0 0]/Helvetica MF ( )505 2971 MS [83 0 0 -83 0 0]/Times-Roman MF (I)592 2971 MS (n)620 2971 MS (s)661 2971 MS (t)693 2971 MS (a)716 2971 MS (l)753 2971 MS (l)776 2971 MS ( )799 2971 MS (y)821 2971 MS (o)861 2971 MS (u)904 2971 MS (r)945 2971 MS ( )973 2971 MS (r)994 2971 MS (s)1022 2971 MS (h)1055 2971 MS (d)1096 2971 MS ( )1138 2971 MS (p)1159 2971 MS (a)1201 2971 MS (c)1238 2971 MS (k)1275 2971 MS (a)1316 2971 MS (g)1353 2971 MS (e)1394 2971 MS ( )1431 2971 MS (a)1452 2971 MS (c)1489 2971 MS (c)1526 2971 MS (o)1563 2971 MS (r)1605 2971 MS (d)1633 2971 MS (i)1675 2971 MS (n)1698 2971 MS (g)1739 2971 MS ( )1780 2971 MS (t)1801 2971 MS (o)1824 2971 MS ( )1866 2971 MS (s)1887 2971 MS (u)1920 2971 MS (p)1961 2971 MS (p)2003 2971 MS (l)2045 2971 MS (i)2068 2971 MS (e)2091 2971 MS (r)2128 2971 MS ( )2156 2971 MS (i)2177 2971 MS (n)2200 2971 MS (s)2242 2971 MS (t)2274 2971 MS (r)2297 2971 MS (u)2325 2971 MS (c)2366 2971 MS (t)2403 2971 MS (i)2426 2971 MS (o)2449 2971 MS (n)2492 2971 MS (s)2533 2971 MS (.)2565 2971 MS (\()592 3163 MS (N)620 3163 MS (T)680 3163 MS (\))732 3163 MS ( )759 3163 MS (I)780 3163 MS (n)808 3163 MS (f)849 3163 MS (o)876 3163 MS (r)918 3163 MS (m)947 3163 MS (a)1010 3163 MS (t)1047 3163 MS (i)1070 3163 MS (o)1093 3163 MS (n)1135 3163 MS ( )1176 3163 MS (p)1197 3163 MS (r)1239 3163 MS (o)1267 3163 MS (v)1309 3163 MS (i)1350 3163 MS (d)1373 3163 MS (e)1415 3163 MS (d)1452 3163 MS ( )1494 3163 MS (h)1515 3163 MS (e)1556 3163 MS (r)1593 3163 MS (e)1621 3163 MS ( )1658 3163 MS (i)1679 3163 MS (s)1702 3163 MS ( )1734 3163 MS (f)1756 3163 MS (o)1783 3163 MS (r)1825 3163 MS ( )1853 3163 MS (t)1874 3163 MS (h)1897 3163 MS (e)1938 3163 MS ( )1975 3163 MS (A)1996 3163 MS (t)2056 3163 MS (a)2079 3163 MS (m)2117 3163 MS (a)2181 3163 MS (n)2219 3163 MS ( )2260 3163 MS (p)2281 3163 MS (a)2323 3163 MS (c)2360 3163 MS (k)2397 3163 MS (a)2438 3163 MS (g)2475 3163 MS (e)2516 3163 MS ( )2553 3163 MS (a)2574 3163 MS (v)2611 3163 MS (a)2653 3163 MS (i)2690 3163 MS (l)2713 3163 MS (a)2736 3163 MS (b)2773 3163 MS (l)2815 3163 MS (e)2838 3163 MS ( )2875 3163 MS (a)2896 3163 MS (t)2933 3163 MS ( )2956 3163 MS 0.105 g (h)2977 3163 MS (t)3018 3163 MS (t)3042 3163 MS (p)3065 3163 MS (:)3107 3163 MS (/)3130 3163 MS (/)3153 3163 MS (w)3177 3163 MS (w)3237 3163 MS (w)3297 3163 MS (.)3356 3163 MS (a)3377 3163 MS (t)3414 3163 MS (a)3437 3163 MS (m)3475 3163 MS (a)3539 3163 MS (n)3577 3163 MS (.)3618 3163 MS (c)3639 3163 MS (o)3676 3163 MS (m)3719 3163 MS 0 g ( )3782 3163 MS (\()3803 3163 MS (t)3831 3163 MS (h)3855 3163 MS (i)3896 3163 MS (s)3919 3163 MS ( )3951 3163 MS (i)3972 3163 MS (s)3996 3163 MS ( )4028 3163 MS (a)4049 3163 MS n 803 3 2977 3172 B 0.105 g f 0 g (c)592 3259 MS (o)629 3259 MS (m)671 3259 MS (m)735 3259 MS (e)799 3259 MS (r)836 3259 MS (c)864 3259 MS (i)901 3259 MS (a)924 3259 MS (l)961 3259 MS ( )984 3259 MS (p)1005 3259 MS (a)1047 3259 MS (c)1084 3259 MS (k)1121 3259 MS (a)1162 3259 MS (g)1200 3259 MS (e)1241 3259 MS (\))1278 3259 MS (.)1306 3259 MS ( )1327 3259 MS (I)1348 3259 MS (n)1376 3259 MS ( )1417 3259 MS (t)1438 3259 MS (h)1462 3259 MS (e)1503 3259 MS ( )1540 3259 MS (f)1561 3259 MS (u)1588 3259 MS (t)1630 3259 MS (u)1654 3259 MS (r)1695 3259 MS (e)1723 3259 MS ( )1760 3259 MS (w)1782 3259 MS (e)1840 3259 MS ( )1877 3259 MS (w)1899 3259 MS (i)1958 3259 MS (l)1982 3259 MS (l)2005 3259 MS ( )2028 3259 MS (d)2049 3259 MS (o)2091 3259 MS ( )2133 3259 MS (a)2154 3259 MS (d)2191 3259 MS (d)2233 3259 MS (i)2275 3259 MS (t)2298 3259 MS (i)2321 3259 MS (o)2344 3259 MS (n)2386 3259 MS (a)2427 3259 MS (l)2464 3259 MS ( )2487 3259 MS (t)2508 3259 MS (e)2531 3259 MS (s)2568 3259 MS (t)2600 3259 MS (i)2623 3259 MS (n)2647 3259 MS (g)2688 3259 MS ( )2729 3259 MS (o)2750 3259 MS (n)2792 3259 MS ( )2833 3259 MS (a)2854 3259 MS (n)2892 3259 MS ( )2933 3259 MS (i)2954 3259 MS (n)2978 3259 MS (t)3019 3259 MS (e)3042 3259 MS (r)3079 3259 MS (n)3107 3259 MS (a)3148 3259 MS (l)3185 3259 MS (l)3209 3259 MS (y)3233 3259 MS ( )3273 3259 MS (d)3294 3259 MS (e)3336 3259 MS (v)3373 3259 MS (e)3414 3259 MS (l)3451 3259 MS (o)3474 3259 MS (p)3516 3259 MS (e)3558 3259 MS (d)3595 3259 MS ( )3637 3259 MS (r)3658 3259 MS (s)3686 3259 MS (h)3718 3259 MS (d)3759 3259 MS ( )3801 3259 MS (p)3822 3259 MS (a)3864 3259 MS (c)3901 3259 MS (k)3938 3259 MS (a)3979 3259 MS (g)4017 3259 MS (e)4058 3259 MS (.)4095 3259 MS ( )4116 3259 MS (L)4137 3259 MS (o)4187 3259 MS (o)4229 3259 MS (k)4271 3259 MS ( )4312 3259 MS (f)4334 3259 MS (o)4361 3259 MS (r)4403 3259 MS (i)592 3355 MS (n)615 3355 MS (f)657 3355 MS (o)684 3355 MS (r)726 3355 MS (m)755 3355 MS (a)818 3355 MS (t)855 3355 MS (i)878 3355 MS (o)901 3355 MS (n)943 3355 MS ( )984 3355 MS (r)1005 3355 MS (e)1033 3355 MS (g)1071 3355 MS (a)1112 3355 MS (r)1149 3355 MS (d)1177 3355 MS (i)1219 3355 MS (n)1242 3355 MS (g)1284 3355 MS ( )1325 3355 MS (t)1346 3355 MS (h)1369 3355 MS (a)1410 3355 MS (t)1447 3355 MS ( )1470 3355 MS (p)1491 3355 MS (a)1533 3355 MS (c)1570 3355 MS (k)1607 3355 MS (a)1649 3355 MS (g)1686 3355 MS (e)1727 3355 MS ( )1764 3355 MS (i)1785 3355 MS (n)1809 3355 MS ( )1850 3355 MS (t)1871 3355 MS (h)1895 3355 MS (e)1936 3355 MS ( )1973 3355 MS (n)1994 3355 MS (e)2035 3355 MS (a)2072 3355 MS (r)2109 3355 MS ( )2137 3355 MS (f)2158 3355 MS (u)2186 3355 MS (t)2227 3355 MS (u)2251 3355 MS (r)2292 3355 MS (e)2320 3355 MS (.)2357 3355 MS (-)592 3546 MS [83 0 0 -83 0 0]/Helvetica MF ( )619 3546 MS [83 0 0 -83 0 0]/Times-Roman MF (\()742 3546 MS (N)770 3546 MS (T)830 3546 MS (\))882 3546 MS ( )909 3546 MS (S)930 3546 MS (e)976 3546 MS (t)1013 3546 MS ( )1036 3546 MS (t)1057 3546 MS (h)1080 3546 MS (e)1121 3546 MS ( )1158 3546 MS (e)1179 3546 MS (n)1216 3546 MS (v)1258 3546 MS (i)1299 3546 MS (r)1322 3546 MS (o)1350 3546 MS (n)1392 3546 MS (m)1434 3546 MS (e)1498 3546 MS (n)1535 3546 MS (t)1577 3546 MS ( )1600 3546 MS (f)1621 3546 MS (i)1648 3546 MS (l)1672 3546 MS (e)1695 3546 MS ( )1732 3546 MS (t)1753 3546 MS (o)1776 3546 MS (:)1818 3546 MS ( )1841 3546 MS (C)1862 3546 MS (:)1917 3546 MS (\\)1941 3546 MS (P)1963 3546 MS (r)2010 3546 MS (o)2038 3546 MS (g)2080 3546 MS (r)2121 3546 MS (a)2149 3546 MS (m)2187 3546 MS ( )2250 3546 MS (F)2271 3546 MS (i)2317 3546 MS (l)2341 3546 MS (e)2364 3546 MS (s)2401 3546 MS (\\)2434 3546 MS (P)2456 3546 MS (V)2503 3546 MS (M)2563 3546 MS (3)2637 3546 MS (.)2679 3546 MS (4)2700 3546 MS (\\)2742 3546 MS (W)2764 3546 MS (I)2843 3546 MS (N)2871 3546 MS (3)2931 3546 MS (2)2973 3546 MS (\\)3015 3546 MS (f)3038 3546 MS (i)3065 3546 MS (l)3088 3546 MS (e)3111 3546 MS (.)3148 3546 MS (e)3169 3546 MS (n)3207 3546 MS (v)3248 3546 MS (N)592 3738 MS (o)652 3738 MS (t)694 3738 MS (e)717 3738 MS ( )754 3738 MS (t)775 3738 MS (h)798 3738 MS (a)839 3738 MS (t)876 3738 MS ( )899 3738 MS (o)920 3738 MS (t)962 3738 MS (h)985 3738 MS (e)1026 3738 MS (r)1063 3738 MS ( )1091 3738 MS /IsChar{exch/CharStrings get exch known}bd/MapCh{3 -1 roll/Encoding get 3 1 roll put}bd/MapDegree{dup 16#b0 exch/degree IsChar{/degree}{/ring}ifelse MapCh} bd/MapBB{dup 16#a6 exch/brokenbar IsChar{/brokenbar}{/bar}ifelse MapCh}bd /reencode{findfont begin currentdict dup length dict begin{1 index/FID ne{def} {pop pop}ifelse}forall/FontName exch def dup length 0 ne{/Encoding Encoding 256 array copy def 0 exch{dup type/nametype eq{Encoding 2 index 2 index put pop 1 add}{exch pop}ifelse}forall}if pop currentdict dup end end/FontName get exch definefont dup MapDegree MapBB}bd/LATENC[0/grave/acute/circumflex/tilde/macron /breve/dotaccent/dieresis/ring/cedilla/hungarumlaut/ogonek/caron/dotlessi/fi/fl /Lslash/lslash/Zcaron/zcaron/minus/.notdef/.notdef/.notdef/.notdef/.notdef /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space/exclam/quotedbl /numbersign/dollar/percent/ampersand/quotesingle/parenleft/parenright/asterisk /plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight /nine/colon/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M /N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/asciicircum /underscore/grave/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft /bar/braceright/asciitilde/.notdef/.notdef/.notdef/quotesinglbase/florin /quotedblbase/ellipsis/dagger/daggerdbl/circumflex/perthousand/Scaron /guilsinglleft/OE/.notdef/.notdef/.notdef/.notdef/quoteleft/quoteright /quotedblleft/quotedblright/bullet/endash/emdash/tilde/trademark/scaron /guilsinglright/oe/.notdef/.notdef/Ydieresis/.notdef/exclamdown/cent/sterling /currency/yen/brokenbar/section/dieresis/copyright/ordfeminine/guillemotleft /logicalnot/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior /acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine /guillemotright/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute /Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex /Edieresis/Igrave/Iacute/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute /Ocircumflex/Otilde/Odieresis/multiply/Oslash/Ugrave/Uacute/Ucircumflex /Udieresis/Yacute/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis /aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave/iacute /icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis /divide/oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def LATENC /_Times-Roman /Times-Roman reencode [83 0 0 -83 0 0]/_Times-Roman MF (r)1112 3738 MS (s)1140 3738 MS (h)1173 3738 MS (d)1214 3738 MS ( )1256 3738 MS (p)1277 3738 MS (a)1319 3738 MS (c)1356 3738 MS (k)1393 3738 MS (a)1434 3738 MS (g)1471 3738 MS (e)1512 3738 MS (s)1549 3738 MS ( )1581 3738 MS (m)1602 3738 MS (a)1666 3738 MS (y)1705 3738 MS ( )1746 3738 MS (\()1767 3738 MS (o)1795 3738 MS (r)1837 3738 MS ( )1865 3738 MS (n)1886 3738 MS (o)1927 3738 MS (t)1969 3738 MS (\))1992 3738 MS ( )2020 3738 MS (r)2041 3738 MS (e)2069 3738 MS (q)2106 3738 MS (u)2148 3738 MS (i)2189 3738 MS (r)2212 3738 MS (e)2240 3738 MS ( )2277 3738 MS (t)2298 3738 MS (h)2321 3738 MS (i)2362 3738 MS (s)2385 3738 MS ( )2417 3738 MS (\223)2439 3738 MS (h)2475 3738 MS (e)2516 3738 MS (l)2554 3738 MS (p)2577 3738 MS (\224)2619 3738 MS ( )2656 3738 MS (i)2677 3738 MS (n)2700 3738 MS ( )2741 3738 MS (s)2762 3738 MS (e)2794 3738 MS (t)2831 3738 MS (t)2854 3738 MS (i)2878 3738 MS (n)2901 3738 MS (g)2943 3738 MS ( )2984 3738 MS (t)3005 3738 MS (h)3029 3738 MS (e)3070 3738 MS ( )3107 3738 MS (P)3128 3738 MS (V)3175 3738 MS (M)3235 3738 MS (_)3309 3738 MS (R)3351 3738 MS (O)3406 3738 MS (O)3466 3738 MS (T)3526 3738 MS ( )3578 3738 MS (e)3599 3738 MS (n)3636 3738 MS (v)3677 3738 MS (i)3718 3738 MS (r)3741 3738 MS (o)3769 3738 MS (n)3811 3738 MS (m)3853 3738 MS (e)3917 3738 MS (n)3955 3738 MS (t)3996 3738 MS ( )4019 3738 MS (v)4040 3738 MS (a)4081 3738 MS (l)4118 3738 MS (u)4142 3738 MS (e)4183 3738 MS (.)4220 3738 MS ( )4241 3738 MS (T)4262 3738 MS (h)4314 3738 MS (i)4355 3738 MS (s)4378 3738 MS (i)592 3834 MS (s)615 3834 MS ( )647 3834 MS (a)668 3834 MS ( )705 3834 MS (r)726 3834 MS (e)754 3834 MS (s)791 3834 MS (u)823 3834 MS (l)864 3834 MS (t)887 3834 MS ( )910 3834 MS (o)931 3834 MS (f)974 3834 MS ( )1001 3834 MS (A)1023 3834 MS (t)1082 3834 MS (a)1105 3834 MS (m)1143 3834 MS (a)1207 3834 MS (n)1244 3834 MS (\222)1286 3834 MS (s)1313 3834 MS ( )1345 3834 MS (p)1366 3834 MS (a)1408 3834 MS (c)1445 3834 MS (k)1483 3834 MS (a)1524 3834 MS (g)1561 3834 MS (e)1602 3834 MS ( )1639 3834 MS (n)1661 3834 MS (o)1702 3834 MS (t)1744 3834 MS ( )1767 3834 MS (u)1788 3834 MS (s)1830 3834 MS (i)1862 3834 MS (n)1885 3834 MS (g)1927 3834 MS ( )1968 3834 MS (a)1989 3834 MS (n)2027 3834 MS ( )2068 3834 MS (i)2089 3834 MS (n)2112 3834 MS (d)2153 3834 MS (i)2195 3834 MS (v)2219 3834 MS (i)2260 3834 MS (d)2283 3834 MS (u)2325 3834 MS (a)2366 3834 MS (l)2403 3834 MS (\222)2427 3834 MS (s)2455 3834 MS ( )2487 3834 MS (e)2508 3834 MS (n)2545 3834 MS (v)2587 3834 MS (i)2628 3834 MS (r)2651 3834 MS (o)2679 3834 MS (n)2721 3834 MS (m)2763 3834 MS (e)2827 3834 MS (n)2864 3834 MS (t)2906 3834 MS ( )2929 3834 MS (s)2950 3834 MS (e)2982 3834 MS (t)3019 3834 MS (t)3042 3834 MS (i)3065 3834 MS (n)3089 3834 MS (g)3131 3834 MS (s)3172 3834 MS ( )3204 3834 MS (\()3225 3834 MS (t)3253 3834 MS (h)3276 3834 MS (i)3318 3834 MS (s)3341 3834 MS ( )3373 3834 MS (i)3394 3834 MS (s)3418 3834 MS ( )3450 3834 MS (d)3471 3834 MS (i)3513 3834 MS (s)3536 3834 MS (c)3568 3834 MS (u)3605 3834 MS (s)3646 3834 MS (s)3679 3834 MS (e)3711 3834 MS (d)3748 3834 MS ( )3790 3834 MS (i)3811 3834 MS (n)3834 3834 MS ( )3875 3834 MS (A)3896 3834 MS (t)3955 3834 MS (a)3978 3834 MS (m)4017 3834 MS (a)4081 3834 MS (n)4119 3834 MS (d)592 3930 MS (o)634 3930 MS (c)676 3930 MS (u)713 3930 MS (m)755 3930 MS (e)818 3930 MS (n)855 3930 MS (t)897 3930 MS (a)920 3930 MS (t)957 3930 MS (i)980 3930 MS (o)1003 3930 MS (n)1045 3930 MS (.)1086 3930 MS (\))1107 3930 MS (W)592 4121 MS (i)671 4121 MS (n)694 4121 MS (d)735 4121 MS (o)777 4121 MS (w)820 4121 MS (s)878 4121 MS ( )910 4121 MS (9)931 4121 MS (5)973 4121 MS (/)1015 4121 MS (9)1038 4121 MS (8)1080 4121 MS ( )1122 4121 MS (d)1143 4121 MS (o)1185 4121 MS (e)1227 4121 MS (s)1264 4121 MS ( )1296 4121 MS (n)1317 4121 MS (o)1358 4121 MS (t)1400 4121 MS ( )1423 4121 MS (e)1444 4121 MS (x)1481 4121 MS (h)1522 4121 MS (i)1563 4121 MS (b)1586 4121 MS (i)1628 4121 MS (t)1651 4121 MS ( )1674 4121 MS (t)1695 4121 MS (h)1719 4121 MS (i)1760 4121 MS (s)1784 4121 MS ( )1816 4121 MS (p)1837 4121 MS (r)1879 4121 MS (o)1907 4121 MS (b)1949 4121 MS (l)1991 4121 MS (e)2014 4121 MS (m)2051 4121 MS ( )2114 4121 MS (a)2135 4121 MS (s)2172 4121 MS ( )2204 4121 MS (i)2225 4121 MS (t)2249 4121 MS ( )2272 4121 MS (u)2293 4121 MS (s)2334 4121 MS (e)2366 4121 MS (s)2404 4121 MS ( )2436 4121 MS (t)2457 4121 MS (h)2481 4121 MS (e)2522 4121 MS ( )2559 4121 MS (s)2580 4121 MS (e)2612 4121 MS (t)2649 4121 MS (t)2672 4121 MS (i)2695 4121 MS (n)2719 4121 MS (g)2761 4121 MS (s)2802 4121 MS ( )2834 4121 MS (i)2855 4121 MS (n)2879 4121 MS ( )2920 4121 MS (C)2941 4121 MS (:)2996 4121 MS (\\)3020 4121 MS (A)3043 4121 MS (u)3103 4121 MS (t)3144 4121 MS (o)3167 4121 MS (e)3209 4121 MS (x)3247 4121 MS (e)3288 4121 MS (c)3325 4121 MS (.)3362 4121 MS (b)3383 4121 MS (a)3425 4121 MS (t)3462 4121 MS ( )3485 4121 MS (t)3506 4121 MS (o)3529 4121 MS ( )3571 4121 MS (p)3592 4121 MS (i)3634 4121 MS (c)3657 4121 MS (k)3694 4121 MS (u)3735 4121 MS (p)3776 4121 MS ( )3818 4121 MS (t)3839 4121 MS (h)3862 4121 MS (e)3903 4121 MS ( )3940 4121 MS (e)3961 4121 MS (n)3999 4121 MS (v)4041 4121 MS (i)4082 4121 MS (r)4105 4121 MS (o)4133 4121 MS (n)4175 4121 MS (m)4217 4121 MS (e)4281 4121 MS (n)4318 4121 MS (t)4359 4121 MS (v)592 4217 MS (a)633 4217 MS (l)670 4217 MS (u)693 4217 MS (e)734 4217 MS (s)772 4217 MS (.)804 4217 MS (4)442 4505 MS (.)484 4505 MS [83 0 0 -83 0 0]/Helvetica MF ( )505 4505 MS [83 0 0 -83 0 0]/_Times-Roman MF (C)592 4505 MS (o)647 4505 MS (p)689 4505 MS (y)732 4505 MS ( )772 4505 MS (t)793 4505 MS (h)816 4505 MS (e)857 4505 MS ( )894 4505 MS (a)915 4505 MS (p)952 4505 MS (p)994 4505 MS (r)1036 4505 MS (o)1064 4505 MS (p)1106 4505 MS (r)1148 4505 MS (i)1176 4505 MS (a)1199 4505 MS (t)1236 4505 MS (e)1259 4505 MS ( )1296 4505 MS (P)1317 4505 MS (V)1364 4505 MS (M)1424 4505 MS ( )1498 4505 MS (c)1519 4505 MS (o)1556 4505 MS (m)1598 4505 MS (p)1661 4505 MS (i)1703 4505 MS (l)1726 4505 MS (e)1749 4505 MS ( )1786 4505 MS (s)1807 4505 MS (h)1839 4505 MS (e)1880 4505 MS (l)1917 4505 MS (l)1941 4505 MS ( )1964 4505 MS (\()1985 4505 MS (w)2014 4505 MS (i)2072 4505 MS (t)2096 4505 MS (h)2119 4505 MS ( )2160 4505 MS (i)2181 4505 MS (c)2204 4505 MS (o)2241 4505 MS (n)2284 4505 MS (\))2325 4505 MS ( )2353 4505 MS (t)2374 4505 MS (o)2397 4505 MS ( )2439 4505 MS (y)2461 4505 MS (o)2501 4505 MS (u)2543 4505 MS (r)2584 4505 MS ( )2612 4505 MS (d)2633 4505 MS (e)2675 4505 MS (s)2712 4505 MS (k)2744 4505 MS (t)2785 4505 MS (o)2808 4505 MS (p)2850 4505 MS (.)2892 4505 MS ( )2913 4505 MS (Y)2934 4505 MS (o)2994 4505 MS (u)3036 4505 MS ( )3077 4505 MS (w)3099 4505 MS (i)3158 4505 MS (l)3181 4505 MS (l)3204 4505 MS ( )3227 4505 MS (w)3249 4505 MS (a)3308 4505 MS (n)3346 4505 MS (t)3387 4505 MS ( )3410 4505 MS (t)3431 4505 MS (o)3454 4505 MS ( )3496 4505 MS (u)3517 4505 MS (s)3559 4505 MS (e)3591 4505 MS ( )3628 4505 MS (t)3649 4505 MS (h)3672 4505 MS (i)3714 4505 MS (s)3737 4505 MS ( )3769 4505 MS (D)3790 4505 MS (O)3850 4505 MS (S)3911 4505 MS ( )3957 4505 MS (w)3979 4505 MS (i)4038 4505 MS (n)4061 4505 MS (d)4102 4505 MS (o)4144 4505 MS (w)4187 4505 MS (w)592 4600 MS (h)651 4600 MS (e)693 4600 MS (n)731 4600 MS ( )772 4600 MS (c)793 4600 MS (o)830 4600 MS (m)873 4600 MS (p)936 4600 MS (i)978 4600 MS (l)1001 4600 MS (i)1024 4600 MS (n)1048 4600 MS (g)1089 4600 MS ( )1130 4600 MS (P)1151 4600 MS (V)1198 4600 MS (M)1258 4600 MS (.)1332 4600 MS ( )1353 4600 MS (P)1374 4600 MS (e)1421 4600 MS (r)1458 4600 MS (h)1486 4600 MS (a)1527 4600 MS (p)1564 4600 MS (s)1606 4600 MS ( )1638 4600 MS (m)1660 4600 MS (o)1723 4600 MS (r)1765 4600 MS (e)1793 4600 MS ( )1830 4600 MS (i)1851 4600 MS (m)1875 4600 MS (p)1938 4600 MS (o)1980 4600 MS (r)2022 4600 MS (t)2050 4600 MS (a)2073 4600 MS (n)2110 4600 MS (t)2151 4600 MS (,)2174 4600 MS ( )2195 4600 MS (w)2217 4600 MS (h)2276 4600 MS (e)2318 4600 MS (n)2355 4600 MS ( )2396 4600 MS (o)2417 4600 MS (t)2459 4600 MS (h)2483 4600 MS (e)2524 4600 MS (r)2561 4600 MS (s)2589 4600 MS ( )2621 4600 MS (w)2643 4600 MS (a)2702 4600 MS (l)2739 4600 MS (k)2763 4600 MS ( )2804 4600 MS (b)2825 4600 MS (y)2868 4600 MS ( )2908 4600 MS (y)2930 4600 MS (o)2970 4600 MS (u)3013 4600 MS (r)3054 4600 MS ( )3082 4600 MS (d)3103 4600 MS (e)3145 4600 MS (s)3182 4600 MS (k)3214 4600 MS (t)3255 4600 MS (o)3278 4600 MS (p)3320 4600 MS ( )3362 4600 MS (\226)3383 4600 MS ( )3425 4600 MS (t)3446 4600 MS (h)3469 4600 MS (e)3510 4600 MS (y)3548 4600 MS ( )3588 4600 MS (w)3609 4600 MS (i)3669 4600 MS (l)3693 4600 MS (l)3716 4600 MS ( )3739 4600 MS (s)3760 4600 MS (e)3792 4600 MS (e)3829 4600 MS ( )3866 4600 MS (t)3887 4600 MS (h)3911 4600 MS (a)3952 4600 MS (t)3989 4600 MS ( )4012 4600 MS (y)4034 4600 MS (o)4074 4600 MS (u)4117 4600 MS ( )4158 4600 MS (a)4179 4600 MS (r)4216 4600 MS (e)4244 4600 MS ( )4281 4600 MS (a)4302 4600 MS (p)592 4696 MS (r)634 4696 MS (o)662 4696 MS (u)704 4696 MS (d)745 4696 MS ( )787 4696 MS (P)808 4696 MS (V)855 4696 MS (M)915 4696 MS ( )989 4696 MS (3)1009 4696 MS (.)1051 4696 MS (4)1072 4696 MS (.)1114 4696 MS (0)1134 4696 MS ( )1176 4696 MS (u)1197 4696 MS (s)1238 4696 MS (e)1270 4696 MS (r)1307 4696 MS (!)1335 4696 MS (-)592 4888 MS (\()742 4888 MS (N)770 4888 MS (T)830 4888 MS (\))882 4888 MS (C)1042 4888 MS (:)1097 4888 MS (\\)1121 4888 MS (P)1143 4888 MS (r)1190 4888 MS (o)1218 4888 MS (g)1260 4888 MS (r)1301 4888 MS (a)1329 4888 MS (m)1367 4888 MS ( )1430 4888 MS (F)1451 4888 MS (i)1497 4888 MS (l)1520 4888 MS (e)1543 4888 MS (s)1581 4888 MS (\\)1614 4888 MS (P)1636 4888 MS (V)1683 4888 MS (M)1743 4888 MS (3)1817 4888 MS (.)1859 4888 MS (4)1880 4888 MS (\\)1922 4888 MS (W)1944 4888 MS (I)2023 4888 MS (N)2051 4888 MS (3)2111 4888 MS (2)2153 4888 MS (\\)2195 4888 MS (P)2217 4888 MS (V)2264 4888 MS (M)2324 4888 MS ( )2398 4888 MS (N)2419 4888 MS (T)2479 4888 MS ( )2531 4888 MS (C)2552 4888 MS (o)2607 4888 MS (m)2650 4888 MS (p)2713 4888 MS (i)2755 4888 MS (l)2778 4888 MS (e)2801 4888 MS ( )2838 4888 MS (S)2859 4888 MS (h)2905 4888 MS (e)2946 4888 MS (l)2983 4888 MS (l)3007 4888 MS (-)592 4984 MS (\()742 4984 MS (9)770 4984 MS (5)812 4984 MS (/)854 4984 MS (9)877 4984 MS (8)919 4984 MS (\))960 4984 MS (C)1042 4984 MS (:)1097 4984 MS (\\)1121 4984 MS (P)1143 4984 MS (r)1190 4984 MS (o)1218 4984 MS (g)1260 4984 MS (r)1301 4984 MS (a)1329 4984 MS (m)1367 4984 MS ( )1430 4984 MS (F)1451 4984 MS (i)1497 4984 MS (l)1520 4984 MS (e)1543 4984 MS (s)1581 4984 MS (\\)1614 4984 MS (P)1636 4984 MS (V)1683 4984 MS (M)1743 4984 MS (3)1817 4984 MS (.)1859 4984 MS (4)1880 4984 MS (\\)1922 4984 MS (W)1944 4984 MS (I)2023 4984 MS (N)2051 4984 MS (3)2111 4984 MS (2)2153 4984 MS (\\)2195 4984 MS (P)2217 4984 MS (V)2264 4984 MS (M)2324 4984 MS ( )2398 4984 MS (C)2419 4984 MS (o)2474 4984 MS (m)2517 4984 MS (p)2580 4984 MS (i)2622 4984 MS (l)2646 4984 MS (e)2669 4984 MS ( )2706 4984 MS (S)2727 4984 MS (h)2773 4984 MS (e)2814 4984 MS (l)2852 4984 MS (l)2875 4984 MS (\()592 5175 MS (9)620 5175 MS (5)662 5175 MS (/)704 5175 MS (9)727 5175 MS (8)769 5175 MS (\))810 5175 MS ( )838 5175 MS (I)859 5175 MS (f)887 5175 MS ( )914 5175 MS (y)935 5175 MS (o)975 5175 MS (u)1018 5175 MS ( )1059 5175 MS (r)1080 5175 MS (u)1108 5175 MS (n)1149 5175 MS ( )1190 5175 MS (t)1211 5175 MS (h)1235 5175 MS (e)1276 5175 MS ( )1313 5175 MS (C)1335 5175 MS (:)1390 5175 MS (\\)1414 5175 MS (P)1436 5175 MS (r)1483 5175 MS (o)1511 5175 MS (g)1553 5175 MS (r)1594 5175 MS (a)1622 5175 MS (m)1660 5175 MS ( )1723 5175 MS (F)1744 5175 MS (i)1790 5175 MS (l)1813 5175 MS (e)1836 5175 MS (s)1874 5175 MS (\\)1907 5175 MS (P)1929 5175 MS (V)1976 5175 MS (M)2036 5175 MS (3)2110 5175 MS (.)2152 5175 MS (4)2173 5175 MS (\\)2215 5175 MS (m)2237 5175 MS (a)2301 5175 MS (k)2339 5175 MS (e)2380 5175 MS (.)2417 5175 MS (b)2438 5175 MS (a)2480 5175 MS (t)2517 5175 MS ( )2540 5175 MS (f)2562 5175 MS (i)2589 5175 MS (l)2612 5175 MS (e)2635 5175 MS ( )2672 5175 MS (a)2693 5175 MS (n)2730 5175 MS (d)2771 5175 MS ( )2813 5175 MS (s)2834 5175 MS (e)2866 5175 MS (e)2903 5175 MS ( )2940 5175 MS (\223)2962 5175 MS (O)2998 5175 MS (u)3058 5175 MS (t)3100 5175 MS ( )3123 5175 MS (o)3144 5175 MS (f)3186 5175 MS ( )3213 5175 MS (e)3234 5175 MS (n)3272 5175 MS (v)3314 5175 MS (i)3355 5175 MS (r)3378 5175 MS (o)3406 5175 MS (n)3448 5175 MS (m)3490 5175 MS (e)3554 5175 MS (n)3591 5175 MS (t)3632 5175 MS ( )3655 5175 MS (s)3677 5175 MS (p)3709 5175 MS (a)3751 5175 MS (c)3788 5175 MS (e)3825 5175 MS (\224)3862 5175 MS (,)3899 5175 MS ( )3920 5175 MS (t)3941 5175 MS (h)3964 5175 MS (i)4005 5175 MS (s)4028 5175 MS ( )4060 5175 MS (i)4081 5175 MS (n)4105 5175 MS (d)4146 5175 MS (i)4188 5175 MS (c)4211 5175 MS (a)4248 5175 MS (t)4285 5175 MS (e)4308 5175 MS (s)4345 5175 MS (t)592 5271 MS (h)615 5271 MS (a)656 5271 MS (t)693 5271 MS ( )716 5271 MS (y)738 5271 MS (o)778 5271 MS (u)821 5271 MS ( )862 5271 MS (h)883 5271 MS (a)924 5271 MS (v)962 5271 MS (e)1003 5271 MS ( )1040 5271 MS (t)1061 5271 MS (o)1084 5271 MS (o)1126 5271 MS ( )1168 5271 MS (m)1190 5271 MS (a)1253 5271 MS (n)1291 5271 MS (y)1333 5271 MS ( )1373 5271 MS (e)1394 5271 MS (n)1432 5271 MS (v)1473 5271 MS (i)1515 5271 MS (r)1538 5271 MS (o)1566 5271 MS (n)1608 5271 MS (m)1650 5271 MS (e)1714 5271 MS (n)1751 5271 MS (t)1792 5271 MS ( )1815 5271 MS (v)1837 5271 MS (a)1878 5271 MS (r)1915 5271 MS (i)1943 5271 MS (a)1966 5271 MS (b)2003 5271 MS (l)2045 5271 MS (e)2068 5271 MS (s)2105 5271 MS ( )2137 5271 MS (s)2158 5271 MS (e)2190 5271 MS (t)2227 5271 MS ( )2250 5271 MS (f)2272 5271 MS (o)2299 5271 MS (r)2341 5271 MS ( )2369 5271 MS (y)2391 5271 MS (o)2431 5271 MS (u)2473 5271 MS (r)2514 5271 MS ( )2542 5271 MS (D)2563 5271 MS (O)2623 5271 MS (S)2684 5271 MS ( )2730 5271 MS (s)2751 5271 MS (h)2783 5271 MS (e)2824 5271 MS (l)2862 5271 MS (l)2885 5271 MS (.)2908 5271 MS ( )2929 5271 MS (T)2950 5271 MS (h)3002 5271 MS (i)3043 5271 MS (s)3066 5271 MS ( )3098 5271 MS (c)3119 5271 MS (a)3156 5271 MS (n)3193 5271 MS ( )3234 5271 MS (b)3255 5271 MS (e)3297 5271 MS ( )3334 5271 MS (r)3355 5271 MS (e)3383 5271 MS (s)3420 5271 MS (o)3452 5271 MS (l)3494 5271 MS (v)3517 5271 MS (e)3558 5271 MS (d)3595 5271 MS ( )3637 5271 MS (b)3658 5271 MS (y)3701 5271 MS (:)3741 5271 MS ( )3764 5271 MS (r)3785 5271 MS (i)3813 5271 MS (g)3837 5271 MS (h)3878 5271 MS (t)3919 5271 MS ( )3942 5271 MS (c)3963 5271 MS (l)4000 5271 MS (i)4023 5271 MS (c)4046 5271 MS (k)4084 5271 MS ( )4125 5271 MS (t)4146 5271 MS (h)4170 5271 MS (e)4211 5271 MS (\223)592 5367 MS (P)628 5367 MS (V)675 5367 MS (M)735 5367 MS ( )809 5367 MS (C)830 5367 MS (o)885 5367 MS (m)928 5367 MS (p)991 5367 MS (i)1033 5367 MS (l)1057 5367 MS (e)1080 5367 MS ( )1117 5367 MS (S)1138 5367 MS (h)1184 5367 MS (e)1225 5367 MS (l)1263 5367 MS (l)1286 5367 MS (\224)1309 5367 MS ( )1346 5367 MS (i)1367 5367 MS (c)1390 5367 MS (o)1427 5367 MS (n)1469 5367 MS ( )1510 5367 MS (\226)1531 5367 MS ( )1573 5367 MS (s)1594 5367 MS (e)1626 5367 MS (l)1663 5367 MS (e)1686 5367 MS (c)1723 5367 MS (t)1760 5367 MS ( )1783 5367 MS (\223)1805 5367 MS (p)1841 5367 MS (r)1883 5367 MS (o)1911 5367 MS (p)1953 5367 MS (e)1995 5367 MS (r)2032 5367 MS (t)2060 5367 MS (i)2083 5367 MS (e)2106 5367 MS (s)2143 5367 MS (\224)2175 5367 MS ( )2212 5367 MS (\226)2233 5367 MS ( )2275 5367 MS (c)2296 5367 MS (h)2333 5367 MS (o)2374 5367 MS (o)2416 5367 MS (s)2458 5367 MS (e)2490 5367 MS ( )2527 5367 MS (\223)2548 5367 MS (m)2584 5367 MS (e)2647 5367 MS (m)2686 5367 MS (o)2750 5367 MS (r)2792 5367 MS (y)2821 5367 MS (\224)2861 5367 MS ( )2898 5367 MS (t)2919 5367 MS (a)2942 5367 MS (b)2979 5367 MS ( )3021 5367 MS (\226)3042 5367 MS ( )3084 5367 MS (i)3105 5367 MS (n)3128 5367 MS (c)3169 5367 MS (r)3206 5367 MS (e)3234 5367 MS (a)3271 5367 MS (s)3308 5367 MS (e)3340 5367 MS ( )3377 5367 MS (t)3398 5367 MS (h)3422 5367 MS (e)3463 5367 MS ( )3500 5367 MS (\223)3522 5367 MS (I)3558 5367 MS (n)3586 5367 MS (i)3627 5367 MS (t)3650 5367 MS (i)3674 5367 MS (a)3697 5367 MS (l)3734 5367 MS ( )3757 5367 MS (e)3778 5367 MS (n)3815 5367 MS (v)3857 5367 MS (i)3898 5367 MS (r)3921 5367 MS (o)3949 5367 MS (n)3991 5367 MS (m)4033 5367 MS (e)4097 5367 MS (n)4135 5367 MS (t)4176 5367 MS (\224)4199 5367 MS (s)592 5463 MS (e)624 5463 MS (t)661 5463 MS (t)684 5463 MS (i)707 5463 MS (n)731 5463 MS (g)772 5463 MS ( )813 5463 MS (\226)834 5463 MS ( )876 5463 MS (c)897 5463 MS (l)934 5463 MS (i)957 5463 MS (c)980 5463 MS (k)1018 5463 MS ( )1059 5463 MS (\223)1080 5463 MS (O)1117 5463 MS (K)1177 5463 MS (\224)1237 5463 MS (.)1274 5463 MS ( )1295 5463 MS (O)1316 5463 MS (u)1376 5463 MS (r)1417 5463 MS ( )1445 5463 MS (i)1466 5463 MS (n)1490 5463 MS (i)1531 5463 MS (t)1554 5463 MS (i)1577 5463 MS (a)1600 5463 MS (l)1637 5463 MS ( )1660 5463 MS (s)1682 5463 MS (e)1714 5463 MS (t)1751 5463 MS (t)1774 5463 MS (i)1797 5463 MS (n)1821 5463 MS (g)1862 5463 MS ( )1903 5463 MS (i)1924 5463 MS (s)1948 5463 MS ( )1980 5463 MS (2)2001 5463 MS (0)2043 5463 MS (4)2085 5463 MS (8)2127 5463 MS (.)2169 5463 MS ( )2190 5463 MS (W)2211 5463 MS (e)2290 5463 MS ( )2326 5463 MS (r)2347 5463 MS (e)2375 5463 MS (q)2412 5463 MS (u)2454 5463 MS (i)2495 5463 MS (r)2518 5463 MS (e)2546 5463 MS (d)2583 5463 MS ( )2625 5463 MS (t)2646 5463 MS (h)2669 5463 MS (i)2710 5463 MS (s)2733 5463 MS ( )2765 5463 MS (v)2786 5463 MS (a)2827 5463 MS (l)2864 5463 MS (u)2888 5463 MS (e)2929 5463 MS ( )2966 5463 MS (o)2987 5463 MS (n)3029 5463 MS ( )3070 5463 MS (W)3091 5463 MS (i)3170 5463 MS (n)3193 5463 MS (d)3234 5463 MS (o)3276 5463 MS (w)3319 5463 MS (s)3378 5463 MS ( )3410 5463 MS (9)3431 5463 MS (5)3473 5463 MS ( )3515 5463 MS (a)3536 5463 MS (n)3573 5463 MS (d)3614 5463 MS ( )3656 5463 MS (9)3677 5463 MS (8)3719 5463 MS ( )3761 5463 MS (m)3782 5463 MS (a)3845 5463 MS (c)3882 5463 MS (h)3920 5463 MS (i)3961 5463 MS (n)3985 5463 MS (e)4026 5463 MS (s)4063 5463 MS ( )4095 5463 MS (w)4117 5463 MS (i)4176 5463 MS (t)4199 5463 MS (h)4223 5463 MS (C)592 5559 MS (+)647 5559 MS (+)694 5559 MS (,)741 5559 MS ( )762 5559 MS (F)783 5559 MS (o)829 5559 MS (r)871 5559 MS (t)899 5559 MS (r)922 5559 MS (a)950 5559 MS (n)987 5559 MS (,)1028 5559 MS ( )1049 5559 MS (a)1070 5559 MS (n)1107 5559 MS (d)1148 5559 MS ( )1190 5559 MS (P)1211 5559 MS (V)1258 5559 MS (M)1318 5559 MS ( )1392 5559 MS (e)1413 5559 MS (n)1450 5559 MS (v)1491 5559 MS (i)1532 5559 MS (r)1555 5559 MS (o)1583 5559 MS (n)1625 5559 MS (m)1667 5559 MS (e)1731 5559 MS (n)1769 5559 MS (t)1810 5559 MS ( )1833 5559 MS (v)1855 5559 MS (a)1896 5559 MS (l)1933 5559 MS (u)1956 5559 MS (e)1997 5559 MS (s)2035 5559 MS ( )2067 5559 MS (i)2088 5559 MS (n)2112 5559 MS (s)2153 5559 MS (t)2185 5559 MS (a)2208 5559 MS (l)2245 5559 MS (l)2268 5559 MS (e)2291 5559 MS (d)2328 5559 MS (.)2370 5559 MS ( )2391 5559 MS (I)2412 5559 MS (f)2440 5559 MS ( )2467 5559 MS (y)2489 5559 MS (o)2529 5559 MS (u)2572 5559 MS ( )2613 5559 MS (d)2634 5559 MS (o)2676 5559 MS ( )2718 5559 MS (m)2740 5559 MS (o)2803 5559 MS (r)2845 5559 MS (e)2873 5559 MS (,)2910 5559 MS ( )2931 5559 MS (e)2952 5559 MS (x)2989 5559 MS (p)3030 5559 MS (e)3072 5559 MS (c)3109 5559 MS (t)3146 5559 MS ( )3169 5559 MS (t)3190 5559 MS (o)3213 5559 MS ( )3255 5559 MS (i)3276 5559 MS (n)3299 5559 MS (c)3340 5559 MS (r)3377 5559 MS (e)3405 5559 MS (a)3442 5559 MS (s)3479 5559 MS (e)3511 5559 MS ( )3548 5559 MS (t)3569 5559 MS (h)3593 5559 MS (i)3634 5559 MS (s)3657 5559 MS ( )3689 5559 MS (v)3711 5559 MS (a)3752 5559 MS (l)3789 5559 MS (u)3813 5559 MS (e)3854 5559 MS (.)3891 5559 MS showpage %%Page: 2 2 13.238 780.059 translate 72 600 div dup neg scale 0 0 transform .25 add round .25 sub exch .25 add round .25 sub exch itransform translate [83 0 0 -83 0 0]/Times-Roman MF (5)442 576 MS (.)484 576 MS [83 0 0 -83 0 0]/Helvetica MF ( )505 576 MS [83 0 0 -83 0 0]/Times-Roman MF (A)592 576 MS (c)651 576 MS (t)688 576 MS (i)711 576 MS (v)735 576 MS (a)776 576 MS (t)813 576 MS (e)836 576 MS ( )873 576 MS (t)894 576 MS (h)918 576 MS (e)959 576 MS ( )996 576 MS (n)1017 576 MS (e)1058 576 MS (w)1097 576 MS ( )1155 576 MS (e)1176 576 MS (n)1214 576 MS (v)1256 576 MS (i)1297 576 MS (r)1320 576 MS (o)1348 576 MS (n)1390 576 MS (m)1432 576 MS (e)1496 576 MS (n)1534 576 MS (t)1575 576 MS ( )1598 576 MS (v)1619 576 MS (a)1660 576 MS (r)1697 576 MS (i)1725 576 MS (a)1748 576 MS (b)1785 576 MS (l)1827 576 MS (e)1850 576 MS (s)1887 576 MS (.)1919 576 MS (-)592 767 MS (\()742 767 MS (N)770 767 MS (T)830 767 MS (\))882 767 MS (L)1042 767 MS (o)1092 767 MS (g)1134 767 MS (o)1175 767 MS (f)1218 767 MS (f)1245 767 MS ( )1272 767 MS (a)1293 767 MS (n)1331 767 MS (d)1372 767 MS ( )1414 767 MS (t)1435 767 MS (h)1458 767 MS (e)1499 767 MS (n)1537 767 MS ( )1578 767 MS (l)1599 767 MS (o)1622 767 MS (g)1664 767 MS (o)1705 767 MS (n)1748 767 MS (.)1789 767 MS /IsChar{exch/CharStrings get exch known}bd/MapCh{3 -1 roll/Encoding get 3 1 roll put}bd/MapDegree{dup 16#b0 exch/degree IsChar{/degree}{/ring}ifelse MapCh} bd/MapBB{dup 16#a6 exch/brokenbar IsChar{/brokenbar}{/bar}ifelse MapCh}bd /reencode{findfont begin currentdict dup length dict begin{1 index/FID ne{def} {pop pop}ifelse}forall/FontName exch def dup length 0 ne{/Encoding Encoding 256 array copy def 0 exch{dup type/nametype eq{Encoding 2 index 2 index put pop 1 add}{exch pop}ifelse}forall}if pop currentdict dup end end/FontName get exch definefont dup MapDegree MapBB}bd/LATENC[0/grave/acute/circumflex/tilde/macron /breve/dotaccent/dieresis/ring/cedilla/hungarumlaut/ogonek/caron/dotlessi/fi/fl /Lslash/lslash/Zcaron/zcaron/minus/.notdef/.notdef/.notdef/.notdef/.notdef /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space/exclam/quotedbl /numbersign/dollar/percent/ampersand/quotesingle/parenleft/parenright/asterisk /plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight /nine/colon/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M /N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/asciicircum /underscore/grave/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft /bar/braceright/asciitilde/.notdef/.notdef/.notdef/quotesinglbase/florin /quotedblbase/ellipsis/dagger/daggerdbl/circumflex/perthousand/Scaron /guilsinglleft/OE/.notdef/.notdef/.notdef/.notdef/quoteleft/quoteright /quotedblleft/quotedblright/bullet/endash/emdash/tilde/trademark/scaron /guilsinglright/oe/.notdef/.notdef/Ydieresis/.notdef/exclamdown/cent/sterling /currency/yen/brokenbar/section/dieresis/copyright/ordfeminine/guillemotleft /logicalnot/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior /acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine /guillemotright/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute /Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex /Edieresis/Igrave/Iacute/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute /Ocircumflex/Otilde/Odieresis/multiply/Oslash/Ugrave/Uacute/Ucircumflex /Udieresis/Yacute/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis /aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave/iacute /icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis /divide/oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def LATENC /_Times-Roman /Times-Roman reencode [83 0 0 -83 0 0]/_Times-Roman MF (N)742 959 MS (o)802 959 MS (t)844 959 MS ( )867 959 MS (a)888 959 MS (s)925 959 MS ( )957 959 MS (i)978 959 MS (n)1001 959 MS (t)1042 959 MS (r)1065 959 MS (u)1094 959 MS (s)1135 959 MS (i)1167 959 MS (v)1191 959 MS (e)1232 959 MS ( )1269 959 MS (a)1290 959 MS (s)1327 959 MS ( )1359 959 MS (\223)1381 959 MS (o)1417 959 MS (t)1459 959 MS (h)1482 959 MS (e)1523 959 MS (r)1560 959 MS (\224)1588 959 MS ( )1625 959 MS (a)1646 959 MS (p)1683 959 MS (p)1725 959 MS (l)1767 959 MS (i)1790 959 MS (c)1813 959 MS (a)1850 959 MS (t)1887 959 MS (i)1910 959 MS (o)1933 959 MS (n)1975 959 MS (s)2017 959 MS ( )2049 959 MS (t)2070 959 MS (h)2093 959 MS (a)2134 959 MS (t)2171 959 MS ( )2194 959 MS (r)2215 959 MS (e)2243 959 MS (q)2280 959 MS (u)2322 959 MS (i)2363 959 MS (r)2386 959 MS (e)2414 959 MS ( )2451 959 MS (a)2472 959 MS ( )2509 959 MS (r)2530 959 MS (e)2558 959 MS (b)2595 959 MS (o)2637 959 MS (o)2679 959 MS (t)2721 959 MS ( )2744 959 MS (a)2765 959 MS (f)2802 959 MS (t)2829 959 MS (e)2852 959 MS (r)2889 959 MS ( )2917 959 MS (e)2938 959 MS (v)2975 959 MS (e)3016 959 MS (r)3053 959 MS (y)3082 959 MS ( )3122 959 MS (o)3143 959 MS (t)3185 959 MS (h)3208 959 MS (e)3249 959 MS (r)3286 959 MS ( )3314 959 MS (s)3336 959 MS (t)3368 959 MS (e)3391 959 MS (p)3428 959 MS (\205)3470 959 MS ( )3553 959 MS (T)3574 959 MS (h)3626 959 MS (i)3667 959 MS (s)3690 959 MS ( )3722 959 MS (s)3743 959 MS (t)3775 959 MS (e)3798 959 MS (p)3835 959 MS ( )3877 959 MS (i)3898 959 MS (s)3921 959 MS ( )3953 959 MS (n)3975 959 MS (e)4016 959 MS (c)4053 959 MS (e)4090 959 MS (s)4127 959 MS (s)4160 959 MS (a)4192 959 MS (r)4229 959 MS (y)4258 959 MS ( )4298 959 MS (s)4319 959 MS (o)4351 959 MS (t)742 1055 MS (h)765 1055 MS (a)806 1055 MS (t)843 1055 MS ( )866 1055 MS (t)887 1055 MS (h)911 1055 MS (e)952 1055 MS ( )989 1055 MS (n)1010 1055 MS (e)1051 1055 MS (w)1089 1055 MS ( )1148 1055 MS (r)1169 1055 MS (e)1197 1055 MS (g)1235 1055 MS (i)1276 1055 MS (s)1299 1055 MS (t)1331 1055 MS (r)1354 1055 MS (y)1383 1055 MS ( )1424 1055 MS (e)1445 1055 MS (n)1482 1055 MS (t)1523 1055 MS (r)1546 1055 MS (i)1574 1055 MS (e)1597 1055 MS (s)1635 1055 MS ( )1667 1055 MS (a)1688 1055 MS (r)1725 1055 MS (e)1753 1055 MS ( )1790 1055 MS (r)1811 1055 MS (e)1839 1055 MS (c)1876 1055 MS (o)1913 1055 MS (g)1955 1055 MS (n)1996 1055 MS (i)2037 1055 MS (z)2060 1055 MS (e)2097 1055 MS (d)2134 1055 MS ( )2176 1055 MS (a)2197 1055 MS (s)2234 1055 MS ( )2266 1055 MS (e)2287 1055 MS (n)2324 1055 MS (v)2366 1055 MS (i)2407 1055 MS (r)2430 1055 MS (o)2458 1055 MS (n)2500 1055 MS (m)2542 1055 MS (e)2606 1055 MS (n)2644 1055 MS (t)2685 1055 MS ( )2708 1055 MS (v)2729 1055 MS (a)2770 1055 MS (r)2807 1055 MS (i)2835 1055 MS (a)2858 1055 MS (b)2895 1055 MS (l)2937 1055 MS (e)2960 1055 MS (s)2998 1055 MS (.)3030 1055 MS (-)592 1247 MS (\()742 1247 MS (9)770 1247 MS (5)812 1247 MS (/)854 1247 MS (9)877 1247 MS (8)919 1247 MS (\))960 1247 MS (R)1042 1247 MS (e)1097 1247 MS (b)1134 1247 MS (o)1176 1247 MS (o)1218 1247 MS (t)1260 1247 MS (J)742 1438 MS (u)775 1438 MS (s)816 1438 MS (t)848 1438 MS ( )871 1438 MS (c)892 1438 MS (a)929 1438 MS (n)966 1438 MS (\222)1008 1438 MS (t)1035 1438 MS ( )1058 1438 MS (b)1079 1438 MS (e)1121 1438 MS ( )1158 1438 MS (a)1179 1438 MS (v)1216 1438 MS (o)1257 1438 MS (i)1299 1438 MS (d)1322 1438 MS (e)1364 1438 MS (d)1401 1438 MS (.)1443 1438 MS ( )1464 1438 MS (T)1485 1438 MS (h)1537 1438 MS (a)1578 1438 MS (t)1615 1438 MS ( )1638 1438 MS (i)1659 1438 MS (s)1682 1438 MS (,)1714 1438 MS ( )1735 1438 MS (u)1756 1438 MS (n)1797 1438 MS (l)1838 1438 MS (e)1861 1438 MS (s)1899 1438 MS (s)1931 1438 MS ( )1963 1438 MS (y)1985 1438 MS (o)2025 1438 MS (u)2068 1438 MS ( )2109 1438 MS (s)2130 1438 MS (w)2163 1438 MS (i)2222 1438 MS (t)2246 1438 MS (c)2269 1438 MS (h)2306 1438 MS ( )2347 1438 MS (t)2368 1438 MS (o)2391 1438 MS ( )2433 1438 MS (N)2454 1438 MS (T)2514 1438 MS (.)2566 1438 MS (6)442 1630 MS (.)484 1630 MS [83 0 0 -83 0 0]/Helvetica MF ( )505 1630 MS [83 0 0 -83 0 0]/_Times-Roman MF (Y)592 1630 MS (o)652 1630 MS (u)694 1630 MS ( )735 1630 MS (a)756 1630 MS (r)793 1630 MS (e)821 1630 MS ( )858 1630 MS (n)879 1630 MS (o)920 1630 MS (w)963 1630 MS ( )1021 1630 MS (r)1042 1630 MS (e)1070 1630 MS (a)1107 1630 MS (d)1144 1630 MS (y)1187 1630 MS ( )1227 1630 MS (t)1248 1630 MS (o)1271 1630 MS ( )1313 1630 MS (c)1334 1630 MS (o)1371 1630 MS (m)1414 1630 MS (p)1477 1630 MS (i)1519 1630 MS (l)1542 1630 MS (e)1565 1630 MS ( )1602 1630 MS (P)1623 1630 MS (V)1670 1630 MS (M)1730 1630 MS ( )1804 1630 MS (o)1825 1630 MS (n)1867 1630 MS ( )1908 1630 MS (y)1930 1630 MS (o)1970 1630 MS (u)2013 1630 MS (r)2054 1630 MS ( )2082 1630 MS (m)2104 1630 MS (a)2167 1630 MS (c)2204 1630 MS (h)2242 1630 MS (i)2283 1630 MS (n)2307 1630 MS (e)2348 1630 MS (.)2385 1630 MS (1)592 1822 MS (.)634 1822 MS [83 0 0 -83 0 0]/Helvetica MF ( )655 1822 MS [83 0 0 -83 0 0]/_Times-Roman MF (D)742 1822 MS (o)802 1822 MS (u)844 1822 MS (b)885 1822 MS (l)927 1822 MS (e)950 1822 MS (-)987 1822 MS (c)1014 1822 MS (l)1051 1822 MS (i)1074 1822 MS (c)1097 1822 MS (k)1135 1822 MS ( )1176 1822 MS (t)1197 1822 MS (h)1221 1822 MS (e)1262 1822 MS ( )1299 1822 MS (d)1320 1822 MS (e)1362 1822 MS (s)1399 1822 MS (k)1431 1822 MS (t)1472 1822 MS (o)1495 1822 MS (p)1537 1822 MS ( )1579 1822 MS (P)1600 1822 MS (V)1647 1822 MS (M)1707 1822 MS ( )1781 1822 MS (c)1802 1822 MS (o)1839 1822 MS (m)1882 1822 MS (p)1945 1822 MS (i)1987 1822 MS (l)2010 1822 MS (e)2033 1822 MS ( )2070 1822 MS (s)2091 1822 MS (h)2123 1822 MS (e)2164 1822 MS (l)2202 1822 MS (l)2225 1822 MS ( )2248 1822 MS (i)2269 1822 MS (c)2292 1822 MS (o)2329 1822 MS (n)2371 1822 MS (.)2412 1822 MS (2)592 1917 MS (.)634 1917 MS [83 0 0 -83 0 0]/Helvetica MF ( )655 1917 MS [83 0 0 -83 0 0]/_Times-Roman MF (T)742 1917 MS (y)794 1917 MS (p)834 1917 MS (e)876 1917 MS ( )913 1917 MS (m)935 1917 MS (a)998 1917 MS (k)1036 1917 MS (e)1077 1917 MS (.)1114 1917 MS (b)1135 1917 MS (a)1177 1917 MS (t)1214 1917 MS ( )1237 1917 MS (a)1258 1917 MS (t)1295 1917 MS ( )1318 1917 MS (t)1339 1917 MS (h)1362 1917 MS (e)1403 1917 MS ( )1440 1917 MS (D)1461 1917 MS (O)1521 1917 MS (S)1581 1917 MS ( )1627 1917 MS (c)1648 1917 MS (o)1685 1917 MS (m)1727 1917 MS (m)1792 1917 MS (a)1856 1917 MS (n)1894 1917 MS (d)1935 1917 MS ( )1977 1917 MS (p)1998 1917 MS (r)2040 1917 MS (o)2068 1917 MS (m)2111 1917 MS (p)2174 1917 MS (t)2216 1917 MS ( )2239 1917 MS (t)2260 1917 MS (o)2283 1917 MS ( )2325 1917 MS (s)2346 1917 MS (e)2378 1917 MS (e)2415 1917 MS ( )2452 1917 MS (m)2473 1917 MS (a)2537 1917 MS (k)2575 1917 MS (e)2616 1917 MS (f)2653 1917 MS (i)2681 1917 MS (l)2704 1917 MS (e)2727 1917 MS ( )2764 1917 MS (o)2785 1917 MS (p)2827 1917 MS (t)2869 1917 MS (i)2892 1917 MS (o)2915 1917 MS (n)2957 1917 MS (s)2998 1917 MS (.)3030 1917 MS (3)592 2013 MS (.)634 2013 MS [83 0 0 -83 0 0]/Helvetica MF ( )655 2013 MS [83 0 0 -83 0 0]/_Times-Roman MF (G)742 2013 MS (o)802 2013 MS ( )844 2013 MS (f)865 2013 MS (o)892 2013 MS (r)934 2013 MS ( )962 2013 MS (i)983 2013 MS (t)1006 2013 MS (!)1029 2013 MS (7)442 2205 MS (.)484 2205 MS [83 0 0 -83 0 0]/Helvetica MF ( )505 2205 MS [83 0 0 -83 0 0]/_Times-Roman MF (T)592 2205 MS (o)644 2205 MS ( )685 2205 MS (p)706 2205 MS (l)748 2205 MS (a)771 2205 MS (c)808 2205 MS (e)845 2205 MS ( )882 2205 MS (P)902 2205 MS (V)949 2205 MS (M)1009 2205 MS ( )1083 2205 MS (s)1104 2205 MS (h)1136 2205 MS (o)1177 2205 MS (r)1219 2205 MS (t)1247 2205 MS (c)1270 2205 MS (u)1307 2205 MS (t)1348 2205 MS (s)1371 2205 MS ( )1403 2205 MS (i)1424 2205 MS (n)1448 2205 MS ( )1489 2205 MS (y)1511 2205 MS (o)1551 2205 MS (u)1593 2205 MS (r)1635 2205 MS ( )1663 2205 MS (S)1684 2205 MS (T)1730 2205 MS (A)1782 2205 MS (R)1842 2205 MS (T)1897 2205 MS ( )1949 2205 MS (m)1970 2205 MS (e)2033 2205 MS (n)2071 2205 MS (u)2112 2205 MS ( )2153 2205 MS (\226)2174 2205 MS ( )2216 2205 MS (t)2237 2205 MS (w)2261 2205 MS (o)2320 2205 MS ( )2362 2205 MS (o)2383 2205 MS (p)2425 2205 MS (t)2467 2205 MS (i)2490 2205 MS (o)2513 2205 MS (n)2555 2205 MS (s)2596 2205 MS ( )2628 2205 MS (\226)2649 2205 MS ( )2691 2205 MS (\()2712 2205 MS (A)2740 2205 MS (\))2799 2205 MS ( )2827 2205 MS (f)2848 2205 MS (o)2875 2205 MS (r)2917 2205 MS ( )2945 2205 MS (a)2966 2205 MS (l)3003 2205 MS (l)3026 2205 MS ( )3049 2205 MS (u)3071 2205 MS (s)3112 2205 MS (e)3144 2205 MS (r)3181 2205 MS (s)3209 2205 MS (,)3241 2205 MS ( )3262 2205 MS (\()3283 2205 MS (B)3311 2205 MS (\))3367 2205 MS ( )3395 2205 MS (f)3416 2205 MS (o)3443 2205 MS (r)3485 2205 MS ( )3513 2205 MS (i)3534 2205 MS (n)3557 2205 MS (d)3598 2205 MS (i)3640 2205 MS (v)3663 2205 MS (i)3704 2205 MS (d)3727 2205 MS (u)3770 2205 MS (a)3811 2205 MS (l)3848 2205 MS ( )3871 2205 MS (u)3892 2205 MS (s)3934 2205 MS (e)3966 2205 MS (r)4003 2205 MS (s)4031 2205 MS (:)4063 2205 MS (\()592 2397 MS (A)620 2397 MS (\))679 2397 MS [83 0 0 -83 0 0]/Helvetica MF ( )707 2397 MS [83 0 0 -83 0 0]/_Times-Roman MF (T)742 2397 MS (o)794 2397 MS ( )835 2397 MS (i)856 2397 MS (n)879 2397 MS (s)920 2397 MS (t)952 2397 MS (a)975 2397 MS (l)1012 2397 MS (l)1035 2397 MS ( )1058 2397 MS (s)1079 2397 MS (h)1112 2397 MS (o)1153 2397 MS (r)1195 2397 MS (t)1223 2397 MS (c)1246 2397 MS (u)1283 2397 MS (t)1324 2397 MS (s)1348 2397 MS ( )1380 2397 MS (s)1401 2397 MS (o)1433 2397 MS ( )1475 2397 MS (t)1496 2397 MS (h)1519 2397 MS (a)1560 2397 MS (t)1598 2397 MS ( )1621 2397 MS (a)1642 2397 MS (l)1679 2397 MS (l)1702 2397 MS ( )1725 2397 MS (u)1746 2397 MS (s)1788 2397 MS (e)1820 2397 MS (r)1857 2397 MS (s)1885 2397 MS ( )1917 2397 MS (h)1938 2397 MS (a)1979 2397 MS (v)2017 2397 MS (e)2058 2397 MS ( )2095 2397 MS (t)2116 2397 MS (h)2140 2397 MS (e)2181 2397 MS (m)2219 2397 MS (:)2283 2397 MS (\()967 2588 MS (N)995 2588 MS (T)1055 2588 MS (\))1107 2588 MS (1)1267 2588 MS (.)1309 2588 MS (C)1417 2588 MS (r)1472 2588 MS (e)1500 2588 MS (a)1537 2588 MS (t)1574 2588 MS (e)1597 2588 MS ( )1634 2588 MS (d)1655 2588 MS (i)1697 2588 MS (r)1720 2588 MS (e)1748 2588 MS (c)1785 2588 MS (t)1822 2588 MS (o)1845 2588 MS (r)1887 2588 MS (y)1915 2588 MS ( )1955 2588 MS ( )1976 2588 MS ( )1997 2588 MS (P)2018 2588 MS (V)2065 2588 MS (M)2125 2588 MS ( )2199 2588 MS ( )2220 2588 MS (i)2241 2588 MS (n)2264 2588 MS ( )2305 2588 MS ( )2326 2588 MS ( )2347 2588 MS (C)2368 2588 MS (:)2423 2588 MS (\\)2447 2588 MS (W)2469 2588 MS (I)2548 2588 MS (N)2576 2588 MS (N)2636 2588 MS (T)2696 2588 MS (\\)2748 2588 MS (P)2770 2588 MS (r)2817 2588 MS (o)2845 2588 MS (f)2887 2588 MS (i)2914 2588 MS (l)2937 2588 MS (e)2960 2588 MS (s)2997 2588 MS (\\)3030 2588 MS (A)3053 2588 MS (l)3113 2588 MS (l)3136 2588 MS ( )3159 2588 MS (U)3180 2588 MS (s)3240 2588 MS (e)3272 2588 MS (r)3309 2588 MS (s)3338 2588 MS (\\)3371 2588 MS (S)3393 2588 MS (t)3439 2588 MS (a)3462 2588 MS (r)3499 2588 MS (t)3527 2588 MS ( )3550 2588 MS (M)3571 2588 MS (e)3645 2588 MS (n)3683 2588 MS (u)3724 2588 MS (\\)3766 2588 MS (P)3788 2588 MS (r)3835 2588 MS (o)3863 2588 MS (g)3905 2588 MS (r)3946 2588 MS (a)3974 2588 MS (m)4012 2588 MS (s)4076 2588 MS [83 0 0 -83 0 0]/Helvetica MF ( )1267 2684 MS [83 0 0 -83 0 0]/_Times-Roman MF (2)1267 2684 MS (.)1309 2684 MS (C)1417 2684 MS (r)1472 2684 MS (e)1500 2684 MS (a)1537 2684 MS (t)1574 2684 MS (e)1597 2684 MS ( )1634 2684 MS (a)1655 2684 MS ( )1692 2684 MS (s)1713 2684 MS (h)1745 2684 MS (o)1786 2684 MS (r)1828 2684 MS (t)1856 2684 MS (c)1879 2684 MS (u)1916 2684 MS (t)1958 2684 MS ( )1981 2684 MS (f)2002 2684 MS (o)2029 2684 MS (r)2071 2684 MS ( )2099 2684 MS ( )2120 2684 MS ( )2141 2684 MS ( )2162 2684 MS (C)2183 2684 MS (:)2238 2684 MS (\\)2262 2684 MS (P)2284 2684 MS (r)2331 2684 MS (o)2359 2684 MS (g)2401 2684 MS (r)2442 2684 MS (a)2470 2684 MS (m)2508 2684 MS ( )2571 2684 MS (F)2592 2684 MS (i)2638 2684 MS (l)2661 2684 MS (e)2684 2684 MS (s)2722 2684 MS (\\)2755 2684 MS (P)2777 2684 MS (V)2824 2684 MS (M)2884 2684 MS (3)2958 2684 MS (.)3000 2684 MS (4)3021 2684 MS (\\)3063 2684 MS (l)3085 2684 MS (i)3108 2684 MS (b)3131 2684 MS (\\)3174 2684 MS (W)3196 2684 MS (I)3275 2684 MS (N)3303 2684 MS (3)3363 2684 MS (2)3405 2684 MS (\\)3447 2684 MS (p)3469 2684 MS (v)3511 2684 MS (m)3553 2684 MS (.)3617 2684 MS (e)3638 2684 MS (x)3676 2684 MS (e)3717 2684 MS (3)1267 2780 MS (.)1309 2780 MS [83 0 0 -83 0 0]/Helvetica MF ( )1330 2780 MS [83 0 0 -83 0 0]/_Times-Roman MF (P)1417 2780 MS (l)1464 2780 MS (a)1487 2780 MS (c)1524 2780 MS (e)1561 2780 MS ( )1598 2780 MS (s)1619 2780 MS (h)1651 2780 MS (o)1692 2780 MS (r)1734 2780 MS (t)1762 2780 MS (c)1785 2780 MS (u)1822 2780 MS (t)1863 2780 MS ( )1886 2780 MS (i)1907 2780 MS (n)1930 2780 MS ( )1971 2780 MS (C)1993 2780 MS (:)2048 2780 MS (\\)2072 2780 MS (W)2094 2780 MS (I)2173 2780 MS (N)2201 2780 MS (N)2261 2780 MS (T)2321 2780 MS (\\)2373 2780 MS (P)2395 2780 MS (r)2442 2780 MS (o)2470 2780 MS (f)2512 2780 MS (i)2539 2780 MS (l)2562 2780 MS (e)2585 2780 MS (s)2622 2780 MS (\\)2654 2780 MS (A)2678 2780 MS (l)2738 2780 MS (l)2761 2780 MS ( )2784 2780 MS (U)2805 2780 MS (s)2865 2780 MS (e)2897 2780 MS (r)2934 2780 MS (s)2963 2780 MS (\\)2996 2780 MS (S)3018 2780 MS (t)3064 2780 MS (a)3087 2780 MS (r)3124 2780 MS (t)3152 2780 MS ( )3175 2780 MS (M)3196 2780 MS (e)3270 2780 MS (n)3308 2780 MS (u)3349 2780 MS (\\)3391 2780 MS (P)3413 2780 MS (r)3460 2780 MS (o)3488 2780 MS (g)3530 2780 MS (r)3571 2780 MS (a)3599 2780 MS (m)3637 2780 MS (s)3701 2780 MS (\\)3734 2780 MS (P)3756 2780 MS (V)3803 2780 MS (M)3863 2780 MS (4)1267 2876 MS (.)1309 2876 MS [83 0 0 -83 0 0]/Helvetica MF ( )1330 2876 MS [83 0 0 -83 0 0]/_Times-Roman MF (R)1417 2876 MS (e)1472 2876 MS (n)1509 2876 MS (a)1550 2876 MS (m)1588 2876 MS (e)1652 2876 MS ( )1689 2876 MS (s)1710 2876 MS (h)1743 2876 MS (o)1784 2876 MS (r)1826 2876 MS (t)1854 2876 MS (c)1877 2876 MS (u)1914 2876 MS (t)1955 2876 MS ( )1978 2876 MS ( )1999 2876 MS (\223)2021 2876 MS (P)2057 2876 MS (V)2104 2876 MS (M)2164 2876 MS ( )2238 2876 MS (C)2259 2876 MS (o)2314 2876 MS (n)2356 2876 MS (s)2398 2876 MS (o)2430 2876 MS (l)2472 2876 MS (e)2495 2876 MS (\224)2532 2876 MS (5)1267 2971 MS (.)1309 2971 MS [83 0 0 -83 0 0]/Helvetica MF ( )1330 2971 MS [83 0 0 -83 0 0]/_Times-Roman MF (C)1417 2971 MS (r)1472 2971 MS (e)1500 2971 MS (a)1537 2971 MS (t)1574 2971 MS (e)1597 2971 MS ( )1634 2971 MS (a)1655 2971 MS ( )1692 2971 MS (s)1713 2971 MS (h)1745 2971 MS (o)1786 2971 MS (r)1828 2971 MS (t)1856 2971 MS (c)1879 2971 MS (u)1916 2971 MS (t)1958 2971 MS ( )1981 2971 MS (f)2002 2971 MS (o)2029 2971 MS (r)2071 2971 MS ( )2099 2971 MS (C)2120 2971 MS (:)2175 2971 MS (\\)2199 2971 MS (P)2221 2971 MS (r)2268 2971 MS (o)2296 2971 MS (g)2338 2971 MS (r)2379 2971 MS (a)2407 2971 MS (m)2445 2971 MS ( )2508 2971 MS (F)2530 2971 MS (i)2576 2971 MS (l)2599 2971 MS (e)2622 2971 MS (s)2659 2971 MS (\\)2692 2971 MS (P)2714 2971 MS (V)2761 2971 MS (M)2821 2971 MS (3)2895 2971 MS (.)2937 2971 MS (4)2958 2971 MS (\\)3000 2971 MS (l)3023 2971 MS (i)3046 2971 MS (b)3069 2971 MS (\\)3112 2971 MS (W)3134 2971 MS (I)3213 2971 MS (N)3241 2971 MS (3)3301 2971 MS (2)3343 2971 MS (\\)3385 2971 MS (p)3407 2971 MS (v)3449 2971 MS (m)3491 2971 MS (d)3554 2971 MS (3)3596 2971 MS (.)3638 2971 MS (e)3659 2971 MS (x)3697 2971 MS (e)3738 2971 MS (6)1267 3067 MS (.)1309 3067 MS [83 0 0 -83 0 0]/Helvetica MF ( )1330 3067 MS [83 0 0 -83 0 0]/_Times-Roman MF (P)1417 3067 MS (l)1464 3067 MS (a)1487 3067 MS (c)1524 3067 MS (e)1561 3067 MS ( )1598 3067 MS (s)1619 3067 MS (h)1651 3067 MS (o)1692 3067 MS (r)1734 3067 MS (t)1762 3067 MS (c)1785 3067 MS (u)1822 3067 MS (t)1863 3067 MS ( )1886 3067 MS (i)1907 3067 MS (n)1930 3067 MS ( )1971 3067 MS (C)1993 3067 MS (:)2048 3067 MS (\\)2072 3067 MS (W)2094 3067 MS (I)2173 3067 MS (N)2201 3067 MS (N)2261 3067 MS (T)2321 3067 MS (\\)2373 3067 MS (P)2395 3067 MS (r)2442 3067 MS (o)2470 3067 MS (f)2512 3067 MS (i)2539 3067 MS (l)2562 3067 MS (e)2585 3067 MS (s)2622 3067 MS (\\)2655 3067 MS (A)2678 3067 MS (l)2738 3067 MS (l)2761 3067 MS ( )2784 3067 MS (U)2805 3067 MS (s)2865 3067 MS (e)2897 3067 MS (r)2934 3067 MS (s)2963 3067 MS (\\)2996 3067 MS (S)3018 3067 MS (t)3064 3067 MS (a)3087 3067 MS (r)3124 3067 MS (t)3152 3067 MS ( )3175 3067 MS (M)3196 3067 MS (e)3270 3067 MS (n)3308 3067 MS (u)3349 3067 MS (\\)3391 3067 MS (P)3413 3067 MS (r)3460 3067 MS (o)3488 3067 MS (g)3530 3067 MS (r)3571 3067 MS (a)3599 3067 MS (m)3637 3067 MS (s)3701 3067 MS (\\)3734 3067 MS (P)3756 3067 MS (V)3803 3067 MS (M)3863 3067 MS (7)1267 3163 MS (.)1309 3163 MS [83 0 0 -83 0 0]/Helvetica MF ( )1330 3163 MS [83 0 0 -83 0 0]/_Times-Roman MF (R)1417 3163 MS (e)1472 3163 MS (n)1509 3163 MS (a)1550 3163 MS (m)1588 3163 MS (e)1652 3163 MS ( )1689 3163 MS (s)1710 3163 MS (h)1743 3163 MS (o)1784 3163 MS (r)1826 3163 MS (t)1854 3163 MS (c)1877 3163 MS (u)1914 3163 MS (t)1955 3163 MS ( )1978 3163 MS ( )1999 3163 MS (\223)2021 3163 MS (P)2057 3163 MS (V)2104 3163 MS (M)2164 3163 MS ( )2238 3163 MS (D)2259 3163 MS (a)2319 3163 MS (e)2356 3163 MS (m)2393 3163 MS (o)2457 3163 MS (n)2500 3163 MS (\224)2541 3163 MS (8)1267 3259 MS (.)1309 3259 MS [83 0 0 -83 0 0]/Helvetica MF ( )1330 3259 MS [83 0 0 -83 0 0]/_Times-Roman MF (C)1417 3259 MS (r)1472 3259 MS (e)1500 3259 MS (a)1537 3259 MS (t)1574 3259 MS (e)1597 3259 MS ( )1634 3259 MS (a)1655 3259 MS ( )1692 3259 MS (s)1713 3259 MS (h)1745 3259 MS (o)1786 3259 MS (r)1828 3259 MS (t)1856 3259 MS (c)1879 3259 MS (u)1916 3259 MS (t)1958 3259 MS ( )1981 3259 MS (f)2002 3259 MS (o)2029 3259 MS (r)2071 3259 MS ( )2099 3259 MS (C)2120 3259 MS (:)2175 3259 MS (\\)2199 3259 MS (P)2221 3259 MS (r)2268 3259 MS (o)2296 3259 MS (g)2338 3259 MS (r)2379 3259 MS (a)2407 3259 MS (m)2445 3259 MS ( )2508 3259 MS (F)2530 3259 MS (i)2576 3259 MS (l)2599 3259 MS (e)2622 3259 MS (s)2659 3259 MS (\\)2692 3259 MS (P)2714 3259 MS (V)2761 3259 MS (M)2821 3259 MS (3)2895 3259 MS (.)2937 3259 MS (4)2958 3259 MS (\\)3000 3259 MS (m)3023 3259 MS (a)3087 3259 MS (n)3125 3259 MS (\\)3167 3259 MS (W)3189 3259 MS (I)3268 3259 MS (N)3296 3259 MS (3)3356 3259 MS (2)3398 3259 MS (\\)3440 3259 MS (P)3462 3259 MS (v)3509 3259 MS (m)3551 3259 MS (h)3615 3259 MS (e)3657 3259 MS (l)3694 3259 MS (p)3717 3259 MS (.)3759 3259 MS (h)3780 3259 MS (l)3821 3259 MS (p)3844 3259 MS (9)1267 3355 MS (.)1309 3355 MS [83 0 0 -83 0 0]/Helvetica MF ( )1330 3355 MS [83 0 0 -83 0 0]/_Times-Roman MF (P)1417 3355 MS (l)1464 3355 MS (a)1487 3355 MS (c)1524 3355 MS (e)1561 3355 MS ( )1598 3355 MS (s)1619 3355 MS (h)1651 3355 MS (o)1692 3355 MS (r)1734 3355 MS (t)1762 3355 MS (c)1785 3355 MS (u)1822 3355 MS (t)1863 3355 MS ( )1886 3355 MS (i)1907 3355 MS (n)1930 3355 MS ( )1971 3355 MS (C)1993 3355 MS (:)2048 3355 MS (\\)2072 3355 MS (W)2094 3355 MS (I)2173 3355 MS (N)2201 3355 MS (N)2261 3355 MS (T)2321 3355 MS (\\)2373 3355 MS (P)2395 3355 MS (r)2442 3355 MS (o)2470 3355 MS (f)2512 3355 MS (i)2539 3355 MS (l)2562 3355 MS (e)2585 3355 MS (s)2622 3355 MS (\\)2655 3355 MS (A)2678 3355 MS (l)2738 3355 MS (l)2761 3355 MS ( )2784 3355 MS (U)2805 3355 MS (s)2865 3355 MS (e)2897 3355 MS (r)2934 3355 MS (s)2963 3355 MS (\\)2996 3355 MS (S)3018 3355 MS (t)3064 3355 MS (a)3087 3355 MS (r)3124 3355 MS (t)3152 3355 MS ( )3175 3355 MS (M)3196 3355 MS (e)3270 3355 MS (n)3308 3355 MS (u)3349 3355 MS (\\)3391 3355 MS (P)3413 3355 MS (r)3460 3355 MS (o)3488 3355 MS (g)3530 3355 MS (r)3571 3355 MS (a)3599 3355 MS (m)3637 3355 MS (s)3701 3355 MS (\\)3734 3355 MS (P)3756 3355 MS (V)3803 3355 MS (M)3863 3355 MS (1)1267 3451 MS (0)1309 3451 MS (.)1351 3451 MS [83 0 0 -83 0 0]/Helvetica MF ( )1372 3451 MS [83 0 0 -83 0 0]/_Times-Roman MF (R)1417 3451 MS (e)1472 3451 MS (n)1509 3451 MS (a)1550 3451 MS (m)1588 3451 MS (e)1652 3451 MS ( )1689 3451 MS (s)1710 3451 MS (h)1743 3451 MS (o)1784 3451 MS (r)1826 3451 MS (t)1854 3451 MS (c)1877 3451 MS (u)1914 3451 MS (t)1955 3451 MS ( )1978 3451 MS ( )1999 3451 MS (\223)2021 3451 MS (P)2057 3451 MS (V)2104 3451 MS (M)2164 3451 MS ( )2238 3451 MS (H)2259 3451 MS (e)2319 3451 MS (l)2356 3451 MS (p)2379 3451 MS (\224)2421 3451 MS (\()967 3642 MS (9)995 3642 MS (5)1037 3642 MS (/)1079 3642 MS (9)1102 3642 MS (8)1144 3642 MS (\))1185 3642 MS (1)1267 3642 MS (.)1309 3642 MS (C)1417 3642 MS (r)1472 3642 MS (e)1500 3642 MS (a)1537 3642 MS (t)1574 3642 MS (e)1597 3642 MS ( )1634 3642 MS (d)1655 3642 MS (i)1697 3642 MS (r)1720 3642 MS (e)1748 3642 MS (c)1785 3642 MS (t)1822 3642 MS (o)1845 3642 MS (r)1887 3642 MS (y)1915 3642 MS ( )1955 3642 MS ( )1976 3642 MS ( )1997 3642 MS (P)2018 3642 MS (V)2065 3642 MS (M)2125 3642 MS ( )2199 3642 MS ( )2220 3642 MS (i)2241 3642 MS (n)2264 3642 MS ( )2305 3642 MS ( )2326 3642 MS ( )2347 3642 MS (C)2368 3642 MS (:)2423 3642 MS (\\)2447 3642 MS (W)2469 3642 MS (I)2548 3642 MS (N)2576 3642 MS (D)2636 3642 MS (O)2696 3642 MS (W)2756 3642 MS (S)2835 3642 MS (\\)2882 3642 MS (S)2905 3642 MS (t)2951 3642 MS (a)2974 3642 MS (r)3011 3642 MS (t)3039 3642 MS ( )3062 3642 MS (M)3083 3642 MS (e)3157 3642 MS (n)3194 3642 MS (u)3236 3642 MS (\\)3278 3642 MS (P)3300 3642 MS (r)3347 3642 MS (o)3375 3642 MS (g)3417 3642 MS (r)3458 3642 MS (a)3486 3642 MS (m)3524 3642 MS (s)3588 3642 MS (2)1267 3738 MS (.)1309 3738 MS (C)1417 3738 MS (r)1472 3738 MS (e)1500 3738 MS (a)1537 3738 MS (t)1574 3738 MS (e)1597 3738 MS ( )1634 3738 MS (a)1655 3738 MS ( )1692 3738 MS (s)1713 3738 MS (h)1745 3738 MS (o)1786 3738 MS (r)1828 3738 MS (t)1856 3738 MS (c)1879 3738 MS (u)1916 3738 MS (t)1958 3738 MS ( )1981 3738 MS (f)2002 3738 MS (o)2029 3738 MS (r)2071 3738 MS ( )2099 3738 MS ( )2120 3738 MS ( )2141 3738 MS ( )2162 3738 MS (C)2183 3738 MS (:)2238 3738 MS (\\)2262 3738 MS (P)2284 3738 MS (r)2331 3738 MS (o)2359 3738 MS (g)2401 3738 MS (r)2442 3738 MS (a)2470 3738 MS (m)2508 3738 MS ( )2571 3738 MS (F)2592 3738 MS (i)2638 3738 MS (l)2661 3738 MS (e)2684 3738 MS (s)2722 3738 MS (\\)2755 3738 MS (P)2777 3738 MS (V)2824 3738 MS (M)2884 3738 MS (3)2958 3738 MS (.)3000 3738 MS (4)3021 3738 MS (\\)3063 3738 MS (l)3085 3738 MS (i)3108 3738 MS (b)3131 3738 MS (\\)3174 3738 MS (W)3196 3738 MS (I)3275 3738 MS (N)3303 3738 MS (3)3363 3738 MS (2)3405 3738 MS (\\)3447 3738 MS (p)3469 3738 MS (v)3511 3738 MS (m)3553 3738 MS (.)3617 3738 MS (e)3638 3738 MS (x)3676 3738 MS (e)3717 3738 MS (3)1267 3834 MS (.)1309 3834 MS (P)1417 3834 MS (l)1464 3834 MS (a)1487 3834 MS (c)1524 3834 MS (e)1561 3834 MS ( )1598 3834 MS (s)1619 3834 MS (h)1651 3834 MS (o)1692 3834 MS (r)1734 3834 MS (t)1762 3834 MS (c)1785 3834 MS (u)1822 3834 MS (t)1863 3834 MS ( )1886 3834 MS (i)1907 3834 MS (n)1930 3834 MS ( )1971 3834 MS (C)1993 3834 MS (:)2048 3834 MS (\\)2072 3834 MS (W)2094 3834 MS (I)2173 3834 MS (N)2201 3834 MS (D)2261 3834 MS (O)2321 3834 MS (W)2381 3834 MS (S)2460 3834 MS (\\)2507 3834 MS (S)2530 3834 MS (t)2576 3834 MS (a)2599 3834 MS (r)2636 3834 MS (t)2664 3834 MS ( )2687 3834 MS (M)2708 3834 MS (e)2782 3834 MS (n)2819 3834 MS (u)2861 3834 MS (\\)2903 3834 MS (P)2925 3834 MS (r)2972 3834 MS (o)3000 3834 MS (g)3042 3834 MS (r)3083 3834 MS (a)3111 3834 MS (m)3149 3834 MS (s)3213 3834 MS ( )3245 3834 MS (\\)3267 3834 MS (P)3289 3834 MS (V)3336 3834 MS (M)3396 3834 MS (4)1267 3930 MS (.)1309 3930 MS [83 0 0 -83 0 0]/Helvetica MF ( )1330 3930 MS [83 0 0 -83 0 0]/_Times-Roman MF (R)1417 3930 MS (e)1472 3930 MS (n)1509 3930 MS (a)1550 3930 MS (m)1588 3930 MS (e)1652 3930 MS ( )1689 3930 MS (s)1710 3930 MS (h)1743 3930 MS (o)1784 3930 MS (r)1826 3930 MS (t)1854 3930 MS (c)1877 3930 MS (u)1914 3930 MS (t)1955 3930 MS ( )1978 3930 MS ( )1999 3930 MS (\223)2021 3930 MS (P)2057 3930 MS (V)2104 3930 MS (M)2164 3930 MS ( )2238 3930 MS (C)2259 3930 MS (o)2314 3930 MS (n)2356 3930 MS (s)2398 3930 MS (o)2430 3930 MS (l)2472 3930 MS (e)2495 3930 MS (\224)2532 3930 MS (5)1267 4026 MS (.)1309 4026 MS [83 0 0 -83 0 0]/Helvetica MF ( )1330 4026 MS [83 0 0 -83 0 0]/_Times-Roman MF (C)1417 4026 MS (r)1472 4026 MS (e)1500 4026 MS (a)1537 4026 MS (t)1574 4026 MS (e)1597 4026 MS ( )1634 4026 MS (a)1655 4026 MS ( )1692 4026 MS (s)1713 4026 MS (h)1745 4026 MS (o)1786 4026 MS (r)1828 4026 MS (t)1856 4026 MS (c)1879 4026 MS (u)1916 4026 MS (t)1958 4026 MS ( )1981 4026 MS (f)2002 4026 MS (o)2029 4026 MS (r)2071 4026 MS ( )2099 4026 MS (C)2120 4026 MS (:)2175 4026 MS (\\)2199 4026 MS (P)2221 4026 MS (r)2268 4026 MS (o)2296 4026 MS (g)2338 4026 MS (r)2379 4026 MS (a)2407 4026 MS (m)2445 4026 MS ( )2508 4026 MS (F)2530 4026 MS (i)2576 4026 MS (l)2599 4026 MS (e)2622 4026 MS (s)2659 4026 MS (\\)2692 4026 MS (P)2714 4026 MS (V)2761 4026 MS (M)2821 4026 MS (3)2895 4026 MS (.)2937 4026 MS (4)2958 4026 MS (\\)3000 4026 MS (l)3023 4026 MS (i)3046 4026 MS (b)3069 4026 MS (\\)3112 4026 MS (W)3134 4026 MS (I)3213 4026 MS (N)3241 4026 MS (3)3301 4026 MS (2)3343 4026 MS (\\)3385 4026 MS (p)3407 4026 MS (v)3449 4026 MS (m)3491 4026 MS (d)3554 4026 MS (3)3596 4026 MS (.)3638 4026 MS (e)3659 4026 MS (x)3697 4026 MS (e)3738 4026 MS (6)1267 4121 MS (.)1309 4121 MS [83 0 0 -83 0 0]/Helvetica MF ( )1330 4121 MS [83 0 0 -83 0 0]/_Times-Roman MF (P)1417 4121 MS (l)1464 4121 MS (a)1487 4121 MS (c)1524 4121 MS (e)1561 4121 MS ( )1598 4121 MS (s)1619 4121 MS (h)1651 4121 MS (o)1692 4121 MS (r)1734 4121 MS (t)1762 4121 MS (c)1785 4121 MS (u)1822 4121 MS (t)1863 4121 MS ( )1886 4121 MS (i)1907 4121 MS (n)1930 4121 MS ( )1971 4121 MS (C)1993 4121 MS (:)2048 4121 MS (\\)2072 4121 MS (W)2094 4121 MS (I)2173 4121 MS (N)2201 4121 MS (D)2261 4121 MS (O)2321 4121 MS (W)2381 4121 MS (S)2460 4121 MS (\\)2507 4121 MS (S)2530 4121 MS (t)2576 4121 MS (a)2599 4121 MS (r)2636 4121 MS (t)2664 4121 MS ( )2687 4121 MS (M)2708 4121 MS (e)2782 4121 MS (n)2819 4121 MS (u)2861 4121 MS (\\)2903 4121 MS (P)2925 4121 MS (r)2972 4121 MS (o)3000 4121 MS (g)3042 4121 MS (r)3083 4121 MS (a)3111 4121 MS (m)3149 4121 MS (s)3213 4121 MS ( )3245 4121 MS (\\)3267 4121 MS (P)3289 4121 MS (V)3336 4121 MS (M)3396 4121 MS (7)1267 4217 MS (.)1309 4217 MS [83 0 0 -83 0 0]/Helvetica MF ( )1330 4217 MS [83 0 0 -83 0 0]/_Times-Roman MF (R)1417 4217 MS (e)1472 4217 MS (n)1509 4217 MS (a)1550 4217 MS (m)1588 4217 MS (e)1652 4217 MS ( )1689 4217 MS (s)1710 4217 MS (h)1743 4217 MS (o)1784 4217 MS (r)1826 4217 MS (t)1854 4217 MS (c)1877 4217 MS (u)1914 4217 MS (t)1955 4217 MS ( )1978 4217 MS ( )1999 4217 MS (\223)2021 4217 MS (P)2057 4217 MS (V)2104 4217 MS (M)2164 4217 MS ( )2238 4217 MS (D)2259 4217 MS (a)2319 4217 MS (e)2356 4217 MS (m)2393 4217 MS (o)2457 4217 MS (n)2500 4217 MS (\224)2541 4217 MS (8)1267 4313 MS (.)1309 4313 MS [83 0 0 -83 0 0]/Helvetica MF ( )1330 4313 MS [83 0 0 -83 0 0]/_Times-Roman MF (C)1417 4313 MS (r)1472 4313 MS (e)1500 4313 MS (a)1537 4313 MS (t)1574 4313 MS (e)1597 4313 MS ( )1634 4313 MS (a)1655 4313 MS ( )1692 4313 MS (s)1713 4313 MS (h)1745 4313 MS (o)1786 4313 MS (r)1828 4313 MS (t)1856 4313 MS (c)1879 4313 MS (u)1916 4313 MS (t)1958 4313 MS ( )1981 4313 MS (f)2002 4313 MS (o)2029 4313 MS (r)2071 4313 MS ( )2099 4313 MS (C)2120 4313 MS (:)2175 4313 MS (\\)2199 4313 MS (P)2221 4313 MS (r)2268 4313 MS (o)2296 4313 MS (g)2338 4313 MS (r)2379 4313 MS (a)2407 4313 MS (m)2445 4313 MS ( )2508 4313 MS (F)2530 4313 MS (i)2576 4313 MS (l)2599 4313 MS (e)2622 4313 MS (s)2659 4313 MS (\\)2692 4313 MS (P)2714 4313 MS (V)2761 4313 MS (M)2821 4313 MS (3)2895 4313 MS (.)2937 4313 MS (4)2958 4313 MS (\\)3000 4313 MS (m)3023 4313 MS (a)3087 4313 MS (n)3125 4313 MS (\\)3167 4313 MS (W)3189 4313 MS (I)3268 4313 MS (N)3296 4313 MS (3)3356 4313 MS (2)3398 4313 MS (\\)3440 4313 MS (P)3462 4313 MS (v)3509 4313 MS (m)3551 4313 MS (h)3615 4313 MS (e)3657 4313 MS (l)3694 4313 MS (p)3717 4313 MS (.)3759 4313 MS (h)3780 4313 MS (l)3821 4313 MS (p)3844 4313 MS (9)1267 4409 MS (.)1309 4409 MS [83 0 0 -83 0 0]/Helvetica MF ( )1330 4409 MS [83 0 0 -83 0 0]/_Times-Roman MF (P)1417 4409 MS (l)1464 4409 MS (a)1487 4409 MS (c)1524 4409 MS (e)1561 4409 MS ( )1598 4409 MS (s)1619 4409 MS (h)1651 4409 MS (o)1692 4409 MS (r)1734 4409 MS (t)1762 4409 MS (c)1785 4409 MS (u)1822 4409 MS (t)1863 4409 MS ( )1886 4409 MS (i)1907 4409 MS (n)1930 4409 MS ( )1971 4409 MS (C)1993 4409 MS (:)2048 4409 MS (\\)2072 4409 MS (W)2094 4409 MS (I)2173 4409 MS (N)2201 4409 MS (D)2261 4409 MS (O)2321 4409 MS (W)2381 4409 MS (S)2460 4409 MS (\\)2507 4409 MS (S)2530 4409 MS (t)2576 4409 MS (a)2599 4409 MS (r)2636 4409 MS (t)2664 4409 MS ( )2687 4409 MS (M)2708 4409 MS (e)2782 4409 MS (n)2819 4409 MS (u)2861 4409 MS (\\)2903 4409 MS (P)2925 4409 MS (r)2972 4409 MS (o)3000 4409 MS (g)3042 4409 MS (r)3083 4409 MS (a)3111 4409 MS (m)3149 4409 MS (s)3213 4409 MS ( )3245 4409 MS (\\)3267 4409 MS (P)3289 4409 MS (V)3336 4409 MS (M)3396 4409 MS (1)1267 4505 MS (0)1309 4505 MS (.)1351 4505 MS [83 0 0 -83 0 0]/Helvetica MF ( )1372 4505 MS [83 0 0 -83 0 0]/_Times-Roman MF (R)1417 4505 MS (e)1472 4505 MS (n)1509 4505 MS (a)1550 4505 MS (m)1588 4505 MS (e)1652 4505 MS ( )1689 4505 MS (s)1710 4505 MS (h)1743 4505 MS (o)1784 4505 MS (r)1826 4505 MS (t)1854 4505 MS (c)1877 4505 MS (u)1914 4505 MS (t)1955 4505 MS ( )1978 4505 MS ( )1999 4505 MS (\223)2021 4505 MS (P)2057 4505 MS (V)2104 4505 MS (M)2164 4505 MS ( )2238 4505 MS (H)2259 4505 MS (e)2319 4505 MS (l)2356 4505 MS (p)2379 4505 MS (\224)2421 4505 MS showpage %%Page: 3 3 13.238 780.059 translate 72 600 div dup neg scale 0 0 transform .25 add round .25 sub exch .25 add round .25 sub exch itransform translate [83 0 0 -83 0 0]/Times-Roman MF (\()592 576 MS (B)620 576 MS (\))676 576 MS [83 0 0 -83 0 0]/Helvetica MF ( )704 576 MS [83 0 0 -83 0 0]/Times-Roman MF (T)742 576 MS (o)794 576 MS ( )835 576 MS (i)856 576 MS (n)879 576 MS (s)920 576 MS (t)952 576 MS (a)975 576 MS (l)1012 576 MS (l)1035 576 MS ( )1058 576 MS (s)1079 576 MS (h)1112 576 MS (o)1153 576 MS (r)1195 576 MS (t)1223 576 MS (c)1246 576 MS (u)1283 576 MS (t)1324 576 MS (s)1348 576 MS ( )1380 576 MS (s)1401 576 MS (o)1433 576 MS ( )1475 576 MS (t)1496 576 MS (h)1519 576 MS (a)1560 576 MS (t)1598 576 MS ( )1621 576 MS (o)1642 576 MS (n)1684 576 MS (l)1725 576 MS (y)1748 576 MS ( )1789 576 MS (a)1810 576 MS (n)1848 576 MS ( )1889 576 MS (i)1910 576 MS (n)1934 576 MS (d)1975 576 MS (i)2017 576 MS (v)2040 576 MS (i)2081 576 MS (d)2104 576 MS (u)2147 576 MS (a)2188 576 MS (l)2225 576 MS ( )2248 576 MS (h)2269 576 MS (a)2310 576 MS (s)2348 576 MS ( )2380 576 MS (t)2401 576 MS (h)2425 576 MS (e)2466 576 MS (m)2504 576 MS (:)2567 576 MS (\()967 767 MS (N)995 767 MS (T)1055 767 MS (\))1107 767 MS (1)1267 767 MS (.)1309 767 MS (C)1417 767 MS (r)1472 767 MS (e)1500 767 MS (a)1537 767 MS (t)1574 767 MS (e)1597 767 MS ( )1634 767 MS (d)1655 767 MS (i)1697 767 MS (r)1720 767 MS (e)1748 767 MS (c)1785 767 MS (t)1822 767 MS (o)1845 767 MS (r)1887 767 MS (y)1915 767 MS ( )1955 767 MS ( )1976 767 MS ( )1997 767 MS (P)2018 767 MS (V)2065 767 MS (M)2125 767 MS ( )2199 767 MS ( )2220 767 MS (i)2241 767 MS (n)2264 767 MS ( )2305 767 MS (C)2326 767 MS (:)2381 767 MS (\\)2405 767 MS (W)2427 767 MS (I)2506 767 MS (N)2534 767 MS (N)2594 767 MS (T)2654 767 MS (\\)2706 767 MS (P)2728 767 MS (r)2775 767 MS (o)2803 767 MS (f)2845 767 MS (i)2872 767 MS (l)2895 767 MS (e)2918 767 MS (s)2956 767 MS (\\)2989 767 MS (<)3011 767 MS (u)3058 767 MS (s)3100 767 MS (e)3132 767 MS (r)3169 767 MS (n)3197 767 MS (a)3238 767 MS (m)3276 767 MS (e)3340 767 MS (>)3377 767 MS (\\)3425 767 MS (S)3447 767 MS (t)3494 767 MS (a)3517 767 MS (r)3554 767 MS (t)3582 767 MS ( )3605 767 MS (M)3626 767 MS (e)3700 767 MS (n)3737 767 MS (u)3779 767 MS (\\)3821 767 MS (P)3843 767 MS (r)3890 767 MS (o)3918 767 MS (g)3960 767 MS (r)4001 767 MS (a)4029 767 MS (m)4067 767 MS (s)4130 767 MS [83 0 0 -83 0 0]/Helvetica MF ( )1267 863 MS [83 0 0 -83 0 0]/Times-Roman MF (2)1267 863 MS (.)1309 863 MS (C)1417 863 MS (r)1472 863 MS (e)1500 863 MS (a)1537 863 MS (t)1574 863 MS (e)1597 863 MS ( )1634 863 MS (a)1655 863 MS ( )1692 863 MS (s)1713 863 MS (h)1745 863 MS (o)1786 863 MS (r)1828 863 MS (t)1856 863 MS (c)1879 863 MS (u)1916 863 MS (t)1958 863 MS ( )1981 863 MS (f)2002 863 MS (o)2029 863 MS (r)2071 863 MS ( )2099 863 MS ( )2120 863 MS ( )2141 863 MS ( )2162 863 MS (C)2183 863 MS (:)2238 863 MS (\\)2262 863 MS (P)2284 863 MS (r)2331 863 MS (o)2359 863 MS (g)2401 863 MS (r)2442 863 MS (a)2470 863 MS (m)2508 863 MS ( )2571 863 MS (F)2592 863 MS (i)2638 863 MS (l)2661 863 MS (e)2684 863 MS (s)2722 863 MS (\\)2755 863 MS (P)2777 863 MS (V)2824 863 MS (M)2884 863 MS (3)2958 863 MS (.)3000 863 MS (4)3021 863 MS (\\)3063 863 MS (l)3085 863 MS (i)3108 863 MS (b)3131 863 MS (\\)3174 863 MS (W)3196 863 MS (I)3275 863 MS (N)3303 863 MS (3)3363 863 MS (2)3405 863 MS (\\)3447 863 MS (p)3469 863 MS (v)3511 863 MS (m)3553 863 MS (.)3617 863 MS (e)3638 863 MS (x)3676 863 MS (e)3717 863 MS [83 0 0 -83 0 0]/Helvetica MF ( )1267 959 MS [83 0 0 -83 0 0]/Times-Roman MF (3)1267 959 MS (.)1309 959 MS (P)1417 959 MS (l)1464 959 MS (a)1487 959 MS (c)1524 959 MS (e)1561 959 MS ( )1598 959 MS (s)1619 959 MS (h)1651 959 MS (o)1692 959 MS (r)1734 959 MS (t)1762 959 MS (c)1785 959 MS (u)1822 959 MS (t)1863 959 MS ( )1886 959 MS (i)1907 959 MS (n)1930 959 MS ( )1971 959 MS (C)1993 959 MS (:)2048 959 MS (\\)2072 959 MS (W)2094 959 MS (I)2173 959 MS (N)2201 959 MS (N)2261 959 MS (T)2321 959 MS (\\)2373 959 MS (P)2395 959 MS (r)2442 959 MS (o)2470 959 MS (f)2512 959 MS (i)2539 959 MS (l)2562 959 MS (e)2585 959 MS (s)2622 959 MS (\\)2655 959 MS (<)2677 959 MS (u)2725 959 MS (s)2767 959 MS (e)2799 959 MS (r)2836 959 MS (n)2864 959 MS (a)2905 959 MS (m)2943 959 MS (e)3007 959 MS (>)3044 959 MS (\\)3092 959 MS (S)3114 959 MS (t)3160 959 MS (a)3183 959 MS (r)3220 959 MS (t)3248 959 MS ( )3271 959 MS (M)3292 959 MS (e)3366 959 MS (n)3404 959 MS (u)3445 959 MS (\\)3487 959 MS (P)3509 959 MS (r)3556 959 MS (o)3584 959 MS (g)3626 959 MS (r)3667 959 MS (a)3695 959 MS (m)3733 959 MS (s)3797 959 MS ( )3829 959 MS (\\)3850 959 MS (P)3873 959 MS (V)3920 959 MS (M)3980 959 MS [83 0 0 -83 0 0]/Helvetica MF ( )1267 1055 MS [83 0 0 -83 0 0]/Times-Roman MF (4)1267 1055 MS (.)1309 1055 MS /IsChar{exch/CharStrings get exch known}bd/MapCh{3 -1 roll/Encoding get 3 1 roll put}bd/MapDegree{dup 16#b0 exch/degree IsChar{/degree}{/ring}ifelse MapCh} bd/MapBB{dup 16#a6 exch/brokenbar IsChar{/brokenbar}{/bar}ifelse MapCh}bd /reencode{findfont begin currentdict dup length dict begin{1 index/FID ne{def} {pop pop}ifelse}forall/FontName exch def dup length 0 ne{/Encoding Encoding 256 array copy def 0 exch{dup type/nametype eq{Encoding 2 index 2 index put pop 1 add}{exch pop}ifelse}forall}if pop currentdict dup end end/FontName get exch definefont dup MapDegree MapBB}bd/LATENC[0/grave/acute/circumflex/tilde/macron /breve/dotaccent/dieresis/ring/cedilla/hungarumlaut/ogonek/caron/dotlessi/fi/fl /Lslash/lslash/Zcaron/zcaron/minus/.notdef/.notdef/.notdef/.notdef/.notdef /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space/exclam/quotedbl /numbersign/dollar/percent/ampersand/quotesingle/parenleft/parenright/asterisk /plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight /nine/colon/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M /N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/asciicircum /underscore/grave/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft /bar/braceright/asciitilde/.notdef/.notdef/.notdef/quotesinglbase/florin /quotedblbase/ellipsis/dagger/daggerdbl/circumflex/perthousand/Scaron /guilsinglleft/OE/.notdef/.notdef/.notdef/.notdef/quoteleft/quoteright /quotedblleft/quotedblright/bullet/endash/emdash/tilde/trademark/scaron /guilsinglright/oe/.notdef/.notdef/Ydieresis/.notdef/exclamdown/cent/sterling /currency/yen/brokenbar/section/dieresis/copyright/ordfeminine/guillemotleft /logicalnot/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior /acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine /guillemotright/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute /Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex /Edieresis/Igrave/Iacute/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute /Ocircumflex/Otilde/Odieresis/multiply/Oslash/Ugrave/Uacute/Ucircumflex /Udieresis/Yacute/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis /aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave/iacute /icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis /divide/oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def LATENC /_Times-Roman /Times-Roman reencode [83 0 0 -83 0 0]/_Times-Roman MF (R)1417 1055 MS (e)1472 1055 MS (n)1509 1055 MS (a)1550 1055 MS (m)1588 1055 MS (e)1652 1055 MS ( )1689 1055 MS (s)1710 1055 MS (h)1743 1055 MS (o)1784 1055 MS (r)1826 1055 MS (t)1854 1055 MS (c)1877 1055 MS (u)1914 1055 MS (t)1955 1055 MS ( )1978 1055 MS ( )1999 1055 MS (\223)2021 1055 MS (P)2057 1055 MS (V)2104 1055 MS (M)2164 1055 MS ( )2238 1055 MS (C)2259 1055 MS (o)2314 1055 MS (n)2356 1055 MS (s)2398 1055 MS (o)2430 1055 MS (l)2472 1055 MS (e)2495 1055 MS (\224)2532 1055 MS [83 0 0 -83 0 0]/Helvetica MF ( )1267 1151 MS [83 0 0 -83 0 0]/_Times-Roman MF (5)1267 1151 MS (.)1309 1151 MS (C)1417 1151 MS (r)1472 1151 MS (e)1500 1151 MS (a)1537 1151 MS (t)1574 1151 MS (e)1597 1151 MS ( )1634 1151 MS (a)1655 1151 MS ( )1692 1151 MS (s)1713 1151 MS (h)1745 1151 MS (o)1786 1151 MS (r)1828 1151 MS (t)1856 1151 MS (c)1879 1151 MS (u)1916 1151 MS (t)1958 1151 MS ( )1981 1151 MS (f)2002 1151 MS (o)2029 1151 MS (r)2071 1151 MS ( )2099 1151 MS (C)2120 1151 MS (:)2175 1151 MS (\\)2199 1151 MS (P)2221 1151 MS (r)2268 1151 MS (o)2296 1151 MS (g)2338 1151 MS (r)2379 1151 MS (a)2407 1151 MS (m)2445 1151 MS ( )2508 1151 MS (F)2530 1151 MS (i)2576 1151 MS (l)2599 1151 MS (e)2622 1151 MS (s)2659 1151 MS (\\)2692 1151 MS (P)2714 1151 MS (V)2761 1151 MS (M)2821 1151 MS (3)2895 1151 MS (.)2937 1151 MS (4)2958 1151 MS (\\)3000 1151 MS (l)3023 1151 MS (i)3046 1151 MS (b)3069 1151 MS (\\)3112 1151 MS (W)3134 1151 MS (I)3213 1151 MS (N)3241 1151 MS (3)3301 1151 MS (2)3343 1151 MS (\\)3385 1151 MS (p)3407 1151 MS (v)3449 1151 MS (m)3491 1151 MS (d)3554 1151 MS (3)3596 1151 MS (.)3638 1151 MS (e)3659 1151 MS (x)3697 1151 MS (e)3738 1151 MS [83 0 0 -83 0 0]/Helvetica MF ( )1267 1247 MS [83 0 0 -83 0 0]/_Times-Roman MF (6)1267 1247 MS (.)1309 1247 MS (P)1417 1247 MS (l)1464 1247 MS (a)1487 1247 MS (c)1524 1247 MS (e)1561 1247 MS ( )1598 1247 MS (s)1619 1247 MS (h)1651 1247 MS (o)1692 1247 MS (r)1734 1247 MS (t)1762 1247 MS (c)1785 1247 MS (u)1822 1247 MS (t)1863 1247 MS ( )1886 1247 MS (i)1907 1247 MS (n)1930 1247 MS ( )1971 1247 MS (C)1993 1247 MS (:)2048 1247 MS (\\)2072 1247 MS (W)2094 1247 MS (I)2173 1247 MS (N)2201 1247 MS (N)2261 1247 MS (T)2321 1247 MS (\\)2373 1247 MS (P)2395 1247 MS (r)2442 1247 MS (o)2470 1247 MS (f)2512 1247 MS (i)2539 1247 MS (l)2562 1247 MS (e)2585 1247 MS (s)2622 1247 MS (\\)2655 1247 MS (<)2677 1247 MS (u)2725 1247 MS (s)2767 1247 MS (e)2799 1247 MS (r)2836 1247 MS (n)2864 1247 MS (a)2905 1247 MS (m)2943 1247 MS (e)3007 1247 MS (>)3044 1247 MS (\\)3092 1247 MS (S)3114 1247 MS (t)3160 1247 MS (a)3183 1247 MS (r)3220 1247 MS (t)3248 1247 MS ( )3271 1247 MS (M)3292 1247 MS (e)3366 1247 MS (n)3404 1247 MS (u)3445 1247 MS (\\)3487 1247 MS (P)3509 1247 MS (r)3556 1247 MS (o)3584 1247 MS (g)3626 1247 MS (r)3667 1247 MS (a)3695 1247 MS (m)3733 1247 MS (s)3797 1247 MS ( )3829 1247 MS (\\)3850 1247 MS (P)3873 1247 MS (V)3920 1247 MS (M)3980 1247 MS [83 0 0 -83 0 0]/Helvetica MF ( )1267 1342 MS [83 0 0 -83 0 0]/_Times-Roman MF (7)1267 1342 MS (.)1309 1342 MS (R)1417 1342 MS (e)1472 1342 MS (n)1509 1342 MS (a)1550 1342 MS (m)1588 1342 MS (e)1652 1342 MS ( )1689 1342 MS (s)1710 1342 MS (h)1743 1342 MS (o)1784 1342 MS (r)1826 1342 MS (t)1854 1342 MS (c)1877 1342 MS (u)1914 1342 MS (t)1955 1342 MS ( )1978 1342 MS ( )1999 1342 MS (\223)2021 1342 MS (P)2057 1342 MS (V)2104 1342 MS (M)2164 1342 MS ( )2238 1342 MS (D)2259 1342 MS (a)2319 1342 MS (e)2356 1342 MS (m)2393 1342 MS (o)2457 1342 MS (n)2500 1342 MS (\224)2541 1342 MS [83 0 0 -83 0 0]/Helvetica MF ( )1267 1438 MS [83 0 0 -83 0 0]/_Times-Roman MF (8)1267 1438 MS (.)1309 1438 MS (C)1417 1438 MS (r)1472 1438 MS (e)1500 1438 MS (a)1537 1438 MS (t)1574 1438 MS (e)1597 1438 MS ( )1634 1438 MS (a)1655 1438 MS ( )1692 1438 MS (s)1713 1438 MS (h)1745 1438 MS (o)1786 1438 MS (r)1828 1438 MS (t)1856 1438 MS (c)1879 1438 MS (u)1916 1438 MS (t)1958 1438 MS ( )1981 1438 MS (f)2002 1438 MS (o)2029 1438 MS (r)2071 1438 MS ( )2099 1438 MS (C)2120 1438 MS (:)2175 1438 MS (\\)2199 1438 MS (P)2221 1438 MS (r)2268 1438 MS (o)2296 1438 MS (g)2338 1438 MS (r)2379 1438 MS (a)2407 1438 MS (m)2445 1438 MS ( )2508 1438 MS (F)2530 1438 MS (i)2576 1438 MS (l)2599 1438 MS (e)2622 1438 MS (s)2659 1438 MS (\\)2692 1438 MS (P)2714 1438 MS (V)2761 1438 MS (M)2821 1438 MS (3)2895 1438 MS (.)2937 1438 MS (4)2958 1438 MS (\\)3000 1438 MS (m)3023 1438 MS (a)3087 1438 MS (n)3125 1438 MS (\\)3167 1438 MS (W)3189 1438 MS (I)3268 1438 MS (N)3296 1438 MS (3)3356 1438 MS (2)3398 1438 MS (\\)3440 1438 MS (P)3462 1438 MS (v)3509 1438 MS (m)3551 1438 MS (h)3615 1438 MS (e)3657 1438 MS (l)3694 1438 MS (p)3717 1438 MS (.)3759 1438 MS (h)3780 1438 MS (l)3821 1438 MS (p)3844 1438 MS [83 0 0 -83 0 0]/Helvetica MF ( )1267 1534 MS [83 0 0 -83 0 0]/_Times-Roman MF (9)1267 1534 MS (.)1309 1534 MS (P)1417 1534 MS (l)1464 1534 MS (a)1487 1534 MS (c)1524 1534 MS (e)1561 1534 MS ( )1598 1534 MS (s)1619 1534 MS (h)1651 1534 MS (o)1692 1534 MS (r)1734 1534 MS (t)1762 1534 MS (c)1785 1534 MS (u)1822 1534 MS (t)1863 1534 MS ( )1886 1534 MS (i)1907 1534 MS (n)1930 1534 MS ( )1971 1534 MS (C)1993 1534 MS (:)2048 1534 MS (\\)2072 1534 MS (W)2094 1534 MS (I)2173 1534 MS (N)2201 1534 MS (N)2261 1534 MS (T)2321 1534 MS (\\)2373 1534 MS (P)2395 1534 MS (r)2442 1534 MS (o)2470 1534 MS (f)2512 1534 MS (i)2539 1534 MS (l)2562 1534 MS (e)2585 1534 MS (s)2622 1534 MS (\\)2655 1534 MS (<)2677 1534 MS (u)2725 1534 MS (s)2767 1534 MS (e)2799 1534 MS (r)2836 1534 MS (n)2864 1534 MS (a)2905 1534 MS (m)2943 1534 MS (e)3007 1534 MS (>)3044 1534 MS (\\)3092 1534 MS (S)3114 1534 MS (t)3160 1534 MS (a)3183 1534 MS (r)3220 1534 MS (t)3248 1534 MS ( )3271 1534 MS (M)3292 1534 MS (e)3366 1534 MS (n)3404 1534 MS (u)3445 1534 MS (\\)3487 1534 MS (P)3509 1534 MS (r)3556 1534 MS (o)3584 1534 MS (g)3626 1534 MS (r)3667 1534 MS (a)3695 1534 MS (m)3733 1534 MS (s)3797 1534 MS ( )3829 1534 MS (\\)3850 1534 MS (P)3873 1534 MS (V)3920 1534 MS (M)3980 1534 MS [83 0 0 -83 0 0]/Helvetica MF ( )1267 1630 MS [83 0 0 -83 0 0]/_Times-Roman MF (1)1267 1630 MS (0)1309 1630 MS (.)1351 1630 MS (R)1417 1630 MS (e)1472 1630 MS (n)1509 1630 MS (a)1550 1630 MS (m)1588 1630 MS (e)1652 1630 MS ( )1689 1630 MS (s)1710 1630 MS (h)1743 1630 MS (o)1784 1630 MS (r)1826 1630 MS (t)1854 1630 MS (c)1877 1630 MS (u)1914 1630 MS (t)1955 1630 MS ( )1978 1630 MS ( )1999 1630 MS (\223)2021 1630 MS (P)2057 1630 MS (V)2104 1630 MS (M)2164 1630 MS ( )2238 1630 MS (H)2259 1630 MS (e)2319 1630 MS (l)2356 1630 MS (p)2379 1630 MS (\224)2421 1630 MS (\()967 1822 MS (9)995 1822 MS (5)1037 1822 MS (/)1079 1822 MS (9)1102 1822 MS (8)1144 1822 MS (\))1185 1822 MS (o)1342 1822 MS (p)1384 1822 MS (t)1426 1822 MS (i)1449 1822 MS (o)1472 1822 MS (n)1514 1822 MS ( )1555 1822 MS (n)1576 1822 MS (o)1617 1822 MS (t)1659 1822 MS ( )1682 1822 MS (a)1703 1822 MS (v)1740 1822 MS (a)1781 1822 MS (i)1818 1822 MS (l)1841 1822 MS (a)1864 1822 MS (b)1901 1822 MS (l)1943 1822 MS (e)1966 1822 MS ( )2003 1822 MS (o)2024 1822 MS (n)2066 1822 MS ( )2107 1822 MS (9)2128 1822 MS (5)2170 1822 MS (/)2212 1822 MS (9)2235 1822 MS (8)2277 1822 MS ( )2319 1822 MS (s)2340 1822 MS (y)2373 1822 MS (s)2413 1822 MS (t)2445 1822 MS (e)2468 1822 MS (m)2506 1822 MS (s)2570 1822 MS ( )2602 1822 MS (\226)2623 1822 MS (o)2665 1822 MS (p)2707 1822 MS (e)2749 1822 MS (r)2786 1822 MS (a)2814 1822 MS (t)2851 1822 MS (i)2874 1822 MS (n)2897 1822 MS (g)2939 1822 MS ( )2980 1822 MS (s)3001 1822 MS (y)3034 1822 MS (s)3075 1822 MS (t)3107 1822 MS (e)3130 1822 MS (m)3168 1822 MS ( )3232 1822 MS (l)3253 1822 MS (i)3276 1822 MS (m)3300 1822 MS (i)3364 1822 MS (t)3387 1822 MS (a)3410 1822 MS (t)3448 1822 MS (i)3471 1822 MS (o)3494 1822 MS (n)3536 1822 MS (I)442 2206 MS (M)470 2206 MS (P)544 2206 MS (O)591 2206 MS (R)651 2206 MS (T)706 2206 MS (A)758 2206 MS (N)817 2206 MS (T)877 2206 MS ( )929 2206 MS (N)950 2206 MS (O)1010 2206 MS (T)1069 2206 MS (E)1121 2206 MS (S)1172 2206 MS (:)1218 2206 MS n 4019 5 430 2234 B f (A)442 2411 MS (L)502 2411 MS (P)552 2411 MS (H)599 2411 MS (A)660 2411 MS ( )719 2411 MS (V)740 2411 MS (S)800 2411 MS ( )846 2411 MS (I)867 2411 MS (N)895 2411 MS (T)955 2411 MS (E)1007 2411 MS (L)1058 2411 MS (:)1108 2411 MS (A)592 2507 MS (l)651 2507 MS (t)674 2507 MS (h)698 2507 MS (o)739 2507 MS (u)782 2507 MS (g)823 2507 MS (h)865 2507 MS ( )906 2507 MS (b)927 2507 MS (o)969 2507 MS (t)1011 2507 MS (h)1034 2507 MS ( )1075 2507 MS (I)1096 2507 MS (n)1124 2507 MS (t)1165 2507 MS (e)1188 2507 MS (l)1225 2507 MS ( )1248 2507 MS (a)1269 2507 MS (n)1307 2507 MS (d)1348 2507 MS ( )1390 2507 MS (A)1412 2507 MS (l)1471 2507 MS (p)1494 2507 MS (h)1536 2507 MS (a)1577 2507 MS ( )1614 2507 MS (b)1635 2507 MS (a)1677 2507 MS (s)1714 2507 MS (e)1746 2507 MS (d)1783 2507 MS ( )1825 2507 MS (m)1847 2507 MS (a)1910 2507 MS (c)1947 2507 MS (h)1985 2507 MS (i)2026 2507 MS (n)2050 2507 MS (e)2091 2507 MS (s)2128 2507 MS ( )2160 2507 MS (c)2181 2507 MS (a)2218 2507 MS (n)2256 2507 MS ( )2297 2507 MS (r)2318 2507 MS (u)2346 2507 MS (n)2388 2507 MS ( )2429 2507 MS (N)2450 2507 MS (T)2510 2507 MS (,)2562 2507 MS ( )2583 2507 MS (r)2604 2507 MS (e)2632 2507 MS (m)2669 2507 MS (e)2732 2507 MS (m)2770 2507 MS (b)2833 2507 MS (e)2875 2507 MS (r)2912 2507 MS ( )2940 2507 MS (t)2961 2507 MS (h)2984 2507 MS (a)3026 2507 MS (t)3063 2507 MS ( )3086 2507 MS (t)3107 2507 MS (h)3130 2507 MS (e)3171 2507 MS (s)3209 2507 MS (e)3241 2507 MS ( )3278 2507 MS (t)3299 2507 MS (w)3323 2507 MS (o)3382 2507 MS ( )3424 2507 MS (s)3445 2507 MS (y)3478 2507 MS (s)3519 2507 MS (t)3551 2507 MS (e)3574 2507 MS (m)3611 2507 MS (s)3676 2507 MS ( )3708 2507 MS (r)3729 2507 MS (e)3757 2507 MS (q)3794 2507 MS (u)3836 2507 MS (i)3878 2507 MS (r)3901 2507 MS (e)3929 2507 MS ( )3966 2507 MS (t)3987 2507 MS (h)4010 2507 MS (e)4051 2507 MS (i)4088 2507 MS (r)4111 2507 MS ( )4139 2507 MS (o)4160 2507 MS (w)4203 2507 MS (n)4262 2507 MS (b)592 2603 MS (i)634 2603 MS (n)657 2603 MS (a)698 2603 MS (r)735 2603 MS (y)764 2603 MS ( )804 2603 MS (f)825 2603 MS (o)852 2603 MS (r)894 2603 MS (m)923 2603 MS (a)987 2603 MS (t)1024 2603 MS (.)1047 2603 MS ( )1068 2603 MS (T)1089 2603 MS (h)1141 2603 MS (u)1182 2603 MS (s)1223 2603 MS (,)1255 2603 MS ( )1276 2603 MS (y)1298 2603 MS (o)1338 2603 MS (u)1381 2603 MS ( )1422 2603 MS (m)1444 2603 MS (u)1508 2603 MS (s)1550 2603 MS (t)1582 2603 MS ( )1605 2603 MS (c)1626 2603 MS (o)1663 2603 MS (m)1706 2603 MS (p)1769 2603 MS (i)1811 2603 MS (l)1834 2603 MS (e)1857 2603 MS ( )1894 2603 MS (P)1915 2603 MS (V)1962 2603 MS (M)2022 2603 MS ( )2096 2603 MS (c)2117 2603 MS (o)2154 2603 MS (d)2196 2603 MS (e)2238 2603 MS (s)2275 2603 MS ( )2307 2603 MS (f)2328 2603 MS (o)2355 2603 MS (r)2397 2603 MS ( )2425 2603 MS (t)2446 2603 MS (h)2469 2603 MS (e)2510 2603 MS ( )2547 2603 MS (t)2568 2603 MS (a)2591 2603 MS (r)2628 2603 MS (g)2656 2603 MS (e)2697 2603 MS (t)2734 2603 MS ( )2757 2603 MS (p)2778 2603 MS (h)2821 2603 MS (y)2863 2603 MS (s)2904 2603 MS (i)2936 2603 MS (c)2959 2603 MS (a)2996 2603 MS (l)3033 2603 MS ( )3056 2603 MS (a)3077 2603 MS (r)3114 2603 MS (c)3142 2603 MS (h)3179 2603 MS (i)3220 2603 MS (t)3244 2603 MS (e)3267 2603 MS (c)3304 2603 MS (t)3341 2603 MS (u)3364 2603 MS (r)3405 2603 MS (e)3433 2603 MS (.)3470 2603 MS (K)442 2794 MS (N)502 2794 MS (O)562 2794 MS (W)622 2794 MS (N)701 2794 MS ( )761 2794 MS (P)782 2794 MS (R)829 2794 MS (O)884 2794 MS (B)944 2794 MS (L)1000 2794 MS (E)1050 2794 MS (M)1101 2794 MS (S)1175 2794 MS (:)1221 2794 MS (T)592 2890 MS (h)644 2890 MS (e)685 2890 MS (r)722 2890 MS (e)750 2890 MS ( )787 2890 MS (a)808 2890 MS (p)845 2890 MS (p)886 2890 MS (e)928 2890 MS (a)965 2890 MS (r)1002 2890 MS (s)1030 2890 MS ( )1062 2890 MS (t)1083 2890 MS (o)1106 2890 MS ( )1148 2890 MS (b)1169 2890 MS (e)1211 2890 MS ( )1248 2890 MS (a)1269 2890 MS ( )1305 2890 MS (\223)1326 2890 MS (t)1362 2890 MS (i)1385 2890 MS (m)1409 2890 MS (e)1473 2890 MS (o)1510 2890 MS (u)1552 2890 MS (t)1593 2890 MS (\224)1616 2890 MS ( )1653 2890 MS (p)1674 2890 MS (r)1716 2890 MS (o)1744 2890 MS (b)1786 2890 MS (l)1828 2890 MS (e)1851 2890 MS (m)1889 2890 MS ( )1952 2890 MS (r)1973 2890 MS (e)2001 2890 MS (l)2038 2890 MS (a)2061 2890 MS (t)2098 2890 MS (e)2121 2890 MS (d)2158 2890 MS ( )2200 2890 MS (t)2221 2890 MS (o)2244 2890 MS ( )2286 2890 MS (p)2307 2890 MS (o)2349 2890 MS (r)2391 2890 MS (t)2419 2890 MS (s)2442 2890 MS ( )2474 2890 MS (o)2495 2890 MS (n)2537 2890 MS ( )2578 2890 MS (t)2599 2890 MS (h)2622 2890 MS (e)2663 2890 MS ( )2700 2890 MS (N)2721 2890 MS (T)2781 2890 MS (/)2833 2890 MS (9)2856 2890 MS (5)2898 2890 MS (/)2940 2890 MS (9)2962 2890 MS (8)3004 2890 MS ( )3046 2890 MS (s)3067 2890 MS (y)3099 2890 MS (s)3139 2890 MS (t)3172 2890 MS (e)3195 2890 MS (m)3233 2890 MS (s)3297 2890 MS ( )3329 2890 MS (o)3350 2890 MS (r)3392 2890 MS ( )3420 2890 MS (w)3442 2890 MS (i)3500 2890 MS (t)3523 2890 MS (h)3547 2890 MS ( )3588 2890 MS (A)3609 2890 MS (t)3668 2890 MS (a)3691 2890 MS (m)3728 2890 MS (a)3791 2890 MS (n)3830 2890 MS (.)3872 2890 MS ( )3894 2890 MS (O)3915 2890 MS (n)3975 2890 MS (e)4016 2890 MS ( )4053 2890 MS (s)4075 2890 MS (o)4107 2890 MS (u)4149 2890 MS (r)4190 2890 MS (c)4218 2890 MS (e)4255 2890 MS (s)592 2986 MS (u)624 2986 MS (g)666 2986 MS (g)707 2986 MS (e)748 2986 MS (s)786 2986 MS (t)818 2986 MS (e)841 2986 MS (d)878 2986 MS ( )920 2986 MS (m)942 2986 MS (a)1005 2986 MS (k)1043 2986 MS (i)1084 2986 MS (n)1108 2986 MS (g)1149 2986 MS ( )1190 2986 MS (a)1211 2986 MS (l)1248 2986 MS (l)1272 2986 MS ( )1295 2986 MS (c)1316 2986 MS (o)1353 2986 MS (n)1395 2986 MS (n)1436 2986 MS (e)1477 2986 MS (c)1514 2986 MS (t)1552 2986 MS (i)1575 2986 MS (o)1598 2986 MS (n)1640 2986 MS (s)1682 2986 MS ( )1714 2986 MS (n)1735 2986 MS (o)1776 2986 MS (n)1818 2986 MS (-)1860 2986 MS (p)1887 2986 MS (e)1929 2986 MS (r)1966 2986 MS (s)1994 2986 MS (i)2026 2986 MS (s)2050 2986 MS (t)2082 2986 MS (e)2105 2986 MS (n)2142 2986 MS (t)2184 2986 MS (.)2207 2986 MS ( )2228 2986 MS (T)2249 2986 MS (h)2301 2986 MS (e)2342 2986 MS ( )2379 2986 MS (s)2400 2986 MS (y)2433 2986 MS (m)2474 2986 MS (p)2538 2986 MS (t)2580 2986 MS (o)2603 2986 MS (m)2646 2986 MS ( )2709 2986 MS (i)2730 2986 MS (s)2753 2986 MS ( )2785 2986 MS (t)2806 2986 MS (h)2830 2986 MS (a)2871 2986 MS (t)2908 2986 MS ( )2931 2986 MS (i)2952 2986 MS (t)2975 2986 MS ( )2998 2986 MS (t)3019 2986 MS (a)3042 2986 MS (k)3080 2986 MS (e)3121 2986 MS (s)3158 2986 MS ( )3190 2986 MS (s)3212 2986 MS (o)3244 2986 MS (m)3287 2986 MS (e)3350 2986 MS ( )3387 2986 MS (t)3408 2986 MS (i)3431 2986 MS (m)3455 2986 MS (e)3519 2986 MS ( )3556 2986 MS (b)3577 2986 MS (e)3619 2986 MS (f)3656 2986 MS (o)3683 2986 MS (r)3725 2986 MS (e)3753 2986 MS ( )3790 2986 MS (a)3811 2986 MS ( )3848 2986 MS (r)3869 2986 MS (e)3897 2986 MS (c)3934 2986 MS (o)3971 2986 MS (n)4013 2986 MS (n)4054 2986 MS (e)4095 2986 MS (c)4132 2986 MS (t)4169 2986 MS (i)4192 2986 MS (o)4215 2986 MS (n)4258 2986 MS ( )4299 2986 MS (t)4320 2986 MS (o)4343 2986 MS (a)592 3082 MS ( )629 3082 MS (d)650 3082 MS (r)692 3082 MS (o)720 3082 MS (p)762 3082 MS (p)803 3082 MS (e)845 3082 MS (d)882 3082 MS ( )924 3082 MS (o)944 3082 MS (r)986 3082 MS ( )1014 3082 MS (d)1035 3082 MS (e)1077 3082 MS (l)1114 3082 MS (e)1137 3082 MS (t)1174 3082 MS (e)1197 3082 MS (d)1234 3082 MS ( )1275 3082 MS (h)1296 3082 MS (o)1337 3082 MS (s)1379 3082 MS (t)1411 3082 MS ( )1434 3082 MS (i)1455 3082 MS (s)1478 3082 MS ( )1510 3082 MS (a)1531 3082 MS (c)1568 3082 MS (c)1605 3082 MS (e)1642 3082 MS (p)1679 3082 MS (t)1721 3082 MS (e)1744 3082 MS (d)1781 3082 MS (.)1823 3082 MS ( )1844 3082 MS (T)1865 3082 MS (h)1917 3082 MS (e)1958 3082 MS ( )1995 3082 MS (e)2016 3082 MS (r)2053 3082 MS (r)2081 3082 MS (o)2108 3082 MS (r)2150 3082 MS ( )2178 3082 MS (\223)2199 3082 MS (c)2235 3082 MS (a)2272 3082 MS (n)2309 3082 MS (n)2350 3082 MS (o)2391 3082 MS (t)2433 3082 MS ( )2456 3082 MS (c)2477 3082 MS (o)2514 3082 MS (n)2556 3082 MS (n)2598 3082 MS (e)2639 3082 MS (c)2676 3082 MS (t)2713 3082 MS ( )2736 3082 MS (t)2757 3082 MS (o)2780 3082 MS ( )2822 3082 MS (r)2843 3082 MS (s)2871 3082 MS (h)2903 3082 MS ( )2944 3082 MS (p)2965 3082 MS (o)3007 3082 MS (r)3049 3082 MS (t)3077 3082 MS ( )3100 3082 MS (\205)3121 3082 MS ( )3204 3082 MS (c)3225 3082 MS (a)3262 3082 MS (n)3299 3082 MS (n)3340 3082 MS (o)3381 3082 MS (t)3424 3082 MS ( )3447 3082 MS (s)3468 3082 MS (h)3501 3082 MS (u)3542 3082 MS (t)3583 3082 MS (d)3606 3082 MS (o)3648 3082 MS (w)3691 3082 MS (n)3750 3082 MS ( )3791 3082 MS (r)3812 3082 MS (s)3840 3082 MS (h)3872 3082 MS ( )3913 3082 MS (c)3934 3082 MS (l)3971 3082 MS (i)3995 3082 MS (e)4018 3082 MS (n)4056 3082 MS (t)4097 3082 MS ( )4120 3082 MS (s)4141 3082 MS (o)4173 3082 MS (c)4215 3082 MS (k)4253 3082 MS (e)4294 3082 MS (t)4331 3082 MS (\224)4354 3082 MS (a)592 3178 MS (p)629 3178 MS (p)671 3178 MS (e)713 3178 MS (a)750 3178 MS (r)787 3178 MS (s)815 3178 MS ( )847 3178 MS (i)868 3178 MS (n)891 3178 MS ( )932 3178 MS (t)953 3178 MS (h)976 3178 MS (e)1017 3178 MS ( )1054 3178 MS (h)1075 3178 MS (o)1116 3178 MS (s)1158 3178 MS (t)1191 3178 MS (e)1214 3178 MS (r)1251 3178 MS ( )1279 3178 MS (w)1301 3178 MS (i)1359 3178 MS (n)1383 3178 MS (d)1424 3178 MS (o)1466 3178 MS (w)1509 3178 MS ( )1568 3178 MS (d)1589 3178 MS (u)1631 3178 MS (r)1672 3178 MS (i)1700 3178 MS (n)1723 3178 MS (g)1765 3178 MS ( )1806 3178 MS (a)1827 3178 MS ( )1864 3178 MS (P)1885 3178 MS (V)1932 3178 MS (M)1992 3178 MS ( )2066 3178 MS (a)2087 3178 MS (d)2124 3178 MS (d)2166 3178 MS ( )2208 3178 MS (c)2229 3178 MS (o)2266 3178 MS (m)2308 3178 MS (m)2372 3178 MS (a)2436 3178 MS (n)2473 3178 MS (d)2514 3178 MS ( )2556 3178 MS (f)2578 3178 MS (r)2605 3178 MS (o)2633 3178 MS (m)2676 3178 MS ( )2739 3178 MS (c)2760 3178 MS (o)2797 3178 MS (n)2839 3178 MS (s)2880 3178 MS (o)2912 3178 MS (l)2954 3178 MS (e)2977 3178 MS (.)3014 3178 MS (L)442 3369 MS (A)493 3369 MS (T)552 3369 MS (E)604 3369 MS ( )655 3369 MS (B)676 3369 MS (R)732 3369 MS (E)787 3369 MS (A)838 3369 MS (K)897 3369 MS (I)957 3369 MS (N)985 3369 MS (G)1045 3369 MS ( )1105 3369 MS (N)1126 3369 MS (T)1186 3369 MS (/)1238 3369 MS (9)1261 3369 MS (5)1303 3369 MS (/)1345 3369 MS (9)1368 3369 MS (8)1410 3369 MS ( )1452 3369 MS (N)1473 3369 MS (E)1533 3369 MS (W)1584 3369 MS (S)1663 3369 MS (:)1709 3369 MS 0.105 g (h)592 3465 MS (t)633 3465 MS (t)656 3465 MS (p)679 3465 MS (:)721 3465 MS (/)744 3465 MS (/)767 3465 MS (w)791 3465 MS (w)851 3465 MS (w)911 3465 MS (.)970 3465 MS (e)991 3465 MS (p)1028 3465 MS (m)1071 3465 MS (.)1135 3465 MS (o)1156 3465 MS (r)1198 3465 MS (n)1226 3465 MS (l)1267 3465 MS (.)1290 3465 MS (g)1312 3465 MS (o)1353 3465 MS (v)1395 3465 MS (/)1436 3465 MS (~)1459 3465 MS (s)1505 3465 MS (s)1537 3465 MS (c)1569 3465 MS (o)1606 3465 MS (t)1648 3465 MS (t)1671 3465 MS n 1100 3 592 3474 B f 0 g (F)442 3848 MS (i)488 3848 MS (l)511 3848 MS (e)534 3848 MS (n)571 3848 MS (a)612 3848 MS (m)650 3848 MS (e)714 3848 MS (:)751 3848 MS ( )774 3848 MS (i)795 3848 MS (n)819 3848 MS (s)860 3848 MS (t)893 3848 MS (a)916 3848 MS (l)953 3848 MS (l)976 3848 MS (a)999 3848 MS (t)1036 3848 MS (i)1059 3848 MS (o)1082 3848 MS (n)1124 3848 MS (.)1165 3848 MS (d)1186 3848 MS (o)1228 3848 MS (c)1270 3848 MS (L)442 3944 MS (a)492 3944 MS (s)529 3944 MS (t)561 3944 MS ( )584 3944 MS (U)606 3944 MS (p)666 3944 MS (d)708 3944 MS (a)750 3944 MS (t)787 3944 MS (e)810 3944 MS (d)847 3944 MS (:)889 3944 MS ( )912 3944 MS (3)933 3944 MS (-)975 3944 MS (1)1002 3944 MS (5)1044 3944 MS (-)1086 3944 MS (1)1113 3944 MS (9)1155 3944 MS (9)1197 3944 MS (9)1239 3944 MS showpage PageSV restore %%Trailer %%DocumentNeededFonts: %%+ Helvetica %%+ Times-Roman %%DocumentSuppliedFonts: end %%Pages: 3 %%EOF ./pvm3/WIN32/into-Autoexec.bat0100644007401100000360000000014706672027751015134 0ustar kohlgopherrem CALL C:\PROGRA~1\PVM3.4\WIN32\PVMVARS.BAT AUTOEXEC rem - End of lines added by PVM 3.4.0 Setup rem ./pvm3/WIN32/PVM Compile Shell.pif0100644007401100000360000000170706672272010015454 0ustar kohlgopherxPVM Compile Shell €C:\WINDOWS\COMMAND.COMC:\PROGRA~1\PVM3.4ÿPMICROSOFT PIFEX‡qWINDOWS 386 3.0h€d2ÿÿÿÿWINDOWS VMM 4.0ÿÿ¬C:\Program Files\PVM3.4\pvm.ico22Èè  TerminalCourier NewP2àìËÿÿÿÿÿÿÿÿ!7 ./pvm3/WIN32/pvm.ico0100644007401100000360000000525606653174376013231 0ustar kohlgopher(6 è^00hF( À€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿªªªª ÿªª ª ª ÿ𪪪ªªð𪪪ª ÿªªªªª ª ªªªª ÿªªªÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿðÿðÿÿðÿðÿðððððÿðððÿððÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ( @€€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿªªª ÿÿÿÿÿÿÿÿÿÿªªª ÿðÿÿÿÿÿÿÿªªªÿðªÿÿÿÿÿªªªÿ𪪠ÿððÿÿÿªª ÿÿ𪪪 ÿð ÿªª ÿÿðªªÿ ðÿªªÿÿð ÿÿª ÿªªÿÿÿððª ÿªªÿÿðÿ𠪪ðªªÿÿÿÿ ªª𪪠ÿÿªªª ÿªª ªª ð𪪪ªªªªªªªª ð ªªªÿªªª ªªª ªª ÿ𪪠ÿÿ𪪪 ªªª ÿðª ÿ𠪪ª ªªÿªÿÿ ªªª ªªÿÿ ªªª ª ÿðÿ ÿ ªªª ª ÿðÿ𪪪ªª ÿÿ  ªªªªª ÿÿª  ªªªªªÿðÿÿªªªªªªªÿÿðÿÿªªª ÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿðÿððÿÿÿÿÿÿÿÿðÿðÿÿÿÿÿððÿÿÿÿÿÿððÿÿÿÿÿðÿðÿðÿÿÿÿðÿðÿð(0`€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿªªÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿªªª ÿÿÿÿðÿðÿÿÿÿðÿÿÿÿÿÿªªª ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿªªªÿÿÿÿÿðÿÿÿÿÿÿÿÿªªªÿÿÿÿð  ÿðÿðÿÿÿÿªªªÿÿÿð ª ðÿð ÿÿªªªÿÿÿÿªªª ÿ  ðÿªª ðÿÿÿÿÿÿ ªªªÿ  ððÿªª ðÿðÿð ª ÿðª ðÿªª ÿð ªð  ÿðª ðÿ𪪠𠪪ª ðÿ  ªðÿÿªª ÿ ªªªªªªÿ  ªðÿÿªªª ªªªªªªª ÿ𪠪ðÿÿªªªªªªªªªªªªªªªðª ªðÿÿªªª  ªªªªªªªªªª  ªªðÿÿ ÿ ªªªªªªªªªª ªªðÿÿªÿÿ𠪪ªªªªªªªª ªªÿÿÿÿªªªªªªªªªª ª ÿ ÿÿ𪪪ªªªªªªª ª ÿÿÿ ÿ𪪪ªªªªªªª ªðÿÿÿªªªªªªªªªª ªðÿÿÿ ÿÿ ªªªªªªªªªª  ÿÿÿÿª𠪪ªªªªªªªª  ÿÿÿ ªªªªªªªªªªª ðÿÿ  ªªªªªªªªªðÿÿÿªªªªªªªªªÿÿðÿÿÿÿªªªÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿððÿðÿÿÿðÿÿÿÿÿÿðÿÿÿÿðÿÿÿÿÿðÿÿÿÿÿÿðÿÿÿÿðÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿðÿÿÿðÿÿÿÿÿðÿðÿÿÿðÿÿÿÿÿðÿðÿÿÿðÿÿÿÿÿðÿÿðÿÿðÿÿðÿÿÿðÿÿðÿÿðÿÿðÿÿÿðÿÿðÿÿðÿÿðÿÿÿððÿÿÿÿÿÿÿÿÿÿððÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ./pvm3/WIN32/PVM NT Compile Shell.lnk0100644007401100000360000000124006673301457015765 0ustar kohlgopherLÀFÛ€Œ7Up¹»Ž*‘ñ"A¾ ¼#äU¼-sàOÐ ê:i¢Ø+00#C:\1¹1(&Œ|€Winnt10&‰ 0system322-¡" €€Cmd.exeW<V ¨¥üXWestern HemlockC:\WINNT\system32\CMD.EXE..\..\..\WINNT\system32\CMD.EXEC:\program files\pvm3.4%C:\Program Files\PVM3.4\WIN32\pvm.icoÌ õP–P( 08514oemle15Ó0€DD2€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿ./pvm3/doc/0042755007401100000360000000000010117676455011666 5ustar kohlgopher./pvm3/doc/arches0100644007401100000360000000016706221572053013043 0ustar kohlgopher check out the pvm_intro.1 man page for this information. it was a pain to maintain two versions of the same list. -b ./pvm3/doc/bugreport0100644007401100000360000000257207331302567013615 0ustar kohlgopher PVM version 3 Bug Report Form 08 June 1994 ________________________________________________________________________ If you find a bug in PVM, please report it to: pvm@msr.csm.ornl.gov ________________________________________________________________________ Please try to include the following information: * The exact version and patch level of PVM you're using (e.g. 3.4.0). This is necessary, because we don't want to go looking through source for all past versions of PVM. Also, if you're using an old version, you mave have found a bug that we've already fixed. * The machine type(s) you're using, hardware and software (e.g. DEC 3000/500 running OSF 1.2). This is helpful if we want to try to reproduce the bug here. Also, we know very little about some of the machines PVM runs on and we'll be able to tell you that. * The machine architecture PVM chooses for you (e.g. ALPHA). * What shell you use (csh, ksh, ...). * A short description of the problem (what happens, when it happens, what you did, etc.). Include any relevant input you typed and output printed by PVM. Don't edit the output to format it or summarize it (except maybe for removing 10000 lines that say the same thing - make a note you did this). Crucial information about the bug may be in a few numbers or words. * Please warn us if you've made any changes to the distribution source. ./pvm3/doc/example.pvmrc0100644007401100000360000000077706221572057014372 0ustar kohlgopher # # example PVM console startup script # copy this file to $HOME/.pvmrc # # # command aliases # alias ? help alias print_environment spawn -> /bin/env alias h help alias j jobs alias t ps alias tm trace alias v version # # important for debugging # setenv PVM_EXPORT DISPLAY # # want to see these trace events by default # tm addhosts delhosts halt tm pvm_mytid pvm_exit pvm_parent tm send recv nrecv probe mcast trecv sendsig recvf version # print PVM release version id # print console TID #conf ./pvm3/doc/release-notes0100644007401100000360000003504210117676362014353 0ustar kohlgopher ------------------------------------------------------------------------ PVM Version 3.4.5 is Available on Netlib 8 September 2004 ------------------------------------------------------------------------ The latest PVM release 3.4.5 is mainly bug fixes and additional support for varying Linux distributions and some better 64-bit Linux/AMD support (like it doesn't seg fauly any more :-). Added strerror() support instead of old crusty global vars. New architectures were added for AIX5*. Fixed hilarious bug in pvmtmpnam(), caused crash after 10,000 spawns... :-D While there's a variety of little tweaks, there are no significant changes or additions to the basic functionality. ------------------------------------------------------------------------ PVM Version 3.4.4 is Available on Netlib 28 September 2001 ------------------------------------------------------------------------ There are many bug fixes and a couple new features included in the Version 3.4.4 release. Most of these are not significant, unless you are running on some of the less common architectures which may now be supported! :-) * One new feature in PVM 3.4.4 is the concept of a "Virtual Machine ID". You can now set the PVM_VMID environment variable to an arbitrary string (or use the "id=" option in a host file), and this will distinguish multiple virtual machines all running on the same set of hosts under the same userid. (This feature was originally introduced by SGI in their commercial PVM product, and has now been generalized for the public PVM system.) This feature seems to be something that people often want, and the PVM_VMID seems to be the cleanest way to provide this functionality, rather than overloading the SHAREDTMP and other internals. * Linux / gcc fixes: got rid of many invasive new compiler warnings, like "tmpnam() is dangerous" and some old crusty varargs code. * Added some new archs, like DARWIN & MACOSX for Macs (huhuhuhuh), CYGWIN, and BEOSCYLD, and updated some arches like FreeBSD systems. * Extended the syntax of the "where" argument in pvm_spawn() to include a working directory, as in "foo.org:/home/joe". * Fixed direct routing bug that could result in deadlock, also fixed (?) direct routing in WIN32. * Fixed bug to appropriately set message context around message handler invocations. * Added use of new strerror() function in place of direct use of sys_errlist/sys_nerr, for systems that don't grok that. * Minor WIN32 tweaks and bug fixes... Please see the notes in the "pvm_intro" and "pvmd3" man pages for more details. Several other new environment variables are also documented there. ------------------------------------------------------------------------ PVM Version 3.4.0 is Available on Netlib 12 March 1999 ------------------------------------------------------------------------ Besides bug fixes to 3.3, there are many new features in Version 3.4 (see man pages for more details): -------- Message Context -------- * To allow more flexibility in organizing message tags sets, and to provide support for "safe" libraries that will not inadvertently intercept user messages, the concept of "message context" in PVM has been introduced. The context is an additional system-defined message tag that each message carries, such that each given message can only be sent or received within a single unique context. For example, all internal system messages in PVM now utilize a different context than the base user application context, so that system messages cannot be incorrectly received by the application. The user can determine the current context, create a new context, set the current context and free message contexts using the new routines pvm_getcontext(), pvm_newcontext(), pvm_setcontext() and pvm_freecontext(), respectively (see man pages for details). The context itself is an integer value which can be packed into messages and sent to cooperating tasks, or placed in a message mailbox (see below) for client-service lookup. By default, all tasks are spawned in the same base context. -------- Message Handlers -------- * In the spirit of Active Messages, PVM now supports "message handlers" for automatic processing of incoming messages. The user can define any number of message handler functions, each with a corresponding (source, tag, context) tuple. Then when a message matching a particular tuple arrives at the local task, the user-specified handler routine is automatically invoked to process the message. Within a message handler, the message can be unpacked and a simple response message can be packed and sent (using pvm_send() only). The new PVM routines for creating and deleting message handlers are pvm_addmhf() and pvm_delmhf(), respectively (see man pages for details). Note that message handlers are only invoked when the application is already executing a PVM messaging routine - handlers cannot interrupt normal program execution. Typically, message handlers will trigger transparently during other communication, but the user can specifically invoke them by calling pvm_probe() or an equivalent function in a loop. -------- Message Mailboxes -------- * To provide a new means for name service that does not require the PVM dynamic group server ("pvmgs"), a "message mailbox" mechanism has been added to PVM 3.4. Using this feature a user application can post a message to a public mailbox which can subsequently be "looked up" and retrieved by other independently spawned tasks in the virtual machine. Each mailbox is created using a specific "class name" and can consist of either exactly one or many entries for that given name. When a task "looks up" a mailbox entry, it receives back the message contained in it, to be unpacked and processed as desired. Mailboxes can be mutually exclusive, to act as a locking mechanism for resources, and can be created as "persistent" so that they will continue to exist after the owner (or creator) task exits. The new routines in PVM for creating, retrieving and freeing message mailboxes are pvm_putinfo(), pvm_recvinfo() and pvm_delinfo(), respectively, plus an additional routine, pvm_getmboxinfo(), for obtaining a list of the currently- defined class names (see man pages for details). -------- Spawn Siblings -------- * Often when designing SPMD programs, it is useful to know which tasks were spawned together as a group. This information can be used to form static groups for efficient group communication, or simply for referencing other members of your own "spawn siblings". The new PVM call pvm_siblings() (see man page for details) returns a list of integer task ids that corresponds to all the tasks that were spawned together from a single pvm_spawn() call (or from the "pvm" console). -------- Tracing -------- * Routines in libpvm and the group library have included built-in tracing of calling parameter/results since PVM 3.3. In PVM 3.4, the tracing facility has been completely rewritten to be more general, flexible and maintainable. As a result, the tracing capabilities of PVM 3.4 have been expanded to support trace buffering, several levels of tracing, and user-defined trace events. The graphical PVM interface, XPVM 1.2, has been rewritten to use a new PVM library, libpvmtrc, and a new text-based trace collection tool ("tracer") has been added to the standard PVM distribution to allow easy trace file collection on systems where X11 compilation is either difficult or impossible. In addition, the new tracing facility now supports "automatic" attachment to trace collection programs, so that when tasks are independently spawned, e.g. from the shell, their trace events will still propagate to the proper trace tool (without any manual "attachment" procedure). Other various improvements have been applied to specific trace events, e.g. pvm_send() events now carry the message size information, allowing proper driving of XPVM's Message Queue View (you will notice the difference in the message coloring to indicate this added capability). Upon re-compiling XPVM with the new PVM 3.4 libraries (by clearing the defines for PVMVERSION and PVMGLIB, and modifying TRCDIR to point to pvm3/tracer in the file "xpvm/src/Makefile.aimk"), you will find additional options on the "Tasks.../SPAWN" dialog to control the new tracing features. The new "pvm" console also supports new options to the "trace" commands (type "help trace" in the console for a description). For additional information regarding use of the more advanced tracing features, send email to "kohlja@ornl.gov". * Added new "trcsort" program (in pvm3/tracer subdirectory) for sorting trace files by timestamp. Takes into account approximate clock skew among hosts (still no guarantees about "tachyons" though). -------- Misc -------- * Most of the MIMD and SHMEM code has been completely rewritten (as of this beta release, the SHMEM ports are still work in progress) to eliminate many bugs and improve maintainability and robustness. On architectures that support shared memory operations, the default PVM architecture selection is now non-shmem, and to turn on selection of the appropriate *MP architecture the user must set the environment variable "PVM_SHMEM" to "ON", as in "setenv PVM_SHMEM ON" (see "Potential Incompatibilities" below). The style of compiling PVM applications for MPP systems has also changed slightly - please refer to the pvm3/examples directory for the proper Makefile.aimk targets. * The Makefiles for PVM 3.4 have been completely overhauled to (theoretically) allow easier setting of desired compile options from the new top level Makefile.aimk. The new defines "CFLOPTS" and "FFLOPTS" are passed down into the various subdirectories and then prepended to the definitions for CFLAGS and FFLAGS, respectively. Likewise, setting CC or F77 at the top level will force that setting throughout the source tree when making at the top level. * Extensive work has been done on the PVM port to Windows systems, the "WIN32" architecture. The stuff really works now! :-) * Added new "srm" simple resource manager example, in pvm3/rm. * Added new pvm_setopt() option "PvmNoReset" for system tasks, to prevent tasks from being killed during a system reset. * Added new pvm_setopt() option "PvmNoSpawnParent" so that tasks can now use pvm_parent() to determine if they are the "master" in master-slave applications, even if tasks are spawned from the "pvm" console or XPVM. ------------------------------------------------------------------------ Bug Fixes: * Remote task output collection and tracing is now correctly working on MPP systems such as PGON and SHMEM architectures. * It is now possible to fully interoperate pvm_send(), pvm_recv(), pvm_nrecv() and pvm_trecv() with pvm_psend() and pvm_precv() (assuming that the appropriate PvmDataRaw data encoding is used!). MPPs can use pvm_psend() and pvm_precv() off-machine with tasks that are using the traditional send and receive routines. * Modified pvm_freebuf() so that freeing a NULL buffer no longer generates an error. Many 3.3 codes exhibited this error through the use of pvm_freebuf( pvm_setsbuf(x) ) where there was no old send buffer. * A static character variable has been utilized inside pvm_version() to prevent stack problems on certain architectures. * Cleaned up LINUX defines for latest Linux kernel header files, no longer yaks on "struct fd_set rfds" everywhere. * Removed ancient "-lmutex" from SGI architectures ARCHDLIB defines! * Lots of manual pages additions and fixes (more to come...). ------------------------------------------------------------------------ Changes - Potential Incompatibilities: * The old "$SGIMP" environment variable has been subsumed with the new "$PVM_SHMEM" environment variable. * Due to incompatibilities between AIX 4.1 and 4.2, the previous RS6K architecture has been split to add several new architectures for different OS / SHMEM combinations: AIX46K, AIX4MP, AIX4SP2. * All of the various daemon-to-task and task-to-task protocols have been moved to a new public header file, "pvm3/include/pvmproto.h". The constants for utilizing the protocols for task control messages and other system support programs are all included in this new header file. * Tracing facility has been completely rewritten, new trace messages are incompatible with PVM 3.3 tracing tools (except XPVM 1.2, see above). However, the new libpvmtrc.a tracing library is provided for collecting and manipulating PVM trace files. See the "tracer" example for details. * Defunct functs - the following functions are no longer supported in PVM 3.4: pvm_insert(), pvm_delete(), pvm_lookup(). The name service features that these routines provided are now handled using the message mailbox system. For backwards compatibility, these functions have been implemented on top of the mailbox system, but pvm_insert(), pvm_delete(), pvm_lookup() are obsolete and should not be used. * Obsolete functions - the following functions will be eliminated in a future release: pvm_getmwid(), pvm_setmwid(). Users should switch to pvm_getminfo() and pvm_setminfo(). ------------------------------------------------------------------------ How to get it: It's just been put on netlib2.CS.UTK.EDU and will propagate to the other servers soon. From Netlib, to get a uuencoded, compressed tarfile: echo "send pvm3.3.tar.z.uu from pvm3" | mail netlib@ORNL.GOV For more information from Netlib about PVM: echo "send index from pvm3" | mail netlib@ORNL.GOV Using Xnetlib: select directory pvm3, file pvm3.3.tar.z.uu Via FTP: host netlib2.CS.UTK.EDU, login anonymous, directory /pvm3 For more information about file retrieval from netlib: finger anon@netlib2.CS.UTK.EDU Send bug reports, comments, questions to: pvm@MSR.EPM.ORNL.GOV Use newsgroup for discussion: comp.parallel.pvm ------------------------------------------------------------------------ Sincerely, The PVM research group (:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(:(: James Arthur Kohl, Ph.D. "Da Blooos Brathas?! They Keeper of the PVM Code... :-o still owe you money, Fool!" Oak Ridge National Laboratory kohlja@ornl.gov http://www.csm.ornl.gov/~kohl/ Long Live Curtis Blues!!! :):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):) ./pvm3/cygwin.mak0100644007401100000360000000426507240353005013077 0ustar kohlgopher#*****************************************************************************# # # makefile # for PVM in the Cygwin environement # #*****************************************************************************# intro: @echo @echo "This is a makefile for (re)compiling the PVM code" @echo "and/or the examples for the cygwin environment. For" @echo "generic use, you must provide one of the following inputs:" @echo @echo "make -f cygwin.mak pvm" @echo " -- will recompile and reinstall the PVM code" @echo " by compiling the libpvm, daemon," @echo " groupserver and console" @echo @echo "make -f cygwin.mak examples" @echo " -- will recompile the C examples" @echo @echo "make -f cygwin.mak all" @echo " -- will compile the items above" @echo @echo "make -f cygwin.mak clean" @echo " -- will erase the object files" @echo @echo "make -f cygwin.mak tidy" @echo " -- will erase the object and executables" @echo all: pvm examples pvm: _lib _tracer _console _pvmgs @echo "Installation complete." @echo _lib: @echo "Compiling and installing library (C) and daemon" cd src ; \ make -f cygwin.mak @echo touch _lib _tracer: @echo "Compiling and installing tracer" cd tracer ; \ make -f cygwin.mak @echo touch _tracer _console: @echo "Compiling and installing console" cd console ; \ make -f cygwin.mak @echo touch _console _pvmgs: @echo "Compiling and installing groupserver" cd pvmgs ; \ make -f cygwin.mak @echo touch _pvmgs examples: _cexamples _cexamples: @echo "Building C examples" cd examples ; \ make -f cygwin.mak c-all @echo touch _cexamples tidy: clean @echo "Cleaning Execs and Libs ..." rm -f bin/win32/*.exe rm -f console/win32/*.exe rm -f tracer/win32/*.{exe,a} rm -f lib/win32/*.{exe,a} @echo clean: @echo "Cleaning objects ..." rm -f _lib src/win32/*.o @echo "Cleaning console objects ..." rm -f _console console/win32/*.o @echo "Cleaning pvmgs objects ..." rm -f _pvmgs pvmgs/win32/*.o @echo "Cleaning tracer objects ..." rm -f _tracer tracer/win32/*.o @echo "Cleaning examples objects ..." rm -f _cexamples examples/win32/*.o @echo ./pvm3/console/0042755007401100000360000000000010117676455012563 5ustar kohlgopher./pvm3/console/cygwin.mak0100644007401100000360000000237207240354747014554 0ustar kohlgopher#*****************************************************************************# # # makefile # for the PVM console: pvm.exe # #*****************************************************************************# include $(PVM_ROOT_U)/conf/win32cygwin.def PVM_CONSOLE = $(PVM_ARCH) OBJS = $(PVM_ARCH)/cmds.o \ $(PVM_ARCH)/cons.o \ $(PVM_ARCH)/job.o \ $(PVM_ARCH)/trc.o LIBS = $(LIB) \ $(PVM_ROOT_U)/tracer/$(PVM_ARCH)/libpvmtracer.a LINK_FLAGS = -lreadline all: $(PVM_CONSOLE)/pvm.exe # $(PVM_CONSOLE)/pvm.exe: $(OBJS) $(LIBS) $(CC) -o $(PVM_CONSOLE)/pvm $(OBJS) $(LIBS) $(LINK_FLAGS) $(PVM_ARCH)/cmds.o: $(PVM_ROOT_U)/console/cmds.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ROOT_U)/console/$(PVM_ARCH)/cmds.o $(PVM_ROOT_U)/console/cmds.c $(PVM_ARCH)/cons.o: $(PVM_ROOT_U)/console/cons.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ROOT_U)/console/$(PVM_ARCH)/cons.o $(PVM_ROOT_U)/console/cons.c $(PVM_ARCH)/trc.o: $(PVM_ROOT_U)/console/trc.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ROOT_U)/console/$(PVM_ARCH)/trc.o $(PVM_ROOT_U)/console/trc.c $(PVM_ARCH)/job.o: $(PVM_ROOT_U)/console/job.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ROOT_U)/console/$(PVM_ARCH)/job.o $(PVM_ROOT_U)/console/job.c # Clean up everything but the .EXEs clean: -rm -f $(PVM_ARCH)/*.o ./pvm3/console/Makefile.aimk0100644007401100000360000000266206401337646015141 0ustar kohlgopher# # $Id: Makefile.aimk,v 1.12 1997/08/28 18:12:54 pvmsrc Exp $ # # Generic Makefile body to be concatenated to config header. # # Imports: # PVM_ARCH = the official pvm-name of your processor # ARCHCFLAGS = special cc flags # ARCHLIB = special libs needed for daemon # SHELL = /bin/sh PVMDIR = ../.. SDIR = $(PVMDIR)/console TRCDIR = $(PVMDIR)/tracer PVMIDIR = $(PVMDIR)/include PVMSDIR = $(PVMDIR)/src TRCIDIR = $(TRCDIR) PVMLDIR = $(PVMDIR)/lib/$(PVM_ARCH) TRCLDIR = $(TRCDIR)/$(PVM_ARCH) PVMLIB = pvm3 TRCLIB = pvmtrc LIBPREFIX = lib PVMLIBDEP = $(PVMLDIR)/$(LIBPREFIX)$(PVMLIB).a TRCLIBDEP = $(TRCLDIR)/$(LIBPREFIX)$(TRCLIB).a CFLAGS = $(CFLOPTS) -DIMA_$(PVM_ARCH) -I$(PVMIDIR) -I$(TRCIDIR) \ -I$(PVMSDIR) $(ARCHCFLAGS) LIBS = $(LOPT) -L$(TRCLDIR) -L$(PVMLDIR) \ -l$(TRCLIB) -l$(PVMLIB) $(ARCHLIB) OBJ = cons.o cmds.o job.o trc.o default: pvm$(EXESFX) install: $(PVMLDIR) $(PVMLDIR)/pvm$(EXESFX) $(PVMLDIR): - mkdir $(PVMLDIR) $(PVMLDIR)/pvm$(EXESFX): pvm$(EXESFX) cp pvm$(EXESFX) $(PVMLDIR) pvm$(EXESFX): $(OBJ) $(PVMLIBDEP) $(TRCLIBDEP) $(CC) $(CFLAGS) -o pvm$(EXESFX) $(OBJ) $(LIBS) cons.o: $(SDIR)/cons.c $(CC) $(CFLAGS) -c $(SDIR)/cons.c cmds.o: $(SDIR)/cmds.c $(CC) $(CFLAGS) -c $(SDIR)/cmds.c job.o: $(SDIR)/job.c $(CC) $(CFLAGS) -c $(SDIR)/job.c trc.o: $(SDIR)/trc.c $(CC) $(CFLAGS) -c $(SDIR)/trc.c clean: rm -f *.o pvm$(EXESFX) # # Source File Dependencies # include $(PVMDEPPATH)$(SDIR)/pvmdep ./pvm3/console/Makefile.mak0100644007401100000360000000305306670011636014757 0ustar kohlgopher# # $Id: Makefile.mak,v 1.8 1999/03/05 17:25:50 pvmsrc Exp $ # # Nmake file for the PVM console: pvm.exe # # PVM_ARCH = the official pvm-name of your processor # ARCHCFLAGS = special cc flags # ARCHLIB = special libs needed for daemon # !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !include $(PVM_ROOT)\conf\$(PVM_ARCH).def OBJS = $(PVM_ARCH)\cmds.obj $(PVM_ARCH)\cons.obj \ $(PVM_ARCH)\job.obj $(PVM_ARCH)\trc.obj LIBS = $(PVM_ROOT)\lib\$(PVM_ARCH)\libpvm3.lib \ $(PVM_ROOT)\tracer\$(PVM_ARCH)\libpvmtracer.lib all: paths pvm.exe # paths: if not exist $(PVM_ARCH) mkdir $(PVM_ARCH) if not exist "..\bin\$(PVM_ARCH)\$(NULL)" mkdir "..\bin\$(PVM_ARCH)" pvm.exe: $(OBJS) $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\lib\$(PVM_ARCH)\pvm.exe \ $(OBJS) $(LIBS) $(link_flags) $(PVM_ARCH)\cmds.obj: $(PVM_ROOT)\console\cmds.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\console\$(PVM_ARCH)\cmds.obj \ $(PVM_ROOT)\console\cmds.c $(PVM_ARCH)\cons.obj: $(PVM_ROOT)\console\cons.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\console\$(PVM_ARCH)\cons.obj \ $(PVM_ROOT)\console\cons.c $(PVM_ARCH)\trc.obj: $(PVM_ROOT)\console\trc.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\console\$(PVM_ARCH)\trc.obj \ $(PVM_ROOT)\console\trc.c $(PVM_ARCH)\job.obj: $(PVM_ROOT)\console\job.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\console\$(PVM_ARCH)\job.obj \ $(PVM_ROOT)\console\job.c # Clean up everything but the .EXEs clean: -del $(PVM_ARCH)\*.obj -del $(PVM_ARCH)\*.pdb ./pvm3/console/pvmdep0100644007401100000360000000230706336076173013775 0ustar kohlgopher# # *** DO NOT MODIFY *** AUTOMATICALLY GENERATED *** # # $Id: pvmdep,v 1.1 1997/05/13 14:36:43 pvmsrc Exp $ # # PVM Source Header Dependencies # cmds.o: $(PVMDIR)/include/pvm3.h cmds.o: $(PVMDIR)/include/pvmtev.h cmds.o: $(PVMDIR)/src/bfunc.h cmds.o: $(PVMDIR)/src/listmac.h cmds.o: $(PVMDIR)/tracer/trcdef.h cmds.o: $(PVMDIR)/tracer/trcproto.h cmds.o: $(PVMDIR)/tracer/trctype.h cmds.o: $(SDIR)/cmd.h cmds.o: $(SDIR)/job.h cmds.o: $(SDIR)/myalloc.h cons.o: $(PVMDIR)/include/pvm3.h cons.o: $(PVMDIR)/include/pvmtev.h cons.o: $(PVMDIR)/src/bfunc.h cons.o: $(PVMDIR)/src/listmac.h cons.o: $(PVMDIR)/tracer/trcdef.h cons.o: $(PVMDIR)/tracer/trcproto.h cons.o: $(PVMDIR)/tracer/trctype.h cons.o: $(SDIR)/cmd.h cons.o: $(SDIR)/job.h cons.o: $(SDIR)/myalloc.h job.o: $(PVMDIR)/include/pvm3.h job.o: $(PVMDIR)/include/pvmtev.h job.o: $(PVMDIR)/src/bfunc.h job.o: $(PVMDIR)/src/listmac.h job.o: $(PVMDIR)/tracer/trcdef.h job.o: $(PVMDIR)/tracer/trcproto.h job.o: $(PVMDIR)/tracer/trctype.h job.o: $(SDIR)/job.h job.o: $(SDIR)/myalloc.h trc.o: $(PVMDIR)/include/pvm3.h trc.o: $(PVMDIR)/include/pvmtev.h trc.o: $(PVMDIR)/tracer/trcdef.h trc.o: $(PVMDIR)/tracer/trcproto.h trc.o: $(PVMDIR)/tracer/trctype.h trc.o: $(SDIR)/job.h ./pvm3/console/cmds.c0100644007401100000360000016664210001307174013644 0ustar kohlgopher static char rcsid[] = "$Id: cmds.c,v 1.45 2004/01/14 18:46:20 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * cmds.c * * PVM console commands. * * $Log: cmds.c,v $ * Revision 1.45 2004/01/14 18:46:20 pvmsrc * Added new AIX5* arches. * (Spanker=kohl) * * Revision 1.44 2001/09/26 23:37:22 pvmsrc * Made hd_vmid additions to hostd mirror struct... * - don't know if this is really necessary, but wtf. * (Spanker=kohl) * * Revision 1.43 2001/09/25 21:18:13 pvmsrc * Minor TMPNAMFUN()/tmpnam() cleanup. * - moved macro def to pvm3.h, renamed PVMTNPMAN(). * - same for LEN_OF_TMP_NAM -> PVMTMPNAMLEN. * - mostly a huge waste of time, since *both* tmpnam() & mktemp() * produce the same "dangerous" warning message in Linux/gcc... * - damn. * (Spanker=kohl) * * Revision 1.42 2001/08/17 20:18:32 pvmsrc * Added --host= option to spawn command. * - allows passing IP address in place of host name. * - used gnu-like syntax at Paul Gray's suggestion... :-) * (Spanker=kohl) * * Revision 1.41 2001/07/30 17:46:08 pvmsrc * O.K., Paul's bug was legit. Some goofy (Mandrake) Linux passes * stderr back through rsh... * - weed out lines with stuff like "/bin/ls: ... No such file..." * (Spanker=kohl) * * Revision 1.40 2001/07/30 16:52:00 pvmsrc * Minor cleanup to auto-diag routine... * - slightly more solid checking for leftover /tmp/pvmd.* files. * - inspired by a pseudo-bug report from Paul Gray, could be bogus... * :-) * (Spanker=kohl) * * Revision 1.39 2001/07/30 16:02:31 pvmsrc * epm -> csm... * (Spanker=kohl) * * Revision 1.38 2001/04/23 14:41:41 pvmsrc * Tweaked spawn_cmd() parsing to allow -:wd working directory spec. * - i.e. without a host or arch specified... * - fixed help spawn text. * (Spanker=kohl) * * Revision 1.37 2001/02/02 17:05:50 pvmsrc * Fixed typo in Win32 diagnostic message output. * (Spanker=kohl) * * Revision 1.36 2000/03/29 20:01:40 pvmsrc * Stoopid typo... :-Q * (Spanker=kohl) * * Revision 1.35 2000/02/18 22:01:42 pvmsrc * Cleaned up Windows side of diagnose_cant_start_pvm()... * - lose any '\r' at end of rsh output. * - use "chdir" instead of "pwd" for Windows O.S. check. * - minor typos... * (Spanker=kohl) * * Revision 1.34 2000/02/15 18:06:20 pvmsrc * Modified jobs_cmd() to dump task ids for traced jobs... * - can't use output buffers, must use TRC_ID->tevtask_list list. * - snagged necessary state constants from trclib.h, can't just * #include it, as it #includes fricking everything... :-Q * (Spanker=kohl) * * Revision 1.33 2000/02/15 17:06:42 pvmsrc * Added new getopt / setopt console commands. * - for setting PVM console task's PVM options (like PvmShowTids). * Fixed debug flags in tickle help. * (Spanker=kohl) * * Revision 1.32 2000/02/14 20:30:59 pvmsrc * Lose #define-d RSHCOMMAND usage. * - use new pvmgetrsh() routine, which checks for PVM_RSH or else * uses old RSHCOMMAND interface. * (Spanker=kohl) * * Revision 1.31 2000/02/10 22:17:38 pvmsrc * Cleaned up diagnose_cant_start_pvmd() test routine a bunch. * - replaced gobs of inline code with new do_rsh_cmd() routine. * - added new check_env_var() routine to sort through extra * garbage in rsh commands when checking env vars... * (Spanker=kohl) * * Revision 1.30 2000/02/10 20:43:37 pvmsrc * Added checking for new PVM_TMP env var on remote host. * - in diagnose_cant_start_pvm()... * - use in place of hard-coded /tmp or \TEMP... * (Spanker=kohl) * * Revision 1.29 2000/01/26 23:34:17 pvmsrc * *** Added Killer Routine of All Time - diagnose_cant_start_pvm() *** * Nearly 800 lines of pure joy! :-D * - on "Can't start pvmd" error, tries to rsh to host and checks * everything from rhosts to $PVM_ROOT to /tmp/pmvd.* crap files. * - should theoretically work on both Unix and Windows machines, * for both Unix and Windows remote hosts (tested for Unix :-). * - with any luck this will cut bug mail in half... yeah right. * (Spanker=kohl) * * Revision 1.28 1999/07/08 18:59:39 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.27 1999/06/11 17:27:35 pvmsrc * When breaking up multiline commands into subcommands, * dump out each command as you execute it, along with a fresh prompt. * (Spanker=kohl) * * Revision 1.26 1999/06/10 16:57:16 pvmsrc * Fixed docmd() to handle commands with '\n's in them... * - a la file input redirection, cut & paste, etc. * - break string into individual commands and execute. * (Spanker=kohl) * * Revision 1.25 1999/02/05 20:36:17 pvmsrc * More contributions from Edward Vigmond . * - better readline interface, with command completion & help. * (Spanker=kohl) * * Revision 1.24 1998/11/20 19:43:07 pvmsrc * Changes so that win32 will compile & build. Also, common * source for win32 & unix. * (Spanker=sscott) * * Revision 1.23 1998/01/28 23:03:39 pvmsrc * Fixed tracing bogusness! * - host add / del notifies for tracing were getting scrunched by * console host add notify, etc... * - moved message / notify tag constants to job.h and USED THEM. * - initialized nextjob properly... * - added new "joboffset" global in cons.c for dumping more * reasonable job numbers to user. * (Spanker=kohl) * * Revision 1.22 1997/12/31 22:13:15 pvmsrc * Updated "xpvm" trace mask settings. * (Spanker=kohl) * * Revision 1.21 1997/08/29 16:56:53 pvmsrc * Added TEV_USER_DEFINED to "xpvm" default trace mask settings... * (Spanker=kohl) * * Revision 1.20 1997/07/09 13:21:03 pvmsrc * Fixed Author Header. * * Revision 1.19 1997/05/13 14:37:38 pvmsrc * Changed header file $includes: * - ../src/listmac.h -> listmac.h * - ../src/bfunc.h -> bfunc.h * - use -I$(PVMDIR)/src in Makefile.aimk instead. * * Revision 1.18 1997/05/02 20:18:51 pvmsrc * D-Oh. * * Revision 1.17 1997/05/01 15:41:14 pvmsrc * SGI Compiler Warning Cleanup. * * Revision 1.16 1997/04/30 21:15:35 pvmsrc * SGI Compiler Warning Cleanup. * * Revision 1.15 1997/04/17 12:53:15 pvmsrc * rename of pvm_mboxinfo() to include word "get" * * Revision 1.14 1997/04/10 20:34:35 pvmsrc * "CVS": Modified Files: * Typo... * * Revision 1.13 1997/04/10 20:09:33 pvmsrc * Rewrote names_cmd() for new pvm_mboxinfo() syntax. * - pvm_getnames() is history. * * Revision 1.12 1997/04/09 20:18:13 pvmsrc * Minor fixes (like being able to actually pass args to "reset"... :-). * * Revision 1.11 1997/04/09 19:53:12 pvmsrc * Merged resetinfo_cmd() command into reset_cmd() routine. * - check for args, adjust calling parms to pvmreset()... * * Revision 1.10 1997/04/09 18:31:58 pvmsrc * Added new "resetinfo" command. * - like a reset, but without all the task bloodshed... :-)~ * * Revision 1.9 1997/04/08 17:08:46 pvmsrc * Extracted guts of reset_cmd() routine: * - created new system pvmreset() routine for general usage. * * Revision 1.8 1997/04/01 19:35:44 pvmsrc * Corrected flag to PvmMbox... * * Revision 1.7 1997/04/01 17:04:45 pvmsrc * Updated mbox stuff: * - changed args of pvm_putinfo(). * - renamed pvm_getinfo() (again) -> pvm_recvinfo(), w/ new syntax. * * Revision 1.6 1997/03/27 20:09:51 pvmsrc * Added PvmNoSpawnParent to pvm_spawn() calls in spawn_cmd(). * * Revision 1.5 1997/02/17 16:29:04 pvmsrc * Added checking of pvm_getnoresets() list in reset_cmd(). * * Revision 1.4 1997/01/28 19:13:17 pvmsrc * New Copyright Notice & Authors. * * Revision 1.3 1996/10/24 23:03:39 pvmsrc * Updated to new tracing facilty. * - new trace_cmd() options: * * "xpvm" mask mimick. * * "buf" trace buffer size query & set. * * "opt" trace options query & set. * - new job creation handling for spawn command, * tracing vs. output vs. both... * - installed new trc_print_tmask() library call for trace mask dump. * * Revision 1.2 1996/10/08 18:29:39 pvmsrc * Renamed routines: * - pvm_put() -> pvm_putinfo(). * - pvm_get() -> pvm_getinfo(). * * Revision 1.1 1996/09/23 20:25:35 pvmsrc * Initial revision * * Revision 1.8 1995/11/02 15:11:40 manchek * added to tickle help * * Revision 1.7 1995/09/05 19:06:52 manchek * help text lowercase * * Revision 1.6 1995/07/03 18:59:51 manchek * help text * * Revision 1.5 1995/07/03 18:57:29 manchek * added ps 's' flag, tickle help 100. * ps doesn't print tasks with tid 0 unless -x flag used * * Revision 1.4 1995/05/17 15:26:17 manchek * added "return 0" to lots of commands. * added idump command * * Revision 1.3 1994/10/15 18:38:56 manchek * updated task flags and ps list headers * * Revision 1.2 1994/06/03 20:01:51 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:30:32 manchek * Initial revision * */ #include #include #ifdef SYSVSTR #include #else #include #endif #include #include #include #include #include #include "cmd.h" #include "myalloc.h" #include "listmac.h" #include "bfunc.h" #include "job.h" #ifndef WIN32 #include #endif #define PVMERRMSG(n) ((n) <= 0 && (n) > -pvm_nerr \ ? pvm_errlist[-(n)] : "Unknown Error") char *getenv(); void i_dump(); extern char **environ; extern char *pvm_errlist[]; extern int pvm_nerr; extern struct Pvmtevinfo pvmtevinfo[]; extern char *prompt; int add_cmd(); int alias_cmd(); int conf_cmd(); int delete_cmd(); int echo_cmd(); int export_cmd(); int getopt_cmd(); int halt_cmd(); int help_cmd(); int id_cmd(); int idump_cmd(); /* int insert_cmd(); */ int jobs_cmd(); int kill_cmd(); /* int lookup_cmd(); */ int mstat_cmd(); int names_cmd(); int quit_cmd(); int pstat_cmd(); int put_cmd(); /* int remove_cmd(); */ int reset_cmd(); int setenv_cmd(); int setopt_cmd(); int sig_cmd(); int spawn_cmd(); int start_cmd(); int tasks_cmd(); int tickle_cmd(); int trace_cmd(); int unalias_cmd(); int unexport_cmd(); int version_cmd(); extern struct alias *aliases; /* from cons.c */ extern struct pvmhostinfo *hostlist; /* from cons.c */ extern struct job *joblist; /* from job.c */ extern int mytid; /* from cons.c */ extern int narchs; /* from cons.c */ extern int joboffset; /* from cons.c */ extern int nextjob; /* from cons.c */ extern int nhosts; /* from cons.c */ struct cmdsw commands[] = { { "add", 2, 0, add_cmd }, { "alias", 1, 0, alias_cmd }, { "conf", 1, 1, conf_cmd }, { "delete", 2, 0, delete_cmd }, { "echo", 1, 0, echo_cmd }, { "export", 1, 0, export_cmd }, { "getopt", 1, 2, getopt_cmd }, { "halt", 1, 1, halt_cmd }, { "help", 1, 2, help_cmd }, { "id", 1, 1, id_cmd }, { "idump", 1, 2, idump_cmd }, /* { "insert", 4, 4, insert_cmd }, */ { "jobs", 1, 2, jobs_cmd }, { "kill", 2, 0, kill_cmd }, /* { "lookup", 3, 3, lookup_cmd }, */ { "mstat", 2, 0, mstat_cmd }, { "names", 1, 2, names_cmd }, { "ps", 1, 2, tasks_cmd }, { "pstat", 2, 0, pstat_cmd }, { "put", 4, 4, put_cmd }, { "quit", 1, 1, quit_cmd }, /* { "remove", 3, 3, remove_cmd }, */ { "reset", 1, 4, reset_cmd }, { "setenv", 1, 0, setenv_cmd }, { "setopt", 3, 3, setopt_cmd }, { "sig", 3, 0, sig_cmd }, { "spawn", 2, 0, spawn_cmd }, { "trace", 1, 0, trace_cmd }, { "tickle", 2, 11, tickle_cmd }, { "unalias", 2, 0, unalias_cmd }, { "unexport", 1, 0, unexport_cmd }, { "version", 1, 1, version_cmd }, { 0, 0, 0, 0 } }; /* Host descriptor (pieces lifted from pvm3/src/host.h - pvmd stuff) */ struct hostd { int hd_ref; /* num refs to this struct */ int hd_hostpart; /* host tid base */ char *hd_name; /* name */ char *hd_arch; /* cpu arch class */ char *hd_login; /* loginname [used master only] */ char *hd_dpath; /* daemon executable */ char *hd_epath; /* task exec search path */ char *hd_bpath; /* debugger executable */ char *hd_wdir; /* pvmd working dir */ char *hd_sopts; /* hoster options */ int hd_flag; int hd_dsig; /* data signature */ int hd_err; /* error code */ int hd_mtu; /* max snd/rcv length */ /* struct sockaddr_in hd_sad; /^ UDP address/port */ int hd_rxseq; /* expected next seq num from host */ int hd_txseq; /* next tx seq num to host */ /* struct pkt *hd_txq; /^ not-yet-sent packet queue to host */ /* struct pkt *hd_opq; /^ outstanding packets to host */ int hd_nop; /* length of opq */ /* struct pkt *hd_rxq; /^ packet reordering queue from host */ /* struct pmsg *hd_rxm; /^ to-us msg reassembly from host */ /* struct timeval hd_rtt; /^ estd round-trip time to host */ int hd_speed; /* cpu relative speed */ /* struct mca *hd_mcas; /^ from-host mca cache */ char *hd_aname; /* name to use for network address */ char *hd_vmid; /* virtual machine id for host */ }; freealias(ap) struct alias *ap; { LISTDELETE(ap, a_link, a_rlink); MY_FREE(ap->a_name); while (ap->a_num-- > 0) MY_FREE(ap->a_args[ap->a_num]); MY_FREE(ap->a_args); MY_FREE(ap); return 0; } struct alias * newalias(name, num, args) char *name; int num; char **args; { struct alias *ap, *ap2; ap = TALLOC(1, struct alias, "alias"); ap->a_name = STRALLOC(name); ap->a_args = TALLOC(num + 1, char *, "aargs"); ap->a_num = num; while (num-- > 0) ap->a_args[num] = STRALLOC(args[num]); for (ap2 = aliases->a_link; ap2 != aliases; ap2 = ap2->a_link) if (strcmp(ap2->a_name, name) > 0) break; LISTPUTBEFORE(ap2, ap, a_link, a_rlink); return ap; } struct alias * findalias(name) char *name; { struct alias *ap; for (ap = aliases->a_link; ap != aliases; ap = ap->a_link) if (!strcmp(ap->a_name, name)) return ap; return (struct alias*)0; } docmd(cmd) char *cmd; { char *p; struct cmdsw *csp; struct alias *ap; int i; int ac; char *av[128]; int self; char *nextcmd = NULL; int first = 1; /* * check for '\n's in command, separate commands */ nextcmd = cmd; do { /* * look for a newline... */ cmd = nextcmd; while ( *nextcmd != '\0' && *nextcmd != '\n' ) nextcmd++; if ( *nextcmd == '\n' ) { *nextcmd++ = '\0'; if ( !first ) printf( prompt ); else first = 0; printf( "%s\n", cmd ); } /* * parse command */ ac = sizeof(av)/sizeof(av[0]) - 1; if (acav(cmd, &ac, av)) { fputs("command too long\n", stdout); return 0; } if (!ac) return 0; /* * resolve aliases */ for (ap = aliases->a_link; ap != aliases; ap = ap->a_link) ap->a_flag = 0; while (ap = findalias(av[0])) { if (ap->a_flag) { printf("alias loop\n"); return 0; } ap->a_flag = 1; if (ap->a_num > 1) { if (ac + ap->a_num > sizeof(av)/sizeof(av[0])) { fputs("command too long\n", stdout); return 0; } for (i = ac; --i > 0; ) av[i + ap->a_num - 1] = av[i]; ac += ap->a_num - 1; } self = !strcmp(av[0], ap->a_args[0]); for (i = ap->a_num; i-- > 0; ) av[i] = ap->a_args[i]; if (self) break; } /* * find command and call it */ av[ac] = 0; p = av[0]; for (csp = commands; csp->cmd; csp++) { if (!strcmp(csp->cmd, p)) { if (ac >= csp->a1 && (ac <= csp->a2 || !csp->a2)) (csp->fun)(ac, av); else printf("%s: wrong #args\n", p); break; } } if (!csp->cmd) printf("%s: not found\n", p); } while ( *nextcmd != '\0' ); return 0; } /**************** ** Commands ** ** ** ****************/ add_cmd(ac, av) int ac; char **av; { int diagnose = 0; int cc; int *sv; int i; av++; ac--; sv = TALLOC(ac, int, "int"); if ((cc = pvm_addhosts(av, ac, sv)) >= 0) { if (cc > 0) pvm_recv(-1, HostsAddedTag); /* waste the notify message */ printf("%d successful\n", cc); fputs(" HOST DTID\n", stdout); for (i = 0; i < ac; i++) if ((cc = sv[i]) < 0) { printf("%24s %8s\n", av[i], PVMERRMSG(cc)); if (cc == PvmCantStart) diagnose++; } else printf("%24s %8x\n", av[i], cc); /* Try to Further Diagnose "PvmCantStart" Cases... */ /* Otherwise, sure to generate MORE BUG MAIL!!! :-Q */ if ( diagnose ) { printf( "\nAuto-Diagnosing Failed Hosts...\n" ); for (i = 0; i < ac; i++) { if (sv[i] == PvmCantStart) { printf( "%s...\n", av[i] ); diagnose_cant_start_pvm( av[i] ); printf( "\n" ); } } } } MY_FREE(sv); pvm_config(&nhosts, &narchs, &hostlist); return 0; } diagnose_cant_start_pvm( hostline ) char *hostline; { FILE *fp; #ifndef WIN32 struct passwd *pw; #endif struct hostd hp; struct stat statck; char lhost[1024]; char pvmarch[1024]; char pvmroot[1024]; char pvmtmp[1024]; char result[1024]; char result2[1024]; char tcmd[1024]; char tmp[255]; char user[1024]; int remote_os = -1; int len; int i; /* Extract Raw Host Name from Add Command */ if ( parsehost(hostline, &hp) < 0 ) { printf( "Error Parsing Host String!\n" ); printf( "Cannot Auto-Diagnose!\n" ); return( 0 ); } /* Get Local Hostname */ gethostname( lhost, 1024 ); /* Get Local User */ #ifndef WIN32 if ( (pw = getpwuid( getuid() )) != NULL ) strcpy( user, pw->pw_name ); else strcpy( user, "" ); #else strcpy( user, MyGetUserName() ); #endif /* Ping / Timeout Test */ /* * Maybe later - for now rsh returns "Connection timed out" * printf( "Pinging Host \"%s\"...\n", hp.hd_name ); sprintf( tcmd, "ping -c 1 %s 1>%s 2>&1", hp.hd_name, tfile ); system( tcmd ); fp = fopen( tfile, "r" ); if ( fp != NULL ) { while ( fgets( result, 1024, fp ) != NULL ) { printf( "%s\n", result ); } fclose( fp ); } else printf( "Ping Command Failed - Test Skipped...\n" ); unlink( tfile ); */ /* Verify Rsh Path */ printf( "Verifying Local Path to \"rsh\"...\n" ); strcpy( tcmd, pvmgetrsh() ); if ( stat( tcmd, &statck ) < 0 ) { printf( "\nError - File %s Not Found!\n", tcmd ); #ifndef WIN32 printf( "Use \"whereis rsh\" or \"which rsh\" to determine\n" ); printf( "where \"rsh\" is on your system and modify the\n" ); printf( "$PVM_ROOT/conf/$PVM_ARCH.def configuration file\n" ); #else printf( "Determine the path to the \"rsh\" command on your\n" ); printf( "system, and edit %PVM_ROOT%\\conf\\WIN32.def\n" ); #endif printf( "to adjust the path for the -DRSHCOMMAND=\\\"\\\"\n" ); printf( "flag. Then recompile PVM and your applications.\n" ); return( 0 ); } else printf( "Rsh found in %s - O.K.\n", tcmd ); /* Rsh Test */ if ( do_rsh_cmd( &hp, "Testing Rsh/Rhosts Access to", "echo YES", result, 1024 ) ) { /* check result */ if ( !strncmp( result, "YES", 3 ) ) printf( "Rsh/Rhosts Access is O.K.\n" ); else { printf( "\nRsh/Rhosts Access FAILED - \"%s\"\n", result ); printf( "Make sure host %s is up and connected to\n", hp.hd_name ); printf( "a network and check its DNS / IP address.\n" ); printf( "Also verify that %s is allowed\n", lhost ); printf( "rsh access on %s\n", hp.hd_name ); printf( "Add this line to the $HOME/.rhosts on %s:\n", hp.hd_name ); printf( "%s %s\n", lhost, user ); return( 0 ); } } else return( 0 ); /* Is Remote Host O.S. Windows or Unix? */ if ( do_rsh_cmd( &hp, "Checking O.S. Type (Unix test) on", "pwd", result, 1024 ) ) { /* Unix-land */ if ( result[0] == '/' ) { printf( "Host %s is Unix-based.\n", hp.hd_name ); remote_os = 0; } else if ( do_rsh_cmd( &hp, "Checking O.S. Type (Win test) on", "chdir", result2, 1024 ) ) { /* Windows-land */ len = strlen( result2 ); if ( len >= 3 && result2[0] >= 'A' && result2[0] <= 'Z' && result2[1] == ':' && result2[2] == '\\' ) { printf( "Host %s is Windows-based.\n", hp.hd_name ); remote_os = 1; } /* Hmmm... Go Figure. */ else { len = strlen( result ); for ( i=0 ; i < len - 1 && remote_os < 0 ; i++ ) { if ( result[i] == '/' ) { printf( "Assuming Host %s to be Unix-based.\n", hp.hd_name ); remote_os = 0; } else if ( result[0] == '\\' ) { printf( "Assuming Host %s to be Windows-based.\n", hp.hd_name ); remote_os = 1; } } if ( remote_os < 0 ) { len = strlen( result2 ); if ( !len ) { printf( "Assuming Host %s to be Unix-based.\n", hp.hd_name ); remote_os = 0; } else { for ( i=0 ; i < len - 1 && remote_os < 0 ; i++ ) { if ( result2[i] == '/' ) { printf( "Assuming Host %s to be Unix-based.\n", hp.hd_name ); remote_os = 0; } else if ( result2[0] == '\\' ) { printf( "Assuming Host %s to be Windows-based.\n", hp.hd_name ); remote_os = 1; } } } } if ( remote_os < 0 ) { printf( "Error - Cannot Determine Remote O.S.!\n" ); printf( "Can't Auto-Diagnose.\n" ); return( 0 ); } } } } else return( 0 ); /* PVM_ROOT Test */ if ( do_rsh_cmd( &hp, ( remote_os == 0 ) ? "Checking $PVM_ROOT on" : "Checking %PVM_ROOT% on", ( remote_os == 0 ) ? "echo $PVM_ROOT" : "echo %PVM_ROOT%", result, 1024 ) ) { /* check for undefined variable (Unix) */ if ( remote_os == 0 && !check_env_var( "PVM_ROOT", result ) ) { printf( "\nThe $PVM_ROOT Environment Variable is Not Set!\n" ); printf( "Use one of the shell *.stub files in\n" ); printf( "the pvm3/lib directory to set up the\n" ); printf( "PVM environment on host %s.\n", hp.hd_name ); return( 0 ); } /* check for undefined variable (Windows) */ else if ( remote_os == 1 && !strncmp( result, "ECHO", 4 ) ) { printf( "\nThe %%PVM_ROOT%% Environment Variable is Not Set!\n" ); printf( "Check your PVM installation on host %s or\n", hp.hd_name ); printf( "set the %%PVM_ROOT%% environment variable\n" ); printf( "in the C:\\AUTOEXEC.BAT file to point to\n" ); printf( "PVM3.4 directory:\n" ); printf( "set PVM_ROOT = C:\\PVM3.4\n" ); return( 0 ); } /* check for bogus relative path (Unix) */ else if ( remote_os == 0 && result[0] != '/' ) { printf( "\nThe value of the $PVM_ROOT environment\n" ); printf( "variable on %s is invalid (\"%s\").\n", hp.hd_name, result ); printf( "Use the absolute path to the pvm3/ directory.\n" ); return( 0 ); } /* check for bogus relative path (Windows) */ else if ( remote_os == 1 && ( result[1] != ':' || result[2] != '\\' ) ) { printf( "\nThe value of the %%PVM_ROOT%% environment\n" ); printf( "variable on %s is invalid (\"%s\").\n", hp.hd_name, result ); printf( "Use the absolute path to the PVM3.4 directory.\n" ); return( 0 ); } /* appears to be O.K., fall through to next test */ else { strcpy( pvmroot, result ); printf( "%sPVM_ROOT%s on %s Appears O.K. (\"%s\")\n", ( remote_os == 0 ) ? "$" : "%", ( remote_os == 0 ) ? "" : "%", hp.hd_name, pvmroot ); } } else return( 0 ); /* Pvmd Script Existence Test (a.k.a. $PVM_ROOT Validity Test) */ if ( do_rsh_cmd( &hp, "Verifying Location of PVM Daemon Script on", ( remote_os == 0 ) ? "\\ls $PVM_ROOT/lib/pvmd" : "dir /B /L %PVM_ROOT%\\lib\\pvmd.bat", result, 1024 ) ) { /* expected pvmd script path */ if ( remote_os == 0 ) sprintf( tmp, "%s/lib/pvmd", pvmroot ); else sprintf( tmp, "pvmd.bat" ); /* check existence of pvmd script */ if ( strcmp( result, tmp ) ) { printf( "\nPVM Daemon Script \"%s\"\n", tmp ); printf( "Was Not Found on %s\n", hp.hd_name ); printf( "Please check the setting of %sPVM_ROOT%s...\n", ( remote_os == 0 ) ? "$" : "%", ( remote_os == 0 ) ? "" : "%" ); return( 0 ); } else printf( "PVM Daemon Script Found (\"%s\")\n", tmp ); } else return( 0 ); /* Determine Remote Host Architecture */ if ( do_rsh_cmd( &hp, "Determining PVM Architecture on", ( remote_os == 0 ) ? "echo $PVM_ARCH" : "echo %PVM_ARCH%", result, 1024 ) ) { /* check for undefined variable */ if ( ( remote_os == 0 && check_env_var( "PVM_ARCH", result ) ) || ( remote_os == 1 && strncmp( result, "ECHO", 4 ) ) ) { printf( "%sPVM_ARCH%s on %s set to %s\n", ( remote_os == 0 ) ? "$" : "%", ( remote_os == 0 ) ? "" : "%", hp.hd_name, result ); strcpy( pvmarch, result ); } else { printf( "%sPVM_ARCH%s not set on %s\n", ( remote_os == 0 ) ? "$" : "%", ( remote_os == 0 ) ? "" : "%", hp.hd_name ); if ( remote_os == 1 ) { printf( "Assuming WIN32.\n" ); strcpy( pvmarch, "WIN32" ); } else pvmarch[0] = '\0'; } } else return( 0 ); /* Manually Determine Remote Host Architecture (Unix Only) */ if ( remote_os == 0 && pvmarch[0] == '\0' ) { if ( do_rsh_cmd( &hp, "Manually Determining PVM Architecture on", "$PVM_ROOT/lib/pvmgetarch", result, 1024 ) ) { len = strlen( result ); /* sanity check */ if ( len > 1 ) { printf( "$PVM_ARCH for %s is %s.\n", hp.hd_name, result ); strcpy( pvmarch, result ); } else { printf( "Could Not Determine $PVM_ARCH.\n" ); printf( "Can't Further Auto-Diagnose.\n" ); return( 0 ); } } else return( 0 ); } /* Existence of pvmd3 Executable? */ if ( remote_os == 0 ) sprintf( tmp, "\\ls $PVM_ROOT/lib/%s/pvmd3", pvmarch ); else sprintf( tmp, "dir /B /L %%PVM_ROOT%%\\lib\\%s\\pvmd3.exe", pvmarch ); if ( do_rsh_cmd( &hp, "Verifying Existence of PVM Daemon Executable on", tmp, result, 1024 ) ) { /* expected pvmd executable path */ if ( remote_os == 0 ) sprintf( tmp, "%s/lib/%s/pvmd3", pvmroot, pvmarch ); else sprintf( tmp, "pvmd3.exe" ); /* check existence of pvmd executable */ if ( strcmp( result, tmp ) ) { printf( "\nPVM Daemon Executable \"%s\"\n", tmp ); printf( "Was Not Found on %s!\n", hp.hd_name ); printf( "Has PVM been compiled there?\n" ); return( 0 ); } else printf( "PVM Daemon Executable Found (\"%s\")\n", tmp ); } else return( 0 ); /* Determine Remote Host Temp Directory (if set) */ if ( do_rsh_cmd( &hp, "Determining PVM Temporary Directory on", ( remote_os == 0 ) ? "echo $PVM_TMP" : "echo %PVM_TMP%", result, 1024 ) ) { /* check for undefined variable */ if ( ( remote_os == 0 && check_env_var( "PVM_TMP", result ) ) || ( remote_os == 1 && strncmp( result, "ECHO", 4 ) ) ) { printf( "%sPVM_TMP%s on %s set to %s\n", ( remote_os == 0 ) ? "$" : "%", ( remote_os == 0 ) ? "" : "%", hp.hd_name, result ); strcpy( pvmtmp, result ); } else { printf( "%sPVM_TMP%s not set on %s\n", ( remote_os == 0 ) ? "$" : "%", ( remote_os == 0 ) ? "" : "%", hp.hd_name ); if ( remote_os == 1 ) { printf( "Assuming C:\\TEMP.\n" ); strcpy( pvmtmp, "C:\\TEMP" ); } else { printf( "Assuming /tmp.\n" ); strcpy( pvmtmp, "/tmp" ); } } } else return( 0 ); /* Pvmd Already Running There / Leftover Pvmd Files? */ if ( remote_os == 0 ) sprintf( tmp, "\\ls -l %s/pvmd.* | grep %s", pvmtmp, ( hp.hd_login != NULL ) ? hp.hd_login : user ); else /* should really also check %TEMP% */ sprintf( tmp, "dir /B /L %s\\pvmd.%s", pvmtmp, ( hp.hd_login != NULL ) ? hp.hd_login : user ); if ( do_rsh_cmd( &hp, "Checking for Leftover PVM Daemon Files on", tmp, result, 1024 ) ) { len = strlen( result ); /* Find Any? (Unix) */ if ( remote_os == 0 ) { /* search for a '/pvmd', if found assume a hit */ for ( i=0 ; i < len - 1 ; i++ ) { /* bail out if "/bin/ls: ... No such file..." */ if ( !strncmp( result + i, "ls:", 3 ) ) break; else if ( !strncmp( result + i, "/pvmd.", 6 ) ) { printf( "\nPVM Daemon Files Found on %s!\n", hp.hd_name ); printf( "PVM Could Already Be Running or else it\n" ); printf( "crashed and left behind a %s/pvmd.\n", pvmtmp ); printf( "daemon file.\n" ); printf( "Halt PVM if it is running on %s, or else\n", hp.hd_name ); printf( "remove any leftover %s/pvmd.* files.\n", pvmtmp ); return( 0 ); } } printf( "No PVM Daemon Files Found.\n" ); } /* Find Any? (Windows) */ else if ( remote_os == 1 && !strncmp( result, "pvmd", 4 ) ) { printf( "\nPVM Daemon Files Found on %s!\n", hp.hd_name ); printf( "Either PVM is Already Running or else it\n" ); printf( "crashed and left behind a \\TEMP\\pvmd.%s\n", ( hp.hd_login != NULL ) ? hp.hd_login : user ); printf( "daemon file.\n" ); printf( "Halt PVM if it is running on %s, or else\n", hp.hd_name ); printf( "remove any leftover \\TEMP\\pvmd.* files.\n" ); return( 0 ); } /* No Pvmd Files, O.K.? */ else printf( "No PVM Daemon Files Found.\n" ); } else return( 0 ); /* Hmmm... Must Be O.K. (ha ha ha) */ printf( "\nHost %s Appears to Be Correctly Configured.\n", hp.hd_name ); #ifndef WIN32 printf( "Please check your local %s/pvml.%d log file\n", pvmgettmp(), getuid() ); #else printf( "Please check your local %s\\pvml.%s log file\n", pvmgettmp(), user ); #endif printf( "for error messages, or else email \"%s\" for\n", "pvm@msr.csm.ornl.gov" ); printf( "further assistance.\n" ); return( 1 ); } do_rsh_cmd( hp, label, cmd, result, rsize ) struct hostd *hp; char *label; char *cmd; char *result; int rsize; { FILE *fp; char tfile[1024]; char tcmd[1024]; char tmp[255]; int ret = 1; int len; /* Generate Temporary File for Test Output */ (void)PVMTMPNAMFUN(tfile); /* Dump Test Label */ printf( "%s Host \"%s\"...\n", label, hp->hd_name ); /* Construct Rsh Command */ sprintf( tcmd, "%s ", pvmgetrsh() ); if ( hp->hd_login != NULL ) { sprintf( tmp, "-l %s ", hp->hd_login ); strcat( tcmd, tmp ); } sprintf( tmp, "%s '%s' ", hp->hd_name, cmd ); strcat( tcmd, tmp ); #ifndef WIN32 sprintf( tmp, "1>%s 2>&1", tfile ); #else sprintf( tmp, "> %s", tfile ); #endif strcat( tcmd, tmp ); /* Execute Rsh Command */ system( tcmd ); /* Collect Rsh Command Results */ fp = fopen( tfile, "r" ); if ( fp != NULL ) { if ( fgets( result, rsize, fp ) != NULL ) { /* strip off '\n' */ len = strlen( result ); if ( len > 0 && result[ len - 1 ] == '\n' ) result[ len - 1 ] = '\0'; /* strip off any '\r' */ len = strlen( result ); if ( len > 0 && result[ len - 1 ] == '\r' ) result[ len - 1 ] = '\0'; } else { printf( "Error Parsing Output - Can't Auto-Diagnose.\n" ); ret = 0; } fclose( fp ); } else { printf( "Rsh Command Failed - Check Your Execution Path!\n" ); ret = 0; } unlink( tfile ); return( ret ); } check_env_var( name, result ) char *name; char *result; { char *ptr; int nlen = strlen( name ); /* Standard "FOO - Undefined variable" Response? */ if ( !strncmp( result, name, nlen ) ) return( 0 ); /* Check for preceding garbage before standard response */ ptr = result + 1; while ( *ptr != '\0' && strlen( ptr ) >= nlen ) { if ( !strncmp( ptr, name, nlen ) ) return( 0 ); ptr++; } /* Look for "[Uu]ndefined" in result... */ ptr = result; while ( *ptr != '\0' && strlen( ptr ) >= 9 ) { if ( !strncmp( ptr, "Undefined", nlen ) || !strncmp( ptr, "undefined", nlen ) ) return( 0 ); ptr++; } /* Must Be O.K. */ return( 1 ); } /* parsehost() * * Parse hostfile line into hostd. * (lifted from pvm3/src/host.c - pvmd code... hacked a little :-) */ int parsehost(buf, hp) char *buf; struct hostd *hp; { char *av[10]; /* parsed words */ int ac; int err = 0; ac = sizeof(av)/sizeof(av[0]); if (acav(buf, &ac, av)) { printf("parsehost(): line too long\n"); goto bad; } if (!ac) goto bad; /* Initialize Host Struct Fields */ hp->hd_name = (char *) NULL; hp->hd_arch = (char *) NULL; hp->hd_login = (char *) NULL; hp->hd_dpath = (char *) NULL; hp->hd_epath = (char *) NULL; hp->hd_bpath = (char *) NULL; hp->hd_wdir = (char *) NULL; hp->hd_sopts = (char *) NULL; hp->hd_vmid = (char *) NULL; /* add options to host descriptor */ while (--ac > 0) { if (!strncmp(av[ac], "lo=", 3)) { if (hp->hd_login) MY_FREE(hp->hd_login); hp->hd_login = STRALLOC(av[ac] + 3); continue; } if (!strncmp(av[ac], "dx=", 3)) { if (hp->hd_dpath) MY_FREE(hp->hd_dpath); hp->hd_dpath = STRALLOC(av[ac] + 3); continue; } if (!strncmp(av[ac], "ep=", 3)) { if (hp->hd_epath) MY_FREE(hp->hd_epath); hp->hd_epath = STRALLOC(av[ac] + 3); continue; } if (!strncmp(av[ac], "sp=", 3)) { hp->hd_speed = atoi(av[ac] + 3); /* hp->hd_flag |= HF_SPEED; */ continue; } if (!strncmp(av[ac], "bx=", 3)) { if (hp->hd_bpath) MY_FREE(hp->hd_bpath); hp->hd_bpath = STRALLOC(av[ac] + 3); continue; } if (!strncmp(av[ac], "wd=", 3)) { if (hp->hd_wdir) MY_FREE(hp->hd_wdir); hp->hd_wdir = STRALLOC(av[ac] + 3); continue; } if (!strncmp(av[ac], "so=", 3)) { if (hp->hd_sopts) MY_FREE(hp->hd_sopts); hp->hd_sopts = STRALLOC(av[ac] + 3); continue; } if (!strncmp(av[ac], "ip=", 3)) { if (hp->hd_aname) MY_FREE(hp->hd_aname); hp->hd_aname = STRALLOC(av[ac] + 3); continue; } if (!strncmp(av[ac], "id=", 3)) { if (hp->hd_vmid) MY_FREE(hp->hd_vmid); hp->hd_vmid = STRALLOC(av[ac] + 3); continue; } printf("parsehost(): unknown option \"%s\"\n", av[ac]); err++; } if (err) goto bad; if (hp->hd_name) MY_FREE(hp->hd_name); hp->hd_name = STRALLOC(av[0]); return 0; bad: return -1; } alias_cmd(ac, av) int ac; char **av; { struct alias *ap; char *p; int i; if (ac < 3) { for (ap = aliases->a_link; ap != aliases; ap = ap->a_link) { fputs(ap->a_name, stdout); p = "\t"; for (i = 0; i < ap->a_num; i++) { printf("%s%s", p, ap->a_args[i]); p = " "; } fputs("\n", stdout); } } else { if (ap = findalias(av[1])) freealias(ap); newalias(av[1], ac - 2, av + 2); } return 0; } conf_cmd(ac, av) int ac; char **av; { int i; ac = ac; av = av; if (!pvm_config(&nhosts, &narchs, &hostlist)) { printf("%d host%s, %d data format%s\n", nhosts, (nhosts > 1 ? "s" : ""), narchs, (narchs > 1 ? "s" : "")); fputs(" HOST DTID ARCH SPEED DSIG\n", stdout); for (i = 0; i < nhosts; i++) printf("%24s %8x %8s%8d 0x%08x\n", hostlist[i].hi_name, hostlist[i].hi_tid, hostlist[i].hi_arch, hostlist[i].hi_speed, hostlist[i].hi_dsig); } return 0; } delete_cmd(ac, av) int ac; char **av; { int cc; int i; int *sv; av++; ac--; sv = TALLOC(ac, int, "int"); if ((cc = pvm_delhosts(av, ac, sv)) >= 0) { printf("%d successful\n", cc); fputs(" HOST STATUS\n", stdout); for (i = 0; i < ac; i++) { printf("%24s ", av[i]); if ((cc = sv[i]) < 0) printf("%8s\n", PVMERRMSG(cc)); else printf("deleted\n"); } } MY_FREE(sv); return 0; } echo_cmd(ac, av) int ac; char **av; { int i; char *p = ""; for (i = 1; i < ac; i++) { printf("%s%s", p, av[i]); p = " "; } printf("\n"); return 0; } halt_cmd(ac, av) int ac; char **av; { ac = ac; av = av; if (!pvm_halt()) { pvmendtask(); exit(0); } return 0; } char *helptx[] = { "add add Add hosts to virtual machine", "add Syntax: add hostname ...", "alias alias Define/list command aliases", "alias Syntax: alias [name command args ...]", "conf conf List virtual machine configuration", "conf Syntax: conf", "conf Output fields:", "conf HOST host name", "conf DTID tid base of pvmd", "conf ARCH xhost architecture", "conf SPEED host relative speed", "delete delete Delete hosts from virtual machine", "delete Syntax: delete hostname ...", "echo echo Echo arguments", "echo Syntax: echo [ arg ... ]", "export export Add environment variables to spawn export list", "export Syntax: export [ varname ... ]", "getopt getopt Display PVM options for the console task", "getopt Syntax: getopt [ what ]", "halt halt Stop pvmds", "halt Syntax: halt", "help help Print helpful information about a command", "help Syntax: help [ command ]", "id id Print console task id", "id Syntax: id", "idump-idump Call i_dump to display heap contents", "idump-Syntax: idump [ how ]", /* "insert-insert Add entry to database", "insert-Syntax: insert name index|-1 hexvalue", */ "jobs jobs Display list of running jobs", "jobs Syntax: jobs [ options ]", "jobs Options: -l give long listing", "kill kill Terminate tasks", "kill Syntax: kill [ options ] tid ...", "kill Options: -c kill children of tid", /* "lookup-lookup Find entry in database", "lookup-Syntax: lookup name index|-1", */ "names names List message mailbox names", "names Syntax: names [ pattern ]", "mstat mstat Show status of hosts", "mstat Syntax: mstat name ...", "ps ps List tasks", "ps Syntax: ps [ -axh ]", "ps Options: -a all hosts (default is local)", "ps -hhost specific host tid", "ps -nhost specific host name", "ps -l long (show process id)", "ps -x show all tasks (e.g. console and nulls)", "ps Output fields:", "ps HOST host name", "ps TID task id", "ps PTID parent task id", "ps PID task process id", "ps FLAG status", "ps COMMAND executable name", "ps FLAG values:", "ps f task process is child of pvmd", "ps c task connected to pvmd", "ps a task waiting authorization", "ps o task connection being closed", "ps s task needs too many shared pages, is deadlocked", "ps H hoster task", "ps R resource manager task", "ps T tasker task", "pstat pstat Show status of tasks", "pstat Syntax: pstat tid ...", "put put Add entry to message mailbox", "put Syntax: put name flags", "quit quit Exit console", "quit Syntax: quit", /* "remove-remove Delete entry from database", "remove-Syntax: remove name index", */ "reset reset Kill all tasks, delete leftover mboxes", "reset Syntax: reset\n", "reset reset info Delete orphaned persistent mbox entries", "reset Syntax: reset info [ class [ index ] ]", "setenv setenv Display or set environment variables", "setenv Syntax: setenv [ name [ value ] ]", "setopt setopt Set PVM options - for the console task *only*!", "setopt Syntax: setopt what value", "sig sig Send signal to task", "sig Syntax: sig signum task ...", "spawn spawn Spawn task", "spawn Syntax: spawn [ options ] file [ arg ... ]", "spawn Options: -(count) number of tasks, default is 1", "spawn -(host) spawn on host, default is any", "spawn -(host):(wd) spawn on host, in directory 'wd'", "spawn --host=(IP) spawn on host with given IP addr", "spawn --host=(IP):(wd) spawn on IP, in directory 'wd'", "spawn -(ARCH) spawn on hosts of ARCH", "spawn -(ARCH):(wd) spawn on hosts of ARCH, in 'wd'", "spawn -:(wd) spawn in working directory 'wd'", "spawn -? enable debugging", "spawn -> redirect job output to console", "spawn ->(file) redirect output of job to file", "spawn ->>(file) append output of job to file", "spawn -@ trace job, output to terminal", "spawn -@(file) trace job, output to file", "tickle-tickle Tickle pvmd", "tickle-Syntax: tickle how [ arg ... ]", "tickle-How:", "tickle- 0 dump heap", "tickle- 1 dump host table", "tickle- 2 dump local task table", "tickle- 3 dump waitc list", "tickle- 4 dump message mailbox", "tickle- 5 get debugmask", "tickle- 6 (mask) set debugmask", "tickle- mask is the sum of the following bits for information about", "tickle- 1 Packet routing", "tickle- 2 Message routing and entry points", "tickle- 4 Task state", "tickle- 8 Slave pvmd startup", "tickle- 16 Host table updates", "tickle- 32 Select loop", "tickle- 64 IP network", "tickle- 128 Multiprocessor nodes", "tickle- 256 Resource manager interface", "tickle- 512 Application warnings (scrapped messages etc.)", "tickle- 1024 Wait contexts", "tickle- 2048 Shared memory operations", "tickle- 4096 Semaphores", "tickle- 8192 Locks", "tickle- 16384 Message routing", "tickle- 32768 Message mailbox", "tickle- 65536 Tracer tracing", "tickle- 131072 Multicast tracking", "tickle- 7 (num) set nopax", "tickle- 8 (dtid) trigger hostfail", "tickle- 9 (rst) dump pvmd statistics, clear if rst true", "tickle- 100 dump shared memory data structures", "trace trace Set/display trace event mask", "trace Syntax: trace", "trace trace [+] name ...", "trace trace - name ...", "trace trace [+] *", "trace trace - *", "trace trace xpvm (default mask for XPVM display)", "trace trace buf nbytes", "trace trace buf", "trace trace opt < full | time | count >", "trace trace opt", "unalias unalias Undefine command alias", "unalias Syntax: unalias name ...", "unexport unexport Remove environment variables from spawn export list", "unexport Syntax: unexport [ varname ... ]", "version version Show libpvm version", "version Syntax: version", 0 }; help_cmd(ac, av) int ac; char **av; { char **p; char *topic; int l; struct cmdsw *csp; /* if not specified, topic = help */ if (ac > 1) topic = av[1]; else topic = "help"; l = strlen(topic); /* search through messages for ones matching topic */ for (p = helptx; *p; p++) { if (!strncmp(topic, *p, l) && ((*p)[l] == ' ' || (*p)[l] == '-')) printf("%s\n", (*p) + l + 1); } if (!strcmp(topic, "help")) { printf("Commands are:\n"); for (csp = commands; csp->cmd; csp++) { l = strlen(csp->cmd); for (p = helptx; *p; p++) if (!strncmp(csp->cmd, *p, l) && (*p)[l] == ' ') { printf(" %s\n", (*p) + l + 1); break; } } } return 0; } id_cmd(ac, av) int ac; char **av; { ac = ac; av = av; printf("t%x\n", mytid); return 0; } idump_cmd(ac, av) int ac; char **av; { int how = 0; if (ac > 1) how = atoi(av[1]); i_dump(how); return 0; } /* insert_cmd(ac, av) int ac; char **av; { int cc; int data; ac = ac; data = axtoi(av[3]); if ((cc = pvm_insert(av[1], axtoi(av[2]), data)) >= 0) printf("%s, %d = 0x%08x\n", av[1], cc, data); else if (cc == PvmDupEntry) printf("already exists\n"); return 0; } */ jobs_cmd(ac, av) int ac; char **av; { struct job *jp; struct obuf *op; int l = 0; int ntask; struct pvmtaskinfo *tip; TRC_TEVTASK tt; if (ac > 1 && !strcmp(av[1], "-l")) { l = 1; print_task_hdr(0); if (!hostlist) pvm_config(&nhosts, &narchs, &hostlist); } for (jp = joblist->j_link; jp != joblist; jp = jp->j_link) { printf("%c%d:%s", (jp->j_flag & JOB_TRACE ? 'T' : ' '), jp->j_jid - joboffset, (l ? "\n" : "")); if (jp->j_flag & JOB_TRACE) { tt = jp->j_trcid->tevtask_list; while ( tt ) { if ( tt->tevstatus == TRC_TASK_ALIVE || tt->outstatus == TRC_TASK_OUT ) { if (l) { if (!pvm_tasks(tt->tid, &ntask, &tip) && ntask == 1) print_task_rec(&tip[0], 0); else printf(" t%x", tt->tid); printf("\n"); } else printf(" t%x", tt->tid); } tt = tt->next; } if (!l) printf("\n"); } else if (jp->j_obufs) { for (op = jp->j_obufs->o_link; op != jp->j_obufs; op = op->o_link) if (l) { if (!pvm_tasks(op->o_tid, &ntask, &tip) && ntask == 1) print_task_rec(&tip[0], 0); else printf(" t%x", op->o_tid); printf("\n"); } else printf(" t%x", op->o_tid); if (!l) printf("\n"); } } return 0; } kill_cmd(ac, av) int ac; char **av; { int i; int tid, tid2; char *p; int host = 0; int cflg = 0; struct pvmtaskinfo *tip; int ntask; if (ac > 1 && av[1][0] == '-') { ac--; for (p = *++av; *p; p++) switch (*p) { case 'c': cflg = 1; break; case '-': break; default: printf("unknown flag -%c\n", *p); break; } } if (ac < 2) { fputs("incorrect arg count\n", stdout); return 1; } if (cflg && pvm_tasks(host, &ntask, &tip) < 0) return 1; while (ac > 1) { ac--; tid = tidtoi(*++av); if (cflg) { for (i = 0; i < ntask; i++) if (tip[i].ti_ptid == tid) { tid2 = tip[i].ti_tid; if (tid2 != mytid) pvm_kill(tid2); } } else { if (tid == mytid) printf("t%x: that's me.\n", tid); else pvm_kill(tid); } } return 0; } /* lookup_cmd(ac, av) int ac; char **av; { int cc, data = 0; ac = ac; if ((cc = pvm_lookup(av[1], axtoi(av[2]), &data)) >= 0) printf("%s, %d = 0x%08x\n", av[1], cc, data); else if (cc == PvmNoEntry) printf("no such entry\n"); return 0; } */ mstat_cmd(ac, av) int ac; char **av; { int i; int cc; for (i = 1; i < ac; i++) { cc = pvm_mstat(av[i]); printf("%24s %s\n", av[i], (cc < 0 ? PVMERRMSG(cc) : "ok")); } return 0; } pstat_cmd(ac, av) int ac; char **av; { int i; int tid; int cc; for (i = 1; i < ac; i++) { tid = tidtoi(av[i]); cc = pvm_pstat(tid); printf("t%8x %s\n", tid, (cc < 0 ? PVMERRMSG(cc) : "run")); } return 0; } quit_cmd() { printf("\n"); if (mytid > 0) { pvm_exit(); printf("pvmd still running.\n"); } #ifdef WIN32 WSACleanup(); #endif exit(0); return 0; /* for stupid SGI compiler :-Q */ } /* remove_cmd(ac, av) int ac; char **av; { int cc; ac = ac; if ((cc = pvm_delete(av[1], axtoi(av[2]))) > 0) printf("deleted %s, %d\n", av[1], cc); else if (cc == PvmNoEntry) printf("no such entry\n"); return 0; } */ reset_cmd(ac, av) int ac; char **av; { char *class = (char *) NULL; int killtasks = 1; int index = -1; /* Check for Info (mbox) Reset */ if ( ac > 1 ) { if ( !strcmp( av[1], "info" ) ) { killtasks = 0; if ( ac > 2 ) { class = av[2]; if ( ac > 3 ) index = atoi( av[3] ); } } else { printf( "\"%s\" arg to reset not valid\n", av[1] ); return 1; } } /* Call the universal VM-spanker routine... :-) */ pvmreset( mytid, killtasks, class, index ); return 0; } setenv_cmd(ac, av) int ac; char **av; { char **pp; char *p; char *sep; int n; int i; switch (ac) { case 1: for (pp = environ; *pp; pp++) printf("%s\n", *pp); break; case 2: if (p = getenv(av[1])) printf("%s\n", p); break; default: if (ac > 2) { n = 0; for (i = ac; i-- > 1; ) n += strlen(av[i]) + 1; p = TALLOC(n, char, "env"); strcpy(p, av[1]); strcat(p, "="); sep = ""; for (i = 2; i < ac; i++) { strcat(p, sep); strcat(p, av[i]); sep = " "; } pvmputenv(p); } break; } return 0; } static char *setop_strs[] = { "PvmRoute", "PvmDebugMask", "PvmAutoErr", "PvmOutputTid", "PvmOutputCode", "PvmTraceTid", "PvmTraceCode", "PvmTraceBuffer", "PvmTraceOptions", "PvmFragSize", "PvmResvTids", "PvmSelfOutputTid", "PvmSelfOutputCode", "PvmSelfTraceTid", "PvmSelfTraceCode", "PvmSelfTraceBuffer", "PvmSelfTraceOptions", "PvmShowTids", #if defined(IMA_AIX4MP) || defined(IMA_AIX5MP) \ || defined(IMA_ALPHAMP) || defined(IMA_CSPP) \ || defined(IMA_HPPAMP) || defined(IMA_RS6KMP) \ || defined(IMA_SGIMP) || defined(IMA_SGIMP6) \ || defined(IMA_SGIMP64) || defined(IMA_SUNMP) "PvmPollType", "PvmPollTime", #else "", "", #endif "PvmOutputContext", "PvmTraceContext", "PvmSelfOutputContext", "PvmSelfTraceContext", "PvmNoReset", NULL }; setopt_cmd(ac, av) int ac; char **av; { char **name; int what = -1; int value; int cc; int i; name = setop_strs; i = 1; while ( *name != NULL && what < 0 ) { if ( !strcmp( *name, av[1] ) ) what = i; else { name++; i++; } } if ( what > 0 ) { value = atoi( av[2] ); cc = pvm_setopt( what, value ); printf("%s Changed from %d to %d\n", av[1], cc, value ); } else printf("PVM Option \"%s\" Unknown.\n", av[1] ); return 0; } getopt_cmd(ac, av) int ac; char **av; { char **name; int what = -1; int value; int cc; int i; switch( ac ) { case 1: name = setop_strs; i = 1; while ( *name != NULL ) { if ( strcmp( *name, "" ) ) { cc = pvm_getopt( i ); printf("%s Currently Set to %d\n", *name, cc ); } name++; i++; } break; case 2: name = setop_strs; i = 1; while ( *name != NULL && what < 0 ) { if ( !strcmp( *name, av[1] ) ) what = i; else { name++; i++; } } if ( what > 0 ) { cc = pvm_getopt( what ); printf("%s Currently Set to %d\n", av[1], cc ); } else printf("PVM Option \"%s\" Unknown.\n", av[1] ); break; } return 0; } sig_cmd(ac, av) int ac; char **av; { int i; int signum; int tid; signum = atoi(av[1]); for (i = 2; i < ac; i++) { tid = tidtoi(av[i]); pvm_sendsig(tid, signum); } return 0; } spawn_cmd(ac, av) int ac; char **av; { int *tids = 0; char *where = 0; int flags = PvmNoSpawnParent; int count = 1; int i; int oflg = 0; int tflg = 0; int app; char *ofn = 0; char *tfn = 0; struct job *jp, *jp2; void status_msg(); void event_dump_hdr(); void output_dump_hdr(); while (av[1][0] == '-') { if (ac < 3) { fputs("incorrect arg count\n", stdout); return 1; } if (av[1][1] == '~') { flags |= PvmHostCompl; av[1]++; } if (av[1][1] == '.' || islower(av[1][1])) { where = av[1] + 1; flags |= PvmTaskHost; } if (av[1][1] == ':') where = av[1] + 1; if (isupper(av[1][1])) { where = av[1] + 1; flags |= PvmTaskArch; } if (av[1][1] == '?') flags |= PvmTaskDebug; if (isdigit(av[1][1])) count = atoi(av[1] + 1); if (av[1][1] == '>') { oflg = 1; app = 0; ofn = av[1] + 2; if (av[1][2] == '>') { app = 1; ofn++; } if (!*ofn) ofn = 0; /* printf("%s to %s\n", (app ? "Append" : "Write"), (ofn ? ofn : "(console)")); */ } if (av[1][1] == '@') { tflg = 1; tfn = av[1] + 2; if (!*tfn) tfn = ""; } /* gnu-like host (where) arg, allows IP's to be used... */ if (av[1][1] == '-') { if ( !strncmp( &(av[1][2]), "host=", 5 ) ) { where = av[1] + 7; flags |= PvmTaskHost; } } av++; ac--; } if (tflg) { jp2 = job_new(nextjob); jp2->j_flag |= JOB_TRACE; jp2->j_trcid = trc_get_tracer_id(); jp2->j_trcid->status_msg = status_msg; if (tfn && !strcmp(tfn,"")) jp2->j_trcid->event_dump_hdr = event_dump_hdr; if (oflg && !ofn) ofn = ""; if (ofn) jp2->j_trcid->output_dump_hdr = output_dump_hdr; jp2->j_trcid->event_ctx = pvm_getcontext(); jp2->j_trcid->event_tag = nextjob; jp2->j_trcid->output_ctx = pvm_getcontext(); jp2->j_trcid->output_tag = nextjob + 1; trc_set_tracing_codes( jp2->j_trcid ); printf("[%d]\n", nextjob - joboffset); nextjob += 2; trc_set_trace_file( jp2->j_trcid, tfn ); if (!trc_reset_trace_file( jp2->j_trcid )) { job_free(jp2); return 1; } trc_save_host_status_events( jp2->j_trcid ); if (ofn) { trc_set_output_file( jp2->j_trcid, ofn ); if (!trc_open_output_file( jp2->j_trcid )) { job_free(jp2); return 1; } } oflg = 0; } else { pvm_setopt(PvmTraceTid, 0); if (oflg) { pvm_setopt(PvmOutputTid, mytid); pvm_setopt(PvmOutputContext, pvm_getcontext()); pvm_setopt(PvmOutputCode, nextjob); jp = job_new(nextjob); printf("[%d]\n", nextjob - joboffset); nextjob++; if (ofn) { jp->j_ff = fopen(ofn, (app ? "a" : "w")); if (!jp->j_ff) { perror(ofn); job_free(jp); return 1; } } } else pvm_setopt(PvmOutputTid, 0); } tids = TALLOC(count > 1 ? count : 1, int, "int"); if ((i = pvm_spawn(av[1], &av[2], flags, where, count, tids)) >= 0) { if (oflg & !i) job_free(jp); if (tflg & !i) job_free(jp2); printf("%d successful\n", i); for (i = 0; i < count; i++) if (tids[i] < 0) printf("%s\n", PVMERRMSG(tids[i])); else printf("t%x\n", tids[i]); } MY_FREE(tids); return 0; } static char *tflgs[] = { 0, "f", "c", "a", "o", "s", 0, 0, "R", "H", "T" }; char * task_flags(f) int f; { static char buf[64]; int bit, i; sprintf(buf, "%x/", f); i = sizeof(tflgs)/sizeof(tflgs[0]) - 1; bit = 1 << i; while (i >= 0) { if ((f & bit) && tflgs[i]) { strcat(buf, tflgs[i]); strcat(buf, ","); } bit /= 2; i--; } buf[strlen(buf) - 1] = 0; return buf; } print_task_hdr(lflg) int lflg; { if (lflg) fputs(" HOST TID PTID PID FLAG 0x COMMAND\n", stdout); else fputs(" HOST TID FLAG 0x COMMAND\n", stdout); return 0; } print_task_rec(tip, lflg) struct pvmtaskinfo *tip; int lflg; { struct pvmhostinfo *hip = 0; if (hostlist) { for (hip = hostlist + nhosts - 1; hip >= hostlist; hip--) if (hip->hi_tid == tip->ti_host) break; if (hip < hostlist) hip = 0; } if (hip) printf("%24s", hip->hi_name); else printf("%24x", tip->ti_host); if (tip->ti_tid == mytid) printf(" (cons)"); else printf(" %8x", tip->ti_tid); if (lflg) { if (tip->ti_ptid == mytid) printf(" (cons)"); else if (tip->ti_ptid) printf(" %8x", tip->ti_ptid); else printf(" -"); printf(" %6d", tip->ti_pid); } printf(" %9s", task_flags(tip->ti_flag)); printf(" %-12s", tip->ti_a_out[0] ? tip->ti_a_out : "-"); return 0; } tasks_cmd(ac, av) int ac; char **av; { struct pvmtaskinfo *tip; int ntask; int i; struct pvmhostinfo *hip = 0; int xflg = 0; char *p; int host = pvm_tidtohost(mytid); int lflg = 0; if (!hostlist) pvm_config(&nhosts, &narchs, &hostlist); if (ac > 1) { for (p = av[1]; *p; p++) switch (*p) { case 'n': p++; if (!strcmp(p, ".")) pvm_tidtohost(mytid); else { for (hip = hostlist + nhosts; --hip >= hostlist; ) if (!(strcmp(p, hip->hi_name))) { host = hip->hi_tid; break; } if (hip < hostlist) printf("unknown host %s\n", p); } while (*p) p++; p--; break; case 'h': host = tidtoi(++p); while (*p) p++; p--; break; case 'a': host = 0; break; case 'l': lflg = 1; break; case 'x': xflg = 1; break; case '-': break; default: printf("unknown flag -%c\n", *p); break; } } if (!pvm_tasks(host, &ntask, &tip)) { print_task_hdr(lflg); for (i = 0; i < ntask; i++) { if (!xflg && (tip[i].ti_tid == mytid || tip[i].ti_tid == 0)) continue; print_task_rec(&tip[i], lflg); printf("\n"); } } return 0; } tickle_cmd(ac, av) int ac; char **av; { int nar; int arg[10]; int i; ac--; av++; for (nar = 0; nar < ac; nar++) arg[nar] = axtoi(av[nar]); if (!pvm_tickle(nar, arg, &nar, arg)) { printf("("); for (i = 0; i < nar; i++) printf(" %d", arg[i]); printf(" )\n"); } return 0; } printtm(who) int who; { Pvmtmask tm; pvm_gettmask(who, tm); trc_print_tmask(tm); return 0; } trace_cmd(ac, av) int ac; char **av; { static int topt = PvmTraceFull; static int tbuf = 0; int i; int onoff = 1; int e; int l; char buf[64]; char *optstr; Pvmtmask tm; int settm; if (ac == 1) { printtm(PvmTaskChild); return 0; } pvm_gettmask(PvmTaskChild, tm); settm = 0; for (i = 1; i < ac; i++) { if (!strcmp(av[i], "+")) { onoff = 1; } else if (!strcmp(av[i], "-")) { onoff = 0; } else if (!strcmp(av[i], "*")) { for (e = TEV_FIRST; e <= TEV_MAX; e++) { if (onoff) TEV_MASK_SET(tm, e); else TEV_MASK_UNSET(tm, e); } settm++; } else if (!strcmp(av[i], "buf")) { if ( i + 1 < ac ) { tbuf = atoi(av[++i]); pvm_setopt( PvmTraceBuffer, tbuf ); } else { printf("\nTrace Buffering set to %d bytes\n\n", tbuf); } } else if (!strcmp(av[i], "opt")) { if ( i + 1 < ac ) { i++; if ( !strcmp( av[i], "full" ) ) topt = PvmTraceFull; else if ( !strcmp( av[i], "time" ) ) topt = PvmTraceTime; else if ( !strcmp( av[i], "count" ) ) topt = PvmTraceCount; else { printf( "\nError: Unknown Trace Option \"%s\"\n\n", av[i] ); } pvm_setopt( PvmTraceOptions, topt ); } else { switch ( topt ) { case PvmTraceFull: optstr = "full"; break; case PvmTraceTime: optstr = "time"; break; case PvmTraceCount: optstr = "count"; break; default: { sprintf( buf, "", topt ); optstr = buf; } } printf("\nTrace Options set to \"%s\"\n\n", optstr ); } } else if (!strcmp(av[i], "xpvm")) { TEV_MASK_INIT( tm ); TEV_MASK_SET( tm, TEV_BARRIER ); TEV_MASK_SET( tm, TEV_BCAST ); TEV_MASK_SET( tm, TEV_JOINGROUP ); TEV_MASK_SET( tm, TEV_LVGROUP ); TEV_MASK_SET( tm, TEV_MYTID ); TEV_MASK_SET( tm, TEV_PARENT ); TEV_MASK_SET( tm, TEV_SIBLINGS ); TEV_MASK_SET( tm, TEV_SPAWN ); TEV_MASK_SET( tm, TEV_SENDSIG ); TEV_MASK_SET( tm, TEV_KILL ); TEV_MASK_SET( tm, TEV_EXIT ); TEV_MASK_SET( tm, TEV_MCAST ); TEV_MASK_SET( tm, TEV_SEND ); TEV_MASK_SET( tm, TEV_RECV ); TEV_MASK_SET( tm, TEV_RECVF ); TEV_MASK_SET( tm, TEV_NRECV ); TEV_MASK_SET( tm, TEV_PSEND ); TEV_MASK_SET( tm, TEV_PRECV ); TEV_MASK_SET( tm, TEV_TRECV ); TEV_MASK_SET( tm, TEV_PROBE ); TEV_MASK_SET( tm, TEV_ADDMHF ); TEV_MASK_SET( tm, TEV_DELMHF ); TEV_MASK_SET( tm, TEV_MHF_INVOKE ); TEV_MASK_SET( tm, TEV_USER_DEFINED ); settm++; } else { if (!strncmp(av[i], "pvm_", 4)) strcpy(buf, av[i] + 4); else strcpy(buf, av[i]); for (e = TEV_FIRST; e <= TEV_MAX; e++) if (!strcmp(pvmtevinfo[e].name, buf) || !strcmp(pvmtevinfo[e].name, av[i])) break; if ( e <= TEV_MAX ) { if (onoff) TEV_MASK_SET(tm, e); else TEV_MASK_UNSET(tm, e); settm++; } else printf("no such event \"%s\"\n", av[i]); } } if ( settm ) pvm_settmask(PvmTaskChild, tm); return 0; } unalias_cmd(ac, av) int ac; char **av; { struct alias *ap; int i; for (i = 1; i < ac; i++) if (ap = findalias(av[i])) freealias(ap); return 0; } version_cmd(ac, av) int ac; char **av; { ac = ac; av = av; printf("%s\n", pvm_version()); return 0; } names_cmd(ac, av) int ac; char **av; { struct pvmmboxinfo *classes; int nclasses; int i, j; int cc; pvm_getmboxinfo((ac > 1 ? av[1] : "*"), &nclasses, &classes); for ( i=0 ; i < nclasses ; i++ ) { printf("<%s>:\n", classes[i].mi_name); for ( j=0 ; j < classes[i].mi_nentries ; j++ ) printf("\tindex=%d owner=0x%x/%d flags=0x%x\n", classes[i].mi_indices[j], classes[i].mi_owners[j], classes[i].mi_owners[j], classes[i].mi_flags[j] ); printf("\n"); } return 0; } put_cmd(ac, av) int ac; char **av; { int cc; pvm_packf("%+ %d", PvmDataDefault, 0); cc = pvm_putinfo(av[1], pvm_getsbuf(), (int)atoi(av[2])); if (cc < 0) printf("%s\n", pvm_errlist[-cc]); return 0; } export_cmd(ac, av) int ac; char **av; { int i; char *p; if (ac == 1) { p = getenv("PVM_EXPORT"); printf("PVM_EXPORT=%s\n", p ? p : ""); } else { for (i = 1; i < ac; i++) pvm_export(av[i]); } return 0; } unexport_cmd(ac, av) int ac; char **av; { int i; for (i = 1; i < ac; i++) pvm_unexport(av[i]); return 0; } ./pvm3/console/cons.c0100644007401100000360000004431507240352721013661 0ustar kohlgopher static char rcsid[] = "$Id: cons.c,v 1.31 2001/02/07 23:10:09 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * cons.c * * PVM-console task. Gives the user a shell to manage the virtual * machine and other tasks. * * $Log: cons.c,v $ * Revision 1.31 2001/02/07 23:10:09 pvmsrc * CYGWIN Changes. * (Spanker=kohl) * * Revision 1.30 2000/02/15 18:05:54 pvmsrc * Modified console to intialize trace mask at startup. * - use "trace xpvm" command via trace_cmd() interface. * (Spanker=kohl) * * Revision 1.29 1999/07/08 18:02:48 pvmsrc * Fixed up crummy readline garbage. * - added omitted "char *line" argument to rl_got_line(), * use instead of rl_line_buffer global, else miss EOF condition. * - in command_completion(), keep track of last line buffer, * only dump help syntax once, then let readline dump files * instead. * (Spanker=kohl) * * Revision 1.28 1999/06/11 19:40:07 pvmsrc * Another (re-)update of the readline stuff from Edward Vigmond... * (Spanker=kohl) * * Revision 1.27 1999/06/11 17:27:34 pvmsrc * When breaking up multiline commands into subcommands, * dump out each command as you execute it, along with a fresh prompt. * (Spanker=kohl) * * Revision 1.26 1999/05/18 22:29:55 pvmsrc * More hacks on the readline stuff. * - from Edward Vigmond . * (Spanker=kohl) * * Revision 1.25 1999/03/25 21:49:31 pvmsrc * Readline Support Update. * - from Edward Vigmond . * (Spanker=kohl) * * Revision 1.24 1999/02/05 20:36:15 pvmsrc * More contributions from Edward Vigmond . * - better readline interface, with command completion & help. * (Spanker=kohl) * * Revision 1.23 1999/02/03 19:57:14 pvmsrc * Added support for system that have readline(). * - patch submitted by Edward Vigmond . * (Spanker=kohl) * * Revision 1.22 1998/11/20 19:43:09 pvmsrc * Changes so that win32 will compile & build. Also, common * source for win32 & unix. * (Spanker=sscott) * * Revision 1.21 1998/10/05 21:12:06 pvmsrc * One last uncomment from Markus... :-) * (Spanker=kohl) * * Revision 1.20 1998/10/02 16:23:36 pvmsrc * Single source code merge of Win32 and Unix code. * oops - last one missed some things... * (Spanker=sscott) * * Revision 1.19 1998/01/28 23:03:40 pvmsrc * Fixed tracing bogusness! * - host add / del notifies for tracing were getting scrunched by * console host add notify, etc... * - moved message / notify tag constants to job.h and USED THEM. * - initialized nextjob properly... * - added new "joboffset" global in cons.c for dumping more * reasonable job numbers to user. * (Spanker=kohl) * * Revision 1.18 1997/12/29 19:38:17 pvmsrc * Deleted linux/time.h include. Don't need it on Redhat 4.2 or 5.0. * (Spanker=phil) * * Revision 1.17 1997/12/01 19:21:25 pvmsrc * Replaced #ifdef IMA_OS2 fd_set declarations: * - new #ifdef FDSETNOTSTRUCT. * - choose between "fd_set foo" and "struct fd_set foo"... * (Spanker=kohl) * * Revision 1.16 1997/11/04 23:14:45 pvmsrc * Cleaned up fd_set stuff (hopefully). * (Spanker=kohl) * * Revision 1.15 1997/07/09 13:21:04 pvmsrc * Fixed Author Header. * * Revision 1.14 1997/06/25 18:03:58 pvmsrc * WIN32 changes from Markus. * * Revision 1.13 1997/05/13 14:37:39 pvmsrc * Changed header file $includes: * - ../src/listmac.h -> listmac.h * - ../src/bfunc.h -> bfunc.h * - use -I$(PVMDIR)/src in Makefile.aimk instead. * * Revision 1.12 1997/05/01 15:49:44 pvmsrc * Oops... exit_handler() must be int funct, not void. * - for pvm_addmhf()... * * Revision 1.11 1997/05/01 15:41:16 pvmsrc * SGI Compiler Warning Cleanup. * * Revision 1.10 1997/04/29 19:37:41 pvmsrc * Commented out signal( SIGTERM, SIGIGN ). * - not needed with PvmNoReset setopt now... * * Revision 1.9 1997/04/24 12:37:04 pvmsrc * Added NEEDSSELECTH switch to simplify ifdefs on IBM machines. * * Revision 1.8 1997/04/08 20:22:31 pvmsrc * Sonofabitch. Typo. * * Revision 1.7 1997/04/08 20:15:28 pvmsrc * Spanked sscott's spank... :-} * * Revision 1.6 1997/03/06 14:52:48 pvmsrc * Yanked out spank. * - removed Bob's test code for mbox & context... * * Revision 1.5 1997/02/17 19:51:54 pvmsrc * Added setting of PvmNoReset for pvm console. * * Revision 1.4 1997/01/28 19:13:18 pvmsrc * New Copyright Notice & Authors. * * Revision 1.3 1996/10/24 23:04:05 pvmsrc * Updated for new tracing facility. * - new init, select handling with checkmsgs(), * and notify event / trace / output handling. * * Revision 1.2 1996/10/08 18:29:40 pvmsrc * Renamed routines: * - pvm_put() -> pvm_putinfo(). * - pvm_get() -> pvm_getinfo(). * * Revision 1.1 1996/09/23 20:25:36 pvmsrc * Initial revision * * Revision 1.6 1995/05/30 16:51:30 manchek * added SP2MPI architecture * * Revision 1.5 1995/05/17 15:28:06 manchek * added FDSETISINT switch. * allow pvm_getfds() to fail silently (e.g. for shared memory) * * Revision 1.4 1994/10/15 18:40:09 manchek * don't compare add-host notify source to 0x80000000 * * Revision 1.3 1994/06/03 20:01:52 manchek * version 3.3.0 * * Revision 1.2 1993/09/16 21:33:40 manchek * moved notify(HostAdd) to before we read script file. * added include for linux/time.h * * Revision 1.1 1993/08/30 23:30:32 manchek * Initial revision * */ #include #include /* #ifdef IMA_LINUX */ /* #include */ /* #endif */ #ifdef NEEDSSELECTH #include #endif #ifdef IMA_I860 #include #endif #ifdef SYSVSTR #include #else #include #endif #include #include #include #include #include "cmd.h" #include "myalloc.h" #include "listmac.h" #include "bfunc.h" #include "job.h" #ifdef HASREADLINE #include #ifndef CYGWIN #include #endif char **command_completion(); void rl_got_line(); #endif #define PVMERRMSG(n) ((n) <= 0 && (n) > -pvm_nerr \ ? pvm_errlist[-(n)] : "Unknown Error") char *getenv(); #ifdef WIN32 extern int nAlert; WSADATA WSAData; #endif extern char *pvm_errlist[]; extern int pvm_nerr; extern struct job *joblist; /* from job.c */ extern struct cmdsw commands[]; extern char *helptx[]; int mytid = -1; int nhosts = 0; int narchs = 0; struct pvmhostinfo *hostlist = 0; struct alias *aliases = 0; int joboffset = FirstJobTag - 1; int nextjob = FirstJobTag; #ifdef WIN32 int system_loser_win = FALSE; #endif char *prompt = "pvm> "; int exit_handler(mid) int mid; { printf("Console: exit handler called\n"); pvm_freebuf(mid); return 0; } main(argc, argv) int argc; char **argv; { static struct timeval more_msgs = { 0, 0 }; char cmd[1024]; int cc; int i; int src, cod, len; char *p; FILE *ff; #ifdef FDSETNOTSTRUCT fd_set rfds, fds; #else struct fd_set rfds, fds; #endif int nfds; int n; int *np = 0; struct pvmminfo minfo; struct timeval *timeout; int more; int ac; char *av[128]; #ifdef WIN32 /* WSAStartup has to be called before any socket command */ /* can be executed. Why ? Ask Bill */ HANDLE hStdin; struct timeval zerotimeout = { 0, 0 }; /* if ( WSAStartup( 0x0101, &WSAData ) != 0 ) { printf("\nWSAStartup() failed\n"); ExitProcess( 1 ); } */ #endif #ifdef CYGWIN /* To run properly, the PVM console has to be run in CYGWIN's tty mode */ { char *cygwin_env; int cygwin_tty = 0; cygwin_env = getenv("CYGWIN"); if (cygwin_env==NULL) cygwin_env = getenv("CYGWIN32"); if (cygwin_env!=NULL) { cygwin_tty = (strstr(cygwin_env, "tty") == NULL); cygwin_tty |= (strstr(cygwin_env, "TTY") == NULL); } if (!cygwin_tty) { fprintf(stderr, "PVM will not run properly if not in tty mode.\n"); fprintf(stderr, "Please set the following before calling PVM again:\n"); fprintf(stderr, "SET CYGWIN=tty (Cygwin B20)\n"); fprintf(stderr, "SET CYGWIN32=tty (Cygwin B19)\n"); exit(1); } } #endif pvm_setopt(PvmResvTids, 1); aliases = TALLOC(1, struct alias, "alias"); BZERO((char*)aliases, sizeof(struct alias)); aliases->a_link = aliases->a_rlink = aliases; if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'd') pvm_setopt(PvmDebugMask, pvmstrtoi(argv[1] + 2)); pvm_setopt(PvmRoute, PvmDontRoute); pvm_setopt(PvmSelfTraceTid, -1); pvm_setopt(PvmSelfOutputTid, -1); i = pvm_setopt(PvmAutoErr, 0); cc = pvm_start_pvmd(argc - 1, argv + 1, 1); if (cc < 0) { if (cc != PvmDupHost) { pvm_perror("Console"); exit(1); } printf("pvmd already running.\n"); } pvm_setopt(PvmAutoErr, i); if ((mytid = pvm_mytid()) < 0) exit(1); (void)signal(SIGINT, SIG_IGN); /* (void)signal(SIGTERM, SIG_IGN); now PvmNoReset */ #ifndef WIN32 /* NT console problem - original NT codes had commented out */ pvm_setopt( PvmNoReset, 1 ); pvm_setopt( PvmTraceOptions, PvmTraceFull ); pvm_setopt( PvmTraceBuffer, 0 ); #endif job_init(); /* set default trace mask to xpvm */ sprintf(cmd, "trace xpvm"); ac = sizeof(av)/sizeof(av[0]) - 1; if (!acav(cmd, &ac, av) && ac) trace_cmd(ac, av); pvm_notify(PvmHostAdd, HostsAddedTag, -1, (int*)0); BZERO(&minfo, sizeof(minfo)); minfo.src = -1; minfo.ctx = -1; minfo.tag = MyExitTag; #ifndef WIN32 /* NT console problem - original NT codes had commented out */ pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, exit_handler); pvm_notify(PvmTaskExit, MyExitTag, 1, &mytid); #endif if (!(p = getenv("HOME"))) p = "."; sprintf(cmd, "%s/.pvmrc", p); if (ff = fopen(cmd, "r")) { while (fgets(cmd, sizeof(cmd)-1, ff)) docmd(cmd); (void)fclose(ff); } FD_ZERO(&rfds); #ifndef WIN32 FD_SET(0, &rfds); #endif nfds = 1; i = pvm_setopt(PvmAutoErr, 0); if (pvm_getfds(&np) > 0) { FD_SET(np[0], &rfds); nfds = np[0] + 1; } pvm_setopt(PvmAutoErr, i); trc_init(); #ifdef HASREADLINE rl_attempted_completion_function = (CPPFunction *) command_completion; rl_callback_handler_install( prompt, rl_got_line ); #else printf(prompt); fflush(stdout); #endif #ifdef WIN32 hStdin = GetStdHandle(STD_INPUT_HANDLE); #endif while (1) { /* * flush task stdout and trace events */ if (mytid > 0) more = checkmsgs(); else more = 0; if ( more ) timeout = &more_msgs; else #ifndef WIN32 timeout = (struct timeval *) NULL; #else timeout = &zerotimeout; #endif /* * wait for command or more output */ fds = rfds; if ((n = select(nfds, #ifdef FDSETISINT (int *)&fds, (int *)0, (int *)0, #else (fd_set *)&fds, (fd_set *)0, (fd_set *)0, #endif timeout)) == -1) { perror("select"); #ifndef WIN32 continue; #endif } #ifdef WIN32 else if (n != 0) printf("select: returned untouched data \n"); #endif #ifdef WIN32 if (WAIT_TIMEOUT == WaitForSingleObject(hStdin,2000)) continue; /* no input */ #else if (n > 0 && FD_ISSET(0, &fds)) { #endif #ifdef HASREADLINE rl_callback_read_char(); #else if ((n = read(0, cmd, sizeof(cmd)-1)) < 1) { printf("quit\n"); quit_cmd(); } cmd[n] = 0; docmd(cmd); printf(prompt); fflush(stdout); #endif #ifndef WIN32 } #endif } } /* acav() * * Parse a string into words separated by whitespace. * Max number of words is original value of *acp. * * Trashes out the original string. * Returns 0 with av[0]..av[*acp - 1] pointing to the words. * Returns 1 if too many words. * Returns -1 if unbalanced quote. */ int acav(s, acp, av) char *s; /* the string to parse */ int *acp; /* max num words in, num words found out */ char **av; /* pointers to words */ { int ac = 0; /* number of words found */ char *p = s; /* input scanner */ char *q; /* output */ int n = *acp; /* max number of words allowed */ int mode = 0; /* quote mode */ while (*p) { while (isspace(*p)) p++; if (*p) { if (*p == '#') break; if (ac >= n) { *acp = ac; return 1; } q = p; av[ac++] = p; while (*p) { if (mode) { if (mode == '\\') { *q++ = *p; mode = 0; } else if (mode == *p) { mode = 0; } else *q++ = *p; } else { if (isspace(*p)) break; switch (*p) { case '"': case '\'': case '\\': mode = *p; break; default: *q++ = *p; break; } } p++; } if (*p) p++; if (*q) *q = 0; if (mode) { printf("unmatched %c\n", (char)mode); return -1; } } } *acp = ac; return 0; } /* xtoi() * * Yet another version of ascii hex to integer */ xtoi(p) char *p; { int i = 0; char c; while (isxdigit(c = *p++)) { i = (i << 4) + c - (isdigit(c) ? '0' : (isupper(c) ? 'A' : 'a') - 10); } return i; } /* axtoi() * * ascii hex or decimal to integer. */ axtoi(p) char *p; { if (p[0] == '0' && p[1] == 'x') return xtoi(p + 2); else return atoi(p); } int tidtoi(p) char *p; { if (*p == 't') p++; return xtoi(p); } checkmsgs() { int cc; int len, cod, src; int n; struct job *jp; int *dtids; int i, j; int more, tmp; struct job *jpnext; /* Shit, really need context here to keep old pvm_nrecv(-1,-1)... */ /* Should use 2 contexts, one for original console msgs and one */ /* for tracer stuff... */ /* Get Host Add Notifies */ while ((cc = pvm_nrecv(-1, HostsAddedTag)) > 0) { pvm_upkint(&n, 1, 1); dtids = TALLOC(n, int, ""); pvm_upkint(dtids, n, 1); printf("\nConsole: %d new host%s added\n", n, (n == 1 ? "" : "s")); pvm_freebuf(cc); if (!pvm_config(&nhosts, &narchs, &hostlist)) { fputs(" HOST DTID ARCH SPEED\n", stdout); for (j = n; j-- > 0; ) for (i = nhosts; i-- > 0; ) { if (dtids[j] == hostlist[i].hi_tid) { printf("%24s %8x %8s%8d\n", hostlist[i].hi_name, hostlist[i].hi_tid, hostlist[i].hi_arch, hostlist[i].hi_speed); break; } } } MY_FREE(dtids); } /* Poll Jobs... This Sux... Needs Context... */ jp = joblist->j_link; more = 0; while (jp != joblist) { jpnext = jp->j_link; /* Trace Job */ if (jp->j_flag & JOB_TRACE) { if (trc_recv_messages(jp->j_trcid, 10, &tmp) > 0 ) { fflush(jp->j_trcid->trace_out); } if ( tmp ) more++; if ( jp->j_trcid->complete ) { printf("[%d] finished\n", jp->j_jid - joboffset); job_free(jp); } } /* Output Job */ else { while ((cc = pvm_nrecv(-1, jp->j_jid)) > 0) { pvm_bufinfo(cc, &len, &cod, &src); checkoutput(jp, cc, len, cod, src); } } jp = jpnext; } if (cc < 0) exit(1); return( more ); } #ifdef HASREADLINE /* Readline Support Routines */ /* Provided by Edward Vigmond */ char *command_generator __ProtoGlarp__(( char *, int )); char *command_help_generator __ProtoGlarp__(( char *, int )); /* * readline has detected a complete input line */ void rl_got_line( line ) char *line; { char *expcmd; if ( line == NULL ) { printf( "quit\n" ); quit_cmd(); } /* try and expand input, if so print expanded comnmand */ if ( history_expand( line, &expcmd ) == 1 ) { printf( "%s\n", expcmd ); fflush( stdout ); } /* if the command is not the same as the previous, store it */ if ( *line ) { if ( !history_length || strcmp( history_get( history_length )->line, expcmd ) ) add_history( expcmd ); } docmd( expcmd ); free( expcmd ); } char ** command_completion( text, start, end ) char *text; int start; int end; { static char *last_line = (char *) NULL; char **matches = (char **) NULL; char tchar[2]; if ( start == 0 ) { if ( last_line ) { free( last_line ); last_line = (char *) NULL; } matches = completion_matches( text, command_generator ); } /* if only the command entered so far, give the syntax */ else if ( start == end ) { if ( !last_line || strcmp( last_line, rl_line_buffer ) ) { matches = completion_matches( text, command_help_generator ); if ( last_line ) free( last_line ); last_line = strdup( rl_line_buffer ); } } return( matches ); } /* function to match partially completed command names */ char * command_generator( text, state ) char *text; int state; { static int list_index, len; char *name; if ( !state ) { list_index = 0; len = strlen( text ); } while( name = commands[ list_index ].cmd ) { list_index++; if ( !strncmp( name, text, len ) ) return( strdup( name ) ); } return( (char *) NULL ); } /* * this function outputs the help for the command but does not inform * readline of a match since readline sorts the command completion * alphabetically, thus mixing up the help message */ char * command_help_generator( text, state ) char *text; int state; { static int list_index, len, found_one; char *syntax; if ( !state ) { list_index = 0; len = strchr( rl_line_buffer, ' ' ) - rl_line_buffer; found_one = 0; } while ( syntax = helptx[ list_index ] ) { list_index++; if ( !strncmp( syntax, rl_line_buffer, len ) ) { if ( !found_one ) { found_one = 1; printf( "\n" ); } printf( "%s\n", strchr( syntax, ' ' ) + 1 ); fflush( stdout ); } } if ( found_one && !syntax ) rl_forced_update_display(); return( (char *) NULL ); } #endif ./pvm3/console/job.c0100644007401100000360000001764507052304777013510 0ustar kohlgopher static char rcsid[] = "$Id: job.c,v 1.10 2000/02/15 17:16:47 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * job.c * * Job descriptor / output gathering code. * * $Log: job.c,v $ * Revision 1.10 2000/02/15 17:16:47 pvmsrc * *Really* removed old checktrace() routine. * - hasn't been called for years... duh... * (Spanker=kohl) * * Revision 1.9 2000/02/15 17:06:20 pvmsrc * Modified dumping of task output / trace events. * - key off of PvmShowTids option, leave off task id prefix if set. * (Spanker=kohl) * * Revision 1.8 1999/07/08 18:59:41 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.7 1998/01/28 23:03:41 pvmsrc * Fixed tracing bogusness! * - host add / del notifies for tracing were getting scrunched by * console host add notify, etc... * - moved message / notify tag constants to job.h and USED THEM. * - initialized nextjob properly... * - added new "joboffset" global in cons.c for dumping more * reasonable job numbers to user. * (Spanker=kohl) * * Revision 1.6 1997/07/09 13:21:07 pvmsrc * Fixed Author Header. * * Revision 1.5 1997/05/13 14:37:41 pvmsrc * Changed header file $includes: * - ../src/listmac.h -> listmac.h * - ../src/bfunc.h -> bfunc.h * - use -I$(PVMDIR)/src in Makefile.aimk instead. * * Revision 1.4 1997/05/01 15:41:17 pvmsrc * SGI Compiler Warning Cleanup. * * Revision 1.3 1997/01/28 19:13:19 pvmsrc * New Copyright Notice & Authors. * * Revision 1.2 1996/10/24 23:04:30 pvmsrc * Updated for new tracing facility: * - removed old checktrace() stuff... * * Revision 1.1 1996/09/23 20:25:38 pvmsrc * Initial revision * * Revision 1.2 1994/06/03 20:01:52 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:30:32 manchek * Initial revision * */ #include #ifdef SYSVSTR #include #define CINDEX(s,c) strchr(s,c) #else #include #define CINDEX(s,c) index(s,c) #endif #include #include #include "myalloc.h" #include "job.h" #include "listmac.h" #include "bfunc.h" extern char *pvm_errlist[]; extern int pvm_nerr; extern int mytid; /* from cons.c */ extern int joboffset; /* from cons.c */ struct job *joblist = 0; struct job * job_new(jid) int jid; { struct job *jp = joblist->j_link; struct job *jp2; struct obuf *op; while (jp != joblist && jp->j_jid < jid) jp = jp->j_link; if (jp->j_jid != jid) { jp2 = TALLOC(1, struct job, "job"); BZERO((char*)jp2, sizeof(struct job)); jp2->j_jid = jid; op = TALLOC(1, struct obuf, "obuf"); BZERO((char*)op, sizeof(struct obuf)); op->o_link = op->o_rlink = op; jp2->j_obufs = op; LISTPUTBEFORE(jp, jp2, j_link, j_rlink); jp = jp2; } return jp; } job_init() { if (!joblist) { joblist = TALLOC(1, struct job, "job"); BZERO((char*)joblist, sizeof(struct job)); joblist->j_link = joblist->j_rlink = joblist; } return 0; } struct job * job_find(jid) int jid; { struct job *jp = joblist->j_link; while (jp != joblist && jp->j_jid < jid) jp = jp->j_link; if (jp->j_jid == jid) return jp; return (struct job*)0; } job_free(jp) struct job *jp; { LISTDELETE(jp, j_link, j_rlink); if (jp->j_obufs) MY_FREE(jp->j_obufs); if (jp->j_ff) (void)fclose(jp->j_ff); MY_FREE(jp); return 0; } struct obuf * obuf_find(jp, tid) struct job *jp; int tid; { struct obuf *op = jp->j_obufs->o_link; while (op != jp->j_obufs && op->o_tid < tid) op = op->o_link; if (op->o_tid == tid) return op; return (struct obuf*)0; } struct obuf * obuf_new(jp, tid) struct job *jp; int tid; { struct obuf *op = jp->j_obufs->o_link; struct obuf *op2; while (op != jp->j_obufs && op->o_tid < tid) op = op->o_link; if (op->o_tid != tid) { op2 = TALLOC(1, struct obuf, "obuf"); BZERO((char*)op2, sizeof(struct obuf)); op2->o_tid = tid; LISTPUTBEFORE(op, op2, o_link, o_rlink); op = op2; } return op; } obuf_free(jp, op) struct job *jp; struct obuf *op; { LISTDELETE(op, o_link, o_rlink); if (op->o_buf) MY_FREE(op->o_buf); MY_FREE(op); if (jp->j_obufs->o_link == jp->j_obufs) { printf("[%d] finished\n", jp->j_jid - joboffset); job_free(jp); } return 0; } obuf_dump(jp) struct job *jp; { struct obuf *op; for (op = jp->j_obufs->o_link; op != jp->j_obufs; op = op->o_link) { printf("obuf_dump() t%x\n", op->o_tid); } return 0; } checkoutput(jp, cc, len, cod, src) struct job *jp; int cc; /* message mid */ int len; int cod; int src; { int tid; /* task */ int n; /* length or event code */ char *p; int ptid; struct obuf *op; int show; show = pvm_getopt( PvmShowTids ); pvm_upkint(&tid, 1, 1); pvm_upkint(&n, 1, 1); if (n > 0) { if (!(op = obuf_find(jp, tid))) { printf("Bogus message, job %d has no task t%x\n", jp->j_jid - joboffset, tid); goto hork; } if (n + op->o_len >= op->o_maxl) { op->o_maxl = op->o_len + n + 1; /* printf("REALLOC t%x buf to %d\n", tid, op->o_maxl); */ if (op->o_buf) op->o_buf = TREALLOC(op->o_buf, op->o_maxl, char); else op->o_buf = TALLOC(op->o_maxl, char, ""); } pvm_upkbyte(op->o_buf + op->o_len, n, 1); op->o_buf[op->o_len + n] = 0; /* printf("UNPACK t%x {%s}\n", tid, op->o_buf + op->o_len); */ p = op->o_buf + op->o_len; op->o_len += n; while (p = CINDEX(p, '\n')) { *p++ = 0; if ( show ) fprintf((jp->j_ff ? jp->j_ff : stdout), "[%d:t%x] ", jp->j_jid - joboffset, tid); fprintf((jp->j_ff ? jp->j_ff : stdout), "%s\n", op->o_buf); op->o_len -= p - op->o_buf; BCOPY(p, op->o_buf, op->o_len); p = op->o_buf; } } else { switch (n) { case 0: if (!(op = obuf_find(jp, tid))) { printf("Bogus message, job %d has no task t%x\n", jp->j_jid - joboffset, tid); goto hork; } if (op->o_len > 0) { if ( show ) fprintf((jp->j_ff ? jp->j_ff : stdout), "[%d:t%x] ", jp->j_jid - joboffset, tid); fprintf((jp->j_ff ? jp->j_ff : stdout), "%s\n", op->o_buf); op->o_len = 0; } op->o_flag |= GOTEOF; if (op->o_flag == (GOTSPAWN|GOTEOF)) { if ( show ) fprintf((jp->j_ff ? jp->j_ff : stdout), "[%d:t%x] EOF\n", jp->j_jid - joboffset, tid); obuf_free(jp, op); } break; case -1: if (!(op = obuf_find(jp, tid))) op = obuf_new(jp, tid); /* pvm_upkint(&ptid, 1, 1); */ op->o_flag |= GOTSPAWN; if (op->o_flag == (GOTSPAWN|GOTEOF)) { if ( show ) fprintf((jp->j_ff ? jp->j_ff : stdout), "[%d:t%x] EOF\n", jp->j_jid - joboffset, tid); obuf_free(jp, op); } break; case -2: if (!(op = obuf_find(jp, tid))) op = obuf_new(jp, tid); /* pvm_upkint(&ptid, 1, 1); */ break; default: printf("Bogus message from job %d task t%x\n", jp->j_jid - joboffset, tid); break; } } hork: pvm_freebuf(cc); return 0; } ./pvm3/console/trc.c0100644007401100000360000000632507052303614013504 0ustar kohlgopher static char rcsid[] = "$Id: trc.c,v 1.7 2000/02/15 17:06:20 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * trc.c * * Tracer Library Interface Routines * */ /* Tracer Library External Header */ #include #ifndef WIN32 #include #else #include #include #endif #include #include #include "job.h" extern int mytid; /* from cons.c */ extern int joboffset; /* from cons.c */ extern struct job *joblist; /* from cons.c */ /* Set Up Tracer Library */ int trc_init() { /* Initialize Tracer */ trc_tracer_init(); /* Set Tracer Globals */ TRC_HOST_ADD_NOTIFY_CODE = TrcHostAddTag; TRC_HOST_DEL_NOTIFY_CODE = TrcHostDelTag; TRC_VERSION = trc_copy_str( pvm_version() ); TRC_NAME = "Console"; TRC_TID = mytid; /* Check Hosts */ trc_initialize_hosts( (TRC_ID) NULL ); return( 0 ); } struct job *get_job_trcid( ID ) TRC_ID ID; { struct job *jp; jp = joblist->j_link; while ( jp != joblist ) { if ( jp->j_trcid == ID ) return( jp ); jp = jp->j_link; } fprintf( stderr, "Warning: Matching Job Trace ID Not Found\n" ); return( (struct job *) NULL ); } /* Tracer Stub Routines - Called by library... */ /* Status Message Handler */ void status_msg( ID, msg ) TRC_ID ID; char *msg; { struct job *jp; /* Find Corresponding Job */ jp = get_job_trcid( ID ); if ( jp != NULL ) fprintf( stderr, "[%d] libpvmtrc: %s\n", jp->j_jid - joboffset, msg ); } /* Trace Event Line Header */ void event_dump_hdr( ID, tid ) TRC_ID ID; int tid; { struct job *jp; int show; jp = get_job_trcid( ID ); if ( jp != NULL ) { show = pvm_getopt( PvmShowTids ); if ( show ) fprintf( ID->trace_out, "[T%d:t%x] ", jp->j_jid - joboffset, tid ); } } /* Task Output Line Header */ void output_dump_hdr( ID, tid ) TRC_ID ID; int tid; { struct job *jp; int show; jp = get_job_trcid( ID ); if ( jp != NULL ) { show = pvm_getopt( PvmShowTids ); if ( show ) fprintf( ID->output_fp, "[%d:t%x] ", jp->j_jid - joboffset, tid ); } } ./pvm3/console/cmd.h0100644007401100000360000000432106741172435013467 0ustar kohlgopher /* $Id: cmd.h,v 1.5 1999/07/08 18:59:41 kohl Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * cmd.h * * Command descriptors. * * $Log: cmd.h,v $ * Revision 1.5 1999/07/08 18:59:41 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.4 1997/07/09 13:21:02 pvmsrc * Fixed Author Header. * * Revision 1.3 1997/01/28 19:13:21 pvmsrc * New Copyright Notice & Authors. * * Revision 1.2 1996/09/26 21:13:41 pvmsrc * Spanked the stupid CVS "Id" strings. * - comments for headers, not rcsid's stupid... :-Q * * Revision 1.1 1996/09/23 20:25:41 pvmsrc * Initial revision * * Revision 1.2 1994/06/03 20:01:51 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:30:31 manchek * Initial revision * */ struct cmdsw { char *cmd; /* command name */ int a1; /* min number of args */ int a2; /* max number of args */ int (*fun)(); /* function */ }; struct alias { struct alias *a_link, *a_rlink; char *a_name; int a_num; char **a_args; int a_flag; }; ./pvm3/console/job.h0100644007401100000360000001106407052312635013472 0ustar kohlgopher /* $Id: job.h,v 1.8 2000/02/15 18:06:21 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * job.h * * Job descriptors. * * $Log: job.h,v $ * Revision 1.8 2000/02/15 18:06:21 pvmsrc * Modified jobs_cmd() to dump task ids for traced jobs... * - can't use output buffers, must use TRC_ID->tevtask_list list. * - snagged necessary state constants from trclib.h, can't just * #include it, as it #includes fricking everything... :-Q * (Spanker=kohl) * * Revision 1.7 1999/07/08 18:59:41 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.6 1998/01/28 23:03:43 pvmsrc * Fixed tracing bogusness! * - host add / del notifies for tracing were getting scrunched by * console host add notify, etc... * - moved message / notify tag constants to job.h and USED THEM. * - initialized nextjob properly... * - added new "joboffset" global in cons.c for dumping more * reasonable job numbers to user. * (Spanker=kohl) * * Revision 1.5 1997/07/09 13:21:09 pvmsrc * Fixed Author Header. * * Revision 1.4 1997/01/28 19:13:23 pvmsrc * New Copyright Notice & Authors. * * Revision 1.3 1996/10/24 23:04:56 pvmsrc * Added new #include "trcdef.h" for tracer library. * - added TRC_ID j_trcid field to job struct. * * Revision 1.2 1996/09/26 21:13:42 pvmsrc * Spanked the stupid CVS "Id" strings. * - comments for headers, not rcsid's stupid... :-Q * * Revision 1.1 1996/09/23 20:25:42 pvmsrc * Initial revision * * Revision 1.2 1994/06/03 20:01:52 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:30:32 manchek * Initial revision * */ /* include new tracer library header */ #include "trcdef.h" struct job { struct job *j_link, *j_rlink; /* chain of all jobs */ int j_jid; /* unique job id */ int j_flag; /* flags */ #define JOB_TRACE 1 TRC_ID j_trcid; /* tracer library handler ID */ struct obuf *j_obufs; /* head of obuf list, null if trace */ FILE *j_ff; /* if writing to file, else -1 */ }; #define GOTSPAWN 1 #define GOTEOF 2 /* Task Trace Status Constants - copied from trclib.h */ #define TRC_TASK_NOLIFE 0 #define TRC_TASK_ALIVE 1 #define TRC_TASK_DEAD 2 #define TRC_TASK_IGNORE 3 #define TRC_TASK_WAITEND 4 /* Task Output Status Constants - also copied from trclib.h */ #define TRC_TASK_NOOUT 0 #define TRC_TASK_OUT 1 #define TRC_TASK_EOF 2 #define TRC_TASK_WAITEOF 3 #define HostsAddedTag 0 #define MyExitTag 1 #define TrcHostAddTag 2 #define TrcHostDelTag 3 #define FirstJobTag 4 /* * used to collect output from a task */ struct obuf { struct obuf *o_link, *o_rlink; /* chain of all tasks in job */ int o_tid; /* task id */ char *o_buf; /* buffered partial line */ int o_len; /* length of buf */ int o_maxl; /* space in buf */ int o_flag; /* task state */ }; int job_init __ProtoGlarp__(( void )); struct job *job_new __ProtoGlarp__(( int jid )); struct job *job_find __ProtoGlarp__(( int jid )); int job_free __ProtoGlarp__(( struct job *jp )); struct obuf * obuf_new __ProtoGlarp__(( struct job *jp, int tid )); struct obuf * obuf_find __ProtoGlarp__(( struct job *jp, int tid )); int obuf_free __ProtoGlarp__(( struct job *jp, struct obuf *op )); int obuf_dump __ProtoGlarp__(( struct job *jp )); int checkoutput __ProtoGlarp__(( struct job *jp, int cc, int len, int cod, int src )); ./pvm3/console/myalloc.h0100644007401100000360000000462006741172436014367 0ustar kohlgopher /* $Id: myalloc.h,v 1.5 1999/07/08 18:59:42 kohl Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * myalloc.h * * Malloc defines. * * $Log: myalloc.h,v $ * Revision 1.5 1999/07/08 18:59:42 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.4 1997/07/09 13:21:10 pvmsrc * Fixed Author Header. * * Revision 1.3 1997/01/28 19:13:24 pvmsrc * New Copyright Notice & Authors. * * Revision 1.2 1996/09/26 21:13:45 pvmsrc * Spanked the stupid CVS "Id" strings. * - comments for headers, not rcsid's stupid... :-Q * * Revision 1.1 1996/09/23 20:25:43 pvmsrc * Initial revision * * Revision 1.3 1994/11/07 20:53:43 manchek * include stdlib if available * * Revision 1.2 1994/06/03 20:01:53 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:30:32 manchek * Initial revision * */ #ifdef HASSTDLIB #include #endif #define MY_ALLOC(n,g) malloc((unsigned)(n)) #define MY_REALLOC(p,n) realloc((char*)(p),(unsigned)(n)) #define MY_FREE(p) free((char*)(p)) #define TALLOC(n,t,g) (t*)MY_ALLOC((n)*sizeof(t),(g)) #define TREALLOC(p,n,t) (t*)MY_REALLOC(p,(n)*sizeof(t)) #define STRALLOC(s) strcpy(TALLOC(strlen(s)+1,char,"str"),s) ./pvm3/console/ALPHAMP/0042755007401100000360000000000010117676455013645 5ustar kohlgopher./pvm3/console/ALPHAMP/Makefile0100644007401100000360000000062306604767074015305 0ustar kohlgopher# # $Id: Makefile,v 1.4 1998/10/01 21:03:56 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/console PVM_ARCH = ALPHAMP CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) # install: default $(LIBDIR) default: $(MAKE) PVMLIB=pvm3s -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean $(LIBDIR): mkdir $(LIBDIR) ./pvm3/console/HPPAMP/0042755007401100000360000000000010117676455013550 5ustar kohlgopher./pvm3/console/HPPAMP/Makefile0100644007401100000360000000062206604767122015201 0ustar kohlgopher# # $Id: Makefile,v 1.3 1998/10/01 21:04:18 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/console PVM_ARCH = HPPAMP CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) # install: default $(LIBDIR) default: $(MAKE) PVMLIB=pvm3s -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean $(LIBDIR): mkdir $(LIBDIR) ./pvm3/console/OS2/0042755007401100000360000000000010117676455013166 5ustar kohlgopher./pvm3/console/OS2/Makefile0100644007401100000360000000060706401362443014612 0ustar kohlgopher# # $Id: Makefile,v 1.3 1997/08/28 20:52:51 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/console PVM_ARCH = OS2 CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) install: default $(LIBDIR) default: make LIBPREFIX="" -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install clean: make -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean $(LIBDIR): mkdir $(LIBDIR) ./pvm3/console/PGON/0042755007401100000360000000000010117676455013326 5ustar kohlgopher./pvm3/console/PGON/Makefile0100644007401100000360000000061206604767142014760 0ustar kohlgopher# # $Id: Makefile,v 1.3 1998/10/01 21:04:34 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/console PVM_ARCH = PGON CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) # install: default $(LIBDIR) default: $(MAKE) CC=icc -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean $(LIBDIR): mkdir $(LIBDIR) ./pvm3/console/RS6KMP/0042755007401100000360000000000010117676455013545 5ustar kohlgopher./pvm3/console/RS6KMP/Makefile0100644007401100000360000000063106604767166015206 0ustar kohlgopher# # $Id: Makefile,v 1.5 1998/10/01 21:04:54 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/console PVM_ARCH = RS6KMP CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) # install: default $(LIBDIR) default: $(MAKE) PVMLIB=pvm3s -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean $(LIBDIR): mkdir $(LIBDIR) ./pvm3/console/SGIMP64/0042755007401100000360000000000010117676455013614 5ustar kohlgopher./pvm3/console/SGIMP64/Makefile0100644007401100000360000000062306604767244015253 0ustar kohlgopher# # $Id: Makefile,v 1.4 1998/10/01 21:05:40 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/console PVM_ARCH = SGIMP64 CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) # install: default $(LIBDIR) default: $(MAKE) PVMLIB=pvm3s -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean $(LIBDIR): mkdir $(LIBDIR) ./pvm3/console/SGIMP6/0042755007401100000360000000000010117676455013530 5ustar kohlgopher./pvm3/console/SGIMP6/Makefile0100644007401100000360000000062206604767226015166 0ustar kohlgopher# # $Id: Makefile,v 1.2 1998/10/01 21:05:26 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/console PVM_ARCH = SGIMP6 CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) # install: default $(LIBDIR) default: $(MAKE) PVMLIB=pvm3s -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean $(LIBDIR): mkdir $(LIBDIR) ./pvm3/console/SGIMP/0042755007401100000360000000000010117676455013442 5ustar kohlgopher./pvm3/console/SGIMP/Makefile0100644007401100000360000000062106604767205015074 0ustar kohlgopher# # $Id: Makefile,v 1.4 1998/10/01 21:05:09 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/console PVM_ARCH = SGIMP CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) # install: default $(LIBDIR) default: $(MAKE) PVMLIB=pvm3s -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean $(LIBDIR): mkdir $(LIBDIR) ./pvm3/console/SUNMP/0042755007401100000360000000000010117676455013465 5ustar kohlgopher./pvm3/console/SUNMP/Makefile0100644007401100000360000000062106604767263015123 0ustar kohlgopher# # $Id: Makefile,v 1.4 1998/10/01 21:05:55 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/console PVM_ARCH = SUNMP CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) # install: default $(LIBDIR) default: $(MAKE) PVMLIB=pvm3s -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean $(LIBDIR): mkdir $(LIBDIR) ./pvm3/examples/0042755007401100000360000000000010117676455012737 5ustar kohlgopher./pvm3/examples/cygwin.mak0100644007401100000360000001621507240354763014727 0ustar kohlgopher#*****************************************************************************# # # makefile # for PVM Examples: # c: hello hello_other spmd master1 slave1 timing mbox bwtest # f: spmdf hit gexample ms-sl # #*****************************************************************************# include $(PVM_ROOT_U)/conf/win32cygwin.def PVM_BIN = $(PVM_ROOT_U)/bin/$(PVM_ARCH) SDIR = $(PVM_ROOT_U)/examples CPROGS = $(PVM_BIN)/gexample \ $(PVM_BIN)/hello \ $(PVM_BIN)/hello_other \ $(PVM_BIN)/master1 \ $(PVM_BIN)/slave1 \ $(PVM_BIN)/spmd \ $(PVM_BIN)/timing \ $(PVM_BIN)/timing_slave \ $(PVM_BIN)/mbox \ $(PVM_BIN)/bwtest CTXPROGS = $(PVM_BIN)/inherita \ $(PVM_BIN)/inheritb \ $(PVM_BIN)/inherit1 \ $(PVM_BIN)/inherit2 \ $(PVM_BIN)/inherit3 MBPROGS = $(PVM_BIN)/task0 \ $(PVM_BIN)/task1 \ $(PVM_BIN)/task_end \ $(PVM_BIN)/rme \ $(PVM_BIN)/lmbi \ $(PVM_BIN)/gmbi MHFPROGS = $(PVM_BIN)/mhf_server \ $(PVM_BIN)/mhf_tickle default: $(PVM_BIN)/hello_other $(PVM_BIN)/hello all: c-all # $(MHFPROGS) c-all: $(CPROGS) $(CTXPROGS) $(MBPROGS) # $(MHFPROGS) ############################################################### # C ############################################################### $(PVM_BIN)/timing: $(PVM_ARCH)/timing.o $(LIB) $(GLIB) $(CC) -o $(PVM_BIN)/timing $(PVM_ARCH)/timing.o \ $(LIB) $(GLIB) $(LINK_FLAGS) $(PVM_BIN)/timing_slave: $(PVM_ARCH)/timing_slave.o $(LIB) $(GLIB) $(CC) -o $(PVM_BIN)/timing_slave $(PVM_ARCH)/timing_slave.o \ $(LIB) $(GLIB) $(LINK_FLAGS) $(PVM_BIN)/gexample: $(PVM_ARCH)/gexample.o $(LIB) $(GLIB) $(CC) -o $(PVM_BIN)/gexample $(PVM_ARCH)/gexample.o \ $(LIB) $(GLIB) $(LINK_FLAGS) $(PVM_BIN)/hello: $(PVM_ARCH)/hello.o $(LIB) $(CC) -o $(PVM_BIN)/hello $(PVM_ARCH)/hello.o \ $(LIB) $(LINK_FLAGS) $(PVM_BIN)/hello_other: $(PVM_ARCH)/hello_other.o $(LIB) $(CC) -o $(PVM_BIN)/hello_other $(PVM_ARCH)/hello_other.o \ $(LIB) $(LINK_FLAGS) $(PVM_BIN)/mbox: $(PVM_ARCH)/mbox.o $(LIB) $(CC) -o $(PVM_BIN)/mbox $(PVM_ARCH)/mbox.o \ $(LIB) $(LINK_FLAGS) $(PVM_BIN)/bwtest: $(PVM_ARCH)/bwtest.o $(LIB) $(GLIB) $(CC) -o $(PVM_BIN)/bwtest $(PVM_ARCH)/bwtest.o \ $(LIB) $(GLIB) $(LINK_FLAGS) $(PVM_BIN)/master1: $(PVM_ARCH)/master1.o $(LIB) $(CC) -o $(PVM_BIN)/master1 $(PVM_ARCH)/master1.o \ $(LIB) $(LINK_FLAGS) $(PVM_BIN)/slave1: $(PVM_ARCH)/slave1.o $(LIB) $(CC) -o $(PVM_BIN)/slave1 $(PVM_ARCH)/slave1.o \ $(LIB) $(LINK_FLAGS) $(PVM_BIN)/spmd: $(PVM_ARCH)/spmd.o $(LIB) $(GLIB) $(CC) -o $(PVM_BIN)/spmd $(PVM_ARCH)/spmd.o \ $(LIB) $(GLIB) $(LINK_FLAGS) $(PVM_BIN)/inherita: $(PVM_ARCH)/inherita.o $(LIB) $(CC) -o $(PVM_BIN)/inherita $(PVM_ARCH)/inherita.o \ $(LIB) $(LINK_FLAGS) $(PVM_BIN)/inheritb: $(PVM_ARCH)/inheritb.o $(LIB) $(CC) -o $(PVM_BIN)/inheritb $(PVM_ARCH)/inheritb.o \ $(LIB) $(LINK_FLAGS) $(PVM_BIN)/inherit1: $(PVM_ARCH)/inherit1.o $(LIB) $(CC) -o $(PVM_BIN)/inherit1 $(PVM_ARCH)/inherit1.o \ $(LIB) $(LINK_FLAGS) $(PVM_BIN)/inherit2: $(PVM_ARCH)/inherit2.o $(LIB) $(CC) -o $(PVM_BIN)/inherit2 $(PVM_ARCH)/inherit2.o \ $(LIB) $(LINK_FLAGS) $(PVM_BIN)/inherit3: $(PVM_ARCH)/inherit3.o $(LIB) $(CC) -o $(PVM_BIN)/inherit3 $(PVM_ARCH)/inherit3.o \ $(LIB) $(LINK_FLAGS) $(PVM_BIN)/task0: $(PVM_ARCH)/task0.o $(PVM_ARCH)/taskf.o $(LIB) $(CC) -o $(PVM_BIN)/task0 $(PVM_ARCH)/task0.o $(PVM_ARCH)/taskf.o \ $(LIB) $(LINK_FLAGS) $(PVM_BIN)/task1: $(PVM_ARCH)/task1.o $(PVM_ARCH)/taskf.o $(LIB) $(CC) -o $(PVM_BIN)/task1 $(PVM_ARCH)/task1.o $(PVM_ARCH)/taskf.o \ $(LIB) $(LINK_FLAGS) $(PVM_BIN)/task_end: $(PVM_ARCH)/task_end.o $(LIB) $(CC) -o $(PVM_BIN)/task_end $(PVM_ARCH)/task_end.o \ $(LIB) $(LINK_FLAGS) $(PVM_BIN)/rme: $(PVM_ARCH)/rme.o $(LIB) $(CC) -o $(PVM_BIN)/rme $(PVM_ARCH)/rme.o \ $(LIB) $(LINK_FLAGS) $(PVM_BIN)/lmbi: $(PVM_ARCH)/lmbi.o $(PVM_ARCH)/taskf.o $(LIB) $(CC) -o $(PVM_BIN)/lmbi $(PVM_ARCH)/lmbi.o $(PVM_ARCH)/taskf.o \ $(LIB) $(LINK_FLAGS) $(PVM_BIN)/gmbi: $(PVM_ARCH)/gmbi.o $(PVM_ARCH)/taskf.o $(LIB) $(CC) -o $(PVM_BIN)/gmbi $(PVM_ARCH)/gmbi.o $(PVM_ARCH)/taskf.o \ $(LIB) $(LINK_FLAGS) $(PVM_BIN)/mhf_server: $(PVM_ARCH)/mhf_server.o $(LIB) $(CC) -o $(PVM_BIN)/mhf_server $(PVM_ARCH)/mhf_server.o \ $(LIB) $(LINK_FLAGS) $(PVM_BIN)/mhf_tickle: $(PVM_ARCH)/mhf_tickle.o $(LIB) $(CC) -o $(PVM_BIN)/mhf_tickle $(PVM_ARCH)/mhf_tickle.o \ $(LIB) $(LINK_FLAGS) ############# # C OBJS ############# $(PVM_ARCH)/mbox.o: $(SDIR)/mbox.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/mbox.o $(SDIR)/mbox.c $(PVM_ARCH)/bwtest.o: $(SDIR)/bwtest.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/bwtest.o $(SDIR)/bwtest.c $(PVM_ARCH)/timing.o: $(SDIR)/timing.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/timing.o $(SDIR)/timing.c $(PVM_ARCH)/timing_slave.o: $(SDIR)/timing_slave.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/timing_slave.o $(SDIR)/timing_slave.c $(PVM_ARCH)/gexample.o: $(SDIR)/gexample.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/gexample.o $(SDIR)/gexample.c $(PVM_ARCH)/hello.o: $(SDIR)/hello.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/hello.o $(SDIR)/hello.c $(PVM_ARCH)/hello_other.o: $(SDIR)/hello_other.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/hello_other.o $(SDIR)/hello_other.c $(PVM_ARCH)/master1.o: $(SDIR)/master1.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/master1.o $(SDIR)/master1.c $(PVM_ARCH)/slave1.o: $(SDIR)/slave1.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/slave1.o $(SDIR)/slave1.c $(PVM_ARCH)/spmd.o: $(SDIR)/spmd.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/spmd.o $(SDIR)/spmd.c $(PVM_ARCH)/taskf.o: $(SDIR)/taskf.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/taskf.o $(SDIR)/taskf.c $(PVM_ARCH)/inherita.o: $(SDIR)/inherita.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/inherita.o $(SDIR)/inherita.c $(PVM_ARCH)/inheritb.o: $(SDIR)/inheritb.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/inheritb.o $(SDIR)/inheritb.c $(PVM_ARCH)/inherit1.o: $(SDIR)/inherit1.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/inherit1.o $(SDIR)/inherit1.c $(PVM_ARCH)/inherit2.o: $(SDIR)/inherit2.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/inherit2.o $(SDIR)/inherit2.c $(PVM_ARCH)/inherit3.o: $(SDIR)/inherit3.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/inherit3.o $(SDIR)/inherit3.c $(PVM_ARCH)/task0.o: $(SDIR)/task0.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/task0.o $(SDIR)/task0.c $(PVM_ARCH)/task1.o: $(SDIR)/task1.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/task1.o $(SDIR)/task1.c $(PVM_ARCH)/task_end.o: $(SDIR)/task_end.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/task_end.o $(SDIR)/task_end.c $(PVM_ARCH)/rme.o: $(SDIR)/rme.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/rme.o $(SDIR)/rme.c $(PVM_ARCH)/lmbi.o: $(SDIR)/lmbi.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/lmbi.o $(SDIR)/lmbi.c $(PVM_ARCH)/gmbi.o: $(SDIR)/gmbi.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/gmbi.o $(SDIR)/gmbi.c $(PVM_ARCH)/mhf_server.o: $(SDIR)/mhf_server.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/mhf_server.o $(SDIR)/mhf_server.c $(PVM_ARCH)/mhf_tickle.o: $(SDIR)/mhf_tickle.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/mhf_tickle.o $(SDIR)/mhf_tickle.c # Clean up everything but the .EXEs clean: -rm -f $(PVM_ARCH)/*.o ./pvm3/examples/Makefile.aimk0100644007401100000360000001751610001306731015277 0ustar kohlgopher# # $Id: Makefile.aimk,v 1.18 2004/01/14 18:43:37 pvmsrc Exp $ # # Makefile.aimk for PVM example programs. # # Set PVM_ROOT to the path where PVM includes & libraries are installed. # Set PVM_ARCH to your architecture type (SUN4, HP9K, RS6K, SGI, etc.) # Set ARCHLIB to any special libs needed on PVM_ARCH (-lrpc, -lsocket, # etc.) # otherwise leave ARCHLIB blank # # PVM_ARCH and ARCHLIB, among other things, are set for you if you # use "$PVM_ROOT/lib/aimk" instead of "make". # # aimk also creates a $PVM_ARCH directory below this one and will cd # to it before invoking make - this allows building in parallel on # different arches. # SHELL = /bin/sh PVMDIR = ../.. SDIR = $(PVMDIR)/examples BDIR = $(PVMDIR)/bin XDIR = $(BDIR)/$(PVM_ARCH) CFLOPTS = -g CFLAGS = $(CFLOPTS) -I$(PVMDIR)/include $(ARCHCFLAGS) ##### Need to select some architecture-specific libraries to link tasks # The default setup is for workstations ### Select PVMLIB depending on architecture. # For MPPs (PGON and AIX5SP2/AIX4SP2/SP2MPI) select: # PVMLIB = -lpvm3pe # For Workstations and shared memory architectures select: # PVMLIB = -lpvm3 PVMLIB = -lpvm3 ### Select the PVMHLIB depending on architecture # Host versions of programs use sockets to communicate with the daemon. # They can be built with aimk hostprogs, they are only necessary for # MPPs and are OPTIONAL for other architectures # # For MPPs and Workstations select # PVMHLIB = -lpvm3 # for Shared Memory Archtiectures # PVMHLIB = -lpvm3s PVMHLIB = -lpvm3 ######################################################################## LIBS = $(PVMLIB) $(ARCHLIB) HLIBS = $(PVMHLIB) $(ARCHLIB) GLIBS = -lgpvm3 #F77 = f77 FORT = `case "$(FC)@$(F77)" in @) echo f77 ;; *@) echo $(FC) ;; @*) echo $(F77) ;; *) echo $(FC) ;; esac` FFLOPTS = -g FFLAGS = $(FFLOPTS) $(ARCHFFLAGS) FLIBS = -lfpvm3 LDFLAGS = $(LOPT) -L$(PVMDIR)/lib/$(PVM_ARCH) CPROGS = hello$(EXESFX) hello_other$(EXESFX) \ gexample$(EXESFX) \ master1$(EXESFX) slave1$(EXESFX) \ spmd$(EXESFX) \ timing$(EXESFX) timing_slave$(EXESFX) \ gmbi$(EXESFX) \ dbwtest$(EXESFX) ibwtest$(EXESFX) \ pbwtest$(EXESFX) rbwtest$(EXESFX) HOSTCPROGS = helloh gexampleh master1h timingh gmbih FPROGS = fgexample$(EXESFX) fmaster1$(EXESFX) fslave1$(EXESFX) \ fspmd$(EXESFX) hitc$(EXESFX) hitc_slave$(EXESFX) HOSTFPROGS = fmaster1h hitch CTXPROGS = inherita$(EXESFX) inheritb$(EXESFX) inherit1$(EXESFX) \ inherit2$(EXESFX) inherit3$(EXESFX) MBPROGS = taskf.o task0$(EXESFX) task1$(EXESFX) \ task_end$(EXESFX) rme$(EXESFX) \ lmbi$(EXESFX) gmbi$(EXESFX) MHFPROGS = mhf_server$(EXESFX) mhf_tickle$(EXESFX) default: hello$(EXESFX) hello_other$(EXESFX) all: c-all f-all c-all: $(CPROGS) $(CTXPROGS) $(MBPROGS) $(MHFPROGS) f-all: $(FPROGS) hostprogs: $(HOSTCRPROGS) $(HOSTFPROGS) clean: rm -f *.o $(CPROGS) $(FPROGS) $(CTXPROGS) $(MBPROGS) $(MHFPROGS) $(XDIR): - mkdir $(BDIR) - mkdir $(XDIR) hello$(EXESFX): $(SDIR)/hello.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/hello.c $(LDFLAGS) $(LIBS) mv $@ $(XDIR) helloh: $(SDIR)/hello.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/hello.c $(LDFLAGS) $(HLIBS) mv $@ $(XDIR) hello_other$(EXESFX): $(SDIR)/hello_other.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/hello_other.c $(LDFLAGS) $(LIBS) mv $@ $(XDIR) dbwtest$(EXESFX): $(SDIR)/bwtest.c $(XDIR) $(CC) $(CFLAGS) -DENCODE=PvmDataDefault -DPACK -o $@ \ $(SDIR)/bwtest.c $(LDFLAGS) $(GLIBS) $(LIBS) mv $@ $(XDIR) ibwtest$(EXESFX): $(SDIR)/bwtest.c $(XDIR) $(CC) $(CFLAGS) -DPACK -DENCODE=PvmDataInPlace -o $@ \ $(SDIR)/bwtest.c $(LDFLAGS) $(GLIBS) $(LIBS) mv $@ $(XDIR) pbwtest$(EXESFX): $(SDIR)/bwtest.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/bwtest.c $(LDFLAGS) $(GLIBS) $(LIBS) mv $@ $(XDIR) rbwtest$(EXESFX): $(SDIR)/bwtest.c $(XDIR) $(CC) $(CFLAGS) -DPACK -DENCODE=PvmDataRaw -o $@ \ $(SDIR)/bwtest.c $(LDFLAGS) $(GLIBS) $(LIBS) mv $@ $(XDIR) timing$(EXESFX): $(SDIR)/timing.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/timing.c $(LDFLAGS) $(LIBS) mv $@ $(XDIR) timingh: $(SDIR)/timing.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/timing.c $(LDFLAGS) $(HLIBS) mv $@ $(XDIR) timing_slave$(EXESFX): $(SDIR)/timing_slave.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/timing_slave.c $(LDFLAGS) $(LIBS) mv $@ $(XDIR) spmd$(EXESFX): $(SDIR)/spmd.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/spmd.c $(LDFLAGS) $(LIBS) mv $@ $(XDIR) fspmd$(EXESFX): $(SDIR)/spmd.f $(XDIR) $(FORT) $(FFLAGS) -o $@ $(SDIR)/spmd.f $(LDFLAGS) $(FLIBS) $(LIBS) mv $@ $(XDIR) master1$(EXESFX): $(SDIR)/master1.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/master1.c $(LDFLAGS) $(LIBS) mv $@ $(XDIR) master1h: $(SDIR)/master1.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/master1.c $(LDFLAGS) $(HLIBS) mv $@ $(XDIR) slave1$(EXESFX): $(SDIR)/slave1.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/slave1.c $(LDFLAGS) $(LIBS) mv $@ $(XDIR) fmaster1$(EXESFX): $(SDIR)/master1.f $(XDIR) $(FORT) $(FFLAGS) -o $@ $(SDIR)/master1.f \ $(LDFLAGS) $(FLIBS) $(LIBS) mv $@ $(XDIR) fmaster1h: $(SDIR)/master1.f $(XDIR) $(FORT) $(FFLAGS) -o $@ $(SDIR)/master1.f \ $(LDFLAGS) $(FLIBS) $(HLIBS) mv $@ $(XDIR) fslave1$(EXESFX): $(SDIR)/slave1.f $(XDIR) $(FORT) $(FFLAGS) -o $@ $(SDIR)/slave1.f $(LDFLAGS) $(FLIBS) $(LIBS) mv $@ $(XDIR) hitc$(EXESFX): $(SDIR)/hitc.f $(XDIR) $(FORT) $(FFLAGS) -o $@ $(SDIR)/hitc.f $(LDFLAGS) $(FLIBS) $(LIBS) mv $@ $(XDIR) hitch: $(SDIR)/hitc.f $(XDIR) $(FORT) $(FFLAGS) -o $@ $(SDIR)/hitc.f $(LDFLAGS) $(FLIBS) $(HLIBS) mv $@ $(XDIR) hitc_slave$(EXESFX): $(SDIR)/hitc_slave.f $(XDIR) $(FORT) $(FFLAGS) -o $@ $(SDIR)/hitc_slave.f \ $(LDFLAGS) $(FLIBS) $(LIBS) mv $@ $(XDIR) gexample$(EXESFX): $(SDIR)/gexample.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/gexample.c $(LDFLAGS) $(GLIBS) $(LIBS) mv $@ $(XDIR) gexampleh: $(SDIR)/gexample.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/gexample.c \ $(LDFLAGS) $(GLIBS) $(HLIBS) mv $@ $(XDIR) fgexample$(EXESFX): $(SDIR)/gexample.f $(XDIR) $(FORT) $(FFLAGS) -o $@ $(SDIR)/gexample.f \ $(LDFLAGS) $(FLIBS) $(GLIBS) $(LIBS) mv $@ $(XDIR) mbox$(EXESFX): $(SDIR)/mbox.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/mbox.c $(LDFLAGS) $(LIBS) mv $@ $(XDIR) inherita$(EXESFX): $(SDIR)/inherita.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/inherita.c $(LDFLAGS) $(LIBS) mv $@ $(XDIR) inheritb$(EXESFX): $(SDIR)/inheritb.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/inheritb.c $(LDFLAGS) $(LIBS) mv $@ $(XDIR) inherit1$(EXESFX): $(SDIR)/inherit1.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/inherit1.c $(LDFLAGS) $(LIBS) mv $@ $(XDIR) inherit2$(EXESFX): $(SDIR)/inherit2.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/inherit2.c $(LDFLAGS) $(LIBS) mv $@ $(XDIR) inherit3$(EXESFX): $(SDIR)/inherit3.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/inherit3.c $(LDFLAGS) $(LIBS) mv $@ $(XDIR) taskf.o: $(SDIR)/taskf.c $(CC) $(CFLAGS) -c $(SDIR)/taskf.c task0$(EXESFX): $(SDIR)/task0.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/task0.c taskf.o $(LDFLAGS) $(LIBS) mv $@ $(XDIR) task1$(EXESFX): $(SDIR)/task1.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/task1.c taskf.o $(LDFLAGS) $(LIBS) mv $@ $(XDIR) task_end$(EXESFX): $(SDIR)/task_end.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/task_end.c taskf.o $(LDFLAGS) $(LIBS) mv $@ $(XDIR) rme$(EXESFX): $(SDIR)/rme.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/rme.c taskf.o $(LDFLAGS) $(LIBS) mv $@ $(XDIR) lmbi$(EXESFX): $(SDIR)/lmbi.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/lmbi.c taskf.o $(LDFLAGS) $(HLIBS) mv $@ $(XDIR) gmbi$(EXESFX): $(SDIR)/gmbi.c taskf.o $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/gmbi.c taskf.o $(LDFLAGS) $(LIBS) mv $@ $(XDIR) gmbih: $(SDIR)/gmbi.c taskf.o $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/gmbi.c taskf.o $(LDFLAGS) $(HLIBS) mv $@ $(XDIR) mhf_server$(EXESFX): $(SDIR)/mhf_server.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/mhf_server.c $(LDFLAGS) $(LIBS) mv $@ $(XDIR) mhf_tickle$(EXESFX): $(SDIR)/mhf_tickle.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/mhf_tickle.c $(LDFLAGS) $(LIBS) mv $@ $(XDIR) ./pvm3/examples/Makefile.mak0100644007401100000360000003213206672252420015133 0ustar kohlgopher# # $Id: Makefile.mak,v 1.11 1999/03/12 17:55:28 pvmsrc Exp $ # #*************************************************************# #** **# #** PVM Examples: **# #** c: hello.exe hello_other.exe **# #** spmd.exe master1 slave1 **# #** timing mbox bwtest **# #** f: spmdf hit **# #** gexample ms-sl **# #*************************************************************# !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !include $(PVM_ROOT)\conf\$(PVM_ARCH).def SDIR = $(PVM_ROOT)\examples CPROGS = gexample hello hello_other master1 slave1 spmd \ timing timing_slave mbox bwtest FPROGS = fmaster1 fslave1 fspmd hitc hitc_slave CTXPROGS = inherita inheritb inherit1 inherit2 inherit3 MBPROGS = task0 task1 task_end rme lmbi gmbi MHFPROGS = mhf_server mhf_tickle LIB = $(PVM_ROOT)\lib\$(PVM_ARCH)\libpvm3.lib GLIB = $(PVM_ROOT)\lib\$(PVM_ARCH)\libgpvm3.lib FLIB = $(PVM_ROOT)\libfpvm\$(PVM_ARCH)\libfpvm3.lib FLIBPATH = /LIBPATH:$(PVM_FLIBDIR) \ /LIBPATH:$(PVM_CLIBDIR) default: bin hello_other hello all: bin c-all f-all c-all: bin $(CPROGS) $(CTXPROGS) $(MBPROGS) $(MHFPROGS) f-all: bin $(FPROGS) ############################################################### # C ############################################################### bin: if not exist "$(PVM_ARCH)\$(NULL)" mkdir "$(PVM_ARCH)" if not exist "$(PVM_ROOT)\bin\$(NULL)" mkdir "$(PVM_ROOT)\bin" if not exist "$(PVM_ROOT)\bin\$(PVM_ARCH)\$(NULL)" \ mkdir "$(PVM_ROOT)\bin\$(PVM_ARCH)" timing: $(PVM_ARCH)\timing.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\timing.exe \ $(PVM_ARCH)\timing.obj $(LIB) $(GLIB) $(link_flags) timing_slave: $(PVM_ARCH)\timing_slave.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\timing_slave.exe \ $(PVM_ARCH)\timing_slave.obj $(LIB) $(GLIB) $(link_flags) gexample: $(PVM_ARCH)\gexample.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\gexample.exe \ $(PVM_ARCH)\gexample.obj $(LIB) $(GLIB) $(link_flags) hello: $(PVM_ARCH)\hello.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\hello.exe \ $(PVM_ARCH)\hello.obj $(LIB) $(link_flags) hello_other: $(PVM_ARCH)\hello_other.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\hello_other.exe \ $(PVM_ARCH)\hello_other.obj $(LIB) $(link_flags) mbox: $(PVM_ARCH)\mbox.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\mbox.exe \ $(PVM_ARCH)\mbox.obj $(LIB) $(link_flags) bwtest: $(PVM_ARCH)\bwtest.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\bwtest.exe \ $(PVM_ARCH)\bwtest.obj $(LIB) $(GLIB) $(link_flags) master1: $(PVM_ARCH)\master1.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\master1.exe \ $(PVM_ARCH)\master1.obj $(LIB) $(link_flags) slave1: $(PVM_ARCH)\slave1.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\slave1.exe \ $(PVM_ARCH)\slave1.obj $(LIB) $(link_flags) spmd: $(PVM_ARCH)\spmd.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\spmd.exe \ $(PVM_ARCH)\spmd.obj $(LIB) $(GLIB) $(link_flags) inherita: $(PVM_ARCH)\inherita.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\inherita.exe \ $(PVM_ARCH)\inherita.obj $(LIB) $(link_flags) inheritb: $(PVM_ARCH)\inheritb.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\inheritb.exe \ $(PVM_ARCH)\inheritb.obj $(LIB) $(link_flags) inherit1: $(PVM_ARCH)\inherit1.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\inherit1.exe \ $(PVM_ARCH)\inherit1.obj $(LIB) $(link_flags) inherit2: $(PVM_ARCH)\inherit2.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\inherit2.exe \ $(PVM_ARCH)\inherit2.obj $(LIB) $(link_flags) inherit3: $(PVM_ARCH)\inherit3.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\inherit3.exe \ $(PVM_ARCH)\inherit3.obj $(LIB) $(link_flags) task0: $(PVM_ARCH)\task0.obj $(PVM_ARCH)\taskf.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\task0.exe \ $(PVM_ARCH)\task0.obj $(PVM_ARCH)\taskf.obj $(LIB) $(link_flags) task1: $(PVM_ARCH)\task1.obj $(PVM_ARCH)\taskf.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\task1.exe \ $(PVM_ARCH)\task1.obj $(PVM_ARCH)\taskf.obj $(LIB) $(link_flags) task_end: $(PVM_ARCH)\task_end.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\task_end.exe \ $(PVM_ARCH)\task_end.obj $(LIB) $(link_flags) rme: $(PVM_ARCH)\rme.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\rme.exe \ $(PVM_ARCH)\rme.obj $(LIB) $(link_flags) lmbi: $(PVM_ARCH)\lmbi.obj $(PVM_ARCH)\taskf.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\lmbi.exe \ $(PVM_ARCH)\lmbi.obj $(PVM_ARCH)\taskf.obj $(LIB) $(link_flags) gmbi: $(PVM_ARCH)\gmbi.obj $(PVM_ARCH)\taskf.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\gmbi.exe \ $(PVM_ARCH)\gmbi.obj $(PVM_ARCH)\taskf.obj $(LIB) $(link_flags) mhf_server: $(PVM_ARCH)\mhf_server.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\mhf_server.exe \ $(PVM_ARCH)\mhf_server.obj $(LIB) $(link_flags) mhf_tickle: $(PVM_ARCH)\mhf_tickle.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\mhf_tickle.exe \ $(PVM_ARCH)\mhf_tickle.obj $(LIB) $(link_flags) ############# # C OBJS ############# $(PVM_ARCH)\mbox.obj: $(SDIR)\mbox.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\mbox.obj $(SDIR)\mbox.c $(PVM_ARCH)\bwtest.obj: $(SDIR)\bwtest.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\bwtest.obj $(SDIR)\bwtest.c $(PVM_ARCH)\timing.obj: $(SDIR)\timing.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\timing.obj $(SDIR)\timing.c $(PVM_ARCH)\timing_slave.obj: $(SDIR)\timing_slave.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\timing_slave.obj $(SDIR)\timing_slave.c $(PVM_ARCH)\gexample.obj: $(SDIR)\gexample.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\gexample.obj $(SDIR)\gexample.c $(PVM_ARCH)\hello.obj: $(SDIR)\hello.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\hello.obj $(SDIR)\hello.c $(PVM_ARCH)\hello_other.obj: $(SDIR)\hello_other.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\hello_other.obj $(SDIR)\hello_other.c $(PVM_ARCH)\master1.obj: $(SDIR)\master1.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\master1.obj $(SDIR)\master1.c $(PVM_ARCH)\slave1.obj: $(SDIR)\slave1.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\slave1.obj $(SDIR)\slave1.c $(PVM_ARCH)\spmd.obj: $(SDIR)\spmd.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\spmd.obj $(SDIR)\spmd.c $(PVM_ARCH)\taskf.obj: $(SDIR)\taskf.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\taskf.obj $(SDIR)\taskf.c $(PVM_ARCH)\inherita.obj: $(SDIR)\inherita.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\inherita.obj $(SDIR)\inherita.c $(PVM_ARCH)\inheritb.obj: $(SDIR)\inheritb.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\inheritb.obj $(SDIR)\inheritb.c $(PVM_ARCH)\inherit1.obj: $(SDIR)\inherit1.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\inherit1.obj $(SDIR)\inherit1.c $(PVM_ARCH)\inherit2.obj: $(SDIR)\inherit2.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\inherit2.obj $(SDIR)\inherit2.c $(PVM_ARCH)\inherit3.obj: $(SDIR)\inherit3.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\inherit3.obj $(SDIR)\inherit3.c $(PVM_ARCH)\task0.obj: $(SDIR)\task0.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\task0.obj $(SDIR)\task0.c $(PVM_ARCH)\task1.obj: $(SDIR)\task1.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\task1.obj $(SDIR)\task1.c $(PVM_ARCH)\task_end.obj: $(SDIR)\task_end.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\task_end.obj $(SDIR)\task_end.c $(PVM_ARCH)\rme.obj: $(SDIR)\rme.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\rme.obj $(SDIR)\rme.c $(PVM_ARCH)\lmbi.obj: $(SDIR)\lmbi.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\lmbi.obj $(SDIR)\lmbi.c $(PVM_ARCH)\gmbi.obj: $(SDIR)\gmbi.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\gmbi.obj $(SDIR)\gmbi.c $(PVM_ARCH)\mhf_server.obj: $(SDIR)\mhf_server.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\mhf_server.obj $(SDIR)\mhf_server.c $(PVM_ARCH)\mhf_tickle.obj: $(SDIR)\mhf_tickle.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\mhf_tickle.obj $(SDIR)\mhf_tickle.c ############################################################# # FORTRAN ############################################################# fspmd: $(PVM_ARCH)\spmdf.obj $(linkexe) $(conflags) $(FLIBPATH) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\spmdf.exe \ $(PVM_ARCH)\spmdf.obj $(LIB) $(GLIB) $(FLIB) $(link_flags) fmaster1: $(PVM_ARCH)\master1f.obj $(linkexe) $(conflags) $(FLIBPATH) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\fmaster1.exe \ $(PVM_ARCH)\master1f.obj $(LIB) $(GLIB) $(FLIB) $(link_flags) fslave1: $(PVM_ARCH)\slave1f.obj $(linkexe) $(conflags) $(FLIBPATH) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\fslave1.exe \ $(PVM_ARCH)\slave1f.obj $(LIB) $(GLIB) $(FLIB) $(link_flags) fgexample: $(PVM_ARCH)\gexamplef.obj $(linkexe) $(conflags) $(FLIBPATH) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\fgexample.exe \ $(PVM_ARCH)\gexamplef.obj $(LIB) $(GLIB) $(FLIB) $(link_flags) hitc: $(PVM_ARCH)\hitc.obj $(linkexe) $(conflags) $(FLIBPATH) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\hitc.exe \ $(PVM_ARCH)\hitc.obj $(LIB) $(GLIB) $(FLIB) $(link_flags) hitc_slave: $(PVM_ARCH)\hitc_slave.obj $(linkexe) $(conflags) $(FLIBPATH) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\hitc_slave.exe \ $(PVM_ARCH)\hitc_slave.obj $(LIB) $(GLIB) $(FLIB) $(link_flags) ############## # FORTRAN OBJS ############## $(PVM_ARCH)\hitc.obj: $(SDIR)\hitc.f $(fc) $(cdebug) /Fo$(PVM_ARCH)\hitc.obj $(fflags) $(cvars) \ $(SDIR)\hitc.f $(PVM_ARCH)\hitc_slave.obj: $(SDIR)\hitc_slave.f $(fc) $(cdebug) /Fo$(PVM_ARCH)\hitc_slave.obj $(fflags) $(cvars) \ $(SDIR)\hitc_slave.f $(PVM_ARCH)\spmdf.obj: $(SDIR)\spmd.f $(fc) $(cdebug) /Fo$(PVM_ARCH)\spmdf.obj $(fflags) $(cvars) \ $(SDIR)\spmd.f $(PVM_ARCH)\gexamplef.obj: $(SDIR)\gexample.f $(fc) $(cdebug) /Fo$(PVM_ARCH)\gexamplef.obj $(fflags) $(cvars) \ $(SDIR)\gexample.f $(PVM_ARCH)\slave1f.obj: $(SDIR)\slave1.f $(fc) $(cdebug) /Fo$(PVM_ARCH)\slave1f.obj $(fflags) $(cvars) \ $(SDIR)\slave1.f $(PVM_ARCH)\master1f.obj: $(SDIR)\master1.f $(fc) $(cdebug) /Fo$(PVM_ARCH)\master1f.obj $(fflags) $(cvars) \ $(SDIR)\master1.f # Clean all Fortran example codes - .OBJ and .EXE tidy-f: -del $(PVM_ARCH)\spmdf.obj -del $(PVM_ARCH)\master1f.obj -del $(PVM_ARCH)\slave1f.obj -del $(PVM_ARCH)\gexamplef.obj -del $(PVM_ARCH)\hitc.obj -del $(PVM_ARCH)\hitc_slave.obj -del $(PVM_ROOT)\bin\$(PVM_ARCH)\spmdf.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\fmaster1.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\fslave1.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\fgexample.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\hitc.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\hitc_slave.exe # Clean all C example codes - .OBJ and .EXE tidy-c: -del $(PVM_ARCH)\timing.obj -del $(PVM_ARCH)\timing_slave.obj -del $(PVM_ARCH)\gexample.obj -del $(PVM_ARCH)\hello.obj -del $(PVM_ARCH)\hello_other.obj -del $(PVM_ARCH)\mbox.obj -del $(PVM_ARCH)\bwtest.obj -del $(PVM_ARCH)\master1.obj -del $(PVM_ARCH)\slave1.obj -del $(PVM_ARCH)\spmd.obj -del $(PVM_ARCH)\inherita.obj -del $(PVM_ARCH)\inheritb.obj -del $(PVM_ARCH)\inherit1.obj -del $(PVM_ARCH)\inherit2.obj -del $(PVM_ARCH)\inherit3.obj -del $(PVM_ARCH)\task0.obj -del $(PVM_ARCH)\taskf.obj -del $(PVM_ARCH)\task1.obj -del $(PVM_ARCH)\task_end.obj -del $(PVM_ARCH)\rme.obj -del $(PVM_ARCH)\lmbi.obj -del $(PVM_ARCH)\gmbi.obj -del $(PVM_ARCH)\mhf_server.obj -del $(PVM_ARCH)\mhf_tickle.obj -del $(PVM_ROOT)\bin\$(PVM_ARCH)\timing.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\timing_slave.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\gexample.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\hello.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\hello_other.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\mbox.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\bwtest.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\master1.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\slave1.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\spmd.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\inherita.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\inheritb.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\inherit1.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\inherit2.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\inherit3.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\task0.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\task1.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\task_end.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\rme.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\lmbi.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\gmbi.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\mhf_server.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\mhf_tickle.exe # Clean up everything but the .EXEs clean: -del *.obj -del *.pdb ./pvm3/examples/Readme0100644007401100000360000001641506355024741014053 0ustar kohlgopher PVM Version 3.4 EXAMPLES _____________________________________________________________________ This directory contains C and FORTRAN example programs using PVM 3.4 All examples assume that pvm is installed and currently running. Each target can be made separately by typing in % aimk Each section tells how to compile the example, run the example, and what output is expected. Some of the examples run slightly differently on MPPs (PGON and SP2MPI), the difference are noted, where applicable in the section "MPP notes". =============================================================== 1.) hello + hello_other: Two programs that cooperate - shows how to create a new task and pass messages between tasks. Source files: hello.c hello_other.c To compile: % aimk hello hello_other Run from shell: % hello Run from pvm console: pvm> spawn -> hello Sample output: i'm t40002 from t40003: hello, world from gollum.epm.ornl.gov MPP Notes: If you desire to run the hello example from the shell, then you need to compile the "helloh" % aimk helloh % helloh =============================================================== 2.) master1 + slave1, fmaster1 + fslave1 A master/slave example where the master process creates and directs some number of slave processes that cooperate to do the work. C and FORTRAN versions. [f]master1 will spawn 3*<#hosts> slave tasks on the virtual machine. Source files: master1.c slave1.c master1.f slave1.f To compile: % aimk master1 slave1 fmaster1 fslave1 To run from shell (C version): % master1 To run from shell (Fortran version) % fmaster1 To Run from PVM console: pvm> spawn -> master1 OR pvm> spawn -> fmaster1 Sample output: Spawning 3 worker tasks ... SUCCESSFUL I got 100.000000 from 1; (expecting 100.000000) I got 200.000000 from 0; (expecting 200.000000) I got 300.000000 from 2; (expecting 300.000000) MPP Notes: If you desire to run the master examples from the shell, then you need to compile the "master1h", fmaster1h" % aimk master1h fmaster1h % master1h =============================================================== 3.) spmd, fspmd An SPMD (Single Program Multiple Data) example that uses pvm_siblings (pvmfsiblings) to determine the number of tasks (and their task ids) that were spawned together. The parallel computation then performs a simple token ring and passes a message. This program should be run from the pvm console. Source Files: spmd.c spmd.f To compile: % aimk spmd fspmd To run from pvm console: pvm> spawn -4 -> spmd OR pvm> spawn -4 -> fspmd Sample output: [4:t4000f] Pass a token through the 4 tid ring: [4:t4000f] 262159 -> 262160 -> 262161 -> 262162 -> 262159 [4:t4000f] token ring done =============================================================== 4.) dbwtest, ibwtest, pbwtest, rbwtest A simple bandwidth tester. This test uses standard ping-pong type tests and illustrates how different packing/sending can affect message performance. This example can be compiled with several different options to test different types of packing. dbwtest - pvm default (PvmDataDefault) packing ibwtest - pvm inplace packing (PvmInPlace) pbwtest - pvm_psend/precv rbwtest - pvm raw data packing (PvmRaw) Source files: bwtest.c To compile: % aimk dbwtest ibwtest pbwtest rbwtest To run from console: pvm> spawn -2 -> dbwtest To run from the shell: machine1% dbwtest machine2% dbwtest (Note two copies of _bwtest must be running for the code to complete) Sample output: [4:t40003] --- Simple PVM Bandwidth Test ---- [4:t40003] Using pack option: PvmDataDefault [4:t40003] Max data size is: 800000 [4:t40003] Number of iterations/sample: 20 [4:t40003] [4:t40003] [4:t40003] Roundtrip time is measured from user-space to user-space. [4:t40003] For packed messages this includes the combined time of: [4:t40003] inst 0: pvm_initsend() [4:t40003] inst 0: pvm_pack() [4:t40003] inst 0: pvm_send() [4:t40003] inst 1: pvm_recv() [4:t40003] inst 1: pvm_unpack() [4:t40003] inst 1: pvm_initsend() [4:t40003] inst 1: pvm_pack() [4:t40003] inst 1: pvm_send() [4:t40003] inst 0: pvm_recv() [4:t40003] inst 0: pvm_unpack() [4:t40003] [4:t40003] [4:t40003] --------------------------------------- [4:t40003] 40003 -- I am the master [4:t40003] t40003: 100000 doubles received correctly [4:t40003] [4:t40003] [4:t40003] Roundtrip T = 1247 (us) (0.0000 MB/s) Data size: 0 [4:t40003] Roundtrip T = 1090 (us) (0.0147 MB/s) Data size: 8 [4:t40003] Roundtrip T = 1161 (us) (0.1378 MB/s) Data size: 80 [4:t40003] Roundtrip T = 1589 (us) (1.0069 MB/s) Data size: 800 [4:t40003] Roundtrip T = 6556 (us) (2.4405 MB/s) Data size: 8000 [4:t40003] Roundtrip T = 64579 (us) (2.4776 MB/s) Data size: 80000 [4:t40003] Roundtrip T = 668035 (us) (2.3951 MB/s) Data size: 800000 =============================================================== 5.) timing + timing_slave: A simple program to illustrate how to measure network bandwidth and latency. =============================================================== 6.) hitc + hitc_slave: A simplified kernel of a larger supercondutor application, hitc illustrates dynamic load balancing using the 'pool of tasks' paradigm. A synthetic workload is created in this example, and hitc automatically places one slave per host. =============================================================== 7.) gexample, fgexample Illustrates the use of group functions including reduce f.e. global sum and user defined reduce functions. Source files: gexample.c gexample.f To compile: % aimk gexample fgexample To run from the shell: % gexample To run from the PVM console: pvm> spawn -3 -> gexample Sample output: [7:t4004f] This program demonstrates some group and reduction [7:t4004f] operations in PVM. The output displays the [7:t4004f] the product of the first column of a Toeplitz matrix [7:t4004f] and the matrix 1-norm. The matrix data is distributed [7:t4004f] among several processors. The Toeplitz matrix is [7:t4004f] symmetric with the first row being the row [7:t4004f] vector [1 2 ... n]. [7:t4004f] [7:t4004f] --> Using 3 processors <-- [7:t4004f] [7:t4004f] The 1-Norm is 5050 [7:t4004f] ( Should be the sum of the integers from 1 to 100 ) [7:t4004f] The product of column 1 is 9.33262e+157 [7:t4004f] ( Should be 100 factorial) MPP Notes: MPPs need host versions of programs run from the shell. These are the targets gexampleh, fgexampleh. % aimk gexampleh fgexampleh % gexampleh *********************************************************************** *********************************************************************** The executables are placed in pvm3/bin/ARCH. Step 1) Start PVM Start up PVM by typing pvm [hostfile] This console allows the user to add/delete hosts if desired. Step 2) Run the desired example Step 3) Stop PVM When the user is through with the virtual machine PVM can be shut down by giving 'halt' command to PVM console. pvm> halt ./pvm3/examples/bwtest.c0100644007401100000360000001636606673254662014426 0ustar kohlgopher static char rcsid[] = "$Id: bwtest.c,v 1.11 1999/03/15 19:04:18 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* bwtest.c - bandwidth tester * This is yet another bandwidth tester. * It measures user-space to user-space times. * * The measurement is a standard ping-pong with roundtrip time measured * from the originating sender. * * This is a PVM test code */ #include "pvm3.h" #include "stdio.h" /* needed to help 64bit compilers understand printf */ #ifndef SAMPLE #define SAMPLE 20 /* sample rate */ #endif #ifndef MAXSIZE #define MAXSIZE 100000 /* must be a power of 10 */ #endif #define VTAG 10 #define MTAG 100 #ifndef ENCODE #define ENCODE PvmDataInPlace #endif #define GETTIME(_x,_y) pvmgetclock((_x)) #ifndef WIN32 #include #else #include #endif struct timeval tv1, tv2; #define TIMER_CLEAR (tv1.tv_sec = tv1.tv_usec = tv2.tv_sec = tv2.tv_usec =0) #define TIMER_START GETTIME(&tv1, (struct timezone*)0) #define TIMER_STOP GETTIME(&tv2, (struct timezone*)0) #define TIMER_ELAPSED \ ( ( tv2.tv_usec - tv1.tv_usec ) \ + ( ( tv2.tv_sec - tv1.tv_sec) * 1.E6 ) ) #define GNAME "bwtest" void pingpong(); /* where all the work is done and measured */ main(argc, argv) int argc; char *argv[]; { int mytid; int myinst; int othertid; int otherinst; if ((mytid = pvm_mytid()) < 0) exit(-1); if((myinst = pvm_joingroup(GNAME)) < 0) { pvm_perror("Error joining bwtest group"); exit(-1); } printf(" %x myinst is %d \n", mytid, myinst); switch (myinst % 2) { case 0: otherinst = myinst + 1; while ((othertid = pvm_gettid(GNAME, otherinst)) < 0) pvmsleep(1); pingpong(mytid, othertid); break; case 1: otherinst = myinst - 1; while ((othertid = pvm_gettid(GNAME, otherinst)) < 0) pvmsleep(1); pingpong(othertid, mytid); break; } pvm_lvgroup(GNAME); pvm_exit(); } void validate(data, size) double data[]; int size; { int i; int mytid; mytid = pvm_mytid(); for (i = 0; i < size; i++) if ((i*i - data[i]) > 0.01) { printf("error: data[%d] = %g\n", i, data[i]); break; } if (i == size) printf("t%x: %d doubles received correctly\n\n\n", mytid, i); } /* exchange messages and measure the transit time */ void pingpong(mastertid, slavetid) int mastertid; int slavetid; { int ismaster; int mytid; int n; int size; int t; static double data[MAXSIZE]; char str[32]; /* test node-to-node send */ mytid = pvm_mytid(); ismaster = ( mytid == mastertid ); if (ismaster) { #ifdef PACK print_header(ENCODE, MAXSIZE*sizeof(double), SAMPLE); #else print_header(-1, MAXSIZE*sizeof(double), SAMPLE); #endif } printf("%x -- I am the %s \n", mytid, (ismaster ? "master" : "slave")); /* first validate that all doubles are sent and returned correctly */ if (ismaster) { for (n = 0; n < MAXSIZE; n++) data[n] = n*n; #ifdef PACK pvm_initsend(ENCODE); pvm_pkdouble(data, MAXSIZE, 1); pvm_send(slavetid, VTAG); /* send the data */ pvm_recv(slavetid, VTAG); /* recv it back and validate */ pvm_upkdouble(data, MAXSIZE, 1); #else pvm_psend(slavetid, VTAG, data, MAXSIZE, PVM_DOUBLE); pvm_precv(slavetid, VTAG, data, MAXSIZE, PVM_DOUBLE, (int*)0, (int*)0, (int*)0); #endif } else { #ifdef PACK pvm_recv(mastertid, VTAG); /* recv and unpack */ pvm_upkdouble(data, MAXSIZE, 1); pvm_initsend(ENCODE); /* echo */ pvm_pkdouble(data, MAXSIZE, 1); pvm_send(mastertid, VTAG); /* send the data */ #else pvm_precv(mastertid, VTAG, data, MAXSIZE, PVM_DOUBLE, (int*)0, (int*)0, (int*)0); pvm_psend(mastertid, VTAG, data, MAXSIZE, PVM_DOUBLE); #endif } validate(data, MAXSIZE); sprintf(str, "%d doubles from t%x", MAXSIZE, slavetid); /* now do the ping-pong */ for (size = 0; size <= MAXSIZE; size = ( size ? 10*size : 1) ) { TIMER_CLEAR; TIMER_START; for (n = 0; n < SAMPLE; n++) { if (ismaster) { #ifdef PACK pvm_initsend(ENCODE); pvm_pkdouble(data, size, 1); pvm_send(slavetid, MTAG); pvm_recv(slavetid, MTAG); pvm_upkdouble(data, size, 1); #else pvm_psend(slavetid, MTAG, data, size, PVM_DOUBLE); pvm_precv(slavetid, MTAG, data, size, PVM_DOUBLE, (int*)0, (int*)0, (int*)0); #endif /*PACK*/ } else { #ifdef PACK pvm_recv(mastertid, MTAG); pvm_upkdouble(data, size, 1); pvm_initsend(ENCODE); pvm_pkdouble(data, size, 1); pvm_send(mastertid, MTAG); #else pvm_precv(mastertid, MTAG, data, size, PVM_DOUBLE, (int*)0, (int*)0, (int*)0); pvm_psend(mastertid, MTAG, data, size, PVM_DOUBLE); #endif /*PACK*/ } } if (ismaster) { TIMER_STOP; t = (int) TIMER_ELAPSED / SAMPLE; printf("Roundtrip T = %d (us) (%.4f MB/s) Data size: %d\n", t, 2.0*8.0*(float)size/(float)t, ((int)sizeof(double))*size); } } } int print_header(packtype, size, niter) int packtype; int size; int niter; { printf("--- Simple PVM Bandwidth Test ----\n"); printf(" Using pack option: %s \n", (packtype == PvmDataRaw ? "PvmDataRaw" : (packtype == PvmDataInPlace ? "PvmDataInPlace" : (packtype == PvmDataDefault ? "PvmDataDefault" : (packtype == -1 ? "Psend/Precv" : "Unknown"))))); printf(" Max data size is: %d \n", size); printf(" Number of iterations/sample: %d \n", niter); printf(" \n\n"); printf(" Roundtrip time is measured from user-space to user-space.\n"); if ( packtype != -1) { printf(" For packed messages this includes the combined time of: \n"); printf(" inst 0: pvm_initsend() \n"); printf(" inst 0: pvm_pack() \n"); printf(" inst 0: pvm_send() \n"); printf(" inst 1: pvm_recv() \n"); printf(" inst 1: pvm_unpack() \n"); printf(" inst 1: pvm_initsend() \n"); printf(" inst 1: pvm_pack() \n"); printf(" inst 1: pvm_send() \n"); printf(" inst 0: pvm_recv() \n"); printf(" inst 0: pvm_unpack() \n"); } else { printf(" For pvm_psend/precv this includes the combined time of: \n"); printf(" inst 0: pvm_psend() \n"); printf(" inst 1: pvm_precv() \n"); printf(" inst 1: pvm_psend() \n"); printf(" inst 0: pvm_precv() \n"); } printf("\n\n---------------------------------------\n"); return 0; } ./pvm3/examples/gexample.c0100644007401100000360000001430606625343447014705 0ustar kohlgopher static char rcsid[] = "$Id: gexample.c,v 1.4 1998/11/20 19:46:47 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* Example of some group function and reduction functions in PVM * * 11 March 1994 - Creation by P. Papadopoulos (phil@msr.epm.ornl.gov) * 27 June 1997 - updated to allow spmd-style startups for PVM 3.4 * * */ #include #ifdef HASSTDLIB #include #endif #include "pvm3.h" #ifdef WIN32 #ifdef min #undef min #endif #ifdef max #undef max #endif #endif #define min(u,v) ( (u) < (v) ? (u) : (v) ) #define max(u,v) ( (u) > (v) ? (u) : (v) ) #define MATRIXGROUP "matrix" #define DEFAULT_DIMENSION 100 #define DEFAULT_NPROC 10 #define INITTAG 1000 #define SUMTAG INITTAG + 1 #define PRODTAG SUMTAG + 1 extern void calcprod(); main() { int info, mytid, myinst, gsize, nproc = 0; int maxmax; int dimension = 0; int ninst, error; int tids[32]; int *subblock, *colsum; double *colprod; int blksize,nextra,mysrow,i,j,sumsqr,itemp; int *stids; int spmd = 0; /* flag to indicate we were started in a spmd-style */ int nsibs; mytid = pvm_mytid(); /* enroll */ if ((nsibs = pvm_siblings( &stids )) > 1) /* nsibs spawned together */ spmd = 1; if( (myinst = pvm_joingroup(MATRIXGROUP)) < 0 ) { pvm_perror( "Could not join group \n" ); pvm_exit(); exit( -1 ); } if ( myinst == 0 ) { printf(" This program demonstrates some group and reduction \n"); printf(" operations in PVM. The output displays the \n"); printf(" the product of the first column of a Toeplitz matrix\n"); printf(" and the matrix 1-norm. The matrix data is distributed \n"); printf(" among several processors. The Toeplitz matrix is \n"); printf(" symmetric with the first row being the row \n"); printf(" vector [1 2 ... n].\n"); if ( !spmd && pvm_parent() == PvmNoParent ) { while ( nproc <= 0 || nproc > 32 || dimension <= 0) { printf( " Input dimension ( >0 ) of matrix: " ); scanf( "%d", &dimension ); printf( " Input number of tasks (1-32): " ); scanf( "%d", &nproc ); } } else { nproc = DEFAULT_NPROC; dimension = DEFAULT_DIMENSION; } if (!spmd && nproc > 1) { ninst = pvm_spawn( "gexample", (char **) 0, 0, "", nproc-1, tids); nproc = min (nproc, ninst + 1); } if (spmd) nproc = nsibs; pvm_initsend( PvmDataDefault ); pvm_pkint( &nproc, 1, 1 ); pvm_pkint( &dimension, 1, 1 ); if (spmd) pvm_mcast(stids, nsibs, INITTAG); else pvm_mcast( tids, nproc - 1, INITTAG ); printf("\n --> Using %d processors <-- \n\n", nproc); } else /* other nodes receive the number of processors from 0 */ { pvm_recv( -1, INITTAG ); pvm_upkint( &nproc, 1, 1 ); pvm_upkint( &dimension, 1, 1); } /* Make the group static. freezegroup will wait until nproc tids have joined the group. */ info = pvm_freezegroup(MATRIXGROUP,nproc); /* Map matrix rows to processors -- */ blksize = dimension/nproc ; nextra = dimension % nproc; if( myinst < nextra ) { mysrow = (blksize + 1) * myinst; blksize++; } else mysrow = (blksize + 1)*(nextra) + blksize*(myinst - nextra); subblock = (int *) calloc(blksize*dimension,sizeof(int)); colsum = (int *) calloc(dimension,sizeof(int)); colprod = (double *) calloc(dimension,sizeof(double)); if (mysrow >= dimension) /* too many processors ! */ blksize = 0; /* Assign data to this subblock. The entries below make the entire matrix a symmetric Toeplitz matrix (i.e. diagonals are of constant value) */ for (i = 0; i < blksize; i++) for (j = 0; j < dimension; j++) *(subblock + i*dimension + j) = 1 + abs(mysrow + i - j); /* Locally compute the sum of each column and put into colsum */ for (j = 0; j < dimension; j++) { colsum[j] = 0; colprod[j] = 1.0; } for (i = 0; i < blksize; i ++) for(j = 0; j < dimension; j++) { itemp = *(subblock + j + i*dimension); colsum[j] += abs( itemp ); colprod[j] *= abs( itemp ); } /* synchronize the computation and then reduce using pvm_sum. This gives a row vector that has the all the columns sums */ if ( pvm_reduce(PvmSum,colsum,dimension,PVM_INT,SUMTAG, MATRIXGROUP,0) < 0 ) pvm_perror( "pvm_reduce had an error \n") ; pvm_reduce(calcprod,colprod,dimension,PVM_DOUBLE,PRODTAG, MATRIXGROUP,0); if( myinst == 0) { maxmax = 0; for (j = 0; j < dimension; j++) maxmax = max(colsum[j],maxmax); printf(" The 1-Norm is %d \n" , maxmax ); printf(" ( Should be the sum of the integers from 1 to %d )\n", dimension ); printf(" The product of column 1 is %g \n" , colprod[0] ); printf(" ( Should be %d factorial)\n", dimension); } info = pvm_barrier(MATRIXGROUP,-1); /* make sure processes are finished*/ if (info < 0) printf("Barrier failed with result code %d\n", info); pvm_lvgroup(MATRIXGROUP); free(subblock); free(colsum); free(colprod); pvm_exit(); } /*** A User-defined Reduction Function ***/ void calcprod(datatype,x,y,num,info) int *datatype; double *x,*y; int *num, *info; { int i; for (i = 0 ; i < *num; i++) x[i] *= y[i]; } ./pvm3/examples/gmbi.c0100644007401100000360000000754707024271357014024 0ustar kohlgopher static char rcsid[] = "$Id: gmbi.c,v 1.6 1999/12/10 21:38:55 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * Filename: gmbi.c get mailbox info * * This program will simply grab and dump the "info" fields * from the mailbox to display. * * A search expression is used to specify which of the mailboxes * to grab and display. Note that from the command line prompt * the expression should be enclosed within 'single' quotes so * that your shell does not try to process it... * * Example: gmbi 'ra*ts' * Will match any ( rats ) entry that contains at least one a: * ie ) rats - raats - ra123ts - etc... * * Both the unqualified gmbi as well as gmbi '*' * will return all mailbox entries. * * * usage: gmbi * * files used: gmbi.c taskf.c */ #include #ifndef WIN32 #include /* for gethostname */ #else #include "pvmwin.h" #endif #include #include "pvm3.h" char *get_flagstring(); main( argc, argv ) int argc; char *argv[]; { char *me = "gmbi"; int info; /* status of function call */ char pattern[100]; /* regular expression to search on */ int nclasses; /* number of classes returned */ /* pointer to pvmmboxinfo structure */ static struct pvmmboxinfo *classes = (struct pvmmboxinfo *) NULL; int i, j; /* temp integer */ /* display_incomming_parameters( me, argc, argv ); */ /* * validate input parameters */ if ( argc == 2 ) { /* * got valid data -- use it... */ strcpy( pattern, argv[1] ); /* copy expression to local */ } else { /* * didn't get the full command line input - see if can recover? */ if ( argc == 1 ) { /* * default to retrieve all mailbox entries */ strcpy( pattern, "*" ); } else { /* * command line input is wacked - make user try again... */ printf( "\n\nusage: gmbi \n" ); exit( -1 ); } } /* end_if */ /* * get the mailbox information for the user specified expression * pattern and display results */ if ( (info = pvm_getmboxinfo( pattern, &nclasses, &classes )) < 0 ) { printf( "\n\nsomething broke in pvm_getmboxinfo...\n\n" ); exit( -1 ); } printf( "\n%s: %d mbox entries returned.", me, nclasses ); printf( "\n-------------------------------" ); for ( i=0 ; i < nclasses ; i++ ) { printf( "\n%s: class name: <%s>", me, classes[i].mi_name ); for ( j=0 ; j < classes[i].mi_nentries ; j++ ) { printf( "\n\t: indices <%d>\towner_tid \tflags <%d> = <%s>", classes[i].mi_indices[j], classes[i].mi_owners[j], classes[i].mi_flags[j], get_flagstring( classes[i].mi_flags[j] ) ); } /* end_for j */ } /* end_for i */ printf( "\n\n" ); } /* end_main */ ./pvm3/examples/hello.c0100644007401100000360000000327006360710434014172 0ustar kohlgopher static char rcsid[] = "$Id: hello.c,v 1.2 1997/07/09 13:24:44 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ #include #include "pvm3.h" main() { int cc, tid; char buf[100]; printf("i'm t%x\n", pvm_mytid()); cc = pvm_spawn("hello_other", (char**)0, 0, "", 1, &tid); if (cc == 1) { cc = pvm_recv(-1, -1); pvm_bufinfo(cc, (int*)0, (int*)0, &tid); pvm_upkstr(buf); printf("from t%x: %s\n", tid, buf); } else printf("can't start hello_other\n"); pvm_exit(); exit(0); } ./pvm3/examples/hello_other.c0100644007401100000360000000305706360710435015377 0ustar kohlgopher static char rcsid[] = "$Id: hello_other.c,v 1.2 1997/07/09 13:24:45 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ #include "pvm3.h" main() { int ptid; char buf[100]; ptid = pvm_parent(); strcpy(buf, "hello, world from "); gethostname(buf + strlen(buf), 64); pvm_initsend(PvmDataDefault); pvm_pkstr(buf); pvm_send(ptid, 1); pvm_exit(); exit(0); } ./pvm3/examples/inherit1.c0100644007401100000360000000615506360710437014622 0ustar kohlgopher static char rcsid[] = "$Id: inherit1.c,v 1.3 1997/07/09 13:24:47 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * Filename: inherit1.c * * support program for inherita.c - read docs in that file */ #ifndef WIN32 #include /* for gethostname */ #else #include "pvmwin.h" #endif #include "pvm3.h" main() { char *me = "inherit1"; int cc, tid, ptid; char buf[100], buf2[100]; char machine[25]; int mycontext; ptid = pvm_parent(); mycontext = pvm_getcontext(); gethostname( machine, 25 ); sprintf( buf, "%s t%x on machine <%s> with context %d.", me, pvm_mytid(), machine, mycontext ); /* Send message to parent */ pvm_initsend( PvmDataDefault ); pvm_pkstr( buf ); pvm_send( ptid, 1 ); /* * Spawn a child process to confirm that it will inherit the * parent context. */ cc = pvm_spawn( "inherit2", (char **) 0, PvmTaskDefault, "", 1, &tid ); if ( cc != 1 ){ printf( "%s: can't start inherit2\n", me ); pvm_exit(); exit( 0 ); } sprintf( buf, "%s: I just spawned inherit2 as tid t%x with context %d.\n", me, tid, pvm_getcontext() ); /* Send message to parent */ pvm_initsend( PvmDataDefault ); pvm_pkstr( buf ); pvm_send( ptid, 1 ); /* * wait to receive message from child */ cc = pvm_recv( -1, -1 ); pvm_bufinfo( cc, (int *) 0, (int *) 0, &tid ); pvm_upkstr( buf2 ); sprintf( buf, "%s: t%x %s\n", me, tid, buf2 ); /* Send message to parent */ pvm_initsend( PvmDataDefault ); pvm_pkstr( buf ); pvm_send( ptid, 1 ); sprintf( buf, "%s t%x on machine <%s> with context %d.", me, pvm_mytid(), machine, mycontext ); /* Send message to parent */ pvm_initsend( PvmDataDefault ); pvm_pkstr( buf ); pvm_send( ptid, 1 ); sprintf( buf, "END - sent from %s t%x on machine <%s> with context %d.", me, pvm_mytid(), machine, mycontext ); /* Send message to parent */ pvm_initsend( PvmDataDefault ); pvm_pkstr( buf ); pvm_send( ptid, 1 ); pvm_exit(); exit( 0 ); } ./pvm3/examples/inherit2.c0100644007401100000360000000362106360710440014610 0ustar kohlgopher static char rcsid[] = "$Id: inherit2.c,v 1.3 1997/07/09 13:24:48 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * Filename: inherit2.c * * support program for inherita.c and inheritb.c * - read docs in those files. */ #ifndef WIN32 #include /* for gethostname */ #else #include "pvmwin.h" #endif #include "pvm3.h" main() { char *me = "inherit2"; int ptid; char buf[100]; char machine[25]; ptid = pvm_parent(); gethostname( machine, 25 ); sprintf( buf, "\t%s t%x on machine <%s> with context %d.", me, pvm_mytid(), machine, pvm_getcontext() ); /* Send message to parent */ pvm_initsend( PvmDataDefault ); pvm_pkstr( buf ); pvm_send( ptid, 1 ); pvm_exit(); exit( 0 ); } ./pvm3/examples/inherit3.c0100644007401100000360000000713706360710442014621 0ustar kohlgopher static char rcsid[] = "$Id: inherit3.c,v 1.3 1997/07/09 13:24:50 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * Filename: inherit3.c * * support program for inherita.c - read docs in that file */ #ifndef WIN32 #include /* for gethostname */ #else #include "pvmwin.h" #endif #include "pvm3.h" main() { char *me = "inherit3"; int cc, tid, ptid; char buf[100], buf2[100]; char machine[25]; int mycontext, context_1; ptid = pvm_parent(); gethostname( machine, 25 ); sprintf( buf, "%s t%x on machine <%s> with context %d.", me, pvm_mytid(), machine, pvm_getcontext() ); /* Send message to parent */ pvm_initsend( PvmDataDefault ); pvm_pkstr( buf ); pvm_send( ptid, 1 ); context_1 = pvm_newcontext(); /* create new context */ mycontext = pvm_setcontext( context_1 ); /* activate new context */ sprintf( buf, "%s t%x on machine <%s> with context %d.", me, pvm_mytid(), machine, pvm_getcontext() ); pvm_setcontext( mycontext ); /* Send message to parent */ pvm_initsend( PvmDataDefault ); pvm_pkstr( buf ); pvm_send( ptid, 1 ); pvm_setcontext( context_1 ); /* * Spawn a child process to confirm that it will inherit the * parent context. */ cc = pvm_spawn( "inherit2", (char **) 0, PvmTaskDefault, "", 1, &tid ); if ( cc != 1 ) { printf( "%s: can't start inherit2\n", me ); pvm_exit(); exit( 0 ); } sprintf( buf, "%s: I just spawned inherit2 as tid t%x with context %d.\n", me, tid, pvm_getcontext() ); pvm_setcontext( mycontext ); /* Send message to parent */ pvm_initsend( PvmDataDefault ); pvm_pkstr( buf ); pvm_send( ptid, 1 ); pvm_setcontext( context_1 ); /* * wait to receive message from child */ cc = pvm_recv( -1, -1 ); pvm_bufinfo( cc, (int *) 0, (int *) 0, &tid ); pvm_upkstr( buf2 ); sprintf( buf, "%s: t%x %s\n", me, tid, buf2 ); pvm_setcontext( mycontext ); /* Send message to parent */ pvm_initsend( PvmDataDefault ); pvm_pkstr( buf ); pvm_send( ptid, 1 ); sprintf( buf, "%s t%x on machine <%s> with context %d.", me, pvm_mytid(), machine, pvm_getcontext() ); /* Send message to parent */ pvm_initsend( PvmDataDefault ); pvm_pkstr( buf ); pvm_send( ptid, 1 ); sprintf( buf, "END - sent from %s t%x on machine <%s> with context %d.", me, pvm_mytid(), machine, pvm_getcontext() ); /* Send message to parent */ pvm_initsend( PvmDataDefault ); pvm_pkstr( buf ); pvm_send( ptid, 1 ); pvm_exit(); exit( 0 ); } ./pvm3/examples/inherita.c0100644007401100000360000000767706360710443014711 0ustar kohlgopher static char rcsid[] = "$Id: inherita.c,v 1.4 1997/07/09 13:24:51 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * Filename: inherita.c * * This example code performs two tests depending on how it is * executed. * * Form (test 1) confirms that a new context is inherited by all * following children. Here, inherita spawns inherit1 which in * turn spawns inherit2 - all of which inherit the context of the * initial inherita program. * * Form (test 2) confirms that a child task's new context will be * inherited by its subsequent child tasks. Here, inherita spawns * inherit3 which gets a new context and then spawns inherit2. * inherit2 now inherits that new context from inherit3 and not * the original from inherita. * * files used: test 1. inherita inherit1 inherit2 * test 2. inherita inherit3 inherit2 * * usage: test 1. inherita inherit1 * test 2. inherita inherit3 */ #include #ifndef WIN32 #include /* for gethostname */ #else #include "pvmwin.h" #endif #include "pvm3.h" main( argc, argv ) int argc; char *argv[]; { char *me = "inherita"; int cc, tid, mytid; char buf[100]; char machine[25]; int context_1, context_2; int j; /* display_incomming_parameters( me, argc, argv ); */ if ( argc < 2 ) { printf( "\nusage: inherita [inherit1 | inherit3]\n"); pvm_exit(); exit( 0 ); } printf( "\nWill attempt to spawn <%s> from %s.\n\n", argv[1], me ); if ( (mytid = pvm_mytid()) == PvmSysErr ) { /* enroll in pvm */ printf( "\nPVM not up!\n" ); exit( -1 ); } gethostname( machine, 25 ); printf( "%s: t%x on machine <%s> with original context %d.\n", me, pvm_mytid(), machine, pvm_getcontext() ); context_2 = pvm_newcontext(); /* create new context */ context_1 = pvm_setcontext( context_2 ); /* activate new context */ printf( "%s: t%x on machine <%s> with changed context %d.\n\n", me, pvm_mytid(), machine, pvm_getcontext() ); /* * Spawn a child process to confirm that it will inherit the * parent context. */ cc = pvm_spawn( argv[1], (char **) 0, PvmTaskDefault, "", 1, &tid ); if ( cc != 1 ) { printf( "%s: can't start %s\n", me, argv[1] ); pvm_exit(); exit( 0 ); } for ( ; ; ) { /* * wait to receive message from child */ cc = pvm_recv( -1, -1 ); pvm_bufinfo( cc, (int *) 0, (int *) 0, &tid ); pvm_upkstr( buf ); printf( "%s: t%x %s\n", me, tid, buf ); if ( strncmp( buf, "END", 3 ) == 0 ) break; } printf( "\n%s: t%x on machine <%s> with changed context %d.\n", me, pvm_mytid(), machine, pvm_getcontext() ); /* restore original context */ context_2 = pvm_setcontext( context_1 ); printf( "%s: t%x on machine <%s> with original context %d.\n", me, pvm_mytid(), machine, pvm_getcontext() ); pvm_exit(); exit( 0 ); } ./pvm3/examples/inheritb.c0100644007401100000360000000715206360710444014677 0ustar kohlgopher static char rcsid[] = "$Id: inheritb.c,v 1.3 1997/07/09 13:24:52 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * Filename: inheritb.c * * This example shows how a generic receive any message from any task * may "select" the message to receive based on the context. * * inheritb starts two children (2 x inherit2), each under their own * context so that the parent (inheritb) may receive communication * based on the child's context. * * files used: inheritb.c inherit2.c * * usage: inheritb * */ #include #ifndef WIN32 #include /* for gethostname */ #else #include "pvmwin.h" #endif #include "pvm3.h" main() { char *me = "inheritb"; int context_original, context_1, context_2; int ptid, tid, gptid, cc; char buf[100]; char machine[25]; int i=0; gethostname( machine, 25 ); printf( "%d:%s: t%x on machine <%s> with context %d.\n", i++, me, pvm_mytid(), machine, pvm_getcontext() ); context_original = pvm_getcontext(); /* retrieve initial context */ context_1 = pvm_newcontext(); /* get new context 1 */ pvm_setcontext( context_1 ); /* activate new context 1 */ printf( "%d:%s: t%x on machine <%s> with new #1 context %d ", i++, me, pvm_mytid(), machine, pvm_getcontext() ); printf( "--> spawn 1st inherit2.\n" ); /* start 1st inherit2 worker @ context 1 */ pvm_spawn( "inherit2", (char **) 0, PvmTaskDefault, "", 1, &tid ); context_2 = pvm_newcontext(); /* get new context 2 */ pvm_setcontext(context_2); /* activate new context 2 */ printf( "%d:%s: t%x on machine <%s> with new #2 context %d ", i++, me, pvm_mytid(), machine, pvm_getcontext() ); printf( "--> spawn 2nd inherit2.\n" ); /* start 2nd inherit2 worker @ context 2 */ pvm_spawn( "inherit2", (char **) 0, PvmTaskDefault, "", 1, &tid ); /* receive from inherit2 worker 2 @ context 2 */ cc = pvm_recv( -1, -1 ); pvm_bufinfo( cc, (int *) 0, (int *) 0, &tid ); pvm_upkstr( buf ); printf( "%d:%s: t%x %s <-- received from 2nd inherit2.\n", i++, me, tid, buf); /* reactivate initial context 1*/ pvm_setcontext(context_1); printf( "%d:%s: t%x on machine <%s> with new #1 context %d.\n", i++, me, pvm_mytid(), machine, pvm_getcontext() ); /* receive from inherit2 worker 1 @ context 1 */ cc = pvm_recv( -1, -1 ); pvm_bufinfo( cc, (int *) 0, (int *) 0, &tid ); pvm_upkstr( buf ); printf( "%d:%s: t%x %s <-- received from 1st inherit2.\n", i++, me, tid, buf ); pvm_exit(); exit( 0 ); } ./pvm3/examples/lmbi.c0100644007401100000360000001523206651142311014007 0ustar kohlgopher static char rcsid[] = "$Id: lmbi.c,v 1.6 1999/01/19 17:45:45 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * Filename: lmbi.c * * This program will "populate" the mailbox with a number of entries * so that another program ( gmbi.c ) may then retrieve these entries * using the pvm_getmboxinfo() function. * * Flags will be set the same for all instances started. * * usage: lmbi #instances #ifndef WIN32 #include /* for gethostname */ #else #include "pvmwin.h" #endif #include #include "pvm3.h" main( argc, argv ) int argc; char *argv[]; { char *me = "lmbi"; char machine[25]; char message[250]; int mytid; char service_name[25]; int i; int index; /* returned index for mailbox entry */ char flagc[10]; /* hold characters for flags */ int flags; /* PvmMbox flags set */ char *flagstring; /* pointer to string of flag settings */ int their_tid; /* tid of task sending service request */ char msg_txt[100]; /* message received as service request */ int msg_buf; /* message buffer to receive on */ int entries = 0; /* # of entries to load into mailbox db */ char exit_status; /* incomming exit_status flag value */ int context; /* context of this message */ /* display_incomming_parameters( me, argc, argv ); */ /* * validate input parameters */ if ( argc == 4 ) { /* correct quantity - anyway... */ entries = atoi( argv[1] ); /* number of entries to insert */ strcpy( flagc, argv[2] ); /* copy flags to local */ exit_status = argv[3][0]; /* grab only the 1st character */ if ( exit_status != 'w' && exit_status != 'e' ) { /* unknown exit_status entered - complain and exit */ printf( "\n\nInvalid exit_status value <%c> entered.\n", exit_status ); printf( "\texit_status:\n" ); printf( "\t\twait for end message\t\tw\n" ); printf( "\t\texit when finished loading\te\n" ); exit( -1 ); } } else { /* unknown input sequence - complain and exit */ printf( "\n\nusage: lmbi #instances \n" ); printf( "\tflags:\n" ); printf( "\t\tPvmMboxDefault\t\td\n" ); printf( "\t\tPvmMboxPersistent\tp\n" ); printf( "\t\tPvmMboxMultiInstance\tm\n" ); printf( "\t\tPvmMboxOverWritable\to\n" ); printf( "\texit_status:\n" ); printf( "\t\twait for end message\t\tw\n" ); printf( "\t\texit when finished loading\te\n" ); exit( -1 ); } printf( "%s: sending <%s> to set_flags.\n", me, flagc ); if ( ( flags = set_flags( flagc, &flagstring ) ) < 0 ) { exit( -1 ); /* something failed - abort! */ } printf( "%s: create %d mailbox instances ", me, entries ); printf( "with flags set to <%d> : <%s>.\n", flags, flagstring ); if ( ( mytid = pvm_mytid() ) == PvmSysErr ) { printf( "\nPVM not up!\n" ); exit( -1 ); } gethostname( machine, 25 ); printf( "%s: t%x on machine <%s> with context %d.\n\n", me, mytid, machine, pvm_getcontext() ); /* * create and insert the mailbox entries */ for ( i=0 ; i < entries ; i++ ) { /* * create message to place in mailbox */ context = pvm_getcontext(); sprintf( service_name, "t%x%s%d", mytid, me, i ); sprintf( message, "%s: service_name %s flags %d = %s machine %s tid t%x context %d", me, service_name, flags, flagstring, machine, mytid, context ); pvm_initsend( PvmDataDefault ); pvm_packf( "%+ %d %d %s %s", PvmDataDefault, mytid, context, machine, message ); if ( (index = pvm_putinfo( service_name, pvm_getsbuf(), flags )) == PvmExists ) { printf( "can't register - service already running\n" ); exit( -1 ); } printf( "%s: just inserted entry <%s> at index %d.\n", me, service_name, index ); printf( "\tmessage inserted: %s\n", message ); } /* end_for */ /* * Decide if should hang around and wait for another task to shut * me down or if I should simply exit on my own. * This decision is important in the case of using ( or not ) the * persistent flag as mailbox entries without the persistent flag * marked will be removed when their creating task exits. * Thus must either mark as persistent or hang around if I want * to look at or keep around these mailbox entries. */ if ( exit_status == 'w' ) { for ( ; ; ) { /* * wait for exit request */ printf("%s: t%x on machine <%s> with context %d", me, mytid, machine, pvm_getcontext()); printf(" - waiting for exit request.\n"); msg_buf = pvm_recv( -1, -1 ); pvm_bufinfo( msg_buf, (int *) 0, (int *) 0, &their_tid ); pvm_upkstr( msg_txt ); printf( "%s: t%x %s.\n", me, mytid, msg_txt ); if ( strncmp( msg_txt, "END", 3 ) == 0 ) break; } /* end_for */ } /* end_if */ pvm_exit(); exit( 0 ); } ./pvm3/examples/master1.c0100644007401100000360000000603606360710465014452 0ustar kohlgopher static char rcsid[] = "$Id: master1.c,v 1.4 1997/07/09 13:25:09 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ #include #include "pvm3.h" #define SLAVENAME "slave1" main() { int mytid; /* my task id */ int tids[32]; /* slave task ids */ int n, nproc, numt, i, who, msgtype, nhost, narch; float data[100], result[32]; struct pvmhostinfo *hostp; /* enroll in pvm */ mytid = pvm_mytid(); /* Set number of slaves to start */ pvm_config( &nhost, &narch, &hostp ); nproc = nhost * 3; if( nproc > 32 ) nproc = 32 ; printf("Spawning %d worker tasks ... " , nproc); /* start up slave tasks */ numt=pvm_spawn(SLAVENAME, (char**)0, 0, "", nproc, tids); if( numt < nproc ){ printf("\n Trouble spawning slaves. Aborting. Error codes are:\n"); for( i=numt ; i expected status returned 1. ( mbox ) -> 1 2. * ( mbox query ) -> 0 3. ( mbox sleep=3 & ) -> 1 * ( mbox query 0 ) -> 1 * ( mbox query ) -> 1 4. * ( mbox query ) -> 0 5. ( mbox sleep=3 & ) -> 1 * ( mbox query 0 ) -> 1 * ( mbox query ) -> 1 ( mbox sleep=3 & ) -> 1 * ( mbox query 0 ) -> 1 * ( mbox query ) -> 1 6. * ( mbox query ) -> 0 7. ( mbox sleep=3 & ) -> 1 ( mbox excl ) -> 0 8. * ( mbox query ) -> 0 9. ( mbox sleep=3 & ) -> 1 ( mbox favail ) -> 1 * ( mbox query ) -> 0 10. ( mbox sleep=3 & ) -> 1 ( mbox favail excl ) -> 1 * ( mbox query 0 ) -> 1 * ( mbox query 1 ) -> 0 * ( mbox query ) -> 1 11. * ( mbox query ) -> 0 12. ( mbox sleep=3 & ) -> 1 ( mbox sleep=3 favail excl & ) -> 1 * ( mbox query 0 ) -> 1 * ( mbox query 1 ) -> 1 * ( mbox query ) -> 2 13. * ( mbox query ) -> 0 14. ( mbox sleep=3 lock & ) -> 1 * ( mbox query 0 ) -> 1 * ( mbox query ) -> 1 ( mbox ) -> 0 ( mbox lock ) -> 0 ( mbox excl ) -> 0 ( mbox lock excl ) -> 0 ( mbox delete 0 ) -> 0 ( mbox favail ) -> 1 * ( mbox query 0 ) -> 1 * ( mbox query 1 ) -> 0 * ( mbox query ) -> 1 15. ( mbox query ) -> 0 16. ( mbox sleep=3 lock & ) -> 1 ( mbox sleep=3 favail & ) -> 1 * ( mbox query 0 ) -> 1 * ( mbox query 1 ) -> 1 * ( mbox query ) -> 2 ( mbox favail ) -> 1 * ( mbox query 0 ) -> 1 * ( mbox query 1 ) -> 0 * ( mbox query ) -> 1 17. ( mbox query ) -> 0 18. ( mbox sleep=3 lock & ) -> 1 ( mbox sleep=3 favail & ) -> 1 * ( mbox query 0 ) -> 1 * ( mbox query 1 ) -> 1 * ( mbox query ) -> 2 ( mbox favail excl ) -> 1 * ( mbox query 0 ) -> 1 * ( mbox query 1 ) -> 1 * ( mbox query ) -> 2 19. ( mbox query ) -> 0 20. ( mbox pers ) -> 1 * ( mbox query 0 ) -> 1 * ( mbox query ) -> 1 ( mbox delete 0 ) -> 1 * ( mbox query ) -> 0 21. ( mbox pers lock ) -> 1 * ( mbox query 0 ) -> 1 * ( mbox query ) -> 1 ( mbox delete 0 ) -> 1 * ( mbox query ) -> 0 22. ( mbox pers ) -> 1 * ( mbox delete 0 ) -> 1 23. ( mbox pers ) -> 1 ( mbox pers favail ) -> 1 * ( mbox query 0 ) -> 1 * ( mbox query 1 ) -> 0 * ( mbox query ) -> 1 ( mbox delete 0 ) -> 1 24. ( mbox pers ) -> 1 ( mbox pers excl ) -> 0 ( mbox pers favail excl ) -> 1 ( mbox pers favail excl ) -> 1 * ( mbox query 0 ) -> 1 * ( mbox query 1 ) -> 1 * ( mbox query 2 ) -> 1 * ( mbox query ) -> 3 ( mbox delete ) -> 3 25. ( mbox sleep=10 noreset & ) -> 1 ( ... do pvm reset ... ) ( mbox query 0 ) -> 1 26. ( mbox delete ) -> 0 27. ( mbox noexit ) -> 1 * ( mbox query ) -> 0 **********************************************************************/ #include #include #include "pvm3.h" #define MBOX_CLASS "mbox_test" void dump_flags(); void set_flags(); void usage(); int mytid; main( argc, argv ) int argc; char *argv[]; { char CLASS_NAME[255]; struct pvmmboxinfo *classes; int nclasses; char pattern[255]; char *cmds[100]; int ncmds; char bufout[255]; char bufin[255]; char *arg; int NINDICES = 10; int do_noreset; int do_favail; int do_unpack; int do_minst; int do_owrit; int do_rddel; int do_sleep; int do_exit; int do_pers; int do_wait; int index; int flags; int done; int i, j; int ret; int tmp; int cc; /* Parse Command Line */ strcpy( CLASS_NAME, MBOX_CLASS ); do_noreset = 0; do_favail = 0; do_unpack = 1; do_minst = 0; do_owrit = 0; do_rddel = 0; do_sleep = 0; do_exit = 1; do_pers = 0; do_wait = 0; ncmds = 0; for ( i=1 ; i < argc ; i++ ) { arg = argv[i]; if ( arg[0] == '-' ) arg++; if ( !strcmp( arg, "pers" ) ) do_pers++; else if ( !strcmp( arg, "favail" ) ) do_favail++; else if ( !strcmp( arg, "sleep" ) ) do_sleep = 10; else if ( !strncmp( arg, "sleep=", 6 ) ) sscanf( arg + 6, "%d", &do_sleep ); else if ( !strcmp( arg, "owrit" ) ) do_owrit++; else if ( !strcmp( arg, "minst" ) ) do_minst++; else if ( !strcmp( arg, "rddel" ) ) do_rddel++; else if ( !strcmp( arg, "wait" ) ) do_wait++; else if ( !strcmp( arg, "noexit" ) ) do_exit = 0; else if ( !strcmp( arg, "noreset" ) ) do_noreset = 1; else if ( !strncmp( arg, "name=", 5 ) ) { strcpy( CLASS_NAME, arg + 5 ); do_unpack = 0; } else if ( !strncmp( arg, "nindices=", 9 ) ) NINDICES = atoi( arg + 9 ); else if ( !strcmp( arg, "help" ) ) usage(); else cmds[ ncmds++ ] = arg; } /* Enter PVM */ mytid = pvm_mytid(); if ( mytid < 0 ) { printf( "*** Could not connect to PVM... Exiting... ***\n" ); exit( -1 ); } else printf( "mbox started as tid=0x%x\n", mytid ); ret = 0; if ( do_noreset ) pvm_setopt( PvmNoReset, 1 ); /* Do Basic Stuff & Check */ if ( !ncmds ) { strcpy( bufin, "This Message Left Here By Mbox" ); set_flags( &flags, do_pers, do_favail, do_owrit, do_minst, do_rddel, do_wait ); index = stuff_msg( CLASS_NAME, flags, bufin, mytid ); if ( index < 0 ) exit( -1 ); cc = check_msg( CLASS_NAME, index, 0, bufout, &tmp, do_unpack ); if ( cc < 0 ) exit( -1 ); if ( strcmp( bufout, bufin ) ) { printf( "String Mismatch Error: \"%s\" != \"%s\"\n", bufout, bufin ); } else if ( tmp != mytid ) { printf( "Number Mismatch Error: %d != %d\n", tmp, mytid ); } else { printf( "Retrieved Message is a Match.\n" ); ret++; } if ( do_sleep ) pvmsleep( do_sleep ); } /* Execute Commands */ else { if ( !strcmp( cmds[0], "query" ) ) { set_flags( &flags, do_pers, do_favail, do_owrit, do_minst, do_rddel, do_wait ); if ( ncmds == 1 ) { for ( i=0 ; i < NINDICES ; i++ ) { cc = check_msg( CLASS_NAME, i, flags, bufout, &tmp, do_unpack ); if ( cc < 0 ) printf( "No Message at Index=%d\n", i ); else { printf( "Message at Index=%d: \"%s\" 0x%x\n", i, bufout, tmp ); ret++; } } } else { index = atoi( cmds[1] ); cc = check_msg( CLASS_NAME, index, flags, bufout, &tmp, do_unpack ); if ( cc < 0 ) printf( "No Message at Index=%d\n", index ); else { printf( "Message at Index=%d: \"%s\" 0x%x\n", index, bufout, tmp ); ret++; } } } else if ( !strcmp( cmds[0], "delete" ) ) { set_flags( &flags, do_pers, do_favail, do_owrit, do_minst, do_rddel, do_wait ); if ( ncmds == 1 ) { for ( i=0 ; i < NINDICES ; i++ ) { cc = pvm_delinfo( CLASS_NAME, i, flags ); if ( cc < 0 ) { pvm_perror( "pvm_delinfo()" ); printf( "No Message to Delete at Index=%d\n", i ); } else { printf( "Message at Index=%d Deleted.\n", i ); ret++; } } } else { index = atoi( cmds[1] ); cc = pvm_delinfo( CLASS_NAME, index, flags ); if ( cc < 0 ) { pvm_perror( "pvm_delinfo()" ); printf( "No Message to Delete at Index=%d\n", index ); } else { printf( "Message at Index=%d Deleted.\n", index ); ret++; } } } else if ( !strcmp( cmds[0], "querynoreset" ) ) { done = 0; i = 0; while ( !done ) { cc = check_msg( PVMNORESETCLASS, i, PvmMboxFirstAvail, bufout, &tmp, 0 ); if ( cc < 0 ) done++; else { pvm_upkint( &tmp, 1, 1 ); printf( "NoReset Message at Index=%d: 0x%x\n", i, tmp ); ret++; i++; } } } else if ( !strcmp( cmds[0], "spawn" ) ) { pvm_spawn( "mbox", argv + 2, PvmTaskHost | PvmHostCompl, ".", 1, &cc ); if ( cc < 0 ) pvm_perror( "Spawning on Other Host" ); else { pvm_notify( PvmTaskExit, 100, 1, &cc ); pvm_recv( -1, 100 ); } } else if ( !strcmp( cmds[0], "info" ) ) { if ( ncmds == 1 ) strcpy( pattern, "*" ); else strcpy( pattern, cmds[1] ); if ( (cc = pvm_getmboxinfo( pattern, &nclasses, &classes )) < 0 ) pvm_perror( "Querying Mbox Info" ); else { for ( i=0 ; i < nclasses ; i++ ) { printf( "Class \"%s\" has %d entries:\n", classes[i].mi_name, classes[i].mi_nentries ); for ( j=0 ; j < classes[i].mi_nentries ; j++ ) { printf( "\tindex=%d owner=0x%x/%d flags=0x%x\n", classes[i].mi_indices[j], classes[i].mi_owners[j], classes[i].mi_owners[j], classes[i].mi_flags[j] ); } printf( "\n" ); } } } else if ( !strcmp( cmds[0], "default" ) ) { set_flags( &flags, 1 /*do_pers*/, 1 /*do_favail*/, do_owrit, 1 /*do_minst*/, do_rddel, do_wait ); for ( i=0 ; i < 6 ; i++ ) { sprintf( bufin, "This Message Left Here By Mbox (%d)", i ); index = stuff_msg( CLASS_NAME, flags, bufin, mytid ); if ( index < 0 ) exit( -1 ); cc = check_msg( CLASS_NAME, index, 0, bufout, &tmp, do_unpack ); if ( cc < 0 ) exit( -1 ); if ( strcmp( bufout, bufin ) ) { printf( "String Mismatch Error: \"%s\" != \"%s\"\n", bufout, bufin ); } else if ( tmp != mytid ) { printf( "Number Mismatch Error: %d != %d\n", tmp, mytid ); } else { printf( "Retrieved Message is a Match.\n" ); ret++; } } if ( do_sleep ) pvmsleep( do_sleep ); cc = pvm_delinfo( CLASS_NAME, 3, flags ); if ( cc < 0 ) { pvm_perror( "pvm_delinfo()" ); printf( "No Message to Delete at Index=%d\n", index ); } else { printf( "Message at Index=%d Deleted.\n", index ); ret++; } sprintf( bufin, "This Message Left Here By Mbox (X)" ); index = stuff_msg( CLASS_NAME, flags, bufin, mytid ); if ( index < 0 ) exit( -1 ); cc = check_msg( CLASS_NAME, index, 0, bufout, &tmp, do_unpack ); if ( cc < 0 ) exit( -1 ); if ( strcmp( bufout, bufin ) ) { printf( "String Mismatch Error: \"%s\" != \"%s\"\n", bufout, bufin ); } else if ( tmp != mytid ) { printf( "Number Mismatch Error: %d != %d\n", tmp, mytid ); } else { printf( "Retrieved Message is a Match.\n" ); ret++; } if ( do_sleep ) pvmsleep( do_sleep ); for ( i=0 ; i < 3 ; i++ ) { cc = pvm_delinfo( CLASS_NAME, i, flags ); if ( cc < 0 ) { pvm_perror( "pvm_delinfo()" ); printf( "No Message to Delete at Index=%d\n", i ); } else { printf( "Message at Index=%d Deleted.\n", i ); ret++; } } set_flags( &flags, 0 /*do_pers*/, 1 /*do_favail*/, 0 /*do_owrit*/, 1 /*do_minst*/, 1 /*do_rddel*/, do_wait ); cc = check_msg( CLASS_NAME, 0, flags, bufout, &tmp, do_unpack ); if ( cc < 0 ) exit( -1 ); printf( "Retrieved Message is \"%s\" from tid=%d.\n", bufout, tmp ); ret++; set_flags( &flags, 0 /*do_pers*/, 1 /*do_favail*/, 0 /*do_owrit*/, 1 /*do_minst*/, 0 /*do_rddel*/, do_wait ); cc = check_msg( CLASS_NAME, 0, flags, bufout, &tmp, do_unpack ); if ( cc < 0 ) exit( -1 ); printf( "Retrieved Message is \"%s\" from tid=%d.\n", bufout, tmp ); ret++; } else if ( !strcmp( cmds[0], "default33" ) ) { for ( i=0 ; i < 7 ; i++ ) { tmp = ( i == 6 ) ? -1 : i; index = pvm_insert( CLASS_NAME, tmp, i * 2 ); if ( index < 0 ) { pvm_perror( "pvm_insert()" ); exit( -1 ); } else { printf( "Value %d Successfully Inserted at %d (req=%d)\n", i * 2, index, tmp ); ret++; } cc = pvm_insert( CLASS_NAME, index, i * 3 ); if ( cc < 0 ) { printf( "Re-insert at Index=%d Failed as Expected.\n", index ); ret++; } else { printf( "Uh-Oh, Re-Insert at Index=%d Succeeded!\n", index ); } cc = pvm_lookup( CLASS_NAME, index, &tmp ); if ( cc < 0 ) { pvm_perror( "pvm_lookup()" ); exit( -1 ); } if ( tmp != i * 2 ) printf( "Mismatch Error: %d != %d\n", tmp, i * 2 ); else { printf( "Retrieved Value is a Match.\n" ); ret++; } } if ( do_sleep ) pvmsleep( do_sleep ); index = 3; cc = pvm_delete( CLASS_NAME, index ); if ( cc < 0 ) { pvm_perror( "pvm_delete()" ); printf( "No Message to Delete at Index=%d\n", index ); } else { printf( "Message at Index=%d Deleted.\n", index ); ret++; } index = pvm_insert( CLASS_NAME, -1, 123 ); if ( index < 0 ) { pvm_perror( "pvm_insert()" ); exit( -1 ); } else { printf( "Value %d Successfully Inserted at %d (req=%d)\n", 123, index, -1 ); ret++; } cc = pvm_insert( CLASS_NAME, index, 246 ); if ( cc < 0 ) { printf( "Re-insert at Index=%d Failed as Expected.\n", index ); ret++; } else { printf( "Uh-Oh, Re-Insert at Index=%d Succeeded!\n", index ); } cc = pvm_lookup( CLASS_NAME, index, &tmp ); if ( cc < 0 ) { pvm_perror( "pvm_lookup()" ); exit( -1 ); } if ( tmp != 123 ) printf( "Mismatch Error: %d != %d\n", tmp, 123 ); else { printf( "Retrieved Value is a Match.\n" ); ret++; } if ( do_sleep ) pvmsleep( do_sleep ); for ( i=0 ; i < 3 ; i++ ) { cc = pvm_delete( CLASS_NAME, i ); if ( cc < 0 ) { pvm_perror( "pvm_delete()" ); printf( "No Message to Delete at Index=%d\n", i ); } else { printf( "Message at Index=%d Deleted.\n", i ); ret++; } } cc = pvm_lookup( CLASS_NAME, -1, &tmp ); if ( cc < 0 ) { pvm_perror( "pvm_lookup()" ); exit( -1 ); } printf( "First Available Lookup at Index=%d -> %d\n", cc, tmp ); ret++; } else if ( !strcmp( cmds[0], "direct" ) ) { set_flags( &flags, 0 /*do_pers*/, 1 /*do_favail*/, do_owrit, 1 /*do_minst*/, do_rddel, do_wait ); for ( i=0 ; i < 3 ; i++ ) { sprintf( bufin, "This Message Left Here By Mbox (%d)", i ); index = stuff_msg( CLASS_NAME, flags, bufin, mytid ); if ( index < 0 ) exit( -1 ); cc = check_msg( CLASS_NAME, index, 0, bufout, &tmp, do_unpack ); if ( cc < 0 ) exit( -1 ); if ( strcmp( bufout, bufin ) ) { printf( "String Mismatch Error: \"%s\" != \"%s\"\n", bufout, bufin ); } else if ( tmp != mytid ) { printf( "Number Mismatch Error: %d != %d\n", tmp, mytid ); } else { printf( "Retrieved Message is a Match.\n" ); ret++; } } if ( do_sleep ) pvmsleep( do_sleep ); set_flags( &flags, 0 /*do_pers*/, 0 /*do_favail*/, do_owrit, 0 /*do_minst*/, do_rddel, do_wait ); sprintf( bufin, "This Message Left Here By Mbox (X)" ); index = stuff_msg( CLASS_NAME, flags | PvmMboxDirectIndex( 1 ), bufin, mytid ); if ( index < 0 ) exit( -1 ); for ( i=0 ; i < 3 ; i++ ) { cc = check_msg( CLASS_NAME, i, 0, bufout, &tmp, do_unpack ); if ( cc < 0 ) exit( -1 ); } } } if ( do_exit ) pvm_exit(); exit( ret ); } void set_flags( flags, do_pers, do_favail, do_owrit, do_minst, do_rddel, do_wait ) int *flags; int do_pers; int do_favail; int do_owrit; int do_minst; int do_rddel; int do_wait; { *flags = PvmMboxDefault; if ( do_pers ) *flags |= PvmMboxPersistent; if ( do_favail ) *flags |= PvmMboxFirstAvail; if ( do_owrit ) *flags |= PvmMboxOverWritable; if ( do_minst ) *flags |= PvmMboxMultiInstance; if ( do_rddel ) *flags |= PvmMboxReadAndDelete; if ( do_wait ) *flags |= PvmMboxWaitForInfo; } void dump_flags( flags ) int flags; { if ( flags & PvmMboxPersistent ) printf( " PERSISTENT" ); if ( flags & PvmMboxFirstAvail ) printf( " FIRST_AVAIL" ); if ( flags & PvmMboxOverWritable ) printf( " OVER_WRITABLE" ); if ( flags & PvmMboxMultiInstance ) printf( " MULTI_INSTANCE" ); if ( flags & PvmMboxReadAndDelete ) printf( " READ_AND_DELETE" ); } int stuff_msg( class, flags, str, num ) char *class; int flags; char *str; int num; { int cc; /* Create Message */ pvm_initsend( PvmDataDefault ); pvm_pkstr( str ); pvm_pkint( &num, 1, 1 ); /* Insert Into Class */ cc = pvm_putinfo( class, pvm_getsbuf(), flags ); if ( cc < 0 ) pvm_perror( "Inserting Message" ); else { printf( "Inserted Message Into \"%s\" at index=%d:", class, cc ); dump_flags( flags ); printf( "\n" ); printf( "\t\"%s\"\n", str ); printf( "\t0x%x\n", num ); } pvm_freebuf( pvm_getsbuf() ); return( cc ); } int check_msg( class, index, flags, str, num, do_unpack ) char *class; int index; int flags; char *str; int *num; int do_unpack; { int cc; /* Retrieve Message */ cc = pvm_recvinfo( class, index, flags ); if ( cc < 0 ) pvm_perror( "Retrieving Message" ); else { if ( do_unpack ) { pvm_upkstr( str ); pvm_upkint( num, 1, 1 ); } printf( "Retrieved Message From \"%s\" at index=%d:", class, index ); dump_flags( flags ); printf( "\n" ); if ( do_unpack ) { printf( "\t\"%s\"\n", str ); printf( "\t0x%x\n", *num ); } else printf( "\t(not unpacked)\n" ); } return( cc ); } void usage() { printf( "\n" ); printf( "usage: mbox [pers] [favail] [owrit] [minst] [rddel]\n" ); printf( "\t[sleep[=]] [name=]\n" ); printf( "\t[query []] [wait] [noreset] [noexit]\n" ); printf( "\t[info []] [delete []] [direct]\n" ); printf( "\t[default] [default33] [nindices=] [help]\n" ); printf( "\n" ); exit( 0 ); } ./pvm3/examples/mhf_server.c0100644007401100000360000004133406651142313015230 0ustar kohlgopher static char rcsid[] = "$Id: mhf_server.c,v 1.4 1999/01/19 17:45:47 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /*************************************************************** * Filename: mhf_server.c * * This is a "server" program for testing message handler functions. * Use the mhf_tickle program to speak to this server. * * Operation: * 1. startup pvm console * 2. startup the mhf_server * 3. startup as many mhf_tickle instances as you wish * - follow menu options and in-code comments on * how to run and what it tests / shows... * ***************************************************************/ #include "stdio.h" #include "pvm3.h" #define NOISE1 1 /* sets level of program noise - minimum noise */ /* #define NOISE2 2 each level "up" adds noise */ #define PMH 0 /* display present message handlers */ #define LMH 1 /* load message handler */ #define DMH 2 /* delete message handler */ #define ERJ 3 /* tell mhf_server() to pvm_exit() and rejoin */ #define HIT 4 /* message to hit a specified handler... */ #define GSMB 7 /* NOT USED IN mhf_server() - use to grab the */ /* mhf_server contact info from mailbox again... */ #define CEAT 8 /* client (this program ) exit pvm and terminate */ /* self - server not contacted... */ #define SEAT 9 /* server exits pvm and terminate self */ #define SC1 1 /* string_catcher1 */ #define SC2 2 /* string_catcher2 */ #define SC3 3 /* string_catcher3 */ #define SC4 4 /* string_catcher4 */ #define SC5 5 /* string_catcher5 */ #define IC1 6 /* int_catcher6 */ #define IC2 7 /* int_catcher7 */ #define IC3 8 /* int_catcher8 */ #define IC4 9 /* int_catcher9 */ #define IC5 0 /* int_catcher10 */ #define STR_LEN 100 #define YES 1 #define NO 0 /* * globals to bring back message handler information */ int mhf_catch; /* should be same as number of "catcher" hit */ int mhf_magic_number; char mhf_msg[STR_LEN]; /**********************************************************************/ /**********************************************************************/ /********************************************************************** * register this server via "well known" mailbox so others may contact us * mailbox name is set to... server = "mhf_server" * * Returns mailbox index where placed */ int register_server( mytid, ctx, machine, server ) int mytid; int ctx; char *machine; char *server; { char *me = "register_server"; int index; pvm_initsend( PvmDataDefault ); pvm_pkint( &mytid, 1, 1 ); pvm_pkint( &ctx, 1, 1 ); pvm_pkstr( machine ); if ( ( index = pvm_putinfo( server, pvm_getsbuf( ), PvmMboxDefault ) ) < 0 ) { /* * problem inserting mailbox entry - tell user why, exit pvm, and terminate task... */ switch ( index ) { case PvmExists: printf( "\n%s: Named service already running\n", me ); break; case PvmBadParam: printf( "\n%s: Invalid argument to pvm_recvinfo( ).\n", me ); break; case PvmNoSuchBuf: printf( "\n%s: Message buffer id does not exist.\n", me ); break; case PvmDenied: printf( "\n%s: Key locked by another task, can't delete.\n", me ); break; case PvmNoMem: printf( "\n%s: Libpvm is unable to allocate memory to pack data.\n", me ); break; case PvmNotFound: printf( "\n%s: Requested key does not exist.\n", me ); break; default: lpvmerr( "\n%s: task0.c: error %d", me, index ); break; } /* end_switch */ return( index ); /* returns error code */ } printf( "%s: mailbox... just inserted server <%s> at mailbox %d with context %d.\n", me, server, index, ctx ); return( index ); } /* register_server */ /********************************************************************** * Function: string_catcher1 - unpack 1 string * string_catcher2 - unpack 2 strings * string_catcher3 - unpack 3 strings * string_catcher4 - unpack 4 strings * string_catcher5 - unpack 5 strings * * int_catcher6 - unpack 1 integer * int_catcher7 - unpack 2 integers * int_catcher8 - unpack 3 integers * int_catcher9 - unpack 4 integers * int_catcher10 - unpack 5 integers * * These are all simple message handlers to use in testing loading, * deleting, and using message handlers. * * Each one simply echos out the information that is being sent. * Thus showing that a given handler may "handle" messages of a given type. **********************************************************************/ int string_catcher1( mid ) int mid; { char *me = "string_catcher1"; int rbf; rbf = pvm_setrbuf( mid ); pvm_upkint( &mhf_catch, 1, 1 ); pvm_upkstr( mhf_msg ); printf( "\n%s: string_catcher%d received message -->> <%s>\n\n", me, mhf_catch, mhf_msg ); pvm_freebuf( pvm_setrbuf( rbf ) ); return 0; } /* string_catcher1 */ int string_catcher2( mid ) int mid; { char *me = "string_catcher2"; int rbf; rbf = pvm_setrbuf( mid ); pvm_upkint( &mhf_catch, 1, 1 ); pvm_upkstr( mhf_msg ); printf( "\n%s: string_catcher%d received message -->> <%s>\n\n", me, mhf_catch, mhf_msg ); pvm_freebuf( pvm_setrbuf( rbf ) ); return 0; } /* string_catcher2 */ int string_catcher3( mid ) int mid; { char *me = "string_catcher3"; int rbf; rbf = pvm_setrbuf( mid ); pvm_upkint( &mhf_catch, 1, 1 ); pvm_upkstr( mhf_msg ); printf( "\n%s: string_catcher%d received message -->> <%s>\n\n", me, mhf_catch, mhf_msg ); pvm_freebuf( pvm_setrbuf( rbf ) ); return 0; } /* string_catcher3 */ int string_catcher4( mid ) int mid; { char *me = "string_catcher4"; int rbf; rbf = pvm_setrbuf( mid ); pvm_upkint( &mhf_catch, 1, 1 ); pvm_upkstr( mhf_msg ); printf( "\n%s: string_catcher%d received message -->> <%s>\n\n", me, mhf_catch, mhf_msg ); pvm_freebuf( pvm_setrbuf( rbf ) ); return 0; } /* string_catcher4 */ int string_catcher5( mid ) int mid; { char *me = "string_catcher5"; int rbf; rbf = pvm_setrbuf( mid ); pvm_upkint( &mhf_catch, 1, 1 ); pvm_upkstr( mhf_msg ); printf( "\n%s: string_catcher%d received message -->> <%s>\n\n", me, mhf_catch, mhf_msg ); pvm_freebuf( pvm_setrbuf( rbf ) ); return 0; } /* string_catcher5 */ int int_catcher6( mid ) int mid; { char *me = "int_catcher6"; int rbf; rbf = pvm_setrbuf( mid ); pvm_upkint( &mhf_catch, 1, 1 ); pvm_upkint( &mhf_magic_number, 1, 1 ); printf( "\n%s: int_catcher%d received magic number -->> %d.\n\n", me, mhf_catch, mhf_magic_number ); pvm_freebuf( pvm_setrbuf( rbf ) ); return 0; } /* int_catcher6 */ int int_catcher7( mid ) int mid; { char *me = "int_catcher7"; int rbf; rbf = pvm_setrbuf( mid ); pvm_upkint( &mhf_catch, 1, 1 ); pvm_upkint( &mhf_magic_number, 1, 1 ); printf( "\n%s: int_catcher%d received magic number -->> %d.\n\n", me, mhf_catch, mhf_magic_number ); pvm_freebuf( pvm_setrbuf( rbf ) ); return 0; } /* int_catcher7 */ int int_catcher8( mid ) int mid; { char *me = "int_catcher8"; int rbf; rbf = pvm_setrbuf( mid ); pvm_upkint( &mhf_catch, 1, 1 ); pvm_upkint( &mhf_magic_number, 1, 1 ); printf( "\n%s: int_catcher%d received magic number -->> %d.\n\n", me, mhf_catch, mhf_magic_number ); pvm_freebuf( pvm_setrbuf( rbf ) ); return 0; } /* int_catcher8 */ int int_catcher9( mid ) int mid; { char *me = "int_catcher9"; int rbf; rbf = pvm_setrbuf( mid ); pvm_upkint( &mhf_catch, 1, 1 ); pvm_upkint( &mhf_magic_number, 1, 1 ); printf( "\n%s: int_catcher%d received magic number -->> %d.\n\n", me, mhf_catch, mhf_magic_number ); pvm_freebuf( pvm_setrbuf( rbf ) ); return 0; } /* int_catcher9 */ int int_catcher10( mid ) int mid; { char *me = "int_catcher10"; int rbf; rbf = pvm_setrbuf( mid ); pvm_upkint( &mhf_catch, 1, 1 ); pvm_upkint( &mhf_magic_number, 1, 1 ); printf( "\n%s: int_catcher%d received magic number -->> %d.\n\n", me, mhf_catch, mhf_magic_number ); pvm_freebuf( pvm_setrbuf( rbf ) ); return 0; } /* int_catcher10 */ /**********************************************************************/ /**********************************************************************/ /**********************************************************************/ main ( argc, argv ) int argc; char *argv[]; { char *me = "mhf_server"; int cc; /* local stuff */ int mytid; /* tid of this server */ int ctid; /* tid of request sender - to this server */ int msgtag; /* sender specified message tag */ int length; /* length of message */ int sctx; /* server's context */ int info; /* status return and temporary input values */ int mhid; /* message handler id */ int lmh; /* int represent local message handler to ping */ int index; /* mailbox entry index */ char msg[STR_LEN]; /* used for local info messages */ char msg_txt[STR_LEN]; /* used for received messages */ char machine[25]; int FOREVER = YES; /* * for display - note IC5 position */ static char *mh_arr[] = { "IC5", "SC1", "SC2", "SC3", "SC4", "SC5", "IC1", "IC2", "IC3", "IC4" }; /* expected message information coming from "tickle" program */ char action_tag; /* action for server to take -> p, l, d, x j */ int src; /* message source = sender's tid */ int tag; /* message tag */ int ctx; /* message context */ if ( ( mytid = pvm_mytid( ) ) < 0 ){ printf( "\n%s: try starting pvm first...\n", me ); exit( -1 ); } gethostname( machine, 25 ); sctx = pvm_newcontext( ); /* get new context */ pvm_setcontext( sctx ); /* activate new context */ printf( "%s: t%x on machine <%s> with context %d.\n", me, mytid, machine, pvm_getcontext( ) ); if ( register_server( mytid, sctx, machine, me ) < 0 ){ pvm_exit( ); exit( -1 ); } pvmdisplaymhfinfo( me, "startup...", mytid ); /* * startup message "server" to wait for messages * leave when receive the "END" message * * Remember: message handlers are keying on specific * source - tag - context --> tuples... */ while( FOREVER ) { if ( ( cc = pvm_recv( -1, -1 ) ) < 0 ){ /* receive all */ lpvmerr( "\nmhf_server: pvm_recv( ): error %d", cc ); pvm_exit( ); exit( 0 ); } /* who sent message */ if ( (info = pvm_bufinfo( cc, &length, &msgtag, &ctid )) < 0 ){ lpvmerr( "\nmhf_server: pvm_bufinfo( ): error %d", info ); pvm_exit( ); exit( 0 ); } switch ( msgtag ){ case PMH: /* display present message handlers */ pvm_upkstr( msg_txt ); sprintf( msg, "%s: PMH: %s", me, msg_txt ); pvmdisplaymhfinfo( me, msg, mytid ); break; /* load message handler */ /* ( src=tid_of_sender ...usually..., tag, ctx ) */ case LMH: /* tid of msg handler ONLY user - unless wildcard -1 */ pvm_upkint( &src, 1, 1 ); pvm_upkint( &tag, 1, 1 ); pvm_upkint( &ctx, 1, 1 ); /* number indicates which handler to load */ pvm_upkint( &info, 1, 1 ); #ifdef NOISE2 sprintf( msg, "%s: LMH: BEFORE load with pvm_addmhf( src = t%x, tag = %d, ctx = %d ) -> load %s", me, src, tag, ctx, mh_arr[info] ); pvmdisplaymhfinfo( me, msg, mytid ); #endif switch ( info ){ case SC1: mhid = pvm_addmhf( src, tag, ctx, string_catcher1 ); break; case SC2: mhid = pvm_addmhf( src, tag, ctx, string_catcher2 ); break; case SC3: mhid = pvm_addmhf( src, tag, ctx, string_catcher3 ); break; case SC4: mhid = pvm_addmhf( src, tag, ctx, string_catcher4 ); break; case SC5: mhid = pvm_addmhf( src, tag, ctx, string_catcher5 ); break; case IC1: mhid = pvm_addmhf( src, tag, ctx, int_catcher6 ); break; case IC2: mhid = pvm_addmhf( src, tag, ctx, int_catcher7 ); break; case IC3: mhid = pvm_addmhf( src, tag, ctx, int_catcher8 ); break; case IC4: mhid = pvm_addmhf( src, tag, ctx, int_catcher9 ); break; case IC5: mhid = pvm_addmhf( src, tag, ctx, int_catcher10 ); break; default: printf( "\n%s: no such message handler <%d> to load... Only 0 - 9 available!", me, info ); mhid = PvmBadParam; break; } /* end_switch ( info ) */ if ( mhid == PvmExists ){ printf( "\n%s: message handler already exists...\n", me ); break; } if ( mhid < 0 ){ printf( "\n%s: pvm_addmhf failed with error code %d.\n", me, mhid ); break; } #ifdef NOISE1 sprintf( msg, "%s: LMH: AFTER load with pvm_addmhf( src = t%x, tag = %d, ctx = %d ) -> loaded %s", me, src, tag, ctx, mh_arr[info] ); pvmdisplaymhfinfo( me, msg, mytid ); #endif break; case DMH: /* delete message handler */ pvm_upkint( &mhid, 1, 1 ); #ifdef NOISE2 sprintf( msg, "%s: DMH: BEFORE delete with pvm_delmhf( mhid = %d )", me, mhid ); pvmdisplaymhfinfo( me, msg, mytid ); #endif if ( ( info = pvm_delmhf( mhid ) ) < 0 ){ sprintf( msg,"%s: pvm_delmhf failed - no such handler existed.", me ); lpvmerr( msg, PvmNotFound ); break; } sprintf( msg, "%s: DMH: AFTER delete with pvm_delmhf( mhid = %d )", me, mhid ); pvmdisplaymhfinfo( me, msg, mytid ); break; case ERJ: /* tell mhf_server() to pvm_exit( ) and then rejoin ->> check message handlers existance */ #ifdef NOISE2 sprintf( msg, "%s: ERJ: BEFORE pvm_exit( )", me ); pvmdisplaymhfinfo( me, msg, mytid ); #endif /* * exit pvm part... */ if ( ( info = pvm_exit( ) ) < 0 ){ printf( "\n%s: pvm_exit failed with error code %d.\n", me, info ); break; } #ifdef NOISE1 printf( "\n%s: Just did pvm_exit...\n", me ); sprintf( msg, "%s: ERJ: AFTER pvm_exit( )", me ); pvmdisplaymhfinfo( me, msg, mytid ); #endif /* * rejoin pvm part... */ if ( ( mytid = pvm_mytid( ) ) < 0 ){ printf( "\n%s: could not restart - pvm not up...\n", me ); exit( -1 ); } #ifdef NOISE1 printf( "%s: just rejoined pvm...\n", me ); printf( "%s: restarted as t%x on machine <%s> with context %d.\n", me, mytid, machine, pvm_getcontext( ) ); sprintf( msg, "%s: ERJ: rejoin pvm AFTER pvm_exit( )", me ); pvmdisplaymhfinfo( me, msg, mytid ); #endif /* * re-register server via mailbox... */ if ( ( info = register_server( mytid, sctx, machine, me ) ) < 0 ){ printf( "\n%s: register_server( ) failed with error code %d.\n", me, info ); pvm_exit( ); exit( -1 ); } #ifdef NOISE1 printf( "%s: just registered server...\n", me ); #endif break; case HIT: /* message to hit a specified handler... */ pvm_upkint( &lmh, 1, 1 ); /* integer indicates which target trying to ping */ if ( lmh == mhf_catch ) printf( "\n%s: HIT: ping target %d - %s ", me, lmh, mh_arr[lmh] ); else printf( "\n%s: NO HIT: lmh = %d - %s mhf_catch = %d - ?C? ", me, lmh, mh_arr[lmh], mhf_catch ); switch ( lmh ) { case 1: case 2: case 3: case 4: case 5: pvm_upkstr( msg_txt ); if ( strcmp( msg_txt, mhf_msg ) == 0 ) printf( "strings match <%s>.\n", msg_txt ); else printf( "strings NO match - local <%s> mhf <%s>.\n", msg_txt, mhf_msg ); break; case 0: case 6: case 7: case 8: case 9: pvm_upkint( &cc, 1, 1 ); if ( cc == mhf_magic_number ) printf( "magic_numbers match %d.\n", cc ); else printf( "magic_numbers NO match - local %d mhf %d.\n", cc, mhf_magic_number ); break; } sprintf( msg, "%s: HIT:", me ); pvmdisplaymhfinfo( me, msg, mytid ); /* * reset globals to some known values for testing */ mhf_catch = -99; mhf_magic_number = -99; strcpy ( mhf_msg, "NO MATCH" ); break; case SEAT: /* server exits pvm and terminate self */ sprintf( msg, "%s: CEAT: Termiate Self...", me ); pvmdisplaymhfinfo( me, msg, mytid ); FOREVER = NO; /* will cause program termination */ break; default:/* invalid msgtag - just ignore the message */ printf( "%s: default: INVALID msgtag: length = %d msgtag = <%d> ctid = t%x", me, length, msgtag, ctid ); break; } /* switch_end */ fflush( stdout ); } /* end_while_FOREVER */ pvm_exit( ); exit( 0 ); } /* end_main */ ./pvm3/examples/mhf_tickle.c0100644007401100000360000004417506625343444015214 0ustar kohlgopher static char rcsid[] = "$Id: mhf_tickle.c,v 1.4 1998/11/20 19:46:44 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /*************************************************************** * Filename: mhf_tickle.c * * This program "tickles" the mhf_server program for testing * message handler functionality. Also serves as an example * of how you may use and drive the message handlers... * * Operation: * 1. startup pvm console * 2. startup the mhf_server * 3. startup as many mhf_tickle instances as you wish * - follow menu options and in-code comments on * how to run and what it tests / shows... * * This code is dedicated to "Tickle-Me-Elmore". * And yes that is Elmore.... ***************************************************************/ #include "stdio.h" #ifndef WIN32 #include #else #include #endif #include "pvm3.h" /* #define NOISE1 1 sets level of program noise - minimum noise */ #define PMH 0 /* display present message handlers */ #define LMH 1 /* load message handler */ #define DMH 2 /* delete message handler */ #define ERJ 3 /* tell mhf_server() to pvm_exit( ) and then rejoin. */ #define HIT 4 /* message to hit a specified handler... */ #define GSMB 7 /* use to grab the mhf_server contact info from mailbox again... */ #define CEAT 8 /* client ( this program ) exit pvm and terminate self - server not contacted... */ #define SEAT 9 /* server exits pvm and terminate self */ #define SC1 1 /* string_catcher1 */ #define SC2 2 /* string_catcher2 */ #define SC3 3 /* string_catcher3 */ #define SC4 4 /* string_catcher4 */ #define SC5 5 /* string_catcher5 */ #define IC1 6 /* int_catcher6 */ #define IC2 7 /* int_catcher7 */ #define IC3 8 /* int_catcher8 */ #define IC4 9 /* int_catcher9 */ #define IC5 0 /* int_catcher10 */ #define STR_LEN 100 #define TRUE 1 #define FALSE 0 #define YES TRUE #define NO FALSE #define SUCCESS 0 #ifdef WIN32 #undef FAILED /* necessary on win32 because of winerror.h */ #endif #define FAILED -1 extern int errno; /***************************************************************/ void eat_line( c ) char c; { while ( c != '\n' ) c = getchar( ); /* eat the remaining chars on the line */ } /* eat_line */ /* * get single character and discard remainder of input line */ char getc_line( c ) char *c; { scanf( "%c", c ); /* c is the address ( pointer ) for the char storage */ eat_line( *c ); return( *c ); } /* getc_line */ /* * get string - no spaces */ char * gets_lim_nw( max_len, s ) int max_len; char *s; { char *me = "gets_lim_nw"; char c; int i = 0; int first_char = TRUE; while ( ( ( c = getchar( ) ) != '\n' ) && ( i < ( max_len - 1 ) ) ) { if ( !( isspace( c ) ) ) /* not a white space character */ { /* printf( "\n%s: save char [%c] in position s[%d]", me, c, i ); sls-debug */ s[i++] = c; /* not a white space, so keep the character */ first_char = FALSE; /* mark having read the first non-white space char */ } else /* is a white space character */ { if ( !( first_char ) ) /* other than first character to read is whitespace */ break; /* kick out of the read loop */ } } s[i] = (char) NULL; eat_line( c ); /* eat the remaining characters on this line */ return( s ); } /* gets_lim_nw */ /* * look for the user specified service name */ int locate_server( service, tid, ctx, server ) char *service; int *tid; int *ctx; char *server; { char *me = "locate_server"; int msg_buf; msg_buf = pvm_recvinfo( service, 0, PvmMboxDefault ); if ( msg_buf >= 0 ) { pvm_setrbuf( msg_buf ); pvm_upkint( tid, 1, 1 ); pvm_upkint( ctx, 1, 1 ); pvm_upkstr( server ); } else { /* * problem retrieving mailbox entry - tell user why, exit pvm, and terminate task... */ switch ( msg_buf ) { case PvmExists: printf( "\n%s: Named service already running\n", me ); break; case PvmBadParam: printf( "\n%s: Invalid argument to pvm_recvinfo( ).\n", me ); break; case PvmNoSuchBuf: printf( "\n%s: Message buffer id does not exist.\n", me ); break; case PvmDenied: printf( "\n%s: Key locked by another task, can't delete.\n", me ); break; case PvmNoMem: printf( "\n%s: Libpvm is unable to allocate memory to pack data.\n", me ); break; case PvmNotFound: printf( "\n%s: Requested key does not exist.\n", me ); break; default: lpvmerr( "\nmhf_tickle: error %d", msg_buf ); break; } /* end_switch */ return( msg_buf ); } /* printf( "%s: just retrieved mailbox with stid = t%x sctx = %d server = %s service = %s.\n", me, *tid, *ctx, server, service ); */ return( msg_buf ); } /* locate_server */ /* * returns integer representing which message handler to load */ int mhl( ) { char *me = "mhl"; char menu_selection; int got_menu_selection = NO; char zero = '0'; do{ printf( "\n" ); printf( "\n Load Message Handler" ); printf( "\n --------------------" ); printf( "\n" ); printf( "\n 1. string_catcher1" ); printf( "\n 2. string_catcher2" ); printf( "\n 3. string_catcher3" ); printf( "\n 4. string_catcher4" ); printf( "\n 5. string_catcher5" ); printf( "\n 6. int_catcher6" ); printf( "\n 7. int_catcher7" ); printf( "\n 8. int_catcher8" ); printf( "\n 9. int_catcher9" ); printf( "\n 0. int_catcher10" ); printf( "\n" ); printf( "\n Enter Selection: " ); getc_line( &menu_selection ); switch ( menu_selection ) { case '0': /* drop through */ case '1': /* drop through */ case '2': /* drop through */ case '3': /* drop through */ case '4': /* drop through */ case '5': /* drop through */ case '6': /* drop through */ case '7': /* drop through */ case '8': /* drop through */ case '9': got_menu_selection = YES; } } while ( !got_menu_selection ); return ( menu_selection-zero ); } /* mhl */ /* * returns integer value representing option selected ( not char value ) */ int mhto( ) { char *me = "mhto"; char menu_selection; int got_menu_selection = NO; char zero = '0'; do{ printf( "\n" ); printf( "\n Message Handler Trial Options" ); printf( "\n -----------------------------" ); printf( "\n" ); printf( "\n 0. PMH - display present message handlers." ); printf( "\n 1. LMH - load message handler." ); printf( "\n 2. DMH - delete message handler." ); printf( "\n 3. ERJ - tell mhf_server() to pvm_exit( ) and then rejoin." ); printf( "\n 4. HIT - message to hit a specified handler..." ); printf( "\n 5. - available." ); printf( "\n 6. - available." ); printf( "\n 7. GSMB - get server from mail box again ( use if drop connection )." ); printf( "\n 8. CEAT - client ( this program ) exit pvm and terminate self." ); printf( "\n 9. SEAT - tell server to exit pvm and terminate self." ); printf( "\n" ); printf( "\n Enter Selection: " ); getc_line( &menu_selection ); switch ( menu_selection ) { case '0': /* drop through */ case '1': /* drop through */ case '2': /* drop through */ case '3': /* drop through */ case '4': /* drop through */ case '7': /* drop through */ case '8': /* drop through */ case '9': got_menu_selection = YES; } } while ( !got_menu_selection ); return ( menu_selection-zero ); } /* mhto */ /* * get hex - move to next line */ int getx_line( i ) int *i; { char *me = "geti_line"; char c[STR_LEN]; /* temporary location to hold input string to convert to integer */ gets_lim_nw( STR_LEN, c ); /* grab the input string */ *i = strtol( c, ( char ** )NULL, 16 ); /* convert string to hexadecimal, bas 16 */ if ( errno == ERANGE ) return( FAILED ); return( SUCCESS ); } /* getx_line */ /* * get integer - move to next line */ int geti_line( i ) int *i; { char *me = "geti_line"; char c[STR_LEN]; /* temporary location to hold input string to convert to integer */ gets_lim_nw( STR_LEN, c ); /* grab the input string */ *i = strtol( c, ( char ** )NULL, 10 ); /* convert string to integer, base 10 */ if ( errno == ERANGE ) return( FAILED ); return( SUCCESS ); } /* geti_line */ /* * discard current input line */ /* * simple way to coordinate some timing tasks... */ void press_enter_key( message ) char *message; { char c = (char) NULL; printf( "%s", message ); eat_line( c ); } /* press_enter_key */ /* * get string within length limit allow only single white spaces */ char * gets_lim_ows( max_len, s ) int max_len; char *s; { char c; int i = 0; int last_space = TRUE; while ( ( ( c = getchar( ) ) != '\n' ) && ( i < ( max_len - 1 ) ) ) { if ( isspace( c ) ) { c = ' '; /* ensure that c is a char space - not other white space */ if ( !( last_space ) ) { /* last char was not a space */ s[i++] = c; /* so add to string */ /*printf( "\nsave char [%c]", c ); sls-debug */ } last_space = TRUE; /* mark last char read was a white space */ } else { s[i++] = c; last_space = FALSE; /* mark last char read was not a space */ /*printf( "\nsave char [%c]", c ); sls-debug */ } } /* don't permit to end on space char - so move backward to first non-white space char */ /* note that this may result in one-less than the maximum number of chars available being read */ while ( isspace( s[--i] ) ) { /* do nothing... */ } s[++i] = (char) NULL; eat_line( c ); /* eat the remaining characters on this line */ return( s ); } /* gets_lim_ows */ /***************************************************************/ main ( argc, argv ) int argc; char *argv[]; { char *me = "mhf_tickle"; char machine[25]; int mytid; int ctx; /* client original context */ int i; char msg_txt[STR_LEN]; /* used for sending messages */ int stid; /* server's tid */ int sctx; /* server's context */ char *service = "mhf_server"; char server[25]; /* machine name of server */ int mh_src; /* message handler source ( tid ) to talk to */ int mh_tag; /* message handler tag to talk to */ int mh_ctx; /* message handler context to talk to */ int mhid; /* message handler id - used to delete them */ int option; /* user entered option selection */ int load_mh; /* message handler to load */ /* * for display - note IC5 position */ static char *mh_arr[] = { "IC5", "SC1", "SC2", "SC3", "SC4", "SC5", "IC1", "IC2", "IC3", "IC4" }; mytid = pvm_mytid( ); ctx = pvm_getcontext( ); /* original starting context */ gethostname( machine, 25 ); #ifdef NOISE1 printf( "%s: t%x on machine <%s> with context %d.\n", me, mytid, machine, ctx ); #endif if ( locate_server( service, &stid, &sctx, server ) < 0 ){ pvm_exit( ); exit( -1 ); } #ifdef NOISE1 printf( "%s: just retrieved mailbox with stid = t%x sctx = %d server = %s service = %s.\n", me, stid, sctx, server, service ); #endif do{ option = mhto( ); /* get Message Handler Trial Options */ switch ( option ){ case PMH:/***** * display present message handlers */ printf( "\n%s: PMH - display present message handlers\n", me ); pvm_setcontext( sctx ); /* set my context to that of server */ sprintf( msg_txt, "Are you talking to me!!!" ); pvm_initsend( PvmDataDefault ); pvm_pkstr( msg_txt ); pvm_send( stid, PMH ); printf( "%s: sent--<%s> to: stid = t%x sctx = %d.\n", me, msg_txt, stid, sctx );fflush( stdout ); break; case LMH:/***** * load message handler, ( src=tid_of_sender, tag, ctx ) */ printf( "\n%s: client: src=tid = t%x ctx = %d.", me, mytid, ctx ); printf( "\n%s: server: src=tid = t%x ctx = %d.\n", me, stid, sctx ); printf( "\n%s: LMH - load message handler", me ); pvm_setcontext( sctx ); /* set my context to that of server */ pvm_initsend( PvmDataDefault ); mh_src = mytid; /* can't spoof a source tid - must use existing one... */ printf( "\n%s: message source tid: t%x\n", me, mh_src ); pvm_pkint( &mh_src, 1, 1 ); printf( "%s: message source tag: ", me ); if ( geti_line( &mh_tag ) != SUCCESS ){ printf( "\n%s: problem on source tag - try again...\n", me ); break; } pvm_pkint( &mh_tag, 1, 1 ); printf( "%s: message source ctx: ", me ); if ( geti_line( &mh_ctx ) != SUCCESS ){ printf( "\n%s: problem on context input - try again...\n", me ); break; } pvm_pkint( &mh_ctx, 1, 1 ); load_mh = mhl( ); pvm_pkint( &load_mh, 1, 1 ); /* handler to load in mhf_server( ) code */ printf( "\n%s: will attempt loading message handler %s with src = t%x = %d, tag = %d, ctx = %d\n", me, mh_arr[load_mh], mh_src, mh_src, mh_tag, mh_ctx ); pvm_send( stid, LMH ); break; case DMH:/***** * delete message handler */ printf( "\n%s: DMH - delete message handler", me ); pvm_setcontext( sctx ); /* set my context to that of server */ printf( "\n%s: delete message handler id: ", me ); if ( geti_line( &mhid ) != SUCCESS ){ printf( "\n%s: problem on message handler id input - try again...\n", me ); break; } pvm_initsend( PvmDataDefault ); pvm_pkint( &mhid, 1, 1 ); pvm_send( stid, DMH ); break; case ERJ:/***** * tell mhf_server() to pvm_exit( ) and then rejoin. ->> check message handlers existance */ printf( "\n%s: ERJ - tell mhf_server() to pvm_exit( )", me ); pvm_setcontext( sctx ); /* set my context to that of server */ pvm_initsend( PvmDataDefault ); pvm_send( stid, ERJ ); /* * must relocate the server as past info is now stale */ printf( "%s: Looking for service = %s.\n", me, service ); press_enter_key( "Press Enter key when server is ready to continue..." ); if ( locate_server( service, &stid, &sctx, server ) < 0 ){ pvm_exit( ); exit( -1 ); } printf( "%s: just retrieved mailbox with stid = t%x sctx = %d server = %s service = %s.\n", me, stid, sctx, server, service ); break; case HIT:/***** * message to hit a specified handler... */ printf( "\n%s: HIT - message to hit a specified handler...", me ); printf( "\n%s: set message tag: ", me ); if ( geti_line( &mh_tag ) != SUCCESS ){ printf( "\n%s: problem on source tag - try again...\n", me ); break; } printf( "%s: message source ctx: ", me ); if ( geti_line( &mh_ctx ) != SUCCESS ){ printf( "\n%s: problem on context input - try again...\n", me ); break; } pvm_setcontext( mh_ctx ); /* set my context to that which handler expects */ load_mh = mhl( ); /* select handler to "hit" */ pvm_initsend( PvmDataDefault ); pvm_pkint( &load_mh, 1, 1 ); /* integer indicates which trying to ping */ switch ( load_mh ) { case 1: case 2: case 3: case 4: case 5: printf( "\n%s: Enter message to ping message handler string_catcher%d: ",me, load_mh ); gets_lim_ows( STR_LEN, msg_txt ); printf( "\n%s: will ping %s:string_catcher%d with message <%s>.\n", me, mh_arr[load_mh], load_mh, msg_txt ); pvm_pkstr( msg_txt ); break; case 0: case 6: case 7: case 8: case 9: printf( "\n%s: Enter integer to ping message handler int_catcher%d: ",me, load_mh ); geti_line( &i ); printf( "\n%s: will ping %s:int_catcher%d with integer <%d>.\n", me, mh_arr[load_mh], load_mh, i ); pvm_pkint( &i, 1, 1 ); break; default: /* should never get here... */ printf( "\n\n%s: mhl( ) returned value <%d> out of bounds...\n\n", me, load_mh ); pvm_exit( ); exit( -1 ); break; } pvm_send( stid, mh_tag ); /* the send that the mhf should intercept */ /* * now tickle the mhf_server so that it knows that a * message should have been intercepted on its behalf */ pvm_setcontext( sctx ); /* set my context to that of server */ pvm_initsend( PvmDataDefault ); pvm_pkint( &load_mh, 1, 1 ); /* integer indicates which trying to ping */ switch ( load_mh ) { case 1: case 2: case 3: case 4: case 5: pvm_pkstr( msg_txt ); break; case 0: case 6: case 7: case 8: case 9: pvm_pkint( &i, 1, 1 ); break; } pvm_send( stid, HIT ); /* the send to "tickle" mhf_server with */ break; case GSMB:/***** * use to grab the mhf_server contact info from mailbox again... * No actual contact with mhf_server - only its entry into mailbox * * Necessary if another instance of mhf_tickle does a ERJ on you... */ if ( locate_server( service, &stid, &sctx, server ) < 0 ){ pvm_exit( ); exit( -1 ); } #ifdef NOISE1 printf( "%s: just retrieved mailbox with stid = t%x sctx = %d server = %s service = %s.\n", me, stid, sctx, server, service ); #endif break; case SEAT:/***** * server exits pvm and terminate self */ printf( "\n%s: SEAT - server exits pvm and terminate self\n\n", me ); pvm_setcontext( sctx ); /* set my context to that of server */ pvm_initsend( PvmDataDefault ); pvm_send( stid, SEAT ); pvm_exit( ); exit( 0 ); break; case CEAT:/***** * client ( this program ) exits pvm and terminate self - server not contacted... */ printf( "\n%s: CEAT - client ( this program ) exits pvm and terminate self\n\n", me ); pvm_exit( ); exit( 0 ); break; default:/******* * invalid msgtag - just ignore the message */ printf( "\n%s: default - junk input - try again...", me ); break; } pvm_setcontext( ctx ); /* reset context to that of client program mhf_tickle( ) */ } while ( ( option != SEAT ) && ( option != CEAT ) ); pvm_exit( ); exit( 0 ); } /* end_main */ ./pvm3/examples/ptest.c0100644007401100000360000000715106360710473014233 0ustar kohlgopher static char rcsid[] = "$Id: ptest.c,v 1.2 1997/07/09 13:25:15 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ #include #include "pvm3.h" #define GRP "group" #define DSIZE 10000 extern int pvmdebmask; main(argc, argv) int argc; char **argv; { int i; int j; int k; int l; int mytid; int mynod; int niter = 8; int ntask = 4; int pnod; int mydbmask = 0; int myiter = 1; double tstarray[DSIZE]; mytid = pvm_mytid(); if (argc > 1) ntask = atoi(argv[1]); else { printf("usage: ptest [debugmask] [niter] [sync/iteration]"); exit (-1); } if (argc > 2) mydbmask = atoi(argv[2]); if (argc > 3) niter = atoi(argv[3]); if (argc > 4) myiter = atoi(argv[4]); printf("%x understands %d processes\n", mytid, ntask); mynod = pvm_joingroup(GRP); if (mynod == 0) pvmdebmask= mydbmask; pvm_freezegroup(GRP,ntask); pnod = pvm_gettid(GRP,0); for (i = 0; i < niter; i ++) { for (k = 0; k < DSIZE; k ++) tstarray[k] = 2*k + mynod + (i*DSIZE); if (mynod == 0) { printf("Receiving data iter %d ...",i); if ( i > niter/2) printf(" (pvm_recv) "); else printf(" (pvm_precv) "); printf("\n"); /* i_dump(1); */ for (j = 1; j < ntask; j ++) { if ( i > niter/2) { pvm_recv(pvm_gettid(GRP,j),0); pvm_upkdouble(tstarray,DSIZE,1); } else { pvm_precv(pvm_gettid(GRP,j), 0, tstarray, DSIZE, PVM_DOUBLE, (int*)0, (int*)0, (int*)0); } for (k = 0; k < DSIZE; k++) if( tstarray[k] != (2*k + j + i*DSIZE) ) { printf("Array match failed on iter %d, task %d index %d\n", i, j, k); printf("Data should have been %f and was %f \n", (double)(2*k + j + i*DSIZE), tstarray[k]); printf("Next 10 values are :\n"); l = k; for ( k = l; k < l + 10; k++) printf("%d should have been %f was %f \n",k, (double)(2*k + j + i*DSIZE), tstarray[k]); exit(-1); } } printf("Data validated from all tasks! \n"); if ( (i % myiter) == 0) { pvm_initsend(PvmDataDefault); pvm_pkint(&i,1,1); for (l =1; l < ntask; l++) pvm_send(pvm_gettid(GRP,l),10); } } else { pvm_psend(pnod, 0, tstarray, DSIZE, PVM_DOUBLE); if ( (i % myiter ) == 0) { pvm_recv(pnod,10); pvm_upkint(&k,1,1); if (k != i) { printf("%x received iteration count %d instead of %d \n", mytid, k, i); exit(-1); } } } } pvm_lvgroup(GRP); pvm_exit(); } ./pvm3/examples/rme.c0100644007401100000360000000674606360710475013672 0ustar kohlgopher static char rcsid[] = "$Id: rme.c,v 1.4 1997/07/09 13:25:17 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * Filename: rme.c ( remove mailbox entry ) * * This program will seek out a "well known" service from a mailbox * and then remove it. * * Don't bother with flags here as they are not used by pvm_delinfo() * * usage: rme [service_name] [index_nbr] * * Note: If a task is waiting for someone to communicate via mailbox * information will be left stranded after this program removes * the associated entry from the mailbox database. * * files used: rme.c taskf.c */ #include #ifndef WIN32 #include /* for gethostname */ #else #include "pvmwin.h" #endif #include "pvm3.h" main( argc, argv ) int argc; char *argv[]; { char *me = "rme"; char machine[25]; int mytid; int info; int index; /* index of the service seeking */ char *service_name; /* name of the service seeking */ /* display_incomming_parameters( me, argc, argv ); */ printf( "\n" ); if ( argc != 3 ) { printf( "\nusage: task_end [service_name] [index_nbr]\n" ); exit( -1 ); } index = atoi( argv[2] ); service_name = argv[1]; printf( "Looking for service name <%s> with index number [%d].\n", service_name, index ); if ( ( mytid = pvm_mytid() ) == PvmSysErr ) { printf( "\nPVM not up!\n" ); exit( -1 ); } gethostname( machine, 25 ); printf( "%s: t%x on machine <%s> with context %d.\n", me, mytid, machine, pvm_getcontext() ); /* * attempt to delete the ( service_name, index ) pair from the * mailbox */ if ( (info = pvm_delinfo( service_name, index, PvmMboxDefault )) < 0 ) { /* * did not find mailbox - tell user why and exit... */ switch ( info ) { case PvmNotFound: printf( "\n%s: no service running for <%s> index <%d>\n", me, service_name, index ); break; case PvmBadParam: printf( "\n%s: Invalid argument to pvm_recvinfo().\n", me ); break; case PvmNoSuchBuf: printf( "\n%s: Message buffer id does not exist.\n", me ); break; case PvmDenied: printf( "\n%s: Key locked by another task, can't delete.\n", me ); break; default: lpvmerr( "\n%s: rme.c: error %d", me, info ); break; } /* end_switch */ exit( -1 ); } /* end_if */ pvm_exit(); exit( 0 ); } ./pvm3/examples/slave1.c0100644007401100000360000000542606360710476014275 0ustar kohlgopher static char rcsid[] = "$Id: slave1.c,v 1.2 1997/07/09 13:25:18 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ #include #include "pvm3.h" main() { int mytid; /* my task id */ int tids[32]; /* task ids */ int n, me, i, nproc, master, msgtype; float data[100], result; float work(); /* enroll in pvm */ mytid = pvm_mytid(); /* Receive data from master */ msgtype = 0; pvm_recv( -1, msgtype ); pvm_upkint(&nproc, 1, 1); pvm_upkint(tids, nproc, 1); pvm_upkint(&n, 1, 1); pvm_upkfloat(data, n, 1); /* Determine which slave I am (0 -- nproc-1) */ for( i=0; i #include #include "pvm3.h" #define MAXNPROC 32 void dowork(); main() { int mytid; /* my task id */ int *tids; /* array of task ids */ int me; /* my process number */ int i; int ntids; /* enroll in pvm */ mytid = pvm_mytid(); /* determine the size of my sibling list */ ntids = pvm_siblings(&tids); for (i = 0; i < ntids; i ++) if ( tids[i] == mytid) { me = i; break; } if (me == 0) { printf("Pass a token through the %3d tid ring:\n", ntids); for (i = 0; i < ntids; i ++) { printf( "%6d -> ", tids[i]); if (i % 6 == 0 && i > 0) printf("\n"); } printf("%6d \n", tids[0]); } /*--------------------------------------------------------------------------*/ dowork( me, ntids, tids ); /* program finished exit pvm */ pvm_exit(); exit(1); } /* Simple example passes a token around a ring */ void dowork( me, nproc, tids ) int me; int nproc; int tids[]; { int token; int src, dest; int count = 1; int stride = 1; int msgtag = 4; /* Determine neighbors in the ring */ if ( me == 0 ) src = tids[nproc -1]; else src = tids[me -1]; if (me == nproc - 1) dest = tids[0]; else dest = tids[me + 1]; if( me == 0 ) { token = dest; pvm_initsend( PvmDataDefault ); pvm_pkint( &token, count, stride ); pvm_send( dest, msgtag ); pvm_recv( src, msgtag ); printf("token ring done\n"); } else { pvm_recv( src, msgtag ); pvm_upkint( &token, count, stride ); pvm_initsend( PvmDataDefault ); pvm_pkint( &token, count, stride ); pvm_send( dest, msgtag ); } } ./pvm3/examples/starter.c0100644007401100000360000000633406673254664014576 0ustar kohlgopher static char rcsid[] = "$Id: starter.c,v 1.3 1999/03/15 19:04:20 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ #include #include "pvm3.h" char prog_name[256]; void usage(); /* extern variables */ extern int errno, optind; extern char *optarg; main(argc, argv) int argc; char **argv; { int mytid; /* my task id */ int tids[32]; /* slave task ids */ int n, nproc, numt, i, who, msgtype, nhost, narch, ch; float data[100], result[32]; struct pvmhostinfo *hostp[32]; int info, ntasks, done, j; struct pvmtaskinfo *taskp; /* Set number of slaves to start */ while ((ch = getopt(argc, argv, "n:")) != EOF) { switch(ch) { case 'n': nproc = atoi(optarg); break; default: usage(); break; } } argc -= optind; argv += optind; if (argc < 1) { usage(); } /* Get program name */ strcpy(prog_name, argv[0]); argv += 1; printf("%s program to be spawned %d times.\n", prog_name, nproc); /* enroll in pvm */ mytid = pvm_mytid(); pvm_setopt(PvmAutoErr, 1); pvm_catchout(stdout); /* start up slave tasks */ numt=pvm_spawn(prog_name, argv, 0, "", nproc, tids); if( numt < nproc ){ printf("Trouble spawning slaves. Aborting. Error codes are:\n"); for( i=numt ; i \n"); exit(1); } ./pvm3/examples/task0.c0100644007401100000360000001407606625343442014124 0ustar kohlgopher static char rcsid[] = "$Id: task0.c,v 1.6 1998/11/20 19:46:42 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * Filename: task0.c * * This program will place a "well known" service into a mailbox * along with a communication context. It will then wait for another * task to communicate via that context. * * task1.c is designed as the "other" communicating task. * task_end.c tells task0 to terminate itself and quit waiting. * * Note that you may load a number of these into the mailbox providing * they have unique key. * * The task_end.c program will cause this service to gracefully exit * pvm. * * usage: task0 [service_name] * * PvmMboxDefault d * PvmMboxPersistent p * PvmMboxMultiInstance m * PvmMboxOverWritable o * * files used: task0.c taskf.c */ #include #ifndef WIN32 #include /* for gethostname */ #else #include "pvmwin.h" #endif #include #include "pvm3.h" main( argc, argv ) int argc; char *argv[]; { char *me = "task0"; char machine[25]; int mytid; int context0, context1; char *service_name; int service_ctr = 0; /* count of the # of service requests */ int i; int index; /* returned index for mailbox entry */ char flagc[10]; /* hold characters for flags */ int flags; /* PvmMbox flags set */ char *flagstring; /* pointer to string of flag settings */ int their_tid; /* tid of task sending service request */ char msg_txt[100]; /* message received as service request */ int msg_buf; /* message buffer to receive on */ /* display_incomming_parameters( me, argc, argv ); */ /* * validate input parameters */ if ( argc == 3 ) { /* we got what we wanted -- all three */ strcpy( flagc, argv[2] ); /* copy flags to local */ } else { if ( argc == 2 ) { /* assume flags left off */ /* - so force flags to PvmMboxDefault */ strcpy( flagc, "d" ); } else { /* unknown input sequence - complain and exit */ printf( "\n\nusage: task0 [service_name] \n" ); printf( "\tPvmMboxDefault\t\td\n" ); printf( "\tPvmMboxPersistent\tp\n" ); printf( "\tPvmMboxMultiInstance\tm\n" ); printf( "\tPvmMboxOverWritable\to\n" ); exit( -1 ); } } printf( "%s: sending <%s> to set_flags.\n", me, flagc ); if ( ( flags = set_flags( flagc, &flagstring ) ) < 0 ) { exit( -1 ); /* something failed - abort! */ } service_name = argv[1]; printf( "%s: service name <%s> with flags <%d> : <%s>.\n", me, service_name, flags, flagstring ); if ( ( mytid = pvm_mytid() ) == PvmSysErr ) { printf( "\nPVM not up!\n" ); exit( -1 ); } gethostname( machine, 25 ); printf( "%s: t%x on machine <%s> with context %d.\n", me, mytid, machine, pvm_getcontext() ); context1 = pvm_newcontext(); /* create new context1 */ context0 = pvm_setcontext( context1 ); /* activate new context1 */ printf( "%s: t%x on machine <%s> with context %d.\n", me, mytid, machine, pvm_getcontext() ); /* * create message to place in mailbox */ pvm_initsend( PvmDataDefault ); pvm_packf( "%+ %d %d %s", PvmDataDefault, mytid, context1, machine ); if ( (index = pvm_putinfo( service_name, pvm_getsbuf(), flags )) < 0 ) { /* * did not find mailbox - tell user why and exit... */ switch ( index ) { case PvmExists: printf( "\n%s: Names service already running\n", me ); break; case PvmNotFound: printf( "\n%s: no service running\n", me ); break; case PvmBadParam: printf( "\n%s: Invalid argument to pvm_recvinfo().\n", me ); break; case PvmNoSuchBuf: printf( "\n%s: Message buffer id does not exist.\n", me ); break; case PvmDenied: printf( "\n%s: Key locked by another task, can't delete.\n", me ); break; default: lpvmerr( "\n%s: task0.c: error %d", me, index ); break; } /* end_switch */ exit( -1 ); } printf( "%s: just inserted service name <%s> at index %d.\n", me, service_name, index ); for ( ; ; ) { /* * wait for service requests */ printf( "%s: t%x on machine <%s> with context %d ", me, mytid, machine, pvm_getcontext() ); printf( "- waiting for service request.\n" ); msg_buf = pvm_recv( -1, -1 ); pvm_bufinfo( msg_buf, (int *) 0, (int *) 0, &their_tid ); pvm_upkstr( msg_txt ); printf( "%s: t%x %s Request number %d.\n", me, mytid, msg_txt, ++service_ctr ); if ( strncmp( msg_txt, "END", 3 ) == 0 ) break; /* * send a greeting message to service requestor */ sprintf( msg_txt, "welcome to my server - you are service request number %d.", service_ctr ); pvm_initsend( PvmDataDefault ); pvm_pkstr( msg_txt ); pvm_send( their_tid, 1 ); } /* * reset back to my original context */ (void) pvm_setcontext( context0 ); printf( "%s: t%x on machine <%s> with context %d.\n", me, mytid, machine, pvm_getcontext() ); printf( "%s: handled %d service requests.\n", me, service_ctr ); pvm_exit(); exit( 0 ); } ./pvm3/examples/task1.c0100644007401100000360000001456006625343442014123 0ustar kohlgopher static char rcsid[] = "$Id: task1.c,v 1.5 1998/11/20 19:46:42 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * Filename: task1.c * * This program will seek out a "well known" service from a mailbox * and then initiate communication with that service via the * mailbox "message" specified communication context. * * This is designed to be used along with task0.c as they have * coordinated mailbox message formats. * * usage: task1 [service_name] * * PvmMboxDefault d * PvmMboxFirstAvail f * PvmMboxReadAndDelete r * * Note: A task started by task0.c is waiting for someone to * communicate via mailbox information. If task1 communicates via * a PvmMboxReadAndDelete - the mailbox entry will be removed but * the waiting task will be left to wait indefinately since no * longer is the associated mailbox information available. * Additional code is required to clean-up waiting task too - * but that is not the intent of this code example... * * files used: task1.c taskf.c */ #include #ifndef WIN32 #include /* for gethostname */ #else #include "pvmwin.h" #endif #include "pvm3.h" main( argc, argv ) int argc; char *argv[]; { char *me = "task1"; char machine[25]; /* local machine that task1 is running on */ int mytid; /* tid of task1 */ int my_context; /* context of task1 - itself */ int i; int index = 0; /* index of mailbox message */ char *service_name; /* name of the service seeking */ int their_context; /* context of the service's owner */ /* - comm on this context */ int msg_buf; /* buffer to store mailbox's message */ int their_tid; /* tid "offering" the desired service */ char server[25]; /* name of machine "offering" the service */ char msg_txt[100]; /* message to send to service */ char flagc[10]; /* hold characters for flags */ int flags; /* PvmMbox flags set */ char *flagstring; /* pointer to string of flag settings */ /* display_incomming_parameters( me, argc, argv ); */ /* * validate input parameters */ if ( argc == 4 ) { /* we got what we wanted -- all three */ strcpy( flagc, argv[3] ); /* copy flags to local */ index = atoi( argv[2] ); /* get the index value */ } else { if ( argc == 2 ) { /* assume index and flags left off */ /* - so force index = 0, flags = PvmMboxDefault */ strcpy( flagc, "d" ); index = 0; } else{ /* unknown input sequence - complain and exit */ printf( "\n\nusage: task1 [service_name] \n" ); printf( "\tPvmMboxDefault\t\td\n" ); printf( "\tPvmMboxFirstAvail\tf\n" ); printf( "\tPvmMboxReadAndDelete\tr\n\n" ); exit( -1 ); } } /* printf( "%s: sending <%s> to set_flags.\n", me, flagc ); */ if ( ( flags = set_flags( flagc, &flagstring ) ) < 0 ) { exit( -1 ); /* something failed - abort! */ } service_name = argv[1]; printf( "%s: Looking for service name <%s>, index %d ", me, service_name, index ); printf( "- my flags are <%d> : <%s>.\n", flags, flagstring ); if ( ( mytid = pvm_mytid() ) == PvmSysErr ) { printf( "\nPVM not up!\n" ); exit( -1 ); } gethostname( machine, 25 ); printf( "%s: t%x on machine <%s> with context %d.\n", me, mytid, machine, pvm_getcontext() ); /* * look for the user specified service name */ msg_buf = pvm_recvinfo( service_name, index, flags ); if ( msg_buf >= 0 ) { pvm_setrbuf( msg_buf ); pvm_upkint( &their_tid, 1, 1 ); pvm_upkint( &their_context, 1, 1 ); pvm_upkstr( server ); /* * Note that this displays the "index" requested which may * not be the actual one of that returned if PvmMboxFirstAvail * flag is set... */ printf( "%s: service name <%s> and index %d with flags <%s> ", me, service_name, index, flagstring ); printf( "tid: %x and with context: %d\n", their_tid, their_context ); } else { switch ( msg_buf ) { case PvmNotFound: printf( "\n%s: no service running\n", me ); break; case PvmBadParam: printf( "\n%s: Invalid argument to pvm_recvinfo().\n", me ); break; case PvmNoSuchBuf: printf( "\n%s: Message buffer id does not exist.\n", me ); break; case PvmDenied: printf( "\n%s: Key locked by another task, can't delete.\n", me ); break; default: lpvmerr( "task1.c: error", msg_buf ); break; } /* end_switch */ exit( -1 ); } /* * send message to the service with their context set */ /* activate the server's context */ my_context = pvm_setcontext( their_context ); printf( "%s: t%x on machine <%s> with context %d.\n", me, mytid, machine, pvm_getcontext() ); sprintf( msg_txt, "\t%s t%x on machine <%s> with context %d.", me, mytid, machine, pvm_getcontext() ); pvm_initsend( PvmDataDefault ); pvm_pkstr( msg_txt ); pvm_send( their_tid, 1 ); /* * receive message from service */ msg_buf = pvm_recv( their_tid, -1 ); pvm_bufinfo( msg_buf, (int *) 0, (int *) 0, &their_tid ); pvm_upkstr( msg_txt ); printf( "%s: t%x from task t%x %s\n", me, mytid, their_tid, msg_txt ); /* * reset back to my original context */ pvm_setcontext( my_context ); printf( "%s: t%x on machine <%s> with context %d.\n", me, mytid, machine, pvm_getcontext() ); pvm_exit(); exit( 0 ); } ./pvm3/examples/task_end.c0100644007401100000360000001102606360710567014664 0ustar kohlgopher static char rcsid[] = "$Id: task_end.c,v 1.4 1997/07/09 13:26:15 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * Filename: task_end.c * * This program will tell a task0 instance to terminate. * This is done by seeking the "known" service from a mailbox, * initiating communication telling the task to terminate itself. * The message mailbox provides the communication information * to the specified task0 instance. * * usage: task_end [service_name] [index_nbr] * * files used: task_end.c taskf.c */ #include #ifndef WIN32 #include /* for gethostname */ #else #include "pvmwin.h" #endif #include "pvm3.h" main( argc, argv ) int argc; char *argv[]; { char *me = "task_end"; char machine[25]; /* local machine that task1 is running on */ int mytid; /* tid of task1 */ int my_context; /* context of task1 - itself */ int index; /* index of the service seeking */ char *service_name; /* name of the service seeking */ int their_context; /* context of the service's owner */ /* - comm on this context */ int msg_buf; /* buffer to store mailbox's message */ int their_tid; /* tid "offering" the desired service */ char server[25]; /* name of the machine "offering" service */ char msg_txt[100]; /* message to send to service */ /* display_incomming_parameters( me, argc, argv ); */ printf( "\n" ); if ( argc != 3 ) { printf( "\nusage: task_end [service_name] [index_nbr]\n" ); exit( -1 ); } index = atoi( argv[2] ); service_name = argv[1]; printf( "Looking for service name <%s> with index number [%d].\n", service_name, index ); if ( (mytid = pvm_mytid()) == PvmSysErr ) { printf( "\nPVM not up!\n" ); exit( -1 ); } gethostname( machine, 25 ); printf( "%s: t%x on machine <%s> with context %d.\n", me, mytid, machine, pvm_getcontext() ); /* * look for the user specified service name/index pair */ msg_buf = pvm_recvinfo( service_name, index, PvmMboxDefault ); if ( msg_buf >= 0 ) { pvm_setrbuf( msg_buf ); pvm_upkint( &their_tid, 1, 1 ); pvm_upkint( &their_context, 1, 1 ); pvm_upkstr( server ); printf( "service name <%s> of index %d on <%s> id: %x ", service_name, index, server, their_tid ); printf( "with their context: %d\n", their_context ); } else { switch ( msg_buf ) { case PvmNotFound: printf( "\n%s: no service running\n", me ); break; case PvmBadParam: printf( "\n%s: Invalid argument to pvm_recvinfo().\n", me ); break; case PvmNoSuchBuf: printf( "\n%s: Message buffer id does not exist.\n", me ); break; case PvmDenied: printf( "\n%s: Key locked by another task, can't delete.\n", me ); break; default: lpvmerr( "\n%s: task_end.c: error %d", me, msg_buf ); break; } /* end_switch */ exit( -1 ); } /* * send END message to the service with their context set */ /* activate the server's context */ my_context = pvm_setcontext( their_context ); printf( "%s: t%x on machine <%s> with context %d.\n", me, mytid, machine, pvm_getcontext() ); sprintf( msg_txt, "END" ); pvm_initsend( PvmDataDefault ); pvm_pkstr( msg_txt ); pvm_send( their_tid, 1 ); /* * reset back to my original context */ pvm_setcontext( my_context ); printf( "%s: t%x on machine <%s> with context %d.\n", me, mytid, machine, pvm_getcontext() ); pvm_exit(); exit( 0 ); } ./pvm3/examples/taskf.c0100644007401100000360000001311406673475520014210 0ustar kohlgopher static char rcsid[] = "$Id: taskf.c,v 1.4 1999/03/16 15:40:00 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /********************************************************************** * Filename: taskf.c * * contains functions used in mailbox example codes * * task0.c task1.c task_end.c * lmbi.c gmbi.c rme.c * others ??? * *********************************************************************/ #include "stdio.h" #include "pvm3.h" /********************************************************************** * Function: display_incomming_parameters * * displays the command line parameters from program *********************************************************************/ void display_incomming_parameters( who, argc, argv ) char *who; int argc; char *argv[]; { char *me = "display_incomming_parameters"; int i; printf( "\n%s: %d incoming parameters to main.\n", who, argc ); for ( i=0 ; i < argc ; i++ ) printf( "%s: argv[%d] = <%s>\n", who, i, argv[i] ); } /* display_incomming_parameters */ /********************************************************************** * Function: get_flagstring * * flags: Incoming integer that represents the sum of Mbox flags. * * returns: Outgoing string of flags set. * may have: PvmMboxDefault d = 0 * PvmMboxPersistent p = 1 * PvmMboxMultiInstance m = 2 * PvmMboxOverWritable o = 4 * PvmMboxFirstAvail f = 8 * PvmMboxReadAndDelete r = 16 * * returns a pointer to a string containing flags set * returns NULL pointer on error *********************************************************************/ char * get_flagstring( flags ) int flags; { char *me = "get_flagstring"; int size = 0; char *flagstring = ( char * ) NULL; /* * string space to return */ if ( (flagstring = (char *) calloc( 255, sizeof(char) )) == NULL ) { printf( "\n%s: failed on calloc.\n", me ); return( ( char * ) NULL ); } /* set to null so that empty string test works */ flagstring[0] = '\0'; if ( flags == PvmMboxDefault ) { strcat( flagstring, "PvmMboxDefault " ); } else { if ( flags >= PvmMboxReadAndDelete ) { strcat( flagstring, "PvmMboxReadAndDelete " ); flags -= PvmMboxReadAndDelete; } if ( flags >= PvmMboxFirstAvail ) { strcat( flagstring, "PvmMboxFirstAvail " ); flags -= PvmMboxFirstAvail; } if ( flags >= PvmMboxOverWritable ) { strcat( flagstring, "PvmMboxOverWritable " ); flags -= PvmMboxOverWritable; } if ( flags >= PvmMboxMultiInstance ) { strcat( flagstring, "PvmMboxMultiInstance " ); flags -= PvmMboxMultiInstance; } if ( flags >= PvmMboxPersistent ) { strcat( flagstring, "PvmMboxPersistent " ); flags -= PvmMboxPersistent; } } return( flagstring ); } /* get_flagstring */ /********************************************************************** * Function: set_flags * * flagsin: Incoming string containing characters representing the * Mbox switches set. * An empty string is assumed to be "d" for PvmMboxDefault. * valid chars are ( d p m o f r ) in any order. * Any bogus characters are ignored... * * flagstring: Outgoing string of flags set. * may have: PvmMboxDefault d = 0 * PvmMboxPersistent p = 1 * PvmMboxMultiInstance m = 2 * PvmMboxOverWritable o = 4 * PvmMboxFirstAvail f = 8 * PvmMboxReadAndDelete r = 16 * * returns a positive integer representing addition of all set flags. * returns a negative integer to indicate an error condition *********************************************************************/ int set_flags( flagsin, flagstring ) char *flagsin; char **flagstring; { char *me = "set_flags"; int size = 0; int flags = PvmMboxDefault; /* * check for existance of flag character and * set results accordingly */ /* ambiguious but do anyway... */ if ( strchr( flagsin, 'd' ) != NULL ) { flags |= PvmMboxDefault; } if ( strchr( flagsin, 'r' ) != NULL ) { flags |= PvmMboxReadAndDelete; } if ( strchr( flagsin, 'f' ) != NULL ) { flags |= PvmMboxFirstAvail; } if ( strchr( flagsin, 'o' ) != NULL ) { flags |= PvmMboxOverWritable; } if ( strchr( flagsin, 'm' ) != NULL ) { flags |= PvmMboxMultiInstance; } if ( strchr( flagsin, 'p' ) != NULL ) { flags |= PvmMboxPersistent; } /* * get flags. * flags other than those expected "drfomp" will return as * PvmMboxDefault */ if ( (*flagstring = get_flagstring( flags )) == NULL ) return( -1 ); return( flags ); } /* set_flags */ ./pvm3/examples/timing.c0100644007401100000360000001165306604771067014374 0ustar kohlgopher static char rcsid[] = "$Id: timing.c,v 1.4 1998/10/01 21:20:55 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * timing.c * * Does a few communication timing tests on pvm. * Uses `timing_slave' to echo messages. * ---------------------------------------------------------------------------- * If this test is run over machines with differnet data formats * Then change 'ENCODING' to PvmDataDefault in timing and timing_slave * ---------------------------------------------------------------------------- * * 9 Dec 1991 Manchek * 14 Oct 1992 Geist - revision to pvm3 * 6 Mar 1994 Geist - synch tasks and add direct route */ #ifdef HASSTDLIB #include #endif #include #ifndef WIN32 #include #endif #include #include #include #include #include "pvm3.h" #define SLAVENAME "timing_slave" #define ENCODING PvmDataRaw main(argc, argv) int argc; char **argv; { int mytid; /* my task id */ int stid = 0; /* slave task id */ int reps = 20; /* number of samples per test */ struct timeval tv1, tv2; /* for timing */ int dt1, dt2; /* time for one iter */ int at1, at2; /* accum. time */ int numint; /* message length */ int n; int i; int *iarray = 0; /* enroll in pvm */ if ((mytid = pvm_mytid()) < 0) { exit(1); } printf("i'm t%x\n", mytid); /* start up slave task */ if (pvm_spawn(SLAVENAME, (char**)0, 0, "", 1, &stid) < 0 || stid < 0) { fputs("can't initiate slave\n", stderr); goto bail; } /* Wait for slave task to start up */ pvm_setopt(PvmRoute, PvmRouteDirect); pvm_recv( stid, 0 ); printf("slave is task t%x\n", stid); /* * round-trip timing test */ puts("Doing Round Trip test, minimal message size\n"); at1 = 0; /* pack buffer */ pvm_initsend(ENCODING); pvm_pkint(&stid, 1, 1); puts(" N uSec"); for (n = 1; n <= reps; n++) { gettimeofday(&tv1, (struct timezone*)0); if (pvm_send(stid, 1)) { fprintf(stderr, "can't send to \"%s\"\n", SLAVENAME); goto bail; } if (pvm_recv(-1, -1) < 0) { pvm_perror( "recv error" ); goto bail; } gettimeofday(&tv2, (struct timezone*)0); dt1 = (tv2.tv_sec - tv1.tv_sec) * 1000000 + tv2.tv_usec - tv1.tv_usec; printf("%2d %8d\n", n, dt1); at1 += dt1; } printf("RTT Avg uSec %d\n", at1 / reps); /* * bandwidth test for different message lengths */ puts("\nDoing Bandwidth tests\n"); for (numint = 25; numint < 1000000; numint *= 10) { printf("\nMessage size %d\n", numint * 4); at1 = at2 = 0; iarray = (int*)malloc(numint * sizeof(int)); puts(" N Pack uSec Send uSec"); for (n = 1; n <= reps; n++) { gettimeofday(&tv1, (struct timezone*)0); pvm_initsend(ENCODING); pvm_pkint(iarray, numint, 1); gettimeofday(&tv2, (struct timezone*)0); dt1 = (tv2.tv_sec - tv1.tv_sec) * 1000000 + tv2.tv_usec - tv1.tv_usec; gettimeofday(&tv1, (struct timezone*)0); if (pvm_send(stid, 1)) { fprintf(stderr, "can't send to \"%s\"\n", SLAVENAME); goto bail; } if (pvm_recv(-1, -1) < 0) { pvm_perror( "recv error" ); goto bail; } gettimeofday(&tv2, (struct timezone*)0); dt2 = (tv2.tv_sec - tv1.tv_sec) * 1000000 + tv2.tv_usec - tv1.tv_usec; printf("%2d %8d %8d\n", n, dt1, dt2); at1 += dt1; at2 += dt2; } if (!(at1 /= reps)) at1 = 1; if (!(at2 /= reps)) at2 = 1; puts("Avg uSec"); printf(" %8d %8d\n", at1, at2); puts("Avg Byte/uSec"); printf(" %8f %8f\n", (numint * 4) / (double)at1, (numint * 4) / (double)at2); } /* we have to do this because the last message might be taking * up all the shared memory pages. */ pvm_freebuf(pvm_getsbuf()); puts("\ndone"); bail: if (stid > 0) pvm_kill(stid); pvm_exit(); exit(1); } ./pvm3/examples/timing_slave.c0100644007401100000360000000417606360710573015562 0ustar kohlgopher static char rcsid[] = "$Id: timing_slave.c,v 1.2 1997/07/09 13:26:19 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * timing_slave.c * * See timing.c */ #include #include #include #include "pvm3.h" #define ENCODING PvmDataRaw main(argc, argv) int argc; char **argv; { int mytid; /* my task id */ int dtid; /* driver task */ int bufid; int n = 0; /* enroll in pvm */ mytid = pvm_mytid(); /* tell parent I am ready */ pvm_setopt(PvmRoute, PvmRouteDirect); pvm_initsend(ENCODING); pvm_send( pvm_parent(), 0 ); /* pack mytid in buffer */ pvm_initsend(ENCODING); pvm_pkint(&mytid, 1, 1); /* our job is just to echo back to the sender when we get a message */ while (1) { bufid = pvm_recv(-1, -1); pvm_bufinfo(bufid, (int*)0, (int*)0, &dtid); pvm_freebuf(pvm_getrbuf()); /* for shared memory refcount hang */ pvm_send(dtid, 2); /* printf("echo %d\n", ++n); */ } } ./pvm3/examples/gexample.f0100644007401100000360000001357706371373617014721 0ustar kohlgopherC C $Id: gexample.f,v 1.3 1997/08/04 15:38:55 pvmsrc Exp $ C C Example of some group function and reduction functions in PVM C SPMD style program C C 11 March 1994 - Creation by P. Papadopoulos (phil@msr.epm.ornl.gov) C C C program gexample implicit none include '../include/fpvm3.h' C --- Set Initial and Default Parameters integer DEF_DIMENSION, INITTAG,SUMTAG,PRODTAG parameter (DEF_DIMENSION = 100 ) parameter (INITTAG = 1000 ) parameter (SUMTAG = INITTAG+1) parameter (PRODTAG = INITTAG+2) integer mytid, myinst, nproc, maxmax, root integer dimension, ninst, bufid integer tids(32) integer nsibs integer nhost, narch, dtid, speed integer blksize, nextra, mysrow, i, j, itemp, info integer subblock(DEF_DIMENSION,DEF_DIMENSION) integer colsum(DEF_DIMENSION) real*8 colprod(DEF_DIMENSION) character*32 host, arch logical spmd C --- External declarations of PVM and User defined reduce function external PvmSum external calcprod C ---------------- Begin Program ----------------------------------------- spmd = .false. c Enroll in PVM and join a group call pvmfmytid( mytid ) C Try to determine if we were spawned spmd-style call pvmfsiblings(nsibs, 0, tids(1)) if (nsibs .gt. 1) spmd = .true. call pvmfjoingroup( 'matrix', myinst ) if( myinst .lt. 0 ) then call pvmfperror( 'joingroup: ', info) call pvmfexit( info ) stop endif c Set matrix size and number of tasks. call pvmfconfig( nhost, narch, dtid, host, arch, speed, info ) nproc = 2*nhost if( nproc .gt. 32 ) nproc = 32 dimension = DEF_DIMENSION if( myinst .eq. 0 ) then print* print*, 'This program demonstrates some group and reduction' print*, 'operations in PVM. The output displays the' print*, 'the product of the first column of a 100x100 Toeplitz' print*, 'matrix and the matrix 1-norm. The matrix data is' print*, 'distributed among several tasks. The Toeplitz' print*, 'matrix is symmetric with the first row being the' print*, 'row vector [1 2 ... n].' print* c Start up more copies of myself if(nproc .gt. 1 .and. .not.spmd) then print*, 'There are ',nhost, ' machines in the configuration' print*, 'Starting ',nproc - 1, ' tasks' call pvmfspawn( 'fgexample', PVMDEFAULT, '*', > nproc -1, tids, ninst ) if( ninst .lt. nproc-1 ) then print*, 'Trouble in spawn. Check tids' print*, tids call pvmflvgroup( 'matrix', info ) call pvmfexit( info ) endif endif if ( spmd ) nproc = nsibs print*, ' --> using ', nproc, ' processors <--' print* endif c Wait till everyone has joined the group and freeze it call pvmffreezegroup( 'matrix', nproc, info ) c Broadcast input data to all members if( myinst .eq. 0 ) then call pvmfinitsend( PVMDEFAULT, bufid ) call pvmfpack(INTEGER4, nproc, 1, 1, info) call pvmfpack(INTEGER4, dimension, 1, 1, info ) call pvmfbcast( 'matrix', INITTAG ,info ) else call pvmfrecv( -1, INITTAG, info ) call pvmfunpack( INTEGER4, nproc, 1, 1 ,info) call pvmfunpack( INTEGER4, dimension, 1, 1, info) endif C Map matrix rows to processors -- blksize = dimension/nproc nextra = mod(dimension, nproc) if( myinst .lt. nextra ) then mysrow = 1 + (blksize + 1) * myinst blksize = blksize + 1 else mysrow = 1+ (blksize + 1)*(nextra) + blksize*(myinst - nextra) endif if( mysrow .gt. dimension) then blksize = 0 endif C Assign data to this subblock. The entries below make the entire matrix C a symmetric Toeplitz matrix (i.e. diagonals are of constant value) do j=1, dimension do i=1, blksize subblock(i,j) = abs(mysrow + i - j) end do end do C Locally compute the sum of each column and put into colsum do j=1, dimension colsum(j) = 0 colprod(j) = 1.0 end do do j=1, dimension do i=1,blksize itemp = abs ( subblock(i,j) ) colsum(j) = colsum(j) + itemp colprod(j) = colprod(j) * itemp end do end do C Get global sum by calling reduce using PvmSum root = 0 call pvmfreduce( PvmSum, colsum, dimension, INTEGER4, SUMTAG, > 'matrix', root, info) c Here is example of supplying a user-defined OP to reduce call pvmfreduce( calcprod, colprod, dimension, REAL8, PRODTAG, > 'matrix', root, info) c Root prints out result if( myinst .eq. root ) then maxmax = 0 do j=1,dimension maxmax = max(colsum(j),maxmax) end do write(6,*) ' The 1-Norm is ', maxmax write(6,1000) dimension write(6,*) ' The product of column 1 is', colprod(1) write(6,1001) dimension endif 1000 format(' (Should be the sum of the first ', I3, ' integers)') 1001 format(' (Should be ', I3, ' factorial)') c Problem done. Be sure all members have finished computation before exit. call pvmfbarrier( 'matrix', nproc, info) call pvmflvgroup( 'matrix', info) call pvmfexit( info ) stop end c---------------------------------------------------------------------------- C *** Example of a User-defined Reduction Function ***/ subroutine calcprod( datatype, x, y, num, info ) integer datatype real*8 x(num), y(num) integer num, info integer i do i=1,num x(i) = x(i) * y(i) end do return end ./pvm3/examples/hitc.f0100644007401100000360000000545606616365770014046 0ustar kohlgopherc c $Id: hitc.f,v 1.2 1998/10/30 16:40:24 pvmsrc Exp $ c program hitc_master include '../include/fpvm3.h' c --------------------------------------------------------- c HiTc master program. Gets user input. spawns tasks. c Uses pool-of-tasks dynamic load balancing c --------------------------------------------------------- integer i, info, nhost, narch, msgtype, n, negr integer mytid, tids(0:32) integer who, idummy double precision random character*12 hostname character*8 arch c ------------ Starting up all the tasks --------------------------- c Enroll this program in PVM call pvmfmytid( mytid ) c Find out how many hosts are in virtual machine c Start one hitc_slave task on each one. call pvmfconfig( nhost, narch, idummy, hostname, arch, > idummy, info ) c print *, nhost,' hosts detected in configuration' call pvmfspawn( 'hitc_slave', PVMDEFAULT, '*', nhost, tids, info ) if( info .lt. nhost ) then print *,'Error in spawn. info=', info do 100 i=0, nhost-1 print *,'tid',i,tids(i) 100 continue endif c Set Problem size relative to virtual machine size c Number of energies per task negr = 10 c Initial problem size n = 140 c Broadcast data to all node programs call pvmfinitsend( PVMDEFAULT, info ) call pvmfpack( INTEGER4, n, 1, 1, info ) msgtype = 1 call pvmfmcast( nhost, tids, msgtype, info ) c Size of the job pool numleft = nhost*negr-nhost c wait for results from nodes do 30 i=1,nhost*negr msgtype = 2 call pvmfrecv( -1, msgtype, info ) call pvmfunpack( INTEGER4, who, 1, 1, info ) print *,'I got result from tid:',who c Send more work to this idle task if( numleft .gt. 0 ) then n = 130 + 10*random() else n = -1 endif call pvmfinitsend( PVMDEFAULT, info ) call pvmfpack( INTEGER4, n, 1, 1, info ) msgtype = 1 call pvmfsend( who, msgtype, info ) print *,'sent ',who,' task of size:',n numleft = numleft - 1 30 continue c program finished leave PVM before exiting print *,'Program Finished' call pvmfexit(info) stop end c----------------------------------------------------------------------------- double precision function random() c----------------------------------------------------- c Routine returns a pseudo-random number between 0-1. c----------------------------------------------------- integer m, i, md, seed double precision fmd data m/25173/,i/13849/,md/65536/,fmd/65536.d0/,seed/17/ save seed seed = mod(m*seed+i,md) random = seed/fmd return end ./pvm3/examples/hitc_slave.f0100644007401100000360000002127106221574504015216 0ustar kohlgopherc c $Id: hitc_slave.f,v 1.1 1996/09/23 20:55:32 pvmsrc Exp $ c program hitc_slave include '../include/fpvm3.h' c ------------------------------------------------------ c Slave performs work requested by the master c ------------------------------------------------------ parameter(iplmax=3,ipkkr=(iplmax+1)**2,ipbase=5) parameter(iprkkr=ipkkr*2,iprmtr=iprkkr*ipbase) c integer info, mytid, mtid, msgtype real*8 random complex*16 amt(iprmtr,iprmtr),bmt(iprmtr,iprmtr) c Enroll this program in PVM call pvmfmytid( mytid ) c Get the master's task id call pvmfparent( mtid ) c ------- Begin work loop -------- 1 continue c Receive data from host msgtype = 1 call pvmfrecv( mtid, msgtype, info ) call pvmfunpack( INTEGER4, n, 1, 1, info ) c Check if problem is over if( n .lt. 1 ) goto 9999 c Generate matrix of given size do 20 i=1,n do 10 j=1,n amt(i,j) = random() bmt(i,j) = cmplx(0.d0,0.d0) 10 continue 20 continue c Calculate Matrix Inverse call matinv( n, amt, bmt ) c Send result to host call pvmfinitsend( PVMDEFAULT, info ) call pvmfpack( INTEGER4, mytid, 1, 1, info ) msgtype = 2 call pvmfsend( mtid, msgtype, info ) c Go To top and await more work. goto 1 9999 continue print *,mytid,' received no-more-work flag: exiting...' call pvmfexit(info) stop end c ================================================================== c subroutine matinv( nrmatr, amt, bmt ) c c ================================================================== c implicit real*8 (a-h,o-z) c parameter(iplmax=3,ipkkr=(iplmax+1)**2,ipbase=5) parameter(iprkkr=ipkkr*2,iprmtr=iprkkr*ipbase) c complex*16 amt(iprmtr,iprmtr),bmt(iprmtr,iprmtr) complex*16 td(iprmtr),ad(iprmtr),bd(iprmtr) complex*16 amtinv,m1 c c ************************************************************** c calculates the matrix inverse needed to determine c elements of the tau-matrix. c c Level 2 BLAS version............................... c ************************************************************** m1=(-1.00d+00,0.0d+00) c c general case............ do 16 i=1,nrmatr amtinv=1.0d+00/amt(i,i) do 12 j=1,i bd(j)=bmt(i,j) td(j)=amtinv*amt(j,i) 12 continue ad(i)=amt(i,i) td(i)=(0.0d+00,0.0d+00) do 13 j=i+1,nrmatr ad(j)=amt(i,j) 13 td(j)=amtinv*amt(j,i) c c level 2 blas c call zgeru(nrmatr,i,m1,td,1,bd,1,bmt,iprmtr) call zgeru(nrmatr,nrmatr-i+1,m1,td,1,ad(i),1,amt(1,i),iprmtr) c 16 continue c return end ************************************************************************ * SUBROUTINE ZGERU ( M, N, ALPHA, X, INCX, Y, INCY, A, LDA ) * .. Scalar Arguments .. COMPLEX*16 ALPHA INTEGER INCX, INCY, LDA, M, N * .. Array Arguments .. COMPLEX*16 A( LDA, * ), X( * ), Y( * ) * .. * * Purpose * ======= * * ZGERU performs the rank 1 operation * * A := alpha*x*y' + A, * * where alpha is a scalar, x is an m element vector, y is an n element * vector and A is an m by n matrix. * * Parameters * ========== * * M - INTEGER. * On entry, M specifies the number of rows of the matrix A. * M must be at least zero. * Unchanged on exit. * * N - INTEGER. * On entry, N specifies the number of columns of the matrix A. * N must be at least zero. * Unchanged on exit. * * ALPHA - COMPLEX*16 . * On entry, ALPHA specifies the scalar alpha. * Unchanged on exit. * * X - COMPLEX*16 array of dimension at least * ( 1 + ( m - 1 )*abs( INCX ) ). * Before entry, the incremented array X must contain the m * element vector x. * Unchanged on exit. * * INCX - INTEGER. * On entry, INCX specifies the increment for the elements of * X. INCX must not be zero. * Unchanged on exit. * * Y - COMPLEX*16 array of dimension at least * ( 1 + ( n - 1 )*abs( INCY ) ). * Before entry, the incremented array Y must contain the n * element vector y. * Unchanged on exit. * * INCY - INTEGER. * On entry, INCY specifies the increment for the elements of * Y. INCY must not be zero. * Unchanged on exit. * * A - COMPLEX*16 array of DIMENSION ( LDA, n ). * Before entry, the leading m by n part of the array A must * contain the matrix of coefficients. On exit, A is * overwritten by the updated matrix. * * LDA - INTEGER. * On entry, LDA specifies the first dimension of A as declared * in the calling (sub) program. LDA must be at least * max( 1, m ). * Unchanged on exit. * * * Level 2 Blas routine. * * -- Written on 22-October-1986. * Jack Dongarra, Argonne National Lab. * Jeremy Du Croz, Nag Central Office. * Sven Hammarling, Nag Central Office. * Richard Hanson, Sandia National Labs. * * * .. Parameters .. COMPLEX*16 ZERO PARAMETER ( ZERO = ( 0.0D+0, 0.0D+0 ) ) * .. Local Scalars .. COMPLEX*16 TEMP INTEGER I, INFO, IX, J, JY, KX * .. External Subroutines .. EXTERNAL XERBLA * .. Intrinsic Functions .. INTRINSIC MAX * .. * .. Executable Statements .. * * Test the input parameters. * INFO = 0 IF ( M.LT.0 )THEN INFO = 1 ELSE IF( N.LT.0 )THEN INFO = 2 ELSE IF( INCX.EQ.0 )THEN INFO = 5 ELSE IF( INCY.EQ.0 )THEN INFO = 7 ELSE IF( LDA.LT.MAX( 1, M ) )THEN INFO = 9 END IF IF( INFO.NE.0 )THEN CALL XERBLA( 'ZGERU ', INFO ) RETURN END IF * * Quick return if possible. * IF( ( M.EQ.0 ).OR.( N.EQ.0 ).OR.( ALPHA.EQ.ZERO ) ) $ RETURN * * Start the operations. In this version the elements of A are * accessed sequentially with one pass through A. * IF( INCY.GT.0 )THEN JY = 1 ELSE JY = 1 - ( N - 1 )*INCY END IF IF( INCX.EQ.1 )THEN DO 20, J = 1, N IF( Y( JY ).NE.ZERO )THEN TEMP = ALPHA*Y( JY ) DO 10, I = 1, M A( I, J ) = A( I, J ) + X( I )*TEMP 10 CONTINUE END IF JY = JY + INCY 20 CONTINUE ELSE IF( INCX.GT.0 )THEN KX = 1 ELSE KX = 1 - ( M - 1 )*INCX END IF DO 40, J = 1, N IF( Y( JY ).NE.ZERO )THEN TEMP = ALPHA*Y( JY ) IX = KX DO 30, I = 1, M A( I, J ) = A( I, J ) + X( IX )*TEMP IX = IX + INCX 30 CONTINUE END IF JY = JY + INCY 40 CONTINUE END IF * RETURN * * End of ZGERU . * END SUBROUTINE XERBLA ( SRNAME, INFO ) * .. Scalar Arguments .. INTEGER INFO CHARACTER*6 SRNAME * .. * * Purpose * ======= * * XERBLA is an error handler for the Level 2 BLAS routines. * * It is called by the Level 2 BLAS routines if an input parameter is * invalid. * * Installers should consider modifying the STOP statement in order to * call system-specific exception-handling facilities. * * Parameters * ========== * * SRNAME - CHARACTER*6. * On entry, SRNAME specifies the name of the routine which * called XERBLA. * * INFO - INTEGER. * On entry, INFO specifies the position of the invalid * parameter in the parameter-list of the calling routine. * * * Auxiliary routine for Level 2 Blas. * * Written on 20-July-1986. * * .. Executable Statements .. * WRITE (*,99999) SRNAME, INFO * STOP * 99999 FORMAT ( ' ** On entry to ', A6, ' parameter number ', I2, $ ' had an illegal value' ) * * End of XERBLA. * END c----------------------------------------------------------------------------- double precision function random() c----------------------------------------------------- c Routine returns a pseudo-random number between 0-1. c----------------------------------------------------- integer m, i, md, seed double precision fmd data m/25173/,i/13849/,md/65536/,fmd/65536.d0/,seed/17/ save seed seed = mod(m*seed+i,md) random = seed/fmd return end ./pvm3/examples/master1.f0100644007401100000360000000560206354543077014461 0ustar kohlgopherc c $Id: master1.f,v 1.2 1997/06/26 19:42:55 pvmsrc Exp $ c program master1 include '../include/fpvm3.h' c --------------------------------------------------------- c Example fortran program illustrating the use of PVM 3 c --------------------------------------------------------- integer i, info, nproc, nhost, msgtype integer mytid, iptid, dtid, tids(0:32) integer who, speed double precision result(32), data(100) character*18 nodename, host character*8 arch c ------------ Starting up all the tasks --------------------------- c Enroll this program in PVM call pvmfmytid( mytid ) c Set number of slaves to spawn. c Note standard input cannot be read if spawned from console, so just c derive nprocs from the VM config call pvmfconfig( nhost, narch, dtid, host, arch, speed, info ) nproc = nhost * 3 if( nproc .gt. 32 ) nproc = 32 c c Initiate nproc instances of slave1 program c If arch is set to '*' then ANY configured machine is acceptable write(6,6000) nproc 6000 format(' ','Spawning ', I4, ' tasks ...') 6001 format(' ',25X, 'SUCCESSFUL') nodename = 'fslave1' arch = '*' call pvmfspawn( nodename, PVMDEFAULT, arch, nproc, tids, numt ) c Check for problems 100 continue if( numt .lt. nproc ) then print *, 'trouble spawning ',nodename print *, ' Check tids for error code' call shutdown( numt, tids ) endif write(6,6001) c ------- Begin user program -------- n = 100 c Initiate data array do 20 i=1,n data(i) = 1 20 continue c broadcast data to all node programs call pvmfinitsend( PVMDEFAULT, info ) call pvmfpack( INTEGER4, nproc, 1, 1, info ) call pvmfpack( INTEGER4, tids, nproc, 1, info ) call pvmfpack( INTEGER4, n, 1, 1, info ) call pvmfpack( REAL8, data, n, 1, info ) msgtype = 1 call pvmfmcast( nproc, tids, msgtype, info ) c wait for results from nodes msgtype = 2 do 30 i=1,nproc call pvmfrecv( -1, msgtype, info ) call pvmfunpack( INTEGER4, who, 1, 1, info ) call pvmfunpack( REAL8, result(who+1), 1, 1, info ) if (who .eq. 0) then write(6,6002) result(who+1), who, (nproc - 1) * 100.0 else write(6,6002) result(who+1), who, (2 * who - 1) * 100.0 endif 6002 format(' ', 'I got ', F15.7, ' from', I4, + ' (expected ',F15.7,' )') 30 continue c --------- End user program -------- c program finished leave PVM before exiting call pvmfexit(info) stop end subroutine shutdown( nproc, tids ) integer nproc, tids(*) c c Kill all tasks I spawned and then myself c do 10 i=0, nproc call pvmfkill( tids(i), info ) 10 continue call pvmfexit( info ) stop return end ./pvm3/examples/slave1.f0100644007401100000360000000456506221574507014302 0ustar kohlgopherc c $Id: slave1.f,v 1.1 1996/09/23 20:55:35 pvmsrc Exp $ c program slave1 include '../include/fpvm3.h' c ------------------------------------------------------ c Example fortran program illustrating use of PVM 3 c ------------------------------------------------------ integer info, mytid, mtid, msgtype, me integer tids(0:32) double precision result, data(100) double precision work c Enroll this program in PVM call pvmfmytid( mytid ) c Get the master's task id call pvmfparent( mtid ) c ------- Begin user program -------- c Receive data from host msgtype = 1 call pvmfrecv( mtid, msgtype, info ) call pvmfunpack( INTEGER4, nproc, 1, 1, info ) call pvmfunpack( INTEGER4, tids, nproc, 1, info ) call pvmfunpack( INTEGER4, n, 1, 1, info ) call pvmfunpack( REAL8, data, n, 1, info ) c Determine which slave I am (0 -- nproc-1) do 5 i=0, nproc if( tids(i) .eq. mytid ) me = i 5 continue c Do calculations with data result = work( me, n, data, tids, nproc ) c Send result to host call pvmfinitsend( PVMDEFAULT, info ) call pvmfpack( INTEGER4, me, 1, 1, info ) call pvmfpack( REAL8, result, 1, 1, info ) msgtype = 2 call pvmfsend( mtid, msgtype, info ) c --------- End user program -------- c Program finished. Leave PVM before exiting call pvmfexit(info) stop end double precision function work( me, n, data, tids, nproc ) include '../include/fpvm3.h' c -------------------------------------- c Just a simple routine for illustration c -------------------------------------- double precision data(*), sum, psum integer i, n, me, inum integer tids(0:*) sum = 0.0 do 10 i=1,n sum = sum + me * data(i) 10 continue c ---------------------------------------- c Pass partial result to neighboring node c to illustrate node-to-node communication c ---------------------------------------- call pvmfinitsend( PVMDEFAULT, info ) call pvmfpack( REAL8, sum, 1, 1, info) inum = me+1 if( inum .eq. nproc ) inum = 0 call pvmfsend( tids(inum), 77, info ) call pvmfrecv( -1, 77, info ) call pvmfunpack( REAL8, psum, 1, 1, info) work = sum + psum return end ./pvm3/examples/spmd.f0100644007401100000360000000530006401355600014025 0ustar kohlgopherc c $Id: spmd.f,v 1.4 1997/08/28 20:11:44 pvmsrc Exp $ c c---------------------------------------- c SPMD Fortran example using PVM 3 c Illustrates use of new pvm3.4 call pvmfsiblings c---------------------------------------- program spmd include '../include/fpvm3.h' PARAMETER( MAXNPROC=32 ) integer mytid, me, info integer tids(0:MAXNPROC -1) integer ntids c ------------- c Enroll in pvm c ------------- call pvmfmytid( mytid ) c -------------------------------------------- c Call pvmfsiblings to determine how many tasks were c spawned with me. c -------------------------------------------- me = -1 call pvmfsiblings(ntids, 0, tids(0)) if (ntids .gt. MAXNPROC) ntids = MAXNPROC do i = 0, ntids - 1 call pvmfsiblings(ntids, i, tids(i)) if (tids(i) .eq. mytid) me = i end do if (me .eq. -1) then call pvmfexit(info) stop endif if (me .eq. 0) then write (6,*) 'Pass a token through the', ntids, ' tid ring:' write (6,6000) (tids(i), i=0, ntids-1), tids(0) 6000 format( 6(I7:, ' -> ')) end if call dowork( me, ntids ) c ------------------------- c program finished exit pvm c ------------------------- call pvmfexit(info) stop end subroutine dowork( me, nproc ) include '../include/fpvm3.h' c------------------------------------------------- c Simple subroutine to pass a token around a ring c------------------------------------------------- integer me, nproc integer token, src, dest, count, stride, msgtag integer ndum c ------------------------------- c Determine neighbors in the ring c ------------------------------- call pvmfsiblings(ndum, me-1, src ) call pvmfsiblings(ndum, me+1, dest ) if( me .eq. 0 ) call pvmfsiblings( ndum, nproc-1, src ) if( me .eq. nproc - 1 ) call pvmfsiblings( ndum, 0, dest) count = 1 stride = 1 msgtag = 4 if( me .eq. 0 ) then token = dest call pvmfinitsend( PVMDEFAULT, info ) call pvmfpack( INTEGER4, token, count, stride, info ) call pvmfsend( dest, msgtag, info ) call pvmfrecv( src, msgtag, info ) print*, 'token ring done' else call pvmfrecv( src, msgtag, info ) call pvmfunpack( INTEGER4, token, count, stride, info ) call pvmfinitsend( PVMDEFAULT, info ) call pvmfpack( INTEGER4, token, count, stride, info ) call pvmfsend( dest, msgtag, info ) endif return end ./pvm3/examples/AIX4SP2/0042755007401100000360000000000010117676455013771 5ustar kohlgopher./pvm3/examples/AIX4SP2/Makefile0100644007401100000360000000227206474365505015431 0ustar kohlgopher# # $Id: Makefile,v 1.1 1998/02/23 21:33:57 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/examples CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) include ${CONFFILE} #### Example programs that can be built by ../Makefile.aimk EXAMPLES = hello hello_other \ master1 slave1 fmaster1 fslave1 \ spmd fspmd \ dbwtest ibwtest pbwtest rbwtest \ timing timingh timing_slave \ hitc hitc_slave \ gexample fgexample \ gmbi \ lmbi HEXAMPLES = helloh \ master1h \ timingh \ gexampleh fgexampleh \ gmbih \ hitch #### Targets that are NOT example programs but are recognized by # ../Makefile.aimk AIMKTARGETS = default all c-all f-all hostprogs clean #### How to build programs using ../Makefile.aimk. Notice that # PVMLIB and PVMHLIB are set for MPPs (lpvm3pe, lpvm3, respectively). # Hence the default examples are built for MPP nodes. ${EXAMPLES}: make -f $(CONFFILE) PVMLIB=-lpvm3pe PVMHLIB=-lpvm3 FORT=${NODEFORT}\ CC=${NODECC} -f $(SDIR)/Makefile.aimk $@ ${HEXAMPLES} ${AIMKTARGETS}: make -f $(CONFFILE) PVMLIB=-lpvm3pe PVMHLIB=-lpvm3 FORT=${FORTRAN}\ CC=${CC} -f $(SDIR)/Makefile.aimk $@ ./pvm3/examples/OS2/0042755007401100000360000000000010117676455013342 5ustar kohlgopher./pvm3/examples/OS2/Makefile0100644007401100000360000000050406401362472014764 0ustar kohlgopher# # $Id: Makefile,v 1.2 1997/08/28 20:53:14 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/examples PVM_ARCH = OS2 CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) all: make FORT=g77 -f $(CONFFILE) -f $(SDIR)/Makefile.aimk all clean: make -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean ./pvm3/examples/PGON/0042755007401100000360000000000010117676455013502 5ustar kohlgopher./pvm3/examples/PGON/Makefile0100644007401100000360000000230306604767464015142 0ustar kohlgopher# # $Id: Makefile,v 1.7 1998/10/01 21:08:04 pvmsrc Exp $ # # PVMDIR = ../.. SDIR = $(PVMDIR)/examples CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) include ${CONFFILE} #### Example programs that can be built by ../Makefile.aimk EXAMPLES = hello hello_other \ master1 slave1 fmaster1 fslave1 \ spmd fspmd \ dbwtest ibwtest pbwtest rbwtest \ timing timingh timing_slave \ hitc hitc_slave \ gexample fgexample \ gmbi \ lmbi HEXAMPLES = helloh \ master1h \ timingh \ gexampleh fgexampleh \ gmbih \ hitch #### Targets that are NOT example programs but are recognized by # ../Makefile.aimk AIMKTARGETS = default all c-all f-all hostprogs clean #### How to build programs using ../Makefile.aimk. Notice that # PVMLIB and PVMHLIB are set for MPPs (lpvm3pe, lpvm3, respectively). # Hence the default examples are built for MPP nodes. ${EXAMPLES}: $(MAKE) -f $(CONFFILE) PVMLIB=-lpvm3pe PVMHLIB=-lpvm3 \ FORT=${NODEFORT} CC=${NODECC} -f $(SDIR)/Makefile.aimk $@ ${HEXAMPLES} ${AIMKTARGETS}: $(MAKE) -f $(CONFFILE) PVMLIB=-lpvm3pe PVMHLIB=-lpvm3 \ FORT=${FORTRAN} CC=${CC} -f $(SDIR)/Makefile.aimk $@ ./pvm3/examples/SP2MPI/0042755007401100000360000000000010117676455013711 5ustar kohlgopher./pvm3/examples/SP2MPI/Makefile0100644007401100000360000000230306604767503015343 0ustar kohlgopher# # $Id: Makefile,v 1.8 1998/10/01 21:08:19 pvmsrc Exp $ # # PVMDIR = ../.. SDIR = $(PVMDIR)/examples CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) include ${CONFFILE} #### Example programs that can be built by ../Makefile.aimk EXAMPLES = hello hello_other \ master1 slave1 fmaster1 fslave1 \ spmd fspmd \ dbwtest ibwtest pbwtest rbwtest \ timing timingh timing_slave \ hitc hitc_slave \ gexample fgexample \ gmbi \ lmbi HEXAMPLES = helloh \ master1h \ timingh \ gexampleh fgexampleh \ gmbih \ hitch #### Targets that are NOT example programs but are recognized by # ../Makefile.aimk AIMKTARGETS = default all c-all f-all hostprogs clean #### How to build programs using ../Makefile.aimk. Notice that # PVMLIB and PVMHLIB are set for MPPs (lpvm3pe, lpvm3, respectively). # Hence the default examples are built for MPP nodes. ${EXAMPLES}: $(MAKE) -f $(CONFFILE) PVMLIB=-lpvm3pe PVMHLIB=-lpvm3 \ FORT=${NODEFORT} CC=${NODECC} -f $(SDIR)/Makefile.aimk $@ ${HEXAMPLES} ${AIMKTARGETS}: $(MAKE) -f $(CONFFILE) PVMLIB=-lpvm3pe PVMHLIB=-lpvm3 \ FORT=${FORTRAN} CC=${CC} -f $(SDIR)/Makefile.aimk $@ ./pvm3/pvmgs/0042755007401100000360000000000010117676455012255 5ustar kohlgopher./pvm3/pvmgs/cygwin.mak0100644007401100000360000000217607240354776014252 0ustar kohlgopher#*****************************************************************************# # # makefile # for libgpvm3.a, pvmgs # #*****************************************************************************# include $(PVM_ROOT_U)/conf/win32cygwin.def LOBJ = $(PVM_ARCH)/pvmgsu_aux.o \ $(PVM_ARCH)/pvmgsu_core.o \ $(PVM_ARCH)/pvmgs_func.o PVM_BIN = $(PVM_ROOT_U)/bin/$(PVM_ARCH) all: $(GLIB) $(PVM_BIN)/pvmgs.exe $(PVM_BIN)/pvmgs.exe: $(PVM_ARCH)/pvmgs_core.o $(PVM_ARCH)/pvmgs_func.o $(CC) -o $(PVM_BIN)/pvmgs $(PVM_ARCH)/pvmgs_core.o \ $(PVM_ARCH)/pvmgs_func.o $(LIB) $(LINK_FLAGS) $(GLIB): $(LOBJ) ar -rs $(GLIB) $(LOBJ) $(PVM_ARCH)/pvmgsu_aux.o: pvmgsu_aux.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/pvmgsu_aux.o pvmgsu_aux.c $(PVM_ARCH)/pvmgsu_core.o: pvmgsu_core.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/pvmgsu_core.o pvmgsu_core.c $(PVM_ARCH)/pvmgs_func.o: pvmgs_func.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/pvmgs_func.o pvmgs_func.c $(PVM_ARCH)/pvmgs_core.o: pvmgs_core.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/pvmgs_core.o pvmgs_core.c # Clean up everything but the .EXEs clean : -rm -f $(PVM_ARCH)/*.o ./pvm3/pvmgs/Makefile.aimk0100644007401100000360000000721207401766407014631 0ustar kohlgopher# # $Id: Makefile.aimk,v 1.11 2001/11/30 20:33:11 pvmsrc Exp $ # # Generic Makefile body to be concatenated to config header. # # Imports: # PVM_ARCH = the official pvm-name of your processor # ARCHCFLAGS = special cc flags # ARCHLIB = special libs needed for daemon # HASRANLIB = 't' or 'f' # # Define: # NOSTRCASE if libc doesn't have strcasecmp, strncasecmp # SYSVSIGNAL for system5 signal handling # SYSVSTR for strchr() instead of index() # SHELL = /bin/sh PVMDIR = ../.. SDIR = $(PVMDIR)/pvmgs DOBJ = pvmgs_core.o pvmgs_func.o LOBJ = pvmgsu_core.o pvmgsu_aux.o pvmgs_func.o PVMIDIR = $(PVMDIR)/include PVMSDIR = $(PVMDIR)/src PVMBDIR = $(PVMDIR)/bin PVMXDIR = $(PVMBDIR)/$(PVM_ARCH) PVMLDIR = $(PVMDIR)/lib/$(PVM_ARCH) PVMLIB = pvm3 LIBPREFIX = lib PVMLIBDEP = $(PVMLDIR)/$(LIBPREFIX)$(PVMLIB).a # Add -DPVMGSTIMEOUT=XXX to CFLAGS to allow timeouts for PVM group # server requests, where XXX is the number of seconds for the timeout. # (Note: this flag can also be added to the ARCHCFLAGS define in the # PVM conf file, i.e.: $PVM_ROOT/conf/$PVM_ARCH.def ) CFLAGS = $(CFLOPTS) -I$(PVMIDIR) -I$(PVMSDIR) -DIMA_$(PVM_ARCH) \ $(ARCHCFLAGS) LIBS = $(LOPT) -L$(PVMLDIR) -l$(PVMLIB) $(ARCHLIB) DIRS = $(PVMXDIR) $(PVMLDIR) PROGS = $(PVMXDIR)/pvm_gstat$(EXESFX) \ $(PVMXDIR)/pvmgs$(EXESFX) \ $(PVMXDIR)/pvmgroups$(EXESFX) LPROGS = $(PVMLDIR)/pvmgs$(EXESFX) LIBGPVM = $(LIBPREFIX)gpvm3.a install: all install-mpp: all-mpp all: $(DIRS) $(PROGS) $(PVMLDIR)/$(LIBGPVM) $(LPROGS) all-mpp: $(DIRS) $(PROGS) $(PVMLDIR)/$(LIBGPVM)-mpp $(LPROGS) $(PVMXDIR): - mkdir $(PVMBDIR) - mkdir $(PVMXDIR) $(PVMLDIR): - mkdir $(PVMLDIR) $(PVMXDIR)/pvm_gstat$(EXESFX): pvm_gstat$(EXESFX) cp pvm_gstat$(EXESFX) $(PVMXDIR) $(PVMXDIR)/pvmgs$(EXESFX): pvmgs$(EXESFX) cp pvmgs$(EXESFX) $(PVMXDIR) $(PVMXDIR)/pvmgroups$(EXESFX): pvmgroups$(EXESFX) cp pvmgroups$(EXESFX) $(PVMXDIR) $(PVMLDIR)/$(LIBGPVM): $(LIBGPVM) cp $(LIBGPVM) $(PVMLDIR) case x$(HASRANLIB) in xt ) echo ranlib; ranlib $(PVMLDIR)/$(LIBGPVM) ;; esac $(PVMLDIR)/$(LIBGPVM)-mpp: $(LIBGPVM)-mpp cp $(LIBGPVM) $(PVMLDIR) case x$(HASRANLIB) in xt ) echo ranlib; ranlib $(PVMLDIR)/$(LIBGPVM) ;; esac touch $(PVMLDIR)/$(LIBGPVM)-mpp $(PVMLDIR)/pvmgs$(EXESFX): pvmgs$(EXESFX) cp pvmgs$(EXESFX) $(PVMLDIR) pvmgroups$(EXESFX): pvmgroups.o $(LIBGPVM) $(PVMLIBDEP) $(CC) $(CFLAGS) -o $@ pvmgroups.o $(LIBGPVM) $(LIBS) pvmgs$(EXESFX): $(DOBJ) $(PVMLIBDEP) $(CC) $(CFLAGS) -o $@ $(DOBJ) $(LIBS) $(LIBGPVM): $(LOBJ) rm -f $(LIBGPVM) $(AR) cr $(LIBGPVM) $(LOBJ) case x$(HASRANLIB) in xt ) echo ranlib; ranlib $(LIBGPVM) ;; esac $(LIBGPVM)-mpp: $(LOBJ) rm -f $(LIBGPVM) $(AR_FRONT) cr $(LIBGPVM) $(LOBJ) case x$(HASRANLIB) in xt ) echo ranlib; ranlib $(LIBGPVM) ;; esac touch $(LIBGPVM)-mpp pvm_gstat$(EXESFX): pvm_gstat.o $(LIBGPVM) $(PVMLIBDEP) $(CC) $(CFLAGS) -o $@ pvm_gstat.o $(LIBGPVM) $(LIBS) clean: rm -f $(DOBJ) $(LOBJ) pvmgs$(EXESFX) $(LIBGPVM) \ pvm_gstat.o pvmgroups.o pvm_gstat$(EXESFX) pvmgroups$(EXESFX) tidy: rm -f $(DOBJ) $(LOBJ) lint: lint -DARCHCLASS=\"$(PVM_ARCH)\" pvmgs.c > Ld lint -DARCHCLASS=\"$(PVM_ARCH)\" pvm_gsulib.c > Ll # pvmgsu_core.o: $(SDIR)/pvmgsu_core.c $(CC) $(CFLAGS) -c $(SDIR)/pvmgsu_core.c pvmgsu_aux.o: $(SDIR)/pvmgsu_aux.c $(CC) $(CFLAGS) -c $(SDIR)/pvmgsu_aux.c pvmgroups.o: $(SDIR)/pvmgroups.c $(CC) $(CFLAGS) -c $(SDIR)/pvmgroups.c pvm_gstat.o: $(SDIR)/pvm_gstat.c $(CC) $(CFLAGS) -c $(SDIR)/pvm_gstat.c pvmgs_core.o: $(SDIR)/pvmgs_core.c $(CC) $(CFLAGS) -c $(SDIR)/pvmgs_core.c pvmgs_func.o: $(SDIR)/pvmgs_func.c $(CC) $(CFLAGS) -c $(SDIR)/pvmgs_func.c # # Source File Dependencies # include $(PVMDEPPATH)$(SDIR)/pvmdep ./pvm3/pvmgs/Makefile.mak0100644007401100000360000000436306670012005014445 0ustar kohlgopher# # $Id: Makefile.mak,v 1.6 1999/03/05 17:27:33 pvmsrc Exp $ # #*************************************************************# #** **# #** (N)make file for **# #** libgpvm3.lib pvmgs **# #** **# #** **# #** **# #*************************************************************# # USER installation specific part -- to be modified !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !include $(PVM_ROOT)\conf\$(PVM_ARCH).def SDIR = $(PVM_ROOT)\pvmgs LOBJ = $(PVM_ARCH)\pvmgsu_aux.obj \ $(PVM_ARCH)\pvmgsu_core.obj \ $(PVM_ARCH)\pvmgs_func.obj #all: paths libgpvm3.lib $(libgpvm3dll) pvmgs.exe all: paths libgpvm3.lib pvmgs.exe paths: if not exist "$(PVM_ARCH)\$(NULL)" mkdir "$(PVM_ARCH)" if not exist "..\lib\$(PVM_ARCH)\$(NULL)" mkdir "..\lib\$(PVM_ARCH)" if not exist "..\bin\$(PVM_ARCH)\$(NULL)" mkdir "..\bin\$(PVM_ARCH)" pvmgs.exe: $(PVM_ARCH)\pvmgs_core.obj $(PVM_ARCH)\pvmgs_func.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\pvmgs.exe \ $(PVM_ARCH)\pvmgs_core.obj $(PVM_ARCH)\pvmgs_func.obj \ $(PVM_ROOT)\lib\$(PVM_ARCH)\libpvm3.lib $(link_flags) libgpvm3.lib: $(LOBJ) $(linklib) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\lib\$(PVM_ARCH)\libgpvm3.lib $(LOBJ) libgpvm3.dll: $(LOBJ) $(linkdll) $(conflags) \ $(OUTDLL)$(PVM_ROOT)\lib\$(PVM_ARCH)\libgpvm3.dll $(LOBJ) \ $(link_flags) $(PVM_ARCH)\pvmgsu_aux.obj: $(SDIR)\pvmgsu_aux.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmgsu_aux.obj $(SDIR)\pvmgsu_aux.c $(PVM_ARCH)\pvmgsu_core.obj: $(SDIR)\pvmgsu_core.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmgsu_core.obj $(SDIR)\pvmgsu_core.c $(PVM_ARCH)\pvmgs_func.obj: $(SDIR)\pvmgs_func.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmgs_func.obj $(SDIR)\pvmgs_func.c $(PVM_ARCH)\pvmgs_core.obj: $(SDIR)\pvmgs_core.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmgs_core.obj $(SDIR)\pvmgs_core.c # Clean up everything but the .EXEs clean : -del $(PVM_ARCH)\*.obj ./pvm3/pvmgs/pvmdep0100644007401100000360000000403306336133721013456 0ustar kohlgopher# # *** DO NOT MODIFY *** AUTOMATICALLY GENERATED *** # # $Id: pvmdep,v 1.1 1997/05/13 18:49:53 pvmsrc Exp $ # # PVM Source Header Dependencies # pvm_gstat.o: $(PVMDIR)/include/pvm3.h pvm_gstat.o: $(PVMDIR)/src/pvmalloc.h pvm_gstat.o: $(SDIR)/pvmgs_const.h pvm_gstat.o: $(SDIR)/pvmgs_decl.h pvm_gstat.o: $(SDIR)/pvmgs_ds.h pvm_gstat.o: $(SDIR)/pvmgs_mac.h pvm_gstat.o: $(SDIR)/pvmgsd.h pvmgroups.o: $(PVMDIR)/include/pvm3.h pvmgroups.o: $(SDIR)/pvmgs_const.h pvmgroups.o: $(SDIR)/pvmgs_decl.h pvmgroups.o: $(SDIR)/pvmgs_ds.h pvmgroups.o: $(SDIR)/pvmgs_mac.h pvmgroups.o: $(SDIR)/pvmgsd.h pvmgs_core.o: $(PVMDIR)/include/pvm3.h pvmgs_core.o: $(PVMDIR)/src/pvmalloc.h pvmgs_core.o: $(SDIR)/pvmgs_const.h pvmgs_core.o: $(SDIR)/pvmgs_decl.h pvmgs_core.o: $(SDIR)/pvmgs_ds.h pvmgs_core.o: $(SDIR)/pvmgs_mac.h pvmgs_core.o: $(SDIR)/pvmgsd.h pvmgs_func.o: $(PVMDIR)/include/pvm3.h pvmgs_func.o: $(PVMDIR)/src/bfunc.h pvmgs_func.o: $(PVMDIR)/src/global.h pvmgs_func.o: $(PVMDIR)/src/pvmalloc.h pvmgs_func.o: $(PVMDIR)/src/pvmmimd.h pvmgs_func.o: $(SDIR)/pvmgs_const.h pvmgs_func.o: $(SDIR)/pvmgs_decl.h pvmgs_func.o: $(SDIR)/pvmgs_ds.h pvmgs_func.o: $(SDIR)/pvmgs_mac.h pvmgs_func.o: $(SDIR)/pvmgsd.h pvmgsu_aux.o: $(PVMDIR)/include/pvm3.h pvmgsu_aux.o: $(PVMDIR)/include/pvmtev.h pvmgsu_aux.o: $(PVMDIR)/src/bfunc.h pvmgsu_aux.o: $(PVMDIR)/src/global.h pvmgsu_aux.o: $(PVMDIR)/src/lpvm.h pvmgsu_aux.o: $(PVMDIR)/src/pvmalloc.h pvmgsu_aux.o: $(PVMDIR)/src/pvmmimd.h pvmgsu_aux.o: $(PVMDIR)/src/tevmac.h pvmgsu_aux.o: $(SDIR)/pvmgs_const.h pvmgsu_aux.o: $(SDIR)/pvmgs_decl.h pvmgsu_aux.o: $(SDIR)/pvmgs_ds.h pvmgsu_aux.o: $(SDIR)/pvmgs_mac.h pvmgsu_aux.o: $(SDIR)/pvmgsd.h pvmgsu_core.o: $(PVMDIR)/include/pvm3.h pvmgsu_core.o: $(PVMDIR)/include/pvmtev.h pvmgsu_core.o: $(PVMDIR)/src/bfunc.h pvmgsu_core.o: $(PVMDIR)/src/lpvm.h pvmgsu_core.o: $(PVMDIR)/src/pvmalloc.h pvmgsu_core.o: $(PVMDIR)/src/tevmac.h pvmgsu_core.o: $(SDIR)/pvmgs_const.h pvmgsu_core.o: $(SDIR)/pvmgs_decl.h pvmgsu_core.o: $(SDIR)/pvmgs_ds.h pvmgsu_core.o: $(SDIR)/pvmgs_mac.h pvmgsu_core.o: $(SDIR)/pvmgsd.h ./pvm3/pvmgs/pvmgroups.c0100644007401100000360000000300606423475263014454 0ustar kohlgopher static char rcsid[] = "$Id: pvmgroups.c,v 1.5 1997/10/22 22:14:11 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ #include "pvm3.h" #include "pvmgsd.h" #include "pvmproto.h" main() { int gstid; pvm_mytid(); gstid = gs_getgstid(); pvm_setcontext( SYSCTX_DG ); pvm_initsend(PvmDataDefault); pvm_send(gstid, DUMP); } ./pvm3/pvmgs/pvmgs_core.c0100644007401100000360000003063506423475265014570 0ustar kohlgopher static char rcsid[] = "$Id: pvmgs_core.c,v 1.6 1997/10/22 22:14:13 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* This is the core of the group server. Everything is now dynamically allocated keep memory cost down and allow larger groups. */ /* * pvmgs.c * PVM group server * * This program maintains group lists. Processes may join or add * by sending the appropriate request to the group server. * * 4 Mar 1993 adamb: Fixed gs_barrier to reset the barrier * after it's been reached * 8 Jul 1993 adamb: Fixed gs_register'pvm_delete so it won't * print bogus error messages * 6 Feb 1994 adamb: Added DEADTID functionality, including removing * a taskid from the blocking barrier list if needed * 24 Apr 1994 Donato: Added gs_tidlist() in exchange for gs_bcast() * 1 May 1994 Papadopoulos: removed length limit for groupnames * */ #include #include "pvm3.h" #include "pvmalloc.h" #include "pvmgsd.h" #include "pvmproto.h" /* ================ main() ========================================= */ /* Main program for the group server */ int main( argc, argv ) int argc; char *argv[]; { GROUP_LIST hash_list[HASHSIZE]; /* open hashing table */ int ngroups, gstid; int nameindex; /* index of pvmgs-defnd names */ /* attach to the virtual machine */ if( (gstid = pvm_mytid()) < 0 ) { pvm_perror( GSNAME ); return( -1 ); } /* register this group server */ if ( !gs_register( GSNAME, gstid ) ) { /* set default context for system dynamic groups */ pvm_setcontext( SYSCTX_DG ); /* initialize the data structures */ gs_init( hash_list, &ngroups ); /* handle the group server functions */ gs_handle( hash_list, &ngroups, &gstid ); } pvm_exit(); return( PvmOk ); } /* ================ gs_init() ====================================== */ /* Initialize the data structures for holding group data */ int gs_init( hash_list, ngroups ) GROUP_LIST_PTR hash_list; int *ngroups; { int i; *ngroups = 0; gs_hash_init( hash_list ); return( PvmOk ); } /* ================ gs_deadtid() =================================== */ /* Called when a tid has left the VM ands needs to be deleted from */ /* all existing groups */ int gs_deadtid( tid, hash_list, ngroups ) int tid; GROUP_LIST_PTR hash_list; int *ngroups; { GROUP_LIST_PTR current; GROUP_LIST_PTR next; int i; for ( i=0; i < HASHSIZE ; i++ ) /* go thru entire list of groups */ { current = hash_list+i; current = current->next; while ( current != (GROUP_LIST_PTR) NULL ) { next = current->next; /* call to gs_leave may free */ /* struct pointed to by current */ gs_leave( current->group->name, tid, hash_list, ngroups ); current = next; } } return( PvmOk ); } /* ================ gs_pstate () =================================== */ /* Dump the information held by the group server */ int gs_pstate( name, hash_list, ngroups ) char *name; GROUP_LIST_PTR hash_list; int *ngroups; { GROUP_LIST_PTR current; GROUP_STRUCT_PTR group; int i, j; fprintf( stderr, "%s 0x%x, %d groups:\n", name, pvm_mytid(), *ngroups); for ( i=0 ; i < HASHSIZE ; i++ ) /* go thru entire list of groups */ { current = hash_list + i; current = current->next; while ( current != (GROUP_LIST_PTR) NULL ) { group = current->group; fprintf( stderr, "group: %s size: %d ", group->name, group->ntids ); fprintf( stderr, "barrier_count: %d barrier_reached %d\n ", group->barrier_count, group->barrier_reached ); fprintf( stderr, "sgroup_count: %d sgroup_reached %d\n ", group->sgroup_count, group->sgroup_reached ); fprintf( stderr, " Tids: \n" ); for ( j=0 ; j < group->maxntids ; j++ ) if ( group->tids[j] != NOTID ) fprintf( stderr, "(%d, 0x%x) ", j, group->tids[j] ); fprintf( stderr, "\n" ); if ( group->barrier_reached > 0 ) { fprintf( stderr, "tids waiting on barrier:\n" ); for ( j=0 ; j < group->barrier_reached ; j++ ) fprintf( stderr, "0x%x ", group->btids[j] ); fprintf( stderr, "\n" ); } if ( group->sgroup_reached > 0 ) { fprintf( stderr, "tids waiting on static formation:\n" ); if ( group->stids != (int *) NULL ) for ( j=0 ; j < group->sgroup_reached ; j++ ) fprintf( stderr, "0x%x ", group->stids[j] ); fprintf( stderr, "\n" ); } if ( group->nhosts > 0 ) { fprintf( stderr, "Host characterization:\n" ); for ( j=0 ; j < group->nhosts ; j++ ) fprintf( stderr, "host %x - %d procs, %x coord \n", pvm_tidtohost( group->pcoord[j] ), group->np_onhost[j], group->pcoord[j] ); } current = current->next; } } return( PvmOk ); } /* ================ gs_ls () ======================================= */ /* Pack up a message that lists the information held by the group */ /* server */ int gs_ls( hash_list, ngroups ) GROUP_LIST_PTR hash_list; int *ngroups; { GROUP_LIST_PTR current; GROUP_LIST_PTR next; GROUP_STRUCT_PTR group; int i, j; pvm_initsend( PvmDataDefault ); pvm_pkint( ngroups, 1, 1 ); for ( i=0 ; i < HASHSIZE ; i++ ) /* go thru entire list of groups */ { current = hash_list + i; current = current->next; while ( current != (GROUP_LIST_PTR) NULL ) { group = current->group; pvm_pkint( &(group->len), 1, 1 ); pvm_pkstr( group->name ); pvm_pkint( &(group->ntids), 1, 1 ); pvm_pkint( &(group->maxntids), 1, 1 ); pvm_pkint( &(group->barrier_count), 1, 1 ); pvm_pkint( &(group->barrier_reached), 1, 1 ); pvm_pkint( group->tids,group->maxntids, 1 ); if ( group->barrier_reached > 0 ) pvm_pkint( group->btids, group->barrier_reached, 1 ); current = current->next; } } return( PvmOk ); } /* ================ gs_handle () =================================== */ /* Handle the incoming msg tags and call the appropriate operation */ int gs_handle( hash_list, ngroups, gstid ) GROUP_LIST_PTR hash_list; int *ngroups, *gstid; { int len, msgtag, tid, gid, cc, ftid, inst, i, size, ntids, listsize; int cnt, hosttid, nhosts, nmem_onhost, pcoord; int *nmem_onhostv = (int *) NULL, *pcoordv = (int *) NULL; int mxupklen = 0; GROUP_STRUCT_PTR group; char *groupname = (char *) NULL; int *tidlist = (int *) NULL; int maxntids = 0, info; int gstate; while ( 1 ) { if ( (cc = pvm_recv( -1, -1 )) < 0 ) /* receive a request */ { pvm_perror( "gs_handle(recv)" ); return( cc ); } /* get: length of message, message tag, and sending tid */ if ( (cc = pvm_bufinfo( pvm_getrbuf(), &len, &msgtag, &tid )) < 0 ) { pvm_perror("gs_handle(bufinfo)"); return( cc ); } /* Most group functions require unpacking a group name, so */ /* Make sure variable groupname is always long enough */ REALLOCSTRING( len, mxupklen , groupname, "gs_handle(entry)" ); switch( msgtag ) { case (DIE): /* leave a suicide note */ gs_pstate( "pvmgs", hash_list, ngroups ); return( PvmOk ); case (JOIN): /* join a group with the lowest avail gid */ pvm_upkstr( groupname ); gid = gs_join( groupname, tid, hash_list, ngroups ); /* tell me if the tid dies */ if ( pvm_notify( PvmTaskExit, DEADTID, 1, &tid ) < 0 ) pvm_perror( "pvmgs-join" ); SENDINTRESULT( gid, tid, msgtag, "gs_handle(join)" ); break; case (LEAVE): /* leave a group */ pvm_upkstr( groupname ); cc = gs_leave( groupname, tid, hash_list, ngroups ); SENDINTRESULT( cc, tid, msgtag, "gs_handle(leave)" ); break; case (DEADTID): /* task in one or more groups has died */ pvm_upkint( &tid, 1, 1 ); if ( tid < 0 ) { fprintf( stderr, "pvmgs: weird dead tid x%x %d\n", tid, tid ); break; } cc = gs_deadtid( tid, hash_list, ngroups ); break; case (BARRIER): /* Handle barrier for a group */ case (BARRIERV): pvm_upkstr( groupname ); pvm_upkint( &cnt, 1, 1 ); cc = gs_barrier( groupname, msgtag, cnt, tid, hash_list, ngroups ); /* send back a response only if there is an error */ if ( cc < 0 ) SENDINTRESULT( cc, tid, msgtag, "gs_handle(barrier)" ); break; case (BCAST): /* broadcast and tidlists */ case (TIDLIST): pvm_upkstr( groupname ); cc = gs_tidlist( groupname, ((msgtag == BCAST) ? 0 : 1), hash_list, ngroups, &gstate ); if ( cc ) /* there was error, send back error code */ SENDINTRESULT( cc, tid, msgtag, "gs_handle(bcast)" ) else /* send the already-packed tid-list */ { PK_STATE( tid, gstate, groupname, hash_list, ngroups, "gs_handle(bcast)" ); SENDRESULT( tid, msgtag, "gs_handle(bcast)" ); } break; case (GSIZE): /* return the current group size */ pvm_upkstr( groupname ); size = gs_gsize( groupname, hash_list, ngroups, &gstate ); PK_IRESULT( size, "gs_handle(gsize)" ); PK_STATE( tid, gstate, groupname, hash_list, ngroups, "gs_handle(gsize)" ); SENDRESULT( tid, msgtag, "gs_handle(gsize)" ); break; case (GETINST): /* return inst of tid in group groupname */ pvm_upkstr( groupname ); pvm_upkint( &ftid, 1, 1 ); inst = gs_getinst( groupname, ftid, hash_list, ngroups, &gstate ); PK_IRESULT( inst, "gs_handle(getinst)" ); PK_STATE( tid, gstate, groupname, hash_list, ngroups, "gs_handle(getinst)" ); SENDRESULT( tid, msgtag, "gs_handle(getinst)" ); break; case (GETTID): /* return tid from (group,instance) pair */ pvm_upkstr( groupname ); pvm_upkint( &inst, 1, 1 ); ftid = gs_gettid( groupname, inst, hash_list, ngroups, &gstate ); PK_IRESULT( ftid, "gs_handle(gettid)" ); PK_STATE( tid, gstate, groupname, hash_list, ngroups, "gs_handle(gettid)" ); SENDRESULT( tid, msgtag, "gs_handle(gettid)" ); break; case (STATICGROUP): /* Form a static group */ pvm_upkstr( groupname ); pvm_upkint( &size, 1, 1 ); info = gs_static( groupname, size, tid, hash_list, ngroups ); if ( info < 0 ) SENDINTRESULT( info, tid, msgtag, "gs_handle(static)" ); /* gs_static will mcast list to group when formed */ break; case DUMP: gs_pstate( "DUMP", hash_list, ngroups ); break; case GSLS: gs_ls( hash_list, ngroups ); pvm_send( tid, msgtag ); break; case HOSTCHAR: /* get host characteristics */ pvm_upkstr( groupname ); pvm_upkint( &hosttid, 1, 1 ); gs_host_char( groupname, hash_list, ngroups, hosttid, &pcoord, &nmem_onhost, &nhosts, &gstate ); PK_IRESULT( nhosts, "gs_handle(hostchar)" ); pvm_pkint( &nmem_onhost, 1, 1 ); pvm_pkint( &pcoord, 1, 1 ); PK_STATE( tid, gstate, groupname, hash_list, ngroups, "gs_handle(hostchar)" ); SENDRESULT( tid, msgtag, "gs_handle(hostchar)" ); break; case HOSTCHARV: /* get host characteristics */ pvm_upkstr( groupname ); gs_host_all( groupname, hash_list, ngroups, &pcoordv, &nmem_onhostv, &nhosts, &gstate ); PK_IRESULT( nhosts, "gs_handle(hostchar)" ); pvm_pkint( nmem_onhostv, nhosts, 1 ); pvm_pkint( pcoordv, nhosts, 1 ); PK_STATE( tid, gstate, groupname, hash_list, ngroups, "gs_handle(hostchar)" ); SENDRESULT( tid, msgtag, "gs_handle(hostchar)" ); break; default: break; } /* Switch - statement */ } /* While - statement */ } ./pvm3/pvmgs/pvmgs_func.c0100644007401100000360000007472307111015724014562 0ustar kohlgopher static char rcsid[] = "$Id: pvmgs_func.c,v 1.9 2000/05/18 16:35:32 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ #include #include "pvm3.h" #include "pvmalloc.h" #include "pvmgsd.h" #include "bfunc.h" #include "global.h" #include "pvmmimd.h" /* for TIDISNODE, TIDONNODE macros */ #ifdef SYSVSTR #include #else #include #endif /* ================ gs_realloc_int_array ============================ */ /* reallocate an integer array if the nelems > maxelems. Copy the old array to the new array and initialize the remaining part of the new array to init. */ int * gs_realloc_int_array(nelems, maxelems, array, inc, init, caller) int nelems; int *maxelems; int *array; int inc; int init; char *caller; { int i; int *newarray, *newvalue; int oldmax; int *value; if (nelems <= *maxelems) return(array); newarray = array; oldmax = *maxelems; *maxelems += inc; if ( (newarray = (int *) PVM_ALLOC(sizeof(int) * (*maxelems), caller)) == (int *) NULL) { fprintf(stderr, "could not allocate memory: %s\n", caller); return(newarray); } /* copy the old array contents to the new array, initialize the */ /* new memory with the specified init value */ if (oldmax > 0) BCOPY(array, newarray, oldmax*sizeof(int)); newvalue = newarray+oldmax; for (i = oldmax; i < *maxelems; i++) *newvalue++ = init; if (array != (int *) NULL) /* initial array could be NULL */ PVM_FREE(array); return(newarray); } /* ================ gs_hash_init () ================================== */ /* Initialize the hash list data structure */ int gs_hash_init(hash_list) GROUP_LIST_PTR hash_list; { int g; for (g = 0; g < HASHSIZE; g++) { hash_list->prev = (GROUP_LIST_PTR) NULL; hash_list->next = (GROUP_LIST_PTR) NULL; hash_list->group = (GROUP_STRUCT_PTR) NULL; hash_list++; } return(PvmOk); } /* ================ gs_struct_init () ================================ */ /* Allocate and initialize a group structure */ /* Memory is allocated for the group name and the group name is copied */ /* into the structure. */ GROUP_STRUCT_PTR gs_struct_init(groupname) char *groupname; { GROUP_STRUCT_PTR rvalue; if ( (rvalue = (GROUP_STRUCT_PTR)PVM_ALLOC(sizeof(GROUP_STRUCT), GSNAME)) == (GROUP_STRUCT_PTR) NULL) return (rvalue); /* Out of resources */ if ( (rvalue->name = (char *) PVM_ALLOC(sizeof(char)*(strlen(groupname)+1), GSNAME)) == (char *) NULL) { PVM_FREE(rvalue); fprintf(stderr, "gs_struct_init(), couldn't allocate memory\n"); return (GROUP_STRUCT_PTR) NULL; } rvalue->len = strlen(groupname); strcpy(rvalue->name,groupname); rvalue->ntids = 0; rvalue->tids = (int *) NULL; rvalue->maxntids = 0; rvalue->barrier_count = -1; rvalue->barrier_reached = 0; rvalue->barrier_index = 0; rvalue->btids = (int *) NULL; rvalue->maxbtids = 0; rvalue->staticgroup = DYNAMIC; rvalue->sgroup_count = -1; rvalue->sgroup_reached = 0; rvalue->stids = (int *) NULL; rvalue->maxstids = 0; rvalue->ninfotids = 0; rvalue->infotids = (int *) NULL; rvalue->maxinfotids = 0; rvalue->nhosts = 0; rvalue->np_onhost = (int *) NULL; rvalue->pcoord = (int *) NULL; rvalue->maxhosts = 0; return rvalue; } /* ================ gs_struct_destroy () ============================= */ /* Destroy a group structure */ /* Memory is deallocated for tids, barrier tids, and infotids */ int gs_struct_destroy(group) GROUP_STRUCT_PTR group; { if (group != (GROUP_STRUCT_PTR) NULL ) { if ( group->name != (char *) NULL) PVM_FREE(group->name); if ( group->btids != (int *) NULL) PVM_FREE(group->btids); if ( group->tids != (int *) NULL) PVM_FREE(group->tids); if ( group->infotids != (int *) NULL) PVM_FREE(group->infotids); if ( group->stids != (int *) NULL) PVM_FREE(group->stids); if ( group->np_onhost != (int *) NULL) PVM_FREE(group->np_onhost); if ( group->pcoord != (int *) NULL) PVM_FREE(group->pcoord); PVM_FREE(group); } return (PvmOk); } /* ================ gs_hash_clear () ================================ */ /* Clear all group data held in the hash list */ int gs_hash_clear( hash_list, ngroups, size) GROUP_LIST_PTR hash_list; int *ngroups; int size; { int i; int j; GROUP_LIST_PTR current; GROUP_LIST_PTR prev; GROUP_LIST_PTR root; GROUP_STRUCT_PTR group; for (i=0; i < size; i++) /* go through entire list of groups */ { current = hash_list+i; root = current; current = current->next; root->next = (GROUP_LIST_PTR) NULL; /* sever the list */ while (current != (GROUP_LIST_PTR) NULL) { gs_struct_destroy(current->group); (*ngroups)--; prev = current; current = current->next; PVM_FREE(prev); } } return (*ngroups); } /* ================ gs_hash_name () =================================== */ /* Hash the group name to get the list entry for this group. */ /* optionally creates an element in the linked list */ GROUP_LIST_PTR gs_hash_name(name, hash_list, ngroups, create) char *name; GROUP_LIST_PTR hash_list; int *ngroups; int create; { char *key; int hash_index; int len = 0; int match; int relation; int sum = 0; GROUP_LIST_PTR current; GROUP_LIST_PTR listentry; GROUP_LIST_PTR prev; GROUP_STRUCT_PTR group; if (name == (char *) NULL || *name == '\0') return( (GROUP_LIST_PTR) NULL); /* Null group name error */ /* The following is the hash algorithm. */ key = name; while (*key != '\0') /* sum all the characters in the string */ { sum += INTERVAL(MINCHAR, *key, MAXCHAR); key++; len++; } hash_index = sum/len; hash_index = hash_index - MINCHAR; /* hash into the table and then do a linear search for the name */ /* if there is a collision */ /* names are kept in lexicographic order */ prev = hash_list + hash_index; current = prev->next; listentry = (GROUP_LIST_PTR) NULL; while (current != (GROUP_LIST_PTR) NULL ) { relation = strncmp(name, current->group->name, MAX(current->group->len,len)); if ( relation == 0 ) /* strings are exactly equal */ { listentry = current; break; /* found the group name */ } if (relation < 0) break; /* group name does not exist */ prev = current; /* go to next entry in linked list */ current = current->next; } if (create != CREATE || listentry != (GROUP_LIST_PTR) NULL) return listentry; /*return what we found, if anything */ /* we didn't find the group, but have been asked to create it */ if ( (group = gs_struct_init(name)) == (GROUP_STRUCT_PTR) NULL) return (GROUP_LIST_PTR) NULL; listentry = gs_list_insert(group, prev, current); if (listentry != (GROUP_LIST_PTR) NULL) (*ngroups)++; return(listentry); } /* ================ gs_list_insert () ================================= */ /* Insert the group structure into the hash list */ GROUP_LIST_PTR gs_list_insert(group, prev, current) GROUP_LIST_PTR prev; GROUP_LIST_PTR current; GROUP_STRUCT_PTR group; { GROUP_LIST_PTR newentry; GROUP_LIST_PTR vptr; /* The member is inserted after prev */ /* to simplify logic: the head of the least always contains */ /* null group info, and is never destroyed */ newentry = (GROUP_LIST_PTR) PVM_ALLOC(sizeof(GROUP_LIST), "gs_list_insert"); if (newentry == (GROUP_LIST_PTR) NULL) /* error allocing memory */ { fprintf(stderr, "gs_list_insert failed to alloc memory \n"); return (GROUP_LIST_PTR) NULL; } newentry->group = group; newentry->next = current; newentry->prev = prev; prev->next = newentry; /* prev will always be non-null */ if (current != (GROUP_LIST_PTR) NULL) current->prev = newentry; return (newentry); } /* ================ gs_group () ======================================= */ /* Return a pointer to a group structure, optionally create the group */ /* structure. */ GROUP_STRUCT_PTR gs_group(groupname, hash_list, ngroups, create) char *groupname; GROUP_LIST_PTR hash_list; int *ngroups; int create; { GROUP_LIST_PTR listentry; listentry = gs_hash_name(groupname, hash_list, ngroups, create); if (listentry != (GROUP_LIST_PTR) NULL) return( listentry->group ); else return (GROUP_STRUCT_PTR) NULL; } /* ================ gs_delete_group () ================================ */ /* Delete the group structure and free memory */ int gs_delete_group(groupname, hash_list, ngroups) char *groupname; GROUP_LIST_PTR hash_list; int *ngroups; { GROUP_LIST_PTR listentry; listentry = gs_hash_name(groupname, hash_list, ngroups, NOCREATE); if (listentry == (GROUP_LIST_PTR) NULL) return (PvmNoGroup); listentry->prev->next = listentry->next; if (listentry->next != (GROUP_LIST_PTR) NULL) listentry->next->prev = listentry->prev; gs_struct_destroy(listentry->group); PVM_FREE(listentry); (*ngroups)--; return (PvmOk); } /* ================ gs_join() ======================================= */ int gs_join(gname, tid, hash_list, ngroups) char *gname; int tid; GROUP_LIST_PTR hash_list; int *ngroups; { int hostindx; int inst; int thishost; GROUP_STRUCT_PTR group; /* check for valid group name */ if (gname == (char*) 0 || *gname == '\0') return(PvmNullGroup); if ( (group = gs_group(gname, hash_list, ngroups, CREATE)) == (GROUP_STRUCT_PTR) NULL) return(PvmNoGroup); if (group->staticgroup == STATIC || group->staticgroup == STATICDEAD ) return(PvmNotInGroup); /* can't join a (dead) static group */ /* first check to see if the tid is already in the tid list */ for (inst = 0; inst < group->maxntids; inst++) if (group->tids[inst] == tid) return(PvmDupGroup); /* not in the group; make sure there is room in the tid list to */ /* add the tid */ group->tids = gs_realloc_int_array(group->ntids + 1, &(group->maxntids), group->tids, DELTANTIDS, NOTID, "gs_join"); if (group->tids == (int *) NULL) return(PvmNoMem); /* find the lowest available open slot to insert this tid. */ /* call to gs_realloc_int_array guarantees there is room. */ for (inst = 0; inst < group->maxntids; inst ++) if (group->tids[inst] == NOTID) { group->ntids++; group->tids[inst] = tid; break; } /* update the #procs on a particular host */ thishost = gs_tidtohost(tid); hostindx = gs_binsearch(group->pcoord,group->nhosts,thishost, gs_tidtohost); if (hostindx < 0) hostindx = gs_newhost(group,hostindx); if (tid < group->pcoord[hostindx] || group->pcoord[hostindx] == NOTID) group->pcoord[hostindx] = tid; /*new coordinator */ group->np_onhost[hostindx] ++; if (inst < group->maxntids) return(inst); /* sanity check -- if here, something got screwed up */ fprintf(stderr, "gs_join: book keeping error, shouldn't happen\n"); fprintf(stderr, "\t tid %d, ntids %d maxntids %d\n", tid, group->ntids, group->maxntids); return(PvmMismatch); } /* ================ gs_leave() ====================================== */ /* remove the tid from the group, remove the group if there are no more tids left in the group */ int gs_leave(gname, tid, hash_list, ngroups) char *gname; int tid; GROUP_LIST_PTR hash_list; int *ngroups; { int gid; int hostindx; int itmp, i; int thishost; GROUP_STRUCT_PTR group; /* check for valid group name */ if (gname == (char*) 0 || *gname == '\0') return(PvmNullGroup); if ( (group = gs_group(gname, hash_list, ngroups, NOCREATE)) == (GROUP_STRUCT_PTR) NULL) return(PvmNoGroup); for (gid = 0; gid < group->maxntids; gid++) /* find the tid */ if(group->tids[gid] == tid) break; if (gid == group->maxntids) /* if the tid is not there */ return(PvmNotInGroup); group->tids[gid] = NOTID; /* delete it from the group */ group->ntids--; /* update the #procs on a particular host */ thishost = gs_tidtohost(tid); hostindx = gs_binsearch(group->pcoord,group->nhosts,thishost, gs_tidtohost); if (hostindx >= 0) { if (-- group->np_onhost[hostindx] == 0) gs_delhost(group,hostindx); else if (group->pcoord[hostindx] == tid) /* find new coordinator */ { group->pcoord[hostindx] = NOTID; for (i = 0; i < group->maxntids; i++) if (gs_tidtohost(group->tids[i]) == thishost) if (group->tids[i] < group->pcoord[hostindx] || group->pcoord[hostindx] == NOTID) group->pcoord[hostindx] = group->tids[i]; } } if (group->staticgroup == STATIC) /* mark group as dead */ { group->staticgroup = STATICDEAD; /* release any tids waiting on a barrier. */ pvm_initsend(PvmDataDefault); if (group->barrier_count > 0) { itmp = PvmNoGroup; /* send them an error */ pvm_pkint(&itmp, 1, 1); pvm_mcast(group->btids, group->barrier_count, BARRIER); group->barrier_count = PvmNoGroup; } } if( group->ntids <= 0) /* delete the group if count is zero */ gs_delete_group(gname, hash_list, ngroups); return(PvmOk); } /* ================ gs_register() =================================== */ /* register the name with pvm so other processes can get it */ /* return -1 if can't register, 0 otherwise */ int gs_register(name, tid) char *name; int tid; { int cc; int sbuf,ssbuf; ssbuf = pvm_setsbuf(0); sbuf = pvm_initsend(PvmDataDefault); pvm_pkint(&tid,1,1); if ( (cc = pvm_putinfo(name, sbuf, PvmMboxDefault)) != 0 ) { pvm_perror("Group Server already running?"); } pvm_setsbuf(ssbuf); pvm_freebuf(sbuf); return(cc); /* Will be PvmOK if register succeeded, < 0 otherwise */ } /* ================ gs_getinst() ==================================== */ /* returns the instance associated with (tid,gname) */ int gs_getinst(gname, tid, hash_list, ngroups, gstate) char *gname; int tid; GROUP_LIST_PTR hash_list; int *ngroups, *gstate; { int gid; GROUP_STRUCT_PTR group; *gstate = DYNAMIC; /* check for valid group name */ if (gname == (char*) 0 || *gname == '\0') return(PvmNullGroup); group = gs_group(gname, hash_list, ngroups, NOCREATE); if (group == (GROUP_STRUCT_PTR) NULL) return(PvmNoGroup); for (gid = 0; gid < group->maxntids; gid++) /* find the tid */ if(group->tids[gid] == tid) break; if (gid == group->maxntids) /* if the tid's not there */ return(PvmNotInGroup); if (group->staticgroup == STATIC) *gstate = STATIC; return(gid); } /* ================ gs_gettid() ===================================== */ /* returns the tid associated with (inst, gname) */ int gs_gettid(gname, inst, hash_list, ngroups, gstate) char *gname; int inst; GROUP_LIST_PTR hash_list; int *ngroups, *gstate; { int rtid; GROUP_STRUCT_PTR group; *gstate = DYNAMIC; /* check for valid group name */ if (gname == (char*) 0 || *gname == '\0') return(PvmNullGroup); group = gs_group(gname, hash_list, ngroups, NOCREATE); if (group == (GROUP_STRUCT_PTR) NULL) return(PvmNoGroup); if (inst < 0 || inst > group->maxntids) /* check for valid inst */ return(PvmNoInst); if (group->staticgroup == STATIC) *gstate = STATIC; rtid = group->tids[inst]; return( (rtid != NOTID ? rtid : PvmNoInst) ); } /* ================ gs_gsize() ======================================= */ /* returns the size of gname */ int gs_gsize(gname, hash_list, ngroups, gstate) char *gname; GROUP_LIST_PTR hash_list; int *ngroups, *gstate; { GROUP_STRUCT_PTR group; *gstate = DYNAMIC; /* check for valid group name */ if (gname == (char*) 0 || *gname == '\0') return(PvmNullGroup); group = gs_group(gname, hash_list, ngroups, NOCREATE); if (group == (GROUP_STRUCT_PTR) NULL) return(PvmNoGroup); if (group->staticgroup == STATIC) *gstate = STATIC; /* return the group size */ return(group->ntids); } /* ================ gs_tidlist() ==================================== */ /* returns the list of tids in the group */ int gs_tidlist(gname, holes_not_allowed, hash_list, ngroups, gstate) char *gname; int holes_not_allowed; GROUP_LIST_PTR hash_list; int *ngroups, *gstate; { int i; int cnt; int gi; int hole_exists = 0; int ntids; int *tids; GROUP_STRUCT_PTR group; *gstate = DYNAMIC; /* check for valid group name */ if (gname == (char*) 0 || *gname == '\0') return(PvmNullGroup); group = gs_group(gname, hash_list, ngroups, NOCREATE); if (group == (GROUP_STRUCT_PTR) NULL) return(PvmNoGroup); if (group->staticgroup == STATICDEAD) /* no collectives allowed on */ return(PvmNoGroup); /* a dead static group */ ntids = group->ntids; if ( (tids = (int *) PVM_ALLOC(group->ntids * sizeof(int), "gs_tidlist()")) == (int *) NULL ) return (PvmNoMem); for (i = 0, cnt = 0; i < group->maxntids; i++) { if (group->tids[i] != -1) tids[cnt++] = group->tids[i]; else if (i < ntids) hole_exists = 1; if (cnt > ntids) break; /* don't want to overwrite mem */ } if (cnt != ntids) { fprintf(stderr, "gs_tidlist: cnt (%d) != ntids (%d) \n", cnt, group->ntids); return(PvmSysErr); } if (holes_not_allowed && hole_exists) /* detected missing inst #s */ return(PvmNoInst); /* scatter and gather require no holes */ pvm_initsend(PvmDataDefault); /* pack 'em up */ pvm_pkint(&ntids, 1, 1); pvm_pkint(tids, cnt, 1); PVM_FREE(tids); if (group->staticgroup == STATIC) *gstate = STATIC; return (PvmOk); } /* ================ gs_barrier() ==================================== */ /* process a barrier request or a static group formation request */ int gs_barrier(gname, msgtag, cnt, tid, hash_list, ngroups) char *gname; int msgtag; int cnt; int tid; GROUP_LIST_PTR hash_list; int *ngroups; { int i, info; int gstate; int pcoord; int nhosts, nmem_onhost; GROUP_STRUCT_PTR group; /* check for valid group name */ if (gname == (char*) 0 || *gname == '\0') return(PvmNullGroup); group = gs_group(gname, hash_list, ngroups, NOCREATE); if (group == (GROUP_STRUCT_PTR) NULL) return(PvmNoGroup); if (group->staticgroup == STATICDEAD) return(PvmNoGroup); for (i = 0; i < group->maxntids; i++) /* tid is in group? */ if (group->tids[i] == tid) break; if (i == group->maxntids) return(PvmNotInGroup); /* if it's the whole group the set the count to the # in the group */ if (cnt == -1) cnt = group->ntids; if (group->barrier_count == -1) /* is it a new barrier ? */ { group->barrier_count = cnt; group->barrier_reached = 0; group->barrier_index = 0; } else { if (cnt != group->barrier_count) /* make sure counts match */ return(PvmMismatch); } /* store the tid */ group->btids = gs_realloc_int_array(group->barrier_index + 1, &(group->maxbtids), group->btids, DELTABTIDS, NOTID, "gs_barrier"); group->btids[group->barrier_index++] = tid; if (msgtag == BARRIER) group->barrier_reached++; else /* (msgtag == BARRIERV) */ /* an on-host coordinator is representing nmem_onhost tasks in this barrier call */ { gs_host_char(gname, hash_list, ngroups, gs_tidtohost(tid), &pcoord, &nmem_onhost, &nhosts, &gstate); group->barrier_reached += nmem_onhost; } /* if reached is bigger than count then there is a problem */ /* this would happen if count was zero */ if (group->barrier_count < group->barrier_reached) return(PvmMismatch); /* if we're not at the barrier then return */ if (group->barrier_count != group->barrier_reached) return(PvmOk); /* let everyone continue, send them the count */ pvm_initsend(PvmDataDefault); pvm_pkint(&(group->barrier_count), 1, 1); pvm_mcast(group->btids, group->barrier_index, BARRIER); group->barrier_count = -1; /* reset the barrier */ return(PvmOk); } /* ================ gs_static() ==================================== */ /* Forms a static group based upon the tid list and size */ int gs_static(gname, size, tid, hash_list, ngroups) char *gname; int size; int tid; GROUP_LIST_PTR hash_list; int *ngroups; { int i, info; GROUP_STRUCT_PTR group; /* check for valid group name */ if (gname == (char*) 0 || *gname == '\0') return(PvmNullGroup); group = gs_group(gname, hash_list, ngroups, NOCREATE); if (group == (GROUP_STRUCT_PTR) NULL) return(PvmNoGroup); if (group->staticgroup == STATIC) return(PvmDupGroup); for (i = 0; i < group->maxntids; i++) /* tid is in group? */ if (group->tids[i] == tid) break; if (i == group->maxntids) return(PvmNotInGroup); /* if it's the whole group then set the size to the # in the group */ if (size == -1) size = group->ntids; if (group->sgroup_count == -1) /* first to form the static group */ { group->sgroup_count = size; group->sgroup_reached = 0; } else { if (size != group->sgroup_count) /* make sure counts match */ return(PvmMismatch); } /* store the tid */ group->stids = gs_realloc_int_array(group->sgroup_reached + 1, &(group->maxstids), group->stids, DELTABTIDS, NOTID, "gs_static"); group->stids[group->sgroup_reached++] = tid; /* if reached is bigger than count then there is a problem */ /* this would happen if count was zero */ if (group->sgroup_count < group->sgroup_reached) return(PvmMismatch); /* if we've not completed with every tid calling then return */ if (group->sgroup_count != group->sgroup_reached) return(PvmOk); /* let everyone continue, send them the count */ group->staticgroup = STATIC; for (i=0; i < group->sgroup_count; i++) gs_newstaticcache(group->stids[i],gname, hash_list, ngroups, "gs_static"); /* record that tid has data */ pvm_initsend(PvmDataDefault); pvm_pkint(&(group->sgroup_count), 1, 1); pvm_pkint(&(group->staticgroup),1,1); gs_pkstaticinfo(group); /* pack up the information */ pvm_mcast(group->stids, group->sgroup_count, STATICGROUP); PVM_FREE(group->stids); group->stids = (int *) NULL; return(PvmOk); } /* ================ gs_pkstaticinfo() ============================= */ int gs_pkstaticinfo(group) GROUP_STRUCT_PTR group; { pvm_pkint(&(group->len),1,1); pvm_pkstr(group->name); pvm_pkint(&(group->ntids),1,1); pvm_pkint(&(group->maxntids),1,1); pvm_pkint(group->tids,group->maxntids,1); pvm_pkint(&(group->nhosts),1,1); pvm_pkint(group->np_onhost,group->nhosts,1); return(pvm_pkint(group->pcoord, group->nhosts,1)); } /* ================ gs_newstaticcache() ============================ */ int gs_newstaticcache(tid, groupname, hash_list, ngroups, caller) int tid; char *groupname; GROUP_LIST_PTR hash_list; int *ngroups; char *caller; { GROUP_STRUCT_PTR group; int i; group = gs_group(groupname, hash_list, ngroups, NOCREATE); if (group == (GROUP_STRUCT_PTR) NULL) return (0); group->infotids = gs_realloc_int_array( group->ninfotids + 1, &(group->maxinfotids), group->infotids, DELTANTIDS, NOTID, caller ); if (group->infotids != (int *) NULL) { for (i=0; i < group->ninfotids; i++) if (group->infotids[i] == tid) break; if (i == group->ninfotids) /* haven't sent info to this tid */ { group->infotids[group->ninfotids] = tid; group->ninfotids++; } return (PvmgsNotCached); } return(PvmOk); } /* ================ gs_tidtohost() ============================ */ /* int hosttid = gs_tidtohost(int tid) * returns tid of host with following qualifications * node tasks on mimd machines are considered to be on different * hosts that hosts programs. This is because the PGON internal * collective ops don't work across service and compute partitions. */ int gs_tidtohost(tid) int tid; { int hostid; hostid = pvm_tidtohost(tid); if (TIDISNODE(tid)) hostid = hostid | TIDONNODE; return (hostid); } /* ================ gs_binsearch() ============================ */ /* int index = gs_binsearch(array, nitems, target, mapfunc) * int *array; integer array to search; * int nitems; how many items in the array * int target; value searching for; * int (*mapfunc)(); func to map array value before compare * * returns * index >= 0 if found * -n -(index+1) where target should reside */ int gs_binsearch(array,nitems,target,mapfunc) int *array; int nitems; int target; int (*mapfunc)(); { int gs_retint(); int maxidx, maxval, mididx, midval, minidx, minval; int tmpidx; if (nitems < 1) return (-1); /* make sure there is at least 1 */ minidx = 0; maxidx = nitems-1; if (!mapfunc) mapfunc = gs_retint; if ( target < (minval = (*mapfunc)(*(array+minidx))) ) return -1; if ( target > (maxval = (*mapfunc)(*(array+maxidx))) ) return -(nitems+1); mididx = minidx; midval = minval; if (midval == target) return(mididx); /* single element */ { while (minidx != maxidx) { if (midval == target) return(mididx); if (maxval == target) return(maxidx); if ((tmpidx = (minidx + maxidx)/2) != mididx) mididx = tmpidx; else return (-(mididx + 2)); midval = (*mapfunc)(*(array + mididx)); if (midval > target) { maxidx = mididx; maxval = midval; } else { minidx = mididx; minval = midval; } } } return -1; /* not reached */ } /* ================ gs_retint() ============================ */ /* return its integer argument, used by gs_binsearch when mapfunc is null */ int gs_retint(arg) int arg; { return(arg); } /* ================ gs_newhost() ============================ */ /* insert new host information in the group structure * index used is the one returned by gs_binsearch */ int gs_newhost(group,index) GROUP_STRUCT_PTR group; int index; { int i; int oldmaxhosts; if (index >= 0) return(index); oldmaxhosts = group->maxhosts; group->np_onhost = gs_realloc_int_array(group->nhosts + 1, &(group->maxhosts), group->np_onhost, DELTANTIDS, 0, "gs_newhost"); group->maxhosts = oldmaxhosts; group->pcoord = gs_realloc_int_array(group->nhosts + 1, &(group->maxhosts), group->pcoord, DELTANTIDS, NOTID, "gs_newhost"); index = (-1 - index); /* where new info should be stored */ for (i = group->nhosts; i > index; i --) { group->pcoord[i] = group->pcoord[i-1]; group->np_onhost[i] = group->np_onhost[i-1]; } group->pcoord[i] = NOTID; group->np_onhost[i] = 0; group->nhosts++; return(index); /* return where this host info can be found */ } /* ================ gs_delhost() ============================ */ /* delete host information from group structure * index used is the one returned by gs_binsearch */ int gs_delhost(group,index) GROUP_STRUCT_PTR group; int index; { int i; if (index < 0 ) return (0); for (i = index; i < group->nhosts -1; i++) { group->np_onhost[i] = group->np_onhost[i+1]; group->pcoord[i] = group->pcoord[i+1]; } group->nhosts--; return(0); } /* ================ gs_host_char() ============================ */ /* Characterize a host with the number of procs and the local coordinator * of group functions */ int gs_host_char(gname, hash_list, ngroups, hosttid, pcoord, nmem_onhost, nhosts, gstate) char *gname; GROUP_LIST_PTR hash_list; int *ngroups; int hosttid; int *pcoord; int *nmem_onhost; int *nhosts; int *gstate; { int hostindx; GROUP_STRUCT_PTR group; *nmem_onhost = 0; *nhosts = 0; *gstate = DYNAMIC; *pcoord = NOTID; /* check for valid group name */ if (gname == (char*) 0 || *gname == '\0') return(PvmNullGroup); group = gs_group(gname, hash_list, ngroups, NOCREATE); if (group == (GROUP_STRUCT_PTR) NULL) return(PvmNoGroup); hostindx = gs_binsearch(group->pcoord,group->nhosts,hosttid, gs_tidtohost); if (hostindx < 0) return(PvmNoGroup); *nmem_onhost = group->np_onhost[hostindx]; *pcoord = group->pcoord[hostindx]; *nhosts = group->nhosts; *gstate = group->staticgroup; return(PvmOk); } /* ================ gs_host_all() ============================ */ /* vectors of information about all hosts in a group */ int gs_host_all(gname, hash_list, ngroups, pcoordv, nmem_onhostv, nhosts, gstate) char *gname; GROUP_LIST_PTR hash_list; int *ngroups; int **pcoordv; int **nmem_onhostv; int *nhosts; int *gstate; { int hostindx; GROUP_STRUCT_PTR group; *nmem_onhostv = (int *) NULL; *nhosts = 0; *gstate = DYNAMIC; *pcoordv = (int *) NULL; /* check for valid group name */ if (gname == (char*) 0 || *gname == '\0') return(PvmNullGroup); group = gs_group(gname, hash_list, ngroups, NOCREATE); if (group == (GROUP_STRUCT_PTR) NULL) return(PvmNoGroup); *nmem_onhostv = group->np_onhost; *pcoordv = group->pcoord; *nhosts = group->nhosts; *gstate = group->staticgroup; return(PvmOk); } ./pvm3/pvmgs/pvm_gstat.c0100644007401100000360000000753507401766407014431 0ustar kohlgopher static char rcsid[] = "$Id: pvm_gstat.c,v 1.8 2001/11/30 20:33:11 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* pvm_gstat - print the status of all groups held */ #include #include "pvm3.h" #include "pvmalloc.h" #include "pvmgsd.h" #include "pvmproto.h" #define NEWMEM(p,n,t) \ if (p != (t *) NULL) \ PVM_FREE(p); \ p = (t *) PVM_ALLOC(n * sizeof(t) ,"pvm_gstat") extern struct timeval *pvmgs_tmout; /* from libgpvm */ int main(argc, argv) int argc; char *argv[]; { int gstid; int i, j, ng; GROUP_STRUCT group; group.len = 0; group.name = (char *) NULL; group.tids = (int *) NULL; group.btids = (int *) NULL; pvm_mytid(); if((gstid = gs_getgstid()) < 0) { fprintf(stderr, "%s: no groups server\n", argv[0]); return(-1); } pvm_setcontext( SYSCTX_DG ); pvm_initsend(PvmDataDefault); pvm_send(gstid, GSLS); if ( pvm_trecv(gstid, GSLS, pvmgs_tmout) <= 0) { fprintf(stderr, "Error receiving message from group server\n"); exit (-1); } /* Unpack the information for each group */ pvm_upkint(&ng, 1, 1); if (ng == 0) fprintf(stdout, "no groups exist\n"); for (i = 0; i < ng; i++) { pvm_upkint(&(group.len),1,1); NEWMEM(group.name, group.len+1,char); pvm_upkstr(group.name); pvm_upkint(&(group.ntids), 1, 1); pvm_upkint(&(group.maxntids), 1,1); pvm_upkint(&(group.barrier_count), 1, 1); pvm_upkint(&(group.barrier_reached),1,1); NEWMEM(group.tids, group.maxntids, int); NEWMEM(group.btids, group.barrier_reached, int); pvm_upkint(group.tids, group.maxntids, 1); if (group.barrier_reached > 0) pvm_upkint(group.btids, group.barrier_reached, 1); fprintf(stdout, "group: %s, size: %d, barrier_count %d, barrier_reached %d\n", group.name, group.ntids, group.barrier_count, group.barrier_reached); fputs("tids:\n", stdout); for (j = 0; j < group.maxntids; j++) if (group.tids[j] > 0) fprintf(stdout, "%d 0x%x\t", j, group.tids[j]); fputs("\n", stdout); if (group.barrier_reached > 0) { fputs("tids waiting on barrier:\n", stdout); for (j = 0; j < group.barrier_reached; j++) fprintf(stdout, "0x%x\t", group.btids[j]); fputs("\n", stdout); } } pvm_exit(); } ./pvm3/pvmgs/pvmgsu_aux.c0100644007401100000360000010222506423660242014604 0ustar kohlgopher static char rcsid[] = "$Id: pvmgsu_aux.c,v 1.9 1997/10/23 14:35:14 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmgsu_aux.c - auxiliary group library routines, gather and scatter * 6 Jun 1995 Native mode reduce for Paragon. Donato * 8 Mar 1994 Added reduce & assoc routines. Donato & P.Papadopoulos * 24 Apr 1994 Added scatter, gather, gs_get_datasize routines. Donato * */ #ifdef HASSTDLIB #include #endif #include #include #include "pvmalloc.h" #include "bfunc.h" #include "lpvm.h" #include #include "tevmac.h" #include "global.h" #include "pvmmimd.h" #include "pvmgsd.h" #include "pvmproto.h" extern int pvm_errno; extern int pvmmytid; extern int pvmtoplvl; extern struct Pvmtracer pvmtrc; /* ========== ================ * ========== Declarations & Routines for the Paragon ================ * ========== ================ * Note: int and long are the same on the paragon */ #if defined(IMA_PGON) extern int pvmpgonpartsize; /* from lpvmmimd.c */ /* ================ NativeFunction() for the PGON ==================== */ /* This routine compares the address of the user provided function to the built-in pvm functions to determine and then call the appropriate native mode function on the Paragon. */ int NativeFunction(user_func, datatype, x, y, num) #ifdef IMA_SCO void (*user_func)(int*, void*, void*, int*, int*); #else void (*user_func)(); #endif void *x, *y; int datatype, num; { if (user_func==PvmSum) { switch(datatype) { case (PVM_INT): case (PVM_LONG): _gisum((int *) x, num, (int *) y); break; case (PVM_FLOAT): _gssum((float *) x, num, (float *) y); break; case (PVM_DOUBLE): _gdsum((double *) x, num, (double *) y); break; default: return(PvmNotImpl); } /* end switch */ } else if (user_func==PvmMax) { switch(datatype) { case (PVM_INT): case (PVM_LONG): _gihigh((int *) x, num, (int *) y); break; case (PVM_FLOAT): _gshigh((float *) x, num, (float *) y); break; case (PVM_DOUBLE): _gdhigh((double *) x, num, (double *) y); break; default: return(PvmNotImpl); } /* end switch */ } else if (user_func==PvmMin) { switch(datatype) { case (PVM_INT): case (PVM_LONG): _gilow((int *) x, num, (int *) y); break; case (PVM_FLOAT): _gslow((float *) x, num, (float *) y); break; case (PVM_DOUBLE): _gdlow((double *) x, num, (double *) y); break; default: return(PvmNotImpl); } /* end switch */ } else if (user_func==PvmProduct) { switch(datatype) { case (PVM_INT): case (PVM_LONG): _giprod((int *) x, num, (int *) y); break; case (PVM_FLOAT): _gsprod((float *) x, num, (float *) y); break; case (PVM_DOUBLE): _gdprod((double *) x, num, (double *) y); break; default: return(PvmNotImpl); } /* end switch */ } else return(PvmNotImpl); return(PvmOk); } /* end NativeFunction() */ #endif /* #ifdef PGON */ /* ================ pvm_reduce() ===================================== */ /* int info = pvm_reduce(void (*func)(), void *data, int count, int datatype, int msgtag, char *gname, int rootinst) where void (*func)(int *datatype, void *data, void *work, int *num, int *info) Currently, this implementation uses a fan in algorithm to perform the reduce operation. Each group member sends their data to the coordinator on their host machine. The coordinator performs the specified function combining its own data and the data from the group members on the same host. On the Paragon the nx native global operations are utilized if all the nodes of the Paragon are part of the group. The coordinators then pass their results on to the specified root node of the reduce operation. */ int pvm_reduce(func, data, count, datatype, msgtag, gname, rootinst) #ifdef IMA_SCO void (*func)(int*, void*, void*, int*, int*); #else void (*func)(); #endif void *data; int count, datatype, msgtag, rootinst; char *gname; { int cnt, roottid, datasize, cc=PvmOk, rbuf, sbuf; int coordinator, nmembers_on_host, nhosts_in_group, mask=0; void *work = NULL; /* work array to be allocated */ int (*packfunc)(), (*unpackfunc)(); int x; int savectx; TEV_DECLS BGN_TRACE( TEV_REDUCE, gname, TEV_DID_MC, &msgtag ); rbuf = pvm_setrbuf(0); /* set receive buf */ sbuf = pvm_mkbuf(PvmDataDefault); sbuf = pvm_setsbuf(sbuf); /* set context for dynamic groups */ savectx = pvm_setcontext( SYSCTX_DG ); if ( (data == NULL) || (count <= 0) ) /* check some parameters */ { cc = PvmBadParam; goto done; } /* get instance number - caller must be in group, root must be in group */ if ( (cc = pvm_getinst(gname, pvmmytid)) < PvmOk ) goto done; if ( (cc = roottid = pvm_gettid (gname, rootinst)) < PvmOk ) goto done; if ( (cc = datasize = gs_get_datasize(datatype)) < PvmOk ) goto done; /* set up pointers to the appropriate pack and unpack routines */ if ( (cc = gs_pack_unpack(datatype, &packfunc, &unpackfunc) ) < PvmOk) goto done; if ((work = (void *) PVM_ALLOC(count*datasize, "pvm_reduce")) == NULL) { cc = PvmNoMem; goto done; } pvm_grphostinfo(gname, gs_tidtohost(pvmmytid), &coordinator, &nmembers_on_host, &nhosts_in_group); #if defined(IMA_PGON) /* if all the nodes are participating, then call the Native mode version, if one exists. The native function call is a side-effect of the call to NativeFunction. If the coordinator and roottid are PGON nodes, there is no need to differentiate (e.g. pass data from coordinator to roottid). */ mask = TIDHOST | TIDPTYPE; if ( TIDISNODE(pvmmytid) && ( pvmpgonpartsize == nmembers_on_host ) && ( (cc = NativeFunction(func, datatype, data, work, count)) == PvmOk) ) { if ( TIDISNODE(roottid) && (pvmmytid & mask) == (roottid & mask) ) coordinator = roottid; } else #endif /* end if defined(IMA_PGON) */ { if ( (pvmmytid==coordinator) && (nmembers_on_host>1) ) { /* recv data from other group members on same host, perform func */ for (cnt = nmembers_on_host-1; cnt>0; cnt--) { if ( (cc = pvm_recv(-1, msgtag) ) < PvmOk) goto done; if ( (cc = (*unpackfunc)( work, count, 1)) < PvmOk) goto done; (*func)( &datatype, data, work, &count, &cc ); if (cc < PvmOk) goto done; /* error flag from func */ } } else if (pvmmytid != coordinator) { /* send data to the data coordinator on this same host */ pvm_initsend(PvmDataDefault); if ( (cc = (*packfunc)( data, count, 1) ) < PvmOk ) goto done; if ( (cc = pvm_send( coordinator, msgtag)) < PvmOk ) goto done;; } } if ( (pvmmytid==coordinator) && (pvmmytid != roottid) ) { /* send data to the roottid for the reduce operation */ pvm_initsend(PvmDataDefault); if ( (cc = (*packfunc)( data, count, 1) ) < PvmOk ) goto done; if ( (cc = pvm_send( roottid, msgtag)) < PvmOk ) goto done; } /* Root node of the reduce operation: - get data from my host coordinator, if necessary - get work values from each of the other hosts - perform the specified functions on data from other hosts */ if (pvmmytid == roottid) { /* if root isn't the host coordinator, receive from coordinator 1st */ if (pvmmytid != coordinator) { if ( (cc = pvm_recv(coordinator, msgtag) ) < PvmOk) goto done; if ( (cc = (*unpackfunc)( data, count, 1)) < PvmOk) goto done; } if (nhosts_in_group-- <= 0) goto done; /* recv data from other group members on diff host, perform func */ for (cnt = nhosts_in_group; cnt>0; cnt--) { if ( (cc = pvm_recv(-1, msgtag) ) < PvmOk) goto done; if ( (cc = (*unpackfunc)( work, count, 1)) < PvmOk) goto done; (*func)( &datatype, data, work, &count, &cc ); if (cc < PvmOk) goto done; /* error flag from func */ } /* end for */ } cc = PvmOk; done: /* restore user's buffers */ pvm_freebuf(pvm_setrbuf(rbuf)); pvm_freebuf(pvm_setsbuf(sbuf)); /* restore user context */ pvm_setcontext( savectx ); if (work != NULL) PVM_FREE(work); /* free work space */ if (cc < 0) lpvmerr("pvm_reduce",cc); END_TRACE( TEV_REDUCE, TEV_DID_CC, &cc ); return(cc); } /* end pvm_reduce() */ /* ================ gs_pack_unpack()================================== */ /* int info = gs_pack_unpack( int datatype, int (**packfunc)(), int (**unpackfunc)() ) Sets up pointers to the appropriate pack and unpack function based on datatype specified. */ int gs_pack_unpack(datatype, packfunc, unpackfunc) int datatype, (**packfunc)(), (**unpackfunc)(); { switch(datatype) { case (PVM_STR): *packfunc = pvm_pkstr; *unpackfunc = pvm_upkstr; break; case (PVM_BYTE): *packfunc = pvm_pkbyte; *unpackfunc = pvm_upkbyte; break; case (PVM_SHORT): *packfunc = pvm_pkshort; *unpackfunc = pvm_upkshort; break; case (PVM_INT): *packfunc = pvm_pkint; *unpackfunc = pvm_upkint; break; case (PVM_LONG): *packfunc = pvm_pklong; *unpackfunc = pvm_upklong; break; case (PVM_FLOAT): *packfunc = pvm_pkfloat; *unpackfunc = pvm_upkfloat; break; case (PVM_DOUBLE): *packfunc = pvm_pkdouble; *unpackfunc = pvm_upkdouble; break; case (PVM_CPLX): *packfunc = pvm_pkcplx; *unpackfunc = pvm_upkcplx; break; case (PVM_DCPLX): *packfunc = pvm_pkdcplx; *unpackfunc = pvm_upkdcplx; break; default: return(PvmBadParam); } return(PvmOk); } /* ================ PvmMax()========================================== */ /* void PvmMax(int *datatype, void *x, void *y, int *num, int *info) Assigns the elements of x the maximum value between the corresponding elements of x and y. For complex values the maximum is determined by maximum modulus. */ void PvmMax(datatype, x, y, num, info) int *datatype; void *x, *y; int *num, *info; { char *xchar, *ychar; int *xint, *yint; short *xshort, *yshort; long *xlong, *ylong; float *xfloat, *yfloat; double *xdouble, *ydouble; float xfreal, xfimag, yfreal, yfimag; double xdreal, xdimag, ydreal, ydimag; float xsqrfloat, ysqrfloat; double xsqrdouble, ysqrdouble; int i, count; count = *num; switch(*datatype) { case (PVM_BYTE): xchar = (char *) x; ychar = (char *) y; for (i=0; i xsqrfloat) { xfloat[i] = yfreal; xfloat[i+1] = yfimag; } } break; case (PVM_DCPLX): /* double complex - complex*16 in fortran - treated as 2 doubles */ /* returns the complex pair with the greatest magnitude */ xdouble = (double *) x; ydouble = (double *) y; for (i=0; i<2*count; i+=2) { xdreal = xdouble[i]; xdimag = xdouble[i+1]; ydreal = ydouble[i]; ydimag = ydouble[i+1]; xsqrdouble = xdreal*xdreal + xdimag*xdimag; ysqrdouble = ydreal*ydreal + ydimag*ydimag; if (ysqrdouble > xsqrdouble) { xdouble[i] = ydreal; xdouble[i+1] = ydimag; } } break; default: *info = PvmBadParam; return; } /* end switch */ *info = PvmOk; return; } /* end of PvmMax() */ /* ================ PvmMin()========================================== */ /* void PvmMin(int *datatype, void *x, void *y, int *num, int *info) Assigns the elements of x the minimum value between the corresponding elements of x and y. For complex values the minimum is determined by minimum modulus. */ void PvmMin(datatype, x, y, num, info) int *datatype; void *x, *y; int *num, *info; { char *xchar, *ychar; short *xshort, *yshort; int *xint, *yint; long *xlong, *ylong; float *xfloat, *yfloat; double *xdouble, *ydouble; float xfreal, xfimag, yfreal, yfimag; double xdreal, xdimag, ydreal, ydimag; float xsqrfloat, ysqrfloat; double xsqrdouble, ysqrdouble; int i, count; count = *num; switch(*datatype) { case (PVM_BYTE): xchar = (char *) x; ychar = (char *) y; for (i=0; i #endif #include #include #include "pvmalloc.h" #include "bfunc.h" #include "lpvm.h" #include #include "tevmac.h" #include "pvmgsd.h" #include "pvmproto.h" #if defined(IMA_PGON) #include #endif int gstid = -1; static int myoldtid = -1; extern int pvm_errno; extern int pvmmytid; extern int pvmtoplvl; extern struct Pvmtracer pvmtrc; /* Declarations for static group information */ static GROUP_LIST sgroup_list[HASHSIZE]; static int ngroups = -1; /* Set PVM Group Server Timeout (if any), In Seconds */ #ifndef PVMGSTIMEOUT struct timeval *pvmgs_tmout = (struct timeval *) NULL; #else struct timeval pvmgs_tmout_struct = { PVMGSTIMEOUT, 0 }; struct timeval *pvmgs_tmout = &pvmgs_tmout_struct; #endif /* ================ gs_getgstid() ==================================== */ /* int info = getgstid() */ /* gs_getgstid returns the tid of the group server, starts the server */ /* if it is not running */ int gs_getgstid() { int info; int mytid; int otid; int rbuf; int srbuf; int ttid; mytid = pvm_mytid(); if (gstid >= 0 && mytid == myoldtid) return (gstid); srbuf = pvm_setrbuf(0); if ( pvm_recvinfo(GSNAME, 0, PvmMboxDefault) == PvmNotFound ) { /* Don't trace output from the spawned group server */ otid = pvm_setopt(PvmOutputTid, 0); ttid = pvm_setopt(PvmTraceTid, 0); info = pvm_spawn("pvmgs", (char **)0, PvmMppFront, (char *)0, 1, &gstid); pvm_setopt(PvmOutputTid, otid); pvm_setopt(PvmTraceTid, ttid); if (info != 1) { if (info == 0 && gstid < 0) { pvm_errno = gstid; pvm_perror("gs_getgstid() failed to start group server"); } return pvm_errno; } while( pvm_recvinfo(GSNAME, 0, PvmMboxDefault) == PvmNotFound ) /* wait for it to register */ ; } /* unpack the group server tid */ pvm_upkint(&gstid,1,1); pvm_setrbuf(srbuf); /* initialize storage for static group information */ if (myoldtid == -1) { ngroups = 0; gs_hash_init(sgroup_list); } else gs_hash_clear(sgroup_list, &ngroups, HASHSIZE); myoldtid = mytid; return(gstid); } /* ================ pvm_joingroup()=================================== */ /* int inum = pvm_joingroup(char* group) Adds the calling tid to the named group and returns its instance number. Always adds the task in the first available slot such that if one task leaves a group and another later joins, then the later task will get the instance number freed by the earlier task. This allows users to keep a contiguous block of instance numbers [0,p-1]. */ int pvm_joingroup(group) char *group; { int gid; int x; TEV_DECLS; BGN_TRACE( TEV_JOINGROUP, group, 0, (int *) NULL ); int_query_server(group, JOIN, "pvm_joingroup", &gid, 0); END_TRACE( TEV_JOINGROUP, TEV_DID_CC, &gid ); if (gid < 0) pvm_errno = gid; return gid; } /* ================ pvm_lvgroup()=================================== */ /* int info = pvm_lvgroup(char* group) Removes the calling tid from the named group. Returns only after getting confirmation from server. This allows users to coordinate leaving and joining. */ int pvm_lvgroup(group) char *group; { int rc; int x; GROUP_STRUCT_PTR sgroup; TEV_DECLS; BGN_TRACE( TEV_LVGROUP, group, 0, (int *) NULL ); /* delete any statically held group information */ gs_delete_group(group, sgroup_list, &ngroups); int_query_server(group, LEAVE, "pvm_lvgroup", &rc, 0); END_TRACE( TEV_LVGROUP, TEV_DID_CC, &rc ); if (rc < 0) pvm_errno = rc; return(rc); } /* ================ pvm_getinst() ==================================== */ /* int inum = pvm_getinst(char* group, int tid) Returns the instance number of the specified tid in the named group. Can be called by any task. */ int pvm_getinst(group, tid) char *group; int tid; { int foo; int inst; int x; TEV_DECLS; BGN_TRACE( TEV_GETINST, group, TEV_DID_GT, &tid ); inst = gs_getinst(group, tid, sgroup_list, &ngroups, &foo); if (inst < 0) /* didn't find the info in local memory */ int_query_server(group, GETINST, "pvm_getinst", &inst, tid); END_TRACE( TEV_GETINST, TEV_DID_GI, &inst ); if (inst < 0) pvm_errno = inst; return(inst); } /* ================ pvm_gettid() ===================================== */ /* int tid = pvm_gettid(char * group, int inum) Returns the tid of the task defined by the group/inum pair. Can be called by any task. */ int pvm_gettid(group, inst) char *group; int inst; { int foo; int tid; int x; TEV_DECLS; BGN_TRACE( TEV_GETTID, group, TEV_DID_GI, &inst ); tid = gs_gettid(group, inst, sgroup_list, &ngroups, &foo); if (tid < 0) /* didn't find the info in local memory */ int_query_server(group, GETTID, "pvm_gettid", &tid, inst); END_TRACE( TEV_GETTID, TEV_DID_GT, &tid ); if (tid < 0) pvm_errno = tid; return(tid); } /* ================ pvm_gsize() ====================================== */ /* int gsize = pvm_gsize(char* group) Returns the present size of the named group. */ int pvm_gsize(group) char *group; { int foo; int size; int x; TEV_DECLS; BGN_TRACE( TEV_GSIZE, group, 0, (int *) NULL ); size= gs_gsize(group, sgroup_list, &ngroups, &foo); if (size < 0) /* didn't find the info in local memory */ int_query_server(group, GSIZE, "pvm_gsize", &size, 0); END_TRACE( TEV_GSIZE, TEV_DID_GS, &size ); if (size < 0) pvm_errno = size; return(size); } /* ================ pvm_bcast() ===================================== */ /* int info = pvm_bcast(char* group, int msgtag) Broadcast message to all members presently in the named group (excluding yourself if you are in the group). Calling tid need not be in the group. */ int pvm_bcast(group, msgtag) char *group; int msgtag; { int bailout=0; int cc; int i; int mytid; int ntids; int rbuf; int sbuf; int *tids = (int *) NULL; int x; TEV_DECLS; BGN_TRACE( TEV_BCAST, group, TEV_DID_MC, &msgtag ); if ((cc = gs_get_tidlist(group, msgtag, &ntids, &tids, 0)) < 0) bailout = 1; if ((mytid = pvm_mytid()) < 0 && ! bailout) { pvm_perror("pvm_bcast"); cc = PvmSysErr; bailout = 1; } /* if I'm the only one in the group */ if ((ntids == 1) && (tids[0] == mytid ) && ! bailout) { cc = PvmNoInst; bailout = 1; } if (! bailout ) { for (i = 0; i < ntids; i++) /* remove my tid */ { if (tids[i] == mytid) { /* move the last tid to here and shorten the list */ tids[i] = tids[--ntids]; break; } } if ((cc = pvm_mcast(tids, ntids, msgtag)) > 0) cc = 0; } if (cc < 0) pvm_errno = cc; if ( TEV_AMEXCL ) /* Special handling of tracing for bcast */ { if (TEV_DO_TRACE(TEV_BCAST,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); if (cc < 0) { TEV_PACK_INT( TEV_DID_MDL, TEV_DATA_ARRAY, (int *) NULL, 0, 1 ); } else { TEV_PACK_INT( TEV_DID_MDL, TEV_DATA_ARRAY, tids, ntids, 1 ); } TEV_FIN; } TEV_ENDEXCL; } if (tids) PVM_FREE(tids); return(cc); } /* ================ pvm_barrier() ==================================== */ /* int info = pvm_barrier(char* group, int count) Calling task waits until count members of named group also call pvm_barrier. If user places -1 for count then the present size of the group is used. Note this option is not useful if the size of the group is changing. A process must be a member of a group to call pvm_barrier on that group */ int pvm_barrier(group, cnt) char *group; int cnt; { int rc; int x; #if defined(IMA_PGON) int gstate; int mytid; int nhosts; int nmem; int pcoord; extern int pvmpgonpartsize; #endif TEV_DECLS; BGN_TRACE( TEV_BARRIER, group, TEV_DID_GBC, &cnt); /* use gsync when possible on the PGON. 1) The group must be static 2) The size of the PGON partition must equal number pgon nodes in group 3) If group has other hosts besides pgon, then 1 node from pgon represents all the nodes to the group server. */ #if defined(IMA_PGON) mytid = pvm_mytid(); rc = gs_host_char(group,sgroup_list, &ngroups, gs_tidtohost(mytid), &pcoord, &nmem, &nhosts, &gstate); if (rc == 0 && nmem == pvmpgonpartsize ) /*use gsync */ { rc = _gsync(); if ( rc >= 0 && nhosts > 1) /* sync'ed pgon, now sync w/others */ { if (pcoord == mytid) int_query_server(group, BARRIERV, "pvm_barrier", &rc, cnt); _gsync(); } } else #endif int_query_server(group, BARRIER, "pvm_barrier", &rc, cnt); if (rc > 0) rc = 0; END_TRACE( TEV_BARRIER, TEV_DID_CC, &rc ); if (rc < 0) pvm_errno = rc; return(rc); } /* ================ pvm_freezegroup() =============================== */ /* int info = pvm_freezegroup(char *group, int size) The named dynamic group is frozen. Group information is cached by the local process. */ int pvm_freezegroup(group, size) char *group; int size; { int rc; int x; /* BGN_TRACE( TEV_FREEZE, group, TEV_DID_GS, &size ); */ int_query_server(group, STATICGROUP, "pvm_freezegroup", &rc, size); /* END_TRACE( TEV_FREEZE, TEV_DID_CC, &rc ); */ return(rc); } /* **************** ROUTINES THAT DIRECTLY CONTACT THE SERVER ************/ /* ================ pvm_gsdump() ==================================== */ /* * void pvm_gsdump() * ask pvmgs to dump it's state. Assumes pvmgs is running */ void pvm_gsdump() { int savectx; int sbuf; savectx = pvm_setcontext( SYSCTX_DG ); sbuf = pvm_mkbuf(PvmDataDefault); sbuf = pvm_setsbuf(sbuf); pvm_send(gstid, DUMP); pvm_freebuf(pvm_setsbuf(sbuf)); pvm_setcontext( savectx ); } /* ================ int_query_server() =============================== */ /* Query server to get a single integer of information. Single integer */ /* int info = int_query_server(char *group, int request, char *caller, * int *rvalue, int optarg) * group - string to identify the group * request - integer ID of request * requests are: JOIN, LEAVE, GETTID, GETINST, BARRIER, GSIZE * STATICGROUP * caller - string to use in error reporting * rvalue - value returned by server * optarg - optional argument used by some requests (e.g., barrier, * freezegroup) * * The request is made of the group server for group. It is possible * for the server to not only return the information, but to tack on * the instance map of the group. If this happens, then a new entry * is kept locally to cache the info for this group. */ int int_query_server(group, request, caller, rvalue, optarg) char *group; int request; char *caller; int *rvalue; int optarg; { int len; int rbuf; int sbuf,stid; int state; int savectx; GROUP_STRUCT_PTR sgroup; pvm_mytid(); if (group == (char*)0 || *group == '\0') return (*rvalue = PvmNullGroup); if ( (stid = gs_getgstid()) < 0) /* find the server's tid */ return (*rvalue = PvmSysErr); /* set context for dynamic groups */ savectx = pvm_setcontext( SYSCTX_DG ); /* send the request to the group server. */ if ((sbuf = pvm_mkbuf(PvmDataDefault)) < 0) pvm_perror(caller); if ((sbuf = pvm_setsbuf(sbuf)) < 0) pvm_perror(caller); if (pvm_pkstr(group) < 0) pvm_perror(caller); if (request == GETINST || request == GETTID || request == BARRIER || request == BARRIERV || request == STATICGROUP) { /* pack optarg */ if (pvm_pkint(&optarg, 1, 1 ) < 0) pvm_perror(caller); } if (pvm_send(stid, request) < 0) pvm_perror(caller); if ((rbuf = pvm_setrbuf(0)) < 0) /* get return value from server */ pvm_perror(caller); if (request == BARRIERV) request = BARRIER; { if (pvm_trecv(stid, request, pvmgs_tmout) <= 0) pvm_perror(caller); } if (pvm_upkint(rvalue, 1, 1) < 0) pvm_perror(caller); if (request == JOIN || request == LEAVE || request == BARRIER || *rvalue < 0 ) state = DYNAMIC; /* no state data will be returned */ else pvm_upkint(&state,1,1); if (state == STATIC) /* we've got new static group info */ gs_cachegroup(sgroup_list, &ngroups, &sgroup); pvm_freebuf(pvm_setsbuf(sbuf)); /* restore the users mbufs */ pvm_freebuf(pvm_setrbuf(rbuf)); /* restore user context */ pvm_setcontext( savectx ); return (PvmOk); } /* ================ gs_get_tidlist() ================================= */ /* int info = gs_get_tidlist(char *group, int msgtag, int *ntids, int **tids, int holes_not_allowed) group - groupname msgtag - msgtag to use for querying server ntids - number of tids in the tidlist tids - the tidlist itself. Malloc'ed holes_not_allowed - flag to indicate tid list must not have holes. */ int gs_get_tidlist(group, msgtag, ntids, tids, holes_not_allowed) char *group; int msgtag; int *ntids; int **tids; int holes_not_allowed; { int cc; int i; int len; int rbuf; int sbuf, state, stid; int savectx; GROUP_STRUCT_PTR sgroup; if ( group == (char*)0 || *group == '\0' ) return(PvmNullGroup); /* look up to see if the information is held locally */ sgroup = gs_group(group, sgroup_list, &ngroups, NOCREATE); if (sgroup != (GROUP_STRUCT_PTR) NULL) { if (holes_not_allowed) { for (i=0; i < sgroup->ntids; i++) if (sgroup->tids[i] == NOTID) { *ntids = -1; return (*ntids); } } *tids = (int *) PVM_ALLOC(sgroup->maxntids*sizeof(int),"tidlist"); for (i = 0; i < sgroup->maxntids; i++) (*tids)[i] = sgroup->tids[i]; *ntids = sgroup->ntids; return (PvmOk); } /* find out the server's tid, start the server if need be */ if ( (stid = gs_getgstid()) < 0 ) return(PvmSysErr); sbuf = pvm_mkbuf(PvmDataDefault); /* send rqst to server */ sbuf = pvm_setsbuf(sbuf); rbuf = pvm_setrbuf(0); pvm_pkstr(group); /* set context for dynamic groups */ savectx = pvm_setcontext( SYSCTX_DG ); if (holes_not_allowed) { pvm_send(stid, TIDLIST); /* e.g. scatter, gather */ cc = pvm_trecv(stid, TIDLIST, pvmgs_tmout); } else { pvm_send(stid, BCAST); /* e.g. bcast */ cc = pvm_trecv(stid, BCAST, pvmgs_tmout); } /* Catch pvmgs timeout... */ if ( cc <= 0 ) return(PvmSysErr); /* restore user context */ pvm_setcontext( savectx ); pvm_upkint(ntids, 1, 1); if (*ntids < 0) /* check for number of tids in group */ { pvm_freebuf(pvm_setsbuf(sbuf)); pvm_freebuf(pvm_setrbuf(rbuf)); return(*ntids); } if (*ntids == 0) /* if there is no one in the group */ { pvm_freebuf(pvm_setsbuf(sbuf)); pvm_freebuf(pvm_setrbuf(rbuf)); return(PvmNoInst); } /* make room for the tids */ *tids = (int *)PVM_ALLOC((*ntids) * sizeof(int), "gs_get_tidlist"); if ((*tids) == (int *) NULL) { pvm_freebuf(pvm_setsbuf(sbuf)); pvm_freebuf(pvm_setrbuf(rbuf)); return(PvmSysErr); } pvm_upkint(*tids, *ntids, 1); pvm_upkint(&state,1,1); if (state == STATIC) /* we've got new static group info */ gs_cachegroup(sgroup_list, &ngroups, &sgroup); pvm_freebuf(pvm_setsbuf(sbuf)); /* restore the users mbufs */ pvm_freebuf(pvm_setrbuf(rbuf)); return(PvmOk); } /* ================ gs_cachegroup() ================================== */ /* int info = gs_cachegroup(GROUP_LIST_PTR sgroup_list, int *ngroups, GROUP_STRUCT_PTR *rsgroup); sgroup_list - hash table that holds any static group information ngroups - number of groups in the hash table *rsgroup - pointer to structure that holds static info unpack group information from a message and then create the group in the group list; */ int gs_cachegroup(sgroup_list, ngroups, rsgroup) GROUP_LIST_PTR sgroup_list; int *ngroups; GROUP_STRUCT_PTR *rsgroup; { char *newname = (char *) NULL; int info; int len; GROUP_STRUCT_PTR sgroup; *rsgroup = (GROUP_STRUCT_PTR) NULL; if ( (info = pvm_upkint(&len,1,1)) < 0 ) DO_ERROR_RTN( info, "gs_cachegroup" ); if (len < 0) /* didn't get a valid groupname */ return(-1); if ( (newname = (char *) PVM_ALLOC(sizeof(char)*(len + 1), "gs_cachegroup") ) == (char *) NULL) DO_ERROR_RTN( PvmNoMem, "gs_cachegroup" ); if ( (info = pvm_upkstr(newname)) < 0 ) { PVM_FREE(newname); DO_ERROR_RTN( info, "gs_cachegroup" ); } sgroup = gs_group(newname, sgroup_list, ngroups, CREATE); if (sgroup != (GROUP_STRUCT_PTR) NULL) { if ( (info = pvm_upkint(&(sgroup->ntids),1,1) ) < 0 ) { PVM_FREE(newname); DO_ERROR_RTN( info, "gs_cachegroup" ); } if ( (info = pvm_upkint(&(sgroup->maxntids),1,1) ) < 0 ) { PVM_FREE(newname); DO_ERROR_RTN( info, "gs_cachegroup" ); } sgroup->tids = (int *) PVM_ALLOC(sgroup->maxntids*sizeof(int), "gs_cachegroup"); if (sgroup->tids == (int *) NULL) gs_delete_group(newname, sgroup_list, ngroups); else { if ( (info = pvm_upkint(sgroup->tids,sgroup->maxntids,1) ) < 0) { gs_delete_group(newname, sgroup_list, ngroups); PVM_FREE(newname); DO_ERROR_RTN( info, "gs_cachegroup" ); } info = pvm_upkint(&(sgroup->nhosts),1,1); sgroup->np_onhost = (int *) PVM_ALLOC(sizeof(int) * sgroup->nhosts,"gs_cachegroup"); sgroup->pcoord = (int *) PVM_ALLOC(sizeof(int) * sgroup->nhosts,"gs_cachegroup"); pvm_upkint(sgroup->np_onhost,sgroup->nhosts,1); info = pvm_upkint(sgroup->pcoord,sgroup->nhosts,1); if (info < 0) { gs_delete_group(newname, sgroup_list, ngroups); PVM_FREE(newname); DO_ERROR_RTN( info, "gs_cachegroup" ); } sgroup->maxhosts = sgroup->nhosts; } sgroup->staticgroup = STATIC; *rsgroup = sgroup; /* set the pointer to the group struct */ } PVM_FREE(newname); /* free the malloc'ed memory */ return (PvmOk); } /* ================ pvm_grphostinfo() =============================== */ /* int info = pvm_grphostinfo(char *group, int hosttid, int *coord, int *nmem_onhost, int *nhosts) * return information about how many hosts are represented in the group and * which tid should be used to coordinate local (on-host) group operations */ int pvm_grphostinfo(group, hosttid, coord, nmem_onhost, nhosts) char *group; int hosttid, *coord, *nmem_onhost, *nhosts; { GROUP_STRUCT_PTR sgroup; int foo; int info; int rbuf, rc; int sbuf, state, stid; int x; int savectx; /* BGN_TRACE( TEV_GRPHOST, group, TEV_DID_HPT, &hosttid ); */ info = gs_host_char(group, sgroup_list, &ngroups, hosttid, coord, nmem_onhost, nhosts, &foo); if (info != PvmOk ) /* info not local */ { if ( (stid = gs_getgstid()) < 0) { /* find the server's ti */ info = PvmSysErr; /* END_TRACE( TEV_GRPHOST, TEV_DID_CC, &info ); */ return( info ); } /* set context for dynamic groups */ savectx = pvm_setcontext( SYSCTX_DG ); sbuf = pvm_mkbuf(PvmDataDefault); rbuf = pvm_setrbuf(0); sbuf = pvm_setsbuf(sbuf); if ((info = pvm_pkstr(group)) < 0 ) goto cleanup; if ((info = pvm_pkint(&hosttid,1,1)) < 0) goto cleanup; if ((info = pvm_send(stid,HOSTCHAR)) < 0) goto cleanup; if ((info = pvm_trecv(stid,HOSTCHAR,pvmgs_tmout)) <= 0) goto cleanup; if ((info = pvm_upkint(nhosts,1,1)) < 0) goto cleanup; if ((info = pvm_upkint(nmem_onhost,1,1)) < 0) goto cleanup; if ((info = pvm_upkint(coord,1,1)) < 0) goto cleanup; if (( info = pvm_upkint(&state,1,1)) < 0) goto cleanup; if (state == STATIC) /* we've got new static group info */ gs_cachegroup(sgroup_list, &ngroups, &sgroup); cleanup: sbuf = pvm_setsbuf(sbuf); rbuf = pvm_setrbuf(rbuf); pvm_freebuf(sbuf); pvm_freebuf(rbuf); /* restore user context */ pvm_setcontext( savectx ); } /* END_TRACE( TEV_GRPHOST, TEV_DID_CC, &info ); */ return(info); } /* ================ pvm_grpvhostinfo() =============================== */ /* int info = pvm_grpvhostinfo(char *group, int **coord, int **nmem_onhost, int *nhosts) * return #vectors# of information about how may hosts are represented in * a group, the local coordinating tid for each host, and #procs on each host * * NOTE: for efficiency, the data in the vectors *nmem_host and *coord are valid only until the next call to pvm_grpvhostinfo */ static int *gsu_coordv = (int *) NULL; static int *gsu_onhostv = (int *) NULL; static int gsu_maxhosts = 0; int pvm_grpvhostinfo(group, coordv, nmem_onhostv, nhosts) char *group; int **coordv, **nmem_onhostv, *nhosts; { int foo; int info; int rbuf, rc; int sbuf, state, stid; int x; int savectx; GROUP_STRUCT_PTR sgroup; /* BGN_TRACE( TEV_GRPVHOST, group, TEV_DID_HPT, &hosttid ); */ info = gs_host_all(group, sgroup_list, &ngroups, coordv, nmem_onhostv, nhosts, &foo); if (info != PvmOk ) /* info not local */ { if ( (stid = gs_getgstid()) < 0) { /* find the server's ti */ info = PvmSysErr; /* END_TRACE( TEV_GRPHOST, TEV_DID_CC, &info ); */ return( info ); } /* set context for dynamic groups */ savectx = pvm_setcontext( SYSCTX_DG ); sbuf = pvm_mkbuf(PvmDataDefault); rbuf = pvm_setrbuf(0); sbuf = pvm_setsbuf(sbuf); if ((info = pvm_pkstr(group)) < 0) goto cleanup; if ((info = pvm_send(stid,HOSTCHARV)) < 0) goto cleanup; if ((info = pvm_trecv(stid,HOSTCHARV,pvmgs_tmout)) <= 0) goto cleanup; if ((info = pvm_upkint(nhosts,1,1)) < 0) goto cleanup; if (*nhosts > gsu_maxhosts) { if (gsu_coordv) PVM_FREE(gsu_coordv); if (gsu_onhostv) PVM_FREE(gsu_onhostv); gsu_coordv = (int *) PVM_ALLOC(*nhosts*sizeof(int), "pvm_grp_hostv"); gsu_onhostv = (int *) PVM_ALLOC(*nhosts*sizeof(int), "pvm_grp_hostv"); gsu_maxhosts = *nhosts; } if (gsu_onhostv == (int *) NULL || gsu_coordv == (int *) NULL) { info = PvmOutOfRes; goto cleanup; } if ((info = pvm_upkint(gsu_onhostv,*nhosts,1)) < 0) goto cleanup; if ((info = pvm_upkint(gsu_coordv,*nhosts,1)) < 0) goto cleanup; if ((info = pvm_upkint(&state,1,1)) < 0) goto cleanup; if (state == STATIC) /* we've got new static group info */ gs_cachegroup(sgroup_list, &ngroups, &sgroup); cleanup: sbuf = pvm_setsbuf(sbuf); rbuf = pvm_setrbuf(rbuf); pvm_freebuf(sbuf); pvm_freebuf(rbuf); /* restore user context */ pvm_setcontext( savectx ); *nmem_onhostv = gsu_onhostv; *coordv = gsu_coordv; } /* END_TRACE( TEV_GRPVHOST, TEV_DID_CC, &info ); */ return(info); } ./pvm3/pvmgs/pvmgs_const.h0100644007401100000360000000746206625343660014772 0ustar kohlgopher /* $Id: pvmgs_const.h,v 1.4 1998/11/20 19:49:04 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* File: pvmgs_const.h - constants used for pvmgs programs */ #define GSNAME "pvmgs" /* Message tags that the server responds to */ #define DIE 0 /* halt the group server */ #define JOIN 1 /* join a group */ #define LEAVE 2 /* leave a group */ #define BARRIER 3 /* group barrier */ #define BCAST 4 /* broadcast to a group */ #define GETINST 5 /* get the group inst given the task id */ #define GETTID 6 /* get the task id given the group inst */ #define GSIZE 7 /* get the group size */ #define RESET 8 /* reset the group server */ #define DUMP 9 /* dump the state */ #define GSLS 10 /* send back a list of the groups */ #define DEADTID 11 /* notify tag used when a task dies */ #define TIDLIST 12 /* get list of tids for group */ #define STATICGROUP 13 /* form a static group */ #define HOSTCHAR 14 /* get nproc, coord for a host in a group */ #define HOSTCHARV 15 /* get nproc, coord for all hosts in group */ #define BARRIERV 16 /* barrier call by host coordinator */ /* Initial Storage dimensions and Delta Storage Dimensions */ #define DELTANTIDS 10 /* increment for remalloc */ #define DELTABTIDS DELTANTIDS /* increment for remalloc */ /* Hash Table dimension */ /* WIN32 wants to define its own values in WINNT.H -- we can't allow this... */ #ifdef WIN32 #undef MINCHAR #undef MAXCHAR #endif #define MINCHAR 32 #define MAXCHAR 127 #define HASHSIZE MAXCHAR - MINCHAR + 1 /* Other manifest constants */ #define CREATE 1 /* flag to create hash entry */ #define NOCREATE 0 #define NOTID -1 /* indicates no tid */ #define STATIC 1 /* indicate a group is static */ #define DYNAMIC 2 /* indicate a group is dynamic */ #define STATICDEAD 3 /* dead static group */ #define PvmgsNotCached 1 /* tid has not cached the data */ ./pvm3/pvmgs/pvmgs_decl.h0100644007401100000360000000371706360713541014545 0ustar kohlgopher /* $Id: pvmgs_decl.h,v 1.2 1997/07/09 13:51:29 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ int gs_init(); int gs_hash_init(); int gs_sgroup_init(); GROUP_STRUCT_PTR gs_struct_init(); int gs_struct_destroy(); GROUP_LIST_PTR gs_hash_name(); GROUP_LIST_PTR gs_list_insert(); GROUP_STRUCT_PTR gs_group(); int gs_delete_group(); int gs_handle(); int gs_pstate(); int gs_join(); int gs_leave(); int gs_barrier(); int gs_deadtid(); int gs_tidlist(); int gs_gsize(); int gs_gettid(); int gs_pstate(); int gs_ls(); int gs_uniquename(); int gs_static(); int gs_pkstaticinfo(); int gs_newstaticcache(); int * gs_realloc_int_array(); int gs_binsearch(); int gs_newhost(); int gs_delhost(); int gs_host_char(); int gs_host_all(); int gs_retint(); int gs_tidtohost(); int gs_hash_clear(); ./pvm3/pvmgs/pvmgsd.h0100644007401100000360000000257506360713546013730 0ustar kohlgopher /* $Id: pvmgsd.h,v 1.2 1997/07/09 13:51:34 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ #include "pvmgs_const.h" #include "pvmgs_ds.h" #include "pvmgs_mac.h" #include "pvmgs_decl.h" ./pvm3/pvmgs/pvmgs_ds.h0100644007401100000360000000617406360713542014245 0ustar kohlgopher /* $Id: pvmgs_ds.h,v 1.2 1997/07/09 13:51:30 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* File: pvmgs_ds.h - Define various data structures used by the group server*/ /* Structure that defines a group */ typedef struct group_struct { char *name; /* the name of the group */ int len; /* length of the group name */ int ntids; /* number of tids */ int *tids; /* array of the tids */ int maxntids; /* max number of tids before remalloc*/ int barrier_count; /* count for the current barrier */ int barrier_reached; /* number of procs reaching barrier */ int barrier_index; /* number of tids we need to release */ int *btids; /* tids that have reached barrier */ int maxbtids; /* max number of btids before remalloc */ int sgroup_count; /* count for static group formation */ int sgroup_reached; /* number of procs reaching sgroup */ int *stids; /* tids that have reached sgroup */ int maxstids; /* max number of stids before remalloc */ int staticgroup; /* tell if this is a static group */ int ninfotids; /* if static, how many have the info */ int *infotids; /* list of tids that have the static info */ int maxinfotids; /* max num of info tids before remalloc */ int nhosts; /* hosts in this group */ int *np_onhost; /* #procs on host */ int *pcoord; /* proc that coords collectives on a host */ int maxhosts; /* max number of hosts before remalloc */ } GROUP_STRUCT, *GROUP_STRUCT_PTR; /* A doubly-linked list of group structures */ typedef struct group_list { struct group_list *prev, *next; GROUP_STRUCT_PTR group; } GROUP_LIST, *GROUP_LIST_PTR; ./pvm3/pvmgs/pvmgs_mac.h0100644007401100000360000001025106360713545014371 0ustar kohlgopher /* $Id: pvmgs_mac.h,v 1.6 1997/07/09 13:51:33 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* File: pvmgs_mac.h - various macros that are used throughout the */ /* group server */ /* Set the pvm_errno to info, print the error, and then return the */ /* error */ #define DO_ERROR_RTN( info, caller ) \ { pvm_errno = info; pvm_perror( caller ); return( info ); } /* Allocate new memory for a string based if length > mxlen */ #define REALLOCSTRING( length, mxlen, name, caller ) \ { if ( (length) > (mxlen) ) \ { \ if ( name != (char *) NULL ) \ PVM_FREE( name ); \ name = (char *) PVM_ALLOC( sizeof(char) * (length + 1), \ caller ); \ mxlen = length; \ } \ } /* Init a send buffer and pack the single integer result */ /* caller is used for error reporting */ #define PK_IRESULT( result, caller) \ { if ( pvm_initsend( PvmDataDefault ) < 0 ) \ pvm_perror( caller ); \ if ( pvm_pkint( &(result), 1, 1 ) < 0 ) \ pvm_perror( caller ); \ } /* Pack state. If state is STATIC then pack all group information. */ #define PK_STATE( tid, state, name, hash_list, ngroups, caller ) \ { if ( pvm_pkint( &(state), 1, 1 ) < 0 ) \ pvm_perror( caller ); \ if ( state == STATIC ) \ if ( gs_newstaticcache( tid, name, hash_list, ngroups, \ caller ) == PvmgsNotCached ) \ gs_pkstaticinfo( gs_group( name, hash_list, ngroups, \ NOCREATE ) ); \ } /* Send packed buffer to tid, msgtag. Caller used for err reporting */ #define SENDRESULT( tid, msgtag, caller ) \ if ( pvm_send( tid, msgtag ) < 0 ) \ pvm_perror( caller ); /* Create a send buffer, pack a single integer, and send it */ #define SENDINTRESULT( result, tid, msgtag, caller ) \ { PK_IRESULT( result, caller ); SENDRESULT( tid, msgtag, caller ) } /* Begin a trace event, keep track of the current trace level */ /* Optionally packs a single integer argument */ #define BGN_TRACE( event, strarg, did, intarg ) \ if ( TEV_EXCLUSIVE ) { \ if (TEV_DO_TRACE( event, TEV_EVENT_ENTRY ) ) \ { \ TEV_PACK_STRING( TEV_DID_GN, TEV_DATA_SCALAR, \ strarg ? strarg: "", 1, 1 ); \ if ( intarg != (int *) NULL ) \ TEV_PACK_INT( did, TEV_DATA_SCALAR, intarg, 1, 1 ); \ TEV_FIN; \ } \ } /* End trace event and send back an integer */ #define END_TRACE( event, did, intarg ) \ if ( TEV_AMEXCL ) { \ if (TEV_DO_TRACE( event, TEV_EVENT_EXIT ) ) \ { \ TEV_PACK_INT( did, TEV_DATA_SCALAR, intarg, 1, 1 ); \ TEV_FIN; \ } \ TEV_ENDEXCL; \ } /* Max, min. Interval confines the argument to the interval */ #ifndef MAX #define MAX(x,y) ((x) > (y) ? (x) : (y)) #endif #ifndef MIN #define MIN(x,y) ((x) < (y) ? (x) : (y)) #endif #define INTERVAL(x,a,y) MIN(MAX((x),(a)), (y)) ./pvm3/pvmgs/OS2/0042755007401100000360000000000010117676455012660 5ustar kohlgopher./pvm3/pvmgs/OS2/Makefile0100644007401100000360000000063306401364452014305 0ustar kohlgopher# # $Id: Makefile,v 1.1 1997/08/28 21:10:02 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/pvmgs PVM_ARCH = OS2 CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) # install: default $(LIBDIR) default: make LIBPREFIX="" -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install clean: make LIBPREFIX="" -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean $(LIBDIR): mkdir $(LIBDIR) ./pvm3/pvmgs/PGON/0042755007401100000360000000000010117676455013020 5ustar kohlgopher./pvm3/pvmgs/PGON/Makefile0100644007401100000360000000061406604767655014465 0ustar kohlgopher# # $Id: Makefile,v 1.5 1998/10/01 21:10:05 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/pvmgs PVM_ARCH = PGON CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) # install: default $(LIBDIR) default: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install-mpp clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean $(LIBDIR): mkdir $(LIBDIR) ./pvm3/src/0042755007401100000360000000000010117676455011710 5ustar kohlgopher./pvm3/src/cygwin.mak0100644007401100000360000001247607240355075013702 0ustar kohlgopher#*****************************************************************************# # # makefile # for libpvm3.a, pvmd3 # #*****************************************************************************# include $(PVM_ROOT_U)/conf/win32cygwin.def PVM_LIB = $(PVM_ROOT_U)/lib/$(PVM_ARCH) XDR_H = $(PVM_ROOT_U)/xdr/types.h $(PVM_ROOT_U)/xdr/xdr.h LOBJ = $(PVM_ARCH)/global.o \ $(PVM_ARCH)/imalloc.o \ $(PVM_ARCH)/lpvm.o \ $(PVM_ARCH)/lpvmcat.o \ $(PVM_ARCH)/lpvmgen.o \ $(PVM_ARCH)/lpvmglob.o \ $(PVM_ARCH)/lpvmpack.o \ $(PVM_ARCH)/pmsg.o \ $(PVM_ARCH)/pvmalloc.o \ $(PVM_ARCH)/pvmcruft.o \ $(PVM_ARCH)/pvmdabuf.o \ $(PVM_ARCH)/pvmerr.o \ $(PVM_ARCH)/pvmfrag.o \ $(PVM_ARCH)/tev.o \ $(PVM_ARCH)/waitc.o \ $(PVM_ARCH)/xdr.o \ $(PVM_ARCH)/xdr_floa.o \ $(PVM_ARCH)/xdr_mem.o DOBJ = $(PVM_ARCH)/ddpro.o \ $(PVM_ARCH)/global.o \ $(PVM_ARCH)/host.o \ $(PVM_ARCH)/hoster.o \ $(PVM_ARCH)/imalloc.o \ $(PVM_ARCH)/msgbox.o \ $(PVM_ARCH)/pkt.o \ $(PVM_ARCH)/pmsg.o \ $(PVM_ARCH)/pvmalloc.o \ $(PVM_ARCH)/pvmcruft.o \ $(PVM_ARCH)/pvmd.o \ $(PVM_ARCH)/pvmdabuf.o \ $(PVM_ARCH)/pvmdpack.o \ $(PVM_ARCH)/pvmdtev.o \ $(PVM_ARCH)/pvmdunix.o \ $(PVM_ARCH)/pvmerr.o \ $(PVM_ARCH)/pvmfrag.o \ $(PVM_ARCH)/pvmlog.o \ $(PVM_ARCH)/pvmregex.o \ $(PVM_ARCH)/regex.o \ $(PVM_ARCH)/sdpro.o \ $(PVM_ARCH)/task.o \ $(PVM_ARCH)/tdpro.o \ $(PVM_ARCH)/waitc.o \ $(PVM_ARCH)/xdr.o \ $(PVM_ARCH)/xdr_mem.o \ $(PVM_ARCH)/xdr_floa.o all: $(LIB) $(PVM_LIB)/pvmd3.exe $(PVM_LIB)/pvmd3.exe: $(DOBJ) $(CC) -o $(PVM_LIB)/pvmd3 $(DOBJ) $(LINK_FLAGS) $(LIB): $(LOBJ) ar -rs $(LIB) $(LOBJ) $(PVM_ARCH)/ddpro.o: ddpro.c $(XDR_H) global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/ddpro.o ddpro.c $(PVM_ARCH)/global.o: global.c $(XDR_H) global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/global.o global.c $(PVM_ARCH)/host.o: host.c $(XDR_H) global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/host.o host.c $(PVM_ARCH)/hoster.o: hoster.c $(XDR_H) global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/hoster.o hoster.c $(PVM_ARCH)/imalloc.o: imalloc.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/imalloc.o imalloc.c $(PVM_ARCH)/lpvm.o: lpvm.c $(XDR_H) global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/lpvm.o lpvm.c $(PVM_ARCH)/lpvmcat.o: lpvmcat.c $(XDR_H) global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/lpvmcat.o lpvmcat.c $(PVM_ARCH)/lpvmgen.o: lpvmgen.c $(XDR_H) global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/lpvmgen.o lpvmgen.c $(PVM_ARCH)/lpvmglob.o: lpvmglob.c $(XDR_H) global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/lpvmglob.o lpvmglob.c $(PVM_ARCH)/lpvmpack.o: lpvmpack.c $(XDR_H) global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/lpvmpack.o lpvmpack.c $(PVM_ARCH)/msgbox.o: msgbox.c $(XDR_H) global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/msgbox.o msgbox.c $(PVM_ARCH)/pkt.o: pkt.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/pkt.o pkt.c $(PVM_ARCH)/pmsg.o: pmsg.c $(XDR_H) global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/pmsg.o pmsg.c $(PVM_ARCH)/pvmalloc.o: pvmalloc.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/pvmalloc.o pvmalloc.c $(PVM_ARCH)/pvmcruft.o: pvmcruft.c global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/pvmcruft.o pvmcruft.c $(PVM_ARCH)/pvmd.o: pvmd.c $(XDR_H) global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/pvmd.o pvmd.c $(PVM_ARCH)/pvmdabuf.o: pvmdabuf.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/pvmdabuf.o pvmdabuf.c $(PVM_ARCH)/pvmdpack.o: pvmdpack.c $(XDR_H) global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/pvmdpack.o pvmdpack.c $(PVM_ARCH)/pvmdtev.o: pvmdtev.c $(XDR_H) global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/pvmdtev.o pvmdtev.c $(PVM_ARCH)/pvmdunix.o:pvmdunix.c $(XDR_H) global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/pvmdunix.o pvmdunix.c $(PVM_ARCH)/pvmerr.o: pvmerr.c global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/pvmerr.o pvmerr.c $(PVM_ARCH)/pvmfrag.o: pvmfrag.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/pvmfrag.o pvmfrag.c $(PVM_ARCH)/pvmlog.o: pvmlog.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/pvmlog.o pvmlog.c $(PVM_ARCH)/pvmregex.o: regex/pvmregex.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/pvmregex.o regex/pvmregex.c $(PVM_ARCH)/regex.o: regex/regex.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/regex.o regex/regex.c $(PVM_ARCH)/sdpro.o: sdpro.c $(XDR_H) global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/sdpro.o sdpro.c $(PVM_ARCH)/task.o: task.c $(XDR_H) global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/task.o task.c $(PVM_ARCH)/tdpro.o: tdpro.c $(XDR_H) global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/tdpro.o tdpro.c $(PVM_ARCH)/tev.o: tev.c $(XDR_H) global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/tev.o tev.c $(PVM_ARCH)/waitc.o: waitc.c $(XDR_H) global.h $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/waitc.o waitc.c $(PVM_ARCH)/xdr.o: $(PVM_ROOT_U)/xdr/xdr.c $(XDR_H) $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/xdr.o $(PVM_ROOT_U)/xdr/xdr.c $(PVM_ARCH)/xdr_floa.o: $(PVM_ROOT_U)/xdr/xdr_floa.c $(XDR_H) $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/xdr_floa.o $(PVM_ROOT_U)/xdr/xdr_floa.c $(PVM_ARCH)/xdr_mem.o: $(PVM_ROOT_U)/xdr/xdr_mem.c $(XDR_H) $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/xdr_mem.o $(PVM_ROOT_U)/xdr/xdr_mem.c # Clean up everything but the .EXEs clean : -rm -f $(PVM_ARCH)/*.o ./pvm3/src/Makefile.aimk0100644007401100000360000003237507277033102014262 0ustar kohlgopher# # $Id: Makefile.aimk,v 1.40 2001/05/11 18:58:10 pvmsrc Exp $ # # Generic Makefile body to be concatenated to config header. # # Imports: # PVM_ARCH = the official pvm-name of your processor # ARCHCFLAGS = special cc flags # ARCHDLIB = special libs needed for daemon # ARCHDOBJ = special objects needed for daemon # HASRANLIB = 't' or 'f' # AMEM = Memory page locks from Convex # PLOCKFILE = Page Lock in line code from SUN # # Compatibility defines (usually in conf/*.def): # FDSETPATCH if system includes don't have fd_set stuff # USESTRERROR if sys_errlist, sys_nerr not public, use strerror() # HASERRORVARS if errno, sys_nerr, sys_errlist already declared # HASSTDLIB if system has stdlib.h # NEEDENDIAN to include # NEEDMENDIAN to include # NOGETDTBLSIZ if system doesn't have getdtablesize() # NOREXEC if system doesn't have rexec() # NOSOCKOPT if system doesn't have setsockopt() / it doesn't work # NOSTRCASE if system doesn't have strcasecmp, strncasecmp # NOTMPNAM if system doesn't have tmpnam() or it's hosed # NOUNIXDOM to disable use of Unix domain sockets # NOWAIT3 if system doesn't have wait3() # NOWAITPID if system doesn't have waitpid() either # RSHCOMMAND= for rsh command other than "/usr/ucb/rsh" # (can override using PVM_RSH environment variable) # SHAREDTMP if /tmp is shared between machines (yecch) # SOCKADHASLEN if struct sockaddr has an sa_len field # SYSVBFUNC if system uses memcpy() instead of bcopy(), etc. # SYSVSIGNAL if system has sysV signal handling # SYSVSTR if system uses strchr() instead of index() # UDPMAXLEN= for alternate max udp packet size # NEEDSSELECTH if you need to include select.h to get fd_set (IBMs) # SOCKLENISUINT if socket parameter is unsigned int (or size_t), # generally -> recvfrom() accept() getsockname() # remove flag for AIX 4.1 compiler complaints... # FDSETNOTSTRUCT if fd_set var declarations do not require "struct" # CTIMEISTIMET if ctime() takes an arg of type "time_t" # SYSERRISCONST if char *sys_errlist[] defined as const # # Options defines: # CLUMP_ALLOC allocates several data structures in big chunks # MCHECKSUM to enable crc checksums on messages # RSHNPLL= for number of parallel rsh startups (default is 5) # RSHTIMEOUT= for rsh timeout other than default (60 sec) # STATISTICS to enable collection of statistics in pvmd # TIMESTAMPLOG to enable timestamps in pvmd log file # USE_PVM_ALLOC to enable instrumented malloc functs (for pvm debug) # USE_GNU_REGEX to enable use of GNU Regex for Mbox Lookup # -> requires installation of GNU regex, as well as # modifying the following defines (see below): # REGEXCONF, REGEXCONFOS2, REGEXOBJS # SHELL = /bin/sh PVMDIR = ../.. SDIR = $(PVMDIR)/src LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) CFLOPTS = -O #CFLOPTS = -g #OPTIONS = -DCLUMP_ALLOC #OPTIONS = -DSTATISTICS #OPTIONS = -p OPTIONS = -DCLUMP_ALLOC -DSTATISTICS \ -DTIMESTAMPLOG -DSANITY CFLAGS = $(CFLOPTS) $(OPTIONS) -I$(PVMDIR)/include \ -DARCHCLASS=\"$(PVM_ARCH)\" -DIMA_$(PVM_ARCH) \ $(ARCHCFLAGS) LIBPREFIX = lib LIBPVM = $(LIBPREFIX)pvm3 # # GNU Regular Expression Defines - set if needed # REGEXCONF = #REGEXCONF = regexconfig REGEXCONFOS2 = #REGEXCONFOS2 = regexconfig-os2 REGEXOBJS = #REGEXOBJS = pvmregex.o regex.o # # PVM Daemon & Library Objects # DOBJ = \ ddpro.o \ host.o \ hoster.o \ imalloc.o \ msgbox.o \ pkt.o \ pmsg.o \ pvmalloc.o \ pvmcruft.o \ pvmd.o \ pvmdpack.o \ pvmdtev.o \ pvmerr.o \ pvmfrag.o \ pvmlog.o \ sdpro.o \ task.o \ tdpro.o \ waitc.o \ global.o \ $(REGEXOBJS) SOCKDOBJ = \ pvmdabuf.o \ pvmdunix.o SHMEMDOBJ = \ $(AMEMOBJ) \ nmdclass.o \ pvmdshmem.o \ pvmshmem.o MPPDOBJ = \ mppchunkhost.o \ mppmsghost.o \ lmsg.o \ pvmdabuf.o \ pvmdmimd.o \ pvmdunix.o BEODOBJ = \ pvmdmimd.o OS2DOBJ = \ deathapi.o \ sthoster.o \ stdlog.o \ rexec.o \ ruserpas.o \ os2spawn.o LOBJ = \ imalloc.o \ tev.o \ lpvmcat.o \ lpvmgen.o \ lpvmpack.o \ lpvmglob.o \ pmsg.o \ pvmalloc.o \ pvmcruft.o \ pvmerr.o \ pvmfrag.o \ waitc.o \ global.o LPVMSOCK = lpvm.o SOCKLOBJ = \ pvmdabuf.o LPVMSHMEM = lpvmshmem.o SHMEMLOBJ = \ $(AMEMOBJ) \ pvmshmem.o LPVMMIMD = lpvmmimd.o MPPLOBJ = \ mppchunknode.o \ mppmsgnode.o \ lmsg.o \ lpvmmpp.o \ pvmdabuf.o OS2LOBJ = stdlog.o REGEXSRC = \ $(SDIR)/regex/Makefile.in \ $(SDIR)/regex/configure \ $(SDIR)/regex/configure.in \ $(SDIR)/regex/pvmregex.c \ $(SDIR)/regex/regex.c \ $(SDIR)/regex/regex.h REGEXDIR = ./regex REGEXCP = \ $(REGEXDIR)/Makefile.in \ $(REGEXDIR)/configure \ $(REGEXDIR)/configure.in \ $(REGEXDIR)/pvmregex.c \ $(REGEXDIR)/regex.c \ $(REGEXDIR)/regex.h REGEXOPTS = CC=$(CC) \ CFLAGS="$(CFLOPTS) -DREGEX_MALLOC $(ARCHCFLAGS)" SHMEMTARGETS = $(LIBDIR)/pvmd3-shm \ $(LIBDIR)/lib-shm $(LIBDIR)/$(LIBPVM)s.a MPPTARGETS = $(LIBDIR)/pvmd3-mpp \ $(LIBDIR)/$(LIBPVM).a $(LIBDIR)/$(LIBPVM)pe.a BEOTARGETS = $(LIBDIR)/pvmd3-beo $(LIBDIR)/$(LIBPVM).a OS2TARGETS = $(LIBDIR)/pvmd3-os2 $(LIBDIR)/lib-os2 all: pvmd3$(EXESFX) $(LIBPVM).a all-shm: pvmd3-shm lib-shm $(LIBPVM)s.a all-mpp: pvmd3-mpp $(LIBPVM).a $(LIBPVM)pe.a all-beo: pvmd3-beo $(LIBPVM).a all-os2: pvmd3-os2 lib-os2 install: $(LIBDIR) $(LIBDIR)/pvmd3$(EXESFX) $(LIBDIR)/$(LIBPVM).a install-shm: $(LIBDIR) $(SHMEMTARGETS) install-mpp: $(LIBDIR) $(MPPTARGETS) install-beo: $(LIBDIR) $(BEOTARGETS) install-os2: $(LIBDIR) $(OS2TARGETS) $(LIBDIR): - mkdir $(LIBDIR) # libdir sock pvmd3 & libpvm3.a $(LIBDIR)/pvmd3$(EXESFX): pvmd3$(EXESFX) cp pvmd3$(EXESFX) $(LIBDIR) $(LIBDIR)/$(LIBPVM).a: $(LIBPVM).a cp $(LIBPVM).a $(LIBDIR) # libdir shm pvmd3 & libpvm3*.a $(LIBDIR)/pvmd3-shm: pvmd3-shm cp pvmd3$(EXESFX) $(LIBDIR) touch $(LIBDIR)/pvmd3-shm $(LIBDIR)/lib-shm: lib-shm cp $(LIBPVM).a $(LIBDIR) touch $(LIBDIR)/lib-shm $(LIBDIR)/$(LIBPVM)s.a: $(LIBPVM)s.a cp $(LIBPVM)s.a $(LIBDIR)/$(LIBPVM)s.a # libdir mpp pvmd3 & libpvm3*.a $(LIBDIR)/pvmd3-mpp: pvmd3-mpp cp pvmd3$(EXESFX) $(LIBDIR) touch $(LIBDIR)/pvmd3-mpp $(LIBDIR)/$(LIBPVM)pe.a: $(LIBPVM)pe.a cp $(LIBPVM)pe.a $(LIBDIR) # libdir Beowulf pvmd3 $(LIBDIR)/pvmd3-beo: pvmd3-beo cp pvmd3$(EXESFX) $(LIBDIR) touch $(LIBDIR)/pvmd3-beo # libdir os2 pvmd3 & libpvm3*.a $(LIBDIR)/pvmd3-os2: pvmd3-os2 cp pvmd3$(EXESFX) $(LIBDIR) touch $(LIBDIR)/pvmd3-os2 $(LIBDIR)/lib-os2: lib-os2 cp $(LIBPVM).a $(LIBDIR) touch $(LIBDIR)/lib-os2 # sock pvmd3 & libpvm3.a pvmd3$(EXESFX): $(REGEXCONF) $(DOBJ) $(SOCKDOBJ) $(CC) $(CFLAGS) -o pvmd3$(EXESFX) $(DOBJ) $(SOCKDOBJ) \ $(LOPT) $(ARCHDLIB) $(LIBPVM).a: $(REGEXCONF) $(LOBJ) $(LPVMSOCK) $(SOCKLOBJ) rm -f $(LIBPVM).a $(AR) cr $(LIBPVM).a $(LOBJ) $(LPVMSOCK) $(SOCKLOBJ) case x$(HASRANLIB) in xt ) echo ranlib; ranlib $(LIBPVM).a ;; esac # shm pvmd3 & libpvm3*.a pvmd3-shm: $(REGEXCONF) $(DOBJ) $(SHMEMDOBJ) $(CC) $(CFLAGS) -o pvmd3$(EXESFX) $(DOBJ) $(SHMEMDOBJ) $(ARCHDLIB) touch pvmd3-shm lib-shm: $(REGEXCONF) $(LOBJ) $(LPVMSHMEM) $(SHMEMLOBJ) rm -f $(LIBPVM).a $(AR) cr $(LIBPVM).a $(LOBJ) $(LPVMSHMEM) $(SHMEMLOBJ) case x$(HASRANLIB) in xt ) echo ranlib; ranlib $(LIBPVM).a ;; esac touch lib-shm $(LIBPVM)s.a: $(REGEXCONF) $(LOBJ) $(LPVMSOCK) $(SOCKLOBJ) rm -f $(LIBPVM)s.a $(AR) cr $(LIBPVM)s.a $(LOBJ) $(LPVMSOCK) $(SOCKLOBJ) case x$(HASRANLIB) in xt ) echo ranlib; ranlib $(LIBPVM)s.a ;; esac # mpp pvmd3 & libpvm3*.a pvmd3-mpp: $(REGEXCONF) $(DOBJ) $(MPPDOBJ) $(CC) $(CFLAGS) -o pvmd3$(EXESFX) $(DOBJ) $(MPPDOBJ) \ $(LOPT) $(ARCHDLIB) touch pvmd3-mpp $(LIBPVM)pe.a: $(REGEXCONF) $(LOBJ) $(LPVMMIMD) $(MPPLOBJ) rm -f $(LIBPVM)pe.a $(AR) cr $(LIBPVM)pe.a $(LOBJ) $(LPVMMIMD) $(MPPLOBJ) # Beowulf(LINUX) pvmd3 & libpvm3.a pvmd3-beo: $(REGEXCONF) $(DOBJ) $(BEODOBJ) $(SOCKDOBJ) $(CC) $(CFLAGS) -o pvmd3$(EXESFX) $(DOBJ) $(BEODOBJ) $(SOCKDOBJ) \ $(LOPT) $(ARCHDLIB) # os2 pvmd3 & libpvm3.a pvmd3-os2: $(REGEXCONFOS2) $(OS2DOBJ) $(DOBJ) $(SOCKDOBJ) $(CC) $(CFLAGS) -o pvmd3$(EXESFX) $(OS2DOBJ) $(DOBJ) $(SOCKDOBJ) \ $(LOPT) $(ARCHDLIB) touch pvmd3-os2 lib-os2: $(REGEXCONFOS2) $(LOBJ) $(OS2LOBJ) $(LPVMSOCK) $(SOCKLOBJ) rm -f $(LIBPVM).a $(AR) cr $(LIBPVM).a $(LOBJ) $(OS2LOBJ) $(LPVMSOCK) $(SOCKLOBJ) case x$(HASRANLIB) in xt ) echo ranlib; ranlib $(LIBPVM).a ;; esac touch lib-os2 # clean: tidy rm -f pvmd3$(EXESFX) $(LIBPVM).a $(LIBPVM)s.a $(LIBPVM)pe.a rm -rf $(REGEXDIR) tidy: rm -f $(DOBJ) $(SOCKDOBJ) $(SHMEMDOBJ) $(MPPDOBJ) \ $(LOBJ) $(LPVMSOCK) $(SOCKLOBJ) $(LPVMSHMEM) $(SHMEMLOBJ) \ $(LPVMMIMD) $(MPPLOBJ) $(REGEXDIR)/*.o \ pvmd3-shm lib-shm pvmd3-mpp pvmd3-os2 lib-os2 \ regexconfig regexconfig-os2 lint: lintd lintl lintd: lint -DARCHCLASS=\"$(PVM_ARCH)\" \ ddpro.c host.c hoster.c imalloc.c pkt.c pmsg.c \ pvmalloc.c pvmcruft.c pvmd.c pvmdtev.c pvmfrag.c pvmlog.c \ task.c tdpro.c waitc.c global.c > Ld lintl: lint -I$(PVMDIR)/include \ lpvm.c lpvmshmem.c lpvmmimd.c \ imalloc.c lpvmcat.c lpvmgen.c lpvmpack.c lpvmglob.c \ pvmalloc.c pvmcruft.c pvmerr.c pvmfrag.c tev.c global.c > Ll amem.o: $(SDIR)/amem.s $(AS) -o amem.o $(SDIR)/amem.s ddpro.o: $(SDIR)/ddpro.c $(CC) $(CFLAGS) -c $(SDIR)/ddpro.c host.o: $(SDIR)/host.c $(CC) $(CFLAGS) -c $(SDIR)/host.c hoster.o: $(SDIR)/hoster.c $(CC) $(CFLAGS) -c $(SDIR)/hoster.c imalloc.o: $(SDIR)/imalloc.c $(CC) $(CFLAGS) -c $(SDIR)/imalloc.c lmsg.o: $(SDIR)/lmsg.c $(NODECC) $(CFLAGS) -DIMA_NODE -c $(SDIR)/lmsg.c lpvm.o: $(SDIR)/lpvm.c $(CC) $(CFLAGS) -c $(SDIR)/lpvm.c lpvmshmem.o: $(SDIR)/lpvmshmem.c $(CC) $(CFLAGS) -c $(SDIR)/lpvmshmem.c $(PLOCKFILE) lpvmmimd.o: $(SDIR)/lpvm.c $(CC) $(CFLAGS) -DIMA_MPP -o lpvmmimd.o -c $(SDIR)/lpvm.c lpvmmpp.o: $(SDIR)/lpvmmpp.c $(NODECC) $(CFLAGS) -DIMA_MPP -c $(SDIR)/lpvmmpp.c lpvmcat.o: $(SDIR)/lpvmcat.c $(CC) $(CFLAGS) -c $(SDIR)/lpvmcat.c lpvmgen.o: $(SDIR)/lpvmgen.c $(CC) $(CFLAGS) -c $(SDIR)/lpvmgen.c lpvmpack.o: $(SDIR)/lpvmpack.c $(CC) $(CFLAGS) -c $(SDIR)/lpvmpack.c lpvmglob.o: $(SDIR)/lpvmglob.c $(CC) $(CFLAGS) -c $(SDIR)/lpvmglob.c msgbox.o: $(SDIR)/msgbox.c $(CC) $(CFLAGS) -c $(SDIR)/msgbox.c mppchunkhost.o: $(SDIR)/mppchunk.c $(CC) $(CFLAGS) -c -o mppchunkhost.o $(SDIR)/mppchunk.c mppchunknode.o: $(SDIR)/mppchunk.c $(NODECC) $(CFLAGS) -DIMA_NODE -c -o mppchunknode.o \ $(SDIR)/mppchunk.c mppmsghost.o: $(SDIR)/mppmsg.c $(CC) $(CFLAGS) -c -o mppmsghost.o $(SDIR)/mppmsg.c mppmsgnode.o: $(SDIR)/mppmsg.c $(NODECC) $(CFLAGS) -DIMA_NODE -c -o mppmsgnode.o $(SDIR)/mppmsg.c nmdclass.o: $(SDIR)/nmdclass.c $(CC) $(CFLAGS) -c $(SDIR)/nmdclass.c pkt.o: $(SDIR)/pkt.c $(CC) $(CFLAGS) -c $(SDIR)/pkt.c pmsg.o: $(SDIR)/pmsg.c $(CC) $(CFLAGS) -c $(SDIR)/pmsg.c pvmalloc.o: $(SDIR)/pvmalloc.c $(CC) $(CFLAGS) -c $(SDIR)/pvmalloc.c pvmcruft.o: $(SDIR)/pvmcruft.c $(CC) $(CFLAGS) -c $(SDIR)/pvmcruft.c pvmd.o: $(SDIR)/pvmd.c $(CC) $(CFLAGS) -c $(SDIR)/pvmd.c pvmdabuf.o: $(SDIR)/pvmdabuf.c $(CC) $(CFLAGS) -c $(SDIR)/pvmdabuf.c pvmdshmem.o: $(SDIR)/pvmdshmem.c $(CC) $(CFLAGS) -c $(SDIR)/pvmdshmem.c $(PLOCKFILE) pvmdmimd.o: pvmdmimd.c $(CC) $(CFLAGS) -I.. -c pvmdmimd.c pvmdpack.o: $(SDIR)/pvmdpack.c $(CC) $(CFLAGS) -c $(SDIR)/pvmdpack.c pvmdunix.o: $(SDIR)/pvmdunix.c $(CC) $(CFLAGS) -c $(SDIR)/pvmdunix.c pvmerr.o: $(SDIR)/pvmerr.c $(CC) $(CFLAGS) -c $(SDIR)/pvmerr.c pvmfrag.o: $(SDIR)/pvmfrag.c $(CC) $(CFLAGS) -c $(SDIR)/pvmfrag.c pvmlog.o: $(SDIR)/pvmlog.c $(CC) $(CFLAGS) -c $(SDIR)/pvmlog.c pvmshmem.o: $(SDIR)/pvmshmem.c $(CC) $(CFLAGS) -c $(SDIR)/pvmshmem.c $(PLOCKFILE) pvmmpp.o: $(SDIR)/pvmmpp.c $(CC) $(CFLAGS) -c $(SDIR)/pvmmpp.c sdpro.o: $(SDIR)/sdpro.c $(CC) $(CFLAGS) -c $(SDIR)/sdpro.c task.o: $(SDIR)/task.c $(CC) $(CFLAGS) -c $(SDIR)/task.c tev.o: $(SDIR)/tev.c $(CC) $(CFLAGS) -c $(SDIR)/tev.c tdpro.o: $(SDIR)/tdpro.c $(CC) $(CFLAGS) -c $(SDIR)/tdpro.c waitc.o: $(SDIR)/waitc.c $(CC) $(CFLAGS) -c $(SDIR)/waitc.c pvmdtev.o: $(SDIR)/pvmdtev.c $(CC) $(CFLAGS) -c $(SDIR)/pvmdtev.c global.o: $(SDIR)/global.c $(CC) $(CFLAGS) -c $(SDIR)/global.c deathapi.o: $(SDIR)/$(PVM_ARCH)/src/deathapi.c $(CC) $(CFLAGS) -c $(SDIR)/$(PVM_ARCH)/src/deathapi.c stdlog.o: $(SDIR)/$(PVM_ARCH)/src/stdlog.c $(CC) $(CFLAGS) -c $(SDIR)/$(PVM_ARCH)/src/stdlog.c sthoster.o: $(SDIR)/$(PVM_ARCH)/src/sthoster.c $(CC) $(CFLAGS) -c $(SDIR)/$(PVM_ARCH)/src/sthoster.c rexec.o: $(SDIR)/$(PVM_ARCH)/src/rexec.c $(CC) $(CFLAGS) -c $(SDIR)/$(PVM_ARCH)/src/rexec.c ruserpas.o: $(SDIR)/$(PVM_ARCH)/src/ruserpas.c $(CC) $(CFLAGS) -c $(SDIR)/$(PVM_ARCH)/src/ruserpas.c os2spawn.o: $(SDIR)/$(PVM_ARCH)/src/os2spawn.c $(CC) $(CFLAGS) -c $(SDIR)/$(PVM_ARCH)/src/os2spawn.c pvmregex.o: $(REGEXDIR)/pvmregex.o cp $(REGEXDIR)/pvmregex.o . regex.o: $(REGEXDIR)/regex.o cp $(REGEXDIR)/regex.o . $(REGEXDIR)/pvmregex.o: $(REGEXCP) cd $(REGEXDIR) ; $(MAKE) $(REGEXOPTS) pvmregex.o $(REGEXDIR)/regex.o: $(REGEXCP) cd $(REGEXDIR) ; $(MAKE) $(REGEXOPTS) regex.o regexconfig: $(REGEXDIR) $(REGEXCP) $(REGEXDIR)/Makefile @ touch regexconfig regexconfig-os2: $(REGEXDIR) $(REGEXCP) cp $(SDIR)/$(PVM_ARCH)/Makefile.reg $(REGEXDIR)/Makefile @ touch regexconfig-os2 $(REGEXDIR)/Makefile: cd $(REGEXDIR) ; CC=$(CC) ./configure $(REGEXCP): $(REGEXSRC) cp $(REGEXSRC) $(REGEXDIR) $(REGEXDIR): @- mkdir $(REGEXDIR) # # Source File Dependencies # include $(PVMDEPPATH)$(SDIR)/pvmdep ./pvm3/src/Makefile.mak0100644007401100000360000001754007024270361014106 0ustar kohlgopher#*************************************************************# # # $Id: Makefile.mak,v 1.11 1999/12/10 21:30:25 pvmsrc Exp $ # # (N)make file for the daemon and pvm library # # PVM_ARCH = the official pvm-name of your processor # ARCHCFLAGS = special cc flags # ARCHLIB = special libs needed for daemon # !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL= !ENDIF !include $(PVM_ROOT)\conf\$(PVM_ARCH).def SDIR = $(PVM_ROOT)\src # "ddpro.c" "host.c" "imalloc.c" "msgbox.c" "pkt.c" "pmsg.c" # "pvmalloc.c" "pvmcruft.c" "pvmd.c" "pvmdabuf.c" "pvmdpack.c" # "pvmdunix.c" "pvmerr.c" "pvmfrag.c" "pvmlog.c" "pvmwin.c" "sdpro.c" # "task.c" "tdpro.c" "waitc.c" "pvmdtev.c" "regex\pvmregex.c" # "regex\regex.c" "global.c" # "..\xdr\xdr.c" "..\xdr\xdr_mem.c" "..\xdr\xdr_floa.c" # # GNU Regex Defines - adjust if needed # REGEXOBJS = REGEXOBJS = $(PVM_ARCH)\pvmregex.obj $(PVM_ARCH)\regex.obj # # PVM Daemon & Library Objects # DOBJ = $(PVM_ARCH)\ddpro.obj $(PVM_ARCH)\host.obj \ $(PVM_ARCH)\imalloc.obj $(PVM_ARCH)\msgbox.obj \ $(PVM_ARCH)\pkt.obj $(PVM_ARCH)\pmsg.obj \ $(PVM_ARCH)\pvmalloc.obj $(PVM_ARCH)\pvmcruft.obj \ $(PVM_ARCH)\pvmd.obj $(PVM_ARCH)\pvmdabuf.obj \ $(PVM_ARCH)\pvmdpack.obj $(PVM_ARCH)\pvmdunix.obj \ $(PVM_ARCH)\pvmerr.obj $(PVM_ARCH)\pvmfrag.obj \ $(PVM_ARCH)\pvmlog.obj $(PVM_ARCH)\pvmwin.obj \ $(PVM_ARCH)\sdpro.obj $(PVM_ARCH)\task.obj \ $(PVM_ARCH)\tdpro.obj $(PVM_ARCH)\waitc.obj \ $(PVM_ARCH)\pvmdtev.obj $(PVM_ARCH)\global.obj \ $(PVM_ARCH)\xdr.obj $(PVM_ARCH)\xdr_mem.obj \ $(PVM_ARCH)\xdr_floa.obj $(REGEXOBJS) LOBJ = $(PVM_ARCH)\imalloc.obj $(PVM_ARCH)\lpvm.obj \ $(PVM_ARCH)\lpvmcat.obj $(PVM_ARCH)\lpvmgen.obj \ $(PVM_ARCH)\tev.obj $(PVM_ARCH)\lpvmpack.obj \ $(PVM_ARCH)\pvmalloc.obj $(PVM_ARCH)\pmsg.obj \ $(PVM_ARCH)\pvmcruft.obj $(PVM_ARCH)\pvmdabuf.obj \ $(PVM_ARCH)\pvmfrag.obj $(PVM_ARCH)\global.obj \ $(PVM_ARCH)\pvmerr.obj $(PVM_ARCH)\lpvmglob.obj \ $(PVM_ARCH)\pvmwin.obj $(PVM_ARCH)\xdr.obj \ $(PVM_ARCH)\xdr_floa.obj $(PVM_ARCH)\xdr_mem.obj \ $(PVM_ARCH)\waitc.obj \ $(PVM_ARCH)\pvmdpack.obj all: paths libpvm3.lib $(pvmd3exe) $(libpvm3dll) paths: if not exist "..\lib\$(PVM_ARCH)\$(NULL)" mkdir "..\lib\$(PVM_ARCH)" if not exist "..\bin\$(PVM_ARCH)\$(NULL)" mkdir "..\bin\$(PVM_ARCH)" if not exist "$(PVM_ARCH)\$(NULL)" mkdir "$(PVM_ARCH)" libpvm3.lib: $(LOBJ) $(linklib) $(conflags) \ $(OUTLIB)$(PVM_ROOT)\lib\$(PVM_ARCH)\libpvm3.lib $(LOBJ) libpvm3.dll: $(LOBJ) $(linkdll) $(conflags) \ $(OUTDLL)$(PVM_ROOT)\lib\$(PVM_ARCH)\libpvm3.dll $(LOBJ) \ $(link_flags) visual_pvmd3.exe: $(DOBJ) $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\lib\win32\pvmd3.exe \ $(FILE) $(BEGIN) $(DOBJ) $(END) $(link_flags) $(PVM_ARCH)\imalloc.obj: $(SDIR)\imalloc.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\imalloc.obj $(SDIR)\imalloc.c $(PVM_ARCH)\msgbox.obj: $(SDIR)\msgbox.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\msgbox.obj $(SDIR)\msgbox.c $(PVM_ARCH)\pmsg.obj: $(SDIR)\pmsg.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\pmsg.obj $(SDIR)\pmsg.c $(PVM_ARCH)\pkt.obj: $(SDIR)\pkt.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\pkt.obj $(SDIR)\pkt.c $(PVM_ARCH)\pvmalloc.obj: $(SDIR)\pvmalloc.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\pvmalloc.obj \ $(SDIR)\pvmalloc.c $(PVM_ARCH)\pvmdpack.obj: $(SDIR)\pvmdpack.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\pvmdpack.obj \ $(SDIR)\pvmdpack.c $(PVM_ARCH)\pvmerr.obj: $(SDIR)\pvmerr.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\pvmerr.obj $(SDIR)\pvmerr.c $(PVM_ARCH)\pvmlog.obj: $(SDIR)\pvmlog.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\pvmlog.obj $(SDIR)\pvmlog.c $(PVM_ARCH)\pvmdabuf.obj: $(SDIR)\pvmdabuf.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\pvmdabuf.obj \ $(SDIR)\pvmdabuf.c $(PVM_ARCH)\host.obj: $(SDIR)\host.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\host.obj $(SDIR)\host.c $(PVM_ARCH)\pvmfrag.obj: $(SDIR)\pvmfrag.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\pvmfrag.obj $(SDIR)\pvmfrag.c $(PVM_ARCH)\lpvmglob.obj: $(SDIR)\lpvmglob.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\lpvmglob.obj \ $(SDIR)\lpvmglob.c $(PVM_ARCH)\pvmcruft.obj: $(SDIR)\pvmcruft.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\pvmcruft.obj \ $(SDIR)\pvmcruft.c $(PVM_ARCH)\pvmdunix.obj: $(SDIR)\pvmdunix.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\pvmdunix.obj \ $(SDIR)\pvmdunix.c $(PVM_ARCH)\pvmwin.obj: $(SDIR)\pvmwin.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\pvmwin.obj $(SDIR)\pvmwin.c $(PVM_ARCH)\sdpro.obj: $(SDIR)\sdpro.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\sdpro.obj $(SDIR)\sdpro.c $(PVM_ARCH)\global.obj: $(SDIR)\global.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\global.obj $(SDIR)\global.c $(PVM_ARCH)\task.obj: $(SDIR)\task.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\task.obj $(SDIR)\task.c $(PVM_ARCH)\tdpro.obj: $(SDIR)\tdpro.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\tdpro.obj $(SDIR)\tdpro.c $(PVM_ARCH)\ddpro.obj: $(SDIR)\ddpro.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\ddpro.obj $(SDIR)\ddpro.c $(PVM_ARCH)\pvmdtev.obj: $(SDIR)\pvmdtev.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\pvmdtev.obj $(SDIR)\pvmdtev.c $(PVM_ARCH)\pvmd.obj: $(SDIR)\pvmd.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\pvmd.obj $(SDIR)\pvmd.c $(PVM_ARCH)\pvmregex.obj: $(SDIR)\regex\pvmregex.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\pvmregex.obj \ $(SDIR)\regex\pvmregex.c $(PVM_ARCH)\regex.obj: $(SDIR)\regex\regex.c $(cc) $(cdebug) $(cflags) $(cvars) -DREGEX_MALLOC -DHAVE_STRING_H \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\regex.obj \ $(SDIR)\regex\regex.c $(PVM_ARCH)\waitc.obj: $(SDIR)\waitc.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\waitc.obj $(SDIR)\waitc.c $(PVM_ARCH)\tev.obj: $(SDIR)\tev.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\tev.obj $(SDIR)\tev.c $(PVM_ARCH)\lpvm.obj: $(SDIR)\lpvm.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\lpvm.obj $(SDIR)\lpvm.c $(PVM_ARCH)\lpvmcat.obj: $(SDIR)\lpvmcat.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\lpvmcat.obj $(SDIR)\lpvmcat.c $(PVM_ARCH)\lpvmgen.obj: $(SDIR)\lpvmgen.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\lpvmgen.obj $(SDIR)\lpvmgen.c $(PVM_ARCH)\lpvmpack.obj: $(SDIR)\lpvmpack.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\lpvmpack.obj \ $(SDIR)\lpvmpack.c $(PVM_ARCH)\xdr_mem.obj: $(PVM_ROOT)\xdr\xdr_mem.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\xdr_mem.obj \ $(PVM_ROOT)\xdr\xdr_mem.c $(PVM_ARCH)\xdr_floa.obj: $(PVM_ROOT)\xdr\xdr_floa.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\xdr_floa.obj \ $(PVM_ROOT)\xdr\xdr_floa.c $(PVM_ARCH)\xdr.obj: $(PVM_ROOT)\xdr\xdr.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\xdr.obj $(PVM_ROOT)\xdr\xdr.c $(PVM_ARCH)\pvmarchc.obj: $(SDIR)\pvmarchc.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\pvmarchc.obj \ $(SDIR)\pvmarchc.c $(PVM_ARCH)\pvmumbuf.obj: $(SDIR)\pvmumbuf.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ROOT)\src\$(PVM_ARCH)\pvmumbuf.obj \ $(SDIR)\pvmumbuf.c # Clean up everything but the .EXEs clean : -del $(PVM_ARCH)\*.obj ./pvm3/src/pvmdep0100644007401100000360000002434206352043024013110 0ustar kohlgopher# # *** DO NOT MODIFY *** AUTOMATICALLY GENERATED *** # # $Id: pvmdep,v 1.3 1997/06/18 20:33:24 pvmsrc Exp $ # # PVM Source Header Dependencies # ddpro.o: $(PVMDIR)/include/pvm3.h ddpro.o: $(PVMDIR)/include/pvmproto.h ddpro.o: $(PVMDIR)/include/pvmtev.h ddpro.o: $(SDIR)/bfunc.h ddpro.o: $(SDIR)/global.h ddpro.o: $(SDIR)/host.h ddpro.o: $(SDIR)/listmac.h ddpro.o: $(SDIR)/msgbox.h ddpro.o: $(SDIR)/pmsg.h ddpro.o: $(SDIR)/pvmalloc.h ddpro.o: $(SDIR)/task.h ddpro.o: $(SDIR)/waitc.h global.o: $(PVMDIR)/include/pvm3.h global.o: $(PVMDIR)/include/pvmtev.h global.o: $(SDIR)/global.h global.o: $(SDIR)/host.h global.o: $(SDIR)/lpvm.h global.o: $(SDIR)/mppchunk.h global.o: $(SDIR)/mppmsg.h global.o: $(SDIR)/msgbox.h global.o: $(SDIR)/pkt.h global.o: $(SDIR)/pmsg.h global.o: $(SDIR)/tevmac.h global.o: $(SDIR)/waitc.h host.o: $(PVMDIR)/include/pvm3.h host.o: $(PVMDIR)/include/pvmproto.h host.o: $(SDIR)/bfunc.h host.o: $(SDIR)/global.h host.o: $(SDIR)/host.h host.o: $(SDIR)/pkt.h host.o: $(SDIR)/pmsg.h host.o: $(SDIR)/pvmalloc.h hoster.o: $(PVMDIR)/include/pvm3.h hoster.o: $(PVMDIR)/include/pvmproto.h hoster.o: $(SDIR)/bfunc.h hoster.o: $(SDIR)/global.h hoster.o: $(SDIR)/host.h hoster.o: $(SDIR)/listmac.h hoster.o: $(SDIR)/pmsg.h hoster.o: $(SDIR)/pvmalloc.h hoster.o: $(SDIR)/tvdefs.h imalloc.o: $(SDIR)/bfunc.h lmsg.o: $(PVMDIR)/include/pvm3.h lmsg.o: $(SDIR)/listmac.h lmsg.o: $(SDIR)/lmsg.h lmsg.o: $(SDIR)/mppmsg.h lmsg.o: $(SDIR)/pvmalloc.h lmsg.o: $(SDIR)/pvmdabuf.h lmsg.o: $(SDIR)/pvmmagic.h lpvm.o: $(PVMDIR)/include/pvm3.h lpvm.o: $(PVMDIR)/include/pvmproto.h lpvm.o: $(PVMDIR)/include/pvmtev.h lpvm.o: $(SDIR)/bfunc.h lpvm.o: $(SDIR)/global.h lpvm.o: $(SDIR)/host.h lpvm.o: $(SDIR)/listmac.h lpvm.o: $(SDIR)/lmsg.h lpvm.o: $(SDIR)/lpvm.h lpvm.o: $(SDIR)/mppchunk.h lpvm.o: $(SDIR)/mppmsg.h lpvm.o: $(SDIR)/pkt.h lpvm.o: $(SDIR)/pmsg.h lpvm.o: $(SDIR)/pvmalloc.h lpvm.o: $(SDIR)/pvmfrag.h lpvm.o: $(SDIR)/pvmmimd.h lpvm.o: $(SDIR)/tevmac.h lpvm.o: $(SDIR)/tvdefs.h lpvm.o: $(SDIR)/waitc.h lpvmcat.o: $(PVMDIR)/include/pvm3.h lpvmcat.o: $(PVMDIR)/include/pvmproto.h lpvmcat.o: $(PVMDIR)/include/pvmtev.h lpvmcat.o: $(SDIR)/bfunc.h lpvmcat.o: $(SDIR)/global.h lpvmcat.o: $(SDIR)/listmac.h lpvmcat.o: $(SDIR)/lpvm.h lpvmcat.o: $(SDIR)/mppchunk.h lpvmcat.o: $(SDIR)/mppmsg.h lpvmcat.o: $(SDIR)/pkt.h lpvmcat.o: $(SDIR)/pvmalloc.h lpvmcat.o: $(SDIR)/tevmac.h lpvmcat.o: $(SDIR)/tvdefs.h lpvmgen.o: $(PVMDIR)/include/pvm3.h lpvmgen.o: $(PVMDIR)/include/pvmproto.h lpvmgen.o: $(PVMDIR)/include/pvmtev.h lpvmgen.o: $(SDIR)/bfunc.h lpvmgen.o: $(SDIR)/global.h lpvmgen.o: $(SDIR)/host.h lpvmgen.o: $(SDIR)/listmac.h lpvmgen.o: $(SDIR)/lpvm.h lpvmgen.o: $(SDIR)/mppchunk.h lpvmgen.o: $(SDIR)/mppmsg.h lpvmgen.o: $(SDIR)/pkt.h lpvmgen.o: $(SDIR)/pmsg.h lpvmgen.o: $(SDIR)/pvmalloc.h lpvmgen.o: $(SDIR)/tevmac.h lpvmgen.o: $(SDIR)/tvdefs.h lpvmgen.o: $(SDIR)/waitc.h lpvmglob.o: $(PVMDIR)/include/pvm3.h lpvmglob.o: $(PVMDIR)/include/pvmtev.h lpvmglob.o: $(SDIR)/global.h lpvmglob.o: $(SDIR)/host.h lpvmglob.o: $(SDIR)/pmsg.h lpvmglob.o: $(SDIR)/tevmac.h lpvmglob.o: $(SDIR)/waitc.h lpvmmimd.o: $(PVMDIR)/include/pvm3.h lpvmmimd.o: $(PVMDIR)/include/pvmproto.h lpvmmimd.o: $(PVMDIR)/include/pvmtev.h lpvmmimd.o: $(SDIR)/bfunc.h lpvmmimd.o: $(SDIR)/global.h lpvmmimd.o: $(SDIR)/listmac.h lpvmmimd.o: $(SDIR)/lpvm.h lpvmmimd.o: $(SDIR)/mppchunk.h lpvmmimd.o: $(SDIR)/mppmsg.h lpvmmimd.o: $(SDIR)/pkt.h lpvmmimd.o: $(SDIR)/pmsg.h lpvmmimd.o: $(SDIR)/pvmalloc.h lpvmmimd.o: $(SDIR)/pvmdmp.h lpvmmimd.o: $(SDIR)/pvmfrag.h lpvmmimd.o: $(SDIR)/pvmmimd.h lpvmmimd.o: $(SDIR)/tevmac.h lpvmmpp.o: $(PVMDIR)/include/pvm3.h lpvmmpp.o: $(PVMDIR)/include/pvmproto.h lpvmmpp.o: $(PVMDIR)/include/pvmtev.h lpvmmpp.o: $(SDIR)/bfunc.h lpvmmpp.o: $(SDIR)/global.h lpvmmpp.o: $(SDIR)/listmac.h lpvmmpp.o: $(SDIR)/lmsg.h lpvmmpp.o: $(SDIR)/lpvm.h lpvmmpp.o: $(SDIR)/mppchunk.h lpvmmpp.o: $(SDIR)/mppmsg.h lpvmmpp.o: $(SDIR)/pkt.h lpvmmpp.o: $(SDIR)/pmsg.h lpvmmpp.o: $(SDIR)/pvmalloc.h lpvmmpp.o: $(SDIR)/pvmfrag.h lpvmmpp.o: $(SDIR)/pvmmimd.h lpvmmpp.o: $(SDIR)/tevmac.h lpvmpack.o: $(PVMDIR)/include/pvm3.h lpvmpack.o: $(PVMDIR)/include/pvmproto.h lpvmpack.o: $(PVMDIR)/include/pvmtev.h lpvmpack.o: $(SDIR)/bfunc.h lpvmpack.o: $(SDIR)/global.h lpvmpack.o: $(SDIR)/listmac.h lpvmpack.o: $(SDIR)/lpvm.h lpvmpack.o: $(SDIR)/mppchunk.h lpvmpack.o: $(SDIR)/mppmsg.h lpvmpack.o: $(SDIR)/pkt.h lpvmpack.o: $(SDIR)/pmsg.h lpvmpack.o: $(SDIR)/pvmalloc.h lpvmpack.o: $(SDIR)/pvmfrag.h lpvmpack.o: $(SDIR)/tevmac.h lpvmshmem.o: $(PVMDIR)/include/pvm3.h lpvmshmem.o: $(PVMDIR)/include/pvmproto.h lpvmshmem.o: $(PVMDIR)/include/pvmtev.h lpvmshmem.o: $(SDIR)/bfunc.h lpvmshmem.o: $(SDIR)/global.h lpvmshmem.o: $(SDIR)/host.h lpvmshmem.o: $(SDIR)/listmac.h lpvmshmem.o: $(SDIR)/lpvm.h lpvmshmem.o: $(SDIR)/mppchunk.h lpvmshmem.o: $(SDIR)/mppmsg.h lpvmshmem.o: $(SDIR)/pkt.h lpvmshmem.o: $(SDIR)/pmsg.h lpvmshmem.o: $(SDIR)/pvmalloc.h lpvmshmem.o: $(SDIR)/pvmdabuf.h lpvmshmem.o: $(SDIR)/pvmfrag.h lpvmshmem.o: $(SDIR)/pvmshmem.h lpvmshmem.o: $(SDIR)/tevmac.h lpvmshmem.o: $(SDIR)/waitc.h mppchunk.o: $(PVMDIR)/include/pvm3.h mppchunk.o: $(PVMDIR)/include/pvmproto.h mppchunk.o: $(SDIR)/bfunc.h mppchunk.o: $(SDIR)/global.h mppchunk.o: $(SDIR)/listmac.h mppchunk.o: $(SDIR)/lmsg.h mppchunk.o: $(SDIR)/mppchunk.h mppchunk.o: $(SDIR)/mppmsg.h mppchunk.o: $(SDIR)/pkt.h mppchunk.o: $(SDIR)/pvmalloc.h mppchunk.o: $(SDIR)/pvmmimd.h mppmsg.o: $(PVMDIR)/include/pvm3.h mppmsg.o: $(PVMDIR)/include/pvmproto.h mppmsg.o: $(SDIR)/bfunc.h mppmsg.o: $(SDIR)/global.h mppmsg.o: $(SDIR)/listmac.h mppmsg.o: $(SDIR)/lmsg.h mppmsg.o: $(SDIR)/lpvm.h mppmsg.o: $(SDIR)/mppchunk.h mppmsg.o: $(SDIR)/mppmsg.h mppmsg.o: $(SDIR)/pkt.h mppmsg.o: $(SDIR)/pvmalloc.h mppmsg.o: $(SDIR)/pvmmimd.h msgbox.o: $(PVMDIR)/include/pvm3.h msgbox.o: $(SDIR)/global.h msgbox.o: $(SDIR)/listmac.h msgbox.o: $(SDIR)/msgbox.h msgbox.o: $(SDIR)/pmsg.h msgbox.o: $(SDIR)/pvmalloc.h nmdclass.o: $(PVMDIR)/include/pvm3.h nmdclass.o: $(SDIR)/listmac.h nmdclass.o: $(SDIR)/pvmalloc.h pkt.o: $(PVMDIR)/include/pvm3.h pkt.o: $(SDIR)/bfunc.h pkt.o: $(SDIR)/listmac.h pkt.o: $(SDIR)/pkt.h pkt.o: $(SDIR)/pvmalloc.h pkt.o: $(SDIR)/pvmdabuf.h pmsg.o: $(PVMDIR)/include/pvm3.h pmsg.o: $(PVMDIR)/include/pvmproto.h pmsg.o: $(PVMDIR)/include/pvmtev.h pmsg.o: $(SDIR)/bfunc.h pmsg.o: $(SDIR)/global.h pmsg.o: $(SDIR)/listmac.h pmsg.o: $(SDIR)/lpvm.h pmsg.o: $(SDIR)/mppchunk.h pmsg.o: $(SDIR)/mppmsg.h pmsg.o: $(SDIR)/pkt.h pmsg.o: $(SDIR)/pmsg.h pmsg.o: $(SDIR)/pvmalloc.h pmsg.o: $(SDIR)/pvmfrag.h pvmalloc.o: $(PVMDIR)/include/pvm3.h pvmalloc.o: $(SDIR)/pvmalloc.h pvmcruft.o: $(PVMDIR)/include/pvm3.h pvmcruft.o: $(PVMDIR)/include/pvmproto.h pvmcruft.o: $(SDIR)/global.h pvmcruft.o: $(SDIR)/lpvm.h pvmcruft.o: $(SDIR)/mppchunk.h pvmcruft.o: $(SDIR)/mppmsg.h pvmcruft.o: $(SDIR)/pkt.h pvmcruft.o: $(SDIR)/pvmalloc.h pvmd.o: $(PVMDIR)/include/pvm3.h pvmd.o: $(PVMDIR)/include/pvmproto.h pvmd.o: $(PVMDIR)/include/pvmtev.h pvmd.o: $(SDIR)/bfunc.h pvmd.o: $(SDIR)/global.h pvmd.o: $(SDIR)/host.h pvmd.o: $(SDIR)/listmac.h pvmd.o: $(SDIR)/pkt.h pvmd.o: $(SDIR)/pmsg.h pvmd.o: $(SDIR)/pvmalloc.h pvmd.o: $(SDIR)/pvmdabuf.h pvmd.o: $(SDIR)/pvmfrag.h pvmd.o: $(SDIR)/task.h pvmd.o: $(SDIR)/tvdefs.h pvmd.o: $(SDIR)/waitc.h pvmdabuf.o: $(PVMDIR)/include/pvm3.h pvmdabuf.o: $(SDIR)/pvmalloc.h pvmdpack.o: $(PVMDIR)/include/pvm3.h pvmdpack.o: $(SDIR)/global.h pvmdpack.o: $(SDIR)/listmac.h pvmdpack.o: $(SDIR)/pmsg.h pvmdpack.o: $(SDIR)/pvmalloc.h pvmdpack.o: $(SDIR)/pvmfrag.h pvmdshmem.o: $(PVMDIR)/include/pvm3.h pvmdshmem.o: $(PVMDIR)/include/pvmproto.h pvmdshmem.o: $(SDIR)/bfunc.h pvmdshmem.o: $(SDIR)/global.h pvmdshmem.o: $(SDIR)/host.h pvmdshmem.o: $(SDIR)/listmac.h pvmdshmem.o: $(SDIR)/pkt.h pvmdshmem.o: $(SDIR)/pvmalloc.h pvmdshmem.o: $(SDIR)/pvmdabuf.h pvmdshmem.o: $(SDIR)/pvmshmem.h pvmdshmem.o: $(SDIR)/task.h pvmdshmem.o: $(SDIR)/waitc.h pvmdtev.o: $(PVMDIR)/include/pvm3.h pvmdtev.o: $(PVMDIR)/include/pvmproto.h pvmdtev.o: $(PVMDIR)/include/pvmtev.h pvmdtev.o: $(SDIR)/global.h pvmdtev.o: $(SDIR)/pmsg.h pvmdtev.o: $(SDIR)/tevmac.h pvmdunix.o: $(PVMDIR)/include/pvm3.h pvmdunix.o: $(PVMDIR)/include/pvmproto.h pvmdunix.o: $(PVMDIR)/include/pvmtev.h pvmdunix.o: $(SDIR)/bfunc.h pvmdunix.o: $(SDIR)/global.h pvmdunix.o: $(SDIR)/host.h pvmdunix.o: $(SDIR)/listmac.h pvmdunix.o: $(SDIR)/pmsg.h pvmdunix.o: $(SDIR)/pvmalloc.h pvmdunix.o: $(SDIR)/task.h pvmdunix.o: $(SDIR)/waitc.h pvmerr.o: $(PVMDIR)/include/pvm3.h pvmerr.o: $(SDIR)/global.h pvmerr.o: $(SDIR)/lpvm.h pvmerr.o: $(SDIR)/mppchunk.h pvmerr.o: $(SDIR)/mppmsg.h pvmerr.o: $(SDIR)/pkt.h pvmfrag.o: $(PVMDIR)/include/pvm3.h pvmfrag.o: $(SDIR)/listmac.h pvmfrag.o: $(SDIR)/pvmalloc.h pvmfrag.o: $(SDIR)/pvmdabuf.h pvmfrag.o: $(SDIR)/pvmfrag.h pvmshmem.o: $(PVMDIR)/include/pvm3.h pvmshmem.o: $(PVMDIR)/include/pvmproto.h pvmshmem.o: $(SDIR)/bfunc.h pvmshmem.o: $(SDIR)/global.h pvmshmem.o: $(SDIR)/listmac.h pvmshmem.o: $(SDIR)/pvmalloc.h pvmshmem.o: $(SDIR)/pvmshmem.h sdpro.o: $(PVMDIR)/include/pvm3.h sdpro.o: $(PVMDIR)/include/pvmproto.h sdpro.o: $(SDIR)/bfunc.h sdpro.o: $(SDIR)/global.h sdpro.o: $(SDIR)/host.h sdpro.o: $(SDIR)/pmsg.h sdpro.o: $(SDIR)/pvmalloc.h sdpro.o: $(SDIR)/task.h sdpro.o: $(SDIR)/waitc.h task.o: $(PVMDIR)/include/pvm3.h task.o: $(PVMDIR)/include/pvmproto.h task.o: $(PVMDIR)/include/pvmtev.h task.o: $(SDIR)/bfunc.h task.o: $(SDIR)/global.h task.o: $(SDIR)/host.h task.o: $(SDIR)/listmac.h task.o: $(SDIR)/msgbox.h task.o: $(SDIR)/pkt.h task.o: $(SDIR)/pmsg.h task.o: $(SDIR)/pvmalloc.h task.o: $(SDIR)/task.h task.o: $(SDIR)/waitc.h tdpro.o: $(PVMDIR)/include/pvm3.h tdpro.o: $(PVMDIR)/include/pvmproto.h tdpro.o: $(PVMDIR)/include/pvmtev.h tdpro.o: $(SDIR)/bfunc.h tdpro.o: $(SDIR)/global.h tdpro.o: $(SDIR)/host.h tdpro.o: $(SDIR)/listmac.h tdpro.o: $(SDIR)/pmsg.h tdpro.o: $(SDIR)/pvmalloc.h tdpro.o: $(SDIR)/task.h tdpro.o: $(SDIR)/waitc.h tev.o: $(PVMDIR)/include/pvm3.h tev.o: $(PVMDIR)/include/pvmtev.h tev.o: $(SDIR)/global.h tev.o: $(SDIR)/lpvm.h tev.o: $(SDIR)/mppchunk.h tev.o: $(SDIR)/mppmsg.h tev.o: $(SDIR)/pkt.h tev.o: $(SDIR)/pmsg.h tev.o: $(SDIR)/tevmac.h tev.o: $(SDIR)/tvdefs.h waitc.o: $(PVMDIR)/include/pvm3.h waitc.o: $(PVMDIR)/include/pvmproto.h waitc.o: $(SDIR)/bfunc.h waitc.o: $(SDIR)/global.h waitc.o: $(SDIR)/host.h waitc.o: $(SDIR)/listmac.h waitc.o: $(SDIR)/lpvm.h waitc.o: $(SDIR)/mppchunk.h waitc.o: $(SDIR)/mppmsg.h waitc.o: $(SDIR)/pkt.h waitc.o: $(SDIR)/pmsg.h waitc.o: $(SDIR)/pvmalloc.h waitc.o: $(SDIR)/waitc.h ./pvm3/src/ddpro.c0100644007401100000360000021770710001307617013154 0ustar kohlgopher static char rcsid[] = "$Id: ddpro.c,v 1.48 2004/01/14 18:50:55 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * ddpro.c * * Entry points for messages from network. * * $Log: ddpro.c,v $ * Revision 1.48 2004/01/14 18:50:55 pvmsrc * Added new AIX5* arches. * (Spanker=kohl) * * Revision 1.47 2002/04/16 15:06:00 pvmsrc * WIN32 Fixes for Multiple Domains. * - submitted by Jigen Zhou . * (Spanker=kohl) * * Revision 1.46 2002/02/21 23:18:40 pvmsrc * Added new (not to be documented!) PVM_MAX_TASKS env var support. * - for Mahir Lokvancic . * - forcefully limits the number of tasks that can attach to a * pvmd, required on Solaris in rare circumstances when hard * FD_SETSIZE limit is reached, and all hell breaks loose... * - check return for task_new() call, can now produce NULL ptr, * indicating PvmOutOfRes... * (Spanker=kohl) * * Revision 1.45 2001/09/26 23:35:19 pvmsrc * Added new hd_vmid to hostd struct. * - use to override local PVM_VMID settings with hostfile "id=" option * (Spanker=kohl) * * Revision 1.44 2001/09/26 21:22:16 pvmsrc * Added Handling for Optional Virtual Machine ID. * - extra vmid comes through with SM_STHOST message (after wincmd). * - instruct user to type VMID on remote pvmd stdin for manual startup * - in phase1(), after potential rsh/rexec, write VMID env string * to remote pvmd's stdin. * (Spanker=kohl) * * Revision 1.43 2001/05/11 17:31:56 pvmsrc * Cast getcwd() call, in case header file sucks. * - eliminates warning message on compile... * (Spanker=kohl) * * Revision 1.42 2001/04/23 14:16:13 pvmsrc * Added new working directory option to pvm_spawn(). * - use "where" argument to cram in working directory, * e.g. where = "msr.epm.ornl.gov:/home/user/project/bozo" * - TM_SPAWN strips out working directory & creates PVMSPAWNWD env var * - exectasks() (called by DM_EXEC or SM_EXEC) checks for env var * and does a chdir() (even uses getcwd() to reset directory :-). * - should not introduce any run-time incompatibility with older * PVM releases. * - PvmTaskHost or PvmTaskArch flags need not be used, i.e. * pvm_spawn( "foo", 0, PvmTaskDefault, ":/tmp", 1, &tid ) works. * (Spanker=kohl) * * Revision 1.41 2001/02/07 23:14:02 pvmsrc * First Half of CYGWIN Check-ins... * (Spanker=kohl) * * Revision 1.40 2000/06/16 16:27:32 pvmsrc * DAMN. The seemingly cool and efficient tp->t_flag / TF_MBNOTIFY * solution is not as cool as previously thought. * - each pvmd only keeps a *local* tasks table...! D-OH! * - need to just search the wait context list for an existing * WT_TASKX mbox notify, as previously feared. * - already checking wait context list for WT_RECVINFO, so this * is not too terrible... * - Damn, though... * Removed TF_MBNOTIFY contant - now fricking useless. * (Spanker=kohl) * * Revision 1.39 2000/06/13 22:37:56 pvmsrc * In dm_db(): * - on successful insert, check whether task already had an mbox * notify (for mb_tidy()) set up. * - after first such notify / waitc created, set tp->t_flag * TF_MBNOTIFY bit. * - this avoids a HUGE number of redundant notifies for multiple * inserts by the same task. D-Oh! * (Spanker=kohl) * * Revision 1.38 2000/02/17 23:12:08 pvmsrc * *** Changes for new BEOLIN port *** * - MPP-like, similar to SP2, etc. * - submitted by Paul Springer . * - format-checked & cleaned up by Jeembo... :-) * (Spanker=kohl) * * Revision 1.37 2000/02/16 21:59:38 pvmsrc * Fixed up #include stuff... * - use for IMA_TITN... * - #include before any NEEDMENDIAN #includes... * (Spanker=kohl) * * Revision 1.36 2000/02/10 23:53:35 pvmsrc * Added new PvmIPLoopback error code: * - Master Host IP Address tied to Loopback. * - check for this case in addhosts(), don't even TRY to add hosts... * (Spanker=kohl) * * Revision 1.35 1999/08/19 15:39:22 pvmsrc * Whoa... New wincmd stuff was whacking addhost protocol! * - *always* pack in something for wincmd, else the attempt to unpack * "possible" wincmd will snag start of next host's startup info... * - damn. * (Spanker=kohl) * * Revision 1.34 1999/07/08 18:59:50 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.33 1999/03/05 17:21:23 pvmsrc * improved to work with registry/environment on NT/win95-98 * and devstudio 5/6 * (Spanker=sscott) * * Revision 1.32 1999/02/10 22:38:24 pvmsrc * Fixed passing of pvmdebmask to new / slave pvmds... * - need to do -d0x%x to insure interpreted as hex (not just -d%x). * - report submitted by Paul Springer . * (Spanker=kohl) * * Revision 1.31 1999/01/28 18:55:30 pvmsrc * Modified logic to allow alternate WIN32 pvmd path. * - use new PVM_WINDPATH env var if set, else new WINPVMDPATH define. * - append alternate WIN32 command path to end of SM_STHOST message, * so smart hosters (and pvmd' running hoster()) can unpack it * and use it if the default Unix pvmd path fails to start a pvmd. * (Spanker=kohl) * * Revision 1.30 1998/10/02 15:43:55 pvmsrc * Single source code merge of Win32 and Unix code. * (Spanker=sscott) * * Revision 1.29 1998/02/23 22:51:24 pvmsrc * Added AIX4SP2 stuff. * (Spanker=kohl) * * Revision 1.28 1998/01/12 21:13:22 pvmsrc * Replaced inline constants with new task output op defines. * - TO_NEW == -2. * - TO_SPAWN == -1. * - TO_EOF == 0. * (Spanker=kohl) * * Revision 1.27 1997/08/29 13:34:59 pvmsrc * OS2 Port Submitted by Bohumir Horeni, horeni@login.cz. * (Spanker=kohl) * * Revision 1.26 1997/08/26 22:55:25 pvmsrc * Make sure wp->wa_mesg is cleared after sendmessage() call. * - otherwise wait_delete() will re-free the pmsg struct causing * major bogusness... * (Spanker=kohl) * * Revision 1.25 1997/08/18 19:08:37 pvmsrc * Cleaned up dm_pstatack() routine. * - had leftover pmsg_dump() calls in it, was cluttering * up /tmp/pvml.. * (Spanker=kohl) * * Revision 1.24 1997/06/27 18:03:30 pvmsrc * Integrated WIN32 changes. * * Revision 1.23 1997/06/17 19:04:26 pvmsrc * Enhanced WT_SPAWN case in hostfailentry(). * - for PvmTaskDefault, if the host that the pvmd picked has failed, * go ahead and retry spawning it on another host. * * Revision 1.22 1997/06/16 13:39:44 pvmsrc * Updated exectasks() to pass additional information during spawn ops. * * Revision 1.21 1997/05/19 21:18:13 pvmsrc * Awwww Shit. I did it. * - crunchzap() sux, can't free buf in startack() until ac/av used. * * Revision 1.20 1997/05/12 20:28:17 pvmsrc * Removed duplicate #includes... * * Revision 1.19 1997/05/07 21:22:07 pvmsrc * AAAIIIEEEEEEEEE!!!! * - removed all static-limited string unpacking: * * replaced with use of: * upkstralloc() / PVM_FREE() (for pvmd stuff). * new pvmupkstralloc() / PVM_FREE() (for lpvm stuff). * * manual allocation of local buffers for sprintf() & packing. * * alternate static string arrays to replace fixed-length cases. * * I hope this shit works... :-Q * * Revision 1.18 1997/05/02 13:43:43 pvmsrc * call mpp_load for SP2MPI * * Revision 1.17 1997/04/30 21:25:54 pvmsrc * SGI Compiler Warning Cleanup. * * Revision 1.16 1997/04/10 18:59:06 pvmsrc * Damn. Stupid typo (as opposed to a smart one?). * * Revision 1.15 1997/04/10 18:46:56 pvmsrc * Bug fix in dm_db(): * - return value for mb_lookup() call was overwriting req index, * need to save req in case PvmMboxWaitForInfo... * * Revision 1.14 1997/04/10 18:32:03 pvmsrc * Damn. Forgot the stupid PvmMboxWaitForInfo flag check... D-Oh! * * Revision 1.13 1997/04/10 17:53:19 pvmsrc * Added handling of blocking (PvmMboxWaitForInfo) calls to pvm_recvinfo(). * - in dm_db(), on TMDB_GET, if not found create WT_RECVINFO. * - in dm_db(), on TMDB_PUT, check for matching WT_RECVINFO & release. * - in hostfailentry(), wipe out any pending WT_RECVINFOs if host * where task resided is now toast. * * Revision 1.12 1997/04/09 19:37:56 pvmsrc * Added class name and index args to pvmreset() routine: * - allow systematic elimination of leftover persistents... * - heh, heh, heh... * In dm_db(), check for name (class) and req (index) match * for TMDB_RESET case (""/-1 for all, resp). * * Revision 1.11 1997/04/09 14:36:06 pvmsrc * PVM patches from the base 3.3.10 to 3.3.11 versions where applicable. * Originals by Bob Manchek. Altered by Graham Fagg where required. * * Revision 1.10 1997/04/08 19:57:47 pvmsrc * Promoted mbox static "classes" to public global "pvmmboxclasses". * - so pvmd can spank mboxes in ddpro.c... :-Q * - renamed everywhere, moved decl / extern to global.[ch]. * * Revision 1.9 1997/04/08 19:42:55 pvmsrc * *** Added new system reset protocol / wait linkage. * - new DM_RESET / dm_reset() & DM_RESETACK / dm_resetack(). * - new WT_RESET wait type. * - modified dm_db() to include new TMDB_RESET(nnr, noresets) option: * * clean up mboxes, except for "no-reset" tasks. * * for persistent mboxes, set up WT_RESET to remove mbox on task * exit, propagate to task's host via DM_RESET. * * on task exit, WT_RESET wipes mbox out, DM_RESETACK passes * word on to master pvmd (if necessary). * * Revision 1.8 1997/03/07 14:05:11 pvmsrc * Phixed Phunky Phil #endif. * - no preceding tab on some archs. * * Revision 1.7 1997/03/06 20:55:34 pvmsrc * add call to mpp_load when loading onto compute partition. * * Revision 1.6 1997/02/13 19:05:05 pvmsrc * Fixed mbox cleanup problem: * - in dm_db() for TMDB_PUT case, if successful create master PVMD * notify on inserting task (if task not local, forward DM_NOTIFY). * - then on task exit, call mb_tidy() if WT_TASKX notify wait context * exists (in hostfailentry() and task_cleanup()), or if empty * notify propagates back to master PVMD via DM_NOTIFYACK. * * Revision 1.5 1997/02/13 15:10:00 pvmsrc * Removed unnecessary extern for struct waitc *waitlist. * - now in global.h. * * Revision 1.4 1997/01/28 19:26:14 pvmsrc * New Copyright Notice & Authors. * * Revision 1.3 1996/10/25 13:57:16 pvmsrc * Replaced old #includes for protocol headers: * - , "ddpro.h", "tdpro.h" * With #include of new combined header: * - * * Revision 1.2 1996/10/24 21:50:47 pvmsrc * Moved #include "global.h" below other #include's for typing. * Added #include for TEV_* constants. * Added extern struct Pvmtracer pvmtracer for tracer info. * Modified exectasks(): * - if tracer present, adjust settings for trace & output collect, * and munge the environment to replace values for PVMTMASK, * PVMTRCBUF & PVMTRCOPT. * - replaced inline code with call to new tev_send_newtask(). * - modified checking of trctid / outtid, check for < 0, not non-zero * in case task denies external collect. * Added handling of new DM_SLCONF_TRACE in dm_slconf(): * - tracer update configuration msg. * - also added packing up of same in startack(). * * Revision 1.1 1996/09/23 23:44:06 pvmsrc * Initial revision * * Revision 1.15 1996/05/13 20:23:21 manchek * a few fixes to manual startup code * * Revision 1.14 1995/07/24 18:23:14 manchek * spelling problem * * Revision 1.13 1995/07/19 21:27:20 manchek * use new function pvmnametag instead of [dts]mname * * Revision 1.12 1995/07/03 19:03:35 manchek * if shared memory, get status from global table in dm_task before replying * * Revision 1.11 1995/06/16 16:11:34 manchek * hack to pass output and trace sink to mpp_load for PGON * * Revision 1.10 1995/05/30 17:26:30 manchek * added ifdefs for SP2MPI architecture * * Revision 1.9 1995/05/17 16:04:36 manchek * added HF_OVERLOAD flag. * changed global mytid to pvmmytid * * Revision 1.8 1995/02/01 21:03:07 manchek * addhosts returns PvmDSysErr instead of -1 if something breaks. * mpp_load is called with environment so it can be passed to tasks. * dm_execack processes received tids in order instead of backwards * * Revision 1.7 1994/10/15 19:02:36 manchek * cast message tags for comparison as integer. * send output and trace open messages for dmp and shmem ports. * check newhosts when deleting host * * Revision 1.6 1994/07/18 19:18:10 manchek * hostfailentry() no longer matches pvmd' to t0. * wa_dep wasn't propogated from hoststart to htupd * * Revision 1.5 1994/06/30 21:33:46 manchek * addhosts() uses PVM_DPATH envar * * Revision 1.4 1994/06/21 18:29:21 manchek * subscript arith in dmname() broke with opt * * Revision 1.3 1994/06/04 22:33:16 manchek * missed resetting busyadding in hostfailentry(WT_HTUPD) * * Revision 1.2 1994/06/03 20:38:12 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:26:47 manchek * Initial revision * */ #ifdef IMA_TITN #include #else #include #endif #ifdef NEEDMENDIAN #include #endif #ifdef NEEDENDIAN #include #endif #ifdef NEEDSENDIAN #include #endif #ifdef WIN32 #include "pvmwin.h" #endif #if defined(WIN32) || defined(CYGWIN) #include "..\xdr\types.h" #include "..\xdr\xdr.h" #else #include #include #endif #ifdef WIN32 #include #include #include #include #else #include #include #include #include #endif #ifdef SYSVSTR #include #else #include #endif #include #include #include #include #include "pvmalloc.h" #include "host.h" #include "pmsg.h" #include "waitc.h" #include "task.h" #include "listmac.h" #if defined(IMA_PGON) || defined(IMA_I860) || defined(IMA_CM5) \ || defined(SHMEM) || defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) \ || defined(IMA_AIX5SP2) || defined(IMA_BEOLIN) #include "pvmdmp.h" #endif #include "bfunc.h" #include #include "msgbox.h" #include "global.h" void pvmbailout(); char *inadport_hex(); char *getenv(); void hex_inadport __ProtoGlarp__ (( char *, struct sockaddr_in * )); void mesg_rewind __ProtoGlarp__ (( struct pmsg * )); void tev_send_newtask(); char **colonsep(); char *varsub(); char *pvmnametag(); extern int pvmdebmask; /* from pvmd.c */ extern char **epaths; /* from pvmd.c */ extern char *debugger; /* from pvmd.c */ extern struct htab *filehosts; /* from pvmd.c */ extern struct htab *hosts; /* from pvmd.c */ extern int hostertid; /* from pvmd.c */ extern struct task *locltasks; /* from task.c */ extern char *myarchname; /* from pvmd.c */ extern int myhostpart; /* from pvmd.c */ extern int pvmmytid; /* from pvmd.c */ extern struct htab *newhosts; /* from pvmd.c */ extern int pprime; /* from pvmd.c */ extern int runstate; /* from pvmd.c */ extern int pvmschedtid; /* from pvmd.c */ extern struct Pvmtracer pvmtracer; /* from pvmd.c */ extern int tidhmask; /* from pvmd.c */ extern int tidlmask; /* from pvmd.c */ #ifndef IMA_WIN32_WATCOM extern char **environ; #endif int busyadding = 0; /* lock for addhost op */ int hosterwid = 0; /* wid waiting on hoster */ /*************** ** Private ** ** ** ***************/ int dm_add(); int dm_addack(); int dm_db(); int dm_dback(); int dm_delhost(); int dm_delhostack(); int dm_halt(); int dm_hostsync(); int dm_hostsyncack(); int dm_htcommit(); int dm_htdel(); int dm_htupd(); int dm_htupdack(); int dm_mca(); int dm_notify(); int dm_notifyack(); int dm_null(); int dm_pstat(); int dm_pstatack(); int dm_reset(); int dm_resetack(); int dm_sendsig(); int dm_slconf(); int dm_exec(); int dm_execack(); int dm_startack(); int dm_task(); int dm_taskack(); int dm_taskout(); int (*netswitch[])() = { dm_add, dm_addack, dm_exec, dm_execack, dm_sendsig, dm_htupd, dm_htupdack, dm_htcommit, dm_slconf, dm_startack, dm_task, dm_taskack, dm_delhost, dm_delhostack, dm_null, dm_taskout, dm_pstat, dm_pstatack, dm_halt, dm_mca, dm_notify, dm_notifyack, dm_db, dm_dback, dm_reset, dm_resetack, dm_htdel, dm_hostsync, dm_hostsyncack, }; /* hostfailentry() * * We've decided a remote pvmd has failed. * Wake up any wait context waiting on that host (different action * for each kind of wait). * Send a HTDEL message to remaining hosts except us. */ int hostfailentry(hp) struct hostd *hp; { int hpart = hp->hd_hostpart; struct waitc *wp, *wp2; struct pmsg *mp; struct pvmmentry *ep; if (pvmdebmask & PDMHOST) { pvmlogprintf("hostfailentry() host %s\n", hp->hd_name); hd_dump(hp); } if (hp == hosts->ht_hosts[hosts->ht_master]) { pvmlogerror("hostfailentry() lost master host, we're screwwwed\n"); pvmbailout(0); } /* * if we're master pvmd, send HT_DEL message to all others */ if (hp->hd_hostpart && hosts->ht_master == hosts->ht_local) { struct hostd *hp2; int hh; mp = mesg_new(0); mp->m_tag = DM_HTDEL; pkint(mp, hosts->ht_serial); pkint(mp, hp->hd_hostpart); for (hh = hosts->ht_last; hh > 0; hh--) if (hh != hosts->ht_local && (hp2 = hosts->ht_hosts[hh]) && hp2 != hp) { mp->m_ref++; mp->m_dst = hp2->hd_hostpart | TIDPVMD; sendmessage(mp); } pmsg_unref(mp); /* inform the scheduler too */ if (pvmschedtid) { mp = mesg_new(0); mp->m_tag = SM_HOSTX; mp->m_dst = pvmschedtid; pkint(mp, hp->hd_hostpart | TIDPVMD); sendmessage(mp); } } for (wp = waitlist->wa_link; wp != waitlist; wp = wp->wa_link) { if (wp->wa_on && (wp->wa_on & TIDHOST) == hpart) { switch (wp->wa_kind) { case WT_ADDHOST: /* the master must have died */ case WT_DELHOST: /* the master must have died */ pvmlogprintf("hostfailentry() can't deal with wait kind %d\n", wp->wa_kind); break; case WT_HTUPD: if (wp->wa_peer == wp) { int hh; mp = mesg_new(0); mp->m_tag = DM_HTCOMMIT; for (hh = hosts->ht_last; hh > 0; hh--) if (hh != hosts->ht_local && (hp = hosts->ht_hosts[hh])) { mp->m_ref++; mp->m_dst = hp->hd_hostpart | TIDPVMD; sendmessage(mp); } pmsg_unref(mp); busyadding = 0; sendmessage(wp->wa_mesg); wp->wa_mesg = 0; } break; case WT_SPAWN: { struct waitc_spawn *wxp; int retry = 0; int v; wxp = (struct waitc_spawn*)wp->wa_spec; /* mark tasks assigned to this host as failed */ /* (or reset if PvmTaskDefault) */ for (v = wxp->w_veclen; v-- > 0; ) if (wxp->w_vec[v] == hp->hd_hostpart) if (!(wxp->w_flags & (PvmTaskHost|PvmTaskArch))) { wxp->w_vec[v] = 0; retry++; } else wxp->w_vec[v] = PvmHostFail; ht_delete(wxp->w_ht, hp); /* try assigning task again without failed host */ if ( retry ) assign_tasks(wp); /* is this was the last wait, reply to task */ if (wp->wa_peer == wp) assign_tasks(wp); } break; case WT_TASK: /* send message if we're the last waiter */ if (wp->wa_peer == wp) { mp = wp->wa_mesg; mp->m_ref++; sendmessage(mp); } break; case WT_HOSTSTART: /* reply to waiter */ busyadding = 0; if (wp->wa_spec) { free_waitc_add((struct waitc_add *)wp->wa_spec); wp->wa_spec = 0; } pkint(wp->wa_mesg, PvmDSysErr); sendmessage(wp->wa_mesg); wp->wa_mesg = 0; break; case WT_TASKX: if (wp->wa_tid && wp->wa_mesg) { sendmessage(wp->wa_mesg); wp->wa_mesg = 0; } mb_tidy(wp->wa_on); break; case WT_RESET: if (wp->wa_tid && wp->wa_mesg) { sendmessage(wp->wa_mesg); wp->wa_mesg = 0; } mb_tidy_reset(wp->wa_on); break; case WT_RECVINFO: /* clean up pending recvinfo */ ep = (struct pvmmentry *) wp->wa_spec; if ( ep->me_msg ) /* class name (overload :-Q) */ PVM_FREE( ep->me_msg ); PVM_FREE( ep ); break; case WT_HOSTF: sendmessage(wp->wa_mesg); wp->wa_mesg = 0; break; case WT_PSTAT: case WT_MSTAT: case WT_HOSTSYNC: pkint(wp->wa_mesg, PvmHostFail); sendmessage(wp->wa_mesg); wp->wa_mesg = 0; break; default: pvmlogprintf("hostfailentry() alien wait kind %d\n", wp->wa_kind); break; } wp2 = wp->wa_rlink; wait_delete(wp); wp = wp2; } } return 0; } int netentry(hp, mp) struct hostd *hp; struct pmsg *mp; { int c = mp->m_tag; if (pvmdebmask & PDMMESSAGE) { pvmlogprintf( "netentry() from host %s src t%x dst t%x tag %s wid %d\n", hp->hd_name, mp->m_src, mp->m_dst, pvmnametag(c, (int *)0), mp->m_wid); /* pvmhdump(mp->m_frag->fr_link->fr_dat, mp->m_frag->fr_link->fr_len, "netentry() "); */ } if (c < (int)DM_FIRST || c > (int)DM_LAST) { pvmlogprintf("netentry() message from t%x with bogus code %s\n", mp->m_src, pvmnametag(c, (int *)0)); goto bail; } c -= DM_FIRST; (netswitch[c])(hp, mp); bail: pmsg_unref(mp); return 0; } /********************************* ** Pvmd message entry points ** ** ** *********************************/ /* hostids_new() * * Get a list of new host tids (ones not it user in host table). * Wrap around to lowest number when we reach the maximum. * Return as many as are available. */ int hostids_new(num, tids) int *num; /* count requested, returned */ int *tids; /* return tids */ { static int lasthh = 1; int oldhh; int maxhostid = tidhmask >> (ffs(tidhmask) - 1); int i; oldhh = lasthh; /* find next free hostid */ for (i = 0; i < *num; i++) { if (++lasthh > maxhostid) lasthh = 1; while ((lasthh <= hosts->ht_last && hosts->ht_hosts[lasthh])) { if (++lasthh > maxhostid) lasthh = 1; if (lasthh == oldhh) goto done; } tids[i] = lasthh << (ffs(tidhmask) - 1); /* pvmlogprintf("hostids_new() tid %x\n", tids[i]); */ } done: return *num = i; } free_waitc_add(wxp) struct waitc_add *wxp; { int i; for (i = 0; i < wxp->w_num && wxp->w_hosts[i]; i++) hd_unref(wxp->w_hosts[i]); PVM_FREE(wxp->w_hosts); PVM_FREE(wxp); return 0; } /* addhosts() * * Add hosts requested with DM_ADD or SM_ADD. Call the hoster or * start 'em. */ int addhosts(mp, rmp) struct pmsg *mp; /* the request message */ struct pmsg *rmp; /* reply message blank */ { struct hostd *hp, *hp2; struct pmsg *mp2; struct waitc *wp = 0; struct waitc_add *wxp = 0; int i, j; int count; int ngood; int ntid; struct hostent *he; int maxhostid = (tidhmask >> ffs(tidhmask) - 1); int hh; int pid; int *tids; char *winpvmdpath; char *pvmdpath; char *vmid; char *buf; int len; /* * have to lock this for 2 reasons: * 1. system can't handle overlapping host table updates, * 2. the new host tids aren't reserved */ if (busyadding) { /* pvmlogerror("addhosts() already adding new hosts\n"); */ pkint(rmp, PvmAlready); sendmessage(rmp); return 0; } busyadding = 1; /* sanity check count */ if (upkint(mp, &count) || count < 1 || count > maxhostid) { pvmlogerror("addhosts() bad msg format\n"); goto bad; } /* * make wait context, extract host list from message, */ wp = wait_new(WT_HOSTSTART); wp->wa_tid = mp->m_src; wp->wa_dep = mp->m_wid; wxp = TALLOC(1, struct waitc_add, "waix"); wxp->w_num = count; wxp->w_hosts = TALLOC(count, struct hostd *, "waiv"); BZERO((char*)wxp->w_hosts, count * sizeof(struct hostd *)); wp->wa_spec = (void *)wxp; for (i = 0; i < count; i++) { hp = hd_new(0); wxp->w_hosts[i] = hp; if (upkstralloc(mp, &buf)) { pvmlogerror("addhosts() bad msg format\n"); goto bad; } if (parsehost(buf, hp)) { hp->hd_err = PvmBadParam; } else { /* Set unspecified fields from hostfile if available */ if (filehosts && ((hp2 = nametohost(filehosts, hp->hd_name)) || (hp2 = filehosts->ht_hosts[0]))) applydefaults(hp, hp2); } PVM_FREE(buf); } /* * verify we have a chance to add these babies... * check whether our IP is "real" or just loopback */ hp = hosts->ht_hosts[hosts->ht_local]; if ( hp->hd_sad.sin_addr.s_addr == htonl(0x7f000001) ) { /* damn, we're hosed. bail on host adds with new */ /* PvmIPLoopback error code... */ for (i = 0; i < count; i++) { hp = wxp->w_hosts[i]; if (hp->hd_err) continue; hp->hd_err = PvmIPLoopback; } } /* * lookup IP addresses XXX we already have some of them */ ngood = 0; for (i = 0; i < count; i++) { hp = wxp->w_hosts[i]; if (hp->hd_err) continue; if (he = gethostbyname(hp->hd_aname ? hp->hd_aname : hp->hd_name)) { BCOPY(he->h_addr_list[0], (char*)&hp->hd_sad.sin_addr, sizeof(struct in_addr)); } else { if (pvmdebmask & PDMSTARTUP) { pvmlogprintf( "start_slaves() can't gethostbyname: %s\n", hp->hd_name); } hp->hd_err = PvmNoHost; continue; } /* make sure it's not already configured */ if (!(hp->hd_flag & HF_OVERLOAD)) { for (hh = hosts->ht_last; hh > 0; hh--) if ((hp2 = hosts->ht_hosts[hh]) && (hp2->hd_sad.sin_addr.s_addr == hp->hd_sad.sin_addr.s_addr)) { hp->hd_err = PvmDupHost; break; } if (hp->hd_err) continue; /* make sure new ones aren't duplicated */ for (j = i; j-- > 0; ) if (hp->hd_sad.sin_addr.s_addr == wxp->w_hosts[j]->hd_sad.sin_addr.s_addr) { hp->hd_err = PvmDupHost; break; } if (hp->hd_err) continue; } ngood++; } /* * assign tids XXX these are unreserved until hosts are added... */ ntid = ngood; tids = TALLOC(ngood, int, "xxx"); hostids_new(&ntid, tids); if (ntid < ngood) { pvmlogerror("addhosts() out of hostids\n"); ngood = ntid; } for (j = i = 0; i < count; i++) { hp = wxp->w_hosts[i]; if (hp->hd_err) continue; if (j < ntid) hp->hd_hostpart = tids[j++]; else hp->hd_err = PvmOutOfRes; } PVM_FREE(tids); /* if (!ngood) { XXX don't really need to send the message } */ /* keep stub reply message to caller */ wp->wa_mesg = rmp; /* make request message and send to hoster or pvmd' */ mp2 = mesg_new(0); mp2->m_wid = wp->wa_wid; pkint(mp2, ngood); if (!(pvmdpath = getenv("PVM_DPATH"))) pvmdpath = PVMDPATH; if (!(winpvmdpath = getenv("PVM_WINDPATH"))) winpvmdpath = WINPVMDPATH; for (i = 0; i < count; i++) { hp = wxp->w_hosts[i]; if (hp->hd_err) continue; pkint(mp2, hp->hd_hostpart); pkstr(mp2, hp->hd_sopts ? hp->hd_sopts : ""); if (hp->hd_login) { len = strlen(hp->hd_login) + strlen((hp->hd_aname ? hp->hd_aname : hp->hd_name)) + 2; buf = TALLOC( len, char, "hdl" ); sprintf(buf, "%s@%s", hp->hd_login, (hp->hd_aname ? hp->hd_aname : hp->hd_name)); } else buf = STRALLOC( (hp->hd_aname ? hp->hd_aname : hp->hd_name) ); pkstr(mp2, buf); PVM_FREE(buf); /* default unix dpath */ len = strlen( (hp->hd_dpath ? hp->hd_dpath : pvmdpath) ) + 1 + strlen( (hp->hd_sopts && !strcmp(hp->hd_sopts, "ms") ? "-S" : "-s") ) + 1 + 2 + 16 + 1 + 2 + strlen( hp->hd_name ) + 1 + 5 * ( 16 + 1 ); buf = TALLOC( len, char, "hdall" ); (void)sprintf(buf, "%s %s -d0x%x -n%s %d %s %d", (hp->hd_dpath ? hp->hd_dpath : pvmdpath), (hp->hd_sopts && !strcmp(hp->hd_sopts, "ms") ? "-S" : "-s"), pvmdebmask, hp->hd_name, hosts->ht_master, inadport_hex( &hosts->ht_hosts[hosts->ht_master]->hd_sad), hosts->ht_hosts[hosts->ht_master]->hd_mtu); (void)sprintf(buf + strlen(buf), " %d %s", ((hp->hd_hostpart & tidhmask) >> (ffs(tidhmask) - 1)), inadport_hex(&hp->hd_sad)); pkstr(mp2, buf); PVM_FREE(buf); /* default WIN32 dpath - only if not set manually (a la dx=) */ if (!(hp->hd_dpath)){ len = strlen( winpvmdpath ) + 1 + strlen( (hp->hd_sopts && !strcmp(hp->hd_sopts, "ms") ? "-S" : "-s") ) + 1 + 2 + 16 + 1 + 2 + strlen( hp->hd_name ) + 1 + 5 * ( 16 + 1 ); buf = TALLOC( len, char, "hdallwin" ); (void)sprintf(buf, "%s %s -d0x%x -n%s %d %s %d", winpvmdpath, (hp->hd_sopts && !strcmp(hp->hd_sopts, "ms") ? "-S" : "-s"), pvmdebmask, hp->hd_name, hosts->ht_master, inadport_hex( &hosts->ht_hosts[hosts->ht_master]->hd_sad), hosts->ht_hosts[hosts->ht_master]->hd_mtu); (void)sprintf(buf + strlen(buf), " %d %s", ((hp->hd_hostpart & tidhmask) >> (ffs(tidhmask) - 1)), inadport_hex(&hp->hd_sad)); pkstr(mp2, buf); PVM_FREE(buf); } /* be sure to pack SOMETHING, dammit */ else pkstr(mp2, ""); /* Include VMID (If Any) */ if (hp->hd_vmid) pkstr(mp2, hp->hd_vmid); else if (vmid = getenv("PVM_VMID")) pkstr(mp2, vmid); /* be sure to pack SOMETHING, dammit */ else pkstr(mp2, ""); } mp2->m_tag = SM_STHOST; #if !defined(WIN32) && !defined(IMA_OS2) if (hostertid) { hosterwid = wp->wa_wid; mp2->m_dst = hostertid; wp->wa_on = hostertid; sendmessage(mp2); } else { wp->wa_on = TIDPVMD; if (pid = fork()) { /* still us */ if (pid == -1) { /* nack request if can't fork */ pvmlogperror("addhosts() fork"); goto bad; } else { pprime = pid; pmsg_unref(mp2); } } else { /* pvmd' to do the startup */ beprime(); mesg_rewind(mp2); hoster(mp2); } } #else /* WIN32 */ if (!hostertid) { /* no hoster yet */ hostertid = tid_new(); /* give him a tid so that we can send him the message */ if (start_hoster(hostertid) == -1) { hostertid=0; /* you did not make it buddy */ pvmlogperror("addhosts(): could not start hoster \n"); goto bad; } } hosterwid = wp->wa_wid; mp2->m_dst = hostertid; wp->wa_on = hostertid; sendmessage(mp2); #endif return 0; bad: if (wxp) free_waitc_add(wxp); if (wp) { wp->wa_mesg = 0; /* shared with rmp */ wait_delete(wp); } busyadding = 0; pkint(rmp, PvmDSysErr); sendmessage(rmp); return 0; } #ifdef WIN32 /* start_hoster() * * forkexec the hoster process which * will start other pvmd's. * acts like pvmd' */ int start_hoster(reserved_tid) int reserved_tid; { char hosterpath[128]; (void) strcpy(hosterpath,(char *) pvmgetroot()); (void) strcat(hosterpath,"\\bin\\WIN32\\hoster.exe"); if (hostexectasker(hosterpath,reserved_tid)) return -1; return 0; } int hostexectasker(file, tid) char *file; int tid; { int tids = 0; /* tid from hosterforkexec */ struct pmsg *rmp; struct task *tp = 0; int err = 0; /* error code from forkexec */ rmp = mesg_new(0); rmp->m_dst = pvmmytid; rmp->m_src = pvmmytid; rmp->m_tag = DM_EXECACK; if (err = hosterforkexec(tid,file, &tp)) { tids = err; } else { tp->t_ptid = 0; tp->t_outtid = 0; tp->t_trctid = 0; tp->t_sched = 0; tids = tp->t_tid; } pkint(rmp, 1); pkint(rmp, tids); sendmessage(rmp); return err; } extern char **environ; int hosterforkexec(tid, name, tpp) int tid; /* tid given by hosterexectask */ char *name; /* filename */ struct task **tpp; /* return task context */ { int pid = -1; /* task pid */ char *argv[2]; struct task *tp; /* new task context */ char *expected_pid; char buf[32]; char *myenv[100]; HANDLE hpid; char **p, **q; struct stat sb; extern int *ptr_nfp; /* XXX fix this */ SECURITY_ATTRIBUTES saPipe; PROCESS_INFORMATION pi; STARTUPINFO si; /* for CreateProcess call */ if (stat(name, &sb) == -1) return PvmNoFile; if ((tp = task_new(tid)) == NULL) { pvmlogperror("forkexec_hoster() too many tasks?\n"); return PvmOutOfRes; } p = myenv; q = environ; while (*q) { *p++ = *q++; } /* copy all the environment for socket stuff and more */ expected_pid=malloc(20 * sizeof(char)); sprintf(expected_pid, "PVMEPID=%d", *ptr_nfp); *p++ = expected_pid; *p=0; pvmputenv(expected_pid); argv[0]=name; argv[1]=0; saPipe.nLength = sizeof(SECURITY_ATTRIBUTES); saPipe.lpSecurityDescriptor = NULL; saPipe.bInheritHandle = FALSE; memset(&si, 0, sizeof(si)); si.cb = sizeof(si); if (0) { pid = CreateProcess(name, /* filename */ NULL, /* full command line for child */ NULL, /* process security descriptor */ NULL, /* thread security descriptor */ FALSE, /* inherit handles? */ DETACHED_PROCESS, /* creation flags */ NULL, /* inherited environment address */ NULL, /* startup dir; NULL = start in current */ &si, /* pointer to startup info (input) */ &pi); /* pointer to process info (output) */ /* fprintf(stderr,"yup \n"); */ } else pid = _spawnve(_P_NOWAIT,name,argv,myenv); if (pid == -1) { pvmlogperror("forkexec_hoster() _spawnve"); /* task_free(&tp); */ pvmbailout(0); return PvmOutOfRes; } task_setpid(tp,*ptr_nfp); *ptr_nfp=*ptr_nfp + 1; tp->t_flag |= TF_FORKD; tp->t_a_out = STRALLOC(name); *tpp = tp; return 0; } #endif /* dm_add() * * (Master pvmd) gets request to add new hosts. *DocThis * DM_ADD(wid) { * int count * string name[count] * } *EndDocThis */ int dm_add(hp, mp) struct hostd *hp; struct pmsg *mp; { struct pmsg *rmp; rmp = mesg_new(0); rmp->m_dst = mp->m_src; rmp->m_ctx = mp->m_ctx; rmp->m_tag = DM_ADDACK; rmp->m_wid = mp->m_wid; addhosts(mp, rmp); return 0; } /* dm_addack() * * Reply to DM_ADD operation. * * DM_ADDACK(wid_rtn) { * int nhosts // or error code * int narches // if nhosts >= 0 * { * int tid // or error code * string name * string arch * int mtu * int speed * } [nhosts] * } */ int dm_addack(hp, mp) struct hostd *hp; struct pmsg *mp; { struct waitc *wp; if (!(wp = wait_get(hp, mp, WT_ADDHOST))) return 0; pmsg_packbody(wp->wa_mesg, mp); sendmessage(wp->wa_mesg); wp->wa_mesg = 0; wait_delete(wp); return 0; } /* exectasks() * * Start tasks requested with DM_EXEC or SM_EXEC. * Call the tasker or start 'em. * We try to fork/exec given number of tasks. On first error, fill * remainder of tid array with error code. * Return tid array to caller. */ int exectasks(mp, rmp, schtid) struct pmsg *mp; /* the request message */ struct pmsg *rmp; /* reply message blank */ int schtid; /* scheduler for new tasks */ { struct pmsg *mp2; /* reply message hdl */ int i; struct timeval now; struct waitc_spawn *wxp; /* new task parameters */ int munge_tenv = 0; char tmp[255]; char *wd = 0; char *savewd = 0; wxp = TALLOC(1, struct waitc_spawn, "waix"); BZERO((char*)wxp, sizeof(struct waitc_spawn)); /* unpack message */ if (upkuint(mp, &wxp->w_ptid) || upkstralloc(mp, &wxp->w_file) || upkint(mp, &wxp->w_flags) || upkint(mp, &wxp->w_veclen) || upkint(mp, &wxp->w_argc)) goto bad; if (wxp->w_veclen < 1) goto bad; wxp->w_vec = TALLOC(wxp->w_veclen, int, "tids"); wxp->w_argc += 2; wxp->w_argv = TALLOC(wxp->w_argc + 1, char*, "argv"); BZERO((char*)wxp->w_argv, (wxp->w_argc + 1) * sizeof(char*)); wxp->w_argv++; wxp->w_argv[0] = wxp->w_file; wxp->w_file = 0; wxp->w_argv[--wxp->w_argc] = 0; for (i = 1; i < wxp->w_argc; i++) if (upkstralloc(mp, &wxp->w_argv[i])) goto bad; if (upkuint(mp, &wxp->w_outtid) || upkuint(mp, &wxp->w_outctx) || upkuint(mp, &wxp->w_outtag) || upkuint(mp, &wxp->w_trctid) || upkuint(mp, &wxp->w_trcctx) || upkuint(mp, &wxp->w_trctag) || upkuint(mp, &wxp->w_nenv)) goto bad; wxp->w_hosttotal = wxp->w_veclen; /* this is the task count! */ if (pvmtracer.trctid) { if (!(wxp->w_trctid) && pvmtracer.trctag) { wxp->w_trctid = pvmtracer.trctid; wxp->w_trcctx = pvmtracer.trcctx; wxp->w_trctag = pvmtracer.trctag; munge_tenv++; } } if (pvmtracer.outtid) { if (!(wxp->w_outtid) && pvmtracer.outtag) { wxp->w_outtid = pvmtracer.outtid; wxp->w_outctx = pvmtracer.outctx; wxp->w_outtag = pvmtracer.outtag; } } wxp->w_env = TALLOC((wxp->w_nenv + 1), char*, "env"); BZERO(wxp->w_env, (wxp->w_nenv + 1) * sizeof(char*)); for (i = 0; i < wxp->w_nenv; i++) if (upkstralloc(mp, &wxp->w_env[i])) goto bad; if ( upkuint(mp, &wxp->w_instance) || upkuint(mp, &wxp->w_outof)) goto bad; /* check for spawn working directory */ for (i = 0; i < wxp->w_nenv; i++) if ( !strncmp( "PVMSPAWNWD=", wxp->w_env[i], strlen("PVMSPAWNWD=") ) ) wd = STRALLOC( wxp->w_env[i] + strlen("PVMSPAWNWD=") ); /* munge env for tracing stuff */ if ( munge_tenv ) { sprintf( tmp, "PVMTMASK=%s", pvmtracer.tmask ); pvmenvinsert( &(wxp->w_env), tmp ); sprintf( tmp, "PVMTRCBUF=%d", pvmtracer.trcbuf ); pvmenvinsert( &(wxp->w_env), tmp ); sprintf( tmp, "PVMTRCOPT=%d", pvmtracer.trcopt ); pvmenvinsert( &(wxp->w_env), tmp ); for ( wxp->w_nenv = 0 ; wxp->w_env[ wxp->w_nenv ] ; (wxp->w_nenv)++ ); } /* call ppi_load to get tasks running */ wxp->w_sched = schtid; /* change to desired working directory (if specified) */ if (wd) { savewd = (char *) getcwd( (char *) NULL, 255 ); chdir( wd ); } #if defined(IMA_PGON) || defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) \ || defined(IMA_AIX5SP2) || defined(IMA_BEOLIN) if (!(wxp->w_flags & PvmMppFront)) { mpp_load(wxp); } else #endif { ppi_load(wxp); } /* go back to original directory (if getcwd() was successful) */ if (savewd) chdir( savewd ); for (i = 0; i < wxp->w_veclen; i++) { if (wxp->w_vec[i] > 0) { if (wxp->w_trctid > 0) { tev_send_newtask( wxp->w_trctid, wxp->w_trcctx, wxp->w_trctag, wxp->w_vec[i], wxp->w_ptid, wxp->w_flags, wxp->w_argv[0] ); } if (wxp->w_outtid > 0) { mp2 = mesg_new(0); mp2->m_dst = wxp->w_outtid; mp2->m_ctx = wxp->w_outctx; mp2->m_tag = wxp->w_outtag; pkint(mp2, wxp->w_vec[i]); pkint(mp2, TO_NEW); pkint(mp2, wxp->w_ptid); sendmessage(mp2); } } } pkint(rmp, wxp->w_veclen); for (i = 0; i < wxp->w_veclen; i++) pkint(rmp, wxp->w_vec[i]); sendmessage(rmp); goto cleanup; bad: pvmlogprintf("exectasks() from t%x bad msg format\n", mp->m_src); cleanup: if (wxp->w_argv) *--wxp->w_argv = 0; free_wait_spawn(wxp); if (wd) PVM_FREE(wd); return 0; } /* dm_exec() * * Request to start task processes. * * DM_EXEC(wid) { * int ptid * string file * int flags * int count * int nargs * string argv[nargs] * int outtid * int outctx * int outtag * int trctid * int trcctx * int trctag * int nenv * string env[nenv] * } */ int dm_exec(hp, mp) struct hostd *hp; struct pmsg *mp; { struct pmsg *rmp; hp = hp; rmp = mesg_new(0); rmp->m_dst = mp->m_src; rmp->m_ctx = mp->m_ctx; rmp->m_tag = DM_EXECACK; rmp->m_wid = mp->m_wid; exectasks(mp, rmp, pvmschedtid); return 0; } /* dm_execack() * * Reply to DM_EXEC op. * * DM_EXECACK(wid_rtn) { * int count * int tids[count] * } */ int dm_execack(hp, mp) struct hostd *hp; struct pmsg *mp; { struct waitc *wp; struct waitc_spawn *wxp; int rcnt; /* num of tids+errors returned */ int tid; int v; int err = 0; int i; if (!(wp = wait_get(hp, mp, WT_SPAWN))) return 0; wxp = (struct waitc_spawn*)wp->wa_spec; if (upkint(mp, &rcnt)) goto bad; v = wxp->w_veclen; /* * unpack tids and place in result vector where hostpart is now */ /* pvmlogprintf("dm_execack() hp %x vec len %d, repl len %d\n", hp->hd_hostpart, v, rcnt); */ i = 0; while (rcnt-- > 0) { if (upkint(mp, &tid)) goto bad; if (tid < 0) err++; while (i < v && wxp->w_vec[i] != hp->hd_hostpart) i++; if (i == v) { pvmlogerror("dm_execack() tids don't fit result vector?\n"); wait_delete(wp); return 0; } wxp->w_vec[i++] = tid; } if (err) ht_delete(wxp->w_ht, hp); /* * if everyone has checked in, either restart the failed ones * or reply to the caller. */ if (wp->wa_peer == wp) assign_tasks(wp); wait_delete(wp); return 0; bad: pvmlogprintf("dm_execack() from 0x%x bad msg format\n", mp->m_src); wait_delete(wp); return 0; } /* dm_sendsig() * * Request to send signal to local task. * * DM_SENDSIG { * int tid * int signum * } */ int dm_sendsig(hp, mp) struct hostd *hp; struct pmsg *mp; { int tid; int signum; struct task *tp; hp = hp; if (upkuint(mp, &tid) || upkint(mp, &signum)) { pvmlogerror("dm_sendsig() bad msg format\n"); return 0; } if (tp = task_find(tid)) { ppi_kill(tp, signum); } else if (pvmdebmask & (PDMTASK|PDMAPPL)) { pvmlogprintf("dm_sendsig() signal for t%x scrapped\n", tid); } return 0; } /* dm_htupd() * * Host table update phase 1 - (Non-master) pvmd is notified of new * host table. * * DM_HTUPD(wid) { * int serial * int master * int console * int count * { * int index * string name * string arch * string hexipaddr * int mtu * int speed * int dsig * } [count] * } */ int dm_htupd(hp, mp) struct hostd *hp; struct pmsg *mp; { int count; /* number of hosts in message */ int hh; char buf[16]; /* for converting sockaddr */ struct pmsg *mp2; /* unpack new host table params */ newhosts = ht_new(1); newhosts->ht_local = hosts->ht_local; upkint(mp, &newhosts->ht_serial); upkint(mp, &newhosts->ht_master); upkint(mp, &newhosts->ht_cons); /* add current hosts to the table */ ht_merge(newhosts, hosts); /* unpack new hosts and add to table */ /* XXX if we find a host already in table we should kill it with XXX hostfail and put the new one in its place */ upkint(mp, &count); while (count-- > 0) { upkint(mp, &hh); hp = hd_new(hh); upkstralloc(mp, &hp->hd_name); upkstralloc(mp, &hp->hd_arch); upkstr(mp, buf, sizeof(buf)); hex_inadport(buf, &hp->hd_sad); upkint(mp, &hp->hd_mtu); upkint(mp, &hp->hd_speed); upkint(mp, &hp->hd_dsig); ht_insert(newhosts, hp); hd_unref(hp); } if (pvmdebmask & PDMHOST) { pvmlogerror("dm_htupd() new host table:\n"); ht_dump(newhosts); } runstate = PVMDHTUPD; /* reply to sender that we have new host table */ mp2 = mesg_new(0); mp2->m_dst = mp->m_src; mp2->m_ctx = mp->m_ctx; mp2->m_tag = DM_HTUPDACK; mp2->m_wid = mp->m_wid; sendmessage(mp2); return 0; } /* dm_htupdack() * * Reply to DM_HTUPD op. * * DM_HTUPDACK(wid_rtn) { } */ int dm_htupdack(hp, mp) struct hostd *hp; struct pmsg *mp; { struct waitc *wp; if (!(wp = wait_get(hp, mp, WT_HTUPD))) return 0; /* is this is the last host checking in, send ht commit */ if (wp->wa_peer == wp) { int hh; mp = mesg_new(0); mp->m_tag = DM_HTCOMMIT; for (hh = hosts->ht_last; hh > 0; hh--) if (hh != hosts->ht_local && (hp = hosts->ht_hosts[hh])) { mp->m_ref++; mp->m_dst = hp->hd_hostpart | TIDPVMD; sendmessage(mp); } pmsg_unref(mp); busyadding = 0; sendmessage(wp->wa_mesg); wp->wa_mesg = 0; } wait_delete(wp); return 0; } /* ht_diff() * * Generates a host table containing entries in ht2 but not in ht1. */ struct htab * ht_diff(htp2, htp1) struct htab *htp2; /* more */ struct htab *htp1; /* less */ { struct htab *htp; int hh; htp = ht_new(1); for (hh = htp2->ht_last; hh > 0; hh--) if (htp2->ht_hosts[hh] && !htp2->ht_hosts[hh]->hd_err && (hh > htp1->ht_last || !htp1->ht_hosts[hh])) ht_insert(htp, htp2->ht_hosts[hh]); return htp; } /* gotnewhosts() * * Used to wake up any waitcs of kind WT_HOSTA. * Sends a message containing count and list of new d-tids. */ gotnewhosts(htp2, htp1) struct htab *htp2; /* new host table */ struct htab *htp1; /* old host table */ { struct pmsg *mp; struct htab *htp; struct waitc *wp, *wp2; int hh; mp = 0; for (wp = waitlist->wa_link; wp != waitlist; wp = wp2) { wp2 = wp->wa_link; if (wp->wa_kind == WT_HOSTA) { if (!mp) { mp = mesg_new(0); htp = ht_diff(htp2, htp1); pkint(mp, htp->ht_cnt); for (hh = htp->ht_last; hh > 0; hh--) if (htp->ht_hosts[hh]) pkint(mp, htp->ht_hosts[hh]->hd_hostpart); ht_free(htp); } mp->m_ref++; mp->m_dst = wp->wa_mesg->m_dst; mp->m_ctx = wp->wa_mesg->m_ctx; mp->m_tag = wp->wa_mesg->m_tag; sendmessage(mp); if (wp->wa_count != -1 && --wp->wa_count < 1) wait_delete(wp); } } if (mp) pmsg_unref(mp); return 0; } /* dm_htcommit() * * Host table update phase 2 - commit to new host table. * * DM_HTCOMMIT { } */ int dm_htcommit(hp, mp) struct hostd *hp; struct pmsg *mp; { struct htab *htp; if (hp != hosts->ht_hosts[hosts->ht_master]) { pvmlogprintf("dm_htcommit() from t%x (not master)?\n", mp->m_src); } if (newhosts) { htp = hosts; hosts = newhosts; newhosts = 0; if (pvmdebmask & PDMHOST) { pvmlogprintf( "dm_htcommit() committing from host table serial %d to %d\n", htp->ht_serial, hosts->ht_serial); } gotnewhosts(hosts, htp); ht_free(htp); runstate = PVMDNORMAL; } else { pvmlogerror("dm_htcommit() no new host table pending?\n"); } return 0; } /* dm_slconf() * * Pvmd gets config info (from master). * One of these should arrive before a pvmd is fully up, even * before the host table update, to set private params. * More may be used later to set random knobs. * * DM_SLCONF { * { * int fieldtype // from ddpro.h * string value * } [] // implied * } */ int dm_slconf(hp, mp) struct hostd *hp; struct pmsg *mp; { int t; /* field type */ char *s, *s2; mp = mp; hp = hp; while (!upkint(mp, &t) && !upkstralloc(mp, &s)) { switch (t) { case DM_SLCONF_EP: if (pvmdebmask & (PDMTASK|PDMSTARTUP)) { pvmlogprintf("dm_slconf() ep<%s>\n", s); } epaths = colonsep(varsub(s)); PVM_FREE(s); break; case DM_SLCONF_BP: if (pvmdebmask & PDMSTARTUP) { pvmlogprintf("dm_slconf() bp<%s>\n", s); } debugger = varsub(s); PVM_FREE(s); break; case DM_SLCONF_WD: if (pvmdebmask & (PDMTASK|PDMSTARTUP)) { pvmlogprintf("dm_slconf() wd<%s>\n", s); } s2 = varsub(s); if (chdir(s2) == -1) pvmlogperror(s2); PVM_FREE(s); PVM_FREE(s2); break; case DM_SLCONF_SCHED: if (pvmdebmask & (PDMSCHED|PDMSTARTUP)) { pvmlogprintf("dm_slconf() sched\n", pvmschedtid); } pvmschedtid = pvmxtoi(s); break; case DM_SLCONF_TRACE: { Pvmtmask tmask; int ttid, tctx, ttag, otid, octx, otag, tbuf, topt; if (pvmdebmask & (PDMTRACE|PDMSTARTUP)) { pvmlogprintf("dm_slconf() tracer\n", pvmtracer.trctid); } if (sscanf(s, "%x %d %d %x %d %d %d %d %s", &ttid, &tctx, &ttag, &otid, &octx, &otag, &tbuf, &topt, tmask) != 9) { pvmlogprintf("dm_slconf() bogus string<%s>\n", s); } else { pvmtracer.trctid = ttid; pvmtracer.trcctx = tctx; pvmtracer.trctag = ttag; pvmtracer.outtid = otid; pvmtracer.outctx = octx; pvmtracer.outtag = otag; pvmtracer.trcbuf = tbuf; pvmtracer.trcopt = topt; BCOPY(tmask,pvmtracer.tmask,TEV_MASK_LENGTH); } break; } default: pvmlogprintf("dm_slconf() ? type %d val <%s>\n", t, s); PVM_FREE(s); break; } } return 0; } /* startack() * * Take results from pvmd' or hoster. Update the machine config * if any were successful. Reply to the DM_ADD or SM_ADD request. */ int startack(wp, mp) struct waitc *wp; /* wait context on hoster */ struct pmsg *mp; { struct hostd *hp; struct pmsg *mp2; struct waitc *wp2; /* seed waitc for htupd peer group */ struct waitc *wp3; int count; /* num of new hosts */ int happy; /* num of happy new hosts */ struct waitc_add *wxp; char *av[16]; /* for reply parsing */ int ac; int ver; int i, j; int t; int hh; char *buf; char buf2[256]; /* * unpack startup results, update hosts in wait context */ wxp = (struct waitc_add *)wp->wa_spec; count = wxp->w_num; upkint(mp, &j); while (j-- > 0) { if (upkuint(mp, &t) || upkstralloc(mp, &buf)) { pvmlogerror("startack() bad message format\n"); pkint(wp->wa_mesg, PvmDSysErr); sendmessage(wp->wa_mesg); wp->wa_mesg = 0; wait_delete(wp); busyadding = 0; return 0; } for (i = count; i-- > 0 && wxp->w_hosts[i]->hd_hostpart != t; ) ; if (i < 0) { pvmlogprintf("startack() what? some random tid %x\n", t); pkint(wp->wa_mesg, PvmDSysErr); sendmessage(wp->wa_mesg); wp->wa_mesg = 0; wait_delete(wp); busyadding = 0; PVM_FREE(buf); return 0; } hp = wxp->w_hosts[i]; ac = sizeof(av)/sizeof(av[0]); if (crunchzap(buf, &ac, av) || ac != 5) { pvmlogprintf("startack() host %s expected version, got \"%s\"\n", hp->hd_name, buf); if (!(hp->hd_err = errnamecode(buf))) hp->hd_err = PvmCantStart; PVM_FREE(buf); continue; } ver = atoi(av[0]); if (ver != DDPROTOCOL) { pvmlogprintf( "slave_exec() host %s d-d protocol mismatch (%d/%d)\n", hp->hd_name, ver, DDPROTOCOL); hp->hd_err = PvmBadVersion; continue; } hp->hd_arch = STRALLOC(av[1]); hex_inadport(av[2], &hp->hd_sad); hp->hd_mtu = atoi(av[3]); hp->hd_dsig = atoi(av[4]); PVM_FREE(buf); } /* * update reply message to add-host requestor */ mp2 = wp->wa_mesg; pkint(mp2, count); pkint(mp2, 0); /* XXX narches = 0 for now */ for (i = 0; i < count; i++) { hp = wxp->w_hosts[i]; if (hp->hd_err) { pkint(mp2, hp->hd_err); pkstr(mp2, ""); pkstr(mp2, ""); pkint(mp2, 0); pkint(mp2, 0); } else { pkint(mp2, hp->hd_hostpart); pkstr(mp2, hp->hd_name); pkstr(mp2, hp->hd_arch); pkint(mp2, hp->hd_speed); pkint(mp2, hp->hd_dsig); } } /* * delete broken ones, done now if none succeeded, * otherwise done when host table update is complete. */ for (j = i = 0; i < count; i++) if (!wxp->w_hosts[i]->hd_err) { hp = wxp->w_hosts[i]; wxp->w_hosts[i] = 0; wxp->w_hosts[j++] = hp; } else { hd_unref(wxp->w_hosts[i]); wxp->w_hosts[i] = 0; } count = j; if (count < 1) { busyadding = 0; sendmessage(wp->wa_mesg); wp->wa_mesg = 0; free_waitc_add(wxp); wait_delete(wp); return 0; } wp2 = wait_new(WT_HTUPD); wp2->wa_dep = wp->wa_dep; wp2->wa_mesg = wp->wa_mesg; wp->wa_mesg = 0; /* * make next host table */ newhosts = ht_new(1); newhosts->ht_serial = hosts->ht_serial + 1; newhosts->ht_master = hosts->ht_master; newhosts->ht_cons = hosts->ht_cons; newhosts->ht_local = hosts->ht_local; for (i = 0; i < count; i++) ht_insert(newhosts, wxp->w_hosts[i]); free_waitc_add(wxp); wait_delete(wp); wp = 0; runstate = PVMDHTUPD; /* * send DM_SLCONF message to each new host */ for (hh = newhosts->ht_last; hh > 0; hh--) if (hp = newhosts->ht_hosts[hh]) { mp2 = mesg_new(0); mp2->m_tag = DM_SLCONF; mp2->m_dst = hp->hd_hostpart | TIDPVMD; if (hp->hd_epath) { pkint(mp2, DM_SLCONF_EP); pkstr(mp2, hp->hd_epath); } if (hp->hd_bpath) { pkint(mp2, DM_SLCONF_BP); pkstr(mp2, hp->hd_bpath); } if (hp->hd_wdir) { pkint(mp2, DM_SLCONF_WD); pkstr(mp2, hp->hd_wdir); } if (pvmschedtid) { sprintf(buf2, "%x", pvmschedtid); pkint(mp2, DM_SLCONF_SCHED); pkstr(mp2, buf2); } if (pvmtracer.trctid || pvmtracer.outtid) { sprintf(buf2, "%x %d %d %x %d %d %d %d %s", pvmtracer.trctid, pvmtracer.trcctx, pvmtracer.trctag, pvmtracer.outtid, pvmtracer.outctx, pvmtracer.outtag, pvmtracer.trcbuf, pvmtracer.trcopt, pvmtracer.tmask); pkint(mp2, DM_SLCONF_TRACE); pkstr(mp2, buf2); } sendmessage(mp2); } /* * create host table update message containing all current hosts * plus new ones, send to each new host. */ mp2 = mesg_new(0); mp2->m_tag = DM_HTUPD; pkint(mp2, newhosts->ht_serial); pkint(mp2, newhosts->ht_master); pkint(mp2, newhosts->ht_cons); pkint(mp2, hosts->ht_cnt + newhosts->ht_cnt); for (hh = hosts->ht_last; hh > 0; hh--) if (hp = hosts->ht_hosts[hh]) { pkint(mp2, hh); pkstr(mp2, hp->hd_name); pkstr(mp2, hp->hd_arch); pkstr(mp2, inadport_hex(&hp->hd_sad)); pkint(mp2, hp->hd_mtu); pkint(mp2, hp->hd_speed); pkint(mp2, hp->hd_dsig); } for (hh = newhosts->ht_last; hh > 0; hh--) if (hp = newhosts->ht_hosts[hh]) { pkint(mp2, hh); pkstr(mp2, hp->hd_name); pkstr(mp2, hp->hd_arch); pkstr(mp2, inadport_hex(&hp->hd_sad)); pkint(mp2, hp->hd_mtu); pkint(mp2, hp->hd_speed); pkint(mp2, hp->hd_dsig); } for (hh = newhosts->ht_last; hh > 0; hh--) if (hp = newhosts->ht_hosts[hh]) { mp2->m_ref++; mp2->m_dst = hp->hd_hostpart | TIDPVMD; wp3 = wait_new(WT_HTUPD); wp3->wa_dep = wp2->wa_dep; wp2->wa_mesg->m_ref++; wp3->wa_mesg = wp2->wa_mesg; wp3->wa_on = hp->hd_hostpart; LISTPUTBEFORE(wp2, wp3, wa_peer, wa_rpeer); mp2->m_wid = wp3->wa_wid; sendmessage(mp2); } pmsg_unref(mp2); /* * create host table update message containing happy new hosts, * send to each old host. */ mp2 = mesg_new(0); mp2->m_tag = DM_HTUPD; pkint(mp2, newhosts->ht_serial); pkint(mp2, newhosts->ht_master); pkint(mp2, newhosts->ht_cons); pkint(mp2, newhosts->ht_cnt); for (hh = newhosts->ht_last; hh > 0; hh--) if (hp = newhosts->ht_hosts[hh]) { pkint(mp2, hh); pkstr(mp2, hp->hd_name); pkstr(mp2, hp->hd_arch); pkstr(mp2, inadport_hex(&hp->hd_sad)); pkint(mp2, hp->hd_mtu); pkint(mp2, hp->hd_speed); pkint(mp2, hp->hd_dsig); } for (hh = hosts->ht_last; hh > 0; hh--) if (hh != hosts->ht_local && (hp = hosts->ht_hosts[hh])) { mp2->m_ref++; mp2->m_dst = hp->hd_hostpart | TIDPVMD; wp3 = wait_new(WT_HTUPD); wp3->wa_dep = wp2->wa_dep; wp2->wa_mesg->m_ref++; wp3->wa_mesg = wp2->wa_mesg; wp3->wa_on = hp->hd_hostpart; LISTPUTBEFORE(wp2, wp3, wa_peer, wa_rpeer); mp2->m_wid = wp3->wa_wid; sendmessage(mp2); } pmsg_unref(mp2); /* * update our host table */ gotnewhosts(newhosts, hosts); /* XXX returning to normal state right here is a hack, we should XXX wait for all the htupdacks to come back but we need the XXX regular message service, hostfail entry, etc. */ for (hh = newhosts->ht_last; hh > 0; hh--) if ((hp = newhosts->ht_hosts[hh]) && !hp->hd_err) ht_insert(hosts, hp); hosts->ht_serial = newhosts->ht_serial; if (pvmdebmask & PDMHOST) { pvmlogerror("startack() committing to new host table:\n"); ht_dump(hosts); } runstate = PVMDNORMAL; ht_free(newhosts); newhosts = 0; /* if peered waitcs on htupdack already finished, send the reply */ if (wp2->wa_peer == wp2) { busyadding = 0; sendmessage(wp2->wa_mesg); wp2->wa_mesg = 0; } wait_delete(wp2); return 0; } /* dm_startack() * * The results come back from the pvmd' hoster to pvmd[master]. * * DM_STARTACK(wid_rtn) { * int count * { * int tid * string result // line from slave pvmd or error token * } [count] * } */ int dm_startack(hp, mp) struct hostd *hp; struct pmsg *mp; { struct waitc *wp; /* wait context on pvmd' */ if (!(wp = wait_get(hp, mp, WT_HOSTSTART))) return 0; finack_to_host(hp); startack(wp, mp); return 0; } /* dm_task() * * (Remote or local) pvmd requests information about local task(s). * * DM_TASK(wid) { * int where // 0 for all, hostpart, or full tid * } */ int dm_task(hp, mp) struct hostd *hp; struct pmsg *mp; { struct task *tp; struct pmsg *mp2; int where; hp = hp; if (upkuint(mp, &where)) { pvmlogerror("dm_task() bad msg format\n"); return 0; } #ifdef SHMEM mpp_setstatus(0); /* get status from global info table */ #endif /* pack list of local tasks and reply to waiter */ mp2 = mesg_new(0); mp2->m_dst = mp->m_src; mp2->m_tag = DM_TASKACK; mp2->m_wid = mp->m_wid; if (where & tidlmask) { if (tp = task_find(where)) { pkint(mp2, tp->t_tid); pkint(mp2, tp->t_ptid); pkint(mp2, myhostpart); pkint(mp2, tp->t_flag); pkstr(mp2, tp->t_a_out ? tp->t_a_out : ""); pkint(mp2, tp->t_pid); } } else { for (tp = locltasks->t_link; tp != locltasks; tp = tp->t_link) { pkint(mp2, tp->t_tid); pkint(mp2, tp->t_ptid); pkint(mp2, myhostpart); pkint(mp2, tp->t_flag); pkstr(mp2, (tp->t_a_out ? tp->t_a_out : "")); pkint(mp2, tp->t_pid); } } sendmessage(mp2); return 0; } /* dm_taskack() * * Reply to DM_TASK op. * * DM_TASKACK(wid_rtn) { * { * int tid * int ptid * int hostpart * int flag * string a_out * int pid * } [] // implied * } */ int dm_taskack(hp, mp) struct hostd *hp; struct pmsg *mp; { struct waitc *wp; struct pmsg *mp2; int i; char *p; if (!(wp = wait_get(hp, mp, WT_TASK))) return 0; /* append data to waiting message */ mp2 = wp->wa_mesg; while (!upkint(mp, &i)) { pkint(mp2, i); /* tid */ upkint(mp, &i); /* ptid */ pkint(mp2, i); upkint(mp, &i); /* host */ pkint(mp2, i); upkint(mp, &i); /* flag */ pkint(mp2, i); upkstralloc(mp, &p); /* a.out name */ pkstr(mp2, p); PVM_FREE(p); upkint(mp, &i); /* pid */ pkint(mp2, i); } /* send message if we're the last waiter */ if (wp->wa_peer == wp) { mp2->m_ref++; sendmessage(mp2); } wait_delete(wp); return 0; } /* dm_delhost() * * (Master pvmd) gets request to delete hosts. * * DM_DELHOST(wid) { * int count * string names[count] * } */ int dm_delhost(hp, mp) struct hostd *hp; struct pmsg *mp; { int count; char *buf; struct pmsg *mp2; /* DELHOSTACK message */ struct pmsg *mp3; /* HTDEL message */ struct htab *ht_del; /* hosts to delete */ struct htab *ht_save; /* remaining hosts */ int hh; /* XXX danger, this doesn't check if already doing a host add/delete */ /* sanity check count */ if (upkint(mp, &count)) { pvmlogerror("dm_delhost() bad msg format\n"); return 0; } if (count < 1 || count > (tidhmask >> (ffs(tidhmask) - 1))) { pvmlogerror("dm_delhost() bad count\n"); return 0; } /* * read host names from message, generate delete and save sets * and a DELHOSTACK reply message with result code for each host. * set SHUTDOWN flag for each host in delete set. */ ht_del = ht_new(1); ht_save = ht_new(1); ht_merge(ht_save, hosts); mp2 = mesg_new(0); mp2->m_tag = DM_DELHOSTACK; mp2->m_wid = mp->m_wid; mp2->m_dst = mp->m_src; mp3 = mesg_new(0); mp3->m_tag = DM_HTDEL; pkint(mp3, hosts->ht_serial); pkint(mp2, count); while (count-- > 0) { upkstralloc(mp, &buf); if (hp = nametohost(hosts, buf)) { if (tidtohost(ht_del, hp->hd_hostpart)) { pkint(mp2, PvmDupHost); } else { if (hp->hd_hostpart == myhostpart) pkint(mp2, PvmBadParam); else { ht_insert(ht_del, hp); ht_delete(ht_save, hp); pkint(mp3, hp->hd_hostpart); fin_to_host(hp); pkint(mp2, 0); } } } else pkint(mp2, PvmNoHost); PVM_FREE(buf); } /* * send HTDEL message to all hosts in ht_save set except us */ for (hh = ht_save->ht_last; hh > 0; hh--) if (hh != hosts->ht_local && (hp = ht_save->ht_hosts[hh])) { mp3->m_ref++; mp3->m_dst = hp->hd_hostpart | TIDPVMD; sendmessage(mp3); } pmsg_unref(mp3); /* reply to host that requested DELHOST operation */ sendmessage(mp2); ht_free(ht_del); ht_free(ht_save); return 0; } /* dm_delhostack() * * Reply to DM_DELHOST operation. * * DM_DELHOSTACK(wid_rtn) { * int count // or negative for error * int status[count] // status of each host * } */ int dm_delhostack(hp, mp) struct hostd *hp; struct pmsg *mp; { struct waitc *wp; if (!(wp = wait_get(hp, mp, WT_DELHOST))) return 0; pmsg_packbody(wp->wa_mesg, mp); sendmessage(wp->wa_mesg); wp->wa_mesg = 0; wait_delete(wp); return 0; } /* dm_null() * * No-op message. * * DM_NULL { } */ int dm_null(hp, mp) struct hostd *hp; struct pmsg *mp; { hp = hp; mp = mp; /* pvmlogprintf("dm_null() from %s\n", hp->hd_name); */ return 0; } /* dm_taskout() * * Stdout data from a task. * * DM_TASKOUT { * int tid * int length * char data[length] * } */ int dm_taskout(hp, mp) struct hostd *hp; struct pmsg *mp; { int tid; int l; char *p, *q, c; char buf2[32]; char buf[4100]; /* XXX a bit bigger than in pvmd.c`loclstout() */ hp = hp; if (upkuint(mp, &tid) || upkint(mp, &l) || l < 1) return 0; /* unpack data, leaving room at head of buffer */ p = buf + 32; if (l > sizeof(buf) - (p - buf) - 2) l = sizeof(buf) - (p - buf) - 2; upkbyte(mp, p, l); /* ends with "\n\0" */ if (p[l - 1] != '\n') p[l++] = '\n'; p[l] = 0; sprintf(buf2, "[t%x] ", tid); l = strlen(buf2); while (*p) { for (q = p; *q++ != '\n'; ) ; c = *q; *q = 0; BCOPY(buf2, p - l, l); pvmlogerror(p - l); *q = c; p = q; } return 0; } /* dm_pstat() * * (Remote or local) pvmd requests status of a local task. * * DM_PSTAT(wid) { * int tid * } */ int dm_pstat(hp, mp) struct hostd *hp; struct pmsg *mp; { int tid; struct pmsg *mp2; hp = hp; upkuint(mp, &tid); if (tid == pvmmytid || task_find(tid)) tid = 0; else tid = PvmNoTask; mp2 = mesg_new(0); mp2->m_dst = mp->m_src; mp2->m_tag = DM_PSTATACK; mp2->m_wid = mp->m_wid; pkint(mp2, tid); sendmessage(mp2); return 0; } /* dm_pstatack() * * Reply to DM_PSTAT op. * * DM_PSTATACK(wid_rtn) { * int status * } */ int dm_pstatack(hp, mp) struct hostd *hp; struct pmsg *mp; { struct waitc *wp; if (!(wp = wait_get(hp, mp, 0))) return 0; pmsg_packbody(wp->wa_mesg, mp); sendmessage(wp->wa_mesg); wp->wa_mesg = 0; wait_delete(wp); return 0; } /* dm_halt() * * Task has requested whole machine to halt. * * DM_HALT { } */ int dm_halt(hp, mp) struct hostd *hp; struct pmsg *mp; { int hh; pvmlogprintf("dm_halt() from (%s), halting...\n", hp->hd_name); for (hh = hosts->ht_last; hh > 0; hh--) { if (hh == hosts->ht_local || !(hp = hosts->ht_hosts[hh])) continue; finack_to_host(hp); } runstate = PVMDHALTING; return 0; } /* dm_mca() * * Remote pvmd defines a new (single-use) multicast address, to be used * by a subsequent message. * * DM_MCA { * int gtid // multicast tid * int count // number of addresses * int tids[count] // addresses * } */ int dm_mca(hp, mp) struct hostd *hp; struct pmsg *mp; { struct mca *mcap; int i; /* unpack struct mca from message */ mcap = mca_new(); upkuint(mp, &mcap->mc_tid); upkint(mp, &mcap->mc_ndst); mcap->mc_dsts = TALLOC(mcap->mc_ndst, int, "mcad"); for (i = 0; i < mcap->mc_ndst; i++) upkuint(mp, &mcap->mc_dsts[i]); /* put on list of mcas of src host */ LISTPUTBEFORE(hp->hd_mcas, mcap, mc_link, mc_rlink); if (pvmdebmask & PDMMESSAGE) { pvmlogprintf("dm_mca() mca %x from %s\n", mcap->mc_tid, hp->hd_name); } return 0; } /* dm_notify() * * Remote pvmd requests to be notified on an event. * * DM_NOTIFY(wid) { * int what // event type, currenty only PvmTaskExit * int tid // address * } */ int dm_notify(hp, mp) struct hostd *hp; struct pmsg *mp; { int what, tid; struct waitc *wp; struct pmsg *mp2; hp = hp; upkint(mp, &what); upkuint(mp, &tid); if (what != PvmTaskExit) { pvmlogprintf("dm_notify() what = %d?\n", what); return 0; } mp2 = mesg_new(0); mp2->m_dst = mp->m_src; mp2->m_tag = DM_NOTIFYACK; mp2->m_wid = mp->m_wid; pkint(mp2, tid); if (task_find(tid)) { wp = wait_new(WT_TASKX); wp->wa_on = tid; wp->wa_tid = mp->m_src; wp->wa_dep = mp->m_wid; wp->wa_mesg = mp2; } else { sendmessage(mp2); } return 0; } /* dm_notifyack() * * Reply to DM_NOTIFY op. * * DM_NOTIFYACK(wid_rtn) { } */ int dm_notifyack(hp, mp) struct hostd *hp; struct pmsg *mp; { struct waitc *wp; hp = hp; if (!(wp = wait_get((struct hostd*)0, mp, 0))) return 0; if (wp->wa_tid && wp->wa_mesg) { sendmessage(wp->wa_mesg); wp->wa_mesg = 0; } if ( wp->wa_tid == pvmmytid ) mb_tidy(wp->wa_on); wait_delete(wp); return 0; } /* dm_db() * * (Remote or local) pvmd requests a database op. * * DM_DB(wid) { * int opcode // TMDB_PUT, TMDB_REMOVE, TMDB_GET, TMDB_NAMES * int tid // owner task (XXX we're just taking its word, hahaha) * string name * int index * int flags * msg data // if TMDB_PUT * } */ int dm_db(hp, mp) struct hostd *hp; struct pmsg *mp; { int opcode; /* op requested */ int tid; int req; /* index requested */ int flags; char *name = 0; /* class name */ struct pmsg *mp2 = 0; /* reply */ struct pmsg *mp3 = 0; /* data message */ struct waitc *wp, *wp2; /* wait ctx ptrs (notify, recvinfo */ struct pmsg *mp4 = 0; /* notify forward message */ struct hostd *hp2; /* remote notify host */ struct pvmmclass *np, *np2; /* reset pointers */ struct pvmmentry *ep, *ep2; /* reset pointers */ int *noresets; /* noreset tids */ int nnr; /* # of noreset tasks */ int found; int cc; int i; int notified; hp = hp; if (upkint(mp, &opcode) || upkint(mp, &tid) || upkstralloc(mp, &name) || upkint(mp, &req) || upkint(mp, &flags)) goto badformat; mp2 = mesg_new(0); mp2->m_dst = mp->m_src; mp2->m_tag = DM_DBACK; mp2->m_wid = mp->m_wid; switch (opcode) { case TMDB_PUT: mp3 = mesg_new(0); if (pmsg_unpack(mp, mp3)) goto badformat; if ((req = mb_insert(tid, name, req, flags, mp3)) < 0) pmsg_unref(mp3); else { /* check for any pending requests for this mbox entry */ notified = 0; for (wp = waitlist->wa_link; wp != waitlist; wp = wp2) { wp2 = wp->wa_link; if (wp->wa_kind == WT_RECVINFO) { ep = (struct pvmmentry *) wp->wa_spec; if ( !strcmp( (char *) ep->me_msg, name ) ) { cc = mb_lookup(ep->me_tid, (char *) ep->me_msg, ep->me_ind, ep->me_flags, &mp3); if ( cc != PvmNotFound ) { pkint(wp->wa_mesg, cc); if (mp3) { pmsg_pack(wp->wa_mesg, mp3); pmsg_unref(mp3); } sendmessage(wp->wa_mesg); wp->wa_mesg = 0; PVM_FREE(ep->me_msg); PVM_FREE(ep); wait_delete(wp); } } } /* check if task needs mbox notify for mb_tidy()... */ else if (wp->wa_kind == WT_TASKX) { if ( wp->wa_on == tid && wp->wa_tid == pvmmytid ) notified++; } } /* create mbox notify for mb_tidy() cleanup... */ if ( !notified ) { /* dummy notify for clean up */ wp = wait_new(WT_TASKX); wp->wa_on = tid; wp->wa_tid = pvmmytid; wp->wa_dep = 0; wp->wa_mesg = (struct pmsg *) NULL; /* pass on to non-master host */ hp2 = tidtohost(hosts, tid); if ( hp2 && hp2->hd_hostpart != myhostpart ) { mp4 = mesg_new(0); pkint(mp4, PvmTaskExit); pkint(mp4, tid); mp4->m_dst = hp2->hd_hostpart | TIDPVMD; mp4->m_tag = DM_NOTIFY; mp4->m_wid = wp->wa_wid; sendmessage(mp4); } } } pkint(mp2, req); break; case TMDB_REMOVE: req = mb_delete(tid, name, req, flags); pkint(mp2, req); break; case TMDB_GET: cc = mb_lookup(tid, name, req, flags, &mp3); if ( cc == PvmNotFound && (flags & PvmMboxWaitForInfo) ) { ep = me_new(req); ep->me_tid = tid; ep->me_msg = (struct pmsg *) name; /* XXX ouch, overload */ ep->me_flags = flags; wp = wait_new(WT_RECVINFO); wp->wa_on = tid; wp->wa_tid = pvmmytid; wp->wa_dep = mp->m_wid; wp->wa_mesg = mp2; wp->wa_spec = (void *) ep; return 0; } else { pkint(mp2, cc); if (mp3) { pmsg_pack(mp2, mp3); pmsg_unref(mp3); } } break; case TMDB_NAMES: pkint(mp2, 0); req = mb_names(tid, name, mp2); break; case TMDB_RESET: if ( upkint(mp, &nnr) ) goto badformat; noresets = TALLOC( nnr, int, "int" ); for ( i=0 ; i < nnr ; i++ ) { if ( upkint(mp, &(noresets[i])) ) { PVM_FREE(noresets); goto badformat; } } pkint(mp2, 0); for (np = pvmmboxclasses->mc_link; np != pvmmboxclasses; np = np2) { np2 = np->mc_link; /* If name passed in, only wipe mboxes in that class */ if ( *name == '\0' || !strcmp( np->mc_name, name ) ) { for (ep = np->mc_ent->me_link; ep != np->mc_ent; ep = ep2) { ep2 = ep->me_link; /* If index passed in, only wipe that mbox */ /* -1 == All Entries */ if ( req < 0 || req == ep->me_ind ) { /* Check for Persistency (that thorn in my "side" :-) */ if ( ep->me_flags & PvmMboxPersistent ) { /* Task Already Gone? Spank It. */ if (!(ep->me_tid)) { me_free(np, ep); if (np2->mc_rlink != np) break; } /* Check for No-Reset Task */ /* (Only if actually killing tasks...) */ else if ( flags ) { /* killtasks */ for ( i=0, found=0 ; i < nnr && !found ; i++ ) if ( noresets[i] == ep->me_tid ) found++; /* Not a No-Reset, It WILL die soon. */ /* Wait for cleanup. */ if ( !found ) { wp = wait_new(WT_RESET); wp->wa_on = ep->me_tid; wp->wa_tid = pvmmytid; wp->wa_dep = 0; wp->wa_mesg = (struct pmsg *) NULL; /* pass on to non-master host */ hp2 = tidtohost(hosts, ep->me_tid); if ( hp2 && hp2->hd_hostpart != myhostpart ) { mp4 = mesg_new(0); pkint(mp4, ep->me_tid); mp4->m_dst = hp2->hd_hostpart | TIDPVMD; mp4->m_tag = DM_RESET; mp4->m_wid = wp->wa_wid; sendmessage(mp4); } } } } } } } } PVM_FREE(noresets); break; default: goto badformat; } sendmessage(mp2); PVM_FREE(name); return 0; badformat: pvmlogerror("dm_db() bad msg format\n"); if (name) PVM_FREE(name); if (mp2) pmsg_unref(mp2); return 0; } /* dm_dback() * * Reply to DM_DB op. * * DM_DBACK(wid_rtn) { * int status // and index * if TMDB_PUT, TMDB_REMOVE, TMDB_GET * msg data // if TMDB_GET * else if TMDB_NAMES * string names[] // list of names, length implied * } */ int dm_dback(hp, mp) struct hostd *hp; struct pmsg *mp; { struct waitc *wp; if (!(wp = wait_get(hp, mp, WT_DB))) return 0; pmsg_packbody(wp->wa_mesg, mp); sendmessage(wp->wa_mesg); wp->wa_mesg = 0; wait_delete(wp); return 0; } /* dm_reset() * * Remote pvmd requests to be notified when task is reset. * - for mbox cleanup... * * DM_RESET(wid) { * int tid // task id of persistent mbox owner * } */ int dm_reset(hp, mp) struct hostd *hp; struct pmsg *mp; { int tid; struct waitc *wp; struct pmsg *mp2; hp = hp; upkuint(mp, &tid); mp2 = mesg_new(0); mp2->m_dst = mp->m_src; mp2->m_tag = DM_RESETACK; mp2->m_wid = mp->m_wid; pkint(mp2, tid); if (task_find(tid)) { wp = wait_new(WT_RESET); wp->wa_on = tid; wp->wa_tid = mp->m_src; wp->wa_dep = mp->m_wid; wp->wa_mesg = mp2; } else { sendmessage(mp2); } return 0; } /* dm_resetack() * * Reply to DM_RESET op. * * DM_RESETACK(wid_rtn) { } */ int dm_resetack(hp, mp) struct hostd *hp; struct pmsg *mp; { struct waitc *wp; hp = hp; if (!(wp = wait_get((struct hostd*)0, mp, 0))) return 0; if (wp->wa_tid && wp->wa_mesg) { sendmessage(wp->wa_mesg); wp->wa_mesg = 0; } mb_tidy_reset(wp->wa_on); wait_delete(wp); return 0; } int dm_htdel(hp, mp) struct hostd *hp; struct pmsg *mp; { int serial; int tid; if (hp != hosts->ht_hosts[hosts->ht_master]) { pvmlogprintf("dm_htdel() from t%x (not master)?\n", mp->m_src); return 0; } if (upkint(mp, &serial)) { pvmlogerror("dm_htdel() bad format\n"); return 0; } if (serial != hosts->ht_serial) { pvmlogprintf("dm_htdel() for serial %d, current is %d?\n", serial, hosts->ht_serial); return 0; } while (!upkuint(mp, &tid)) { if (hp = tidtohost(hosts, tid)) { if (pvmdebmask & PDMHOST) { pvmlogprintf("dm_htdel() host %s\n", hp->hd_name); } hostfailentry(hp); ht_delete(hosts, hp); if (newhosts) ht_delete(newhosts, hp); } } return 0; } /* dm_hostsync() * * Request time of day clock sample * * DM_HOSTSYNC(wid) { } */ int dm_hostsync(hp, mp) struct hostd *hp; struct pmsg *mp; { struct pmsg *mp2; struct timeval now; mp = mp; hp = hp; mp2 = mesg_new(0); mp2->m_dst = mp->m_src; mp2->m_tag = DM_HOSTSYNCACK; mp2->m_wid = mp->m_wid; gettimeofday(&now, (struct timezone *)0); pkint(mp2, (int)now.tv_sec); pkint(mp2, (int)now.tv_usec); sendmessage(mp2); return 0; } /* dm_hostsyncack() * * Clock sample comes back * * DM_HOSTSYNCACK(wid_rtn) { * int sec * int usec * } */ int dm_hostsyncack(hp, mp) struct hostd *hp; struct pmsg *mp; { struct waitc *wp; int i; if (!(wp = wait_get(hp, mp, WT_HOSTSYNC))) return 0; pkint(wp->wa_mesg, 0); upkuint(mp, &i); pkint(wp->wa_mesg, i); upkuint(mp, &i); pkint(wp->wa_mesg, i); sendmessage(wp->wa_mesg); wp->wa_mesg = 0; wait_delete(wp); return 0; } struct mca * mca_new() { struct mca *mcap; if (mcap = TALLOC(1, struct mca, "mca")) { mcap->mc_link = mcap->mc_rlink = mcap; mcap->mc_tid = mcap->mc_ndst = 0; mcap->mc_dsts = 0; } return mcap; } void mca_free(mcap) struct mca *mcap; { LISTDELETE(mcap, mc_link, mc_rlink); if (mcap->mc_dsts) PVM_FREE(mcap->mc_dsts); PVM_FREE(mcap); } struct pmsg * mesg_new(master) int master; { struct pmsg *mp; if (mp = pmsg_new(master)) { mp->m_src = pvmmytid; pmsg_setenc(mp, 0x10000000); /* PvmDataDefault */ (mp->m_codef->enc_init)(mp); } return mp; } ./pvm3/src/global.c0100644007401100000360000004304307521531050013275 0ustar kohlgopher static char rcsid[] = "$Id: global.c,v 1.19 2002/07/30 15:35:04 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * global.c * * General PVM Globals. * * $Log: global.c,v $ * Revision 1.19 2002/07/30 15:35:04 pvmsrc * Enhanced PvmIPLoopback error text - "pvm3/"Readme file... Duh... * (Spanker=kohl) * * Revision 1.18 2001/02/07 23:14:03 pvmsrc * First Half of CYGWIN Check-ins... * (Spanker=kohl) * * Revision 1.17 2000/02/10 23:53:34 pvmsrc * Added new PvmIPLoopback error code: * - Master Host IP Address tied to Loopback. * - check for this case in addhosts(), don't even TRY to add hosts... * (Spanker=kohl) * * Revision 1.16 1999/07/08 18:59:52 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.15 1998/11/20 20:03:55 pvmsrc * Changes so that win32 will compile & build. Also, common * Changes so that compiles & builds on NT. Also * common source on win32 & unix. * (Spanker=sscott) * * Revision 1.14 1997/12/31 22:14:23 pvmsrc * Renamed TEV_REMOVE -> TEV_DELINFO. D-Oh. * (Spanker=kohl) * * Revision 1.13 1997/12/23 20:23:47 pvmsrc * Added new TEV_MHF_INVOKE trace event. * - include message handler src/tag/ctx settings. * - include actual message bufid, len, and src/tag/ctx. * - use new TEV_PUSHTOP, TEV_AMPUSHED and TEV_POPTOP macros to * fake top level tracing for PVM calls in message handler. * (Spanker=kohl) * * Revision 1.12 1997/12/17 22:15:34 pvmsrc * Added new mhf trace stuff. * - TEV_DID_MHI definition. * - TEV_ADDMHF & TEV_DELMHF trace event slots. * (Spanker=kohl) * * Revision 1.11 1997/10/24 15:17:42 pvmsrc * Added TEV_DID_RCX to trace events for Receive Message Context. * - in pvm_recv(), pvm_trecv(), pvm_nrecv(), and pvm_precv(). * (Spanker=kohl) * * Revision 1.10 1997/10/24 14:20:51 pvmsrc * Added TEV_DID_MCX to pvmtevdidinfo[]. * - for Message Context. * (Spanker=kohl) * * Revision 1.9 1997/06/27 17:32:19 pvmsrc * Updated for WIN32 header files & Authors. * * Revision 1.8 1997/06/26 19:38:48 pvmsrc * Add PvmParentNotSet * * Revision 1.7 1997/06/23 21:26:14 pvmsrc * Added new PvmHostrNMstr error code. * - Hoster must run on master host. * * Revision 1.6 1997/05/01 20:17:38 pvmsrc * Renamed TEV_MBOXINFO -> TEV_GETMBOXINFO. * * Revision 1.5 1997/04/10 20:13:45 pvmsrc * Replaced trace event for getnames -> mboxinfo. * * Revision 1.4 1997/04/08 19:57:49 pvmsrc * Promoted mbox static "classes" to public global "pvmmboxclasses". * - so pvmd can spank mboxes in ddpro.c... :-Q * - renamed everywhere, moved decl / extern to global.[ch]. * * Revision 1.3 1997/03/06 20:57:36 pvmsrc * Add host.h on its include list * * Revision 1.2 1997/01/28 19:26:16 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/10/24 19:43:02 pvmsrc * Initial revision * * */ #include #include #if defined(WIN32) || defined(CYGWIN) #include "..\xdr\types.h" #include "..\xdr\xdr.h" #else #include #include #endif #include "lpvm.h" #include "pmsg.h" #include "host.h" #include "waitc.h" #include #include "tevmac.h" #include "msgbox.h" #include "global.h" /*************** ** Globals ** ** ** ***************/ /* error messages for -pvm_errno */ char *pvm_errlist[] = { "Error 0", "Error 1", "Bad parameter", "Parameter mismatch", "Value too large", "End of buffer", "No such host", "No such file", "Permission denied", "Error 9", /* not used */ "Malloc failed", "Error 11", /* not used */ "Can't decode message", "Error 13", /* not used */ "Can't contact local daemon", "No current buffer", "No such buffer", "Null group name", "Already in group", "No such group", "Not in group", "No such instance", "Host failed", "No parent task", "Not implemented", "Pvmd system error", "Version mismatch", "Out of resources", "Duplicate host", "Can't start pvmd", "Already in progress", "No such task", "Not Found", "Already Exists", "Hoster must run on master host", "Spawning parent set PvmNoParent", "Master Host IP Address is Loopback! (See pvm3/Readme)", }; int pvm_nerr = /* exported num of errors */ sizeof(pvm_errlist) / sizeof(pvm_errlist[0]); int pvm_errno = 0; /* last err in PVM API funct */ struct waitc *waitlist = 0; /* wait list */ struct pvmmclass *pvmmboxclasses = 0; /* the mbox database */ /* Trace Data Identifier Structures */ struct Pvmtevdid pvmtevdidlist[] = { /* TEV_DID_AN */ "AN", "PVM Architecture Name", /* TEV_DID_AC */ "AC", "PVM Architecture Code", /* TEV_DID_AS */ "AS", "Argument Strings (Argc/Argv)", /* TEV_DID_BF */ "BF", "Block Flag", /* TEV_DID_CC */ "CC", "Condition Code", /* TEV_DID_CN */ "CN", "Class Name", /* TEV_DID_CI */ "CI", "Class Index", /* TEV_DID_CF */ "CF", "Class Flags", /* TEV_DID_CD */ "CD", "Class Data", /* TEV_DID_CR */ "CR", "Returned Class Data", /* TEV_DID_CL */ "CL", "Returned Class Names", /* TEV_DID_CDA */ "CDA", "Collective Data Address", /* TEV_DID_CDT */ "CDT", "Collective Data Type", /* TEV_DID_CDX */ "CDX", "Collective Data", /* TEV_DID_CDC */ "CDC", "Collective Count", /* TEV_DID_CGI */ "CGI", "Collective Group Result Instance", /* TEV_DID_CRF */ "CRF", "Collective Reduce Function", /* TEV_DID_CXC */ "CXC", "Current Message Context", /* TEV_DID_CXF */ "CXF", "Freed Message Context", /* TEV_DID_CXN */ "CXN", "New Message Context", /* TEV_DID_CXS */ "CXS", "Set Message Context", /* TEV_DID_ERI */ "ERI", "PVM Error Identifier", /* TEV_DID_ERR */ "ERR", "PVM Error String", /* TEV_DID_FDS */ "FDS", "File Descriptors", /* TEV_DID_FP */ "FP", "File Pointer", /* TEV_DID_GN */ "GN", "Group Name", /* TEV_DID_GI */ "GI", "Group Instance Number", /* TEV_DID_GT */ "GT", "Group Task ID", /* TEV_DID_GS */ "GS", "Group Size", /* TEV_DID_GBC */ "GBC", "Group Barrier Count", /* TEV_DID_HN */ "HN", "Host Name", /* TEV_DID_HNL */ "HNL", "Host Name List", /* TEV_DID_HNA */ "HNA", "Host Name Alias", /* TEV_DID_HPT */ "HPT", "Host PVMD Task ID", /* TEV_DID_HA */ "HA", "Host Architecture", /* TEV_DID_HSP */ "HSP", "Host Speed", /* TEV_DID_HIS */ "HIS", "Host Information Structures", /* TEV_DID_HCS */ "HCS", "Host Clock Seconds", /* TEV_DID_HCU */ "HCU", "Host Clock Microseconds", /* TEV_DID_HDS */ "HDS", "Host Delta Seconds", /* TEV_DID_HDU */ "HDU", "Host Delta Microseconds", /* TEV_DID_HS */ "HS", "Host Status", /* TEV_DID_INB */ "INB", "Info Number of Message Bytes", /* TEV_DID_IMC */ "IMC", "Info Message Code", /* TEV_DID_IST */ "IST", "Info Message Source Task", /* TEV_DID_MC */ "MC", "Message Code", /* TEV_DID_MCX */ "MCX", "Message Context", /* TEV_DID_MB */ "MB", "Message Buffer", /* TEV_DID_MNB */ "MNB", "Message Number of Bytes", /* TEV_DID_SRC */ "SRC", "Message Source Task ID", /* TEV_DID_DST */ "DST", "Message Destination Task ID", /* TEV_DID_MDL */ "MDL", "Message Destination Task ID List", /* TEV_DID_MTS */ "MTS", "Message Timeout Seconds", /* TEV_DID_MTU */ "MTU", "Message Timeout Microseconds", /* TEV_DID_MRF */ "MRF", "Message Receive Function", /* TEV_DID_MRB */ "MRB", "Message Receive Buffer", /* TEV_DID_MSB */ "MSB", "Message Send Buffer", /* TEV_DID_ME */ "ME", "Message Encoding", /* TEV_DID_MHI */ "MHI", "Message Handler Index", /* TEV_DID_AST */ "AST", "Actual Message Sender Task ID", /* TEV_DID_AMC */ "AMC", "Actual Message Code", /* TEV_DID_AML */ "AML", "Actual Message Length", /* TEV_DID_NE */ "NE", "Notify Event ID", /* TEV_DID_NMC */ "NMC", "Notify Message Code", /* TEV_DID_NCT */ "NCT", "Notify Count", /* TEV_DID_NTL */ "NTL", "Notify Task ID List", /* TEV_DID_NH */ "NH", "Number of Hosts", /* TEV_DID_NA */ "NA", "Number of Architectures", /* TEV_DID_OPT */ "OPT", "PVM Option ID", /* TEV_DID_OPV */ "OPV", "PVM Option Value", /* TEV_DID_OS */ "OS", "Output String", /* TEV_DID_PDA */ "PDA", "Pack Data Address", /* TEV_DID_PDT */ "PDT", "Pack Data Type", /* TEV_DID_PC */ "PC", "Pack Count", /* TEV_DID_PSD */ "PSD", "Pack Stride", /* TEV_DID_PSG */ "PSG", "Pack String", /* TEV_DID_PF */ "PF", "Pack Format", /* TEV_DID_PRF */ "PRF", "Profiling Count", /* TEV_DID_RST */ "RST", "Receive Msg Source Task / Wildcard", /* TEV_DID_RMC */ "RMC", "Receive Msg Code / Wildcard", /* TEV_DID_RCX */ "RCX", "Receive Msg Context", /* TEV_DID_SN */ "SN", "Signal Number", /* TEV_DID_SE */ "SE", "Spawn Executable File", /* TEV_DID_SF */ "SF", "Spawn Flags", /* TEV_DID_SW */ "SW", "Spawn Where", /* TEV_DID_SC */ "SC", "Spawn Count", /* TEV_DID_STL */ "STL", "Spawned Task ID List", /* TEV_DID_SIB */ "SIB", "Sibling Task ID List", /* TEV_DID_TID */ "TID", "Task ID", /* TEV_DID_PT */ "PT", "Parent Task ID", /* TEV_DID_MT */ "MT", "My Task ID", /* TEV_DID_TF */ "TF", "Task Flags", /* TEV_DID_TN */ "TN", "Task Name", /* TEV_DID_PID */ "PID", "Task Process ID", /* TEV_DID_TT */ "TT", "Target Task ID", /* TEV_DID_TW */ "TW", "Tasks Where", /* TEV_DID_TIS */ "TIS", "Task Information Structures", /* TEV_DID_TNT */ "TNT", "Task Info - Number of Tasks", /* TEV_DID_TST */ "TST", "Task Status", /* TEV_DID_TUS */ "TUS", "Task User Usage Seconds", /* TEV_DID_TUU */ "TUU", "Task User Usage Microseconds", /* TEV_DID_TSS */ "TSS", "Task System Usage Seconds", /* TEV_DID_TSU */ "TSU", "Task System Usage Microseconds", /* TEV_DID_TES */ "TES", "Task Exit Status", /* TEV_DID_TA */ "TA", "Tickle Arguments", /* TEV_DID_TR */ "TR", "Tickle Responses", /* TEV_DID_TS */ "TS", "Time Seconds", /* TEV_DID_TU */ "TU", "Time Microseconds", /* TEV_DID_TGS */ "TGS", "Timing Seconds", /* TEV_DID_TGU */ "TGU", "Timing Microseconds", /* TEV_DID_TMW */ "TMW", "Trace Mask Who", /* TEV_DID_TM */ "TM", "Trace Mask", /* TEV_DID_TRC */ "TRC", "Tracer Message Trace Context", /* TEV_DID_TRT */ "TRT", "Tracer Message Trace Tag", /* TEV_DID_TRX */ "TRX", "Tracer Message Output Context", /* TEV_DID_TRO */ "TRO", "Tracer Message Output Tag", /* TEV_DID_TRM */ "TRM", "Tracer Trace Mask", /* TEV_DID_TRB */ "TRB", "Tracer Trace Buffering", /* TEV_DID_TRL */ "TRL", "Tracer Trace Options", /* TEV_DID_VER */ "VER", "PVM Version", /* TEV_DID_VCT */ "VCT", "Trace Event Count", /* TEV_DID_VID */ "VID", "Trace Event ID", /* TEV_DID_WID */ "WID", "Wait Identifier Number" }; /* Trace Event Info */ struct Pvmtevinfo pvmtevinfo[] = { /* TEV_ADDHOSTS */ "addhosts", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_BARRIER */ "barrier", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_BCAST */ "bcast", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_BUFINFO */ "bufinfo", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_CONFIG */ "config", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_DELETE */ "delete", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_DELHOSTS */ "delhosts", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_EXIT */ "exit", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_FREEBUF */ "freebuf", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_GETFDS */ "getfds", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_GETINST */ "getinst", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_GETOPT */ "getopt", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_GETRBUF */ "getrbuf", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_GETSBUF */ "getsbuf", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_GETTID */ "gettid", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_GSIZE */ "gsize", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_HALT */ "halt", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_INITSEND */ "initsend", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_INSERT */ "insert", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_JOINGROUP */ "joingroup", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_KILL */ "kill", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_LOOKUP */ "lookup", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_LVGROUP */ "lvgroup", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_MCAST */ "mcast", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_MKBUF */ "mkbuf", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_MSTAT */ "mstat", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_MYTID */ "mytid", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_NOTIFY */ "notify", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_NRECV */ "nrecv", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_PARENT */ "parent", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_PERROR */ "perror", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_PKBYTE */ "pkbyte", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_PKCPLX */ "pkcplx", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_PKDCPLX */ "pkdcplx", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_PKDOUBLE */ "pkdouble", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_PKFLOAT */ "pkfloat", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_PKINT */ "pkint", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_PKUINT */ "pkuint", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_PKLONG */ "pklong", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_PKULONG */ "pkulong", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_PKSHORT */ "pkshort", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_PKUSHORT */ "pkushort", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_PKSTR */ "pkstr", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_PROBE */ "probe", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_PSTAT */ "pstat", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_RECV */ "recv", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_RECVF */ "recvf", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_SEND */ "send", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_SENDSIG */ "sendsig", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_SETOPT */ "setopt", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_SETRBUF */ "setrbuf", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_SETSBUF */ "setsbuf", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_SPAWN */ "spawn", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_START_PVMD */ "start_pvmd", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_TASKS */ "tasks", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_TICKLE */ "tickle", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_TIDTOHOST */ "tidtohost", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_TRECV */ "trecv", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_UPKBYTE */ "upkbyte", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_UPKCPLX */ "upkcplx", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_UPKDCPLX */ "upkdcplx", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_UPKDOUBLE */ "upkdouble", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_UPKFLOAT */ "upkfloat", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_UPKINT */ "upkint", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_UPKUINT */ "upkuint", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_UPKLONG */ "upklong", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_UPKULONG */ "upkulong", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_UPKSHORT */ "upkshort", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_UPKUSHORT */ "upkushort", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_UPKSTR */ "upkstr", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_VERSION */ "version", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_REG_HOSTER */ "reg_hoster", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_REG_RM */ "reg_rm", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_REG_TASKER */ "reg_tasker", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_REG_TRACER */ "reg_tracer", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_NEWTASK */ "newtask", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_ENDTASK */ "endtask", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_SPNTASK */ "spntask", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_ARCHCODE */ "archcode", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_CATCHOUT */ "catchout", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_GETMWID */ "getmwid", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_GETTMASK */ "gettmask", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_HOSTSYNC */ "hostsync", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_PACKF */ "packf", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_PRECV */ "precv", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_PSEND */ "psend", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_REDUCE */ "reduce", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_SETMWID */ "setmwid", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_SETTMASK */ "settmask", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_UNPACKF */ "unpackf", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_GATHER */ "gather", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_SCATTER */ "scatter", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_PUTINFO */ "putinfo", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_GETINFO */ "getinfo", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_DELINFO */ "delinfo", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_GETMBOXINFO */ "getmboxinfo", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_NEWCONTEXT */ "newcontext", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_FREECONTEXT */ "freecontext", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_SETCONTEXT */ "setcontext", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_GETCONTEXT */ "getcontext", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_SIBLINGS */ "siblings", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_GETMINFO */ "getminfo", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_SETMINFO */ "setminfo", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_ADDMHF */ "addmhf", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_DELMHF */ "delmhf", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_MHF_INVOKE */ "mhf_invoke", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_TIMING */ "timing", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_PROFILING */ "profiling", 0, { 0, 0 }, { 0, 0 }, 0, /* TEV_USER_DEFINED */ "user_defined", 0, { 0, 0 }, { 0, 0 }, 0 }; ./pvm3/src/host.c0100644007401100000360000005572610001307617013022 0ustar kohlgopher static char rcsid[] = "$Id: host.c,v 1.21 2004/01/14 18:50:55 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * host.c * * Host table functions. * * $Log: host.c,v $ * Revision 1.21 2004/01/14 18:50:55 pvmsrc * Added new AIX5* arches. * (Spanker=kohl) * * Revision 1.20 2002/10/07 19:01:47 pvmsrc * Bug in host table dumping - vmid can be NULL... * - fix submitted by Kasidit Chanchio . * (Spanker=kohl) * * Revision 1.19 2001/09/26 23:35:18 pvmsrc * Added new hd_vmid to hostd struct. * - use to override local PVM_VMID settings with hostfile "id=" option * (Spanker=kohl) * * Revision 1.18 2001/02/07 23:14:03 pvmsrc * First Half of CYGWIN Check-ins... * (Spanker=kohl) * * Revision 1.17 2000/07/12 19:24:09 pvmsrc * Goofy fix for FreeBSD - variation on ifreq struct. * - submitted via Frederik Meerwaldt . * (Spanker=kohl) * * Revision 1.16 2000/02/16 21:59:39 pvmsrc * Fixed up #include stuff... * - use for IMA_TITN... * - #include before any NEEDMENDIAN #includes... * (Spanker=kohl) * * Revision 1.15 1999/07/08 18:59:52 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.14 1998/11/20 20:03:57 pvmsrc * Changes so that win32 will compile & build. Also, common * Changes so that compiles & builds on NT. Also * common source on win32 & unix. * (Spanker=sscott) * * Revision 1.13 1998/06/26 12:31:07 pvmsrc * Added IMA_FREEBSD to the ioctl() list of arches that have both * SIOCGIFCONF and OSIOCGIFCONF defined... * - need to force use of SIOCGIFCONF anyway for these bozos... * (Spanker=kohl) * * Revision 1.12 1998/02/23 22:51:27 pvmsrc * Added AIX4SP2 stuff. * (Spanker=kohl) * * Revision 1.11 1997/12/05 16:23:37 pvmsrc * Fixed setting of host table "ht_narch" field. * - used by pvm_config() to return # of archs. * - replaced old pvm_archcode() solution with new data signature * stuff (hd_dsig field in host descriptor). * (Spanker=kohl) * * Revision 1.10 1997/06/27 17:32:21 pvmsrc * Updated for WIN32 header files & Authors. * * Revision 1.9 1997/06/24 20:39:16 pvmsrc * Eliminated unnecessary global externs. * * Revision 1.8 1997/04/30 21:25:56 pvmsrc * SGI Compiler Warning Cleanup. * * Revision 1.7 1997/04/09 14:38:20 pvmsrc * PVM patches from the base 3.3.10 to 3.3.11 versions where applicable. * Originals by Bob Manchek. Altered by Graham Fagg where required. * * Revision 1.6 1997/01/28 19:26:17 pvmsrc * New Copyright Notice & Authors. * * Revision 1.5 1996/10/25 14:04:44 pvmsrc * changed ifdef around ioctl for AIX 3.x/4.x to use IMA_arch-class * * Revision 1.4 1996/10/25 13:57:17 pvmsrc * Replaced old #includes for protocol headers: * - , "ddpro.h", "tdpro.h" * With #include of new combined header: * - * * Revision 1.3 1996/10/24 21:04:45 pvmsrc * Moved #include of "global.h" down below other headers: * - need to have all of the structures / types declared before * the globals can be declared... * * Revision 1.2 1996/10/24 18:14:07 pvmsrc * ifdefs to ioctl call parameter for AIX3.x/4.x difference * * Revision 1.1 1996/09/23 23:44:08 pvmsrc * Initial revision * * Revision 1.10 1996/05/13 20:25:48 manchek/GEF * missing pvmlogerror in readhostfile * * Revision 1.9 1995/11/02 16:01:49 manchek * use NET_IF_IN_SYS if include/sys/net/if.h * * Revision 1.8 1995/07/28 16:51:30 manchek * ifdef for UTS2 * * Revision 1.7 1995/05/17 16:09:13 manchek * added HF_OVERLOAD and '$' syntax * * Revision 1.6 1994/10/15 19:05:39 manchek * must use PVM_FREE instead of free in iflist() * * Revision 1.5 1994/06/21 18:30:55 manchek * HF_SPEED flag now determines whether hd_speed has been set * * Revision 1.4 1994/06/03 20:38:14 manchek * version 3.3.0 * * Revision 1.3 1993/11/30 19:52:05 manchek * readhostfile() puts defaults in ht_hosts[0] * * Revision 1.2 1993/09/15 15:03:31 manchek * defined max() if not already there * * Revision 1.1 1993/08/30 23:26:47 manchek * Initial revision * */ #ifndef WIN32 #include #endif #ifdef IMA_TITN #include #else #include #endif #ifdef NEEDMENDIAN #include #endif #ifdef NEEDENDIAN #include #endif #ifdef NEEDSENDIAN #include #endif #include #if defined(WIN32) || defined(CYGWIN) #include "..\xdr\types.h" #include "..\xdr\xdr.h" #else #include #include #endif #ifdef WIN32 #include "pvmwin.h" #else #ifndef IMA_TITN #include #else #include #endif #include #include #include #ifdef NET_IF_IN_SYS #include #else #include #endif #include #endif #include #ifdef SYSVSTR #include #else #include #endif #include #include #include "pvmalloc.h" #include "host.h" #include "pmsg.h" #include "pkt.h" #include "bfunc.h" #include "global.h" #ifndef max #define max(a,b) ((a)>(b)?(a):(b)) #endif #ifdef SOCKADHASLEN #define SIZ(p) max(sizeof(p), (p).sa_len) #else #define SIZ(p) sizeof(p) #endif char *inadport_decimal(); /*************** ** Globals ** ** ** ***************/ extern int pvmdebmask; /* from pvmd.c */ extern int tidhmask; /* from pvmd.c */ /*************** ** Private ** ** ** ***************/ /***************** ** Interface ** ** ** *****************/ /* hd_new() * * Make a new host descriptor. */ struct hostd * hd_new(hh) int hh; /* index in host table */ { struct hostd *hp; if (hp = TALLOC(1, struct hostd, "hd")) { BZERO((char*)hp, sizeof(struct hostd)); hp->hd_ref = 1; hp->hd_hostpart = hh << (ffs(tidhmask) - 1); hp->hd_sad.sin_family = AF_INET; hp->hd_txq = pk_new(0); hp->hd_opq = pk_new(0); hp->hd_rxq = pk_new(0); hp->hd_txseq = 1; hp->hd_rxseq = 1; hp->hd_speed = 1000; hp->hd_rtt.tv_sec = 1; /* XXX const */ hp->hd_mcas = mca_new(); } return hp; } /* hd_free() * * Free a host descriptor and all associated storage. * Probably want to use hd_unref() instead. */ void hd_free(hp) struct hostd *hp; { struct mca *mcap; if (hp->hd_name) PVM_FREE(hp->hd_name); if (hp->hd_arch) PVM_FREE(hp->hd_arch); if (hp->hd_login) PVM_FREE(hp->hd_login); if (hp->hd_dpath) PVM_FREE(hp->hd_dpath); if (hp->hd_epath) PVM_FREE(hp->hd_epath); if (hp->hd_bpath) PVM_FREE(hp->hd_bpath); if (hp->hd_wdir) PVM_FREE(hp->hd_wdir); if (hp->hd_sopts) PVM_FREE(hp->hd_sopts); if (hp->hd_txq) pk_free(hp->hd_txq); if (hp->hd_opq) pk_free(hp->hd_opq); if (hp->hd_rxq) pk_free(hp->hd_rxq); if (hp->hd_rxm) pmsg_unref(hp->hd_rxm); if (mcap = hp->hd_mcas) { while (mcap->mc_link != mcap) mca_free(mcap->mc_link); mca_free(mcap); } if (hp->hd_aname) PVM_FREE(hp->hd_aname); if (hp->hd_vmid) PVM_FREE(hp->hd_vmid); PVM_FREE(hp); } /* hd_unref() * * Decrement the refcount of a host descriptor. Free it if count * reaches zero. */ void hd_unref(hp) struct hostd *hp; { if (--hp->hd_ref < 1) hd_free(hp); } void hd_dump(hp) struct hostd *hp; { int n; struct pkt *pp, *pp2; pvmlogprintf( " hd_dump() ref %d t 0x%x n \"%s\" a \"%s\" ar \"%s\" dsig 0x%x\n", hp->hd_ref, hp->hd_hostpart, (hp->hd_name ? hp->hd_name : ""), (hp->hd_aname ? hp->hd_aname : ""), (hp->hd_arch ? hp->hd_arch : ""), hp->hd_dsig); pvmlogprintf( " lo \"%s\" so \"%s\" dx \"%s\" ep \"%s\" bx \"%s\" wd \"%s\" sp %d\n", (hp->hd_login ? hp->hd_login : ""), (hp->hd_sopts ? hp->hd_sopts : ""), (hp->hd_dpath ? hp->hd_dpath : ""), (hp->hd_epath ? hp->hd_epath : ""), (hp->hd_bpath ? hp->hd_bpath : ""), (hp->hd_wdir ? hp->hd_wdir : ""), hp->hd_speed); n = 0; if (pp2 = hp->hd_txq) for (pp = pp2->pk_link; pp != pp2; pp = pp->pk_link) n++; pvmlogprintf(" sa %s mtu %d f 0x%x e %d txq %d\n", inadport_decimal(&hp->hd_sad), hp->hd_mtu, hp->hd_flag, hp->hd_err, n); pvmlogprintf( " tx %d rx %d rtt %d.%06d id \"%s\"\n", hp->hd_txseq, hp->hd_rxseq, hp->hd_rtt.tv_sec, hp->hd_rtt.tv_usec, (hp->hd_vmid ? hp->hd_vmid : "")); } /* nametohost() * * Get a host descriptor by hostname. */ struct hostd * nametohost(htp, name) struct htab *htp; char *name; { int hh; struct hostd *hp; if (!strcmp(name, ".")) return htp->ht_hosts[htp->ht_local]; for (hh = htp->ht_last; hh > 0; hh--) if ((hp = htp->ht_hosts[hh]) && !strcmp(name, hp->hd_name)) return hp; return (struct hostd*)0; } /* indtohost() * * Get a host descriptor by its host table index. */ struct hostd * indtohost(htp, n) struct htab *htp; int n; { return (n >= 1 && n <= htp->ht_last) ? htp->ht_hosts[n] : 0; } /* tidtohost() * * Get a host descriptor by its tid. */ struct hostd * tidtohost(htp, tid) struct htab *htp; int tid; { return indtohost(htp, (tid & tidhmask) >> (ffs(tidhmask) - 1)); } /* ht_free() * * Free a host table and unref all hosts in it. */ void ht_free(htp) struct htab *htp; { int i; for (i = 1; i <= htp->ht_last; i++) if (htp->ht_hosts[i]) hd_unref(htp->ht_hosts[i]); PVM_FREE(htp->ht_hosts); PVM_FREE(htp); } /* ht_new() * * Make a new (empty) host table. Length is advisory as ht_hosts * is extended as needed. */ struct htab * ht_new(siz) int siz; /* initial length of ht_hosts[] */ { struct htab *htp; if (siz < 1) siz = 1; htp = TALLOC(1, struct htab, "ht1"); BZERO((char*)htp, sizeof(struct htab)); htp->ht_last = siz; htp->ht_hosts = TALLOC(siz + 1, struct hostd*, "ht2"); BZERO((char*)htp->ht_hosts, (siz + 1) * sizeof(struct hostd*)); return htp; } /* ht_insert() * * Add a host to a host table. Extend ht_hosts if necessary. * Update ht_narch. */ void ht_insert(htp, hp) struct htab *htp; struct hostd *hp; { int hh; int i; unsigned long mask = 0, tmpmask; int *dsigs; int ndsigs; int found; int d; hh = (hp->hd_hostpart & tidhmask) >> (ffs(tidhmask) - 1); /* extend ht_hosts[] if no room */ if (hh > htp->ht_last) { int n = htp->ht_last; htp->ht_last = (hh * 3) / 2; htp->ht_hosts = TREALLOC(htp->ht_hosts, htp->ht_last + 1, struct hostd*); while (++n <= htp->ht_last) htp->ht_hosts[n] = 0; } /* if already have an entry, take this as an update XXX kind of a hack */ if (htp->ht_hosts[hh]) { /* already have an entry */ struct hostd *hp2 = htp->ht_hosts[hh]; if (hp->hd_name) { if (hp2->hd_name) PVM_FREE(hp2->hd_name); hp2->hd_name = STRALLOC(hp->hd_name); } if (hp->hd_arch) { if (hp2->hd_arch) PVM_FREE(hp2->hd_arch); hp2->hd_arch = STRALLOC(hp->hd_arch); } hp2->hd_dsig = hp->hd_dsig; hp2->hd_mtu = hp->hd_mtu; hp2->hd_sad = hp->hd_sad; hp2->hd_speed = hp->hd_speed; } else { /* add new entry */ htp->ht_hosts[hh] = hp; if (hh) htp->ht_cnt++; hp->hd_ref++; } /* update number of arches */ dsigs = TALLOC( htp->ht_cnt, int, "dsigs"); ndsigs = 0; htp->ht_narch = 0; for (hh = htp->ht_last; hh > 0; hh--) { hp = htp->ht_hosts[hh]; if (hp && hp->hd_arch) { d = htp->ht_hosts[hh]->hd_dsig; for ( i=0, found=0 ; i < ndsigs && !found ; i++ ) { if ( dsigs[i] == d ) found++; } if ( !found ) { dsigs[ ndsigs++ ] = d; htp->ht_narch++; } } } PVM_FREE( dsigs ); } /* ht_delete() * * Remove a host from a host table and unreference it. */ void ht_delete(htp, hp) struct htab *htp; struct hostd *hp; { int hh; int i; unsigned long mask = 0, tmpmask; int *dsigs; int ndsigs; int found; int d; hh = (hp->hd_hostpart & tidhmask) >> (ffs(tidhmask) - 1); if (hh < 0 || hh > htp->ht_last || htp->ht_hosts[hh] != hp) { pvmlogerror("ht_delete() host not in table\n"); return; } htp->ht_hosts[hh] = 0; if (hh) htp->ht_cnt--; hd_unref(hp); /* update number of arches */ dsigs = TALLOC( htp->ht_cnt, int, "dsigs"); ndsigs = 0; htp->ht_narch = 0; for (hh = htp->ht_last; hh > 0; hh--) { hp = htp->ht_hosts[hh]; if (hp && hp->hd_arch) { d = htp->ht_hosts[hh]->hd_dsig; for ( i=0, found=0 ; i < ndsigs && !found ; i++ ) { if ( dsigs[i] == d ) found++; } if ( !found ) { dsigs[ ndsigs++ ] = d; htp->ht_narch++; } } } PVM_FREE( dsigs ); } void ht_dump(htp) struct htab *htp; { int hh; pvmlogprintf( "ht_dump() ser %d last %d cnt %d master %d cons %d local %d narch %d\n", htp->ht_serial, htp->ht_last, htp->ht_cnt, htp->ht_master, htp->ht_cons, htp->ht_local, htp->ht_narch); for (hh = 0; hh <= htp->ht_last; hh++) if (htp->ht_hosts[hh]) hd_dump(htp->ht_hosts[hh]); } /* ht_merge() * * Add entries in src host table to dst host table. */ int ht_merge(dst, src) struct htab *dst, *src; { int hh; struct hostd *hp; for (hh = src->ht_last; hh > 0; hh--) if (hp = src->ht_hosts[hh]) ht_insert(dst, hp); return 0; } /* applydefaults() * * Apply default settings to unspecified fields of hostd. */ int applydefaults(hp, defhp) struct hostd *hp; /* hostd to modify */ struct hostd *defhp; /* default settings */ { if (!hp->hd_login && defhp->hd_login) hp->hd_login = STRALLOC(defhp->hd_login); if (!hp->hd_dpath && defhp->hd_dpath) hp->hd_dpath = STRALLOC(defhp->hd_dpath); if (!hp->hd_epath && defhp->hd_epath) hp->hd_epath = STRALLOC(defhp->hd_epath); if (!hp->hd_bpath && defhp->hd_bpath) hp->hd_bpath = STRALLOC(defhp->hd_bpath); if (!hp->hd_wdir && defhp->hd_wdir) hp->hd_wdir = STRALLOC(defhp->hd_wdir); if (!hp->hd_sopts && defhp->hd_sopts) hp->hd_sopts = STRALLOC(defhp->hd_sopts); if (!hp->hd_aname && defhp->hd_aname) hp->hd_aname = STRALLOC(defhp->hd_aname); if (!(hp->hd_flag & HF_SPEED) && (defhp->hd_flag & HF_SPEED)) hp->hd_speed = defhp->hd_speed; if (!hp->hd_vmid && defhp->hd_vmid) hp->hd_vmid = STRALLOC(defhp->hd_vmid); hp->hd_flag |= defhp->hd_flag; return 0; } /* parsehost() * * Parse hostfile line into hostd. */ int parsehost(buf, hp) char *buf; struct hostd *hp; { char *av[10]; /* parsed words */ int ac; int err = 0; ac = sizeof(av)/sizeof(av[0]); if (acav(buf, &ac, av)) { pvmlogprintf("parsehost(): line too long\n"); goto bad; } if (!ac) goto bad; /* add options to host descriptor */ while (--ac > 0) { if (!strncmp(av[ac], "lo=", 3)) { if (hp->hd_login) PVM_FREE(hp->hd_login); hp->hd_login = STRALLOC(av[ac] + 3); continue; } if (!strncmp(av[ac], "dx=", 3)) { if (hp->hd_dpath) PVM_FREE(hp->hd_dpath); hp->hd_dpath = STRALLOC(av[ac] + 3); continue; } if (!strncmp(av[ac], "ep=", 3)) { if (hp->hd_epath) PVM_FREE(hp->hd_epath); hp->hd_epath = STRALLOC(av[ac] + 3); continue; } if (!strncmp(av[ac], "sp=", 3)) { hp->hd_speed = atoi(av[ac] + 3); hp->hd_flag |= HF_SPEED; continue; } if (!strncmp(av[ac], "bx=", 3)) { if (hp->hd_bpath) PVM_FREE(hp->hd_bpath); hp->hd_bpath = STRALLOC(av[ac] + 3); continue; } if (!strncmp(av[ac], "wd=", 3)) { if (hp->hd_wdir) PVM_FREE(hp->hd_wdir); hp->hd_wdir = STRALLOC(av[ac] + 3); continue; } if (!strncmp(av[ac], "so=", 3)) { if (hp->hd_sopts) PVM_FREE(hp->hd_sopts); hp->hd_sopts = STRALLOC(av[ac] + 3); continue; } if (!strncmp(av[ac], "ip=", 3)) { if (hp->hd_aname) PVM_FREE(hp->hd_aname); hp->hd_aname = STRALLOC(av[ac] + 3); continue; } if (!strncmp(av[ac], "id=", 3)) { if (hp->hd_vmid) PVM_FREE(hp->hd_vmid); hp->hd_vmid = STRALLOC(av[ac] + 3); continue; } pvmlogprintf("parsehost(): unknown option \"%s\"\n", av[ac]); err++; } if (err) goto bad; if (hp->hd_name) PVM_FREE(hp->hd_name); hp->hd_name = STRALLOC(av[0]); return 0; bad: return -1; } /* readhostfile() * * Read a host file and return host table with options and ipaddrs * filled in. */ struct htab * readhostfile(fn) char *fn; { struct htab *htp; struct hostd *hp; FILE *ff = 0; char buf[512]; /* line buffer */ int lnum = 0; /* line counter */ int err = 0; /* error count */ struct hostent *he; char *p; struct in_addr *my_in_addrs; int num_addrs; int i; int maxhostid = tidhmask >> (ffs(tidhmask) - 1); struct hostd *defaults = 0; htp = ht_new(1); /* * get list of this host's interfaces so we can detect ourself in file */ if (iflist(&my_in_addrs, &num_addrs) == -1 || num_addrs < 1) { pvmlogprintf("readhostfile() iflist failed\n"); goto bail; } if (!(ff = fopen(fn, "r"))) { pvmlogprintf("readhostfile() %s: can't read\n", fn); goto bail; } /* parse each line of host file */ while (fgets(buf, sizeof(buf), ff)) { lnum++; for (p = buf; *p && isspace(*p); p++); if (!*p || *p == '#') /* leading '#' is comment */ continue; if (lnum > maxhostid) { pvmlogprintf("readhostfile() %s: too many lines\n", fn); err++; break; } hp = hd_new(lnum); while (*p == '&' || *p == '$') { if (*p == '&') /* leading '&' is no-start */ hp->hd_flag |= HF_NOSTART; if (*p == '$') /* leading '$' allows overloading host */ hp->hd_flag |= HF_OVERLOAD; p++; } if (parsehost(p, hp)) { pvmlogprintf("readhostfile() %s %d: errors\n", fn, lnum); err++; goto badline; } /* * if host == "*", change the default options * instead of adding a new host to the list */ if (!strcmp(hp->hd_name, "*")) { if (defaults) hd_unref(defaults); defaults = hp; continue; } /* Set unspecified fields of hp to defaults */ if (defaults) applydefaults(hp, defaults); /* look up ip addr */ if (!(he = gethostbyname(hp->hd_aname ? hp->hd_aname : hp->hd_name))) { pvmlogprintf("readhostfile() %s %d: %s: can't gethostbyname\n", fn, lnum, hp->hd_name); err++; goto badline; } BCOPY(he->h_addr_list[0], (char*)&hp->hd_sad.sin_addr, sizeof(struct in_addr)); /* mark master host to not start */ if (!(hp->hd_flag & HF_OVERLOAD)) for (i = num_addrs; i-- > 0; ) { if (BCMP((char*)&my_in_addrs[i], (char*)&hp->hd_sad.sin_addr, sizeof(struct in_addr)) == 0) { hp->hd_flag |= HF_NOSTART; break; } } ht_insert(htp, hp); hd_unref(hp); continue; badline: hd_unref(hp); } if (err) { pvmlogprintf("readhostfile() %s: %d errors in hostfile\n", fn, err); } if (defaults) { defaults->hd_hostpart = 0; ht_insert(htp, defaults); } fclose(ff); return htp; bail: if (defaults) hd_unref(defaults); if (ff) fclose(ff); ht_free(htp); return (struct htab*)0; } /* iflist() * * Return list of addresses for active network interfaces. */ #ifdef SIOCGIFCONF int iflist(alp, np) struct in_addr **alp; /* return list of addresses */ int *np; /* return len of alp */ { int soc = -1; /* socket */ static struct in_addr *iplist = 0; /* list of interface addrs found */ int nip = 0; /* length of iplist */ char buf[4096]; /* return space for SIOCGIOCONF */ struct ifconf sif; struct ifreq *reqp; struct ifreq req; char *cp; if (iplist) PVM_FREE(iplist); iplist = TALLOC(10, struct in_addr, "ifl"); if ((soc = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { perror("socket"); goto bail; } sif.ifc_ifcu.ifcu_buf = buf; sif.ifc_len = sizeof(buf); if (ioctl(soc, #ifdef OSIOCGIFCONF #if defined(IMA_RS6K) || defined(IMA_RS6KMP) || defined(IMA_SP2MPI) \ || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) \ || defined(IMA_FREEBSD) SIOCGIFCONF #else OSIOCGIFCONF #endif #else SIOCGIFCONF #endif , &sif) == -1) { perror("ioctl"); goto bail; } for (cp = sif.ifc_ifcu.ifcu_buf; cp - sif.ifc_ifcu.ifcu_buf < sif.ifc_len; cp += sizeof(*reqp) - sizeof(struct sockaddr) + SIZ(reqp->ifr_addr)) { reqp = (struct ifreq*)cp; if (reqp->ifr_addr.sa_family != AF_INET) continue; BCOPY(reqp->ifr_name, req.ifr_name, sizeof(req.ifr_name)); if (ioctl(soc, SIOCGIFFLAGS, &req) == -1) { perror("ioctl"); goto bail; } /* On some FreeBSD systems: */ /* if (IFF_UP & req.ifr_flags) { */ if (IFF_UP & req.ifr_ifru.ifru_flags) { if (nip > 0 && !(nip % 10)) iplist = TREALLOC(iplist, (nip + 10), struct in_addr); iplist[nip++] = ((struct sockaddr_in*)(&reqp->ifr_ifru.ifru_addr))->sin_addr; if (pvmdebmask & PDMNET) { long a; a = ((struct sockaddr_in*)(&reqp->ifr_ifru.ifru_addr))->sin_addr.s_addr; a = ntohl(a); pvmlogprintf("iflist() %s %d.%d.%d.%d\n", reqp->ifr_name, 0xff & (a >> 24), 0xff & (a >> 16), 0xff & (a >> 8), 0xff & a); } } } *alp = iplist; *np = nip; return 0; bail: (void)close(soc); return -1; } #else /*SIOCGIFCONF*/ int iflist(alp, np) struct in_addr **alp; /* return list of addresses */ int *np; /* return len of alp */ { static struct in_addr *iplist = 0; /* list of interface addrs found */ int nip = 0; /* length of iplist */ char hn[MAXHOSTNAMELEN]; struct hostent *he; char **p; if (iplist) PVM_FREE(iplist); iplist = TALLOC(10, struct in_addr, "ifl"); if (gethostname(hn, sizeof(hn))) { perror("gethostname"); goto bail; } if (!(he = gethostbyname(hn))) { fprintf(stderr, "can't gethostbyname\n"); goto bail; } for (; he->h_addr_list[nip]; nip++) { if (nip > 0 && !(nip % 10)) iplist = TREALLOC(iplist, (nip + 10), struct in_addr); iplist[nip].s_addr = ((struct in_addr*)(he->h_addr_list[nip]))->s_addr; } *alp = iplist; *np = nip; return 0; bail: return -1; } #endif /*SIOCGIFCONF*/ /* acav() * * Parse a string into words separated by whitespace. * Max number of words is original value of *acp. * * Trashes out the original string. * Returns 0 with av[0]..av[*acp - 1] pointing to the words. * Returns 1 if too many words. */ int acav(s, acp, av) char *s; /* the string to parse */ int *acp; /* max words in, ac out */ char **av; /* pointers to args */ { register int ac; register char *p = s; register int n = *acp; /* separate out words of command */ ac = 0; while (*p) { while (isspace(*p)) p++; if (*p) { if (ac >= n) { /* command too long */ *acp = ac; return 1; } av[ac++] = p; while (*p && !isspace(*p)) p++; if (*p) *p++ = 0; } } *acp = ac; return 0; } ./pvm3/src/hoster.c0100644007401100000360000005552307354714465013370 0ustar kohlgopher static char rcsid[] = "$Id: hoster.c,v 1.20 2001/09/27 21:25:09 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * hoster.c * * Slave pvmd starter. * * $Log: hoster.c,v $ * Revision 1.20 2001/09/27 21:25:09 pvmsrc * BEOSCYLD port. * - submitted by Joe Vitale . * (we renamed it from BEOWULF to BEOSCYLD, but it's his port... :-) * (Spanker=kohl) * * Revision 1.19 2001/09/26 21:22:17 pvmsrc * Added Handling for Optional Virtual Machine ID. * - extra vmid comes through with SM_STHOST message (after wincmd). * - instruct user to type VMID on remote pvmd stdin for manual startup * - in phase1(), after potential rsh/rexec, write VMID env string * to remote pvmd's stdin. * (Spanker=kohl) * * Revision 1.18 2001/02/07 23:14:04 pvmsrc * First Half of CYGWIN Check-ins... * (Spanker=kohl) * * Revision 1.17 2000/02/16 21:59:40 pvmsrc * Fixed up #include stuff... * - use for IMA_TITN... * - #include before any NEEDMENDIAN #includes... * (Spanker=kohl) * * Revision 1.16 2000/02/14 20:31:57 pvmsrc * Lose #define-d RSHCOMMAND usage. * - use new pvmgetrsh() routine, which checks for PVM_RSH or else * uses old RSHCOMMAND interface. * (Spanker=kohl) * * Revision 1.15 1999/08/19 15:39:24 pvmsrc * Whoa... New wincmd stuff was whacking addhost protocol! * - *always* pack in something for wincmd, else the attempt to unpack * "possible" wincmd will snag start of next host's startup info... * - damn. * (Spanker=kohl) * * Revision 1.14 1999/07/08 18:59:53 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.13 1999/01/28 18:56:21 pvmsrc * Added host add retries for alternate WIN32 pvmd command. * - added char *h_wincmd field to hst struct. * - in hoster() check for extra command string at end of each * host unpack (ignore if omitted), stick in h_wincmd ptr. * - in pl_startup() if default pvmd command fails, * and alternate WIN32 command is defined, reset h_cmd and * try phase1() again... * - in phase1(), if doing manual startup and an alternate WIN32 * command is defined, echo that to the user too, so they can * try both before typing back the response... * (Spanker=kohl) * * Revision 1.12 1998/11/20 20:03:58 pvmsrc * Changes so that win32 will compile & build. Also, common * Changes so that compiles & builds on NT. Also * common source on win32 & unix. * (Spanker=sscott) * * Revision 1.11 1997/12/01 19:20:34 pvmsrc * Replaced #ifdef IMA_OS2 fd_set declarations: * - new #ifdef FDSETNOTSTRUCT. * - choose between "fd_set foo" and "struct fd_set foo"... * (Spanker=kohl) * * Revision 1.10 1997/11/04 23:19:16 pvmsrc * Cleaned up fd_set stuff (hopefully). * (Spanker=kohl) * * Revision 1.9 1997/09/10 17:40:54 pvmsrc * Oops... bcopy() -> BCOPY()... * (Spanker=kohl) * * Revision 1.8 1997/08/29 13:35:03 pvmsrc * OS2 Port Submitted by Bohumir Horeni, horeni@login.cz. * (Spanker=kohl) * * Revision 1.7 1997/06/25 22:08:46 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.6 1997/04/21 14:58:22 pvmsrc * Changed #ifdefs that checked IMA_RS6K,IMA_SP2MPI & IMA_AIX46K * to see if select.h was needed into single define NEEDSSELECTH. * New archs need to set this in conf/ * * Revision 1.5 1997/01/28 19:26:19 pvmsrc * New Copyright Notice & Authors. * * Revision 1.4 1996/10/25 13:57:19 pvmsrc * Replaced old #includes for protocol headers: * - , "ddpro.h", "tdpro.h" * With #include of new combined header: * - * * Revision 1.3 1996/10/24 21:04:47 pvmsrc * Moved #include of "global.h" down below other headers: * - need to have all of the structures / types declared before * the globals can be declared... * * Revision 1.2 1996/09/23 23:48:01 pvmsrc * Initial Creation - original hoster.c. * * Revision 1.1 1996/09/23 23:44:09 pvmsrc * Initial revision * * Revision 1.17 1995/11/02 16:36:14 manchek * added NEEDSENDIAN switch * * Revision 1.16 1995/07/28 16:41:01 manchek * wrap HASERRORVARS around errno declarations * * Revision 1.15 1995/07/28 16:04:06 manchek * switch endian includes on flag, not arch name * * Revision 1.14 1995/07/11 18:55:33 manchek * moved printing of PVMSOCK in master_config to main * * Revision 1.13 1995/07/03 19:06:54 manchek * removed POWER4 ifdefs * * Revision 1.12 1995/05/30 17:53:08 manchek * Added ifdefs and small changes for SP2MPI arch * * Revision 1.11 1995/05/17 16:53:03 manchek * use FDSETISINT in select * * Revision 1.10 1995/02/06 21:35:59 manchek * host table mtu set from ourudpmtu instead of UDPMAXLEN * * Revision 1.9 1994/10/15 19:31:31 manchek * fixed typo in log message * * Revision 1.8 1994/06/04 21:45:24 manchek * added unix domain sockets. * ripped out old (serial) startup code * * Revision 1.7 1994/06/03 20:38:27 manchek * version 3.3.0 * * Revision 1.6 1993/11/30 19:54:41 manchek * check the default entry in filehosts when adding new hosts * * Revision 1.5 1993/11/30 16:46:10 manchek * pass whole remote command as a single arg to rsh * * Revision 1.4 1993/11/30 15:54:37 manchek * master pvmd once again doesn't close fds 0..2 - * this broke rexec startup * * Revision 1.3 1993/10/25 20:53:51 manchek * fixed a few typos in error log messages. * added code to close all fds and reopen 0..2 as /dev/null * * Revision 1.2 1993/10/04 20:30:30 manchek * mksocks() now uses pvmdsockfile() instead of TDSOCKNAME * * Revision 1.1 1993/08/30 23:26:51 manchek * Initial revision * */ #ifdef IMA_TITN #include #else #include #endif #ifdef NEEDMENDIAN #include #endif #ifdef NEEDENDIAN #include #endif #ifdef NEEDSENDIAN #include #endif #include #if defined(WIN32) || defined(CYGWIN) #include "..\xdr\types.h" #include "..\xdr\xdr.h" #else #include #include #endif #ifndef WIN32 #include #include #include #include #endif #ifdef NEEDSSELECTH #include #endif #include #include #include #include #ifdef SYSVSTR #include #define CINDEX(s,c) strchr(s,c) #else #include #define CINDEX(s,c) index(s,c) #endif #include #include "pvmalloc.h" #include "pmsg.h" #include "host.h" #include "listmac.h" #include "tvdefs.h" #include "bfunc.h" #include "global.h" #ifdef IMA_BEOSCYLD #include #endif #ifndef RSHTIMEOUT #define RSHTIMEOUT 60 #endif #ifndef RSHNPLL #define RSHNPLL 5 #endif #ifndef max #define max(a,b) ((a)>(b)?(a):(b)) #endif #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif struct hst { int h_tid; char *h_name; char *h_login; char *h_sopts; int h_flag; #define HST_PASSWORD 1 /* ask for a password */ #define HST_MANUAL 2 /* do manual startup */ char *h_cmd; char *h_wincmd; /* alternate WIN32 default pvmd cmd */ char *h_vmid; /* optional virtual machine ID */ char *h_result; }; struct slot { struct slot *s_link, *s_rlink; /* free/active list */ struct hst *s_hst; /* host table entry */ struct timeval s_bail; /* timeout time */ int s_rfd, s_wfd, s_efd; /* slave stdin/out/err */ char s_buf[256]; /* stdout from host */ char s_ebuf[256]; /* stderr from host */ int s_len; /* length of s_buf */ int s_elen; /* length of s_ebuf */ }; /*************** ** Globals ** ** ** ***************/ #ifndef HASERRORVARS extern int errno; #endif extern void pvmbailout(); extern int pvmdebmask; /* from pvmd.c */ extern char *username; /* from pvmd.c */ char *pvmgetrsh(); /*************** ** Private ** ** ** ***************/ static struct slot slots[RSHNPLL+2]; /* state var/context for each slot */ static struct slot *slfree = 0; /* free list of slots */ int hoster(mp) struct pmsg *mp; { struct pmsg *mp2; int num; int i; struct hst **hostlist; struct hst *hp; char *p; /* * unpack the startup message */ upkint(mp, &num); if (pvmdebmask & PDMSTARTUP) { pvmlogprintf("hoster() %d to start\n", num); } if (num > 0) { hostlist = TALLOC(num, struct hst *, "hsts"); for (i = 0; i < num; i++) { hp = TALLOC(1, struct hst, "hst"); hostlist[i] = hp; hp->h_flag = 0; hp->h_result = 0; if (upkint(mp, &hp->h_tid) || upkstralloc(mp, &hp->h_sopts) || upkstralloc(mp, &hp->h_login) || upkstralloc(mp, &hp->h_cmd) || upkstralloc(mp, &hp->h_wincmd) || upkstralloc(mp, &hp->h_vmid)) { pvmlogerror("hoster() bad message format\n"); pvmbailout(0); } /* Check for (possible) alternate WIN32 pvmd cmd */ if (!strcmp(hp->h_wincmd,"")) { PVM_FREE(hp->h_wincmd); hp->h_wincmd = 0; } /* Check for (optional) virtual machine ID */ if (!strcmp(hp->h_vmid,"")) { PVM_FREE(hp->h_vmid); hp->h_vmid = 0; } if (pvmdebmask & PDMSTARTUP) { pvmlogprintf("%d. t%x %s so=\"%s\"\n", i, hp->h_tid, hp->h_login, hp->h_sopts); } if (p = CINDEX(hp->h_login, '@')) { hp->h_name = STRALLOC(p + 1); *p = 0; p = STRALLOC(hp->h_login); PVM_FREE(hp->h_login); hp->h_login = p; } else { hp->h_name = hp->h_login; hp->h_login = 0; } if (!strcmp(hp->h_sopts, "pw")) hp->h_flag |= HST_PASSWORD; if (!strcmp(hp->h_sopts, "ms")) hp->h_flag |= HST_MANUAL; } } /* * do it */ pl_startup(num, hostlist); /* * send results back to pvmd */ mp2 = mesg_new(0); mp2->m_dst = mp->m_src; mp2->m_tag = DM_STARTACK; mp2->m_wid = mp->m_wid; pkint(mp2, num); for (i = 0; i < num; i++) { pkint(mp2, hostlist[i]->h_tid); pkstr(mp2, hostlist[i]->h_result ? hostlist[i]->h_result : "PvmDSysErr"); } if (pvmdebmask & PDMSTARTUP) pvmlogerror("hoster() pvmd' sending back host table\n"); sendmessage(mp2); work(); /* no return */ return 0; /* not reached */ } char * makevis(dst, src) char *dst; char *src; { char c; while (c = *src++ & 0x7f) { if (isprint(c)) *dst++ = c; else { *dst++ = '^'; *dst++ = (c + '@') & 0x7f; } } *dst = 0; return dst; } close_slot(sp) struct slot *sp; { if (sp->s_wfd != -1) (void)close(sp->s_wfd); if (sp->s_rfd != -1) (void)close(sp->s_rfd); if (sp->s_efd != -1) (void)close(sp->s_efd); LISTDELETE(sp, s_link, s_rlink); LISTPUTBEFORE(slfree, sp, s_link, s_rlink); return 0; } pl_startup(num, hostlist) int num; struct hst **hostlist; { int nxth = 0; /* next host in list to start */ struct slot *slact = 0; /* active list of slots */ struct hst *hp; struct slot *sp, *sp2; struct timeval tnow; struct timeval tout; #ifdef FDSETNOTSTRUCT fd_set rfds; /* emx headers */ #else struct fd_set rfds; #endif int nfds; int i; int n; char *p; /* init slot free list */ slfree = &slots[RSHNPLL+1]; slfree->s_link = slfree->s_rlink = slfree; slact = &slots[RSHNPLL]; slact->s_link = slact->s_rlink = slact; for (i = RSHNPLL; i-- > 0; ) { LISTPUTAFTER(slfree, &slots[i], s_link, s_rlink); } /* * keep at this until all hosts in table are completed */ for (; ; ) { /* * if empty slots, start on new hosts */ for (; ; ) { /* find a host for slot */ if (slfree->s_link != slfree && nxth < num) hp = hostlist[nxth++]; else break; sp = slfree->s_link; LISTDELETE(sp, s_link, s_rlink); sp->s_hst = hp; sp->s_len = 0; sp->s_elen = 0; if (pvmdebmask & PDMSTARTUP) { pvmlogprintf("pl_startup() trying %s\n", hp->h_name); } phase1(sp); if (hp->h_result) { /* error or fully started (manual startup) */ if (pvmdebmask & PDMSTARTUP) { pvmlogprintf( "pl_startup() got result \"%s\" for %s phase1()\n", hp->h_result, hp->h_name); } LISTPUTBEFORE(slfree, sp, s_link, s_rlink); } else { /* partially started */ LISTPUTBEFORE(slact, sp, s_link, s_rlink); pvmgetclock(&sp->s_bail); tout.tv_sec = RSHTIMEOUT; tout.tv_usec = 0; TVXADDY(&sp->s_bail, &sp->s_bail, &tout); } } /* if no hosts in progress, we are finished */ if (slact->s_link == slact) break; /* * until next timeout, get output from any slot */ FD_ZERO(&rfds); nfds = 0; TVCLEAR(&tout); pvmgetclock(&tnow); for (sp = slact->s_link; sp != slact; sp = sp->s_link) { if (TVXLTY(&sp->s_bail, &tnow)) { pvmlogprintf("pl_startup() giving up on host %s after %d secs\n", sp->s_hst->h_name, RSHTIMEOUT); sp->s_hst->h_result = STRALLOC("PvmCantStart"); sp2 = sp->s_rlink; close_slot(sp); sp = sp2; continue; } if (!TVISSET(&tout) || TVXLTY(&sp->s_bail, &tout)) tout = sp->s_bail; if (sp->s_rfd >= 0) FD_SET(sp->s_rfd, &rfds); if (sp->s_rfd > nfds) nfds = sp->s_rfd; if (sp->s_efd >= 0) FD_SET(sp->s_efd, &rfds); if (sp->s_efd > nfds) nfds = sp->s_efd; } if (slact->s_link == slact) break; nfds++; if (TVXLTY(&tnow, &tout)) { TVXSUBY(&tout, &tout, &tnow); } else { TVCLEAR(&tout); } if (pvmdebmask & PDMSTARTUP) { pvmlogprintf("pl_startup() select timeout is %d.%06d\n", tout.tv_sec, tout.tv_usec); } if ((n = select(nfds, #ifdef FDSETISINT (int *)&rfds, (int *)0, (int *)0, #else (fd_set *)&rfds, (fd_set *)0, (fd_set *)0, #endif &tout)) == -1) { if (errno != EINTR) { pvmlogperror("pl_startup() select"); pvmbailout(0); } } if (pvmdebmask & PDMSTARTUP) { pvmlogprintf("pl_startup() select returns %d\n", n); } if (n < 1) { if (n == -1 && errno != EINTR) { pvmlogperror("pl_startup() select"); pvmbailout(0); /* XXX this is too harsh */ } continue; } /* * check for response on stdout or stderr of any slave. */ for (sp = slact->s_link; sp != slact; sp = sp->s_link) { /* * stderr ready. log output with remote's host name. */ if (sp->s_efd >= 0 && FD_ISSET(sp->s_efd, &rfds)) { n = read(sp->s_efd, sp->s_ebuf + sp->s_elen, sizeof(sp->s_ebuf) - sp->s_elen - 1); if (n > 0) { sp->s_elen += n; sp->s_ebuf[sp->s_elen] = 0; while (p = CINDEX(sp->s_ebuf, '\n')) { *p = 0; pvmlogprintf("stderr@%s: %s\n", sp->s_hst->h_name, sp->s_ebuf); p++; sp->s_elen -= p - sp->s_ebuf; if (sp->s_elen > 0) { BCOPY(p, sp->s_ebuf, sp->s_elen); sp->s_ebuf[sp->s_elen] = 0; } } if (sp->s_elen == sizeof(sp->s_ebuf) - 1) { pvmlogprintf("stderr@%s: %s\n", sp->s_hst->h_name, sp->s_ebuf); sp->s_elen = 0; } } else { if (sp->s_elen > 0) { pvmlogprintf("stderr@%s: %s\n", sp->s_hst->h_name, sp->s_ebuf); sp->s_elen = 0; } (void)close(sp->s_efd); sp->s_efd = -1; } } /* * stdout ready. * look for a complete line starting with "ddpro". */ if (sp->s_rfd >= 0 && FD_ISSET(sp->s_rfd, &rfds)) { n = read(sp->s_rfd, sp->s_buf + sp->s_len, sizeof(sp->s_buf) - sp->s_len - 1); if (n > 0) { sp->s_len += n; sp->s_buf[sp->s_len] = 0; while (p = CINDEX(sp->s_buf, '\n')) { *p = 0; if (!strncmp(sp->s_buf, "ddpro", 5)) { if (pvmdebmask & PDMSTARTUP) { pvmlogprintf("stdout@%s: %s\n", sp->s_hst->h_name, sp->s_buf); } sp->s_hst->h_result = STRALLOC(sp->s_buf); break; } else { pvmlogprintf("stdout@%s: %s\n", sp->s_hst->h_name, sp->s_buf); p++; sp->s_len -= p - sp->s_buf; if (sp->s_len > 0) { BCOPY(p, sp->s_buf, sp->s_len); sp->s_buf[sp->s_len] = 0; } } } if (sp->s_len == sizeof(sp->s_buf) - 1) { pvmlogprintf("stdout@%s: %s\n", sp->s_hst->h_name, sp->s_buf); sp->s_len = 0; } } else { if (sp->s_len > 0) { pvmlogprintf("stdout@%s: %s\n", sp->s_hst->h_name, sp->s_buf); sp->s_len = 0; } if (n) { pvmlogprintf("stdout@%s", sp->s_hst->h_name); } else { pvmlogprintf("stdout@%s: EOF\n", sp->s_hst->h_name); } if (sp->s_elen > 0) { pvmlogprintf("stderr@%s: %s\n", sp->s_hst->h_name, sp->s_ebuf); sp->s_elen = 0; } /* before failing, check for alternate WIN32 cmd */ if (sp->s_hst->h_wincmd) { if (pvmdebmask & PDMSTARTUP) { pvmlogprintf( "pl_startup() re-trying %s as WIN32\n", hp->h_name); } /* no need to free h_cmd, we're a pvmd'... */ sp->s_hst->h_cmd = sp->s_hst->h_wincmd; sp->s_hst->h_wincmd = 0; phase1(sp); if (!(sp->s_hst->h_result)) { /* partially started */ pvmgetclock(&sp->s_bail); tout.tv_sec = RSHTIMEOUT; tout.tv_usec = 0; TVXADDY(&sp->s_bail, &sp->s_bail, &tout); } } else { sp->s_hst->h_result = STRALLOC("PvmCantStart"); } } if (sp->s_hst->h_result) { sp2 = sp->s_rlink; close_slot(sp); sp = sp2; continue; } } } } return 0; } phase1(sp) struct slot *sp; { struct hst *hp; char *hn; char *av[32]; /* for rsh args */ int ac; char buf[512]; int pid = -1; /* pid of rsh */ char *p; #ifndef NOREXEC struct servent *se; static u_short execport = 0; if (!execport) { if (!(se = getservbyname("exec", "tcp"))) { pvmlogprintf("phase1() can't getservbyname(): %s\n", "exec"); pvmbailout(0); } execport = se->s_port; endservent(); } #endif hp = sp->s_hst; hn = hp->h_name; sp->s_rfd = sp->s_wfd = sp->s_efd = -1; /* * XXX manual startup hack... this is if we can't use rexec or rsh */ if (hp->h_flag & HST_MANUAL) { fprintf(stderr, "*** Manual startup ***\n"); fprintf(stderr, "Login to \"%s\" and type:\n", hn); if (hp->h_wincmd) { fprintf(stderr, "%s\n\n", hp->h_cmd); fprintf(stderr, "or, if that command fails, " ); fprintf(stderr, "for WIN32 hosts try:\n"); fprintf(stderr, "%s\n\n", hp->h_wincmd); } else fprintf(stderr, "%s\n", hp->h_cmd); /* get version */ fprintf(stderr, "Type response: "); fflush(stderr); if (!(fgets(buf, sizeof(buf), stdin))) { pvmlogprintf("host %s read error\n", hn); goto oops; } p = buf + strlen(buf) - 1; if (*p == '\n') *p = 0; hp->h_result = STRALLOC(buf); /* send vmid, if set */ if (hp->h_vmid) { fprintf(stderr, "Now Type the Virtual Machine ID on %s:\n", hn); fprintf(stderr, "%s\n", hp->h_vmid); } /* done */ fprintf(stderr, "Thanks\n"); fflush(stderr); return 0; } /* * XXX end manual startup hack */ if (!(hp->h_flag & HST_PASSWORD)) { /* use rsh to start */ int wpfd[2], rpfd[2], epfd[2]; int i; if (pvmdebmask & PDMSTARTUP) { pvmlogprintf("phase1() trying rsh to %s\n", hn); } /* fork an rsh to startup the slave pvmd */ #ifdef IMA_TITN if (socketpair(AF_UNIX, SOCK_STREAM, 0, wpfd) == -1 || socketpair(AF_UNIX, SOCK_STREAM, 0, rpfd) == -1 || socketpair(AF_UNIX, SOCK_STREAM, 0, epfd) == -1) { pvmlogperror("phase1() socketpair"); goto oops; } #else if (pipe(wpfd) == -1 || pipe(rpfd) == -1 || pipe(epfd) == -1) { pvmlogperror("phase1() pipe"); goto oops; } #endif if (pvmdebmask & PDMSTARTUP) { pvmlogprintf("phase1() pipes: %d %d %d %d %d %d\n", wpfd[0], wpfd[1], rpfd[0], rpfd[1], epfd[0], epfd[1]); } if ((pid = fork()) == -1) { pvmlogperror("phase1() fork"); pvmbailout(0); } if (!pid) { (void)dup2(wpfd[0], 0); (void)dup2(rpfd[1], 1); (void)dup2(epfd[1], 2); for (i = getdtablesize(); --i > 2; ) (void)close(i); ac = 0; av[ac++] = pvmgetrsh(); av[ac++] = hn; if (hp->h_login) { av[ac++] = "-l"; av[ac++] = hp->h_login; } #ifdef IMA_BEOSCYLD /* Chop up the command line and all its parameters into * individual strings. The underlying assumption here is * that PVM_RSH is defined to specify 'bpsh' instead of * 'rsh/ssh'. This bit of code converts the single string * av[2] from this: "pvmd3 -option1 -option2", into this: * av[2] = "pvmd3", av[3] = "-option1", av[4] = "-option2"). * If this is not done 'bpsh' treats the original av[2] as * the file name of the command to be executed, which will * fail to execute. */ p = hp->h_cmd; do { av[ac++] = p; p = strstr(p," "); if (p != NULL) *p++ = '\0'; } while (p != NULL); #else av[ac++] = hp->h_cmd; #endif av[ac++] = 0; if (pvmdebmask & PDMSTARTUP) { for (ac = 0; av[ac]; ac++) fprintf(stderr, "av[%d]=\"%s\" ", ac, av[ac]); fputc('\n', stderr); } execvp(av[0], av); fputs("phase1() execvp failed\n", stderr); fflush(stderr); _exit(1); } (void)close(wpfd[0]); (void)close(rpfd[1]); (void)close(epfd[1]); sp->s_wfd = wpfd[1]; sp->s_rfd = rpfd[0]; sp->s_efd = epfd[0]; } else { /* use rexec to start */ #ifdef NOREXEC pvmlogprintf("slconfg() PVM was built without rexec support, can't take passwords\n"); goto oops; #else if (pvmdebmask & PDMSTARTUP) { pvmlogprintf("phase1() rexec \"%s\"\n", hp->h_cmd); } if ((sp->s_wfd = sp->s_rfd = rexec(&hn, execport, (hp->h_login ? hp->h_login : username), (char*)0, hp->h_cmd, &sp->s_efd)) == -1) { pvmlogprintf("phase1() rexec failed for host %s\n", hn); goto oops; } #endif } /* send vmid, if set */ if (sp->s_hst->h_vmid && sp->s_wfd >= 0) { #ifdef WIN32 win32_write_socket(sp->s_wfd, "PVM_VMID=", 9); win32_write_socket(sp->s_wfd, sp->s_hst->h_vmid, strlen(sp->s_hst->h_vmid)); win32_write_socket(sp->s_wfd, "\n", 1); #else write(sp->s_wfd, "PVM_VMID=", 9); write(sp->s_wfd, sp->s_hst->h_vmid, strlen(sp->s_hst->h_vmid)); write(sp->s_wfd, "\n", 1); #endif } return 0; oops: hp->h_result = STRALLOC("PvmCantStart"); if (sp->s_wfd != -1) close(sp->s_wfd); if (sp->s_rfd != -1) close(sp->s_rfd); if (sp->s_efd != -1) close(sp->s_efd); sp->s_wfd = sp->s_rfd = sp->s_efd = -1; return 1; } ./pvm3/src/imalloc.c0100644007401100000360000003110106506012221013441 0ustar kohlgopher static char rcsid[] = "$Id: imalloc.c,v 1.5 1998/03/24 20:16:17 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * imalloc.c * * Instrumented malloc filter. * * 7 Jun 1991 Robert Manchek manchek@CS.UTK.EDU. * 6 Sep 1991 added static glob and check features. * 17 Dec 1991 added i_realloc, cleaned up. * 8 Sep 1992 added total byte count. * 30 Oct 1992 added object type tag * * To use, add something like the following to your code: * #define malloc(n) i_malloc(n) * #define realloc(p,n) i_realloc(p,n) * #define free(p) i_free(p) * recompile, and link. * * Facilities: * * $ All errors written to fd 2 (not using stdio). * * $ Configurable to die on error for debugger. * Define DIEONERROR as 0 or 1. * * $ Configurable to use statically allocated space for recordkeeping. * This makes imalloc more immune to bad heap space trashing. * Define STATICGLOBS as nonzero. * * $ I_malloc(): * Error on [adjustable] unreasonble length or malloc() failed. * Hashes descriptors of all chunks for i_free() checking. * Numbers requests to indicate order received. * Writes [adjustable] pseudo-random head and tail pads to * aid in checking overrun of chunk. * * $ I_free(ptr): * Error if chunk not i_malloc()d. * Checks head and tail pads. * [Optionally] zeros chunk to aid in detecting late use. * Define ZEROONFREE as 0 or 1. * * $ I_dump(how): * Callable from user program. * Dumps the hash table to see what chunks are active. * If how is 1, checks each chunk's head and tail pads. * */ #ifdef HASSTDLIB #include #endif #include #ifdef SYSVSTR #include #else #include #endif /* #include XXX fails on next */ #include "bfunc.h" #ifndef DIEONERROR #define DIEONERROR 1 #endif #ifndef ZEROONFREE #define ZEROONFREE 1 #endif #ifndef STATICGLOBS #define STATICGLOBS 0 #endif #ifndef DUMPHDR #define DUMPHDR "i_dump()" #endif #ifndef LET0BE1 #define LET0BE1 1 #endif #define NEXTRN(x) (x = (x) + (x) + (((x ^ (x >> 3)) & 0x2000) ? 1 : 0)) #define HASH(p) (((long)(p) ^ ((long)(p) >> 8) ^ ((long)(p) >> 16) ^ ((long)(p) >> 24)) & 0xff) /* write a null-term string */ #if 0 #define SWRITE(fd,s) write((fd),(s),strlen(s)) #endif #define SWRITE(fd,s) pvmlogerror(s) /* this describes a chunk of memory */ struct glob { struct glob *next; /* next glob in hash bucket */ char *base; /* baseaddr of user chunk */ int len; /* len of user chunk */ int id; /* chunk id */ int lop; /* nbytes head padding */ int hip; /* nbytes tail padding */ int rst; /* starting random state */ int flg; char tag[4]; /* content tag */ }; #define OBALLOC 1 /* ob was just alloced - cleared by dump() */ #define OBREALLOC 2 /* ob was just realloced - cleared by dump() */ /* default values */ #if 0 static int debfd = 2; /* debug file descriptor */ #endif static int lengthlimit = 1048576; /* max length malloc allowed */ static int lopad = 16; /* chunk head pad */ static int hipad = 16; /* chunk tail pad */ /* globals */ static int totlnbyts = 0; /* total bytes allocated */ static int rnstate = 1; /* random sequence gen. */ static struct glob *hashtbl[256]; /* chunk hash table */ static char msbuf[256]; /* error message buffer */ static int firsttime = 1; static int globid = 0; /* chunk id counter */ #if STATICGLOBS > 0 static struct glob globheap[STATICGLOBS]; static struct glob *globfl = 0; static int globavail = STATICGLOBS; #endif /* i_choke() * * Found an inconsistency; bail. */ void i_choke() { #if DIEONERROR abort(); #endif } /* i_malloc() * * Allocate a buffer of given length. */ char* i_malloc(len, tag) unsigned len; /* number of bytes */ char *tag; /* content description */ { char *ptr; struct glob *ob; /* hash tbl entry */ struct glob **he; int i; /* gp */ if (firsttime) { firsttime = 0; BZERO((char*)hashtbl, sizeof(hashtbl)); #if STATICGLOBS > 0 /* initialize the glob freelist */ ob = 0; for (i = STATICGLOBS-1; i >= 0; i--) { globheap[i].next = ob; ob = &globheap[i]; } globfl = ob; #endif } /* check req length */ #if LET0BE1 > 0 if (!len) len = 1; #endif if (len < 1 || len > lengthlimit) { (void)sprintf(msbuf, "i_malloc: bogus len=%d\n", len); (void)SWRITE(debfd, msbuf); i_choke(); return (char*)0; } /* do actual malloc */ if (!(ptr = (char*)malloc(len + lopad + hipad))) { (void)sprintf(msbuf, "i_malloc: malloc failed len=%d\n", len); (void)SWRITE(debfd, msbuf); i_choke(); return (char*)0; } /* get descriptor */ #if STATICGLOBS > 0 if (ob = globfl) { globfl = globfl->next; globavail--; } else { (void)sprintf(msbuf, "i_malloc: glob allocate failed (max %d)\n", STATICGLOBS); (void)SWRITE(debfd, msbuf); i_choke(); return (char*)0; } #else if (!(ob = (struct glob*)malloc(sizeof(struct glob)))) { (void)sprintf(msbuf, "i_malloc: malloc failed for glob\n"); (void)SWRITE(debfd, msbuf); i_choke(); return (char*)0; } #endif /* enter descriptor, write head and tail pads */ ob->flg = OBALLOC; ob->id = ++globid; ob->tag[0] = 0; if (tag) strncpy(ob->tag, tag, 4); ob->len = len; ob->lop = lopad; ob->hip = hipad; ob->rst = rnstate; for (i = lopad; i-- > 0; *ptr++ = NEXTRN(rnstate)); ob->base = ptr; he = &hashtbl[HASH(ptr)]; for (i = hipad, ptr += len; i-- > 0; *ptr++ = NEXTRN(rnstate)); ob->next = *he; *he = ob; totlnbyts += len; return ob->base; } /* i_free() * * Give up a previously allocated buffer. */ i_free(loc) char *loc; /* ptr to buffer */ { struct glob *ob; /* freeing this object */ struct glob *preob; /* object before in chain */ int rs; /* reproduced random seqn */ char *ptr = loc; /* gp */ struct glob **he; /* hash tbl entry */ int i; /* gp */ /* sanity check */ if (firsttime) { char *s = "i_free: called before i_malloc?\n"; SWRITE(debfd, s); i_choke(); return 0; } /* delete from hash tbl */ he = &hashtbl[HASH(loc)]; for (preob = 0, ob = *he; ob && ob->base != loc; preob = ob, ob = ob->next); if (!ob) { (void)sprintf(msbuf, "i_free: bogus loc=0x%lx\n", (long) loc); (void)SWRITE(debfd, msbuf); i_choke(); return 0; } rs = ob->rst; /* check head and tail pads */ for (i = ob->lop, ptr -= i; i > 0; i--) if ((0xff & (int)(*ptr++)) != (0xff & NEXTRN(rs))) { (void)sprintf(msbuf, "i_free: scribbled in 0x%lx[%d]\n", (long) loc, -i); (void)SWRITE(debfd, msbuf); i_choke(); } for (i = ob->hip, ptr += ob->len; i > 0; i--) if ((0xff & (int)(*ptr++)) != (0xff & NEXTRN(rs))) { (void)sprintf(msbuf, "i_free: scribbled in 0x%lx[%d+%d]\n", (long) loc, ob->len, ob->hip - i); (void)SWRITE(debfd, msbuf); i_choke(); } /* do actual free */ #if ZEROONFREE BZERO(loc - ob->lop, ob->len + ob->lop + ob->hip); #endif free(loc - ob->lop); totlnbyts -= ob->len; /* reclaim descriptor */ if (preob) preob->next = ob->next; else *he = ob->next; #if STATICGLOBS > 0 ob->next = globfl; globfl = ob; globavail++; #else free((char*)ob); #endif return 0; } /* i_realloc() * * Resize a previously allocated buffer (possibly relocate as well) * and leave the contents unchanged up to the minimum of the old * and new lengths. */ char* i_realloc(loc, len) char *loc; /* old buffer */ unsigned len; /* length of new buffer */ { struct glob *ob; /* freeing this object */ struct glob *preob; /* object before in chain */ int rs; /* reproduced random seqn */ char *ptr = loc; /* gp */ struct glob **he; /* hash tbl entry */ int i; /* gp */ /* sanity check */ if (firsttime) { char *s = "i_realloc: called before i_malloc?\n"; SWRITE(debfd, s); i_choke(); return (char*)0; } /* check req length */ #if LET0BE1 > 0 if (!len) len = 1; #endif if (len < 1 || len > lengthlimit) { (void)sprintf(msbuf, "i_realloc: bogus len=%d\n", len); (void)SWRITE(debfd, msbuf); i_choke(); return (char*)0; } /* delete from hash tbl */ he = &hashtbl[HASH(loc)]; for (preob = 0, ob = *he; ob && ob->base != loc; preob = ob, ob = ob->next); if (!ob) { (void)sprintf(msbuf, "i_realloc: bogus loc=0x%lx\n", (long) loc); (void)SWRITE(debfd, msbuf); i_choke(); return (char*)0; } rs = ob->rst; /* check head and tail pads */ for (i = ob->lop, ptr -= i; i > 0; i--) if ((0xff & (int)(*ptr++)) != (0xff & NEXTRN(rs))) { (void)sprintf(msbuf, "i_realloc: scribbled in 0x%lx[%d]\n", (long) loc, -i); (void)SWRITE(debfd, msbuf); i_choke(); } for (i = ob->hip, ptr += ob->len; i > 0; i--) if ((0xff & (int)(*ptr++)) != (0xff & NEXTRN(rs))) { (void)sprintf(msbuf, "i_realloc: scribbled in 0x%lx[%d+%d]\n", (long) loc, ob->len, ob->hip - i); (void)SWRITE(debfd, msbuf); i_choke(); } /* remove descriptor */ if (preob) preob->next = ob->next; else *he = ob->next; /* realloc */ if (!(ptr = (char*)realloc(loc - ob->lop, len + lopad + hipad))) { (void)sprintf(msbuf, "i_realloc: malloc failed len=%d\n", len); (void)SWRITE(debfd, msbuf); i_choke(); return (char*)0; } /* rewrite descriptor, write head and tail pads */ totlnbyts += len - ob->len; ob->flg = OBREALLOC; ob->id = ++globid; /* XXX ? */ ob->len = len; ob->lop = lopad; ob->hip = hipad; ob->rst = rnstate; for (i = lopad; i-- > 0; *ptr++ = NEXTRN(rnstate)); ob->base = ptr; he = &hashtbl[HASH(ptr)]; for (i = hipad, ptr += len; i-- > 0; *ptr++ = NEXTRN(rnstate)); ob->next = *he; *he = ob; return ob->base; } /* ascdump() * * Convert byte string to printable characters. */ static void ascdump(o, p, e) char **o; /* addr of pointer to output space (passed back) */ char *p; /* string to convert */ int e; /* length of string */ { char *r = *o; char c; while (e-- > 0) { c = 0x7f & *p; if (c < ' ' || c == 0x7f) { c = (c + '@') & 0x7f; *r++ = '^'; } else *r++ = ' '; *r++ = c; p++; } *r++ = '\n'; *r = 0; *o = r; } /* i_dump() * * Dump the table of contents of allocated buffers. */ void i_dump(how) int how; /* != 0 also do sanity checking */ { int ht; /* hash table index */ struct glob *ob; char *r; int i; int rs; /* reproduced random seqn */ char *ptr; /* gp */ int err; char tagstr[5]; #if STATICGLOBS > 0 sprintf(msbuf, "%s %d bytes total/%d globs free\n", DUMPHDR, totlnbyts, globavail); (void)SWRITE(debfd, msbuf); #else sprintf(msbuf, "%s %d bytes total\n", DUMPHDR, totlnbyts); (void)SWRITE(debfd, msbuf); #endif for (ht = 0; ht < 256; ht++) { for (ob = hashtbl[ht]; ob; ob = ob->next) { rs = ob->rst; ptr = ob->base; err = 0; if (how) { for (i = ob->lop, ptr -= i; i > 0; i--) if ((0xff & (int)(*ptr++)) != (0xff & NEXTRN(rs))) { (void)sprintf(msbuf, "%5d 0x%08lx[%d]: scribbled in [%d]\n", ob->id, (long) ob->base, ob->len, -i); (void)SWRITE(debfd, msbuf); err++; } for (i = ob->hip, ptr += ob->len; i > 0; i--) if ((0xff & (int)(*ptr++)) != (0xff & NEXTRN(rs))) { (void)sprintf(msbuf, "%5d 0x%08lx[%d]: scribbled in [%d+%d]\n", ob->id, (long) ob->base, ob->len, ob->len, ob->hip - i); (void)SWRITE(debfd, msbuf); err++; } } if (!err) { strncpy(tagstr, ob->tag, 4); tagstr[4] = 0; sprintf(msbuf, "%5d%c%4s 0x%08lx[%4d]", ob->id, (ob->flg & OBALLOC ? '*' : (ob->flg & OBREALLOC ? '+' : ' ')), tagstr, (long) ob->base, ob->len); r = msbuf + strlen(msbuf); *r++ = ' '; if ((i = ob->len) > 24) i = 24; ascdump(&r, ob->base, i); (void)SWRITE(debfd, msbuf); } ob->flg &= ~(OBALLOC|OBREALLOC); } } } ./pvm3/src/lmsg.c0100644007401100000360000000707106354313362013007 0ustar kohlgopher static char rcsid[] = "$Id: lmsg.c,v 1.3 1997/06/25 22:08:50 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * lmsg.c * * low level message functions. * */ #include #include "pvmalloc.h" #include "listmac.h" #include "pvmdabuf.h" #include "pvmmagic.h" #include "lmsg.h" extern void pvmbailout(); /*************** ** Private ** ** ** ***************/ #ifdef IMA_CSPP /* NOTE: If we were doing flushes on node, we'd have to set dcache_stride to 32 for single node systems and 64 for multinode systems. But since we only do this for cross node systems, we already know it needs to be 64 */ int dcache_stride = 64; #endif #ifdef CLUMP_ALLOC #ifndef MSGID_CLUMP #define MSGID_CLUMP 50 #endif static struct msgid freemsgids; /* free msgid header cache */ static int nummsgids = 0; #endif static struct msgid * msgid_get_header() { struct msgid *mp; int n; #ifdef CLUMP_ALLOC if (nummsgids == 0) { freemsgids.ms_link = freemsgids.ms_rlink = &freemsgids; if (!(mp = TALLOC(MSGID_CLUMP, struct msgid, "mids"))) return (struct msgid *)0; for (n = MSGID_CLUMP; n-- > 0; ) { LISTPUTBEFORE(&freemsgids, mp, ms_link, ms_rlink); mp++; } nummsgids = MSGID_CLUMP; } nummsgids--; mp = freemsgids.ms_link; LISTDELETE(mp, ms_link, ms_rlink); #else mp = TALLOC(1, struct msgid, "mid"); #endif mp->magic = LMSG_MSGID; /* set the magic number */ return mp; } static msgid_put_header(mp) struct msgid *mp; { if (BADMAGIC(LMSG_MSGID, mp->magic)) { pvmlogerror("msgid_put_header(): bad magic number \n"); pvmbailout(0); return PvmSysErr; } #ifdef CLUMP_ALLOC if (nummsgids == 0) freemsgids.ms_link = freemsgids.ms_rlink = &freemsgids; LISTPUTBEFORE(&freemsgids, mp, ms_link, ms_rlink); nummsgids++; #else PVM_FREE(mp); #endif return 0; } /********************** ** Lmsg Functions ** ** ** **********************/ /* msgid_new() * * Create a new message id */ struct msgid * msgid_new() { struct msgid *mp; if (!(mp = msgid_get_header())) goto oops; mp->id = -1; mp->otid = -1; mp->ctxt = -1; mp->complete = 0; mp->ubuf = (char *) 0; return mp; oops: pvmlogerror("msgid_new() can't get memory\n"); pvmbailout(0); return (struct msgid *) 0; } /* msgid_free() * * free the msgid structure */ void msgid_free(mp) struct msgid *mp; { if (mp) msgid_put_header(mp); } ./pvm3/src/lpvm.c0100644007401100000360000026760610001307617013025 0ustar kohlgopher static char rcsid[] = "$Id: lpvm.c,v 1.69 2004/01/14 18:50:55 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * lpvm.c * * Libpvm core for unix environment. * * $Log: lpvm.c,v $ * Revision 1.69 2004/01/14 18:50:55 pvmsrc * Added new AIX5* arches. * (Spanker=kohl) * * Revision 1.68 2003/02/04 20:03:04 pvmsrc * Got rid of Jigen's goofy my_errno... * - never resolved anywhere... * (Spanker=kohl) * * Revision 1.67 2002/04/16 15:06:01 pvmsrc * WIN32 Fixes for Multiple Domains. * - submitted by Jigen Zhou . * (Spanker=kohl) * * Revision 1.66 2002/02/18 19:18:33 pvmsrc * Added "|| defined(IMA_SUN4SOL2)" to "const void *i, *j" #if * for int_compare() / qsort()... * (needed for sure for 64 bit) Solaris) * (Spanker=kohl) * * Revision 1.65 2001/12/07 16:06:09 pvmsrc * Oops! Some new Unix fixes & features break Windows (of course!). * - #ifdef-ed away fcntl() calls for non-blocking sockets / stdin. * (one for bug fix in lpvm.c, one for check_ext_input() in pvmd.c) * (Spanker=kohl) * * Revision 1.64 2001/09/25 21:20:17 pvmsrc * Minor TMPNAMFUN()/tmpnam() cleanup. * - moved macro def to pvm3.h, renamed PVMTNPMAN(). * - same for LEN_OF_TMP_NAM -> PVMTMPNAMLEN. * - mostly a huge waste of time, since *both* tmpnam() & mktemp() * produce the same "dangerous" warning message in Linux/gcc... * - damn. * (Spanker=kohl) * * Revision 1.63 2001/09/25 17:28:09 pvmsrc * Fixed leftover tmpnam() usage -> use TMPNAMFUN() instead... * - also got rid of "double" call to tmpnam()... * (Spanker=kohl) * * Revision 1.62 2001/05/11 19:40:50 pvmsrc * Fixed direct-routing bug, removed blocking socket deadlock. * - fix submitted by Kamil Iskra (as well as * , Dick van Albada , and * Zeger Hendrikse ). * (Spanker=kohl) * * Revision 1.61 2001/05/11 19:21:29 pvmsrc * Added "&& errno != EAGAIN" to select() return code check in mxfer(). * - reported by "Johannes Hennecke" * (Spanker=kohl) * * Revision 1.60 2001/05/11 17:32:26 pvmsrc * Eliminated references to sys_errlist & sys_nerr. * - unnecessary, and we're whacking that crap anyway. * (Spanker=kohl) * * Revision 1.59 2001/02/07 23:14:04 pvmsrc * First Half of CYGWIN Check-ins... * (Spanker=kohl) * * Revision 1.58 2000/06/15 17:51:49 pvmsrc * Fixed bug in WIN32 direct routing. * - stupid #endif in the wrong place, pvm_fd_add() call whacked. * - turned back on direct routing default and setopt. * (Spanker=kohl) * * Revision 1.57 2000/02/17 23:12:10 pvmsrc * *** Changes for new BEOLIN port *** * - MPP-like, similar to SP2, etc. * - submitted by Paul Springer . * - format-checked & cleaned up by Jeembo... :-) * (Spanker=kohl) * * Revision 1.56 2000/02/16 21:59:40 pvmsrc * Fixed up #include stuff... * - use for IMA_TITN... * - #include before any NEEDMENDIAN #includes... * (Spanker=kohl) * * Revision 1.55 2000/02/07 22:22:07 pvmsrc * Hack to help with select()/fd_sets in WIN32: * - fd_set is *NOT* a bit field in WIN32, is a circular buffer. * - must check for !FD_ISSET() before FD_SET() else duplicate * entries possible, and fd_set buffer overflow/overwrite. * - similary, FD_ISSET() check before FD_CLR(). * - patch submitted by "Bruce W. Church" . * (Spanker=kohl) * * Revision 1.54 1999/11/08 17:44:29 pvmsrc * SGI compiler cleanup. * (Spanker=kohl) * * Revision 1.53 1999/07/08 18:59:53 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.52 1999/03/15 19:05:58 pvmsrc * Replaced sleep() calls with pvmsleep(). * - Unix / Win32, C / Fortran compat... * (Spanker=kohl) * * Revision 1.51 1999/03/04 22:09:33 pvmsrc * New SHMD #ifdefs for pvm_psend() & pvm_precv(). * More direct conn debugging output. * (Spanker=kohl) * * Revision 1.50 1999/02/12 17:43:38 pvmsrc * Improved error messages in mksocs() for connect(). * - dump out the socket file being tried, in case some BOZOS (like * the people at Harris :-) put an echo statement into the * pvm3/lib/pvmd script... D-OH! * (Spanker=kohl) * * Revision 1.49 1998/11/20 20:04:00 pvmsrc * Changes so that win32 will compile & build. Also, common * Changes so that compiles & builds on NT. Also * common source on win32 & unix. * (Spanker=sscott) * * Revision 1.48 1998/10/02 15:43:58 pvmsrc * Single source code merge of Win32 and Unix code. * (Spanker=sscott) * * Revision 1.47 1998/09/30 18:08:32 pvmsrc * Fixed (I think :-) the direct connection initialization protocol. * - if two tasks tried to direct connect to each at the same time, * the CONREQ control messages could cross, causing each task * to fail on a connect(). * - instead, independent of Unix Domain / TCP (local / remote) * socket, *always* have greater (numerically) task ID handle * the direct connection, and have lower task ID just drop the * CONREQ on the floor. * - seems to work after extensive testing, both local & remote, * here's hoping... :-) * (Spanker=kohl) * * Revision 1.46 1998/09/23 15:25:23 pvmsrc * Need to make char *username non-extern here. * - username storage has to be somewhere for pvmd & libpvm. * - pvmwin.c can't have the storage, because it wouold clash with * pvmd.c, which needs to define username for non-WIN32 archs... * - beat me with a shovel dammit. * (Spanker=kohl) * * Revision 1.45 1998/08/13 18:32:45 pvmsrc * Added special case for AIX4SP2 arch with SOCKLENISUINT. * - on AIX 4.3 systems, I guess unsigned int is really * unsigned int, and not size_t... D-Oh! * - probably need a better constant name (or two) here... * (Spanker=kohl) * * Revision 1.44 1998/07/24 17:11:44 pvmsrc * Cleaned up use of SOCKLENISUINT / oslen. * - use oslen for every socket-related call: * * bind(), recvfrom(), getsockname() and accept(). * (Spanker=kohl) * * Revision 1.43 1998/03/02 19:27:32 pvmsrc * Fixed PGON typo seg fault parentheses d-oh. (Phil P.) * (Spanker=kohl) * * Revision 1.42 1998/02/23 22:51:29 pvmsrc * Added AIX4SP2 stuff. * (Spanker=kohl) * * Revision 1.41 1998/01/23 20:28:41 pvmsrc * Changed arguments to mxinput so that it will return number of frags * read and the number of messages. * mxfer will now continue reading frags if called by probe or nrecv and * mxinput returns frags > 0 but messages == 0. * (Spanker=phil) * * Revision 1.40 1997/12/31 20:50:02 pvmsrc * Cleaned Up System Message Handlers. * - current send / recv buffers now saved before invocation of * message handler functs. * - removed manual rbf = setrbuf(mid) saving & resetting in * handlers... * (Spanker=kohl) * * Revision 1.39 1997/12/18 21:22:53 pvmsrc * Applied perf patch for IBMs from Anders Alund / Nils Jonsson (PDC). * - nissej@pdc.kth.se * (Spanker=kohl) * * Revision 1.38 1997/12/01 19:20:36 pvmsrc * Replaced #ifdef IMA_OS2 fd_set declarations: * - new #ifdef FDSETNOTSTRUCT. * - choose between "fd_set foo" and "struct fd_set foo"... * (Spanker=kohl) * * Revision 1.37 1997/11/04 23:20:00 pvmsrc * Cleaned up fd_set stuff (hopefully). * Removed unused CINDEX() define. * (Spanker=kohl) * * Revision 1.36 1997/10/24 15:17:46 pvmsrc * Added TEV_DID_RCX to trace events for Receive Message Context. * - in pvm_recv(), pvm_trecv(), pvm_nrecv(), and pvm_precv(). * (Spanker=kohl) * * Revision 1.35 1997/10/24 14:29:23 pvmsrc * Added TEV_DID_MCX / pvmmyctx trace event info to: * - pvm_send(), pvm_mcast(), pvm_recv(), pvm_trecv(), pvm_nrecv(). * - pvm_psend(), pvm_precv(). * (Spanker=kohl) * * Revision 1.34 1997/09/22 21:13:25 pvmsrc * Added new pvmsettaskname() linkage (for shell-spawned tasks only!). * - call pvmsettaskname() before joining PVM, sends task name * (stored in new char *pvmmytaskname global) to pvmd in * TM_CONN2 message. * - appears in trace events and console ps. * (Spanker=kohl) * * Revision 1.33 1997/09/10 21:37:43 pvmsrc * putting socket startup to pvmbeatask. Markus * (Spanker=fischer) * * Revision 1.32 1997/08/29 13:35:06 pvmsrc * OS2 Port Submitted by Bohumir Horeni, horeni@login.cz. * (Spanker=kohl) * * Revision 1.31 1997/08/06 22:43:10 pvmsrc * Added new SGI6 and SGIMP6 arches. * * Revision 1.30 1997/06/27 18:04:17 pvmsrc * Integrated WIN32 changes. * * Revision 1.29 1997/06/12 20:10:37 pvmsrc * Made sure all communications for TC_* task control messages * use the SYSCTX_TC system context. * - some messages being sent in default context... D-Oh... * * Revision 1.28 1997/05/07 21:19:23 pvmsrc * swapped logic around SOCKLENISINT so that it is now * the default path and SOCKLENISUINT is the compile-time * selected path. * * Now, AIX 4.1 will have to remove SOCKLENISUINT from * their AIXxxx.def configure files. * * Revision 1.27 1997/05/07 18:37:13 pvmsrc * AIX 3.2 vs 4.1 vs 4.2 problems resolved (I hope) * Define oslen as size_t with compile flag SOCKLENISINT * for AIX 4.1 to explicitly set to int. * To use flag - set in conf/AIX46K.def. * Tested with cc and gcc on all 3 OS versions. * * Revision 1.26 1997/05/05 15:19:40 pvmsrc * context was not being set in pvmmcast. * * Revision 1.25 1997/05/01 14:11:46 pvmsrc * SGI Compiler Warning Cleanup. * * Revision 1.24 1997/04/30 21:26:00 pvmsrc * SGI Compiler Warning Cleanup. * * Revision 1.23 1997/04/29 20:29:12 pvmsrc * Support new calling sequences defined in mppmsg.h * * Revision 1.22 1997/04/25 19:21:18 pvmsrc * Handle inplace bodies of zero length correctly * * Revision 1.21 1997/04/24 21:06:59 pvmsrc * Excised unused variables. * Support for pvm_psend/precv constructs * * Revision 1.20 1997/04/21 14:58:28 pvmsrc * Changed #ifdefs that checked IMA_RS6K,IMA_SP2MPI & IMA_AIX46K * to see if select.h was needed into single define NEEDSSELECTH. * New archs need to set this in conf/ * * Revision 1.19 1997/04/07 21:09:17 pvmsrc * pvm_addmhf() - new paramter interface * * Revision 1.18 1997/04/03 19:23:13 pvmsrc * Added context for TM_xxx messages * * Revision 1.17 1997/04/01 21:28:11 pvmsrc * Damn Damn Damn. * - pvm_recvinfo() returns a bufid, not an index. Damn. * * Revision 1.16 1997/04/01 20:48:17 pvmsrc * Fixed tracer mbox usage: * - pvm_getinfo() -> pvm_recvinfo(), new semantics handled (recvinfo * sets rbuf implicitly, a la pvm_recv, need to save rbuf). * * Revision 1.15 1997/03/27 19:55:27 pvmsrc * Fixed up pvmbeatask() to go get tracer info if spawned from shell: * - env var info including trace mask, trace buffer size, trace opts. * - use PVMTRACERCLASS mbox entry to fill in values, if matches * on trctid, trcctx, and trctag. * * Revision 1.14 1997/03/07 15:12:11 pvmsrc * Fixed annoying SGI warnings for qsort()'s int_compare() function... * * Revision 1.13 1997/03/06 21:50:17 pvmsrc * Yanked out #includes for and . * - dups with lpvm.h #includes... * * Revision 1.12 1997/03/06 21:06:10 pvmsrc * - added include for lmsg.h, host.h * - for mpp's added pvmmimd.h, mppmsg.h * - moved struct ttpcb definition to header file lpvm.h * - for mpps added call to mpp_ttpcb_find inside of ttpcb_find * - mxinput rewritten to handle mpp input streams when ifdef'ed on * - Added a stack of inplace headers instead of just one dummy header. * so we can do asynch header transmission * - in mxfer: * logic written in to handle mpp streams, including bypass of * reading routes if writing, posting a complete message for * asynch send before checking for read routes, pass information * to pvm_node_send (on mpps) about inplace sending so that * pvm_node_send can be optimized for inplace (not optimized yet :-)) * - in mroute: * direct routing socket setup turned off for MPPs * - in pvmbeatask: * call pvm_mpp_beatask for mpps * don't do socket auth dance for mpps (sockets not used) * - added routine ogm_complete to test if an outgoing message is * complete (when sent asychronously). Returns TRUE for workstations * since writes are synchronous * * Revision 1.11 1997/01/28 19:26:21 pvmsrc * New Copyright Notice & Authors. * * Revision 1.10 1996/12/18 22:27:43 pvmsrc * Extracted duplicate versions of routines from lpvm/mimd/shmem.c, * inserted into shared lpvmgen.c: * - pvmbailout(). * - pvmlogerror(). * - vpvmlogprintf(), pvmlogprintf(). (hope these work on MPP & shmem) * - pvmlogperror(). * * Revision 1.9 1996/10/25 13:57:20 pvmsrc * Replaced old #includes for protocol headers: * - , "ddpro.h", "tdpro.h" * With #include of new combined header: * - * * Revision 1.8 1996/10/24 22:44:31 pvmsrc * Modified for New Tracing Facility: * - moved #include "global.h" below other #include's for typing. * - removed extra #include in lpvm.c... * - added #include of new "lpvm.h" to replace explicit externs. * - removed common control message handlers from lpvm.c: * * extracted to lpvmgen.c for general usage. * * pvm_tc_noop(), pvm_tc_settmask(), pvm_tc_siblings(). * -> lpvmmimd.c & lpvmshmem.c still need remainder of pvmmctl() * replaced with control message handlers. * - arg typing hassles with int_compare() / qsort() exacerbated... * - modified pvmbeatask(): * * handle new tracing info, unpack tracing and output collection * parameters into temp storage, and then check for local task * override before applying. * * read in new tracing env vars PVMTRCBUF & PVMTRCOPT. * * install new common message handlers. * * call new tev_init() routine to set up tracing stuff. * * use new Pvmtracer structures (pvmtrc & pvmctrc) to store info. * - removed pvm_getopt() & pvm_setopt() -> moved to common lpvmgen.c. * - removed old tev_begin(), tev_fin() & tev_do_trace() routines. * - updated trace event generation for pvm_getfds(), pvm_start_pvmd(), * pvm_precv(), pvm_psend(). * * Revision 1.7 1996/10/14 19:17:06 pvmsrc * Used ARCHFLAG SOCKLENISUINT where socket length is unsigned int * * Revision 1.6 1996/10/09 21:48:19 pvmsrc * Problem: * -------- * The problem was the result of AIX4.2 changing the expected datatype of * the XxxxLength parameter in the following system function calls: * * int bind (Socket, Name, NameLength) * int getsockname (Socket, Name, NameLength) * int recvfrom (Socket, Buffer, Length, Flags, From, FromLength) * int accept (Socket, Address, AddressLength) * * The compiler warning message generated was: * Function argument assignment between types "unsigned long*" and "int*" * is not allowed. * * Action: * ------- * In PVM functions where oslen was already declared_ * changed declaration from: int oslen; * to: unsigned int oslen; * * In PVM functions where a local "temporary" variable such as i, j, etc. * was used_ * added declaration of: unsigned int oslen; * and then changed to use oslen where necessary. * * Revision 1.5 1996/10/04 13:17:23 pvmsrc * New context was generated on each spawn. This is bad. * * Revision 1.4 1996/09/24 15:15:46 pvmsrc * Test failure... fixed. * * Revision 1.3 1996/09/24 15:12:19 kohl * Test check in... * * Revision 1.2 1996/09/23 23:30:53 pvmsrc * Initial Creation - original lpvm.c. * * Revision 1.32 1995/11/02 16:07:10 manchek * added NEEDSENDIAN switch. * must declare ptr to sys_errlist const in pvmlogperror for FREEBSD. * free replies to control messages in mxfer * * Revision 1.31 1995/09/06 17:37:24 manchek * aargh, forgot pvm_precv * * Revision 1.30 1995/09/06 17:30:32 manchek * pvm_psend returns not implemented instead of bad param for string type * * Revision 1.29 1995/07/28 16:40:58 manchek * wrap HASERRORVARS around errno declarations * * Revision 1.28 1995/07/28 16:04:05 manchek * switch endian includes on flag, not arch name * * Revision 1.27 1995/07/19 21:43:04 manchek * better mxfer logging * * Revision 1.26 1995/07/19 21:27:49 manchek * use pvmnametag to give symbolic message tags * * Revision 1.25 1995/07/18 16:59:03 manchek * added code to generate and check crc on each message (MCHECKSUM) * * Revision 1.24 1995/07/03 19:05:35 manchek * removed POWER4 arch ifdefs * * Revision 1.23 1995/06/28 18:18:07 manchek * do-nothing check_for_exit so one can be in lpvmshmem.c * * Revision 1.22 1995/06/19 17:35:05 manchek * addr sometimes wasn't set in pvm_tc_conreq, causing segfault * * Revision 1.21 1995/06/12 15:56:14 manchek * added PGON partition size support * * Revision 1.20 1995/06/02 17:19:14 manchek * added check in mxfer() for when outgoing route closed during input * * Revision 1.19 1995/06/01 14:43:54 manchek * pvm_start_pvmd ignores INT, QUIT, TSTP signals * * Revision 1.18 1995/05/30 17:28:08 manchek * added ifdefs for SP2MPI arch * * Revision 1.17 1995/05/17 17:06:54 manchek * added PVMTASKDEBUG envar * * Revision 1.16 1995/05/17 16:16:36 manchek * use FDSETISINT. * use umbuf_get and put instead of ALLOC. * in mksocs, read pvmd sockaddr file only once. * in pvmbeatask, read altpid from environment each time. * add PvmPollTime and Type, NotImplemented. * pvm_start_pvmd reads sockaddr from pvmd instead of sleeping on addr file, * sets PVMSOCK envar from return. * allows better synchronization, master host overloading. * * Revision 1.15 1995/02/01 21:08:46 manchek * error 4 is now PvmOverflow. * connect is retried in case of EINTR * * Revision 1.14 1994/12/20 16:28:19 manchek * added PvmShowTids case to setopt. * removed EOF message on pvmd socket close * * Revision 1.13 1994/10/15 19:07:31 manchek * don't use fd_sets when select returns -1; will hang reading. * cast message tags for comparison as integers * * Revision 1.12 1994/09/02 15:23:37 manchek * fixed segfaults in setopt when task not connected * * Revision 1.11 1994/07/18 19:20:18 manchek * fix to call write() with max 4096 length for RS6K * * Revision 1.10 1994/06/21 19:36:23 manchek * forgot to ifdef tt_spath * * Revision 1.9 1994/06/21 18:31:31 manchek * connect in mksocs() tries several times before giving up. * don't setsockopt() at TCP level on Unix task-task sockets * * Revision 1.8 1994/06/04 21:44:57 manchek * added unix domain sockets * * Revision 1.7 1994/06/03 20:38:15 manchek * version 3.3.0 * * Revision 1.6 1993/11/30 23:50:01 manchek * set nodelay and snd, rcv buffer sizes on t-t sockets * * Revision 1.5 1993/11/30 15:51:30 manchek * beatask complains if it can't write d-auth file (fs full?) * * Revision 1.4 1993/10/04 20:29:05 manchek * mksocks() and pvm_start_pvmd() now use pvmdsockfile(), not TDSOCKNAME. * made pvm_useruid global for pvmcruft.c * * Revision 1.3 1993/10/04 19:10:22 manchek * mctl() conflicts with mctl(2) - declare static for now * * Revision 1.2 1993/09/16 21:36:20 manchek * pvm_start_pvmd() was freeing the return string from pvmgetpvmd() * * Revision 1.1 1993/08/30 23:26:48 manchek * Initial revision * */ #ifdef WIN32 #include "pvmwin.h" #include #include #include #endif #include #ifdef IMA_TITN #include #else #include #endif #ifdef NEEDMENDIAN #include #endif #ifdef NEEDENDIAN #include #endif #ifdef NEEDSENDIAN #include #endif #include #if defined(WIN32) || defined(CYGWIN) #include "..\xdr\types.h" #include "..\xdr\xdr.h" #else #include #include #endif #ifndef WIN32 #include #endif #ifndef NOUNIXDOM #include #endif #ifdef NEEDSSELECTH #include #endif #include #include #ifdef SYSVSTR #include #else #include #endif #include #include #ifdef IMA_BEOLIN #include #endif #include #include "pvmalloc.h" #include "pvmfrag.h" #include "pmsg.h" #include "listmac.h" #include "tvdefs.h" #include "bfunc.h" #include "lpvm.h" #include #include "tevmac.h" #include "host.h" #include "waitc.h" #include "global.h" #include "lmsg.h" #ifdef IMA_MPP #include "pvmmimd.h" #include "mppmsg.h" #endif #ifdef PVM_SHMD /* need the prototypes for the pvm_shmd send and receive calls */ #include "../shmd/shmdproto.h" #endif #ifndef max #define max(a,b) ((a)>(b)?(a):(b)) #endif #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif #ifndef TTSOCKBUF #define TTSOCKBUF 0x8000 #endif /*************** ** Globals ** ** ** ***************/ char *getenv(); void hex_inadport __ProtoGlarp__ (( char *, struct sockaddr_in * )); extern char *inadport_decimal(); extern char *inadport_hex(); char *pvmgetpvmd(); char *pvmdsockfile(); char *pvmnametag(); struct pmsg *midtobuf(); struct pmsg *umbuf_new(); char *debug_flags(); struct msgid *pvm_inprecv = (struct msgid *) NULL; #ifndef HASERRORVARS extern int errno; /* from libc */ #endif #if defined(IMA_PGON) int pvmpgonpartsize = -1; /* FE prog, no partition */ #endif /*************** ** Private ** ** ** ***************/ static int mxfersingle = 1; /* mxfer returns after single frag */ static struct sockaddr_in pvmourinet; /* our host ip addr */ static struct ttpcb *ttlist = 0; /* dll of connected tasks */ static struct ttpcb *topvmd = 0; /* default route (to pvmd) */ static int pvmnfds = 0; /* 1 + highest bit set in fds */ #ifdef FDSETNOTSTRUCT static fd_set pvmrfds; /* rd fdset for mxfer() */ #else static struct fd_set pvmrfds; /* rd fdset for mxfer() */ #endif static struct pmsg *txlist[100]; /* queue for when mroute reentered */ static int txrp = 0; /* txlist read pointer */ static int txwp = 0; /* txlist write pointer */ #ifdef WIN32 char *username = 0; int system_loser_win; #ifndef IMA_WIN32_WATCOM extern char **environ; #endif #ifndef SOCK_DEFINES WSADATA WSAData; extern int nAlert; #define SOCK_DEFINES #endif #endif #ifdef WIN32 int int_compare(const void *i, const void *j); #endif /************************** ** Internal Functions ** ** ** **************************/ int pvm_fd_add(fd, sets) int fd; /* the fd */ int sets; /* which sets */ { #ifdef SANITY #ifndef WIN32 if (fd < 0 || fd >= FD_SETSIZE) { pvmlogprintf("pvm_fd_add() bad fd %d\n", fd); return 1; } #endif #endif if (sets & 1) if ( !FD_ISSET(fd, &pvmrfds) ) { FD_SET(fd, &pvmrfds); #ifdef WIN32 pvmnfds++; #endif } /* if (sets & 2) if ( !FD_ISSET(fd, &pvmwfds) ) { FD_SET(fd, &pvmwfds); #ifdef WIN32 pvmnwfds++; #endif } if (sets & 4) if ( !FD_ISSET(fd, &pvmefds) ) { FD_SET(fd, &pvmefds); #ifdef WIN32 pvmnefds++; #endif } */ #ifndef WIN32 /* if this is new highest, adjust nfds */ if (fd >= pvmnfds) pvmnfds = fd + 1; #endif return 0; } pvm_fd_delete(fd, sets) int fd; /* the fd */ int sets; /* which sets */ { #ifdef SANITY #ifndef WIN32 if (fd < 0 || fd >= FD_SETSIZE) { pvmlogprintf("pvm_fd_delete() bad fd %d\n", fd); return 1; } #endif #endif if (sets & 1) if ( FD_ISSET(fd, &pvmrfds) ) { FD_CLR(fd, &pvmrfds); #ifdef WIN32 pvmnfds--; #endif } /* if (sets & 2) if ( FD_ISSET(fd, &pvmwfds) ) { FD_CLR(fd, &pvmwfds); #ifdef WIN32 pvmnwfds--; #endif } if (sets & 4) if ( FD_ISSET(fd, &pvmefds) ) { FD_CLR(fd, &pvmefds); #ifdef WIN32 pvmnefds--; #endif } */ #ifndef WIN32 /* if this was highest, may have to adjust nfds to new highest */ if (fd + 1 == pvmnfds) while (pvmnfds > 0) { pvmnfds--; if (FD_ISSET(pvmnfds, &pvmrfds) /* || FD_ISSET(pvmnefds, &pvmefds) || FD_ISSET(pvmnwfds, &pvmwfds) */ ) { pvmnfds++; break; } } #endif return 0; } /* ttpcb_new() * * Create a new, blank ttpcb. */ struct ttpcb * ttpcb_new() { struct ttpcb *pcbp; if (pcbp = TALLOC(1, struct ttpcb, "tpcb")) { BZERO((char*)pcbp, sizeof(struct ttpcb)); pcbp->tt_fd = -1; pcbp->tt_rxfrag = pmsg_new(1); BZERO((char*)pcbp->tt_rxfrag, sizeof(struct pmsg)); pcbp->tt_rxfrag->m_link = pcbp->tt_rxfrag->m_rlink = pcbp->tt_rxfrag; } return pcbp; } /* ttpcb_delete() * * Get rid of a ttpcb. Delete it from any list, close the socket, * free any rx frag heap. */ void ttpcb_delete(pcbp) struct ttpcb *pcbp; { struct pmsg *up; if (pcbp->tt_link) { LISTDELETE(pcbp, tt_link, tt_rlink); } if (pcbp->tt_fd != -1) { pvm_fd_delete(pcbp->tt_fd, 3); (void)close(pcbp->tt_fd); } if (up = pcbp->tt_rxfrag) { while (up->m_link != up) umbuf_free(up->m_link); pmsg_unref(up); } if (pcbp->tt_rxf) fr_unref(pcbp->tt_rxf); #ifndef NOUNIXDOM if (pcbp->tt_spath) (void)unlink(pcbp->tt_spath); #endif PVM_FREE(pcbp); } /* ttpcb_creat() * * Create a new task-task entry. Allocates a ttpcb, inserts it in * ttlist. */ struct ttpcb * ttpcb_creat(tid) int tid; /* peer tid */ { struct ttpcb *pcbp, *pcbp2; if (pcbp = ttpcb_new()) { pcbp->tt_tid = tid; for (pcbp2 = ttlist->tt_link; pcbp2 != ttlist; pcbp2 = pcbp2->tt_link) if (pcbp2->tt_tid > tid) break; LISTPUTBEFORE(pcbp2, pcbp, tt_link, tt_rlink); } return pcbp; } /* ttpcb_find() * * Find a task-task entry by tid in ttlist. */ struct ttpcb * ttpcb_find(tid) int tid; /* peer tid */ { struct ttpcb *pcbp; #if defined(IMA_MPP) if ( pcbp = mpp_ttpcb_find(tid)) return pcbp; #endif for (pcbp = ttlist->tt_link; pcbp != ttlist; pcbp = pcbp->tt_link) if (pcbp->tt_tid >= tid) break; return (pcbp->tt_tid == tid) ? pcbp : (struct ttpcb*)0; } /* ttpcb_dead() * * Mark ttpcb dead, close socket, remove it from fd sets. */ void ttpcb_dead(pcbp) struct ttpcb *pcbp; { struct pmsg *up; int sbf; pcbp->tt_state = TTDEAD; if (pcbp->tt_fd != -1) { pvm_fd_delete(pcbp->tt_fd, 3); (void)close(pcbp->tt_fd); /* notify routing socket closed */ /* XXX problems with the route notify messages: XXX they can be delayed / cause deadlock because gotem isn't incremented */ check_routedelete(pcbp); pcbp->tt_fd = -1; } #ifndef NOUNIXDOM if (pcbp->tt_spath) { (void)unlink(pcbp->tt_spath); pcbp->tt_spath = 0; } #endif if (pcbp->tt_rxf) { fr_unref(pcbp->tt_rxf); pcbp->tt_rxf = 0; } if (up = pcbp->tt_rxfrag) { while (up->m_link != up) umbuf_free(up->m_link); } } int ttpcb_dump(pcbp) struct ttpcb *pcbp; { pvmlogprintf("ttpcb_dump() t%x fd=%d sad=%s", pcbp->tt_tid, pcbp->tt_fd, inadport_decimal(&pcbp->tt_sad)); pvmlogprintf(" osad=%s state=%d\n", inadport_decimal(&pcbp->tt_osad), pcbp->tt_state); return 0; } int ttpcb_dumpall() { struct ttpcb *pcbp; pvmlogerror("ttpcb_dumpall()\n"); ttpcb_dump(topvmd); for (pcbp = ttlist->tt_link; pcbp != ttlist; pcbp = pcbp->tt_link) ttpcb_dump(pcbp); return 0; } /* check_routeadd() * * Check if a notify is posted for new route creation, and send us * a message if so. */ int check_routeadd(pcbp) struct ttpcb *pcbp; { struct waitc *wp, *wp2; struct pmsg *up; int sbf; wp = waitlist->wa_link; while (wp != waitlist) { wp2 = wp->wa_link; if (wp->wa_kind == WT_ROUTEA) { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); pvm_pkint(&pcbp->tt_tid, 1, 1); pvm_pkint(&pcbp->tt_fd, 1, 1); sbf = pvm_setsbuf(sbf); up = midtobuf(sbf); up->m_ctx = wp->wa_mesg->m_ctx; up->m_tag = wp->wa_mesg->m_tag; mesg_input(up); if (wp->wa_count != -1 && --wp->wa_count < 1) wait_delete(wp); } wp = wp2; } return 0; } /* check_routedelete() * * Check if a notify is posted for route deletion, and send us * a message if so. */ int check_routedelete(pcbp) struct ttpcb *pcbp; { struct waitc *wp, *wp2; struct pmsg *up; int tid = pcbp->tt_tid; wp = waitlist->wa_link; while (wp != waitlist) { wp2 = wp->wa_link; if (wp->wa_kind == WT_ROUTED && tid == wp->wa_on) { up = wp->wa_mesg; wp->wa_mesg = 0; mesg_input(up); wait_delete(wp); } wp = wp2; } return 0; } int post_routedelete(tid, ctx, tag) int tid; int ctx; int tag; { int sbf; struct waitc *wp; struct pmsg *up; int i; sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); pvm_pkint(&tid, 1, 1); i = -1; pvm_pkint(&i, 1, 1); sbf = pvm_setsbuf(sbf); up = midtobuf(sbf); up->m_ctx = ctx; up->m_tag = tag; if (ttpcb_find(tid)) { wp = wait_new(WT_ROUTED); wp->wa_tid = pvmmytid; wp->wa_on = tid; wp->wa_mesg = up; } else { mesg_input(up); } return 0; } /* pvm_tc_conreq() * * Another task requests a connection with us. * Reply with a TC_CONACK message. * * TC_CONREQ() { * int tdprotocol // t-d protocol revision number * string sockaddr // address of other socket * } */ static int pvm_tc_conreq(mid) int mid; { int src; /* sender of request */ int sbf = 0; /* reply message mid */ int ttpro; /* protocol revision */ struct ttpcb *pcbp; /* pcb for connection */ int ackd; /* allow connection (0) */ char *addr = ""; /* socket address */ int i; int ictx; #ifdef SOCKLENISUINT #if defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) unsigned int oslen; #else size_t oslen; #endif #else int oslen; #endif #ifndef NOUNIXDOM struct sockaddr_un uns; char spath[PVMTMPNAMLEN]; #endif char buf[256]; pvm_bufinfo(mid, (int *)0, (int *)0, &src); pvm_upkint(&ttpro, 1, 1); pvm_upkstr(buf); if (pcbp = ttpcb_find(src)) { if (pvmdebmask & PDMROUTE) { pvmlogprintf( "pvm_tc_conreq() crossed CONREQ from t%x\n", src); } if (pcbp->tt_state == TTCONWAIT) { /* must handle simultaneous connect from both ends: * lower tid of the two just ignores the CONREQ. * higher tid pretends it didn't send a CONREQ, * sends a CONACK back. * this makes the connection single-sided. */ if (pvmdebmask & PDMROUTE) pvmlogerror( "pvmmctl() handling crossed CONREQ\n"); if (pvmmytid > src) { if (listen(pcbp->tt_fd, 1) == -1) pvmlogperror("pvm_tc_conreq() listen"); else { pcbp->tt_state = TTGRNWAIT; pvm_fd_add(pcbp->tt_fd, 1); ackd = 0; if (buf[0] == '/') { #ifdef NOUNIXDOM pvmlogprintf( "%s CONREQ from t%x, ", "pvm_tc_conreq()", src ); pvmlogprintf( "Unix domain socket unsupported\n" ); #else addr = pcbp->tt_spath; #endif } else { hex_inadport(buf, &pcbp->tt_osad); addr = inadport_hex(&pcbp->tt_sad); } check_routeadd(pcbp); sbf=pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); ttpro = TDPROTOCOL; pvm_pkint(&ttpro, 1, 1); pvm_pkint(&ackd, 1, 1); pvm_pkstr(addr); i = pvmrescode; pvmrescode = 1; ictx = pvm_setcontext(SYSCTX_TC); pvm_send(src, TC_CONACK); pvm_setcontext(ictx); pvmrescode = i; pvm_freebuf(pvm_setsbuf(sbf)); } } } else { pvmlogprintf( "pvm_tc_conreq() CONREQ from t%x but state=%d ?\n", src, pcbp->tt_state); } } else { if (pvmdebmask & PDMROUTE) pvmlogprintf("pvm_tc_conreq() CONREQ from t%x\n", src); ackd = 1; pcbp = ttpcb_creat(src); if (pvmrouteopt != PvmDontRoute) { if (buf[0] == '/') { #ifdef NOUNIXDOM pvmlogprintf( "%s CONREQ from t%x, ", "pvm_tc_conreq()", src ); pvmlogprintf( "Unix domain socket unsupported\n" ); #else /*NOUNIXDOM*/ if ((pcbp->tt_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { pvmlogperror("pvm_tc_conreq() socket"); } else { BZERO((char*)&uns, sizeof(uns)); uns.sun_family = AF_UNIX; spath[0] = 0; (void)PVMTMPNAMFUN(spath); strcpy(uns.sun_path, spath); oslen = sizeof(uns); if (bind(pcbp->tt_fd, (struct sockaddr*)&uns, oslen) == -1) { pvmlogperror("pvm_tc_conreq() bind"); } else { if (listen(pcbp->tt_fd, 1) == -1) pvmlogperror("pvm_tc_conreq() listen"); else { pcbp->tt_state = TTGRNWAIT; pvm_fd_add(pcbp->tt_fd, 1); ackd = 0; addr = pcbp->tt_spath = STRALLOC(spath); if (pvmdebmask & PDMROUTE) pvmlogprintf( "%s: %s (t%x)\n", "pvm_tc_conreq()", "new route socket listening", src ); /* new route socket listening, */ /* will be accepted later */ check_routeadd(pcbp); } } } #endif /*NOUNIXDOM*/ } else { if ((pcbp->tt_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { pvmlogperror("pvm_tc_conreq() socket"); } else { pcbp->tt_sad = pvmourinet; oslen = sizeof(pcbp->tt_sad); if (bind(pcbp->tt_fd, (struct sockaddr*)&pcbp->tt_sad, oslen) == -1) { pvmlogperror("pvm_tc_conreq() bind"); } else { if (getsockname(pcbp->tt_fd, (struct sockaddr*)&pcbp->tt_sad, &oslen) == -1) { pvmlogperror("pvm_tc_conreq() getsockname"); } else { if (listen(pcbp->tt_fd, 1) == -1) pvmlogperror("pvm_tc_conreq() listen"); else { hex_inadport(buf, &pcbp->tt_osad); pcbp->tt_state = TTGRNWAIT; pvm_fd_add(pcbp->tt_fd, 1); ackd = 0; addr = inadport_hex(&pcbp->tt_sad); if (pvmdebmask & PDMROUTE) pvmlogprintf( "%s: %s (t%x)\n", "pvm_tc_conreq()", "new route socket listening", src ); /* new route socket listening, */ /* will be accepted later */ check_routeadd(pcbp); } } } } } } if (pvmdebmask & PDMROUTE) pvmlogprintf( "%s: sending CONACK to t%x\n", "pvm_tc_conreq()", src ); sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); ttpro = TDPROTOCOL; pvm_pkint(&ttpro, 1, 1); pvm_pkint(&ackd, 1, 1); pvm_pkstr(addr); i = pvmrescode; pvmrescode = 1; ictx = pvm_setcontext(SYSCTX_TC); pvm_send(src, TC_CONACK); pvm_setcontext(ictx); pvmrescode = i; pvm_freebuf(pvm_setsbuf(sbf)); if (ackd) ttpcb_delete(pcbp); } pvm_freebuf(mid); return 0; } /* pvm_tc_conack() * * Another task replies to our connection request. * * TC_CONACK() { * int tdprotocol // t-d protocol revision number * int ack // 0 ok, 1 denied * string sockaddr // address of other socket * } */ static int pvm_tc_conack(mid) int mid; { int src; /* sender of reply */ int ttpro; /* protocol revision */ int ackd; /* connection allowed (0) */ struct ttpcb *pcbp; /* pcb for connection */ static int linger[2] = { 1, 60 }; /* XXX arbitrary time */ int i; #ifndef NOUNIXDOM struct sockaddr_un uns; #endif char buf[256]; pvm_bufinfo(mid, (int *)0, (int *)0, &src); pvm_upkint(&ttpro, 1, 1); pvm_upkint(&ackd, 1, 1); pvm_upkstr(buf); if (pcbp = ttpcb_find(src)) { if (pcbp->tt_state == TTCONWAIT) { if (pvmdebmask & PDMROUTE) { pvmlogprintf( "pvm_tc_conack() CONACK from t%x ackd=%d\n", src, ackd ); } if (ttpro != TDPROTOCOL) { pvmlogprintf("pvm_tc_conack() t-t protocol mismatch with t%x\n", pcbp->tt_tid); ackd = 1; } else { if (ackd != 0) { if (pvmdebmask & PDMROUTE) { pvmlogprintf("pvm_tc_conack() route to t%x denied\n", pcbp->tt_tid); } } else { if (buf[0] == '/') { #ifdef NOUNIXDOM pvmlogprintf( "pvm_tc_conack() CONREQ from t%x, Unix domain socket unsupported\n", src); ackd = 1; #else /*NOUNIXDOM*/ BZERO((char*)&uns, sizeof(uns)); uns.sun_family = AF_UNIX; strcpy(uns.sun_path, buf); while ((i = connect(pcbp->tt_fd, (struct sockaddr*)&uns, sizeof(uns))) == -1 && errno == EINTR) ; if (i == -1) { pvmlogperror("pvm_tc_conack() connect"); ackd = 1; } else { pcbp->tt_state = TTOPEN; #ifndef WIN32 if ((i = fcntl(pcbp->tt_fd, F_GETFL, 0)) == -1) pvmlogperror("pvm_tc_conack() fcntl"); else { #ifdef O_NDELAY i |= O_NDELAY; #else i |= FNDELAY; #endif (void)fcntl(pcbp->tt_fd, F_SETFL, i); } #endif pvm_fd_add(pcbp->tt_fd, 1); } #endif /*NOUNIXDOM*/ } else { pcbp->tt_osad.sin_family = AF_INET; hex_inadport(buf, &pcbp->tt_osad); while ((i = connect(pcbp->tt_fd, (struct sockaddr*)&pcbp->tt_osad, sizeof(pcbp->tt_osad))) == -1 && errno == EINTR) ; if (i == -1) { pvmlogperror("pvm_tc_conack() connect"); ackd = 1; } else { pcbp->tt_state = TTOPEN; #ifndef NOSOCKOPT if (setsockopt(pcbp->tt_fd, SOL_SOCKET, SO_LINGER, (char*)linger, sizeof(linger)) == -1) pvmlogperror("pvm_tc_conack() setsockopt"); #endif /*NOSOCKOPT*/ #ifndef WIN32 if ((i = fcntl(pcbp->tt_fd, F_GETFL, 0)) == -1) pvmlogperror("pvm_tc_conack() fcntl"); else { #ifdef O_NDELAY i |= O_NDELAY; #else i |= FNDELAY; #endif (void)fcntl(pcbp->tt_fd, F_SETFL, i); } #endif pvm_fd_add(pcbp->tt_fd, 1); } } } } if (ackd != 0) { pcbp->tt_state = TTDENY; (void)close(pcbp->tt_fd); pcbp->tt_fd = -1; } else if (pvmdebmask & PDMROUTE) { pvmlogprintf( "%s: connection accepted to t%x\n", "pvm_tc_conack()", src ); } } else { pvmlogprintf("pvm_tc_conack() CONACK from t%x but state=%d\n", src, pcbp->tt_state); } } else { pvmlogprintf("pvm_tc_conack() suprious CONACK from t%x\n", src); } pvm_freebuf(mid); return 0; } /* pvm_tc_taskexit() * * We are notified that another task (to which we have a direct route) * has exited. */ static int pvm_tc_taskexit(mid) int mid; { int tid; /* exited task id */ struct ttpcb *pcbp; pvm_upkint(&tid, 1, 1); if (pvmdebmask & PDMROUTE) { pvmlogprintf("pvm_tc_taskexit() TASKEXIT for t%x\n", tid); } /* * v3.3: for now, don't close fully open route as we may lose * messages. rely on socket getting EOF */ if ((pcbp = ttpcb_find(tid)) && pcbp->tt_state != TTOPEN) ttpcb_dead(pcbp); pvm_freebuf(mid); return 0; } /* mxinput() * * Input from a connection. * Reassemble packets into messages and receive them. * Returns >= 0 the number of messages added to pvmrxlist, * or negative on error. */ static int mxinput(pcbp, nfr) struct ttpcb *pcbp; int *nfr; /* number of frags read */ { int gotem = 0; /* num msgs added to pvmrxlist */ struct frag *fp; /* shadows pcbp->tt_rxf */ struct frag *fp2; int n; /* bytes received */ int m; /* length of fragment */ struct pmsg *rxup; /* message containing this frag */ struct pmsg *hdfrgpile; char *cp; /* gp */ int src; int dst; int ff; static int fairprobe = 0; *nfr = 0; #if defined(IMA_MPP) /* Messages from Tasks and Messages from the daemon are probed * fairprobe makes sure that neither interface gets starved. * fairprobe is toggled when an EOM is found */ switch (fairprobe) { /* pvm_readfrom returns a pointer to a frag, with its * length properly filled in. cp returns a pointer to the * the start of the data */ case 0: if ((fp = pvm_readfrompeer()) == (struct frag *) NULL) fp = pvm_readfrompvmd(); break; default: if ((fp = pvm_readfrompvmd()) == (struct frag *) NULL) fp = pvm_readfrompeer(); break; } if (!fp) return gotem; /* didn't read anything */ #else if (!pcbp->tt_rxf) if (!(pcbp->tt_rxf = fr_new(pvmfrgsiz))) return PvmNoMem; fp = pcbp->tt_rxf; /* read fragment header separately from body */ n = (fp->fr_len < TDFRAGHDR) ? 0 : pvmget32(fp->fr_dat + 8); n += TDFRAGHDR - fp->fr_len; if (pvmdebmask & PDMPACKET) { pvmlogprintf("mxinput() pcb t%x fr_len=%d fr_dat=+%d n=%d\n", pcbp->tt_tid, fp->fr_len, fp->fr_dat - fp->fr_buf, n); } #ifndef WIN32 n = read(pcbp->tt_fd, fp->fr_dat + fp->fr_len, n); #else n = win32_read_socket( pcbp->tt_fd,fp->fr_dat+fp->fr_len,n); #endif if (pvmdebmask & PDMPACKET) { pvmlogprintf("mxinput() read=%d\n", n); } /* deal with errors and closes */ if (n == -1 && #ifndef WIN32 errno != EWOULDBLOCK && #endif errno != EINTR) { if (pvmdebmask & PDMPACKET) { pvmlogperror("mxinput() read"); pvmlogprintf("mxinput() t%x\n", pcbp->tt_tid); } return PvmSysErr; } if (!n) { if (pvmdebmask & PDMPACKET) { pvmlogprintf("mxinput() t%x read EOF\n", pcbp->tt_tid); } return -1; } if (n < 1) return gotem; if ((fp->fr_len += n) < TDFRAGHDR) return gotem; /* realloc buffer if frag won't fit */ m = TDFRAGHDR + pvmget32(fp->fr_dat + 8); if (fp->fr_len == TDFRAGHDR) { if (m > fp->fr_max - (fp->fr_dat - fp->fr_buf)) { fp2 = fr_new(m); BCOPY(fp->fr_dat, fp2->fr_dat, TDFRAGHDR); fp2->fr_len = fp->fr_len; fr_unref(fp); fp = pcbp->tt_rxf = fp2; if (pvmdebmask & PDMPACKET) { pvmlogprintf("mxinput() realloc frag max=%d\n", m); } } } #endif /* defined (IMA_MPP) */ /* Now get information from the frag header to determine * src, destination, length, etc. */ #if !defined(IMA_MPP) if (fp->fr_len == m) #else if (fp) /* got a frag */ #endif { (*nfr)++; #if !defined (IMA_MPP) pcbp->tt_rxf = 0; #endif cp = fp->fr_dat; dst = pvmget32(cp); src = pvmget32(cp + 4); ff = pvmget8(cp + 12); fp->fr_len -= TDFRAGHDR; fp->fr_dat += TDFRAGHDR; if (pvmdebmask & PDMPACKET) { pvmlogprintf("mxinput() pkt src t%x len %d ff %d\n", src, fp->fr_len, ff); } #if defined(IMA_MPP) if (fp -> fr_rip ) /* frag was received inplace */ { gotem++; fr_unref(fp); /* free frag -- mppprecv knows that the msg completed */ return gotem; } hdfrgpile = pvm_mpp_pmsgs(); #else hdfrgpile = pcbp->tt_rxfrag ; #endif /* * if start of message, make new umbuf, add to frag pile */ if (ff & FFSOM) { cp += TDFRAGHDR; fp->fr_len -= MSGHDRLEN; fp->fr_dat += MSGHDRLEN; rxup = umbuf_new(); rxup->m_enc = pvmget32(cp); rxup->m_tag = pvmget32(cp + 4); rxup->m_ctx = pvmget32(cp + 8); rxup->m_wid = pvmget32(cp + 16); rxup->m_crc = pvmget32(cp + 20); rxup->m_src = src; rxup->m_dst = dst; LISTPUTBEFORE(hdfrgpile, rxup, m_link, m_rlink); } else { /* locate frag's message */ for (rxup = hdfrgpile->m_link; rxup != hdfrgpile; rxup = rxup->m_link) if (rxup->m_src == src) break; } if (rxup == hdfrgpile) { /* uh oh, no message for it */ pvmlogerror("mxinput() frag with no message\n"); fr_unref(fp); } else { LISTPUTBEFORE(rxup->m_frag, fp, fr_link, fr_rlink); rxup->m_len += fp->fr_len; /* * if end of message, move to pvmrxlist and count it */ if (ff & FFEOM) { #if defined(IMA_MPP) fairprobe = (fairprobe ? 0 : 1); #endif LISTDELETE(rxup, m_link, m_rlink); if (pvmdebmask & PDMMESSAGE) { pvmlogprintf( "mxinput() src t%x route t%x ctx %d tag %s len %d\n", rxup->m_src, (pcbp != 0 ? pcbp->tt_tid: -1), rxup->m_ctx, pvmnametag(rxup->m_tag, (int *)0), rxup->m_len); } #ifdef MCHECKSUM if (rxup->m_crc != umbuf_crc(rxup)) { pvmlogprintf( "mxinput() message src t%x route t%x tag %s bad checksum\n", rxup->m_src, pcbp->tt_tid, pvmnametag(rxup->m_tag, (int *)0)); umbuf_free(rxup); } else { #endif pmsg_setenc(rxup, rxup->m_enc); mesg_input(rxup); gotem++; #ifdef MCHECKSUM } #endif } } } return gotem; } /* mxfer() * * Move message frags between task and pvmd or other tasks. * Returns when * Outgoing message (if any) fully sent AND * (Timed out (tmout) OR * At least one message fully received) AND * No message from pvmd partially received. * Returns >= 0 the number of complete messages downloaded, or * negative on error. */ /* define a preallocated pool of inplace headers */ #define SHORT_PAYLOAD 128 #define HEADER_SIZE (TDFRAGHDR + MSGHDRLEN) #define NINPLACE_HDRS (8096/(SHORT_PAYLOAD + HEADER_SIZE)) static char inPlaceHdrPool[NINPLACE_HDRS * ( HEADER_SIZE )]; static int hdrPoolStk = 0; static int mxfer(txup, tmout) struct pmsg *txup; /* outgoing message or null */ struct timeval *tmout; /* time limit to get at least one message */ { struct ttpcb *txpcbp = 0; /* route for ogm */ struct frag *txfp = 0; /* cur ogm frag or null */ struct timeval tin; struct timeval tnow; struct timeval *tvp; #ifdef FDSETNOTSTRUCT fd_set rfds, wfds; #else struct fd_set rfds, wfds; #endif int wantmore = 1; /* nothing rxd yet and not timed out */ int gotem = 0; /* count of received msgs downloaded */ int ff; int n; #ifdef SOCKLENISUINT #if defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) unsigned int oslen; #else size_t oslen; #endif #else int oslen; #endif char *txcp = 0; /* point to remainder of txfp */ int txtogo = 0; /* len of remainder of txfp */ struct sockaddr_in sad; int s; struct ttpcb *pcbp; char *inPlaceHeader = (char *) NULL; /* for inplace data */ int inPlaceBodyLen = 0; /* len of inplace body */ int bypassRead = FALSE; /* bypass reading packets before send?*/ int waitForOgmToComplete = FALSE; int probedForIncomingPkts = FALSE; /* need to probe for incoming pkts */ struct msgid *sendmsg = (struct msgid *) NULL; char errtxt[64]; int nfr = 0, totfr = 0; /* number frags read my mxinput */ int probe = 0; /* called at a probe (nrecv) */ if (tmout) { pvmgetclock(&tin); probe = ( tmout -> tv_sec == 0 && tmout -> tv_usec == 0); } if (txup) { /* transmitting a umsg */ txfp = txup->m_frag->fr_link; if (!txfp->fr_buf) { if (!(txfp = fr_new(MAXHDR))) return PvmNoMem; txfp->fr_dat += MAXHDR; LISTPUTBEFORE(txup->m_frag, txfp, fr_link, fr_rlink); } /* Get connection info for this dest. If none, go to pvmd */ if (!(txpcbp = ttpcb_find(txup->m_dst)) || txpcbp->tt_state != TTOPEN) txpcbp = topvmd; txup->m_ref++; bypassRead = TRUE; /* bypass reading the first time through */ } if (pvmdebmask & PDMMESSAGE) { pvmlogprintf("mxfer() mid %d", (txup ? txup->m_mid : 0)); if (txup) pvmlogprintf(" ctx %d tag %s dst t%x route t%x", txup->m_ctx, pvmnametag(txup->m_tag, (int *)0), txup->m_dst, txpcbp->tt_tid); if (tmout) pvmlogprintf(" tmout %d.%06d\n", tmout->tv_sec, tmout->tv_usec); else pvmlogprintf(" tmout inf\n"); } /* XXX we go an extra time through select because wantmore gets set XXX inside loop. no big deal. also, could avoid calling gettimeofday XXX if tmout is 0.0 */ /* Do this loop if * 1) Sending a frag * OR 2) Received *part* of an incoming frag from the daemon * OR 3) Wantmore is true * OR 4) Need the current OGM to complete its asynch send * OR 5) We haven't probed at least once for incoming packets * * wantmore is initialized to TRUE -> loop exec'ed at least once */ while (txfp || topvmd->tt_rxf || wantmore || waitForOgmToComplete || !probedForIncomingPkts ) { totfr = 0; /* Either we are sending something, or have a partial recv'd frag */ if (txfp || topvmd->tt_rxf) /* gotta block */ { /* must block if sending any message, or receiving from pvmd */ tvp = (struct timeval *) NULL; } else { if (wantmore) { /* Calculate how long to wait inside the "select" * tval = NULL means wait forever * tval = (0,0) means probe * tval = (x,y) means wait at most x sec + y usec */ if (tmout) /* finite time to block */ { pvmgetclock(&tnow); TVXSUBY(&tnow, &tnow, &tin); if (TVXLTY(tmout, &tnow)) /* time's up */ { TVCLEAR(&tnow); wantmore = 0; } else { TVXSUBY(&tnow, tmout, &tnow); } tvp = &tnow; } else { /* forever to block */ tvp = (struct timeval *) NULL; } } else { /* return asap */ TVCLEAR(&tnow); tvp = &tnow; } } /* Here we are setting the read and write file descriptors for * the following select statement. */ #if !defined(IMA_MPP) rfds = pvmrfds; FD_ZERO(&wfds); if (txfp) FD_SET(txpcbp->tt_fd, &wfds); #endif if (pvmdebmask & PDMSELECT) { if (tvp) pvmlogprintf("mxfer() select timeout %d.%06d\n", tvp->tv_sec, tvp->tv_usec); else pvmlogprintf("mxfer() select timeout inf\n"); #if !defined(IMA_MPP) print_fdset("mxfer() rfds=", pvmnfds, &rfds); print_fdset("mxfer() wfds=", pvmnfds, &wfds); #endif } #if !defined(IMA_MPP) probedForIncomingPkts = TRUE; if ((n = select(pvmnfds, #ifdef FDSETISINT (int *)&rfds, (int *)&wfds, (int *)0, #else (fd_set *)&rfds, (fd_set *)&wfds, (fd_set*)0, #endif tvp)) == -1 && errno != EINTR #ifdef IMA_LINUX && errno != EAGAIN #endif ) { pvmlogperror("mxfer() select"); return PvmSysErr; } if (pvmdebmask & PDMSELECT) { pvmlogprintf("mxfer() select returns %d\n", n); } if (n == -1) continue; /* * if pvmd conn has data ready, read packets */ if (FD_ISSET(topvmd->tt_fd, &rfds) && !(mxfersingle && gotem)) { if ((n = mxinput(topvmd, &nfr)) < 0) { if (n != -1) pvmlogerror("mxfer() mxinput bad return on pvmd sock\n"); else if (pvmdebmask & (PDMSELECT|PDMMESSAGE|PDMPACKET)) pvmlogerror("mxfer() EOF on pvmd sock\n"); return PvmSysErr; } totfr += nfr; if (gotem += n) wantmore = 0; } /* * if task conn has data ready, read packets */ /* This goes through *all* of the pcbs that have been defined to * check for messages. This is too much overhead for IMA_MPP * machines. Instead all local routes must be probed at one time. */ for (pcbp = ttlist->tt_link; pcbp != ttlist; pcbp = pcbp->tt_link) { if (pcbp->tt_state == TTOPEN && FD_ISSET(pcbp->tt_fd, &rfds)) { if ((n = mxinput(pcbp, &nfr)) < 0) ttpcb_dead(pcbp); else { totfr += nfr; if (gotem += n) wantmore = 0; } } else /* Try and complete a direct (socket) Connection rqst */ if (pcbp->tt_state == TTGRNWAIT && FD_ISSET(pcbp->tt_fd, &rfds)) { oslen = sizeof(sad); s = accept(pcbp->tt_fd, (struct sockaddr*)&sad, &oslen); if (s == -1) { pvmlogperror("mxfer() accept"); ttpcb_dead(pcbp); } else { #ifndef NOSOCKOPT #ifndef NOUNIXDOM if (!pcbp->tt_spath) { /* not unix sock */ #endif n = 1; if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char*)&n, sizeof(int)) == -1) pvmlogperror("mxfer() setsockopt"); #if (!defined(IMA_RS6K)) \ && (!defined(IMA_AIX46K)) && (!defined(IMA_AIX46K64)) \ && (!defined(IMA_AIX56K)) && (!defined(IMA_AIX56K64)) n = TTSOCKBUF; if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&n, sizeof(int)) == -1 || setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&n, sizeof(n)) == -1) pvmlogperror( "mxfer() setsockopt SO_SNDBUF"); #endif #ifndef NOUNIXDOM } #endif #endif /*NOSOCKOPT*/ if (pvmdebmask & PDMROUTE) { pvmlogprintf("mxfer() accept from t%x = %d\n", pcbp->tt_tid, s); } (void)close(pcbp->tt_fd); /* (void)dup2(s, pcbp->tt_fd); (void)close(s); */ pvm_fd_delete(pcbp->tt_fd, 1); /* notify route socket closed */ check_routedelete(pcbp); pcbp->tt_fd = s; pcbp->tt_state = TTOPEN; #ifndef WIN32 { int i; if ((i = fcntl(pcbp->tt_fd, F_GETFL, 0)) == -1) pvmlogperror("mxfer() fcntl"); else { #ifdef O_NDELAY i |= O_NDELAY; #else i |= FNDELAY; #endif (void)fcntl(pcbp->tt_fd, F_SETFL, i); } } #endif pvm_fd_add(s, 1); /* new route socket created for communication */ check_routeadd(pcbp); } } } bypassRead = bypassRead; /* sgi compiler */ #else /* !IMA_MPP */ /* For Native Messaging mxinput is used to probe pvmd AND tasks when * given a NULL ttpcb pointer */ if (!bypassRead) { probedForIncomingPkts = TRUE; if ((n = mxinput((struct ttpcb *) NULL, &nfr)) < 0) { pvmlogerror("mxfer() mxinput bad return on probe\n"); return PvmSysErr; } totfr += nfr; if (gotem += n) wantmore = 0; } #endif /* !IMA_MPP */ /* * if sending and socket ready to write, send packets */ #if !defined(IMA_MPP) /* XXX Native message direct routes are alway open, if they exist */ if (txfp && txpcbp->tt_state != TTOPEN) { /* make sure our route hasn't just been closed */ txpcbp = topvmd; txcp = 0; txtogo = 0; txfp = txup->m_frag->fr_link; } else #endif { if (txfp && !waitForOgmToComplete #if !defined(IMA_MPP) && FD_ISSET(txpcbp->tt_fd, &wfds) #endif ){ inPlaceHeader = (char *) NULL; /*sending inplace header ?*/ inPlaceBodyLen = 0; /* length of inplace body, if inplace*/ if (!txtogo) /* We haven't sent anything, yet, Build Header */ { if (txfp->fr_u.dab) /* packed data */ { txcp = txfp->fr_dat; } else /* inplace data */ { txcp = inPlaceHeader = inPlaceHdrPool + hdrPoolStk*(HEADER_SIZE+SHORT_PAYLOAD) + HEADER_SIZE; if (pvmdebmask & PDMPACKET) { sprintf(errtxt,"mxfer() hdrPoolStk is %d\n", hdrPoolStk); pvmlogerror(errtxt); } if (hdrPoolStk++ >= NINPLACE_HDRS) { sprintf(errtxt, "mxfer(): > %d inplace frags \n", NINPLACE_HDRS); pvmlogerror(errtxt); return PvmSysErr; } } txtogo = txfp->fr_len; /* * if this is first frag, prepend message header */ ff = 0; if (txfp->fr_rlink == txup->m_frag) { txcp -= MSGHDRLEN; txtogo += MSGHDRLEN; pvmput32(txcp, (txup->m_enc == 0x20000000 ? pvmmydsig : txup->m_enc)); pvmput32(txcp + 4, txup->m_tag); pvmput32(txcp + 8, txup->m_ctx); pvmput32(txcp + 16, txup->m_wid); #ifdef MCHECKSUM pvmput32(txcp + 20, umbuf_crc(txup)); #else pvmput32(txcp + 20, 0); #endif ff = FFSOM; } if (txfp->fr_link == txup->m_frag) ff |= FFEOM; /* * prepend frag header */ txcp -= TDFRAGHDR; pvmput32(txcp, txup->m_dst); pvmput32(txcp + 4, pvmmytid); pvmput32(txcp + 8, txtogo); pvmput32(txcp + 12, 0); /* to keep putrify happy */ pvmput8(txcp + 12, ff); txtogo += TDFRAGHDR; if (!txfp->fr_u.dab) /* inplace data */ { txtogo -= txfp->fr_len; inPlaceBodyLen = txfp->fr_len; } } if (pvmdebmask & PDMPACKET) { pvmlogprintf("mxfer() dst t%x n=%d\n", txup->m_dst, txtogo); } #if defined(IMA_MPP) /* node_send will do an async send. Feed it a midlist struct. * when we get to the end of a message we call ogm_done * to make sure message is really gone, and we can free * memory * */ n = pvm_node_send(txcp, txtogo, txpcbp, &sendmsg, inPlaceHeader, inPlaceBodyLen); #else inPlaceBodyLen = inPlaceBodyLen; /* sgi compiler */ #if defined(IMA_RS6K) || defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) \ || defined(IMA_AIX5SP2) n = write(txpcbp->tt_fd, txcp, min(txtogo, 4096)); #else #ifndef WIN32 n = write(txpcbp->tt_fd, txcp, txtogo); #else n = win32_write_socket(txpcbp->tt_fd,txcp,txtogo); #endif #endif #endif if (pvmdebmask & PDMPACKET) { pvmlogprintf("mxfer() wrote %d\n", n); } if (n == -1 && #ifndef WIN32 errno != EWOULDBLOCK && #endif errno != EINTR) { if (txpcbp == topvmd) { pvmlogperror("mxfer() write pvmd sock"); return PvmSysErr; } else { pvmlogperror("mxfer() write tt sock"); /* reset message and route to pvmd */ ttpcb_dead(txpcbp); txpcbp = topvmd; txcp = 0; txtogo = 0; txfp = txup->m_frag->fr_link; } } if (n > 0) { txcp += n; if ((txtogo -= n) <= 0) { if (txcp == inPlaceHeader && txfp->fr_len ) /* inplace, body length > 0 */ { txcp = txfp->fr_dat; txtogo = txfp->fr_len; bypassRead = TRUE; /* try to send body without doing another read */ } else /* packed */ { txcp = 0; txfp = txfp->fr_link; if (!txfp->fr_buf) { txfp = 0; waitForOgmToComplete = TRUE; bypassRead = FALSE; } } } } else /* we couldn't send, might be a head-head send so ... */ { bypassRead = FALSE; /* enable reading if couldn't send */ } } } /* We are waiting for an outgoing message to complete. We can't send the next message until it does complete */ if (waitForOgmToComplete) { if (ogm_complete(&sendmsg)) { pmsg_unref(txup); /* unref the message */ txup = 0; waitForOgmToComplete = FALSE; hdrPoolStk = 0; /* recover all the inplace headers */ } } /* if not sending, and not waiting for ogm to complete, flush anything waiting in the reentered-send queue */ if (!txfp && txrp != txwp && !waitForOgmToComplete) { txup = txlist[txrp]; if (++txrp >= sizeof(txlist)/sizeof(txlist[0])) txrp = 0; txfp = txup->m_frag->fr_link; txfp = txfp->fr_buf ? txfp : 0; if (!(txpcbp = ttpcb_find(txup->m_dst)) || txpcbp->tt_state != TTOPEN) txpcbp = topvmd; } if (pvmdebmask & PDMMESSAGE) { pvmlogprintf("mxfer() txfp %d gotem %d tt_rxf %d\n", (txfp ? 1 : 0), gotem, (topvmd->tt_rxf ? 1 : 0)); } if (probe && !gotem && totfr) /* got frags, keep reading */ wantmore = 1; } return gotem; } /* mroute() * * Route a message to a destination / Receive incoming messages. * Returns when * Outgoing message (if any) fully sent AND * (Timed out waiting (tmout) OR * At least one message fully received) * Returns >= 0 the number of complete messages downloaded * (although some may have been consumed by message-handlers), * or negative on error. * * If mroute() is reentered (mroute -> mxfer -> handler -> pvm_send), * it queues the message and returns immediately. * The enclosing mxfer() later sends any messages in this queue. */ int mroute(mid, dtid, tag, tmout) int mid; /* message (or 0) */ int dtid; /* dest */ int tag; /* type tag */ struct timeval *tmout; /* get at least one message */ { static int alreadyhere = 0; /* have i called myself? */ struct ttpcb *pcbp; /* pcb for foreign task */ int s; /* socket */ int sbf; /* temp TC_CONREQ message */ struct pmsg *up, *up2; struct sockaddr_in sad; int l; #ifdef SOCKLENISUINT #if defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) unsigned int oslen; #else size_t oslen; #endif #else int oslen; #endif int cc = 0; int gotem = 0; /* count of received messages */ static struct timeval ztv = { 0, 0 }; char *addr = 0; #ifndef NOUNIXDOM struct sockaddr_un uns; char spath[PVMTMPNAMLEN]; #endif if (up = midtobuf(mid)) { up->m_dst = dtid; up->m_tag = tag; } if (alreadyhere) { if (up) { up->m_ref++; txlist[txwp] = up; if (++txwp >= sizeof(txlist)/sizeof(txlist[0])) txwp = 0; if (txwp == txrp) abort(); } /* we can't wait around if reentered */ if (!tmout || tmout->tv_sec || tmout->tv_usec) return PvmNotImpl; return 0; } alreadyhere = 1; /* if sending a message, decide whether we need to route it. */ /* Direct Routing is being set up in this section of code * For workstations (not MPP, SHMEM) * either Unix domain or TCP sockets are used. * task exit notifies are set up for route closure * * For MPPs and SHMEM, * connections to local tasks are always direct and require no * handshake negotiation. */ if (up) { /* We've got something to send */ #if !defined(IMA_MPP) /* This is the workstation direct route setup */ /* Checks made (Workstation): * o route option is direct * o destination is given * o destination is a task * o destination is not me * o could not find task process control block */ if (pvmrouteopt == PvmRouteDirect && dtid && TIDISTASK(dtid) && dtid != pvmmytid && !ttpcb_find(dtid)) { #if !defined(NOUNIXDOM) /* Create a UNIX domain socket to build the direct route */ if ((pvmmytid & TIDHOST) == (dtid & TIDHOST)) { if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { pvmlogperror("mroute() socket"); } else { BZERO((char*)&uns, sizeof(uns)); uns.sun_family = AF_UNIX; spath[0] = 0; (void)PVMTMPNAMFUN(spath); strcpy(uns.sun_path, spath); oslen = sizeof(uns); if (bind(s, (struct sockaddr*)&uns, oslen) == -1) { pvmlogperror("mroute() bind"); (void)close(s); s = -1; } else { pcbp = ttpcb_creat(dtid); pcbp->tt_fd = s; addr = pcbp->tt_spath = STRALLOC(spath); pcbp->tt_state = TTCONWAIT; } } } else { #endif /* !NOUNIXDOM */ /* Open a TCP direct Connection here, instead */ if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) { pvmlogperror("mroute() socket"); } else { sad = pvmourinet; oslen = sizeof(sad); if (bind(s, (struct sockaddr*)&sad, oslen) == -1) { pvmlogperror("mroute() bind"); (void)close(s); s = -1; } else { if (getsockname(s, (struct sockaddr*)&sad, &oslen) == -1) { pvmlogperror("mroute() getsockname"); (void)close(s); s = -1; } else { #ifndef NOSOCKOPT l = 1; if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char*)&l, sizeof(int)) == -1) pvmlogperror("mroute() setsockopt"); #if (!defined(IMA_RS6K)) \ && (!defined(IMA_AIX46K)) && (!defined(IMA_AIX46K64)) \ && (!defined(IMA_AIX56K)) && (!defined(IMA_AIX56K64)) l = TTSOCKBUF; if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&l, sizeof(l)) == -1 || setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&l, sizeof(l)) == -1) pvmlogperror("mroute() setsockopt SO_SNDBUF"); #endif #endif pcbp = ttpcb_creat(dtid); pcbp->tt_fd = s; pcbp->tt_sad = sad; pcbp->tt_state = TTCONWAIT; addr = inadport_hex(&sad); } } } #if !defined(NOUNIXDOM) } #endif /* 1. Request direct connection (TC_CONREQ) * 2. Request Notify so that we can close dead routes */ if (s >= 0) { /* Socket was opened correctly */ /* Send Connection Request */ sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); l = TDPROTOCOL; pvm_pkint(&l, 1, 1); pvm_pkstr(addr); sbf = pvm_setsbuf(sbf); up2 = midtobuf(sbf); up2->m_dst = dtid; up2->m_tag = TC_CONREQ; up2->m_ctx = SYSCTX_TC; cc = mxfer(up2, &ztv); pvm_freebuf(sbf); /* now send a task exit notify to my pvmd */ if (cc >= 0) { gotem += cc; sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); l = PvmTaskExit; pvm_pkint(&l, 1, 1); l = SYSCTX_TC; pvm_pkint(&l, 1, 1); l = TC_TASKEXIT; pvm_pkint(&l, 1, 1); l = 1; pvm_pkint(&l, 1, 1); pvm_pkint(&dtid, 1, 1); sbf = pvm_setsbuf(sbf); up2 = midtobuf(sbf); up2->m_dst = TIDPVMD; up2->m_tag = TM_NOTIFY; up2->m_ctx = SYSCTX_TM; cc = mxfer(up2, &ztv); pvm_freebuf(sbf); } if (pvmdebmask & PDMROUTE) { pvmlogprintf("mroute() CONREQ to t%x\n", dtid); } /* wait until the route pcb changes state */ while (pcbp->tt_state == TTCONWAIT) { if ((cc = mxfer((struct pmsg *)0, (struct timeval *)0)) < 0) break; gotem += cc; } if (pcbp->tt_state == TTOPEN) check_routeadd(pcbp); } } #endif /* IMA_MPP */ } /* now send the original message with whatever route we have */ if (cc >= 0) if ((cc = mxfer(up, tmout)) > 0) gotem += cc; /* clean up any stale route pcbs */ #if !defined(IMA_MPP) pcbp = ttlist->tt_link; while (pcbp != ttlist) if (pcbp->tt_state == TTDEAD) { if (pvmdebmask & PDMROUTE) { pvmlogprintf("mroute() freeing pcb t%x\n", pcbp->tt_tid); } pcbp = pcbp->tt_link; ttpcb_delete(pcbp->tt_rlink); } else pcbp = pcbp->tt_link; #endif /* IMA_MPP */ alreadyhere = 0; return (cc < 0 ? cc : gotem); } /* msendrecv() * * Single op to send a system message (usually to our pvmd) and get * the reply. * Returns message handle or negative if error. */ int msendrecv(other, tag, context) int other; /* dst, src tid */ int tag; /* message tag */ int context; /* context to use for the message */ { static int nextwaitid = 1; int cc; struct pmsg *up; if (!pvmsbuf) return PvmNoBuf; /* send message to other */ if (pvmdebmask & PDMMESSAGE) { pvmlogprintf("msendrecv() to t%x tag %s\n", other, pvmnametag(tag, (int *)0)); } pvmsbuf->m_wid = nextwaitid++; pvmsbuf->m_ctx = context; /* pvmlogprintf("msendrecv() ctx=%d\n", pvmsbuf->m_ctx); */ if ((cc = mroute(pvmsbuf->m_mid, other, tag, (struct timeval *)0)) < 0) return cc; /* recv matching message from other */ for (up = pvmrxlist->m_link; 1; up = up->m_link) { if (up == pvmrxlist) { up = up->m_rlink; if ((cc = mroute(0, 0, 0, (struct timeval *)0)) < 0) return cc; up = up->m_link; if (up == pvmrxlist) continue; } if (pvmdebmask & PDMMESSAGE) { pvmlogprintf("msendrecv() from t%x tag %s\n", up->m_src, pvmnametag(up->m_tag, (int *)0)); } if (up->m_src == other && up->m_tag == tag) { if (up->m_ctx != pvmsbuf->m_ctx) { pvmlogprintf("msendrecv() tag %s, context doesn't match\n", pvmnametag(up->m_tag, (int *)0)); } if (up->m_wid != pvmsbuf->m_wid) { pvmlogprintf("msendrecv() tag %s, waitid doesn't match\n", pvmnametag(up->m_tag, (int *)0)); } break; } } LISTDELETE(up, m_link, m_rlink); if (pvmrbuf) umbuf_free(pvmrbuf); pvmrbuf = 0; if (cc = pvm_setrbuf(up->m_mid)) return cc; return up->m_mid; } static int int_compare(i, j) #if defined (WIN32) || defined(IMA_SGI) || defined(IMA_SGI5) || defined(IMA_SGI6) || defined(IMA_SGI64) || defined(IMA_SGIMP) || defined(IMA_SGIMP6) || defined(IMA_SGIMP64) || defined(IMA_SUN4SOL2) const void *i, *j; #else void *i, *j; #endif { return *((int *)i) - *((int *)j); } /* pvmmcast() * * Multicast a message to a list of destinations. */ int pvmmcast(mid, tids, count, tag) int mid; int *tids; int count; int tag; { static struct timeval ztv = { 0, 0 }; int *dst; int i, j; int cc = 0; struct ttpcb *pcbp; int sbf; /* * make sorted list of destinations */ dst = TALLOC(count, int, "mcal"); BCOPY(tids, dst, count * sizeof(int)); qsort( (void *)dst, (size_t)count, sizeof(int), int_compare); /* * remove duplicates */ j = 0; for (i = 1; i < count; i++) if (dst[i] != dst[j]) dst[++j] = dst[i]; count = j + 1; /* Need to set the context of the message buffer */ pvmsbuf->m_ctx = pvmmyctx; /* * remove self from list * send over any direct routes we have * * XXX we should attempt new routes here if RouteDirect is on. */ j = 0; for (i = 0; i < count; i++) { if (dst[i] == pvmmytid) continue; if ((pcbp = ttpcb_find(dst[i])) && pcbp->tt_state == TTOPEN) mroute(pvmsbuf->m_mid, dst[i], tag, &ztv); else dst[j++] = dst[i]; } count = j; /* destinations still to go */ /* * send rest of addresses to pvmd for distribution */ if (count > 0) { /* announce multicast address list to pvmd */ sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); pvm_pkint(&count, 1, 1); pvm_pkint(dst, count, 1); sbf = pvm_setsbuf(sbf); if ((cc = mroute(sbf, TIDPVMD, TM_MCA, &ztv)) > 0) cc = 0; pvm_freebuf(sbf); /* send message */ if (cc >= 0) if ((cc = mroute(pvmsbuf->m_mid, pvmmytid | TIDGID, tag, &ztv)) > 0) cc = 0; } PVM_FREE(dst); return cc; } /* mksocs() * * Make socket for talking to pvmd. Connect to address advertized * in pvmd socket-name file. * * Returns 0 if okay, else error code. */ static int mksocs() { char buf[128]; #ifndef WIN32 int d; #else HANDLE d; #endif #ifdef SOCKLENISUINT #if defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) unsigned int oslen; #else size_t oslen; #endif #else int oslen; #endif int n; int try; char *p; #ifndef NOUNIXDOM struct sockaddr_un uns; #endif if (topvmd) return 0; /* * get addr of pvmd, make socket to talk. * first try envar PVMSOCK, then try sockaddr file. */ if (!(p = getenv("PVMSOCK"))) { if (!(p = pvmdsockfile())) { pvmlogerror("mksocs() pvmdsockfile() failed\n"); goto bail; } #ifndef WIN32 if ((d = open(p, O_RDONLY, 0)) == -1) { #else d = win32_open_file(p); if (d == (HANDLE) -2) { system_loser_win=TRUE; d = (HANDLE) _open(p,O_RDONLY,0); } if (d== (HANDLE) -1) { #endif pvmlogperror(p); goto bail; } #ifdef WIN32 if (!system_loser_win) { n = win32_read_file(d,buf,sizeof(buf)); win32_close_file(d); } else { n = (int)_read((int)d, (void *)buf, (unsigned int)sizeof(buf)); (void)_close((int)d); } #else n = read(d, buf, sizeof(buf)); (void)close(d); #endif if (n == -1) { pvmlogperror("mksocs() read addr file"); goto bail; } if (n == 0) { pvmlogerror("mksocs() read addr file: wrong length read\n"); goto bail; } buf[n] = 0; p = buf; } FD_ZERO(&pvmrfds); /* FD_ZERO(&pvmwfds); */ pvmnfds = 0; topvmd = ttpcb_new(); topvmd->tt_tid = TIDPVMD; if (p[0] == '/') { #ifdef NOUNIXDOM pvmlogerror("mksocs() no support for Unix domain socket\n"); goto bail; #else /*NOUNIXDOM*/ if ((topvmd->tt_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { pvmlogperror("mksocs() socket"); goto bail; } /* * XXX these 2 loops are a hack - * XXX it keeps too many tasks from overflowing the pvmd listen q. * XXX maybe the pvmd should make a socket pair for the task instead. */ try = 5; while (1) { BZERO((char*)&uns, sizeof(uns)); uns.sun_family = AF_UNIX; strcpy(uns.sun_path, p); n = sizeof(uns); if (connect(topvmd->tt_fd, (struct sockaddr*)&uns, n) == -1) { if (--try <= 0) { pvmlogperror("mksocs() connect"); pvmlogprintf("\tsocket address tried: %s\n",p); goto bail; } pvmsleep(1); /* XXX hmm again */ } else break; } #endif /*NOUNIXDOM*/ } else { if ((topvmd->tt_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { pvmlogperror("mksocs() socket"); goto bail; } try = 5; while (1) { /* goto is at the root of all good programming style */ hex_inadport(p, &topvmd->tt_osad); topvmd->tt_osad.sin_family = AF_INET; n = sizeof(topvmd->tt_osad); if (connect(topvmd->tt_fd, (struct sockaddr*)&topvmd->tt_osad, n) == -1) { if (--try <= 0) { pvmlogperror("mksocs() connect"); pvmlogprintf("\tsocket address tried: %s\n",p); goto bail; } pvmsleep(1); /* XXX hmm again */ } else break; } #ifndef NOSOCKOPT #ifdef WIN32 d = (HANDLE)1; #else d = 1; #endif if (setsockopt(topvmd->tt_fd, IPPROTO_TCP, TCP_NODELAY, (char*)&d, sizeof(int)) == -1) { pvmlogperror("mksocs() setsockopt"); goto bail; } #endif oslen = sizeof(topvmd->tt_sad); if (getsockname(topvmd->tt_fd, (struct sockaddr*)&topvmd->tt_sad, &oslen) == -1) { pvmlogperror("mksocs() getsockname"); goto bail; } } topvmd->tt_state = TTOPEN; pvm_fd_add(topvmd->tt_fd, 1); return 0; bail: if (topvmd) ttpcb_delete(topvmd); topvmd = 0; return PvmSysErr; } /* unmksocs() * * Close socket to local pvmd. */ static int unmksocs() { if (!topvmd) return 1; while (ttlist->tt_link != ttlist) ttpcb_delete(ttlist->tt_link); ttpcb_delete(topvmd); topvmd = 0; return 0; } /* pvmbeatask() * * Initialize libpvm, config process as a task. * This is called as the first step of each libpvm function so no * explicit initialization is required. * * Makes socket to talk to local pvmd, connects to pvmd, trades * config information and authentication. * * Returns 0 if okay, else error code. */ int pvmbeatask() { int sbf = 0, rbf = 0; /* saved rx and tx message handles */ int prver; /* protocol version */ int cookie; /* cookie assigned by pvmd for ident */ int cc; char **ep=0; char authfn[PVMTMPNAMLEN]; /* auth file name */ int authfd = -1; /* auth fd to validate pvmd ident */ int i; char buf[16]; /* for converting sockaddr */ char *p; struct pvmminfo minfo; int outtid, outctx, outtag; int trctid, trcctx, trctag; int need_trcinfo = 0; int new_tracer = 0; char tmask[ 2 * TEV_MASK_LENGTH ]; int tbuf, topt; int mid; #ifdef IMA_BEOLIN struct hostent *hostaddr; char namebuf[128]; #endif TEV_DECLS #ifdef WIN32 /* WSAStartup has to be called before any socket command can be executed. Why ? Ask Bill */ for (ep=environ;*ep;ep++) pvmputenv(*ep); if (WSAStartup(0x0101, &WSAData) != 0) { fprintf(stderr,"\nWSAStartup() failed\n"); ExitProcess(1); } /* setsockopt(INVALID_SOCKET,SOL_SOCKET,SO_OPENTYPE, */ /* (char *)&nAlert,sizeof(int)); */ #endif /* pvm_setopt(PvmDebugMask, -1); */ if (pvmmytid != -1) return 0; pvmmydsig = pvmgetdsig(); TEV_EXCLUSIVE; authfn[0] = 0; #ifndef WIN32 pvmmyupid = getpid(); #else pvmmyupid = _getpid(); /* .... */ #endif /* * get expected pid from environment in case we were started by * the pvmd and someone forked again */ if (p = getenv("PVMEPID")) cookie = atoi(p); else cookie = 0; /* if ((pvm_useruid = getuid()) == -1) */ #ifndef WIN32 if ((pvm_useruid = geteuid()) == -1) { pvmlogerror("can't getuid()\n"); cc = PvmSysErr; goto bail2; } #else if (!username) username = MyGetUserName(); #endif if (p = getenv("PVMTASKDEBUG")) { pvmdebmask = pvmstrtoi(p); if (pvmdebmask) { pvmlogprintf("task debug mask is 0x%x (%s)\n", pvmdebmask, debug_flags(pvmdebmask)); } } #ifndef IMA_MPP if (cc = mksocs()) /* make socket to talk to pvmd */ goto bail2; #endif /* * initialize received-message list */ pvmrxlist = pmsg_new(1); BZERO((char*)pvmrxlist, sizeof(struct pmsg)); pvmrxlist->m_link = pvmrxlist->m_rlink = pvmrxlist; ttlist = TALLOC(1, struct ttpcb, "tpcb"); BZERO((char*)ttlist, sizeof(struct ttpcb)); ttlist->tt_link = ttlist->tt_rlink = ttlist; sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); /* * create empty t-auth file that pvmd must write and we'll check later */ #ifndef IMA_MPP #ifndef NOPROT (void)PVMTMPNAMFUN(authfn); #ifdef IMA_OS2 if ((authfd = open(authfn, O_RDWR|O_CREAT|O_TRUNC, 0600)) == -1) { #else if ((authfd = open(authfn, O_RDONLY|O_CREAT|O_TRUNC, 0600)) == -1) { #endif pvmlogperror(authfn); pvmlogerror("pvmbeatask() can't creat t-auth file\n"); cc = PvmSysErr; goto bail2; } #endif /* * send first connect message to pvmd */ mxfersingle = 1; prver = TDPROTOCOL; pvm_pkint(&prver, 1, 1); pvm_pkstr(authfn); if ((cc = msendrecv(TIDPVMD, TM_CONNECT, SYSCTX_TM)) <= 0) goto bail; pvm_upkint(&prver, 1, 1); if (prver != TDPROTOCOL) { pvmlogprintf("pvmbeatask() t-d protocol mismatch (%d/%d)\n", TDPROTOCOL, prver); cc = PvmSysErr; goto bail; } pvm_upkint(&cc, 1, 1); if (!cc) { pvmlogerror("pvmbeatask() pvmd refuses connection\n"); goto bail; } /* * check our t-auth file; write in pvmd d-auth file */ #ifndef NOPROT #ifdef IMA_BEOLIN sleep(15); /* because of race condition over NFS--yuck! (PLS) */ #endif if ((cc = read(authfd, (char*)&cc, 1)) == -1) { pvmlogperror("pvmbeatask() read authfile"); cc = PvmSysErr; goto bail; } if (cc != 1) { pvmlogerror("pvmbeatask() pvmd didn't validate itself\n"); cc = PvmSysErr; goto bail; } (void)close(authfd); (void)unlink(authfn); pvm_upkstr(authfn); if ((authfd = open(authfn, O_WRONLY, 0)) == -1) { pvmlogperror(authfn); pvmlogerror("pvmbeatask() failed to open d-auth file\n"); authfn[0] = 0; cc = PvmSysErr; goto bail; } cc = write(authfd, authfn, 1); (void)close(authfd); if (cc != 1) { if (cc == -1) pvmlogperror(authfn); pvmlogerror("pvmbeatask() can't write d-auth file\n"); authfn[0] = 0; cc = PvmSysErr; goto bail; } authfd = -1; authfn[0] = 0; #endif /* * send second connect message to pvmd */ pvm_initsend(PvmDataFoo); pvm_pkint(&pvmmyupid, 1, 1); pvm_pkint(&cookie, 1, 1); if ( pvmmytaskname != NULL ) pvm_pkstr(pvmmytaskname); if ((cc = msendrecv(TIDPVMD, TM_CONN2, SYSCTX_TM)) <= 0) goto bail; pvm_upkint(&cc, 1, 1); if (!cc) { pvmlogerror("pvmbeatask() pvmd refuses connection\n"); goto bail; } #endif /* IMA_MPP */ #ifdef IMA_MPP pvm_mpp_beatask(&pvmmytid, &pvmmyptid, &outtid, &outctx, &outtag, &trctid, &trcctx,&trctag, &pvmudpmtu, &pvmschedtid, &topvmd); #else pvm_upkint(&pvmmytid, 1, 1); pvm_upkint(&pvmmyptid, 1, 1); pvm_upkint(&outtid, 1, 1); pvm_upkint(&outctx, 1, 1); pvm_upkint(&outtag, 1, 1); #endif if (!pvmtrc.outtid) { pvmtrc.outtid = outtid; pvmtrc.outctx = outctx; pvmtrc.outtag = outtag; pvmctrc.outtid = pvmtrc.outtid; pvmctrc.outctx = pvmtrc.outctx; pvmctrc.outtag = pvmtrc.outtag; } #ifndef IMA_MPP pvm_upkint(&trctid, 1, 1); pvm_upkint(&trcctx, 1, 1); pvm_upkint(&trctag, 1, 1); #endif if (!pvmtrc.trctid) { pvmtrc.trctid = trctid; pvmtrc.trcctx = trcctx; pvmtrc.trctag = trctag; pvmctrc.trctid = pvmtrc.trctid; pvmctrc.trcctx = pvmtrc.trcctx; pvmctrc.trctag = pvmtrc.trctag; new_tracer++; } if (p = getenv("PVMCTX")) pvmmyctx = pvmstrtoi(p); /* if (pvmmyctx == 0) pvmmyctx = pvm_newcontext(); */ /* get trace mask from envar or zero it */ if ( (p = getenv("PVMTMASK")) ) { if ( strlen(p) + 1 == TEV_MASK_LENGTH ) BCOPY(p, pvmtrc.tmask, TEV_MASK_LENGTH); else TEV_MASK_INIT(pvmtrc.tmask); } else { TEV_MASK_INIT(pvmtrc.tmask); if ( new_tracer ) need_trcinfo++; } BCOPY(pvmtrc.tmask, pvmctrc.tmask, TEV_MASK_LENGTH); /* get trace buffering from envar */ if ((p = getenv("PVMTRCBUF"))) pvmtrc.trcbuf = atoi( p ); else { pvmtrc.trcbuf = 0; if ( new_tracer ) need_trcinfo++; } pvmctrc.trcbuf = pvmtrc.trcbuf; /* get trace options from envar */ if ((p = getenv("PVMTRCOPT"))) pvmtrc.trcopt = atoi( p ); else { pvmtrc.trcopt = 0; if ( new_tracer ) need_trcinfo++; } pvmctrc.trcopt = pvmtrc.trcopt; #ifndef IMA_MPP pvm_upkint(&pvmudpmtu, 1, 1); #endif pvmfrgsiz = pvmudpmtu; #ifndef IMA_MPP pvm_upkint(&i, 1, 1); /* XXX data signature */ pvm_upkstr(buf); #ifdef IMA_BEOLIN if (gethostname(namebuf, sizeof(namebuf)-1) == -1) { pvmlogerror("pvmbeatask() can't gethostname()\n"); hex_inadport(buf, &pvmourinet); } else { /* got name, now get addr */ if (!(hostaddr = gethostbyname( namebuf ))) { pvmlogprintf( "pvmbeatask() can't gethostbyname() for %s\n", namebuf ); hex_inadport(buf, &pvmourinet); } else { /* got addr, now save it */ BCOPY( hostaddr->h_addr_list[0], (char*)&pvmourinet.sin_addr, sizeof(struct in_addr)); } } #else hex_inadport(buf, &pvmourinet); #endif pvmourinet.sin_family = AF_INET; pvmourinet.sin_port = 0; pvm_upkint(&pvmschedtid, 1, 1); #endif wait_init(pvmmytid, TIDLOCAL); BZERO(&minfo, sizeof(minfo)); minfo.src = -1; minfo.ctx = SYSCTX_TC; minfo.tag = TC_CONREQ; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_conreq); minfo.tag = TC_CONACK; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_conack); minfo.tag = TC_TASKEXIT; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_taskexit); minfo.tag = TC_NOOP; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_noop); minfo.tag = TC_SETTRACE; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_settrace); minfo.tag = TC_SETTRCBUF; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_settrcbuf); minfo.tag = TC_SETTRCOPT; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_settrcopt); minfo.tag = TC_SETTMASK; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_settmask); minfo.tag = TC_SIBLINGS; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_siblings); pvm_freebuf(pvm_setrbuf(rbf)); pvm_freebuf(pvm_setsbuf(sbf)); mxfersingle = 0; if ( need_trcinfo ) { rbf = pvm_setrbuf( 0 ); if ( pvm_recvinfo( PVMTRACERCLASS, 0, PvmMboxDefault ) > 0 ) { pvm_upkint(&trctid, 1, 1); pvm_upkint(&trcctx, 1, 1); pvm_upkint(&trctag, 1, 1); pvm_upkint(&outctx, 1, 1); /* unused here */ pvm_upkint(&outtag, 1, 1); /* unused here */ pvm_upkstr(tmask); pvm_upkint(&tbuf, 1, 1); pvm_upkint(&topt, 1, 1); if ( pvmtrc.trctid == trctid && pvmtrc.trcctx == trcctx && pvmtrc.trctag == trctag ) { if ( strlen(tmask) + 1 == TEV_MASK_LENGTH ) { BCOPY(tmask, pvmtrc.tmask, TEV_MASK_LENGTH); BCOPY(pvmtrc.tmask, pvmctrc.tmask, TEV_MASK_LENGTH); } pvmtrc.trcbuf = tbuf; pvmctrc.trcbuf = pvmtrc.trcbuf; pvmtrc.trcopt = topt; pvmctrc.trcopt = pvmtrc.trcopt; } pvm_freebuf(pvm_setrbuf(rbf)); } else pvm_setrbuf(rbf); } tev_init(); if (TEV_AMEXCL) { TEV_ENDEXCL; } return 0; bail: if (pvm_getrbuf() > 0) pvm_freebuf(pvm_getrbuf()); if (pvm_getsbuf() > 0) pvm_freebuf(pvm_getsbuf()); pvm_setrbuf(rbf); pvm_setsbuf(sbf); #ifndef IMA_MPP if (authfd != -1) (void)close(authfd); if (authfn[0]) (void)unlink(authfn); unmksocs(); #endif bail2: if (TEV_AMEXCL) { TEV_ENDEXCL; } return cc; } int pvmendtask() { if (pvmmytid != -1) { #if !defined(IMA_MPP) unmksocs(); #endif pvmmytid = -1; pvmtrc.trctid = 0; } return 0; } void check_for_exit(src) int src; { } /************************ ** Libpvm Functions ** ** ** ************************/ int pvm_getfds(fds) /* XXX this function kinda sucks */ int **fds; /* fd list return */ { static int *fdlist = 0; static int fdlen = 0; int cc; int nfds; struct ttpcb *pcbp; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_GETFDS,TEV_EVENT_ENTRY)) TEV_FIN; } if (!(cc = BEATASK)) { nfds = 1; for (pcbp = ttlist->tt_link; pcbp != ttlist; pcbp = pcbp->tt_link) if (pcbp->tt_state == TTOPEN || pcbp->tt_state == TTGRNWAIT) nfds++; if (fdlen < nfds) { fdlen = (nfds * 3) / 2 + 1; if (fdlist) fdlist = TREALLOC(fdlist, fdlen, int); else fdlist = TALLOC(fdlen, int, "fdlist"); } fdlist[0] = topvmd->tt_fd; nfds = 1; for (pcbp = ttlist->tt_link; pcbp != ttlist; pcbp = pcbp->tt_link) if (pcbp->tt_state == TTOPEN || pcbp->tt_state == TTGRNWAIT) fdlist[nfds++] = pcbp->tt_fd; *fds = fdlist; cc = nfds; } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_GETFDS,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); if (cc > 0) { TEV_PACK_INT( TEV_DID_FDS, TEV_DATA_ARRAY, (int *)fdlist, nfds, 1 ); } TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_getfds", cc) : cc); } int pvm_start_pvmd(argc, argv, block) int argc; /* number of args to pass to pvmd (>= 0) */ char **argv; /* args for pvmd or null */ int block; /* if true, don't return until add hosts are started */ { char *sfn; struct stat sb; int cc; char *fn; /* file to exec */ char **av; int pfd[2]; int n; FILE *ff; char buf[128]; #ifdef WIN32 char *pathending = "\\lib\\win32\\pvmd3.exe"; SECURITY_ATTRIBUTES saPipe; PROCESS_INFORMATION pi; STARTUPINFO si; /* for CreateProcess call */ HANDLE pvmdid; int i = 0; char cmd[256]; #endif TEV_DECLS; if (TEV_EXCLUSIVE) { if (pvmmytid != -1 && TEV_DO_TRACE(TEV_START_PVMD,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_BF, TEV_DATA_SCALAR, &block, 1, 1 ); TEV_PACK_STRING( TEV_DID_AS, TEV_DATA_ARRAY, argv, argc, 1 ); TEV_FIN; } } if (argc < 0 || !argv) argc = 0; #ifndef WIN32 if ((pvm_useruid = getuid()) == -1) { pvmlogerror("can't getuid()\n"); cc = PvmSysErr; goto bail; } #else if (!username) username = MyGetUserName(); #endif if (!(sfn = pvmdsockfile())) { pvmlogerror("pvm_start_pvmd() pvmdsockfile() failed\n"); cc = PvmSysErr; goto bail; } if (stat(sfn, &sb) != -1) { cc = PvmDupHost; goto bail; } #ifdef WIN32 cc = PvmSysErr; fn = malloc(128 * sizeof(char)); strcpy(fn,(char *) pvmgetroot()); strcat(fn,(char *) pathending); av = TALLOC(argc + 2, char *, "argv"); if (argc > 0) BCOPY((char *)&argv[0], (char *)&av[1], argc * sizeof(char*)); av[0] = fn; if (stat(av[0],&sb) == -1) { fprintf(stderr,"Couldn't find daemon executable !\n", "It should be stored in %PVM_ROOT%\\lib\\win32"); goto bail; } av[argc + 1] = 0; strcpy(cmd,""); strcat(cmd, "pvmd3.exe "); for (i=1;i <= argc ;i++) { strcat(cmd,av[i]); strcat(cmd," "); } av[argc + 1] = 0; /* pvmdid gives us back the process handle but it is an int anyway */ saPipe.nLength = sizeof(SECURITY_ATTRIBUTES); saPipe.lpSecurityDescriptor = NULL; saPipe.bInheritHandle = FALSE; memset(&si, 0, sizeof(si)); si.cb = sizeof(si); pvmdid = (HANDLE) CreateProcess( av[0], /* filename */ cmd, /* full command line for child */ /* for example : hostfiles */ NULL, /* process security descriptor */ NULL, /* thread security descriptor */ FALSE, /* inherit handles? */ DETACHED_PROCESS, /* creation flags */ NULL, /* inherited environment address */ NULL, /* startup dir */ /* NULL = start in current */ &si, /* pointer to startup info (input) */ &pi); /* pointer to process info (output) */ if (!pvmdid) { fprintf(stderr,"CreateProcess() failed \n"); fprintf(stderr,"enough memory ?\n"); goto bail; return 1; } CloseHandle(pi.hThread); CloseHandle(pi.hProcess); PVM_FREE(av); while (stat(sfn, &sb) == -1) Sleep(5000); /* what a hack */ #else #ifdef IMA_TITN if (socketpair(AF_UNIX, SOCK_STREAM, 0, pfd) == -1) #else if (pipe(pfd) == -1) #endif { cc = PvmSysErr; goto bail; } fn = pvmgetpvmd(); av = TALLOC(argc + 2, char *, "argv"); if (argc > 0) BCOPY((char *)&argv[0], (char *)&av[1], argc * sizeof(char*)); av[0] = fn; av[argc + 1] = 0; if (!fork()) { (void)close(pfd[0]); /* fork again so the pvmd is not the child - won't have to wait() for it */ if (!fork()) { if (pfd[1] != 1) dup2(pfd[1], 1); for (n = getdtablesize(); n-- > 0; ) if (n != 1) (void)close(n); (void)open("/dev/null", O_RDONLY, 0); /* should be 0 */ (void)open("/dev/null", O_WRONLY, 0); /* should be 2 */ (void)signal(SIGINT, SIG_IGN); (void)signal(SIGQUIT, SIG_IGN); #ifndef IMA_OS2 (void)signal(SIGTSTP, SIG_IGN); #endif execvp(av[0], av); } _exit(0); } (void)close(pfd[1]); (void)wait(0); PVM_FREE(av); if (!(ff = fdopen(pfd[0], "r"))) { cc = PvmSysErr; (void)close(pfd[0]); goto bail; } strcpy(buf, "PVMSOCK="); n = strlen(buf); if (!fgets(buf + n, sizeof(buf) - n - 1, ff)) { cc = PvmCantStart; fclose(ff); goto bail; } fclose(ff); if (strlen(buf + n) < 2) { cc = PvmCantStart; goto bail; } n = strlen(buf); if (buf[n - 1] == '\n') buf[n - 1] = 0; pvmputenv(STRALLOC(buf)); /* fprintf(stderr, "pvm_start_pvmd: %s\n", buf); */ #endif if (cc = BEATASK) goto bail; if (block) { struct pvmhostinfo *hip; int t = 1; pvm_config((int*)0, (int*)0, &hip); while ((cc = pvm_addhosts(&hip[0].hi_name, 1, (int*)0)) == PvmAlready) { pvmsleep(t); if (t < 8) t *= 2; } if (cc != PvmDupHost) goto bail; cc = BEATASK; } bail: if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_START_PVMD,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_start_pvmd", cc) : 0); } #ifndef PVM_SHMD int pvm_precv(tid, tag, cp, len, dt, rtid, rtag, rlen) int tid; int tag; void *cp; int len; int dt; int *rtid; int *rtag; int *rlen; { int nb, mc, src; int rbf; int cc = 0; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PRECV,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_RST, TEV_DATA_SCALAR, &tid, 1, 1 ); TEV_PACK_INT( TEV_DID_RMC, TEV_DATA_SCALAR, &tag, 1, 1 ); TEV_PACK_INT( TEV_DID_RCX, TEV_DATA_SCALAR, &pvmmyctx, 1, 1 ); ad = (long)cp; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &len, 1, 1 ); TEV_PACK_INT( TEV_DID_PDT, TEV_DATA_SCALAR, &dt, 1, 1 ); TEV_FIN; } } switch (dt) { case PVM_BYTE: len *= sizeof(char); break; case PVM_SHORT: case PVM_USHORT: len *= sizeof(short); break; case PVM_INT: case PVM_UINT: len *= sizeof(int); break; case PVM_LONG: case PVM_ULONG: len *= sizeof(long); break; case PVM_FLOAT: len *= sizeof(float); break; case PVM_CPLX: len *= sizeof(float) * 2; break; case PVM_DOUBLE: len *= sizeof(double); break; case PVM_DCPLX: len *= sizeof(double) * 2; break; case PVM_STR: cc = PvmNotImpl; break; default: cc = PvmBadParam; break; } if (!cc) { #if !defined(IMA_MPP) rbf = pvm_setrbuf(0); cc = pvm_recv(tid, tag); if (cc > 0) { pvm_bufinfo(cc, &nb, &mc, &src); if (rlen) *rlen = nb; if (nb < len) len = nb; if (rtag) *rtag = mc; if (rtid) *rtid = src; pvm_upkbyte((char *)cp, len, 1); pvm_freebuf(cc); cc = 0; } pvm_setrbuf(rbf); #else cc = pvm_mppprecv(tid, tag, cp ,len, dt, rtid, rtag, rlen); #endif } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PRECV,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); if ( cc < 0 ) nb = mc = src = -1; TEV_PACK_INT( TEV_DID_MNB, TEV_DATA_SCALAR, &nb, 1, 1 ); TEV_PACK_INT( TEV_DID_MC, TEV_DATA_SCALAR, &mc, 1, 1 ); TEV_PACK_INT( TEV_DID_MCX, TEV_DATA_SCALAR, &pvmmyctx, 1, 1 ); TEV_PACK_INT( TEV_DID_SRC, TEV_DATA_SCALAR, &src, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_precv", cc); return cc; } #else /* PVM_SHMD */ /* Do the PVM_SHMD version of precv */ int pvm_precv(tid, tag, cp, len, dt, rtid, rtag, rlen) int tid; int tag; void *cp; int len; int dt; int *rtid; int *rtag; int *rlen; { return (shmd_pvm_precv (tid, tag, cp, len, dt, rtid, rtag, rlen)); } #endif /* PVM_SHMD */ #ifndef PVM_SHMD int pvm_psend(tid, tag, cp, len, dt) int tid; int tag; void *cp; int len; int dt; { int sbf; int cc = 0; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PSEND,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_DST, TEV_DATA_SCALAR, &tid, 1, 1 ); TEV_PACK_INT( TEV_DID_MC, TEV_DATA_SCALAR, &tag, 1, 1 ); TEV_PACK_INT( TEV_DID_MCX, TEV_DATA_SCALAR, &pvmmyctx, 1, 1 ); ad = (long)cp; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &len, 1, 1 ); TEV_PACK_INT( TEV_DID_PDT, TEV_DATA_SCALAR, &dt, 1, 1 ); TEV_FIN; } } switch (dt) { case PVM_BYTE: len *= sizeof(char); break; case PVM_SHORT: case PVM_USHORT: len *= sizeof(short); break; case PVM_INT: case PVM_UINT: len *= sizeof(int); break; case PVM_LONG: case PVM_ULONG: len *= sizeof(long); break; case PVM_FLOAT: len *= sizeof(float); break; case PVM_CPLX: len *= sizeof(float) * 2; break; case PVM_DOUBLE: len *= sizeof(double); break; case PVM_DCPLX: len *= sizeof(double) * 2; break; case PVM_STR: cc = PvmNotImpl; break; default: cc = PvmBadParam; break; } #if !defined(IMA_MPP) if (!cc) { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataInPlace)); pvm_pkbyte((char *)cp, len, 1); if ((cc = pvm_send(tid, tag)) > 0) cc = 0; pvm_freebuf(pvm_setsbuf(sbf)); } #else cc = pvm_mpppsend((char *) cp, len, tid, tag); #endif if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PSEND,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_psend", cc); return cc; } #else /* i.e. PVM_SHMD */ int pvm_psend(tid, tag, cp, len, dt) int tid; int tag; void *cp; int len; int dt; { /* Go do the shmd thing instead */ return (shmd_pvm_psend(tid, tag, cp, len, dt)); } #endif /* PVM_SHMD */ /* ----- ogm_complete ------ */ int ogm_complete( ogmlist ) struct msgid **ogmlist; { struct msgid *mp, *oldmp, *head; #if defined(IMA_MPP) if (!(mp = *ogmlist) ) return TRUE; /* there is nothing to check */ /* go through the list message ids. checking if the message has complete. If the list is empty at the end, then return that message has finished */ head = mp; mp = mp->ms_link; while (mp != head) { if ((*mp->mfunc->msgdone)(0, &(mp->id), mp->info)) { mp = mp->ms_link; oldmp = mp->ms_rlink; LISTDELETE(oldmp,ms_link, ms_rlink) msgid_free(oldmp); } else mp = mp->ms_link; } /* mp now points to the head of the list */ if ((*mp->mfunc->msgdone)(0, &(mp->id), mp->info)) { if (mp->ms_link == mp) /* the only one left */ { msgid_free(mp); *ogmlist = (struct msgid *) NULL; return TRUE; } else { mp = mp->ms_link; oldmp = mp->ms_rlink; LISTDELETE(oldmp, ms_link, ms_rlink); msgid_free(oldmp); *ogmlist = mp; /* new head of the message id list */ } } return FALSE; #else return TRUE; /* for workstations, the write is sychronous */ #endif } ./pvm3/src/lpvmcat.c0100644007401100000360000002662107240353276013520 0ustar kohlgopher static char rcsid[] = "$Id: lpvmcat.c,v 1.14 2001/02/07 23:14:06 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * lpvmcat.c * * Child task output collection. * * $Log: lpvmcat.c,v $ * Revision 1.14 2001/02/07 23:14:06 pvmsrc * First Half of CYGWIN Check-ins... * (Spanker=kohl) * * Revision 1.13 2000/02/16 21:59:43 pvmsrc * Fixed up #include stuff... * - use for IMA_TITN... * - #include before any NEEDMENDIAN #includes... * (Spanker=kohl) * * Revision 1.12 1999/11/08 17:44:31 pvmsrc * SGI compiler cleanup. * (Spanker=kohl) * * Revision 1.11 1999/07/08 18:59:56 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.10 1998/11/20 20:04:02 pvmsrc * Changes so that win32 will compile & build. Also, common * Changes so that compiles & builds on NT. Also * common source on win32 & unix. * (Spanker=sscott) * * Revision 1.9 1998/01/12 21:13:24 pvmsrc * Replaced inline constants with new task output op defines. * - TO_NEW == -2. * - TO_SPAWN == -1. * - TO_EOF == 0. * (Spanker=kohl) * * Revision 1.8 1997/12/31 20:50:11 pvmsrc * Cleaned Up System Message Handlers. * - current send / recv buffers now saved before invocation of * message handler functs. * - removed manual rbf = setrbuf(mid) saving & resetting in * handlers... * (Spanker=kohl) * * Revision 1.7 1997/06/27 17:32:24 pvmsrc * Updated for WIN32 header files & Authors. * * Revision 1.6 1997/06/12 20:10:40 pvmsrc * Made sure all communications for TC_* task control messages * use the SYSCTX_TC system context. * - some messages being sent in default context... D-Oh... * * Revision 1.5 1997/04/07 21:09:20 pvmsrc * pvm_addmhf() - new paramter interface * * Revision 1.4 1997/01/28 19:26:24 pvmsrc * New Copyright Notice & Authors. * * Revision 1.3 1996/10/25 13:57:23 pvmsrc * Replaced old #includes for protocol headers: * - , "ddpro.h", "tdpro.h" * With #include of new combined header: * - * * Revision 1.2 1996/10/24 21:18:29 pvmsrc * Moved #include "global.h" to end of #include's for typing. * Added #include of new "lpvm.h" in place of explicitly extern-ed * globals... * * Revision 1.1 1996/09/23 23:44:13 pvmsrc * Initial revision * * Revision 1.7 1995/11/02 16:08:12 manchek * added NEEDSENDIAN switch * * Revision 1.6 1995/07/28 16:04:05 manchek * switch endian includes on flag, not arch name * * Revision 1.5 1995/05/17 16:17:24 manchek * fixed buf in pvmclaimo, copying one byte too few * * Revision 1.4 1994/12/20 16:35:57 manchek * added ShowTids option * * Revision 1.3 1994/11/07 21:34:49 manchek * cast message tag for comparison as int * * Revision 1.2 1994/10/15 19:10:08 manchek * don't segfault if we get a TC_OUTPUT message and pvm_catchout never called * * Revision 1.1 1994/06/03 20:38:16 manchek * Initial revision * */ #include #ifdef NEEDMENDIAN #include #include #endif #ifdef NEEDENDIAN #include #endif #ifdef NEEDSENDIAN #include #endif #include #if defined(WIN32) || defined(CYGWIN) #include "..\xdr\types.h" #include "..\xdr\xdr.h" #else #include #include #endif #ifdef SYSVSTR #include #define CINDEX(s,c) strchr(s,c) #else #include #define CINDEX(s,c) index(s,c) #endif #include #include #include "pvmalloc.h" #include "listmac.h" #include "bfunc.h" #include "tvdefs.h" #include "lpvm.h" #include #include "tevmac.h" #include "global.h" /* * used to collect output from a task */ struct tobuf { struct tobuf *o_link, *o_rlink; /* chain of all tasks in job */ int o_tid; /* task id */ int o_len; /* length of buf */ char *o_buf; /* buffered partial line */ int o_maxl; /* space in buf */ int o_flag; /* task state */ #define GOTSPAWN 1 #define GOTEOF 2 #define GOTBOTH (GOTSPAWN|GOTEOF) #define TASKSTATE (GOTSPAWN|GOTEOF) }; /*************** ** Globals ** ** ** ***************/ /*************** ** Private ** ** ** ***************/ static struct tobuf *tobuflist = 0; static FILE *outlogff = 0; /************************** ** Internal Functions ** ** ** **************************/ static int pvmclaimo(); static int pvmflusho(); static int tobuf_init() { int i; struct pvmminfo minfo; int ictx; if (!tobuflist) { tobuflist = TALLOC(1, struct tobuf, "obuf"); BZERO((char*)tobuflist, sizeof(struct tobuf)); tobuflist->o_link = tobuflist->o_rlink = tobuflist; i = pvm_setopt(PvmResvTids, 1); BZERO(&minfo, sizeof(minfo)); minfo.src = -1; minfo.ctx = SYSCTX_TC; minfo.tag = TC_OUTPUT; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvmclaimo); minfo.tag = TC_OUTPUTX; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvmflusho); ictx = pvm_setcontext(SYSCTX_TC); pvm_notify(PvmTaskExit, TC_OUTPUTX, 1, &pvmmytid); pvm_setcontext(ictx); pvm_setopt(PvmResvTids, i); } return 0; } static struct tobuf * tobuf_new(tid) int tid; { struct tobuf *op = tobuflist->o_link; struct tobuf *op2; while (op != tobuflist && op->o_tid < tid) op = op->o_link; if (op->o_tid != tid) { op2 = TALLOC(1, struct tobuf, "tobuf"); BZERO((char*)op2, sizeof(struct tobuf)); op2->o_tid = tid; LISTPUTBEFORE(op, op2, o_link, o_rlink); op = op2; } return op; } static int tobuf_free(op) struct tobuf *op; { LISTDELETE(op, o_link, o_rlink); if (op->o_buf) PVM_FREE(op->o_buf); PVM_FREE(op); return 0; } static struct tobuf * tobuf_find(tid) int tid; { struct tobuf *op = tobuflist->o_link; while (op != tobuflist && op->o_tid < tid) op = op->o_link; if (op->o_tid == tid) return op; return (struct tobuf*)0; } /* pvmflusho() * * Called by pvm_exit() to make sure all task output is flushed. * If outlogff is nonzero, make sure all child tasks have exited * else just toss the output. */ static int pvmflusho() { struct tobuf *op; if (outlogff) { if (tobuflist && tobuflist->o_link != tobuflist) { if (pvmshowtaskid) pvmlogerror("child task(s) still running. waiting...\n"); while (tobuflist->o_link != tobuflist) { /* XXX mroute() does return after ctrl messages received */ if ( mroute(0, 0, 0, (struct timeval *)0) < 0 ) break; } } pvm_catchout((FILE *)0); } if (tobuflist) { while (tobuflist->o_link != tobuflist) tobuf_free(tobuflist->o_link); PVM_FREE(tobuflist); tobuflist = 0; } return 0; } /* pvmclaimo() * * We get output from a child* task (because we called pvm_catchout()) * * TC_OUTPUT() { * int tid // of source task * int length // of output * char output[length] // characters printed * } */ static int pvmclaimo(mid) int mid; { int tid; /* task */ int n; /* length or event code */ char *p; int ptid; struct tobuf *op; /* if (TRACE) { checktrace(jp, cc, len, cod, src); return 0; } */ pvm_upkint(&tid, 1, 1); pvm_upkint(&n, 1, 1); if (!tobuflist) { pvmlogprintf("pvmclaimo() message from task t%x\n", tid); goto done; } if (n > 0) { /* output printed by task */ if (!(op = tobuf_find(tid))) { pvmlogprintf("pvmclaimo() bogus message, no task t%x\n", tid); goto done; } if (n + op->o_len >= op->o_maxl) { op->o_maxl = op->o_len + n + 1; /* printf("REALLOC t%x buf to %d\n", tid, op->o_maxl); */ if (op->o_buf) op->o_buf = TREALLOC(op->o_buf, op->o_maxl, char); else op->o_buf = TALLOC(op->o_maxl, char, ""); } pvm_upkbyte(op->o_buf + op->o_len, n, 1); op->o_buf[op->o_len + n] = 0; /* printf("UNPACK t%x {%s}\n", tid, op->o_buf + op->o_len); */ p = op->o_buf + op->o_len; op->o_len += n; /* XXX would be more efficient to remove all lines before copying remainder */ while (p = CINDEX(p, '\n')) { *p++ = 0; if (outlogff) if (pvmshowtaskid) fprintf(outlogff, "[t%x] %s\n", tid, op->o_buf); else fprintf(outlogff, "%s\n", op->o_buf); op->o_len -= p - op->o_buf; BCOPY(p, op->o_buf, op->o_len + 1); p = op->o_buf; } } else { switch (n) { case TO_EOF: /* EOF from task */ if (!(op = tobuf_find(tid))) { pvmlogprintf("pvmclaimo() bogus message, no task t%x\n", tid); goto done; } if (op->o_len > 0) { if (outlogff) if (pvmshowtaskid) fprintf(outlogff, "[t%x] %s\n", tid, op->o_buf); else fprintf(outlogff, "%s\n", op->o_buf); op->o_len = 0; } op->o_flag |= GOTEOF; if ((op->o_flag & TASKSTATE) == GOTBOTH) { if (outlogff && pvmshowtaskid) fprintf(outlogff, "[t%x] EOF\n", tid); tobuf_free(op); } break; case TO_SPAWN: /* spawn creating new task */ if (!(op = tobuf_find(tid))) { op = tobuf_new(tid); if (outlogff && pvmshowtaskid) fprintf(outlogff, "[t%x] BEGIN\n", tid); } op->o_flag |= GOTSPAWN; if ((op->o_flag & TASKSTATE) == GOTBOTH) { if (outlogff && pvmshowtaskid) fprintf(outlogff, "[t%x] EOF\n", tid); tobuf_free(op); } break; case TO_NEW: /* new task starting up */ if (!(op = tobuf_find(tid))) { op = tobuf_new(tid); if (outlogff && pvmshowtaskid) fprintf(outlogff, "[t%x] BEGIN\n", tid); } break; default: pvmlogprintf("pvmclaimo() bogus message from task t%x\n", tid); break; } } done: pvm_freebuf(mid); return 0; } /************************** ** Exported Functions ** ** ** **************************/ int tobuf_dump() { struct tobuf *op; if (tobuflist) for (op = tobuflist->o_link; op != tobuflist; op = op->o_link) { printf("tobuf_dump() t%x\n", op->o_tid); } else printf("tobuf_dump() tobuflist null\n"); return 0; } /************************ ** Libpvm Functions ** ** ** ************************/ /* pvm_catchout() * * Log output of tasks spawned by us to file. */ int pvm_catchout(ff) FILE *ff; { if (ff) { tobuf_init(); pvm_setopt(PvmOutputTid, pvm_mytid()); pvm_setopt(PvmOutputContext, (int)SYSCTX_TC); pvm_setopt(PvmOutputCode, (int)TC_OUTPUT); outlogff = ff; } else { pvm_setopt(PvmOutputCode, pvm_getopt(PvmSelfOutputCode)); pvm_setopt(PvmOutputContext, pvm_getopt(PvmSelfOutputContext)); pvm_setopt(PvmOutputTid, pvm_getopt(PvmSelfOutputTid)); outlogff = 0; } return PvmOk; } ./pvm3/src/lpvmgen.c0100644007401100000360000033051510014453371013510 0ustar kohlgopher static char rcsid[] = "$Id: lpvmgen.c,v 1.99 2004/02/17 18:01:29 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * lpvmgen.c * * Libpvm generic functions. * * $Log: lpvmgen.c,v $ * Revision 1.99 2004/02/17 18:01:29 pvmsrc * False alarm, removed debug output for AMD64. * (Spanker=kohl) * * Revision 1.98 2004/02/09 17:21:13 pvmsrc * Oops... typo... * (Spanker=kohl) * * Revision 1.97 2004/02/09 17:17:01 pvmsrc * Added pvmlogperror debug output for AMD64... * - the arch that wouldn't die... er, run without seg faulting... :) * (Spanker=kohl) * * Revision 1.96 2004/02/03 21:40:57 pvmsrc * Added check for NULL strerror() return... * - to chase down AMD64 problem... * (Spanker=kohl) * * Revision 1.95 2004/01/14 19:12:34 pvmsrc * Added (char *) cast to strerror() assignment... * (Spanker=kohl) * * Revision 1.94 2004/01/14 18:50:56 pvmsrc * Added new AIX5* arches. * (Spanker=kohl) * * Revision 1.93 2001/09/26 23:35:43 pvmsrc * Removed stuffing of PVM_VMID env var when spawning remote tasks. * - first, each host can have it's own local vmid (why not?), * so we shouldn't stomp that on the spawn. * - second, each local pvmd sets its PVM_VMID env var on startup * if the option is passed to it, so there's no need to * additionally set the vmid on the spawn. * (Spanker=kohl) * * Revision 1.92 2001/09/26 21:22:34 pvmsrc * Added Handling for Optional Virtual Machine ID. * - append PVM_VMID env var to spawn env for tasks (if set). * (Spanker=kohl) * * Revision 1.91 2001/06/28 16:45:29 pvmsrc * D-Oh! Better set context around message handler functions. * - if message comes in with a particular context, reply should * probably be in same context! :-] * (Spanker=kohl) * * Revision 1.90 2001/05/11 18:58:11 pvmsrc * Added use of new "USESTRERROR" define. * - uses strerror() function instead of sys_errlist/sys_nerr * (which aren't public globals on some new operating systems). * (Spanker=kohl) * * Revision 1.89 2001/02/07 23:14:06 pvmsrc * First Half of CYGWIN Check-ins... * (Spanker=kohl) * * Revision 1.88 2000/06/15 17:51:50 pvmsrc * Fixed bug in WIN32 direct routing. * - stupid #endif in the wrong place, pvm_fd_add() call whacked. * - turned back on direct routing default and setopt. * (Spanker=kohl) * * Revision 1.87 2000/02/17 23:12:12 pvmsrc * *** Changes for new BEOLIN port *** * - MPP-like, similar to SP2, etc. * - submitted by Paul Springer . * - format-checked & cleaned up by Jeembo... :-) * (Spanker=kohl) * * Revision 1.86 2000/02/16 21:59:43 pvmsrc * Fixed up #include stuff... * - use for IMA_TITN... * - #include before any NEEDMENDIAN #includes... * (Spanker=kohl) * * Revision 1.85 1999/11/08 17:44:32 pvmsrc * SGI compiler cleanup. * (Spanker=kohl) * * Revision 1.84 1999/10/27 18:49:00 pvmsrc * Fixed (hopefully) the function header declaration for pvm_recvf(). * - should work on all platforms now (using __ProtoGlarp__())... * (Spanker=kohl) * * Revision 1.83 1999/07/08 18:59:56 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.82 1999/03/12 20:55:33 pvmsrc * Don't allow direct routing in WIN32 until we fix it. Shit. * (Spanker=kohl) * * Revision 1.81 1999/01/29 17:02:50 pvmsrc * Implemented pvm_archcode() for 3.4 data signature handling. * - backwards compat. * (Spanker=kohl) * * Revision 1.80 1999/01/14 19:10:25 pvmsrc * More mbox fixes: * - make sure pvm_errno gets set in mbox and old insert/lookup/delete * calls, even if lpvmerr() isn't called because of an accepted * error code. * - modified old 3.3 interface to create persistent mboxes... * - gutted pvm_lookup() to snag the returned index for -1/firstavail * queries, as pvm_recvinfo() doesn't ever return the index value. * D-Oh... Too late to fix it now... * (Spanker=kohl) * * Revision 1.79 1999/01/13 00:04:46 pvmsrc * Filled in backwards compat guts: * - to pvm_insert(), pvm_lookup() & pvm_delete(). * - use mbox stuff, no more #ifdef PVM33COMPAT... * - modified mbox pvm_putinfo() stuff to pass in -1 instead of 0 * for the internal index value... * (Spanker=kohl) * * Revision 1.78 1998/11/20 20:04:04 pvmsrc * Changes so that win32 will compile & build. Also, common * Changes so that compiles & builds on NT. Also * common source on win32 & unix. * (Spanker=sscott) * * Revision 1.77 1998/10/12 21:16:28 pvmsrc * Damn. Typo - should be pvmsbuf->m_mid, not pvmsbuf... D-Oh! * (Spanker=kohl) * * Revision 1.76 1998/10/12 21:08:57 pvmsrc * Fixed pvmtrcsbfsave fiasco in pvm_send/mcast(). * - as used for message number of bytes trace data. * - if not using PvmTraceFull tracing option, pvmtrcsbfsave will not * be set / swapped with pvmsbuf... * - check for non-NULL pvmtrcsbfsave, if not use pvmsbuf instead. * (Spanker=kohl) * * Revision 1.75 1998/10/02 15:44:01 pvmsrc * Single source code merge of Win32 and Unix code. * (Spanker=sscott) * * Revision 1.74 1998/09/02 14:07:05 pvmsrc * Fixed bug in pvm_siblings(). * - incorrect handling of PvmParentNotSet case... * (Spanker=kohl) * * Revision 1.73 1998/08/27 15:16:53 pvmsrc * Plugged memory leak in pvm_recvinfo(). * - pvmrbuf is freed O.K., but the wrapper message from the pvmd * (the one with the mbox message in it :-) was not being freed. * (Spanker=kohl) * * Revision 1.72 1998/06/26 15:26:28 pvmsrc * Fixed pvm_trecv(): * - if timeout is 0, could return without ever probing... * - make sure mroute() is called at least once before timing * out in the 0 case. * (Spanker=kohl) * * Revision 1.71 1998/02/23 22:51:33 pvmsrc * Added AIX4SP2 stuff. * (Spanker=kohl) * * Revision 1.70 1998/01/28 20:08:56 pvmsrc * Added new -DSYSERRISCONST define. * - for const char *sys_errlist... * (Spanker=kohl) * * Revision 1.69 1998/01/28 19:13:52 pvmsrc * Added new IMA_LINUXHPPA to #if cases... * (Spanker=kohl) * * Revision 1.68 1997/12/31 22:14:25 pvmsrc * Renamed TEV_REMOVE -> TEV_DELINFO. D-Oh. * (Spanker=kohl) * * Revision 1.67 1997/12/31 20:51:29 pvmsrc * Added saving / resetting of current send / recv buffer around mhf. * - so each message handler doesn't have to do it. * - while we're at it, might as well set rbuf to mhf message, too. * Removed TEV_DID_MRF trace event element for pvm_addmhf() entry event. * - seemed like a good idea at the time, but no way to avoid the * compiler warnings on SGIs when trying to cast funct ptr to * int ptr for packing into trace message... :-Q * (Spanker=kohl) * * Revision 1.66 1997/12/29 19:41:21 pvmsrc * Changed char *em to const char *em. * For Redhat 4.2/5.0 compatibility under LINUX. * (Spanker=phil) * * Revision 1.65 1997/12/23 20:23:53 pvmsrc * Added new TEV_MHF_INVOKE trace event. * - include message handler src/tag/ctx settings. * - include actual message bufid, len, and src/tag/ctx. * - use new TEV_PUSHTOP, TEV_AMPUSHED and TEV_POPTOP macros to * fake top level tracing for PVM calls in message handler. * (Spanker=kohl) * * Revision 1.64 1997/12/17 22:16:51 pvmsrc * Added tracing instrumentation to pvm_addmhf() and pvm_delmhf(). * - rewrote as necessary to capture return code. * (Spanker=kohl) * * Revision 1.63 1997/11/04 23:20:39 pvmsrc * Added IMA_LINUXALPHA to const char * error log stuff. * (Spanker=kohl) * * Revision 1.62 1997/10/24 15:17:52 pvmsrc * Added TEV_DID_RCX to trace events for Receive Message Context. * - in pvm_recv(), pvm_trecv(), pvm_nrecv(), and pvm_precv(). * (Spanker=kohl) * * Revision 1.61 1997/10/24 14:29:27 pvmsrc * Added TEV_DID_MCX / pvmmyctx trace event info to: * - pvm_send(), pvm_mcast(), pvm_recv(), pvm_trecv(), pvm_nrecv(). * - pvm_psend(), pvm_precv(). * (Spanker=kohl) * * Revision 1.60 1997/09/22 21:13:30 pvmsrc * Added new pvmsettaskname() linkage (for shell-spawned tasks only!). * - call pvmsettaskname() before joining PVM, sends task name * (stored in new char *pvmmytaskname global) to pvmd in * TM_CONN2 message. * - appears in trace events and console ps. * (Spanker=kohl) * * Revision 1.59 1997/09/10 21:36:12 pvmsrc * changing socket startup to pvmbeatask --> pvm_parent did not * enroll correctly. Markus * (Spanker=fischer) * * Revision 1.58 1997/08/29 13:35:10 pvmsrc * OS2 Port Submitted by Bohumir Horeni, horeni@login.cz. * (Spanker=kohl) * * Revision 1.57 1997/08/27 20:19:44 pvmsrc * Fixed bug in tracing - message number of bytes for pvm_send/mcast(). * - "pvmsbuf" is really "pvmtrcbuf" inside tracing scope... D-Oh! * - use saved "pvmtrcsbfsave" buffer id for pvm_bufinfo() instead. * (Spanker=kohl) * * Revision 1.56 1997/08/25 21:46:21 pvmsrc * Fixed call to enc_trc_fin() in pvm_send(). * - for user-defined trace events, pvmsbuf arg was missing... * (Spanker=kohl) * * Revision 1.55 1997/08/06 22:43:16 pvmsrc * Added new SGI6 and SGIMP6 arches. * * Revision 1.54 1997/07/21 19:08:31 pvmsrc * Well slap SScott around the next time you see him. :-) * - fixed pvm_delmhf() to handle boundary case where deleted * entry is at end of list (can't copy last entry to the * deleted slot if you're already there... :-). * - fixed up mesg_input() to check for wildcarded handler tag * like everything else... * * Revision 1.53 1997/07/08 15:29:53 pvmsrc * Don't let routing option be changed on PGON and SP2MPI. * * Revision 1.52 1997/06/27 21:02:29 pvmsrc * removed working debug statments from pvm_delmhf() * * Revision 1.51 1997/06/27 18:04:58 pvmsrc * Integrated WIN32 changes. * * Revision 1.50 1997/06/26 19:38:05 pvmsrc * pvm_siblings now waits for siblings to come from spawning parent * even when PvmNoParent is set. * * Also, if a task is run from the command line, pvm_siblings returns * a sibling set of size 1 and with tid = pvmmytid * * Revision 1.49 1997/06/26 15:03:03 pvmsrc * Awwwwwww Crap. Beat me with a shovel. F---ing Typo. * * Revision 1.48 1997/06/26 14:56:48 pvmsrc * Forget something Steve? D-Oh, D-Oh, D-Oh... * - how about setting the handles[].f field when you create a * message handler -- it comes in handy when you actually * want to HANDLE a message... :-/~ * * Revision 1.47 1997/06/26 13:41:34 pvmsrc * Added default return value to pvm_delmhf(). * - SGI compiler warning (and incorrect (missing) return case, * PvmOk). * - text formatting... (broke up SScott's 200 character long lines :) * * Revision 1.46 1997/06/25 18:02:58 pvmsrc * pvm_addmhf() complete rewrite * pvm_delmhf() complete rewrite * pvm_exit() reversed removal sequence of message handlers. * pvmdisplaymhfinfo() new internal function for testing message handlers * * Revision 1.45 1997/06/23 18:36:04 pvmsrc * Oops... pvm_reg_rm() should add itself to PVMRMCLASS. * - not PVMTASKERCLASS... typo... D-Oh... * * Revision 1.44 1997/06/12 20:10:41 pvmsrc * Made sure all communications for TC_* task control messages * use the SYSCTX_TC system context. * - some messages being sent in default context... D-Oh... * * Revision 1.43 1997/05/21 16:01:47 pvmsrc * Updated ifdefs to include AIX4MP arch type. * * Revision 1.42 1997/05/07 21:22:09 pvmsrc * AAAIIIEEEEEEEEE!!!! * - removed all static-limited string unpacking: * * replaced with use of: * upkstralloc() / PVM_FREE() (for pvmd stuff). * new pvmupkstralloc() / PVM_FREE() (for lpvm stuff). * * manual allocation of local buffers for sprintf() & packing. * * alternate static string arrays to replace fixed-length cases. * * I hope this shit works... :-Q * * Revision 1.41 1997/05/02 19:48:06 pvmsrc * Fix precv on SP2MPI -- needed to be added to an ifdef. * * Revision 1.40 1997/05/02 14:54:16 pvmsrc * Implemented guts of pvm_getmboxinfo(): * - user library side sends pattern & receives back / allocs array. * - at pvmd side mb_names() searches class list for matching pattern, * count up # of entries, and pack up struct info. * (Note: does not yet use GNU regex stuff...) * * Revision 1.39 1997/05/02 13:44:32 pvmsrc * Support for SP2MPI. Comment references to mpierrcode. * * Revision 1.38 1997/05/01 20:17:39 pvmsrc * Renamed TEV_MBOXINFO -> TEV_GETMBOXINFO. * * Revision 1.37 1997/04/30 21:26:02 pvmsrc * SGI Compiler Warning Cleanup. * * Revision 1.36 1997/04/24 21:05:54 pvmsrc * Short circuiting on pvm_precv for mpps * * Revision 1.35 1997/04/21 14:46:28 pvmsrc * pvm_addmhf() ifdefs for SCO * * Revision 1.34 1997/04/17 12:54:25 pvmsrc * rename of pvm_mboxinfo() to include word "get" * * Revision 1.33 1997/04/14 14:28:42 pvmsrc * pvm_exit() now removes all message handlers * * Revision 1.32 1997/04/10 20:32:46 pvmsrc * Typo... * * Revision 1.31 1997/04/10 20:14:20 pvmsrc * (Partially) replaced pvm_getnames() with new pvm_mboxinfo(). * - needs actual implementation details... ha ha ha... * * Revision 1.30 1997/04/09 20:10:52 pvmsrc * Memory spank - freeing static mem... D-Oh... * * Revision 1.29 1997/04/09 19:37:58 pvmsrc * Added class name and index args to pvmreset() routine: * - allow systematic elimination of leftover persistents... * - heh, heh, heh... * In dm_db(), check for name (class) and req (index) match * for TMDB_RESET case (""/-1 for all, resp). * * Revision 1.28 1997/04/09 18:31:13 pvmsrc * Added "killtasks" arg tp pvmreset(): * - allow for only resetting of mboxes, w/o task kill... * - otherwise, too painful to clean up mbox db... * * Revision 1.27 1997/04/08 17:23:31 pvmsrc * Damn, Damn, Damn... * - pvmreset() must be in library side only, pvmds use different * message buffer mgt, packing and sending routines... :-Q * * Revision 1.26 1997/04/07 21:07:57 pvmsrc * pvm_addmhf() - new paramter interface * * pvm_addmhf() and pvm_delmhf() now maintain a "free-list" from which * new entries are first filled before allocating new space. * * Revision 1.25 1997/04/07 19:55:26 pvmsrc * Nope, changed my mind. pvm_getnoresets() saves tidlist in static, * reuse allocated mem on next call, a la pcm_tasks()... * * Revision 1.24 1997/04/07 19:39:58 pvmsrc * Plugged memory leak in pvm_getnoresets(). * - if no return tids ptr provided, just free tidlist array. * * Revision 1.23 1997/04/04 15:44:35 pvmsrc * New pvm_addmhf() and pvm_delmhf() * * Revision 1.22 1997/04/03 19:25:02 pvmsrc * Added context for TM_xxx messages SM_xxx messages use the * PvmBaseContext for compatibility * * Revision 1.21 1997/04/01 21:28:14 pvmsrc * Damn Damn Damn. * - pvm_recvinfo() returns a bufid, not an index. Damn. * * Revision 1.20 1997/03/31 21:39:08 pvmsrc * *** Changed syntax of mbox routines. * - pvm_putinfo() dropped index arg, changed flags semantics. * - pvm_getinfo() -> pvm_recvinfo(), a la pvm_recv()... * - added PvmMboxDefault for flags usage. * - changed routines & calls. * - extension of sscott submission... * * Revision 1.19 1997/03/27 19:56:15 pvmsrc * In pvm_reg_tracer(): * - added packing of other assundry trace settings in tracer mailbox. * - for shell-spawned tasks to get tmask, topt, etc... * * Revision 1.18 1997/03/06 21:07:38 pvmsrc * - added include to pvmmimd.h * - test properly on mpps when trying to set pvmfrgsize * * Revision 1.17 1997/03/04 22:47:25 pvmsrc * Added stuffing of message mailboxes for: * - Resource Managers, Hosters, Taskers and Tracers. * - done by registered task, for auto-cleanup on exit. * - delete info on unregister... * * Revision 1.16 1997/02/17 20:50:58 pvmsrc * D-Oh! D-Oh! D-Oh! A stupid Jim typo: * * PvmFirstAvail & PvmLock -> PvmFirstAvail | PvmLock. * * D-Oh! * * Revision 1.15 1997/02/17 19:43:41 pvmsrc * Added check in pvm_setopt() / PvmNoReset for pvmmytid > 0. * * Revision 1.14 1997/02/17 18:47:26 pvmsrc * Oops... must pass ptr to tids array for pvm_getnoresets(). * * Revision 1.13 1997/02/17 16:29:44 pvmsrc * Added new pvm_getnoresets() routine. * * Revision 1.12 1997/02/13 23:35:44 pvmsrc * Added new PvmNoReset setopt/getopt option. * - added new pvmnoreset, pvmnoresetindex globals in lpvm.[ch]. * - to set use pvm_putinfo() -> PVMNORESETCLASS first avail w/lock, * save index in pvmnoresetindex. * - to unset use pvm_delinfo(). * * Revision 1.11 1997/02/13 15:10:43 pvmsrc * Fixed Bob Bug in pvm_exit(): * - "=" -> "=="... Ooooo... * * Revision 1.10 1997/01/28 19:26:26 pvmsrc * New Copyright Notice & Authors. * * Revision 1.9 1996/12/19 19:59:15 pvmsrc * Fixed pvm log messages for pvm_tc_*() routines. * - stuff no longer in pvmmctl()... * * Revision 1.8 1996/12/19 15:06:45 pvmsrc * Added missing decls for error globals (#ifndef HASERRORVARS). * - errno, sys_errlist[] & sys_nerr. * * Revision 1.7 1996/12/18 22:27:46 pvmsrc * Extracted duplicate versions of routines from lpvm/mimd/shmem.c, * inserted into shared lpvmgen.c: * - pvmbailout(). * - pvmlogerror(). * - vpvmlogprintf(), pvmlogprintf(). (hope these work on MPP & shmem) * - pvmlogperror(). * * Revision 1.6 1996/10/31 20:44:20 pvmsrc * Added a static char version variable in pvm_version() to avoid * stack corruption. * * Revision 1.5 1996/10/25 13:57:24 pvmsrc * Replaced old #includes for protocol headers: * - , "ddpro.h", "tdpro.h" * With #include of new combined header: * - * * Revision 1.4 1996/10/24 22:26:55 pvmsrc * Moved #include "global.h" below other #include's for typing. * Added #include of new "lpvm.h" header to replace explicit externs. * Extracted common message handler routines from lpvm*.c: * - pvm_tc_noop(), pvm_tc_settrace(), pvm_tc_settrcbuf(), * pvm_tc_settrcopt(), pvm_tc_settmask(), and pvm_tc_siblings(). * Extracted PVM option routines from lpvm*.c: * - pvm_getopt() & pvm_setopt(). * - merged special mimd / shmem cases into generic routine. * - added new tracing options PvmTraceBuffer, PvmTraceOptions, * PvmSelfTraceBuffer & PvmSelfTraceOptions. * Modified trace event generation for message / packing routines: * - replaced old TEV_*[01] constants with new TEV_EVENT_ENTRY/EXIT. * - replaced standard pvm_pk*() calls with new TEV_PACK_*() macro * calls and TEV_DID_* identification. * - in pvm_send(), check for user-defined message destination * and handle proper finishing and sending of user-defined * trace event. * - in pvm_spawn(), use new Pvmtracer structure info in place of * old globals, pass along new PVMTRCBUF & PVMTRCOPT env vars. * Added new pvm_reg_tracer() routine for registering a task as a tracer. * * Revision 1.3 1996/10/11 17:03:10 pvmsrc * Replaced references to pvm_remove() with pvm_delinfo(): renamed. * * Revision 1.2 1996/10/08 18:32:21 pvmsrc * Renamed routines: * - pvm_put() -> pvm_putinfo(). * - pvm_get() -> pvm_getinfo(). * * Revision 1.1 1996/09/23 23:44:14 pvmsrc * Initial revision * * Revision 1.10 1995/11/02 16:09:32 manchek * added NEEDSENDIAN switch. * pass environment through spawn on PGON * * Revision 1.9 1995/07/28 16:04:05 manchek * switch endian includes on flag, not arch name * * Revision 1.8 1995/06/12 15:46:46 manchek * pvm_recvf now returns pointer to default matcher instead of 0 * * Revision 1.7 1995/02/01 21:10:33 manchek * pvm_hostsync didn't free its message buffers * * Revision 1.6 1994/11/07 21:36:33 manchek * flush messages on pvm_exit. * function prototype for SCO * * Revision 1.5 1994/10/15 19:12:35 manchek * check for system error in TM_SPAWN reply (cc != count) * * Revision 1.4 1994/06/03 20:38:16 manchek * version 3.3.0 * * Revision 1.3 1993/11/30 15:52:42 manchek * implemented case autoerr == 2 in lpvmerr() * * Revision 1.2 1993/09/16 21:37:39 manchek * pvm_send() missing a return before lpvmerr() * * Revision 1.1 1993/08/30 23:26:48 manchek * Initial revision * */ #include #ifdef NEEDMENDIAN #include #include #endif #ifdef NEEDENDIAN #include #endif #ifdef NEEDSENDIAN #include #endif #include #if defined(WIN32) || defined(CYGWIN) #include "..\xdr\types.h" #include "..\xdr\xdr.h" #else #include #include #endif #ifdef SYSVSTR #include #define CINDEX(s,c) strchr(s,c) #else #include #define CINDEX(s,c) index(s,c) #endif #include #include #ifdef __STDC__ #include #else #include #endif #include #include "pvmalloc.h" #include "pmsg.h" #include "listmac.h" #include "bfunc.h" #include "tvdefs.h" #include "lpvm.h" #include #include "tevmac.h" #include "host.h" #include "waitc.h" #include "global.h" #if defined(IMA_PGON) || defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) \ || defined(IMA_AIX5SP2) || defined(IMA_BEOLIN) #include "pvmmimd.h" #include "lmsg.h" extern struct msgid *pvm_inprecv; #endif #ifndef HASERRORVARS extern int errno; /* from libc */ #ifndef USESTRERROR extern char *sys_errlist[]; extern int sys_nerr; #endif #endif #ifdef WIN32 #ifndef SOCK_DEFINES extern WSADATA WSAData; int nAlert=SO_SYNCHRONOUS_NONALERT; #define SOCK_DEFINES #endif #endif struct mhandler { int mhid; /* unique message handler id */ struct pvmminfo header; /* source, tag, context */ int (*f)(); /* handler function */ }; struct dhandler { int mhid; /* message handler id - used for free list links */ int handle; /* index of associated handles[] entry */ }; /*************** ** Globals ** ** ** ***************/ char *getenv(); struct pmsg *midtobuf(); /*************** ** Private ** ** ** ***************/ static int def_match(); static int (*recv_match)() = def_match; /* handles[] contains structures with message handler info */ static struct mhandler *handles = 0; /* element count for handles[] array - all of these are active */ static int nhandles = 0; /* pointer to the dhandles[] array */ static struct dhandler *dhandles = 0; /* element count for dhandles[] array - not all active though */ static int ndhandles = 0; /* free list dhandles; -1 indicates empty list */ static int fl_dhandles = -1; /************************** ** Internal Functions ** ** ** **************************/ /* * Function: pvmdisplaymhfinfo * * function displays message handler data structure information * */ void pvmdisplaymhfinfo(who, msg, tid) char *who; /* who made this call */ char *msg; /* message from caller */ int tid; /* tid of caller */ { char *me = "pvmdisplaymhfinfo"; int i; int head; printf("\n%s t%x: Display Message Handler Information: ", who, tid ); printf("ndhandles = %d\tnhandles = %d\tfl_dhandles = %d", ndhandles, nhandles, fl_dhandles); printf("\n%s: free list. head <-", me); head = fl_dhandles; while (head != -1){ printf(" %d", head); head = dhandles[head].mhid; } printf(" -< tail"); printf("\n%s t%x: %s\n", who, tid, msg); for (i = 0; i < ndhandles; i++ ) { printf("%s t%x: dhandles[%2d].mhid = %2d .handle = %2d ", who, tid, i, dhandles[i].mhid, dhandles[i].handle); printf("handles[%2d].mhid = %2d .header.src = t%-8x ", i, handles[i].mhid, handles[i].header.src); printf(".header.ctx = %8d .header.tag= %8d\n", handles[i].header.ctx, handles[i].header.tag); } printf("\n\n"); fflush(stdout); } /* pvmdisplaymhfinfo */ static int def_match(mid, tid, tag) int mid; int tid; int tag; { struct pmsg *up; if (!(up = midtobuf(mid))) return PvmNoSuchBuf; return ((tid == -1 || tid == up->m_src) && (tag == -1 || tag == up->m_tag) && (pvmmyctx == -1 || pvmmyctx == up->m_ctx)) ? 1 : 0; } /* pvmbailout() * * Called by low-level stuff in f.e. pvmfrag.c. Don't really want to * bail in libpvm. */ void pvmbailout(n) int n; { n = n; /* ayn rand was here */ } /* pvmlogerror() * * Log a libpvm error message. Prepends a string identifying the task. */ int pvmlogerror(s) char *s; { if (pvmmytid == -1) fprintf(stderr, "libpvm [pid%d]: %s", pvmmyupid, s); #ifdef LOG else if (logfp) { fprintf(logfp, "libpvm [t%x]: %s", pvmmytid, s); fflush(logfp); } #endif else fprintf(stderr, "libpvm [t%x]: %s", pvmmytid, s); return 0; } int vpvmlogprintf(fmt, ap) char *fmt; va_list ap; { static int newline = 1; int cc; if (newline) { if (pvmmytid == -1) fprintf(stderr, "libpvm [pid%d] ", pvmmyupid); else fprintf(stderr, "libpvm [t%x] ", pvmmytid); } cc = vfprintf(stderr, fmt, ap); newline = (fmt[strlen(fmt) - 1] == '\n') ? 1 : 0; fflush(stderr); return(cc); } /* pvmlogprintf() * * Log a libpvm error message. Prepends the task id. Takes * printf-like args. */ int #ifdef __STDC__ pvmlogprintf(const char *fmt, ...) #else pvmlogprintf(va_alist) va_dcl #endif { va_list ap; int cc; #ifdef __STDC__ va_start(ap, fmt); #else char *fmt; va_start(ap); fmt = va_arg(ap, char *); #endif cc = vpvmlogprintf(fmt, ap); va_end(ap); return cc; } /* pvmlogperror() * * Log a libpvm error message. Prepends a string identifying the * task and appends the system error string for _errno. */ int pvmlogperror(s) char *s; { #ifdef SYSERRISCONST const char *em; #else char *em; #endif #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) int l; /* if (mpierrcode) { MPI_Error_string(mpierrcode, pvmtxt, &l); em = pvmtxt; } else */ #ifdef USESTRERROR em = strerror( errno ); #else em = ((errno >= 0 && errno < sys_nerr) ? sys_errlist[errno] : "Unknown Error"); #endif #else #ifdef IMA_CM5 errno = CMMD_get_errno(); #endif #ifdef USESTRERROR em = (char *) strerror( errno ); #else em = ((errno >= 0 && errno < sys_nerr) ? sys_errlist[errno] : "Unknown Error"); #endif #endif /*IMA_SP2MPI*/ pvmlogprintf("%s: %s\n", s, em); return 0; } /* lpvmerr() * * Error has occurred in libpvm function. * Action determined by pvmautoerr (set by setopt): * 0 Do nothing * 1 Print error message * 2 Print error message, exit program with error code * 3 Print error message, abort program */ int lpvmerr(f, n) char *f; /* error location */ int n; /* error code */ { char buf[128]; pvm_errno = n; if (pvmautoerr) { buf[0] = 0; strncat(buf, f, sizeof(buf)-4); strcat(buf, "()"); pvm_perror(buf); fflush(stderr); if (pvmautoerr == 3) abort(); if (pvmautoerr == 2) { pvmautoerr = 1; pvm_exit(); exit(n); } } return n; } /* mesg_input() * * Receive message into task. All received messages go through this function. * If a handler was specified for this tag, call it. * Otherwise, put the message on rxlist. */ int mesg_input(up) struct pmsg *up; { int savesbuf; int saverbuf; int savectx; int i; TEV_DECLS if (pvmdebmask & PDMMESSAGE) pvmlogprintf("mesg_input() src t%x ctx %d tag %s len %d\n", up->m_src, up->m_ctx, pvmnametag(up->m_tag, (int *)0), up->m_len); for (i = nhandles; i-- > 0; ) { if ( (handles[i].header.tag == -1 || handles[i].header.tag == up->m_tag) && (handles[i].header.ctx == -1 || handles[i].header.ctx == up->m_ctx) && (handles[i].header.src == -1 || handles[i].header.src == up->m_src) ) { if (TEV_DO_TRACE(TEV_MHF_INVOKE,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_RST, TEV_DATA_SCALAR, &(handles[i].header.src), 1, 1 ); TEV_PACK_INT( TEV_DID_RMC, TEV_DATA_SCALAR, &(handles[i].header.tag), 1, 1 ); TEV_PACK_INT( TEV_DID_RCX, TEV_DATA_SCALAR, &(handles[i].header.ctx), 1, 1 ); TEV_PACK_INT( TEV_DID_MB, TEV_DATA_SCALAR, &(up->m_mid), 1, 1 ); TEV_PACK_INT( TEV_DID_MNB, TEV_DATA_SCALAR, &(up->m_len), 1, 1 ); TEV_PACK_INT( TEV_DID_MC, TEV_DATA_SCALAR, &(up->m_tag), 1, 1 ); TEV_PACK_INT( TEV_DID_MCX, TEV_DATA_SCALAR, &(up->m_ctx), 1, 1 ); TEV_PACK_INT( TEV_DID_SRC, TEV_DATA_SCALAR, &(up->m_src), 1, 1 ); TEV_FIN; TEV_PUSHTOP; } savesbuf = pvm_setsbuf( 0 ); saverbuf = pvm_setrbuf( up->m_mid ); savectx = pvm_setcontext( up->m_ctx ); (handles[i].f)(up->m_mid); pvm_setcontext( savectx ); pvm_freebuf( pvm_setsbuf( savesbuf ) ); pvm_freebuf( pvm_setrbuf( saverbuf ) ); if ( TEV_AMPUSHED ) TEV_POPTOP; return 0; } } LISTPUTBEFORE(pvmrxlist, up, m_link, m_rlink); return 0; } /************************ ** Message Handlers ** ** ** ************************/ /* pvm_tc_noop() * * Process a NO-OP message. Har. */ int pvm_tc_noop(mid) int mid; { int src; pvm_bufinfo(mid, (int *)0, (int *)0, &src); if (pvmdebmask) { pvmlogprintf("pvm_tc_noop() NOOP from t%x\n", src); } pvm_freebuf(mid); return 0; } /* pvm_tc_settrace() * * Set our tracing on the fly * * TC_SETTRACE() { * int trctid // task id for tracing * int trcctx // message context for trace messages * int trctag // message tag for trace messages * int outtid // task id for stdout output * int outctx // message context for output messages * int outtag // message tag for output messages * string mask // new trace mask * int tbuf // trace buffer size * int topt // trace options * } */ int pvm_tc_settrace(mid) int mid; { int trctid; int trcctx; int trctag; int outtid; int outctx; int outtag; char buf[256]; int tbuf; int topt; pvm_upkint(&trctid, 1, 1); pvm_upkint(&trcctx, 1, 1); pvm_upkint(&trctag, 1, 1); pvm_upkint(&outtid, 1, 1); pvm_upkint(&outctx, 1, 1); pvm_upkint(&outtag, 1, 1); pvm_upkstr(buf); pvm_upkint(&tbuf, 1, 1); pvm_upkint(&topt, 1, 1); if (trctid) { /* cheat on trcctx & trctag to avoid race */ pvmtrc.trcctx = trcctx; pvmtrc.trctag = trctag; pvm_setopt( PvmSelfTraceTid, trctid ); if (strlen(buf) + 1 == TEV_MASK_LENGTH) BCOPY(buf, pvmtrc.tmask, TEV_MASK_LENGTH); else { TEV_MASK_INIT(pvmtrc.tmask); pvmlogerror("pvm_tc_settrace() bogus trace mask\n"); } BCOPY(pvmtrc.tmask, pvmctrc.tmask, TEV_MASK_LENGTH); if (tbuf >= 0) pvmtrc.trcbuf = tbuf; else { pvmtrc.trcbuf = 0; pvmlogerror("pvm_tc_settrace() bogus trace buffering\n"); } if (topt >= 0) pvmtrc.trcopt = topt; else { pvmtrc.trcopt = 0; pvmlogerror("pvm_tc_settrace() bogus trace options\n"); } } if (outtid) { /* cheat on outctx & outtag to avoid race */ pvmtrc.outctx = outctx; pvmtrc.outtag = outtag; pvm_setopt( PvmSelfOutputTid, outtid ); } pvm_freebuf(mid); return 0; } /* pvm_tc_settrcbuf() * * Set our trace buffering on the fly * * TC_SETTRCBUF() { * int buf // new trace buffer size * } */ int pvm_tc_settrcbuf(mid) int mid; { int tbuf; pvm_upkint(&tbuf,1,1); if (tbuf >= 0) pvmtrc.trcbuf = tbuf; else { pvmtrc.trcbuf = 0; pvmlogerror("pvm_tc_settrcbuf() bogus trace buffering\n"); } pvm_freebuf(mid); return 0; } /* pvm_tc_settrcopt() * * Set our trace options on the fly * * TC_SETTRCOPT() { * int opt // new trace options * } */ int pvm_tc_settrcopt(mid) int mid; { int topt; pvm_upkint(&topt,1,1); if (topt >= 0) pvmtrc.trcopt = topt; else { pvmtrc.trcopt = 0; pvmlogerror("pvm_tc_settrcopt() bogus trace options\n"); } pvm_freebuf(mid); return 0; } /* pvm_tc_settmask() * * Set our trace mask on the fly * * TC_SETTMASK() { * string mask // new trace mask * } */ int pvm_tc_settmask(mid) int mid; { char buf[256]; pvm_upkstr(buf); if (strlen(buf) + 1 == TEV_MASK_LENGTH) BCOPY(buf, pvmtrc.tmask, TEV_MASK_LENGTH); else pvmlogerror("pvm_tc_settmask() bogus trace mask\n"); pvm_freebuf(mid); return 0; } /* pvm_tc_siblings() * * Parent task announces our spawn group. * * TC_SIBLINGS() { * int length * int tids[length] // sibling tids * } */ int pvm_tc_siblings(mid) int mid; { pvm_upkint(&pvmnsibs, 1, 1); if (pvmnsibs > 0) { pvmsibtids = TALLOC(pvmnsibs, int, "sibs"); pvm_upkint(pvmsibtids, pvmnsibs, 1); } pvm_freebuf(mid); return 0; } /************************ ** Libpvm Functions ** ** ** ************************/ int pvm_getopt(what) int what; { int rc = 0; int err = 0; TEV_DECLS if (TEV_EXCLUSIVE) { if (pvmmytid != -1 && TEV_DO_TRACE(TEV_GETOPT,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_OPT, TEV_DATA_SCALAR, &what, 1, 1 ); TEV_FIN; } } switch (what) { case PvmRoute: rc = pvmrouteopt; break; case PvmDebugMask: rc = pvmdebmask; break; case PvmAutoErr: rc = pvmautoerr; break; case PvmOutputTid: rc = pvmctrc.outtid; break; case PvmOutputContext: rc = pvmctrc.outctx; break; case PvmOutputCode: rc = pvmctrc.outtag; break; case PvmTraceTid: rc = pvmctrc.trctid; break; case PvmTraceContext: rc = pvmctrc.trcctx; break; case PvmTraceCode: rc = pvmctrc.trctag; break; case PvmTraceBuffer: rc = pvmctrc.trcbuf; break; case PvmTraceOptions: rc = pvmctrc.trcopt; break; case PvmFragSize: rc = pvmfrgsiz; break; case PvmResvTids: rc = pvmrescode; break; case PvmSelfOutputTid: rc = pvmtrc.outtid; break; case PvmSelfOutputContext: rc = pvmtrc.outctx; break; case PvmSelfOutputCode: rc = pvmtrc.outtag; break; case PvmSelfTraceTid: rc = pvmtrc.trctid; break; case PvmSelfTraceContext: rc = pvmtrc.trcctx; break; case PvmSelfTraceCode: rc = pvmtrc.trctag; break; case PvmSelfTraceBuffer: rc = pvmtrc.trcbuf; break; case PvmSelfTraceOptions: rc = pvmtrc.trcopt; break; case PvmShowTids: rc = pvmshowtaskid; break; case PvmNoReset: rc = pvmnoreset; break; #if defined(IMA_AIX4MP) || defined(IMA_AIX5MP) \ || defined(IMA_ALPHAMP) || defined(IMA_CSPP) \ || defined(IMA_HPPAMP) || defined(IMA_RS6KMP) \ || defined(IMA_SGIMP) || defined(IMA_SGIMP6) \ || defined(IMA_SGIMP64) || defined(IMA_SUNMP) case PvmPollTime: rc = pvmpolltime; break; case PvmPollType: rc = pvmpolltype; break; #else /* SHMEM */ case PvmPollTime: case PvmPollType: rc = PvmNotImpl; err = 1; break; #endif /* SHMEM */ default: err = 1; break; } if (TEV_AMEXCL) { if (pvmmytid != -1 && TEV_DO_TRACE(TEV_GETOPT,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_OPV, TEV_DATA_SCALAR, &rc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (err) return lpvmerr("pvm_getopt", PvmBadParam); return rc; } int pvm_setopt(what, val) int what; int val; { int rc = 0; int err = 0; int sbf, rbf; char buf[16]; TEV_DECLS if (TEV_EXCLUSIVE) { if (pvmmytid != -1 && TEV_DO_TRACE(TEV_SETOPT,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_OPT, TEV_DATA_SCALAR, &what, 1, 1 ); TEV_PACK_INT( TEV_DID_OPV, TEV_DATA_SCALAR, &val, 1, 1 ); TEV_FIN; } } switch (what) { case PvmRoute: switch (val) { case PvmDontRoute: case PvmAllowDirect: case PvmRouteDirect: rc = pvmrouteopt; #if (!defined(IMA_PGON)) && (!defined(IMA_SP2MPI)) \ && (!defined(IMA_AIX4SP2)) && (!defined(IMA_AIX5SP2)) pvmrouteopt = val; #endif break; default: rc = PvmBadParam; err = 1; break; } break; case PvmDebugMask: rc = pvmdebmask; pvmdebmask = val; break; case PvmAutoErr: rc = pvmautoerr; pvmautoerr = val; break; case PvmOutputTid: if (val && val != pvmmytid && (val != pvmtrc.outtid || pvmctrc.outtag != pvmtrc.outtag)) { rc = PvmBadParam; err = 1; } else { rc = pvmctrc.outtid; pvmctrc.outtid = val; } break; case PvmOutputContext: if (pvmctrc.outtid > 0 && pvmctrc.outtid != pvmmytid && val != pvmtrc.outctx) { rc = PvmBadParam; err = 1; } else { rc = pvmctrc.outctx; pvmctrc.outctx = val; } break; case PvmOutputCode: if (pvmctrc.outtid > 0 && pvmctrc.outtid != pvmmytid && val != pvmtrc.outtag) { rc = PvmBadParam; err = 1; } else { rc = pvmctrc.outtag; pvmctrc.outtag = val; } break; case PvmTraceTid: if (val && val != pvmmytid && (val != pvmtrc.trctid || pvmctrc.trctag != pvmtrc.trctag)) { rc = PvmBadParam; err = 1; } else { rc = pvmctrc.trctid; pvmctrc.trctid = val; } break; case PvmTraceContext: if (pvmctrc.trctid > 0 && pvmctrc.trctid != pvmmytid && val != pvmtrc.trcctx) { rc = PvmBadParam; err = 1; } else { rc = pvmctrc.trcctx; pvmctrc.trcctx = val; } break; case PvmTraceCode: if (pvmctrc.trctid > 0 && pvmctrc.trctid != pvmmytid && val != pvmtrc.trctag) { rc = PvmBadParam; err = 1; } else { rc = pvmctrc.trctag; pvmctrc.trctag = val; } break; case PvmTraceBuffer: rc = pvmctrc.trcbuf; pvmctrc.trcbuf = val; break; case PvmTraceOptions: switch (val) { case PvmTraceFull: case PvmTraceTime: case PvmTraceCount: rc = pvmctrc.trcopt; pvmctrc.trcopt = val; break; default: rc = PvmBadParam; err = 1; break; } break; case PvmFragSize: #if defined(IMA_AIX4MP) || defined(IMA_AIX5MP) \ || defined(IMA_ALPHAMP) || defined(IMA_CSPP) \ || defined(IMA_HPPAMP) || defined(IMA_RS6KMP) \ || defined(IMA_SGIMP) || defined(IMA_SGIMP6) \ || defined(IMA_SGIMP64) || defined(IMA_SUNMP) rc = PvmBadParam; err = 1; #else /* SHMEM */ #if defined(IMA_CM5) || defined(IMA_CUBE) || defined(IMA_I860) \ || defined(IMA_PGON) || defined(IMA_SP2MPI) \ || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) \ || defined(IMA_BEOLIN) /* if (val < TDFRAGHDR + TTMSGHDR + 4 || val > 1048576) */ if (val < TDFRAGHDR + MSGHDRLEN + 4 || val > MAXFRAGSIZE) #else if (val < TDFRAGHDR + MSGHDRLEN + 4 || val > 1048576) #endif { rc = PvmBadParam; err = 1; } else { rc = pvmfrgsiz; pvmfrgsiz = val; } #endif /* SHMEM */ break; case PvmResvTids: rc = pvmrescode; pvmrescode = val; break; case PvmSelfOutputTid: if (pvmtrc.outtid > 0 || val > 0) { if (rc = BEATASK) err = 1; else { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); what = TS_OUTTID; pvm_pkint(&what, 1, 1); sprintf(buf, "%x", 0xffffffff & val); pvm_pkstr(buf); if ((rc = msendrecv(TIDPVMD, TM_SETOPT, SYSCTX_TM)) > 0) { pvm_freebuf(pvm_setrbuf(rbf)); rc = pvmtrc.outtid; pvmtrc.outtid = val; pvmctrc.outtid = pvmtrc.outtid; pvmctrc.outctx = pvmtrc.outctx; pvmctrc.outtag = pvmtrc.outtag; } else { pvm_setrbuf(rbf); err = 1; } pvm_freebuf(pvm_setsbuf(sbf)); } } else { rc = pvmtrc.outtid; pvmtrc.outtid = val; pvmctrc.outtid = pvmtrc.outtid; pvmctrc.outctx = pvmtrc.outctx; pvmctrc.outtag = pvmtrc.outtag; } break; case PvmSelfOutputContext: rc = PvmNotImpl; err = 1; break; case PvmSelfOutputCode: if (pvmtrc.outtid <= 0 || (rc = BEATASK)) err = 1; else { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); what = TS_OUTTAG; pvm_pkint(&what, 1, 1); sprintf(buf, "%x", 0xffffffff & val); pvm_pkstr(buf); if ((rc = msendrecv(TIDPVMD, TM_SETOPT, SYSCTX_TM)) > 0) { pvm_freebuf(pvm_setrbuf(rbf)); rc = pvmtrc.outtag; pvmtrc.outtag = val; pvmctrc.outtid = pvmtrc.outtid; pvmctrc.outctx = pvmtrc.outctx; pvmctrc.outtag = pvmtrc.outtag; } else { pvm_setrbuf(rbf); err = 1; } pvm_freebuf(pvm_setsbuf(sbf)); } break; case PvmSelfTraceTid: if ( pvmtrc.trctid > 0 || val > 0 ) { if (rc = BEATASK) err = 1; else { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); what = TS_TRCTID; pvm_pkint(&what, 1, 1); sprintf(buf, "%x", 0xffffffff & val); pvm_pkstr(buf); if ((rc = msendrecv(TIDPVMD, TM_SETOPT, SYSCTX_TM)) > 0) { pvm_freebuf(pvm_setrbuf(rbf)); rc = pvmtrc.trctid; pvmtrc.trctid = val; pvmctrc.trctid = pvmtrc.trctid; pvmctrc.trcctx = pvmtrc.trcctx; pvmctrc.trctag = pvmtrc.trctag; } else { pvm_setrbuf(rbf); err = 1; } pvm_freebuf(pvm_setsbuf(sbf)); } } else { rc = pvmtrc.trctid; pvmtrc.trctid = val; pvmctrc.trctid = pvmtrc.trctid; pvmctrc.trcctx = pvmtrc.trcctx; pvmctrc.trctag = pvmtrc.trctag; } break; case PvmSelfTraceContext: rc = PvmNotImpl; err = 1; break; case PvmSelfTraceCode: if (pvmtrc.trctid <= 0 || (rc = BEATASK)) err = 1; else { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); what = TS_TRCTAG; pvm_pkint(&what, 1, 1); sprintf(buf, "%x", 0xffffffff & val); pvm_pkstr(buf); if ((rc = msendrecv(TIDPVMD, TM_SETOPT, SYSCTX_TM)) > 0) { pvm_freebuf(pvm_setrbuf(rbf)); rc = pvmtrc.trctag; pvmtrc.trctag = val; pvmctrc.trctid = pvmtrc.trctid; pvmctrc.trcctx = pvmtrc.trcctx; pvmctrc.trctag = pvmtrc.trctag; } else { pvm_setrbuf(rbf); err = 1; } pvm_freebuf(pvm_setsbuf(sbf)); } break; case PvmSelfTraceBuffer: tev_flush( 1 ); rc = pvmtrc.trcbuf; pvmtrc.trcbuf = val; break; case PvmSelfTraceOptions: tev_flush( 1 ); switch (val) { case PvmTraceFull: case PvmTraceTime: case PvmTraceCount: rc = pvmtrc.trcopt; pvmtrc.trcopt = val; break; default: rc = PvmBadParam; err = 1; break; } break; case PvmShowTids: rc = pvmshowtaskid; pvmshowtaskid = val; break; case PvmNoReset: if ( pvmmytid < 0 ) { rc = PvmBadParam; lpvmerr("pvm_setopt: PvmNoReset task not initialized", rc); err = 1; } else { rc = pvmnoreset; if ( val && !pvmnoreset ) { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataDefault)); pvm_pkint( &pvmmytid, 1, 1 ); if ( pvmnoresetindex = pvm_putinfo( PVMNORESETCLASS, pvm_getsbuf(), PvmMboxMultiInstance ) < 0 ) { rc = PvmSysErr; err = 1; val = 0; } pvm_freebuf(pvm_setsbuf(sbf)); } else if ( !val && pvmnoreset && pvmnoresetindex >= 0 ) { if ( pvm_delinfo( PVMNORESETCLASS, pvmnoresetindex, PvmMboxDefault ) < 0 ) { rc = PvmSysErr; err = 1; val = 0; } pvmnoresetindex = -1; } pvmnoreset = val; } break; #if defined(IMA_AIX4MP) || defined(IMA_AIX5MP) \ || defined(IMA_ALPHAMP) || defined(IMA_CSPP) \ || defined(IMA_HPPAMP) || defined(IMA_RS6KMP) \ || defined(IMA_SGIMP) || defined(IMA_SGIMP6) \ || defined(IMA_SGIMP64) || defined(IMA_SUNMP) case PvmPollTime: rc = pvmpolltime; if (val < 0) { rc = PvmBadParam; err = 1; break; } pvmpolltime = val; break; case PvmPollType: rc = pvmpolltype; if ((val != PvmPollConstant) && (val != PvmPollSleep)) { rc = PvmBadParam; err = 1; break; } pvmpolltype = val; break; #else /* SHMEM */ case PvmPollTime: case PvmPollType: rc = PvmNotImpl; err = 1; break; #endif /* SHMEM */ default: rc = PvmBadParam; err = 1; break; } if (TEV_AMEXCL) { if (pvmmytid != -1 && TEV_DO_TRACE(TEV_SETOPT,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_OPV, TEV_DATA_SCALAR, &rc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (err) return lpvmerr("pvm_setopt", rc); return rc; } int pvmsettaskname( name ) char *name; { if ( name == NULL ) return lpvmerr( "pvmsettaskname", PvmBadParam ); if ( pvmmytid != -1 ) return lpvmerr( "pvmsettaskname", PvmExists ); if ( pvmmytaskname != NULL ) { PVM_FREE( pvmmytaskname ); pvmmytaskname = (char *) NULL; } pvmmytaskname = STRALLOC( name ); return 0; } int pvm_getnoresets( tids, ntids ) int **tids; int *ntids; { static int *tidlist = (int *) NULL; static int num = 0; int index; int done; int save; int mid; int cnt; /* Allocate Initial Tids List */ if ( !tidlist ) { num = 16; tidlist = TALLOC( num, int, "int" ); } /* Save Receive Buffer */ save = pvm_setrbuf( 0 ); /* Search for No Resets */ index = 0; done = 0; cnt = 0; while ( !done ) { if ( pvm_recvinfo( PVMNORESETCLASS, index, PvmMboxFirstAvail ) <= 0 ) { done++; } else { if ( cnt >= num ) { num *= 2; tidlist = TREALLOC( tidlist, num, int ); } pvm_upkint( &(tidlist[cnt++]), 1, 1 ); index++; } } /* Restore Receive Buffer */ pvm_setrbuf( save ); /* Set Return Values */ if ( tids != NULL ) *tids = tidlist; if ( ntids != NULL ) *ntids = cnt; return( PvmOk ); } int pvm_addhosts(names, count, svp) char **names; /* host name vector */ int count; /* length of names */ int *svp; /* status vector return */ { int sbf, rbf; int cc; int i; int *sv; /* status vector */ char *buf; int tmp; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_ADDHOSTS,TEV_EVENT_ENTRY)) { TEV_PACK_STRING( TEV_DID_HNL, TEV_DATA_ARRAY, names, count, 1 ); TEV_FIN; } } if (count < 1 || count > (TIDHOST >> (ffs(TIDHOST) - 1))) { cc = PvmBadParam; } else { if (!(cc = BEATASK)) { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); pvm_pkint(&count, 1, 1); for (i = 0; i < count; i++) pvm_pkstr(names[i]); if (pvmschedtid) cc = msendrecv(pvmschedtid, SM_ADDHOST, PvmBaseContext); else cc = msendrecv(TIDPVMD, TM_ADDHOST, SYSCTX_TM); if (cc > 0) { pvm_upkint(&cc, 1, 1); if (cc >= 0) { if (cc == count) { pvm_upkint(&cc, 1, 1); /* toss narches */ sv = TALLOC(count, int, "sv1"); cc = 0; for (i = 0; i < count; i++) { pvm_upkint(&sv[i], 1, 1); /* toss name, arch, speed, ds */ pvmupkstralloc(&buf); PVM_FREE(buf); pvmupkstralloc(&buf); PVM_FREE(buf); pvm_upkint(&tmp, 1, 1); pvm_upkint(&tmp, 1, 1); if (sv[i] >= 0) cc++; } if (svp) BCOPY((char*)sv, (char*)svp, count * sizeof(int)); PVM_FREE(sv); } else { pvmlogprintf("pvm_addhosts() sent count %d received count %d\n", count, cc); cc = PvmOutOfRes; } } pvm_freebuf(pvm_setrbuf(rbf)); } else pvm_setrbuf(rbf); pvm_freebuf(pvm_setsbuf(sbf)); } } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_ADDHOSTS,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_addhosts", cc); return cc; } int pvm_config(nhostp, narchp, hostp) int *nhostp; int *narchp; struct pvmhostinfo **hostp; { int sbf, rbf, cc; static int nhost = 0; static int narch = 0; static struct pvmhostinfo *hlist = 0; int i; /* char buf[256]; XXX static limit, argh (Not Any More! :-) JAK */ TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_CONFIG,TEV_EVENT_ENTRY)) TEV_FIN; } if (hlist) { while (nhost-- > 0) { PVM_FREE(hlist[nhost].hi_name); PVM_FREE(hlist[nhost].hi_arch); } PVM_FREE(hlist); hlist = 0; nhost = 0; } if (!(cc = BEATASK)) { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); if (pvmschedtid) cc = msendrecv(pvmschedtid, SM_CONFIG, PvmBaseContext); else cc = msendrecv(TIDPVMD, TM_CONFIG, SYSCTX_TM); if (cc > 0) { pvm_upkint(&nhost, 1, 1); pvm_upkint(&narch, 1, 1); hlist = TALLOC(nhost, struct pvmhostinfo, "hi"); for (i = 0; i < nhost; i++) { pvm_upkint(&hlist[i].hi_tid, 1, 1); pvmupkstralloc(&(hlist[i].hi_name)); pvmupkstralloc(&(hlist[i].hi_arch)); pvm_upkint(&hlist[i].hi_speed, 1, 1); pvm_upkint(&hlist[i].hi_dsig, 1, 1); } pvm_freebuf(pvm_setrbuf(rbf)); if (nhostp) *nhostp = nhost; if (narchp) *narchp = narch; if (hostp) *hostp = hlist; cc = 0; } pvm_freebuf(pvm_setsbuf(sbf)); pvm_setrbuf(rbf); } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_CONFIG,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_NH, TEV_DATA_SCALAR, &nhost, 1, 1 ); TEV_PACK_INT( TEV_DID_NA, TEV_DATA_SCALAR, &narch, 1, 1 ); TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_config", cc); return cc; } int pvm_delhosts(names, count, svp) char **names; int count; int *svp; /* status vector return */ { int sbf, rbf; int cc; int i; int *sv; /* return values */ TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_DELHOSTS,TEV_EVENT_ENTRY)) { TEV_PACK_STRING( TEV_DID_HNL, TEV_DATA_ARRAY, names, count, 1 ); TEV_FIN; } } if (count < 1 || count > (TIDHOST >> (ffs(TIDHOST) - 1))) { cc = PvmBadParam; } else { if (!(cc = BEATASK)) { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); pvm_pkint(&count, 1, 1); for (i = 0; i < count; i++) pvm_pkstr(names[i]); if (pvmschedtid) cc = msendrecv(pvmschedtid, SM_DELHOST, PvmBaseContext); else cc = msendrecv(TIDPVMD, TM_DELHOST, SYSCTX_TM); if (cc > 0) { pvm_upkint(&cc, 1, 1); if (cc >= 0) { if (cc == count) { sv = TALLOC(count, int, "sv2"); pvm_upkint(sv, count, 1); cc = 0; for (i = count; i-- > 0; ) if (sv[i] >= 0) cc++; if (svp) BCOPY((char*)sv, (char*)svp, count * sizeof(int)); PVM_FREE(sv); } else { pvmlogprintf("pvm_delhosts() sent count %d received count %d\n", count, cc); cc = PvmOutOfRes; } } pvm_freebuf(pvm_setrbuf(rbf)); } else pvm_setrbuf(rbf); pvm_freebuf(pvm_setsbuf(sbf)); } } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_DELHOSTS,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_delhosts", cc); return cc; } int pvm_exit() { int i, lndh; int sbf, rbf; int cc = 0; struct waitc *wp, *wp2; struct pmsg *up; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_EXIT,TEV_EVENT_ENTRY)) TEV_FIN; } if (pvmmytid != -1) { wp = waitlist->wa_link; while (wp != waitlist) { wp2 = wp->wa_link; if (wp->wa_kind == WT_TASKX) { up = wp->wa_mesg; wp->wa_mesg = 0; mesg_input(up); LISTDELETE(wp, wa_link, wa_rlink); } wp = wp2; } while (pvm_nrecv(-1, -1) > 0) ; /* XXX attempt to flush messages */ fflush(stderr); fflush(stdout); tev_flush( 1 ); sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); if ((cc = msendrecv(TIDPVMD, TM_EXIT, SYSCTX_TM)) > 0) { pvm_freebuf(pvm_setrbuf(rbf)); cc = 0; } else pvm_setrbuf(rbf); pvm_freebuf(pvm_setsbuf(sbf)); /* * remove all task's message handler functions */ lndh = ndhandles - 1; for (i = lndh; i >= 0; i--){ pvm_delmhf(i); } pvmendtask(); } if (TEV_AMEXCL) { TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_exit", cc); return cc; } int pvm_halt() { int cc, sbf, rbf; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_HALT,TEV_EVENT_ENTRY)) TEV_FIN; } if (!(cc = BEATASK)) { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); cc = (msendrecv(TIDPVMD, TM_HALT, SYSCTX_TM) < 0) ? 0 : PvmSysErr; pvm_freebuf(pvm_setsbuf(sbf)); pvm_setrbuf(rbf); } if (TEV_AMEXCL) { TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_halt", cc); return cc; } int pvm_kill(tid) int tid; { int cc; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_KILL,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_TT, TEV_DATA_SCALAR, &tid, 1, 1 ); TEV_FIN; } } cc = pvm_sendsig(tid, SIGTERM); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_KILL,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_kill", cc); return cc; } int pvm_mcast(tids, count, tag) int *tids; /* dest tasks */ int count; /* number of tids */ int tag; /* message type tag */ { int cc; /* for return codes */ int i; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_MCAST,TEV_EVENT_ENTRY)) { int nb = -1; pvm_bufinfo( ( pvmtrcsbfsave ) ? pvmtrcsbfsave : pvmsbuf->m_mid, &nb, (int *) NULL, (int *) NULL ); TEV_PACK_INT( TEV_DID_MNB, TEV_DATA_SCALAR, &nb, 1, 1 ); TEV_PACK_INT( TEV_DID_MC, TEV_DATA_SCALAR, &tag, 1, 1 ); TEV_PACK_INT( TEV_DID_MCX, TEV_DATA_SCALAR, &pvmmyctx, 1, 1 ); TEV_PACK_INT( TEV_DID_MDL, TEV_DATA_ARRAY, tids, count, 1 ); TEV_FIN; } } /* sanity check args and sendable message */ if (!(cc = BEATASK)) { if (!pvmsbuf) cc = PvmNoBuf; else if (count < 0 || (!pvmrescode && (tag & ~0x7fffffff))) cc = PvmBadParam; else if (!pvmrescode) for (i = count; i-- > 0; ) if (!TIDISTASK(tids[i])) { cc = PvmBadParam; break; } } if (!cc && count > 0) cc = pvmmcast(pvmsbuf->m_mid, tids, count, tag); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_MCAST,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_mcast", cc); return cc; } #ifdef WIN32 #ifndef IMA_WIN32_WATCOM extern char **environ; #endif #endif int pvm_mytid() { int cc; char **ep=0; TEV_DECLS; if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_MYTID,TEV_EVENT_ENTRY)) TEV_FIN; } if (!(cc = BEATASK)) cc = pvmmytid; if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_MYTID,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_MT, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_mytid", cc); return cc; } int pvm_mstat(host) char *host; { int sbf, rbf, cc; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_MSTAT,TEV_EVENT_ENTRY)) { TEV_PACK_STRING( TEV_DID_HN, TEV_DATA_SCALAR, host ? host : "", 1, 1 ); TEV_FIN; } } if (!host || !*host) { cc = PvmBadParam; } else { if (!(cc = BEATASK)) { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); pvm_pkstr(host); if ((cc = msendrecv(TIDPVMD, TM_MSTAT, SYSCTX_TM)) > 0) { pvm_upkint(&cc, 1, 1); pvm_freebuf(pvm_setrbuf(rbf)); } else pvm_setrbuf(rbf); pvm_freebuf(pvm_setsbuf(sbf)); } } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_MSTAT,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_HS, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0 && cc != PvmNoHost && cc != PvmHostFail) lpvmerr("pvm_mstat", cc); return cc; } int pvm_notify(what, code, count, vals) int what; int code; int count; int *vals; { static struct timeval ztv = { 0, 0 }; int sbf; int cc; int numtid; int dosend = 0; struct waitc *wp; int flags; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_NOTIFY,TEV_EVENT_ENTRY)) { int tevcount; TEV_PACK_INT( TEV_DID_NE, TEV_DATA_SCALAR, &what, 1, 1 ); TEV_PACK_INT( TEV_DID_NMC, TEV_DATA_SCALAR, &code, 1, 1 ); tevcount = ( what != PvmHostAdd ) ? count : 0; TEV_PACK_INT( TEV_DID_NTL, TEV_DATA_ARRAY, vals, tevcount, 1 ); TEV_FIN; } } flags = what; what &= ~PvmNotifyCancel; if (!(cc = BEATASK)) { if (!pvmrescode && (code & ~0x7fffffff)) { cc = PvmBadParam; } else { switch (what) { case PvmHostDelete: if (count < 1) cc = PvmBadParam; else { numtid = count; dosend = 1; } break; case PvmTaskExit: if (count < 1) cc = PvmBadParam; else for (numtid = count; numtid-- > 0; ) if (!TIDISTASK(vals[numtid])) { cc = PvmBadParam; break; } if (!cc) { for (numtid = count; numtid-- > 0; ) if (vals[numtid] == pvmmytid) { wp = wait_new(WT_TASKX); wp->wa_tid = pvmmytid; wp->wa_on = pvmmytid; sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); pvm_pkint(&pvmmytid, 1, 1); sbf = pvm_setsbuf(sbf); wp->wa_mesg = midtobuf(sbf); wp->wa_mesg->m_ctx = pvmmyctx; wp->wa_mesg->m_tag = code; } numtid = count; dosend = 1; } break; case PvmHostAdd: numtid = 0; vals = &numtid; dosend = 1; break; case PvmRouteAdd: FORLIST (wp, waitlist, wa_link) if (wp->wa_kind == WT_ROUTEA && wp->wa_mesg->m_ctx == pvmmyctx && wp->wa_mesg->m_tag == code) break; if (count == 0 || (flags & PvmNotifyCancel)) { if (wp != waitlist) wait_delete(wp); } else { if (wp == waitlist) { wp = wait_new(WT_ROUTEA); wp->wa_tid = pvmmytid; wp->wa_on = pvmmytid; sbf = pvm_mkbuf(PvmDataFoo); wp->wa_mesg = midtobuf(sbf); wp->wa_mesg->m_ctx = pvmmyctx; wp->wa_mesg->m_tag = code; } wp->wa_count = count; } break; case PvmRouteDelete: if (count < 1) cc = PvmBadParam; else for (numtid = count; numtid-- > 0; ) if (!TIDISTASK(vals[numtid])) { cc = PvmBadParam; break; } if (!cc) { for (numtid = count; numtid-- > 0; ) post_routedelete(vals[numtid], pvmmyctx, code); } break; default: cc = PvmBadParam; break; } if (dosend) { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); pvm_pkint(&flags, 1, 1); pvm_pkint(&pvmmyctx, 1, 1); pvm_pkint(&code, 1, 1); pvm_pkint(&count, 1, 1); pvm_pkint(vals, numtid, 1); if (pvmschedtid) cc = mroute(pvmsbuf->m_mid, pvmschedtid, SM_NOTIFY, &ztv); else cc = mroute(pvmsbuf->m_mid, TIDPVMD, TM_NOTIFY, &ztv); pvm_freebuf(pvm_setsbuf(sbf)); if (cc > 0) cc = 0; } } } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_NOTIFY,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_notify", cc); return cc; } int pvm_nrecv(tid, tag) int tid; int tag; { struct pmsg *up; struct pmsg *bestup; int bestcc = 0; int cc; int alrdy = 0; TEV_DECLS static struct timeval ztv = { 0, 0 }; if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_NRECV,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_RST, TEV_DATA_SCALAR, &tid, 1, 1 ); TEV_PACK_INT( TEV_DID_RMC, TEV_DATA_SCALAR, &tag, 1, 1 ); TEV_PACK_INT( TEV_DID_RCX, TEV_DATA_SCALAR, &pvmmyctx, 1, 1 ); TEV_FIN; } } if (!(cc = BEATASK)) { if (pvmrbuf) umbuf_free(pvmrbuf); pvmrbuf = 0; for (up = pvmrxlist->m_link; 1; up = up->m_link) { if (up == pvmrxlist && bestcc) break; while (up == pvmrxlist) { if (alrdy) { cc = 0; goto done; } up = up->m_rlink; if ((cc = mroute(0, 0, 0, &ztv)) < 0) goto done; up = up->m_link; alrdy = 1; } if ((cc = recv_match(up->m_mid, tid, tag)) < 0) goto done; if (cc == 1) { bestup = up; break; } if (cc > bestcc) { bestcc = cc; bestup = up; } } LISTDELETE(bestup, m_link, m_rlink); bestup->m_flag &= ~MM_UPACK; if (!(cc = pvm_setrbuf(bestup->m_mid))) cc = bestup->m_mid; } done: if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_NRECV,TEV_EVENT_EXIT)) { int nb, mc, src; TEV_PACK_INT( TEV_DID_MB, TEV_DATA_SCALAR, &cc, 1, 1 ); if (cc > 0) pvm_bufinfo(cc, &nb, &mc, &src); else nb = mc = src = -1; TEV_PACK_INT( TEV_DID_MNB, TEV_DATA_SCALAR, &nb, 1, 1 ); TEV_PACK_INT( TEV_DID_MC, TEV_DATA_SCALAR, &mc, 1, 1 ); TEV_PACK_INT( TEV_DID_MCX, TEV_DATA_SCALAR, &pvmmyctx, 1, 1 ); TEV_PACK_INT( TEV_DID_SRC, TEV_DATA_SCALAR, &src, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_nrecv", cc); return cc; } int pvm_parent() { int cc; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PARENT,TEV_EVENT_ENTRY)) TEV_FIN; } if (!(cc = BEATASK)) cc = pvmmyptid ? pvmmyptid : PvmNoParent; if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PARENT,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_PT, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0 && cc != PvmNoParent && cc != PvmParentNotSet ) lpvmerr("pvm_parent", cc); return cc; } int pvm_probe(tid, tag) int tid; int tag; { struct pmsg *up; struct pmsg *bestup; int bestcc = 0; int cc; int alrdy = 0; TEV_DECLS static struct timeval ztv = { 0, 0 }; if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PROBE,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_RST, TEV_DATA_SCALAR, &tid, 1, 1 ); TEV_PACK_INT( TEV_DID_RMC, TEV_DATA_SCALAR, &tag, 1, 1 ); TEV_PACK_INT( TEV_DID_RCX, TEV_DATA_SCALAR, &pvmmyctx, 1, 1 ); TEV_FIN; } } if (!(cc = BEATASK)) { for (up = pvmrxlist->m_link; 1; up = up->m_link) { if (up == pvmrxlist && bestcc) break; while (up == pvmrxlist) { if (alrdy) { cc = 0; goto done; } up = up->m_rlink; if ((cc = mroute(0, 0, 0, &ztv)) < 0) goto done; up = up->m_link; alrdy = 1; } if ((cc = recv_match(up->m_mid, tid, tag)) < 0) goto done; if (cc == 1) { bestup = up; break; } if (cc > bestcc) { bestcc = cc; bestup = up; } } bestup->m_flag &= ~MM_UPACK; cc = bestup->m_mid; } done: if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PROBE,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_probe", cc); return cc; } int pvm_pstat(tid) int tid; /* task */ { int sbf, rbf; int cc; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PSTAT,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_TT, TEV_DATA_SCALAR, &tid, 1, 1 ); TEV_FIN; } } if (!(cc = BEATASK)) { if (!TIDISTASK(tid)) cc = PvmBadParam; else { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); pvm_pkint(&tid, 1, 1); if ((cc = msendrecv(TIDPVMD, TM_PSTAT, SYSCTX_TM)) > 0) { pvm_upkint(&cc, 1, 1); pvm_freebuf(pvm_setrbuf(rbf)); } else pvm_setrbuf(rbf); pvm_freebuf(pvm_setsbuf(sbf)); } } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PSTAT,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_TST, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0 && cc != PvmNoTask) lpvmerr("pvm_pstat", cc); return cc; } int pvm_recv(tid, tag) int tid; int tag; { struct pmsg *up; struct pmsg *bestup; int bestcc = 0; int cc; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_RECV,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_RST, TEV_DATA_SCALAR, &tid, 1, 1 ); TEV_PACK_INT( TEV_DID_RMC, TEV_DATA_SCALAR, &tag, 1, 1 ); TEV_PACK_INT( TEV_DID_RCX, TEV_DATA_SCALAR, &pvmmyctx, 1, 1 ); TEV_FIN; } } if (!(cc = BEATASK)) { if (pvmrbuf) umbuf_free(pvmrbuf); pvmrbuf = 0; for (up = pvmrxlist->m_link; 1; up = up->m_link) { if (up == pvmrxlist && bestcc) break; while (up == pvmrxlist) { up = up->m_rlink; if ((cc = mroute(0, 0, 0, (struct timeval *)0)) < 0) goto done; #if defined(IMA_PGON) || defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) \ || defined(IMA_AIX5SP2) /* bypass matching of messages when in a precv that completed */ if (pvm_inprecv && pvm_inprecv->complete) return 0; #endif up = up->m_link; } if ((cc = recv_match(up->m_mid, tid, tag)) < 0) goto done; if (cc == 1) { bestup = up; break; } if (cc > bestcc) { bestcc = cc; bestup = up; } } LISTDELETE(bestup, m_link, m_rlink); bestup->m_flag &= ~MM_UPACK; if (!(cc = pvm_setrbuf(bestup->m_mid))) cc = bestup->m_mid; } done: if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_RECV,TEV_EVENT_EXIT)) { int nb, mc, src; TEV_PACK_INT( TEV_DID_MB, TEV_DATA_SCALAR, &cc, 1, 1 ); if (cc > 0) pvm_bufinfo(cc, &nb, &mc, &src); else nb = mc = src = -1; TEV_PACK_INT( TEV_DID_MNB, TEV_DATA_SCALAR, &nb, 1, 1 ); TEV_PACK_INT( TEV_DID_MC, TEV_DATA_SCALAR, &mc, 1, 1 ); TEV_PACK_INT( TEV_DID_MCX, TEV_DATA_SCALAR, &pvmmyctx, 1, 1 ); TEV_PACK_INT( TEV_DID_SRC, TEV_DATA_SCALAR, &src, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_recv", cc); return cc; } int (* pvm_recvf(new))() int (*new)__ProtoGlarp__((int,int,int)); { int (*old)() = recv_match; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_RECVF,TEV_EVENT_ENTRY)) TEV_FIN; } recv_match = new ? new : def_match; if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_RECVF,TEV_EVENT_EXIT)) TEV_FIN; TEV_ENDEXCL; } return old; } int pvm_send(tid, tag) int tid; /* dest task */ int tag; /* type code */ { static struct timeval ztv = { 0, 0 }; int tmp; int cc; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_SEND,TEV_EVENT_ENTRY)) { int nb = -1; pvm_bufinfo( ( pvmtrcsbfsave ) ? pvmtrcsbfsave : pvmsbuf->m_mid, &nb, (int *) NULL, (int *) NULL ); TEV_PACK_INT( TEV_DID_MNB, TEV_DATA_SCALAR, &nb, 1, 1 ); TEV_PACK_INT( TEV_DID_DST, TEV_DATA_SCALAR, &tid, 1, 1 ); TEV_PACK_INT( TEV_DID_MC, TEV_DATA_SCALAR, &tag, 1, 1 ); TEV_PACK_INT( TEV_DID_MCX, TEV_DATA_SCALAR, &pvmmyctx, 1, 1 ); TEV_FIN; } } if (!(cc = BEATASK)) { if ( tid == PVM_TRACE_TID && tag == PVM_TRACE_CODE ) { if ( TEV_MASK_CHECK( pvmtrc.tmask, TEV_USER_DEFINED ) ) { /* Schlopp In End of Event Marker */ enc_trc_fin(pvmsbuf); /* Send to Proper Tracer Destination */ pvmsbuf->m_ctx = pvmtrc.trcctx; if ((cc = mroute(pvmsbuf->m_mid, pvmtrc.trctid, pvmtrc.trctag, &ztv)) > 0) cc = 0; } else cc = 0; } else if (!pvmrescode && (!TIDISTASK(tid) || (tag & ~0x7fffffff))) cc = PvmBadParam; else if (!pvmsbuf) cc = PvmNoBuf; else { /* XXX short-ckt to us should go here. maybe can inc frag chain XXX count and make new message, put on pvmrxlist. */ pvmsbuf->m_ctx = pvmmyctx; if ((cc = mroute(pvmsbuf->m_mid, tid, tag, &ztv)) > 0) cc = 0; } } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_SEND,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_send", cc); return cc; } int pvm_sendsig(tid, signum) int tid; int signum; { int cc; int sbf, rbf; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_SENDSIG,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_TT, TEV_DATA_SCALAR, &tid, 1, 1 ); TEV_PACK_INT( TEV_DID_SN, TEV_DATA_SCALAR, &signum, 1, 1 ); TEV_FIN; } } if (!(cc = BEATASK)) { if (!TIDISTASK(tid)) cc = PvmBadParam; else { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); pvm_pkint(&tid, 1, 1); pvm_pkint(&signum, 1, 1); if ((cc = msendrecv(TIDPVMD, TM_SENDSIG, SYSCTX_TM)) > 0) { pvm_freebuf(pvm_setrbuf(rbf)); cc = 0; } else pvm_setrbuf(rbf); pvm_freebuf(pvm_setsbuf(sbf)); } } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_SENDSIG,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_sendsig", cc); return cc; } /* bubble() * * Move nonnegative els to head of array, negative ones to end. * Returns number of nonnegative els. */ static int bubble(n, a) int n; /* length of a */ int *a; { int r, w, t; for (w = r = 0; r < n; r++) { if (a[w] < 0) { if (a[r] >= 0) { t = a[w]; a[w] = a[r]; a[r] = t; w++; } } else { w++; } } return w; } #if defined(IMA_I860) || defined(IMA_CM5) static int pvmgetenvars(ep) char ***ep; { return 0; } #else /*defined(IMA_I860) || defined(IMA_CM5)*/ static int pvmgetenvars(ep) char ***ep; { char **xpl; /* vars to export */ int mxpl; /* cur length of xpl */ int nxpl; /* num vars found */ char buf[200]; char *p, *q; int n; if (p = getenv("PVM_EXPORT")) { mxpl = 5; xpl = TALLOC(mxpl, char *, "env"); xpl[0] = p - 11; nxpl = 1; while (1) { while (*p == ':') p++; if (!*p) break; n = (q = CINDEX(p, ':')) ? q - p : strlen(p); strncpy(buf, p, n); buf[n] = 0; if (q = getenv(buf)) { if (nxpl == mxpl) { mxpl += mxpl / 2 + 1; xpl = TREALLOC(xpl, mxpl, char *); } xpl[nxpl++] = q - n - 1; } p += n; } *ep = xpl; return nxpl; } else { return 0; } } #endif /*defined(IMA_I860) || defined(IMA_CM5)*/ int pvm_spawn(file, argv, flags, where, count, tids) char *file; char **argv; int flags; char *where; int count; int *tids; { int sbf, rbf; /* temp for current tx, rx msgs */ int ictx; int cc; int i, n; char **ep; int *tidlist = 0; char *p; char buf[TEV_MASK_LENGTH + 20]; TEV_DECLS if (p = getenv("PVMTASK")) i = pvmstrtoi(p) | flags; else i = flags; if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_SPAWN,TEV_EVENT_ENTRY)) { TEV_PACK_STRING( TEV_DID_SE, TEV_DATA_SCALAR, file ? file : "", 1, 1 ); TEV_PACK_STRING( TEV_DID_SW, TEV_DATA_SCALAR, where ? where : "", 1, 1 ); TEV_PACK_INT( TEV_DID_SF, TEV_DATA_SCALAR, &i, 1, 1 ); TEV_PACK_INT( TEV_DID_SC, TEV_DATA_SCALAR, &count, 1, 1 ); TEV_FIN; } } if (!(cc = BEATASK)) { if (count < 1) cc = PvmBadParam; else { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); pvm_pkstr(file); pvm_pkint(&i, 1, 1); pvm_pkstr(where ? where : ""); pvm_pkint(&count, 1, 1); if (argv) for (n = 0; argv[n]; n++); else n = 0; pvm_pkint(&n, 1, 1); for (i = 0; i < n; i++) pvm_pkstr(argv[i]); pvm_pkint( &(pvmctrc.outtid), 1, 1 ); pvm_pkint( &(pvmctrc.outctx), 1, 1 ); pvm_pkint( &(pvmctrc.outtag), 1, 1 ); pvm_pkint( &(pvmctrc.trctid), 1, 1 ); pvm_pkint( &(pvmctrc.trcctx), 1, 1 ); pvm_pkint( &(pvmctrc.trctag), 1, 1 ); n = pvmgetenvars(&ep) + 4; pvm_pkint(&n, 1, 1); n -= 4; sprintf(buf, "PVMTMASK=%s", pvmctrc.tmask); pvm_pkstr(buf); sprintf(buf, "PVMTRCBUF=%d", pvmctrc.trcbuf); pvm_pkstr(buf); sprintf(buf, "PVMTRCOPT=%d", pvmctrc.trcopt); pvm_pkstr(buf); sprintf(buf, "PVMCTX=0x%x", pvmmyctx); pvm_pkstr(buf); if (n > 0) { for (i = 0; i < n; i++) pvm_pkstr(ep[i]); PVM_FREE(ep); } if (pvmschedtid) cc = msendrecv(pvmschedtid, SM_SPAWN, PvmBaseContext); else cc = msendrecv(TIDPVMD, TM_SPAWN, SYSCTX_TM); if (cc > 0) { pvm_upkint(&cc, 1, 1); if (cc == count) { tidlist = tids ? tids : TALLOC(count, int, "xxx"); pvm_upkint(tidlist, cc, 1); cc = bubble(cc, tidlist); } pvm_freebuf(pvm_setrbuf(rbf)); } else pvm_setrbuf(rbf); pvm_freebuf(pvm_setsbuf(sbf)); if (cc > 0) { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); pvm_pkint(&cc, 1, 1); pvm_pkint(tidlist, cc, 1); ictx = pvm_setcontext(SYSCTX_TC); pvmmcast(pvmsbuf->m_mid, tidlist, cc, TC_SIBLINGS); pvm_setcontext(ictx); pvm_freebuf(pvm_setsbuf(sbf)); } } } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_SPAWN,TEV_EVENT_EXIT)) { int tevcount; TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); tevcount = ( cc > 0 ) ? cc : 0; TEV_PACK_INT( TEV_DID_STL, TEV_DATA_ARRAY, tidlist, tevcount, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (tidlist != tids && tidlist != NULL) PVM_FREE(tidlist); if (cc < 0) lpvmerr("pvm_spawn", cc); return cc; } int pvm_tasks(where, ntaskp, taskp) int where; /* which host or 0 for all */ int *ntaskp; struct pvmtaskinfo **taskp; { int cc, ec, sbf, rbf, ae; static struct pvmtaskinfo *tlist = 0; static int ntask = 0; int len1 = 5, len2 = 3; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_TASKS,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_TW, TEV_DATA_SCALAR, &where, 1, 1 ); TEV_FIN; } } if (tlist) { while (ntask-- > 0) PVM_FREE(tlist[ntask].ti_a_out); PVM_FREE(tlist); tlist = 0; ntask = 0; } if (!(cc = BEATASK)) { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); pvm_pkint(&where, 1, 1); if (pvmschedtid) cc = msendrecv(pvmschedtid, SM_TASK, PvmBaseContext); else cc = msendrecv(TIDPVMD, TM_TASK, SYSCTX_TM); if (cc > 0) { if (!(cc = pvm_upkint(&ec, 1, 1)) && (cc = ec) >= 0) { tlist = TALLOC(len1, struct pvmtaskinfo, "ti"); ae = pvm_setopt(PvmAutoErr, 0); ntask = 0; while (!pvm_upkint(&tlist[ntask].ti_tid, 1, 1)) { pvm_upkint(&tlist[ntask].ti_ptid, 1, 1); pvm_upkint(&tlist[ntask].ti_host, 1, 1); pvm_upkint(&tlist[ntask].ti_flag, 1, 1); pvmupkstralloc(&(tlist[ntask].ti_a_out)); pvm_upkint(&tlist[ntask].ti_pid, 1, 1); ntask++; if (ntask == len1) { len1 += len2; len2 = ntask; tlist = TREALLOC(tlist, len1, struct pvmtaskinfo); } } pvm_setopt(PvmAutoErr, ae); cc = 0; } pvm_freebuf(pvm_setrbuf(rbf)); if (ntaskp) *ntaskp = ntask; if (taskp) *taskp = tlist; } else pvm_setrbuf(rbf); pvm_freebuf(pvm_setsbuf(sbf)); } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_TASKS,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_PACK_INT( TEV_DID_TNT, TEV_DATA_SCALAR, &ntask, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_tasks", cc); return cc; } int pvm_tickle(narg, argp, nresp, resp) int narg; int *argp; int *nresp; int *resp; { int cc; int sbf, rbf; int nres; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_TICKLE,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_TA, TEV_DATA_ARRAY, argp, narg, 1 ); TEV_FIN; } } if (!(cc = BEATASK)) { if (narg < 1 || narg > 10) cc = PvmBadParam; else { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); pvm_pkint(&narg, 1, 1); pvm_pkint(argp, narg, 1); if ((cc = msendrecv(TIDPVMD, TM_TICKLE, SYSCTX_TM)) > 0) { pvm_upkint(&nres, 1, 1); if (nresp) *nresp = nres; if (resp) pvm_upkint(resp, nres, 1); pvm_freebuf(pvm_setrbuf(rbf)); cc = 0; } else pvm_setrbuf(rbf); pvm_freebuf(pvm_setsbuf(sbf)); } } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_TICKLE,TEV_EVENT_EXIT)) { int tevcount; TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); tevcount = ( resp ) ? nres : 0; TEV_PACK_INT( TEV_DID_TR, TEV_DATA_ARRAY, resp, tevcount, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_tickle", cc); return cc; } int pvm_tidtohost(tid) int tid; { return (tid & TIDHOST); } int pvm_trecv(tid, tag, tmout) int tid; /* source tid to match */ int tag; /* message tag to match */ struct timeval *tmout; /* time to wait for match */ { struct pmsg *up; struct pmsg *bestup; int bestcc = 0; int cc; struct timeval tin, tnow; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_TRECV,TEV_EVENT_ENTRY)) { int ts, tu; TEV_PACK_INT( TEV_DID_RST, TEV_DATA_SCALAR, &tid, 1, 1 ); TEV_PACK_INT( TEV_DID_RMC, TEV_DATA_SCALAR, &tag, 1, 1 ); TEV_PACK_INT( TEV_DID_RCX, TEV_DATA_SCALAR, &pvmmyctx, 1, 1 ); if (tmout) { ts = tmout->tv_sec; tu = tmout->tv_usec; } else ts = tu = -1; TEV_PACK_INT( TEV_DID_MTS, TEV_DATA_SCALAR, &ts, 1, 1 ); TEV_PACK_INT( TEV_DID_MTU, TEV_DATA_SCALAR, &tu, 1, 1 ); TEV_FIN; } } pvmgetclock(&tin); if (!(cc = BEATASK)) { if (pvmrbuf) umbuf_free(pvmrbuf); pvmrbuf = 0; for (up = pvmrxlist->m_link; 1; up = up->m_link) { if (up == pvmrxlist && bestcc) break; while (up == pvmrxlist) { up = up->m_rlink; if (tmout) { pvmgetclock(&tnow); TVXSUBY(&tnow, &tnow, &tin); if (TVXLTY(tmout, &tnow)) { if (bestcc) goto fnd; cc = 0; if (!TVISSET(tmout)) { if ((cc = mroute(0, 0, 0, tmout)) <= 0) goto done; } else goto done; } else { TVXSUBY(&tnow, tmout, &tnow); if ((cc = mroute(0, 0, 0, &tnow)) < 0) goto done; } } else { if ((cc = mroute(0, 0, 0, (struct timeval *)0)) < 0) goto done; } up = up->m_link; } if ((cc = recv_match(up->m_mid, tid, tag)) < 0) goto done; if (cc == 1) { bestup = up; break; } if (cc > bestcc) { bestcc = cc; bestup = up; } } fnd: LISTDELETE(bestup, m_link, m_rlink); bestup->m_flag &= ~MM_UPACK; if (!(cc = pvm_setrbuf(bestup->m_mid))) cc = bestup->m_mid; } done: if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_TRECV,TEV_EVENT_EXIT)) { int nb, mc, src; TEV_PACK_INT( TEV_DID_MB, TEV_DATA_SCALAR, &cc, 1, 1 ); if (cc > 0) pvm_bufinfo(cc, &nb, &mc, &src); else nb = mc = src = -1; TEV_PACK_INT( TEV_DID_MNB, TEV_DATA_SCALAR, &nb, 1, 1 ); TEV_PACK_INT( TEV_DID_MC, TEV_DATA_SCALAR, &mc, 1, 1 ); TEV_PACK_INT( TEV_DID_MCX, TEV_DATA_SCALAR, &pvmmyctx, 1, 1 ); TEV_PACK_INT( TEV_DID_SRC, TEV_DATA_SCALAR, &src, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_trecv", cc); return cc; } char * pvm_version() { static char *_pvm_version_str = PVM_VER; return(_pvm_version_str); } int pvm_reg_rm(hip) struct pvmhostinfo **hip; { int old_sched; int cc; int sbf; int rbf; /* char buf[256]; XXX static limit, argh (Not Any More! :-) JAK */ static struct pvmhostinfo *hin = 0; static int mbindex = -1; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_REG_RM,TEV_EVENT_ENTRY)) { TEV_FIN; } } if (!(cc = BEATASK)) { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); if (pvmschedtid) cc = msendrecv(pvmschedtid, SM_SCHED, PvmBaseContext); else cc = msendrecv(TIDPVMD, TM_SCHED, SYSCTX_TM); if (cc > 0) { pvm_upkint(&cc, 1, 1); if (cc >= 0) { if (hin) { PVM_FREE(hin->hi_name); PVM_FREE(hin->hi_arch); } else hin = TALLOC(1, struct pvmhostinfo, "hi"); pvm_upkint(&hin->hi_tid, 1, 1); pvmupkstralloc(&(hin->hi_name)); pvmupkstralloc(&(hin->hi_arch)); pvm_upkint(&hin->hi_speed, 1, 1); if (hip) *hip = hin; if ( mbindex >= 0 ) pvm_delinfo( PVMRMCLASS, mbindex, PvmMboxDefault ); pvm_setsbuf(pvm_mkbuf(PvmDataDefault)); pvm_pkint(&pvmmytid,1,1); mbindex = pvm_putinfo( PVMRMCLASS, pvm_getsbuf(), PvmMboxMultiInstance ); } pvm_freebuf(pvm_setrbuf(rbf)); } else pvm_setrbuf(rbf); pvm_freebuf(pvm_setsbuf(sbf)); } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_REG_RM,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_reg_rm", cc); return cc; } int pvm_reg_tasker() { static int imit = 0; /* i'm the tasker */ static int mbindex = -1; /* mbox index */ int cc; int sbf; int rbf; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_REG_TASKER,TEV_EVENT_ENTRY)) { TEV_FIN; } } if (!(cc = BEATASK)) { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); cc = imit ? 0 : 1; pvm_pkint(&cc, 1, 1); cc = msendrecv(TIDPVMD, TM_TASKER, SYSCTX_TM); if (cc > 0) { pvm_upkint(&cc, 1, 1); if (!cc) { imit = !imit; if ( imit ) { pvm_setsbuf(pvm_mkbuf(PvmDataDefault)); pvm_pkint(&pvmmytid,1,1); mbindex = pvm_putinfo( PVMTASKERCLASS, pvm_getsbuf(), PvmMboxMultiInstance ); } else if ( mbindex >= 0 ) { if ( pvm_delinfo( PVMTASKERCLASS, mbindex, PvmMboxDefault ) >= 0 ) { mbindex = -1; } } } pvm_freebuf(pvm_setrbuf(rbf)); } else pvm_setrbuf(rbf); pvm_freebuf(pvm_setsbuf(sbf)); } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_REG_TASKER,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_reg_tasker", cc); return cc; } int pvm_reg_hoster() { static int imit = 0; /* i'm the hoster */ static int mbindex = -1; /* mbox index */ int cc; int sbf; int rbf; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_REG_HOSTER,TEV_EVENT_ENTRY)) { TEV_FIN; } } if (!(cc = BEATASK)) { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); cc = imit ? 0 : 1; pvm_pkint(&cc, 1, 1); cc = msendrecv(TIDPVMD, TM_HOSTER, SYSCTX_TM); if (cc > 0) { pvm_upkint(&cc, 1, 1); if (!cc) { imit = !imit; if ( imit ) { pvm_setsbuf(pvm_mkbuf(PvmDataDefault)); pvm_pkint(&pvmmytid,1,1); mbindex = pvm_putinfo( PVMHOSTERCLASS, pvm_getsbuf(), PvmMboxMultiInstance ); } else if ( mbindex >= 0 ) { if ( pvm_delinfo( PVMHOSTERCLASS, mbindex, PvmMboxDefault ) >= 0 ) { mbindex = -1; } } } pvm_freebuf(pvm_setrbuf(rbf)); } else pvm_setrbuf(rbf); pvm_freebuf(pvm_setsbuf(sbf)); } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_REG_HOSTER,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_reg_hoster", cc); return cc; } int pvm_reg_tracer( tctx, ttag, octx, otag, tmask, tbuf, topt ) int tctx; int ttag; int octx; int otag; Pvmtmask tmask; int tbuf; int topt; { static int imit = 0; /* i'm the tracer */ static int mbindex = -1; /* mbox index */ int cc; int sbf; int rbf; int x; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_REG_TRACER,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_TRC, TEV_DATA_SCALAR, &tctx, 1, 1 ); TEV_PACK_INT( TEV_DID_TRT, TEV_DATA_SCALAR, &ttag, 1, 1 ); TEV_PACK_INT( TEV_DID_TRX, TEV_DATA_SCALAR, &octx, 1, 1 ); TEV_PACK_INT( TEV_DID_TRO, TEV_DATA_SCALAR, &otag, 1, 1 ); TEV_PACK_STRING( TEV_DID_TRM, TEV_DATA_SCALAR, tmask, 1, 1 ); TEV_PACK_INT( TEV_DID_TRB, TEV_DATA_SCALAR, &tbuf, 1, 1 ); TEV_PACK_INT( TEV_DID_TRL, TEV_DATA_SCALAR, &topt, 1, 1 ); TEV_FIN; } } if (!(cc = BEATASK)) { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); cc = imit ? 0 : 1; pvm_pkint(&cc, 1, 1); if ( cc ) { pvm_pkint(&tctx, 1, 1); pvm_pkint(&ttag, 1, 1); pvm_pkint(&octx, 1, 1); pvm_pkint(&otag, 1, 1); pvm_pkstr(tmask); pvm_pkint(&tbuf, 1, 1); pvm_pkint(&topt, 1, 1); } cc = msendrecv(TIDPVMD, TM_TRACER, SYSCTX_TM); if (cc > 0) { pvm_upkint(&cc, 1, 1); if (!cc) { imit = !imit; if ( imit ) { pvm_setsbuf(pvm_mkbuf(PvmDataDefault)); pvm_pkint(&pvmmytid,1,1); pvm_pkint(&tctx, 1, 1); pvm_pkint(&ttag, 1, 1); pvm_pkint(&octx, 1, 1); pvm_pkint(&otag, 1, 1); pvm_pkstr(tmask); pvm_pkint(&tbuf, 1, 1); pvm_pkint(&topt, 1, 1); mbindex = pvm_putinfo( PVMTRACERCLASS, pvm_getsbuf(), PvmMboxDefault ); } else if ( mbindex >= 0 ) { if ( pvm_delinfo( PVMTRACERCLASS, mbindex, PvmMboxDefault ) >= 0 ) { mbindex = -1; } } } pvm_freebuf(pvm_setrbuf(rbf)); } else pvm_setrbuf(rbf); pvm_freebuf(pvm_setsbuf(sbf)); } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_REG_TRACER,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_reg_tracer", cc); return cc; } /* pvm_hostsync() * * Get time of day clock from remote host. * Returns current time on remote host, * difference between local clock and remote host clock. * * Note the delta time is a 2s-compl./1000000-compl. signed timeval. * Positive values are normal, negative ones are f.e.: * -1 uSec = -1,999999 * -1 Sec = -1,000000 * -1.1 Sec = -2,999000 */ int pvm_hostsync(host, clk, delta) int host; /* pvmd tid of host */ struct timeval *clk; /* current time on host */ struct timeval *delta; /* time relative to local clock */ { int cc; int sbf, rbf; struct timeval myta, mytb, remt; int i[2]; if (!(cc = BEATASK)) { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); pvm_pkint(&host, 1, 1); gettimeofday(&myta, (struct timezone *) NULL); if ((cc = msendrecv(TIDPVMD, TM_HOSTSYNC,SYSCTX_TM)) > 0) { gettimeofday(&mytb, (struct timezone *) NULL); pvm_upkint(&cc, 1, 1); if (cc >= 0) { cc = 0; pvm_upkint(i, 2, 1); remt.tv_sec = i[0]; remt.tv_usec = i[1]; if (clk) *clk = remt; if (delta) { TVDIVN(&myta, &myta, 2); TVDIVN(&mytb, &mytb, 2); TVXADDY(&myta, &myta, &mytb); TVXSUBY(&myta, &myta, &remt); *delta = myta; } } pvm_freebuf(pvm_setrbuf(rbf)); } else pvm_setrbuf(rbf); pvm_freebuf(pvm_setsbuf(sbf)); } if (cc < 0) lpvmerr("pvm_host_sync", cc); return cc; } /* pvm_gettmask() * * Get our (or child) trace mask. */ int pvm_gettmask(who, tmask) int who; Pvmtmask tmask; { int i; char *tm = 0; if (who == PvmTaskChild) tm = pvmctrc.tmask; else if (who == PvmTaskSelf) tm = pvmtrc.tmask; if (!tm) return lpvmerr("pvm_gettmask", PvmBadParam); BCOPY(tm, tmask, TEV_MASK_LENGTH); return PvmOk; } /* pvm_settmask() * * Set our (or child's) trace mask. */ int pvm_settmask(who, tmask) int who; Pvmtmask tmask; { int i; char *tm = 0; if (who == PvmTaskChild) tm = pvmctrc.tmask; else if (who == PvmTaskSelf) tm = pvmtrc.tmask; if (!tm) return lpvmerr("pvm_settmask", PvmBadParam); BCOPY(tmask, tm, TEV_MASK_LENGTH); return PvmOk; } int pvm_archcode(arch) char *arch; { struct pvmhostinfo *hlist; int sbf, rbf, cc; int nhost, narch; int i; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_ARCHCODE,TEV_EVENT_ENTRY)) { TEV_PACK_STRING( TEV_DID_AN, TEV_DATA_SCALAR, arch ? arch : "", 1, 1 ); TEV_FIN; } } if (!arch) cc = PvmBadParam; else { /* Go get pvm_config() info... :-Q :-Q :-Q */ /* (can't use pvm_config() directly, as stomps */ /* hostinfo structure... Damn. */ if (!(cc = BEATASK)) { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); if (pvmschedtid) cc = msendrecv(pvmschedtid, SM_CONFIG, PvmBaseContext); else cc = msendrecv(TIDPVMD, TM_CONFIG, SYSCTX_TM); if (cc > 0) { pvm_upkint(&nhost, 1, 1); pvm_upkint(&narch, 1, 1); hlist = TALLOC(nhost, struct pvmhostinfo, "hi"); for (i = 0; i < nhost; i++) { pvm_upkint(&hlist[i].hi_tid, 1, 1); pvmupkstralloc(&(hlist[i].hi_name)); pvmupkstralloc(&(hlist[i].hi_arch)); pvm_upkint(&hlist[i].hi_speed, 1, 1); pvm_upkint(&hlist[i].hi_dsig, 1, 1); } pvm_freebuf(pvm_setrbuf(rbf)); } pvm_freebuf(pvm_setsbuf(sbf)); pvm_setrbuf(rbf); cc = PvmNotFound; for ( i=0 ; i < nhost ; i++ ) { if ( !strcmp(hlist[i].hi_arch, arch) ) { cc = hlist[i].hi_dsig; break; } } while (nhost-- > 0) { PVM_FREE(hlist[nhost].hi_name); PVM_FREE(hlist[nhost].hi_arch); } PVM_FREE(hlist); } } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_ARCHCODE,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_AC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_archcode", cc); return( cc ); } int pvm_newcontext() { int sbf, rbf, cc; int mid = -1; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_NEWCONTEXT,TEV_EVENT_ENTRY)) { TEV_FIN; } } if (!(cc = BEATASK)) { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); cc = 0; pvm_pkint(&cc, 1, 1); if ((cc = msendrecv(TIDPVMD, TM_CONTEXT, SYSCTX_TM)) > 0) { pvm_upkint(&cc, 1, 1); pvm_freebuf(pvm_setrbuf(rbf)); } else pvm_setrbuf(rbf); pvm_freebuf(pvm_setsbuf(sbf)); } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_NEWCONTEXT,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CXN, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_newcontext", cc); return cc; } int pvm_freecontext(cid) int cid; { int sbf, rbf, cc; int mid = -1; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_FREECONTEXT,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_CXF, TEV_DATA_SCALAR, &cid, 1, 1 ); TEV_FIN; } } if (!(cc = BEATASK)) { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); pvm_pkint(&cid, 1, 1); if ((cc = msendrecv(TIDPVMD, TM_CONTEXT, SYSCTX_TM)) > 0) { pvm_upkint(&cc, 1, 1); pvm_freebuf(pvm_setrbuf(rbf)); } else pvm_setrbuf(rbf); pvm_freebuf(pvm_setsbuf(sbf)); } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_FREECONTEXT,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_freecontext", cc); return cc; } int pvm_getcontext() { TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_GETCONTEXT,TEV_EVENT_ENTRY)) { TEV_FIN; } } /* Yep, overkill... */ if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_GETCONTEXT,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CXC, TEV_DATA_SCALAR, &pvmmyctx, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return pvmmyctx; } int pvm_setcontext(newctx) int newctx; { int c; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_SETCONTEXT,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_CXS, TEV_DATA_SCALAR, &newctx, 1, 1 ); TEV_FIN; } } c = pvmmyctx; pvmmyctx = newctx; if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_SETCONTEXT,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &c, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return c; } /* * pvm_addmhf() * * add message handler function * * function returns: * index ( >= 0 ) message handler * - can be used to delete the handler via pvm_delmhf() * PvmExists - can't insert as handler already exists * - search by (tag, ctx, src) including "wild-cards" (-1) * */ int pvm_addmhf(src, tag, ctx, f) int src, tag, ctx; /* message source, context, tag */ #ifdef IMA_SCO int (*f)(int); /* handler function */ #else int (*f)(); /* handler function */ #endif { int i; /* temp local */ int hand; /* index into handles[] array -->> internal use only */ /* - not for user */ int mhid; /* message handler index -->> into dhandles[] */ /* -->> give to user */ int exists = 0; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_ADDMHF,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_RST, TEV_DATA_SCALAR, &src, 1, 1 ); TEV_PACK_INT( TEV_DID_RMC, TEV_DATA_SCALAR, &tag, 1, 1 ); TEV_PACK_INT( TEV_DID_RCX, TEV_DATA_SCALAR, &ctx, 1, 1 ); TEV_FIN; } } /* * confirm that does not already exist within "handles" * this includes "wild-card" options in both directions too... * * search from most recently added message handler to system * added message handlers */ for ( i=nhandles-1 ; i >= 0 && !exists ; i-- ){ if ((handles[i].header.tag == -1 || handles[i].header.tag == tag || tag == -1) && (handles[i].header.ctx == -1 || handles[i].header.ctx == ctx || ctx == -1) && (handles[i].header.src == -1 || handles[i].header.src == src || src == -1)) { exists++; } } /* * see if there are any already on free list * - use existing if on free list * - create new if none free - two scenarios: * 1. may be initial message handlers * 2. may be additional message handlers and lists just full * * note: ndhandles never decreases - thus if less than nhandles, * must be some free slots... */ if ( exists ) mhid = PvmExists; else if (ndhandles > nhandles){ /* * there exist some free slots */ mhid = fl_dhandles; /* take from head of free list */ nhandles++; /* incr actual # of active headers */ /* * move next one to head of free list * if tail of list - will move "tail marker" (-1) to * fl_dhandles to indicte empty list */ fl_dhandles = dhandles[mhid].mhid; /* * fill the lists now... */ dhandles[mhid].mhid = mhid; /* set to self */ /* dhandles[mhid].handle no change here as should be next */ /* contiguous on handles[] */ hand = dhandles[mhid].handle; /* set to index -> handles[] */ handles[hand].mhid = mhid; /* set to corresponding mhid */ handles[hand].header.tag = tag; handles[hand].header.ctx = ctx; handles[hand].header.src = src; handles[hand].f = f; /* sonnofabeech! */ } else{ /* no free slots available - will have to allocate more slots... * two scenarios for this: * 1. first time adding message handlers - none ever * allocated. * 2. all presently allocated are filled and active - but * been here before. * * note: since no free slots, must have case of: * ndhandles == nhandles * * ndhandles : is the "high-water" mark as it is never decreased * nhandles : indicates the actual number of active handles */ if (ndhandles == 0){ /* first time here - allocate new memory... */ dhandles = TALLOC(++ndhandles, struct dhandler, "dhandles"); handles = TALLOC(++nhandles, struct mhandler, "mhandle"); } else{ /* been here! - reallocate more space... */ dhandles = TREALLOC(dhandles, ++ndhandles, struct dhandler); handles = TREALLOC(handles, ++nhandles, struct mhandler); } mhid = ndhandles - 1; /* set index into dhandles */ /* * fill the lists now... */ dhandles[mhid].mhid = mhid; /* set to self */ dhandles[mhid].handle = mhid; /* set same since lists full */ handles[mhid].mhid = mhid; handles[mhid].header.tag = tag; handles[mhid].header.ctx = ctx; handles[mhid].header.src = src; handles[mhid].f = f; /* sonnofabeech! */ } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_ADDMHF,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_MHI, TEV_DATA_SCALAR, &mhid, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (mhid < 0) lpvmerr("pvm_addmhf", mhid); return mhid; /* return message handler */ /* -->> index into dhandles[] */ } /* pvm_addmhf */ /* * pvm_delmhf() * * delete message handler function * * function returns: * PvmBadParam - negative mhid value * PvmNotFound - mhid not found in list * - possibly deleted before... * - possibly never existed (access past end of list index) * - return PvmNotFound but no error message as is normal * operation... * PvmOk */ int pvm_delmhf(mhid) int mhid; /* message handler index */ { char *errstr; int htoid; /* handle - moved to - id location */ int hfrid; /* handle - moved from - id location */ int rc = 0; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_DELMHF,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_MHI, TEV_DATA_SCALAR, &mhid, 1, 1 ); TEV_FIN; } } /* * check incomming parameter at lower and upper boundary * - can't have negative mhid values * - too high an index - mhid entry does not exist */ if (mhid < 0) { /* too low */ errstr = "pvm_delmhf"; rc = PvmBadParam; } else if (mhid >= ndhandles) { /* too high */ errstr = "(mhid >= ndhandles) pvm_delmhf"; rc = PvmNotFound; } /* * make sure is not already on free list - can only delete active * mhid entries * * confirm active by: * since handles is contiguous at low order indices, thus any * entry in dhandles[x].handle less-than nhandles is an active * entry and may be deleted */ if ( rc >= 0 ) { if ( dhandles[mhid].handle < nhandles ) { /* * this one's active - delete it */ nhandles--; /* reduce # of active handles[] entries */ htoid = dhandles[mhid].handle; /* handle - moved to */ /* -id location */ hfrid = nhandles; /* handle - moved from - id loc */ /* Don't Spank List if Last Entry... D-Oh! */ if ( htoid != hfrid ) { /* * move the last "active" handle[] entry up to "deleted" * location */ handles[htoid] = handles[hfrid]; /* the move */ /* unnecessary?! handles[hfrid].mhid = htoid; */ /* ("back-link" ptr adjust?) */ /* * adjust dhandles[] to point to * 1. the moved "up" entry * 2. the "deleted" entry */ /* 1. the moved "up" entry */ dhandles[handles[htoid].mhid].handle = htoid; /* 2. the "deleted" entry */ dhandles[mhid].handle = hfrid; } /* * put the "freed" dhandle entry (mhid value) on head of * the free list */ /* link this to previous free list */ dhandles[mhid].mhid = fl_dhandles; fl_dhandles = mhid; /* put this one on head of list */ } else { /* this one is already on free list - not active entry */ errstr = "pvm_delmhf"; rc = PvmNotFound; } } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_DELMHF,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &rc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (rc < 0) lpvmerr(errstr, rc); return( rc ); } /* pvm_delmhf */ int pvm_putinfo(name, mid, flags) char *name; /* class name */ int mid; /* message to store */ int flags; /* options */ { int index = -1; int sbf, rbf, cc; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PUTINFO,TEV_EVENT_ENTRY)) { TEV_PACK_STRING( TEV_DID_CN, TEV_DATA_SCALAR, name ? name : "", 1, 1 ); TEV_PACK_INT( TEV_DID_CI, TEV_DATA_SCALAR, &index, 1, 1 ); TEV_PACK_INT( TEV_DID_CF, TEV_DATA_SCALAR, &flags, 1, 1); TEV_PACK_INT( TEV_DID_CD, TEV_DATA_SCALAR, &mid, 1, 1 ); TEV_FIN; } } if (!name || !*name || index < -1) { cc = PvmBadParam; } else { if (!(cc = BEATASK)) { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); cc = TMDB_PUT; pvm_pkint(&cc, 1, 1); pvm_pkint(&pvmmytid, 1, 1); pvm_pkstr(name); pvm_pkint(&index, 1, 1); pvm_pkint(&flags, 1, 1); pvm_pkmesg(mid); if ((cc = msendrecv(TIDPVMD, TM_DB, SYSCTX_TM)) > 0) { pvm_upkint(&cc, 1, 1); pvm_freebuf(pvm_setrbuf(rbf)); } else pvm_setrbuf(rbf); pvm_freebuf(pvm_setsbuf(sbf)); } } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PUTINFO,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) if (cc != PvmDenied && cc != PvmExists) lpvmerr("pvm_putinfo", cc); else pvm_errno = cc; return cc; } int pvm_recvinfo(name, index, flags) char *name; /* class name */ int index; /* req class index or -1 for any */ int flags; /* options */ { int sbf, cc; int mid = -1; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_GETINFO,TEV_EVENT_ENTRY)) { TEV_PACK_STRING( TEV_DID_CN, TEV_DATA_SCALAR, name ? name : "", 1, 1 ); TEV_PACK_INT( TEV_DID_CI, TEV_DATA_SCALAR, &index, 1, 1 ); TEV_PACK_INT( TEV_DID_CF, TEV_DATA_SCALAR, &flags, 1, 1 ); TEV_FIN; } } if (!name || !*name || index < 0) { cc = PvmBadParam; } else { if (!(cc = BEATASK)) { if (pvmrbuf) umbuf_free(pvmrbuf); pvmrbuf = 0; sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); cc = TMDB_GET; pvm_pkint(&cc, 1, 1); pvm_pkint(&pvmmytid, 1, 1); pvm_pkstr(name); pvm_pkint(&index, 1, 1); pvm_pkint(&flags, 1, 1); if ((cc = msendrecv(TIDPVMD, TM_DB, SYSCTX_TM)) > 0) { pvm_upkint(&cc, 1, 1); if (cc >= 0) { mid = pvm_upkmesg(); pvm_freebuf(pvm_setrbuf(mid)); } } pvm_freebuf(pvm_setsbuf(sbf)); } } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_GETINFO,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_PACK_INT( TEV_DID_CR, TEV_DATA_SCALAR, &mid, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if ( cc < 0 ) { if ( cc != PvmNotFound ) lpvmerr("pvm_recvinfo", cc); else pvm_errno = cc; return cc; } else return mid; } int pvm_delinfo(name, index, flags) char *name; /* class name */ int index; /* class index or -1 for all */ int flags; /* options */ { int sbf, rbf, cc; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_DELINFO,TEV_EVENT_ENTRY)) { TEV_PACK_STRING( TEV_DID_CN, TEV_DATA_SCALAR, name ? name : "", 1, 1 ); TEV_PACK_INT( TEV_DID_CI, TEV_DATA_SCALAR, &index, 1, 1 ); TEV_PACK_INT( TEV_DID_CF, TEV_DATA_SCALAR, &flags, 1, 1 ); TEV_FIN; } } if (!name || !*name || index < 0) { cc = PvmBadParam; } else { if (!(cc = BEATASK)) { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); cc = TMDB_REMOVE; pvm_pkint(&cc, 1, 1); pvm_pkint(&pvmmytid, 1, 1); pvm_pkstr(name); pvm_pkint(&index, 1, 1); pvm_pkint(&flags, 1, 1); if ((cc = msendrecv(TIDPVMD, TM_DB, SYSCTX_TM)) > 0) { pvm_upkint(&cc, 1, 1); pvm_freebuf(pvm_setrbuf(rbf)); } else pvm_setrbuf(rbf); pvm_freebuf(pvm_setsbuf(sbf)); } } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_DELINFO,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) if (cc != PvmDenied && cc != PvmNotFound) lpvmerr("pvm_delinfo", cc); else pvm_errno = cc; return cc; } int pvm_getmboxinfo(pattern, nclasses, classes) char *pattern; /* class name */ int *nclasses; /* number of classes returned */ struct pvmmboxinfo **classes; /* name list returned */ { static struct pvmmboxinfo *clist = (struct pvmmboxinfo *) NULL; static int nclist = 0; int sbf, rbf, cc; int i, j; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_GETMBOXINFO,TEV_EVENT_ENTRY)) { TEV_PACK_STRING( TEV_DID_CN, TEV_DATA_SCALAR, pattern ? pattern : "", 1, 1 ); TEV_FIN; } } if ( !pattern ) pattern = ""; if ( clist ) { for ( i=0 ; i < nclist ; i++ ) { if ( clist[i].mi_name ) PVM_FREE( clist[i].mi_name ); if ( clist[i].mi_indices ) PVM_FREE( clist[i].mi_indices ); if ( clist[i].mi_owners ) PVM_FREE( clist[i].mi_owners ); if ( clist[i].mi_flags ) PVM_FREE( clist[i].mi_flags ); } PVM_FREE( clist ); clist = (struct pvmmboxinfo *) NULL; nclist = 0; } if ( !(cc = BEATASK) ) { sbf = pvm_setsbuf( pvm_mkbuf( PvmDataFoo ) ); rbf = pvm_setrbuf( 0 ); cc = TMDB_NAMES; pvm_pkint( &cc, 1, 1 ); pvm_pkint( &pvmmytid, 1, 1 ); pvm_pkstr( pattern ); cc = 0; pvm_pkint( &cc, 1, 1 ); pvm_pkint( &cc, 1, 1 ); if ( (cc = msendrecv( TIDPVMD, TM_DB, SYSCTX_TM )) > 0 ) { pvm_upkint( &cc, 1, 1 ); if ( cc >= 0 ) { pvm_upkint( &nclist, 1, 1 ); clist = TALLOC( nclist, struct pvmmboxinfo, "classes" ); for ( i=0 ; i < nclist ; i++ ) { pvmupkstralloc( &(clist[i].mi_name) ); pvm_upkint( &(clist[i].mi_nentries), 1, 1 ); clist[i].mi_indices = TALLOC( clist[i].mi_nentries, int, "class_indices" ); clist[i].mi_owners = TALLOC( clist[i].mi_nentries, int, "class_owners" ); clist[i].mi_flags = TALLOC( clist[i].mi_nentries, int, "class_flags" ); for ( j=0 ; j < clist[i].mi_nentries ; j++ ) { pvm_upkint( &(clist[i].mi_indices[j]), 1, 1 ); pvm_upkint( &(clist[i].mi_owners[j]), 1, 1 ); pvm_upkint( &(clist[i].mi_flags[j]), 1, 1 ); } } if (classes) *classes = clist; if (nclasses) *nclasses = nclist; } pvm_freebuf(pvm_setrbuf(rbf)); } else pvm_setrbuf(rbf); pvm_freebuf(pvm_setsbuf(sbf)); } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_GETMBOXINFO,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_getmboxinfo", cc); return cc; } int pvm_siblings(tidsp) int **tidsp; { static int pvmsiblings_me[1]; int cc = PvmParentNotSet; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_SIBLINGS,TEV_EVENT_ENTRY)) { TEV_FIN; } } if (pvmnsibs == -1) /* only call pvm_parent if we haven't gotten sibs */ cc = pvm_parent(); if (cc > 0 || cc == PvmParentNotSet) { /* wait for pvmnsibs to be set by spawning program */ while (pvmnsibs == -1) { cc = mroute(0, 0, 0, (struct timeval *)0); if (cc < 0) break; } if (pvmnsibs != -1) { cc = pvmnsibs; *tidsp = pvmsibtids; } } else if (cc == PvmNoParent) /* I am my only sibling */ { cc = 1; pvmsiblings_me[0] = pvmmytid; *tidsp = pvmsiblings_me; } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_SIBLINGS,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_SIB, TEV_DATA_ARRAY, pvmsibtids, cc, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_siblings", cc); return cc; } int pvm_export(name) char *name; { char *vn = "PVM_EXPORT"; char *e; char *p, *q; int l; if (!name[0]) goto done; if (e = getenv(vn)) { p = e; while (*p) { while (*p == ':') p++; q = p; while (*q && *q != ':') q++; l = q - p; if (strlen(name) == l && !strncmp(name, p, l)) goto done; p = q; } p = TALLOC(strlen(vn) + strlen(e) + strlen(name) + 3, char, "str"); strcpy(p, vn); strcat(p, "="); strcat(p, e); if (e[0]) strcat(p, ":"); strcat(p, name); pvmputenv(p); } else { e = TALLOC(strlen(vn) + strlen(name) + 2, char, "str"); strcpy(e, vn); strcat(e, "="); strcat(e, name); pvmputenv(e); } done: /* e = getenv(vn); pvmlogprintf("pvm_export() %s=%s\n", vn, e); */ return 0; } int pvm_unexport(name) char *name; { char *vn = "PVM_EXPORT"; char *e, *enew; char *p, *q; int l; if (!name[0]) goto done; if (e = getenv(vn)) { p = e; while (*p) { while (*p == ':') p++; q = p; while (*q && *q != ':') q++; l = q - p; if (strlen(name) == l && !strncmp(name, p, l)) { if (*q == ':') q++; else if (p > e && *(p - 1) == ':') p--; enew = TALLOC(strlen(vn) + (p - e) + strlen(q) + 2, char, "str"); strcpy(enew, vn); strcat(enew, "="); strncat(enew, e, p - e); strcat(enew, q); pvmputenv(enew); goto done; } p = q; } } done: /* e = getenv(vn); pvmlogprintf("pvm_unexport() %s=%s\n", vn, e); */ return 0; } /* pvmreset() * * One handy routine for cleaning up the virtual machine. * Used by "pvm" console, XPVM and whoever else is in a * tidy mood. Not necessarily for public consumption... */ int pvmreset( mytid, killtasks, class, index ) int mytid; int killtasks; char *class; int index; { struct pvmtaskinfo *tip; int ntask; int *noresets = (int *) NULL; int nnr = 0; int sbf, rbf; int found; int i, j; int cc; if ( !pvm_tasks( 0, &ntask, &tip ) && ntask > 0 ) { pvm_getnoresets( &noresets, &nnr ); for ( i=0 ; i < ntask && killtasks ; i++ ) { for ( j=0, found=0 ; j < nnr && !found ; j++ ) if ( noresets[j] == tip[i].ti_tid ) found++; if ( !found && tip[i].ti_tid && tip[i].ti_tid != mytid ) pvm_kill(tip[i].ti_tid); } } /* XXX this is gnasty... */ /* while ((i = pvm_lookup("pvmgs", -1, &j)) >= 0) */ /* pvm_delete("pvmgs", i); */ /* Tell Master PVMD to clean up mboxes... */ sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); cc = TMDB_RESET; pvm_pkint(&cc, 1, 1); pvm_pkint(&pvmmytid, 1, 1); pvm_pkstr(class ? class : ""); cc = 0; pvm_pkint(&index, 1, 1); pvm_pkint(&killtasks, 1, 1); pvm_pkint(&nnr, 1, 1); for ( i=0 ; i < nnr ; i++ ) pvm_pkint(&(noresets[i]), 1, 1); if ((cc = msendrecv(TIDPVMD, TM_DB, SYSCTX_TM)) > 0) { pvm_upkint(&cc, 1, 1); pvm_freebuf(pvm_setrbuf(rbf)); } else pvm_setrbuf(rbf); pvm_freebuf(pvm_setsbuf(sbf)); return 0; } /*************************************************************** ** backwards compat functions: built on new mbox interface ** ** ** ***************************************************************/ int pvm_insert(name, req, data) char *name; /* class name */ int req; /* requested class index or -1 for any */ int data; { int sbf, rbf, cc; int flags; int mid; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_INSERT,TEV_EVENT_ENTRY)) { TEV_PACK_STRING( TEV_DID_CN, TEV_DATA_SCALAR, name ? name : "", 1, 1 ); TEV_PACK_INT( TEV_DID_CI, TEV_DATA_SCALAR, &req, 1, 1 ); TEV_PACK_INT( TEV_DID_CD, TEV_DATA_SCALAR, &data, 1, 1 ); TEV_FIN; } } if (!name || !*name || req < -1) { cc = PvmBadParam; } else { if (!(cc = BEATASK)) { flags = PvmMboxDefault | PvmMboxMultiInstance | PvmMboxPersistent; mid = pvm_mkbuf(PvmDataFoo); sbf = pvm_setsbuf(mid); pvm_pkint(&data, 1, 1); pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); cc = TMDB_PUT; pvm_pkint(&cc, 1, 1); pvm_pkint(&pvmmytid, 1, 1); pvm_pkstr(name); pvm_pkint(&req, 1, 1); pvm_pkint(&flags, 1, 1); pvm_pkmesg(mid); if ((cc = msendrecv(TIDPVMD, TM_DB, SYSCTX_TM)) > 0) { pvm_upkint(&cc, 1, 1); pvm_freebuf(pvm_setrbuf(rbf)); } else pvm_setrbuf(rbf); pvm_freebuf(pvm_setsbuf(sbf)); pvm_freebuf(mid); } } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_INSERT,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) if (cc != PvmDupEntry) lpvmerr("pvm_insert", cc); else pvm_errno = cc; return cc; } int pvm_lookup(name, req, datap) char *name; /* class name */ int req; /* req class index or -1 for any */ int *datap; /* data return */ { int sbf, rbf, cc; int flags; int mid; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_LOOKUP,TEV_EVENT_ENTRY)) { TEV_PACK_STRING( TEV_DID_CN, TEV_DATA_SCALAR, name ? name : "", 1, 1 ); TEV_PACK_INT( TEV_DID_CI, TEV_DATA_SCALAR, &req, 1, 1); TEV_FIN; } } if (!name || !*name || req < -1) { cc = PvmBadParam; } else { if (!(cc = BEATASK)) { flags = PvmMboxDefault; if ( req < 0 ) { flags |= PvmMboxFirstAvail; req = 0; } rbf = pvm_setrbuf(0); sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); cc = TMDB_GET; pvm_pkint(&cc, 1, 1); pvm_pkint(&pvmmytid, 1, 1); pvm_pkstr(name); pvm_pkint(&req, 1, 1); pvm_pkint(&flags, 1, 1); if ((cc = msendrecv(TIDPVMD, TM_DB, SYSCTX_TM)) > 0) { pvm_upkint(&cc, 1, 1); if (cc >= 0) { mid = pvm_upkmesg(); pvm_freebuf(pvm_setrbuf(mid)); } } pvm_freebuf(pvm_setsbuf(sbf)); if ( cc >= 0 && datap ) pvm_upkint(datap, 1, 1); pvm_freebuf(pvm_setrbuf(rbf)); } } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_LOOKUP,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) if (cc != PvmNoEntry) lpvmerr("pvm_lookup", cc); else pvm_errno = cc; return cc; } int pvm_delete(name, req) char *name; /* class name */ int req; /* class index or -1 for all */ { int cc; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_DELETE,TEV_EVENT_ENTRY)) { TEV_PACK_STRING( TEV_DID_CN, TEV_DATA_SCALAR, name ? name : "", 1, 1 ); TEV_PACK_INT( TEV_DID_CI, TEV_DATA_SCALAR, &req, 1, 1 ); TEV_FIN; } } if (!name || !*name || req < 0) { cc = PvmBadParam; } else { if (!(cc = BEATASK)) { cc = pvm_delinfo( name, req, PvmMboxDefault ); } } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_DELETE,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) if (cc != PvmNoEntry) lpvmerr("pvm_delete", cc); else pvm_errno = cc; return cc; } ./pvm3/src/lpvmglob.c0100644007401100000360000001723410001307621013652 0ustar kohlgopher static char rcsid[] = "$Id: lpvmglob.c,v 1.19 2004/01/14 18:50:57 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * lpvmglob.c * * Libpvm Globals. * * $Log: lpvmglob.c,v $ * Revision 1.19 2004/01/14 18:50:57 pvmsrc * Added new AIX5* arches. * (Spanker=kohl) * * Revision 1.18 2001/02/07 23:14:08 pvmsrc * First Half of CYGWIN Check-ins... * (Spanker=kohl) * * Revision 1.17 2000/06/15 17:51:52 pvmsrc * Fixed bug in WIN32 direct routing. * - stupid #endif in the wrong place, pvm_fd_add() call whacked. * - turned back on direct routing default and setopt. * (Spanker=kohl) * * Revision 1.16 2000/02/17 23:12:15 pvmsrc * *** Changes for new BEOLIN port *** * - MPP-like, similar to SP2, etc. * - submitted by Paul Springer . * - format-checked & cleaned up by Jeembo... :-) * (Spanker=kohl) * * Revision 1.15 2000/02/16 22:01:00 pvmsrc * Added #ifndef NO_NETINET_TCP_H around for * archs that can't handle it... :-) * (Spanker=kohl) * * Revision 1.14 1999/07/08 18:59:59 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.13 1999/03/12 20:55:37 pvmsrc * Don't allow direct routing in WIN32 until we fix it. Shit. * (Spanker=kohl) * * Revision 1.12 1998/11/20 20:04:07 pvmsrc * Changes so that win32 will compile & build. Also, common * Changes so that compiles & builds on NT. Also * common source on win32 & unix. * (Spanker=sscott) * * Revision 1.11 1997/09/22 21:13:32 pvmsrc * Added new pvmsettaskname() linkage (for shell-spawned tasks only!). * - call pvmsettaskname() before joining PVM, sends task name * (stored in new char *pvmmytaskname global) to pvmd in * TM_CONN2 message. * - appears in trace events and console ps. * (Spanker=kohl) * * Revision 1.10 1997/08/06 22:43:18 pvmsrc * Added new SGI6 and SGIMP6 arches. * * Revision 1.9 1997/06/27 19:53:56 pvmsrc * Fixed polltype/polltime bug in AIX4MP. * * Revision 1.8 1997/06/27 17:32:25 pvmsrc * Updated for WIN32 header files & Authors. * * Revision 1.7 1997/05/29 15:13:06 pvmsrc * Moved decl (init) of pvmrouteopt inside MPP/SHMEM vs. "normal" defines. * - for MPP/SHMEM -> PvmDontRoute, "normal" -> PvmAllowDirect. * * Revision 1.6 1997/05/21 16:01:52 pvmsrc * Updated ifdefs to include AIX4MP arch type. * * Revision 1.5 1997/03/06 21:08:28 pvmsrc * Added includes: * , "host.h" "pvmmimd.h" * * Revision 1.4 1997/02/13 23:35:54 pvmsrc * Added new PvmNoReset setopt/getopt option. * - added new pvmnoreset, pvmnoresetindex globals in lpvm.[ch]. * - to set use pvm_putinfo() -> PVMNORESETCLASS first avail w/lock, * save index in pvmnoresetindex. * - to unset use pvm_delinfo(). * * Revision 1.3 1997/01/28 19:26:28 pvmsrc * New Copyright Notice & Authors. * * Revision 1.2 1996/12/18 22:28:55 pvmsrc * Added new FILE *logfp decl. * - only #ifdef LOG. (previously only in shmem stuff) * - needed for now shared pvmlogerror() routine. * * Revision 1.1 1996/10/24 19:43:39 pvmsrc * Initial revision * * */ #include #include #if defined(WIN32) || defined(CYGWIN) #include "..\xdr\types.h" #include "..\xdr\xdr.h" #else #include #include #endif #ifndef WIN32 #include #ifndef NO_NETINET_TCP_H #include #endif #endif #include "pmsg.h" #include #include "tevmac.h" #include "host.h" #include "waitc.h" #include "global.h" /*************** ** Globals ** ** ** ***************/ int pvmautoerr = 1; /* whether auto print err msg */ struct Pvmtracer pvmctrc = /* child tracer info */ { 0, 0, 0, 0, 0, 0, 0, 0, "" }; struct Pvmtracer pvmtrc = /* task tracer info */ { 0, 0, 0, 0, 0, 0, 0, 0, "" }; int pvmmyptid = -1; /* parent task id */ int pvmmytid = -1; /* this task id */ int pvmmyupid = -1; /* process unix pid */ int pvm_useruid = -1; /* user's unix uid */ int pvmmydsig = 0; /* native data enc, init XDR */ int pvmschedtid = 0; /* scheduler task */ int pvmrescode = 0; /* allow reserved tids, tags */ int pvmshowtaskid = 1; /* catchout shows task ids */ int pvmtoplvl = 1; /* funct called outside lib */ int pvmdebmask = 0; /* which debugging info */ int pvmnoreset = 0; /* task reset override */ int pvmnoresetindex = -1; /* task reset overrd mb index */ char *pvmmytaskname = (char *) NULL; /* task name */ #if defined(IMA_CM5) || defined(IMA_CUBE) || defined(IMA_I860) \ || defined(IMA_PGON) || defined(IMA_SP2MPI) || defined(IMA_ALPHAMP) \ || defined(IMA_CSPP) || defined(IMA_HPPAMP) || defined(IMA_RS6KMP) \ || defined(IMA_SGIMP) || defined(IMA_SGIMP6) || defined(IMA_SGIMP64) \ || defined(IMA_SUNMP) || defined(IMA_AIX4MP) || defined(IMA_AIX5MP) \ || defined(AIX4SP2) || defined(IMA_AIX5SP2) || defined(IMA_BEOLIN) #include "pvmmimd.h" int pvmrouteopt = PvmDontRoute; /* task-task routing style */ int pvmfrgsiz = MAXFRAGSIZE; /* msg frag length (to pack) */ int pvmudpmtu = MAXFRAGSIZE; /* local UDP MTU */ #else int pvmrouteopt = PvmAllowDirect; /* task-task routing style */ int pvmfrgsiz = UDPMAXLEN; /* msg frag length (to pack) */ int pvmudpmtu = UDPMAXLEN; /* local UDP MTU */ #endif int pvmmyctx = 0; /* current message context */ int pvmnsibs = -1; /* number in our spawn group */ int *pvmsibtids = 0; /* tids in our spawn group */ struct pmsg *pvmrxlist = 0; /* not-recvd msg list */ struct pmsg *pvmrbuf = 0; /* current recv/unpack msg */ struct pmsg *pvmsbuf = 0; /* current send/pack msg */ #if defined(IMA_ALPHAMP) || defined(IMA_CSPP) || defined(IMA_HPPAMP) \ || defined(IMA_RS6KMP) || defined(IMA_SGIMP) \ || defined(IMA_SGIMP6) || defined(IMA_SGIMP64) \ || defined(IMA_AIX4MP) || defined(IMA_AIX5MP) \ || defined(IMA_SUNMP) int pvmpolltype = PvmPollSleep; /* memory polling style */ int pvmpolltime = BUSYWAIT; /* time value for poll wait */ #endif #ifdef LOG FILE *logfp = 0; /* my own log file */ #endif /* General Trace Globals */ struct pvmtrcencvec *pvmtrccodef; /* trace packing vector */ struct timeval pvmtrcztv = { 0, 0 }; /* trace zero time value */ struct pmsg *pvmtrcmp; /* trace record buffer mesg */ int pvmtrcsbfsave = 0; /* trace save send buffer */ int pvmtrcsbf = 0; /* trace record buffer */ int pvmtrcdesc; /* trace descriptor status */ int pvmtrctmp; /* trace temporary storage */ int pvmtrcsavekind; /* trace event kind for fin */ ./pvm3/src/lpvmmimd.c0100644007401100000360000014765510001307621013670 0ustar kohlgopher static char rcsid[] = "$Id: lpvmmimd.c,v 1.25 2004/01/14 18:50:57 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * lpvmmimd.c * * Libpvm core for MPP environment. * * $Log: lpvmmimd.c,v $ * Revision 1.25 2004/01/14 18:50:57 pvmsrc * Added new AIX5* arches. * (Spanker=kohl) * * Revision 1.24 2001/05/11 17:32:28 pvmsrc * Eliminated references to sys_errlist & sys_nerr. * - unnecessary, and we're whacking that crap anyway. * (Spanker=kohl) * * Revision 1.23 1999/07/08 18:59:59 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.22 1998/02/23 22:51:37 pvmsrc * Added AIX4SP2 stuff. * (Spanker=kohl) * * Revision 1.21 1997/12/31 20:50:06 pvmsrc * Cleaned Up System Message Handlers. * - current send / recv buffers now saved before invocation of * message handler functs. * - removed manual rbf = setrbuf(mid) saving & resetting in * handlers... * (Spanker=kohl) * * Revision 1.20 1997/12/01 19:20:41 pvmsrc * Replaced #ifdef IMA_OS2 fd_set declarations: * - new #ifdef FDSETNOTSTRUCT. * - choose between "fd_set foo" and "struct fd_set foo"... * (Spanker=kohl) * * Revision 1.19 1997/11/04 23:19:18 pvmsrc * Cleaned up fd_set stuff (hopefully). * (Spanker=kohl) * * Revision 1.18 1997/10/24 15:17:58 pvmsrc * Added TEV_DID_RCX to trace events for Receive Message Context. * - in pvm_recv(), pvm_trecv(), pvm_nrecv(), and pvm_precv(). * (Spanker=kohl) * * Revision 1.17 1997/10/24 14:29:30 pvmsrc * Added TEV_DID_MCX / pvmmyctx trace event info to: * - pvm_send(), pvm_mcast(), pvm_recv(), pvm_trecv(), pvm_nrecv(). * - pvm_psend(), pvm_precv(). * (Spanker=kohl) * * Revision 1.16 1997/06/27 17:32:27 pvmsrc * Updated for WIN32 header files & Authors. * * Revision 1.15 1997/06/12 20:10:44 pvmsrc * Made sure all communications for TC_* task control messages * use the SYSCTX_TC system context. * - some messages being sent in default context... D-Oh... * * Revision 1.14 1997/05/29 15:13:35 pvmsrc * Removed static decls: * - pvmtrcsbf, pvmrouteopt now in lpvmglob.c / lpvm.h. * - pvmtrcmid doesn't exist. * * Revision 1.13 1997/04/30 21:26:05 pvmsrc * SGI Compiler Warning Cleanup. * * Revision 1.12 1997/04/07 21:09:12 pvmsrc * pvm_addmhf() - new paramter interface * * Revision 1.11 1997/04/01 21:28:16 pvmsrc * Damn Damn Damn. * - pvm_recvinfo() returns a bufid, not an index. Damn. * * Revision 1.10 1997/04/01 20:48:19 pvmsrc * Fixed tracer mbox usage: * - pvm_getinfo() -> pvm_recvinfo(), new semantics handled (recvinfo * sets rbuf implicitly, a la pvm_recv, need to save rbuf). * * Revision 1.9 1997/03/27 19:55:29 pvmsrc * Fixed up pvmbeatask() to go get tracer info if spawned from shell: * - env var info including trace mask, trace buffer size, trace opts. * - use PVMTRACERCLASS mbox entry to fill in values, if matches * on trctid, trcctx, and trctag. * * Revision 1.8 1997/03/06 21:50:19 pvmsrc * Yanked out #includes for and . * - dups with lpvm.h #includes... * * Revision 1.7 1997/01/28 19:26:29 pvmsrc * New Copyright Notice & Authors. * * Revision 1.6 1996/12/19 20:17:04 pvmsrc * Replaced old struct umbuf with new struct pmsg. * * Revision 1.5 1996/12/19 19:57:56 pvmsrc * Eradicated remainder of old control message interface. * - replaced pvmmctl() routine with individual messages handlers: * * pvm_tc_shmat() (lpvmshmem.c only). * * pvm_tc_conreq(). * * pvm_tc_conack(). * * pvm_tc_taskexit(). * - added appropriate calls to pvm_addmhf() in pvmbeatask(). * - removed calls to pvmmctl() in mroute() (peer_recv() in * lpvmshmem.c), replaced with new mesg_input() call, * use new pmsg_setenc() routine to set message encoding. * * Revision 1.4 1996/12/18 22:27:48 pvmsrc * Extracted duplicate versions of routines from lpvm/mimd/shmem.c, * inserted into shared lpvmgen.c: * - pvmbailout(). * - pvmlogerror(). * - vpvmlogprintf(), pvmlogprintf(). (hope these work on MPP & shmem) * - pvmlogperror(). * * Revision 1.3 1996/10/25 13:57:27 pvmsrc * Replaced old #includes for protocol headers: * - , "ddpro.h", "tdpro.h" * With #include of new combined header: * - * * Revision 1.2 1996/10/24 22:44:33 pvmsrc * Modified for New Tracing Facility: * - moved #include "global.h" below other #include's for typing. * - removed extra #include in lpvm.c... * - added #include of new "lpvm.h" to replace explicit externs. * - removed common control message handlers from lpvm.c: * * extracted to lpvmgen.c for general usage. * * pvm_tc_noop(), pvm_tc_settmask(), pvm_tc_siblings(). * -> lpvmmimd.c & lpvmshmem.c still need remainder of pvmmctl() * replaced with control message handlers. * - arg typing hassles with int_compare() / qsort() exacerbated... * - modified pvmbeatask(): * * handle new tracing info, unpack tracing and output collection * parameters into temp storage, and then check for local task * override before applying. * * read in new tracing env vars PVMTRCBUF & PVMTRCOPT. * * install new common message handlers. * * call new tev_init() routine to set up tracing stuff. * * use new Pvmtracer structures (pvmtrc & pvmctrc) to store info. * - removed pvm_getopt() & pvm_setopt() -> moved to common lpvmgen.c. * - removed old tev_begin(), tev_fin() & tev_do_trace() routines. * - updated trace event generation for pvm_getfds(), pvm_start_pvmd(), * pvm_precv(), pvm_psend(). * * Revision 1.1 1996/09/23 23:44:17 pvmsrc * Initial revision * * Revision 1.20 1995/11/02 16:12:23 manchek * free replies to control messages in mxfer * * Revision 1.19 1995/11/02 16:11:15 manchek * removed hdump() * * Revision 1.18 1995/09/06 17:37:25 manchek * aargh, forgot pvm_precv * * Revision 1.17 1995/09/06 17:32:39 manchek * pvm_psend returns not implemented instead of bad param for string type * * Revision 1.16 1995/09/05 19:16:11 manchek * changed some comments * * Revision 1.15 1995/07/28 16:40:58 manchek * wrap HASERRORVARS around errno declarations * * Revision 1.14 1995/07/18 19:03:35 manchek * added code to generate and check crc on each message (MCHECKSUM) * * Revision 1.13 1995/06/28 18:19:09 manchek * do-nothing check_for_exit so one can be in lpvmshmem.c * * Revision 1.12 1995/06/19 17:49:22 manchek * was packing random string in TC_CONACK message in pvmmctl * * Revision 1.11 1995/06/16 16:07:54 manchek * set debug mask and trace mask from environment vars. * hack to set trace and output sink and tag for PGON * * Revision 1.10 1995/06/12 15:58:52 manchek * added PGON partition size support * * Revision 1.9 1995/05/30 17:29:52 manchek * Added ifdefs for SP2MPI architecture. * Fixed bug in pvm_precv. * Use asyncsend and probe for incoming messages in pvm_psend. * Prefix my_node, etc. with "pvm" and make them static to avoid name clashes. * Fix in mroute() to handle null message * * Revision 1.8 1995/02/01 21:11:45 manchek * error 4 is now PvmOverflow * * Revision 1.7 1994/12/20 16:39:05 manchek * added pvmshowtaskid variable * * Revision 1.6 1994/11/07 22:39:59 manchek * Modify node_mcast() to handle DataInPlace correctly. * Modify pvm_precv() to deal with packets from service nodes. Those * packets have PVM headers. * Change the limit on pvmfrgsiz in pvm_setopt() to MAXFRAGSIZE. * Respond to RouteDirect requests * * Revision 1.5 1994/09/02 15:25:03 manchek * fixed typos in pvm_precv - rtid should be rlen * * Revision 1.4 1994/06/03 20:38:17 manchek * version 3.3.0 * * Revision 1.3 1993/12/20 15:39:15 manchek * patch 6 from wcj * * Revision 1.1 1993/08/30 23:26:48 manchek * Initial revision * */ #include #include #include #include #ifdef IMA_CM5 #include #endif #include #ifdef SYSVSTR #include #else #include #endif #include #ifdef IMA_PGON #include #endif #ifdef IMA_I860 #include #endif #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) #include #include #include "mpi.h" #endif #include #include #include "pvmalloc.h" #include "pvmfrag.h" #include "pmsg.h" #include "listmac.h" #include "pvmdmp.h" #include "pvmmimd.h" #include "bfunc.h" #include "lpvm.h" #include #include "tevmac.h" #include "global.h" #ifndef max #define max(a,b) ((a)>(b)?(a):(b)) #endif char *getenv(); void hex_inadport __ProtoGlarp__ (( char *, struct sockaddr_in * )); extern struct encvec *enctovec(); /*************** ** Globals ** ** ** ***************/ #ifndef HASERRORVARS extern int errno; /* from libc */ #endif int pvmtidhmask = TIDHOST; /* mask - host field of tids */ int pvmtidnmask = TIDNODE; /* mask - node field of tids */ int pvmtidtmask = TIDPTYPE; /* mask - proc type field of tids */ int pvmpgonpartsize = 0; /* pgon parent partition size */ /*************** ** Private ** ** ** ***************/ static int pvmdebmask = 0; /* which debugging info */ static char pvmtxt[512]; /* scratch for error log */ static struct pmsg *rxfrag = 0; /* not-assembled incm msgs */ static int mpierrcode = 0; /* error code returned by MPI calls */ static struct tmpfrag outfrags[NUMSMHD];/* fragments queued by async send */ static int nextsmhd = 0; /* index of current isend mhdl */ #if defined(IMA_CM5) || defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) \ defined(IMA_AIX5SP2) static struct pmsg *precvlist = 0; /* not-processed incm msgs */ #endif static long pvmmyptype = 0; /* my process type */ static long pvmhostnode = -1; /* host node number */ static int pvmmynode = -1; /* my node number */ #ifdef IMA_I860 static int pvmmyvnode = -1; /* my virtual node number */ #endif static int mysetpart = 0; /* host field & set field */ /* static int recvmask = 0x80000000 + (1<=0 the number of complete messages downloaded, or * negative on error. */ int mroute(mid, dtid, code, tmout) int mid; /* message */ int dtid; /* dest */ int code; /* type code */ struct timeval *tmout; /* get at least one message */ { struct pmsg *txup; /* tx message or null */ struct frag *txfp = 0; /* cur tx frag or null */ int gotem = 0; /* count complete msgs downloaded */ struct pmsg *rxup; /* rx message */ struct frag *fp; char *cp = 0; int src; int dst; int ff; int block; /* get at least one message */ struct timeval tnow, tstop; int len; long node; #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) MPI_Status info; int mpiflag = 0; int mpisiz; #else long info[8]; /* info about pending message */ #endif /* XXX do we really have to do this? */ if ((dtid == TIDPVMD && code == TM_MCA) || dtid == TIDGID) return node_mcast(mid, dtid, code); if (tmout) { if (tmout->tv_sec || tmout->tv_usec) { pvmgetclock(&tnow); tstop.tv_sec = tnow.tv_sec + tmout->tv_sec; tstop.tv_usec = tnow.tv_usec + tmout->tv_usec; block = 1; } else block = 0; } else { block = 1; tstop.tv_sec = -1; tstop.tv_usec = -1; } if (txup = midtobuf(mid)) { txfp = txup->m_frag->fr_link; if (!txfp->fr_buf) { txfp = fr_new(MAXHDR); txfp->fr_dat += MAXHDR; LISTPUTBEFORE(txup->m_frag, txfp, fr_link, fr_rlink); } node_send(txup, txfp, dtid, code); if (!block) return 0; } do { if (block && tstop.tv_sec != -1) { pvmgetclock(&tnow); if (tnow.tv_sec > tstop.tv_sec || (tnow.tv_sec == tstop.tv_sec && tnow.tv_usec >= tstop.tv_usec)) break; } /* * Receive PMTPACK msg only; psent msg can have any (user-supplied) * type not equal to PMTPACK. They're handled by precv. */ node = MPPANYNODE; if (MSGPROBE(node, PMTPACK, info)) { /* * 1. Null msg (except I860) from pvmd, followed by the real msg. * 2. Header (inplace), followed by msg body. * 3. Entire msg from another node. */ if (len = MSGSIZE(info)) { fp = fr_new(len); cp = fp->fr_dat; } if ((mpierrcode = PVMCRECV(node, PMTPACK, cp, len, 0, info)) #if defined(IMA_PGON) || defined(IMA_CM5) || defined(IMA_I860) && (mpierrcode < 0) #endif ) { pvmlogperror("mroute() PVMCRECV"); return PvmSysErr; } if (!len) { /* * Discard null msg. Now we must wait for the real (packed) * msg, otherwise it could get picked up later by precv and * cause problems. */ block = 1; continue; } if ((len = pvmget32(cp + 8) + TDFRAGHDR) != fp->fr_max) { struct frag *hdr; /* buffer for header */ /* inplace data, head & body sent separately */ hdr = fp; fp = fr_new(len); len = hdr->fr_max; BCOPY(hdr->fr_dat, fp->fr_dat, len); fr_unref(hdr); node = MSGSENDER(info); #ifdef IMA_I860 /* msg type is (virtual) node # */ if (_crecv(node, fp->fr_dat + len, fp->fr_max - len) < 0) { #else if ((mpierrcode = PVMCRECV(node, PMTPACK, fp->fr_dat + len, fp->fr_max - len, 0, info)) #if defined(IMA_PGON) || defined(IMA_CM5) && (mpierrcode < 0) #endif ) { #endif pvmlogperror("mroute() PVMCRECV msg body"); return PvmSysErr; } cp = fp->fr_dat; } /* fp->fr_len = fp->fr_max; */ dst = pvmget32(cp); src = pvmget32(cp + 4); fp->fr_len = pvmget32(cp + 8); ff = pvmget8(cp + 12); /* fp->fr_len -= TDFRAGHDR; */ fp->fr_dat += TDFRAGHDR; if (pvmdebmask & PDMPACKET) { sprintf(pvmtxt, "mroute() src t%x len %d dst t%x\n", src, fp->fr_len, dst); pvmlogerror(pvmtxt); } /* * if start of message, make new umbuf, add to frag pile */ if (ff & FFSOM) { cp += TDFRAGHDR; fp->fr_len -= TTMSGHDR; fp->fr_dat += TTMSGHDR; rxup = umbuf_new(); rxup->m_tag = pvmget32(cp); rxup->m_enc = pvmget32(cp + 4); rxup->m_wid = pvmget32(cp + 8); rxup->m_crc = pvmget32(cp + 12); rxup->m_src = src; LISTPUTBEFORE(rxfrag, rxup, m_link, m_rlink); } /* locate frag's message */ for (rxup = rxfrag->m_link; rxup != rxfrag; rxup = rxup->m_link) if (rxup->m_src == src) break; if (rxup == rxfrag) { /* uh oh, no message for it */ pvmlogerror("mroute() frag with no message\n"); fr_unref(fp); } else { LISTPUTBEFORE(rxup->m_frag, fp, fr_link, fr_rlink); rxup->m_len += fp->fr_len; /* * if end of message, move to rxlist and count it */ if (ff & FFEOM) { LISTDELETE(rxup, m_link, m_rlink); #ifdef MCHECKSUM if (rxup->m_crc != umbuf_crc(rxup)) { sprintf(pvmtxt, "mxinput() message src t%x cod %d bad checksum\n", rxup->m_src, rxup->m_tag); pvmlogerror(pvmtxt); umbuf_free(rxup); } else { #endif pmsg_setenc(rxup, rxup->m_enc); mesg_input(rxup); gotem++; #ifdef MCHECKSUM } #endif } } } } while (block && !gotem); return gotem; } /* sends a frag to another process */ int node_send(txup, txfp, dtid, code) struct pmsg *txup; /* tx message or null */ struct frag *txfp; /* cur tx frag or null */ int dtid; /* dest */ int code; /* type code */ { int mask = pvmtidhmask; /* host */ char *txcp = 0; /* point to remainder of txfp */ int txtogo = 0; /* len of txfp */ long node; /* destination node */ long ptype; /* destination process type */ int i; int ff; char dummy[TDFRAGHDR+TTMSGHDR]; /* for inplace data */ #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) MPI_Status mpista; int mpiflag = 0; #endif #if defined(IMA_PGON) || defined(IMA_CM5) || defined(IMA_SP2MPI) \ || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) mask |= pvmtidtmask; /* process type */ #endif if (TIDISNODE(dtid) && (dtid & mask) == (pvmmytid & mask)) { node = dtid & pvmtidnmask; ptype = pvmmyptype; /* send to node directly */ } else { node = pvmhostnode; ptype = PVMDPTYPE; /* send to pvmd first */ } do { /* check any pending sends; free data if send is completed */ if (nextsmhd == NUMSMHD) nextsmhd = 0; i = nextsmhd; while (outfrags[i].tf_mhdl != PVMMHDNULL && ASYNCDONE(outfrags[i].tf_mhdl) > 0) { fr_unref(outfrags[i].tf_fp); #ifdef IMA_CM5 CMMD_free_mcb(outfrags[i].tf_mhdl); #endif outfrags[i++].tf_mhdl = PVMMHDNULL; } if (outfrags[nextsmhd].tf_mhdl != PVMMHDNULL) { if (pvmdebmask & PDMPACKET) pvmlogerror("out of mid's?"); nextsmhd++; /* don't get stuck here; check out next mhd */ continue; } if (txfp->fr_u.dab) /* packed data */ txcp = txfp->fr_dat; else /* inplace data */ txcp = dummy + sizeof(dummy); txtogo = txfp->fr_len; /* * if this is first frag, prepend t-t header */ ff = 0; if (txfp->fr_rlink == txup->m_frag) { txcp -= TTMSGHDR; txtogo += TTMSGHDR; pvmput32(txcp, code); pvmput32(txcp + 4, (txup->m_enc == 2 ? pvmmydsig : txup->m_enc)); pvmput32(txcp + 8, txup->m_wid); #ifdef MCHECKSUM pvmput32(txcp + 12, umbuf_crc(txup)); #else pvmput32(txcp + 12, 0); #endif ff = FFSOM; } if (txfp->fr_link == txup->m_frag) ff |= FFEOM; /* * prepend t-d header */ txcp -= TDFRAGHDR; pvmput32(txcp, dtid); pvmput32(txcp + 4, pvmmytid); pvmput32(txcp + 8, txtogo); pvmput32(txcp + 12, 0); /* to keep putrify happy */ pvmput8(txcp + 12, ff); txtogo += TDFRAGHDR; if (pvmdebmask & PDMPACKET) { sprintf(pvmtxt, "node_send() dst t%x len %d ptype=%ld node=%ld\n", dtid, txfp->fr_len, ptype, node); pvmlogerror(pvmtxt); } if (!txfp->fr_u.dab) { /* inplace data */ if ((mpierrcode = PVMCSEND(PMTPACK, txcp, txtogo- txfp->fr_len, node, ptype)) #if defined(IMA_PGON) || defined(IMA_CM5) || defined(IMA_I860) && (mpierrcode < 0) #endif ) { pvmlogperror("node_send() csend header"); return PvmSysErr; } #ifdef IMA_I860 /* crecv can't select msg with node #; it can only select type */ if (_csend(pvmmyvnode, txfp->fr_dat, txfp->fr_len, node, 0) < 0) { pvmlogperror("node_send() csend inplace data"); return PvmSysErr; } #else /* here the type field is reserved for psend/precv */ if ((mpierrcode = PVMCSEND(PMTPACK, txfp->fr_dat, txfp->fr_len, node, ptype)) #if defined(IMA_PGON) || defined(IMA_CM5) || defined(IMA_I860) && (mpierrcode < 0) #endif ) { pvmlogperror("node_send() csend inplace data"); return PvmSysErr; } #endif } else { if (node != pvmhostnode) { #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) if (mpierrcode = MPI_Isend(txcp, txtogo, MPI_BYTE, node, PMTPACK, MPI_COMM_WORLD, &outfrags[nextsmhd].tf_mhdl)) { #else if ((outfrags[nextsmhd].tf_mhdl = ASYNCSEND(PMTPACK, txcp, txtogo, node, ptype)) < 0) { #endif pvmlogperror("node_send() asyncsend"); return PvmSysErr; } /* don't free data 'til frag's sent */ txfp->fr_u.ref++; outfrags[nextsmhd++].tf_fp = txfp; } else { /* * In multicast, the fragment header may get overwritten * if we use ASYNCSEND. This is OK for node-node send, * because the dst field is not used. But pvmd relies on * this value to deliever the packet. */ if ((mpierrcode = PVMCSEND(PMTPACK, txcp, txtogo, node, ptype)) #if defined(IMA_PGON) || defined(IMA_CM5) || defined(IMA_I860) && (mpierrcode < 0) #endif ) { pvmlogperror("node_send() csend"); return PvmSysErr; } } } txfp = txfp->fr_link; if (!txfp->fr_buf) txfp = 0; } while (txfp); } int node_mcast(mid, dtid, code) int mid; /* message id */ int dtid; /* destination */ int code; /* type */ { int i; long count = 0; int cc = 0; static int *tids; /* intended recipients of multicast message */ static int ntask; /* number of tids */ int sbf; int tmp; static struct timeval ztv = { 0, 0 }; #if defined(IMA_PGON) long *nodes; int mask = pvmtidhmask; /* host */ struct pmsg *txup; /* tx message or null */ struct frag *txfp = 0; /* cur tx frag or null */ int txtogo = 0; /* len of txfp */ int ff; char *txcp = 0; /* point to remainder of txfp */ int len = 0; /* len of txfp */ char dummy[TDFRAGHDR+TTMSGHDR]; /* for inplace data */ #endif /*defined(IMA_PGON)*/ /* intercept multicast info */ if (dtid == TIDPVMD) { pvm_setrbuf(mid); pvm_upkint(&ntask, 1, 1); tids = TALLOC(ntask, int, "tids"); pvm_upkint(tids, ntask, 1); sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); tmp = TIDGID; pvm_pkint(&tmp, 1, 1); pvm_setrbuf(pvm_setsbuf(sbf)); return 0; } #if defined(IMA_PGON) /* #if defined(IMA_PGON) */ mask |= pvmtidtmask; /* process type */ /* #endif */ nodes = TALLOC(ntask, long, "nodes"); for (i = 0; i < ntask; i++) { if (TIDISNODE(tids[i]) && (tids[i] & mask) == (pvmmytid & mask)) nodes[count++] = tids[i] & pvmtidnmask; else cc = mroute(mid, tids[i], code, &ztv); } if (count) { if (txup = midtobuf(mid)) { txfp = txup->m_frag->fr_link; txfp = txfp->fr_buf ? txfp : 0; } while (txfp) { if (txfp->fr_u.dab) /* packed data */ txcp = txfp->fr_dat; else /* inplace data */ txcp = dummy + sizeof(dummy); txtogo = txfp->fr_len; ff = 0; if (txfp->fr_rlink == txup->m_frag) { txcp -= TTMSGHDR; txtogo += TTMSGHDR; pvmput32(txcp, code); pvmput32(txcp + 4, (txup->m_enc == 2 ? pvmmydsig : txup->m_enc)); pvmput32(txcp + 8, txup->m_wid); #ifdef MCHECKSUM pvmput32(txcp + 12, umbuf_crc(txup)); #else pvmput32(txcp + 12, 0); #endif ff = FFSOM; } if (txfp->fr_link == txup->m_frag) ff |= FFEOM; txcp -= TDFRAGHDR; pvmput32(txcp, dtid); pvmput32(txcp + 4, pvmmytid); pvmput32(txcp + 8, txtogo); pvmput32(txcp + 12, 0); /* to keep putrify happy */ pvmput8(txcp + 12, ff); txtogo += TDFRAGHDR; if (pvmdebmask & PDMPACKET) { sprintf(pvmtxt, "node_mcast() len %d\n", txfp->fr_len); pvmlogerror(pvmtxt); } if (count == numnodes() - 1) { if (!txfp->fr_u.dab) { /* inplace data */ if (_csend(PMTPACK, txcp, txtogo - txfp->fr_len, -1, pvmmyptype) < 0) { pvmlogperror("node_mcast() csend header"); return PvmSysErr; } if (_csend(PMTPACK, txfp->fr_dat, txfp->fr_len, -1, pvmmyptype) < 0){ pvmlogperror("node_mcast() csend inplace data"); return PvmSysErr; } } else { /* packed */ if (_csend(PMTPACK, txcp, (long)txtogo, -1, pvmmyptype) < 0) { pvmlogperror("node_mcast() csend"); return PvmSysErr; } } } else { if (!txfp->fr_u.dab) { /* inplace data */ if (_gsendx(PMTPACK, txcp, txtogo - txfp->fr_len, nodes, count) < 0) { pvmlogperror("node_mcast() gsendx header"); return PvmSysErr; } if (_gsendx(PMTPACK, txfp->fr_dat, txfp->fr_len, nodes, count) < 0) { pvmlogperror("node_send() gsendx inplace data"); return PvmSysErr; } } else { if (_gsendx(PMTPACK, txcp, (long)txtogo, nodes, count) < 0){ pvmlogperror("node_mcast() gsendx"); return PvmSysErr; } } } txfp = txfp->fr_link; if (!txfp->fr_buf) txfp = 0; } } PVM_FREE(nodes); #endif /*defined(IMA_PGON)*/ #if defined(IMA_CM5) || defined(IMA_I860) || defined(IMA_SP2MPI) \ || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) for (i = 0; i < ntask; i++) cc = mroute(mid, tids[i], code, &ztv); #endif PVM_FREE(tids); ntask = 0; return cc; } /* msendrecv() * * Single op to send a system message (usually to our pvmd) and get * the reply. * Returns message handle or negative if error. */ int msendrecv(other, code) int other; /* dst, src tid */ int code; /* message code */ { int cc; struct pmsg *up; if (!pvmsbufmid) return PvmNoBuf; /* send code to other */ if (pvmdebmask & PDMMESSAGE) { sprintf(pvmtxt, "msendrecv() to t%x code %d\n", other, code); pvmlogerror(pvmtxt); } if ((cc = mroute(pvmsbuf->m_mid, other, code, (struct timeval *)0)) < 0) return cc; if (code == TM_MCA) /* for node_mcast() */ return 1; /* recv code from other */ for (up = pvmrxlist->m_link; 1; up = up->m_link) { if (up == pvmrxlist) { up = up->m_rlink; if ((cc = mroute(0, 0, 0, (struct timeval *)0)) < 0) return cc; up = up->m_link; } if (pvmdebmask & PDMMESSAGE) { sprintf(pvmtxt, "msendrecv() cmp from t%x code %d\n", up->m_src, up->m_tag); pvmlogerror(pvmtxt); } if (up->m_src == other && up->m_tag == code) break; } LISTDELETE(up, m_link, m_rlink); if (pvmrbuf) umbuf_free(pvmrbuf); pvmrbuf = 0; if (cc = pvm_setrbuf(up->m_mid)) return cc; return up->m_mid; } #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) /* Relay messages between pvmd and node tasks. */ void relay(dsock) int dsock; /* pvmd socket */ { #ifdef FDSETNOTSTRUCT fd_set wrk_rfds, wrk_wfds, rfds, wfds; #else struct fd_set wrk_rfds, wrk_wfds, rfds, wfds; #endif int nfds; struct timeval tout; struct frag *frpvmd = 0; /* (small) frag from pvmd */ struct frag *topvmd = 0; /* (big) frag to pvmd */ struct frag *frtask = 0; /* (big) frag from task */ struct frag *totask; /* (small) frag being sent to task */ char *txcp = 0; /* point to remainder of topvmd */ int txtogo = 0; /* len of remainder of topvmd */ int toread; /* number of bytes to be read from pvmd */ int frtogo; /* len of remainder of a fragment */ int topvmd_dst; /* dst of fragment being sent to pvmd */ int topvmd_src; /* src of fragment being sent to pvmd */ int len; int topvmd_ff; /* ff of fragment being sent to pvmd */ int dst; /* dst of fragment being sent to node */ int node; /* node number */ MPI_Request rmhd; /* msg IDs returned by async recv */ int n; char *cp; int err; MPI_Status sta; /* info on pending message */ int dummy; int flag; /* MPI_Test result */ struct frag *hdr; nfds = dsock + 1; frtask = fr_new(MAXFRAGSIZE); if (err = MPI_Irecv(frtask->fr_dat, frtask->fr_max, MPI_BYTE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &rmhd)) { MPI_Error_string(err, pvmtxt, &dummy); pvmlogerror(pvmtxt); pvmlogerror("relay() MPI_Irecv"); pvm_exit(); MPI_Finalize(); exit(9); } FD_ZERO(&wrk_rfds); FD_ZERO(&wrk_wfds); FD_SET(dsock, &wrk_rfds); while (1) { /* ferry messages between pvmd and tasks */ tout.tv_sec = 0; tout.tv_usec = 0; if (!topvmd && !MPI_Test(&rmhd, &flag, &sta) && flag) { topvmd = frtask; MPI_Get_count(&sta, MPI_BYTE, &txtogo); /* w/ header */ /* sprintf(pvmtxt, "relay() recv %d", txtogo); pvmlogerror(pvmtxt); */ txcp = topvmd->fr_dat; if ((len = pvmget32(txcp + 8) + TDFRAGHDR) != txtogo) { /* inplace data, head & body sent separately */ if (len > MAXFRAGSIZE) { hdr = topvmd; topvmd = fr_new(len); BCOPY(hdr->fr_dat, topvmd->fr_dat, txtogo); fr_unref(hdr); txcp = topvmd->fr_dat; } MPI_Recv(topvmd->fr_dat + txtogo, len - txtogo, MPI_BYTE, sta.MPI_SOURCE, PMTPACK, MPI_COMM_WORLD, &sta); txtogo = len; } frtask = fr_new(MAXFRAGSIZE); /* ready for the next message */ if (err = MPI_Irecv(frtask->fr_dat, frtask->fr_max, MPI_BYTE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &rmhd)) { MPI_Error_string(err, pvmtxt, &dummy); pvmlogerror(pvmtxt); pvmlogerror("relay() MPI_Irecv"); pvm_exit(); MPI_Finalize(); exit(10); } FD_SET(dsock, &wrk_wfds); } rfds = wrk_rfds; wfds = wrk_wfds; if (select(nfds, #ifdef FDSETISINT (int *)&rfds, (int *)&wfds, (int *)0, #else (fd_set *)&rfds, (fd_set *)&wfds, (fd_set *)0, #endif &tout) == -1 && errno != EINTR) { pvmlogperror("relay() select"); pvm_exit(); MPI_Finalize(); exit(11); } if (FD_ISSET(dsock, &rfds)) { if (!frpvmd) { frpvmd = fr_new(MAXFRAGSIZE); toread = TDFRAGHDR; } n = read(dsock, frpvmd->fr_dat + frpvmd->fr_len, toread); /* sprintf(pvmtxt, "relay() read %d", n); pvmlogerror(pvmtxt); */ if (n == -1 && errno != EWOULDBLOCK && errno != EINTR) { pvmlogperror("relay() read pvmd sock"); MPI_Finalize(); exit(12); } if (!n) { /* pvmlogerror("relay() read EOF on pvmd sock\n"); */ MPI_Finalize(); exit(13); } if ((frpvmd->fr_len += n) < TDFRAGHDR) { toread -= n; continue; } n = TDFRAGHDR + pvmget32(frpvmd->fr_dat + 8); /* header + body */ if (frpvmd->fr_len < n) { if (frpvmd->fr_max < n) { /* n > MAXFRAGSIZ */ hdr = frpvmd; frpvmd = fr_new(n); BCOPY(hdr->fr_dat, frpvmd->fr_dat, hdr->fr_len); frpvmd->fr_len = hdr->fr_len; fr_unref(hdr); } toread = n - frpvmd->fr_len; continue; } dst = pvmget32(frpvmd->fr_dat); node = dst & pvmtidnmask; /* inform precv/recv of a packed message */ while (err = MPI_Bsend(&node, 0, MPI_BYTE, node, PMTPACK, MPI_COMM_WORLD)) { MPI_Error_string(err, pvmtxt, &dummy); pvmlogerror(pvmtxt); sprintf(pvmtxt, "relay() can't send null msg to t%x", dst); pvmlogerror(pvmtxt); } while (err = MPI_Bsend(frpvmd->fr_dat, frpvmd->fr_len, MPI_BYTE, node, PMTPACK, MPI_COMM_WORLD)) { MPI_Error_string(err, pvmtxt, &dummy); pvmlogerror(pvmtxt); sprintf(pvmtxt, "relay() can't send to t%x", dst); pvmlogerror(pvmtxt); } fr_unref(frpvmd); frpvmd = 0; /* sprintf(pvmtxt, "relay() sent %d to node %d\n", frpvmd->fr_len, (dst & pvmtidnmask)); pvmlogerror(pvmtxt); */ } if (FD_ISSET(dsock, &wfds)) { n = write(dsock, txcp, txtogo); /* sprintf(pvmtxt, "relay() wrote %d to pvmd\n", n); pvmlogerror(pvmtxt); */ if (n == -1 && errno != EWOULDBLOCK && errno != EINTR) { pvmlogperror("relay() write pvmd sock"); MPI_Finalize(); exit(14); } if (n > 0 && (txtogo -= n) > 0) txcp += n; if (!txtogo) { /* entire message sent */ FD_CLR(dsock, &wrk_wfds); fr_unref(topvmd); topvmd = 0; } } } } /* We're the "host" process. Connect to pvmd. */ void pvmhost() { char *p; int dsock; /* pvmd socket */ struct sockaddr_in dsadr; /* address of pvmd socket */ int n; int pvminfo[SIZEHINFO]; /* ntask, hostpart, ptid, MTU, NDF */ char nullmsg[TDFRAGHDR+TTMSGHDR]; if (!(p = getenv("PVMSOCK"))) { pvmlogerror("pvmhost() getenv() pvmd socket\n"); MPI_Finalize(); exit(2); } mpierrcode = 0; if ((dsock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { pvmlogperror("pvmhost() socket"); MPI_Finalize(); exit(3); } BZERO((char*)&dsadr, sizeof(dsadr)); hex_inadport(p, &dsadr); dsadr.sin_family = AF_INET; n = sizeof(dsadr); while (connect(dsock, (struct sockaddr*)&dsadr, n) == -1) if (errno != EINTR) { pvmlogperror("pvmhost() connect"); MPI_Finalize(); exit(4); } #ifndef NOSOCKOPT n = 1; if (setsockopt(dsock, IPPROTO_TCP, TCP_NODELAY, (char*)&n, sizeof(int)) == -1) { pvmlogperror("pvmhost() setsockopt"); MPI_Finalize(); exit(5); } #endif if (!(p = getenv("PVMEPID"))) { pvmlogerror("pvmhost() getenv() pid\n"); MPI_Finalize(); exit(6); } pvmmyupid = atoi(p); BZERO(nullmsg, TDFRAGHDR+TTMSGHDR); pvmput32(nullmsg, TIDPVMD); pvmput32(nullmsg + 4, pvmmyupid); pvmput32(nullmsg + 8, TTMSGHDR); pvmput32(nullmsg + 12, 0); /* to keep putrify happy */ pvmput8(nullmsg + 12, FFSOM|FFEOM); if (write(dsock, nullmsg, TDFRAGHDR+TTMSGHDR) != TDFRAGHDR+TTMSGHDR || read(dsock, pvminfo, SIZEHINFO*sizeof(int)) != SIZEHINFO*sizeof(int)) { pvmlogperror("pvmhost() write/read"); MPI_Finalize(); exit(8); } MPI_Bcast(pvminfo, SIZEHINFO, MPI_INT, pvmhostnode, MPI_COMM_WORLD); (void)relay(dsock); } #endif /*IMA_SP2MPI*/ /* pvmbeatask() * * Initialize libpvm, config process as a task. * This is called as the first step of each libpvm function so no * explicit initialization is required. * * Returns 0 if okay, else error code. */ int pvmbeatask() { int pvminfo[SIZEHINFO]; /* proto, hostpart, ptid, MTU, NDF */ long rmid = -1; /* msg ID returned by irecv() */ int i; int cc; int ac = 0; char *p; struct pvmminfo minfo; int n; #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) char *msgbuf; /* buffer for Bsend */ int msgbufsiz; #endif int need_trcinfo = 0; int new_tracer = 0; char tmask[ 2 * TEV_MASK_LENGTH ]; int tbuf, topt; int mid, rbf; TEVDECLS if (pvmmytid != -1) return 0; TEV_EXCLUSIVE; if (p = getenv("PVMTASKDEBUG")) { /* read the debug mask */ pvmdebmask = pvmxtoi(p); if (pvmdebmask) { sprintf(pvmtxt,"task debug mask is 0x%x\n", pvmdebmask); pvmlogerror(pvmtxt); } } #if defined(IMA_PGON) || defined(IMA_I860) if ((rmid = _irecv(PMTHOST, pvminfo, sizeof(pvminfo))) < 0) { pvmlogperror("beatask() recv pvminfo"); return PvmSysErr; } if ((pvmhostnode = _myhost()) < 0) pvmlogperror("beatask() no controlling process"); #endif if ((pvm_useruid = getuid()) == -1) { pvmlogerror("can't getuid()\n"); return PvmSysErr; } #ifdef IMA_CM5 CMMD_enable_host(); CMMD_receive_bc_from_host(pvminfo, sizeof(pvminfo)); CMMD_reset_partition_size(pvminfo[0]); if ((pvmmynode = CMMD_self_address()) >= pvminfo[0]) exit(0); /* no task to spawn on this node */ CMMD_fset_io_mode(stdout, CMMD_independent); CMMD_fset_io_mode(stderr, CMMD_independent); pvmhostnode = CMMD_host_node(); #endif #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) MPI_Init(&ac, NULL); MPI_Comm_rank(MPI_COMM_WORLD, &pvmmynode); MPI_Comm_size(MPI_COMM_WORLD, &pvmhostnode); pvmhostnode--; /* host is last process in group */ if (!(p = getenv("PVMBUFSIZE")) || !(msgbufsiz = strtol(p, (char**)0, 0))) msgbufsiz = MPIBUFSIZ; if (!(msgbuf = malloc(msgbufsiz))) pvmlogerror("relay() out of memory"); MPI_Buffer_attach(msgbuf, msgbufsiz); /* used in psend or relay */ if (pvmmynode == pvmhostnode) (void)pvmhost(); MPI_Bcast(pvminfo, SIZEHINFO, MPI_INT, pvmhostnode, MPI_COMM_WORLD); #endif pvmmyupid = getpid(); /* sprintf(pvmtxt, "pvminfo: %d %d %d %d %d node=%d\n", pvminfo[0], pvminfo[1], pvminfo[2], pvminfo[3], pvminfo[4], pvmmynode); pvmlogerror(pvmtxt); fflush(stdout); */ #ifdef IMA_PGON if ((pvmmyptype = myptype()) == INVALID_PTYPE) pvmlogerror("beatask() no process type\n"); pvmmynode = _mynode(); #endif #ifdef IMA_I860 pvmmynode = _mydirect(); pvmmyvnode = _mynode(); if (_csend(PMTPHYS, &pvmmynode, sizeof(int), pvmhostnode, PVMDPTYPE) < 0) pvmlogperror("beatask() can't send to host"); #endif /* * initialize received-message list and fragment reassembly list */ rxfrag = TALLOC(1, struct pmsg, "umb"); BZERO((char*)rxfrag, sizeof(struct pmsg)); rxfrag->m_link = rxfrag->m_rlink = rxfrag; pvmrxlist = TALLOC(1, struct pmsg, "umb"); BZERO((char*)pvmrxlist, sizeof(struct pmsg)); pvmrxlist->m_link = pvmrxlist->m_rlink = pvmrxlist; #if defined(IMA_CM5) || defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) \ || defined(IMA_AIX5SP2) precvlist = TALLOC(1, struct pmsg, "umb"); BZERO((char*)precvlist, sizeof(struct pmsg)); precvlist->m_link = precvlist->m_rlink = precvlist; #endif for (i = 0; i < NUMSMHD; i++) outfrags[i].tf_mhdl = PVMMHDNULL; #if defined(IMA_PGON) || defined(IMA_I860) _msgwait(rmid); #endif #if defined(IMA_PGON) || defined(IMA_I860) || defined(IMA_SP2MPI) \ || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) if (pvminfo[0] != TDPROTOCOL) { sprintf(pvmtxt, "beatask() t-d protocol mismatch (%d/%d)\n", TDPROTOCOL, pvminfo[0]); pvmlogerror(pvmtxt); return PvmSysErr; } #endif n = 1; mysetpart = pvminfo[n++]; pvmmyptid = pvminfo[n++]; pvmudpmtu = pvminfo[n++]; pvmmydsig = pvminfo[n++]; #if defined(IMA_PGON) pvmpgonpartsize = pvminfo[n++]; #endif if (!pvmtrc.outtid) { pvmtrc.outtid = pvminfo[n++]; pvmtrc.outctx = pvminfo[n++]; pvmtrc.outtag = pvminfo[n++]; pvmctrc.outtid = pvmtrc.outtid; pvmctrc.outctx = pvmtrc.outctx; pvmctrc.outtag = pvmtrc.outtag; } if (!pvmtrc.trctid) { pvmtrc.trctid = pvminfo[n++]; pvmtrc.trcctx = pvminfo[n++]; pvmtrc.trctag = pvminfo[n++]; pvmctrc.trctid = pvmtrc.trctid; pvmctrc.trcctx = pvmtrc.trcctx; pvmctrc.trctag = pvmtrc.trctag; new_tracer++; } pvmmytid = mysetpart + pvmmynode; pvmfrgsiz = pvmudpmtu; if (p = getenv("PVMCTX")) pvmmyctx = pvmstrtoi(p); /* get trace mask from envar or zero it */ if ( (p = getenv("PVMTMASK")) ) { if ( strlen(p) + 1 == TEV_MASK_LENGTH ) BCOPY(p, pvmtrc.tmask, TEV_MASK_LENGTH); else TEV_MASK_INIT(pvmtrc.tmask); } else { TEV_MASK_INIT(pvmtrc.tmask); if ( new_tracer ) need_trcinfo++ } BCOPY(pvmtrc.tmask, pvmctrc.tmask, TEV_MASK_LENGTH); /* get trace buffering from envar */ if ((p = getenv("PVMTRCBUF"))) pvmtrc.trcbuf = atoi( p ); else { pvmtrc.trcbuf = 0; if ( new_tracer ) need_trcinfo++ } pvmctrc.trcbuf = pvmtrc.trcbuf; /* get trace options from envar */ if ((p = getenv("PVMTRCOPT"))) pvmtrc.trcopt = atoi( p ); else { pvmtrc.trcopt = 0; if ( new_tracer ) need_trcinfo++ } pvmctrc.trcopt = pvmtrc.trcopt; BZERO(&minfo, sizeof(minfo)); minfo.src = -1; minfo.ctx = SYSCTX_TC; minfo.tag = TC_CONREQ; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_conreq); minfo.tag = TC_CONACK; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_conack); minfo.tag = TC_TASKEXIT; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_taskexit); minfo.tag = TC_NOOP; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_noop); minfo.tag = TC_SETTRACE; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_settrace); minfo.tag = TC_SETTRCBUF; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_settrcbuf); minfo.tag = TC_SETTRCOPT; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_settrcopt); minfo.tag = TC_SETTMASK; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_settmask); minfo.tag = TC_SIBLINGS; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_siblings); if ( need_trcinfo ) { rbf = pvm_setrbuf( 0 ); if ( pvm_recvinfo( PVMTRACERCLASS, 0, PvmMboxDefault ) > 0 ) { pvm_upkint(&trctid, 1, 1); pvm_upkint(&trcctx, 1, 1); pvm_upkint(&trctag, 1, 1); pvm_upkint(&outctx, 1, 1); /* unused here */ pvm_upkint(&outtag, 1, 1); /* unused here */ pvm_upkstr(tmask); pvm_upkint(&tbuf, 1, 1); pvm_upkint(&topt, 1, 1); if ( pvmtrc.trctid == trctid && pvmtrc.trcctx == trcctx && pvmtrc.trctag == trctag ) { if ( strlen(tmask) + 1 == TEV_MASK_LENGTH ) { BCOPY(tmask, pvmtrc.tmask, TEV_MASK_LENGTH); BCOPY(pvmtrc.tmask, pvmctrc.tmask, TEV_MASK_LENGTH); } pvmtrc.trcbuf = tbuf; pvmctrc.trcbuf = pvmtrc.trcbuf; pvmtrc.trcopt = topt; pvmctrc.trcopt = pvmtrc.trcopt; } pvm_freebuf(pvm_setrbuf(rbf)); } else pvm_setrbuf(rbf); } tev_init(); if (TEV_AMEXCL) { TEV_ENDEXCL; } return 0; } int pvmendtask() { #if defined(IMA_PGON) || defined(IMA_I860) || defined(IMA_SP2MPI) \ || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) int i; #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) MPI_Status mpista; #endif for (i = 0; i < NUMSMHD; i++) if (outfrags[i].tf_mhdl != PVMMHDNULL) ASYNCWAIT(outfrags[i].tf_mhdl); #endif if (pvmmytid != -1) { pvmmytid = -1; } #ifdef IMA_CM5 CMMD_all_msgs_wait(); #endif #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) MPI_Finalize(); #endif /* XXX free rxfrag and rxlist */ return 0; } void check_for_exit(src) int src; { } /************************ ** Libpvm Functions ** ** ** ************************/ int pvm_getfds(fds) /* XXX this function kinda sucks */ int **fds; /* fd list return */ { int cc; cc = PvmNotImpl; return (cc < 0 ? lpvmerr("pvm_getfds", cc) : cc); } /* * receive a message for precv * returns 1 if message is received, 0 if not. * returns -1 on error */ int mpprecv(tid, tag, cp, len, rtid, rtag, rlen) int tid; int tag; void *cp; int len; int *rtid; int *rtag; int *rlen; { #if defined(IMA_PGON) || defined(IMA_CM5) long info[8]; #endif #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) MPI_Status info; int mpiflag = 0; int mpisiz; #endif long node; struct pmsg *up; int cc; node = (tid == -1) ? MPPANYNODE : tid & pvmtidnmask; #if defined(IMA_CM5) || defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) \ || defined(IMA_AIX5SP2) for (up = precvlist->m_link; up != precvlist; up = up->m_link) /* message picked up by psend */ if ((tag == -1 || tag == up->m_tag) && (tid == -1 || node == up->m_src)) { struct frag *fp; fp = up->m_frag->fr_rlink; if (fp->fr_max < len) len = fp->fr_max; BCOPY(fp->fr_dat, cp, len); if (rlen) *rlen = len; if (rtid) *rtid = up->m_src + (pvmmytid & ~pvmtidnmask); if (rtag) *rtag = up->m_tag; LISTDELETE(up, m_link, m_rlink); if (pvmdebmask & PDMPACKET) { sprintf(pvmtxt, "pvm_precv() task %x len %d tag %d\n", up->m_src + (pvmmytid & ~pvmtidnmask), rlen ? *rlen : fp->fr_max, rtag ? *rtag : up->m_tag); pvmlogerror(pvmtxt); } umbuf_free(up); return 1; } #endif /* * Msg routed from pvmd has type PMTPACK, so it may have already * been picked up by the last pvm_recv. If so, we call pvm_recv * to process it. Note we only need consider the case tid = -1, * because msg psent by another node cannot have type PMTPACK. */ if (tid == -1) { for (up = pvmrxlist->m_link; up != pvmrxlist; up = up->m_link) if (tag == -1 || tag == up->m_tag) return 0; /* go on to pvm_recv */ if (tag != -1) /* wait for msg with tag or PMTPACK */ while (!MSGPROBE(MPPANYNODE, tag, info)) if (MSGPROBE(pvmhostnode, PMTPACK, info)) { if ((cc = mroute(0, 0, 0, (struct timeval *)0)) < 0) return cc; for (up = pvmrxlist->m_link; up != pvmrxlist; up = up->m_link) if (tag == up->m_tag) return 0; /* go on to pvm_recv */ } } /* 1) from another node: 1a) tid = -1; 1b) tid given; 2) tag = -1 */ #ifndef IMA_PGON if (tag == -1) tag = MPPANYTAG; #endif if ((mpierrcode = PVMCRECV(node, tag, (char*)cp, len, pvmmyptype, info)) #if defined(IMA_PGON) || defined(IMA_CM5) && (mpierrcode < 0) #endif ) { pvmlogperror("precv() PVMCRECV"); return PvmSysErr; } if ((node = MSGSENDER(info)) == pvmhostnode) /* got null msg; go on to pvm_recv */ return 0; if (rlen) *rlen = MSGSIZE(info); if (rtid) *rtid = node + (pvmmytid & ~pvmtidnmask); if (rtag) *rtag = MSGTAG(info); if (pvmdebmask & PDMPACKET) { sprintf(pvmtxt, "pvm_precv() task %x len %d tag %d\n", node + (pvmmytid & ~pvmtidnmask), rlen ? *rlen : MSGSIZE(info), rtag ? *rtag : MSGTAG(info)); pvmlogerror(pvmtxt); } return 1; } int pvm_precv(tid, tag, cp, len, dt, rtid, rtag, rlen) int tid; int tag; void *cp; int len; int dt; int *rtid; int *rtag; int *rlen; { int nb, mc, src; int rbf; int cc = 0; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PRECV,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_RST, TEV_DATA_SCALAR, &tid, 1, 1 ); TEV_PACK_INT( TEV_DID_RMC, TEV_DATA_SCALAR, &tag, 1, 1 ); TEV_PACK_INT( TEV_DID_RCX, TEV_DATA_SCALAR, &pvmmyctx, 1, 1 ); ad = (long)cp; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &len, 1, 1 ); TEV_PACK_INT( TEV_DID_PDT, TEV_DATA_SCALAR, &dt, 1, 1 ); TEV_FIN; } } switch (dt) { case PVM_BYTE: len *= sizeof(char); break; case PVM_SHORT: case PVM_USHORT: len *= sizeof(short); break; case PVM_INT: case PVM_UINT: len *= sizeof(int); break; case PVM_LONG: case PVM_ULONG: len *= sizeof(long); break; case PVM_FLOAT: len *= sizeof(float); break; case PVM_CPLX: len *= sizeof(float) * 2; break; case PVM_DOUBLE: len *= sizeof(double); break; case PVM_DCPLX: len *= sizeof(double) * 2; break; case PVM_STR: cc = PvmNotImpl; break; default: cc = PvmBadParam; break; } if (!cc) { #if defined(IMA_PGON) || defined(IMA_CM5) || defined(IMA_SP2MPI) \ || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) int mask = pvmtidhmask | pvmtidtmask; /* same partition */ if (tid == -1 || (TIDISNODE(tid) && (tid & mask) == (pvmmytid & mask))) /* * 1) Don't know where msg is coming from. * 2) Expect msg from a node in the same partition. */ if (cc = mpprecv(tid, tag, cp, len, &src, &mc, &nb)) { /* 1) Whole msg recv'd. 2) Error */ if (rtid) *rtid = src; if (rtag) *rtag = mc; if (rlen) *rlen = nb; goto done; } #endif rbf = pvm_setrbuf(0); cc = pvm_recv(tid, tag); if (cc > 0) { pvm_bufinfo(cc, &nb, &mc, &src); if (rlen) *rlen = nb; if (nb < len) len = nb; if (rtag) *rtag = mc; if (rtid) *rtid = src; pvm_upkbyte((char *)cp, len, 1); pvm_freebuf(cc); cc = 0; } pvm_setrbuf(rbf); } done: if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PRECV,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); if ( cc < 0 ) nb = mc = src = -1; TEV_PACK_INT( TEV_DID_MNB, TEV_DATA_SCALAR, &nb, 1, 1 ); TEV_PACK_INT( TEV_DID_MC, TEV_DATA_SCALAR, &mc, 1, 1 ); TEV_PACK_INT( TEV_DID_MCX, TEV_DATA_SCALAR, &pvmmyctx, 1, 1 ); TEV_PACK_INT( TEV_DID_SRC, TEV_DATA_SCALAR, &src, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_precv", cc); return cc; } int pvm_psend(tid, tag, cp, len, dt) int tid; int tag; void *cp; int len; int dt; { int sbf; int cc = 0; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PSEND,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_DST, TEV_DATA_SCALAR, &tid, 1, 1 ); TEV_PACK_INT( TEV_DID_MC, TEV_DATA_SCALAR, &tag, 1, 1 ); TEV_PACK_INT( TEV_DID_MCX, TEV_DATA_SCALAR, &pvmmyctx, 1, 1 ); ad = (long)cp; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &len, 1, 1 ); TEV_PACK_INT( TEV_DID_PDT, TEV_DATA_SCALAR, &dt, 1, 1 ); TEV_FIN; } } switch (dt) { case PVM_BYTE: len *= sizeof(char); break; case PVM_SHORT: case PVM_USHORT: len *= sizeof(short); break; case PVM_INT: case PVM_UINT: len *= sizeof(int); break; case PVM_LONG: case PVM_ULONG: len *= sizeof(long); break; case PVM_FLOAT: len *= sizeof(float); break; case PVM_CPLX: len *= sizeof(float) * 2; break; case PVM_DOUBLE: len *= sizeof(double); break; case PVM_DCPLX: len *= sizeof(double) * 2; break; case PVM_STR: cc = PvmNotImpl; break; default: cc = PvmBadParam; break; } if (!cc) { #if defined(IMA_PGON) || defined(IMA_CM5) || defined(IMA_SP2MPI) \ || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) int mask = pvmtidhmask; /* host */ long node = tid & pvmtidnmask; #ifdef IMA_CM5 CMMD_mcb mhdl; int info; #endif #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) MPI_Request mhdl; MPI_Status info, mpista; int mpiflag = 0; int mpisiz; #endif mask |= pvmtidtmask; /* process type */ if (TIDISNODE(tid) && (tid & mask) == (pvmmytid & mask)) { if (pvmdebmask & PDMPACKET) { sprintf(pvmtxt, "pvm_psend() dst t%x len %d ptype=%ld node=%ld\n", tid, len, pvmmyptype, tid & pvmtidnmask); pvmlogerror(pvmtxt); } #ifdef IMA_PGON if (PVMCSEND(tag, cp, len, node, pvmmyptype) < 0) #endif #ifdef IMA_CM5 if ((mhdl = ASYNCSEND(tag, cp, len, node, pvmmyptype)) < 0) #endif #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) if (mpierrcode = MPI_Isend(cp, len, MPI_BYTE, node, tag, MPI_COMM_WORLD, &mhdl)) #endif { pvmlogperror("psend() PVMCSEND"); cc = PvmSysErr; goto done; } #if defined(IMA_CM5) || defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) \ || defined(IMA_AIX5SP2) while (!ASYNCDONE(mhdl)) { int rtag; /* * Psend is really a buffered send. We use async send to * avoid the overhead of buffering (50%). The behavior of * psend is now similar to RouteDirect: the sender blocks * until the other party signals its intention to receive, * but it can accept incoming messages in the meantime. * This avoids deadlock when two tasks send messages to * each other at the same time. */ if (MSGPROBE(MPPANYNODE, MPPANYTAG, info)) { if ((rtag = MSGTAG(info)) != PMTPACK) { struct pmsg *rxup; struct frag *fp; rxup = midtobuf(umbuf_new()); rxup->m_src = MSGSENDER(info); rxup->m_tag = rtag; fp = fr_new(MSGSIZE(info)); LISTPUTBEFORE(rxup->m_frag, fp, fr_link, fr_rlink); if ((mpierrcode = PVMCRECV(rxup->m_src, rtag, fp->fr_dat, fp->fr_max, pvmmyptype, info)) #ifdef IMA_CM5 && (mpierrcode < 0) #endif ) { pvmlogperror("psend() PVMCRECV"); cc = PvmSysErr; goto done; } LISTPUTBEFORE(precvlist, rxup, m_link, m_rlink); } else { if ((cc = mroute(0, 0, 0, (struct timeval *)0)) < 0) goto done; } } } #ifdef IMA_CM5 CMMD_free_mcb(mhdl); #endif #endif /*defined(IMA_CM5) || defined(IMA_SP2MPI)*/ } else #endif /*defined(IMA_PGON) || defined(IMA_CM5) || defined(IMA_SP2MPI)*/ { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataInPlace)); pvm_pkbyte((char *)cp, len, 1); if ((cc = pvm_send(tid, tag)) > 0) cc = 0; pvm_freebuf(pvm_setsbuf(sbf)); } } done: if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PSEND,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_psend", cc); return cc; } ./pvm3/src/lpvmmpp.c0100644007401100000360000004336306364671335013554 0ustar kohlgopher static char rcsid[] = "$Id: lpvmmpp.c,v 1.10 1997/07/21 14:31:57 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * lpvmmpp.c * * support routines for the MPP environment * */ #include #include #include #ifdef SYSVSTR #include #else #include #endif #include #include #include "global.h" #include "pvmalloc.h" #include "pvmfrag.h" #include "listmac.h" #include "bfunc.h" #include #include #include "tevmac.h" #include "mppmsg.h" #include "mppchunk.h" #include "lmsg.h" #include "pmsg.h" #include "pvmmimd.h" #include "global.h" #include "lpvm.h" #ifndef max #define max(a,b) ((a)>(b)?(a):(b)) #endif /*************** ** Globals ** ** ** ***************/ /* Indicate that we are able to receive directly into a users buffer */ extern struct msgid *pvm_inprecv; /* from lpvm.c */ int pvmhostnode; /*************** ** Private ** ** ** ***************/ static int pvmmynode; static int pvmpartsize; static int pvmmyndf; static int pvmtidnmask = TIDNODE; static int pvmtidpmask = TIDPTYPE; static int pvmtidhmask = TIDHOST; static int pvmmyptype; static struct frag * pvm_frReady __ProtoGlarp__(( MSG_INFO_PTR, int, MSGFUNC_PTR, MPP_DIRECTI_PTR, int, int *, struct frag ** )); static MPP_DIRECTI_PTR find_direct __ProtoGlarp__((MPP_DIRECTI_PTR, int, int )); /* header of posted precvs */ static struct msgid *precvIds = (struct msgid *) NULL; static MSG_INFO_PTR nodefrags = (MSG_INFO_PTR) NULL; /* pre-posted recv bufs */ static MSG_INFO_PTR pvmdfrags = (MSG_INFO_PTR) NULL; /* pre-posted recv bufs */ static MPP_DIRECTI_PTR pvmddirect = (MPP_DIRECTI_PTR) NULL; static MPP_DIRECTI_PTR peerdirect = (MPP_DIRECTI_PTR) NULL; static struct ttpcb *peerpcbs = (struct ttpcb *) NULL; static struct ttpcb *pvmdpcb = (struct ttpcb *) NULL; static struct pmsg *rxpmsgs = (struct pmsg *) NULL; static int inplaceDelay = 0; struct pmsg * midtobuf(); char * getenv(); /************************** ** Internal Functions ** ** ** **************************/ /* ------------ pvm_mppbeatask --------- */ /* * * Initialize libpvm, config process as a task. * This is called as the first step of each libpvm function so no * explicit initialization is required. * * Returns 0 if okay, else error code. */ int pvm_mpp_beatask(mytid, myptid, outtid, outctx, outtag, trctid, trcctx, trctag, udpmtu, schedtid, topvmd) int *mytid, *myptid; int *outtid, *outctx, *outtag; int *trctid, *trcctx, *trctag; int *udpmtu, *schedtid; struct ttpcb **topvmd; { char errtxt[64]; char *p; char *s; int ac = 0; int cc; int hostid = 0; int i; int myhost; int mynode, mysetpart; int partsize, partid; int pvminfo[SIZEHINFO]; /* proto, hostpart, ptid, MTU, NDF */ msgmid_t rmid; /* msg ID returned by imsgrecv() */ info_t minfo[MPPINFOSIZE]; /* info that might be returned by msgdone */ MSGFUNC_PTR mfunc; if (pvmmytid != -1) /* already configured */ return 0; mfunc = pvm_hostmsgfunc(); pvm_mpp_message_init(&mynode, &partsize, &pvmhostnode, &pvmmyptype); myhost = pvmhostnode; if (mynode < 0 || partsize < 0 || myhost < 0) { sprintf(errtxt, "mppbeatask(): bad init, node %d, part %d, host %d\n", mynode, partsize, myhost); pvmlogerror(errtxt); return PvmSysErr; } if (pvmdebmask & PDMPACKET) { sprintf(errtxt," %d Posting receive for config message \n", mynode); pvmlogerror(errtxt); } /* Post receive for the configuration message */ if ((*mfunc->imsgrecv)(hostid, MPPANY, PMTCONF, (char *) pvminfo, sizeof(pvminfo), MPPANY, (int *) NULL, &rmid) < 0) { pvmlogperror("beatask() recv pvminfo"); return PvmSysErr; } if (pvmdebmask & PDMPACKET) { sprintf(errtxt," %d Receive posted for config message \n", mynode); pvmlogerror(errtxt); } if ((pvm_useruid = getuid()) == -1) { pvmlogerror("can't getuid()\n"); return PvmSysErr; } pvmmyupid = getpid(); /* * initialize received-message list */ rxpmsgs = TALLOC(1, struct pmsg, "pmsgs"); BZERO((char*)rxpmsgs, sizeof(struct pmsg)); rxpmsgs->m_link = rxpmsgs->m_rlink = rxpmsgs; if (pvmdebmask & PDMPACKET) { sprintf(errtxt," %d Waiting for config message \n", mynode); pvmlogerror(errtxt); } while (!((*mfunc->msgdone)(0, &rmid, minfo))); if (pvmdebmask & PDMPACKET) { sprintf(errtxt," %d Got config message \n", mynode); pvmlogerror(errtxt); } if (pvminfo[0] != TDPROTOCOL) { sprintf(errtxt, "beatask() t-d protocol mismatch (%d/%d)\n", TDPROTOCOL, pvminfo[0]); pvmlogerror(errtxt); return PvmSysErr; } /* We now have the configuration message -- set up various parameters based on the message */ pvmmynode = mynode; mysetpart = pvminfo[1]; *myptid = pvminfo[2]; *udpmtu = pvminfo[3]; pvmmyndf = pvminfo[4]; pvmpartsize = pvminfo[5]; *outtid = pvminfo[6]; *outtag = pvminfo[7]; *outctx = pvminfo[8]; *trctid = pvminfo[9]; *trctag = pvminfo[10]; *trcctx = pvminfo[11]; *mytid = mysetpart + pvmmynode; pvmfrgsiz = pvmudpmtu; /* ---- set up the pre-allocated receive buffers ---- */ pvmddirect = new_directstruct( NSBUFS, NRBUFS ); peerdirect = new_vdirectstruct( pvmpartsize, NSBUFS, NRBUFS); pvmdfrags = init_recv_list(NSBUFS, PMTDBASE, MAXFRAGSIZE, 0, MPPANY, pvm_hostmsgfunc()); nodefrags = init_recv_list(NSBUFS, PMTPBASE, MAXFRAGSIZE, 0, MPPANY, pvm_nodemsgfunc()); /* intialize the packet numbering for packets from daemon */ fill_directstruct (pvmddirect, NRBUFS, pvm_tidtohost(pvmmytid), 0, PMTDBASE, 0, MPPANY); init_chunkostruct( pvmddirect->ordering, NSBUFS); /* intialize the packet numbering for packets from peers */ for (i = 0; i < pvmpartsize; i ++) { fill_directstruct (peerdirect + i, NRBUFS, i, 0, PMTPBASE, 0, MPPANY); init_chunkostruct( (peerdirect+i)->ordering, NSBUFS); } /* ---- Create Task, pvmd PCBs so that they can be found easily ----- */ peerpcbs = TALLOC(pvmpartsize + 1, struct ttpcb, "pcbs"); for (i = 0; i <= pvmpartsize; i ++) { BZERO((char *)(peerpcbs + i), sizeof(struct ttpcb)); (peerpcbs + i) -> tt_tid = i; (peerpcbs + i) -> tt_state = TTOPEN; (peerpcbs + i) -> mpdirect = peerdirect + i; } pvmdpcb = peerpcbs + pvmpartsize; pvmdpcb -> mpdirect = pvmddirect; *topvmd = pvmdpcb; precvIds = msgid_new(); precvIds->ms_link = precvIds->ms_rlink = precvIds; if (s = getenv("PVMINPLACEDELAY")) { inplaceDelay = atoi(s); pvmlogprintf("setting in place delay to %d \n", inplaceDelay); } else #if !defined(IMA_PGON) inplaceDelay = 0; #else inplaceDelay = 250; /* uSec. Seems to work well */ #endif pvm_setopt(PvmRoute, PvmDontRoute); /* Deny direct routing */ return 0; } /* ------ pvm_node_send ------- */ /* this routine sends a single array of data (a pvm fragment) to a process. * The semantics are such that the send is asynchronous with the send * message id added to the sendmsg list. * * inputs: * cp - array of data to be sent * len - length of data * ttpcbp - pointer to the task control structure * sendmsg - list of sendmsgs to add this one to (or merge with for PGONs) * inPlaceHeader - if this is an inplace header, this is == cp * inPlaceBodyLen - length of the inplace body that will follow this header * * outputs: * returns #bytes queued for sending * sendmsg is initialized if *sendmsg == NULL, otherwise the message is * added to the list of outstanding send messages */ int pvm_node_send(cp, len, ttpcbp, smsglist, inPlaceHeader, inPlaceBodyLen) char *cp; /* this is what we are supposed to be sending */ int len; /* this is the length of the frag */ struct ttpcb * ttpcbp; /* info about where this is going */ struct msgid **smsglist; /* msgid for this send */ char *inPlaceHeader; /* This is an inplace header? */ int inPlaceBodyLen; /* Length of inplace fragment */ { int cc; int dtid; int mask; /* used to mask different parts of tid */ msgmid_t mid; int node; /* destination node */ int partid; /* destination partition id */ int tag; MSGFUNC_PTR mfunc; #if defined(IMA_PGON) double dclock(); #endif static double lastClock; double delay; static int savelen = -1;/* save the length of inplace body for next call */ MPP_DIRECTI_PTR tdirect; struct msgid *cmsgid = (struct msgid *) NULL; mask = TIDHOST; dtid = ttpcbp -> tt_tid; if (TIDISNODE(dtid) && (dtid & pvmtidhmask) == (pvmmytid & pvmtidhmask) && (dtid & pvmtidpmask) == (pvmmytid & pvmtidpmask)) { node = dtid & pvmtidnmask; partid = pvmmyptype; /* send to node directly */ mfunc = pvm_nodemsgfunc(); /* point to node-node routines */ } else { node = pvmhostnode; partid = PVMDPTYPE; /* send to pvmd first */ mfunc = pvm_hostmsgfunc(); /* point to host-node routines */ } tdirect = ttpcbp->mpdirect; if (inPlaceHeader) { savelen = inPlaceBodyLen; #if defined(IMA_PGON) if (savelen > 4096 ) { lastClock = dclock(); delay = (double) inplaceDelay / 1e6; } #endif } if ( savelen >= 0 && inPlaceHeader == (char *) NULL) { tag = pvmmynode; /* send inplace body with my physical node # */ #if defined(IMA_PGON) if (savelen > 4096 ) while ((dclock() - lastClock) < delay); #endif savelen = -1; /* as the tag */ } else { tag = tdirect->tagbase + tdirect->sseq; if (++(tdirect->sseq) >= tdirect->nbufs) tdirect->sseq = 0; } { if ((cc = (*mfunc->imsgsend)(0,tag, cp, len, node, partid, &mid)) && (cc < 0)) { pvmlogperror("node_send() IMSGSEND \n "); return PvmSysErr; } /* can't merge id's add to the list */ if (!(mfunc->msgmerge) || !(*smsglist)) { if ( (cmsgid = msgid_new()) == (struct msgid *) NULL) { pvmlogerror("node_send(): couldn't allocate send msgid\n"); return PvmSysErr; } if (! (*smsglist)) /* intialize the list */ { *smsglist = cmsgid; cmsgid->ms_link = cmsgid->ms_rlink = cmsgid; } else /* put at the end of the list of message id's */ LISTPUTBEFORE(*smsglist, cmsgid, ms_link, ms_rlink); } else { cmsgid = *smsglist; cmsgid -> id = (*mfunc->msgmerge)(&(cmsgid->id), &mid); } if (cmsgid -> otid != node) { cmsgid -> id = mid; cmsgid -> otid = node; cmsgid -> complete = 0; cmsgid -> len += len; cmsgid -> mfunc = mfunc; } } return len; } /* ---------- pvm_node_mcast --------- */ /* This multicasts to tasks - it works takes an array of tids * and sends directly to tasks that are on the local partition using * pvm_send. * It returns a list of off-host tids and the number of off-host * tids. The off-host tids should then be sent to using pvm_mcast() * semantics. */ int pvm_node_mcast(tids, count, code, offhtids, offhcnt) int *tids; /* array of tids, on and off host */ int count; /* #of tids */ int code; /* msgtag tag */ int **offhtids; /* array of tids going off host, returns null if none */ int *offhcnt; /* # of tids going off host, returns 0 if none */ { int i; int mask = pvmtidhmask; /* host */ int nlocal = 0; int localidx = count; int nremote = 0; int *tmptids = (int *) NULL; *offhtids = (int *) NULL; *offhcnt = 0; if (!tids || count < 0) /* no tids, or bogus count */ return PvmOk; if (! (tmptids = TALLOC(count, int, "nmcast"))) { pvmlogerror("node_mcast(): couldn't alloc memory\n"); return PvmNoMem; } for (i = 0; i < count; i++) { if ( TIDISNODE(tids[i]) && (tids[i] & mask) == (pvmmytid & mask)) { /* put the local tids starting at the back of the array */ tmptids[--localidx] = tids[i]; /* tid local to us */ nlocal ++; } else { /* put non-local tids at the front of the array */ tmptids[nremote++] = tids[i]; } } /* multicast to the local tasks */ for (i = 0; i < nlocal; i++) pvm_send(tmptids[localidx++], code); /* loop of sends for now */ if (nlocal == count) { PVM_FREE(tmptids); tmptids = (int *) NULL; } else { *offhtids = tmptids; *offhcnt = nremote; } return PvmOk; } int mpp_pvmendtask() { if (pvmmytid != -1) { pvmmytid = -1; pvm_mpp_message_stop(); } return 0; } /* mpp-specific stuff on precv */ int pvm_mppprecv(tid, tag, cp ,len, dt, rtid, rtag, rlen) int tid; int tag; void *cp; int len; int dt; int *rtid; int *rtag; int *rlen; { char errtxt[64]; int rbf; int cc = 0; int l; int x; long ad; static int first = 1; static struct msgid * thisprecv; /* allocate a new message id for this precv */ if (first) { if ( !(thisprecv = msgid_new())) { pvmlogerror("mppprecv(): can't get memory \n"); return PvmNoMem; } first = 0; } thisprecv -> otid = tid; thisprecv -> tag = tag; thisprecv -> ctxt = pvm_getcontext(); thisprecv -> ubuf = cp; thisprecv -> len = len; thisprecv -> complete = 0; pvm_inprecv = thisprecv; if (!cc) { cc = pvm_recv(tid, tag); if (cc >= 0) { if (!(thisprecv->complete)) /* receive went into pvm buffers */ { pvm_bufinfo(cc, &l, rtag, rtid); if (rlen) *rlen = l; if (l < len) len = l; if (pvmdebmask & PDMMESSAGE) { sprintf(errtxt, "precv() unpacking message len = %d\n", l); pvmlogerror(errtxt); } pvm_upkbyte((char *)cp, len, 1); } else /* receive went straight into user memory */ { if(rlen) *rlen = thisprecv -> len; if (pvmdebmask & PDMMESSAGE) { sprintf(errtxt, "precv() short ckted into user buf len = %d\n", l); pvmlogerror(errtxt); } } cc = 0; } } pvm_inprecv = (struct msgid *) NULL; if (cc < 0) lpvmerr("pvm_mppprecv", cc); return cc; } /* ---------- pvm_mpppsend ------------- */ /* mpp_psend does short cuts on buffer management, o This is a reasonable hack that greatly decreases (overhead) latency. o It smacks the message structure directly. */ int pvm_mpppsend(cp, len, tid, tag) char *cp; int len; int tid; int tag; { static char nullusrmsg; static int first = 1; static int psbuf; static struct frag *dfrag; static struct pmsg *psmsg; static struct timeval ztv = { 0, 0 }; int savebuf; int cc; /* First call to psend will create a regular pvm buffer for packing. * o A new message is created as a by-product of pvm_mkbuf. * o A single (inplace) data buffer is created and put in the frag chain * o Later calls will simply twiddle the message buffer and the frag */ if (first) { psbuf = pvm_mkbuf(PvmDataInPlace); /* Make an inplace data buffer */ savebuf = pvm_setsbuf(psbuf); pvm_pkint(&cc, 1, 1); /* create a single frag for msg */ pvm_setsbuf(savebuf); psmsg = midtobuf(psbuf); /* save a pointer to the msg struct */ dfrag = psmsg->m_frag->fr_link; first = 0; } psmsg->m_ctx = pvmmyctx; /* set the context */ if (len) { dfrag->fr_buf = dfrag->fr_dat = cp; dfrag->fr_max = dfrag->fr_len = len; } else { dfrag->fr_buf = dfrag->fr_dat = &nullusrmsg; dfrag->fr_max = dfrag->fr_len = len; } cc = mroute(psbuf, tid, tag, &ztv); /* route the message */ return cc; } /* ----------- pvm_readfrompvmd ----------- */ struct frag * pvm_readfrompvmd() { static int hostbuf = 0; /* buffer we are working on */ static CHUNK_PTR readyFrags = (CHUNK_PTR) NULL; int mxbufs = NRBUFS; MSGFUNC_PTR mfunc; mfunc = pvm_hostmsgfunc(); /* check to see if any fragments are ready to be processed */ return (struct frag *) pvm_chunkReady( pvmdfrags, mxbufs, mfunc, pvmddirect, 1, &hostbuf, &readyFrags); } /* ----------- pvm_readfrompeer ----------- */ struct frag * pvm_readfrompeer() { static int nodebuf = 0; /* buffer we are working on */ static CHUNK_PTR readyFrags = (CHUNK_PTR) NULL; int mxbufs = NRBUFS; MSGFUNC_PTR mfunc; mfunc = pvm_nodemsgfunc(); /* check to see if any fragments are ready to be processed */ return (struct frag *) pvm_chunkReady( nodefrags, mxbufs, mfunc, peerdirect, pvmpartsize, &nodebuf, &readyFrags); } /* ------- init_precvMsgs ----- */ struct msgid * init_precvMsgs() { return msgid_new(); } /* ---------- mpp_ttpcb_find() ------- */ struct ttpcb * mpp_ttpcb_find(dtid) int dtid; { int i; if (TIDISNODE(dtid) && (dtid & pvmtidhmask) == (pvmmytid & pvmtidhmask) && (dtid & pvmtidpmask) == (pvmmytid & pvmtidpmask)) { i = dtid & pvmtidnmask; (peerpcbs + i)->tt_tid = dtid; return peerpcbs + i; } else return (struct ttpcb *) NULL; } /* ---------- pvm_mpp_pmsgs() ------- */ struct pmsg * pvm_mpp_pmsgs() { return rxpmsgs; } /* ----------- find_direct ---------- */ /* this is a hack to find the correct ordering structure for a node. */ MPP_DIRECTI_PTR pvm_find_direct (dlist, nstruct, node) MPP_DIRECTI_PTR dlist; int nstruct; int node; { node = node & pvmtidnmask; /* make sure this is a node */ if (dlist == pvmddirect) return pvmddirect; else { return dlist + node; } } struct msgid * pvm_mpp_get_precvids() { return pvm_inprecv; } ./pvm3/src/lpvmpack.c0100644007401100000360000013504507240353300013654 0ustar kohlgopher static char rcsid[] = "$Id: lpvmpack.c,v 1.21 2001/02/07 23:14:08 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * lpvmpack.c * * Typed packing/unpacking, message buffer manip. * * $Log: lpvmpack.c,v $ * Revision 1.21 2001/02/07 23:14:08 pvmsrc * First Half of CYGWIN Check-ins... * (Spanker=kohl) * * Revision 1.20 2001/02/05 23:05:55 pvmsrc * Fixed va_arg() issue. * - shouldn't use "char" or "short", always use at least "int"... * - error reported by gcc on latest Linux, documentation also * indicates this guideline on SGI and other arches... * - new test suite test validates functionality on SGI (of course, * it worked before, too :-). * - here's hoping this won't break anything... :-o * (Spanker=kohl) * * Revision 1.19 2000/02/16 21:59:46 pvmsrc * Fixed up #include stuff... * - use for IMA_TITN... * - #include before any NEEDMENDIAN #includes... * (Spanker=kohl) * * Revision 1.18 1999/11/08 17:44:34 pvmsrc * SGI compiler cleanup. * (Spanker=kohl) * * Revision 1.17 1999/08/12 15:12:19 pvmsrc * Fixed error in arg to check_for_exit(). * - mp freed before mp->m_src passed in...! D-Oh! * - bug submitted by Einar Arne Soerheim . * (Spanker=kohl) * * Revision 1.16 1999/07/08 19:00:01 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.15 1998/11/23 20:03:38 pvmsrc * In umbuf_free() must check_for_exit() after pmsg_unref() or else we * might splat a message structure before we try decrement it ref * count.. i.e sigfault. * Ops. * (Spanker=fagg) * * Revision 1.14 1998/11/20 20:04:08 pvmsrc * Changes so that win32 will compile & build. Also, common * Changes so that compiles & builds on NT. Also * common source on win32 & unix. * (Spanker=sscott) * * Revision 1.13 1998/11/20 19:30:09 pvmsrc * TC_TASKEXIT messages were setting pp->p_exited but check_for_exit() * was not being called as it got lost when umbuf_free() was updated * to use pmsg functions. * Added check_for_exit() back so that it could call peer_detach() * and thus free shared memory segments again... * A happy bug fix for Sun(tm). * (Spanker=fagg) * * Revision 1.12 1997/11/04 23:21:38 pvmsrc * Added SYSVSTR stuff. * (Spanker=kohl) * * Revision 1.11 1997/08/25 21:47:11 pvmsrc * Fixed pvm_setsbuf() problem with user-defined trace events. * - setsbuf was re-calling enc_trc_init(), pushing second header. * - gutted enc_trc_init() -> extracted into new enc_trc_hdr() routine * that pvm_mkbuf() calls ONCE... * (Spanker=kohl) * * Revision 1.10 1997/06/27 17:32:29 pvmsrc * Updated for WIN32 header files & Authors. * * Revision 1.9 1997/05/07 21:23:29 pvmsrc * Added new pvmupkstralloc() for dynamic string unpacking lunacy. * - with proto in header. * * Revision 1.8 1997/05/01 20:05:30 pvmsrc * Made pvmmidh and pvmmidhsiz global so that lpvmshmem can see * them..... [GEF] * * Revision 1.7 1997/05/01 14:11:48 pvmsrc * SGI Compiler Warning Cleanup. * * Revision 1.6 1997/01/28 19:26:50 pvmsrc * New Copyright Notice & Authors. * * Revision 1.5 1996/10/25 13:57:29 pvmsrc * Replaced old #includes for protocol headers: * - , "ddpro.h", "tdpro.h" * With #include of new combined header: * - * * Revision 1.4 1996/10/24 22:25:59 pvmsrc * Moved #include "global.h" below other #include's for typing. * Added #include of new "lpvm.h" header to replace explicit externs. * Modified trace event generation for message / packing routines: * - replaced old TEV_*[01] constants with new TEV_EVENT_ENTRY/EXIT. * - replaced standard pvm_pk*() calls with new TEV_PACK_*() macro * calls and TEV_DID_* identification. * - in pvm_pkstr(), don't pack string length for user-defined packing * (PvmDataTrace encoding). * * Revision 1.3 1996/10/23 15:57:25 pvmsrc * Changed pvm_freebuf so that freeing the null buffer '0' no longer * causes an error message. Many old 3.3 codes showed this through the * use of pvm_freebuf(pvm_setsbuf(x)) etc where there was no old send * buffer and hense under 3.4 an error was caused. * * This saves having to change BLACS, ParckBench and some collective * Group operations. * * When freeing buffer 0, PvmOK is returned. * * Revision 1.2 1996/09/23 23:28:55 pvmsrc * Initial Creation - original lpvmpack.c. * * Revision 1.12 1995/11/02 16:13:16 manchek * added NEEDSENDIAN switch * * Revision 1.11 1995/09/05 19:17:03 manchek * fp sometimes wasn't set in enc_xdr_init. * overflow test was wrong in enc_xdr_long * * Revision 1.10 1995/07/28 16:04:06 manchek * switch endian includes on flag, not arch name * * Revision 1.9 1995/07/19 20:15:45 manchek * enc*init should append a frag to message if there's already one * * Revision 1.8 1995/06/27 21:51:13 manchek * update fr_num_unpacked before pre_bcopy in byteupk * * Revision 1.7 1995/05/17 16:19:34 manchek * added support for CSPP shared memory * * Revision 1.6 1995/02/01 21:22:27 manchek * new function enc_xdr_ulong. * added overflow tests to enc_xdr_long, enc_xdr_ulong, return PvmOverflow * * Revision 1.5 1994/11/09 15:01:58 manchek * pvm_pkstr and pvm_packf(%s) must fail with PvmNotImpl if PvmDataInPlace * is used. * * Revision 1.4 1994/06/03 21:15:12 manchek * oops, missed a bcopy * * Revision 1.3 1994/06/03 20:38:17 manchek * version 3.3.0 * * Revision 1.2 1993/10/04 19:20:22 manchek * fixed vpackf() - floats get passed as doubles, must unpack that way * * Revision 1.1 1993/08/30 23:26:48 manchek * Initial revision * */ #ifdef WIN32 #include "pvmwin.h" #endif #include #ifdef NEEDMENDIAN #include #include #endif #ifdef NEEDENDIAN #include #endif #ifdef NEEDSENDIAN #include #endif #include #if defined(WIN32) || defined(CYGWIN) #include "..\xdr\types.h" #include "..\xdr\xdr.h" #else #include #include #endif #include #ifdef __STDC__ #include #else #include #endif #ifdef SYSVSTR #include #else #include #endif #include #include #include "pvmalloc.h" #include "pvmfrag.h" #include "pmsg.h" #include "listmac.h" #include "bfunc.h" #include "lpvm.h" #include "tevmac.h" #include "global.h" /* message heap element */ struct mhp { int m_free; /* free list (next or 0) */ struct pmsg *m_umb; /* message or null if on free list */ }; /*************** ** Globals ** ** ** ***************/ /* XXX these moved here from Private list so lpvmshmem can find them */ struct mhp *pvmmidh = 0; /* heap of all msgs */ int pvmmidhsiz = 0; /* length of pvmmidh */ /*************** ** Private ** ** ** ***************/ static int pvmmidhfree = 0; /* head of midh free list */ /*********************************************** ** Umbuf (pmsg wrapper with mid) Functions ** ** ** ***********************************************/ /* mid_new() * * Allocate a message id for a new message. * Returns mid (>0), or PvmNoMem if can't get memory. */ static int mid_new(mp) struct pmsg *mp; { static int nxtmidhsiz; int mid; int ns; struct mhp *newh; /* check free list empty */ if (!pvmmidhfree) { /* extend midh array */ if (pvmmidhsiz) { ns = nxtmidhsiz; if (!(newh = TREALLOC(pvmmidh, ns, struct mhp))) return PvmNoMem; nxtmidhsiz += pvmmidhsiz; } else { nxtmidhsiz = 13; ns = 8; if (!(newh = TALLOC(ns, struct mhp, "mid"))) return PvmNoMem; } pvmmidh = newh; /* put new entries on free list */ while (pvmmidhsiz < ns) { pvmmidh[pvmmidhsiz].m_umb = 0; pvmmidh[pvmmidhsiz].m_free = pvmmidhfree; pvmmidhfree = pvmmidhsiz++; } } /* take next from free list */ mid = pvmmidhfree; pvmmidhfree = pvmmidh[pvmmidhfree].m_free; pvmmidh[mid].m_umb = mp; mp->m_mid = mid; return mid; } /* mid_free() * * Return a message id to the free list. */ static void mid_free(mid) int mid; { if (mid <= 0 || mid >= pvmmidhsiz || !pvmmidh[mid].m_umb) return; pvmmidh[mid].m_umb = 0; pvmmidh[mid].m_free = pvmmidhfree; pvmmidhfree = mid; } /* struct () * * Create a new empty umbuf. */ struct pmsg * umbuf_new() { struct pmsg *mp; if (mp = pmsg_new(0)) { if (mid_new(mp) < 0) { pmsg_unref(mp); mp = 0; } } return mp; } void check_for_free(); /* we need the def here before we call it from umbuf_free() */ /* umbuf_free() * * Free an umbuf */ int umbuf_free(mp) struct pmsg *mp; { int src; mid_free( mp->m_mid ); mp->m_mid = 0; src = mp->m_src; pmsg_unref( mp ); /* check to see if an TC_TASKEXIT message has been caught */ check_for_exit( src ); return 0; } /* midtobuf() * * Return pointer to message buffer given int message id. */ struct pmsg * midtobuf(mid) int mid; { return ((mid > 0 && mid < pvmmidhsiz) ? pvmmidh[mid].m_umb : 0); } int umbuf_dump(mid, lvl) int mid; int lvl; /* 0 - summary, 1 - frag lengths, 2 - frag data */ { struct pmsg *mp; struct frag *fp; if (mid <= 0) { pvmlogprintf("umbuf_dump() BadParam\n"); return PvmBadParam; } if (!(mp = midtobuf(mid))) { pvmlogprintf("umbuf_dump() NoSuchBuf\n"); return PvmNoSuchBuf; } mp = pvmmidh[mid].m_umb; pmsg_dump(mp, lvl); return 0; } int umbuf_list(lvl) int lvl; { int i; struct frag *fp; int rlen; for (i = 1; i < pvmmidhsiz; i++) if (pvmmidh[i].m_umb) umbuf_dump(i, lvl); return 0; } /************************ ** Libpvm Functions ** ** ** ************************/ int pvm_mkbuf(enc) int enc; /* data format */ { struct pmsg *mp; struct frag *fp; int dotrchdr = 0; int cc = 0; int tmp; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_MKBUF,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_ME, TEV_DATA_SCALAR, &enc, 1, 1 ); TEV_FIN; } } switch (enc) { /* verify encoding */ case PvmDataDefault: enc = 0x10000000; /* XXX this just forces XDR */ break; case PvmDataRaw: enc = pvmmydsig; break; case PvmDataInPlace: enc = 0x20000000; break; case PvmDataTrace: enc = 0x40000000; dotrchdr++; break; default: cc = PvmBadParam; } if (!cc) { if (mp = umbuf_new()) { mp->m_src = pvmmytid; pmsg_setenc(mp, enc); cc = mp->m_mid; if (dotrchdr) { tmp = enc_trc_hdr(mp); cc = ( tmp < 0 ) ? tmp : cc; } } else cc = PvmNoMem; } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_MKBUF,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_MB, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_mkbuf", cc); return cc; } int pvm_freebuf(mid) int mid; /* message handle */ { int cc; struct pmsg *mp; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_FREEBUF,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_MB, TEV_DATA_SCALAR, &mid, 1, 1 ); TEV_FIN; } } if (mid < 0) { cc = PvmBadParam; } else if (mp = midtobuf(mid)) { if (pvmsbuf == mp) pvmsbuf = 0; if (pvmrbuf == mp) pvmrbuf = 0; umbuf_free(mp); cc = 0; } else if (mid) cc = PvmNoSuchBuf; else cc = PvmOk; /* don't complain when freeing the null/0 buffer */ /* many 3.3 codes switch and free without checking */ if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_FREEBUF,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_freebuf", cc); return cc; } int pvm_setsbuf(mid) int mid; { struct pmsg *mp = 0; int cc = 0; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_SETSBUF,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_MB, TEV_DATA_SCALAR, &mid, 1, 1 ); TEV_FIN; } } if (mid < 0) { cc = PvmBadParam; } else if (mid == 0) { cc = pvmsbuf ? pvmsbuf->m_mid : 0; pvmsbuf = 0; } else if (mp = midtobuf(mid)) { if (mp == pvmrbuf) pvmrbuf = 0; cc = pvmsbuf ? pvmsbuf->m_mid : 0; pvmsbuf = mp; (mp->m_codef->enc_init)(mp); } else cc = PvmNoSuchBuf; if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_SETSBUF,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_MSB, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_setsbuf", cc); return cc; } int pvm_getsbuf() { int cc; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_GETSBUF,TEV_EVENT_ENTRY)) TEV_FIN; } cc = pvmsbuf ? pvmsbuf->m_mid : 0; if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_GETSBUF,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_MSB, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return cc; } int pvm_setrbuf(mid) int mid; { struct pmsg *mp = 0; int cc = 0; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_SETRBUF,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_MB, TEV_DATA_SCALAR, &mid, 1, 1 ); TEV_FIN; } } if (mid < 0) { cc = PvmBadParam; } else if (mid == 0) { cc = pvmrbuf ? pvmrbuf->m_mid : 0; pvmrbuf = 0; } else if (mp = midtobuf(mid)) { if (mp == pvmsbuf) pvmsbuf = 0; cc = pvmrbuf ? pvmrbuf->m_mid : 0; pvmrbuf = mp; (mp->m_codef->dec_init)(mp); } else cc = PvmNoSuchBuf; if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_SETRBUF,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_MRB, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_setrbuf", cc); return cc; } int pvm_getrbuf() { int cc; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_GETRBUF,TEV_EVENT_ENTRY)) TEV_FIN; } cc = pvmrbuf ? pvmrbuf->m_mid : 0; if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_GETRBUF,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_MRB, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return cc; } int pvm_initsend(enc) int enc; { int cc; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_INITSEND,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_ME, TEV_DATA_SCALAR, &enc, 1, 1 ); TEV_FIN; } } if ((cc = pvm_mkbuf(enc)) >= 0) { if (pvmsbuf) pvm_freebuf(pvmsbuf->m_mid); pvm_setsbuf(cc); } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_INITSEND,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_MSB, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_initsend", cc); return cc; } int pvm_bufinfo(mid, len, code, tid) int mid; int *len; int *code; int *tid; { struct pmsg *mp; int cc; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_BUFINFO,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_MB, TEV_DATA_SCALAR, &mid, 1, 1 ); TEV_FIN; } } if (mid <= 0) cc = PvmBadParam; else if (mp = midtobuf(mid)) { cc = PvmOk; if (len) { if (mp->m_flag & MM_PACK) pmsg_setlen(mp); *len = mp->m_len; } if (code) *code = mp->m_tag; if (tid) *tid = mp->m_src; } else cc = PvmNoSuchBuf; if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_BUFINFO,TEV_EVENT_EXIT)) { int ln, tg, sc; TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); if (!cc) { ln = mp->m_len; tg = mp->m_tag; sc = mp->m_src; } else ln = tg = sc = cc; TEV_PACK_INT( TEV_DID_INB, TEV_DATA_SCALAR, &ln, 1, 1 ); TEV_PACK_INT( TEV_DID_IMC, TEV_DATA_SCALAR, &tg, 1, 1 ); TEV_PACK_INT( TEV_DID_IST, TEV_DATA_SCALAR, &sc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_bufinfo", cc); return cc; } int pvm_pkbyte(cp, cnt, std) char *cp; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PKBYTE,TEV_EVENT_ENTRY)) { ad = (long)cp; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmsbuf) cc = PvmNoBuf; else cc = (pvmsbuf->m_codef->enc_byte) (pvmsbuf, (void*)cp, cnt, std, 1); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PKBYTE,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_pkbyte", cc) : PvmOk); } int pvm_upkbyte(cp, cnt, std) char *cp; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_UPKBYTE,TEV_EVENT_ENTRY)) { ad = (long)cp; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmrbuf) cc = PvmNoBuf; else cc = (pvmrbuf->m_codef->dec_byte) (pvmrbuf, (void*)cp, cnt, std, 1); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_UPKBYTE,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_upkbyte", cc) : PvmOk); } int pvm_pkcplx(xp, cnt, std) float *xp; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PKCPLX,TEV_EVENT_ENTRY)) { ad = (long)xp; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmsbuf) cc = PvmNoBuf; else cc = (pvmsbuf->m_codef->enc_cplx) (pvmsbuf, (void*)xp, cnt, std, sizeof(float)*2); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PKCPLX,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_pkcplx", cc) : PvmOk); } int pvm_upkcplx(xp, cnt, std) float *xp; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_UPKCPLX,TEV_EVENT_ENTRY)) { ad = (long)xp; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmrbuf) cc = PvmNoBuf; else cc = (pvmrbuf->m_codef->dec_cplx) (pvmrbuf, (void*)xp, cnt, std, sizeof(float)*2); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_UPKCPLX,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_upkcplx", cc) : PvmOk); } int pvm_pkdcplx(zp, cnt, std) double *zp; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PKDCPLX,TEV_EVENT_ENTRY)) { ad = (long)zp; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmsbuf) cc = PvmNoBuf; else cc = (pvmsbuf->m_codef->enc_dcplx) (pvmsbuf, (void*)zp, cnt, std, sizeof(double)*2); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PKDCPLX,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_pkdcplx", cc) : PvmOk); } int pvm_upkdcplx(zp, cnt, std) double *zp; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_UPKDCPLX,TEV_EVENT_ENTRY)) { ad = (long)zp; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmrbuf) cc = PvmNoBuf; else cc = (pvmrbuf->m_codef->dec_dcplx) (pvmrbuf, (void*)zp, cnt, std, sizeof(double)*2); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_UPKDCPLX,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_upkdcplx", cc) : PvmOk); } int pvm_pkdouble(dp, cnt, std) double *dp; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PKDOUBLE,TEV_EVENT_ENTRY)) { ad = (long)dp; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmsbuf) cc = PvmNoBuf; else cc = (pvmsbuf->m_codef->enc_double) (pvmsbuf, (void*)dp, cnt, std, sizeof(double)); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PKDOUBLE,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_pkdouble", cc) : PvmOk); } int pvm_upkdouble(dp, cnt, std) double *dp; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_UPKDOUBLE,TEV_EVENT_ENTRY)) { ad = (long)dp; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmrbuf) cc = PvmNoBuf; else cc = (pvmrbuf->m_codef->dec_double) (pvmrbuf, (void*)dp, cnt, std, sizeof(double)); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_UPKDOUBLE,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_upkdouble", cc) : PvmOk); } int pvm_pkfloat(fp, cnt, std) float *fp; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PKFLOAT,TEV_EVENT_ENTRY)) { ad = (long)fp; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmsbuf) cc = PvmNoBuf; else cc = (pvmsbuf->m_codef->enc_float) (pvmsbuf, (void*)fp, cnt, std, sizeof(float)); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PKFLOAT,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_pkfloat", cc) : PvmOk); } int pvm_upkfloat(fp, cnt, std) float *fp; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_UPKFLOAT,TEV_EVENT_ENTRY)) { ad = (long)fp; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmrbuf) cc = PvmNoBuf; else cc = (pvmrbuf->m_codef->dec_float) (pvmrbuf, (void*)fp, cnt, std, sizeof(float)); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_UPKFLOAT,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_upkfloat", cc) : PvmOk); } int pvm_pkint(np, cnt, std) int *np; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PKINT,TEV_EVENT_ENTRY)) { ad = (long)np; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmsbuf) cc = PvmNoBuf; else cc = (pvmsbuf->m_codef->enc_int) (pvmsbuf, (void*)np, cnt, std, sizeof(int)); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PKINT,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_pkint", cc) : PvmOk); } int pvm_pkuint(np, cnt, std) unsigned int *np; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PKUINT,TEV_EVENT_ENTRY)) { ad = (long)np; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmsbuf) cc = PvmNoBuf; else cc = (pvmsbuf->m_codef->enc_uint) (pvmsbuf, (void*)np, cnt, std, sizeof(int)); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PKUINT,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_pkuint", cc) : PvmOk); } int pvm_upkint(np, cnt, std) int *np; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_UPKINT,TEV_EVENT_ENTRY)) { ad = (long)np; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmrbuf) cc = PvmNoBuf; else cc = (pvmrbuf->m_codef->dec_int) (pvmrbuf, (void*)np, cnt, std, sizeof(int)); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_UPKINT,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_upkint", cc) : PvmOk); } int pvm_upkuint(np, cnt, std) unsigned int *np; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_UPKUINT,TEV_EVENT_ENTRY)) { ad = (long)np; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmrbuf) cc = PvmNoBuf; else cc = (pvmrbuf->m_codef->dec_uint) (pvmrbuf, (void*)np, cnt, std, sizeof(int)); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_UPKUINT,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_upkuint", cc) : PvmOk); } int pvm_pklong(np, cnt, std) long *np; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PKLONG,TEV_EVENT_ENTRY)) { ad = (long)np; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmsbuf) cc = PvmNoBuf; else cc = (pvmsbuf->m_codef->enc_long) (pvmsbuf, (void*)np, cnt, std, sizeof(long)); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PKLONG,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_pklong", cc) : PvmOk); } int pvm_pkulong(np, cnt, std) unsigned long *np; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PKULONG,TEV_EVENT_ENTRY)) { ad = (long)np; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmsbuf) cc = PvmNoBuf; else cc = (pvmsbuf->m_codef->enc_ulong) (pvmsbuf, (void*)np, cnt, std, sizeof(long)); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PKULONG,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_pkulong", cc) : PvmOk); } int pvm_upklong(np, cnt, std) long *np; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_UPKLONG,TEV_EVENT_ENTRY)) { ad = (long)np; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmrbuf) cc = PvmNoBuf; else cc = (pvmrbuf->m_codef->dec_long) (pvmrbuf, (void*)np, cnt, std, sizeof(long)); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_UPKLONG,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_upklong", cc) : PvmOk); } int pvm_upkulong(np, cnt, std) unsigned long *np; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_UPKULONG,TEV_EVENT_ENTRY)) { ad = (long)np; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmrbuf) cc = PvmNoBuf; else cc = (pvmrbuf->m_codef->dec_ulong) (pvmrbuf, (void*)np, cnt, std, sizeof(long)); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_UPKULONG,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_upkulong", cc) : PvmOk); } int pvm_pkshort(np, cnt, std) short *np; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PKSHORT,TEV_EVENT_ENTRY)) { ad = (long)np; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmsbuf) cc = PvmNoBuf; else cc = (pvmsbuf->m_codef->enc_short) (pvmsbuf, (void*)np, cnt, std, sizeof(short)); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PKSHORT,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_pkshort", cc) : PvmOk); } int pvm_pkushort(np, cnt, std) unsigned short *np; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PKUSHORT,TEV_EVENT_ENTRY)) { ad = (long)np; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmsbuf) cc = PvmNoBuf; else cc = (pvmsbuf->m_codef->enc_ushort) (pvmsbuf, (void*)np, cnt, std, sizeof(short)); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PKUSHORT,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_pkushort", cc) : PvmOk); } int pvm_upkshort(np, cnt, std) short *np; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_UPKSHORT,TEV_EVENT_ENTRY)) { ad = (long)np; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmrbuf) cc = PvmNoBuf; else cc = (pvmrbuf->m_codef->dec_short) (pvmrbuf, (void*)np, cnt, std, sizeof(short)); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_UPKSHORT,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_upkshort", cc) : PvmOk); } int pvm_upkushort(np, cnt, std) unsigned short *np; int cnt; int std; { int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_UPKUSHORT,TEV_EVENT_ENTRY)) { ad = (long)np; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &cnt, 1, 1 ); TEV_PACK_INT( TEV_DID_PSD, TEV_DATA_SCALAR, &std, 1, 1 ); TEV_FIN; } } if (cnt < 0) cc = PvmBadParam; else if (!pvmrbuf) cc = PvmNoBuf; else cc = (pvmrbuf->m_codef->dec_ushort) (pvmrbuf, (void*)np, cnt, std, sizeof(short)); if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_UPKUSHORT,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_upkushort", cc) : PvmOk); } int pvm_pkstr(cp) char *cp; { int l = strlen(cp) + 1; int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PKSTR,TEV_EVENT_ENTRY)) { ad = (long)cp; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_FIN; } } if (!pvmsbuf) cc = PvmNoBuf; else { /* can't do InPlace without a lot of grief */ if (pvmsbuf->m_enc == 0x20000000) cc = PvmNotImpl; /* user defined, don't pack len, don't pack '\0' */ else if (pvmsbuf->m_enc == 0x40000000) cc = (pvmsbuf->m_codef->enc_byte) (pvmsbuf, (void*)cp, l - 1, 1, 1); else if (!(cc = (pvmsbuf->m_codef->enc_int) (pvmsbuf, (void*)&l, 1, 1, sizeof(int)))) cc = (pvmsbuf->m_codef->enc_byte) (pvmsbuf, (void*)cp, l, 1, 1); } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PKSTR,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_pkstr", cc) : PvmOk); } int pvm_upkstr(cp) char *cp; { int l; int cc; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_UPKSTR,TEV_EVENT_ENTRY)) { ad = (long)cp; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_FIN; } } if (!pvmrbuf) cc = PvmNoBuf; else { if (!(cc = (pvmrbuf->m_codef->dec_int) (pvmrbuf, (void*)&l, 1, 1, sizeof(int)))) cc = (pvmrbuf->m_codef->dec_byte) (pvmrbuf, (void*)cp, l, 1, 1); } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_UPKSTR,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_upkstr", cc) : PvmOk); } /* pvmupkstralloc() (from pvmdpack.c upkstralloc(), spanked slightly) * * Unpack a string from current message. Result is null-terminated, * and in dynamic space.. * Returns 0 if ok. */ int pvmupkstralloc(ss) char **ss; /* return pointer */ { int cc; int l; if (!pvmrbuf) cc = PvmNoBuf; else { if (!(cc = (pvmrbuf->m_codef->dec_int) (pvmrbuf, (void*)&l, 1, 1, sizeof(int)))) { *ss = TALLOC(l, char, "pustr"); if ((cc = (pvmrbuf->m_codef->dec_byte) (pvmrbuf, (void*)*ss, l, 1, 1)) < 0) { PVM_FREE(*ss); *ss = 0; } } } return cc; } int pvm_vpackf(fmt, ap) char *fmt; va_list ap; { char *p = fmt; int cc; int cnt, std; /* count and stride of element */ int vh, vl, vu; /* short, long, unsigned variety */ int isv; /* param is a value not address */ struct encvec *codef; char tc, *cp; /* each type and a pointer */ short th, *hp; int tn, *np; long tl, *lp; float tf, *fp; double td, *dp; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PACKF,TEV_EVENT_ENTRY)) { TEV_PACK_STRING( TEV_DID_PF, TEV_DATA_SCALAR, fmt, 1, 1 ); TEV_FIN; } } if (p[0] == '%' && p[1] == '+') { cc = va_arg(ap, int); if ((cc = pvm_initsend(cc)) < 0) goto hork; p += 2; } if (!pvmsbuf) { cc = PvmNoBuf; goto hork; } codef = pvmsbuf->m_codef; while (*p) { if (*p++ == '%') { cnt = 1; std = 1; isv = 1; vl = vh = vu = 0; if (*p == '*') { cnt = va_arg(ap, int); isv = 0; p++; } else if (isdigit(*p)) { cnt = atoi(p); isv = 0; while (isdigit(*++p)) ; } if (*p == '.') { isv = 0; if (*++p == '*') { std = va_arg(ap, int); p++; } else if (isdigit(*p)) { std = atoi(p); while (isdigit(*++p)) ; } } for (cc = 1; cc; ) { switch (*p++) { case 'h': vh = 1; break; case 'l': vl = 1; break; case 'u': vu = 1; break; default: p--; cc = 0; } } switch (*p++) { case 'c': if (isv) { tc = (char) va_arg(ap, int); cp = &tc; } else cp = va_arg(ap, char *); cc = (codef->enc_byte) (pvmsbuf, (void*)cp, cnt, std, 1); #ifdef DEBUGPACKF printf("%d %d %s%schar\n", cnt, std, (vu ? "unsigned " : ""), (isv ? "" : "&")); #else vu = vu; /* sgi compiler */ #endif break; case 'd': if (vl) { if (isv) { tl = va_arg(ap, long); lp = &tl; } else lp = va_arg(ap, long *); cc = (codef->enc_long) (pvmsbuf, (void*)lp, cnt, std, sizeof(long)); } else if (vh) { if (isv) { th = (short) va_arg(ap, int); hp = &th; } else hp = va_arg(ap, short *); cc = (codef->enc_short) (pvmsbuf, (void*)hp, cnt, std, sizeof(short)); } else { if (isv) { tn = va_arg(ap, int); np = &tn; } else np = va_arg(ap, int *); cc = (codef->enc_int) (pvmsbuf, (void*)np, cnt, std, sizeof(int)); } #ifdef DEBUGPACKF printf("%d %d %s%s%s%sint\n", cnt, std, (vu ? "unsigned " : ""), (vl ? "long " : ""), (vh ? "short " : ""), (isv ? "" : "&")); #endif break; case 'f': if (vl) { if (isv) { td = va_arg(ap, double); dp = &td; } else dp = va_arg(ap, double *); cc = (codef->enc_double) (pvmsbuf, (void*)dp, cnt, std, sizeof(double)); } else { if (isv) { /* tf = va_arg(ap, float); */ td = va_arg(ap, double); tf = td; fp = &tf; } else fp = va_arg(ap, float *); cc = (codef->enc_float) (pvmsbuf, (void*)fp, cnt, std, sizeof(float)); } #ifdef DEBUGPACKF printf("%d %d %s%s\n", cnt, std, (isv ? "" : "&"), (vl ? "double" : "float")); #endif break; case 'x': if (vl) { dp = va_arg(ap, double *); cc = (codef->enc_dcplx) (pvmsbuf, (void*)dp, cnt, std, sizeof(double)*2); } else { fp = va_arg(ap, float *); cc = (codef->enc_cplx) (pvmsbuf, (void*)fp, cnt, std, sizeof(float)*2); } #ifdef DEBUGPACKF printf("%d %d %s&cplx\n", cnt, std, (vl ? "double " : "")); #endif break; case 's': if (pvmsbuf->m_enc == 2) /* oops, can't do this */ cc = PvmNotImpl; else { cp = va_arg(ap, char *); cnt = strlen(cp) + 1; if (!(cc = (codef->enc_int) (pvmsbuf, (void*)&cnt, 1, 1, sizeof(int)))) cc = (codef->enc_byte) (pvmsbuf, (void*)cp, cnt, 1, 1); #ifdef DEBUGPACKF printf("string\n"); #endif } break; default: cc = PvmBadParam; break; } if (cc) goto hork; } /* else printf("'%c'\n", *(p - 1)); */ } cc = PvmOk; hork: if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PACKF,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_packf", cc); return cc; } int #ifdef __STDC__ pvm_packf(const char *fmt, ...) #else pvm_packf(va_alist) va_dcl #endif { va_list ap; int cc; #ifdef __STDC__ va_start(ap, fmt); #else char *fmt; va_start(ap); fmt = va_arg(ap, char *); #endif cc = pvm_vpackf(fmt, ap); va_end(ap); return cc; } int pvm_vunpackf(fmt, ap) char *fmt; va_list ap; { char *p = fmt; int cc; int cnt, std; /* count and stride of element */ int vh, vl, vu; /* short, long, unsigned variety */ struct encvec *codef; char *cp; /* pointers for each type */ short *hp; int *np; long *lp; float *fp; double *dp; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_UNPACKF,TEV_EVENT_ENTRY)) { TEV_PACK_STRING( TEV_DID_PF, TEV_DATA_SCALAR, fmt, 1, 1 ); TEV_FIN; } } if (!pvmrbuf) { cc = PvmNoBuf; goto hork; } codef = pvmrbuf->m_codef; while (*p) { if (*p++ == '%') { cnt = 1; std = 1; vl = vh = vu = 0; if (*p == '*') { cnt = va_arg(ap, int); p++; } else if (isdigit(*p)) { cnt = atoi(p); while (isdigit(*++p)) ; } if (*p == '.') { if (*++p == '*') { std = va_arg(ap, int); p++; } else if (isdigit(*p)) { std = atoi(p); while (isdigit(*++p)) ; } } for (cc = 1; cc; ) { switch (*p++) { case 'h': vh = 1; break; case 'l': vl = 1; break; case 'u': vu = 1; break; default: p--; cc = 0; } } switch (*p++) { case 'c': cp = va_arg(ap, char *); cc = (codef->dec_byte) (pvmrbuf, (void*)cp, cnt, std, 1); break; case 'd': if (vl) { lp = va_arg(ap, long *); cc = (vu ? codef->dec_ulong : codef->dec_long) (pvmrbuf, (void*)lp, cnt, std, sizeof(long)); } else if (vh) { hp = va_arg(ap, short *); cc = (vu ? codef->dec_ushort : codef->dec_short) (pvmrbuf, (void*)hp, cnt, std, sizeof(short)); } else { np = va_arg(ap, int *); cc = (vu ? codef->dec_uint : codef->dec_int) (pvmrbuf, (void*)np, cnt, std, sizeof(int)); } break; case 'f': if (vl) { dp = va_arg(ap, double *); cc = (codef->dec_double) (pvmrbuf, (void*)dp, cnt, std, sizeof(double)); } else { fp = va_arg(ap, float *); cc = (codef->dec_float) (pvmrbuf, (void*)fp, cnt, std, sizeof(float)); } break; case 'x': if (vl) { dp = va_arg(ap, double *); cc = (codef->dec_dcplx) (pvmrbuf, (void*)dp, cnt, std, sizeof(double)*2); } else { fp = va_arg(ap, float *); cc = (codef->dec_cplx) (pvmrbuf, (void*)fp, cnt, std, sizeof(float)*2); } break; case 's': cp = va_arg(ap, char *); if (!(cc = (codef->dec_int) (pvmrbuf, (void*)&cnt, 1, 1, sizeof(int)))) cc = (codef->dec_byte) (pvmrbuf, (void*)cp, cnt, 1, 1); break; default: cc = PvmBadParam; break; } if (cc) goto hork; } } cc = PvmOk; hork: if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_UNPACKF,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_unpackf", cc); return cc; } int #ifdef __STDC__ pvm_unpackf(const char *fmt, ...) #else pvm_unpackf(va_alist) va_dcl #endif { va_list ap; int cc; #ifdef __STDC__ va_start(ap, fmt); #else char *fmt; va_start(ap); fmt = va_arg(ap, char *); #endif cc = pvm_vunpackf(fmt, ap); va_end(ap); return cc; } int pvm_getminfo(mid, info) int mid; struct pvmminfo *info; { struct pmsg *mp; int cc; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_GETMINFO,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_MB, TEV_DATA_SCALAR, &mid, 1, 1 ); TEV_FIN; } } if (mid <= 0) cc = PvmBadParam; else if (mp = midtobuf(mid)) { if (mp->m_flag & MM_PACK) pmsg_setlen(mp); info->len = mp->m_len; info->ctx = mp->m_ctx; info->tag = mp->m_tag; info->wid = mp->m_wid; info->enc = mp->m_enc; info->crc = mp->m_crc; info->src = mp->m_src; info->dst = mp->m_dst; cc = PvmOk; } else cc = PvmNoSuchBuf; if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_GETMINFO,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_getminfo", cc); return cc; } int pvm_setminfo(mid, info) int mid; struct pvmminfo *info; { struct pmsg *mp; int cc; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_SETMINFO,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_MB, TEV_DATA_SCALAR, &mid, 1, 1 ); TEV_FIN; } } if (mid <= 0) cc = PvmBadParam; else if (mp = midtobuf(mid)) { mp->m_ctx = info->ctx; mp->m_tag = info->tag; mp->m_wid = info->wid; mp->m_src = info->src; mp->m_dst = info->dst; cc = PvmOk; } else cc = PvmNoSuchBuf; if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_SETMINFO,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_setminfo", cc); return cc; } int pvm_pkmesg(mid) int mid; { int cc = 0; struct pmsg *mp; if (mid <= 0) cc = PvmBadParam; else if (mp = midtobuf(mid)) { if (!pvmsbuf) cc = PvmNoBuf; else if (mp == pvmsbuf) cc = PvmBadParam; else cc = pmsg_pack(pvmsbuf, mp); } else cc = PvmNoSuchBuf; return cc; } int pvm_pkmesgbody(mid) int mid; { int cc = 0; struct pmsg *mp; if (mid <= 0) cc = PvmBadParam; else if (mp = midtobuf(mid)) { if (!pvmsbuf) cc = PvmNoBuf; else if (mp == pvmsbuf) cc = PvmBadParam; else cc = pmsg_packbody(pvmsbuf, mp); } else cc = PvmNoSuchBuf; return cc; } int pvm_upkmesg() { int cc = 0; struct pmsg *mp; if (!pvmrbuf) cc = PvmNoBuf; else { if (mp = umbuf_new()) { if (!(cc = pmsg_unpack(pvmrbuf, mp))) cc = mp->m_mid; } else cc = PvmNoMem; } return cc; } #ifdef PVM33COMPAT /*************************************************************** ** Crusty functions that will fall off in the next version ** ** ** ***************************************************************/ /* * use pvm_getminfo for pvm_getmwid * use pvm_setminfo for pvm_setmwid */ int pvm_getmwid(mid) int mid; { struct pmsg *mp = 0; int cc = 0; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_GETMWID,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_MB, TEV_DATA_SCALAR, &mid, 1, 1 ); TEV_FIN; } } if (mid < 0) cc = PvmBadParam; else if (mp = midtobuf(mid)) cc = mp->m_wid; else cc = PvmNoSuchBuf; if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_GETMWID,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_WID, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_getmwid", cc); return cc; } int pvm_setmwid(mid, wid) int mid; int wid; { struct pmsg *mp = 0; int cc = 0; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_SETMWID,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_MB, TEV_DATA_SCALAR, &mid, 1, 1 ); TEV_PACK_INT( TEV_DID_WID, TEV_DATA_SCALAR, &wid, 1, 1 ); TEV_FIN; } } if (mid < 0) cc = PvmBadParam; else if (mp = midtobuf(mid)) mp->m_wid = wid; else cc = PvmNoSuchBuf; if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_SETMWID,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_setmwid", cc); return cc; } #endif /*PVM33COMPAT*/ ./pvm3/src/lpvmshmem.c0100644007401100000360000020745410001307621014045 0ustar kohlgopher static char rcsid[] = "$Id: lpvmshmem.c,v 1.47 2004/01/14 18:50:57 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * lpvmshmem.c * * Libpvm core for MPP environment. * * $Log: lpvmshmem.c,v $ * Revision 1.47 2004/01/14 18:50:57 pvmsrc * Added new AIX5* arches. * (Spanker=kohl) * * Revision 1.46 2002/02/18 19:18:35 pvmsrc * Added "|| defined(IMA_SUN4SOL2)" to "const void *i, *j" #if * for int_compare() / qsort()... * (needed for sure for 64 bit) Solaris) * (Spanker=kohl) * * Revision 1.45 2001/09/25 21:21:00 pvmsrc * Yanked "char *pvmgettmp();" decl - now in pvm3.h... * (Spanker=kohl) * * Revision 1.44 2001/05/11 17:32:29 pvmsrc * Eliminated references to sys_errlist & sys_nerr. * - unnecessary, and we're whacking that crap anyway. * (Spanker=kohl) * * Revision 1.43 2000/02/10 20:44:41 pvmsrc * Replaced hard-coded /tmp for PVMSHMFILE. * - use pvmgettmp() routine now to determine PVM temp dir. * (Spanker=kohl) * * Revision 1.42 1999/07/08 19:00:02 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.41 1999/03/15 19:06:03 pvmsrc * Replaced sleep() calls with pvmsleep(). * - Unix / Win32, C / Fortran compat... * (Spanker=kohl) * * Revision 1.40 1999/02/20 14:17:57 pvmsrc * Another try at the SGI compiler warning... :-] * (Spanker=kohl) * * Revision 1.39 1999/02/19 14:10:56 pvmsrc * SGI compiler warning... * (Spanker=kohl) * * Revision 1.38 1998/08/13 18:31:13 pvmsrc * Altered SUNMP to use test and set operations with semaphores * for page locking instead of MUTEX and cond vars. * Changes are mainly in pvmshmem.h, with lots of #ifdefs changes. * Makefile altered to use the PLOCKFILE to indicate the Page Locking * INLINE code used (from SUNMP.conf). * Some changes effect AIX MP versions which still use conditional * variables and may change to semaphores soon. * (Spanker=fagg) * * Revision 1.37 1998/07/24 17:11:46 pvmsrc * Cleaned up use of SOCKLENISUINT / oslen. * - use oslen for every socket-related call: * * bind(), recvfrom(), getsockname() and accept(). * (Spanker=kohl) * * Revision 1.36 1998/02/24 15:36:25 pvmsrc * Oops... leftover typo from umbuf -> pmsg renaming way back when. * - UB_DIFFNODE -> MM_DIFFNODE for IMA_CSPP. * (Spanker=kohl) * * Revision 1.35 1998/02/23 22:51:39 pvmsrc * Added AIX4SP2 stuff. * (Spanker=kohl) * * Revision 1.34 1997/12/31 20:50:09 pvmsrc * Cleaned Up System Message Handlers. * - current send / recv buffers now saved before invocation of * message handler functs. * - removed manual rbf = setrbuf(mid) saving & resetting in * handlers... * (Spanker=kohl) * * Revision 1.33 1997/12/01 19:20:44 pvmsrc * Replaced #ifdef IMA_OS2 fd_set declarations: * - new #ifdef FDSETNOTSTRUCT. * - choose between "fd_set foo" and "struct fd_set foo"... * (Spanker=kohl) * * Revision 1.32 1997/11/04 23:19:21 pvmsrc * Cleaned up fd_set stuff (hopefully). * (Spanker=kohl) * * Revision 1.31 1997/10/24 15:18:03 pvmsrc * Added TEV_DID_RCX to trace events for Receive Message Context. * - in pvm_recv(), pvm_trecv(), pvm_nrecv(), and pvm_precv(). * (Spanker=kohl) * * Revision 1.30 1997/10/24 14:29:33 pvmsrc * Added TEV_DID_MCX / pvmmyctx trace event info to: * - pvm_send(), pvm_mcast(), pvm_recv(), pvm_trecv(), pvm_nrecv(). * - pvm_psend(), pvm_precv(). * (Spanker=kohl) * * Revision 1.29 1997/08/06 22:43:20 pvmsrc * Added new SGI6 and SGIMP6 arches. * * Revision 1.28 1997/07/08 21:25:50 pvmsrc * peer_send() now directs control TC messages via the daemon. * node_mcast() is no-longer called until its pmsg buffer error is found, * i.e. mcast messages are sent via the daemon, using a MCA instead of directly. * pvmmcast() sets the context to the current default. * msendrecv() now takes a context arg! It sets it as well (and the waitid). * beatask() uses SYS contexts on handshakes. * * Revision 1.27 1997/07/03 17:41:50 pvmsrc * Added new sleep_dammit() routine. * - usleep() on SUNMP, RS6KMP, AIX4MP. * - select() w/ timeout everywhere else. * * Revision 1.26 1997/07/02 20:34:58 pvmsrc * Commented out usleep() call. * - not implemented on every arch... * * Revision 1.25 1997/07/02 14:33:45 pvmsrc * beatask() connection attempt tries harder by kicking the daemon * out of select(). * * Revision 1.24 1997/06/27 20:48:08 pvmsrc * Missed AIX arches on write test. * * Revision 1.23 1997/06/25 22:09:10 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.22 1997/06/16 13:42:44 pvmsrc * Oops... My mistake. D-Oh. * - can't use mid as struct pmsg * damn damn damn. * - wouldn't have been a problem if stupid shmem code didn't * call mroute() down inside system... :-/~ * * Revision 1.21 1997/06/12 20:10:46 pvmsrc * Made sure all communications for TC_* task control messages * use the SYSCTX_TC system context. * - some messages being sent in default context... D-Oh... * * Revision 1.20 1997/06/02 13:50:02 pvmsrc * Added missing #include host.h for waitc.h. * * Revision 1.19 1997/06/02 13:24:13 pvmsrc * Added test to shmemuptod() * - so that it creates daemon socket if it doesn't already exist. * * Revision 1.18 1997/05/29 15:14:05 pvmsrc * Removed static decls: * - pvmtrcsbf, pvmrouteopt now in lpvmglob.c / lpvm.h. * - pvmtrcmid doesn't exist. * Fixed arg casting for SGI's: * - read_int() takes (int *), not (struct pidtidhdr *)... * * Revision 1.17 1997/05/27 15:05:30 pvmsrc * Added SHMCONN handshake code into pvmbeatask(): * via new call send_my_pid(). * - this removes strange floating tid 0 processes... * - send_my_pid() calls new function shmemuptod() which is a * simplified one-way mxfer(). * - shmem node tasks still do not read from pvmd via sockets. * Text formatting (JAK). * * Revision 1.16 1997/05/21 16:01:50 pvmsrc * Updated ifdefs to include AIX4MP arch type. * * Revision 1.15 1997/05/21 15:45:41 pvmsrc * pvm_tc_taskexit handled correctly. * Reports error only when no peer entry exits. * * Revision 1.14 1997/05/19 15:00:56 pvmsrc * Number of small fixes: * midtobuf, umbuf_new are prototyped correctly now. * msg contexts set/read correctly in peer_send & peer_recv. * pvmbeatask(): * shmem key id allocated/located without bizzare attachment error. * waitc struct is now set using wait_init() before first use... ;) * pvmmcast(): * mroute is called with a valid mid * TT direct routes are not checked until ttpcb is defined * * Revision 1.13 1997/04/30 21:26:07 pvmsrc * SGI Compiler Warning Cleanup. * * Revision 1.12 1997/04/25 19:19:40 pvmsrc * altered to allow integration into 3.4 messaging. * Changes: * - includes * - added mhp struct def (same as pmsg) * - updated pvmmidh, pvmmidsiz and m_umbs * - added ttpcd lists * - own copy of pvmmcast() (same as lpvm.c) * - own copy of ttpcb_find() minus mpp_ttpcb_find routine XXX * - own copy of post_routedelete() (from lpvmgen.c) * * Revision 1.11 1997/04/07 21:09:14 pvmsrc * pvm_addmhf() - new paramter interface * * Revision 1.10 1997/04/01 21:28:18 pvmsrc * Damn Damn Damn. * - pvm_recvinfo() returns a bufid, not an index. Damn. * * Revision 1.9 1997/04/01 20:48:21 pvmsrc * Fixed tracer mbox usage: * - pvm_getinfo() -> pvm_recvinfo(), new semantics handled (recvinfo * sets rbuf implicitly, a la pvm_recv, need to save rbuf). * * Revision 1.8 1997/03/27 19:55:31 pvmsrc * Fixed up pvmbeatask() to go get tracer info if spawned from shell: * - env var info including trace mask, trace buffer size, trace opts. * - use PVMTRACERCLASS mbox entry to fill in values, if matches * on trctid, trcctx, and trctag. * * Revision 1.7 1997/03/06 21:50:21 pvmsrc * Yanked out #includes for and . * - dups with lpvm.h #includes... * * Revision 1.6 1997/01/28 19:26:52 pvmsrc * New Copyright Notice & Authors. * * Revision 1.5 1996/12/19 19:57:58 pvmsrc * Eradicated remainder of old control message interface. * - replaced pvmmctl() routine with individual messages handlers: * * pvm_tc_shmat() (lpvmshmem.c only). * * pvm_tc_conreq(). * * pvm_tc_conack(). * * pvm_tc_taskexit(). * - added appropriate calls to pvm_addmhf() in pvmbeatask(). * - removed calls to pvmmctl() in mroute() (peer_recv() in * lpvmshmem.c), replaced with new mesg_input() call, * use new pmsg_setenc() routine to set message encoding. * * Revision 1.4 1996/12/18 22:27:50 pvmsrc * Extracted duplicate versions of routines from lpvm/mimd/shmem.c, * inserted into shared lpvmgen.c: * - pvmbailout(). * - pvmlogerror(). * - vpvmlogprintf(), pvmlogprintf(). (hope these work on MPP & shmem) * - pvmlogperror(). * * Revision 1.3 1996/10/25 13:57:31 pvmsrc * Replaced old #includes for protocol headers: * - , "ddpro.h", "tdpro.h" * With #include of new combined header: * - * * Revision 1.2 1996/10/24 22:44:35 pvmsrc * Modified for New Tracing Facility: * - moved #include "global.h" below other #include's for typing. * - removed extra #include in lpvm.c... * - added #include of new "lpvm.h" to replace explicit externs. * - removed common control message handlers from lpvm.c: * * extracted to lpvmgen.c for general usage. * * pvm_tc_noop(), pvm_tc_settmask(), pvm_tc_siblings(). * -> lpvmmimd.c & lpvmshmem.c still need remainder of pvmmctl() * replaced with control message handlers. * - arg typing hassles with int_compare() / qsort() exacerbated... * - modified pvmbeatask(): * * handle new tracing info, unpack tracing and output collection * parameters into temp storage, and then check for local task * override before applying. * * read in new tracing env vars PVMTRCBUF & PVMTRCOPT. * * install new common message handlers. * * call new tev_init() routine to set up tracing stuff. * * use new Pvmtracer structures (pvmtrc & pvmctrc) to store info. * - removed pvm_getopt() & pvm_setopt() -> moved to common lpvmgen.c. * - removed old tev_begin(), tev_fin() & tev_do_trace() routines. * - updated trace event generation for pvm_getfds(), pvm_start_pvmd(), * pvm_precv(), pvm_psend(). * * Revision 1.1 1996/09/23 23:44:20 pvmsrc * Initial revision * * Revision 1.39 1995/11/10 21:37:46 manchek * check for EINTR from semop in peer_wait * * Revision 1.38 1995/11/02 16:17:20 manchek * free replies to control messages in mxfer * * Revision 1.37 1995/09/08 17:26:02 manchek * aargh forgot semicolon * * Revision 1.36 1995/09/08 16:56:17 manchek * experimental changes to pvm_psend to improve performance (postpone freebuf) * * Revision 1.35 1995/09/06 17:37:24 manchek * aargh, forgot pvm_precv * * Revision 1.34 1995/09/06 17:31:41 manchek * pvm_psend returns not implemented instead of bad param for string type * * Revision 1.33 1995/09/05 19:20:30 manchek * changes from bigapple to make busywait work better * * Revision 1.32 1995/07/28 16:40:59 manchek * wrap HASERRORVARS around errno declarations * * Revision 1.31 1995/07/28 15:35:19 manchek * address of copy databuf wasn't set right in peer_send * * Revision 1.30 1995/07/28 15:10:37 manchek * only send message header on first fragment * * Revision 1.29 1995/07/28 15:07:30 manchek * peer_send wasn't generating message checksum * * Revision 1.28 1995/07/24 18:45:51 manchek * message headers passed in inbox shmpkhdr instead of databuf * requires changes to peer_recv, peer_send, msendrecv. * use pvmnametag function to print message tags symbolically * * Revision 1.27 1995/07/19 16:37:51 manchek * peer_send returns NotImpl if DataInPlace used * * Revision 1.26 1995/07/18 17:00:13 manchek * added code to generate and check crc on each message (MCHECKSUM). * get and put wait-id in message header * * Revision 1.25 1995/07/12 01:20:40 manchek * initialize lots of globals, reset in pvmendtask. * pvmendtask checks that globals are set before using them. * catch_kill reinstalls old sighldr, doesn't call if it's SIG_IGN, * sets pidtid state to ST_FINISH. * peer_detach now frees the peer struct * * Revision 1.24 1995/07/11 18:58:30 manchek * peer_wait returns int, -1 if error reading semaphore. * mroute and dynbuf check peer_wait return for error * * Revision 1.23 1995/07/05 16:18:10 manchek * exiting task sets pidtid entry state to ST_FINISH instead of ST_EXIT * * Revision 1.22 1995/07/05 15:36:40 manchek * free messages before sending TASKEXIT in pvmendtask * * Revision 1.21 1995/07/03 20:51:15 manchek * made convex poll-type code in peer_wait() the default case * * Revision 1.20 1995/07/03 20:18:26 manchek * hellish cleanup of comments and formatting. * removed POWER4 ifdefs. * added deadlock detection where task owns all pages in shared * segment and needs still another * * Revision 1.19 1995/06/30 16:24:45 manchek * aargh * * Revision 1.18 1995/06/28 18:17:56 manchek * moved check_for_exit from pvmumbuf.c * * Revision 1.17 1995/06/28 17:59:11 manchek * typo * * Revision 1.16 1995/06/28 15:47:18 manchek * added TC_SHMAT connect handshake * * Revision 1.15 1995/06/19 17:47:58 manchek * was packing random string in TC_CONACK message in pvmmctl * * Revision 1.14 1995/06/02 17:21:34 manchek * pvm_start_pvmd ignores INT, QUIT, TSTP signals * * Revision 1.13 1995/05/30 14:48:37 manchek * in pvmendtask() must call peer_cleanup() before erasing our tid * * Revision 1.12 1995/05/24 19:07:37 manchek * small fix in getdsock(). * changed HPPA shared memory name to HPPAMP * * Revision 1.11 1995/05/22 19:45:45 manchek * added ifdefs for RS6KMP * * Revision 1.10 1995/05/22 19:09:02 manchek * took out ifdefs around read_int(). * with new startup, can read pvmd sockaddr file only once * * Revision 1.9 1995/05/18 17:22:08 manchek * need to export pvminbox and myshmbufid * * Revision 1.8 1995/05/17 16:21:17 manchek * added support for CSPP shared memory. * lots of bug fixes from SGI and Convex. * added PVMTASKDEBUG envar. * pvm_start_pvmd reads sockaddr from pvmd instead of sleeping on addr file. * CSPP port (only) uses new TM_GETOPT message to get trace, output dest. * * Revision 1.7 1995/02/06 21:43:59 manchek * pvmmctl now replies to TC_CONREQ message. * better cleanup of message buffers in pvmendtask * * Revision 1.6 1995/02/01 21:24:47 manchek * error 4 is now PvmOverflow * * Revision 1.5 1994/12/20 16:38:44 manchek * added pvmshowtaskid variable * * Revision 1.4 1994/11/07 22:42:39 manchek * general damage control and cleanup: * initialize variables * send null packets to wake up pvmd instead of reconnecting * clean up on catching SIGTERM * * Revision 1.3 1994/06/30 21:35:40 manchek * typo in peer_recv() * * Revision 1.2 1994/06/04 21:44:31 manchek * updated header. * changed TM_SET to TM_SETOPT * * Revision 1.1 1994/06/03 20:38:18 manchek * Initial revision * */ #include #include #include #include #include #include #include #ifdef SYSVSTR #include #else #include #endif #include #include #include #include #include #include #include #ifdef IMA_SYMM #include #endif #ifdef IMA_KSR1 #include #endif #include #ifdef NEEDSSELECTH #include #endif #include #include #include "pvmalloc.h" #include "pvmdabuf.h" #include "pvmfrag.h" #include "pmsg.h" #include "listmac.h" #include "pvmshmem.h" #include "bfunc.h" #include "lpvm.h" #include "host.h" #include "waitc.h" /* needed by post_routedelete */ #include #include "tevmac.h" #include "global.h" #ifndef max #define max(a,b) ((a)>(b)?(a):(b)) #endif #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif char *getenv(); void hex_inadport __ProtoGlarp__ (( char *, struct sockaddr_in * )); /* These prototypes stop compiler casting structs to ints... */ struct pmsg *midtobuf(); /* Oops someone forgot this one KEV/GEF */ struct pmsg *umbuf_new(); /* Here is another :) KEV/GEF */ extern struct encvec *enctovec(); char *pvmgetpvmd(); char *pvmgethome(); char *pvmdsockfile(); char *pvmnametag(); #ifdef IMA_CSPP int current_node(); #endif /*************** ** Globals ** ** ** ***************/ #ifndef HASERRORVARS extern int errno; /* from libc */ #endif /* XXX this should be in a header file not copied */ /* message heap element */ struct mhp { int m_free; /* free list (next or 0) */ struct pmsg *m_umb; /* message or null if on free list */ }; extern int bufpageused; /* from pvmshmem.c */ extern struct mhp *pvmmidh; /* from lpvmpack.c */ extern int pvmmidhsiz; /* from lpvmpack.c */ int shmbufsiz = 0; /* shared-memory buffer size */ int pvmtidhmask = TIDHOST; /* mask - host field of tids */ int pvmtidlmask = TIDLOCAL; /* mask - local field of tids */ int pgsz = 0; /* system page size */ int pvmpgsz = 0; /* PVM virtual page size */ char *outmsgbuf = 0; /* my outgoing message buffer */ int outbufsz = 0; /* # of frags in outgoing msg buf */ int nbufsowned = 0; /* num shared frags held by us */ struct pidtid *pidtids = 0; /* pid -> tid table */ char *infopage = 0; /* proto, NDF, pid-tid table */ int maxpidtid = 0; /* size of pid-tid table */ int myshmbufid = -1; /* ID of shared-memory buffer */ char *pvminbox = 0; /* incoming message buffer */ struct pmsg *m_umb; /* message or null if on free list */ /*************** ** Private ** ** ** ***************/ static char pvmtxt[512]; /* scratch for error log */ static struct pmsg *rxfrag = 0; /* not-assembled incm msgs */ static struct frag *rxbuf; /* buffer for incoming packts */ #ifdef IMA_SYMM static int cpuonline; /* the number of CPUs available */ static struct shpage *pvmfraginfo; /* frag locks and ref counts */ #endif #ifdef USERECVSEMAPHORE static int mysemid = -1; /* ID of semaphore to sleep on */ #endif static char *pvmdinbox = 0; /* pvmd's incoming message buffer */ static char *pvmdoutbuf = 0; /* pvmd's outgoing message buffer */ static int pvminboxsz = 0; /* size of incoming message buffer */ static int mypidtid = -1; /* my position in pid-tid table */ static int pvmdpid = 0; /* pvmd's Unix proc ID */ static struct sockaddr_in pvmdsad; /* address of pvmd socket */ static int pvmdsock = -1; /* pvmd socket descriptor */ static void (*pvmoldtermhdlr)() = 0; static int pvmsettermhdlr = 1; static int outta_here = 0; /* TT lists used for mcasting [GEF] */ static struct ttpcb *ttlist = 0; /* dll of connected tasks */ static struct ttpcb *topvmd = 0; /* default route (to pvmd) */ /************************** ** Internal Functions ** ** ** **************************/ /* getdsock() * * Get address of pvmd socket, set up pvmdsad. */ void getdsock() { char buf[128]; int d; int n; char *p; if (!(p = getenv("PVMSOCK"))) { if (!(p = pvmdsockfile())) { pvmlogerror("getdsock() pvmdsockfile() failed\n"); return; } if ((d = open(p, O_RDONLY, 0)) == -1) { pvmlogperror(p); return; } n = read(d, buf, sizeof(buf)); (void)close(d); if (n == -1) { pvmlogperror("getdsock() read addr file"); return; } if (n == 0) { pvmlogerror("getdsock() read addr file: wrong length read\n"); return; } buf[n] = 0; p = buf; } hex_inadport(p, &pvmdsad); pvmdsad.sin_family = AF_INET; } /* prodpvmd() * * wake up the pvmd, which is sleeping on sockets and not shared memory. * XXX this sucks. */ void prodpvmd() { static char dummy[TDFRAGHDR]; if (pvmdsock == -1) { if ((pvmdsock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { pvmlogperror("prodpvmd() socket"); return; } if (connect(pvmdsock, (struct sockaddr*)&pvmdsad, sizeof(pvmdsad)) == -1) { pvmlogperror("prodpvmd() connect"); close(pvmdsock); pvmdsock = -1; return; } BZERO(dummy, sizeof(dummy)); } else { write(pvmdsock, dummy, TDFRAGHDR); } } /* peer_wait() * * Check inbox for messages, block on a semaphore if no message. */ int peer_wait() { struct msgboxhdr *inbp = (struct msgboxhdr *)pvminbox; #ifndef USERECVSEMAPHORE PAGELOCK(&inbp->mb_lock); while (inbp->mb_read == inbp->mb_last) #if defined(IMA_SUNMP) && defined(PVMUSEMUTEX) cond_wait(&inbp->mb_cond, &inbp->mb_lock); #endif #if defined(IMA_RS6KMP) || defined(IMA_AIX4MP) || defined(IMA_AIX5MP) pthread_cond_wait(&inbp->mb_cond, &inbp->mb_lock); #endif PAGEUNLOCK(&inbp->mb_lock); #else /*USERECVSEMAPHORE*/ struct sembuf sops; sops.sem_num = 0; sops.sem_op = -1; sops.sem_flg = 0; while (inbp->mb_read == inbp->mb_last) { if (pvmdebmask & PDMSEM) { sprintf(pvmtxt, "peer_wait(): Waiting on semop id = %d\n", mysemid); pvmlogerror(pvmtxt); } if (semop(mysemid, &sops, 1) == -1) { if (errno != EINTR) { sprintf(pvmtxt, "peer_wait(): Error waiting for semop id = %d", mysemid); pvmlogperror(pvmtxt); return -1; } } else if (pvmdebmask & PDMSEM) { sprintf(pvmtxt, "peer_wait(): Processing Event on semop id = %d\n", mysemid); pvmlogerror(pvmtxt); } } #endif /*USERECVSEMAPHORE*/ return 0; } /* pvm_tc_shmat() * * Some Shared Memory Attach Protocol Spanking. * * TC_SHMAT() */ static int pvm_tc_shmat(mid) int mid; { int src; /* sender of request */ struct peer *pp; struct msgboxhdr *dboxp; int ackd; /* allow connection (0) */ pvm_bufinfo(mid, (int *)0, (int *)0, &src); if (!(pp = peer_conn(src, (int *)0)) || pp == (struct peer *)-1L) { pvmlogprintf("pvm_tc_shmat() can't connect to src t%x\n", src); ackd = -1; } else ackd = pvmmytid; dboxp = (struct msgboxhdr *)pp->p_buf; dboxp->mb_attached = ackd; pvm_freebuf(mid); return 0; } /* pvm_tc_conreq() * * Another task requests a connection with us. * Reply with a TC_CONACK message. * * TC_CONREQ() { * int tdprotocol // t-d protocol revision number * string sockaddr // address of other socket * } */ static int pvm_tc_conreq(mid) int mid; { int src; /* sender of request */ int sbf = 0; /* reply message mid */ int ttpro; /* protocol revision */ int ackd; /* allow connection (0) */ int i; int ictx; pvm_bufinfo(mid, (int *)0, (int *)0, &src); pvmlogprintf("pvm_tc_conreq() TCP conn request from t%x!\n", src); sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); ttpro = TDPROTOCOL; ackd = 1; pvm_pkint(&ttpro, 1, 1); pvm_pkint(&ackd, 1, 1); pvm_pkstr(""); i = pvmrescode; pvmrescode = 1; ictx = pvm_setcontext(SYSCTX_TC); pvm_send(src, TC_CONACK); pvm_setcontext(ictx); pvmrescode = i; pvm_freebuf(pvm_setsbuf(sbf)); pvm_freebuf(mid); return 0; } /* pvm_tc_conack() * * Another task replies to our connection request. * * TC_CONACK() { * int tdprotocol // t-d protocol revision number * int ack // 0 ok, 1 denied * string sockaddr // address of other socket * } */ static int pvm_tc_conack(mid) int mid; { int src; /* sender of reply */ pvm_bufinfo(mid, (int *)0, (int *)0, &src); pvmlogprintf("pvm_tc_conack() unexpected TC msg from t%x!\n", src); pvm_freebuf(mid); return 0; } /* pvm_tc_taskexit() * * We are notified that another task (to which we have a direct route) * has exited. */ static int pvm_tc_taskexit(mid) int mid; { int src; /* sender of notify */ struct peer *pp; int found_one = 0; /* did we find a peer? */ pvm_bufinfo(mid, (int *)0, (int *)0, &src); if (!outta_here) { int tid; extern struct peer *peers; pvm_upkint(&tid, 1, 1); for (pp = peers->p_link; pp != peers; pp = pp->p_link) if (pp->p_tid == tid) { pp->p_exited = 1; /* mark as deleted */ found_one = 1; break; } } if (!found_one) /* then it was unexpected! */ pvmlogprintf("pvm_tc_taskexit() unexpected TC msg from t%x!\n", src); pvm_freebuf(mid); return 0; } /* mroute() * * Route a message to a destination. * Returns when * outgoing message (if any) fully sent and * (timed out (tmout) or * at least one message fully received) * Returns >=0 the number of complete messages downloaded, or * negative on error. */ int mroute(mid, dtid, code, tmout) int mid; /* message */ int dtid; /* dest */ int code; /* type tag */ struct timeval *tmout; /* get at least one message */ { struct pmsg *txup; /* tx message or null */ struct frag *txfp = 0; /* cur tx frag or null */ int gotem = 0; /* count complete msgs downloaded */ int block; /* get at least one message */ int loopcount = 0; struct msgboxhdr *inbp; /* incoming box */ struct timeval tnow, tstop; int sbf; /* reply to control message */ int cc; int freethis = 0; /* (control) message came from stack */ int tstkp = 0; int tstk[100]; /* XXX shouldn't be a stack */ /* XXX do we really have to do this? */ /* if ((dtid == TIDPVMD && code == TM_MCA) || dtid == TIDGID) */ /* return node_mcast(mid, dtid, code); */ if (tmout) { if (tmout->tv_sec || tmout->tv_usec) { pvmgetclock(&tnow); tstop.tv_sec = tnow.tv_sec + tmout->tv_sec; tstop.tv_usec = tnow.tv_usec + tmout->tv_usec; block = 1; } else block = 0; } else { block = 1; tstop.tv_sec = -1; tstop.tv_usec = -1; } if (txup = midtobuf(mid)) { txfp = txup->m_frag->fr_link; txfp = txfp->fr_buf ? txfp : 0; } inbp = (struct msgboxhdr *)pvminbox; do { if (block && tstop.tv_sec != -1) { pvmgetclock(&tnow); if (tnow.tv_sec > tstop.tv_sec || (tnow.tv_sec == tstop.tv_sec && tnow.tv_usec >= tstop.tv_usec)) break; } if (pvmpolltype == PvmPollSleep && loopcount++ > pvmpolltime && !txfp && tstop.tv_sec == -1) { PAGELOCK(&inbp->mb_lock); if (inbp->mb_read == inbp->mb_last) { inbp->mb_sleep = 1; PAGEUNLOCK(&inbp->mb_lock); if (peer_wait() == -1) return PvmSysErr; loopcount = 0; } else PAGEUNLOCK(&inbp->mb_lock); } if (inbp->mb_read != inbp->mb_last) { if ((sbf = peer_recv(&gotem)) == -1) return PvmSysErr; if (sbf > 0) { if (txfp) tstk[tstkp++] = sbf; else { txup = midtobuf(sbf); dtid = txup->m_dst; code = txup->m_tag; txfp = txup->m_frag->fr_link; txfp = txfp->fr_buf ? txfp : 0; freethis = 1; } } } if (txfp) { if ((cc = peer_send(txup, txfp, dtid, code)) < 0) return cc; if (cc) { txfp = txfp->fr_link; if (!txfp->fr_buf) { if (freethis) umbuf_free(txup); if (tstkp > 0) { txup = midtobuf(tstk[--tstkp]); dtid = txup->m_dst; code = txup->m_tag; txfp = txup->m_frag->fr_link; txfp = txfp->fr_buf ? txfp : 0; freethis = 1; } else txfp = 0; } } } } while (txfp || (block && !gotem)); return gotem; } /* peer_recv() * * Receive a message fragment from another task. * Reassemble frags into messages and place on rxlist. * On completing a control message, call mesg_input(), * which consumes it. * Returns: * 0 normally, * negative if error, * or message handle of a reply control message to be sent. */ int peer_recv(gotem) int *gotem; { struct pmsg *rxup; /* rx message */ struct pmsg *up; struct frag *fp; int sdr; int src; int ff; struct peer *pp = 0; int next; /* frag being received */ struct shmpkhdr *inmsgs; /* incoming messages */ struct msgboxhdr *inbp; /* incoming box */ int sbf = 0; /* reply control message */ inbp = (struct msgboxhdr *)pvminbox; inmsgs = (struct shmpkhdr *)(inbp + 1); next = (inbp->mb_read + 1) % pvminboxsz; sdr = inmsgs[next].ph_sdr; fp = fr_new(0); if ((sdr & ~pvmtidhmask) != TIDPVMD) { if (!(pp = peer_conn(sdr, (int *)0)) || pp == (struct peer *)-1L) { sprintf(pvmtxt, "peer_recv() can't connect to sender t%x\n", sdr); pvmlogerror(pvmtxt); return PvmSysErr; } fp->fr_dat = pp->p_buf + INBOXPAGE*pgsz + inmsgs[next].ph_dat; } else fp->fr_dat = pvmdoutbuf + inmsgs[next].ph_dat; fp->fr_buf = fp->fr_dat - (inmsgs[next].ph_dat & (pgsz-1)) + PVMPAGEHDR; fp->fr_max = pvmfrgsiz; ff = inmsgs[next].ph_flag; src = inmsgs[next].ph_src; fp->fr_len = inmsgs[next].ph_len; fp->fr_max = pvmfrgsiz; if (pvmdebmask & PDMPACKET) { sprintf(pvmtxt, "peer_recv() sdr t%x src t%x len %d dst t%x flag %d\n", sdr, src, fp->fr_len, inmsgs[next].ph_dst, ff); pvmlogerror(pvmtxt); } /* * if start of message, make new umbuf, add to frag pile */ if (ff & FFSOM) { rxup = umbuf_new(); rxup->m_tag = inmsgs[next].ph_tag; rxup->m_ctx = inmsgs[next].ph_ctx; rxup->m_enc = inmsgs[next].ph_enc; rxup->m_wid = inmsgs[next].ph_wid; rxup->m_crc = inmsgs[next].ph_crc; rxup->m_src = src; #ifdef IMA_CSPP if (pp && pp->p_node != current_node()) rxup->m_flag |= MM_DIFFNODE; #endif LISTPUTBEFORE(rxfrag, rxup, m_link, m_rlink); } /* locate frag's message */ for (rxup = rxfrag->m_link; rxup != rxfrag; rxup = rxup->m_link) if (rxup->m_src == src) break; if (rxup == rxfrag) { /* uh oh, no message for it */ pvmlogerror("peer_recv() frag with no message\n"); fr_unref(fp); } else { LISTPUTBEFORE(rxup->m_frag, fp, fr_link, fr_rlink); rxup->m_len += fp->fr_len; /* * if end of message, move to rxlist and count it */ if (ff & FFEOM) { LISTDELETE(rxup, m_link, m_rlink); #ifdef MCHECKSUM if (rxup->m_crc != umbuf_crc(rxup)) { sprintf(pvmtxt, "peer_recv() message src t%x tag %d bad checksum\n", rxup->m_src, rxup->m_tag); pvmlogerror(pvmtxt); umbuf_free(rxup); } else { #endif pmsg_setenc(rxup, rxup->m_enc); mesg_input(rxup); (*gotem)++; #ifdef MCHECKSUM } #endif } } inbp->mb_read = next; return sbf; } /* peer_send() * * Send fragment to another process. * Establish connection if necessary, exchange handshake message. * * Returns 1 if sent, 0 otherwise, negative on error. */ int peer_send(txup, txfp, dtid, code) struct pmsg *txup; /* tx message or null */ struct frag *txfp; /* cur tx frag or null */ int dtid; /* dest */ int code; /* type code */ { char *cp = 0; /* points to copy-databuf (if necessary) */ int ff; int loc; /* location of data in shared segment */ int next; /* frag being received */ struct peer *pp; struct shmpkhdr *dmsgs; struct msgboxhdr *dboxp; /* receiving box of peer */ if (!txfp->fr_u.dab) { pvmlogerror("peer_send() PvmDataInPlace not implemented\n"); return PvmNotImpl; } /* If its a control message always pass via the daemon */ /* This avoids the I'cant send to you as you haven't handled my */ /* tc_shmat handshake *message* yet problem... it was the chicken first */ /* why? because the daemon is connected as beatask() has worked (maybe) */ if (((dtid & pvmtidhmask) == (pvmmytid & pvmtidhmask) && (dtid & ~pvmtidhmask) != TIDPVMD) /* to local task */ && !(code>=TC_FIRST && code<=TC_LAST) ) /* and not a CTRL TC message */ { int new_connection; if (!(pp = peer_conn(dtid, &new_connection))) return 0; if (pp != (struct peer *)-1L) { dboxp = (struct msgboxhdr *)pp->p_buf; if (new_connection) { struct pmsg *mp; int sbf, l; struct msgboxhdr *inbp = (struct msgboxhdr *)pvminbox; static struct timeval ztv = { 0, 0 }; sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); l = TDPROTOCOL; pvm_pkint(&l, 1, 1); sbf = pvm_setsbuf(sbf); inbp->mb_attached = 0; /* XXX glggg, could we just return to mroute here instead of calling it? */ mp = midtobuf(sbf); mp->m_ctx = SYSCTX_TC; mroute(sbf, dtid, TC_SHMAT, &ztv); pvm_freebuf(sbf); while (!inbp->mb_attached) mroute(0, 0, 0, &ztv); /* avoid deadlock */ if (inbp->mb_attached != dtid) { sprintf(pvmtxt, "peer_send: mb_attached: expected %x, got %x\n", dtid, inbp->mb_attached); pvmlogerror(pvmtxt); } } } else dboxp = (struct msgboxhdr *)pvmdinbox; } else dboxp = (struct msgboxhdr *)pvmdinbox; if ((dboxp->mb_last + 1) % pvminboxsz == dboxp->mb_read) return 0; /* full */ /* * if page is private, copy and replace it with one in shared buf */ if ((loc = txfp->fr_dat - outmsgbuf) > outbufsz * pvmpgsz || loc < 0) { if (nbufsowned == outbufsz) { int i; pvmlogerror("peer_send() Message(s) too long for shared buffer, deadlocked.\n"); PAGELOCK(&((struct shmpghdr *)infopage)->pg_lock); for (i = 0; i < maxpidtid; i++) if (pidtids[i].pt_tid == pvmmytid) { pidtids[i].pt_cond = 1; break; } PAGEUNLOCK(&((struct shmpghdr *)infopage)->pg_lock); } cp = 0; do { if (cp) da_unref(cp); cp = da_new(MAXHDR + txfp->fr_len); } while ((loc = cp - outmsgbuf + MAXHDR) > outbufsz*pvmpgsz || loc < 0); BCOPY(txfp->fr_dat, cp + MAXHDR, txfp->fr_len); txfp->fr_dat = cp + MAXHDR; da_unref(txfp->fr_buf); txfp->fr_buf = cp; } if (txfp->fr_rlink == txup->m_frag) ff = FFSOM; else ff = 0; if (txfp->fr_link == txup->m_frag) ff |= FFEOM; if (pvmdebmask & PDMPACKET) { sprintf(pvmtxt, "peer_send() dst t%x len %d page %d flag %d\n", dtid, txfp->fr_len, loc/pgsz + 1, ff); pvmlogerror(pvmtxt); } dmsgs = (struct shmpkhdr *)(dboxp + 1); PAGELOCK(&dboxp->mb_lock); next = (dboxp->mb_last + 1) % pvminboxsz; /* if receive buffer full, must fail here and try again - sgi:jpb */ if ( next == dboxp->mb_read ) { /* full */ PAGEUNLOCK(&dboxp->mb_lock); return 0; } dmsgs[next].ph_src = pvmmytid; dmsgs[next].ph_dst = dtid; dmsgs[next].ph_sdr = pvmmytid; dmsgs[next].ph_dat = loc; dmsgs[next].ph_len = txfp->fr_len; dmsgs[next].ph_flag = ff; if (ff & FFSOM) { dmsgs[next].ph_tag = code; dmsgs[next].ph_ctx = txup->m_ctx; dmsgs[next].ph_enc = txup->m_enc; dmsgs[next].ph_wid = txup->m_wid; #ifdef MCHECKSUM dmsgs[next].ph_crc = umbuf_crc(txup); #else dmsgs[next].ph_crc = 0; #endif if (pvmdebmask & PDMMESSAGE) { sprintf(pvmtxt, "peer_send() dst t%x tag %s ctx %d\n", dtid, pvmnametag(dmsgs[next].ph_tag,(int*)0), dmsgs[next].ph_ctx); pvmlogerror(pvmtxt); } /* logging */ } else { dmsgs[next].ph_tag = 0; dmsgs[next].ph_ctx = 0; dmsgs[next].ph_enc = 0; dmsgs[next].ph_wid = 0; dmsgs[next].ph_crc = 0; } da_ref(txfp->fr_buf); dboxp->mb_last = next; if (dboxp != (struct msgboxhdr *)pvmdinbox && dboxp->mb_sleep) { /* #if defined(IMA_SUNMP) || defined(IMA_RS6KMP) || defined(IMA_AIX4MP) || defined(IMA_AIX5MP) */ #ifdef PVMUSEMUTEX #ifdef IMA_SUNMP cond_signal(&dboxp->mb_cond); #endif #if defined(IMA_RS6KMP) || defined(IMA_AIX4MP) || defined(IMA_AIX5MP) pthread_cond_signal(&dboxp->mb_cond); #endif #else peer_wake(pp); #endif /* PVMUSEMUTEX */ dboxp->mb_sleep = 0; } /* wake up pvmd */ if (dboxp == (struct msgboxhdr *)pvmdinbox && (dboxp->mb_last + pvminboxsz - 1) % pvminboxsz == dboxp->mb_read) { PAGEUNLOCK(&dboxp->mb_lock); (void)prodpvmd(); } else PAGEUNLOCK(&dboxp->mb_lock); return 1; } int node_mcast(mid, dtid, code) int mid; /* message id */ int dtid; /* destination */ int code; /* type */ { static int *tids = 0; /* intended recipients of multicast message */ static int ntids = -1; static int ntask; /* number of tids */ static struct timeval ztv = { 0, 0 }; int i; long count = 0; int cc = 0; int dummy; /* intercept multicast info */ if (dtid == TIDPVMD) { int sbf = mid; pvm_setrbuf(mid); pvm_upkint(&ntask, 1, 1); if (ntask > ntids) { if (tids) PVM_FREE(tids); tids = TALLOC(ntask, int, "tids"); ntids = ntask; } pvm_upkint(tids, ntask, 1); /* sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); */ pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); dummy = TIDGID; pvm_pkint(&dummy, 1, 1); pvm_setrbuf(pvm_setsbuf(sbf)); return 0; } for (i = 0; i < ntask; i++) if (tids[i] != pvmmytid) cc = mroute(mid, tids[i], code, &ztv); ntask = 0; return cc; } /* msendrecv() * * Single op to send a system message (usually to our pvmd) and get * the reply. * Returns message handle or negative if error. */ int msendrecv(other, code, context) int other; /* dst, src tid */ int code; /* message tag */ int context; /* context to use for the message */ { static int nextwaitid = 1; /* I hope */ int cc; struct pmsg *up; if (!pvmsbuf) return PvmNoBuf; /* send code to other */ if (pvmdebmask & PDMMESSAGE) { sprintf(pvmtxt, "msendrecv() to t%x tag %s\n", other, pvmnametag(code, (int *)0)); pvmlogerror(pvmtxt); } pvmsbuf->m_wid = nextwaitid++; pvmsbuf->m_ctx = context; if ((cc = mroute(pvmsbuf->m_mid, other, code, (struct timeval *)0)) < 0) return cc; /* Oops now what? */ /* if (code == TM_MCA) */ /* for node_mcast() */ /* return 1; */ /* recv code from other */ for (up = pvmrxlist->m_link; 1; up = up->m_link) { if (up == pvmrxlist) { up = up->m_rlink; if ((cc = mroute(0, 0, 0, (struct timeval *)0)) < 0) return cc; up = up->m_link; } if (pvmdebmask & PDMMESSAGE) { sprintf(pvmtxt, "msendrecv() from t%x tag %s\n", up->m_src, pvmnametag(up->m_tag, (int *)0)); pvmlogerror(pvmtxt); } if (up->m_src == other && up->m_tag == code) break; } LISTDELETE(up, m_link, m_rlink); if (pvmrbuf) umbuf_free(pvmrbuf); pvmrbuf = 0; if (cc = pvm_setrbuf(up->m_mid)) return cc; return up->m_mid; } static void catch_kill(sig) int sig; { signal(SIGTERM, pvmoldtermhdlr); if (pvmoldtermhdlr && pvmoldtermhdlr != SIG_IGN) pvmoldtermhdlr(sig); /* XXX yes, i know the table isn't locked. we're in a sighandler */ if (pidtids && pidtids[mypidtid].pt_stat != ST_EXIT) pidtids[mypidtid].pt_stat = ST_FINISH; pvmendtask(); exit(sig); } static int read_int(val) int *val; { return *val; } /* pvmbeatask() * * Initialize libpvm, config process as a task. * This is called as the first step of each libpvm function so no * explicit initialization is required. * * Returns 0 if okay, else error code. * * XXX needs work. lots of inconsistent state is left on error return. * I'm working on it */ int pvmbeatask() { struct shmpkhdr *inmsgs; struct pidtidhdr *pvminfo; struct msgboxhdr *dboxp; /* receiving box of pvmd */ int next; int altpid; /* pid of ancestor forked by pvmd */ int msgcnt; char *msgbuf; /* my message buffer */ int bufid; int i; int pid; int bid; int rc; char *p; struct pvmminfo minfo; int cc = 0; int sbf = 0, rbf = 0; /* saved rx and tx message handles */ int outtid, outctx, outtag; int trctid, trcctx, trctag; int need_trcinfo = 0; int new_tracer = 0; char tmask[ 2 * TEV_MASK_LENGTH ]; int tbuf, topt; int mid; /* union semun { int val; struct semid_ds *buf; ushort *array; } sunion; */ #ifdef LOG char fname[32]; #endif int key, firstkeytried; int mytid; char *pvmtmp; TEV_DECLS if (pvmmytid != -1) return 0; pvmmydsig = pvmgetdsig(); TEV_EXCLUSIVE; if ((pvm_useruid = getuid()) == -1) { pvmlogerror("pvmbeatask() can't getuid()\n"); return PvmSysErr; } if (p = getenv("PVMTASKDEBUG")) { pvmdebmask = pvmxtoi(p); if (pvmdebmask) { sprintf(pvmtxt,"task debug mask is 0x%x\n", pvmdebmask); pvmlogerror(pvmtxt); } } pvmmyupid = getpid(); #ifdef LOG #ifdef IMA_CSPP int scid = get_scid(); pvmtmp = pvmgettmp(); if (scid > 1) sprintf(fname, "%s/pvmt.%d.%d", pvmtmp, pvm_useruid, scid); else #endif sprintf(fname, "%s/pvmt.%d", pvmtmp, pvm_useruid); if ((logfp = fopen(fname, "a")) == NULL) pvmlogerror("pvmbeatask() can't open log file\n"); #endif /* * get expected pid from environment in case we were started by * the pvmd and someone forked again */ if (p = getenv("PVMEPID")) altpid = atoi(p); else altpid = 0; pgsz = sysconf(_SC_PAGESIZE); pvmpgsz = FRAGPAGE*pgsz; pvmfrgsiz = pvmpgsz - PVMPAGEHDR; pvminboxsz = (INBOXPAGE*pgsz - sizeof(struct msgboxhdr))/sizeof(struct shmpkhdr); /* * initialize received-message list and fragment reassembly list */ rxfrag = pmsg_new(1); BZERO((char*)rxfrag, sizeof(struct pmsg)); rxfrag->m_link = rxfrag->m_rlink = rxfrag; pvmrxlist = pmsg_new(1); BZERO((char*)pvmrxlist, sizeof(struct pmsg)); pvmrxlist->m_link = pvmrxlist->m_rlink = pvmrxlist; peer_init(); /* * SIGTERM handler to clean up our shared memory */ if (pvmsettermhdlr) { pvmoldtermhdlr = signal(SIGTERM, catch_kill); pvmsettermhdlr = 0; } /* * get pvmd's message buffer, check protocol revision */ key = pvmshmkey(0); if ((bufid = shmget((key_t)key, 0, PERMS)) == -1) { pvmlogperror("pvmbeatask() shmget: can't connect to pvmd"); return PvmSysErr; } if ((pvmdinbox = (char *)shmat(bufid, 0, 0)) == (char *)-1L) { pvmlogperror("pvmbeatask() shmat pvmd"); return PvmSysErr; } infopage = pvmdinbox + INBOXPAGE*pgsz; pvmdoutbuf = infopage + pgsz; pvminfo = (struct pidtidhdr *)(infopage + PVMPAGEHDR); while ( read_int( (int *) &(pvminfo[0]) ) == 0 ) { pvmsleep(1); if (pvmdebmask & PDMMEM) pvmlogerror("Waiting for pvmd to set protocol\n"); } if (pvminfo->i_proto != TDPROTOCOL) { sprintf(pvmtxt, "beatask() t-d protocol mismatch (%d/%d)\n", TDPROTOCOL, *((int *) &(pvminfo[0]))); pvmlogerror(pvmtxt); return PvmSysErr; } /* * send it a request for connection/task assignment */ dboxp = (struct msgboxhdr *)pvmdinbox; inmsgs = (struct shmpkhdr *)(dboxp + 1); PAGELOCK(&dboxp->mb_lock); while ((next = (dboxp->mb_last + 1) % pvminboxsz) == dboxp->mb_read) ; /* XXX yuck, overloading these fields */ inmsgs[next].ph_src = pvmmyupid; inmsgs[next].ph_dst = altpid; inmsgs[next].ph_dat = -1; inmsgs[next].ph_sdr = 0; inmsgs[next].ph_len = 0; inmsgs[next].ph_flag = 0; inmsgs[next].ph_tag = 0; inmsgs[next].ph_enc = 0; inmsgs[next].ph_wid = 0; inmsgs[next].ph_crc = 0; dboxp->mb_last = next; PAGEUNLOCK(&dboxp->mb_lock); pvmdpid = pvminfo->i_dpid; (void)getdsock(); PAGELOCK(&dboxp->mb_lock); if ((next - 1) % pvminboxsz == dboxp->mb_read) { PAGEUNLOCK(&dboxp->mb_lock); (void)prodpvmd(); } else PAGEUNLOCK(&dboxp->mb_lock); /* * get global parameters from pvmd buffer */ /* pvmmydsig = pvminfo->i_dsig; */ shmbufsiz = pvminfo->i_bufsiz; outbufsz = (shmbufsiz - INBOXPAGE*pgsz)/pvmpgsz; nbufsowned = 0; pidtids = (struct pidtid *)(pvminfo + 1); maxpidtid = (pgsz - sizeof(struct pidtidhdr) - PVMPAGEHDR)/sizeof(struct pidtid); /* * wait for pvmd to write us an entry in pidtid table */ pid = altpid ? altpid : pvmmyupid; mytid = -1; while (mytid == -1) { int ntids; /* number of entries in pid-tid table */ PAGELOCK(&((struct shmpghdr *)infopage)->pg_lock); ntids = min(maxpidtid, ((struct shmpghdr *)infopage)->pg_ref); for (i = 0; i < ntids; i++) if (pidtids[i].pt_pid == pid) { mytid = pidtids[i].pt_tid; pvmmyptid = pidtids[i].pt_ptid; /* pidtids[i].pt_pid = pvmmyupid; */ mypidtid = i; break; } PAGEUNLOCK(&((struct shmpghdr *)infopage)->pg_lock); if (mytid==-1) { /* not entered in pvmd info page yet */ prodpvmd(); /* kick daemon out of select() in work() */ sleep_dammit( 10000 ); /* prevent peer page lock race */ /* on info page */ } } /* * create shared memory segment (and semaphore) * if we can't get the first key, keep trying others * XXX this could be moved back to after the protocol num check. */ firstkeytried = key = pvmshmkey(getpid()); while (1) { /* moved here from down there */ myshmbufid = -1; errno = ENOSPC; /* static int once = 0; */ /* if (once > 3) */ myshmbufid = shmget((key_t)key, shmbufsiz, IPC_CREAT|IPC_EXCL|PERMS); /* else { */ /* myshmbufid = -1; */ /* errno = ENOSPC; */ /* once++; */ /* } */ if (myshmbufid == -1) { if (errno != EACCES && errno != EEXIST) { pvmlogperror("pvmbeatask() shmget"); return PvmSysErr; } } else { #ifdef USERECVSEMAPHORE mysemid = semget((key_t)key, 1, IPC_CREAT|IPC_EXCL|PERMS); if (mysemid == -1) { if (errno != EACCES && errno != EEXIST) { pvmlogperror("pvmbeatask() semget"); shmctl(myshmbufid, IPC_RMID, (struct shmid_ds *)0); return PvmSysErr; } else { shmctl(myshmbufid, IPC_RMID, (struct shmid_ds *)0); } } else { /* sunion.val = 0; if (semctl(mysemid, 0, SETVAL, sunion) == -1) { pvmlogperror("pvmbeatask() semctl SETVAL"); return PvmSysErr; } */ break; } #else break; #endif } key = nextpvmshmkey(key); if (key == firstkeytried) { pvmlogerror("pvmbeatask() can't find a free key!\n"); return PvmSysErr; } } #ifdef IMA_CSPP if ((pvminbox = (char *)shm_search(myshmbufid)) == (char *)-1L) #else if ((pvminbox = (char *)shmat(myshmbufid, 0, 0)) == (char *)-1L) #endif { pvmlogperror("pvmbeatask() shmat"); shmctl(myshmbufid, IPC_RMID, (struct shmid_ds *)0); return PvmSysErr; } outmsgbuf = pvminbox + INBOXPAGE*pgsz; msgbufinit(pvminbox); /* XXX PAGELOCK(pvminfo); */ pidtids[mypidtid].pt_key = key; pidtids[mypidtid].pt_stat = ST_SHMEM; #ifdef IMA_CSPP pidtids[mypidtid].pt_node = current_node(); #endif /* XXX PAGEUNLOCK(pvminfo); */ pvmmytid = mytid; /* OK.. * Daemon has been prodded... so lets give it our Unix pid via * the socket so it can match the socket to the process. * That way, when the socket goes EOF pvmd knows which process * it was.... * Note we call it this late so that pmsg buffers are available. * Although the message is constructed in shmem its sent via the * socket! */ send_my_pid(); /* * Request task trace/output paramters from daemon */ sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); rbf = pvm_setrbuf(0); if ((cc = msendrecv(TIDPVMD, TM_GETOPT, SYSCTX_TM)) > 0) { pvm_upkint(&rc, 1, 1); /* throw out tid, ptid */ pvm_upkint(&rc, 1, 1); pvm_upkint(&outtid, 1, 1); pvm_upkint(&outctx, 1, 1); pvm_upkint(&outtag, 1, 1); if (!pvmtrc.outtid) { pvmtrc.outtid = outtid; pvmtrc.outctx = outctx; pvmtrc.outtag = outtag; pvmctrc.outtid = pvmtrc.outtid; pvmctrc.outctx = pvmtrc.outctx; pvmctrc.outtag = pvmtrc.outtag; } pvm_upkint(&trctid, 1, 1); pvm_upkint(&trcctx, 1, 1); pvm_upkint(&trctag, 1, 1); if (!pvmtrc.trctid) { pvmtrc.trctid = trctid; pvmtrc.trcctx = trcctx; pvmtrc.trctag = trctag; pvmctrc.trctid = pvmtrc.trctid; pvmctrc.trcctx = pvmtrc.trcctx; pvmctrc.trctag = pvmtrc.trctag; new_tracer++; } cc = 0; } pvm_freebuf(pvm_setrbuf(rbf)); pvm_freebuf(pvm_setsbuf(sbf)); if (p = getenv("PVMCTX")) pvmmyctx = pvmstrtoi(p); /* get trace mask from envar or zero it */ if ( (p = getenv("PVMTMASK")) ) { if ( strlen(p) + 1 == TEV_MASK_LENGTH ) BCOPY(p, pvmtrc.tmask, TEV_MASK_LENGTH); else TEV_MASK_INIT(pvmtrc.tmask); } else { TEV_MASK_INIT(pvmtrc.tmask); if ( new_tracer ) need_trcinfo++; } BCOPY(pvmtrc.tmask, pvmctrc.tmask, TEV_MASK_LENGTH); /* get trace buffering from envar */ if ((p = getenv("PVMTRCBUF"))) pvmtrc.trcbuf = atoi( p ); else { pvmtrc.trcbuf = 0; if ( new_tracer ) need_trcinfo++; } pvmctrc.trcbuf = pvmtrc.trcbuf; /* get trace options from envar */ if ((p = getenv("PVMTRCOPT"))) pvmtrc.trcopt = atoi( p ); else { pvmtrc.trcopt = 0; if ( new_tracer ) need_trcinfo++; } pvmctrc.trcopt = pvmtrc.trcopt; /* Setup waitc structures */ wait_init(pvmmytid, TIDLOCAL); BZERO(&minfo, sizeof(minfo)); minfo.src = -1; minfo.ctx = SYSCTX_TC; minfo.tag = TC_SHMAT; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_shmat); minfo.tag = TC_CONREQ; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_conreq); minfo.tag = TC_CONACK; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_conack); minfo.tag = TC_TASKEXIT; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_taskexit); minfo.tag = TC_NOOP; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_noop); minfo.tag = TC_SETTRACE; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_settrace); minfo.tag = TC_SETTRCBUF; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_settrcbuf); minfo.tag = TC_SETTRCOPT; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_settrcopt); minfo.tag = TC_SETTMASK; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_settmask); minfo.tag = TC_SIBLINGS; pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_siblings); if ( need_trcinfo ) { rbf = pvm_setrbuf( 0 ); if ( pvm_recvinfo( PVMTRACERCLASS, 0, PvmMboxDefault ) > 0 ) { pvm_upkint(&trctid, 1, 1); pvm_upkint(&trcctx, 1, 1); pvm_upkint(&trctag, 1, 1); pvm_upkint(&outctx, 1, 1); /* unused here */ pvm_upkint(&outtag, 1, 1); /* unused here */ pvm_upkstr(tmask); pvm_upkint(&tbuf, 1, 1); pvm_upkint(&topt, 1, 1); if ( pvmtrc.trctid == trctid && pvmtrc.trcctx == trcctx && pvmtrc.trctag == trctag ) { if ( strlen(tmask) + 1 == TEV_MASK_LENGTH ) { BCOPY(tmask, pvmtrc.tmask, TEV_MASK_LENGTH); BCOPY(pvmtrc.tmask, pvmctrc.tmask, TEV_MASK_LENGTH); } pvmtrc.trcbuf = tbuf; pvmctrc.trcbuf = pvmtrc.trcbuf; pvmtrc.trcopt = topt; pvmctrc.trcopt = pvmtrc.trcopt; } pvm_freebuf(pvm_setrbuf(rbf)); } else pvm_setrbuf(rbf); } tev_init(); if (TEV_AMEXCL) { TEV_ENDEXCL; } return cc; } /* XXX shouldn't clean up unless pvmmytid set? or at least should check. */ int pvmendtask() { int i; struct shmid_ds shmds; struct pmsg *up; int sbf; static struct timeval ztv = { 0, 0 }; struct peer *pp; extern struct peer *peers; struct pmsg *mp; /* * free any left-over messages. */ pvmsbuf = 0; pvmrbuf = 0; for (i = 1; i < pvmmidhsiz; i++) if (up = pvmmidh[i].m_umb) umbuf_free(up); /* * notify all connected tasks that we are exiting */ outta_here = 1; if (peers) { sbf = pvm_initsend(PvmDataFoo); mp = midtobuf(sbf); mp->m_ctx = SYSCTX_TC; pvm_pkint(&pvmmytid, 1, 1); for (pp = peers->p_link; pp != peers; pp = pp->p_link) if (pp->p_tid && pp->p_tid != pvmmytid) mroute(sbf, pp->p_tid, TC_TASKEXIT, &ztv); pvm_freebuf(sbf); } if (pidtids) { PAGELOCK(&((struct shmpghdr *)infopage)->pg_lock); pidtids[mypidtid].pt_stat = ST_EXIT; PAGEUNLOCK(&((struct shmpghdr *)infopage)->pg_lock); } shmdt(pvminbox); if (shmctl(myshmbufid, IPC_RMID, (struct shmid_ds *)0) == -1) pvmlogperror("pvmendtask() shmctl RMID"); #ifdef USERECVSEMAPHORE if (semctl(mysemid, 0, IPC_RMID) == -1) pvmlogperror("pvmendtask() semctl RMID"); mysemid = -1; #endif pvminbox = 0; shmdt(pvmdinbox); pvmdinbox = 0; infopage = 0; pvmdoutbuf = 0; pidtids = 0; mypidtid = -1; peer_cleanup(); pvmmytid = -1; if (pvmdsock != -1) { (void)close(pvmdsock); pvmdsock = -1; } /* XXX free rxfrag and rxlist */ #ifdef LOG fclose(logfp); #endif return 0; } /* check_for_exit() * * If peer struct for task id marked as exited, check for messages * in heap from the task. If none (borrowing no pages), detach. */ void check_for_exit(src) int src; { extern struct peer *peers; struct peer *pp; for (pp = peers->p_link; pp != peers; pp = pp->p_link) if (pp->p_tid == src) { if (pp->p_exited) { int i; int detach = 1; struct pmsg *up; for (i = 1; i < pvmmidhsiz; i++) { if ((up = pvmmidh[i].m_umb) && (up->m_src == src)) { detach = 0; break; } } if (detach) { peer_detach(pp); } } break; } } /************************ ** Libpvm Functions ** ** ** ************************/ int pvm_getfds(fds) /* XXX this function kinda sucks */ int **fds; /* fd list return */ { int cc; cc = PvmNotImpl; return (cc < 0 ? lpvmerr("pvm_getfds", cc) : cc); } int pvm_start_pvmd(argc, argv, block) int argc; /* number of args to pass to pvmd (>= 0) */ char **argv; /* args for pvmd or null */ int block; /* if true, don't return until add hosts are started */ { char *sfn; struct stat sb; int cc; char *fn; /* file to exec */ char **av; int pfd[2]; int n; FILE *ff; char buf[128]; int x; TEV_DECLS if (TEV_EXCLUSIVE) { if (pvmmytid != -1 && TEV_DO_TRACE(TEV_START_PVMD,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_BF, TEV_DATA_SCALAR, &block, 1, 1 ); TEV_PACK_STRING( TEV_DID_AS, TEV_DATA_ARRAY, argv, argc, 1 ); TEV_FIN; } } if (argc < 0 || !argv) argc = 0; if ((pvm_useruid = getuid()) == -1) { pvmlogerror("can't getuid()\n"); cc = PvmSysErr; goto bail; } if (!(sfn = pvmdsockfile())) { pvmlogerror("pvm_start_pvmd() pvmdsockfile() failed\n"); cc = PvmSysErr; goto bail; } if (stat(sfn, &sb) != -1) { cc = PvmDupHost; goto bail; } #ifdef IMA_TITN if (socketpair(AF_UNIX, SOCK_STREAM, 0, pfd) == -1) #else if (pipe(pfd) == -1) #endif { cc = PvmSysErr; goto bail; } fn = pvmgetpvmd(); av = TALLOC(argc + 2, char *, "argv"); if (argc > 0) BCOPY((char *)&argv[0], (char *)&av[1], argc * sizeof(char*)); av[0] = fn; av[argc + 1] = 0; if (!fork()) { (void)close(pfd[0]); /* fork again so the pvmd is not the child - won't have to wait() for it */ if (!fork()) { if (pfd[1] != 1) dup2(pfd[1], 1); for (n = getdtablesize(); n-- > 0; ) if (n != 1) (void)close(n); (void)open("/dev/null", O_RDONLY, 0); /* should be 0 */ (void)open("/dev/null", O_WRONLY, 0); /* should be 2 */ (void)signal(SIGINT, SIG_IGN); (void)signal(SIGQUIT, SIG_IGN); (void)signal(SIGTSTP, SIG_IGN); execvp(av[0], av); } _exit(0); } (void)close(pfd[1]); (void)wait(0); PVM_FREE(av); if (!(ff = fdopen(pfd[0], "r"))) { cc = PvmSysErr; (void)close(pfd[0]); goto bail; } strcpy(buf, "PVMSOCK="); n = strlen(buf); if (!fgets(buf + n, sizeof(buf) - n - 1, ff)) { cc = PvmCantStart; fclose(ff); goto bail; } fclose(ff); if (strlen(buf + n) < 2) { cc = PvmCantStart; goto bail; } n = strlen(buf); if (buf[n - 1] == '\n') buf[n - 1] = 0; pvmputenv(STRALLOC(buf)); /* fprintf(stderr, "pvm_start_pvmd: %s\n", buf); */ if (cc = BEATASK) goto bail; if (block) { struct pvmhostinfo *hip; int t = 1; pvm_config((int*)0, (int*)0, &hip); while ((cc = pvm_addhosts(&hip[0].hi_name, 1, (int*)0)) == PvmAlready) { pvmsleep(t); if (t < 8) t *= 2; } if (cc != PvmDupHost) goto bail; cc = BEATASK; } bail: if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_START_PVMD,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } return (cc < 0 ? lpvmerr("pvm_start_pvmd", cc) : 0); } int pvm_precv(tid, tag, cp, len, dt, rtid, rtag, rlen) int tid; int tag; void *cp; int len; int dt; int *rtid; int *rtag; int *rlen; { static int last_rbf = 0; int nb, mc, src; int rbf; int cc = 0; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PRECV,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_RST, TEV_DATA_SCALAR, &tid, 1, 1 ); TEV_PACK_INT( TEV_DID_RMC, TEV_DATA_SCALAR, &tag, 1, 1 ); TEV_PACK_INT( TEV_DID_RCX, TEV_DATA_SCALAR, &pvmmyctx, 1, 1 ); ad = (long)cp; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &len, 1, 1 ); TEV_PACK_INT( TEV_DID_PDT, TEV_DATA_SCALAR, &dt, 1, 1 ); TEV_FIN; } } switch (dt) { case PVM_BYTE: len *= sizeof(char); break; case PVM_SHORT: case PVM_USHORT: len *= sizeof(short); break; case PVM_INT: case PVM_UINT: len *= sizeof(int); break; case PVM_LONG: case PVM_ULONG: len *= sizeof(long); break; case PVM_FLOAT: len *= sizeof(float); break; case PVM_CPLX: len *= sizeof(float) * 2; break; case PVM_DOUBLE: len *= sizeof(double); break; case PVM_DCPLX: len *= sizeof(double) * 2; break; case PVM_STR: cc = PvmNotImpl; break; default: cc = PvmBadParam; break; } if (!cc) { if (last_rbf > 0) { pvm_freebuf(last_rbf); last_rbf = 0; } rbf = pvm_setrbuf(0); cc = pvm_recv(tid, tag); if (cc > 0) { pvm_bufinfo(cc, &nb, &mc, &src); if (rlen) *rlen = nb; if (nb < len) len = nb; if (rtag) *rtag = mc; if (rtid) *rtid = src; pvm_upkbyte((char *)cp, len, 1); last_rbf = cc; cc = 0; } pvm_setrbuf(rbf); } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PRECV,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); if ( cc < 0 ) nb = mc = src = -1; TEV_PACK_INT( TEV_DID_MNB, TEV_DATA_SCALAR, &nb, 1, 1 ); TEV_PACK_INT( TEV_DID_MC, TEV_DATA_SCALAR, &mc, 1, 1 ); TEV_PACK_INT( TEV_DID_MCX, TEV_DATA_SCALAR, &pvmmyctx, 1, 1 ); TEV_PACK_INT( TEV_DID_SRC, TEV_DATA_SCALAR, &src, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_precv", cc); return cc; } /* find dynamic buffer */ char * dynbuf(tid, len) int tid; int len; { struct peer *pp; int fd; char fname[32]; struct shmpghdr *ph; char *pvmtmp; while (!(pp = peer_conn(tid, (int *)0))) ; /* XXX this doesn't check for peer_conn returning -1 */ if (len > SHMBUFSIZE && len > pp->p_dlen && pp->p_dbuf) { munmap((caddr_t)pp->p_dbuf, SHMBUFSIZE); pp->p_dbuf = 0; } if (!(ph = (struct shmpghdr *)pp->p_dbuf)) { pvmtmp = pvmgettmp(); sprintf(fname, PVMSHMFILE, pvmtmp, tid); if ((fd = open(fname, O_CREAT|O_RDWR, 0600)) == -1 || (pp->p_dbuf = (char *)mmap(0, max(len,SHMBUFSIZE), PROT_READ|PROT_WRITE, #if defined(IMA_SGIMP) || defined(IMA_SGIMP6) || defined(IMA_SGIMP64) MAP_SHARED|MAP_AUTOGROW, fd, 0)) == (char *)-1L) #else MAP_SHARED, fd, 0)) == (char *)-1) #endif { pvmlogperror(fname); return (char *)-1L; } #ifdef IMA_SUNMP /* fill buffer with 0's */ lseek(fd, len - 1, SEEK_SET); write(fd, fname, 1); #endif close(fd); pp->p_dlen = len; } else if (ph->pg_ref) { /* previous msg has not been recv'd */ while (ph->pg_ref) if (peer_wait() == -1) return (char *)-1L; #ifdef IMA_SUNMP } else if (pp->p_dlen < len) { if ((fd = open(fname, O_CREAT|O_RDWR, 0600)) == -1) { pvmlogperror(fname); return (char *)-1L; } lseek(fd, len - 1, SEEK_SET); write(fd, fname, 1); close(fd); pp->p_dlen = len; #endif } return pp->p_dbuf; } int pvm_psend(tid, tag, cp, len, dt) int tid; int tag; void *cp; int len; int dt; { int sbf; int cc = 0; long ad; TEV_DECLS if (TEV_EXCLUSIVE) { if (TEV_DO_TRACE(TEV_PSEND,TEV_EVENT_ENTRY)) { TEV_PACK_INT( TEV_DID_DST, TEV_DATA_SCALAR, &tid, 1, 1 ); TEV_PACK_INT( TEV_DID_MC, TEV_DATA_SCALAR, &tag, 1, 1 ); TEV_PACK_INT( TEV_DID_MCX, TEV_DATA_SCALAR, &pvmmyctx, 1, 1 ); ad = (long)cp; TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 ); TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &len, 1, 1 ); TEV_PACK_INT( TEV_DID_PDT, TEV_DATA_SCALAR, &dt, 1, 1 ); TEV_FIN; } } switch (dt) { case PVM_BYTE: len *= sizeof(char); break; case PVM_SHORT: case PVM_USHORT: len *= sizeof(short); break; case PVM_INT: case PVM_UINT: len *= sizeof(int); break; case PVM_LONG: case PVM_ULONG: len *= sizeof(long); break; case PVM_FLOAT: len *= sizeof(float); break; case PVM_CPLX: len *= sizeof(float) * 2; break; case PVM_DOUBLE: len *= sizeof(double); break; case PVM_DCPLX: len *= sizeof(double) * 2; break; case PVM_STR: cc = PvmNotImpl; break; default: cc = PvmBadParam; break; } if (!cc) { #if 0 if ((tid & pvmtidhmask) == (pvmmytid & pvmtidhmask) && (tid & ~pvmtidhmask) != TIDPVMD) { /* to local task */ char *dbuf; len += sizeof(struct shmpghdr); if ((dbuf = dynbuf(tid, len)) != (char *)-1L) { BCOPY(cp, dbuf, len); } else cc = PvmSysErr; } else #endif /*0*/ { sbf = pvm_setsbuf(pvm_mkbuf(PvmDataRaw)); pvm_pkbyte((char *)cp, len, 1); if ((cc = pvm_send(tid, tag)) > 0) cc = 0; pvm_freebuf(pvm_setsbuf(sbf)); } } if (TEV_AMEXCL) { if (TEV_DO_TRACE(TEV_PSEND,TEV_EVENT_EXIT)) { TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 ); TEV_FIN; } TEV_ENDEXCL; } if (cc < 0) lpvmerr("pvm_psend", cc); return cc; } /* XXX copied from lpvm.c as needed by pvmmcast */ /* XXX duplicate code should be cleaned up in a support lpvm* file [GEF97] */ static int int_compare(i, j) #if defined(IMA_SGI) || defined(IMA_SGI5) || defined(IMA_SGI6) || defined(IMA_SGI64) || defined(IMA_SGIMP) || defined(IMA_SGIMP6) || defined(IMA_SGIMP64) || defined(IMA_SUN4SOL2) const void *i, *j; #else void *i, *j; #endif { return *((int *)i) - *((int *)j); } /* XXX copied from lpvm.c as needed by pvmmcast again */ /* XXX duplicate code should be cleaned up in a support lpvm* file [GEF97] */ /* XXX, XXX!! note that although shmem is a MPP port I had to take out the */ /* XXX ISA_MPP section as MPP_TTPCB_FIND won't work for shmem machines yet! */ /* ttpcb_find() * * Find a task-task entry by tid in ttlist. */ struct ttpcb * ttpcb_find(tid) int tid; /* peer tid */ { struct ttpcb *pcbp; /* GEF fire fighter (TM) */ /* return (struct ttpcb*)0; */ #if defined(IMA_MPP) if ( pcbp = mpp_ttpcb_find(tid)) return pcbp; #endif for (pcbp = ttlist->tt_link; pcbp != ttlist; pcbp = pcbp->tt_link) if (pcbp->tt_tid >= tid) break; return (pcbp->tt_tid == tid) ? pcbp : (struct ttpcb*)0; } /* XXX copied from lpvm.c as needed by lpvmgen.c */ /* pvmmcast() * * Multicast a message to a list of destinations. */ int pvmmcast(mid, tids, count, tag) int mid; int *tids; int count; int tag; { static struct timeval ztv = { 0, 0 }; int *dst; int i, j; int cc = 0; struct ttpcb *pcbp; int sbf; struct pmsg *mp; /* * make sorted list of destinations */ dst = TALLOC(count, int, "mcal"); BCOPY(tids, dst, count * sizeof(int)); qsort((char*)dst, count, sizeof(int), int_compare); /* pvmsbuf->m_ctx = pvmmyctx; */ /* we are sending mesg mid which may not the same as pvmsbuf->m_mid */ mp = midtobuf(mid); mp->m_ctx = pvmmyctx; /* * remove duplicates */ j = 0; for (i = 1; i < count; i++) if (dst[i] != dst[j]) dst[++j] = dst[i]; count = j + 1; /* * remove self from list * send over any direct routes we have * * XXX we should attempt new routes here if RouteDirect is on. */ j = 0; for (i = 0; i < count; i++) { if (dst[i] == pvmmytid) continue; /* if ((pcbp = ttpcb_find(dst[i])) && pcbp->tt_state == TTOPEN) */ /* mroute(pvmsbuf->m_mid, dst[i], tag, &ztv); */ /* else */ dst[j++] = dst[i]; } count = j; /* destinations still to go */ /* * send rest of addresses to pvmd for distribution */ if (count > 0) { /* announce multicast address list to pvmd */ sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); pvm_pkint(&count, 1, 1); pvm_pkint(dst, count, 1); sbf = pvm_setsbuf(sbf); if ((cc = mroute(sbf, TIDPVMD, TM_MCA, &ztv)) > 0) cc = 0; pvm_freebuf(sbf); /* send message */ if (cc >= 0) /* if ((cc = mroute(pvmsbuf->m_mid, pvmmytid | TIDGID, tag, &ztv)) > 0) */ if ((cc = mroute(mid, pvmmytid | TIDGID, tag, &ztv)) > 0) cc = 0; } PVM_FREE(dst); return cc; } /* XXX copied from lpvm.c as needed by lpvmgen.c */ int post_routedelete(tid, ctx, tag) int tid; int ctx; int tag; { int sbf; struct waitc *wp; struct pmsg *up; int i; sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); pvm_pkint(&tid, 1, 1); i = -1; pvm_pkint(&i, 1, 1); sbf = pvm_setsbuf(sbf); up = midtobuf(sbf); up->m_ctx = ctx; up->m_tag = tag; if (ttpcb_find(tid)) { wp = wait_new(WT_ROUTED); wp->wa_tid = pvmmytid; wp->wa_on = tid; wp->wa_mesg = up; } else { mesg_input(up); } return 0; } /* shmemuptod() * * Move message frags between task and pvmd using SOCKETs only. * Returns when * Outgoing message fully sent or * (Timed out (tmout) OR errored. * * Returns 0 if OK, or negative on error. */ #define HEADER_SIZE (TDFRAGHDR + MSGHDRLEN) static int shmemuptod(txup) struct pmsg *txup; /* outgoing message */ { struct frag *txfp = 0; /* cur ogm frag or null */ struct timeval tin; struct timeval tnow; struct timeval *tvp; #ifdef FDSETNOTSTRUCT fd_set rfds, wfds; #else struct fd_set rfds, wfds; #endif int ff; int n; char *txcp = 0; /* point to remainder of txfp */ int txtogo = 0; /* len of remainder of txfp */ struct sockaddr_in sad; int s; struct msgid *sendmsg = (struct msgid *) NULL; char errtxt[64]; int upfd; /* one-way socket to the daemon */ if (txup) { /* transmitting a umsg */ txfp = txup->m_frag->fr_link; if (!txfp->fr_buf) { if (!(txfp = fr_new(MAXHDR))) return PvmNoMem; txfp->fr_dat += MAXHDR; LISTPUTBEFORE(txup->m_frag, txfp, fr_link, fr_rlink); } /* To the daemon ? */ upfd = pvmdsock; /* txup->m_ref++; */ } if (pvmdebmask & PDMMESSAGE) { pvmlogprintf("shmemuptod() mid %d", (txup ? txup->m_mid : 0)); if (txup) { pvmlogprintf(" ctx %d tag %s", txup->m_ctx, pvmnametag(txup->m_tag, (int *)0)); } } /* must block sending to pvmd */ tvp = (struct timeval *) NULL; /* We haven't sent anything, yet, Build Header */ txcp = txfp->fr_dat; /* packed data */ /* XXXX we assume thats its only packed data TMs */ txtogo = txfp->fr_len; /* actual data size */ /* * This is first and last frag. So prepend message header */ txcp -= MSGHDRLEN; txtogo += MSGHDRLEN; pvmput32(txcp, (txup->m_enc == 0x20000000 ? pvmmydsig : txup->m_enc)); pvmput32(txcp + 4, txup->m_tag); pvmput32(txcp + 8, txup->m_ctx); pvmput32(txcp + 16, txup->m_wid); #ifdef MCHECKSUM pvmput32(txcp + 20, umbuf_crc(txup)); #else pvmput32(txcp + 20, 0); #endif ff = FFSOM | FFEOM; /* Alpha Omega: first and last frag man */ /* * prepend frag header */ txcp -= TDFRAGHDR; pvmput32(txcp, txup->m_dst); pvmput32(txcp + 4, pvmmytid); pvmput32(txcp + 8, txtogo); pvmput32(txcp + 12, 0); /* to keep putrify happy */ pvmput8(txcp + 12, ff); txtogo += TDFRAGHDR; /* * Make sure we have a valid socket address * Prod will connect us to the daemon if we are not already * connected. */ if ( pvmdsock < 0 ) { prodpvmd(); /* connect to the daemon setting pvmdsock */ if ( pvmdsock < 0 ) { /* nested yuck.. */ pvmlogerror("shmemuptod() Can't get daemon socket open\n"); pmsg_unref(txup); /* unref the message */ return -1; } } if (pvmdebmask & PDMPACKET) { pvmlogprintf("shmemuptod() dst t%x n=%d\n", txup->m_dst, txtogo); } /* XXX yep... blocking loop forever!!!!! */ /* If I can't get 100+ bytes up that socket we are */ /* in trouble anyway! */ while (txtogo) { #if defined(IMA_RS6K) || defined(IMA_SP2MPI) || defined(IMA_AIX4) \ || defined (IMA_AIX4MP) || defined(IMA_AIX5MP) \ || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) n = write(pvmdsock, txcp, min(txtogo, 4096)); #else n = write(pvmdsock, txcp, txtogo); #endif if (pvmdebmask & PDMPACKET) pvmlogprintf("shmemuptod() wrote %d\n", n); if (n == -1 && errno != EWOULDBLOCK && errno != EINTR) { pvmlogperror("shmemuptod() write pvmd sock"); return PvmSysErr; } if (n > 0) { txcp += n; txtogo -= n; } } /* while we have data to send */ /* we made it here so the message went! */ pmsg_unref(txup); /* unref the message */ return 0; } int send_my_pid() { struct pmsg *up; int sbf; int cc; sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); pvm_pkint(&pvmmyupid, 1, 1); sbf = pvm_setsbuf(sbf); up = midtobuf(sbf); up->m_dst = TIDPVMD; up->m_tag = TM_SHMCONN; up->m_ctx = SYSCTX_TM; /* I would love a mxfer... but we have to use a custom */ /* one-off routine! */ /* cc = mxfer(up2, &ztv); */ cc = shmemuptod (up); pvm_freebuf(sbf); return cc; } int sleep_dammit( msecs ) int msecs; { #if defined(IMA_SUNMP) || defined(IMA_RS6KMP) || defined(IMA_AIX4MP) \ defined(IMA_AIX5MP) return( usleep( msecs ) ); #else struct timeval biteme; biteme.tv_sec = 0; biteme.tv_usec = msecs; while ( biteme.tv_usec > 1000000 ) { (biteme.tv_sec)++; biteme.tv_usec -= 1000000; } return( select( 0, #ifdef FDSETISINT (int *) NULL, (int *) NULL, (int *) NULL, #else (fd_set *) NULL, (fd_set *) NULL, (fd_set *) NULL, #endif &biteme ) ); #endif } ./pvm3/src/mppchunk.c0100644007401100000360000005542106354313410013666 0ustar kohlgopher static char rcsid[] = "$Id: mppchunk.c,v 1.6 1997/06/25 22:09:12 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* File: mppchunk.c -- implement asynchronous, pre-posted receive * buffers for mpp machines. * * NOTE: This code is designed to handle pvm packets (struct pkt) and * pvm frags (struct frag). The packet and frag structures are very similar. * So similar, in fact, that a small number of macros can be used to define * fwd,rev link ptrs, allocation routines, etc. In this code, these are * generically called chunks. Daemons use packets while user code use * fragments. * * * This code implements virtual sequence numbers to maintain ordered * delivery of message packets to the rest of the messaging system. * * for each connected task (O(1000) for PVM daemons) a packet sequence number * is maintained. Tasks send their packets in increasing * order to the pre-alloced buffers (with wrap when the buffer depth is * depleted). The underlying messaging insures that packets sent in * the same task on the same message tag will arrive at the receiver * in order. However, difficulty arises when multiple tasks are * sharing the buffers. A receive must be processed and then information * about who sent the message is extracted. In this scenario, it is * likely that packets will be received out of order. An example follows * for a buffer depth of four and two tasks A, B. The sequence numbers indicate * the order in which the packets are sent. A has sent 4 packets, B has sent * 7 packets * * BUF1: A(0) B(0) B(4) * BUF2: B(1) A(1) B(5) * BUF3: A(2) B(2) B(6) * BUF4: A(3) B(3) * * If round robin message probing is used, then packets are received in the * following order: * * A(0) B(1) A(2) A(3) B(0) A(1) B(2) B(3) B(4) B(5) B(6) * * In this case B(0) is received before B(1), A(2) and A(3) are both * received before A(1). * * By keeping track of what the current sequence number is for each task, * message delivery order can be maintained. */ /* NEEDED Support Routines: * * struct msgid * pvm_mpp_get_precvids() * * gets a pointer to head of list for post precv(s). * for daemons, this can return (struct msgid) NULL * * MPP_DIRECTI_PTR pvm_find_direct(ostructs, nstructs, src))) * MPP_DIRECTI_PTR ostructs; * int nstructs; * int src; * * ostructs - the start of an array of ordering structs. * nstructs - length of ostructs array * src - tid or node # that we are trying to find the ordering struct */ #include #include #include #include #include #include #include #include "global.h" #include "pvmalloc.h" #include "listmac.h" #include "lmsg.h" #include "mppmsg.h" #include "mppchunk.h" #include "pvmmimd.h" #include "bfunc.h" /* --- external declarations */ extern int errno; extern int pvmdebmask; /* from pvmd.c */ /* Global Variables that can be Changed */ int MAXSEQ = DFN_MAXSEQ; /* Private variables */ static char mpperrtext[128]; /* Prototypes for externals */ MPP_DIRECTI_PTR pvm_find_direct __ProtoGlarp__((MPP_DIRECTI_PTR, int , int)); struct msgid * pvm_mpp_get_precvids __ProtoGlarp__( () ); /* ======== new_directstruct ======== */ /* Allocate and fill and a new MPP_DIRECTI struct */ MPP_DIRECTI_PTR new_directstruct( nrbufs, nsbufs ) int nrbufs; /* number of receive buffers */ int nsbufs; /* number of send buffers */ { MPP_DIRECTI_PTR new; int i; if ( !( new = (MPP_DIRECTI_PTR) TALLOC(1, MPP_DIRECTI, "new_directstruct") ) || ! (new -> ordering = new_chunkostruct( nrbufs ))) { pvmlogerror("new_directstruct: can't get memory\n"); pvmbailout(PvmNoMem); return (MPP_DIRECTI_PTR) NULL; } init_directstruct( new, nsbufs); return new; } /* ======== init_directstruct ======== */ int init_directstruct( dstruct , nsbufs ) MPP_DIRECTI_PTR dstruct; int nsbufs; { /* Initialize the variables. Set unknown values to -1 */ dstruct -> rtid = -1; dstruct -> rpid = -1; dstruct -> tagbase = -1; dstruct -> nbufs = nsbufs; dstruct -> sseq = -1; return PvmOk; } /* ======== fill_directstruct ======== */ int fill_directstruct( dstruct , nsbufs, rtid, rpid, tagbase, seq , appid) MPP_DIRECTI_PTR dstruct; int nsbufs; int rtid; int rpid; int tagbase; int seq; int appid; { /* Initialize the variables. Set unknown values to -1 */ dstruct -> rtid = rtid; dstruct -> rpid = rpid; dstruct -> tagbase = tagbase; dstruct -> nbufs = nsbufs; dstruct -> sseq = seq; dstruct -> appid = appid; return PvmOk; } /* ======== new_vdirectstruct ======== */ /* Allocate and fill n new MPP_DIRECTI structs, return an array of MPP_DIRECTI structs */ MPP_DIRECTI_PTR new_vdirectstruct( nstructs, nsbufs, nrbufs ) int nsbufs; int nrbufs; { MPP_DIRECTI_PTR vnew, current; CHUNK_ORDER_PTR ostructs; int i,j; if ( !( vnew = (MPP_DIRECTI_PTR) TALLOC(nstructs, MPP_DIRECTI, "new_vdirectstruct") ) || !( ostructs = new_vchunkostruct( nstructs, nrbufs ) ) ) { pvmlogerror("new_vdirectstruct: can't get memory\n"); pvmbailout(PvmNoMem); return (MPP_DIRECTI_PTR) NULL; } /* Initialize the variables. Set unknown values to -1 */ for (j = 0; j < nstructs; j++) { current = vnew + j; init_directstruct( current, nsbufs); /* point to one of the ordering structs that we just malloc'ed */ current -> ordering = ostructs + j; } return vnew; } /* ======== new_chunkostruct ======== */ /* Allocate and fill and a new CHUNK_ORDER struct */ CHUNK_ORDER_PTR new_chunkostruct( nbufs ) int nbufs; { CHUNK_ORDER_PTR new; int i; if ( !( new = (CHUNK_ORDER_PTR) TALLOC(1, CHUNK_ORDER, "new_chunkostruct") ) || !( new->bufseq = (int *) TALLOC(nbufs, int, "new_chunkostruct") ) ) { pvmlogerror("new_chunkostruct: can't get memory\n"); pvmbailout(PvmNoMem); return (CHUNK_ORDER_PTR) NULL; } /* init the sequence #'s and buffer sequence #'s, nbufs */ init_chunkostruct( new, nbufs ); return new; } /* ======== new_vchunkostruct ======== */ /* Allocate and fill n new CHUNK_ORDER structs , do it in a couple of mallocs so that initializing a large number of structs is done efficiently */ CHUNK_ORDER_PTR new_vchunkostruct( nstructs, nbufs ) int nstructs; int nbufs; { CHUNK_ORDER_PTR vnew, current; int *bufs; int i,j; if ( !( vnew = (CHUNK_ORDER_PTR) TALLOC(nstructs, CHUNK_ORDER, "new_vchunkostruct") ) || !( bufs = (int *) TALLOC(nbufs * nstructs, int, "new_vchunkostruct") ) ) { pvmlogerror("new_vchunkostruct: can't get memory\n"); pvmbailout(PvmNoMem); return (CHUNK_ORDER_PTR) NULL; } /* init the sequence #'s and buffer sequence #'s, nbufs */ for (j = 0; j < nstructs; j++) { current = vnew + j; current -> bufseq = bufs + ( nbufs * j ); init_chunkostruct( current, nbufs ); } return vnew; } /* ======== init_chunkostruct ======== */ int init_chunkostruct( ostruct , nrbufs ) CHUNK_ORDER_PTR ostruct; int nrbufs; { int i; /* Initialize the variables. Set unknown values to -1 */ ostruct -> nbufs = nrbufs; ostruct -> seq = 0; for (i = 0; i < nrbufs; i ++) ostruct->bufseq[i] = i; ostruct->oochunks = (CHUNK_PTR) NULL; return PvmOk; } /* ======== order_chunk ======== */ /* take a buffer number and pkt_order struct and a pkt, place the pkt on the oopkts list, update sequence #'s. */ int order_chunk( ostruct, ibuf, inchunk ) CHUNK_ORDER_PTR ostruct; int ibuf; CHUNK_PTR inchunk; { int *obseq; /* order buffer sequence number */ CHUNK_PTR firstchunk, tstchunk; obseq = ostruct->bufseq + ibuf; inchunk->CHUNK_SEQ = *obseq; /* store next packet sequence # to arrive in this buffer from this sender*/ *obseq = NEXTCHUNKSEQ(*obseq, ostruct->nbufs); if (ostruct -> oochunks == (CHUNK_PTR) NULL) { ostruct -> oochunks = inchunk; inchunk -> CHUNK_NEXT = inchunk -> CHUNK_PREV = inchunk; } else { firstchunk = tstchunk = ostruct->oochunks; while (SEQLESSTHAN(tstchunk->CHUNK_SEQ, inchunk -> CHUNK_SEQ) && tstchunk -> CHUNK_NEXT != firstchunk) tstchunk = tstchunk -> CHUNK_NEXT; if (SEQLESSTHAN(tstchunk ->CHUNK_SEQ, inchunk->CHUNK_SEQ)) { LISTPUTAFTER(tstchunk, inchunk, CHUNK_NEXT, CHUNK_PREV); } else { LISTPUTBEFORE(tstchunk, inchunk, CHUNK_NEXT, CHUNK_PREV); if (tstchunk == firstchunk) /* new first of the list ? */ ostruct -> oochunks = inchunk; } } if (pvmdebmask & (PDMPACKET | PDMNODE)) { sprintf(mpperrtext,"Ordering packet seq %d from tid %x\n", inchunk -> CHUNK_SEQ, inchunk -> CHUNK_SRC); pvmlogerror(mpperrtext); } return 0; } /* ======== ochunk_delete ======== */ /* delete a pkt from the oopkts struct if any. Adjust the seq number. returns NULL if no packet is ready. */ CHUNK_PTR ochunk_delete( ostruct ) CHUNK_ORDER_PTR ostruct; { CHUNK_PTR tstchunk; if ( !ostruct || ! (ostruct->oochunks)) return (CHUNK_PTR) NULL; tstchunk = ostruct->oochunks; if (tstchunk -> CHUNK_SEQ == ostruct -> seq) /* yep, we got one */ { ostruct->seq = NEXTCHUNKSEQ(ostruct -> seq, 1); if (tstchunk -> CHUNK_NEXT == tstchunk) ostruct -> oochunks = (CHUNK_PTR) NULL; else { ostruct -> oochunks = tstchunk -> CHUNK_NEXT; LISTDELETE(tstchunk, CHUNK_NEXT, CHUNK_PREV); } if (pvmdebmask & (PDMPACKET | PDMNODE)) { sprintf(mpperrtext,"ochunk_delete() packet seq %d from tid %x\n", tstchunk -> CHUNK_SEQ, tstchunk -> CHUNK_SRC); pvmlogerror(mpperrtext); } tstchunk -> CHUNK_NEXT = tstchunk -> CHUNK_PREV = (CHUNK_PTR) NULL; tstchunk -> CHUNK_SEQ = 0; return tstchunk; } return (CHUNK_PTR) NULL; } /* ======== init_recv_list ======== */ /* allocate a message receive array and post the actual receives */ MSG_INFO_PTR init_recv_list( nbufs, tagbase, msize, hsize, appid, llmsg ) int nbufs, tagbase, msize, hsize; int appid; MSGFUNC_PTR llmsg; { MSG_INFO_PTR new, tmp; CHUNK_PTR msgchunk; char * datap; int i; int cc; int mrsize; /* message receive size */ if ( !( new = (MSG_INFO_PTR) TALLOC(nbufs, MSG_INFO, "init_recv_list") ) ) { pvmlogerror("init_recv_list: couldn't allocate memory \n"); return (MSG_INFO_PTR) NULL; } tmp = new; for (i = 0; i < nbufs; i ++) { cc = post_receive(tmp, -1, tagbase + i, msize, hsize, MPPANY, appid, llmsg); tmp ++; if (cc < 0) { sprintf(mpperrtext,"init_recv_list(): post_receive failed! src %d tag %d msize %d hsize %d pid %d appid %d : nbufs %d buffer %d \n", -1, tagbase + i, msize, hsize, MPPANY, appid, nbufs, i); pvmlogerror(mpperrtext); } } return new; } /* ======= post_receive ======== */ /* allocs a new packet and posts an asynchronous receive for the message */ int post_receive(imsg, src, tag, mxsize, headroom, ptype, appid, llmsg) MSG_INFO_PTR imsg; int src, tag, mxsize, headroom; int ptype; int appid; MSGFUNC_PTR llmsg; { int cc; char *datap; char errtxt[128]; CHUNK_PTR msgchunk; if ( !(msgchunk = CHUNK_NEW(mxsize)) ) { pvmlogerror("post_recv: couldn't allocate memory \n"); return PvmNoMem; } datap = msgchunk->CHUNK_DAT + headroom; imsg -> rchunk = msgchunk; /* PVM packet */ imsg -> src = src; imsg -> tag = tag; /* tag for this buffer */ imsg -> mxsize = mxsize; /* max msg size for this buffer */ imsg -> hsize = headroom; /* header size (data offset) */ cc = (*llmsg->imsgrecv)(appid, src, tag, datap, mxsize - headroom, ptype, imsg->info, &(imsg->mid)); if ( cc < 0) { sprintf(errtxt, "post_recv: bad msg id (%d). Fatal! \n", cc); pvmlogerror(errtxt); return PvmSysErr; } } /* ======= post_send ======== */ /* Given a packet,length, and a MPP_DIRECTI structure, send a message to the recipient. Info used from the MPP_DIRECTI struct is rtid; tagbase; nbufs; sseq; Returns: a positive mid if the send was successful. a negative mid if the send was unsuccessful. sequence #s in the MPP_DIRECTI struct are only advanced if the send was successful. */ msgmid_t post_send(buffer, len, distruct, llmsg) char *buffer; int len; MPP_DIRECTI_PTR distruct; MSGFUNC_PTR llmsg; { int appid; int cc; int dest; int ptype; int rtid; int tag; msgmid_t mid; if (distruct == (MPP_DIRECTI_PTR) NULL) return (-1); rtid = distruct->rtid; tag = distruct -> sseq % distruct -> tagbase; dest = (distruct -> rtid) & TIDNODE; ptype = (distruct -> rpid); appid = (distruct -> appid); /* Increment the send sequence number if the send is successful */ if ( (cc = (*llmsg->imsgsend)(appid, tag, buffer, len, dest, ptype, &mid)) >= 0 ) distruct -> sseq = INCRSEQ( distruct->sseq, MAXSEQ); return mid; } /* ======= read_chunk ======== */ /* reads the chunk indicated by the msg_info structure and then re-posts a receive to takes its place. Will not block if the message has completed, so can be used as a "probe with receive" if repost > 0; then repost a receive with the same parameters; */ CHUNK_PTR read_chunk( imsg, src, tag, len , repost, appid, llmsg) MSG_INFO_PTR imsg; int *src; int *tag; int *len; int repost; int appid; MSGFUNC_PTR llmsg; { CHUNK_PTR rchunk= (CHUNK_PTR) NULL; if (imsg && imsg->rchunk && imsg->mid >= 0 && (*llmsg->msgdone)(appid, &(imsg->mid), imsg->info)) { *src = (*llmsg->msgsrc)(imsg->info); *len = (*llmsg->msglen)(imsg->info); *tag = (*llmsg->msgtag)(imsg->info); rchunk = imsg -> rchunk; if (pvmdebmask & PDMPACKET) { sprintf(mpperrtext,"read-chunk(): node %d, len %d, tag %d \n", *src, *len, *tag); pvmlogerror(mpperrtext); } if (repost) post_receive(imsg, imsg->src, imsg->tag, imsg->mxsize, imsg->hsize, MPPANY, appid, llmsg); } return rchunk; } /* -------- pvm_chunkReady() --------- */ /* probe to see if any chunks have arrived. Chunks are in pre-posted * buffers numbered 0, 1, ..., (nbufs-1). * pvm_chunkReady() will return a chunk if it is completed. * chunkReady handles inplace reception of messages by examining the * header structure of the chunk. It allocates more memory if it needs * * Input: * ppmsg - vector of pre-posted receive MSG_INFO pointers (length == nbufs) * nbufs - length of ppmsg array * mfunc - low level message passing primitive functions to use * ostructs - ordering structures * nstructs - number of ordering structures * *cbuf - current buffer to probe in the ppmsg array. Updated by pvm_frReady * **hdReadyList - list of ready chunks, updated by pvm_chunkReady * * Return: * rcp - pointer to ready chunk. NULL if none ready */ CHUNK_PTR pvm_chunkReady(ppmsg, nbufs, mfunc, ostructs, nstructs, cbuf, hdReadyList ) MSG_INFO_PTR ppmsg; /* vector of pre-posted message buffers */ int nbufs; /* number of bufs in ppsmg */ MSGFUNC_PTR mfunc; /* structure of message passing primitives */ MPP_DIRECTI_PTR ostructs; int nstructs; int *cbuf; /* buffer to probe in ppmsg vector */ CHUNK_PTR *hdReadyList; { char *cp; char errtxt[64]; MPP_DIRECTI_PTR tcon; int cc; int i, ipctxt, ipff, iplen, ipsrc, iptag; int flen; int len; int match; int src; int tag, tpff, tpsrc; CHUNK *rcp, *rcp2; struct msgid *precvMsg, *precvIds; if (*hdReadyList) if ((*hdReadyList)->CHUNK_NEXT != *hdReadyList) { rcp = (*hdReadyList)->CHUNK_NEXT; LISTDELETE(rcp, CHUNK_NEXT, CHUNK_PREV); return rcp; } /* check if there is a ready chunk in the preposted buffers. repost the receive for the next time around */ for (i = 0; i < nbufs; i ++) { if ( *cbuf >= nbufs || *cbuf < 0) *cbuf = 0; if (rcp = read_chunk(ppmsg + (*cbuf), &src, &tag, &len, MPPREPOST, MPPANY, mfunc)) { rcp->CHUNK_LEN = len; /* remember how much data was sent */ rcp->CHUNK_SRC = src; /* this will be a node #, not a tid ! */ if (pvmdebmask & (PDMNODE | PDMPACKET)) { tpff = pvmget8(rcp->CHUNK_DAT + 12); tpsrc = pvmget32(rcp->CHUNK_DAT + 4); sprintf(errtxt, "readyChunk()read_chunk src %x node %d len %d ff %d buffer %d\n", tpsrc, src, len, tpff, *cbuf); pvmlogerror(errtxt); } /* find the ordering structure for this task, put this chunk on this tasks reorder queue */ if ( !(tcon = pvm_find_direct(ostructs, nstructs, src))) { pvmlogerror("frReady() could not find ordering struct \n"); return (CHUNK_PTR) NULL; } else order_chunk(tcon->ordering, *cbuf, rcp); /* put on order q */ /* remove in-order chunks on for this task, put them in callers readyFrags queue */ while ( rcp = ochunk_delete(tcon->ordering)) /* de-queue chunks */ { if (!*hdReadyList) /* readyList is empty, initialize */ *hdReadyList = CHUNK_NEW(0); if (pvmdebmask & (PDMNODE | PDMPACKET)) pvmlogprintf("dequeing chunk from %x len %d\n", rcp->CHUNK_SRC, rcp->CHUNK_LEN); /* XXX - This next part is really ugly! It checks if this * chunk is an inplace header and if there is a * precv outstanding for it. If there is, then the message * can go directly into the user memory. * * for daemons, it is sufficient to set precvIds to NULL * This has to be done *AFTER* the frag header has been * dequeued from the readyList to preserve ordering */ if ( (flen = pvmget32(rcp->CHUNK_DAT + 8 ) + TDFRAGHDR) != rcp->CHUNK_LEN ) { ipff = pvmget8(rcp->CHUNK_DAT + 12); match = 0; if (ipff & FFSOM ) /* start of message, check for precv*/ { ipsrc = pvmget32(rcp->CHUNK_DAT + 4); iptag = pvmget32(rcp->CHUNK_DAT + TDFRAGHDR + 4); ipctxt = pvmget32(rcp->CHUNK_DAT + TDFRAGHDR + 8); if (precvMsg = pvm_mpp_get_precvids()) { if ( match = (((precvMsg->otid == -1 || ipsrc == precvMsg->otid) && (precvMsg->tag == -1 || iptag == precvMsg->tag) && (ipctxt == precvMsg->ctxt)) ? 1 : 0) ) { cc = inplaceRecv( src, src, precvMsg->ubuf, precvMsg->len, &iplen, mfunc); precvMsg->len = iplen; precvMsg->complete = 1; /* got it ! */ rcp->CHUNK_RIP = 1; /* received in place */ } } } if (!match) { if ( flen > rcp->CHUNK_MAX ) /* won't fit */ { rcp2 = CHUNK_NEW(flen); BCOPY(rcp->CHUNK_DAT, rcp2->CHUNK_DAT, rcp->CHUNK_LEN); rcp2->CHUNK_SRC = rcp->CHUNK_SRC; rcp2->CHUNK_LEN = rcp->CHUNK_LEN; CHUNK_FREE(rcp); rcp = rcp2; } cc = inplaceRecv(src, src, rcp->CHUNK_DAT + rcp->CHUNK_LEN, rcp->CHUNK_MAX - rcp->CHUNK_LEN, &iplen, mfunc); rcp->CHUNK_LEN += iplen; } } LISTPUTBEFORE(*hdReadyList, rcp, CHUNK_NEXT, CHUNK_PREV); } (*cbuf) ++; /* increment to probe the next buffer */ break; } (*cbuf) ++; /* increment to probe the next buffer */ } /* if ordered frags have been put into the global ready list, then dequeue one of them */ if (*hdReadyList && (*hdReadyList)->CHUNK_NEXT != *hdReadyList) { rcp = (*hdReadyList)->CHUNK_NEXT; LISTDELETE(rcp, CHUNK_NEXT, CHUNK_PREV); if (pvmdebmask & (PDMNODE | PDMPACKET)) pvmlogprintf(" chunk from hdready from %x len %d\n", rcp->CHUNK_SRC, rcp->CHUNK_LEN); return rcp; } else return (CHUNK_PTR) NULL; } /* ------- inplaceRecv() ------- */ int inplaceRecv(src, tag, buf, len, rlen, llmsg) int src; int tag; char *buf; int len; int *rlen; MSGFUNC_PTR llmsg; { MSG_INFO imsg; int appid = 0; /* ignored by tasks */ int cc; int ptype = 0; /* ouch! XXX. Fix this ! */ char logtxt[64]; cc = (*llmsg->imsgrecv)(0, src, tag, buf,len, ptype, imsg.info, &(imsg.mid)); if (cc < 0) { sprintf(logtxt," inplaceRecv(): bad mid (%d)\n", cc); pvmlogerror(logtxt); return PvmSysErr; } while ( (cc = (*llmsg->msgdone)(appid, &(imsg.mid), imsg.info)) == 0 ) /* wait for recv to finish */ ; if (cc < 0) { sprintf(logtxt,"inplaceRecv(): error on msgdone (%d)\n", cc); pvmlogerror(logtxt); return PvmSysErr; } *rlen = (*llmsg->msglen)(imsg.info); return 0; } /* =========== Look for a send mid that has finished ========= */ /* This routine checks to see if there is a free slot to describe a chunk (pkt or frag) that has been asychronously sent. If the available slots (num) are taken, it checks to see if the message has completed. If it has, then it frees the chunk returns >= 0 successful < 0 no free descriptors left, none of the previous ones have completed. */ int pvm_mpp_find_midx(mppsendmids, mppoutchunks, current, num, mfunc ) msgmid_t *mppsendmids; CHUNK_PTR *mppoutchunks; int *current; int num; MSGFUNC_PTR mfunc; { int foundidx; int i, idx; int appid = 0; /** XXXX fix this for PGONPUMA */ info_t minfo[MPPINFOSIZE]; foundidx = 0; idx = *current; for (i = 0; i < num; i++ ) { /* Check if a previous send has finished */ if (mppsendmids[idx] >= 0) { if ((*mfunc->msgdone)(appid, &(mppsendmids[idx]), minfo) ) { mppsendmids[idx] = (msgmid_t) -1; if (mppoutchunks[idx]) { CHUNK_FREE(mppoutchunks[idx]); mppoutchunks[idx] = (CHUNK_PTR) NULL; } foundidx = 1; } } else { if (mppsendmids[idx] == (msgmid_t) MPPMIDFREE) foundidx = 1; } if (foundidx) break; if (++idx >= num) idx = 0; } if (foundidx) { mppsendmids[idx] = (msgmid_t) MPPMIDALLOCED; if ( (*current = idx + 1) >= num) *current = 0; return (idx); } else return (-1); } /* ============ pvm_assign_mid =========== */ /* set the mid in the mppsendmids array */ int pvm_assign_mid(mppsendmids, mid, idx) msgmid_t *mppsendmids; msgmid_t mid; int idx; { mppsendmids[idx] = mid; return 0; }; /* ============ pvm_assign_chunk =========== */ /* set the chunk pointer in the in the mppoutchunks array */ int pvm_assign_chunk(mppoutchunks, icp, idx) CHUNK_PTR *mppoutchunks; CHUNK_PTR icp; int idx; { mppoutchunks[idx] = icp; return 0; } /* ========== pvm_init_asynch_list ========== */ int pvm_init_asynch_list(outmids, outchunks, num) msgmid_t *outmids; CHUNK_PTR *outchunks; int num; { int i; for (i = 0 ; i < num ; i ++ ) { outmids[i] = (msgmid_t) MPPMIDFREE; outchunks[i] = (CHUNK_PTR) NULL; } return 0; } ./pvm3/src/mppmsg.c0100644007401100000360000005241510001307622013334 0ustar kohlgopher static char rcsid[] = "$Id: mppmsg.c,v 1.12 2004/01/14 18:50:58 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* Define low level message functions for the MPP port */ #include #include #include #if defined(NEEDSSELECTH) #include #endif #include #include #include #ifndef NOUNIXDOM #include #endif #include #ifndef NO_NETINET_TCP_H #include #endif #include #include #include "lpvm.h" #include "global.h" #include "pvmalloc.h" #include "listmac.h" #include "lmsg.h" #include "mppmsg.h" #include "mppchunk.h" #include "pvmmimd.h" #include "bfunc.h" /* --- external declarations */ void hex_inadport __ProtoGlarp__ (( char *, struct sockaddr_in * )); extern int errno; extern int pvmdebmask; /* from pvmd.c */ #if defined(IMA_NODE) extern int pvmhostnode; #endif #if defined(IMA_PGON) #include #define ASYNCSEND(_app, _tag, _buf, _len, _dest, _partid, _mid) \ _isend((long)(_tag), _buf, (long)(_len), (long)(_dest), (long)(_partid)) #define ASYNCRECV(_app, _src, _tag, _buf, _len, _partid, _info, _mid) \ _irecvx((long)(_tag), _buf, (long)(_len), (long)(_src), \ (long)(_partid), (long *)_info) #define MSGDONE(_app,_mid,_flag,_status) \ _msgdone(*(_mid)) #define MSGMERGE(_mid1, _mid2) \ _msgmerge(*(_mid1), *(_mid2)) #define MSGTAG(_info) \ _info[0] #define MSGLEN(_info, _len) \ _info[1] #define MSGSRC(_info) \ _info[2] /* Host (daemon) uses the same nx routines that nodes do */ #define HOSTASYNCSEND ASYNCSEND #define HOSTASYNCRECV ASYNCRECV #define HOSTMSGMERGE MSGMERGE #define HOSTMSGDONE MSGDONE #define HOSTMSGTAG MSGTAG #define HOSTMSGLEN MSGLEN #define HOSTMSGSRC MSGSRC #endif /* IMA_PGON */ #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) #if defined(IMA_NODE) #include #define ASYNCSEND(_app, _tag, _buf, _len, _dest, _partid, _mid) \ MPI_Isend((void *) (_buf), len, MPI_BYTE, _dest,\ _tag, MPI_COMM_WORLD, _mid) #define ASYNCRECV(_app, _src, _tag, _buf, _len, _partid, _info, _mid) \ MPI_Irecv((void *) (_buf), _len, MPI_BYTE, _src, _tag,\ MPI_COMM_WORLD, _mid) #define MSGDONE(_app,_mid,_flag,_status) \ MPI_Test(_mid, _flag, _status ) #define MSGTAG(_info) \ (_info)->MPI_TAG #define MSGMERGE(_mid1, _mid2) NULL #define MSGLEN(_info, _len) \ MPI_Get_count(_info, MPI_BYTE, _len) #define MSGSRC(_info) \ (_info)->MPI_SOURCE #else /* IMA_NODE */ #define ASYNCSEND(_app, _tag, _buf, _len, _dest, _partid, _mid) 0 #define ASYNCRECV(_app, _src, _tag, _buf, _len, _partid, _info, _mid) 0 #define MSGDONE(_app,_mid,_flag,_status) 0 #define MSGTAG(_info) 0 #define MSGMERGE(_mid1, _mid2) NULL #define MSGLEN(_info, _len) 0 #define MSGSRC(_info) 0 #endif /*IMA_NODE*/ /* Relay process uses the same routines that nodes do */ #define HOSTASYNCSEND ASYNCSEND #define HOSTASYNCRECV ASYNCRECV #define HOSTMSGMERGE MSGMERGE #define HOSTMSGDONE MSGDONE #define HOSTMSGTAG MSGTAG #define HOSTMSGLEN MSGLEN #define HOSTMSGSRC MSGSRC #endif /* IMA_SP2MPI */ char *getenv(); /* ----------( Node -- Node ) Routines ----------- */ static int pvm_inodesend(appid, tag, buffer, len, dest, partid, mid) int appid; int tag; char *buffer; int len; int dest; int partid; msgmid_t *mid; { #if defined(IMA_PGON) return ((*mid) = ASYNCSEND(appid, tag, buffer, len, dest, partid, mid)); #endif #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) return ASYNCSEND(appid, tag, buffer, len, dest, partid, mid); #endif } static int pvm_inoderecv(appid, src, tag, buffer, len, partid, info, mid) int appid; int src; int tag; char *buffer; int len; int partid; int *info; msgmid_t *mid; { #if defined(IMA_PGON) return ((*mid)=ASYNCRECV(appid, src, tag, buffer, len, partid, info, mid)); #endif #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) return ASYNCRECV(appid, src, tag, buffer, len, partid, info, mid); #endif } static msgmid_t pvm_nodemsgmerge (mid1, mid2) msgmid_t *mid1; msgmid_t *mid2; { return (msgmid_t) MSGMERGE(mid1, mid2); } static int pvm_nodemsgdone (appid, mid, info) int appid; msgmid_t *mid; info_t *info; { int flag; #if defined(IMA_PGON) return MSGDONE(appid, mid, &flag, info); #endif #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) MSGDONE(appid, mid, &flag, info); return flag; #endif } static int pvm_nodemsgsrc( info ) info_t *info; { return MSGSRC(info); } static int pvm_nodemsgtag( info ) info_t *info; { return MSGTAG(info); } static int pvm_nodemsglen( info ) info_t *info; { int len; #if defined(IMA_PGON) return MSGLEN(info, &len); #endif #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) MSGLEN(info,&len); return len; #endif } /* ---------- ( Host <--> Node ) Routines ----------- */ static int pvm_ihostsend(appid, tag, buffer, len, dest, partid, mid) int appid; int tag; char *buffer; int len; int dest; int partid; msgmid_t *mid; { #if defined(IMA_PGON) return ((*mid) = HOSTASYNCSEND(appid, tag, buffer, len, dest, partid, mid)); #endif #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) return HOSTASYNCSEND(appid, tag, buffer, len, dest, partid, mid); #endif } static int pvm_ihostrecv(appid, src, tag, buffer, len, partid, info, mid) int appid; int src; int tag; char *buffer; int len; int partid; int *info; msgmid_t *mid; { #if defined(IMA_PGON) return ((*mid)=HOSTASYNCRECV(appid, src, tag, buffer, len, partid, info, mid)); #endif #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) return HOSTASYNCRECV(appid, src, tag, buffer, len, partid, info, mid); #endif } static msgmid_t pvm_hostmsgmerge (mid1, mid2) msgmid_t *mid1; msgmid_t *mid2; { return HOSTMSGMERGE(mid1, mid2); } static int pvm_hostmsgdone (appid, mid, info) int appid; msgmid_t *mid; info_t *info; { int flag; #if defined(IMA_PGON) return HOSTMSGDONE(appid, mid, &flag, info); #endif #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) HOSTMSGDONE(appid, mid, &flag, info); return flag; #endif } static int pvm_hostmsgsrc( info ) info_t *info; { return HOSTMSGSRC(info); } static int pvm_hostmsgtag( info ) info_t *info; { return HOSTMSGTAG(info); } static int pvm_hostmsglen( info ) info_t *info; { int len; #if defined(IMA_PGON) return HOSTMSGLEN(info, &len); #endif #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) HOSTMSGLEN(info,&len); return len; #endif } static MSGFUNC nodemsgfunc = { pvm_inodesend, pvm_inoderecv, #if defined(IMA_PGON) pvm_nodemsgmerge, #else NULL, #endif pvm_nodemsgdone, pvm_nodemsglen, pvm_nodemsgsrc, pvm_nodemsgtag }; static MSGFUNC hostmsgfunc = { pvm_ihostsend, pvm_ihostrecv, #if defined(IMA_PGON) pvm_hostmsgmerge, #else NULL, #endif pvm_hostmsgdone, pvm_hostmsglen, pvm_hostmsgsrc, pvm_hostmsgtag }; /* -------- External Routines --------- */ MSGFUNC_PTR pvm_nodemsgfunc() { return &nodemsgfunc; } MSGFUNC_PTR pvm_hostmsgfunc() { return &hostmsgfunc; } /* Define some intialization functions that are only used by node procs */ #if defined(IMA_NODE) /* ------ messsage system initialization, destruction ----- */ int pvm_mpp_message_init(node, partsize, host, partid) int *node; int *partsize; int *host; int *partid; { char errtxt[64]; char *msgbuf; char *p; int ac = 0; int msgbufsiz; *node = -1; /* initialize to bogus values */ *partsize = -1; *host = -1; *partid = 0; #if defined(IMA_PGON) if ( (*partid = _myptype()) == INVALID_PTYPE ) { pvmlogerror("mpp_message_init() no process type\n"); return PvmSysErr; } _setptype(0); /* always set ptype to 0 */ *node = _mynode(); *partsize = _numnodes(); *host = *partsize; #endif #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) MPI_Init(&ac, NULL); MPI_Comm_rank(MPI_COMM_WORLD, node); MPI_Comm_size(MPI_COMM_WORLD, partsize); *host = *partsize - 1; /* host is last process in the group */ /* if (!(p = getenv("PVMBUFSIZE")) || !(msgbufsiz = strtol(p, (char**)0, 0))) msgbufsiz = MPIBUFSIZ; if (!(msgbuf = malloc(msgbufsiz))) pvmlogerror("relay() out of memory"); MPI_Buffer_attach(msgbuf, msgbufsiz); used in psend or relay */ if (*node == *host) /* I'm the host, run the host proc */ { (void)pvmhost(); } else /* MPI_Bcast(pvminfo, SIZEHINFO, MPI_INT, pvmhostnode, MPI_COMM_WORLD); */ #endif return 0; } int pvm_mpp_message_stop() { #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) MPI_Finalize(); #endif return 0; } #endif /* IMA_NODE */ /* =============== Host and Relay Processes for MPI =============== */ #if ( defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) \ || defined(IMA_AIX5SP2) ) && defined(IMA_NODE) #define NMPPSBUFMIDS 32 /* number of allowed outstanding send mids */ static msgmid_t mppsendmids[NMPPSBUFMIDS]; static CHUNK_PTR *mppoutchunks[NMPPSBUFMIDS]; static int lastindex = 0; /* ------------ relay -------------- */ /* Relay messages between pvmd and node tasks. */ void relay(dsock, numnodes) int dsock; /* pvmd socket */ int numnodes; /* number of nodes in the partition */ { #ifdef FDSETNOTSTRUCT fd_set wrk_rfds, wrk_wfds, rfds, wfds; #else struct fd_set wrk_rfds, wrk_wfds, rfds, wfds; #endif int nfds; struct timeval tout; struct frag *topvmdq = 0; /* frags to pvmd */ struct frag *frtask = 0; /* (big) frag from task */ struct frag *totaskq; /* frag being sent to task */ struct frag *fp; struct frag *frpvmd = (struct frag *) NULL; char *txcp = 0; /* point to remainder of topvmd */ int txtogo = 0; /* len of remainder of topvmd */ int toread; /* number of bytes to be read from pvmd */ int frtogo; /* len of remainder of a fragment */ int topvmd_dst; /* dst of fragment being sent to pvmd */ int topvmd_src; /* src of fragment being sent to pvmd */ int len; int topvmd_ff; /* ff of fragment being sent to pvmd */ int dst; /* dst of fragment being sent to node */ int node; /* node number */ MPI_Request rmhd; /* msg IDs returned by async recv */ int n; char *cp; int err,i; MPI_Status sta; /* info on pending message */ int dummy; int flag; /* MPI_Test result */ struct frag *hdr; int taskbuf = 0; /* current buffer number to probe */ MPP_DIRECTI_PTR taskdirect = (MPP_DIRECTI_PTR) NULL; /* ordering structs */ MSG_INFO_PTR taskfrags = (MSG_INFO_PTR) NULL; CHUNK_PTR readyFrags = (CHUNK_PTR) NULL; MSGFUNC_PTR mfunc; struct frag *cftd = (struct frag *) NULL; /* cur.frag going to daemon */ struct frag *cftt = (struct frag *) NULL; /* cur. frag to task */ int cftd_togo; /* len left to go to daemon */ int frg_complete; /* flag if outgoing frag is complete */ /* This is the relay process for MPI ports. * * It should be called in pvm_mpp_beatask * after pvm_mpp_message_init, so none of the pre-allocated buffers have * been allocated. * * It is basically a fragment forwarder * pvmd -> task - each fragment is read from the pvmd socket and forwarded to the tasks. task -> pvmd - each fragment is read from a task and forwarded onto the pvmd socket. */ /* Initialization */ mfunc = pvm_hostmsgfunc(); nfds = dsock + 1; /* set up pre-allocated receive buffers to/from tasks */ taskdirect = new_vdirectstruct(numnodes, NSBUFS, NRBUFS); taskfrags = init_recv_list(NSBUFS, PMTDBASE, MAXFRAGSIZE, 0, MPPANY, pvm_hostmsgfunc()); pvmlogprintf("relay() numnodes is %d\n", numnodes); /* initialize the packet numbering for packets to/from peers */ for (i = 0; i < numnodes; i ++) { fill_directstruct (taskdirect + i, NRBUFS, i, 0, PMTDBASE, 0, MPPANY); init_chunkostruct( (taskdirect+i)->ordering, NSBUFS); } /* initialize the fragment queues */ if( !(topvmdq = TALLOC(1, struct frag, "topvmdq")) || !(totaskq = TALLOC(1, struct frag, "totaskq")) ) { pvmlogerror("relay() could not init frag queues\n"); pvm_mpp_message_stop(); exit(PvmOutOfRes); } BZERO((char *) topvmdq, sizeof (struct frag)); BZERO((char *) totaskq, sizeof (struct frag)); topvmdq->fr_link = topvmdq->fr_rlink = topvmdq; totaskq->fr_link = totaskq->fr_rlink = totaskq; /* initialize the asynchronous send structures */ pvm_init_asynch_list(mppsendmids, mppoutchunks, NMPPSBUFMIDS); FD_ZERO(&wrk_rfds); /* zero the file set descriptor for select */ FD_ZERO(&wrk_wfds); tout.tv_sec = tout.tv_usec = 0; /* don't block in select */ while (1) { /* Step 1) get any frags from tasks */ while ( fp = (struct frag *) pvm_chunkReady(taskfrags, NRBUFS, mfunc, taskdirect, numnodes, &taskbuf, &readyFrags) ) { LISTPUTBEFORE(topvmdq, fp, fr_link, fr_rlink); if (pvmdebmask & PDMNODE) pvmlogprintf("Frag from task %d len %d \n", fp->fr_src, fp->fr_len); } /* If we don't have a frag to go to pvmd, check if one has been read */ if (!cftd && topvmdq->fr_link != topvmdq ) { cftd = topvmdq->fr_link; LISTDELETE(cftd, fr_link, fr_rlink); cftd_togo = cftd->fr_len; txcp = cftd->fr_dat; if (pvmdebmask & PDMNODE) pvmlogprintf("Frag to daemoen %d len %d \n", cftd->fr_src, cftd->fr_len); } /* There is a frag that needs to go to the daemon ? */ if (cftd) { FD_SET(dsock, &wrk_wfds); if (pvmdebmask & PDMNODE) pvmlogprintf("Setting dsock in the write fds \n"); } FD_SET(dsock, &wrk_rfds); /* need to probe the socket for reading */ rfds = wrk_rfds; wfds = wrk_wfds; if (select(nfds, #ifdef FDSETISINT (int *)&rfds, (int *)&wfds, (int *)0, #else (fd_set *)&rfds, (fd_set *)&wfds, (fd_set *)0, #endif &tout) == -1 && errno != EINTR) { pvmlogperror("relay() select"); pvm_exit(); pvm_mpp_message_stop(); exit(-1); } /* we've got something read from pvmd, if the frag is complete, then put it on the totaskq */ if (FD_ISSET(dsock, &rfds)) { frg_complete = 1; /* initially mark the frag as completely read */ if (!frpvmd) { /* allocate a data frag */ frpvmd = fr_new(MAXFRAGSIZE); toread = TDFRAGHDR; } n = read(dsock, frpvmd->fr_dat + frpvmd->fr_len, toread); if (n == -1 && errno != EWOULDBLOCK && errno != EINTR) { pvmlogperror("relay() read pvmd sock"); pvm_mpp_message_stop(); exit(12); } if (!n) { /* pvmlogerror("relay() read EOF on pvmd sock\n"); */ pvm_mpp_message_stop(); exit(13); } if ((frpvmd->fr_len += n) < TDFRAGHDR) { toread -= n; frg_complete = 0; } n = TDFRAGHDR + pvmget32(frpvmd->fr_dat + 8); /* get the length */ if (frpvmd->fr_len < n) { if (frpvmd->fr_max < n) { /* n > MAXFRAGSIZ */ hdr = frpvmd; frpvmd = fr_new(n); BCOPY(hdr->fr_dat, frpvmd->fr_dat, hdr->fr_len); frpvmd->fr_len = hdr->fr_len; fr_unref(hdr); } toread = n - frpvmd->fr_len; frg_complete = 0; } if (pvmdebmask & PDMNODE) pvmlogprintf("reading from daemon len %d frg_complete %d \n", frpvmd->fr_len, frg_complete); if (frg_complete) { dst = pvmget32(frpvmd->fr_dat); frpvmd -> fr_src = dst; /* overload the src field with the dst */ LISTPUTAFTER(totaskq, frpvmd, fr_link, fr_rlink); /* queue it */ if (pvmdebmask & PDMNODE) pvmlogprintf("frg_complete dest %x len %d\n", frpvmd->fr_src, frpvmd->fr_len); frpvmd = (struct frag *) NULL; } } if (!cftt && totaskq -> fr_link != totaskq ) { cftt = totaskq->fr_link; LISTDELETE(cftt, fr_link, fr_rlink); if (pvmdebmask & PDMNODE) pvmlogprintf("New frag to task %x len %d \n", cftt->fr_src, cftt->fr_len); } /* Let's see if we something to send to a task */ if (cftt) { if (send_to_node(cftt, taskdirect, numnodes) >= cftt->fr_len) cftt = (struct frag *) NULL; else /* if for some reason send_to_node could not send this frag, the next time through the loop, the frag will be resent. */; } /* Now let's see if we have something to write to the pvmd */ if ( cftd && FD_ISSET(dsock, &wfds)) { if (pvmdebmask & PDMNODE) pvmlogprintf("Writing packet to daemon %d\n", cftd->fr_len); n = write(dsock, txcp, cftd_togo); if (n == -1 && errno != EWOULDBLOCK && errno != EINTR) { pvmlogperror("relay() write pvmd sock"); pvm_mpp_message_stop(); exit(14); } if (n > 0 && (cftd_togo -= n) > 0) txcp += n; if (!cftd_togo) { /* entire message sent */ FD_CLR(dsock, &wrk_wfds); fr_unref(cftd); cftd = (struct frag *) NULL; } } else { if (cftd) if (pvmdebmask & PDMNODE) pvmlogprintf("could not write to daemon \n"); } } } /* --------- send_to_node() ------------ */ /* return the number of bytes sent. This posts sends asynchronously. A fixed number of asynch sends are allowed to be outstanding. If the relay asks for more than this number in sends. send_to_node will return 0. */ send_to_node(fp, taskdirect, numnodes ) struct frag *fp; MPP_DIRECTI_PTR taskdirect; int numnodes; { int appid = 0; int cc; int idx; int len; int node; int ptype; int tag; msgmid_t mid; MPP_DIRECTI_PTR tdirect; MSGFUNC_PTR mfunc; mfunc = pvm_hostmsgfunc(); if ( (idx = pvm_mpp_find_midx(mppsendmids, mppoutchunks, &lastindex, NMPPSBUFMIDS, mfunc)) >= 0) { node = fp->fr_src & TIDNODE; len = fp->fr_len; ptype = (fp->fr_src & TIDPTYPE) >> (ffs(TIDPTYPE) - 1); tdirect = taskdirect + node; tag = tdirect->tagbase + tdirect->sseq; if ( ++(tdirect->sseq) >= tdirect->nbufs) tdirect->sseq = 0; if ( (cc = (*mfunc->imsgsend)(appid, tag, fp->fr_dat, len, node, ptype, &mid)) < 0 ) { pvmlogprintf("Relay -- async send failed! (%d) \n", cc); } else /* send was ok. */ { pvm_assign_mid(mppsendmids, mid, idx); pvm_assign_chunk(mppoutchunks, (CHUNK_PTR) fp, idx); } return (len); } else return 0; /* could not send, no free low-level message ids */ } /* --------- pvmhost() ------------ */ /* We're the "host" process. Connect to pvmd. */ int pvmhost() { char *p; int dsock; /* pvmd socket */ struct sockaddr_in dsadr; /* address of pvmd socket */ int n; int i; int cc; int err; int pvminfo[SIZEHINFO]; /* ntask, hostpart, ptid, MTU, NDF */ char nullmsg[TDFRAGHDR+MSGHDRLEN]; int appid = 0; /* Would be used for PGONPUMA */ MSGFUNC_PTR mfunc; msgmid_t confmid; info_t confinfo; if (!(p = getenv("PVMSOCK"))) { pvmlogerror("pvmhost() getenv() pvmd socket\n"); pvm_mpp_message_stop(); exit(2); } if ((dsock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { pvmlogperror("pvmhost() socket"); pvm_mpp_message_stop(); exit(3); } BZERO((char*)&dsadr, sizeof(dsadr)); hex_inadport(p, &dsadr); dsadr.sin_family = AF_INET; n = sizeof(dsadr); while (connect(dsock, (struct sockaddr*)&dsadr, n) == -1) if (errno != EINTR) { pvmlogperror("pvmhost() connect"); pvm_mpp_message_stop(); exit(4); } #ifndef NOSOCKOPT n = 1; if (setsockopt(dsock, IPPROTO_TCP, TCP_NODELAY, (char*)&n, sizeof(int)) == -1) { pvmlogperror("pvmhost() setsockopt"); pvm_mpp_message_stop(); exit(5); } #endif if (!(p = getenv("PVMEPID"))) { pvmlogerror("pvmhost() getenv() pid\n"); pvm_mpp_message_stop(); exit(6); } pvmmyupid = atoi(p); BZERO(nullmsg, MAXHDR); pvmput32(nullmsg, TIDPVMD); pvmput32(nullmsg + 4, pvmmyupid); pvmput32(nullmsg + 8, MSGHDRLEN); pvmput32(nullmsg + 12, 0); /* to keep putrify happy */ pvmput8(nullmsg + 12, FFSOM|FFEOM); if (write(dsock, nullmsg, TDFRAGHDR+MSGHDRLEN) != TDFRAGHDR+MSGHDRLEN || read(dsock, pvminfo, SIZEHINFO*sizeof(int)) != SIZEHINFO*sizeof(int)) { pvmlogperror("pvmhost() write/read"); pvm_mpp_message_stop(); exit(8); } /* Multicast the configuration message */ mfunc = pvm_hostmsgfunc(); pvmlogprintf("pvmhost() -- Starting configMessage send Loop %d\n", pvmhostnode); for (i = 0; i < pvmhostnode; i ++ ) { if ( (*mfunc->imsgsend)(appid, PMTCONF, (char *) pvminfo, sizeof(pvminfo), i, PVMDPTYPE, &confmid) < 0) { pvmlogperror("pvmhost() configuration message \n"); err = PvmDSysErr; pvm_mpp_message_stop(); exit(9); } while (! ((*mfunc->msgdone)(appid, &confmid, &confinfo))); } pvmlogerror("pvmhost() -- Finished Message send Loop\n"); (void)relay(dsock, pvmhostnode + 1); } #endif /*IMA_SP2MPI*/ ./pvm3/src/msgbox.c0100644007401100000360000003722607240353445013352 0ustar kohlgopher static char rcsid[] = "$Id: msgbox.c,v 1.25 2001/02/07 23:15:49 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * msgbox.c * * Message mailbox database. * * $Log: msgbox.c,v $ * Revision 1.25 2001/02/07 23:15:49 pvmsrc * 2nd Half of CYGWIN Check-ins... * (Spanker=kohl) * * Revision 1.24 2000/02/16 21:59:47 pvmsrc * Fixed up #include stuff... * - use for IMA_TITN... * - #include before any NEEDMENDIAN #includes... * (Spanker=kohl) * * Revision 1.23 1999/12/13 18:13:41 pvmsrc * Moved pvmmatchstring() routine to pvmcruft.c (for usage by pvmtester). * Re-integrated two versions of mb_name() into one with #ifdefs for * the USE_GNU_REGEX stuff. * (Spanker=kohl) * * Revision 1.22 1999/12/10 21:30:45 pvmsrc * Yanked GNU Regex Stuff. * - re-activate using -DUSE_GNU_REGEX define... if you must. * - replaced full regular expression matching in mb_names() * with good ole Unix style '*' globbing, * via pvmmatchstring() a la Jeembo. * (Spanker=kohl) * * Revision 1.21 1999/11/08 17:21:16 pvmsrc * Added new PvmMboxDirectIndex() flag handling to mb_insert(). * - allow atomic re-insert at a specific index. * (Spanker=kohl) * * Revision 1.20 1999/07/08 19:00:04 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.19 1999/01/13 00:03:45 pvmsrc * Fixed up mbox insert stuff, bugs & 3.3 compat (insert/lookup/delete). * - changed to always pass in -1 for index (internal arg only). * - handle minst correctly, supercedes overwritable else no way to * build a minst list from within a single task, always just look * for next unused index if minst set. * - check for pvm_insert() compat, if mbox exists and req != -1 (any), * then return PvmDenied (no overwrite in 3.3). * (Spanker=kohl) * * Revision 1.18 1998/11/20 20:04:10 pvmsrc * Changes so that win32 will compile & build. Also, common * Changes so that compiles & builds on NT. Also * common source on win32 & unix. * (Spanker=sscott) * * Revision 1.17 1997/06/27 17:32:30 pvmsrc * Updated for WIN32 header files & Authors. * * Revision 1.16 1997/05/07 21:23:54 pvmsrc * Fixed manual packing of class name lengths. * - no longer necessary with (pvm)upkstralloc() usage. * Fixed bug: * - only free pattbuf if !pattglob... D-Oh! * * Revision 1.15 1997/05/05 18:17:49 pvmsrc * Added new pvmregex.o targets (part of ./regex stuff). * - extracted mb_names() regex usage to new pvm/regex routines: * void *pvmcompileregex __ProtoGlarp__ (( char * )); * int pvmmatchregex __ProtoGlarp__ (( void *, char * )); * void pvmfreeregex __ProtoGlarp__ (( void ** )); * * Revision 1.14 1997/05/02 19:44:38 pvmsrc * Added GNU Regex Stuff: * - Makefile targets for regex.o * - usage in mb_names() / msgbox.c * * Revision 1.13 1997/05/02 14:54:18 pvmsrc * Implemented guts of pvm_getmboxinfo(): * - user library side sends pattern & receives back / allocs array. * - at pvmd side mb_names() searches class list for matching pattern, * count up # of entries, and pack up struct info. * (Note: does not yet use GNU regex stuff...) * * Revision 1.12 1997/04/10 17:53:54 pvmsrc * Externalized me_new()... * - for WT_RECVINFO usage... * * Revision 1.11 1997/04/08 20:06:33 pvmsrc * Un-static-ed me_free(). * - so ddpro.c can use it... D-Oh. * * Revision 1.10 1997/04/08 19:57:52 pvmsrc * Promoted mbox static "classes" to public global "pvmmboxclasses". * - so pvmd can spank mboxes in ddpro.c... :-Q * - renamed everywhere, moved decl / extern to global.[ch]. * * Revision 1.9 1997/04/08 19:41:11 pvmsrc * Added me_savetid to pvmmentry struct. * - for keeping track of original owner on persistent mboxes. * - allows more careful cleanup in a system reset, set me_tid to 0 * but save original tid in me_savetid first... :-) * * Revision 1.8 1997/04/08 18:45:20 pvmsrc * Yanked out internal struct defns for mclass & mentry. * - replaced with msgbox.h header, and pvmmclass / pvmmentry structs. * * Revision 1.7 1997/04/08 17:53:25 pvmsrc * Added new mb_tidy_reset() routine. * - triggered by task exit during a system reset (when persistent * mbox entries are owned by task). * - clear out any persistent mboxes owned by task, or any others * that have already been cleared. * * Revision 1.6 1997/04/01 16:39:39 pvmsrc * Oops... PvmMboxOverwritable -> PvmMboxOverWritable... D-Oh. * * Revision 1.5 1997/04/01 16:19:25 pvmsrc * Modified mbox internals to properly handle new flags syntax. * - pvm_putinfo(): * * PvmMboxMultiInstance = if index 0 is in use, stick in * first available higher index. * * PvmMboxOverwritable = allow anyone to overwrite or delete * the given mbox entry. * * PvmMboxPersistent = do not remove mailbox on task exit, * allow only PVMD to delete on reset (after task exit only). * - pvm_recvinfo(): * * PvmMboxReadAndDelete = if entry is owned by task or is * overwritable, read entry and atomically delete, else fail. * * PvmMboxFirstAvail = if entry not present at given index, * return next entry by index, else fail. * * Revision 1.4 1997/01/28 19:26:54 pvmsrc * New Copyright Notice & Authors. * * Revision 1.3 1996/10/24 21:04:48 pvmsrc * Moved #include of "global.h" down below other headers: * - need to have all of the structures / types declared before * the globals can be declared... * * Revision 1.2 1996/09/23 23:32:16 pvmsrc * Initial Creation - original msgbox.c. * */ #include #ifdef NEEDMENDIAN #include #include #endif #ifdef NEEDENDIAN #include #endif #ifdef NEEDSENDIAN #include #endif #include #if defined(WIN32) || defined(CYGWIN) #include "..\xdr\types.h" #include "..\xdr\xdr.h" #else #include #include #endif #ifdef SYSVSTR #include #else #include #endif #include "pvmalloc.h" #include "listmac.h" #include "pmsg.h" #include "msgbox.h" #include "global.h" #ifdef USE_GNU_REGEX void *pvmcompileregex __ProtoGlarp__ (( char * )); int pvmmatchregex __ProtoGlarp__ (( void *, char * )); void pvmfreeregex __ProtoGlarp__ (( void ** )); #else int pvmmatchstring __ProtoGlarp__ (( char *, char * )); #endif /*************** ** Globals ** ** ** ***************/ extern int pvmdebmask; /* from pvmd.c */ /*************** ** Private ** ** ** ***************/ struct pvmmentry * me_new(ind) int ind; { struct pvmmentry *ep; if (ep = TALLOC(1, struct pvmmentry, "pvmmentry")) { ep->me_link = ep->me_rlink = ep; ep->me_tid = 0; ep->me_savetid = 0; ep->me_flags = PvmMboxDefault; ep->me_msg = 0; ep->me_ind = ind; } return ep; } static struct pvmmclass * mc_new(name) char *name; { struct pvmmclass *np; if (np = TALLOC(1, struct pvmmclass, "pvmmclass")) { if (name) { np->mc_name = STRALLOC(name); np->mc_ent = me_new(-1); LISTPUTBEFORE(pvmmboxclasses, np, mc_link, mc_rlink); } else { np->mc_link = np->mc_rlink = np; np->mc_name = 0; np->mc_ent = 0; } } return np; } int me_free(np, ep) struct pvmmclass *np; struct pvmmentry *ep; { LISTDELETE(ep, me_link, me_rlink); pmsg_unref(ep->me_msg); PVM_FREE(ep); if (np->mc_ent->me_link == np->mc_ent) { LISTDELETE(np, mc_link, mc_rlink); PVM_FREE(np->mc_name); PVM_FREE(np->mc_ent); PVM_FREE(np); } return 0; } static struct pvmmclass * mc_find(name) char *name; { struct pvmmclass *np; for (np = pvmmboxclasses->mc_link; np != pvmmboxclasses; np = np->mc_link) if (!strcmp(np->mc_name, name)) return np; return (struct pvmmclass *)0; } int mb_init() { pvmmboxclasses = mc_new((char*)0); return 0; } int mb_insert(tid, name, req, flags, mp) int tid; /* owner task */ char *name; /* class name */ int req; /* index requested or -1 for lowest avail */ int flags; struct pmsg *mp; /* message to store */ { struct pvmmclass *np; struct pvmmentry *ep; struct pvmmentry *ep2 = 0; int dind; /* direct index */ int cind; /* current index */ /* must change to always pass in -1 for 3.4 calls */ /* then can distinguish between 3.4 reinsert which succeeds if !overwritable/minst & 3.3 reinsert which should fail */ /* to fix the "if (ep->me_ind == req)" conditional use a "current index": cind = ( req == -1 ) ? 0 : req; */ /* also, minst supercedes overwritable, else no way to build a minst list from within a single task... */ if (!(np = mc_find(name))) if (!(np = mc_new(name))) return PvmNoMem; dind = PvmMboxDirectIndexOf( flags ); cind = ( req == -1 ) ? ( ( dind ) ? dind : 0 ) : req; for (ep = np->mc_ent->me_link; ep != np->mc_ent; ep = ep->me_link) if (ep->me_ind >= cind) break; /* default insert is "locked"... */ if (ep->me_ind == cind) { if (flags & PvmMboxMultiInstance) { if ( req != -1 ) /* hack for 3.3 compat */ return PvmDenied; for (; ep != np->mc_ent; ep = ep->me_link) { if (ep->me_ind != cind) break; cind++; } } else { if ( !(ep->me_flags & PvmMboxOverWritable) && tid != ep->me_tid) { return PvmDenied; } ep2 = ep; } } if (ep2) { ep = ep2->me_link; LISTDELETE(ep2, me_link, me_rlink); pmsg_unref(ep2->me_msg); PVM_FREE(ep2); } ep2 = me_new(cind); ep2->me_tid = tid; ep2->me_flags = flags; ep2->me_msg = mp; LISTPUTBEFORE(ep, ep2, me_link, me_rlink); return cind; } int mb_delete(tid, name, req, flags) int tid; /* owner task */ char *name; /* class name */ int req; /* index */ int flags; /* options */ { struct pvmmclass *np; struct pvmmentry *ep = 0; if (np = mc_find(name)) { for (ep = np->mc_ent->me_link; ep != np->mc_ent; ep = ep->me_link) { if (ep->me_ind == req) break; } if (ep == np->mc_ent) ep = 0; } if (!ep) return PvmNotFound; if ( !(ep->me_flags & PvmMboxOverWritable) && tid != ep->me_tid ) return PvmDenied; req = ep->me_ind; me_free(np, ep); return req; } int mb_lookup(tid, name, req, flags, mpp) int tid; /* owner task */ char *name; /* class name */ int req; /* index requested or -1 for first avail */ int flags; struct pmsg **mpp; /* message return */ { struct pvmmclass *np; struct pvmmentry *ep = 0; if (np = mc_find(name)) { for (ep = np->mc_ent->me_link; ep != np->mc_ent; ep = ep->me_link) { if (ep->me_ind >= req) break; } if (ep == np->mc_ent) ep = 0; else if (!(flags & PvmMboxFirstAvail) && ep->me_ind != req) ep = 0; } if (ep) { if ( flags & PvmMboxReadAndDelete ) { if ( (ep->me_flags & PvmMboxOverWritable) || tid == ep->me_tid ) { req = ep->me_ind; ep->me_msg->m_ref++; *mpp = ep->me_msg; me_free(np, ep); } else { req = PvmDenied; *mpp = (struct pmsg *) NULL; } } else { req = ep->me_ind; ep->me_msg->m_ref++; *mpp = ep->me_msg; } } else req = PvmNotFound; return req; } int mb_names(tid, pattern, mp) int tid; char *pattern; struct pmsg *mp; { struct pvmmclass *np; struct pvmmentry *ep; #ifdef USE_GNU_REGEX void *pattbuff; int pattglob = 0; #endif int cnt; #ifdef USE_GNU_REGEX /* Check for "*" Global Match Pattern */ if ( !strcmp( pattern, "*" ) ) pattglob = 1; /* Compile Regular Expression */ if ( !pattglob ) pattbuff = pvmcompileregex( pattern ); #endif /* Count # of Classes */ cnt = 0; for ( np = pvmmboxclasses->mc_link; np != pvmmboxclasses; np = np->mc_link ) { #ifdef USE_GNU_REGEX if ( pattglob || ( ( pattbuff ) ? ( pvmmatchregex( pattbuff, np->mc_name ) ) : ( !strcmp( pattern, np->mc_name ) ) ) ) #else if ( pvmmatchstring( np->mc_name, pattern ) ) #endif { cnt++; } } pkint( mp, cnt ); /* Pack Class Info */ for ( np = pvmmboxclasses->mc_link; np != pvmmboxclasses; np = np->mc_link ) { #ifdef USE_GNU_REGEX if ( pattglob || ( ( pattbuff ) ? ( pvmmatchregex( pattbuff, np->mc_name ) ) : ( !strcmp( pattern, np->mc_name ) ) ) ) #else if ( pvmmatchstring( np->mc_name, pattern ) ) #endif { pkstr( mp, np->mc_name ); /* Count # of Entries */ cnt = 0; for ( ep = np->mc_ent->me_link; ep != np->mc_ent; ep = ep->me_link ) cnt++; pkint( mp, cnt ); /* Pack Entry Info */ for ( ep = np->mc_ent->me_link; ep != np->mc_ent; ep = ep->me_link ) { pkint( mp, ep->me_ind ); pkint( mp, ep->me_tid ); pkint( mp, ep->me_flags ); } } } #ifdef USE_GNU_REGEX if ( !pattglob && pattbuff ) pvmfreeregex( &pattbuff ); #endif return 0; } int mb_dump(np) struct pvmmclass *np; { struct pvmmentry *ep; pvmlogprintf("<%s>\n", np->mc_name); for (ep = np->mc_ent->me_link; ep != np->mc_ent; ep = ep->me_link) { pvmlogprintf("%d (0x%x): owner 0x%x (was 0x%x) flags %d\n", ep->me_ind, ep->me_ind, ep->me_tid, ep->me_savetid, ep->me_flags); pmsg_dump(ep->me_msg, 2); } return 0; } int mb_dumpall() { struct pvmmclass *np; pvmlogerror("mb_dumpall():\n"); for (np = pvmmboxclasses->mc_link; np != pvmmboxclasses; np = np->mc_link) mb_dump(np); return 0; } /* mb_tidy() * * Task has exited. * Remove any non-sticky entries owned by it. * Remove its tid as owner for sticky entries and reset Lock. */ int mb_tidy(tid) int tid; { struct pvmmclass *np, *np2; struct pvmmentry *ep, *ep2; if (!tid) return 0; if (pvmdebmask & PDMMBOX) pvmlogprintf("mb_tidy() tid 0x%x\n", tid); for (np = pvmmboxclasses->mc_link; np != pvmmboxclasses; np = np2) { np2 = np->mc_link; for (ep = np->mc_ent->me_link; ep != np->mc_ent; ep = ep2) { ep2 = ep->me_link; if (ep->me_tid == tid) { if (ep->me_flags & PvmMboxPersistent) { ep->me_savetid = ep->me_tid; ep->me_tid = 0; } else { me_free(np, ep); if (np2->mc_rlink != np) break; } } } } return 0; } /* mb_tidy_reset() * * Task has exited during a system reset. * Remove any persistent entries owned by it, and any other * persistent entries that have already been cleared. */ int mb_tidy_reset(tid) int tid; { struct pvmmclass *np, *np2; struct pvmmentry *ep, *ep2; if (!tid) return 0; if (pvmdebmask & PDMMBOX) pvmlogprintf("mb_tidy_reset() tid 0x%x\n", tid); for (np = pvmmboxclasses->mc_link; np != pvmmboxclasses; np = np2) { np2 = np->mc_link; for (ep = np->mc_ent->me_link; ep != np->mc_ent; ep = ep2) { ep2 = ep->me_link; /* mb_tidy() & mb_tidy_reset() could be in any order... */ if ( (ep->me_flags & PvmMboxPersistent) && ( ep->me_tid == tid || (!(ep->me_tid) && ep->me_savetid == tid) ) ) { me_free(np, ep); if (np2->mc_rlink != np) break; } } } return 0; } ./pvm3/src/nmdclass.c0100644007401100000360000001310006741172464013645 0ustar kohlgopher static char rcsid[] = "$Id: nmdclass.c,v 1.4 1999/07/08 19:00:04 kohl Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * nmdclass.c * * Name-server database. * * $Log: nmdclass.c,v $ * Revision 1.4 1999/07/08 19:00:04 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.3 1997/06/25 22:09:16 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.2 1997/01/28 19:26:55 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:44:22 pvmsrc * Initial revision * * Revision 1.2 1994/06/03 20:38:19 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:26:49 manchek * Initial revision * */ #include #ifdef SYSVSTR #include #else #include #endif #include #include "pvmalloc.h" #include "listmac.h" /* * one of these for each name (class) in the database */ struct nmdcls { struct nmdcls *nc_link; /* dll of peers */ struct nmdcls *nc_rlink; char *nc_name; /* class name or 0 if list master */ struct nmdind *nc_ent; /* entries in class */ }; /* * one of these for each index (entry) in the database */ struct nmdind { struct nmdind *ni_link; /* dll of peers */ struct nmdind *ni_rlink; int ni_ind; /* index in class or -1 if master */ int ni_data; /* value */ }; /*************** ** Private ** ** ** ***************/ static char pvmtxt[1024]; /* scratch for error log */ static struct nmdcls *classes = 0; /* the database */ struct nmdind * ni_new(ind) int ind; { struct nmdind *ep; if (ep = TALLOC(1, struct nmdind, "nmdi")) { ep->ni_link = ep->ni_rlink = ep; ep->ni_data = 0; ep->ni_ind = ind; } return ep; } struct nmdcls * nc_new(name) char *name; { struct nmdcls *np; if (np = TALLOC(1, struct nmdcls, "nmdc")) { if (name) { np->nc_name = STRALLOC(name); np->nc_ent = ni_new(-1); LISTPUTBEFORE(classes, np, nc_link, nc_rlink); } else { np->nc_link = np->nc_rlink = np; np->nc_name = 0; np->nc_ent = 0; } } return np; } struct nmdcls * nc_find(name) char *name; { struct nmdcls *np; for (np = classes->nc_link; np != classes; np = np->nc_link) if (!strcmp(np->nc_name, name)) return np; return (struct nmdcls*)0; } int nmd_init() { classes = nc_new((char*)0); return 0; } int nmd_insert(name, req, data) char *name; int req; int data; { struct nmdcls *np; struct nmdind *ep, *ep2; if (!(np = nc_find(name))) np = nc_new(name); if (req >= 0) { for (ep = np->nc_ent->ni_link; ep != np->nc_ent; ep = ep->ni_link) if (ep->ni_ind >= req) break; if (ep->ni_ind == req) ep = 0; } else { req = 0; for (ep = np->nc_ent->ni_link; ep != np->nc_ent; ep = ep->ni_link) { if (ep->ni_ind != req) break; req = ep->ni_ind + 1; } } if (ep) { ep2 = ni_new(req); ep2->ni_data = data; LISTPUTBEFORE(ep, ep2, ni_link, ni_rlink); } else req = -1; return req; } int nmd_delete(name, req) char *name; int req; { struct nmdcls *np; struct nmdind *ep = 0; if (np = nc_find(name)) { if (req >= 0) { for (ep = np->nc_ent->ni_link; ep != np->nc_ent; ep = ep->ni_link) if (ep->ni_ind == req) break; if (ep == np->nc_ent) ep = 0; } } if (ep) { req = ep->ni_ind; LISTDELETE(ep, ni_link, ni_rlink); PVM_FREE(ep); if (np->nc_ent->ni_link == np->nc_ent) { LISTDELETE(np, nc_link, nc_rlink); PVM_FREE(np->nc_name); PVM_FREE(np->nc_ent); PVM_FREE(np); } } else req = -1; return req; } int nmd_lookup(name, req, datap) char *name; int req; int *datap; { struct nmdcls *np; struct nmdind *ep = 0; if (np = nc_find(name)) { if (req >= 0) { for (ep = np->nc_ent->ni_link; ep != np->nc_ent; ep = ep->ni_link) if (ep->ni_ind == req) break; } else ep = np->nc_ent->ni_link; if (ep == np->nc_ent) ep = 0; } if (ep) { req = ep->ni_ind; *datap = ep->ni_data; } else req = -1; return req; } int nmd_dump(np) struct nmdcls *np; { struct nmdind *ep; sprintf(pvmtxt, "<%s>\n", np->nc_name); pvmlogerror(pvmtxt); for (ep = np->nc_ent->ni_link; ep != np->nc_ent; ep = ep->ni_link) { sprintf(pvmtxt, "%4d: 0x%08x\n", ep->ni_ind, ep->ni_data); pvmlogerror(pvmtxt); } return 0; } int nmd_dumpall() { struct nmdcls *np; pvmlogerror("nmd_dumpall():\n"); for (np = classes->nc_link; np != classes; np = np->nc_link) nmd_dump(np); return 0; } ./pvm3/src/pkt.c0100644007401100000360000000725206741172465012653 0ustar kohlgopher static char rcsid[] = "$Id: pkt.c,v 1.4 1999/07/08 19:00:05 kohl Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pkt.c * * Packet buffers. * * $Log: pkt.c,v $ * Revision 1.4 1999/07/08 19:00:05 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.3 1997/06/27 17:32:32 pvmsrc * Updated for WIN32 header files & Authors. * * Revision 1.2 1997/01/28 19:26:56 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:44:23 pvmsrc * Initial revision * * Revision 1.3 1995/07/24 18:27:24 manchek * zero pk_cpos on create * * Revision 1.2 1994/06/03 20:38:20 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:26:49 manchek * Initial revision * */ #include #ifndef WIN32 #include #else #include "pvmwin.h" #endif #include #include "pvmalloc.h" #include "pkt.h" #include "pvmdabuf.h" #include "listmac.h" #include "bfunc.h" extern void pvmbailout(); /*************** ** Private ** ** ** ***************/ /********************* ** Pkt Functions ** ** ** *********************/ /* pk_new() * * Create a new pkt, not in a list. * If len is nonzero, len bytes are allocated as data space. * Else, the pkt has no data (is a master or will get data later). * * The following fields are uninitialized: * pk_src, pk_dst, pk_flag, pk_tag, pk_ctx, pk_enc, pk_wid, pk_crc, pk_hostd, * pk_seq, pk_ack, pk_rtv, pk_rta, pk_rto, pk_at, pk_nrt */ struct pkt * pk_new(len) int len; /* (max) buffer size or 0 */ { struct pkt *pp; if (!(pp = TALLOC(1, struct pkt, "pkt"))) goto oops; /* BZERO((char*)pp, sizeof(struct pkt)); */ if (len) { /* slave pkt */ if (!(pp->pk_dat = pp->pk_buf = da_new(len))) { PVM_FREE(pp); goto oops; } pp->pk_max = len; pp->pk_len = 0; pp->pk_link = pp->pk_rlink = 0; } else { /* master */ pp->pk_dat = pp->pk_buf = 0; pp->pk_link = pp->pk_rlink = pp; } pp->pk_cpos = 0; pp->pk_tlink = pp->pk_trlink = 0; return pp; oops: pvmlogerror("pk_new() can't get memory\n"); pvmbailout(0); return (struct pkt*)0; } void pk_free(pp) struct pkt *pp; { struct pkt *pp2, *pp3; if (pp->pk_buf) { /* slave pkt */ if (pp->pk_tlink) { LISTDELETE(pp, pk_tlink, pk_trlink); } da_unref(pp->pk_buf); } else { /* master pkt */ /* free all pkts in chain */ for (pp2 = pp->pk_link; pp2 != pp; pp2 = pp3) { pp3 = pp2->pk_link; LISTDELETE(pp2, pk_link, pk_rlink); pk_free(pp2); } } PVM_FREE(pp); } ./pvm3/src/pmsg.c0100644007401100000360000016345507240353446013026 0ustar kohlgopher static char rcsid[] = "$Id: pmsg.c,v 1.17 2001/02/07 23:15:50 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pmsg.c * * Libpvm and pvmd message descriptors * * $Log: pmsg.c,v $ * Revision 1.17 2001/02/07 23:15:50 pvmsrc * 2nd Half of CYGWIN Check-ins... * (Spanker=kohl) * * Revision 1.16 2001/02/06 22:26:57 pvmsrc * Added handling for -DUSE_XDR_LONGLONG. * - for Alphas with broken XDR... * (Spanker=kohl) * * Revision 1.15 2000/02/16 21:59:48 pvmsrc * Fixed up #include stuff... * - use for IMA_TITN... * - #include before any NEEDMENDIAN #includes... * (Spanker=kohl) * * Revision 1.14 2000/02/11 20:42:09 pvmsrc * Added support for rare Strongarm float byte order to fbol()... * - hope this doesn't break anything else!!! * - submitted by Alexander Schulz . * (Spanker=kohl) * * Revision 1.13 1999/07/08 19:00:05 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.12 1998/11/20 20:06:34 pvmsrc * Changes so that win32 will compile & build. Also, common * Changes so that compiles & builds on NT. Also * common source on win32 & unix. * (spanker=sscott) * * Revision 1.11 1998/03/10 20:32:31 pvmsrc * Fixed tracing bogusness in struct timeval on 64-bit arches... * - need to cast to (int) before packing, else could crop off usecs... * (Spanker=kohl) * * Revision 1.10 1998/02/24 15:36:28 pvmsrc * Oops... leftover typo from umbuf -> pmsg renaming way back when. * - UB_DIFFNODE -> MM_DIFFNODE for IMA_CSPP. * (Spanker=kohl) * * Revision 1.9 1997/11/04 23:21:40 pvmsrc * Added SYSVSTR stuff. * (Spanker=kohl) * * Revision 1.8 1997/08/25 21:47:13 pvmsrc * Fixed pvm_setsbuf() problem with user-defined trace events. * - setsbuf was re-calling enc_trc_init(), pushing second header. * - gutted enc_trc_init() -> extracted into new enc_trc_hdr() routine * that pvm_mkbuf() calls ONCE... * (Spanker=kohl) * * Revision 1.7 1997/06/27 17:32:33 pvmsrc * Updated for WIN32 header files & Authors. * * Revision 1.6 1997/04/30 21:32:14 pvmsrc * SGI Compiler Warning Cleanup. * - fixed up return codes for trace message packing stuff. * * Revision 1.5 1997/04/09 14:40:32 pvmsrc * PVM patches from the base 3.3.10 to 3.3.11 versions where applicable. * Originals by Bob Manchek. Altered by Graham Fagg where required. * * Fixes bogus XDR en/decoding when passing short values. * Original patch was meant for lpvmpack.c but code is now in pmsg.c * * Revision 1.4 1997/01/28 19:26:57 pvmsrc * New Copyright Notice & Authors. * * Revision 1.3 1996/10/25 13:57:32 pvmsrc * Replaced old #includes for protocol headers: * - , "ddpro.h", "tdpro.h" * With #include of new combined header: * - * * Revision 1.2 1996/10/24 22:09:21 pvmsrc * Moved #include "global.h" below other #include's for typing. * Added #include & new "lpvm.h" for tracing & libpvm globals. * Added new user-defined trace event packing encoders: * - new enc_trc_init(), enc_trc_*() routines. * - new dec_trc_init(), dec_trc_*() routines. * - added new trace encoding vector in struct encvec encoders[], * with new selection in pmsg_setenc() for enc = 4 from * 0x40000000 for user-defined tracing. * * Revision 1.1 1996/09/23 23:44:26 pvmsrc * Initial revision * * */ #include #ifdef NEEDMENDIAN #include #include #endif #ifdef NEEDENDIAN #include #endif #ifdef NEEDSENDIAN #include #endif #include #if defined(WIN32) || defined(CYGWIN) #include "..\xdr\types.h" #include "..\xdr\xdr.h" #else #include #include #endif #ifdef SYSVSTR #include #else #include #endif #include #include "pvmalloc.h" #include "pvmfrag.h" #include "pmsg.h" #include "listmac.h" #include "bfunc.h" #include "lpvm.h" #include #include "global.h" /*************** ** Globals ** ** ** ***************/ /*************** ** Private ** ** ** ***************/ #ifdef CLUMP_ALLOC #ifndef PMSG_CLUMP #define PMSG_CLUMP 50 #endif static struct pmsg freepmsgs; /* cache of pmsgs */ static int numpmsgs = 0; #endif /**************************** * Generate data signature * * * ****************************/ static int ibol(o, p, n) int o; char *p; int n; { int i, j; if (p[0] == 0) { i = 0; /* ll */ } else if (p[0] == n - 1) { i = 3; /* hh */ } else if (p[0] == n / 2) { i = 2; /* hl */ } else if (p[0] == n / 2 - 1) { i = 1; /* lh */ } else { fprintf(stderr, "can't generate signature for my integer byte order\n"); abort(); } j = ffs(n) - 1; /* printf(".%d%d.%d%d%d", (i & 2) ? 1 : 0, (i & 1) ? 1 : 0, (j & 4) ? 1 : 0, (j & 2) ? 1 : 0, (j & 1) ? 1 : 0); */ return ((i << 3) | j) << o; } /* * (float)1.0 = * IEEE single ll 00 00 80 3f * IEEE double ll 00 00 00 00 00 00 f0 3f * IEEE single hh 3f 80 00 00 * IEEE double hh 3f f0 00 00 00 00 00 00 * CRAY (hh) 40 01 80 00 00 00 00 00 * Convex s (hh) 40 80 00 00 * Convex d (hh) 40 10 00 00 00 00 00 00 * IBM370 s * IBM370 d * VAX xxxx? */ struct floatsig { int length; unsigned char *bytes; char *name; }; /* * signatures for float = 1.0 in hh byte order, all formats */ static unsigned char fs1[] = { 0x3f, 0x80, 0x00, 0x00 }; static unsigned char fs2[] = { 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static unsigned char fs4[] = { 0x40, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 }; static unsigned char fs5[] = { 0x40, 0x80, 0x00, 0x00 }; static unsigned char fs6[] = { 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static struct floatsig thesigs[] = { { 0, 0, "UNKNOWN" }, { 4, fs1, "IEEE_single" }, { 8, fs2, "IEEE_double" }, { 0, 0, "UNDEFINED" }, { 8, fs4, "Cray" }, { 4, fs5, "Convex_single" }, { 8, fs6, "Convex_double" }, { 0, 0, "UNDEFINED" }, { 0, 0, "UNDEFINED" }, { 0, 0, "UNDEFINED" }, { 0, 0, "UNDEFINED" }, { 0, 0, "UNDEFINED" }, { 0, 0, "UNDEFINED" }, { 0, 0, "UNDEFINED" }, { 0, 0, "UNDEFINED" }, { 0, 0, "UNDEFINED" }, }; static int fbol(o, p, n) int o; unsigned char *p; int n; { int i, j; for (i = 0; i < 16; i++) { if (thesigs[i].length == n) { for (j = 0; j < n; j++) if (p[j] != thesigs[i].bytes[j]) break; if (j == n) return ((3 << 4) | i) << o; for (j = 0; j < n; j++) if (p[n - 1 - j] != thesigs[i].bytes[j]) break; if (j == n) return i << o; /* weird float byte order for Strongarm?! */ /* submitted Alexander Schulz */ for (j = 0; j < n; j++) if (p[(((j/4)*8)+3)-j] != thesigs[i].bytes[j]) break; if (j == n) return ((2 << 4) | i) << o; } } fprintf(stderr, "can't generate signature for my float byte order\n"); abort(); return 0; } /* pvm_getdsig() * * Return data signature for executable, describing representations * of integers and floats. * * Bits: * 0:2 short int size * 3:4 short int byte order * 5:7 int size * 8:9 int byte order * 10:12 long int size * 13:14 long int byte order * 15:18 float format * 19:20 float byte order * 21:24 double float format * 25:26 double float byte order * 27:31 0 * * Sizes are 2 ** (0..7) bytes * Byte order specifies overall order and half-folding: * 00 Little endian (e.g. 0 1 2 3) * 01 Little, but half-swapped (1 0 3 2 or 3 2 1 0 7 6 5 4) * 10 Big, but half swapped (2 3 0 1 or 4 5 6 7 0 1 2 3) * 11 Big endian (3 2 1 0) */ int pvmgetdsig() { static int myfmt = -1; short i0; int i1; long i2; float f0; double f1; int i, j; int fmt; if (myfmt != -1) return myfmt; fmt = 0; i0 = 0; for (i = 0; i < sizeof(i0); i++) i0 += (short)i << (i * 8); fmt |= ibol(0, (char *) &i0, (int) sizeof(i0)); i1 = 0; for (i = 0; i < sizeof(i1); i++) i1 += (int)i << (i * 8); fmt |= ibol(5, (char *) &i1, (int) sizeof(i1)); i2 = 0; for (i = 0; i < sizeof(i2); i++) i2 += (long)i << (i * 8); fmt |= ibol(10, (char *) &i2, (int) sizeof(i2)); f0 = 1.0; fmt |= fbol(15, (unsigned char *) &f0, (int) sizeof(f0)); f1 = 1.0; fmt |= fbol(21, (unsigned char *) &f1, (int) sizeof(f1)); myfmt = fmt; return fmt; } /**************************** ** Message manipulation ** ** ** ****************************/ static struct pmsg * pmsg_get() { struct pmsg *mp; int n; #ifdef CLUMP_ALLOC if (numpmsgs == 0) { freepmsgs.m_link = freepmsgs.m_rlink = &freepmsgs; if (!(mp = TALLOC(PMSG_CLUMP, struct pmsg, "pmsgs"))) return (struct pmsg *)0; for (n = PMSG_CLUMP; n-- > 0; ) { LISTPUTBEFORE(&freepmsgs, mp, m_link, m_rlink); mp++; } numpmsgs = PMSG_CLUMP; } numpmsgs--; mp = freepmsgs.m_link; LISTDELETE(mp, m_link, m_rlink); #else mp = TALLOC(1, struct pmsg, "pmsg"); #endif return mp; } static void pmsg_put(mp) struct pmsg *mp; { #ifdef CLUMP_ALLOC if (numpmsgs == 0) freepmsgs.m_link = freepmsgs.m_rlink = &freepmsgs; LISTPUTBEFORE(&freepmsgs, mp, m_link, m_rlink); numpmsgs++; #else PVM_FREE(mp); #endif } /* pmsg_new() * * Create a new message. * Returns pointer to message struct or NULL if no memory available. */ struct pmsg * pmsg_new(master) int master; /* true if a master (no data) node */ { struct pmsg *mp; if (!(mp = pmsg_get())) goto fail; mp->m_ref = 1; if (master) { mp->m_link = mp->m_rlink = mp; mp->m_frag = 0; } else { mp->m_link = mp->m_rlink = 0; if (!(mp->m_frag = fr_new(0))) { PVM_FREE(mp); goto fail; } } mp->m_codef = 0; mp->m_cfrag = 0; mp->m_mid = 0; mp->m_len = 0; mp->m_ctx = 0; mp->m_tag = 0; mp->m_wid = 0; mp->m_src = 0; mp->m_dst = 0; mp->m_enc = 0; mp->m_flag = 0; mp->m_cpos = 0; mp->m_crc = 0; return mp; fail: return (struct pmsg *)0; } /* pmsg_free() * * Free a message or list of messages. If m_frag is nonzero, this is * a slave node; unlink and free it and its frag list. Else, it's * a master node; free all slave nodes too. */ static void pmsg_free(mp) struct pmsg *mp; { if (mp->m_frag) { /* slave message */ if (mp->m_link && mp->m_rlink) { LISTDELETE(mp, m_link, m_rlink); } fr_unref(mp->m_frag); } else { /* master */ while (mp->m_link != mp) pmsg_free(mp->m_link); } pmsg_put(mp); } /* pmsg_unref() * * Decrement message ref count, and free message if ref count reaches 0. */ void pmsg_unref(mp) struct pmsg *mp; { if (--mp->m_ref < 1) pmsg_free(mp); } /* pmsg_extend() * * Add a new empty fragment to the end of a message. */ int pmsg_extend(mp) struct pmsg *mp; { struct frag *fp; if (fp = fr_new(pvmfrgsiz)) { fp->fr_dat += MAXHDR; LISTPUTBEFORE(mp->m_frag, fp, fr_link, fr_rlink); return 0; } return PvmNoMem; } /* pmsg_decmore() * * Step to the next fragment to unpack. */ int pmsg_decmore(mp) struct pmsg *mp; { #if 0 mp->m_cpos = 0; if (mp->m_cfrag == mp->m_frag) /* no message left */ return PvmNoData; mp->m_cfrag = mp->m_cfrag->fr_link; if (mp->m_cfrag == mp->m_frag) return PvmNoData; return 0; #endif mp->m_cpos = 0; if (mp->m_cfrag == mp->m_frag) /* no message left */ return PvmNoData; while ((mp->m_cfrag = mp->m_cfrag->fr_link) != mp->m_frag) if (mp->m_cfrag->fr_len > 0) break; if (mp->m_cfrag == mp->m_frag) return PvmNoData; return 0; } /* bytepk() * * Insert a stream of bytes into message. Allocate more fragments as * necessary. * Returns 0 else PvmNoMem if malloc fails. */ static int bytepk(mp, cp, num, siz, lnc) struct pmsg *mp; char *cp; /* base of data */ int num; /* num of chunks */ int siz; /* size of chunk */ int lnc; /* lead to next chunk */ { struct frag *fp; /* working frag */ int togo; /* bytes left in chunk */ int r; /* bytes (space) left in frag */ if (siz == lnc) { /* if contiguous, treat as single chunk */ lnc = (siz *= num); num = 1; } lnc -= siz; /* now bytes between chunks */ while (num-- > 0) { /* copy chunks until done */ for (togo = siz; togo > 0; ) { fp = mp->m_frag->fr_rlink; r = fp->fr_max - (fp->fr_dat - fp->fr_buf) - fp->fr_len; if (togo <= r) { /* space in frag for entire chunk */ BCOPY(cp, fp->fr_dat + fp->fr_len, togo); fp->fr_len += togo; cp += togo; togo = 0; } else { if (r > 0) { /* space for part of chunk */ BCOPY(cp, fp->fr_dat + fp->fr_len, r); fp->fr_len += r; togo -= r; cp += r; } else { /* no space, add new frag */ if (r = pmsg_extend(mp)) return r; } } } cp += lnc; } return 0; } /* byteupk() * * Extract bytes from message, continuing to new fragments as necessary. * Returns 0 else PvmNoData if end of message reached early. */ #ifdef IMA_CSPP static void pre_bcopy(unsigned int s1, unsigned int s2, int n); #endif static int byteupk(mp, cp, num, siz, lnc) struct pmsg *mp; char *cp; /* base of data */ int num; /* num of chunks */ int siz; /* size of chunk */ int lnc; /* lead to next chunk */ { struct frag *fp; /* working frag */ int togo; /* bytes left in chunk */ int r; /* bytes (data) left in frag */ #ifdef IMA_CSPP int diff_node = mp->m_flag & MM_DIFFNODE; #endif if (siz == lnc) { /* if contiguous, treat as single chunk */ lnc = (siz *= num); num = 1; } lnc -= siz; /* now bytes between chunks */ while (num-- > 0) { /* copy chunks until done */ for (togo = siz; togo > 0; ) { fp = mp->m_cfrag; r = fp->fr_len - mp->m_cpos; if (togo <= r) { /* frag contains rest of chunk */ #ifdef IMA_CSPP fp->fr_num_unpacked += togo; if (diff_node) { pre_bcopy((unsigned int)(fp->fr_dat + mp->m_cpos), (unsigned int)cp, togo); } else #endif BCOPY(fp->fr_dat + mp->m_cpos, cp, togo); mp->m_cpos += togo; cp += togo; togo = 0; } else { if (r > 0) { /* frag contains part of chunk */ #ifdef IMA_CSPP fp->fr_num_unpacked += r; if (diff_node) { pre_bcopy((unsigned int)(fp->fr_dat + mp->m_cpos), (unsigned int)cp, r); } else #endif BCOPY(fp->fr_dat + mp->m_cpos, cp, r); mp->m_cpos += r; togo -= r; cp += r; } else { /* no space, add new frag */ if (r = pmsg_decmore(mp)) return r; } } } cp += lnc; } return 0; } /*************************** ** Raw-format encoders ** ** ** ***************************/ /* enc_raw_init() * * Initialize a message buffer to pack raw data. */ static int enc_raw_init(mp) struct pmsg *mp; { if (!(mp->m_flag & MM_PACK)) { mp->m_flag &= ~MM_UPACK; mp->m_flag |= MM_PACK; if (mp->m_frag->fr_link == mp->m_frag) return pmsg_extend(mp); } return 0; } /* dec_raw_init() * * Initialize a message buffer to unpack raw data. */ static int dec_raw_init(mp) struct pmsg *mp; { if (!(mp->m_flag & MM_UPACK)) { mp->m_flag &= ~MM_PACK; mp->m_flag |= MM_UPACK; mp->m_cfrag = mp->m_frag->fr_link; mp->m_cpos = 0; } return 0; } /* enc_raw_any() * * Encode any data type into a raw format message buffer. */ static int enc_raw_any(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { return bytepk(mp, (char*)vp, cnt, siz, std * siz); } /* dec_raw_any() * * Decode any data type from a raw format message buffer. */ static int dec_raw_any(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { return byteupk(mp, (char*)vp, cnt, siz, std * siz); } /*************************** ** XDR-format encoders ** ** ** ***************************/ #ifdef FAKEXDRFLOAT /* ** These two are missing on some machines. */ static int xdr_float(xdrp, fp) XDR *xdrp; float *fp; { return xdr_long(xdrp, (long*)fp); } static int xdr_double(xdrp, dp) XDR *xdrp; double *dp; { return xdr_long(xdrp, (long*)dp + 1) && xdr_long(xdrp, (long*)dp); } #endif/*FAKEXDRFLOAT*/ #if defined(BOGUSXDR) /* ** Encoders for machines without XDR routines but with XDR-format ** data. */ static int enc_xdr_init(mp) struct pmsg *mp; { return enc_raw_init(mp); } static int enc_xdr_byte(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { struct frag *fp; int cc; fp = mp->m_frag->fr_rlink; if (cc = bytepk(mp, (char*)vp, cnt, siz, std * siz)) return cc; fp->fr_len = (fp->fr_len + 3) & ~3; return 0; } static int enc_xdr_short(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register short *np; register char *cp; char buf[4]; int cc = 0; for (np = (short*)vp; cnt-- > 0; np += std) { cp = (char *)np; buf[3] = *cp; buf[2] = *(cp+1); if (cc = bytepk(mp, buf, 4, 1, 1)) return cc; } return 0; } static int enc_xdr_int(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register int *np; register char *cp; char buf[4]; int cc = 0; for (np = (int *)vp; cnt-- > 0; np += std) { cp = (char *)np; buf[3] = *cp; buf[2] = *(cp+1); buf[1] = *(cp+2); buf[0] = *(cp+3); if (cc = bytepk(mp, buf, 4, 1, 1)) return cc; } return 0; } static int enc_xdr_long(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register long *np; register char *cp; char buf[8]; int cc = 0; for (np = (long *)vp; cnt-- > 0; np += std) { cp = (char *)np; #ifdef USE_XDR_LONGLONG buf[7] = *cp; buf[6] = *(cp+1); buf[5] = *(cp+2); buf[4] = *(cp+3); buf[3] = *(cp+4); buf[2] = *(cp+5); buf[1] = *(cp+6); buf[0] = *(cp+7); #else buf[3] = *cp; buf[2] = *(cp+1); buf[1] = *(cp+2); buf[0] = *(cp+3); #endif if (cc = bytepk(mp, buf, #ifdef USE_XDR_LONGLONG 8, #else 4, #endif 1, 1)) return cc; } return 0; } static int enc_xdr_float(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register float *np; register char *cp; char buf[4]; int cc = 0; for (np = (float *)vp; cnt-- > 0; np += std) { cp = (char *)np; buf[3] = *cp; buf[2] = *(cp+1); buf[1] = *(cp+2); buf[0] = *(cp+3); if (cc = bytepk(mp, buf, 4, 1, 1)) return cc; } return 0; } static int enc_xdr_double(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register double *np; register char *cp; char buf[8]; int cc = 0; for (np = (double *)vp; cnt-- > 0; np += std) { cp = (char *)np; buf[7] = *cp; buf[6] = *(cp+1); buf[5] = *(cp+2); buf[4] = *(cp+3); buf[3] = *(cp+4); buf[2] = *(cp+5); buf[1] = *(cp+6); buf[0] = *(cp+7); if (cc = bytepk(mp, buf, 8, 1, 1)) return cc; } return 0; } typedef struct {float r, i;} complex; typedef struct {double r, i;} dcplx; static int enc_xdr_cplx(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register complex *np; register char *cp; char buf[8]; int cc = 0; for (np = (complex *)vp; cnt-- > 0; np += std) { cp = (char *)np; buf[3] = *cp; buf[2] = *(cp+1); buf[1] = *(cp+2); buf[0] = *(cp+3); buf[7] = *(cp+4); buf[6] = *(cp+5); buf[5] = *(cp+6); buf[4] = *(cp+7); if (cc = bytepk(mp, buf, 8, 1, 1)) return cc; } return 0; } static int enc_xdr_dcplx(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register dcplx *np; register char *cp; char buf[16]; int cc = 0; for (np = (dcplx *)vp; cnt-- > 0; np += std) { cp = (char *)np; buf[7] = *cp; buf[6] = *(cp+1); buf[5] = *(cp+2); buf[4] = *(cp+3); buf[3] = *(cp+4); buf[2] = *(cp+5); buf[1] = *(cp+6); buf[0] = *(cp+7); buf[15] = *(cp+8); buf[14] = *(cp+9); buf[13] = *(cp+10); buf[12] = *(cp+11); buf[11] = *(cp+12); buf[10] = *(cp+13); buf[9] = *(cp+14); buf[8] = *(cp+15); if (cc = bytepk(mp, buf, 16, 1, 1)) return cc; } return 0; } static int dec_xdr_init(mp) struct pmsg *mp; { return dec_raw_init(mp); } static int dec_xdr_byte(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { int cc; if (cc = byteupk(mp, (char*)vp, cnt, siz, std * siz)) return cc; mp->m_cpos = (mp->m_cpos + 3) & ~3; return 0; } static int dec_xdr_short(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register short *np; register char *cp; char buf[4]; int cc = 0; for (np = (short*)vp; cnt-- > 0; np += std) { if (cc = byteupk(mp, buf, 4, 1, 1)) return cc; cp = (char *)np; *cp = buf[3]; *(cp+1) = buf[2]; } return 0; } static int dec_xdr_int(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register int *np; register char *cp; char buf[4]; int cc = 0; for (np = (int *)vp; cnt-- > 0; np += std) { if (cc = byteupk(mp, buf, 4, 1, 1)) return cc; cp = (char *)np; *cp = buf[3]; *(cp+1) = buf[2]; *(cp+2) = buf[1]; *(cp+3) = buf[0]; } return 0; } static int dec_xdr_long(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register long *np; register char *cp; char buf[8]; int cc = 0; for (np = (long *)vp; cnt-- > 0; np += std) { if (cc = byteupk(mp, buf, #ifdef USE_XDR_LONGLONG 8, #else 4, #endif 1, 1)) return cc; cp = (char *)np; #ifdef USE_XDR_LONGLONG *cp = buf[7]; *(cp+1) = buf[6]; *(cp+2) = buf[5]; *(cp+3) = buf[4]; *(cp+4) = buf[3]; *(cp+5) = buf[2]; *(cp+6) = buf[1]; *(cp+7) = buf[0]; #else *cp = buf[3]; *(cp+1) = buf[2]; *(cp+2) = buf[1]; *(cp+3) = buf[0]; #endif } return 0; } static int dec_xdr_float(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register float *np; register char *cp; char buf[4]; int cc = 0; for (np = (float *)vp; cnt-- > 0; np += std) { if (cc = byteupk(mp, buf, 4, 1, 1)) return cc; cp = (char *)np; *cp = buf[3]; *(cp+1) = buf[2]; *(cp+2) = buf[1]; *(cp+3) = buf[0]; } return 0; } static int dec_xdr_double(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register double *np; register char *cp; char buf[8]; int cc = 0; for (np = (double *)vp; cnt-- > 0; np += std) { if (cc = byteupk(mp, buf, 8, 1, 1)) return cc; cp = (char *)np; *cp = buf[7]; *(cp+1) = buf[6]; *(cp+2) = buf[5]; *(cp+3) = buf[4]; *(cp+4) = buf[3]; *(cp+5) = buf[2]; *(cp+6) = buf[1]; *(cp+7) = buf[0]; } return 0; } static int dec_xdr_cplx(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register complex *np; register char *cp; char buf[8]; int cc = 0; for (np = (complex *)vp; cnt-- > 0; np += std) { if (cc = byteupk(mp, buf, 8, 1, 1)) return cc; cp = (char *)np; *cp = buf[3]; *(cp+1) = buf[2]; *(cp+2) = buf[1]; *(cp+3) = buf[0]; *(cp+4) = buf[7]; *(cp+5) = buf[6]; *(cp+6) = buf[5]; *(cp+7) = buf[4]; } return 0; } static int dec_xdr_dcplx(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register dcplx *np; register char *cp; char buf[16]; int cc = 0; for (np = (dcplx *)vp; cnt-- > 0; np += std) { if (cc = byteupk(mp, buf, 16, 1, 1)) return cc; cp = (char *)np; *cp = buf[7]; *(cp+1) = buf[6]; *(cp+2) = buf[5]; *(cp+3) = buf[4]; *(cp+4) = buf[3]; *(cp+5) = buf[2]; *(cp+6) = buf[1]; *(cp+7) = buf[0]; *(cp+8) = buf[15]; *(cp+9) = buf[14]; *(cp+10) = buf[13]; *(cp+11) = buf[12]; *(cp+12) = buf[11]; *(cp+13) = buf[10]; *(cp+14) = buf[9]; *(cp+15) = buf[8]; } return 0; } #else /*BOGUSXDR*/ /* ** These are the normal XDR encoders for machines with XDR functions. */ /* enc_xdr_init() * * Initialize a message buffer to pack XDR format data */ static int enc_xdr_init(mp) struct pmsg *mp; { struct frag *fp; int cc; if (!(mp->m_flag & MM_PACK)) { mp->m_flag &= ~MM_UPACK; mp->m_flag |= MM_PACK; if ((fp = mp->m_frag->fr_link) == mp->m_frag) { if (cc = pmsg_extend(mp)) return cc; fp = fp->fr_link; } xdrmem_create(&mp->m_xdr, fp->fr_dat, (unsigned)(fp->fr_max - (fp->fr_dat - fp->fr_buf)), XDR_ENCODE); } return 0; } /* enc_xdr_step() * * Add a new fragment to an XDR format message */ static int enc_xdr_step(mp) struct pmsg *mp; { struct frag *fp; int cc; if (cc = pmsg_extend(mp)) return cc; fp = mp->m_frag->fr_rlink; xdrmem_create(&mp->m_xdr, fp->fr_dat, (unsigned)(fp->fr_max - (fp->fr_dat - fp->fr_buf)), XDR_ENCODE); return 0; } static int enc_xdr_byte(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { struct frag *fp; int cc; fp = mp->m_frag->fr_rlink; if (cc = bytepk(mp, (char*)vp, cnt, 1, std)) return cc; if (fp != mp->m_frag->fr_rlink) { fp = mp->m_frag->fr_rlink; xdrmem_create(&mp->m_xdr, fp->fr_dat, (unsigned)(fp->fr_max - (fp->fr_dat - fp->fr_buf)), XDR_ENCODE); } fp->fr_len = (fp->fr_len + 3) & ~3; xdr_setpos(&mp->m_xdr, fp->fr_len); return 0; } static int enc_xdr_short(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register short *np; int cc = 0; for (np = (short*)vp; cnt-- > 0; np += std) if (!xdr_short(&mp->m_xdr, np)) { mp->m_frag->fr_rlink->fr_len = xdr_getpos(&mp->m_xdr); if (cc = enc_xdr_step(mp)) break; else if (!xdr_short(&mp->m_xdr, np)) { cc = PvmNoMem; break; } } mp->m_frag->fr_rlink->fr_len = xdr_getpos(&mp->m_xdr); return cc; } static int enc_xdr_int(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register int *np; int cc = 0; for (np = (int*)vp; cnt-- > 0; np += std) if (!xdr_int(&mp->m_xdr, np)) { mp->m_frag->fr_rlink->fr_len = xdr_getpos(&mp->m_xdr); if (cc = enc_xdr_step(mp)) break; else if (!xdr_int(&mp->m_xdr, np)) { cc = PvmNoMem; break; } } mp->m_frag->fr_rlink->fr_len = xdr_getpos(&mp->m_xdr); return cc; } static int enc_xdr_long(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register long *np; int cc = 0; for (np = (long*)vp; cnt-- > 0; np += std) #ifdef USE_XDR_LONGLONG if (!xdr_longlong_t(&mp->m_xdr, np)) #else if (!xdr_long(&mp->m_xdr, np)) #endif { #ifdef USE_XDR_LONGLONG if ((*np & ~(long)0x7fffffffffffffff) && (*np & ~(long)0x7fffffffffffffff) != ~(long)0x7fffffffffffffff) #else if ((*np & ~(long)0x7fffffff) && (*np & ~(long)0x7fffffff) != ~(long)0x7fffffff) #endif { cc = PvmOverflow; break; } mp->m_frag->fr_rlink->fr_len = xdr_getpos(&mp->m_xdr); if (cc = enc_xdr_step(mp)) break; else #ifdef USE_XDR_LONGLONG if (!xdr_longlong_t(&mp->m_xdr, np)) #else if (!xdr_long(&mp->m_xdr, np)) #endif { cc = PvmNoMem; break; } } mp->m_frag->fr_rlink->fr_len = xdr_getpos(&mp->m_xdr); return cc; } static int enc_xdr_ulong(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register unsigned long *np; int cc = 0; for (np = (unsigned long*)vp; cnt-- > 0; np += std) #ifdef USE_XDR_LONGLONG if (!xdr_u_longlong_t(&mp->m_xdr, np)) #else if (!xdr_u_long(&mp->m_xdr, np)) #endif { #ifdef USE_XDR_LONGLONG if (*np & ~(long)0xffffffffffffffff) #else if (*np & ~(long)0xffffffff) #endif { cc = PvmOverflow; break; } mp->m_frag->fr_rlink->fr_len = xdr_getpos(&mp->m_xdr); if (cc = enc_xdr_step(mp)) break; else #ifdef USE_XDR_LONGLONG if (!xdr_u_longlong_t(&mp->m_xdr, np)) #else if (!xdr_u_long(&mp->m_xdr, np)) #endif { cc = PvmNoMem; break; } } mp->m_frag->fr_rlink->fr_len = xdr_getpos(&mp->m_xdr); return cc; } static int enc_xdr_float(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register float *fp; int cc = 0; for (fp = (float*)vp; cnt-- > 0; fp += std) if (!xdr_float(&mp->m_xdr, fp)) { mp->m_frag->fr_rlink->fr_len = xdr_getpos(&mp->m_xdr); if (cc = enc_xdr_step(mp)) break; else if (!xdr_float(&mp->m_xdr, fp)) { cc = PvmNoMem; break; } } mp->m_frag->fr_rlink->fr_len = xdr_getpos(&mp->m_xdr); return cc; } static int enc_xdr_double(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register double *dp; int cc = 0; int n; for (dp = (double*)vp; cnt-- > 0; dp += std) { if (!xdr_double(&mp->m_xdr, dp)) { if (cc = enc_xdr_step(mp)) break; else if (!xdr_double(&mp->m_xdr, dp)) { cc = PvmNoMem; break; } } mp->m_frag->fr_rlink->fr_len = xdr_getpos(&mp->m_xdr); } return cc; } static int enc_xdr_cplx(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register float *xp; int cc = 0; std = std * 2 - 1; for (xp = (float*)vp; cnt-- > 0; xp += std) { if (!xdr_float(&mp->m_xdr, xp)) { mp->m_frag->fr_rlink->fr_len = xdr_getpos(&mp->m_xdr); if (cc = enc_xdr_step(mp)) break; else if (!xdr_float(&mp->m_xdr, xp)) { cc = PvmNoMem; break; } } xp++; if (!xdr_float(&mp->m_xdr, xp)) { mp->m_frag->fr_rlink->fr_len = xdr_getpos(&mp->m_xdr); if (cc = enc_xdr_step(mp)) break; else if (!xdr_float(&mp->m_xdr, xp)) { cc = PvmNoMem; break; } } } mp->m_frag->fr_rlink->fr_len = xdr_getpos(&mp->m_xdr); return cc; } static int enc_xdr_dcplx(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register double *zp; int cc = 0; std = std * 2 - 1; for (zp = (double*)vp; cnt-- > 0; zp += std) { if (!xdr_double(&mp->m_xdr, zp)) { if (cc = enc_xdr_step(mp)) break; else if (!xdr_double(&mp->m_xdr, zp)) { cc = PvmNoMem; break; } } mp->m_frag->fr_rlink->fr_len = xdr_getpos(&mp->m_xdr); zp++; if (!xdr_double(&mp->m_xdr, zp)) { if (cc = enc_xdr_step(mp)) break; else if (!xdr_double(&mp->m_xdr, zp)) { cc = PvmNoMem; break; } } mp->m_frag->fr_rlink->fr_len = xdr_getpos(&mp->m_xdr); } return cc; } /* dec_xdr_init() * * Initialize a message buffer to unpack XDR format data. */ static int dec_xdr_init(mp) struct pmsg *mp; { struct frag *fp = mp->m_frag->fr_link; if (!(mp->m_flag & MM_UPACK)) { mp->m_flag &= ~MM_PACK; mp->m_flag |= MM_UPACK; mp->m_cfrag = fp; mp->m_cpos = 0; xdrmem_create(&mp->m_xdr, fp->fr_dat, (unsigned)(fp->fr_len), XDR_DECODE); } return 0; } /* dec_xdr_step() * * Step to the next fragment of an XDR format message. * * The current fragment might not be fully consumed - messages are * refragmented on 4-byte boundaries, but XDR 'atomic' sizes for * us are 4 bytes and 8 bytes (doubles). * If the next fragment exists, copy the remaining bytes to the head * of its buffer and continue unpacking. * XXX 1. There might not be enough headroom (unlikely). * XXX 2. If we share databufs we can't modify them (maybe?). */ static int dec_xdr_step(mp) struct pmsg *mp; { struct frag *fp; int cc; int l; char *p; if (mp->m_cpos != mp->m_cfrag->fr_len) { p = mp->m_cfrag->fr_dat + mp->m_cpos; l = mp->m_cfrag->fr_len - mp->m_cpos; if (cc = pmsg_decmore(mp)) return cc; fp = mp->m_cfrag; if (fp->fr_dat - fp->fr_buf < l) { pvmlogerror("aaugh, no space for fixup, kill me\n"); return PvmBadMsg; } else { /* pvmlogprintf("fragment has %d bytes left, doing fixup\n", l); */ fp->fr_dat -= l; fp->fr_len += l; BCOPY(p, fp->fr_dat, l); } } else { if (cc = pmsg_decmore(mp)) return cc; fp = mp->m_cfrag; } xdrmem_create(&mp->m_xdr, fp->fr_dat, (unsigned)(fp->fr_len), XDR_DECODE); return 0; } static int dec_xdr_byte(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { struct frag *fp; int cc; fp = mp->m_cfrag; if (cc = byteupk(mp, (char*)vp, cnt, 1, std)) return cc; if (fp != mp->m_cfrag) { fp = mp->m_cfrag; xdrmem_create(&mp->m_xdr, fp->fr_dat, (unsigned)(fp->fr_len), XDR_DECODE); } mp->m_cpos = (mp->m_cpos + 3) & ~3; xdr_setpos(&mp->m_xdr, mp->m_cpos); return 0; } static int dec_xdr_short(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register short *np; int cc = 0; for (np = (short*)vp; cnt-- > 0; np += std) if (!xdr_short(&mp->m_xdr, np)) { mp->m_cpos = xdr_getpos(&mp->m_xdr); if (cc = dec_xdr_step(mp)) break; else if (!xdr_short(&mp->m_xdr, np)) { cc = PvmNoData; break; } } mp->m_cpos = xdr_getpos(&mp->m_xdr); return cc; } static int dec_xdr_int(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register int *np; int cc = 0; for (np = (int*)vp; cnt-- > 0; np += std) if (!xdr_int(&mp->m_xdr, np)) { mp->m_cpos = xdr_getpos(&mp->m_xdr); if (cc = dec_xdr_step(mp)) break; else if (!xdr_int(&mp->m_xdr, np)) { cc = PvmNoData; break; } } mp->m_cpos = xdr_getpos(&mp->m_xdr); return cc; } static int dec_xdr_long(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register long *np; int cc = 0; for (np = (long*)vp; cnt-- > 0; np += std) #ifdef USE_XDR_LONGLONG if (!xdr_longlong_t(&mp->m_xdr, np)) #else if (!xdr_long(&mp->m_xdr, np)) #endif { mp->m_cpos = xdr_getpos(&mp->m_xdr); if (cc = dec_xdr_step(mp)) break; else #ifdef USE_XDR_LONGLONG if (!xdr_longlong_t(&mp->m_xdr, np)) #else if (!xdr_long(&mp->m_xdr, np)) #endif { cc = PvmNoData; break; } } mp->m_cpos = xdr_getpos(&mp->m_xdr); return cc; } static int dec_xdr_ushort(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register unsigned short *np; int cc = 0; for (np = (unsigned short*)vp; cnt-- > 0; np += std) if (!xdr_u_short(&mp->m_xdr, np)) { mp->m_cpos = xdr_getpos(&mp->m_xdr); if (cc = dec_xdr_step(mp)) break; else if (!xdr_u_short(&mp->m_xdr, np)) { cc = PvmNoData; break; } } mp->m_cpos = xdr_getpos(&mp->m_xdr); return cc; } static int dec_xdr_uint(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register unsigned int *np; int cc = 0; for (np = (unsigned int*)vp; cnt-- > 0; np += std) if (!xdr_u_int(&mp->m_xdr, np)) { mp->m_cpos = xdr_getpos(&mp->m_xdr); if (cc = dec_xdr_step(mp)) break; else if (!xdr_u_int(&mp->m_xdr, np)) { cc = PvmNoData; break; } } mp->m_cpos = xdr_getpos(&mp->m_xdr); return cc; } static int dec_xdr_ulong(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register unsigned long *np; int cc = 0; for (np = (unsigned long*)vp; cnt-- > 0; np += std) #ifdef USE_XDR_LONGLONG if (!xdr_u_longlong_t(&mp->m_xdr, np)) #else if (!xdr_u_long(&mp->m_xdr, np)) #endif { mp->m_cpos = xdr_getpos(&mp->m_xdr); if (cc = dec_xdr_step(mp)) break; else #ifdef USE_XDR_LONGLONG if (!xdr_u_longlong_t(&mp->m_xdr, np)) #else if (!xdr_u_long(&mp->m_xdr, np)) #endif { cc = PvmNoData; break; } } mp->m_cpos = xdr_getpos(&mp->m_xdr); return cc; } static int dec_xdr_float(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register float *fp; int cc = 0; for (fp = (float*)vp; cnt-- > 0; fp += std) if (!xdr_float(&mp->m_xdr, fp)) { mp->m_cpos = xdr_getpos(&mp->m_xdr); if (cc = dec_xdr_step(mp)) break; else if (!xdr_float(&mp->m_xdr, fp)) { cc = PvmNoData; break; } } mp->m_cpos = xdr_getpos(&mp->m_xdr); return cc; } static int dec_xdr_double(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register double *dp; int cc = 0; for (dp = (double*)vp; cnt-- > 0; dp += std) { if (!xdr_double(&mp->m_xdr, dp)) { if (cc = dec_xdr_step(mp)) break; else if (!xdr_double(&mp->m_xdr, dp)) { cc = PvmNoData; break; } } mp->m_cpos = xdr_getpos(&mp->m_xdr); } return cc; } static int dec_xdr_cplx(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register float *xp; int cc = 0; std = std * 2 - 1; for (xp = (float*)vp; cnt-- > 0; xp += std) { if (!xdr_float(&mp->m_xdr, xp)) { mp->m_cpos = xdr_getpos(&mp->m_xdr); if (cc = dec_xdr_step(mp)) break; else if (!xdr_float(&mp->m_xdr, xp)) { cc = PvmNoData; break; } } xp++; if (!xdr_float(&mp->m_xdr, xp)) { mp->m_cpos = xdr_getpos(&mp->m_xdr); if (cc = dec_xdr_step(mp)) break; else if (!xdr_float(&mp->m_xdr, xp)) { cc = PvmNoData; break; } } } mp->m_cpos = xdr_getpos(&mp->m_xdr); return cc; } static int dec_xdr_dcplx(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { register double *zp; int cc = 0; std = std * 2 - 1; for (zp = (double*)vp; cnt-- > 0; zp += std) { if (!xdr_double(&mp->m_xdr, zp)) { if (cc = dec_xdr_step(mp)) break; else if (!xdr_double(&mp->m_xdr, zp)) { cc = PvmNoData; break; } } mp->m_cpos = xdr_getpos(&mp->m_xdr); zp++; if (!xdr_double(&mp->m_xdr, zp)) { if (cc = dec_xdr_step(mp)) break; else if (!xdr_double(&mp->m_xdr, zp)) { cc = PvmNoData; break; } } mp->m_cpos = xdr_getpos(&mp->m_xdr); } return cc; } #endif /*BOGUSXDR*/ /************************* ** In-place encoders ** ** ** *************************/ static int enc_inp_init(mp) struct pmsg *mp; { return 0; } static int enc_inp_any(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { struct frag *fp; if (std != 1) return PvmNotImpl; if (vp && cnt && siz) { fp = fr_snew((char *)vp, cnt * siz); LISTPUTBEFORE(mp->m_frag, fp, fr_link, fr_rlink); } #if 0 if (std != 1) { if (std < 1) return PvmBadParam; fp->fr_max = fp->fr_len = siz + (cnt - 1) * std * siz; fp->fr_csz = siz; fp->fr_lnc = std * siz; fp->fr_u.spr = 1; } #endif return 0; } /********************* ** Trace encoders ** ** ** *********************/ static int enc_trc_init(mp) struct pmsg *mp; { return enc_xdr_init(mp); } int /* not static */ enc_trc_hdr(mp) struct pmsg *mp; { struct timeval timestamp; int tsec, tusec; int tmp; int cc; gettimeofday( ×tamp, (struct timezone *) 0 ); tsec = (int) timestamp.tv_sec; tusec = (int) timestamp.tv_usec; if ( (cc = enc_xdr_init(mp)) ) return( cc ); tmp = TEV_MARK_USER_EVENT_RECORD; if ((cc = enc_xdr_int(mp, (void *) &tmp, 1, 1, (int) sizeof(int)))) return( cc ); tmp = TEV_USER_DEFINED; if ((cc = enc_xdr_int(mp, (void *) &tmp, 1, 1, (int) sizeof(int)))) return( cc ); tmp = strlen( pvmtevinfo[TEV_USER_DEFINED].name ) + 1; if ((cc = enc_xdr_int(mp, (void *) &tmp, 1, 1, (int) sizeof(int)))) return( cc ); if ((cc = enc_xdr_byte(mp, (void *)(pvmtevinfo[TEV_USER_DEFINED].name), tmp, 1, 1))) return( cc ); if ((cc = enc_xdr_int(mp, (void *) &tsec, 1, 1, (int) sizeof(int)))) return( cc ); if ((cc = enc_xdr_int(mp, (void *) &tusec, 1, 1, (int) sizeof(int)))) return( cc ); return( 0 ); } int /* not static */ enc_trc_fin(mp) struct pmsg *mp; { int tmp; tmp = TEV_MARK_USER_EVENT_RECORD_END; return( enc_xdr_int(mp, (void *) &tmp, 1, 1, (int) sizeof(int)) ); } static int enc_trc_byte(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { int type; int cc; if ( cnt ) { if ( cnt == 1 ) { type = TEV_DATA_BYTE | TEV_DATA_SCALAR; if ( (cc = enc_xdr_int(mp, (void *) &type, 1, 1, (int) sizeof(int))) ) return cc; } else { type = TEV_DATA_BYTE | TEV_DATA_ARRAY; if ( (cc = enc_xdr_int(mp, (void *) &type, 1, 1, (int) sizeof(int))) ) return cc; if ( (cc = enc_xdr_int(mp, (void *) &cnt, 1, 1, (int) sizeof(int))) ) return cc; } return enc_xdr_byte(mp, vp, cnt, std, siz); } return 0; } static int enc_trc_short(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { int type; int cc; if ( cnt ) { if ( cnt == 1 ) { type = TEV_DATA_SHORT | TEV_DATA_SCALAR; if ( (cc = enc_xdr_int(mp, (void *) &type, 1, 1, (int) sizeof(int))) ) return cc; } else { type = TEV_DATA_SHORT | TEV_DATA_ARRAY; if ( (cc = enc_xdr_int(mp, (void *) &type, 1, 1, (int) sizeof(int))) ) return cc; if ( (cc = enc_xdr_int(mp, (void *) &cnt, 1, 1, (int) sizeof(int))) ) return cc; } return enc_xdr_short(mp, vp, cnt, std, siz); } return 0; } static int enc_trc_int(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { int type; int cc; if ( cnt ) { if ( cnt == 1 ) { type = TEV_DATA_INT | TEV_DATA_SCALAR; if ( (cc = enc_xdr_int(mp, (void *) &type, 1, 1, (int) sizeof(int))) ) return cc; } else { type = TEV_DATA_INT | TEV_DATA_ARRAY; if ( (cc = enc_xdr_int(mp, (void *) &type, 1, 1, (int) sizeof(int))) ) return cc; if ( (cc = enc_xdr_int(mp, (void *) &cnt, 1, 1, (int) sizeof(int))) ) return cc; } return enc_xdr_int(mp, vp, cnt, std, siz); } /* Weasel Hack to Sneak in Trace Markers, with cnt == 0... :-) */ /* Need to be able to insert markers without other data type and */ /* array size crapola - it's either this or a new pvm_pkmarker() */ /* routine and an enc_mrk for each encoding (which is more bogus).*/ else if ( vp != NULL && *((int *) vp) < 0 ) { return enc_xdr_int(mp, vp, 1, 1, (int) sizeof(int)); } return 0; } static int enc_trc_long(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { int type; int cc; if ( cnt ) { if ( cnt == 1 ) { type = TEV_DATA_LONG | TEV_DATA_SCALAR; if ( (cc = enc_xdr_int(mp, (void *) &type, 1, 1, (int) sizeof(int))) ) return cc; } else { type = TEV_DATA_LONG | TEV_DATA_ARRAY; if ( (cc = enc_xdr_int(mp, (void *) &type, 1, 1, (int) sizeof(int))) ) return cc; if ( (cc = enc_xdr_int(mp, (void *) &cnt, 1, 1, (int) sizeof(int))) ) return cc; } return enc_xdr_long(mp, vp, cnt, std, siz); } return 0; } static int enc_trc_ulong(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { int type; int cc; if ( cnt ) { if ( cnt == 1 ) { type = TEV_DATA_ULONG | TEV_DATA_SCALAR; if ( (cc = enc_xdr_int(mp, (void *) &type, 1, 1, (int) sizeof(int))) ) return cc; } else { type = TEV_DATA_ULONG | TEV_DATA_ARRAY; if ( (cc = enc_xdr_int(mp, (void *) &type, 1, 1, (int) sizeof(int))) ) return cc; if ( (cc = enc_xdr_int(mp, (void *) &cnt, 1, 1, (int) sizeof(int))) ) return cc; } #if defined(I860_NODE) /* XXX are handwritten anyhow */ return enc_xdr_long(mp, vp, cnt, std, siz); #else return enc_xdr_ulong(mp, vp, cnt, std, siz); #endif } return 0; } static int enc_trc_float(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { int type; int cc; if ( cnt ) { if ( cnt == 1 ) { type = TEV_DATA_FLOAT | TEV_DATA_SCALAR; if ( (cc = enc_xdr_int(mp, (void *) &type, 1, 1, (int) sizeof(int))) ) return cc; } else { type = TEV_DATA_FLOAT | TEV_DATA_ARRAY; if ( (cc = enc_xdr_int(mp, (void *) &type, 1, 1, (int) sizeof(int))) ) return cc; if ( (cc = enc_xdr_int(mp, (void *) &cnt, 1, 1, (int) sizeof(int))) ) return cc; } return enc_xdr_float(mp, vp, cnt, std, siz); } return 0; } static int enc_trc_double(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { int type; int cc; if ( cnt ) { if ( cnt == 1 ) { type = TEV_DATA_DOUBLE | TEV_DATA_SCALAR; if ( (cc = enc_xdr_int(mp, (void *) &type, 1, 1, (int) sizeof(int))) ) return cc; } else { type = TEV_DATA_DOUBLE | TEV_DATA_ARRAY; if ( (cc = enc_xdr_int(mp, (void *) &type, 1, 1, (int) sizeof(int))) ) return cc; if ( (cc = enc_xdr_int(mp, (void *) &cnt, 1, 1, (int) sizeof(int))) ) return cc; } return enc_xdr_double(mp, vp, cnt, std, siz); } return 0; } static int enc_trc_cplx(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { int type; int cc; if ( cnt ) { if ( cnt == 1 ) { type = TEV_DATA_CPLX | TEV_DATA_SCALAR; if ( (cc = enc_xdr_int(mp, (void *) &type, 1, 1, (int) sizeof(int))) ) return cc; } else { type = TEV_DATA_CPLX | TEV_DATA_ARRAY; if ( (cc = enc_xdr_int(mp, (void *) &type, 1, 1, (int) sizeof(int))) ) return cc; if ( (cc = enc_xdr_int(mp, (void *) &cnt, 1, 1, (int) sizeof(int))) ) return cc; } return enc_xdr_cplx(mp, vp, cnt, std, siz); } return 0; } static int enc_trc_dcplx(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { int type; int cc; if ( cnt ) { if ( cnt == 1 ) { type = TEV_DATA_DCPLX | TEV_DATA_SCALAR; if ( (cc = enc_xdr_int(mp, (void *) &type, 1, 1, (int) sizeof(int))) ) return cc; } else { type = TEV_DATA_DCPLX | TEV_DATA_ARRAY; if ( (cc = enc_xdr_int(mp, (void *) &type, 1, 1, (int) sizeof(int))) ) return cc; if ( (cc = enc_xdr_int(mp, (void *) &cnt, 1, 1, (int) sizeof(int))) ) return cc; } return enc_xdr_dcplx(mp, vp, cnt, std, siz); } return 0; } static int dec_trc_init(mp) struct pmsg *mp; { return dec_xdr_init(mp); } static int dec_trc_byte(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { return dec_xdr_byte(mp, vp, cnt, std, siz); } static int dec_trc_short(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { return dec_xdr_short(mp, vp, cnt, std, siz); } static int dec_trc_int(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { return dec_xdr_int(mp, vp, cnt, std, siz); } static int dec_trc_long(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { return dec_xdr_long(mp, vp, cnt, std, siz); } static int dec_trc_ushort(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { #if defined(I860_NODE) /* XXX are handwritten anyhow */ return dec_xdr_short(mp, vp, cnt, std, siz); #else return dec_xdr_ushort(mp, vp, cnt, std, siz); #endif } static int dec_trc_uint(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { #if defined(I860_NODE) /* XXX are handwritten anyhow */ return dec_xdr_int(mp, vp, cnt, std, siz); #else return dec_xdr_uint(mp, vp, cnt, std, siz); #endif } static int dec_trc_ulong(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { #if defined(I860_NODE) /* XXX are handwritten anyhow */ return dec_xdr_long(mp, vp, cnt, std, siz); #else return dec_xdr_ulong(mp, vp, cnt, std, siz); #endif } static int dec_trc_float(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { return dec_xdr_float(mp, vp, cnt, std, siz); } static int dec_trc_double(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { return dec_xdr_double(mp, vp, cnt, std, siz); } static int dec_trc_cplx(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { return dec_xdr_cplx(mp, vp, cnt, std, siz); } static int dec_trc_dcplx(mp, vp, cnt, std, siz) struct pmsg *mp; void *vp; int cnt, std, siz; { return dec_xdr_dcplx(mp, vp, cnt, std, siz); } /******************************************* ** Alien (can't do it) en/decoder stub ** ** ** *******************************************/ static int enc_alien() { return PvmBadMsg; } /**************************** ** Encoder switch table ** ** ** ****************************/ static struct encvec encoders[] = { { enc_raw_init, dec_raw_init, /* Raw (native) 0 */ enc_raw_any, dec_raw_any, enc_raw_any, dec_raw_any, enc_raw_any, dec_raw_any, enc_raw_any, dec_raw_any, enc_raw_any, dec_raw_any, enc_raw_any, dec_raw_any, enc_raw_any, dec_raw_any, enc_raw_any, dec_raw_any, enc_raw_any, dec_raw_any, enc_raw_any, dec_raw_any, enc_raw_any, dec_raw_any }, { enc_xdr_init, dec_xdr_init, /* XDR 1 */ enc_xdr_byte, dec_xdr_byte, enc_xdr_short, dec_xdr_short, enc_xdr_int, dec_xdr_int, enc_xdr_long, dec_xdr_long, #if defined(I860_NODE) enc_xdr_short, dec_xdr_short, /* XXX are handwritten anyhow */ enc_xdr_int, dec_xdr_int, enc_xdr_long, dec_xdr_long, #else enc_xdr_short, dec_xdr_ushort, enc_xdr_int, dec_xdr_uint, enc_xdr_ulong, dec_xdr_ulong, #endif enc_xdr_float, dec_xdr_float, enc_xdr_double, dec_xdr_double, enc_xdr_cplx, dec_xdr_cplx, enc_xdr_dcplx, dec_xdr_dcplx }, { enc_inp_init, enc_alien, /* In place (encode only) 2 */ enc_inp_any, enc_alien, enc_inp_any, enc_alien, enc_inp_any, enc_alien, enc_inp_any, enc_alien, enc_inp_any, enc_alien, enc_inp_any, enc_alien, enc_inp_any, enc_alien, enc_inp_any, enc_alien, enc_inp_any, enc_alien, enc_inp_any, enc_alien, enc_inp_any, enc_alien }, { enc_trc_init, dec_trc_init, /* Trace (a la XDR + annot) 4 */ enc_trc_byte, dec_trc_byte, enc_trc_short, dec_trc_short, enc_trc_int, dec_trc_int, enc_trc_long, dec_trc_long, enc_trc_short, dec_trc_ushort, enc_trc_int, dec_trc_uint, enc_trc_ulong, dec_trc_ulong, enc_trc_float, dec_trc_float, enc_trc_double, dec_trc_double, enc_trc_cplx, dec_trc_cplx, enc_trc_dcplx, dec_trc_dcplx }, { enc_alien, dec_raw_init, /* Alien (can't deal) 5 */ enc_alien, dec_raw_any, /* unpacking bytes allowed */ enc_alien, enc_alien, enc_alien, enc_alien, enc_alien, enc_alien, enc_alien, enc_alien, enc_alien, enc_alien, enc_alien, enc_alien, enc_alien, enc_alien, enc_alien, enc_alien, enc_alien, enc_alien, enc_alien, enc_alien }, }; /* pmsg_setlen() * * Set m_len field of pmsg (after packing because we don't keep track * of it). */ int pmsg_setlen(mp) struct pmsg *mp; { struct frag *fp, *fp2; int l = 0; fp = fp2 = mp->m_frag; while ((fp = fp->fr_link) != fp2) l += fp->fr_len; mp->m_len = l; return l; } /* pmsg_setenc() * * Set encoding parameter for message, initialize encode/decode vector. */ int pmsg_setenc(mp, enc) struct pmsg *mp; int enc; { mp->m_enc = enc; if (enc == pvmmydsig) /* native */ enc = 0; else if (enc == 0x10000000) /* xdr */ enc = 1; else if (enc == 0x20000000) /* inplace */ enc = 2; else if (enc == 0x40000000) /* trace */ enc = 3; else /* alien */ enc = 4; mp->m_codef = &encoders[enc]; return 0; } int pmsg_dump(mp, lvl) struct pmsg *mp; int lvl; /* 0 - summary, 1 - frag lengths, 2 - frag data */ { struct frag *fp; if (mp->m_flag & MM_PACK) pmsg_setlen(mp); #ifdef MCHECKSUM pvmlogprintf( "pmsg_dump(0x%x) ref=%d mid=%d len=%d ctx=0x%x tag=%d wid=0x%x src=0x%x dst=0x%x enc=0x%x flag=%d crc=0x%x\n", mp, mp->m_ref, mp->m_mid, mp->m_len, mp->m_ctx, mp->m_tag, mp->m_wid, mp->m_src, mp->m_dst, mp->m_enc, mp->m_flag, pmsg_crc(mp)); #else pvmlogprintf( "pmsg_dump(0x%x) ref=%d mid=%d len=%d ctx=0x%x tag=%d wid=0x%x src=0x%x dst=0x%x enc=0x%x flag=%d\n", mp, mp->m_ref, mp->m_mid, mp->m_len, mp->m_ctx, mp->m_tag, mp->m_wid, mp->m_src, mp->m_dst, mp->m_enc, mp->m_flag); #endif if (lvl > 0) { for (fp = mp->m_frag->fr_link; fp != mp->m_frag; fp = fp->fr_link) { pvmlogprintf(" frag=0x%x max=%d ofs=%d len=%d\n", fp, fp->fr_max, fp->fr_dat - fp->fr_buf, fp->fr_len); if (lvl > 1) pvmhdump(fp->fr_dat, fp->fr_len, " "); } } return 0; } /* pmsg_pack() * * Pack a message into another message, including header fields. */ int pmsg_pack(mp, mp2) struct pmsg *mp; /* message to pack into */ struct pmsg *mp2; /* message to include */ { struct frag *fp; int cc; if (mp2->m_flag & MM_PACK) pmsg_setlen(mp2); if (cc = (mp->m_codef->enc_int) (mp, (void*)&mp2->m_len, 1, 1, sizeof(int))) return cc; if (cc = (mp->m_codef->enc_int) (mp, (void*)&mp2->m_ctx, 1, 1, sizeof(int))) return cc; if (cc = (mp->m_codef->enc_int) (mp, (void*)&mp2->m_tag, 1, 1, sizeof(int))) return cc; if (cc = (mp->m_codef->enc_int) (mp, (void*)&mp2->m_wid, 1, 1, sizeof(int))) return cc; if (cc = (mp->m_codef->enc_int) (mp, (void*)&mp2->m_enc, 1, 1, sizeof(int))) return cc; if (cc = (mp->m_codef->enc_int) (mp, (void*)&mp2->m_crc, 1, 1, sizeof(int))) return cc; if (cc = (mp->m_codef->enc_int) (mp, (void*)&mp2->m_src, 1, 1, sizeof(int))) return cc; if (cc = (mp->m_codef->enc_int) (mp, (void*)&mp2->m_dst, 1, 1, sizeof(int))) return cc; if (fp = mp2->m_frag) while ((fp = fp->fr_link) != mp2->m_frag) { if (cc = (mp->m_codef->enc_int) (mp, (void*)&fp->fr_len, 1, 1, sizeof(int))) return cc; if (cc = (mp->m_codef->enc_byte) (mp, (void*)fp->fr_dat, fp->fr_len, 1, 1)) return cc; } return cc; } /* pmsg_packbody() * * Pack body of a message into another message. * Shares fragments between the messages. */ int pmsg_packbody(mp, mp2) struct pmsg *mp; /* message to pack into */ struct pmsg *mp2; /* message to include body of */ { struct frag *fp, *fp2; int cc; if (mp->m_enc != mp2->m_enc) cc = PvmMismatch; else { cc = 0; if ((fp = mp2->m_frag) && fp->fr_link != fp) { fp2 = mp->m_frag->fr_rlink; if (fp2 != mp->m_frag && fp2->fr_len == 0) { LISTDELETE(fp2, fr_link, fr_rlink); fr_unref(fp2); } while ((fp = fp->fr_link) != mp2->m_frag) { fp2 = fr_new(0); fp2->fr_buf = fp->fr_buf; fp2->fr_max = fp->fr_max; fp2->fr_dat = fp->fr_dat; fp2->fr_len = fp->fr_len; da_ref(fp->fr_buf); LISTPUTBEFORE(mp->m_frag, fp2, fr_link, fr_rlink); } } } return cc; } /* pmsg_unpack() * * Unpack a message from a message. */ int pmsg_unpack(mp, mp2) struct pmsg *mp; /* message to unpack from */ struct pmsg *mp2; /* blank message to write on */ { struct frag *fp; int cc; int mlen; int frl; if (cc = (mp->m_codef->dec_int) (mp, (void*)&mlen, 1, 1, sizeof(int))) return cc; if (cc = (mp->m_codef->dec_int) (mp, (void*)&mp2->m_ctx, 1, 1, sizeof(int))) return cc; if (cc = (mp->m_codef->dec_int) (mp, (void*)&mp2->m_tag, 1, 1, sizeof(int))) return cc; if (cc = (mp->m_codef->dec_int) (mp, (void*)&mp2->m_wid, 1, 1, sizeof(int))) return cc; if (cc = (mp->m_codef->dec_int) (mp, (void*)&mp2->m_enc, 1, 1, sizeof(int))) return cc; if (cc = (mp->m_codef->dec_int) (mp, (void*)&mp2->m_crc, 1, 1, sizeof(int))) return cc; if (cc = (mp->m_codef->dec_int) (mp, (void*)&mp2->m_src, 1, 1, sizeof(int))) return cc; if (cc = (mp->m_codef->dec_int) (mp, (void*)&mp2->m_dst, 1, 1, sizeof(int))) return cc; mp2->m_len = 0; if (mlen < 0) cc = PvmBadMsg; else { while (mlen > 0) { if (cc = (mp->m_codef->dec_int) (mp, (void*)&frl, 1, 1, sizeof(int))) break; if (!(fp = fr_new(frl + MAXHDR))) { cc = PvmNoMem; break; } fp->fr_dat += MAXHDR; fp->fr_len = frl; if (cc = (mp->m_codef->dec_byte) (mp, (void*)fp->fr_dat, frl, 1, 1)) break; LISTPUTBEFORE(mp2->m_frag, fp, fr_link, fr_rlink); mp2->m_len += frl; mlen -= frl; } pmsg_setenc(mp2, mp2->m_enc); } return cc; } /************************** ** Vendor Custom Code ** ** ** **************************/ #ifdef IMA_CSPP static void internal_pre_bcopy(unsigned int, unsigned int, int); void read_prefetch_region(unsigned int, int); static void pre_bcopy(s1, s2, n) unsigned int s1; unsigned int s2; int n; { int offset; /* make life easy. only work on chunks of at least 4 lines */ if (n < 320) { read_prefetch_region(s1 & ~0x3f, n + (s1 & 0x3f)); BCOPY((void *)s1, (void *)s2, n); return; } /* force starting alignment */ offset = (unsigned int)s1 & 0x3f; if (offset) { offset = 64 - offset; BCOPY((void *)s1, (void *)s2, offset); s1 += offset; s2 += offset; n -= offset; } /* deal with case where n is not a multiple of 64 */ offset = n & 0x3f; if (offset) { n &= ~0x3f; internal_pre_bcopy(s1, s2, n); s1 += n; s2 += n; BCOPY((void *)s1, (void *)s2, offset); return; } /* n is a multiple of 64 */ internal_pre_bcopy(s1, s2, n); return; } static void internal_pre_bcopy(s1, s2, n) unsigned int s1; unsigned int s2; int n; { read_prefetch_region(s1, 192); /* prefetch 0, 1 & 2 */ while (1) { read_prefetch_region(s1+192, 64); /* prefetch 3 */ if (n == 256) break; BCOPY((void *)s1, (void *)s2, 64); /* copy 0 */ s1 += 64; s2 += 64; n -= 64; read_prefetch_region(s1+192, 64); /* prefetch 0 */ if (n == 256) break; BCOPY((void *)s1, (void *)s2, 64); /* copy 1 */ s1 += 64; s2 += 64; n -= 64; read_prefetch_region(s1+192, 64); /* prefetch 1 */ if (n == 256) break; BCOPY((void *)s1, (void *)s2, 64); /* copy 2 */ s1 += 64; s2 += 64; n -= 64; read_prefetch_region(s1+192, 64); /* prefetch 2 */ if (n == 256) break; BCOPY((void *)s1, (void *)s2, 64); /* copy 3 */ s1 += 64; s2 += 64; n -= 64; } BCOPY((void *)s1, (void *)s2, 256); /* last 4 lines */ } #endif ./pvm3/src/pvmalloc.c0100644007401100000360000000477706741172466013704 0ustar kohlgopher static char rcsid[] = "$Id: pvmalloc.c,v 1.4 1999/07/08 19:00:06 kohl Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmalloc.c * * Malloc filter interface. * * $Log: pvmalloc.c,v $ * Revision 1.4 1999/07/08 19:00:06 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.3 1997/06/25 22:09:18 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.2 1997/01/28 19:26:59 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:44:28 pvmsrc * Initial revision * * Revision 1.2 1994/06/03 20:38:21 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:26:50 manchek * Initial revision * */ #include #include "pvmalloc.h" char *i_malloc(), *i_realloc(); /*************** ** Private ** ** ** ***************/ /***************** ** Interface ** ** ** *****************/ char * pvm_alloc(n, tag) unsigned n; char *tag; { char *r; if (!(r = i_malloc(n, tag))) { pvmlogprintf("pvm_alloc: can't get %d bytes", n); } return r; } char * pvm_realloc(p, n) char *p; unsigned n; { char *r; if (!(r = i_realloc(p, n))) { pvmlogprintf("pvm_realloc: can't get %d bytes", n); } return r; } void pvm_free(p) char *p; { (void)i_free(p); } ./pvm3/src/pvmcruft.c0100644007401100000360000006651510023644747013725 0ustar kohlgopher static char rcsid[] = "$Id: pvmcruft.c,v 1.40 2004/03/10 17:01:27 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * cruft.c * * Missing links and other wonk. * * $Log: pvmcruft.c,v $ * Revision 1.40 2004/03/10 17:01:27 pvmsrc * Fixed funny pvmtmpnam() bug... (ha ha ha :) * - first pvmd call for socket file will name clash after 10000 * task spawns (t-auth/d-auth)... (go figure... :-) * - tweaked to start counter at 0, but thereafter roll over back to 1. * (Spanker=kohl) * * Revision 1.39 2002/04/23 16:33:29 pvmsrc * Added overflow check in pvmtmpnam() for PVMTMPNAMLEN string length... * - just a good idea to check, though it's a lazy check-and-bail... * (Spanker=kohl) * * Revision 1.38 2001/09/27 21:25:10 pvmsrc * BEOSCYLD port. * - submitted by Joe Vitale . * (we renamed it from BEOWULF to BEOSCYLD, but it's his port... :-) * (Spanker=kohl) * * Revision 1.37 2001/09/26 22:04:20 pvmsrc * Modified temp file prefix in pvmtmpnam(). * - tmp* -> pvmtmp*. * (Spanker=kohl) * * Revision 1.36 2001/09/26 21:22:59 pvmsrc * Append VMID string to PVMD socket file name in pvmdsockfile(). * - if set in PVM_VMID env var. * - not restricted to be integer as in SGI, can be arbitrary * string... heh, heh... :-} * (Spanker=kohl) * * Revision 1.35 2001/09/25 21:21:02 pvmsrc * Yanked "char *pvmgettmp();" decl - now in pvm3.h... * (Spanker=kohl) * * Revision 1.34 2001/02/09 15:23:47 pvmsrc * Minor tweak to pvmgettmp() for Markus. * - check %PVM_TMP% & registry before resorting to %TEMP%. * (Spanker=kohl) * * Revision 1.33 2001/02/07 23:15:51 pvmsrc * 2nd Half of CYGWIN Check-ins... * (Spanker=kohl) * * Revision 1.32 2001/02/02 14:50:26 pvmsrc * Win32 fixes & additions. * (Spanker=kohl) * * Revision 1.31 2000/03/29 20:04:12 pvmsrc * Added prototype for pvm_readregistry() routine. * (Spanker=sscott) * * Revision 1.30 2000/02/17 23:12:15 pvmsrc * *** Changes for new BEOLIN port *** * - MPP-like, similar to SP2, etc. * - submitted by Paul Springer . * - format-checked & cleaned up by Jeembo... :-) * (Spanker=kohl) * * Revision 1.29 2000/02/16 23:30:24 pvmsrc * Added back in read_pvmregistry() calls. * - for PVM_ROOT and PVM_TMP, if env vars not present on WIN32. * - couldn't find reference to PVM_ARCH anywhere, Markus?! * (Spanker=kohl) * * Revision 1.28 2000/02/14 20:32:11 pvmsrc * Added new pvmgetrsh() routine * - checks for PVM_RSH or else uses old RSHCOMMAND interface. * - one-stop shopping for rsh... * (Spanker=kohl) * * Revision 1.27 2000/02/10 20:45:15 pvmsrc * Replaced hard-coded /tmp usage. * - modified pvmgettmp() to try $PVM_TMP env var for Unix, too. * - use for TDSOCKNAME / TDSOCKNAME_CSPP in pvmdsockfile(). * Also in pvmdsockfile(): * - fixed WIN32 chdir() problem, cleaned up string manip. * (Spanker=kohl) * * Revision 1.26 1999/12/13 18:13:55 pvmsrc * Moved pvmmatchstring() here from msgbox.c. * - for use by pvmtester stuff... * (Spanker=kohl) * * Revision 1.25 1999/07/08 19:00:06 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.24 1999/03/16 16:29:56 pvmsrc * Oops... Fixed typing problem for WIN32 in pvmsleep()... * (Spanker=kohl) * * Revision 1.23 1999/03/15 19:06:32 pvmsrc * Added new pvmsleep() routine. * - Unix / Win32, C / Fortran compat... * - invokes Sleep() on WIN32 (with secs * 1000 :-)~ * (Spanker=kohl) * * Revision 1.22 1999/03/05 17:21:15 pvmsrc * improved to work with registry/environment on NT/win95-98 * and devstudio 5/6 * (Spanker=sscott) * * Revision 1.21 1999/02/09 23:06:53 pvmsrc * Cleaned up temp file stuff (mainly for WIN32). * - extracted new pvmgettmp() routine for returning tmp directory. * (Spanker=kohl) * * Revision 1.20 1999/02/09 20:10:10 pvmsrc * Cleaned up pvmgetroot(). * - some arch cases not properly executed. * - for WIN32, if read_pvmregistry() fails, give the env var a shot. * (Spanker=kohl) * * Revision 1.19 1998/10/02 15:44:04 pvmsrc * Single source code merge of Win32 and Unix code. * (Spanker=sscott) * * Revision 1.18 1998/09/23 15:23:42 pvmsrc * changes to use WIN32 registry as per Markus. * ifdef in pvmd.c::colonsep() to include WIN32 and OS2 * (Spanker=phil) * * Revision 1.17 1997/12/01 19:20:48 pvmsrc * Replaced #ifdef IMA_OS2 fd_set declarations: * - new #ifdef FDSETNOTSTRUCT. * - choose between "fd_set foo" and "struct fd_set foo"... * (Spanker=kohl) * * Revision 1.16 1997/11/04 23:19:25 pvmsrc * Cleaned up fd_set stuff (hopefully). * (Spanker=kohl) * * Revision 1.15 1997/06/27 19:19:34 pvmsrc * Integrated WIN32 changes. * * Revision 1.14 1997/05/27 14:47:04 pvmsrc * New message type added: TM_SHMCONN. * * Revision 1.13 1997/04/30 21:26:10 pvmsrc * SGI Compiler Warning Cleanup. * * Revision 1.12 1997/04/21 14:58:23 pvmsrc * Changed #ifdefs that checked IMA_RS6K,IMA_SP2MPI & IMA_AIX46K * to see if select.h was needed into single define NEEDSSELECTH. * New archs need to set this in conf/ * * Revision 1.11 1997/04/08 19:41:41 pvmsrc * Added "DM_RESET", "DM_RESETACK" to taglist2... * * Revision 1.10 1997/04/08 17:23:33 pvmsrc * Damn, Damn, Damn... * - pvmreset() must be in library side only, pvmds use different * message buffer mgt, packing and sending routines... :-Q * * Revision 1.9 1997/04/08 17:08:17 pvmsrc * Oops... need to pass in caller's tid, lest they be reset, too... * * Revision 1.8 1997/04/07 20:51:18 pvmsrc * Added pvmreset() routine. * - for use by "pvm" console / XPVM, etc. * - wipe out tasks, and tell master pvmd to clean up mboxes. * * Revision 1.7 1997/03/06 21:50:23 pvmsrc * Yanked out #includes for and . * - dups with lpvm.h #includes... * * Revision 1.6 1997/03/06 21:09:47 pvmsrc * use dclock() for pvmgetclock() * * Revision 1.5 1997/01/28 19:27:00 pvmsrc * New Copyright Notice & Authors. * * Revision 1.4 1996/10/25 13:57:57 pvmsrc * Replaced old #includes for protocol headers: * - , "ddpro.h", "tdpro.h" * With #include of new combined header: * - * * Revision 1.3 1996/10/24 21:30:39 pvmsrc * Moved #include "global.h" to below other #includes for typing. * Added #include of new "lpvm.h" & replaced explicit externs. * Added new trace control constants: * - TM_TRACER, for pvm_reg_tracer() messages. * - TC_SETTRACE, TC_SETTRCBUF, TC_SETTRCOPT, for on-the-fly setopt * control message / handlers. * * Revision 1.2 1996/09/27 13:17:09 pvmsrc * Added special #include of for old RS6K (AIX 3.2): * - fd_set declarations not found in on those systems, * or evidently in SP2MPI, need . * - similar fixes already existed in hoster.c, lpvm.c and pvmd.c. * * Revision 1.1 1996/09/23 23:44:29 pvmsrc * Initial revision * * Revision 1.10 1995/11/02 16:21:34 manchek * made pvmhdump write to pvm log. * new switch NEEDSFFS for ffs. * added pvmcopyenv, pvmenvinsert and pvmfreeenv * * Revision 1.9 1995/07/19 21:26:27 manchek * new function pvmnametag converts message tag to name or decimal string * * Revision 1.8 1995/07/18 17:01:35 manchek * added function pvmcrcappend to generate 32-bit crcs * * Revision 1.7 1995/05/24 16:58:42 manchek * whacked doofy coding style in pvmhdump * * Revision 1.6 1995/05/17 16:27:52 manchek * added support for CSPP subcomplexes (/tmp file naming) * * Revision 1.5 1994/11/07 22:48:09 manchek * added tweaks for SX3, SCO * * Revision 1.4 1994/07/18 19:21:05 manchek * pvmputenv() matched variable name substrings (need to compare = too) * * Revision 1.3 1994/06/03 20:38:22 manchek * version 3.3.0 * * Revision 1.2 1993/10/04 20:28:27 manchek * added pvmdsockfile() function * * Revision 1.1 1993/08/30 23:26:50 manchek * Initial revision * */ #include #ifdef IMA_TITN #include #else #include #endif #ifndef WIN32 #include #include #else #include #endif #ifdef NEEDSSELECTH #include #endif #include #include #ifdef SYSVSTR #include #define CINDEX(s,c) strchr(s,c) #else #include #define CINDEX(s,c) index(s,c) #endif #include #include #include "pvmalloc.h" #include "lpvm.h" #include "global.h" #ifdef WIN32 char *read_pvmregistry __ProtoGlarp__(( const char * )); #endif /*************** ** Globals ** ** ** ***************/ #ifndef RSHCOMMAND #define RSHCOMMAND "/usr/ucb/rsh" #endif char *getenv(); #ifdef WIN32 extern char *username; #endif #ifdef IMA_BEOSCYLD #include #endif /*************** ** Private ** ** ** ***************/ int pvmput32(p, n) char *p; int n; { *p++ = n >> 24; *p++ = n >> 16; *p++ = n >> 8; *p = n; return 0; } int pvmput16(p, n) char *p; int n; { *p++ = n >> 8; *p = n; return 0; } int pvmput8(p, n) char *p; int n; { *p = n; return 0; } int pvmget32(p) char *p; { return ((0xff & p[0]) << 24) + ((0xff & p[1]) << 16) + ((0xff & p[2]) << 8) + (0xff & p[3]); } int pvmget16(p) char *p; { return ((0xff & p[0]) << 8) + (0xff & p[1]); } int pvmget8(p) char *p; { return 0xff & *p; } #ifdef NOGETDTBLSIZ #ifdef IMA_TITN int getdtablesize() { return 64; } #else /*IMA_TITN*/ #ifdef IMA_SX3 int getdtablesize() { return 64*8; } #else /*IMA_SX3*/ #ifdef WIN32 int getdtablesize() { return 64; } #else #include int getdtablesize() { return sysconf(_SC_OPEN_MAX); } #endif #endif /*IMA_SX3*/ #endif /*IMA_TITN*/ #endif /*NOGETDTBLSIZ*/ #ifdef NEEDSFFS int ffs(x) int x; { int n = 1, m = 1; if (!x) return 0; while (!(x & m)) { m += m; n++; } return n; } #endif #ifndef IMA_WIN32_WATCOM extern char **environ; #endif /* pvmputenv() * * Replacement for systems that don't have putenv. * Tries to be conservative, i.e. doesn't assume that environ * points to malloc'd space. * * String must never be freed... */ int pvmputenv(s) char *s; /* string of form "NAME=Value" */ { char *p; /* gp */ int l; /* length of env var name or env */ static char **myen = 0; /* last environ that i created */ char **newen; /* new env if extending */ char **ep, **ep2; /* gp */ /* sanity check the string and locate the '=' */ if (!s) return -1; for (p = s; *p && *p != '='; p++); if (p == s || !*p) return -1; l = p - s + 1; /* must include '=' */ /* search current environ for name */ for (ep = environ; *ep; ep++) if (!strncmp(*ep, s, l)) break; if (*ep) { /* already there, replace it */ *ep = s; } else { /* not there, must extend environ */ /* length needed is? */ for (l = 2, ep = environ; *ep; l++, ep++); if (environ == myen) { /* mine, reallocate */ if (!(newen = (char**)realloc((char *)environ, (unsigned)(l * sizeof(char*))))) return -1; } else { /* not mine, alloc new and copy */ if (!(newen = (char**)malloc((unsigned)(l * sizeof(char*))))) return -1; for (ep = environ, ep2 = newen; *ep2++ = *ep++; ); } newen[l - 2] = s; newen[l - 1] = 0; environ = myen = newen; } return 0; } /* pvmcopyenv() * * Make copy of an environment list (null-terminated vector of strings). * This is just like environ, but we own all the strings. * Can also be used to create an empty list, by passing a null pointer. * * Returns pointer to environment or NULL if malloc fails. */ char ** pvmcopyenv(anyep) char **anyep; /* old environment to copy, or NULL */ { char **newep; int i, n; if (anyep) { for (n = 0; anyep[n]; n++) ; if (newep = TALLOC(n + 1, char *, "env")) { newep[n] = 0; for (i = 0; i < n; i++) { if (!(newep[i] = STRALLOC(anyep[i]))) { while (i-- > 0) PVM_FREE(newep[i]); PVM_FREE(newep); newep = 0; break; } } } } else { if (newep = TALLOC(1, char *, "env")) newep[0] = 0; } return newep; } /* pvmenvinsert() * * Put a copy of a string into an environment list (made by pvmcopyenv). * List must be one of ours, since we malloc and free the strings. * * Returns zero or success, or -1 if malloc fails. * May update pointer to environment on return. */ int pvmenvinsert(anep, s) char ***anep; /* environment pointer, may change (NOT environ) */ char *s; /* string of form "NAME=Value" */ { char **ep; char **newep; char *p; int l; /* length of env var name or env */ newep = *anep; if (!s || !(p = CINDEX(s, '='))) return -1; l = p - s + 1; /* must include the '=' */ /* search environ for name */ for (ep = newep; *ep; ep++) if (!strncmp(*ep, s, l)) break; if (*ep) { /* already there, replace it */ PVM_FREE(*ep); *ep = STRALLOC(s); } else { /* not there, must extend environ */ /* length needed is? */ for (l = 2, ep = newep; *ep; l++, ep++); if (!(newep = TREALLOC((char *)newep, l, char *))) return -1; newep[l - 2] = STRALLOC(s); newep[l - 1] = 0; *anep = newep; } return 0; } /* pvmfreeenv() * * Free an environment list (made by pvmcopyenv). */ int pvmfreeenv(anep) char **anep; { char **p; for (p = anep; *p; p++) PVM_FREE(*p); PVM_FREE(anep); return 0; } /* pvmxtoi() * * Yet another version of ascii hex to integer */ pvmxtoi(p) char *p; { int i = 0; char c; if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) p += 2; while (isxdigit(c = *p++)) { i = (i << 4) + c - (isdigit(c) ? '0' : (isupper(c) ? 'A' : 'a') - 10); } return i; } /* pvmstrtoi() * * Convert string in decimal, hex or octal to integer. */ int pvmstrtoi(p) char *p; { int i = 0; char c; if (*p == '0') { p++; if (*p == 'x' || *p == 'X') while (isxdigit(c = *++p)) i = (i << 4) + c - (isdigit(c) ? '0' : (isupper(c) ? 'A' : 'a') - 10); else while (c = *p++, c >= '0' && c <= '7') i = (i << 3) + c - '0'; return i; } else return (int)atoi(p); } #ifndef I860_NODE /* hex_inadport() * * Takes a string of format 00000000:0000 and returns a sockaddr_in. */ void hex_inadport(s, sad) char *s; struct sockaddr_in *sad; { sad->sin_addr.s_addr = htonl((unsigned)pvmxtoi(s)); s = (s = CINDEX(s, ':')) ? s + 1 : ""; sad->sin_port = htons((unsigned short)pvmxtoi(s)); } /* inadport_decimal() * * Returns printable string corr. to sockaddr_in with addr in decimal. */ char * inadport_decimal(sad) struct sockaddr_in *sad; { static char buf[32]; int a; a = ntohl(0xffffffff & sad->sin_addr.s_addr); sprintf(buf, "%d.%d.%d.%d:%d", 0xff & (a >> 24), 0xff & (a >> 16), 0xff & (a >> 8), 0xff & a, 0xffff & (int)ntohs(sad->sin_port)); return buf; } /* inadport_hex() * * Returns printable string corr. to sockaddr_in with addr in hex. */ char * inadport_hex(sad) struct sockaddr_in *sad; { static char buf[16]; int a; a = ntohl(0xffffffff & sad->sin_addr.s_addr); sprintf(buf, "%08x:%04x", a, 0xffff & (int)ntohs(sad->sin_port)); return buf; } #endif /*I860_NODE*/ #ifdef NOTMPNAM char * pvmtmpnam(buf) char *buf; { static int f = 0; static int n = 0; static char scratch[255]; char *pvmtmp; if (!buf) buf = scratch; pvmtmp = pvmgettmp(); #ifndef WIN32 sprintf(buf, "%s/pvmtmp%06d.%d", pvmtmp, getpid(), n); #else sprintf(buf, "%s\\pvmtmp%06d.%d", pvmtmp, getpid(), n); #endif /* Silly Hack to avoid stomping on pvmd's first pvmtmpnam() call to get it's socket file... :-) */ n = 1 + (f++ % 10000); /* Better Check for String Overflow... */ /* (Late Check is Better Than No Check... :-) */ if ( strlen( buf ) >= PVMTMPNAMLEN ) { pvmlogperror("Whoa! PVMTMPNAMLEN Overflow in pvmtmpnam()..."); pvmlogprintf("<%s> = %d >= %d", buf, strlen( buf ), PVMTMPNAMLEN); pvmbailout(0); exit(1); /* the other meaning of bail out */ } return buf; } #endif /*NOTMPNAM*/ #ifdef IMA_BEOSCYLD /* * Implement a version of gethostname() that gives the "right" answer * for a Scyld Beowulf cluster; calling bproc_currnode() here is why * both the pvm daemon and the pvm library are linked with libbproc */ int gethostname(name, len) char * name; size_t len; { int retval; retval = snprintf(name,len,".%d",bproc_currnode()); return( (retval == -1) ? retval : 0 ); } #endif pvmhdump(cp, n, pad) char *cp; /* bytes */ int n; /* length */ char *pad; /* tag string */ { static char *buf = 0; static int bufl = 0; int i, l; char *r; pad = pad ? pad : ""; l = strlen(pad) + 50; if (l > bufl) { if (buf) PVM_FREE(buf); if (!(buf = TALLOC(l, char, "hdump"))) { bufl = 0; pvmlogerror("pvmhdump() malloc failed\n"); return 1; } bufl = l; } r = buf; for (i = 0; n-- > 0; i = (i + 1) & 15) { sprintf(r, "%s%02x", i ? " " : pad, 0xff & *cp++); r += strlen(r); if (!n || i == 15) { strcpy(r, "\n"); pvmlogerror(buf); r = buf; } } return 0; } /* pvmgethome() * * Return path of user homedir. */ char * pvmgethome() { static char *hd = 0; #ifndef WIN32 /* which registry should we use otherwise ? */ if (!hd) { if (hd = getenv("HOME")) { hd = STRALLOC(hd); } else { pvmlogerror("warning: can't getenv(HOME), using /\n"); hd = "/"; } } #else hd="\\"; #endif return hd; } /* pvmgetroot() * * Return absolute path of PVM top level directory. */ char * pvmgetroot() { static char *rd = 0; if (!rd) { #ifdef IMA_CSPP struct stat buf; rd = STRALLOC("/usr/convex/pvm"); if (stat(rd, &buf) == -1) { pvmlogperror( "Unable to default PVM_ROOT to /usr/convex/pvm"); pvmbailout(0); exit(1); /* the other meaning of bail out */ } pvmputenv("PVM_ROOT=/usr/convex/pvm"); pvmlogerror("Defaulting PVM_ROOT to /usr/convex/pvm"); #else #ifdef CYGWIN rd = getenv("PVM_ROOT_U"); #else rd = getenv("PVM_ROOT"); #endif #ifdef WIN32 if (!rd) rd = read_pvmregistry("PVM_ROOT"); #endif #endif if (!rd) { pvmlogerror("PVM_ROOT environment variable not set.\n"); pvmbailout(0); exit(1); /* the other meaning of bail out */ } } return rd; } /* pvmgettmp() * * Return absolute path of PVM temporary directory. */ char * pvmgettmp() { static char *td = 0; if (!td) { #ifndef WIN32 if ( !(td=getenv("PVM_TMP")) ) #ifdef IMA_BEOLIN td = "/tmps"; /* the shared tmp */ #else td = "/tmp"; #endif #else if ( !(td=getenv("PVM_TMP")) ) { if ( !(td=read_pvmregistry("PVM_TMP")) ) { if ( !(td=getenv("TEMP")) ) { td = "C:\\TEMP"; fprintf(stderr, "Could not get %%PVM_TMP%% or %%TEMP%% "); fprintf(stderr, "-> using \"%s\".\n", td); fprintf(stderr, "Please check your PVM installation.\n"); } } } #endif } return td; } /* pvmgetrsh() * * Return absolute path of the rsh executable for the local system. */ char * pvmgetrsh() { static char *rd = 0; if (!rd) { if ( !(rd=getenv("PVM_RSH")) ) rd = RSHCOMMAND; } return rd; } /* pvmgetpvmd() * * Return absolute path of pvmd startup script. */ char * pvmgetpvmd() { char *r; static char *pp = 0; if (!pp) { if (PVMDFILE[0] == '/') pp = PVMDFILE; else { r = pvmgetroot(); pp = TALLOC(strlen(r) + strlen(PVMDFILE) + 2, char, "pvmdpath"); sprintf(pp, "%s/%s", r, PVMDFILE); } } return pp; } /* pvmdsockfile() * * Returns name of file where pvmd advertises its sockaddr. * Assumes global pvm_useruid is set before calling. */ char * pvmdsockfile() { static char buf[255]; char hna[128]; char *pvmtmp; char *p; #ifdef IMA_CSPP int scid = get_scid(); /* default (system) subcomplex ID is 1 */ #endif pvmtmp = pvmgettmp(); #ifdef SHAREDTMP if (gethostname(hna, sizeof(hna)-1) == -1) { pvmlogerror("pvmdsockfile() can't gethostname()\n"); return (char*)0; } if (p = CINDEX(hna, '.')) *p = 0; #ifdef IMA_CSPP if (scid > 1) (void)sprintf(buf, TDSOCKNAME_CSPP, pvmtmp, pvm_useruid, scid, hna); else #endif (void)sprintf(buf, TDSOCKNAME, pvmtmp, pvm_useruid, hna); #else #ifdef IMA_CSPP if (scid > 1) (void)sprintf(buf, TDSOCKNAME_CSPP, pvmtmp, pvm_useruid, scid); else #endif #ifdef WIN32 sprintf( buf, "%s\\pvmd.%s", pvmtmp, username ); #else (void)sprintf(buf, TDSOCKNAME, pvmtmp, pvm_useruid); #endif #endif /* Append a Virtual Machine ID, If Set */ if ( p = getenv("PVM_VMID") ) { strcat( buf, "." ); strcat( buf, p ); } return buf; } #ifdef IMA_CSPP #include /* get_scid () * * (Convex CSPP only) * Returns the subcomplex identifier for the calling process */ int get_scid () { static int my_scid = -1; int rc; struct cnx_pattributes pattrib; if (my_scid < 0) { my_scid = 0; if ((rc = cnx_getpattr(getpid(), CNX_PATTR_SCID, &pattrib)) != 0) { pvmlogperror ("get_scid: Unable to get scid"); return 0; } my_scid = pattrib.pattr_scid; } return my_scid; } #endif /*IMA_CSPP*/ #define PVMCRCPOLY 0xedb88320 unsigned int pvmcrcappend(buf, len, crc) char *buf; /* buffer to append to crc value */ int len; /* length */ unsigned int crc; /* initial value */ { static unsigned int crctbl[256]; static int once = 1; if (once) { int i, j; unsigned int v; for (i = 0; i < 256; i++) { v = i; for (j = 8; j--; ) v = v & 1 ? (v >> 1) ^ PVMCRCPOLY : v >> 1; crctbl[i] = v; } once = 0; } while (len-- > 0) crc = ((crc >> 8) & 0x00ffffff) ^ crctbl[(crc ^ *buf++) & 0xff]; return crc; } static char *taglist1[] = { "TM_CONNECT", "TM_CONN2", "TM_EXIT", "TM_ADDHOST", "TM_DELHOST", "TM_CONFIG", "TM_MSTAT", "TM_HALT", "TM_TICKLE", "TM_SPAWN", "TM_PSTAT", "TM_SENDSIG", "TM_TASK", "TM_MCA", "TM_NOTIFY", "TM_DB", "TM_SCHED", "TM_TASKER", "TM_HOSTER", "TM_TRACER", "TM_HOSTSYNC", "TM_SETOPT", "TM_GETOPT", "TM_CONTEXT", "TM_SHMCONN", }; static char *taglist2[] = { "DM_ADD", "DM_ADDACK", "DM_EXEC", "DM_EXECACK", "DM_SENDSIG", "DM_HTUPD", "DM_HTUPDACK", "DM_HTCOMMIT", "DM_SLCONF", "DM_STARTACK", "DM_TASK", "DM_TASKACK", "DM_DELHOST", "DM_DELHOSTACK", "DM_NULL", "DM_TASKOUT", "DM_PSTAT", "DM_PSTATACK", "DM_HALT", "DM_MCA", "DM_NOTIFY", "DM_NOTIFYACK", "DM_DB", "DM_DBACK", "DM_RESET", "DM_RESETACK", "DM_HTDEL", "DM_HOSTSYNC", "DM_HOSTSYNCACK", }; static char *taglist3[] = { "TC_CONREQ", "TC_CONACK", "TC_TASKEXIT", "TC_NOOP", "TC_OUTPUT", "TC_SETTRACE", "TC_SETTMASK", "TC_SETTRCBUF", "TC_SETTRCOPT", "TC_SHMAT", "TC_OUTPUTX", "TC_SIBLINGS", }; static char *taglist4[] = { "SM_SPAWN", "SM_EXEC", "SM_EXECACK", "SM_TASK", "SM_CONFIG", "SM_ADDHOST", "SM_DELHOST", "SM_ADD", "SM_ADDACK", "SM_NOTIFY", "SM_TASKX", "SM_HOSTX", "SM_HANDOFF", "SM_SCHED", "SM_STHOST", "SM_STHOSTACK", "SM_STTASK", }; struct nametag { int first; int last; char **names; }; static struct nametag nametaglist[] = { { TM_CONNECT, TM_SHMCONN, taglist1 }, { DM_ADD, DM_HOSTSYNCACK, taglist2 }, { TC_CONREQ, TC_SIBLINGS, taglist3 }, { SM_SPAWN, SM_STTASK, taglist4 }, }; /* pvmnametag() * * Convert message tag to symbolic name for reserved tags. * Returns name string or decimal tag if not found. * If found is nonnull, return whether found. */ char * pvmnametag(tag, found) int tag; int *found; { static char buf[32]; int i, j; for (i = sizeof(nametaglist)/sizeof(nametaglist[0]); i-- > 0; ) if (tag >= nametaglist[i].first && tag <= nametaglist[i].last) { j = tag - nametaglist[i].first; if (found) *found = 1; return nametaglist[i].names[j]; } sprintf(buf, "%d", tag); if (found) *found = 0; return buf; } /* debug_flags() * * Convert debug mask to flag names */ static char *dflgs[] = { "pkt", /* 1 */ "msg", /* 2 */ "tsk", /* 4 */ "slv", /* 8 */ "hst", /* 10 */ "sel", /* 20 */ "net", /* 40 */ "mpp", /* 80 */ "sch", /* 100 */ "app", /* 200 */ "wai", /* 400 */ "mem", /* 800 */ "sem", /* 1000 */ "lck", /* 2000 */ "rtg", /* 4000 */ "mbx" /* 8000 */ }; char * debug_flags(mask) int mask; { static char buf[64]; int bit, i; buf[0] = 0; for (bit = 1, i = 0; i < sizeof(dflgs)/sizeof(dflgs[0]); i++, bit *= 2) if (mask & bit) { if (buf[0]) strcat(buf, ","); strcat(buf, dflgs[i]); } return buf; } /* print_fdset() * * Print an fd_set in human-readable format. */ print_fdset(pad, n, f) char *pad; /* label at head */ int n; /* max fd + 1 */ #ifdef FDSETNOTSTRUCT fd_set *f; /* fd set */ #else struct fd_set *f; /* fd set */ #endif { int i; char *s = ""; pvmlogprintf("%s", pad); for (i = 0; i < n; i++) if (FD_ISSET(i, f)) { pvmlogprintf("%s%d", s, i); s = ","; } pvmlogprintf("\n"); return 0; } #ifdef I860_NODE int gettimeofday(tp, tzp) struct timeval *tp; struct timezone *tzp; { double t, dclock(); t = dclock(); tp->tv_sec = t; tp->tv_usec = (t - tp->tv_sec)*1.0E06; return 0; } #endif /* pvmgetclock() * * Use this whenever we need a clock value in seconds and microseconds. * Return values shouldn't be compared to those from gettimeofday, * because it doesn't necessarily return the actual time of day. */ int pvmgetclock(tm) struct timeval *tm; { #if defined(IMA_PGON) double dclock(); double t; t = dclock(); tm->tv_sec = t; tm->tv_usec = (t - tm->tv_sec)*1.0E06; #else return gettimeofday(tm, (struct timezone*)0); #endif } /* pvmsleep() * * A consistent way to invoke sleep(), from: * Unix / Windows, C / Fortran */ int pvmsleep( secs ) int secs; { int ret; #ifdef WIN32 Sleep( secs * 1000 ); ret = secs; #else ret = (int) sleep( secs ); #endif return( ret ); } /* pvmmatchstring() * * Replacement for GNU Regex pattern matching. */ int pvmmatchstring( str, pattern ) char *str; char *pattern; { char *start; char *save; char *x; char *y; /* Find Start of Search String (Ignore Preceding '*'s) */ start = pattern; while ( *start == '*' && *start != '\0' ) start++; /* Null Search - Always Matches */ if ( *start == '\0' ) return( 1 ); /* Initialize Pointers */ x = str; y = start; /* Search Line for Start of Search String */ while ( *x != '\0' ) { /* Starting Match Found... Check it Out */ if ( *x == *y ) { /* Save Continuation Pointer */ save = x + 1; /* Traverse Line Until No Longer Matches */ while ( *x != '\0' && *y != '\0' && *x == *y ) { x++; y++; /* Nested '*' Search Expansion */ if ( *y == '*' ) { if ( pvmmatchstring( x, y + 1 ) ) return( 1 ); else break; } /* Skip Over '\' for Escaped '*'s */ else if ( *y == '\\' && *(y+1) == '*' ) y++; } /* It's a Match! */ if ( *y == '\0' ) return( 1 ); /* Reset and Continue */ x = save; y = start; } else x++; } return( 0 ); } ./pvm3/src/pvmdabuf.c0100644007401100000360000000506506741172472013657 0ustar kohlgopher static char rcsid[] = "$Id: pvmdabuf.c,v 1.5 1999/07/08 19:00:10 kohl Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmdabuf.c * * Data buffer manip. * * $Log: pvmdabuf.c,v $ * Revision 1.5 1999/07/08 19:00:10 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.4 1997/06/25 22:09:20 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.3 1997/03/06 21:10:17 pvmsrc * quad align dabufs by adding double q[2] in alignme * * Revision 1.2 1997/01/28 19:27:04 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:44:31 pvmsrc * Initial revision * * Revision 1.2 1994/06/03 20:38:23 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:26:50 manchek * Initial revision * */ #include #include "pvmalloc.h" union alignme { long l; char *p; double d; double q[2]; /* quad-word alignment */ }; #define RCOFFSET sizeof(union alignme) /*************** ** Private ** ** ** ***************/ char * da_new(len) int len; { char *p; if (p = TALLOC(len + RCOFFSET, char, "data")) { p += RCOFFSET; *(int*)(p - sizeof(int)) = 1; } return p; } void da_ref(p) char *p; { ++*(int*)(p - sizeof(int)); } void da_unref(p) char *p; { if (--*(int*)(p - sizeof(int)) < 1) PVM_FREE(p - RCOFFSET); } ./pvm3/src/pvmd.c0100644007401100000360000037471410117657410013023 0ustar kohlgopher static char rcsid[] = "$Id: pvmd.c,v 1.81 2004/09/08 19:35:36 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmd.c * * Mr. pvm daemon. * * $Log: pvmd.c,v $ * Revision 1.81 2004/09/08 19:35:36 pvmsrc * Added #ifdef IMA_AIX56K64 to unsigned int oslen fiasco... * (Spanker=kohl) * * Revision 1.80 2004/02/06 20:05:38 pvmsrc * Yanked out all the AMD64 test crap. * - it was just the time.h header all along...! ;-/~ * (Spanker=kohl) * * Revision 1.79 2004/02/06 16:50:36 pvmsrc * Yet more ctime() test crap for AMD64... * (Spanker=kohl) * * Revision 1.78 2004/02/04 23:30:14 pvmsrc * Yet more temp AMD64 hacks... * (Spanker=kohl) * * Revision 1.77 2004/02/04 21:46:23 pvmsrc * Temp hack for AMD64 seg fault... * (Spanker=kohl) * * Revision 1.76 2004/01/14 18:51:02 pvmsrc * Added new AIX5* arches. * (Spanker=kohl) * * Revision 1.75 2002/10/14 19:23:12 pvmsrc * Oops! Need to htons() to convert the host byte to network byte order! * - for PVMNETSOCKPORT cruft... * (Spanker=kohl) * * Revision 1.74 2002/10/07 14:30:32 pvmsrc * Added new PVMNETSOCKPORT env var for mksocs(). * - allow starting port address for netsock binding, in the hopes * that PVM will get a port that is allowed access through a * firewall...! * (it's about time!) * (Spanker=kohl) * * Revision 1.73 2002/07/03 16:57:54 pvmsrc * Fixes for compilation on Linux Alpha. * - submitted by "David Mathog" . * (Spanker=kohl) * * Revision 1.72 2002/04/16 15:06:02 pvmsrc * WIN32 Fixes for Multiple Domains. * - submitted by Jigen Zhou . * (Spanker=kohl) * * Revision 1.71 2002/02/21 23:17:40 pvmsrc * Added new (not to be documented!) PVM_MAX_TASKS env var support. * - for Mahir Lokvancic . * - forcefully limits the number of tasks that can attach to a * pvmd, required on Solaris in rare circumstances when hard * FD_SETSIZE limit is reached, and all hell breaks loose... * - set new pvm_max_ntasks global depending on env var (0 = no limit) * - check return for task_new() call, can now produce NULL ptr, * indicating PvmOutOfRes... * (Spanker=kohl) * * Revision 1.70 2001/12/07 16:06:11 pvmsrc * Oops! Some new Unix fixes & features break Windows (of course!). * - #ifdef-ed away fcntl() calls for non-blocking sockets / stdin. * (one for bug fix in lpvm.c, one for check_ext_input() in pvmd.c) * (Spanker=kohl) * * Revision 1.69 2001/11/26 17:45:12 pvmsrc * Added #define for MAXPATHLEN for goofy arches... :-) * (Spanker=kohl) * * Revision 1.68 2001/09/28 12:43:18 pvmsrc * D-Oh! Stupid Solaris doesn't recognize FNDELAY, only O_NDELAY... :-Q * (Spanker=kohl) * * Revision 1.67 2001/09/27 21:25:11 pvmsrc * BEOSCYLD port. * - submitted by Joe Vitale . * (we renamed it from BEOWULF to BEOSCYLD, but it's his port... :-) * (Spanker=kohl) * * Revision 1.66 2001/09/26 21:23:21 pvmsrc * Added Handling for Optional Virtual Machine ID. * - added new check_ext_input() routine to check for extension * options on stdin before anything else happens... currently * only expects env string a la "PVM_VMID=xxxx", but more options * could be added on same input line, white-space-separated... * - extra vmid comes through with SM_STHOST message (after wincmd) * to hoster. * - user instructed to type VMID (or other options) to pvmd stdin * during manual startup. * (Spanker=kohl) * * Revision 1.65 2001/09/25 21:20:19 pvmsrc * Minor TMPNAMFUN()/tmpnam() cleanup. * - moved macro def to pvm3.h, renamed PVMTNPMAN(). * - same for LEN_OF_TMP_NAM -> PVMTMPNAMLEN. * - mostly a huge waste of time, since *both* tmpnam() & mktemp() * produce the same "dangerous" warning message in Linux/gcc... * - damn. * (Spanker=kohl) * * Revision 1.64 2001/04/04 15:13:58 pvmsrc * Fixed pesky bug buried in pvmd opq... * - ack packets were being stuck at the end of the output queue, * where they could get delayed (not lost) long enough to trigger * a cascade of packet retries from remote pvmds. * - solution is to stick ack packets after new (zero-rtv) packets, * but before and locally queued retry packets (which can block * processing of the opq at a specified time...). * Yanked Bogus chdir() from WIN32 forkexec(). * - patch submitted by Peter J. Puchyr, SpaceTime Software * (Spanker=kohl) * * Revision 1.63 2001/02/07 23:15:51 pvmsrc * 2nd Half of CYGWIN Check-ins... * (Spanker=kohl) * * Revision 1.62 2001/02/02 14:50:26 pvmsrc * Win32 fixes & additions. * (Spanker=kohl) * * Revision 1.61 2000/10/11 20:50:24 pvmsrc * Yikes... * - fixed '//' comments in WIN32 forkexec() implementation to * '/ * * /'. * - apparently intereferes with SUN4SOL2 preprocessor? HOW BOGUS. * (Spanker=kohl) * * Revision 1.60 2000/02/18 15:48:43 pvmsrc * Commented out ECONNREFUSED check for sendto() in LINUX. * - apparently results from local networking problems... * - leave in code as a sign post for future occurrences. * (Spanker=kohl) * * Revision 1.59 2000/02/17 23:12:16 pvmsrc * *** Changes for new BEOLIN port *** * - MPP-like, similar to SP2, etc. * - submitted by Paul Springer . * - format-checked & cleaned up by Jeembo... :-) * (Spanker=kohl) * * Revision 1.58 2000/02/17 16:42:56 pvmsrc * Added hack to ignore errno=ECONNREFUSED from sendto() for Linux. * - apparently occurs intermittently on some setups... * - patch submitted by Russell Mora . * (Spanker=kohl) * * Revision 1.57 2000/02/16 22:01:25 pvmsrc * Fixed up #include stuff... * - use for IMA_TITN... * - #include before any NEEDMENDIAN #includes... * Added #ifndef NO_NETINET_TCP_H around for * archs that can't handle it... :-) * (Spanker=kohl) * * Revision 1.56 2000/02/11 21:04:03 pvmsrc * Added new PVMHOSTFILE env var. * - submitted by Anders Mundt Due . * (Spanker=kohl) * * Revision 1.55 2000/02/10 20:46:12 pvmsrc * Yanked char *pvmtmpspec for WIN32. * - not necessary, fixed string manip in log file name gen. * (Spanker=kohl) * * Revision 1.54 2000/02/07 22:22:10 pvmsrc * Hack to help with select()/fd_sets in WIN32: * - fd_set is *NOT* a bit field in WIN32, is a circular buffer. * - must check for !FD_ISSET() before FD_SET() else duplicate * entries possible, and fd_set buffer overflow/overwrite. * - similary, FD_ISSET() check before FD_CLR(). * - patch submitted by "Bruce W. Church" . * (Spanker=kohl) * * Revision 1.53 1999/07/08 19:00:07 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.52 1999/03/05 17:21:18 pvmsrc * improved to work with registry/environment on NT/win95-98 * and devstudio 5/6 * (Spanker=sscott) * * Revision 1.51 1999/02/09 23:07:18 pvmsrc * Don't re-invoke read_pvmregistry("PVM_ROOT")... * - use pvmgetroot(). * In varsub(), if read_pvmregistry() fails for substring, * try getenv() too just in case... * (Spanker=kohl) * * Revision 1.50 1999/02/09 20:11:00 pvmsrc * Typo in log message... * (Spanker=kohl) * * Revision 1.49 1998/11/20 20:06:38 pvmsrc * Changes so that win32 will compile & build. Also, common * Changes so that compiles & builds on NT. Also * common source on win32 & unix. * (spanker=sscott) * * Revision 1.48 1998/10/02 15:44:06 pvmsrc * Single source code merge of Win32 and Unix code. * (Spanker=sscott) * * Revision 1.47 1998/09/23 15:31:59 pvmsrc * Damn! A non-#ifdef WIN32-ed read_pvmregistry() call! Blarghhh... * (Spanker=kohl) * * Revision 1.46 1998/09/23 15:23:45 pvmsrc * changes to use WIN32 registry as per Markus. * ifdef in pvmd.c::colonsep() to include WIN32 and OS2 * (Spanker=phil) * * Revision 1.45 1998/08/13 18:32:49 pvmsrc * Added special case for AIX4SP2 arch with SOCKLENISUINT. * - on AIX 4.3 systems, I guess unsigned int is really * unsigned int, and not size_t... D-Oh! * - probably need a better constant name (or two) here... * (Spanker=kohl) * * Revision 1.44 1998/07/24 17:31:25 pvmsrc * Fixed use of PVM_TIMET stuff: * - on dorky systems (like LINUXALPHA) timeval->tv_sec could be an * int, while time_t is a long, so casting the &tnow.tv_sec ptr * blows chunks. * - e.g., check this date: Fri Oct 11 07:59:03 3386993 :-) * - use a temp var & cast the value before passing the ptr... * - thanks to Greg Lindahl (lindahl@cs.virginia.edu) for the patch. * (Spanker=kohl) * * Revision 1.43 1998/07/24 17:11:49 pvmsrc * Cleaned up use of SOCKLENISUINT / oslen. * - use oslen for every socket-related call: * * bind(), recvfrom(), getsockname() and accept(). * (Spanker=kohl) * * Revision 1.42 1998/06/03 18:46:37 pvmsrc * Enhanced spawning of default pluggable modules... * - created static env var name list "modulenames[]". * - replaced simple command name handling with acav() parsing... * - check for non-zero myhostpart to avoid re-spawning modules * in pvmd'... * (Spanker=kohl) * * Revision 1.41 1998/06/02 20:49:00 pvmsrc * Added new locl_spawn() routine for pvmd to spawn local system tasks. * - applied for new env vars interface to pluggable modules: * * $PVM_TASKER - defines tasker to spawn on pvmd startup. * * $PVM_HOSTER - defines hoster to spawn on pvmd startup. * * $PVM_RM - defines resource manager to spawn on pvmd startup. * (Spanker=kohl) * * Revision 1.40 1998/02/23 22:51:46 pvmsrc * Added AIX4SP2 stuff. * (Spanker=kohl) * * Revision 1.39 1998/01/28 21:27:35 pvmsrc * Leftover LINUX fixes: * - un-#ifdef-ed sendto() error ENOMEM for LINUX, should be O.K. for * every arch. * - also commented out #ifndef LINUX socket addressing stuff in * netinput(), looks a bit antiquated and seems to work just * fine without it - here's hoping. * (Spanker=kohl) * * Revision 1.38 1998/01/28 19:31:31 pvmsrc * Added new -DCTIMEISTIMET flag. * - the #if defined() list for PVM_TIMET was getting way * out of hand... :-) * (Spanker=kohl) * * Revision 1.37 1998/01/28 19:13:57 pvmsrc * Added new IMA_LINUXHPPA to #if cases... * (Spanker=kohl) * * Revision 1.36 1998/01/12 21:13:27 pvmsrc * Replaced inline constants with new task output op defines. * - TO_NEW == -2. * - TO_SPAWN == -1. * - TO_EOF == 0. * (Spanker=kohl) * * Revision 1.35 1997/12/01 19:20:51 pvmsrc * Replaced #ifdef IMA_OS2 fd_set declarations: * - new #ifdef FDSETNOTSTRUCT. * - choose between "fd_set foo" and "struct fd_set foo"... * (Spanker=kohl) * * Revision 1.34 1997/11/04 23:22:25 pvmsrc * Cleaned up fd_set stuff (hopefully). * Added IMA_LINUXALPHA to PVM_TIMET stuff. * (Spanker=kohl) * * Revision 1.33 1997/08/29 13:35:14 pvmsrc * OS2 Port Submitted by Bohumir Horeni, horeni@login.cz. * (Spanker=kohl) * * Revision 1.32 1997/08/26 22:54:02 pvmsrc * fixed Win32 slave_config * (Spanker=fischer) * * Revision 1.31 1997/07/30 19:01:21 pvmsrc * Markus Fixes. * * Revision 1.30 1997/07/23 14:37:24 pvmsrc * Added support for new UXPV arch. * * Revision 1.29 1997/07/16 21:10:41 pvmsrc * WIN32 Fixes - Markus. * * Revision 1.28 1997/07/02 20:27:29 pvmsrc * Fixed startup race on shmem to that a shmem task can get fully * configured before getting any messages. * This involved adding two states * TF_PRESHMCONN and TF_SHM. TF_PRESHMCONN indicates that messages * with MM_PRIO set can be sent to a task, but regular messages are * queued. This allows shmem tasks to be completely configured * before any messages flow. When the daemon changes the state from * TF_PRESHMCONN to TF_SHMCONN it calls shm_wrt_pkts to write any * packets that were queued before task state changed to TF_SHMCONN. * * Revision 1.27 1997/06/27 21:17:17 pvmsrc * Using sigset() to force daemon under SUNMP to catch SIGCLD. * * Revision 1.26 1997/06/27 19:26:09 pvmsrc * Integrated WIN32 changes. * * Revision 1.25 1997/06/24 20:37:56 pvmsrc * Installed new env var features: * - PVM_PATH overrides default execution path (but not hostfile ep=). * - PVM_WD overrides default working directory (but not hostfile wd=). * * Revision 1.24 1997/06/16 13:41:11 pvmsrc * forkexec() passes extra info to taskers. * * Revision 1.23 1997/06/12 20:14:57 pvmsrc * Added #define for MAXPATHLEN. * - fix submitted by Brian Forney (bforney@cray.com) * of Cray Research, Inc. * * Revision 1.22 1997/06/02 13:21:22 pvmsrc * Added TM_SHMCONN test in pkt_to_task so that remote tasks write to local * tasks via their shared memory instead of the t-d socket. * * Revision 1.21 1997/05/29 15:14:34 pvmsrc * Added IMA_SGIMP64 to the infamous PVM_TIMET #define list. :-) * * Revision 1.20 1997/05/27 14:49:25 pvmsrc * Added test for shmem and TF_SHMCONN to mesg_to_task(): * so that mpp_output is used insted of locloutput when a t-d * socket exists when tasks are connected via shared memory * correctly... * * Revision 1.19 1997/05/13 13:27:01 pvmsrc * Fixed up SGI64 crapola - PVM_TIMET -> time_t. * * Revision 1.18 1997/05/08 21:06:30 pvmsrc * defined PVM_TIMET to time_t for LINUX and LINUXSPARC * and PVM_TIMET to long for all others so * that calls to ctime don't generate warnings * * Revision 1.17 1997/05/07 21:19:19 pvmsrc * swapped logic around SOCKLENISINT so that it is now * the default path and SOCKLENISUINT is the compile-time * selected path. * * Now, AIX 4.1 will have to remove SOCKLENISUINT from * their AIXxxx.def configure files. * * Revision 1.16 1997/05/07 18:37:10 pvmsrc * AIX 3.2 vs 4.1 vs 4.2 problems resolved (I hope) * Define oslen as size_t with compile flag SOCKLENISINT * for AIX 4.1 to explicitly set to int. * To use flag - set in conf/AIX46K.def. * Tested with cc and gcc on all 3 OS versions. * * Revision 1.15 1997/05/05 18:51:16 pvmsrc * Removed Ifdefs so that select timeout was set properly for PGONs. * * Revision 1.14 1997/05/02 13:50:20 pvmsrc * Support for SP2MPI. call mpp_init() mpp_output() * * Revision 1.13 1997/04/30 21:26:24 pvmsrc * SGI Compiler Warning Cleanup. * * Revision 1.12 1997/04/21 14:58:25 pvmsrc * Changed #ifdefs that checked IMA_RS6K,IMA_SP2MPI & IMA_AIX46K * to see if select.h was needed into single define NEEDSSELECTH. * New archs need to set this in conf/ * * Revision 1.11 1997/04/03 16:13:55 pvmsrc * 1) Fixed sequence number rollover bug (apparent only when nopax > 1) * 2) Fixed queueing order of output pkts (opq). (apparent when nopax > 1) * Packets could be queued in reverse order causing the remote daemon * to reorder packets even when there were no transmission errors. * * Revision 1.10 1997/03/07 14:01:06 pvmsrc * Support for Mpps. * * Revision 1.9 1997/02/13 15:10:02 pvmsrc * Removed unnecessary extern for struct waitc *waitlist. * - now in global.h. * * Revision 1.8 1997/01/28 19:27:02 pvmsrc * New Copyright Notice & Authors. * * Revision 1.7 1996/11/26 19:18:33 pvmsrc * Added code to prevent multiple pvmds for a single user on one machine. * Define OVERLOADHOST if want to enable multiple pvmds. * * Revision 1.6 1996/10/25 13:57:59 pvmsrc * Replaced old #includes for protocol headers: * - , "ddpro.h", "tdpro.h" * With #include of new combined header: * - * * Revision 1.5 1996/10/24 21:31:36 pvmsrc * Moved #include "global.h" to below other #includes for typing. * Added #include (to get TEV_* constants). * Added decl for storing registered tracer info: * - struct Pvmtracer pvmtracer. * - init to { 0, 0, 0, 0, 0, 0, 0, 0, "" }. * Changed comparisons on tp->t_outtid: * - check for > 0, not just non-zero. * - to handle new case where task sets to -1 to deny external collect. * * Revision 1.4 1996/10/14 19:17:03 pvmsrc * Used ARCHFLAG SOCKLENISUINT where socket length is unsigned int * * Revision 1.3 1996/10/09 21:48:16 pvmsrc * Problem: * -------- * The problem was the result of AIX4.2 changing the expected datatype of * the XxxxLength parameter in the following system function calls: * * int bind (Socket, Name, NameLength) * int getsockname (Socket, Name, NameLength) * int recvfrom (Socket, Buffer, Length, Flags, From, FromLength) * int accept (Socket, Address, AddressLength) * * The compiler warning message generated was: * Function argument assignment between types "unsigned long*" and "int*" * is not allowed. * * Action: * ------- * In PVM functions where oslen was already declared_ * changed declaration from: int oslen; * to: unsigned int oslen; * * In PVM functions where a local "temporary" variable such as i, j, etc. * was used_ * added declaration of: unsigned int oslen; * and then changed to use oslen where necessary. * * Revision 1.2 1996/09/23 23:27:26 pvmsrc * Initial Creation - original pvmd.c. * * Revision 1.40 1995/11/02 16:29:24 manchek * added -t flag for test mode. * put back save under packet header in netoutput. * refragment in pkt_to_host now handles message header correctly * * Revision 1.39 1995/09/05 19:22:07 manchek * forgot ifdef for SP2MPI * * Revision 1.38 1995/07/28 20:52:01 manchek * missed changing src to pk_src in loclinpkt * * Revision 1.37 1995/07/28 16:40:59 manchek * wrap HASERRORVARS around errno declarations * * Revision 1.36 1995/07/24 19:52:02 manchek * message header no longer part of packet data, goes in pkt struct. * socket drivers in {locl,net}{in,out}put must strip and reconstitute headers. * no longer need to replicate first fragment of message to send, * or to save-under. * cleaned up line between loclinput and loclinpkt. * * Revision 1.35 1995/07/19 21:26:57 manchek * use new function pvmnametag instead of [dts]mname * * Revision 1.34 1995/07/18 17:02:03 manchek * added code to generate and check crc on each message (MCHECKSUM) * * Revision 1.33 1995/07/11 18:56:00 manchek * main prints PVMSOCK instead of master_config (after mpp_init) * * Revision 1.32 1995/07/05 16:20:39 manchek * work calls mpp_dredge for zombies if task with zero tid closes socket * (possibly a shared memory task exiting) * * Revision 1.31 1995/07/03 19:16:24 manchek * removed POWER4 ifdefs and misc. schmutz * * Revision 1.30 1995/06/28 15:27:33 manchek * pvmbailout doesn't set global bailing_out * * Revision 1.29 1995/06/16 16:28:35 manchek * (CSPP) CINDEX macro defined both in pvmd.c and system include file. * can undef CINDEX before we define it for us * * Revision 1.28 1995/06/02 17:51:44 manchek * added code to balance spawn (forks) on CSPP * * Revision 1.27 1995/05/30 17:46:59 manchek * Added ifdefs for SP2MPI arch * * Revision 1.26 1995/05/17 16:31:57 manchek * changed global mytid to pvmmytid. * pvmbailout sets global bailing_out (used by shared memory code). * use PVMDDEBUG envar to set pvmdebmask at startup. * added new debug classes. * use FDSETISINT. * on LINUX systems, check sendto for ENOMEM. * * Revision 1.25 1995/02/06 22:40:11 manchek * shared memory ports call mpp_setmtu before slave_config * * Revision 1.24 1995/02/06 18:52:24 manchek * added debugging prints for when main select in work fails (solaris) * * Revision 1.23 1995/02/06 05:01:28 manchek * hmm * * Revision 1.22 1995/02/03 16:45:27 manchek * touch up reap - define rus as int if we don't think struct rusage exists * * Revision 1.21 1995/02/01 21:31:23 manchek * added clear_opq_of, called when host is deleted from table or pvmd' exits * * Revision 1.20 1994/12/20 16:40:35 manchek * use O_NONBLOCK for RS6K * * Revision 1.19 1994/11/08 19:05:07 manchek * mpp fix? * * Revision 1.18 1994/11/08 15:30:51 manchek * shared memory cleanup * * Revision 1.17 1994/10/15 19:27:02 manchek * make wrk_fds_init(), use instead of FD_ZERO. * don't send FIN|ACK to ourself in bailout. * don't clean up task until SIGCHLD if TF_FORKD set. * check newhosts when deleting host. * cast message tags for comparison as integers. * in beprime() call task_init instead of trying to clean up * * Revision 1.16 1994/09/02 15:48:17 manchek * added UXPM ifdef to parallel SUN4SOL2 * * Revision 1.15 1994/09/02 15:27:55 manchek * forgot to inc refcount of nth fragment in sendmessage * * Revision 1.14 1994/07/18 19:21:51 manchek * added PDMWAITC. * fix to call write() with max 4096 length for RS6K * * Revision 1.13 1994/06/30 21:36:56 manchek * don't check remote sockaddr in netinput() on LINUX * * Revision 1.12 1994/06/04 21:45:10 manchek * added unix domain sockets * * Revision 1.11 1994/06/03 20:38:22 manchek * version 3.3.0 * * Revision 1.10 1993/12/20 15:39:28 manchek * patch 6 from wcj * * Revision 1.9 1993/10/25 20:51:11 manchek * make sure pvmd doesn't use 0..2 for sockets, etc. - open /dev/null. * added code to change process group/disassoc. from tty (TTYDIS). * ping other pvmds also when run state is PVMDHTUPD * * Revision 1.8 1993/10/12 14:18:37 manchek * fixed bug in locloutput() - hung if write() returned 0 * * Revision 1.7 1993/10/04 20:27:42 manchek * renamed useruid to pvm_useruid for compat with libpvm * * Revision 1.6 1993/10/04 19:17:45 manchek * on Solaris, sendto() can return ECHILD. Hahahahahaha!!! * * Revision 1.5 1993/10/04 19:12:25 manchek * hd_txseq wasn't wrapped properly with NEXTSEQNUM * * Revision 1.4 1993/09/23 20:36:19 manchek * fixed broken mca lookup * * Revision 1.3 1993/09/22 19:14:47 manchek * added network resend statistic. * removed redundant code in netinpkt() where it finds mca * * Revision 1.2 1993/09/16 21:45:32 manchek * replaced reap() - now uses SYSVSIGNAL and NOWAIT3 macros * * Revision 1.1 1993/08/30 23:26:50 manchek * Initial revision * */ #include #ifndef WIN32 #include #endif #ifdef IMA_TITN #include #else #include #endif #ifdef NEEDMENDIAN #include #endif #ifdef NEEDENDIAN #include #endif #ifdef NEEDSENDIAN #include #endif #include #if defined(WIN32) || defined(CYGWIN) #include "..\xdr\types.h" #include "..\xdr\xdr.h" #else #include #include #endif #ifdef WIN32 #include "pvmwin.h" #include #else #include #include #include #include #include #include #ifndef NO_NETINET_TCP_H #include #endif #include #include #endif #ifdef IMA_BEOSCYLD #include #endif #ifndef IMA_TITN #ifndef WIN32 #include #endif #endif #ifndef NOWAIT3 #include #endif #ifdef NEEDSSELECTH #include #endif #include #ifndef NOUNIXDOM #include #endif #ifdef IMA_LINUXALPHA #include #endif #include #include #include #include /* Must come before local CINDEX macro definition */ #if defined(IMA_CSPP) && defined(BALANCED_SPAWN) #include #include #include #undef CINDEX #endif #ifdef SYSVSTR #include #define CINDEX(s,c) strchr(s,c) #else #include #define CINDEX(s,c) index(s,c) #endif #include #include "pvmalloc.h" #include "host.h" #include "pvmdabuf.h" #include "pvmfrag.h" #include "pmsg.h" #include "pkt.h" #include "task.h" #include "waitc.h" #include "listmac.h" #include "tvdefs.h" #if defined(IMA_PGON) || defined(IMA_I860) || defined(IMA_CM5) \ || defined(SHMEM) || defined(IMA_SP2MPI) \ || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) \ || defined(IMA_BEOLIN) #include "pvmdmp.h" #endif #include "bfunc.h" #include #include "global.h" #ifdef IMA_CRAY #define MAXPATHLEN PATH_MAX+1 #endif #if defined(IMA_CRAY) || defined(IMA_CRAY2) || defined(IMA_I860) || defined(IMA_E88K) || defined(IMA_SCO) #ifndef MAXPATHLEN #define MAXPATHLEN CANBSIZ #endif #endif #ifndef max #define max(a,b) ((a)>(b)?(a):(b)) #endif #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif #ifndef TTYDIS #define TTYDIS 0 #endif #ifndef SOMAXCONN #define SOMAXCONN 5 #endif #ifdef STATISTICS struct statistics { int selneg, selzer, selrdy; /* neg, zero, ready selects */ int rdneg, rdzer, rdok; /* neg, zero, positive reads */ int wrneg, wrzer, wrshr, wrok; /* neg, zero, short, ok writes */ int sdneg, sdok; /* neg, ok sendtos */ int rfok; /* ok recvfroms */ int refrag; /* refragmented frags */ int netret; /* network resends */ }; struct statistics stats; #endif struct deaddata { int dd_pid; /* process id */ int dd_es; /* unix exit status */ struct timeval dd_ut; /* user time used */ struct timeval dd_st; /* system time used */ }; void catch(); char *debug_flags(); char *pvmnametag(); void biteme(); void evilsig(); char *getenv(); char *inadport_decimal(); char *inadport_hex(); void pvmbailout(); char *pvmdsockfile(); char *pvmgethome(); char *pvmgetroot(); void reap(); void i_dump(); void hex_inadport __ProtoGlarp__ (( char *, struct sockaddr_in * )); void mesg_rewind __ProtoGlarp__ (( struct pmsg * )); void locl_spawn(); /* void make_valid(char *n); sls */ void make_valid(); #ifndef WIN32 void check_ext_input(); #endif #ifdef CTIMEISTIMET #define PVM_TIMET time_t #else #define PVM_TIMET long #endif #if defined(IMA_PGON) && !defined(IMA_MPP) #define IMA_MPP #endif #ifdef WIN32 char *read_pvmregistry __ProtoGlarp__(( const char * )); #endif /*************** ** Globals ** ** ** ***************/ #ifndef HASERRORVARS extern int errno; #endif extern struct task *locltasks; /* from task.c */ extern int log_fd; /* from logging.c */ char **epaths = 0; /* exec search path */ char *debugger = 0; /* debugger executable */ int pvmdebmask = 0; /* which debugging info */ struct htab *filehosts = 0; /* advisory host table from hostfile */ struct htab *hosts = 0; /* active host table */ int hostertid = 0; /* slave pvmd starter task */ char *loclsnam = 0; /* t-d socket or addr file path */ int loclsock = -1; /* pvmd-task master tcp socket */ #ifndef NOUNIXDOM char *loclspath = 0; /* t-d socket path */ #endif char *myarchname = ARCHCLASS; int myhostpart = 0; /* host number shifted to tid host field */ int pvmfrgsiz = UDPMAXLEN; /* message frag length (to pack) */ int pvmmydsig = 0; /* host native data enc */ int pvmmytid = 0; /* this pvmd tid */ int pvmmyupid = -1; /* pvmd pid */ int netsock = -1; /* host-host udp socket */ int nopax = 1; /* number of outstanding pkts on d-d link */ struct htab *newhosts = 0; /* hosts being added by pvmd' */ struct htab *oldhosts = 0; /* real host table (for pvmd') */ int pvmudpmtu = UDPMAXLEN; /* local UDP MTU */ int ppnetsock = -1; /* pvmd' host-host udp socket */ int pprime = 0; /* pvmd' pid for when we're forked */ int runstate = 0; /* pvmd run state */ int pvmschedtid = 0; /* scheduler task id */ int taskertid = 0; /* task starter task */ struct Pvmtracer pvmtracer = /* task tracer info struct */ { 0, 0, 0, 0, 0, 0, 0, 0, "" }; int tidhmask = TIDHOST; /* mask for host field of tids */ int tidlmask = TIDLOCAL; /* mask for local field of tids */ int pvm_useruid = -1; /* our uid */ char *username = 0; /* our loginname */ #ifdef WIN32 /* the userid is not available in WIN 32! */ /* some useless binary sid struct */ int system_loser_win=FALSE; int nAlert=SO_SYNCHRONOUS_NONALERT; int nFileHandle; WSADATA WSAData; LPOSVERSIONINFO osinfo=0; BOOL os_is_NT=FALSE; #endif /*************** ** Private ** ** ** ***************/ static int totprobes = 0; static int altprobe = 100; /* ratio of mpp_input() to select for pgons */ static struct deaddata *deads = 0; /* circ queue of dead task data */ static int ndead = 0; /* len of deads */ static struct pkt *opq = 0; /* outstanding pkt q to all hosts */ static int rdead = 0; /* read ptr for deads */ static int slavemode = 0; /* started by master pvmd */ static struct pmsg *addmesg = 0; /* message to self to add slaves */ static int wdead = 0; /* write ptr for deads */ #ifdef FDSETNOTSTRUCT static fd_set wrk_rfds; /* fd_sets for select() in work() */ static fd_set wrk_wfds; /* static fd_set wrk_efds; */ #else static struct fd_set wrk_rfds; /* fd_sets for select() in work() */ static struct fd_set wrk_wfds; /* static struct fd_set wrk_efds; */ #endif static int wrk_nfds = 0; /* 1 + highest bit set in fds */ int pvm_max_ntasks = 0; /* bound on total number of tasks */ /* allowed to attach to pvmd... */ /* == 0 for no bound... */ static char *modulenames[] = { "PVM_TASKER", "PVM_TRACER", "PVM_HOSTER", "PVM_RM", 0 }; main(argc, argv) int argc; char **argv; { int i, j; char *name = ""; struct passwd *pe; int testmode = 0; struct timeval tnow; char buf[128]; #ifndef WIN32 /* check for extension config options */ check_ext_input(); /* make sure 0, 1, 2 are in use */ (void)open("/dev/null", O_RDONLY, 0); (void)open("/dev/null", O_RDONLY, 0); (void)open("/dev/null", O_RDONLY, 0); #else /* WSAStartup has to be called before any socket command */ /* can be executed. Why ? Ask Bill */ if (WSAStartup(0x0101, &WSAData) != 0) { printf("\nWSAStartup() failed\n"); ExitProcess(1); } setsockopt(INVALID_SOCKET,SOL_SOCKET,SO_OPENTYPE, (char *)&nAlert,sizeof(int)); osinfo=malloc(sizeof(OSVERSIONINFO)); osinfo->dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(osinfo); os_is_NT= ( osinfo->dwPlatformId == VER_PLATFORM_WIN32_NT); #endif { char *p; if (p = getenv("PVMDDEBUG")) pvmdebmask = pvmstrtoi(p); } #ifndef WIN32 if ((pvm_useruid = getuid()) == -1) { pvmlogerror("main() can't getuid()\n"); pvmbailout(0); } #else username = MyGetUserName(); #endif pvmsetlog(3); #ifndef WIN32 if (pe = getpwuid(pvm_useruid)) username = STRALLOC(pe->pw_name); else pvmlogerror("main() can't getpwuid\n"); endpwent(); #endif #ifdef WIN32 if ((pvmmyupid = getpid()) == -1) { pvmlogerror("main() can't getpid() %d \n",GetLastError()); pvmbailout(0); } #else if ((pvmmyupid = getpid()) == -1) { pvmlogerror("main() can't getpid()\n"); pvmbailout(0); } #endif (void)pvmgetroot(); /* fail here if we can't */ sprintf(buf, "PVM_ARCH=%s", myarchname); pvmputenv(STRALLOC(buf)); pvmmydsig = pvmgetdsig(); ppi_config(argc, argv); #if defined(IMA_PGON) || defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) \ || defined(IMA_AIX5SP2) || defined(IMA_BEOLIN) mpp_init(&argc, argv); #endif for (i = j = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'd': pvmdebmask = pvmstrtoi(argv[i] + 2); break; case 'n': name = argv[i] + 2; break; case 'S': argv[j++] = argv[i]; case 's': slavemode = 1; break; case 't': testmode = 1; break; #ifdef WIN32 case 'u': if (os_is_NT==FALSE) { /* someone is on win95 ... */ argv[i]++;argv[i]++; strcpy(username,argv[i]); } else if (strcmp(strcat("-u",username),argv[i])) { fprintf(stderr, "Provided Username(%s) does not match ", username); fprintf(stderr,"with OS account(%s).\n", argv[i]); fprintf(stderr,"Wrong rshd ?!\n"); exit(1); } break; #endif default: argv[j++] = argv[i]; } } else { argv[j++] = argv[i]; } } argc = j; if (pvmdebmask) { pvmlogprintf("version %s\n", PVM_VER); pvmlogprintf("ddpro %d tdpro %d\n", DDPROTOCOL, TDPROTOCOL); pvmlogprintf("main() debug mask is 0x%x (%s)\n", pvmdebmask, debug_flags(pvmdebmask)); } if (!*name) { if (gethostname(buf, sizeof(buf)-1) == -1) { pvmlogerror("main() can't gethostname()\n"); pvmbailout(0); } name = buf; } if (testmode) { PVM_TIMET time_temp; gettimeofday(&tnow, (struct timezone*)0); pvmlogprintf("version %s ddpro %d tdpro %d sdpro %d\n", PVM_VER, DDPROTOCOL, TDPROTOCOL, SDPROTOCOL); time_temp = (PVM_TIMET) tnow.tv_sec; pvmlogprintf(ctime(&time_temp)); for (i = 0; i < argc; i++) pvmlogprintf("argv[%d]=\"%s\"\n", i, argv[i]); exit(0); } { char *p; if (p = getenv("PVM_MAX_TASKS")) { pvm_max_ntasks = atoi(p); if (pvm_max_ntasks < 0) pvm_max_ntasks = 0; } } if (slavemode) /* slave pvmd */ slave_config(name, argc, argv); else /* master pvmd */ master_config(name, argc, argv); #if TTYDIS & 8 setsid(); #endif #if TTYDIS & 4 setpgid(0, 0); #endif #if TTYDIS & 2 setpgrp(0, 0); #endif #if TTYDIS & 1 if ((i = open("/dev/tty", O_RDWR, 0)) != -1) { (void)ioctl(i, TIOCNOTTY, 0); (void)close(i); } #endif myhostpart = hosts->ht_local << (ffs(tidhmask) - 1); pvmmytid = myhostpart | TIDPVMD; ndead = 1000; /* XXX hum, static limit makes this easy to do */ /* deads = TALLOC(ndead, int, "pids"); */ deads = TALLOC(ndead, struct deaddata, "dead"); BZERO((char*)deads, ndead * sizeof(struct deaddata)); #ifndef WIN32 /* no signaling in win32 because no parent child relation ... :-( */ #ifndef IMA_I860 /* this signal interferes with getcube() on I860 */ #ifdef SYSVSIGNAL #ifndef IMA_BEOSCYLD (void)signal(SIGCLD, reap); #endif #ifdef IMA_SUNMP sigset(SIGCLD, reap); /* yep we go really want to catch our kids */ #endif #else (void)signal(SIGCHLD, reap); #endif /* SYSVSIGNAL */ #endif /*IMA_I860*/ #endif if (signal(SIGINT, SIG_IGN) != SIG_IGN) #ifdef WIN32 (void)signal(SIGINT, (void*) catch); #else (void)signal(SIGINT, catch); #endif if (signal(SIGTERM, SIG_IGN) != SIG_IGN) #ifdef WIN32 (void)signal(SIGTERM, (void *) catch); #else (void)signal(SIGTERM, catch); #endif #ifndef WIN32 (void)signal(SIGHUP, SIG_IGN); (void)signal(SIGPIPE, SIG_IGN); #endif #ifndef WIN32 (void)signal(SIGFPE, evilsig); (void)signal(SIGILL, evilsig); #else (void)signal(SIGFPE, (void *)evilsig); (void)signal(SIGILL, (void *)evilsig); #endif #ifdef SIGBUS (void)signal(SIGBUS, evilsig); #endif #ifndef WIN32 (void)signal(SIGSEGV, evilsig); #else (void)signal(SIGSEGV, (void *)evilsig); #endif #ifdef SIGSYS (void)signal(SIGSYS, evilsig); #endif #ifdef SIGDANGER (void)signal(SIGDANGER, biteme); #endif #ifdef STATISTICS reset_statistics(); #endif task_init(); wait_init(myhostpart, TIDLOCAL); mb_init(); ppi_init(); opq = pk_new(0); opq->pk_tlink = opq->pk_trlink = opq; /* print local socket address on stdout in case someone cares */ if (!slavemode) { printf("%s\n", getenv("PVMSOCK")); fflush(stdout); } /* XXX hack to start slaves automatically */ if (!slavemode && filehosts) { struct hostd *hp; int hh; int n = 0; for (hh = filehosts->ht_last; hh >= 1; hh--) if ((hp = filehosts->ht_hosts[hh]) && !(hp->hd_flag & HF_NOSTART)) n++; if (n) { addmesg = mesg_new(0); addmesg->m_tag = DM_ADD; pkint(addmesg, n); for (hh = 1; hh <= filehosts->ht_last; hh++) if ((hp = filehosts->ht_hosts[hh]) && !(hp->hd_flag & HF_NOSTART)) pkstr(addmesg, hp->hd_name); addmesg->m_dst = TIDPVMD; } } work(); pvmbailout(0); /* not reached */ exit(0); } #ifndef WIN32 void check_ext_input() { char input[256]; char *ptr, *ptr2; char c; int flags; int i; /* Set stdin Non-Blocking */ flags = fcntl( 0, F_GETFL, 0 ); fcntl( 0, F_SETFL, flags | O_NDELAY ); /* Test for Input */ i = 0; while ( (int)(input[i] = getc( stdin )) != (char) EOF && input[i] != '\n' && i < 255 ) i++; input[i] = '\0'; /* Parse Extension Options Here */ if ( i ) { ptr = input; while ( *ptr != '\0' ) { /* Virtual Machine ID */ if ( !strncmp( "PVM_VMID=", ptr, 9 ) ) { ptr2 = ptr + 9; while ( *ptr2 != ' ' && *ptr2 != '\t' && *ptr2 != '\0' ) ptr2++; c = *ptr2; *ptr2 = '\0'; pvmputenv(STRALLOC(ptr)); *ptr2 = c; ptr = ptr2; } /* Move Past Unknown Options */ else while ( *ptr != ' ' && *ptr != '\t' && *ptr != '\0' ) ptr++; /* Advance to Next Option */ while ( *ptr == ' ' || *ptr == '\t' ) ptr++; } } /* Reset stdin to Blocking */ fcntl( 0, F_SETFL, flags ); } #endif static char *ffnames[] = { "SOM", "EOM", "DAT", "FIN", "ACK" }; char * pkt_flags(ff) int ff; { static char buf[64]; int bit, i; buf[0] = 0; for (bit = 1, i = 0; i < sizeof(ffnames)/sizeof(ffnames[0]); i++, bit *= 2) if (ff & bit) { if (buf[0]) strcat(buf, ","); strcat(buf, ffnames[i]); } if (!buf[0]) strcpy(buf, "0"); return buf; } void evilsig(sig) int sig; { if (runstate == PVMDISTASK) exit(sig); (void)signal(SIGILL, SIG_DFL); (void)signal(SIGFPE, SIG_DFL); #ifdef SIGBUS (void)signal(SIGBUS, SIG_DFL); #endif (void)signal(SIGSEGV, SIG_DFL); #ifdef SIGSYS (void)signal(SIGSYS, SIG_DFL); #endif (void)signal(SIGINT, SIG_DFL); (void)signal(SIGTERM, SIG_DFL); #ifndef WIN32 (void)signal(SIGHUP, SIG_DFL); (void)signal(SIGPIPE, SIG_DFL); #endif #ifdef SYSVSIGNAL (void)signal(SIGCLD, SIG_DFL); #else #ifndef WIN32 (void)signal(SIGCHLD, SIG_DFL); #endif #endif pvmlogprintf("evilsig() caught signal %d\n", sig); i_dump(1); /* abort(); */ pvmbailout(-sig); } void catch(sig) int sig; { if (runstate == PVMDISTASK) exit(sig); (void)signal(SIGINT, SIG_DFL); (void)signal(SIGTERM, SIG_DFL); pvmlogprintf("catch() caught signal %d\n", sig); pvmbailout(sig); } #ifdef SIGDANGER void biteme(sig) int sig; { pvmlogprintf("biteme() caught signal %d and spaced it.\n", sig); pvmlogerror("the mad fools, when will they learn?\n"); #ifdef SYSVSIGNAL (void)signal(SIGDANGER, biteme); #endif } #endif /*SIGDANGER*/ /* reap() * * Child process has exited. Put its pid in the fifo of tasks * to be cleaned up (in the work loop). */ void reap(sig) int sig; { int pid; int es = 0; #ifndef WIN32 #ifndef NOWAIT3 #if defined(RUSAGE_SELF) struct rusage rus; #else int rus; #endif #endif sig = sig; #ifdef NOWAIT3 #ifdef NOWAITPID if ((pid = wait(&es)) > 0) #else #ifdef IMA_BEOSCYLD if ((pid = waitpid(-1, &es, WNOHANG)) > 0) #else while ((pid = waitpid(-1, &es, WNOHANG)) > 0) #endif #endif #else /*NOWAIT3*/ while ((pid = wait3(&es, WNOHANG, &rus)) > 0) #endif /*NOWAIT3*/ { #if !defined(NOWAIT3) && defined(RUSAGE_SELF) deads[wdead].dd_ut = rus.ru_utime; deads[wdead].dd_st = rus.ru_stime; #else deads[wdead].dd_ut.tv_sec = 0; deads[wdead].dd_ut.tv_usec = 0; deads[wdead].dd_st.tv_sec = 0; deads[wdead].dd_st.tv_usec = 0; #endif deads[wdead].dd_pid = pid; deads[wdead].dd_es = es; if (++wdead >= ndead) wdead = 0; } #ifdef SYSVSIGNAL #ifndef IMA_BEOSCYLD (void)signal(SIGCLD, reap); #endif #endif #endif } /* pvmbailout() * * We're hosed. Clean up as much as possible and exit. */ void pvmbailout(n) int n; { struct task *tp; pvmlogprintf("pvmbailout(%d)\n", n); /* sockaddr file */ if (loclsnam) (void)unlink(loclsnam); /* kill local tasks */ #ifdef SHMEM mpp_cleanup(); #endif if (locltasks) for (tp = locltasks->t_link; tp != locltasks; tp = tp->t_link) { if (tp->t_pid) #ifndef WIN32 #ifdef IMA_OS2 (void)os2_kill(tp->t_pid, SIGTERM); #else (void)kill(tp->t_pid, SIGTERM); #endif #else (void)kill(tp->t_pid,tp->t_handle,SIGTERM); #endif if (tp->t_authnam) (void)unlink(tp->t_authnam); } /* shutdown slave pvmds / notify master */ if (netsock != -1) { char dummy[DDFRAGHDR]; int hh; struct hostd *hp; if (pvmdebmask) pvmlogerror("sending FIN|ACK to all pvmds\n"); for (hh = hosts->ht_last; hh >= 1; hh--) if ((hp = hosts->ht_hosts[hh]) && hp->hd_hostpart != myhostpart) { pvmput32(dummy, hp->hd_hostpart | TIDPVMD); pvmput32(dummy + 4, myhostpart | TIDPVMD); pvmput16(dummy + 8, 0); pvmput16(dummy + 10, 0); pvmput8(dummy + 12, FFFIN|FFACK); sendto(netsock, dummy, DDFRAGHDR, 0, (struct sockaddr*)&hp->hd_sad, sizeof(hp->hd_sad)); } } #ifndef NOUNIXDOM if (loclspath) (void)unlink(loclspath); #endif if (n < 0) abort(); exit(n); } void wrk_fds_init() { wrk_nfds = 0; FD_ZERO(&wrk_rfds); FD_ZERO(&wrk_wfds); /* FD_ZERO(&wrk_efds); */ } wrk_fds_add(fd, sets) int fd; /* the fd */ int sets; /* which sets */ { #ifdef SANITY #ifndef WIN32 if (fd < 0 || fd >= FD_SETSIZE) { pvmlogprintf("wrk_fds_add() bad fd %d\n", fd); return 1; } #endif #endif if (sets & 1) if ( !FD_ISSET(fd, &wrk_rfds) ) { FD_SET(fd, &wrk_rfds); #ifdef WIN32 wrk_nfds++; #endif } if (sets & 2) if ( !FD_ISSET(fd, &wrk_wfds) ) { FD_SET(fd, &wrk_wfds); #ifdef WIN32 if ( !(sets & 1) ) wrk_nfds++; #endif } /* if (sets & 4) if ( !FD_ISSET(fd, &wrk_efds) ) { FD_SET(fd, &wrk_efds); #ifdef WIN32 wrk_nefds++; #endif } */ #ifndef WIN32 /* if this is new highest, adjust nfds */ if (fd >= wrk_nfds) wrk_nfds = fd + 1; #endif return 0; } wrk_fds_delete(fd, sets) int fd; /* the fd */ int sets; /* which sets */ { #ifdef SANITY #ifndef WIN32 if (fd < 0 || fd >= FD_SETSIZE) { pvmlogprintf("wrk_fds_delete() bad fd %d\n", fd); return 1; } #endif #endif if (sets & 1) if ( FD_ISSET(fd, &wrk_rfds) ) { FD_CLR(fd, &wrk_rfds); #ifdef WIN32 wrk_nfds--; #endif } if (sets & 2) if ( FD_ISSET(fd, &wrk_wfds) ) { FD_CLR(fd, &wrk_wfds); #ifdef WIN32 if ( !(sets & 1) ) wrk_nfds--; #endif } /* if (sets & 4) if ( FD_ISSET(fd, &wrk_efds) ) { FD_CLR(fd, &wrk_efds); #ifdef WIN32 wrk_nefds--; #endif } */ #ifndef WIN32 /* if this was highest, may have to adjust nfds to new highest */ if (fd + 1 == wrk_nfds) while (wrk_nfds > 0) { wrk_nfds--; if (FD_ISSET(wrk_nfds, &wrk_rfds) || FD_ISSET(wrk_nfds, &wrk_wfds) /* || FD_ISSET(wrk_nfds, &wrk_efds) */ ) { wrk_nfds++; break; } } #endif return 0; } /* clear_opq_of() * * Clear packets dst for host in opq but _not_ in host hd_opq. */ int clear_opq_of(tid) int tid; /* host */ { struct pkt *pp, *pp2; for (pp = opq->pk_tlink; pp != opq; pp = pp->pk_tlink) { if (pp->pk_dst == tid && !pp->pk_link) { pp2 = pp->pk_trlink; LISTDELETE(pp, pk_tlink, pk_trlink); pk_free(pp); pp = pp2; } } return 0; } /* work() * * The whole sausage */ work() { static int lastpinged = 0; /* host that got last keepalive msg */ #ifdef FDSETNOTSTRUCT fd_set rfds, wfds; /* result of select */ /* fd_set efds; */ #else struct fd_set rfds, wfds; /* result of select */ /* struct fd_set efds; */ #endif int nrdy; /* number of fds ready after select */ struct timeval tbail; /* time to bail if state = STARTUP */ struct timeval tping; /* time to send next keepalive packet */ struct timeval tnow; struct timeval tout; struct pmsg *mp; struct task *tp; struct hostd *hp; #if defined(IMA_PGON) || defined(IMA_I860) || defined(SHMEM) int nodemsg = 0; #if defined(IMA_PGON) struct timeval tpgon; /* time to spend in paragon select */ double tbpl; /* time at beginning of probe loop */ double toutpl; /* timeout in the probe loop */ int timed_out; extern double dclock(); #endif #endif #ifdef SHMEM int someclosed; #endif gettimeofday(&tnow, (struct timezone*)0); if (pvmdebmask || myhostpart) { PVM_TIMET time_temp; pvmlogprintf("%s (%s) %s %s\n", hosts->ht_hosts[hosts->ht_local]->hd_name, inadport_decimal(&hosts->ht_hosts[hosts->ht_local]->hd_sad), myarchname, PVM_VER); pvmlogprintf("ready "); time_temp = (PVM_TIMET) tnow.tv_sec; pvmlogprintf(ctime(&time_temp)); } /* * check for default plug-in modules (& start them) * (only if pvmd, not for pvmd'...) */ if ( myhostpart ) { char *av[5]; char *buf; char *cmd; int ac; int i; for ( i=0 ; modulenames[i] ; i++ ) { cmd = getenv( modulenames[i] ); if ( cmd != NULL ) { buf = STRALLOC( cmd ); ac = sizeof(av)/sizeof(av[0]); if (!buf || acav( buf, &ac, av )) { pvmlogprintf( "$%s: Line Too Long \"%s\".\n", modulenames[i], cmd ); } else { av[ ac ] = (char *) NULL; locl_spawn( av[0], av + 1 ); } if (buf) PVM_FREE( buf ); } } } /* * remind myself to start those pesky slave pvmds */ if (addmesg) { struct pmsg *mp = addmesg; addmesg = 0; sendmessage(mp); } /* * init bail (for PVMDSTARTUP) and ping times */ pvmgetclock(&tnow); tout.tv_sec = DDBAILTIME; tout.tv_usec = 0; TVXADDY(&tbail, &tnow, &tout); tout.tv_sec = DDPINGTIME; tout.tv_usec = 0; TVXADDY(&tping, &tnow, &tout); /* init select fd sets */ wrk_fds_init(); if (loclsock >= 0) wrk_fds_add(loclsock, 1); wrk_fds_add(netsock, 1); for (; ; ) { /* * clean up after any tasks that we got SIGCHLDs for */ #ifdef IMA_BEOSCYLD reap(SIGCLD); #endif while (rdead != wdead) { if (deads[rdead].dd_pid == pprime) { int cc; #ifdef SOCKLENISUINT #if defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) \ || defined(IMA_AIX56K64) || defined(IMA_LINUXALPHA) unsigned int oslen; #else size_t oslen; #endif #else int oslen; #endif struct sockaddr_in osad; struct timeval t; char buf[DDFRAGHDR]; hostfailentry(hosts->ht_hosts[0]); clear_opq_of((int)(TIDPVMD | hosts->ht_hosts[0]->hd_hostpart)); pprime = 0; while (1) { FD_ZERO(&rfds); FD_SET(ppnetsock, &rfds); t.tv_sec = 0; t.tv_usec = 0; cc = select(ppnetsock + 1, #ifdef FDSETISINT (int *)&rfds, (int *)0, (int *)0, #else (fd_set *)&rfds, (fd_set *)0, (fd_set *)0, #endif &t); if (cc == 1) { oslen = sizeof(osad); recvfrom(ppnetsock, buf, sizeof(buf), 0, (struct sockaddr*)&osad, &oslen); } else if (cc != -1 || errno != EINTR) break; } } else { if (tp = task_findpid(deads[rdead].dd_pid)) { /* check for output one last time XXX this could be cleaner by going through main select again XXX before flushing the task */ tp->t_status = deads[rdead].dd_es; tp->t_utime = deads[rdead].dd_ut; tp->t_stime = deads[rdead].dd_st; while (tp->t_out >= 0) { #ifdef FDSETNOTSTRUCT fd_set rfds; #else struct fd_set rfds; #endif FD_ZERO(&rfds); FD_SET(tp->t_out, &rfds); TVCLEAR(&tout); if (select(tp->t_out + 1, #ifdef FDSETISINT (int *)&rfds, (int *)0, (int *)0, #else (fd_set *)&rfds, (fd_set *)0, (fd_set *)0, #endif &tout) == 1) loclstout(tp); else break; } #if defined(IMA_PGON) || defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) \ || defined(IMA_AIX5SP2) || defined(IMA_BEOLIN) mpp_free(tp); #endif task_cleanup(tp); task_free(tp); } } if (++rdead >= ndead) rdead = 0; } netoutput(); if (runstate == PVMDHALTING) { pvmlogerror("work() pvmd halting\n"); pvmbailout(0); } /* bail if new slave and haven't been configured for too long */ pvmgetclock(&tnow); if (runstate == PVMDSTARTUP && TVXLTY(&tbail, &tnow)) { pvmlogerror("work() run = STARTUP, timed out waiting for master\n"); pvmbailout(0); } /* * send keepalive message to remote pvmd once in a while */ if (TVXLTY(&tping, &tnow)) { if (pvmdebmask & (PDMPACKET|PDMSELECT)) pvmlogerror("work() ping timer\n"); if (runstate == PVMDNORMAL || runstate == PVMDHTUPD) { do { if (++lastpinged > hosts->ht_last) lastpinged = 1; } while (!(hp = hosts->ht_hosts[lastpinged])); if (hp->hd_hostpart != myhostpart && hp->hd_txq->pk_link == hp->hd_txq) { mp = mesg_new(0); mp->m_tag = DM_NULL; mp->m_dst = hp->hd_hostpart | TIDPVMD; sendmessage(mp); } } tout.tv_sec = DDPINGTIME; tout.tv_usec = 0; TVXADDY(&tping, &tnow, &tout); } /* * figure select timeout */ if (opq->pk_tlink == opq) tout = tping; else tout = opq->pk_tlink->pk_rtv; if (TVXLTY(&tout, &tnow)) { TVCLEAR(&tout); } else { TVXSUBY(&tout, &tout, &tnow); } if (pvmdebmask & PDMSELECT) { pvmlogprintf("work() select tout is %d.%06d\n", tout.tv_sec, tout.tv_usec); } #ifdef SHMEM if ((nodemsg = mpp_probe()) == 1) { mpp_input(); TVCLEAR(&tout); } #endif rfds = wrk_rfds; wfds = wrk_wfds; /* efds = wrk_efds; */ if (pvmdebmask & PDMSELECT) { pvmlogprintf("work() wrk_nfds=%d\n", wrk_nfds); print_fdset("work() rfds=", wrk_nfds, &rfds); print_fdset("work() wfds=", wrk_nfds, &wfds); } #if !defined(IMA_PGON) && !defined(IMA_I860) if ((nrdy = select(wrk_nfds, #ifdef FDSETISINT (int *)&rfds, (int *)&wfds, (int *)0, #else (fd_set *)&rfds, (fd_set *)&wfds, (fd_set *)0, #endif &tout)) == -1) { if (errno != EINTR) { pvmlogperror("work() select"); pvmlogprintf(" wrk_nfds=%d\n", wrk_nfds); print_fdset(" rfds=", wrk_nfds, &wrk_rfds); print_fdset(" wfds=", wrk_nfds, &wrk_wfds); pvmlogprintf(" netsock=%d, ppnetsock=%d, loclsock=%d\n", netsock, ppnetsock, loclsock); task_dump(); pvmbailout(0); } } #else /*IMA_PGON/IMA_I860*/ timed_out = 0; toutpl = (double)tout.tv_sec + 1e-6*((double)tout.tv_usec); tbpl = dclock(); /* use the pgon hw clock */ if (pvmdebmask & PDMSELECT) { pvmlogprintf( "work() probe loop timeout is %f dclock is %f\n", toutpl,tbpl); } do { totprobes++; if ((nodemsg = mpp_input()) > 1) { mpp_input(); TVCLEAR(&tpgon); } else { tout.tv_sec = 0; tout.tv_usec = TIMEOUT; } rfds = wrk_rfds; wfds = wrk_wfds; nrdy = 0; if (totprobes % altprobe == 0) { totprobes = 0; if ((nrdy = select(wrk_nfds, #ifdef FDSETISINT (int *)&rfds, (int *)&wfds, (int *)0, #else (fd_set *)&rfds, (fd_set *)&wfds, (fd_set *)0, #endif &tout)) == -1) { if (errno != EINTR) { pvmlogperror("work() select"); pvmbailout(0); } } if ( (dclock() - tbpl ) >= toutpl) timed_out = 1; else timed_out = 0; if (timed_out && pvmdebmask & PDMSELECT) { pvmlogprintf( "work() probe loop timeout, dclock %f\n", dclock()); } } /* Try to send packets that are still on the mpp output q */ mpp_output( (struct task *) NULL, (struct pkt *) NULL); } while(!(nrdy || nodemsg || timed_out)); #endif /*IMA_PGON/IMA_I860*/ #ifdef STATISTICS switch (nrdy) { case -1: stats.selneg++; break; case 0: stats.selzer++; break; default: stats.selrdy++; break; } #endif if (pvmdebmask & PDMSELECT) { pvmlogprintf("work() SELECT returns %d\n", nrdy); } /* * check network socket and local master socket for action */ if (nrdy > 0) { if (FD_ISSET(netsock, &rfds)) { nrdy--; netinput(); } if (loclsock >= 0 && FD_ISSET(loclsock, &rfds)) { nrdy--; loclconn(); } } /* * check tasks for action */ #ifdef SHMEM someclosed = 0; #endif if (loclsock >= 0) { for (tp = locltasks->t_link; nrdy > 0 && tp != locltasks; tp = tp->t_link) { if (tp->t_sock >= 0 && FD_ISSET(tp->t_sock, &rfds)) { FD_CLR(tp->t_sock, &rfds); nrdy--; if (loclinput(tp)) { #ifdef SHMEM if (tp->t_tid == 0) someclosed++; #endif if (pvmdebmask & PDMTASK) { pvmlogprintf( "work() error reading from t%x, marking dead\n", tp->t_tid); } if (!(tp->t_flag & TF_FORKD)) { tp = tp->t_rlink; task_cleanup(tp->t_link); task_free(tp->t_link); } else wrk_fds_delete(tp->t_sock, 3); continue; } } if (tp->t_sock >= 0 && FD_ISSET(tp->t_sock, &wfds)) { FD_CLR(tp->t_sock, &wfds); nrdy--; if (locloutput(tp)) { #ifdef SHMEM if (tp->t_tid == 0) someclosed++; #endif if (!(tp->t_flag & TF_FORKD)) { tp = tp->t_rlink; task_cleanup(tp->t_link); task_free(tp->t_link); } else wrk_fds_delete(tp->t_sock, 3); continue; } } if (tp->t_out >= 0 && FD_ISSET(tp->t_out, &rfds)) { FD_CLR(tp->t_out, &rfds); nrdy--; loclstout(tp); } } } #if defined(IMA_CM5) || defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) \ || defined(IMA_AIX5SP2) || defined(IMA_BEOLIN) mpp_output((struct task *)0, (struct pkt *)0); #endif #ifdef SHMEM if (someclosed) mpp_dredge(); #endif } } /* locl_spawn() * * Shortcut to spawn a task on local host. * (a.k.a. taskers, etc, at startup) */ void locl_spawn( file, argv ) char *file; char **argv; { struct pmsg *spawnmesg; char **ep; int i; int n; spawnmesg = mesg_new(0); spawnmesg->m_tag = DM_EXEC; spawnmesg->m_dst = TIDPVMD; pkint(spawnmesg, PvmParentNotSet); pkstr(spawnmesg, file); pkint(spawnmesg, PvmTaskDefault | PvmMppFront); pkint(spawnmesg, 1); /* number of tasks per host */ if (argv) for (n = 0; argv[n]; n++); else n = 0; pkint(spawnmesg, n); for ( i=0 ; i < n ; i++ ) pkstr(spawnmesg, argv[i]); pkint(spawnmesg, 0); /* outtid */ pkint(spawnmesg, 0); /* outctx */ pkint(spawnmesg, 0); /* outtag */ pkint(spawnmesg, 0); /* trctid */ pkint(spawnmesg, 0); /* trcctx */ pkint(spawnmesg, 0); /* trctag */ pkint(spawnmesg, 0); /* inherit pvmd env vars as is */ pkint(spawnmesg, 0); /* start proc location */ pkint(spawnmesg, 1); /* total tasks to spawn */ sendmessage(spawnmesg); } /* netoutput() * * Send packets out the wire to remote pvmds. */ netoutput() { struct timeval tnow, tx; struct pkt *pp, *pp2; struct hostd *hp; char *cp; int len; int cc; char dummy[DDFRAGHDR]; /* len = 0; for (pp = opq->pk_tlink; pp != opq; pp = pp->pk_tlink) len++; pvmlogprintf("netoutput() %d in opq\n", len); */ if (opq->pk_tlink == opq) return 0; /* * send any pkts whose time has come */ pvmgetclock(&tnow); while ((pp = opq->pk_tlink) != opq && TVXLTY(&pp->pk_rtv, &tnow)) { /* * fail if we've tried too hard */ hp = pp->pk_hostd; if (pp->pk_nrt >= DDMINRETRIES && pp->pk_rto.tv_sec >= DDMINTIMEOUT) { /* host is toast */ pvmlogprintf( "netoutput() timed out sending to %s after %d, %d.%06d\n", hp->hd_name, pp->pk_nrt, pp->pk_rto.tv_sec, pp->pk_rto.tv_usec); hd_dump(hp); hostfailentry(hp); clear_opq_of((int)(TIDPVMD | hp->hd_hostpart)); ht_delete(hosts, hp); if (newhosts) ht_delete(newhosts, hp); continue; } cp = pp->pk_dat; len = pp->pk_len; if (pp->pk_flag & FFSOM) { cp -= MSGHDRLEN; len += MSGHDRLEN; if (cp < pp->pk_buf) { pvmlogerror("netoutput() no headroom for message header\n"); return 0; } pvmput32(cp, pp->pk_enc); pvmput32(cp + 4, pp->pk_tag); pvmput32(cp + 8, pp->pk_ctx); pvmput32(cp + 16, pp->pk_wid); pvmput32(cp + 20, pp->pk_crc); } cp -= DDFRAGHDR; len += DDFRAGHDR; /* * save under packet header, because databuf may be shared. * we don't worry about message header, because it's only at the head. */ BCOPY(cp, dummy, sizeof(dummy)); if (cp < pp->pk_buf) { pvmlogerror("netoutput() no headroom for packet header\n"); return 0; } if (pvmdebmask & PDMPACKET) { pvmlogprintf( "netoutput() pkt to %s src t%x dst t%x f %s len %d seq %d ack %d retry %d\n", hp->hd_name, pp->pk_src, pp->pk_dst, pkt_flags(pp->pk_flag), pp->pk_len, pp->pk_seq, pp->pk_ack, pp->pk_nrt); } pvmput32(cp, pp->pk_dst); pvmput32(cp + 4, pp->pk_src); pvmput16(cp + 8, pp->pk_seq); pvmput16(cp + 10, pp->pk_ack); pvmput32(cp + 12, 0); /* to keep purify happy */ pvmput8(cp + 12, pp->pk_flag); #if 0 /* drop (don't send) random packets */ if (!(random() & 3)) { pvmlogerror("netoutput() darn, dropped one\n"); cc = -1; } else #endif if ((cc = sendto(netsock, cp, len, 0, (struct sockaddr*)&hp->hd_sad, sizeof(hp->hd_sad))) == -1 && errno != EINTR #ifndef WIN32 && errno != ENOBUFS #endif #ifdef IMA_LINUX /* some Linux systems report this intermittent error */ /* && errno != ECONNREFUSED */ #endif /* hope this works for all archs, not just linux */ && errno != ENOMEM ) { pvmlogperror("netoutput() sendto"); #if defined(IMA_SUN4SOL2) || defined(IMA_X86SOL2) || defined(IMA_SUNMP) || defined(IMA_UXPM) || defined(IMA_UXPV) /* life, don't talk to me about life... */ if (errno == ECHILD) pvmlogerror("this message brought to you by solaris\n"); else #endif pvmbailout(0); } #ifdef STATISTICS if (cc == -1) stats.sdneg++; else stats.sdok++; #endif BCOPY(dummy, cp, sizeof(dummy)); /* restore under header */ /* * set timer for next retry */ if (cc != -1) { if ((pp->pk_flag & (FFFIN|FFACK)) == (FFFIN|FFACK)) { pk_free(pp); if (hp != hosts->ht_hosts[0]) { hostfailentry(hp); clear_opq_of((int)(TIDPVMD | hp->hd_hostpart)); ht_delete(hosts, hp); if (newhosts) ht_delete(newhosts, hp); } continue; } if (!((pp->pk_flag & FFDAT) || (pp->pk_flag & (FFFIN|FFACK)) == FFFIN)) { pk_free(pp); continue; } if (!TVISSET(&pp->pk_at)) pp->pk_at = tnow; TVXADDY(&pp->pk_rtv, &tnow, &pp->pk_rta); TVXADDY(&pp->pk_rto, &pp->pk_rto, &pp->pk_rta); #ifdef STATISTICS if (pp->pk_nrt) stats.netret++; #endif ++pp->pk_nrt; if (pp->pk_rta.tv_sec < DDMAXRTT) { TVXADDY(&pp->pk_rta, &pp->pk_rta, &pp->pk_rta); } } else { tx.tv_sec = DDERRRETRY/1000000; tx.tv_usec = DDERRRETRY%1000000; TVXADDY(&pp->pk_rtv, &tnow, &tx); TVXADDY(&pp->pk_rto, &pp->pk_rto, &tx); } /* reinsert packet into opq */ LISTDELETE(pp, pk_tlink, pk_trlink); for (pp2 = opq->pk_trlink; pp2 != opq; pp2 = pp2->pk_trlink) if (TVXLTY(&pp2->pk_rtv, &pp->pk_rtv)) break; LISTPUTAFTER(pp2, pp, pk_tlink, pk_trlink); } return 0; } /* netinput() * * Input from a remote pvmd. * Accept a packet, do protocol stuff then pass pkt to netinpkt(). */ int netinput() { struct sockaddr_in osad; /* sender's ip addr */ #ifdef SOCKLENISUINT #if defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) \ || defined(IMA_AIX56K64) || defined(IMA_LINUXALPHA) unsigned int oslen; #else size_t oslen; #endif #else int oslen; #endif /* sockaddr length */ struct timeval tnow; struct pkt *pp, *pp2; struct hostd *hp; char *cp; int sqn; int aqn; int ff; int dst; int src; int hh; int already; struct timeval tdiff; /* packet rtt */ int rttusec; /* * alloc new pkt buffer and read packet */ pp = pk_new(pvmudpmtu); if (TDFRAGHDR > DDFRAGHDR) pp->pk_dat += TDFRAGHDR - DDFRAGHDR; oslen = sizeof(osad); if ((pp->pk_len = recvfrom(netsock, pp->pk_dat, pp->pk_max - (pp->pk_dat - pp->pk_buf), 0, (struct sockaddr*)&osad, &oslen)) == -1) { if (errno != EINTR) pvmlogperror("netinput() recvfrom(netsock)"); goto scrap; } #if 0 /* drop random packets */ if (!(random() & 3)) { pvmlogerror("netinput() oops, dropped one\n"); goto scrap; } #endif #ifdef STATISTICS stats.rfok++; #endif cp = pp->pk_dat; pp->pk_len -= DDFRAGHDR; pp->pk_dat += DDFRAGHDR; dst = pp->pk_dst = pvmget32(cp); src = pp->pk_src = pvmget32(cp + 4); sqn = pp->pk_seq = pvmget16(cp + 8); aqn = pvmget16(cp + 10); ff = pp->pk_flag = pvmget8(cp + 12); if (ff & FFSOM) { if (pp->pk_len < MSGHDRLEN) { pvmlogprintf("netinput() SOM pkt src t%x dst t%x too short\n", src, dst); goto scrap; } cp += DDFRAGHDR; pp->pk_enc = pvmget32(cp); pp->pk_tag = pvmget32(cp + 4); pp->pk_ctx = pvmget32(cp + 8); pp->pk_wid = pvmget32(cp + 16); pp->pk_crc = pvmget32(cp + 20); pp->pk_len -= MSGHDRLEN; pp->pk_dat += MSGHDRLEN; } /* * make sure it's from where it claims */ hh = (src & tidhmask) >> (ffs(tidhmask) - 1); if (hh < 0 || hh > hosts->ht_last || !(hp = hosts->ht_hosts[hh]) /* #ifndef IMA_LINUX */ /* appears to be O.K. now in RedHat 5.0... JAK 1/28/98 */ /* * XXX removing these lines is a hack and reduces security between * XXX pvmds somewhat, but it's the easiest fix for Linux right now. */ || (osad.sin_addr.s_addr != hp->hd_sad.sin_addr.s_addr) || (osad.sin_port != hp->hd_sad.sin_port) /* #endif */ ) { pvmlogprintf("netinput() bogus pkt from %s\n", inadport_decimal(&osad)); goto scrap; } if (pvmdebmask & PDMPACKET) { pvmlogprintf( "netinput() pkt from %s src t%x dst t%x f %s len %d seq %d ack %d\n", hp->hd_name, src, dst, pkt_flags(ff), pp->pk_len, sqn, aqn); } if ((ff & (FFFIN|FFACK)) == (FFFIN|FFACK)) { if (hh == hosts->ht_master) { /* * FIN|ACK from master means we should bailout */ if (runstate == PVMDPRIME) { if (pvmdebmask & PDMSTARTUP) pvmlogerror("work() PVMDPRIME halting\n"); exit(0); } pvmlogprintf("netinput() FIN|ACK from master (%s)\n", hp->hd_name); runstate = PVMDHALTING; } else { /* * FIN|ACK from slave means it croaked */ pvmlogprintf("netinput() FIN|ACK from %s\n", hp->hd_name); hd_dump(hp); hostfailentry(hp); clear_opq_of((int)(TIDPVMD | hp->hd_hostpart)); if (hp->hd_hostpart) { ht_delete(hosts, hp); if (newhosts) ht_delete(newhosts, hp); } } goto scrap; } /* * done with outstanding packet covered by this ack */ if (ff & FFACK) { for (pp2 = hp->hd_opq->pk_link; pp2 != hp->hd_opq; pp2 = pp2->pk_link) if (pp2->pk_seq == aqn) { if (pp2->pk_flag & FFDAT) { if (pp2->pk_nrt == 1) { pvmgetclock(&tnow); TVXSUBY(&tdiff, &tnow, &pp2->pk_at); rttusec = tdiff.tv_sec * 1000000 + tdiff.tv_usec; if (rttusec < 1) rttusec = 1000; /* XXX const */ else if (rttusec > DDMAXRTT*1000000) rttusec = DDMAXRTT*1000000; rttusec += 3 * (hp->hd_rtt.tv_sec * 1000000 + hp->hd_rtt.tv_usec); rttusec /= 4; hp->hd_rtt.tv_sec = rttusec / 1000000; hp->hd_rtt.tv_usec = rttusec % 1000000; } } if (pp2->pk_flag & FFFIN) { finack_to_host(hp); } hp->hd_nop--; LISTDELETE(pp2, pk_link, pk_rlink); pk_free(pp2); break; } } /* * move another pkt to output q */ /* if ((hp->hd_opq->pk_link == hp->hd_opq) */ if (hp->hd_nop < nopax && (hp->hd_txq->pk_link != hp->hd_txq)) { if (pvmdebmask & PDMPACKET) { pvmlogprintf("netinput() pkt to opq\n"); } pp2 = hp->hd_txq->pk_link; LISTDELETE(pp2, pk_link, pk_rlink); TVCLEAR(&pp2->pk_rtv); TVXADDY(&pp2->pk_rta, &hp->hd_rtt, &hp->hd_rtt); TVCLEAR(&pp2->pk_rto); TVCLEAR(&pp2->pk_at); pp2->pk_nrt = 0; pp2->pk_hostd = hp; pp2->pk_seq = hp->hd_txseq; hp->hd_txseq = NEXTSEQNUM(hp->hd_txseq); LISTPUTBEFORE(hp->hd_opq, pp2, pk_link, pk_rlink); hp->hd_nop++; LISTPUTBEFORE(opq, pp2, pk_tlink, pk_trlink); } if (!(ff & (FFDAT|FFFIN))) goto scrap; /* * send an ack for the pkt */ pp2 = pk_new(DDFRAGHDR); /* XXX could reref a dummy databuf here */ pp2->pk_dat += DDFRAGHDR; pp2->pk_dst = hp->hd_hostpart | TIDPVMD; pp2->pk_src = pvmmytid; pp2->pk_flag = FFACK; TVCLEAR(&pp2->pk_rtv); TVCLEAR(&pp2->pk_rta); TVCLEAR(&pp2->pk_rto); TVCLEAR(&pp2->pk_at); pp2->pk_nrt = 0; pp2->pk_hostd = hp; pp2->pk_seq = 0; pp2->pk_ack = sqn; /* * Bogus! Acks can't be put at end of opq, as could be * stuck behind packet retries with non-zero pk_rtv's... * Better place Acks, in order, after other zero-rtv-ed (new) * packets, but *before* any retry packets... */ /* LISTPUTAFTER(opq, pp2, pk_tlink, pk_trlink); */ { struct pkt *pp3; for (pp3 = opq->pk_tlink; pp3 != opq; pp3 = pp3->pk_tlink) if (TVXLTY(&pp2->pk_rtv, &pp3->pk_rtv)) break; LISTPUTBEFORE(pp3, pp2, pk_tlink, pk_trlink); } if (!(ff & FFDAT)) goto scrap; /* * if we don't have it already, put it in reordering q */ pp2 = 0; if (SEQLESSTHAN(sqn, hp->hd_rxseq)) already = 1; else { already = 0; for (pp2 = hp->hd_rxq->pk_link; pp2 != hp->hd_rxq; pp2 = pp2->pk_link) if (!SEQLESSTHAN(pp2->pk_seq,sqn)) { if (pp2->pk_seq == sqn) already = 1; break; } } if (already) { if (pvmdebmask & PDMPACKET) { pvmlogprintf("netinput() pkt resent from %s seq %d\n", hp->hd_name, sqn); } goto scrap; } LISTPUTBEFORE(pp2, pp, pk_link, pk_rlink); /* * accept pkts from reordering q */ while (pp = hp->hd_rxq->pk_link, pp != hp->hd_rxq && pp->pk_seq == hp->hd_rxseq) { hp->hd_rxseq = NEXTSEQNUM(hp->hd_rxseq); LISTDELETE(pp, pk_link, pk_rlink); netinpkt(hp, pp); } return 0; scrap: if (pp) pk_free(pp); return 0; } /* netinpkt() * * Consume pkt from network. It's either for the pvmd and needs to * be reassembled into a message or it's for a local task and needs * to be put on the queue to be sent. */ netinpkt(hp, pp) struct hostd *hp; struct pkt *pp; { struct mca *mcap = 0; struct task *tp; struct pmsg *mp; struct frag *fp; struct pkt *pp2; int src = pp->pk_src; int dst = pp->pk_dst; int ff = pp->pk_flag; char *cp; int i; int firstmca = 1; if (pvmdebmask & PDMPACKET) { pvmlogprintf( "netinpkt() pkt from %s src t%x dst t%x f %s len %d\n", hp->hd_name, src, dst, pkt_flags(ff), pp->pk_len); } /* throw out packet if it's not for us */ if (TIDISMCA(dst)) { for (mcap = hp->hd_mcas->mc_link; mcap != hp->hd_mcas; mcap = mcap->mc_link) if (mcap->mc_tid == dst) break; if (mcap == hp->hd_mcas) mcap = 0; } if ((dst & tidhmask) != myhostpart && !mcap) { if (pvmdebmask & (PDMPACKET|PDMAPPL)) { pvmlogprintf( "netinpkt() pkt from t%x for t%x scrapped (not us)\n", src, dst); } goto done; } if (mcap) { for (i = mcap->mc_ndst; i-- > 0; ) { dst = mcap->mc_dsts[i]; if (tp = task_find(dst)) { /* to local task */ pp2 = pk_new(0); pp2->pk_src = src; pp2->pk_dst = dst; pp2->pk_flag = ff; #if defined(IMA_MPP) if (firstmca) { pp2->pk_flag |= (FFMCA | FFMCAWH); firstmca = 0; } else pp2->pk_flag |= FFMCA; #endif pp2->pk_enc = pp->pk_enc; pp2->pk_tag = pp->pk_tag; pp2->pk_ctx = pp->pk_ctx; pp2->pk_wid = pp->pk_wid; pp2->pk_crc = pp->pk_crc; pp2->pk_buf = pp->pk_buf; pp2->pk_max = pp->pk_max; pp2->pk_dat = pp->pk_dat; pp2->pk_len = pp->pk_len; da_ref(pp->pk_buf); pkt_to_task(tp, pp2); } else if (pvmdebmask & (PDMPACKET|PDMAPPL)) { pvmlogprintf( "netinpkt() mc pkt from t%x for t%x scrapped (no dst)\n", src, dst); } } if (ff & FFEOM) { if (pvmdebmask & PDMMESSAGE) { pvmlogprintf("netinpkt() freed mca %x from t%x\n", mcap->mc_tid, hp->hd_name); } mca_free(mcap); } goto done; } if ((dst & ~tidhmask) == TIDPVMD) { /* for pvmd */ if (ff & FFSOM) { /* start of message */ if (hp->hd_rxm) { pvmlogprintf("netinpkt() repeated start pkt from %s\n", hp->hd_name); goto done; } hp->hd_rxm = mesg_new(0); hp->hd_rxm->m_enc = pp->pk_enc; hp->hd_rxm->m_tag = pp->pk_tag; hp->hd_rxm->m_ctx = pp->pk_ctx; hp->hd_rxm->m_wid = pp->pk_wid; hp->hd_rxm->m_crc = pp->pk_crc; hp->hd_rxm->m_dst = dst; hp->hd_rxm->m_src = src; } else { /* middle or end of message */ if (!hp->hd_rxm) { pvmlogprintf( "netinpkt() spurious pkt (no message) from %s\n", hp->hd_name); goto done; } } fp = fr_new(0); fp->fr_buf = pp->pk_buf; fp->fr_dat = pp->pk_dat; fp->fr_max = pp->pk_max; fp->fr_len = pp->pk_len; da_ref(pp->pk_buf); LISTPUTBEFORE(hp->hd_rxm->m_frag, fp, fr_link, fr_rlink); hp->hd_rxm->m_len += fp->fr_len; if (ff & FFEOM) { /* end of message */ mp = hp->hd_rxm; hp->hd_rxm = 0; #ifdef MCHECKSUM if (mp->m_crc != mesg_crc(mp)) { pvmlogprintf( "netinpkt() message from t%x to t%x bad checksum\n", src, dst); /* XXX must free message? */ goto done; } #endif mesg_rewind(mp); if (TIDISTASK(src)) { if (src == pvmschedtid) { schentry(mp); } else if (pvmdebmask & (PDMMESSAGE|PDMAPPL)) { pvmlogprintf( "netinpkt() mesg from t%x to t%x tag %d scrapped\n", src, dst, mp->m_tag); /* XXX must free message? */ } } else { netentry(hp, mp); } } } else { /* for a task */ if (tp = task_find(dst)) { #if defined(IMA_PGON) || defined(IMA_I860) if (TIDISNODE(dst)) mpp_output(tp, pp); else #endif pkt_to_task(tp, pp); pp = 0; } else { if (pvmdebmask & (PDMPACKET|PDMAPPL)) { pvmlogprintf( "netinpkt() pkt from t%x for t%x scrapped (no dst)\n", src, dst); /* XXX must free message? */ } goto done; } } done: if (pp) pk_free(pp); return 0; } /* loclconn() * * Task has attempted to connect. Accept the new connection and make * a blank context for it. */ loclconn() { struct task *tp; /* new task context */ #ifdef SOCKLENISUINT #if defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) \ || defined(IMA_AIX56K64) || defined(IMA_LINUXALPHA) unsigned int oslen; #else size_t oslen; #endif #else int oslen; #endif int i; #ifndef NOUNIXDOM struct sockaddr_un uns; #endif /* #ifdef SHMEM return 0; just getma outa here boy! #endif */ if ((tp = task_new(0)) == NULL) { pvmlogprintf("loclconn() too many tasks?\n" ); return PvmOutOfRes; } #ifdef NOUNIXDOM tp->t_salen = sizeof(tp->t_sad); oslen = sizeof(tp->t_sad); if ((tp->t_sock = accept(loclsock, (struct sockaddr*)&tp->t_sad, &oslen)) == -1) { pvmlogperror("loclconn() accept"); task_free(tp); tp = 0; } else { if (pvmdebmask & (PDMPACKET|PDMTASK)) { pvmlogprintf("loclconn() accept from %s sock %d\n", inadport_decimal(&tp->t_sad), tp->t_sock); } #ifndef NOSOCKOPT i = 1; if (setsockopt(tp->t_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&i, sizeof(int)) == -1) { pvmlogperror("loclconn() setsockopt"); } #endif } #else /*NOUNIXDOM*/ oslen = sizeof(uns); if ((tp->t_sock = accept(loclsock, (struct sockaddr*)&uns, &oslen)) == -1) { pvmlogperror("loclconn() accept"); task_free(tp); tp = 0; } else { if (pvmdebmask & (PDMPACKET|PDMTASK)) pvmlogerror("loclconn() accept\n"); } #endif /*NOUNIXDOM*/ if (tp) { #ifndef WIN32 if ((i = fcntl(tp->t_sock, F_GETFL, 0)) == -1) pvmlogperror("loclconn: fcntl"); else { #ifdef IMA_RS6K /* did you ever feel as though your mind had started to erode? */ i |= O_NONBLOCK; #else /*IMA_RS6K*/ #ifdef O_NDELAY i |= O_NDELAY; #else i |= FNDELAY; #endif #endif /*IMA_RS6K*/ (void)fcntl(tp->t_sock, F_SETFL, i); } #endif wrk_fds_add(tp->t_sock, 1); } return 0; } /* locloutput() * * Output to local task. Sends packets until write() blocks. * Deletes task's bit from wrk_wfds if no more data to send. * * Returns 0 if okay, else -1 if unrecoverable error. */ locloutput(tp) struct task *tp; { struct pkt *pp; char *cp; int len; int n; while ((pp = tp->t_txq->pk_link)->pk_buf) { if (!pp->pk_cpos || pp->pk_cpos < pp->pk_dat) { /* * prepend frag [message] headers if we'll be writing them. */ cp = pp->pk_dat; len = pp->pk_len; if (pp->pk_flag & FFSOM) { cp -= MSGHDRLEN; len += MSGHDRLEN; if (cp < pp->pk_buf) { pvmlogerror("locloutput() no headroom for message header\n"); return 0; } pvmput32(cp, pp->pk_enc); pvmput32(cp + 4, pp->pk_tag); pvmput32(cp + 8, pp->pk_ctx); pvmput32(cp + 16, pp->pk_wid); pvmput32(cp + 20, pp->pk_crc); } cp -= TDFRAGHDR; if (cp < pp->pk_buf) { pvmlogerror("locloutput() no headroom for packet header\n"); return 0; } pvmput32(cp, pp->pk_dst); pvmput32(cp + 4, pp->pk_src); pvmput32(cp + 8, len); pvmput32(cp + 12, 0); /* to keep purify happy */ pvmput8(cp + 12, pp->pk_flag & (FFSOM|FFEOM)); len += TDFRAGHDR; } if (pp->pk_cpos) { cp = pp->pk_cpos; len = pp->pk_len + (pp->pk_dat - cp); } else { pp->pk_cpos = cp; if (pvmdebmask & PDMPACKET) { pvmlogprintf( "locloutput() src t%x dst t%x f %s len %d\n", pp->pk_src, pp->pk_dst, pkt_flags(pp->pk_flag), len); } } /* * send as much as possible; skip to next packet when all sent */ #if defined(IMA_RS6K) || defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) \ || defined(IMA_AIX5SP2) n = write(tp->t_sock, cp, min(len, 4096)); #else #ifndef WIN32 n = write(tp->t_sock, cp, len); #else n = win32_write_socket(tp->t_sock,cp,len); #endif #endif #ifdef STATISTICS if (n == -1) stats.wrneg++; else if (!n) stats.wrzer++; else if (n == len) stats.wrok++; else stats.wrshr++; #endif if (n == -1) { if (errno != EINTR #ifndef WIN32 && errno != EWOULDBLOCK && errno != ENOBUFS #endif && errno != EAGAIN) { #ifdef WIN32 if (GetLastError() != WSAECONNRESET) { #endif pvmlogperror("locloutput() write"); pvmlogprintf("locloutput() marking t%x dead\n", tp->t_tid); #ifdef WIN32 } #endif return -1; } break; } if (n > 0) { if (pvmdebmask & PDMPACKET) { pvmlogprintf( "locloutput() src t%x dst t%x wrote %d\n", pp->pk_src, pp->pk_dst, n); } if ((len - n) > 0) { pp->pk_cpos += n; } else { #if defined(IMA_CM5) || defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) \ || defined(IMA_AIX5SP2) || defined(IMA_BEOLIN) int dst = pp->pk_dst; #endif LISTDELETE(pp, pk_link, pk_rlink); pk_free(pp); #if defined(IMA_CM5) || defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) \ || defined(IMA_AIX5SP2) /* Not done for BEOLIN, since tp2 is tp, */ /* the task on which we are working (PLS) */ if (TIDISNODE(dst)) { struct task *tp2; /* Expensive! But what else can we do? */ if ((tp2 = task_find(dst)) && (tp2->t_flag & TF_CLOSE)) { mpp_free(tp2); /* XXX task_cleanup(tp2); */ task_free(tp2); } } #endif /*defined(IMA_CM5) || defined(IMA_SP2MPI)*/ } } else break; } if (tp->t_txq->pk_link == tp->t_txq) { wrk_fds_delete(tp->t_sock, 2); /* flush context if TF_CLOSE set */ if (tp->t_flag & TF_CLOSE) return -1; } return 0; } /* loclinput() * * Input from a task. * Accept a packet and pass pkt to loclinpkt(). * Returns 0 else -1 if error (work() should clean up the task context). */ loclinput(tp) struct task *tp; { struct pkt *pp = 0; struct pkt *pp2; int n, m; again: /* * if no current packet, start a new one */ if (!tp->t_rxp) { tp->t_rxp = pk_new(pvmudpmtu); /* tp->t_rxp = pk_new(TDFRAGHDR + 2); */ if (DDFRAGHDR > TDFRAGHDR) tp->t_rxp->pk_dat += DDFRAGHDR - TDFRAGHDR; } pp = tp->t_rxp; /* * read the fragment header and body separately so we can * make a bigger buffer if needed */ n = (pp->pk_len < TDFRAGHDR) ? 0 : pvmget32(pp->pk_dat + 8); n += TDFRAGHDR - pp->pk_len; if (pvmdebmask & PDMPACKET) { pvmlogprintf("loclinput() t%x fr_len=%d fr_dat=+%d n=%d\n", tp->t_tid, pp->pk_len, pp->pk_dat - pp->pk_buf, n); } #ifndef WIN32 n = read(tp->t_sock, pp->pk_dat + pp->pk_len, n); #else n = win32_read_socket(tp->t_sock,pp->pk_dat + pp->pk_len,n); #endif if (pvmdebmask & PDMPACKET) { if (n >= 0) { pvmlogprintf("loclinput() read=%d\n", n); } else pvmlogperror("loclinput() read"); } #ifdef STATISTICS switch (n) { case -1: stats.rdneg++; break; case 0: stats.rdzer++; break; default: stats.rdok++; break; } #endif if (n == -1) { if (errno != EINTR #ifndef WIN32 && errno != EWOULDBLOCK #endif ) { pvmlogperror("loclinput() read"); pvmlogprintf("loclinput() marking t%x dead\n", tp->t_tid); return -1; } return 0; } if (!n) { if (pvmdebmask & (PDMPACKET|PDMMESSAGE|PDMTASK)) { pvmlogprintf("loclinput() read EOF from t%x sock %d\n", tp->t_tid, tp->t_sock); } return -1; } if ((pp->pk_len += n) < TDFRAGHDR) return 0; /* * if we have a complete frag, accept it */ m = TDFRAGHDR + pvmget32(pp->pk_dat + 8); if (pp->pk_len == m) { tp->t_rxp = 0; pp->pk_dst = pvmget32(pp->pk_dat); #if defined(IMA_PGON) || defined(IMA_I860) || defined(IMA_CM5) \ || defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) \ || defined(IMA_AIX5SP2) pp->pk_src = pvmget32(pp->pk_dat + 4); #else pp->pk_src = tp->t_tid; #endif pp->pk_flag = pvmget8(pp->pk_dat + 12); pp->pk_len -= TDFRAGHDR; pp->pk_dat += TDFRAGHDR; if (pp->pk_flag & FFSOM) { if (pp->pk_len < MSGHDRLEN) { pvmlogprintf( "loclinput() SOM pkt src t%x dst t%x too short\n", pp->pk_src, pp->pk_dst); pk_free(pp); return 0; } pp->pk_enc = pvmget32(pp->pk_dat); pp->pk_tag = pvmget32(pp->pk_dat + 4); pp->pk_ctx = pvmget32(pp->pk_dat + 8); pp->pk_wid = pvmget32(pp->pk_dat + 16); pp->pk_crc = pvmget32(pp->pk_dat + 20); pp->pk_len -= MSGHDRLEN; pp->pk_dat += MSGHDRLEN; } if (loclinpkt(tp, pp)) return -1; return 0; } /* realloc buffer if frag won't fit */ if (pp->pk_len == TDFRAGHDR) { if (m > pp->pk_max - (pp->pk_dat - pp->pk_buf)) { if (!(tp->t_flag & TF_CONN)) { pvmlogprintf( "loclinput() unconnected task sends frag length %d (ha)\n", m); return -1; } if (DDFRAGHDR > TDFRAGHDR) { pp2 = pk_new(m + DDFRAGHDR - TDFRAGHDR); pp2->pk_dat += DDFRAGHDR - TDFRAGHDR; } else pp2 = pk_new(m); BCOPY(pp->pk_dat, pp2->pk_dat, TDFRAGHDR); pp2->pk_len = pp->pk_len; pk_free(pp); pp = tp->t_rxp = pp2; if (pvmdebmask & PDMPACKET) { pvmlogprintf("loclinput() realloc frag max=%d\n", m); } } goto again; } return 0; } /* loclinpkt() * * Consume pkt from task. * If it's for the pvmd it needs to be reassembled into a message. * If for a local or foreign task it needs to be put on a queue to be sent. * If for a remote pvmd, reassemble as for local then fwd whole message. * Returns 0 else -1 if error (work() should cleanup the * task context). */ loclinpkt(tp, pp) struct task *tp; struct pkt *pp; { int dst; /* pkt dst */ int ff; /* pkt flags */ struct pkt *pp2; struct frag *fp; struct pmsg *mp; struct hostd *hp; struct task *tp2; #if defined(IMA_CM5) || defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) \ || defined(IMA_AIX5SP2) struct task *socktp = tp; /* owner of the socket */ #endif dst = pp->pk_dst; ff = pp->pk_flag; if (pvmdebmask & PDMPACKET) { pvmlogprintf( "loclinpkt() src t%x dst t%x f %s len %d\n", pp->pk_src, dst, pkt_flags(ff), pp->pk_len); } #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) if (pp->pk_src > 0 && !tp->t_tid && (tp2 = task_findpid(pp->pk_src))) { /* connect request from pvmhost */ mpp_conn(tp, tp2); pk_free(pp); return -1; } #endif #if defined(IMA_PGON) || defined(IMA_I860) || defined(IMA_CM5) \ || defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) \ || defined(IMA_AIX5SP2) if (TIDISNODE(pp->pk_src)) /* from a node */ if (!(tp = task_find(pp->pk_src))) { pvmlogprintf("loclinpkt() from unknown task t%x\n", pp->pk_src); goto done; } #endif /*defined(IMA_PGON) || defined(IMA_I860) || defined(IMA_CM5) || defined(IMA_SP2MPI)*/ /* * if to multicast addr, replicate pkt in each q */ if (TIDISMCA(dst) && tp->t_mca && tp->t_mca->mc_tid == dst) { struct mca *mcap = tp->t_mca; int i; for (i = mcap->mc_ndst; i-- > 0; ) { dst = mcap->mc_dsts[i]; if (hp = tidtohost(hosts, dst)) { pp2 = pk_new(0); pp2->pk_src = pp->pk_src; pp2->pk_dst = mcap->mc_tid; pp2->pk_flag = ff; pp2->pk_enc = pp->pk_enc; pp2->pk_tag = pp->pk_tag; pp2->pk_ctx = pp->pk_ctx; pp2->pk_wid = pp->pk_wid; pp2->pk_crc = pp->pk_crc; pp2->pk_buf = pp->pk_buf; pp2->pk_max = pp->pk_max; pp2->pk_dat = pp->pk_dat; pp2->pk_len = pp->pk_len; da_ref(pp->pk_buf); if (hp->hd_hostpart == myhostpart) { netinpkt(hp, pp2); } else { pkt_to_host(hp, pp2); } } else if (pvmdebmask & (PDMPACKET|PDMAPPL)) { pvmlogprintf( "loclinpkt() pkt src t%x dst t%x scrapped (no such host)\n", pp->pk_src, dst); } } /* free mca on last pkt */ if (ff & FFEOM) { if (pvmdebmask & PDMMESSAGE) { pvmlogprintf("loclinpkt() freed mca %x for t%x\n", mcap->mc_tid, tp->t_tid); } mca_free(mcap); tp->t_mca = 0; } goto done; } /* * if to a pvmd, always reassemble (forward if not for us) */ if ((dst & ~tidhmask) == TIDPVMD) { if (ff & FFSOM) { /* start of message */ if (tp->t_rxm) { pvmlogprintf("loclinpkt() repeated start pkt t%x\n", tp->t_tid); goto done; } tp->t_rxm = mesg_new(0); tp->t_rxm->m_ctx = pp->pk_ctx; tp->t_rxm->m_tag = pp->pk_tag; tp->t_rxm->m_enc = pp->pk_enc; tp->t_rxm->m_wid = pp->pk_wid; tp->t_rxm->m_crc = pp->pk_crc; tp->t_rxm->m_dst = dst; tp->t_rxm->m_src = tp->t_tid; } else { /* middle or end of message */ if (!tp->t_rxm) { pvmlogprintf( "loclinpkt() pkt with no message src t%x\n", tp->t_tid); goto done; } } fp = fr_new(0); fp->fr_buf = pp->pk_buf; fp->fr_dat = pp->pk_dat; fp->fr_max = pp->pk_max; fp->fr_len = pp->pk_len; da_ref(pp->pk_buf); LISTPUTBEFORE(tp->t_rxm->m_frag, fp, fr_link, fr_rlink); tp->t_rxm->m_len += fp->fr_len; if (ff & FFEOM) { /* end of message */ mp = tp->t_rxm; tp->t_rxm = 0; #ifdef MCHECKSUM if (mp->m_crc != mesg_crc(mp)) { pvmlogprintf( "loclinpkt() message src t%x dst t%x bad checksum\n", mp->m_src, dst); goto done; } #endif if (!(dst & tidhmask) || (dst & tidhmask) == myhostpart) { /* local */ mesg_rewind(mp); if (mp->m_tag >= (int)SM_FIRST && mp->m_tag <= (int)SM_LAST && (mp->m_src == pvmschedtid || mp->m_src == hostertid || mp->m_src == taskertid)) { schentry(mp); } else { loclentry(tp, mp); } } else { /* remote */ if (!tp->t_tid) { pvmlogprintf("loclinpkt() pkt src null dst t%x\n", dst); goto done; } sendmessage(mp); } /* * if sock is -1, tm_conn2() wants us to throw out this context * because it's been merged into another. */ #if defined(IMA_CM5) || defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) \ || defined(IMA_AIX5SP2) /* node procs have no socket; they use pvmhost's */ if (socktp->t_sock == -1) #else if (tp->t_sock == -1) #endif { pk_free(pp); return -1; } } goto done; } /* * if to a task, put in local or remote send queue */ if (TIDISTASK(dst)) { if (!tp->t_tid) { pvmlogprintf("loclinpkt() pkt src null dst t%x\n", dst); goto done; } if ((dst & tidhmask) == myhostpart) { /* local host */ if (tp2 = task_find(dst)) { #if defined(IMA_PGON) || defined(IMA_I860) if (TIDISNODE(dst)) mpp_output(tp2, pp); else #endif pkt_to_task(tp2, pp); /* LISTPUTBEFORE(tp2->t_txq, pp, pk_link, pk_rlink); */ pp = 0; } else if (pvmdebmask & (PDMPACKET|PDMAPPL)) { pvmlogprintf( "loclinpkt() pkt src t%x dst t%x scrapped (no such task)\n", pp->pk_src, dst); } } else { /* remote host */ if (hp = tidtohost(hosts, dst)) { pkt_to_host(hp, pp); pp = 0; } else { if (pvmdebmask & (PDMPACKET|PDMAPPL)) { pvmlogprintf( "loclinpkt() pkt src t%x dst t%x scrapped (no such host)\n", pp->pk_src, dst); } goto done; } } } done: if (pp) pk_free(pp); return 0; } /* loclstout() * * Read stdout/err pipe from a task. * Ship it to the output log tid if set, else send it to the master * pvmd to scribble in its log file. */ loclstout(tp) struct task *tp; { int n; struct pmsg *mp; static char buf[4000]; #ifndef WIN32 n = read(tp->t_out, buf, sizeof(buf) - 1); #else n = win32_read_socket(tp->t_out,buf, sizeof(buf) -1); #endif if (n < 1) { if (n == 0 || (errno != EINTR #ifndef WIN32 && errno != EWOULDBLOCK #endif )) { wrk_fds_delete(tp->t_out, 1); #ifndef WIN32 (void)close(tp->t_out); #else (void)_close(tp->t_out); #endif tp->t_out = -1; if (tp->t_outtid > 0) { mp = mesg_new(0); mp->m_dst = tp->t_outtid; mp->m_ctx = tp->t_outctx; mp->m_tag = tp->t_outtag; pkint(mp, tp->t_tid); pkint(mp, TO_EOF); sendmessage(mp); tp->t_outtid = 0; } } } else { mp = mesg_new(0); pkint(mp, tp->t_tid); pkint(mp, n); pkbyte(mp, buf, n); if (tp->t_outtid > 0) { mp->m_dst = tp->t_outtid; mp->m_ctx = tp->t_outctx; mp->m_tag = tp->t_outtag; } else { mp->m_tag = DM_TASKOUT; mp->m_dst = hosts->ht_hosts[hosts->ht_cons]->hd_hostpart | TIDPVMD; } sendmessage(mp); } return 0; } /* mesg_to_task() * * Append a message to the send queue for a task. * * N.B. Message must contain at least one frag or this will honk. */ int mesg_to_task(tp, mp) struct task *tp; struct pmsg *mp; { struct frag *fp = mp->m_frag->fr_link; struct pkt *pp; int ff = FFSOM; /* frag flags */ int dst = mp->m_dst; if (pvmdebmask & PDMMESSAGE) { pvmlogprintf("mesg_to_task() dst t%x tag %s len %d\n", dst, pvmnametag(mp->m_tag, (int *)0), mp->m_len); } /* if nothing yet in q, add task's sock to wrk_wfds */ if (tp->t_sock >= 0) wrk_fds_add(tp->t_sock, 2); do { pp = pk_new(0); if (ff & FFSOM) { pp->pk_enc = mp->m_enc; pp->pk_tag = mp->m_tag; pp->pk_ctx = mp->m_ctx; pp->pk_wid = mp->m_wid; #ifdef MCHECKSUM pp->pk_crc = mesg_crc(mp); #else pp->pk_crc = 0; #endif } pp->pk_buf = fp->fr_buf; pp->pk_dat = fp->fr_dat; pp->pk_max = fp->fr_max; pp->pk_len = fp->fr_len; da_ref(pp->pk_buf); if (fp->fr_link == mp->m_frag) ff |= FFEOM; pp->pk_src = TIDPVMD; pp->pk_dst = dst; pp->pk_flag = ff; ff = 0; #if defined(IMA_PGON) || defined(IMA_I860) if (TIDISNODE(dst)) { mpp_output(tp, pp); continue; } #endif #ifdef SHMEM if ((tp->t_sock < 0) && ( (tp->t_flag & TF_SHMCONN) || ((tp->t_flag & TF_PRESHMCONN) && (mp->m_flag & MM_PRIO)) ) ) { /* If shmem and no d-t socket or fully connected shmem */ /* use mpp routine instead of socket one */ mpp_output(tp, pp); continue; } #endif if (mp->m_flag & MM_PRIO) { LISTPUTAFTER(tp->t_txq, pp, pk_link, pk_rlink); } else { pkt_to_task(tp, pp); /* LISTPUTBEFORE(tp->t_txq, pp, pk_link, pk_rlink); */ } } while ((fp = fp->fr_link) != mp->m_frag); return 0; } /* sendmessage() * * Send a message. If it's for a local task or remote host, cut * apart the fragments and queue to be sent. If it's for the local * pvmd, just call netentry() with the whole message. * * N.B. MM_PRIO only works for single-frag messages. */ int sendmessage(mp) struct pmsg *mp; { struct hostd *hp = 0; struct task *tp; struct frag *fp; struct pkt *pp; int ff = FFSOM; int dst = mp->m_dst; if (!dst) { pvmlogerror("sendmessage() what? to t0\n"); } if (pvmdebmask & PDMMESSAGE) { pvmlogprintf("sendmessage() dst t%x ctx %d tag %s len %d\n", dst, mp->m_ctx, pvmnametag(mp->m_tag, (int *)0), mp->m_len); } /* * add a frag to empty message to simplify handling */ if ((fp = mp->m_frag->fr_link) == mp->m_frag) { fp = fr_new(MAXHDR); fp->fr_dat += MAXHDR; LISTPUTBEFORE(mp->m_frag, fp, fr_link, fr_rlink); } /* * route message */ if (!(dst & tidhmask) || (dst & tidhmask) == myhostpart) { /* to local */ if (TIDISTASK(dst)) { /* to local task */ if (tp = task_find(dst)) { mesg_to_task(tp, mp); } else if (pvmdebmask & (PDMMESSAGE|PDMAPPL)) { pvmlogprintf( "sendmessage() scrapped, no such task t%x\n", dst); } } else { /* to myself */ mp->m_ref++; mesg_rewind(mp); netentry(hosts->ht_hosts[hosts->ht_local], mp); } } else { /* to remote */ /* lookup host */ if (runstate == PVMDHTUPD) hp = tidtohost(newhosts, dst); if (!hp && !(hp = tidtohost(hosts, dst))) { if (pvmdebmask & (PDMMESSAGE|PDMAPPL)) { pvmlogprintf("sendmessage() scrapped, no such host t%x\n", dst); } goto bail; } /* packetize frags */ do { pp = pk_new(0); if (ff & FFSOM) { pp->pk_enc = mp->m_enc; pp->pk_tag = mp->m_tag; pp->pk_ctx = mp->m_ctx; pp->pk_wid = mp->m_wid; #ifdef MCHECKSUM pp->pk_crc = mesg_crc(mp); #else pp->pk_crc = 0; #endif } pp->pk_buf = fp->fr_buf; pp->pk_dat = fp->fr_dat; pp->pk_max = fp->fr_max; pp->pk_len = fp->fr_len; da_ref(pp->pk_buf); if (fp->fr_link == mp->m_frag) ff |= FFEOM; pp->pk_src = mp->m_src; pp->pk_dst = dst; pp->pk_flag = ff; ff = 0; if (mp->m_flag & MM_PRIO) { if (pvmdebmask & (PDMMESSAGE|PDMAPPL)) pvmlogerror("sendmessage() PRIO message to host? (scrapped)\n"); } else { pkt_to_host(hp, pp); } } while ((fp = fp->fr_link) != mp->m_frag); } bail: pmsg_unref(mp); return 0; } /* forkexec() * * Search directories in epaths for given file. * Clean up any files we opened, fork and exec the named process. * Leave std{out,err} open so the process can whine if it needs to. * * Returns 0 if ok (and fills in tpp), else returns PvmNoFile or * PvmOutOfRes * * N.B. must be able to use argv[-1]. */ #ifndef WIN32 /* too many ifdefs, WIN 32 gets its own */ #ifdef IMA_OS2 #include static int nextfakepid = 10000000; /* XXX fix this */ int *ptr_nfp = &nextfakepid; #endif int forkexec(flags, name, argv, nenv, env, inst, hosttotal, outof, tpp) int flags; /* exec options */ char *name; /* filename */ char **argv; /* arg list (argv[-1] must be there) */ int nenv; /* num of envars */ char **env; /* envars */ int inst; /* this processes instance */ int hosttotal; /* how many on this host */ int outof; /* how many are being spawned across machine */ struct task **tpp; /* return task context */ { int tid; /* task tid */ int pid; /* task pid */ int pfd[2]; /* pipe back from task */ struct task *tp; /* new task context */ char path[MAXPATHLEN]; struct stat sb; char **ep, **eplist; int i; struct pmsg *mp; /* message to tasker */ struct waitc *wp; int ac; int realrunstate; char buf[32]; #ifdef IMA_BEOSCYLD int node; #endif static char *nullep[] = { "", 0 }; #ifndef IMA_OS2 static int nextfakepid = 10000000; /* XXX fix this */ #endif if ((tid = tid_new()) < 0) { pvmlogerror("forkexec() out of tids?\n"); return PvmOutOfRes; } if ((tp = task_new(tid)) == NULL) { pvmlogerror("forkexec() too many tasks?\n"); return PvmOutOfRes; } /* search for file */ eplist = CINDEX(name, '/') ? nullep : epaths; for (ep = eplist; *ep; ep++) { (void)strcpy(path, *ep); if (path[0]) (void)strcat(path, "/"); (void)strncat(path, name, sizeof(path) - strlen(path) - 1); #ifdef IMA_OS2 (void)strcat(path,".exe"); /* no *.cmd !!! */ #endif #ifdef IMA_BEOSCYLD /* what node are we on? */ node = bproc_currnode(); /* only perform the stat check when we're * running on the master; since the slave * nodes typically don't contain binaries, * the stat call is more than likely to fail * anyway; down below we perform some bproc * magic to "find" the binary back on the * master when we're running on a slave */ if(node == BPROC_NODE_MASTER) #endif if (stat(path, &sb) == -1 || ((sb.st_mode & S_IFMT) != S_IFREG) || !(sb.st_mode & S_IEXEC)) { if (pvmdebmask & PDMTASK) { pvmlogprintf("forkexec() stat failed <%s>\n", path); } continue; } if (taskertid) { mp = mesg_new(0); mp->m_tag = SM_STTASK; mp->m_dst = taskertid; pkint(mp, tid); pkint(mp, flags); pkstr(mp, path); for (ac = 1; argv[ac]; ac++) ; pkint(mp, ac); pkstr(mp, path); for (i = 1; i < ac; i++) pkstr(mp, argv[i]); pkint(mp, nenv + 1); sprintf(buf, "PVMEPID=%d", nextfakepid); pkstr(mp, buf); task_setpid(tp, nextfakepid); if (++nextfakepid > 20000000) nextfakepid = 10000000; for (i = 0; i < nenv; i++) pkstr(mp, env[i]); pkint(mp, inst); pkint(mp, hosttotal); pkint(mp, outof); if (pvmdebmask & PDMTASK) { pvmlogprintf("forkexec() info:: inst %d host %d outof %d\n", inst, hosttotal, outof); } wp = wait_new(WT_TASKSTART); wp->wa_tid = tid; wp->wa_on = taskertid; mp->m_wid = wp->wa_wid; sendmessage(mp); if (pvmdebmask & PDMTASK) { pvmlogprintf("forkexec() sent tasker t%x pid %d\n", tp->t_tid, tp->t_pid); } } else { #ifdef IMA_TITN if (socketpair(AF_UNIX, SOCK_STREAM, 0, pfd) == -1) { pvmlogperror("forkexec() socketpair"); task_free(tp); return PvmOutOfRes; } #else if (pipe(pfd) == -1) { pvmlogperror("forkexec() pipe"); task_free(tp); return PvmOutOfRes; } #endif /* * switch runstate to is-task before forking to avoid race. * if we're killed as a task, we don't want to clean up pvmd stuff. */ realrunstate = runstate; runstate = PVMDISTASK; #if defined(IMA_CSPP) && defined(BALANCED_SPAWN) pid = cnx_sc_fork(CNX_INHERIT_SC, (int) __get_node_id()); #else #ifndef IMA_OS2 pid = fork(); #else pid = os2_spawn( path, argv, nenv, env, ( flags & PvmTaskDebug ) ? debugger : 0 ); #endif #endif if (pid) runstate = realrunstate; if (!pid) { /* close any random fds */ dup2(pfd[1], 1); dup2(1, 2); for (i = getdtablesize(); --i > 2; ) (void)close(i); /* * set envars */ while (nenv-- > 0) { pvmputenv(env[nenv]); /* pvmlogprintf("forkexec() putenv(%s)\n", env[nenv]); */ } /* * put expected pid in environment for libpvm in case * the process we exec forks before connecting back to the pvmd */ sprintf(buf, "PVMEPID=%d", getpid()); pvmputenv(buf); argv[0] = path; if (flags & PvmTaskDebug) { char *p; argv--; if (p = getenv("PVM_DEBUGGER")) argv[0] = p; else argv[0] = debugger; execv(argv[0], argv); } else { #ifdef IMA_BEOSCYLD /* if we're running on the master */ if(node == BPROC_NODE_MASTER) { /* simply call execv */ execv(path,argv); } /* if we're running on a slave node */ else { /* migrate process back to the master */ if(bproc_move(BPROC_NODE_MASTER) != -1) { /* locate the executable */ for(ep = eplist; *ep; ep++) { strcpy(path,*ep); if(path[0]) strcat(path,"/"); strncat(path,name,sizeof(path)-strlen(path)-1); if((stat(path,&sb) == -1) || ((sb.st_mode & S_IFMT) != S_IFREG) || !(sb.st_mode & S_IEXEC)) { /* try the next path */ continue; } else { /* execmove back to the slave */ bproc_execmove(node,path,argv,env); /* if we get this far, the call to execmove * failed and we now have a ghost job back * on the slave and this whacked job on the * master; if we exit, both jobs are cleaned * up through the magic of bproc */ exit(1); } } /* if we fell through the loop, we didn't * find the executable file; in this case * we move back to the slave and return */ if(bproc_move(node) == -1) { /* if the move back to the slave fails, * we have a ghost job back on the slave * and this whacked job on the master; * if we exit, both jobs are cleaned up * through the magic of bproc */ exit(1); } else { /* since the move back to the slave was * successfully and we were unable to find * the executable back on the master, we * mimic forkexec's normal functionality * of ending the for-loop */ break; } } else if (pvmdebmask & PDMTASK) { pvmlogprintf( "forkexec() bproc move to master failed\n"); } /* end-if moving to master */ } /* end-if running on a slave */ #else execv(path, argv); #endif } exit(1); } if (pid == -1) { pvmlogperror("forkexec() fork"); (void)close(pfd[0]); (void)close(pfd[1]); task_free(tp); return PvmOutOfRes; } (void)close(pfd[1]); task_setpid(tp, pid); tp->t_out = pfd[0]; tp->t_flag |= TF_FORKD; wrk_fds_add(tp->t_out, 1); if (pvmdebmask & PDMTASK) { pvmlogprintf("forkexec() new task t%x pid %d pfd=%d\n", tp->t_tid, tp->t_pid, tp->t_out); } } tp->t_a_out = STRALLOC(name); *tpp = tp; return 0; } if (pvmdebmask & PDMTASK) { pvmlogprintf("forkexec() didn't find <%s>\n", name); } task_free(tp); return PvmNoFile; } #else #ifndef IMA_WIN32_WATCOM extern char **environ; #endif static int nextfakepid = 10000000; /* XXX fix this */ int *ptr_nfp = &nextfakepid; int forkexec(flags, name, argv, nenv, env, inst, hosttotal, outof, tpp) int flags; /* exec options */ char *name; /* filename */ char **argv; /* arg list (argv[-1] must be there) */ int nenv; /* num of envars */ char **env; /* envars */ int inst; /* this processes instance */ int hosttotal; /* how many on this host */ int outof; /* how many are being spawned elsewhere */ struct task **tpp; /* return task context */ { int tid; /* task tid */ int pid=-1; /* task pid */ struct task *tp; /* new task context */ char *path; struct stat sb; char **ep, **eplist; int i; struct mesg *mp; /* message to tasker */ struct waitc *wp; int ac; char *expected_pid=0; char buf[32]; HANDLE hpid; const char *penv=0; char filename[128]; SECURITY_ATTRIBUTES saPipe; int fSuccess; HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup, hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup, hInputFile, hSaveStdin, hSaveStdout; SECURITY_DESCRIPTOR SecDescript; SECURITY_ATTRIBUTES saAttr; PROCESS_INFORMATION pi; STARTUPINFO si; /* for CreateProcess call */ char fixedargv[256]; static char *nullep[] = { "", 0 }; path = (char *) malloc (128 * sizeof(char)); if ((tid = tid_new()) < 0) { pvmlogerror("forkexec() out of tids?\n"); return PvmOutOfRes; } if ((tp = task_new(tid)) == NULL) { pvmlogerror("forkexec() too many tasks?\n"); return PvmOutOfRes; } /* PIPE SECURITY STUFF */ InitializeSecurityDescriptor(&SecDescript,SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(&SecDescript,TRUE,NULL,FALSE); /* Set the bInheritHandle flag so pipe handles are inherited. */ saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = &SecDescript; /* The steps for redirecting child process's STDOUT: 1. Save current STDOUT, to be restored later. 2. Create anonymous pipe to be STDOUT for child process. 3. Set STDOUT of the parent process to be write handle of the pipe, so it is inherited by the child process. 4. Create a noninheritable duplicate of the read handle and close the inheritable read handle. */ /* Save the handle to the current STDOUT. */ hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE); if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) pvmlogprintf("Stdout pipe creation failed\n"); /* Set a write handle to the pipe to be STDOUT. */ if (! SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr)) pvmlogprintf("Redirecting STDOUT failed"); /* Create noninheritable read handle and close the inheritable */ /* read handle. */ fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd, GetCurrentProcess(), &hChildStdoutRdDup , 0, FALSE, DUPLICATE_SAME_ACCESS); if( !fSuccess ) pvmlogprintf("DuplicateHandle failed"); CloseHandle(hChildStdoutRd); /* The steps for redirecting child process's STDIN: 1. Save current STDIN, to be restored later. 2. Create anonymous pipe to be STDIN for child process. 3. Set STDIN of the parent to be the read handle of the pipe, so it is inherited by the child process. 4. Create a noninheritable duplicate of the write handle, and close the inheritable write handle. */ /* Save the handle to the current STDIN. */ hSaveStdin = GetStdHandle(STD_INPUT_HANDLE); /* Create a pipe for the child process's STDIN. */ if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) pvmlogprintf("Stdin pipe creation failed\n"); /* Set a read handle to the pipe to be STDIN. */ if (! SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd)) pvmlogprintf("Redirecting Stdin failed"); /* Duplicate the write handle to the pipe so it is not inherited. */ fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr, GetCurrentProcess(), &hChildStdinWrDup, 0, FALSE, /* not inherited */ DUPLICATE_SAME_ACCESS); if (! fSuccess) pvmlogprintf("DuplicateHandle failed"); CloseHandle(hChildStdinWr); /* search for file */ strcpy(filename,name); /* store the filename */ eplist = CINDEX(filename, '/') ? nullep : epaths; make_valid(filename); for (ep = eplist; *ep; ep++) { (void)strcpy(path, *ep); if (path[0]) (void)strcat(path, "/"); (void)strncat(path, filename, sizeof(path) - strlen(path) - 1); if (stat(path, &sb) == -1 || ((sb.st_mode & S_IFMT) != S_IFREG) || !(sb.st_mode & S_IEXEC)) { if (pvmdebmask & PDMTASK) { pvmlogprintf("forkexec() stat failed <%s>\n", path); } continue; } /* have found the path with executable */ argv[0] = path; expected_pid=malloc(64 * sizeof(char)); sprintf(expected_pid, "PVMEPID=%d", nextfakepid); penv=(const char*) expected_pid; if (_putenv(penv)) { pvmlogerror("putenv failed !\n"); exit(1); } /* concatenate the argv together, glue it */ if (argv[0]) { strcpy(fixedargv,argv[0]); strcat(fixedargv," "); for (i=1; argv[i];i++) { strcat(fixedargv,argv[i]); strcat(fixedargv," "); } fixedargv[strlen(fixedargv)-1]=0; } if (flags & PvmTaskDebug) { char *pdebug; if (pdebug = getenv("PVM_DEBUGGER")) argv[0] = pdebug; saPipe.nLength = sizeof(SECURITY_ATTRIBUTES); saPipe.lpSecurityDescriptor = NULL; saPipe.bInheritHandle = FALSE; memset(&si, 0, sizeof(si)); si.cb = sizeof(si); pid = CreateProcess( argv[0], /* filename */ fixedargv, /* command line for child */ NULL, /* process security descriptor */ NULL, /* thread security descriptor */ FALSE, /* inherit handles? */ DEBUG_PROCESS, /* creation flags */ NULL, /* inherited environment address */ NULL, /* startup dir */ /* NULL = start in current */ &si, /* ptr to startup info (input) */ &pi); /* ptr to process info (output) */ } else { saPipe.nLength = sizeof(SECURITY_ATTRIBUTES); saPipe.lpSecurityDescriptor = NULL; saPipe.bInheritHandle = FALSE; memset(&si, 0, sizeof(si)); si.cb = sizeof(si); pid = CreateProcess( argv[0], /* filename */ fixedargv, /* command line for child */ NULL, /* process security descriptor */ NULL, /* thread security descriptor */ FALSE, /* inherit handles? */ DETACHED_PROCESS, /* creation flags */ NULL, /* inherited environment address */ NULL, /* startup dir */ /* NULL = start in current */ &si, /* ptr to startup info (input) */ &pi); /* ptr to process info (output) */ } if (pid == -1) { pvmlogperror("forkexec() _spawnve"); task_free(tp); return PvmOutOfRes; } CloseHandle(pi.hThread); task_sethandle(tp,pi.hProcess); task_setpid(tp,nextfakepid); nextfakepid++; tp->t_flag |= TF_FORKD; if (pvmdebmask & PDMTASK) { pvmlogprintf("forkexec() new task t%x pid %d pfd=%d\n", tp->t_tid, tp->t_pid, tp->t_out); } tp->t_a_out = STRALLOC(filename); *tpp = tp; return 0; } /* for */ if (pvmdebmask & PDMTASK) { pvmlogprintf("forkexec() didn't find <%s>\n", filename); } task_free(tp); return PvmNoFile; } /* convenience for pvm programs, just program your executable without */ /* any .exe appendix. added on WIN32 machines automatically. make it */ /* valid */ void make_valid(n) char *n; { char *appendix=".exe"; int lenapp=0; char *position=0; int i=strlen(n)-1; int j; lenapp= strlen(appendix)-1; if ((i= i- lenapp) > 0) { position=n; for (j=0;jht_local); htp->ht_master = hosts->ht_local; htp->ht_local = 0; ht_insert(htp, hosts->ht_hosts[hosts->ht_local]); ht_insert(htp, hosts->ht_hosts[0]); htp->ht_hosts[htp->ht_master]->hd_txseq = htp->ht_hosts[0]->hd_rxseq; htp->ht_hosts[htp->ht_master]->hd_rxseq = htp->ht_hosts[0]->hd_txseq; oldhosts = hosts; hosts = htp; #ifndef NOUNIXDOM loclspath = 0; #endif (void)close(loclsock); loclsock = -1; loclsnam = 0; (void)close(netsock); netsock = ppnetsock; ppnetsock = -1; locltasks = 0; task_init(); /* close everything but netsock, log_fd and 0, 1, 2 */ for (i = getdtablesize(); --i > 2; ) if (i != netsock && i != log_fd) (void)close(i); wrk_fds_init(); wrk_fds_add(netsock, 1); opq = pk_new(0); opq->pk_tlink = opq->pk_trlink = opq; wdead = 0; rdead = 0; return 0; } /* pkt_to_host() * * Add data pkt to send queue (txq) for a host. Consume the pkt. * If data plus header length is greater than host mtu, * refragment into >1 pkts. * * We have to pay special attention to the FFSOM packet - make it * shorter so there's room to prepend the message header later. * * If send window to host has room, push packet to opq. */ int pkt_to_host(hp, pp) struct hostd *hp; struct pkt *pp; { int maxl = (hp->hd_mtu < pvmudpmtu ? hp->hd_mtu : pvmudpmtu) - DDFRAGHDR; int llim = pp->pk_flag & FFSOM ? maxl - MSGHDRLEN : maxl; pp->pk_flag = (pp->pk_flag & (FFSOM|FFEOM)) | FFDAT; if (pvmdebmask & PDMPACKET) { pvmlogprintf("pkt_to_host() pkt src t%x dst t%x f %s len %d\n", pp->pk_src, pp->pk_dst, pkt_flags(pp->pk_flag), pp->pk_len); } if (pp->pk_len <= llim) { LISTPUTBEFORE(hp->hd_txq, pp, pk_link, pk_rlink); } else { struct pkt *pp2; char *cp = pp->pk_dat; int togo; int n; int ff = pp->pk_flag & FFSOM; int fe = pp->pk_flag & FFEOM; for (togo = pp->pk_len; togo > 0; togo -= n) { n = min(togo, llim); if ((pvmdebmask & PDMPACKET) && togo != pp->pk_len) { pvmlogprintf("pkt_to_host() refrag len %d\n", n); } #ifdef STATISTICS stats.refrag++; #endif pp2 = pk_new(0); pp2->pk_src = pp->pk_src; pp2->pk_dst = pp->pk_dst; if (n == togo) ff |= fe; pp2->pk_flag = ff | FFDAT; ff = 0; llim = maxl; pp2->pk_enc = pp->pk_enc; pp2->pk_tag = pp->pk_tag; pp2->pk_ctx = pp->pk_ctx; pp2->pk_wid = pp->pk_wid; pp2->pk_crc = pp->pk_crc; pp2->pk_buf = pp->pk_buf; pp2->pk_max = pp->pk_max; pp2->pk_dat = cp; pp2->pk_len = n; da_ref(pp->pk_buf); cp += n; LISTPUTBEFORE(hp->hd_txq, pp2, pk_link, pk_rlink); } pk_free(pp); } while (hp->hd_nop < nopax && (hp->hd_txq->pk_link != hp->hd_txq)) { if (pvmdebmask & PDMPACKET) { pvmlogprintf("pkt_to_host() pkt to opq\n"); } pp = hp->hd_txq->pk_link; LISTDELETE(pp, pk_link, pk_rlink); TVCLEAR(&pp->pk_rtv); TVXADDY(&pp->pk_rta, &hp->hd_rtt, &hp->hd_rtt); TVCLEAR(&pp->pk_rto); TVCLEAR(&pp->pk_at); pp->pk_nrt = 0; pp->pk_hostd = hp; pp->pk_seq = hp->hd_txseq; hp->hd_txseq = NEXTSEQNUM(hp->hd_txseq); pp->pk_ack = 0; LISTPUTBEFORE(hp->hd_opq, pp, pk_link, pk_rlink); hp->hd_nop++; LISTPUTBEFORE(opq, pp, pk_tlink, pk_trlink); } return 0; } int fin_to_host(hp) struct hostd *hp; { struct pkt *pp; if (pvmdebmask & PDMPACKET) { pvmlogprintf("fin_to_host() %s\n", hp->hd_name); } pp = pk_new(DDFRAGHDR); /* XXX could reref a dummy databuf here */ pp->pk_dat += DDFRAGHDR; pp->pk_dst = hp->hd_hostpart | TIDPVMD; pp->pk_src = pvmmytid; pp->pk_flag = FFFIN; TVCLEAR(&pp->pk_rtv); TVXADDY(&pp->pk_rta, &hp->hd_rtt, &hp->hd_rtt); TVCLEAR(&pp->pk_rto); TVCLEAR(&pp->pk_at); pp->pk_nrt = 0; pp->pk_hostd = hp; pp->pk_seq = hp->hd_txseq; hp->hd_txseq = NEXTSEQNUM(hp->hd_txseq); pp->pk_ack = 0; LISTPUTBEFORE(hp->hd_opq, pp, pk_link, pk_rlink); hp->hd_nop++; LISTPUTAFTER(opq, pp, pk_tlink, pk_trlink); return 0; } int finack_to_host(hp) struct hostd *hp; { struct pkt *pp; if (pvmdebmask & PDMPACKET) { pvmlogprintf("finack_to_host() %s\n", hp->hd_name); } pp = pk_new(DDFRAGHDR); /* XXX could reref a dummy databuf here */ pp->pk_dat += DDFRAGHDR; pp->pk_dst = hp->hd_hostpart | TIDPVMD; pp->pk_src = pvmmytid; pp->pk_flag = FFFIN|FFACK; TVCLEAR(&pp->pk_rtv); TVCLEAR(&pp->pk_rta); TVCLEAR(&pp->pk_rto); TVCLEAR(&pp->pk_at); pp->pk_nrt = 0; pp->pk_hostd = hp; pp->pk_seq = 0; pp->pk_ack = 0; LISTPUTAFTER(opq, pp, pk_tlink, pk_trlink); return 0; } /* pkt_to_task() * * Add data pkt to send queue (txq) for a task. Consume the pkt. * If data plus header length is greater than task mtu, * refragment into >1 pkts. */ int pkt_to_task(tp, pp) struct task *tp; struct pkt *pp; { if (tp->t_sock >= 0 && (tp->t_flag & TF_CONN) #ifdef SHMEM && !(tp -> t_flag & TF_SHM) /* don't add socket if a shm task */ #endif ) wrk_fds_add(tp->t_sock, 2); #if defined(IMA_PGON) || defined(IMA_I860) if (TIDISNODE(pp->pk_dst)) mpp_output(tp, pp); else #endif #ifdef SHMEM if (((tp->t_sock < 0) && (tp->t_flag & TF_SHMCONN)) || (tp->t_flag & TF_SHMCONN) ) mpp_output(tp, pp); else #endif #ifdef LocalRefragmentTest if (pp->pk_len + DDFRAGHDR <= pvmudpmtu) { LISTPUTBEFORE(tp->t_txq, pp, pk_link, pk_rlink); } else { struct pkt *pp2; int maxl = pvmudpmtu - DDFRAGHDR; char *cp = pp->pk_dat; int togo; int n; int ff = pp->pk_flag & FFSOM; int fe = pp->pk_flag & FFEOM; for (togo = pp->pk_len; togo > 0; togo -= n) { n = min(togo, maxl); pvmlogprintf("pkt_to_task() refrag len %d\n", n); pp2 = pk_new(0); pp2->pk_src = pp->pk_src; pp2->pk_dst = pp->pk_dst; if (n == togo) ff |= fe; pp2->pk_flag = ff | FFDAT; ff = 0; pp2->pk_enc = pp->pk_enc; pp2->pk_tag = pp->pk_tag; pp2->pk_ctx = pp->pk_ctx; pp2->pk_wid = pp->pk_wid; pp2->pk_crc = pp->pk_crc; pp2->pk_buf = pp->pk_buf; pp2->pk_max = pp->pk_max; pp2->pk_dat = cp; pp2->pk_len = n; da_ref(pp->pk_buf); cp += n; LISTPUTBEFORE(tp->t_txq, pp2, pk_link, pk_rlink); } pk_free(pp); } #else /*LocalRefragmentTest*/ { if (pvmdebmask & PDMMESSAGE) pvmlogprintf("pkt_to_task: queueing %x \n", pp->pk_dst); LISTPUTBEFORE(tp->t_txq, pp, pk_link, pk_rlink); } #endif /*LocalRefragmentTest*/ return 0; } #ifdef STATISTICS dump_statistics() { pvmlogprintf(" select: rdy %d, zero %d, neg %d\n", stats.selrdy, stats.selzer, stats.selneg); pvmlogprintf(" sendto: ok %d, neg %d recvfrom: ok %d\n", stats.sdok, stats.sdneg, stats.rfok); pvmlogprintf(" read: pos %d, zero %d, neg %d\n", stats.rdok, stats.rdzer, stats.rdneg); pvmlogprintf(" write: ok %d, short %d, zero %d, neg %d\n", stats.wrok, stats.wrshr, stats.wrzer, stats.wrneg); pvmlogprintf(" refrags: %d\n", stats.refrag); pvmlogprintf(" netwk resends: %d\n", stats.netret); return 0; } reset_statistics() { BZERO((char*)&stats, sizeof(stats)); return 0; } #endif /*STATISTICS*/ #if defined(IMA_CSPP) && defined(BALANCED_SPAWN) static int number_nodes = -1; static int number_cpus = -1; static cnx_scid_t scid_num; static int __get_node_id() { static int current_node = 0; static int current_cpu = 0; if (number_nodes == -1) { number_nodes = get_number_nodes(); number_cpus = get_number_cpus(current_node); goto done; } if (number_nodes == 1) { goto done; } if (current_cpu < (number_cpus - 1) ) { current_cpu++; } else { current_cpu = 0; if (current_node < (number_nodes - 1)) { current_node++; number_cpus = get_number_cpus(current_node); } else { current_node = 0; number_cpus = get_number_cpus(current_node); if (pvmdebmask & PDMTASK) { pvmlogerror ( "Warning:pvm_spawn restarting process placement on Node 0"); } } } done: return current_node; } static cnx_is_scnode_basic_info_data_t sc_info[CNX_MAX_NODES]; static int get_number_nodes() { cnx_is_target_data_t target; int ret; cnx_pattributes_t pattr; int val; char errortxt[128]; cnx_getpattr(getpid(), CNX_PATTR_SCID, &pattr); scid_num = pattr.pattr_scid; cnx_sysinfo_target_scnode(&target, scid_num, CNX_IS_ALL_NODES); ret = cnx_sysinfo( CNX_IS_SCNODE_BASIC_INFO, (void *) &target, sc_info, CNX_MAX_NODES, CNX_IS_SCNODE_BASIC_INFO_COUNT, (unsigned *) &val); if (ret == -1) { sprintf(errortxt, "Error calling cnx_sysinfo in %s:line %d errno: %d \n", __FILE__, __LINE__, errno); pvmlogerror(errortxt); exit (-1); } return val; } static int get_number_cpus(int current_node) { return sc_info[current_node].num_cpus; } #endif /*defined(IMA_CSPP) && defined(BALANCED_SPAWN)*/ /* mksocs() * * Make UDP sockets netsock and ppnetsock. Make TCP master socket * loclsock. * * Returns 0 if ok, * else 2 if pvmd already running, * else 1. */ int mksocs() { struct hostd *hp = hosts->ht_hosts[hosts->ht_local]; struct hostd *hp0 = hosts->ht_hosts[0]; struct sockaddr_in sin; char buf[128]; char *sfn; #ifndef WIN32 int d; #else HANDLE d; int e=0; #endif #ifndef NOSOCKOPT int bsz; #endif char *p; #ifdef SOCKLENISUINT #if defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) \ || defined(IMA_AIX56K64) || defined(IMA_LINUXALPHA) unsigned int oslen; #else size_t oslen; #endif #else int oslen; #endif int cc; #ifndef NOUNIXDOM char spath[PVMTMPNAMLEN]; /* local socket path */ struct sockaddr_un uns; #endif #ifdef IMA_BEOLIN struct hostent *hostaddr; #endif short tmpp; /* * make pvmd-pvmd socket */ if ((netsock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { pvmlogperror("mksocs() socket netsock"); return 1; } p = getenv("PVMNETSOCKPORT"); tmpp = (p) ? atoi(p) : 0; hp->hd_sad.sin_port = htons(tmpp); do { oslen = sizeof(hp->hd_sad); if ((cc=bind(netsock, (struct sockaddr*)&hp->hd_sad, oslen)) == -1) { if (p) { tmpp++; hp->hd_sad.sin_port = htons(tmpp); } else { pvmlogperror("mksocs() bind netsock"); return 1; } } } while ( cc == -1 && p && hp->hd_sad.sin_port < 65535 ); if ( cc == -1 ) { pvmlogperror("mksocs() bind netsock"); return 1; } oslen = sizeof(hp->hd_sad); if (getsockname(netsock, (struct sockaddr*)&hp->hd_sad, &oslen) == -1) { pvmlogperror("mksocs() getsockname netsock"); return 1; } /* * make pvmd-pvmd' socket */ if ((ppnetsock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { pvmlogperror("mksocs() socket ppnetsock"); return 1; } hp0->hd_sad.sin_port = 0; oslen = sizeof(hp0->hd_sad); if (bind(ppnetsock, (struct sockaddr*)&hp0->hd_sad, oslen) == -1) { pvmlogperror("mksocs() bind ppnetsock"); return 1; } oslen = sizeof(hp0->hd_sad); if (getsockname(ppnetsock, (struct sockaddr*)&hp0->hd_sad, &oslen) == -1) { pvmlogperror("mksocs() getsockname ppnetsock"); return 1; } /* * make pvmd-local task socket */ #ifdef NOUNIXDOM if ((loclsock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { pvmlogperror("mksocs() socket loclsock"); return 1; } /* * first try localhost address (loopback) then regular address * XXX 127.0.0.1 is a hack, we should really gethostbyaddr() */ BZERO((char*)&sin, sizeof(sin)); #if defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) || defined(IMA_AIX5SP2) sin = hp->hd_sad; /* allow task to connect from a node */ #else #ifdef IMA_BEOLIN /* allow connection from another node */ sin.sin_family = AF_INET; if (gethostname(buf, sizeof(buf)-1) == -1) { pvmlogerror("mksocs() can't gethostname()\n"); return 1; } else { /* got name, now get addr */ if (!(hostaddr = gethostbyname( buf ))) { pvmlogprintf( "mksocs() can't gethostbyname() for %s\n", buf ); return 1; } else { /* got addr, now save it */ BCOPY( hostaddr->h_addr_list[0], (char*)&sin.sin_addr, sizeof(struct in_addr)); } } sin.sin_port = 0; #else sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(0x7f000001); sin.sin_port = 0; #endif #endif oslen = sizeof(sin); if (bind(loclsock, (struct sockaddr*)&sin, oslen) == -1) { sin = hp->hd_sad; oslen = sizeof(sin); if (bind(loclsock, (struct sockaddr*)&sin, oslen) == -1) { pvmlogperror("mksocs() bind loclsock"); return 1; } } oslen = sizeof(sin); if (getsockname(loclsock, (struct sockaddr*)&sin, &oslen) == -1) { pvmlogperror("mksocs() getsockname loclsock"); return 1; } if (listen(loclsock, SOMAXCONN) == -1) { pvmlogperror("mksocs() listen loclsock"); return 1; } #ifndef NOSOCKOPT bsz = pvmudpmtu * 2; if (setsockopt(netsock, SOL_SOCKET, SO_SNDBUF, (char*)&bsz, sizeof(bsz)) == -1 || setsockopt(netsock, SOL_SOCKET, SO_RCVBUF, (char*)&bsz, sizeof(bsz)) == -1 || setsockopt(ppnetsock, SOL_SOCKET, SO_SNDBUF, (char*)&bsz, sizeof(bsz)) == -1 || setsockopt(ppnetsock, SOL_SOCKET, SO_RCVBUF, (char*)&bsz, sizeof(bsz)) == -1) { pvmlogperror("mksocs() setsockopt"); return 1; } #endif /*NOSOCKOPT*/ p = inadport_hex(&sin); #else /*NOUNIXDOM*/ if ((loclsock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { pvmlogperror("mksocs() socket loclsock"); return 1; } BZERO((char*)&uns, sizeof(uns)); uns.sun_family = AF_UNIX; spath[0] = 0; (void)PVMTMPNAMFUN(spath); strcpy(uns.sun_path, spath); /* XXX len? */ oslen = sizeof(uns); if (bind(loclsock, (struct sockaddr*)&uns, oslen) == -1) { pvmlogperror("mksocs() bind loclsock"); return 1; } if (listen(loclsock, SOMAXCONN) == -1) { pvmlogperror("mksocs() listen loclsock"); return 1; } loclspath = STRALLOC(spath); p = spath; #endif /*NOUNIXDOM*/ /* * make pvmd-local task socket address file */ if (!(sfn = pvmdsockfile())) { pvmlogerror("mksocs() pvmdsockfile() failed\n"); pvmbailout(0); } #ifndef WIN32 if ((d = open(sfn, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC, 0600)) == -1) { if (errno == EEXIST) { #else d = win32_create_file(sfn, CREATE_NEW); if ((int) d == -2){ /* this code is for WIN95 */ system_loser_win = TRUE; e = _open(sfn,O_CREAT|O_EXCL|O_WRONLY|O_TRUNC, 0600); } if (((int)d == -1) || (e ==-1)) { if (1) { /* errno == EEXIST */ #endif #ifndef OVERLOADHOST #ifdef WIN32 if (d == INVALID_HANDLE_VALUE) { (void) pvmlogprintf("mksocs() %s failed. You are required to run on NTFS\n", sfn); return 1; /* same as write address */ } else #endif (void)pvmlogprintf( "mksocs() %s exists. pvmd already running?\n", sfn); return 2; #endif } else { pvmlogperror(sfn); pvmlogerror("mksocs() can't write address file\n"); return 1; } } else { #ifndef WIN32 cc = write(d, p, strlen(p)); #else CloseHandle(d); if (!system_loser_win) { if ((d = (HANDLE) win32_open_file(sfn)) == (HANDLE) -1) { pvmlogprintf("could not open file %s: %d \n", sfn,GetLastError()); return 2; } cc = win32_write_file(d,p,strlen(p)); } else /* the win95 case */ cc = write(e,p,strlen(p)); #endif if (cc != strlen(p)) { if (cc == -1) { pvmlogperror(sfn); pvmlogerror("mksocs() can't write address file\n"); } else { (void)pvmlogprintf( "mksocs() aargh, short write on %s: %d\n", sfn, cc); pvmlogerror("mksocs() is the partition full?\n"); } #ifndef WIN32 (void)close(d); #else if (d) CloseHandle(d); if (e) close(e); #endif (void)unlink(sfn); return 1; } loclsnam = STRALLOC(sfn); #ifndef WIN32 (void)close(d); #else if (d) win32_close_file(d); if (e) close(e); #endif } /* set PVMSOCK envar */ sprintf(buf, "PVMSOCK=%s", p); p = STRALLOC(buf); pvmputenv(p); return 0; } /* colonsep() * * Break string into substrings on ':' delimiter. * Return null-terminated array of strings, in new malloc'd space. * Modifies the original string. */ char ** colonsep(s) char *s; /* the string to break up */ { char **els; int nel = 2; /* length of els */ char *p, *q; #if defined (IMA_OS2) || defined (WIN32) for (p = s; p = CINDEX(p, ';'); p++) #else for (p = s; p = CINDEX(p, ':'); p++) #endif nel++; els = TALLOC(nel, char*, "path"); nel = 0; for (p = s; p; p = q) { #if defined (IMA_OS2) || defined (WIN32) if (q = CINDEX(p, ';')) #else if (q = CINDEX(p, ':')) #endif *q++ = 0; els[nel++] = p; } els[nel] = 0; return els; } /* varsub() * * Substitute environment variables into string. * Variables named by $NAME or ${NAME}. * Return string in new malloc'd space. */ char * varsub(s) char *s; { int rm = 8; /* length of result string space */ char *r; /* result string */ int rl = 0; char *p; char *vn, *vv; char c; int l; r = TALLOC(rm, char, "var"); while (*s) { for (p = s; *p && *p != '$'; p++) ; if (l = p - s) { if (rl + l >= rm) { rm = rl + l + 1; r = TREALLOC(r, rm, char); } strncpy(r + rl, s, l); rl += l; } s = p++; if (*s == '$') { if (*p == '{') p++; vn = p; while (isalnum(*p) || *p == '_') p++; c = *p; *p = 0; vv = getenv(vn); #ifdef WIN32 if (!vv) vv = (char *) read_pvmregistry(vn); #endif *p = c; if (*p == '}') p++; if (vv) l = strlen(vv); else { vv = s; l = p - s; } if (l) { if (rl + l >= rm) { rm = rl + l + 1; r = TREALLOC(r, rm, char); } strncpy(r + rl, vv, l); rl += l; } s = p; } } r[rl] = 0; return r; } /* crunchzap() * * Parse a string into words delimited by <> pairs. * Max number of words is original value of *acp. * * Trashes out the original string. * Returns 0 with av[0]..av[*acp - 1] pointing to the words. * Returns 1 if too many words. */ int crunchzap(s, acp, av) char *s; /* the string to parse */ int *acp; /* max words in, ac out */ char **av; /* pointers to args */ { register int ac; register char *p = s; register int n = *acp; /* separate out words of command */ ac = 0; while (*p) { while (*p && *p++ != '<'); if (*p) { if (ac >= n) { /* command too long */ *acp = ac; return 1; } av[ac++] = p; while (*p && *p != '>') p++; if (*p) *p++ = 0; } } *acp = ac; return 0; } /* master_config() * * Master pvmd. Config a host table with length 1. */ int master_config(hn, argc, argv) char *hn; /* hostname or null */ int argc; char **argv; { struct hostent *he; struct hostd *hp; struct hostd *hp2; int i; char *s; if (argc > 2) { pvmlogerror("usage: pvmd3 [-ddebugmask] [-nhostname] [hostfile]\n"); pvmbailout(0); } if (argc == 2) { filehosts = readhostfile(argv[1]); } else if (s = getenv("PVMHOSTFILE")) { filehosts = readhostfile(s); } if (pvmdebmask & PDMSTARTUP) { if (filehosts) { pvmlogerror("master_config() host file:\n"); ht_dump(filehosts); } else pvmlogerror("master_config() null host file\n"); } hosts = ht_new(1); hosts->ht_serial = 1; hosts->ht_master = 1; hosts->ht_cons = 1; hosts->ht_local = 1; hp = hd_new(1); hp->hd_name = STRALLOC(hn); hp->hd_arch = STRALLOC(myarchname); hp->hd_mtu = pvmudpmtu; hp->hd_dsig = pvmmydsig; ht_insert(hosts, hp); hd_unref(hp); hp = hd_new(0); hp->hd_name = STRALLOC("pvmd'"); hp->hd_arch = STRALLOC(myarchname); hp->hd_mtu = pvmudpmtu; hp->hd_dsig = pvmmydsig; ht_insert(hosts, hp); hd_unref(hp); /* * get attributes from host file if available */ hp = hosts->ht_hosts[1]; if (filehosts && ((hp2 = nametohost(filehosts, hp->hd_name)) || (hp2 = filehosts->ht_hosts[0]))) { applydefaults(hp, hp2); } if (!hp->hd_epath) { if ((s = getenv("PVM_PATH"))) hp->hd_epath = STRALLOC(s); else hp->hd_epath = STRALLOC(DEFBINDIR); } epaths = colonsep(varsub(hp->hd_epath)); if (!hp->hd_bpath) hp->hd_bpath = STRALLOC(DEFDEBUGGER); debugger = varsub(hp->hd_bpath); if (!hp->hd_wdir) { if ((s = getenv("PVM_WD"))) hp->hd_wdir = STRALLOC(s); else hp->hd_wdir = STRALLOC(pvmgethome()); } s = varsub(hp->hd_wdir); if (chdir(s) == -1) pvmlogperror(s); PVM_FREE(s); if (!(he = gethostbyname(hp->hd_aname ? hp->hd_aname : hp->hd_name))) { pvmlogprintf("master_config() %s: can't gethostbyname\n", hn); pvmbailout(0); } BCOPY(he->h_addr_list[0], (char*)&hp->hd_sad.sin_addr, sizeof(struct in_addr)); hp = hosts->ht_hosts[0]; BCOPY(he->h_addr_list[0], (char*)&hp->hd_sad.sin_addr, sizeof(struct in_addr)); if (pvmdebmask & (PDMHOST|PDMSTARTUP)) { pvmlogerror("master_config() host table:\n"); ht_dump(hosts); } if (mksocs()) pvmbailout(0); #ifndef WIN32 /* close everything but our sockets */ for (i = getdtablesize(); --i > 2; ) /* XXX don't like this - hard to maintain */ if (i != netsock && i != ppnetsock && i != loclsock && i != log_fd) (void)close(i); /* reopen 0, 1, 2*/ (void)open("/dev/null", O_RDONLY, 0); (void)open("/dev/null", O_WRONLY, 0); (void)dup2(1, 2); #endif pvmsetlog(2); runstate = PVMDNORMAL; return 0; } /* slave_config() * * Slave pvmd being started by master. Trade minimal config info * so we can send packets back and forth. */ int slave_config(hn, argc, argv) char *hn; int argc; char **argv; { int lh; /* local host index */ int mh; /* master host index */ struct hostd *hp; int i, j; int ac; int ms = 0; /* manual (humanoid) startup */ #ifndef WIN32 int dof = 1; /* fork, exit parent (default) */ #else int dof = 0; #endif int bad = 0; char *p; char *s; for (i = j = ac = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'S': ms = 1; break; case 'f': dof = 0; break; default: pvmlogprintf("slave_config() unknown switch: %s\n", argv[i]); bad++; } } else { argv[j++] = argv[i]; ac++; } } argc = ac; if (bad || argc != 6) { pvmlogerror("slave_config: bad args\n"); pvmbailout(0); } mh = atoi(argv[1]); lh = atoi(argv[4]); hosts = ht_new(1); hosts->ht_serial = 1; hosts->ht_master = mh; hosts->ht_cons = mh; hosts->ht_local = lh; hp = hd_new(mh); hp->hd_name = STRALLOC("?"); hex_inadport(argv[2], &hp->hd_sad); hp->hd_mtu = atoi(argv[3]); ht_insert(hosts, hp); hd_unref(hp); hp = hd_new(0); hp->hd_name = STRALLOC("pvmd'"); hp->hd_arch = STRALLOC(myarchname); hp->hd_mtu = pvmudpmtu; hp->hd_dsig = pvmmydsig; hex_inadport(argv[5], &hp->hd_sad); ht_insert(hosts, hp); hd_unref(hp); hp = hd_new(lh); hp->hd_name = STRALLOC(hn); hp->hd_arch = STRALLOC(myarchname); hp->hd_mtu = pvmudpmtu; hp->hd_dsig = pvmmydsig; hex_inadport(argv[5], &hp->hd_sad); ht_insert(hosts, hp); hd_unref(hp); if (i = mksocs()) { if (i == 2) { printf("PvmDupHost\n"); fflush(stdout); } pvmbailout(0); } printf("ddpro<%d> arch<%s> ip<%s> mtu<%d> dsig<%d>\n", DDPROTOCOL, myarchname, inadport_hex(&hp->hd_sad), pvmudpmtu, pvmmydsig); fflush(stdout); #ifndef WIN32 #if !defined(IMA_OS2) && !defined(CYGWIN) if (!ms) (void)read(0, (char*)&i, 1); #endif if (dof) { if (i = fork()) { if (i == -1) pvmlogperror("slave_config() fork"); exit(0); } /* close everything but our sockets */ for (i = getdtablesize(); --i >= 0; ) /* XXX don't like this - hard to maintain */ if (i != netsock && i != loclsock && i != log_fd) (void)close(i); } /* reopen 0, 1, 2*/ (void)open("/dev/null", O_RDONLY, 0); (void)open("/dev/null", O_WRONLY, 0); (void)dup2(1, 2); #endif pvmsetlog(2); if ((p = getenv("PVM_PATH"))) s = STRALLOC(p); else s = STRALLOC(DEFBINDIR); epaths = colonsep(varsub(s)); PVM_FREE(s); s = STRALLOC(DEFDEBUGGER); debugger = varsub(s); PVM_FREE(s); if ((s = getenv("PVM_WD"))) p = STRALLOC(s); else p = STRALLOC(pvmgethome()); s = varsub(p); if (chdir(s) == -1) pvmlogperror(s); PVM_FREE(p); PVM_FREE(s); runstate = PVMDSTARTUP; return 0; } ./pvm3/src/pvmdpack.c0100644007401100000360000001424107240353451013645 0ustar kohlgopher static char rcsid[] = "$Id: pvmdpack.c,v 1.11 2001/02/07 23:15:53 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmdpack.c * * Pvmd message packing and unpacking. * * $Log: pvmdpack.c,v $ * Revision 1.11 2001/02/07 23:15:53 pvmsrc * 2nd Half of CYGWIN Check-ins... * (Spanker=kohl) * * Revision 1.10 2000/02/16 21:59:49 pvmsrc * Fixed up #include stuff... * - use for IMA_TITN... * - #include before any NEEDMENDIAN #includes... * (Spanker=kohl) * * Revision 1.9 1999/07/08 19:00:10 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.8 1998/11/20 20:06:40 pvmsrc * Changes so that win32 will compile & build. Also, common * Changes so that compiles & builds on NT. Also * common source on win32 & unix. * (spanker=sscott) * * Revision 1.7 1997/11/04 23:21:41 pvmsrc * Added SYSVSTR stuff. * (Spanker=kohl) * * Revision 1.6 1997/06/27 17:32:51 pvmsrc * Updated for WIN32 header files & Authors. * * Revision 1.5 1997/06/24 20:39:18 pvmsrc * Eliminated unnecessary global externs. * * Revision 1.4 1997/04/30 21:26:26 pvmsrc * SGI Compiler Warning Cleanup. * * Revision 1.3 1997/01/28 19:27:22 pvmsrc * New Copyright Notice & Authors. * * Revision 1.2 1996/10/24 21:04:49 pvmsrc * Moved #include of "global.h" down below other headers: * - need to have all of the structures / types declared before * the globals can be declared... * * Revision 1.1 1996/09/23 23:44:32 pvmsrc * Initial revision * * */ #ifdef NEEDMENDIAN #include #include #endif #ifdef NEEDENDIAN #include #endif #ifdef NEEDSENDIAN #include #endif #include #if defined(WIN32) || defined(CYGWIN) #include "..\xdr\types.h" #include "..\xdr\xdr.h" #else #include #include #endif #ifdef SYSVSTR #include #else #include #endif #include "pvmalloc.h" #include "pvmfrag.h" #include "pmsg.h" #include "listmac.h" #include "global.h" /*************** ** Private ** ** ** ***************/ /***************** ** Interface ** ** ** *****************/ /* pkbyte() * * Pack bytes into a message. * Returns 0 if ok. */ int pkbyte(mp, p, n) struct pmsg *mp; /* message to pack */ char *p; int n; { return (mp->m_codef->enc_byte) (mp, (void*)p, n, 1, 1); } /* upkbyte() * * Unpack bytes from a message. * Returns 0 if ok. */ int upkbyte(mp, p, n) struct pmsg *mp; /* message to unpack */ char *p; /* unpack into */ int n; { /* pvmlogprintf("upkbyte(0x%lx, 0x%lx, %d)\n", (long)mp, (long)p, n); */ return (mp->m_codef->dec_byte) (mp, (void*)p, n, 1, 1); } /* pkint() * * Pack a integer into a message. * Returns 0 if ok. */ int pkint(mp, i) struct pmsg *mp; /* message to pack */ int i; /* int to pack */ { return (mp->m_codef->enc_int) (mp, (void*)&i, 1, 1, sizeof(int)); } /* upkint() * * Unpack a signed integer from a message. * Returns 0 if ok. */ int upkint(mp, np) struct pmsg *mp; /* message to unpack */ int *np; /* int to unpack into */ { return (mp->m_codef->dec_int) (mp, (void*)np, 1, 1, sizeof(int)); } /* upkuint() * * Unpack an unsigned integer from a message. * Returns 0 if ok. */ int upkuint(mp, np) struct pmsg *mp; /* message to unpack */ int *np; /* int to unpack into */ { return (mp->m_codef->dec_uint) (mp, (void*)np, 1, 1, sizeof(int)); } /* pkstr() * * Pack a null-term string into a message. * Returns 0 if ok. */ int pkstr(mp, s) struct pmsg *mp; /* message to pack */ char *s; /* string to pack */ { int cc; int l = strlen(s) + 1; if (!(cc = (mp->m_codef->enc_int) (mp, (void*)&l, 1, 1, sizeof(int)))) cc = (mp->m_codef->enc_byte) (mp, (void*)s, l, 1, 1); return cc; } /* upkstr() * * Unpack a string from a message. Result is null-terminated. * Any length greater than mlen is discarded from message.. * Returns 0 if ok. */ int upkstr(mp, s, mlen) struct pmsg *mp; /* message to unpack */ char *s; /* space to unpack in */ int mlen; /* max bytes to unpack incl null */ { int cc; int l; if (!(cc = (mp->m_codef->dec_int) (mp, (void*)&l, 1, 1, sizeof(int)))) { if (l <= 0) cc = PvmNoData; else if (l <= mlen) cc = (mp->m_codef->dec_byte) (mp, (void*)s, l, 1, 1); else cc = PvmNoMem; } return cc; } /* upkstralloc() * * Unpack a string from a message. Result is null-terminated, * and in dynamic space.. * Returns 0 if ok. */ int upkstralloc(mp, ss) struct pmsg *mp; /* message to unpack */ char **ss; /* return pointer */ { int cc; int l; if (!(cc = (mp->m_codef->dec_int) (mp, (void*)&l, 1, 1, sizeof(int)))) { if (l <= 0) cc = PvmNoData; else { *ss = TALLOC(l, char, "ustr"); if ((cc = (mp->m_codef->dec_byte) (mp, (void*)*ss, l, 1, 1)) < 0) { PVM_FREE(*ss); *ss = 0; } } } return cc; } /* mesg_rewind() * * A hack to rewind a message. */ void mesg_rewind(mp) struct pmsg *mp; { mp->m_flag &= ~MM_UPACK; (mp->m_codef->dec_init)(mp); } ./pvm3/src/pvmdshmem.c0100644007401100000360000006620510001307626014037 0ustar kohlgopher static char rcsid[] = "$Id: pvmdshmem.c,v 1.21 2004/01/14 18:51:02 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmdshmem.c * * Shared-memory MPP interface. * * $Log: pvmdshmem.c,v $ * Revision 1.21 2004/01/14 18:51:02 pvmsrc * Added new AIX5* arches. * (Spanker=kohl) * * Revision 1.20 2002/02/21 23:18:41 pvmsrc * Added new (not to be documented!) PVM_MAX_TASKS env var support. * - for Mahir Lokvancic . * - forcefully limits the number of tasks that can attach to a * pvmd, required on Solaris in rare circumstances when hard * FD_SETSIZE limit is reached, and all hell breaks loose... * - check return for task_new() call, can now produce NULL ptr, * indicating PvmOutOfRes... * (Spanker=kohl) * * Revision 1.19 2001/09/25 21:21:04 pvmsrc * Yanked "char *pvmgettmp();" decl - now in pvm3.h... * (Spanker=kohl) * * Revision 1.18 2000/02/10 20:45:33 pvmsrc * Replaced hard-coded /tmp usage. * - use pvmgettmp() routine now to determine PVM temp dir. * (Spanker=kohl) * * Revision 1.17 1999/07/08 19:00:11 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.16 1998/08/13 18:31:15 pvmsrc * Altered SUNMP to use test and set operations with semaphores * for page locking instead of MUTEX and cond vars. * Changes are mainly in pvmshmem.h, with lots of #ifdefs changes. * Makefile altered to use the PLOCKFILE to indicate the Page Locking * INLINE code used (from SUNMP.conf). * Some changes effect AIX MP versions which still use conditional * variables and may change to semaphores soon. * (Spanker=fagg) * * Revision 1.15 1997/11/04 23:21:43 pvmsrc * Added SYSVSTR stuff. * (Spanker=kohl) * * Revision 1.14 1997/07/02 20:27:32 pvmsrc * Fixed startup race on shmem to that a shmem task can get fully * configured before getting any messages. * This involved adding two states * TF_PRESHMCONN and TF_SHM. TF_PRESHMCONN indicates that messages * with MM_PRIO set can be sent to a task, but regular messages are * queued. This allows shmem tasks to be completely configured * before any messages flow. When the daemon changes the state from * TF_PRESHMCONN to TF_SHMCONN it calls shm_wrt_pkts to write any * packets that were queued before task state changed to TF_SHMCONN. * * Revision 1.13 1997/06/27 20:54:41 pvmsrc * Allow forked process to be caught by daemon * when its not ignoring SIGCLD. * * Revision 1.12 1997/06/25 22:09:34 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.11 1997/06/24 20:39:19 pvmsrc * Eliminated unnecessary global externs. * * Revision 1.10 1997/06/16 13:42:10 pvmsrc * Upated forkexec arg list. * * Revision 1.9 1997/06/02 13:50:03 pvmsrc * Added missing #include host.h for waitc.h. * * Revision 1.8 1997/06/02 13:26:43 pvmsrc * Changed mpp_input so that spawned processes can be claimed after * exiting. Previously they were claimed as their shadow t0 died * and set a flag in work() that would get caught leading to * mpp_dredge() finding them sometime later... * * Revision 1.7 1997/05/21 16:01:53 pvmsrc * Updated ifdefs to include AIX4MP arch type. * * Revision 1.6 1997/05/19 15:03:01 pvmsrc * pvmfrgsiz is now set according to memory page size and msg header * lengths instead of just the UDP host-host packet size! * Mesg headers are set correctly in mpp_input / mpp_output to include * contexts etc * * Revision 1.5 1997/04/25 19:17:29 pvmsrc * Mashed to make it work within 3.4 new messaging system. Added: * - correct includes * - changed ph_cod's to ph_tag's and pk_cod -> pk_tag * - add duplicate of pvmdunix ppi_kill() * * Revision 1.4 1997/01/28 19:27:23 pvmsrc * New Copyright Notice & Authors. * * Revision 1.3 1996/10/25 13:58:01 pvmsrc * Replaced old #includes for protocol headers: * - , "ddpro.h", "tdpro.h" * With #include of new combined header: * - * * Revision 1.2 1996/10/24 21:04:50 pvmsrc * Moved #include of "global.h" down below other headers: * - need to have all of the structures / types declared before * the globals can be declared... * * Revision 1.1 1996/09/23 23:44:33 pvmsrc * Initial revision * * Revision 1.20 1995/11/02 16:31:23 manchek * skip over stale packets from dead tasks in mpp_input * * Revision 1.19 1995/09/05 19:24:05 manchek * mpp_input copies all pages for now (in case sender task exits) * * Revision 1.18 1995/07/25 17:35:32 manchek * mpp_probe cancels retry to a task if not ready. * mpp_output returns success code * * Revision 1.17 1995/07/24 21:48:25 manchek * mpp_output puts pkts in order (at the end) of ovfpkts. * mpp_probe consumes ovfpkts in order to retry * * Revision 1.16 1995/07/24 19:22:33 manchek * message, frag headers passed in inbox shmpkhdr instead of databuf * changes in mpp_input, mpp_output. * removed mpp_mcast - wasn't called * * Revision 1.15 1995/07/12 01:12:14 manchek * do nothing in mpp_free if tid is zero. * peer_detach now frees peer struct. * mpp_dredge can reclaim pidtid slot immediately if task not registered * * Revision 1.14 1995/07/05 16:21:40 manchek * added ST_FINISH to pidtid_dump * * Revision 1.13 1995/07/05 16:16:29 manchek * added mpp_dredge function to skim pidtid table for zombies and call * task_cleanup and task_free. * mpp_free (called from task_free) now reclaims pidtid table entry * * Revision 1.12 1995/07/03 19:55:47 manchek * hellish cleanup of comments and formatting. * removed POWER4 ifdefs. * removed removeshm(). * added mpp_setstatus() and pidtid_dump() * * Revision 1.11 1995/06/28 15:50:57 manchek * added arg to peer_conn calls * * Revision 1.10 1995/06/19 17:45:01 manchek * inc refcount before signalling in mpp_output * * Revision 1.9 1995/06/02 16:21:10 manchek * fixed references to detached memory segments * * Revision 1.8 1995/05/22 19:51:37 manchek * added ifdefs for RS6KMP * * Revision 1.7 1995/05/18 17:22:25 manchek * need to export pvminbox and myshmbufid * * Revision 1.6 1995/05/17 16:41:29 manchek * changed global mytid to pvmmytid. * changed inbox to pvminbox and mybufid to myshmbufid. * added support for CSPP shared memory. * unset TF_FORKD flag if task doesn't reconnect with expected pid * * Revision 1.5 1995/02/06 22:42:01 manchek * new function mpp_setmtu, called before slave_config * * Revision 1.4 1995/02/01 21:35:06 manchek * added nenv and envp args to mpp_load, which passes them to forkexec * * Revision 1.3 1994/11/08 15:35:07 manchek * shared memory damage control * */ #include #include #include #include #include #ifdef IMA_SYMM #include /* XXX for open(); change to fcntl.h in ptx? */ #include #endif #include #include #include #include #include #include #include #include #ifdef SYSVSTR #include #else #include #endif #include #include #include "pvmalloc.h" #include "pvmdabuf.h" #include "pkt.h" #include "task.h" #include "listmac.h" #include "pvmshmem.h" #include "bfunc.h" #include "host.h" #include "waitc.h" #include "global.h" #ifndef max #define max(a,b) ((a)>(b)?(a):(b)) #endif #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif char *getenv(); extern int pvmdebmask; /* from pvmd.c */ extern int pvm_useruid; /* from pvmd.c */ extern int pvmmytid; /* from pvmd.c */ extern int pvmmydsig; /* from pvmd.c */ extern int pvmudpmtu; /* from pvmd.c */ extern int pvmmyupid; /* from pvmd.c */ extern struct peer *peers; /* from pvmshmem.c */ /*************** ** Globals ** ** ** ***************/ char *outmsgbuf = 0; /* outgoing message buffer */ int outbufsz = 0; /* size of outgoing msg buffer */ int nbufsowned = 0; /* num shared frags held by us */ int pgsz = 0; /* page size */ int pvmpgsz = 0; /* PVM virtual page size */ char *infopage = 0; /* proto, NDF, pid-tid table */ struct pidtid *pidtids = 0; /* pid -> tid table */ int maxpidtid = 0; /* size of pid-tid table */ int shmbufsiz = 0; /* shared-memory buffer size */ int myshmbufid = -1; /* shared-memory msg buffer ID */ char *pvminbox = 0; /* incoming message header buffer */ extern int pvmfrgsiz; /* From pvmd.c frag size */ /* included here as we change it in ppi_config*/ /*************** ** Private ** ** ** ***************/ static char pvmtxt[512]; /* scratch for error log */ static int inboxsz = 0; /* size of incoming message buffer */ static struct pkt *ovfpkts = 0; /* packets waiting to be delivered */ static int globid = -1; /* ID of global shared segment */ /* * Buffer layout * ____________________ * | inbox | 1 * |____________________| * | pid->tid table | 2 * |____________________| * | | 3 * | outmsgbuf | * | . | . * | . | . * | . | . * * * Note: tasks don't keep a pid-tid table, so their outgoing message * buffer starts at the second page. * * To send messages to one another, the sender puts the message header, * which contains its own task ID and the location of the message body * (expressed as an offset from the head of the segment), into the inbox * of the intended receiver. When the addressee is ready to accept the * message, it reads the message header and locates the message fragments * in the sender's outgoing message buffer. Access to buffers are guarded * locks. Tasks can read the same data simultaneously, but one must obtain * exclusive access to the page before it can modify the data. * * Messages to tasks on other hosts are routed by pvmd. */ int ppi_config(argc, argv) int argc; char **argv; { pgsz = sysconf(_SC_PAGESIZE); pvmudpmtu = pgsz - PVMPAGEHDR; /* XXX yuck host to host limited */ pvmfrgsiz = pvmudpmtu; /* host-task limit.. not same as UDP host to host */ /* except h-h is not same as it should be, see above */ return 0; } /* ppi_init() * * Create our shared memory segment, initialize stuff, etc. * * XXX shouldn't just return if something goes wrong */ void ppi_init() { struct pidtidhdr *pvminfo; char *pvmtmp = pvmgettmp(); char *p; int key; #ifdef LOG char fname[32]; FILE *logfp; #ifdef IMA_CSPP int scid = get_scid(); if (scid > 1) sprintf(fname, "%s/pvmt.%d.%d", pvmtmp, pvm_useruid, scid); else #else sprintf(fname, "%s/pvmt.%d", pvmtmp, pvm_useruid); #endif logfp = fopen(fname, "w"); fclose(logfp); #endif /*LOG*/ pvmpgsz = FRAGPAGE*pgsz; inboxsz = (INBOXPAGE*pgsz - sizeof(struct msgboxhdr))/sizeof(struct shmpkhdr); if (!(p = getenv("PVMBUFSIZE")) || !(shmbufsiz = strtol(p, (char**)0, 0))) shmbufsiz = SHMBUFSIZE; key = pvmshmkey(0); if ((myshmbufid = shmget((key_t)key, shmbufsiz, IPC_CREAT|PERMS)) == -1) { pvmlogperror("ppi_init() can't create msg buffer"); pvmbailout(0); return; } #ifdef IMA_CSPP if ((pvminbox = (char *)shm_search(myshmbufid)) == (char *)-1L) #else if ((pvminbox = (char *)shmat(myshmbufid, 0, 0)) == (char *)-1L) #endif { pvmlogperror("ppi_init() can't attach msg buffer"); shmctl(myshmbufid, IPC_RMID, (struct shmid_ds *)0); myshmbufid = -1; pvmbailout(0); return; } infopage = pvminbox + INBOXPAGE*pgsz; outmsgbuf = infopage + pgsz; if (!(outbufsz = (shmbufsiz - INBOXPAGE*pgsz - pgsz)/pvmpgsz)) { pvmlogerror("ppi_init() SHMBUFSIZE too small!"); shmctl(myshmbufid, IPC_RMID, (struct shmid_ds *)0); myshmbufid = -1; pvmbailout(0); return; } nbufsowned = 0; msgbufinit(pvminbox); #ifndef IMA_KSR1 PAGEINITLOCK(&((struct shmpghdr *)infopage)->pg_lock); #endif ((struct shmpghdr *)infopage)->pg_ref = 0; pvminfo = (struct pidtidhdr *)(infopage + PVMPAGEHDR); pvminfo->i_proto = TDPROTOCOL; pvminfo->i_dsig = pvmmydsig; pvminfo->i_next = 0; pvminfo->i_bufsiz = shmbufsiz; pvminfo->i_dpid = pvmmyupid; pidtids = (struct pidtid *)(pvminfo + 1); maxpidtid = (pgsz - sizeof(struct pidtidhdr) - PVMPAGEHDR)/sizeof(struct pidtid); BZERO((char *)pidtids, sizeof(struct pidtid)*maxpidtid); { int i; for (i = 0; i < maxpidtid; i++) pidtids[i].pt_stat = ST_EXIT; } peer_init(); ovfpkts = pk_new(0); ovfpkts -> pk_link = ovfpkts->pk_rlink = ovfpkts; /* #if defined(SUN4SOL2) sprintf(pvmtxt, "%ld CPUs online\n", sysconf(_SC_NPROCESSORS_ONLN)); sprintf(pvmtxt, "%ld CPUs online\n", sysconf(15)); pvmlogerror(pvmtxt); #endif */ } /* mpp_free() * * Remove shared resources for tid. * Delete it from peers list (possibly removing segment and semaphore). * Delete its pidtid table entry. */ void mpp_free(tid) int tid; { struct peer *pp; struct task *tp; int i; if (pvmdebmask & (PDMTASK|PDMNODE)) { sprintf(pvmtxt, "mpp_free() t%x\n", tid); pvmlogerror(pvmtxt); } if (!tid) return; for (pp = peers->p_link; pp != peers; pp = pp->p_link) { if (pp->p_tid == tid) { peer_detach(pp); break; } } PAGELOCK(&((struct shmpghdr *)infopage)->pg_lock); for (i = 0; i < maxpidtid; i++) if (pidtids[i].pt_tid == tid) { pidtids[i].pt_stat = ST_EXIT; break; } PAGEUNLOCK(&((struct shmpghdr *)infopage)->pg_lock); } /* mpp_conn() * * Fill in pid->tid->key table for a new task. * This isn't really "connection" (done by peer_conn). */ int mpp_conn(tp) struct task *tp; { int firstidx, idx; struct pidtidhdr *pvminfo = (struct pidtidhdr *)(infopage + PVMPAGEHDR); PAGELOCK(&((struct shmpghdr *)infopage)->pg_lock); firstidx = idx = pvminfo->i_next; while (pidtids[idx].pt_stat != ST_EXIT) { if (++idx == maxpidtid) idx = 0; if (idx == firstidx) { PAGEUNLOCK(&((struct shmpghdr *)infopage)->pg_lock); pvmlogerror("mpp_conn() pidtid table full\n"); return PvmOutOfRes; } } if ((firstidx = idx + 1) == maxpidtid) firstidx = 0; pvminfo->i_next = firstidx; /* XXX so wtf good is an almost-refcount? */ if (((struct shmpghdr *)infopage)->pg_ref < maxpidtid) ((struct shmpghdr *)infopage)->pg_ref++; pidtids[idx].pt_tid = tp->t_tid; pidtids[idx].pt_ptid = tp->t_ptid; pidtids[idx].pt_stat = ST_NOTREADY; pidtids[idx].pt_pid = tp->t_pid; pidtids[idx].pt_key = 0; pidtids[idx].pt_cond = 0; PAGEUNLOCK(&((struct shmpghdr *)infopage)->pg_lock); if (pvmdebmask & (PDMTASK|PDMMEM)) { sprintf(pvmtxt, "mpp_conn() assigning pidtid[%d] to t%x\n", idx, tp->t_tid); pvmlogerror(pvmtxt); } if (pvmdebmask & PDMTASK) { sprintf(pvmtxt, "mpp_conn() new task t%x\n", tp->t_tid); pvmlogerror(pvmtxt); } return 0; } void mpp_input() { int next; struct pkt *pp; struct peer *pe; struct task *tp; int tid; int sdr; int src; int dst; int len; char *cp, *buf; struct msgboxhdr *inbp; struct shmpkhdr *inmsgs; inbp = (struct msgboxhdr *)pvminbox; inmsgs = (struct shmpkhdr *)(inbp + 1); do { next = (inbp->mb_read + 1) % inboxsz; sdr = inmsgs[next].ph_sdr; src = inmsgs[next].ph_src; if (inmsgs[next].ph_dat < 0) { /* new task */ int ipid; if (!(ipid = inmsgs[next].ph_dst)) ipid = src; if (!(tp = task_findpid(ipid))) { /* not spawned by us */ if ((tid = tid_new()) < 0) { pvmlogerror("mpp_input() out of tids?\n"); continue; } if ((tp = task_new(tid)) == NULL) { pvmlogerror("mpp_input() too many tasks?\n"); continue; } task_setpid(tp, src); mpp_conn(tp); } else if (tp->t_pid != src) { task_setpid(tp, src); tp->t_flag &= ~TF_FORKD; } tp->t_flag |= TF_CONN | TF_SHM; continue; } if (!(pe = peer_conn(sdr, (int *)0)) || pe == (struct peer *)-1L) { sprintf(pvmtxt, "mpp_input() can't connect to sender t%x\n", sdr); pvmlogerror(pvmtxt); continue; } cp = pe->p_buf + INBOXPAGE*pgsz + inmsgs[next].ph_dat; buf = cp - (inmsgs[next].ph_dat & (pgsz-1)) + PVMPAGEHDR; dst = inmsgs[next].ph_dst; len = inmsgs[next].ph_len; /* * must copy all packets (for now). * sender may exit, and we don't check if we have page references * into a segment before we detach. */ /* if (TIDISHERE(dst, pvmmytid) && TIDISTASK(dst)) { */ pp = pk_new(len + MAXHDR); pp->pk_dat += MAXHDR; BCOPY(cp, pp->pk_dat, len); da_unref(buf); cp = pp->pk_dat; /* } else { pp = pk_new(0); pp->pk_dat = cp; pp->pk_buf = buf; pp->pk_max = pvmudpmtu; } */ pp->pk_len = len; pp->pk_src = src; pp->pk_dst = dst; pp->pk_flag = inmsgs[next].ph_flag; pp->pk_tag = inmsgs[next].ph_tag; pp->pk_ctx = inmsgs[next].ph_ctx; pp->pk_enc = inmsgs[next].ph_enc; pp->pk_wid = inmsgs[next].ph_wid; pp->pk_crc = inmsgs[next].ph_crc; if (tp = task_find(src)) { loclinpkt(tp, pp); /* CL tasks caught here. forked ones caught by SIGCHLD/SIGCLD */ if ((tp->t_flag & TF_CLOSE) && !(tp->t_flag & TF_FORKD)) { task_cleanup(tp); task_free(tp); } } else { sprintf(pvmtxt, "mpp_input() from unknown task t%x\n", src); pvmlogerror(pvmtxt); pk_free(pp); } } while ((inbp->mb_read = next) != inbp->mb_last); } /* mpp_output() * * Send packet to a task if it's connected, otherwise queue it in * a list to be retried later. * * Returns 0 if packet sent, else 1. */ int mpp_output(tp, pp) struct task *tp; struct pkt *pp; { struct peer *pe; int dst; struct shmpkhdr *dmsgs = 0; struct pkt *pp1, *pp2; struct msgboxhdr *dboxp; char *cp; int loc; int next; dst = pp->pk_dst; /* * if page is private, copy and replace it with one in shared buf */ if ((loc = pp->pk_dat - outmsgbuf) > outbufsz * pvmpgsz || loc < 0) { if (nbufsowned == outbufsz) { static int once = 1; if (once) { pvmlogerror("mpp_output() Message(s) too long for shared buffer, deadlocked.\n"); once = 0; } } cp = 0; do { if (cp) da_unref(cp); cp = da_new(MAXHDR + pp->pk_len); } while ((loc = cp - outmsgbuf) > outbufsz*pvmpgsz || loc < 0); BCOPY(pp->pk_dat, cp + MAXHDR, pp->pk_len); pp->pk_dat = cp + MAXHDR; da_unref(pp->pk_buf); pp->pk_buf = cp; } if ((pe = peer_conn(dst, (int *)0)) && pe != (struct peer *)-1L) { dboxp = (struct msgboxhdr *)pe->p_buf; dmsgs = (struct shmpkhdr *)(dboxp + 1); PAGELOCK(&dboxp->mb_lock); if ((next = (dboxp->mb_last + 1) % inboxsz) != dboxp->mb_read) { if (pvmdebmask & PDMPACKET) { sprintf(pvmtxt, "mpp_output() src t%x dst t%x ff %x len %d\n", pp->pk_src, pp->pk_dst, pp->pk_flag & (FFSOM|FFEOM), pp->pk_len); pvmlogerror(pvmtxt); } dmsgs[next].ph_src = pp->pk_src; dmsgs[next].ph_dst = dst; dmsgs[next].ph_sdr = pvmmytid; dmsgs[next].ph_dat = loc; dmsgs[next].ph_len = pp->pk_len; dmsgs[next].ph_flag = pp->pk_flag & (FFSOM|FFEOM); dmsgs[next].ph_ctx = pp->pk_ctx; dmsgs[next].ph_tag = pp->pk_tag; dmsgs[next].ph_enc = pp->pk_enc; dmsgs[next].ph_wid = pp->pk_wid; dmsgs[next].ph_crc = pp->pk_crc; da_ref(pp->pk_buf); dboxp->mb_last = next; if (dboxp->mb_sleep) { /* #if defined(IMA_SUNMP) || defined(IMA_RS6KMP) || defined(IMA_AIX4MP) || defined(IMA_AIX5MP) */ #ifdef PVMUSEMUTEX #ifdef IMA_SUNMP cond_signal(&dboxp->mb_cond); #endif #if defined(IMA_RS6KMP) || defined(IMA_AIX4MP) || defined(IMA_AIX5MP) pthread_cond_signal(&dboxp->mb_cond); #endif #else peer_wake(pe); #endif /* PVMUSEMUTEX */ dboxp->mb_sleep = 0; } PAGEUNLOCK(&dboxp->mb_lock); pk_free(pp); return 0; } else LISTPUTBEFORE(ovfpkts, pp, pk_link, pk_rlink); PAGEUNLOCK(&dboxp->mb_lock); } else LISTPUTBEFORE(ovfpkts, pp, pk_link, pk_rlink); return 1; } /* mpp_probe() * * Try to send buffered packets that couldn't be delivered before. * Update state of task from NOTREADY to SOCKET if it has socket connection. * XXX shouldn't be done here, why not in loclconn. * * Returns 1 if packets ready for receipt, else 0. */ int mpp_probe() { struct pkt *pp, *pp2, *tosend; int dst; struct task *tp; int hasmsg; struct msgboxhdr *inbp = (struct msgboxhdr *)pvminbox; struct pidtidhdr *pvminfo = (struct pidtidhdr *)(infopage + PVMPAGEHDR); int ntids, i; tosend = ovfpkts; ovfpkts = pk_new(0); ovfpkts -> pk_link = ovfpkts -> pk_rlink = ovfpkts; while ((pp = tosend->pk_link) != tosend) { LISTDELETE(pp, pk_link, pk_rlink); dst = pp->pk_dst; if (tp = task_find(dst)) { if (tp->t_sock < 0) { if (mpp_output(tp, pp)) { for (pp = tosend->pk_link; pp != tosend; pp = pp2) { pp2 = pp->pk_link; if (pp->pk_dst == dst) { LISTDELETE(pp, pk_link, pk_rlink); LISTPUTBEFORE(ovfpkts, pp, pk_link, pk_rlink); } } } } else pkt_to_task(tp, pp); } else { sprintf(pvmtxt, "mpp_probe() pkt from t%x to t%x scrapped", pp->pk_src, pp->pk_dst); pvmlogperror(pvmtxt); pk_free(pp); } } pk_free(tosend); ntids = min(maxpidtid, ((struct shmpghdr *)infopage)->pg_ref); for (i = 0; i < ntids; i++) if (pidtids[i].pt_stat == ST_NOTREADY && (tp = task_find(pidtids[i].pt_tid)) && tp->t_sock >= 0) pidtids[i].pt_stat = ST_SOCKET; hasmsg = (inbp->mb_read != inbp->mb_last); return hasmsg; } /* mpp_cleanup() * * We're bailing out. All hands on deck. Remove our shared segment and * as many segments and semaphores as we can for our tasks. * */ void mpp_cleanup() { struct peer *pp; struct shmid_ds shmds; /* if (pvminbox && shmdt(pvminbox) == -1) pvmlogperror("mpp_cleanup() shmdt inbox"); */ if (myshmbufid != -1 && shmctl(myshmbufid, IPC_RMID, (struct shmid_ds *)0) == -1) pvmlogperror("mpp_cleanup() shmctl IPC_RMID mybuf"); if (peers) { for (pp = peers->p_link; pp != peers; pp = pp->p_link) { if (pp->p_buf) { shmdt(pp->p_buf); pp->p_buf = 0; } if (pp->p_shmid == -1 && pp->p_key) pp->p_shmid = shmget((key_t)pp->p_key, shmbufsiz, 0); if (pp->p_shmid != -1 && shmctl(pp->p_shmid, IPC_RMID, (struct shmid_ds *)0) == -1) { sprintf(pvmtxt, "shmctl id=0x%x", pp->p_shmid); pvmlogperror(pvmtxt); } #ifdef USERECVSEMAPHORE if (pp->p_semid == -1 && pp->p_key) pp->p_semid = semget((key_t)pp->p_key, 1, PERMS); if (pp->p_semid != -1 && semctl(pp->p_semid, 0, IPC_RMID) == -1) { sprintf(pvmtxt, "semctl id=0x%x", pp->p_semid); pvmlogperror(pvmtxt); } #endif pp->p_key = 0; } } } pidtid_dump() { int i; char *s; pvmlogerror("pidtid_dump()\n"); for (i = 0; i < maxpidtid; i++) { switch (pidtids[i].pt_stat) { case ST_EXIT: s = 0; break; case ST_NOTREADY: s = "NOTREADY"; break; case ST_SHMEM: s = "SHMEM"; break; case ST_SOCKET: s = "SOCKET"; break; case ST_FINISH: s = "FINISH"; break; default: s = "UNKNOWN"; break; } if (s) { sprintf(pvmtxt, "%4d pid %d tid %x ptid %x stat %s key 0x%x", i, pidtids[i].pt_pid, pidtids[i].pt_tid, pidtids[i].pt_ptid, s, pidtids[i].pt_key); #ifdef IMA_CSPP sprintf(pvmtxt + strlen(pvmtxt), " node %d\n", pidtids[i].pt_node); #else strcat(pvmtxt, "\n"); #endif pvmlogerror(pvmtxt); } } return 0; } /* mpp_setstatus() * * Take snapshot of task conditions and set flags in task records. */ int mpp_setstatus(tid) int tid; /* not used right now */ { int i; struct task *tp; PAGELOCK(&((struct shmpghdr *)infopage)->pg_lock); for (i = 0; i < maxpidtid; i++) if (pidtids[i].pt_stat != ST_EXIT) if (tp = task_find(pidtids[i].pt_tid)) { tp->t_flag &= ~TF_DEADSND; if (pidtids[i].pt_cond) tp->t_flag |= TF_DEADSND; } PAGEUNLOCK(&((struct shmpghdr *)infopage)->pg_lock); return 0; } /* mpp_dredge() * * Dredge pidtid table for zombies, with pt_stat == ST_FINISH. * Exit the task cleanly if it still exists and recycle the table entry. */ int mpp_dredge() { int i; struct task *tp; PAGELOCK(&((struct shmpghdr *)infopage)->pg_lock); for (i = 0; i < maxpidtid; i++) if (pidtids[i].pt_stat == ST_FINISH) { if (tp = task_find(pidtids[i].pt_tid)) { PAGEUNLOCK(&((struct shmpghdr *)infopage)->pg_lock); task_cleanup(tp); task_free(tp); PAGELOCK(&((struct shmpghdr *)infopage)->pg_lock); } else pidtids[i].pt_stat = ST_EXIT; } PAGEUNLOCK(&((struct shmpghdr *)infopage)->pg_lock); return 0; } /* ppi_load() * * Fork and exec new tasks. Give them pidtid table entries. */ int ppi_load(wxp) struct waitc_spawn *wxp; { int i; struct task *tp; int err = 0; for (i = 0; i < wxp->w_veclen; i++) { if (err) { wxp->w_vec[i] = err; } else { if (err = forkexec(wxp->w_flags, wxp->w_argv[0], wxp->w_argv, wxp->w_nenv, wxp->w_env, (wxp->w_instance+i), wxp->w_hosttotal, wxp->w_outof, &tp)) { wxp->w_vec[i] = err; } else { tp->t_ptid = wxp->w_ptid; tp->t_outtid = wxp->w_outtid; tp->t_outctx = wxp->w_outctx; tp->t_outtag = wxp->w_outtag; tp->t_trctid = wxp->w_trctid; tp->t_trcctx = wxp->w_trcctx; tp->t_trctag = wxp->w_trctag; tp->t_sched = wxp->w_sched; mpp_conn(tp); /* XXX this can fail, dunno how to clean up */ wxp->w_vec[i] = tp->t_tid; } } } return 0; } /* XXX this is just a basic copy of the pvmdunix code so we can at least compile */ int ppi_kill(tp, signum) struct task *tp; int signum; { if (tp->t_pid) (void)kill(tp->t_pid, signum); else pvmlogprintf("ppi_kill() signal for t%x scrapped (pid = 0)\n", tp->t_tid); return 0; } /* write any packets waiting the tp -> t_txq, send queue, these may have been stacked up before the task state changed to TF_SHMCONN This is currently called by tm_getopt when the state change is marked from TF_PRESHMCONN to TF_SHMCONN */ int shm_wrt_pkts(tp) struct task * tp; { struct pkt *pp, *pp2, *pptmp; struct pkt tmplist; if (tp -> t_txq) { pptmp = &tmplist; pptmp -> pk_link = pptmp->pk_rlink = pptmp; /* Take packets off of the t_txq */ pp = tp -> t_txq -> pk_link; while (pp != tp -> t_txq) { pp2 = pp; pp = pp -> pk_link; LISTDELETE(pp2, pk_link, pk_rlink); LISTPUTBEFORE(pptmp, pp2, pk_link, pk_rlink); } pp = pptmp -> pk_link; while (pp != pptmp) { pp2 = pp; pp = pp -> pk_link; LISTDELETE(pp2, pk_link, pk_rlink); if (tp -> t_flag & TF_SHMCONN) { if ( pvmdebmask & PDMPACKET) pvmlogprintf("shm_wrt_pkts for %x \n", tp -> t_tid); mpp_output(tp, pp2); } else break; } } return 0; } ./pvm3/src/pvmdtev.c0100644007401100000360000002154107240353451013526 0ustar kohlgopher static char rcsid[] = "$Id: pvmdtev.c,v 1.7 2001/02/07 23:15:53 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmdtev.c * * PVMD Tracing routines. * */ /* * Trace Descriptors Generated Manually (for simplicity) * */ #include #if defined(WIN32) || defined(CYGWIN) #include "..\xdr\types.h" #include "..\xdr\xdr.h" #else #include #include #endif #ifdef WIN32 #include #else #include #endif #include #include "pmsg.h" #include #include "tevmac.h" #include "global.h" #define CHECKLISTSIZE 100 static int init_checklist[CHECKLISTSIZE]; static int init_start = 0; static int init_end = 0; void tev_init_pvmd( dst, ctx, tag ) int dst; int ctx; int tag; { struct Pvmtevdid *ptr; struct pmsg *mp; int i; /* Check for Existing Tracer */ for ( i=init_start ; i != init_end ; i = (i + 1) % CHECKLISTSIZE ) { if ( init_checklist[i] == dst ) return; } init_checklist[init_end] = dst; init_end = ( init_end + 1 ) % CHECKLISTSIZE; init_start = ( init_end == init_start ) ? ( init_start + 1 ) % CHECKLISTSIZE : init_start; /* Send Semantic Identifiers to Trace Collector */ mp = mesg_new( 0 ); mp->m_ctx = ctx; mp->m_tag = tag; mp->m_dst = dst; pkint( mp, TEV_MARK_DATA_ID ); for ( i=0 ; i <= TEV_DID_MAX ; i++ ) { ptr = &(pvmtevdidlist[i]); /* Pack Semantic ID, Name & Description */ pkint( mp, i ); pkstr( mp, ptr->did ); pkstr( mp, ptr->desc ); } pkint( mp, TEV_MARK_DATA_ID_END ); sendmessage( mp ); } void tev_send_newtask( dst, ctx, tag, tid, ptid, flags, name ) int dst; int ctx; int tag; int tid; int ptid; int flags; char *name; { static int checklist[CHECKLISTSIZE]; static int start = 0; static int end = 0; struct timeval now; struct pmsg *mp; int flag; int tmp; int i; mp = mesg_new( 0 ); mp->m_ctx = ctx; mp->m_tag = tag; mp->m_dst = dst; gettimeofday( &now, (struct timezone *) 0 ); /* Check for Init */ tev_init_pvmd( dst, ctx, tag ); /* Check for Descriptor */ flag = 0; for ( i=start ; i != end && !flag ; i = (i + 1) % CHECKLISTSIZE ) { if ( checklist[i] == dst ) flag++; } /* Pack NEWTASK Event Message (with descriptor if necessary) */ /* Header */ if ( !flag ) { pkint( mp, TEV_MARK_EVENT_DESC ); pkint( mp, TEV_NEWTASK ); pkstr( mp, pvmtevinfo[ TEV_NEWTASK ].name ); checklist[end] = dst; end = ( end + 1 ) % CHECKLISTSIZE; start = ( end == start ) ? ( start + 1 ) % CHECKLISTSIZE : start; } else { pkint( mp, TEV_MARK_EVENT_RECORD ); pkint( mp, TEV_NEWTASK ); } /* Time Stamp Seconds */ if ( !flag ) { pkint( mp, TEV_DID_TS ); pkint( mp, TEV_DATA_INT | TEV_DATA_SCALAR ); } pkint( mp, (int) now.tv_sec ); /* Time Stamp Microseconds */ if ( !flag ) { pkint( mp, TEV_DID_TU ); pkint( mp, TEV_DATA_INT | TEV_DATA_SCALAR ); } pkint( mp, (int) now.tv_usec ); /* Task ID */ if ( !flag ) { pkint( mp, TEV_DID_TID ); pkint( mp, TEV_DATA_INT | TEV_DATA_SCALAR ); } pkint( mp, tid ); /* Parent Task ID */ if ( !flag ) { pkint( mp, TEV_DID_PT ); pkint( mp, TEV_DATA_INT | TEV_DATA_SCALAR ); } pkint( mp, ptid ); /* Task Flags */ if ( !flag ) { pkint( mp, TEV_DID_TF ); pkint( mp, TEV_DATA_INT | TEV_DATA_SCALAR ); } pkint( mp, flags ); /* Task Name */ if ( !flag ) { pkint( mp, TEV_DID_TN ); pkint( mp, TEV_DATA_STRING | TEV_DATA_SCALAR ); } pkstr( mp, name ); /* End Marker */ if ( !flag ) pkint( mp, TEV_MARK_EVENT_DESC_END ); else pkint( mp, TEV_MARK_EVENT_RECORD_END ); sendmessage( mp ); } void tev_send_spntask( dst, ctx, tag, tid, ptid ) int dst; int ctx; int tag; int tid; int ptid; { static int checklist[CHECKLISTSIZE]; static int start = 0; static int end = 0; struct timeval now; struct pmsg *mp; int flag; int tmp; int i; mp = mesg_new( 0 ); mp->m_ctx = ctx; mp->m_tag = tag; mp->m_dst = dst; gettimeofday( &now, (struct timezone *) 0 ); /* Check for Init */ tev_init_pvmd( dst, ctx, tag ); /* Check for Descriptor */ flag = 0; for ( i=start ; i != end && !flag ; i = (i + 1) % CHECKLISTSIZE ) { if ( checklist[i] == dst ) flag++; } /* Pack SPNTASK Event Message (with descriptor if necessary) */ /* Header */ if ( !flag ) { pkint( mp, TEV_MARK_EVENT_DESC ); pkint( mp, TEV_SPNTASK ); pkstr( mp, pvmtevinfo[ TEV_SPNTASK ].name ); checklist[end] = dst; end = ( end + 1 ) % CHECKLISTSIZE; start = ( end == start ) ? ( start + 1 ) % CHECKLISTSIZE : start; } else { pkint( mp, TEV_MARK_EVENT_RECORD ); pkint( mp, TEV_SPNTASK ); } /* Time Stamp Seconds */ if ( !flag ) { pkint( mp, TEV_DID_TS ); pkint( mp, TEV_DATA_INT | TEV_DATA_SCALAR ); } pkint( mp, (int) now.tv_sec ); /* Time Stamp Microseconds */ if ( !flag ) { pkint( mp, TEV_DID_TU ); pkint( mp, TEV_DATA_INT | TEV_DATA_SCALAR ); } pkint( mp, (int) now.tv_usec ); /* Task ID */ if ( !flag ) { pkint( mp, TEV_DID_TID ); pkint( mp, TEV_DATA_INT | TEV_DATA_SCALAR ); } pkint( mp, tid ); /* Parent Task ID */ if ( !flag ) { pkint( mp, TEV_DID_PT ); pkint( mp, TEV_DATA_INT | TEV_DATA_SCALAR ); } pkint( mp, ptid ); /* End Marker */ if ( !flag ) pkint( mp, TEV_MARK_EVENT_DESC_END ); else pkint( mp, TEV_MARK_EVENT_RECORD_END ); sendmessage( mp ); } void tev_send_endtask( dst, ctx, tag, tid, status, usec, uusec, ssec, susec ) int dst; int ctx; int tag; int tid; int status; long usec; long uusec; long ssec; long susec; { static int checklist[CHECKLISTSIZE]; static int start = 0; static int end = 0; struct timeval now; struct pmsg *mp; int flag; int tmp; int i; mp = mesg_new( 0 ); mp->m_ctx = ctx; mp->m_tag = tag; mp->m_dst = dst; gettimeofday( &now, (struct timezone *) 0 ); /* Check for Init */ tev_init_pvmd( dst, ctx, tag ); /* Check for Descriptor */ flag = 0; for ( i=start ; i != end && !flag ; i = (i + 1) % CHECKLISTSIZE ) { if ( checklist[i] == dst ) flag++; } /* Pack ENDTASK Event Message (with descriptor if necessary) */ /* Header */ if ( !flag ) { pkint( mp, TEV_MARK_EVENT_DESC ); pkint( mp, TEV_ENDTASK ); pkstr( mp, pvmtevinfo[ TEV_ENDTASK ].name ); checklist[end] = dst; end = ( end + 1 ) % CHECKLISTSIZE; start = ( end == start ) ? ( start + 1 ) % CHECKLISTSIZE : start; } else { pkint( mp, TEV_MARK_EVENT_RECORD ); pkint( mp, TEV_ENDTASK ); } /* Time Stamp Seconds */ if ( !flag ) { pkint( mp, TEV_DID_TS ); pkint( mp, TEV_DATA_INT | TEV_DATA_SCALAR ); } pkint( mp, (int) now.tv_sec ); /* Time Stamp Microseconds */ if ( !flag ) { pkint( mp, TEV_DID_TU ); pkint( mp, TEV_DATA_INT | TEV_DATA_SCALAR ); } pkint( mp, (int) now.tv_usec ); /* Task ID */ if ( !flag ) { pkint( mp, TEV_DID_TID ); pkint( mp, TEV_DATA_INT | TEV_DATA_SCALAR ); } pkint( mp, tid ); /* Task Status */ if ( !flag ) { pkint( mp, TEV_DID_TST ); pkint( mp, TEV_DATA_INT | TEV_DATA_SCALAR ); } pkint( mp, status ); /* User Time Seconds */ if ( !flag ) { pkint( mp, TEV_DID_TUS ); pkint( mp, TEV_DATA_INT | TEV_DATA_SCALAR ); } pkint( mp, (int) usec ); /* User Time Microseconds */ if ( !flag ) { pkint( mp, TEV_DID_TUU ); pkint( mp, TEV_DATA_INT | TEV_DATA_SCALAR ); } pkint( mp, (int) uusec ); /* System Time Seconds */ if ( !flag ) { pkint( mp, TEV_DID_TSS ); pkint( mp, TEV_DATA_INT | TEV_DATA_SCALAR ); } pkint( mp, (int) ssec ); /* System Time Microseconds */ if ( !flag ) { pkint( mp, TEV_DID_TSU ); pkint( mp, TEV_DATA_INT | TEV_DATA_SCALAR ); } pkint( mp, (int) susec ); /* End Marker */ if ( !flag ) pkint( mp, TEV_MARK_EVENT_DESC_END ); else pkint( mp, TEV_MARK_EVENT_RECORD_END ); sendmessage( mp ); } ./pvm3/src/pvmdunix.c0100644007401100000360000001402707240353452013715 0ustar kohlgopher static char rcsid[] = "$Id: pvmdunix.c,v 1.15 2001/02/07 23:15:54 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmdunix.c * * Support routines for pvmd in unix environment. * * $Log: pvmdunix.c,v $ * Revision 1.15 2001/02/07 23:15:54 pvmsrc * 2nd Half of CYGWIN Check-ins... * (Spanker=kohl) * * Revision 1.14 2000/02/16 22:00:29 pvmsrc * Fixed up #include stuff... * - use for IMA_TITN... * - #include before any NEEDMENDIAN #includes... * (Spanker=kohl) * * Revision 1.13 2000/02/08 16:58:59 pvmsrc * Re-arranged #include of header files for CRAY J932se. * - move rpc/types.h, rpc/xdr.h before sys/time.h, sys/socket.h... * - patch submitted by "Francois Moyroud" * (Spanker=kohl) * * Revision 1.12 1999/07/08 19:00:11 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.11 1998/11/20 20:10:40 pvmsrc * Lets try this again.... * * Changes so that compiles & builds on win32. Also, single * source win32 & unix * (Spanker=sscott) * * Revision 1.10 1997/08/29 13:35:17 pvmsrc * OS2 Port Submitted by Bohumir Horeni, horeni@login.cz. * (Spanker=kohl) * * Revision 1.9 1997/07/30 19:01:23 pvmsrc * Markus Fixes. * * Revision 1.8 1997/06/27 19:52:15 pvmsrc * Integrated WIN32 changes. * * Revision 1.7 1997/06/24 20:39:21 pvmsrc * Eliminated unnecessary global externs. * * Revision 1.6 1997/06/16 13:40:35 pvmsrc * ppi_load changed to pass extra info into forkexec call to help taskers. * * Revision 1.5 1997/03/06 21:11:38 pvmsrc * formatting :-) * * Revision 1.4 1997/01/28 19:27:25 pvmsrc * New Copyright Notice & Authors. * * Revision 1.3 1996/10/25 13:58:04 pvmsrc * Replaced old #includes for protocol headers: * - , "ddpro.h", "tdpro.h" * With #include of new combined header: * - * * Revision 1.2 1996/10/24 21:04:52 pvmsrc * Moved #include of "global.h" down below other headers: * - need to have all of the structures / types declared before * the globals can be declared... * * Revision 1.1 1996/09/23 23:44:35 pvmsrc * Initial revision * */ #ifndef WIN32 #include #endif #ifdef IMA_TITN #include #else #include #endif #ifdef NEEDMENDIAN #include #endif #ifdef NEEDENDIAN #include #endif #ifdef NEEDSENDIAN #include #endif #include #if defined(WIN32) || defined(CYGWIN) #include "..\xdr\types.h" #include "..\xdr\xdr.h" #else #include #include #endif #ifdef WIN32 #include "pvmwin.h" #include #else #include #include #include #include #endif #ifdef SYSVSTR #include #define CINDEX(s,c) strchr(s,c) #else #include #define CINDEX(s,c) index(s,c) #endif #include #include #include #include #include "pvmalloc.h" #include "host.h" #include "pmsg.h" #include "waitc.h" #include "task.h" #include "listmac.h" #include "bfunc.h" #include "global.h" #if defined(IMA_CRAY) || defined(IMA_CRAY2) || defined(IMA_I860) || defined(IMA_E88K) || defined(IMA_SCO) #ifndef MAXPATHLEN #define MAXPATHLEN CANBSIZ #endif #endif /*************** ** Globals ** ** ** ***************/ /* ppi_load() * * Start a set of new tasks running on this host. */ int ppi_load(wxp) struct waitc_spawn *wxp; { int i; struct task *tp; int err = 0; #ifdef WIN32 /* even being left untouched the filename gets a further */ /* extension to %SystemRoot% which causes to return PvmNoFile */ char filename[64]; strcpy(filename,wxp->w_argv[0]); #endif for (i = 0; i < wxp->w_veclen; i++) { if (err) { wxp->w_vec[i] = err; } else { #ifdef WIN32 strcpy(wxp->w_argv[0],filename); #endif if ( err = forkexec(wxp->w_flags, wxp->w_argv[0], wxp->w_argv, wxp->w_nenv, wxp->w_env, (wxp->w_instance+i), wxp->w_hosttotal, wxp->w_outof, &tp)) /* inst+i as each process is started inst is really an offset */ { wxp->w_vec[i] = err; } else { tp->t_ptid = wxp->w_ptid; tp->t_outtid = wxp->w_outtid; tp->t_outctx = wxp->w_outctx; tp->t_outtag = wxp->w_outtag; tp->t_trctid = wxp->w_trctid; tp->t_trcctx = wxp->w_trcctx; tp->t_trctag = wxp->w_trctag; tp->t_sched = wxp->w_sched; wxp->w_vec[i] = tp->t_tid; } } } return 0; } int ppi_kill(tp, signum) struct task *tp; int signum; { if (tp->t_pid) #ifndef WIN32 #ifdef IMA_OS2 (void)os2_kill(tp->t_pid, signum); #else (void)kill(tp->t_pid, signum); #endif #else (void)kill(tp->t_pid,tp->t_handle,signum); #endif else pvmlogprintf("ppi_kill() signal for t%x scrapped (pid = 0)\n", tp->t_tid); return 0; } int ppi_config(argc, argv) int argc; char **argv; { return 0; } int ppi_init() { return 0; } ./pvm3/src/pvmerr.c0100644007401100000360000000725007050647577013373 0ustar kohlgopher static char rcsid[] = "$Id: pvmerr.c,v 1.8 2000/02/10 23:53:35 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmerr.c * * Text of PVM error messages. * * $Log: pvmerr.c,v $ * Revision 1.8 2000/02/10 23:53:35 pvmsrc * Added new PvmIPLoopback error code: * - Master Host IP Address tied to Loopback. * - check for this case in addhosts(), don't even TRY to add hosts... * (Spanker=kohl) * * Revision 1.7 1999/07/08 19:00:12 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.6 1997/10/01 15:35:41 pvmsrc * Added missing "PvmParentNotSet" name to errnames[] array. * - for errnamecode() routine... * (Spanker=kohl) * * Revision 1.5 1997/06/25 22:09:36 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.4 1997/06/23 21:26:15 pvmsrc * Added new PvmHostrNMstr error code. * - Hoster must run on master host. * * Revision 1.3 1997/01/28 19:27:26 pvmsrc * New Copyright Notice & Authors. * * Revision 1.2 1996/10/24 21:18:30 pvmsrc * Moved #include "global.h" to end of #include's for typing. * Added #include of new "lpvm.h" in place of explicitly extern-ed * globals... * * Revision 1.1 1996/09/23 23:44:36 pvmsrc * Initial revision * */ #include #include #include "lpvm.h" #include "global.h" /*************** ** Globals ** ** ** ***************/ /*************** ** Private ** ** ** ***************/ static char *errnames[] = { "PvmOk", "", "PvmBadParam", "PvmMismatch", "PvmOverflow", "PvmNoData", "PvmNoHost", "PvmNoFile", "PvmDenied", "", "PvmNoMem", "", "PvmBadMsg", "", "PvmSysErr", "PvmNoBuf", "PvmNoSuchBuf", "PvmNullGroup", "PvmDupGroup", "PvmNoGroup", "PvmNotInGroup", "PvmNoInst", "PvmHostFail", "PvmNoParent", "PvmNotImpl", "PvmDSysErr", "PvmBadVersion", "PvmOutOfRes", "PvmDupHost", "PvmCantStart", "PvmAlready", "PvmNoTask", "PvmNotFound", "PvmExists", "PvmHostrNMstr", "PvmParentNotSet", "PvmIPLoopback", 0 }; int pvm_perror(s) char *s; { if (pvmmytid == -1) fprintf(stderr, "libpvm [pid%d]: ", pvmmyupid); else fprintf(stderr, "libpvm [t%x]: ", pvmmytid); fprintf(stderr, "%s: %s\n", (s ? s : "(null)"), (pvm_errno <= 0 && pvm_errno > -pvm_nerr ? pvm_errlist[-pvm_errno] : "Unknown Error")); return 0; } int errnamecode(s) char *s; { int i; for (i = 0; errnames[i]; i++) if (!strcmp(s, errnames[i])) return -i; return 0; } ./pvm3/src/pvmfrag.c0100644007401100000360000001370606741172474013520 0ustar kohlgopher static char rcsid[] = "$Id: pvmfrag.c,v 1.5 1999/07/08 19:00:12 kohl Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmfrag.c * * Frag buffer util. * * $Log: pvmfrag.c,v $ * Revision 1.5 1999/07/08 19:00:12 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.4 1997/06/25 22:09:37 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.3 1997/04/24 20:58:53 pvmsrc * intialize fr_rip to 0 * * Revision 1.2 1997/01/28 19:27:27 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:44:37 pvmsrc * Initial revision * * Revision 1.3 1995/05/17 16:42:49 manchek * added support for CSPP shared memory. * use CLUMP_ALLOC option to clump frag headers * * Revision 1.2 1994/06/03 20:38:24 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:26:51 manchek * Initial revision * */ #include #include "pvmalloc.h" #include "pvmfrag.h" #include "listmac.h" #include "pvmdabuf.h" extern void pvmbailout(); /*************** ** Private ** ** ** ***************/ #ifdef IMA_CSPP /* NOTE: If we were doing flushes on node, we'd have to set dcache_stride to 32 for single node systems and 64 for multinode systems. But since we only do this for cross node systems, we already know it needs to be 64 */ int dcache_stride = 64; #endif #ifdef CLUMP_ALLOC #ifndef FRAG_CLUMP #define FRAG_CLUMP 500 #endif static struct frag freefrags; /* free frag header cache */ static int numfrags = 0; #endif static struct frag * frag_get_header() { struct frag *fp; int n; #ifdef CLUMP_ALLOC if (numfrags == 0) { freefrags.fr_link = freefrags.fr_rlink = &freefrags; if (!(fp = TALLOC(FRAG_CLUMP, struct frag, "frgs"))) return (struct frag *)0; for (n = FRAG_CLUMP; n-- > 0; ) { LISTPUTBEFORE(&freefrags, fp, fr_link, fr_rlink); fp++; } numfrags = FRAG_CLUMP; } numfrags--; fp = freefrags.fr_link; LISTDELETE(fp, fr_link, fr_rlink); #else fp = TALLOC(1, struct frag, "frag"); #endif return fp; } static frag_put_header(fp) struct frag *fp; { #ifdef CLUMP_ALLOC if (numfrags == 0) freefrags.fr_link = freefrags.fr_rlink = &freefrags; LISTPUTBEFORE(&freefrags, fp, fr_link, fr_rlink); numfrags++; #else PVM_FREE(fp); #endif return 0; } /********************** ** Frag Functions ** ** ** **********************/ /* fr_new() * * Create a new frag with 1 reference, not in a list. * If len is nonzero, len bytes are allocated as data space. * Else, the frag has no data (is a master or will get data later). */ struct frag * fr_new(len) int len; /* (max) buffer size or 0 */ { struct frag *fp; if (!(fp = frag_get_header())) goto oops; if (len) { /* slave frag */ fp->fr_link = fp->fr_rlink = 0; if (!(fp->fr_dat = fp->fr_buf = da_new(len))) { frag_put_header(fp); goto oops; } fp->fr_max = len; } else { /* master */ fp->fr_link = fp->fr_rlink = fp; fp->fr_dat = fp->fr_buf = 0; fp->fr_max = 0; } fp->fr_len = 0; fp->fr_u.ref = 1; fp->fr_u.dab = 1; fp->fr_u.spr = 0; fp->fr_rip = 0; #ifdef IMA_CSPP fp->fr_num_unpacked = 0; #endif /* pvmlogprintf("fr_new() %d = %lx\n", len, fp); */ return fp; oops: pvmlogerror("fr_new() can't get memory\n"); pvmbailout(0); return (struct frag*)0; } /* fr_snew() * * Create a new frag with 1 reference, not in a list. * Its buffer is assumed to be a writable, dense, non-databuf. */ struct frag * fr_snew(cp, len) char *cp; /* buffer */ int len; /* buffer size */ { struct frag *fp; if (!(fp = frag_get_header())) goto oops; fp->fr_link = fp->fr_rlink = 0; fp->fr_dat = fp->fr_buf = cp; fp->fr_max = fp->fr_len = len; fp->fr_u.ref = 1; fp->fr_u.dab = 0; fp->fr_u.spr = 0; fp->fr_rip = 0; return fp; oops: pvmlogerror("fr_snew() can't get memory\n"); pvmbailout(0); return (struct frag*)0; } /* fr_unref() * * Reduce frag refcount by 1. If result is < 1: * If the frag is a master, unref all its slave frags * Else, unref its data. * Then, free the frag. */ void fr_unref(fp) struct frag *fp; /* master frag */ { /* pvmlogprintf("fr_unref() %lx ref %d\n", fp, fp->fr_u.ref); */ if (fp->fr_u.ref-- == 1) { struct frag *fp2, *fp3; if (fp->fr_buf) { /* slave frag */ if (fp->fr_u.dab) #ifdef IMA_CSPP if (fp->fr_num_unpacked) { unsigned int addr = (unsigned int)(fp->fr_dat); int nbytes = fp->fr_num_unpacked; nbytes += (addr & 0x3f); addr &= ~0x3f; dcache_flush_region(addr, nbytes); } #endif da_unref(fp->fr_buf); } else { /* master frag */ /* unref all frags in chain */ for (fp2 = fp->fr_link; fp2 != fp; fp2 = fp3) { fp3 = fp2->fr_link; LISTDELETE(fp2, fr_link, fr_rlink); fr_unref(fp2); } } frag_put_header(fp); } } ./pvm3/src/pvmlog.c0100644007401100000360000003315310055137064013345 0ustar kohlgopher static char rcsid[] = "$Id: pvmlog.c,v 1.25 2004/05/26 15:56:36 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmlog.c * * Error logging fac. * * $Log: pvmlog.c,v $ * Revision 1.25 2004/05/26 15:56:36 pvmsrc * Attempt to fix yet-another-x86_64 bug... * - looks like varargs stuff is one-time-use-only... * -> replace repeated vfprintf() calls with one vsprintf() call... * (Spanker=kohl) * * Revision 1.24 2004/02/09 17:17:02 pvmsrc * Added pvmlogperror debug output for AMD64... * - the arch that wouldn't die... er, run without seg faulting... :) * (Spanker=kohl) * * Revision 1.23 2004/02/03 21:40:57 pvmsrc * Added check for NULL strerror() return... * - to chase down AMD64 problem... * (Spanker=kohl) * * Revision 1.22 2004/01/14 19:12:35 pvmsrc * Added (char *) cast to strerror() assignment... * (Spanker=kohl) * * Revision 1.21 2001/09/26 21:23:56 pvmsrc * Added Handling for Optional Virtual Machine ID. * - append virtual machine ID string to pvmd log file, too, * if set in PVM_VMID env var. * - not restricted to be integer as in SGI, can be arbitrary * string... heh, heh... :-} * (Spanker=kohl) * * Revision 1.20 2001/09/25 21:21:05 pvmsrc * Yanked "char *pvmgettmp();" decl - now in pvm3.h... * (Spanker=kohl) * * Revision 1.19 2001/05/11 18:58:13 pvmsrc * Added use of new "USESTRERROR" define. * - uses strerror() function instead of sys_errlist/sys_nerr * (which aren't public globals on some new operating systems). * (Spanker=kohl) * * Revision 1.18 2000/03/30 18:01:18 pvmsrc * Damn. Max PVMD Log Size Checking Whacked! * - everything goes through pvmlogprintf() now, transferred old * code from pvmlogerror() to truncate logging... * (Spanker=kohl) * * Revision 1.17 2000/02/10 20:46:43 pvmsrc * Replaced hard-coded /tmp usage with PVMDLOGFILE. * - use pvmgettmp() routine now to determine PVM temp dir. * - also, eliminated goofy pvmtmpspec stuff for WIN32, cleaned up * string manip... * (Spanker=kohl) * * Revision 1.16 1999/12/10 21:29:40 pvmsrc * Added pvmdlogmax = pvmdlogmax for picky SGI compiler warning... :-Q * (Spanker=kohl) * * Revision 1.15 1999/07/08 19:00:13 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.14 1999/02/09 23:06:54 pvmsrc * Cleaned up temp file stuff (mainly for WIN32). * - extracted new pvmgettmp() routine for returning tmp directory. * (Spanker=kohl) * * Revision 1.13 1998/11/20 20:06:42 pvmsrc * Changes so that win32 will compile & build. Also, common * Changes so that compiles & builds on NT. Also * common source on win32 & unix. * (spanker=sscott) * * Revision 1.12 1998/10/02 15:44:09 pvmsrc * Single source code merge of Win32 and Unix code. * (Spanker=sscott) * * Revision 1.11 1998/09/23 15:23:48 pvmsrc * changes to use WIN32 registry as per Markus. * ifdef in pvmd.c::colonsep() to include WIN32 and OS2 * (Spanker=phil) * * Revision 1.10 1998/01/28 20:09:00 pvmsrc * Added new -DSYSERRISCONST define. * - for const char *sys_errlist... * (Spanker=kohl) * * Revision 1.9 1998/01/28 19:13:59 pvmsrc * Added new IMA_LINUXHPPA to #if cases... * (Spanker=kohl) * * Revision 1.8 1997/12/29 19:40:03 pvmsrc * Made char *em a const char *em for LINUX machines. * (Redhat 5.0/4.2 compatible.) * (Spanker=phil) * * Revision 1.7 1997/11/04 23:20:42 pvmsrc * Added IMA_LINUXALPHA to const char * error log stuff. * (Spanker=kohl) * * Revision 1.6 1997/08/29 13:35:18 pvmsrc * OS2 Port Submitted by Bohumir Horeni, horeni@login.cz. * (Spanker=kohl) * * Revision 1.5 1997/07/11 18:44:52 pvmsrc * WIN32 fix for console bug (quit caused halt) - Markus. * * Revision 1.4 1997/06/27 20:04:54 pvmsrc * Integrated WIN32 changes. * * Revision 1.3 1997/04/30 21:32:48 pvmsrc * SGI Compiler Warning Cleanup. * - fixed up return codes for vpvmlogprintf(). * * Revision 1.2 1997/01/28 19:27:29 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:44:39 pvmsrc * Initial revision * * Revision 1.6 1995/07/28 16:41:00 manchek * wrap HASERRORVARS around errno declarations * * Revision 1.5 1995/05/17 16:44:56 manchek * added CSPP subcomplex support (/tmp file names include proc. id). * use PVMDLOGMAX envar to set logging limit to /tmp/pvml.uid * * Revision 1.4 1994/06/03 20:38:25 manchek * version 3.3.0 * * Revision 1.3 1993/11/30 15:53:59 manchek * added timestamp option * * Revision 1.2 1993/10/04 20:31:21 manchek * renamed useruid to pvm_useruid for compat with libpvm. * added alternate logfile name if SHAREDTMP is defined * * Revision 1.1 1993/08/30 23:26:51 manchek * Initial revision * */ #include #include #include #include #include #include #ifdef SYSVSTR #include #define CINDEX(s,c) strchr(s,c) #else #include #define CINDEX(s,c) index(s,c) #endif #if defined (__STDC__) || defined(IMA_WIN32_WATCOM) #include #else #include #endif #ifndef PVMDLOGMAX #define PVMDLOGMAX 1000000 /* (approx) max chars to log to file */ #endif /* pvmd log file name */ #ifdef SHAREDTMP #define PVMDLOGFILE "%s/pvml.%d.%s" #else #ifndef WIN32 #define PVMDLOGFILE "%s/pvml.%d" #else #define PVMDLOGFILE "%s\\pvml.%s" /* for default */ #endif #endif #ifdef IMA_CSPP #ifdef SHAREDTMP #define PVMDLOGFILE_CSPP "%s/pvml.%d.%d.%s" #else #define PVMDLOGFILE_CSPP "%s/pvml.%d.%d" #endif int get_scid(); #endif /*IMA_CSPP*/ /*************** ** Globals ** ** ** ***************/ char *getenv(); #ifndef HASERRORVARS extern int errno; /* from libc */ #ifndef USESTRERROR extern int sys_nerr; extern char *sys_errlist[]; #endif #endif #ifdef IMA_OS2 #include /* ERRORVARS */ #endif extern int pvmmytid; /* from pvmd.c */ extern int pvmmyupid; /* from pvmd.c */ extern int pvm_useruid; /* from pvmd.c */ #ifdef WIN32 extern char *username; /* from pvmd.c */ #endif int log_fd = -1; /* error log file */ /*************** ** Private ** ** ** ***************/ static int log_how = 1; /* how much error logging we can do */ FILE *log_ff = 0; static int log_alrdy = 0; /* how much already written to file */ static int pvmdlogmax = PVMDLOGMAX; static char *toomuch = "\n*** logging truncated\n"; static int atnewline = 1; /* on new log line (XXX ick) */ /* pvmsetlog() * * Set new error logging level. * If how & 1, write to stderr * If how & 2, write to log file in /tmp */ int pvmsetlog(how) int how; { char buf[255]; char hna[128]; char *pvmtmp; char *p; #ifdef IMA_CSPP int scid = get_scid(); /* default (system) subcomplex ID is 1) */ /* differentiate logfile when not on system s/c */ #endif if (2 & how & ~log_how) { pvmtmp = pvmgettmp(); #ifdef SHAREDTMP if (gethostname(hna, sizeof(hna)-1) == -1) { pvmlogerror("pvmsetlog() can't gethostname()\n"); return 0; } if (p = CINDEX(hna, '.')) *p = 0; #ifdef IMA_CSPP if (scid > 1) (void)sprintf(buf, PVMDLOGFILE_CSPP, pvmtmp, pvm_useruid, scid, hna); else #endif (void)sprintf(buf, PVMDLOGFILE, pvmtmp, pvm_useruid, hna); #else /*SHAREDTMP*/ #ifdef IMA_CSPP if (scid > 1) (void)sprintf(buf, PVMDLOGFILE_CSPP, pvmtmp, pvm_useruid, scid); else #endif #ifndef WIN32 (void)sprintf(buf, PVMDLOGFILE, pvmtmp, pvm_useruid); #else (void)sprintf(buf, "%s\\pvml.%s", pvmtmp, username); #endif #endif /*SHAREDTMP*/ /* Append a Virtual Machine ID, If Set */ if ( p = getenv("PVM_VMID") ) { strcat( buf, "." ); strcat( buf, p ); } if ((log_fd = open(buf, O_WRONLY|O_TRUNC|O_CREAT|O_APPEND, 0600)) != -1) log_ff = fdopen(log_fd, "a"); else how &= ~2; if (p = getenv("PVMDLOGMAX")) pvmdlogmax = atoi(p); pvmdlogmax = pvmdlogmax; /* for picky SGI compiler warning */ } if (2 & log_how & ~how) { (void)fclose(log_ff); log_ff = 0; log_fd = -1; } log_how = how; return 0; } int vpvmlogprintf(fmt, ap) char *fmt; va_list ap; { char vtmp[255]; int cnt = 0; int cc; #ifdef TIMESTAMPLOG time_t now; struct tm *tmp; time(&now); tmp = localtime(&now); #endif /*TIMESTAMPLOG*/ /* snag var arg string, in case re-use whacks it... */ /* (thank you very much x86_64... :-Q */ vsprintf(vtmp, fmt, ap); if (log_how & 1) { if (atnewline) { if (pvmmytid) fprintf(stderr, "[t%x] ", pvmmytid); else fprintf(stderr, "[pvmd pid%d] ", pvmmyupid); #ifdef TIMESTAMPLOG fprintf(stderr, "%02d/%02d %02d:%02d:%02d ", tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); #endif /*TIMESTAMPLOG*/ } /* cc = vfprintf(stderr, fmt, ap); */ cc = fprintf(stderr, vtmp); cnt = ( cc >= 0 ) ? cnt + cc : cc; fflush(stderr); } if (log_how & 2) { if (log_alrdy < pvmdlogmax) { if (atnewline) { if (pvmmytid) fprintf(log_ff, "[t%x] ", pvmmytid); else fprintf(log_ff, "[pvmd pid%d] ", pvmmyupid); #ifdef TIMESTAMPLOG fprintf(log_ff, "%02d/%02d %02d:%02d:%02d ", tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); #endif /*TIMESTAMPLOG*/ } /* cc = vfprintf(log_ff, fmt, ap); */ cc = fprintf(log_ff, vtmp); cnt = ( cnt >= 0 ) ? ( ( cc >= 0 ) ? cnt + cc : cc ) : cnt; fflush(log_ff); if ((log_alrdy += cnt) >= pvmdlogmax) (void)write(log_fd, toomuch, strlen(toomuch)); } } atnewline = (fmt[strlen(fmt) - 1] == '\n') ? 1 : 0; /* if ((log_how & 4) && hosts->ht_local != hosts->ht_cons) { XXX send error-log message to console host } */ return(cnt); } int #if defined (__STDC__) || defined(IMA_WIN32_WATCOM) pvmlogprintf(const char *fmt, ...) #else pvmlogprintf(va_alist) va_dcl #endif { va_list ap; int cc; #if defined (__STDC__) || defined(IMA_WIN32_WATCOM) va_start(ap, fmt); #else char *fmt; va_start(ap); fmt = va_arg(ap, char *); #endif cc = vpvmlogprintf(fmt, ap); va_end(ap); return cc; } int pvmlogperror(s) char *s; /* text */ { #ifdef WIN32 char em[16]; int error_nr=0; #else #ifdef SYSERRISCONST const char *em; #else char *em; #endif #endif int i; #ifndef WIN32 #ifdef USESTRERROR em = (char *) strerror( errno ); #else em = ((errno >= 0 && errno < sys_nerr) ? sys_errlist[errno] : "Unknown Error"); #endif #else error_nr = GetLastError(); sprintf(em,"%d",error_nr); #endif pvmlogprintf("%s: ", s); pvmlogprintf("errno=%d", errno); pvmlogprintf("\n"); pvmlogprintf("em=0x%lx\n", (long) em); for (i=0; i < 10 ; i++ ) pvmlogprintf("[%x/%c]", em[i]); pvmlogprintf("\n"); pvmlogprintf("%s: %s\n", s, em); return 0; } /* pvmlogerror() * * Log an error message. Effect depends on how far we've gotten. * If log_how & 1, write to stderr. * If log_how & 2, can write to the logfile. * If log_how & 4, can send message to console pvmd. */ pvmlogerror(s) char *s; /* text */ { pvmlogprintf("%s", s); atnewline = 1; return 0; #if NOMORELOGERROR int len = strlen(s); char buf[40]; int l; #ifdef TIMESTAMPLOG time_t now; struct tm *tmp; time(&now); tmp = localtime(&now); #endif /*TIMESTAMPLOG*/ if (log_how & 1) { #ifdef TIMESTAMPLOG if (pvmmytid) fprintf(stderr, "[t%x] %02d/%02d %02d:%02d:%02d %s", pvmmytid, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec, s); else fprintf(stderr, "[pvmd pid%d] %02d/%02d %02d:%02d:%02d %s", pvmmyupid, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec, s); #else /*TIMESTAMPLOG*/ if (pvmmytid) fprintf(stderr, "[t%x] %s", pvmmytid, s); else fprintf(stderr, "[pvmd pid%d] %s", pvmmyupid, s); #endif /*TIMESTAMPLOG*/ } if (log_how & 2) { if (log_alrdy < pvmdlogmax) { #ifdef TIMESTAMPLOG if (pvmmytid) sprintf(buf, "[t%x] %02d/%02d %02d:%02d:%02d ", pvmmytid, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); else sprintf(buf, "[pvmd pid%d] %02d/%02d %02d:%02d:%02d ", pvmmyupid, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); #else /*TIMESTAMPLOG*/ if (pvmmytid) sprintf(buf, "[t%x] ", pvmmytid); else sprintf(buf, "[pvmd pid%d] ", pvmmyupid); #endif /*TIMESTAMPLOG*/ l = strlen(buf); (void)write(log_fd, buf, l); (void)write(log_fd, s, len); if ((log_alrdy += len + l) >= pvmdlogmax) (void)write(log_fd, toomuch, strlen(toomuch)); } } /* if ((log_how & 4) && hosts->ht_local != hosts->ht_cons) { XXX send error-log message to console host } */ #endif } ./pvm3/src/pvmshmem.c0100644007401100000360000005146310001307627013674 0ustar kohlgopher static char rcsid[] = "$Id: pvmshmem.c,v 1.11 2004/01/14 18:51:03 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmshmem.c * * Shared-memory stuff. * * $Log: pvmshmem.c,v $ * Revision 1.11 2004/01/14 18:51:03 pvmsrc * Added new AIX5* arches. * (Spanker=kohl) * * Revision 1.10 1999/07/08 19:00:14 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.9 1998/08/13 18:31:12 pvmsrc * Altered SUNMP to use test and set operations with semaphores * for page locking instead of MUTEX and cond vars. * Changes are mainly in pvmshmem.h, with lots of #ifdefs changes. * Makefile altered to use the PLOCKFILE to indicate the Page Locking * INLINE code used (from SUNMP.conf). * Some changes effect AIX MP versions which still use conditional * variables and may change to semaphores soon. * (Spanker=fagg) * * Revision 1.8 1998/03/05 16:31:31 pvmsrc * Hack for CSPP - _touch() wasn't typed before use... :-Q * (Spanker=kohl) * * Revision 1.7 1997/07/08 20:18:07 pvmsrc * Better logging in peer_conn() * * Revision 1.6 1997/06/25 22:11:10 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.5 1997/05/21 16:01:55 pvmsrc * Updated ifdefs to include AIX4MP arch type. * * Revision 1.4 1997/04/25 19:18:14 pvmsrc * Corrected includes. * * Revision 1.3 1997/01/28 19:27:30 pvmsrc * New Copyright Notice & Authors. * * Revision 1.2 1996/10/25 14:19:06 pvmsrc * Replaced old #includes for protocol headers: * - , "ddpro.h", "tdpro.h" * With #include of new combined header: * - * * Revision 1.1 1996/09/23 23:44:40 pvmsrc * Initial revision * * Revision 1.21 1995/11/02 16:33:04 manchek * peer_conn returns -1 if peer has disconnected * * Revision 1.21 1995/11/02 16:33:04 manchek * peer_conn returns -1 if peer has disconnected * * Revision 1.20 1995/09/07 17:38:27 manchek * Add __synch() when releasing lock. * * Revision 1.19 1995/07/28 15:42:45 manchek * _touch does all pages, uses PVMTOUCH envar to switch on * * Revision 1.18 1995/07/28 14:31:42 manchek * oops, shm_search had too many args * * Revision 1.17 1995/07/24 18:32:21 manchek * da_new warns of using malloc. * had the wrong ST_ state test in peer_conn * * Revision 1.16 1995/07/19 18:05:14 manchek * peer_dump prints peer info even if stat fails * * Revision 1.15 1995/07/12 01:32:52 manchek * peer_conn checks that p_buf is nonzero before returning connection, * also that tid and state in pidtid table are correct. * peer_detach zeros p_buf before detaching in case interrupt occurs, * now unlinks and frees peer struct. * peer_cleanup adjusted to this * * Revision 1.14 1995/07/05 15:33:32 manchek * clean up semaphore too in peer_detach * * Revision 1.13 1995/07/03 21:15:40 manchek * declare getenv * * Revision 1.12 1995/07/03 20:36:14 manchek * made convex loopback code the general case in peer_conn() * * Revision 1.11 1995/07/03 19:35:43 manchek * hellish cleanup of comments and formatting. * removed POWER4 ifdefs. * maintain shared page counter to da_xxx to help detect deadlock. * shared segment key now created by task, passed through pt_key. * added pvmshmkey(), nextpvmshmkey() * * Revision 1.10 1995/06/28 16:08:49 manchek * peer_conn returns new connection status * * Revision 1.9 1995/06/02 16:22:10 manchek * zero p_buf in peer_detach() so we don't reference segment later * * Revision 1.8 1995/05/30 14:37:38 manchek * touched shared segment after detaching in peer_detach() * * Revision 1.7 1995/05/24 19:08:55 manchek * changed HPPA shared memory name to HPPAMP * * Revision 1.6 1995/05/22 19:53:00 manchek * added ifdefs for RS6KMP * * Revision 1.5 1995/05/18 17:22:34 manchek * need to import pvminbox and myshmbufid * * Revision 1.4 1995/05/17 16:47:22 manchek * bug fixes from SGI and Convex. * added CSPP shared memory support * * Revision 1.3 1994/11/08 15:36:49 manchek * shared memory damage control * * Revision 1.2 1994/06/04 21:44:25 manchek * updated header * * Revision 1.1 1994/06/03 20:38:26 manchek * Initial revision * */ #include #include #include #include #include #include #ifdef IMA_SYMM #include #endif #include #include #include #include "pvmalloc.h" #include "listmac.h" #include "pvmshmem.h" #include "bfunc.h" #include "global.h" #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif extern int pvmdebmask; /* from pvmd.c or lpvmshmem.c */ extern int pvmmytid; /* from pvmd.c or lpvmshmem.c */ extern int pvmpgsz; /* from pvmdshmem.c or lpvmshmem.c */ extern int pgsz; /* from pvmdshmem.c or lpvmshmem.c */ extern char *outmsgbuf; /* from pvmdshmem.c or lpvmshmem.c */ extern int outbufsz; /* from pvmdshmem.c or lpvmshmem.c */ extern int nbufsowned; /* from pvmdshmem.c or lpvmshmem.c */ extern char *infopage; /* from pvmdshmem.c or lpvmshmem.c */ extern struct pidtid *pidtids; /* from pvmdshmem.c or lpvmshmem.c */ extern int maxpidtid; /* from pvmdshmem.c or lpvmshmem.c */ extern int shmbufsiz; /* from pvmdshmem.c or lpvmshmem.c */ extern int myshmbufid; /* from pvmdshmem.c or lpvmshmem.c */ extern char *pvminbox; /* from pvmdshmem.c or lpvmshmem.c */ char *getenv(); /*************** ** Globals ** ** ** ***************/ struct peer *peers = 0; /* tasks we're connected to */ int bufpageused = 0; /* number of dirty pages in msg buf */ /*************** ** Private ** ** ** ***************/ static char pvmtxt[512]; /* scratch for error log */ static int nxtpage = 0; /* next free page in outgoing msg buf */ #ifdef IMA_CSPP static void _touch(); #endif /******************************************************* ** Shared-memory data buffer manipulation routines ** ** ** *******************************************************/ /* msgbufinit() * * Initialize the shared-memory message buffer. */ int msgbufinit(buf) char *buf; { char *p, *end; end = buf + shmbufsiz; #ifndef IMA_KSR1 #if defined(IMA_SUNMP) && defined(PVMUSEMUTEX) cond_init(&((struct msgboxhdr *)buf)->mb_cond, USYNC_PROCESS, 0); #endif #if defined(IMA_RS6KMP) || defined(IMA_AIX4MP) || defined(IMA_AIX5MP) pthread_cond_init(&((struct msgboxhdr *)buf)->mb_cond, NULL); #endif PAGEINITLOCK(&((struct msgboxhdr *)buf)->mb_lock); ((struct msgboxhdr *)buf)->mb_sleep = 0; #endif ((struct msgboxhdr *)buf)->mb_read = -1; ((struct msgboxhdr *)buf)->mb_last = -1; for (p = outmsgbuf; p < end; p += pvmpgsz) { #if !defined(TEST_ADD) && !defined(IMA_KSR1) PAGEINITLOCK(&((struct shmpghdr *)p)->pg_lock); #endif ((struct shmpghdr *)p)->pg_priv = 0; ((struct shmpghdr *)p)->pg_ref = 0; } if (pvmdebmask & PDMNODE) { sprintf(pvmtxt, "msgbufinit() outmsgbuf=0x%x\n", outmsgbuf); pvmlogerror(pvmtxt); sprintf(pvmtxt, "msgbufinit() last buffer=0x%x\n", p - pvmpgsz); pvmlogerror(pvmtxt); sprintf(pvmtxt, "msgbufinit() pvmpgsz=%d\n", pvmpgsz); pvmlogerror(pvmtxt); } return 0; } /* da_new() * * Replacement for functions in pvmdabuf.c * * Try to find a free page. Check page 0 first, and then the current one. * If neither is free, then move beyond the current page towards the end * of the buffer. */ char * da_new(len) int len; { char *p; int start; if (len > pvmpgsz - PVMPAGEHDR) { sprintf(pvmtxt, "da_new() len = %d: frag must fit in a page\n", len); pvmlogerror(pvmtxt); return 0; } #ifdef IMA_CSPP p = outmsgbuf + nxtpage*pvmpgsz; #else p = outmsgbuf; if (nxtpage && !((struct shmpghdr *)p)->pg_ref) nxtpage = 0; /* recycle to avoid page fault */ else p += nxtpage*pvmpgsz; #endif start = nxtpage; while (1) { if (((struct shmpghdr *)p)->pg_ref == 0) { nbufsowned++; break; } if (++nxtpage == outbufsz) { nxtpage = 0; p = outmsgbuf; } else p += pvmpgsz; if (nxtpage == start) { /* buffer full */ p = TALLOC(len + PVMPAGEHDR, char, "data"); if (p) { static int once = 1; if (once) { once = 0; pvmlogerror("da_new() Warning: shared buffer full, using malloc\n"); } #if !defined(IMA_KSR1) && !defined(TEST_ADD) PAGEINITLOCK(&((struct shmpghdr *)p)->pg_lock); #endif ((struct shmpghdr *)p)->pg_priv = 1; } break; } } if (nxtpage >= bufpageused) bufpageused = nxtpage + 1; if (p) { ((struct shmpghdr *)p)->pg_ref = 1; return (p + PVMPAGEHDR); } else return 0; } void da_ref(p) char *p; { p -= PVMPAGEHDR; #ifdef TEST_ADD TEST_ADD(&((struct shmpghdr *)p)->pg_ref, 1); #else PAGELOCK(&((struct shmpghdr *)p)->pg_lock); ++((struct shmpghdr *)p)->pg_ref; PAGEUNLOCK(&((struct shmpghdr *)p)->pg_lock); #endif } void da_unref(p) char *p; { p -= PVMPAGEHDR; #ifdef TEST_ADD if ((long) TEST_ADD(&((struct shmpghdr *)p)->pg_ref, -1L) < 0) pvmlogerror("ref count is negative!\n"); #else PAGELOCK(&((struct shmpghdr *)p)->pg_lock); if (--((struct shmpghdr *)p)->pg_ref < 0) { sprintf(pvmtxt, "ref = %d on page %d\n", ((struct shmpghdr *)p)->pg_ref, (p - outmsgbuf)/pgsz + 1); pvmlogerror(pvmtxt); } PAGEUNLOCK(&((struct shmpghdr *)p)->pg_lock); #endif if (((struct shmpghdr *)p)->pg_priv) { if (((struct shmpghdr *)p)->pg_ref < 1) PVM_FREE(p); } else { if (p >= outmsgbuf && p < outmsgbuf + outbufsz * pvmpgsz) nbufsowned--; } } void peer_init() { peers = TALLOC(1, struct peer, "peer"); BZERO((char*)peers, sizeof(struct peer)); peers->p_link = peers->p_rlink = peers; } /* peer_conn() * * Attach peer's message buffer. * Returns pointer to peer struct, * Else 0 if peer isn't ready to receive yet * Or -1 if peer can't be contacted via shared memory or has disconnected. */ struct peer * peer_conn(tid, new_connection) int tid; int *new_connection; { struct peer *pp; char *p; if (new_connection) *new_connection = 0; for (pp = peers->p_link; pp != peers; pp = pp->p_link) { if (pp->p_tid == tid) { /* already connected */ if (pp->p_exited || !pp->p_buf) { if (pvmdebmask & PDMMEM) { sprintf(pvmtxt, "peer_conn() t%x has exited?\n", tid); pvmlogerror(pvmtxt); } return ((struct peer *)-1L); } else { if (pvmdebmask & PDMMEM) { sprintf(pvmtxt, "peer_conn() to t%x got pp addr %lx\n", tid, pp); pvmlogerror(pvmtxt); } return pp; } } /* * test p_buf in case we're in the process of destroying this peer struct */ #if 0 /* XXX disconnect from inactive peers */ if (pp2->p_tid == -1) { /* used by pvmd */ /* peer_detach(pp2); */ shmdt(pp2->p_buf); LISTDELETE(pp2, p_link, p_rlink); PVM_FREE(pp2); } #endif } if (pp == peers && tid == pvmmytid) { if (!(pp = TALLOC(1, struct peer, "peer"))) { pvmlogerror("peer_conn() can't get memory\n"); return (struct peer *)0; } BZERO((char*)pp, sizeof(struct peer)); pp->p_buf = pvminbox; pp->p_shmid = myshmbufid; pp->p_tid = pvmmytid; pp->p_semid = -1; LISTPUTAFTER(peers, pp, p_link, p_rlink); } else if (pp == peers && tid) { int bufid, ntids, i, key; /* PAGELOCK(pvminfo); */ /* XXX the first few don't have to search the whole empty table. hmm. */ ntids = min(maxpidtid, ((struct shmpghdr *)infopage)->pg_ref); for (i = 0; i < ntids; i++) if (pidtids[i].pt_tid == tid && pidtids[i].pt_stat != ST_EXIT) { if (pidtids[i].pt_stat == ST_NOTREADY) return (struct peer *)0; if (pidtids[i].pt_stat == ST_SOCKET) return (struct peer *)-1L; /* must be ST_SHMEM or ST_FINISH */ break; } if (i == ntids) { if (pvmdebmask & PDMMEM) { sprintf(pvmtxt, "peer_conn() could not find t%x in daemon list\n", tid); pvmlogerror(pvmtxt); } return (struct peer *)-1L; /* PAGEUNLOCK(pvminfo); */ } key = pidtids[i].pt_key; if ((bufid = shmget((key_t)key, shmbufsiz, 0)) == -1) { sprintf(pvmtxt, "peer_conn() shmget t%x key 0x%x", tid, key); pvmlogperror(pvmtxt); return (struct peer *)0; } while ((p = (char *)shmat(bufid, 0, 0)) == (char *)-1L) { sprintf(pvmtxt, "peer_conn() shmat to t%x using bufid %d\n", tid, bufid); pvmlogperror(pvmtxt); if (errno == EMFILE && (pp = peers->p_rlink) != peers) { shmdt(pp->p_buf); LISTDELETE(pp, p_link, p_rlink); PVM_FREE(pp); continue; } return (struct peer *)0; } #ifdef IMA_CSPP _touch(p); #endif if (!(pp = TALLOC(1, struct peer, "peer"))) { pvmlogerror("peer_conn() can't get memory\n"); return (struct peer *)0; } BZERO((char*)pp, sizeof(struct peer)); pp->p_key = key; pp->p_tid = tid; pp->p_buf = p; pp->p_shmid = bufid; pp->p_semid = -1; #ifdef IMA_CSPP pp->p_node = pidtids[i].pt_node; #endif pp->p_exited = 0; LISTPUTAFTER(peers, pp, p_link, p_rlink); if (new_connection) *new_connection = 1; } return pp; } /* peer_wake() * * Wake up sleeping task that we just sent message to. */ void peer_wake(pp) struct peer *pp; { struct sembuf sops; if (pp->p_semid == -1 && (pp->p_semid = semget((key_t)pp->p_key, 1, PERMS)) == -1) { sprintf(pvmtxt, "peer_wake() semget t%x key 0x%x\n", pp->p_tid, pp->p_key); pvmlogperror(pvmtxt); return; } sops.sem_num = 0; sops.sem_op = 1; sops.sem_flg = 0; if (semop(pp->p_semid, &sops, 1) == -1) { sprintf(pvmtxt, "peer_wake() semop t%x\n", pp->p_tid); pvmlogperror(pvmtxt); } else if (pvmdebmask & PDMSEM) { sprintf(pvmtxt,"peer_wake() sem %d\n", pp->p_semid); pvmlogerror(pvmtxt); } } /* peer_detach() * * Detach peer's msg buffer, destroy if no one else is attached to it. */ int peer_detach(pp) struct peer *pp; { struct shmid_ds shmds; char *p; if (pp->p_tid != pvmmytid) { /* * zero p_buf before destroying it in case we're interrupted right here. * yes, it happend. */ if (p = pp->p_buf) { pp->p_buf = 0; if (shmdt(p) == -1) pvmlogperror("peer_detach() shmdt"); } if (!shmctl(pp->p_shmid, IPC_STAT, &shmds) && shmds.shm_nattch == 0) { shmctl(pp->p_shmid, IPC_RMID, (struct shmid_ds *)0); #ifdef USERECVSEMAPHORE if (pp->p_semid == -1 && pp->p_key) pp->p_semid = semget((key_t)pp->p_key, 1, PERMS); if (pp->p_semid != -1) semctl(pp->p_semid, 0, IPC_RMID); #endif } } LISTDELETE(pp, p_link, p_rlink); PVM_FREE(pp); return 0; } void peer_cleanup() { while (peers->p_link != peers) peer_detach(peers->p_link); } int peer_dump() { struct peer *pp; struct shmid_ds shmds; pvmlogerror("peer_dump()\n"); for (pp = peers->p_link; pp != peers; pp = pp->p_link) { if (shmctl(pp->p_shmid, IPC_STAT, &shmds) == -1) { sprintf(pvmtxt, "peer_dump() shmctl STAT %d", pp->p_shmid); pvmlogperror(pvmtxt); sprintf(pvmtxt, " t%x key=0x%x shmid=%d semid=%d shmlen=%d\n", pp->p_tid, pp->p_key, pp->p_shmid, pp->p_semid, pp->p_dlen); pvmlogerror(pvmtxt); } else { sprintf(pvmtxt, " t%x key=0x%x shmid=%d semid=%d shmlen=%d shmna=%d\n", pp->p_tid, pp->p_key, pp->p_shmid, pp->p_semid, pp->p_dlen, (int)shmds.shm_nattch); pvmlogerror(pvmtxt); } } return 0; } #ifdef IMA_CSPP #define SHMIDPIDPART 0xfff #endif #ifndef SHMIDUIDPART #define SHMIDUIDPART 0xffff0000 #endif #ifndef SHMIDPIDPART #define SHMIDPIDPART 0xffff #endif /* pvmshmkey() * * Get the shared-memory segment key of the pvmd, if pid == 0, * else of process pid. */ int pvmshmkey(pid) int pid; { static int pvmd_key = 0; int k; char *p; if (!pvmd_key) { if (p = getenv("PVMKEY")) pvmd_key = atoi(p); else pvmd_key = getuid(); pvmd_key = (pvmd_key << 16) & SHMIDUIDPART; if (!pvmd_key) pvmd_key = SHMIDUIDPART; #ifdef IMA_CSPP pvmd_key |= (get_scid() & 0xf) << 12; #endif } if (pid) { if (!(pid &= SHMIDPIDPART)) pid = 1; k = pvmd_key | pid; if (pvmdebmask & (PDMMEM | PDMSEM)) { sprintf(pvmtxt, "pvmshmkey(): shm/sem key is 0x%x\n", k); pvmlogerror(pvmtxt); } } else { k = pvmd_key; if (pvmdebmask & (PDMMEM | PDMSEM)) { sprintf(pvmtxt, "pvmshmkey(): pvmd shm/sem key is 0x%x\n", k); pvmlogerror(pvmtxt); } } return k; } /* nextpvmshmkey() * * Get a new shared memory key to try (in case the default failed). */ int nextpvmshmkey(key) int key; { int pid; pid = (key + 1) & SHMIDPIDPART; if (!pid) pid = 1; pid |= pvmshmkey(0); if (pvmdebmask & (PDMMEM | PDMSEM)) { sprintf(pvmtxt, "nextpvmshmkey() shm/sem key is 0x%x\n", pid); pvmlogerror(pvmtxt); } return pid; } #if defined(IMA_CSPP) || defined(IMA_HPPAMP) void init_lock(vp, f, l) pvmspplock_t *vp; char *f; int l; { if (pvmdebmask & PDMLOCK) { sprintf(pvmtxt,"init_lock(): init %#x from %s line %d\n", vp,f,l); pvmlogerror(pvmtxt); } *(int *)vp = 1; } int acquire_lock(vp, f, l) pvmspplock_t *vp; char *f; int l; { int * volatile ip = (int *)vp; int i=0, j=0; if (pvmdebmask & PDMLOCK) { sprintf(pvmtxt,"acquire_lock(): polling %#x from %s line %d\n", ip,f,l); pvmlogerror(pvmtxt); } while (1) { while (!(*ip)) i++; if (__ldcws32(ip)) break; j++; } if (pvmdebmask & PDMLOCK) { if (i) sprintf(pvmtxt,"acquire_lock(): acquired %#x after %d/%d polls\n", ip, i, j); else sprintf(pvmtxt,"acquire_lock(): acquired %#x\n", ip); pvmlogerror(pvmtxt); } return 0; } int release_lock(vp,f,l) pvmspplock_t *vp; char *f; int l; { if (pvmdebmask & PDMLOCK) { sprintf(pvmtxt,"release_lock(): releasing %#x from %s line %d\n", vp,f,l); pvmlogerror(pvmtxt); } __synch(); *(int *)vp = 1; return 0; } #endif /*defined(IMA_CSPP) || defined(IMA_HPPAMP)*/ #ifdef IMA_CSPP static int touch_flg = -1; /* flag to page memory early */ #define DONT_TOUCH 0 #define TOUCH_PAGES 1 /* _touch() * * Touch all the pages in this shared memory block */ static void _touch(addr) char *addr; { switch (touch_flg) { case TOUCH_PAGES: { char *shm_pg; int pgsz = sysconf(_SC_PAGESIZE); if(pvmdebmask & PDMMEM) { sprintf(pvmtxt, "Touching block at addr 0x%x (%d bytes)\n", addr, shmbufsiz); pvmlogerror(pvmtxt); } for (shm_pg = addr; shm_pg < (addr + shmbufsiz); shm_pg += pgsz) shm_pg[63] = 0; } break; case DONT_TOUCH: break; default: touch_flg = (getenv("PVMTOUCH") ? TOUCH_PAGES : DONT_TOUCH); if(pvmdebmask & (PDMTASK|PDMMEM)) { sprintf(pvmtxt, "Shared memory touching: %s\n", touch_flg ? "ON" : "OFF" ); pvmlogerror(pvmtxt); } } return; } /* * ---> On CSPP SYS V memory systems, the VM addr given to the PVM daemon may * ---> not work for the PVM clients. Search for an open spot in the VM space * ---> that will work for SOM and ESOM executables. */ #define GATEWY_LO_ADDR 0xbff00000 #define GATEWY_HI_ADDR 0xc0010000 #define SHM_HI_ADDR 0xf0000000 #define SHM_LO_ADDR 0x80000000 char * shm_search(bufid) int bufid; { unsigned int i, unmapped = 1; char *inbox; int shm_incr_addr = (shmbufsiz + 4095) & (~4095); /* round up */ for(i = GATEWY_LO_ADDR; i > SHM_LO_ADDR && unmapped; i-=shm_incr_addr) { inbox = (char*)shmat(bufid, (char*) i, 0); unmapped = (inbox == (char*)-1L); if ( unmapped && (pvmdebmask & PDMMEM) ) { sprintf(pvmtxt, "shm_search(): shmat() failed attach at %#x\n", i); pvmlogerror(pvmtxt); } } for(i = GATEWY_HI_ADDR; i < SHM_HI_ADDR && unmapped; i+=shm_incr_addr) { inbox = (char*)shmat(bufid, (char*) i, 0); unmapped = (inbox == (char*)-1L); if ( unmapped && (pvmdebmask & PDMMEM) ) { sprintf(pvmtxt, "shm_search(): shmat() failed attach at %#x\n", i); pvmlogerror(pvmtxt); } } if ( unmapped ) { pvmlogerror("shm_search(): Unable to shmat\n"); return (char *) -1; } if (pvmdebmask & PDMMEM) { sprintf(pvmtxt, "shm_search(): shmat attached to addr %x\n", (unsigned int) inbox); pvmlogerror(pvmtxt); } /* Page in the shared memory */ _touch(inbox); return inbox; } #endif /*IMA_CSPP*/ ./pvm3/src/pvmshmmsg.c0100644007401100000360000006075207052631373014074 0ustar kohlgopher static char rcsid[] = "$Id: pvmshmmsg.c,v 1.3 2000/02/16 23:30:03 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * */ /* Design/philosophy of shared memory message transport: 1) Each task allocates a shared memory segment. 2) The shared memory segment is logically split into two parts a) the message control page b) data buffer pool 3) Reading/writing access to all of the shared memory is controlled by a single semaphore (or lock) on the message control page. 4) The data buffers are of fixed size (MAXFRAGSIZE). Messages that are longer than this fixed size must be fragmented. 5) Message sends/recvs are based on asynchronous semantics. For a send to complete, a matching receive must be posted at the destination. What this means is that the receiver must allocate a buffer from the shared pool before a sender can write. 6) The number of message copies needed to send a message from user space to user space is 3. One copy is the original pvm pack. The "send" is a copy into a shared buffer. The third is the pvm unpack. Shared Memory Segment (1 per process) |-------------------| | | 0 | | | control page | | | | | CTRLPAGELEN - 1 |-------------------| | | CTRLPAGELEN | | | data buffer | | | | | CTRLPAGELEN + MAXFRAGSIZE - 1 |-------------------| | | CTRLPAGELEN + MAXFRAGSIZE | | | data buffer | | | | | CTRLPAGELEN + 2*MAXFRAGSIZE - 1 |-------------------| o o o | | | | SHMSEGSIZE - 1 |-------------------| -- Mutual exclusion control exclusion. - Whenever a task (either a sender or receiver) wants to interrogate (determine if a receive has been posted/completed) the entire control page is exclusively locked. 1) Posting a receive - the receiver must pre-allocate a fixed size buffer from his shared memory pool. Step 1) acquire lock. Step 2) Find first free open message msgcntrl.msgs[i]. Update msgctrl.nmsgs if adding to number of messages Step 3) Modify msginfo.msgs[i] to reflect desired src, tag, and maxlen. Offset into the shared memory region gives the buffer. msgcntrl.msgs[i].status = ISRECVMSG. Step 4) release lock. Step 5) return i to caller for message completion testing. 2) Receive completion for message i Step 1) acquire lock Step 2) determine if message has completed by checking msgcntrl.msgs[i].status & COMPLETE Step 3) If complete, mark mscntrl.msgs[i].status = NOBUFFER Step 4) Release lock. Step 5) Return pointer to data buffer if complete, else return 0; 3) Posting a send: On sender's side, for each receiver, retain a queue of send requests. Add send to *end* of task send queue. */ #include #include #include #include #include #include #include #include #include #include "global.h" #include "pvmalloc.h" #include "listmac.h" #include "pvmdabuf.h" #include "pvmmagic.h" #include "lmsg.h" #include "pvmmimd.h" #include "pvmshmmsg.h" #include "bfunc.h" extern int pvmdebmask; /* GEF */ /* extern int pvmmynode; */ /* not imported from lpvmmind.c yet... */ static int pvmmynode = -1; /* GEF */ struct segdesc *pvmmyshmseg = (struct segdesc *) NULL; static struct shm_midlist pvm_shmmids[NSHMMIDS]; static int lastMidAlloced = 1; char *getenv(); /* ============================================ Section I shared memory creation, destruction and attachment. lock (semaphore) creation, destruction. attachment. ============================================ */ /* --------- pvm_shmget ------- */ /* Create a shared segment. o For the "owner" of the shared segment, It should be called with: len = length of segment iAmOwner= 1; o For client attaching to a shared segment, It should be called len= 0; iAmOwner= 0; o pvm_shmat must be called with id returned in segdesc->segid to bind to the shared segment */ struct segdesc * pvm_shmget(key, len, iAmOwner) key_t key; int len; int iAmOwner; { struct segdesc *rseg; struct shmid_ds shminfo; int flags = 0; if ((rseg = (struct segdesc *) TALLOC(1, struct segdesc, "shmget")) == 0) { pvmlogerror( "pvm_shmget (): No memory for seg descriptor \n"); return (struct segdesc *) NULL; } BZERO(rseg, sizeof(struct segdesc)); if (iAmOwner) flags =IPC_CREAT | IPC_EXCL | PERMS; else flags = PERMS; if ((rseg -> segid = shmget(key, len, flags)) == -1 && pvmdebmask & PDMNODE) { pvmlogperror ("pvm_shmget (): could not create shared segment \n"); /* GEF */ /* there was just a free here... wonder if pvm_free will work */ /* FREE(rseg); */ PVM_FREE(rseg); return (struct segdesc *) NULL; } shmctl(rseg -> segid , IPC_STAT, &shminfo); rseg -> len= shminfo.shm_segsz; rseg -> bound = 0; rseg -> segControl = (struct msgctrl *) NULL; rseg -> pagelock = rseg -> pageunlock = 0; rseg -> lock = 0; rseg -> iAmOwner= iAmOwner; return rseg; } /* -------- pvm_shmat () ------ */ /* attach to a previously defined shared segment. This is called after a successful call to pvm_shmget */ char * pvm_shmat ( sseg ) struct segdesc *sseg; { char *buffer; if (sseg->bound) return(sseg->start); if (!sseg->lock) { pvmlogerror( "pvm_shmat(): need to get lock before attach\n") ; return (char *) NULL; } if ( (buffer = shmat(sseg->segid, (char *) NULL, 0) ) == (char *) NULL) { pvmlogerror( "pvm_shmat() : could not attach to the share segment\n"); return (char *) NULL; } sseg -> start = buffer; sseg -> segControl = (struct msgctrl *) buffer; /* Initialize and/or Update msgctrl section of this shared segment */ (*sseg->pagelock) (sseg->lock); if (sseg -> iAmOwner) pvm_msgctrlInit(sseg -> segControl, sseg->len, MAXFRAGSIZE, MAXFRAGSIZE); sseg->segControl->nattach ++; /* our idea of # tasks attached */ (*sseg->pageunlock) (sseg->lock); sseg->bound = 1; return buffer; } /* -------pvm_shmdt() ---------- */ /* detach from a previously attached shared segment */ int pvm_shmdt ( sseg ) struct segdesc *sseg; { struct shmid_ds shminfo; if (!sseg || !sseg -> bound ) /* not bound to the shared segment */ return (0); (*sseg -> pagelock)(sseg -> lock); sseg -> segControl -> nattach --; /* find out how many are attached to this segment */ shmctl ( sseg -> segid, IPC_STAT, &shminfo); if ( shminfo.shm_nattch == 1 ) /* I am the only one left, destroy */ shmctl( sseg -> segid, IPC_RMID, &shminfo); (*sseg -> pageunlock)( sseg -> lock ); shmdt( sseg -> start); /* the segment will get destroyed after detach */ /* reset structure variables */ sseg -> bound = 0; sseg -> segControl = (struct msgctrl *) 0; sseg -> segid = 0; sseg -> len = 0; sseg -> start = (char *) NULL; /* iAmOwner is shared between the shm seg and the semaphore lock */ /* thus we leave this variable to be reset by the pvm_lockdt() call */ /* unless the lock as already gone.. yes the lock we used above! */ if (!sseg->lock) sseg -> iAmOwner= 0; return 0; } /* -------pvm_shmfree() ---------- */ /* delete a shared segment ( this is also done by the shmdt.... ) */ int pvm_shmfree ( sseg ) struct segdesc *sseg; { struct shmid_ds shminfo; /* We haven't checked to see if this segment is locked... */ /* We also haven't checked to see if we are attached/own it etc */ /* Ok.. just grab it */ (*sseg -> pagelock)(sseg -> lock); /* find out how many are attached to this segment */ shmctl ( sseg -> segid, IPC_STAT, &shminfo); if ( shminfo.shm_nattch == 0 ) shmctl( sseg -> segid, IPC_RMID, &shminfo); else /* what? */ shmctl( sseg -> segid, IPC_RMID, &shminfo); /* yep, wrong... should send message to all so that they can detach */ /* in a nice way */ (*sseg -> pageunlock)( sseg -> lock ); /* reset structure variables */ sseg -> bound = 0; sseg -> segControl = (struct msgctrl *) 0; sseg -> segid = 0; sseg -> len = 0; sseg -> start = (char *) NULL; sseg -> iAmOwner= 0; return 0; } /* --------- pvm_lockget ------- */ /* Create a lock for a particular shared segment. If owner of the lock, initialize the lock. */ int pvm_lockget (key, sseg, iAmOwner ) key_t key; struct segdesc *sseg; int iAmOwner; { int flags; int semid; /* GEF */ /* ops SysV requires that we explicitly declare this if the forth arg is needed * in any shmem op. */ /* union semun lockarg; */ union semun { int val; struct semid_ds *buf; ushort *array; } lockarg; int lockcmd; if ( sseg == (struct segdesc *) NULL) { pvmlogerror( "pvm_lockget (): invalid segment descriptor \n"); return PvmBadParam; } if (iAmOwner) flags =IPC_CREAT | IPC_EXCL | PERMS; else flags = PERMS; if ((sseg -> lock = semget(key, 1, flags)) == -1 && pvmdebmask& PDMNODE) { sseg -> lock = 0; pvmlogperror( "pvm_lockget (): could not create lock \n"); return 0; } sseg -> pagelock = pvm_shmlock; sseg -> pageunlock = pvm_shmunlock; /* If I am the owner, initialize the lock to 0 (unlocked) */ lockcmd = IPC_SET; lockarg.val = 0; semctl( sseg -> lock, 0, lockcmd, lockarg ); return sseg -> lock; } /* --------- pvm_lockdt ------- */ /* detach from a lock that has been gotten by pvm_lockget */ int pvm_lockdt ( sseg ) struct segdesc *sseg; { int lockcmd; int semid; /* see above routine GEF */ /* union semun lockarg; */ union semun { int val; struct semid_ds *buf; ushort *array; } lockarg; if (!sseg || !sseg -> lock ) return 0; if ( sseg -> iAmOwner ) /* I own the lock, will free it */ { /* Lock the page -- upon deletion, any tasks waiting on the */ /* semaphore will be woken up and returned an error */ (* sseg -> pagelock ) (sseg->lock); lockcmd = IPC_RMID; lockarg.val = 0; semctl ( sseg -> lock, 0, lockcmd, lockarg ); /* we can now reset the ownership variable if the shm seg has gone */ if (!sseg->start) sseg -> iAmOwner= 0; } sseg -> lock = 0; sseg -> pagelock = sseg -> pageunlock = 0; return 0; } /* --------- pvm_shmlock --------- */ int pvm_shmlock( lock ) PVM_LOCK lock; { struct sembuf lockop; lockop.sem_num= 0; lockop.sem_op= 1; lockop.sem_flg= 0; if (pvmdebmask & PDMSEM ) pvmlogprintf ("Acquiring lock %d \n" , lock) ; while (semop(lock, &lockop, 1) == -1) { if (errno != EINTR) { pvmlogprintf(" Fatal Error acquiring lock %d (errno %d)\n", lock, errno); return PvmSysErr; } /* GEF */ pvmsleep (1); /* don't even ask... */ } if (pvmdebmask & PDMSEM ) pvmlogprintf("lock %d acquired \n", lock); return 0; } /* --------- pvm_shmunlock --------- */ int pvm_shmunlock(lock) PVM_LOCK lock; { struct sembuf lockop; lockop.sem_num = 0; lockop.sem_op = -1; lockop. sem_flg= 0; if (pvmdebmask & PDMSEM ) pvmlogprintf ("Releasing lock %d \n", lock); while (semop(lock, &lockop, 1) == -1) { if (errno != EINTR ) { pvmlogprintf(" Fatal Error releasing lock %d (errno %d)\n", lock, errno); return PvmSysErr; } } if (pvmdebmask & PDMSEM) pvmlogprintf("lock %d released \n", lock); return 0; } /* --------- pvm_msgctrlInit --------- */ /* initialize the message control page at the beginning of the shared memory segment pointed to by cblock of length len. */ int pvm_msgctrlInit(cblock, len, ctrlpagelen, blksize) struct msgctrl *cblock; int len; /* length of the controlled shared segment */ int ctrlpagelen;/* length of the control page */ int blksize; /* size of blocks that will be allocd out of this shared seg */ { BZERO((char *) cblock, ctrlpagelen); cblock -> len = len; cblock -> maxmsgs= (len- ctrlpagelen) /blksize; return 0; } /* --------- pvm_shmmsginit () --- */ /* Initialize shared memory messaging, structures for the local task */ int pvm_shmmsginit( key, localseg ) key_t *key; struct segdesc **localseg; { key_t lockkey; key_t shmkey; int first; int lock; int nretries; char *tmp_shmseg_ptr; struct segdesc * myshmseg; /* Step 1 - create my local shared memory segment */ /* Step 2 - create lock for local shared segment */ /* Step 3 - create the local midlist for posted sends and receives */ nretries = 0; /* === Step 1: === */ /* This section really just makes a segment descriptor and a shm key */ first = shmkey = (key_t) pvm_shmkey(getpid()); do { if ( (myshmseg = pvm_shmget(shmkey, SHMSEGLEN, SHM_OWNER)) != (struct segdesc *) NULL ) { if ( (tmp_shmseg_ptr = shmat(myshmseg->segid, (char *) NULL, 0) ) == (char *) NULL) /* GEF */ /* Can't it in this order as we need a lock before pvm_shat() will work */ /* if ( pvm_shmat( myshmseg ) == (char *) NULL) */ /* we attach as this is the surest way of testing everything's ok */ /* GEF */ { pvmlogprintf("Created segment but could not attach!\n"); pvm_shmfree(myshmseg); myshmseg = (struct segdesc *) NULL; return PvmSysErr; } else shmdt (tmp_shmseg_ptr); /* we detach here to make sure that the attach count is right */ break; } else { nretries ++; shmkey = (key_t) pvm_nextshmkey(shmkey); } } while (shmkey != first); if (!myshmseg) { pvmlogprintf("Could not create shared memory segment after %d\n", nretries); return PvmSysErr; } /* ==== Step 2: ===== */ /* ops Phil... the key used for the shared memory segment may be used */ /* by another semaphore.. so is should really be a loop like above */ /* I know... it stinks, but... */ lockkey = shmkey; if ( (lock = pvm_lockget(lockkey, myshmseg, LOCK_OWNER)) == 0) { pvmlogprintf("Could not create lock \n"); return PvmSysErr; } /* ==== Step 2 and a half: ===== */ /* ok... we can use the PVM_SHMAT routine now as we have a valid lock... */ if ( pvm_shmat( myshmseg ) == (char *) NULL) { pvmlogprintf("Created segment but could not attach!\n"); pvm_shmfree(myshmseg); myshmseg = (struct segdesc *) NULL; return PvmSysErr; } /* ==== Step 3: ===== */ /* Initialize the send/receive midlist */ BZERO( pvm_shmmids, NSHMMIDS*sizeof(struct shm_midlist)); *localseg = myshmseg; *key = shmkey; return 0; } /* --------- pvm_shmkey () --- */ /* pvm_shmkey() * * Get the shared-memory segment key of the pvmd, if pid == 0, * else of process pid. */ int pvm_shmkey(pid) int pid; { static int pvmd_key = 0; int k; char *p; if (!pvmd_key) { if (p = getenv("PVMKEY")) pvmd_key = atoi(p); else pvmd_key = getuid(); pvmd_key = (pvmd_key << 16) & SHMIDUIDPART; if (!pvmd_key) pvmd_key = SHMIDUIDPART; #ifdef IMA_CSPP pvmd_key |= (get_scid() & 0xf) << 12; #endif } if (pid) { if (!(pid &= SHMIDPIDPART)) pid = 1; k = pvmd_key | pid; if (pvmdebmask & (PDMMEM | PDMSEM)) { pvmlogprintf("pvmshmkey(): shm/sem key is 0x%x\n", k); } } else { k = pvmd_key; if (pvmdebmask & (PDMMEM | PDMSEM)) { pvmlogprintf("pvmshmkey(): pvmd shm/sem key is 0x%x\n", k); } } return k; } /* --------- pvm_nextshmkey () --- */ /* pvm_nextshmkey() * * Get a new shared memory key to try (in case the default failed). */ int pvm_nextshmkey(key) int key; { int pid; pid = (key + 1) & SHMIDPIDPART; if (!pid) pid = 1; /* GEF */ /* pid |= pvmshmkey(0); */ pid |= pvm_shmkey(0); if (pvmdebmask & (PDMMEM | PDMSEM)) { pvmlogprintf("nextpvmshmkey() shm/sem key is 0x%x\n", pid); } return pid; } /* ========================================== Section II Basic shared memory messaging ========================================== */ /* --------- pvm_allocShmmid ------ */ int pvm_allocShmmid(midentry) struct shm_midlist **midentry; { int i; for (i = lastMidAlloced; i < NSHMMIDS; i++) { if (!pvm_shmmids[i].ml_status) /* this mid is free */ { pvm_shmmids[i].ml_status = ISALLOCED; lastMidAlloced = i; *midentry = pvm_shmmids + i; return i; } } for (i = 1; i < lastMidAlloced; i++) { if (!pvm_shmmids[i].ml_status) /* this mid is free */ { pvm_shmmids[i].ml_status = ISALLOCED; lastMidAlloced = i; *midentry = pvm_shmmids + i; return i; } } return PvmSysErr; /* all the mids were full */ } /* --------- pvm_freeShmmid ------ */ int pvm_freeShmmid(mid) { pvm_shmmids[mid].ml_status = 0; lastMidAlloced = mid; /* try to reclaim the mids */ return 0; } /* --------- pvm_irecvshm --------- */ /* return the mid of the posted receive message. The mid is allocated from pvm_shmmidlist; */ int pvm_irecvshm(sseg, buf, len, src, tag, info) struct segdesc *sseg; char *buf; int len; int src; int tag; int *info; { int freebuf; int msgnum; int offset; struct msgctrl *control; struct msginfo *thismsginfo; struct shm_midlist *midentry; int midListId; if (sseg == (struct segdesc *) NULL) return PvmBadParam; /* invalid shared segment */ if ( (offset = (buf - sseg -> start)) < 0 || (sseg -> start + sseg -> len) < (buf + len) ) return PvmBadParam; /* data buffer not completely in shared seg */ if ( (midListId = pvm_allocShmmid( &midentry)) < 0) return midListId; /* record the receive info in the midlist */ midentry -> ml_status = ISRECVMSG; midentry -> ml_src = src; midentry -> ml_tag = tag; midentry -> ml_len = len; midentry -> ml_buf = buf; midentry -> shm_msgnum = -1; midentry -> ml_info = info; midentry -> ml_link = midentry -> ml_rlink = (struct shm_midlist *) NULL; (*sseg->pagelock)(sseg->lock); /* acquire lock */ control = sseg->segControl; /* determine which msginfo buffer we can use for this message */ freebuf = 0; for (msgnum = 0; msgnum < control->nmsgs; msgnum++ ) { freebuf = control->msgs[msgnum].mi_status == NOBUFFER; if (freebuf) break; } /* If no free msginfo buffers, Space for one more ? */ if (msgnum == control->nmsgs) { if (control -> nmsgs >= control -> maxmsgs) /* too many posted recv's*/ { midentry -> ml_status = NOBUFFER; /* free the midentry */ (*sseg->pageunlock)(sseg->lock); /* release lock */ return PvmSysErr; /* out of mids */ } else control-> nmsgs ++; } /* Set the msginfo buffer parameters */ thismsginfo = &(control->msgs[msgnum]); thismsginfo -> mi_src = src; thismsginfo -> mi_tag = tag; thismsginfo -> mi_len = len; thismsginfo -> mi_offset = offset; thismsginfo -> mi_midlistId = midListId; thismsginfo -> mi_status = ISRECVMSG; (*sseg->pageunlock)(sseg->lock); /* release lock */ return midListId; /* Valid message number */ } /* --------- pvm_isendshm --------- */ /* return the mid of the posted send message. The mid is allocated from pvm_shmmidlist; if buf = 0, isendshm will not allocate a new mid. It will instead try to move any messages on the sendq to the destination. */ int pvm_isendshm(sseg, buf, len, dst, tag) struct segdesc *sseg; char *buf; int len; int dst; int tag; { int freebuf; int i; int msgnum; int offset; struct msgctrl *control; struct msginfo *tstmsg; struct shm_midlist *midentry; struct shm_midlist *testentry; int midListId = 0; char *sbuf; if (sseg == (struct segdesc *) NULL) return PvmBadParam; /* invalid shared segment */ if (buf) /* we are actually trying to send something */ { if ( (midListId = pvm_allocShmmid( &midentry)) < 0) return midListId; /* record the receive info in the midlist */ midentry -> ml_status = ISSENDMSG; midentry -> ml_dst = dst; midentry -> ml_tag = tag; midentry -> ml_len = len; midentry -> ml_buf = buf; midentry -> shm_msgnum = -1; midentry -> ml_info = 0; midentry -> ml_link = midentry -> ml_rlink = (struct shm_midlist *) NULL; /* Put this on the sendq for this shared segment, this maintains point-to-point message order */ if ( !sseg -> sendq ) sseg -> sendq = midentry; else LISTPUTBEFORE (sseg -> sendq, midentry, ml_link, ml_rlink); } testentry = sseg -> sendq; /* get message to send */ control = sseg->segControl; while ( testentry ) { (*sseg->pagelock)(sseg->lock); /* acquire lock */ tstmsg = control -> msgs; for (i = 0; i < control -> nmsgs; i++) { if ( tstmsg -> mi_status & ISRECVMSG && ! ( tstmsg -> mi_status & COMPLETE ) && ! ( tstmsg -> mi_status & BUFINFLUX ) /*another writer?*/ && (tstmsg -> mi_src == MPPANY || tstmsg -> mi_src == testentry->ml_dst) && (tstmsg -> mi_tag == MPPANY || tstmsg -> mi_tag == testentry->ml_tag) && (tstmsg -> mi_len >= testentry -> ml_len) ) { /* record send message information in the shared buffer */ tstmsg -> mi_status |= BUFINFLUX; /* write in progress */ tstmsg -> mi_tag = testentry -> ml_tag; tstmsg -> mi_src = pvmmynode; tstmsg -> mi_len = testentry -> ml_len; sbuf = sseg -> start + tstmsg -> mi_offset; /* unlock the control segment while copying */ (*sseg -> pageunlock)(sseg -> lock); BCOPY (sbuf, testentry -> ml_buf, testentry -> ml_len); /* NOTE: control->nmsgs may have increased while unlocked, this means that control->nmsgs can never decrease, or errors can occur */ /* relock to update message that has been copied */ (*sseg -> pagelock)(sseg -> lock); tstmsg -> mi_status &= ~BUFINFLUX; /* write complete */ tstmsg -> mi_status |= COMPLETE; /* message complete */ /* record information in our mid structure entry */ testentry -> ml_status |= COMPLETE; break; } tstmsg ++; /* look to see if another entry can receive this one */ } /* if we were able to complete this message, try to send next one */ if ( testentry -> ml_status & COMPLETE ) { if (testentry -> ml_link) { sseg -> sendq = testentry -> ml_link; LISTDELETE (testentry, ml_link, ml_rlink); testentry = sseg -> sendq; /* get the next send message */ } else { sseg -> sendq = testentry = ( struct shm_midlist * ) NULL; } } } return midListId; /* Valid message number */ } /* --------- pvm_shmmsgdone --------- */ /* test to see if a message has completed. For send messages, if the message has not completed, attempt to resend, if a message is is done, then release the mid in midListId; */ pvm_shmsgdone (midListId) int midListId; { int rval; struct shm_midlist *midentry; struct msginfo *tstmsg; struct segdesc *sseg; if (midListId < 1 || midListId >= NSHMMIDS) return PvmBadParam; midentry = &(pvm_shmmids[midListId]); if (! midentry -> ml_status ) /* No Buffer defined, SEND or RECV */ return PvmBadParam; if ( midentry -> ml_status & ISRECVMSG ) /* This is a receive message */ { if ( midentry -> shm_msgnum < 0) /* invalid shared message num */ return PvmBadParam; sseg = midentry -> shmseg; tstmsg = &(sseg->segControl->msgs[ midentry -> shm_msgnum ]); (*sseg -> pagelock)(sseg -> lock ); /* lock page and check status */ if ( tstmsg -> mi_status & COMPLETE ) /* message completed */ { midentry -> ml_status |= COMPLETE; midentry -> ml_info[TAGENTRY] = tstmsg -> mi_tag; midentry -> ml_info[SRCENTRY] = tstmsg -> mi_src; midentry -> ml_info[LENENTRY] = tstmsg -> mi_len; tstmsg -> mi_status = NOBUFFER; /* Free this message buffer*/ } (*sseg -> pageunlock)(sseg -> lock ); /* unlock page */ } else if (midentry -> ml_status & ISSENDMSG ) { if (! (midentry -> ml_status & COMPLETE)) { /* message isn't complete, try and send again */ pvm_isendshm( midentry -> shmseg , (char *) NULL, 0, 0, 0, (int *) NULL); } } /* Check one more time, if the send/recv operation has completed. if it has, mark the midlist entry as free and return that the message has completed */ if ((rval = (midentry -> ml_status & COMPLETE)) != 0) pvm_freeShmmid( midListId); return rval; } ./pvm3/src/pvmwin.c0100644007401100000360000003267607620022043013364 0ustar kohlgopher static char rcsid[] = "$Id: pvmwin.c,v 1.9 2003/02/04 20:35:47 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ #include #include "pvmalloc.h" #include "pvmwin.h" #include #include extern int debugmask; extern char *username; char * read_pvmregistry(token_call) const char *token_call; { long return_value; HKEY top=NULL; HKEY phkResult = NULL; static char subkey[]="SOFTWARE\\PVM"; static char root[]="SOFTWARE\\PVM"; static char token[16]; LPTSTR key_name =""; DWORD type = REG_EXPAND_SZ; int value_size=0; int i=0; char value[64]; char *give_back = (char *) malloc (64 * sizeof(char)); value_size=sizeof(value); top = HKEY_LOCAL_MACHINE; for (i=0; token_call[i];i++) token[i]=token_call[i]; token[i++]=0; token[i++]=0; key_name=subkey; return_value = RegOpenKeyEx(top, key_name, 0, KEY_EXECUTE, &phkResult); if ( return_value != ERROR_SUCCESS ) { fprintf(stderr,"RegOpenKey failed for %s: %d\n",token,(int) return_value); return NULL; } return_value = RegQueryValueEx(phkResult, token, NULL, (LPDWORD) &type, (LPBYTE) &value, (LPDWORD)&value_size); if ( return_value != ERROR_SUCCESS ) { fprintf(stderr,"RegQueryValueEx failed for %s: %d \n", token,(int) return_value); return NULL; } strcpy(give_back,(char *)value); RegCloseKey(phkResult); return (char* ) give_back; } void Wait(id, prv) HANDLE id; DWORD *prv; { if (!WaitForSingleObject(id, INFINITE)) { *prv = 2; } else { if (!GetExitCodeThread(id, prv)) { *prv = 4; } } } int win32_write_socket (s, tosend, size) SOCKET s; const char FAR *tosend; int size; { int nSend=0; int size2send=size; while (size2send > 0) { if ((nSend = send(s, tosend, size2send, 0)) == -1) return nSend; tosend += nSend; size2send -= nSend; } /* pvmlogprintf("loclinput, to send: %d yes, send: %d\n", size,size-size2send); */ return size-size2send; /* this should be $size in the end */ } int win32_read_socket (s, torecv, size) SOCKET s; char FAR *torecv; int size; { int nReceived=0; int size2recv=size; while (size2recv > 0) { if ((nReceived = recv(s, torecv, size2recv, 0)) == -1) return nReceived; /* Nothing received - EOF? */ /* return any bytes read */ if (!nReceived) return size-size2recv; torecv += nReceived; size2recv -= nReceived; } /* pvmlogprintf("loclinput, to read: %d yes, read: %d\n", size,size-size2recv); */ return size-size2recv; } int gettimeofday(t, tzp) struct timeval *t; struct timezone *tzp; { struct _timeb timebuffer; /* this calls the time and returns sec ** msec */ _ftime( &timebuffer ); t->tv_sec=timebuffer.time; t->tv_usec=timebuffer.millitm*1000; return 1; } char * GetLastErrorToStr (error) int error; { switch(error) { case WSAENETDOWN: return("The network subsystem has failed.\n"); break; case WSAEINTR: return("A blocking call was cancelled. This can be caused \ by\n1) a short response time, or\n2) \ User interrupts the process.\n"); break; case WSAEINPROGRESS: return("A blocking call is in progress.\n"); break; case WSAENOBUFS: return("No buffer space is available.\n"); break; case WSAENOTSOCK: return("Invalid socket descriptor.\n"); break; case WSAEADDRINUSE: return("The specified address is already in use.\n"); break; case WSAEADDRNOTAVAIL: return("The specified address is not available\nfrom the local machine.\n"); break; case WSAECONNREFUSED: return("The connection attempt was refused.\n"); break; case WSAEINVAL: return("The socket is not bound to an address.\n"); break; case WSAEISCONN: return("The socket is already connected.\n"); break; case WSAEMFILE: return("The maximum number of sockets has exceeded.\n"); break; case WSAENETUNREACH: return("Network cannot be reached from this host at this time.\n"); break; case WSAETIMEDOUT: return("Attempt to connect timed out without establishing a connection.\n"); break; case WSAENOTCONN: return("The socket is not connected.\n"); break; case WSAESHUTDOWN: return("The socket has been shut down.\n"); break; case WSAECONNABORTED: return("The socket connection has been reset.\n"); break; case WSAECONNRESET: return("Socket shutdown by remote.\n"); break; case WSAEACCES: return("The requested address is a broadcast address.\n"); break; case WSAENETRESET: return("The socket connection has been reset.\n"); break; case WSAHOST_NOT_FOUND: return("Host could not found.\n"); break; default: return("could not match error tag"); break; } } void nt_rpc_report(s) char *s; { printf("Error: %s: %d\n",s,GetLastError()); } void ErrorHandler(s) char *s; { printf("Error: %s: %d\n",s,GetLastError()); } int win32_close_file(f) HANDLE f; { int success; success = CloseHandle(f); return success; } HANDLE win32_create_file(TMP_AREA, mode) char *TMP_AREA; int mode; { HANDLE hFile; PSECURITY_DESCRIPTOR pSD; PACL pACLNew; DWORD cbACL = 1024; PSID pSID; DWORD cbSID = 1024; LPSTR szUserName; DWORD dwUserNameLength; LPSTR lpszDomain; DWORD cchDomainName = 80; PSID_NAME_USE psnuType; /* begin of adding, by Jigen Zhou */ LPSTR szUser = NULL; DWORD cchUser = 81; LPSTR szDomain = NULL; DWORD cchDomain = 81; HANDLE hToken = NULL; PTOKEN_USER ptiUser = NULL; DWORD cbti = 0; SID_NAME_USE snu; /* end of adding */ /* Initialize a new security descriptor. */ pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); /* defined in WINNT.H */ if (pSD == NULL) { ErrorHandler("LocalAlloc"); return FALSE; } if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) { ErrorHandler("InitializeSecurityDescriptor"); goto Cleanup; } /* Initialize a new ACL. */ pACLNew = (PACL) LocalAlloc(LPTR, cbACL); if (pACLNew == NULL) { ErrorHandler("LocalAlloc"); goto Cleanup; } if (!InitializeAcl(pACLNew, cbACL, ACL_REVISION2)) { if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { return (HANDLE) -2; } ErrorHandler("InitializeAcl"); goto Cleanup; } /* Retrieve the SID for User */ if (username) szUserName=username; else szUserName=MyGetUserName(); /* begin of changing, by Jigen Zhou */ /* Get the calling thread's access token. */ if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken)) { /* Retry against process token if no thread token exists. */ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) fprintf(stderr,"Error to open thread/process token\n"); } if (hToken) { /* Obtain the size of the user information in the token. */ if (GetTokenInformation(hToken, TokenUser, NULL, 0, &cbti)) { /* Call should have failed due to zero-length buffer. */ ErrorHandler("GetTokenInformation"); goto Cleanup; } /* Allocate buffer for user information in the token. */ ptiUser = (PTOKEN_USER)LocalAlloc(LPTR, cbti); if (ptiUser== NULL) { ErrorHandler("LocalAlloc"); goto Cleanup; } /* Retrieve the user information from the token. */ if (!GetTokenInformation(hToken, TokenUser, ptiUser, cbti, &cbti)) { pvmlogprintf("Error while GetTokenInformation: %d\n", GetLastError()); pvmlogprintf("Continued by LookupAccountName\n"); hToken = NULL; } else { /* Retrieve user name and domain name based on user's SID. */ szUser = (LPSTR)LocalAlloc(LPTR, cchUser); szDomain = (LPSTR)LocalAlloc(LPTR, cchDomain); if ((szUser == NULL) || (szDomain == NULL)) { ErrorHandler("LocalAlloc"); goto Cleanup; } if (!LookupAccountSid(NULL, ptiUser->User.Sid, szUser, &cchUser, szDomain, &cchDomain, &snu)) { pvmlogprintf("Error while LookupAccountSid: %d\n", GetLastError()); pvmlogprintf("Continued by LookupAccountName\n"); hToken = NULL; } else { if (strcmp(szUser, szUserName)) { pvmlogprintf("LookupAccountSid get %s does not match %s\n", szUser, szUserName); pvmlogprintf("Continued by LookupAccountName\n"); hToken = NULL; } else { pSID = ptiUser->User.Sid; } } } } if (hToken == NULL) { /* This is the original block of code */ pSID = (PSID) LocalAlloc(LPTR, cbSID); psnuType = (PSID_NAME_USE) LocalAlloc(LPTR, 1024); lpszDomain = (LPSTR) LocalAlloc(LPTR, cchDomainName); if (pSID == NULL || psnuType == NULL || lpszDomain == NULL) { ErrorHandler("LocalAlloc"); goto Cleanup; } if (!LookupAccountName((LPSTR) NULL, /* local name */ szUserName, pSID, &cbSID, lpszDomain, &cchDomainName, psnuType)) { ErrorHandler("LookupAccountName"); goto Cleanup; } } /* end of changing, by Jigen Zhou */ if (!IsValidSid(pSID)) ErrorHandler("SID is not valid.\n"); /* Allow read but not write access to the file. */ if (!AddAccessAllowedAce(pACLNew, ACL_REVISION2, GENERIC_ALL, pSID)) { ErrorHandler("AddAccessAllowedAce"); goto Cleanup; } /* Add a new ACL to the security descriptor. */ if (!SetSecurityDescriptorDacl(pSD, TRUE, /* fDaclPresent flag */ pACLNew, FALSE)) { /* not a default disc. ACL */ ErrorHandler("SetSecurityDescriptorDacl"); goto Cleanup; } hFile = CreateFile(TMP_AREA, GENERIC_WRITE | GENERIC_READ, // FILE_SHARE_READ | FILE_SHARE_WRITE, 0, NULL, mode, FILE_ATTRIBUTE_NORMAL, NULL); if (GetLastError() == ERROR_ALREADY_EXISTS) if (mode == CREATE_NEW) return (HANDLE) -1; if (hFile == INVALID_HANDLE_VALUE) { return (HANDLE) -1; } /* Apply the new security descriptor to the file. */ if (!SetFileSecurity(TMP_AREA, DACL_SECURITY_INFORMATION, pSD)) { ErrorHandler("SetFileSecurity"); goto Cleanup; } /* printf("Successfully added access-allowed ACE to file's DACL.\n"); */ return hFile; Cleanup: FreeSid(pSID); if(pSD != NULL) LocalFree((HLOCAL) pSD); if(pACLNew != NULL) LocalFree((HLOCAL) pACLNew); if(psnuType != NULL) LocalFree((HLOCAL) psnuType); if(lpszDomain != NULL) LocalFree((HLOCAL) lpszDomain); return 0; } int win32_write_file(f, s, size) HANDLE f; char *s; int size; { int sizewritten=0; if (!WriteFile(f,s,size,&sizewritten,NULL)) { pvmlogprintf("Could not write to file :%d \n",GetLastError()); return 0; } return sizewritten; } int win32_read_file(f, s, size) HANDLE f; char *s; int size; { int sizeread=0; if (!ReadFile(f,s,size,&sizeread,NULL)) { pvmlogprintf("Could not read data from file :%d \n", GetLastError()); return -1; } return sizeread; } HANDLE win32_open_file(TMP_AREA) char *TMP_AREA; { HANDLE hF; hF= win32_create_file(TMP_AREA,OPEN_EXISTING); if (hF == INVALID_HANDLE_VALUE) printf("Could not open file %s: %d \n",TMP_AREA,GetLastError()); return hF; } int kill(pid, p_handle, signal) int pid; int p_handle; int signal; { HANDLE hProcess; // DebugBreak(); if (p_handle) if (!TerminateProcess((HANDLE)p_handle,signal)) { pvmlogprintf("Unable to terminate process: %d \n",p_handle); } else return TRUE; hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid); if (hProcess) { if (!TerminateProcess(hProcess,signal)) { pvmlogprintf("Unable to terminate process: %d \n",hProcess); } else {CloseHandle (hProcess);return TRUE;} } CloseHandle (hProcess); return TRUE; } char * MyGetUserName() { char *thisname=0; char myuser[64]; DWORD szuser=64; if (!GetUserName(myuser,&szuser)) { pvmlogprintf("You are not logged on to this machine: %d\n", GetLastError()); pvmlogprintf("Continued by provided username\n"); return NULL; } thisname = STRALLOC(myuser); return thisname; } int win32_delete_file(TMP_AREA) char *TMP_AREA; { return (!DeleteFile(TMP_AREA)); } ./pvm3/src/sdpro.c0100644007401100000360000001700607457036734013205 0ustar kohlgopher static char rcsid[] = "$Id: sdpro.c,v 1.10 2002/04/16 15:06:04 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * sdpro.c * * Pvmd entry points for messages from scheduler. * * $Log: sdpro.c,v $ * Revision 1.10 2002/04/16 15:06:04 pvmsrc * WIN32 Fixes for Multiple Domains. * - submitted by Jigen Zhou . * (Spanker=kohl) * * Revision 1.9 2001/02/07 23:15:54 pvmsrc * 2nd Half of CYGWIN Check-ins... * (Spanker=kohl) * * Revision 1.8 2000/02/16 22:00:29 pvmsrc * Fixed up #include stuff... * - use for IMA_TITN... * - #include before any NEEDMENDIAN #includes... * (Spanker=kohl) * * Revision 1.7 1999/07/08 19:00:15 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.6 1998/11/20 20:06:45 pvmsrc * Changes so that win32 will compile & build. Also, common * Changes so that compiles & builds on NT. Also * common source on win32 & unix. * (spanker=sscott) * * Revision 1.5 1997/06/27 17:32:55 pvmsrc * Updated for WIN32 header files & Authors. * * Revision 1.4 1997/01/28 19:27:31 pvmsrc * New Copyright Notice & Authors. * * Revision 1.3 1996/10/25 13:58:06 pvmsrc * Replaced old #includes for protocol headers: * - , "ddpro.h", "tdpro.h" * With #include of new combined header: * - * * Revision 1.2 1996/10/24 21:04:53 pvmsrc * Moved #include of "global.h" down below other headers: * - need to have all of the structures / types declared before * the globals can be declared... * * Revision 1.1 1996/09/23 23:44:42 pvmsrc * Initial revision * * Revision 1.4 1995/07/19 21:28:16 manchek * use new function pvmnametag instead of [dts]mname * * Revision 1.3 1994/10/15 19:29:02 manchek * cast message tags for comparison as integers * * Revision 1.2 1994/07/18 19:22:56 manchek * ALPHA segfaulted on array subscript * * Revision 1.1 1994/06/03 20:38:27 manchek * Initial revision * * */ #ifdef IMA_TITN #include #else #include #endif #ifdef NEEDMENDIAN #include #endif #ifdef NEEDENDIAN #include #endif #ifdef NEEDSENDIAN #include #endif #ifdef WIN32 #include "pvmwin.h" #endif #if defined(WIN32) || defined(CYGWIN) #include "..\xdr\types.h" #include "..\xdr\xdr.h" #else #include #include #endif #ifdef WIN32 #include #else #include #include #include #endif #include #include #include #include "pvmalloc.h" #include "host.h" #include "pmsg.h" #include "waitc.h" #include "task.h" #include "bfunc.h" #include "global.h" extern int pvmdebmask; /* from pvmd.c */ extern int hostertid; /* from pvmd.c */ extern int hosterwid; /* from ddpro.c */ extern int pvmschedtid; /* from pvmd.c */ extern int taskertid; /* from pvmd.c */ /*************** ** Private ** ** ** ***************/ int sm_bogus(); int sm_exec(); int sm_add(); int sm_handoff(); int sm_sthostack(); int sm_taskx(); int (*smswitch[])() = { sm_bogus, sm_exec, sm_bogus, sm_bogus, sm_bogus, sm_bogus, sm_bogus, sm_add, sm_bogus, sm_bogus, sm_taskx, sm_bogus, sm_handoff, sm_bogus, sm_bogus, sm_sthostack, sm_bogus, }; int schentry(mp) struct pmsg *mp; { int c = mp->m_tag; if (pvmdebmask & PDMMESSAGE) { pvmlogprintf("schentry() from t%x tag %s\n", mp->m_src, pvmnametag(c, (int *)0)); } if (c < (int)SM_FIRST || c > (int)SM_LAST) { pvmlogprintf("schentry() message from t%x with bogus tag %d\n", mp->m_src, c); goto bail; } c -= SM_FIRST; (smswitch[c])(mp); bail: pmsg_unref(mp); return 0; } int sm_bogus(mp) struct pmsg *mp; { pvmlogprintf("sm_bogus() message from t%x tag %s ?\n", mp->m_src, pvmnametag(mp->m_tag, (int *)0)); return 0; } /* sm_exec(wid) * * Request the pvmd to start task processes. * Just like DM_EXEC but different. */ int sm_exec(mp) struct pmsg *mp; { struct pmsg *rmp; rmp = mesg_new(0); rmp->m_dst = mp->m_src; rmp->m_ctx = mp->m_ctx; rmp->m_tag = SM_EXECACK; rmp->m_wid = mp->m_wid; exectasks(mp, rmp, mp->m_src); return 0; } /* sm_add() * * Scheduler requests the master pvmd to add hosts. * Just like DM_ADD but different. * * SM_ADD(wid) { * int count * string name[count] * } */ int sm_add(mp) struct pmsg *mp; { struct pmsg *rmp; rmp = mesg_new(0); rmp->m_dst = mp->m_src; rmp->m_ctx = mp->m_ctx; rmp->m_tag = SM_ADDACK; rmp->m_wid = mp->m_wid; addhosts(mp, rmp); return 0; } /* sm_taskx() * * Tasker notifies us that process exited. * * SM_TASKX() { * int tid // of toasted process * int status // exit status * int u_sec // user time used * int u_usec * int s_sec // system time used * int s_usec * } */ int sm_taskx(mp) struct pmsg *mp; { int tid; struct task *tp; int i; if (mp->m_src != taskertid) { pvmlogprintf("sm_taskx() from t%x (not the tasker)\n", mp->m_src); return 0; } upkuint(mp, &tid); if (tp = task_find(tid)) { if (pvmdebmask & PDMTASK) { pvmlogprintf("sm_taskx() t%x\n", tid); } upkuint(mp, &tp->t_status); upkuint(mp, &i); tp->t_utime.tv_sec = i; upkuint(mp, &i); tp->t_utime.tv_usec = i; upkuint(mp, &i); tp->t_stime.tv_sec = i; upkuint(mp, &i); tp->t_stime.tv_usec = i; task_cleanup(tp); task_free(tp); } else { if (pvmdebmask & PDMTASK) { pvmlogprintf("sm_taskx() t%x (no such)\n", tid); } } return 0; } /* sm_handoff() * * Current scheduler for this pvmd gets reassigned. * * SM_HANDOFF() { * uint newsched // tid * } */ int sm_handoff(mp) struct pmsg *mp; { int tid; upkuint(mp, &tid); if (pvmdebmask & PDMSCHED) { pvmlogprintf("sm_handoff() old t%x new t%x\n", pvmschedtid, tid); } pvmschedtid = tid; return 0; } /* sm_sthostack() * * Hoster finishes starting slave pvmds. * * SM_STHOSTACK(wid_rtn) { * { * int tid * string result * } [] // implied * } */ int sm_sthostack(mp) struct pmsg *mp; { struct waitc *wp; /* wait context on pvmd' */ if (mp->m_src != hostertid) { pvmlogprintf("sm_sthostack() from t%x (not the hoster)\n", mp->m_src); return 0; } if (mp->m_wid != hosterwid) { pvmlogprintf("sm_sthostack() from t%x bad wid %d wanted %d\n", mp->m_src, mp->m_wid, hosterwid); return 0; } if (!(wp = wait_find(hosterwid))) return 0; hosterwid = 0; startack(wp, mp); return 0; } ./pvm3/src/task.c0100644007401100000360000005253407457036622013021 0ustar kohlgopher static char rcsid[] = "$Id: task.c,v 1.25 2002/04/16 15:04:50 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * task.c * * Task descriptors. * * $Log: task.c,v $ * Revision 1.25 2002/04/16 15:04:50 pvmsrc * Fixed bug in task_cleanup(): * - & vs && in scheduler notification code... :-Q * - bug report submitted by Yan Xiao . * (Spanker=kohl) * * Revision 1.24 2002/02/21 23:18:07 pvmsrc * Added new (not to be documented!) PVM_MAX_TASKS env var support. * - for Mahir Lokvancic . * - forcefully limits the number of tasks that can attach to a * pvmd, required on Solaris in rare circumstances when hard * FD_SETSIZE limit is reached, and all hell breaks loose... * - check pvm_max_ntasks global when allocating new tasks * (0 = no limit) * - in task_new() call, if limit reached return NULL ptr, * indicating PvmOutOfRes... * - keep track of private "ntasks" counter in task_new()/task_free(), * only increment for non-zero tids (avoid counting temp task * structs...). * (Spanker=kohl) * * Revision 1.23 2001/02/07 23:15:54 pvmsrc * 2nd Half of CYGWIN Check-ins... * (Spanker=kohl) * * Revision 1.22 2000/09/01 14:39:22 pvmsrc * Plugged memory (waitc) leak in task_cleanup(): * - better get rid of any notify wait contexts, if the task is * dead we probably don't care any more... * - added wait_delete() for WT_HOSTA, WT_TASKX, WT_ROUTEA, WT_ROUTED. * - I hope this doesn't break any shit... :-o * (Spanker=kohl) * * Revision 1.21 2000/02/17 23:12:19 pvmsrc * *** Changes for new BEOLIN port *** * - MPP-like, similar to SP2, etc. * - submitted by Paul Springer . * - format-checked & cleaned up by Jeembo... :-) * (Spanker=kohl) * * Revision 1.20 2000/02/16 22:00:30 pvmsrc * Fixed up #include stuff... * - use for IMA_TITN... * - #include before any NEEDMENDIAN #includes... * (Spanker=kohl) * * Revision 1.19 1999/07/08 19:00:15 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.18 1998/11/20 20:06:47 pvmsrc * Changes so that win32 will compile & build. Also, common * Changes so that compiles & builds on NT. Also * common source on win32 & unix. * (spanker=sscott) * * Revision 1.17 1998/10/02 15:44:10 pvmsrc * Single source code merge of Win32 and Unix code. * (Spanker=sscott) * * Revision 1.16 1998/01/12 21:13:30 pvmsrc * Replaced inline constants with new task output op defines. * - TO_NEW == -2. * - TO_SPAWN == -1. * - TO_EOF == 0. * (Spanker=kohl) * * Revision 1.15 1997/12/01 22:17:43 pvmsrc * Fixed tracer registry problem. * - in task_cleanup(), if exited task was the tracer, forward a * DM_SLCONF_TRACE message to all hosts to clear tracer setting. * (Spanker=kohl) * * Revision 1.14 1997/06/27 20:05:27 pvmsrc * Integrated WIN32 changes. * * Revision 1.13 1997/06/27 19:22:08 pvmsrc * Task struct updated to hold message state info about its last message * to the RM. * Avoids duplicate messages and helps migrated/new RMs understand task * state. * * Revision 1.12 1997/06/02 13:50:05 pvmsrc * Added missing #include host.h for waitc.h. * * Revision 1.11 1997/05/12 20:28:20 pvmsrc * Removed duplicate #includes... * * Revision 1.10 1997/04/30 21:26:29 pvmsrc * SGI Compiler Warning Cleanup. * * Revision 1.9 1997/04/10 17:52:35 pvmsrc * Added WT_RECVINFO case to task_cleanup(). * - if task died while waiting for a reply from pvm_recvinfo(), * wipe out the wait context. * * Revision 1.8 1997/04/08 19:42:57 pvmsrc * *** Added new system reset protocol / wait linkage. * - new DM_RESET / dm_reset() & DM_RESETACK / dm_resetack(). * - new WT_RESET wait type. * - modified dm_db() to include new TMDB_RESET(nnr, noresets) option: * * clean up mboxes, except for "no-reset" tasks. * * for persistent mboxes, set up WT_RESET to remove mbox on task * exit, propagate to task's host via DM_RESET. * * on task exit, WT_RESET wipes mbox out, DM_RESETACK passes * word on to master pvmd (if necessary). * * Revision 1.7 1997/04/04 15:45:39 pvmsrc * Take into account the number of system contexts (NUM_SYSCTX) * that are preallocated. * * Revision 1.6 1997/02/13 19:05:07 pvmsrc * Fixed mbox cleanup problem: * - in dm_db() for TMDB_PUT case, if successful create master PVMD * notify on inserting task (if task not local, forward DM_NOTIFY). * - then on task exit, call mb_tidy() if WT_TASKX notify wait context * exists (in hostfailentry() and task_cleanup()), or if empty * notify propagates back to master PVMD via DM_NOTIFYACK. * * Revision 1.5 1997/02/13 15:10:04 pvmsrc * Removed unnecessary extern for struct waitc *waitlist. * - now in global.h. * * Revision 1.4 1997/01/28 19:27:32 pvmsrc * New Copyright Notice & Authors. * * Revision 1.3 1996/10/25 13:58:07 pvmsrc * Replaced old #includes for protocol headers: * - , "ddpro.h", "tdpro.h" * With #include of new combined header: * - * * Revision 1.2 1996/10/24 22:10:04 pvmsrc * Moved #include "global.h" below other #include's for typing. * Added #include for tracing constants. * Added extern struct Pvmtracer pvmtracer for tracer info. * Modified checking of trctid / outtid: * - check for > 0, not non-zero, to handle new case where task * denies external collection. * Replaced inline code for pvmd trace events with new routine calls: * - tev_send_endtask(). * On task exit, check for tracer registration -> clear tracer info... * * Revision 1.1 1996/09/23 23:44:43 pvmsrc * Initial revision * * Revision 1.8 1995/09/05 19:26:36 manchek * clear wait WT_HOSTF in task_cleanup * * Revision 1.7 1995/05/17 16:53:35 manchek * don't need mytid anymore * * Revision 1.6 1995/02/06 18:45:45 manchek * added stuff to task_dump * * Revision 1.5 1994/11/08 15:40:59 manchek * shared memory cleanup. * check if wa_tid is zero before sending message in task_cleanup * * Revision 1.4 1994/10/15 19:32:49 manchek * added log in task_free() * * Revision 1.3 1994/06/03 20:38:28 manchek * version 3.3.0 * * Revision 1.2 1993/11/30 15:55:25 manchek * task_free() deletes auth file if one exists * * Revision 1.1 1993/08/30 23:26:51 manchek * Initial revision * */ #ifdef IMA_TITN #include #else #include #endif #ifdef NEEDMENDIAN #include #endif #ifdef NEEDENDIAN #include #endif #ifdef NEEDSENDIAN #include #endif #include #if defined(WIN32) || defined(CYGWIN) #include "..\xdr\types.h" #include "..\xdr\xdr.h" #else #include #include #endif #ifdef WIN32 #include "pvmwin.h" #include #else #include #include #include #endif #ifdef SYSVSTR #include #else #include #endif #include #include "pmsg.h" #include "pkt.h" #include "task.h" #include "host.h" #include "waitc.h" #include "pvmalloc.h" #include "listmac.h" #include "bfunc.h" #include #include "msgbox.h" #include "global.h" /*************** ** Globals ** ** ** ***************/ extern void pvmbailout(); extern int busyadding; /* from ddpro.c */ extern int pvmdebmask; /* from pvmd.c */ extern int hostertid; /* from pvmd.c */ extern struct htab *hosts; /* from pvmd.c */ extern int myhostpart; /* from pvmd.c */ extern int taskertid; /* from pvmd.c */ extern struct Pvmtracer pvmtracer; /* from pvmd.c */ extern int tidlmask; /* from pvmd.c */ extern int pvm_max_ntasks; /* from pvmd.c */ struct task *locltasks = 0; /* all task structs sorted by tid */ void task_dump(); void tev_send_endtask(); /*************** ** Private ** ** ** ***************/ static struct ccon *cconlist = 0; static int ntasks = 0; /* tot # of tasks registered w/this pvmd */ /***************** ** Interface ** ** ** *****************/ /* task_init() * * Call once before any other task stuff. */ void task_init() { if (!locltasks) { locltasks = TALLOC(1, struct task, "task"); BZERO((char*)locltasks, sizeof(struct task)); locltasks->t_link = locltasks; locltasks->t_rlink = locltasks; locltasks->t_plink = locltasks; locltasks->t_prlink = locltasks; cconlist = TALLOC(1, struct ccon, "ccon"); BZERO((char*)cconlist, sizeof(struct ccon)); cconlist->c_link = cconlist->c_rlink = cconlist; } } /* ccon_new() * * Allocate a new unique context id to a task. */ struct ccon * ccon_new(tp) struct task *tp; { static int lastcid = 0; int startcid; int cid; struct ccon *cp, *cp2; if (++lastcid > tidlmask - NUM_SYSCTX) lastcid = 1; startcid = lastcid; cp = cconlist; while (1) { cid = myhostpart + lastcid; while (cp->c_cid < cid) if ((cp = cp->c_link) == cconlist) break; if (cp->c_cid != cid) break; if (++lastcid > tidlmask) { lastcid = 1; cp = cconlist; } if (lastcid == startcid) { pvmlogprintf("ccon_new() out of cids?\n"); return 0; } } if (!(cp2 = TALLOC(1, struct ccon, "ccon"))) { pvmlogprintf("ccon_new() can't get memory\n"); return 0; } cp2->c_cid = cid; cp2->c_tid = tp->t_tid; LISTPUTBEFORE(tp->t_ccs, cp2, c_peer, c_rpeer); LISTPUTBEFORE(cp, cp2, c_link, c_rlink); if (pvmdebmask & PDMTASK) { pvmlogprintf("ccon_new() tid=%x cid=%x\n", cp2->c_tid, cp2->c_cid); } return cp2; } /* tid_new() * * Generates a task id not already in use. * * XXX Be sure to call task_new() with tid before calling * tid_new() again. */ int tid_new() { static int lastind = 0; /* last local-part assigned */ int startind; /* to detect when we're out of tids */ struct task *tp; int tid; if (++lastind > tidlmask) lastind = 1; startind = lastind; tp = locltasks; while (1) { tid = myhostpart + lastind; while (tp->t_tid < tid) if ((tp = tp->t_link) == locltasks) break; if (tp->t_tid != tid) return tid; if (++lastind > tidlmask) { lastind = 1; tp = locltasks; } if (lastind == startind) return -1; } } #ifdef WIN32 void task_sethandle(tp,t_handle) struct task *tp; int t_handle; { tp->t_handle = t_handle; } #endif /* task_new() * * Make a new task descriptor, add to list of local tasks but not * to by-pid list. */ struct task * task_new(tid) int tid; { struct task *tp, *tp2; if (tid) { ntasks++; if (pvmdebmask & PDMTASK) { pvmlogprintf("task_new(%d) ntasks=%d pvm_max_ntasks=%d\n", tid, ntasks, pvm_max_ntasks ); } if (pvm_max_ntasks && ntasks > pvm_max_ntasks) { pvmlogprintf("task_new() too many tasks?\n"); ntasks--; /* this one didn't make it... :-) */ return( (struct task *) NULL ); } } if (!(tp = TALLOC(1, struct task, "task"))) { pvmlogprintf("task_new() can't get memory\n"); pvmbailout(0); } BZERO((char*)tp, sizeof(struct task)); tp->t_tid = tid; tp->t_txq = pk_new(0); tp->t_sock = -1; tp->t_out = -1; tp->t_authfd = -1; tp->t_schedlmsg = 0; tp->t_ccs = TALLOC(1, struct ccon, "ccon"); tp->t_ccs->c_link = tp->t_ccs->c_rlink = 0; tp->t_ccs->c_peer = tp->t_ccs->c_rpeer = tp->t_ccs; tp->t_ccs->c_cid = 0; tp->t_ccs->c_tid = tid; FORLIST (tp2, locltasks, t_link) if (tp2->t_tid > tid) break; LISTPUTBEFORE(tp2, tp, t_link, t_rlink); return tp; } /* task_free() * * Do low-level cleanup needed when a task exits. * Remove task descriptor from lists and destroy it. * Close any fds, unlink any files, free mbufs. */ void task_free(tp) struct task *tp; { struct timeval now; struct pmsg *mp; struct ccon *cp; if (pvmdebmask & PDMTASK) { pvmlogprintf("task_free() t%x\n", tp->t_tid); } #ifdef SHMEM /* XXX this is inside out - mpp_free should call task_free. XXX but for now task_free is what's called. XXX this will change in the portable processor interface XXX cleanup. */ mpp_free(tp->t_tid); #endif #ifdef IMA_BEOLIN mpp_free(tp); #endif if (tp->t_plink && tp->t_prlink) { LISTDELETE(tp, t_plink, t_prlink); } if (tp->t_link && tp->t_rlink) { LISTDELETE(tp, t_link, t_rlink); } if (tp->t_rxm) pmsg_unref(tp->t_rxm); if (tp->t_rxp) pk_free(tp->t_rxp); if (tp->t_txq) pk_free(tp->t_txq); if (tp->t_wait) wait_delete(tp->t_wait); if (tp->t_authnam) { (void)unlink(tp->t_authnam); PVM_FREE(tp->t_authnam); } if (tp->t_sock != -1) { wrk_fds_delete(tp->t_sock, 3); #ifdef WIN32 closesocket(tp->t_sock); #else (void)close(tp->t_sock); #endif } if (tp->t_out != -1) { wrk_fds_delete(tp->t_out, 1); #ifdef WIN32 closesocket(tp->t_out); #else (void)close(tp->t_out); #endif } if (tp->t_outtid > 0) { mp = mesg_new(0); mp->m_dst = tp->t_outtid; mp->m_ctx = tp->t_outctx; mp->m_tag = tp->t_outtag; pkint(mp, tp->t_tid); pkint(mp, TO_EOF); sendmessage(mp); tp->t_outtid = 0; } if (tp->t_trctid > 0) { tev_send_endtask( tp->t_trctid, tp->t_trcctx, tp->t_trctag, tp->t_tid, tp->t_status, tp->t_utime.tv_sec, tp->t_utime.tv_usec, tp->t_stime.tv_sec, tp->t_stime.tv_usec ); tp->t_trctid = 0; } if (tp->t_authfd != -1) (void)close(tp->t_authfd); if (tp->t_a_out) PVM_FREE(tp->t_a_out); if (tp->t_mca) mca_free(tp->t_mca); if (tp->t_ccs) { while (cp = LISTFIRST(tp->t_ccs, c_peer)) { LISTDELETE(cp, c_link, c_rlink); LISTDELETE(cp, c_peer, c_rpeer); PVM_FREE(cp); } PVM_FREE(tp->t_ccs); } if (tp->t_tid) { ntasks--; if (pvmdebmask & PDMTASK) { pvmlogprintf("task_free(%d) ntasks=%d\n", tp->t_tid, ntasks ); } } PVM_FREE(tp); } /* task_find() * * Find a task in local tasks list by its tid. */ struct task * task_find(tid) int tid; { struct task *tp; if (tid) { tp = locltasks->t_link; while (tp != locltasks && tp->t_tid < tid) tp = tp->t_link; if (tp->t_tid == tid) return tp; } return (struct task*)0; } /* task_findpid() * * Find a task in local tasks list by its pid. */ struct task * task_findpid(pid) int pid; { struct task *tp; tp = locltasks->t_plink; while (tp != locltasks && tp->t_pid < pid) tp = tp->t_plink; return (tp->t_pid == pid) ? tp : (struct task*)0; } /* task_setpid() * * Set the pid for a task, insert it into by-pid list. Move it * if it's already in the list. */ void task_setpid(tp, pid) struct task *tp; int pid; { struct task *tp2; if (tp->t_plink) { LISTDELETE(tp, t_plink, t_prlink); } tp->t_pid = pid; for (tp2 = locltasks->t_plink; tp2 != locltasks; tp2 = tp2->t_plink) if (tp2->t_pid > pid) break; LISTPUTBEFORE(tp2, tp, t_plink, t_prlink); } /* task_cleanup() * * Do high-level cleanup needed when a task exits. * Wake up any entities waiting on task, free multicast context. * XXX should flush any partial messages, but that would be hard. hm. */ void task_cleanup(tp) struct task *tp; { struct pmsg *mp; struct waitc *wp, *wp2; struct task *tp2; struct pvmmentry *ep; struct hostd *hp; struct pmsg *mpd; char buf[512]; int hh; /* notify anyone who asked */ if (tp->t_tid) { if (pvmdebmask & PDMTASK) pvmlogprintf("task_cleanup() t%x\n", tp->t_tid); for (wp = waitlist->wa_link; wp != waitlist; wp = wp->wa_link) { /* waits depending on this task */ if (wp->wa_on == tp->t_tid) { switch (wp->wa_kind) { case WT_HOSTSTART: busyadding = 0; free_waitc_add((struct waitc_add *)wp->wa_spec); pkint(wp->wa_mesg, PvmDSysErr); sendmessage(wp->wa_mesg); wp->wa_mesg = 0; if (pvmdebmask & (PDMTASK|PDMSTARTUP)) pvmlogprintf( "task_cleanup() hoster t%x takes wid %d with it\n", tp->t_tid, wp->wa_wid); break; case WT_TASKSTART: if (wp->wa_tid) { if (pvmdebmask & PDMTASK) { pvmlogprintf( "task_cleanup() tasker t%x takes t%x with it\n", tp->t_tid, wp->wa_tid); } if (tp2 = task_find(wp->wa_tid)) { wp->wa_tid = 0; task_cleanup(tp2); task_free(tp2); } } break; case WT_TASKX: if (wp->wa_tid && wp->wa_mesg) { sendmessage(wp->wa_mesg); wp->wa_mesg = 0; } mb_tidy(tp->t_tid); break; case WT_RESET: if (wp->wa_tid && wp->wa_mesg) { sendmessage(wp->wa_mesg); wp->wa_mesg = 0; } mb_tidy_reset(tp->t_tid); break; case WT_RECVINFO: /* clean up pending recvinfo */ ep = (struct pvmmentry *) wp->wa_spec; if ( ep->me_msg ) /* class name (overload :-Q) */ PVM_FREE( ep->me_msg ); PVM_FREE( ep ); break; case WT_HOSTA: break; default: pvmlogprintf( "task_cleanup() can't deal with wait kind %d\n", wp->wa_kind); break; } wp2 = wp; wp = wp->wa_rlink; wait_delete(wp2); continue; } /* waits this task was waiting on */ if (wp->wa_tid == tp->t_tid) { switch (wp->wa_kind) { case WT_HOSTF: case WT_HOSTA: case WT_TASKX: case WT_ROUTEA: case WT_ROUTED: case WT_TASKSTART: wp2 = wp; /* some kinds we can toss now */ wp = wp->wa_rlink; wait_delete(wp2); break; default: wp->wa_tid = 0; /* in case tid gets recycled */ break; } } } /* notify the scheduler */ if ((tp->t_sched)&&(tp->t_schedlmsg!=SM_TASKX)) { mp = mesg_new(0); mp->m_dst = tp->t_sched; mp->m_tag = SM_TASKX; tp->t_schedlmsg = SM_TASKX; if (pvmdebmask & PDMSCHED) { pvmlogprintf("task_cleanup() taskx to t%x status = 0x%x\n", tp->t_sched, tp->t_status); } pkint(mp, tp->t_tid); pkint(mp, tp->t_status); pkint(mp, (int)tp->t_utime.tv_sec); pkint(mp, (int)tp->t_utime.tv_usec); pkint(mp, (int)tp->t_stime.tv_sec); pkint(mp, (int)tp->t_stime.tv_usec); sendmessage(mp); } /* check if it's the hoster */ if (tp->t_tid == hostertid) { if (pvmdebmask & (PDMTASK|PDMSTARTUP)) { pvmlogprintf("task_cleanup() unreg hoster t%x\n", tp->t_tid); } hostertid = 0; } /* check if it's the tasker */ if (tp->t_tid == taskertid) { if (pvmdebmask & PDMTASK) { pvmlogprintf("task_cleanup() unreg tasker t%x\n", tp->t_tid); } taskertid = 0; } /* check if it's the tracer */ if (tp->t_tid == pvmtracer.trctid) { if (pvmdebmask & PDMTASK) { pvmlogprintf("task_cleanup() unreg tracer t%x\n", tp->t_tid); } pvmtracer.trctid = 0; pvmtracer.trcctx = 0; pvmtracer.trctag = 0; pvmtracer.outtid = 0; pvmtracer.outctx = 0; pvmtracer.outtag = 0; TEV_MASK_INIT(pvmtracer.tmask); pvmtracer.trcbuf = 0; pvmtracer.trcopt = 0; /* tell the other pvmds */ for (hh = hosts->ht_last; hh > 0; hh--) { if (hh != hosts->ht_local && (hp = hosts->ht_hosts[hh])) { mpd = mesg_new(0); mpd->m_tag = DM_SLCONF; mpd->m_dst = hp->hd_hostpart | TIDPVMD; pkint(mpd, DM_SLCONF_TRACE); sprintf(buf, "%x %d %d %x %d %d %d %d %s", pvmtracer.trctid, pvmtracer.trcctx, pvmtracer.trctag, pvmtracer.outtid, pvmtracer.outctx, pvmtracer.outtag, pvmtracer.trcbuf, pvmtracer.trcopt, pvmtracer.tmask); pkstr(mpd, buf); sendmessage(mpd); } } } } /* complete multicast */ if (tp->t_mca) { /* XXX should send an EOM frag to all rcpts */ mca_free(tp->t_mca); tp->t_mca = 0; } } void task_dump() { struct task *tp; struct pkt *pp; struct ccon *cp; pvmlogprintf("task_dump()\n"); pvmlogprintf(" tid ptid flag pid soc out wait outtid trctid sched es\n"); for (tp = locltasks->t_link; tp != locltasks; tp = tp->t_link) { pvmlogprintf("%8x %8x %4x %6d %3d %3d %8d %8x %8x %8x %4x\n", tp->t_tid, tp->t_ptid, tp->t_flag, tp->t_pid, tp->t_sock, tp->t_out, (tp->t_wait ? tp->t_wait->wa_wid : 0), tp->t_outtid, tp->t_trctid, tp->t_sched, tp->t_status); if (LISTFIRST(tp->t_txq, pk_link)) { pvmlogprintf(" txq:pkt src dst flag len ofs\n"); FORLIST (pp, tp->t_txq, pk_link) { pvmlogprintf("%08x %8x %8x %4x %6d %6d\n", pp, pp->pk_src, pp->pk_dst, pp->pk_flag, pp->pk_len, pp->pk_dat - pp->pk_buf); } } if (LISTFIRST(tp->t_ccs, c_peer)) { pvmlogprintf("contexts:"); FORLIST (cp, tp->t_ccs, c_peer) pvmlogprintf(" 0x%x", cp->c_cid); pvmlogprintf("\n"); } } } int ccon_dumpall() { struct ccon *cp; pvmlogprintf("ccon_dumpall()\n"); FORLIST (cp, cconlist, c_link) pvmlogprintf(" tid=%x cid=%x\n", cp->c_tid, cp->c_cid); return 0; } ./pvm3/src/tdpro.c0100644007401100000360000016761107435300122013173 0ustar kohlgopher static char rcsid[] = "$Id: tdpro.c,v 1.34 2002/02/21 23:18:42 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * tdpro.c * * Entry points for messages from local tasks. * * $Log: tdpro.c,v $ * Revision 1.34 2002/02/21 23:18:42 pvmsrc * Added new (not to be documented!) PVM_MAX_TASKS env var support. * - for Mahir Lokvancic . * - forcefully limits the number of tasks that can attach to a * pvmd, required on Solaris in rare circumstances when hard * FD_SETSIZE limit is reached, and all hell breaks loose... * - check return for task_new() call, can now produce NULL ptr, * indicating PvmOutOfRes... * (Spanker=kohl) * * Revision 1.33 2001/09/25 21:20:20 pvmsrc * Minor TMPNAMFUN()/tmpnam() cleanup. * - moved macro def to pvm3.h, renamed PVMTNPMAN(). * - same for LEN_OF_TMP_NAM -> PVMTMPNAMLEN. * - mostly a huge waste of time, since *both* tmpnam() & mktemp() * produce the same "dangerous" warning message in Linux/gcc... * - damn. * (Spanker=kohl) * * Revision 1.32 2001/04/23 14:16:14 pvmsrc * Added new working directory option to pvm_spawn(). * - use "where" argument to cram in working directory, * e.g. where = "msr.epm.ornl.gov:/home/user/project/bozo" * - TM_SPAWN strips out working directory & creates PVMSPAWNWD env var * - exectasks() (called by DM_EXEC or SM_EXEC) checks for env var * and does a chdir() (even uses getcwd() to reset directory :-). * - should not introduce any run-time incompatibility with older * PVM releases. * - PvmTaskHost or PvmTaskArch flags need not be used, i.e. * pvm_spawn( "foo", 0, PvmTaskDefault, ":/tmp", 1, &tid ) works. * (Spanker=kohl) * * Revision 1.31 2001/02/07 23:15:58 pvmsrc * 2nd Half of CYGWIN Check-ins... * (Spanker=kohl) * * Revision 1.30 2000/02/17 23:12:20 pvmsrc * *** Changes for new BEOLIN port *** * - MPP-like, similar to SP2, etc. * - submitted by Paul Springer . * - format-checked & cleaned up by Jeembo... :-) * (Spanker=kohl) * * Revision 1.29 2000/02/16 22:00:30 pvmsrc * Fixed up #include stuff... * - use for IMA_TITN... * - #include before any NEEDMENDIAN #includes... * (Spanker=kohl) * * Revision 1.28 1999/07/08 19:00:16 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.27 1998/11/20 20:06:49 pvmsrc * Changes so that win32 will compile & build. Also, common * Changes so that compiles & builds on NT. Also * common source on win32 & unix. * (spanker=sscott) * * Revision 1.26 1998/01/12 21:13:31 pvmsrc * Replaced inline constants with new task output op defines. * - TO_NEW == -2. * - TO_SPAWN == -1. * - TO_EOF == 0. * (Spanker=kohl) * * Revision 1.25 1997/09/22 21:14:02 pvmsrc * Modified TM_CONN2/tm_conn2() linkage for shell-spanwed tasks. * - check for additional task name packed in message, save it in * task structure, use it for tev_newtask(). * (Spanker=kohl) * * Revision 1.24 1997/09/18 14:14:44 pvmsrc * Fixed bug in tm_mca(): * - loop to filter out bogus dests could hang, if a tid was not * local and on a failed host, index i would not get incremented, * resulting in an infinite loop... * - added second index to count dsts. * - submitted by Kamran Kazemi (kamran@cs.uwa.edu.au). * (Spanker=kohl) * * Revision 1.23 1997/08/29 13:35:20 pvmsrc * OS2 Port Submitted by Bohumir Horeni, horeni@login.cz. * (Spanker=kohl) * * Revision 1.22 1997/08/26 22:55:28 pvmsrc * Make sure wp->wa_mesg is cleared after sendmessage() call. * - otherwise wait_delete() will re-free the pmsg struct causing * major bogusness... * (Spanker=kohl) * * Revision 1.21 1997/08/11 14:40:13 pvmsrc * Attempt to remove CRAY compiler warning. * - if ( 1 ) got bail caused unreachables... * - replaced with "dummy_true" var set to 1, to trick compiler?! :-) * * Revision 1.20 1997/07/02 20:27:35 pvmsrc * Fixed startup race on shmem to that a shmem task can get fully * configured before getting any messages. * This involved adding two states * TF_PRESHMCONN and TF_SHM. TF_PRESHMCONN indicates that messages * with MM_PRIO set can be sent to a task, but regular messages are * queued. This allows shmem tasks to be completely configured * before any messages flow. When the daemon changes the state from * TF_PRESHMCONN to TF_SHMCONN it calls shm_wrt_pkts to write any * packets that were queued before task state changed to TF_SHMCONN. * * Revision 1.19 1997/06/27 17:32:56 pvmsrc * Updated for WIN32 header files & Authors. * * Revision 1.18 1997/06/27 16:10:01 pvmsrc * Spawning tasks with option PvmNoSpawnParent get the * parent tid set to PvmParentNotSet in spawned tasks. * * Revision 1.17 1997/06/24 20:39:22 pvmsrc * Eliminated unnecessary global externs. * * Revision 1.16 1997/06/23 21:26:46 pvmsrc * Added checking for master host in tm_hoster(). * - actually check hd_hostpart instead of ht_local/ht_master indices, * in case freaking host table has copies/duplicates. * (always wear 2 condoms... :-) * - return new PvmHostrNMstr error code. * * Revision 1.15 1997/06/16 13:41:44 pvmsrc * assign_tasks() now passes distribution info in DM_EXEC message. * * Revision 1.14 1997/06/02 13:20:48 pvmsrc * tm_shmconn() marks old task w/ TF_CLOSE * - so work() doesn't complain about a dead socket. * * Revision 1.13 1997/05/28 14:04:05 pvmsrc * Cleaned up TM_SHMCONN() handler routine. * - formatted like hell, and didn't compile clean on SGI64. * * Revision 1.12 1997/05/27 14:45:53 pvmsrc * Added new TM message TM_SHMCONN with routine tm_shmconn(): * which merges records and sets TF_SHMCONN flag. * Updated entry point in loclentry() as well: * to accept this type of connection. * * Revision 1.11 1997/05/12 20:28:22 pvmsrc * Removed duplicate #includes... * * Revision 1.10 1997/05/07 21:22:12 pvmsrc * AAAIIIEEEEEEEEE!!!! * - removed all static-limited string unpacking: * * replaced with use of: * upkstralloc() / PVM_FREE() (for pvmd stuff). * new pvmupkstralloc() / PVM_FREE() (for lpvm stuff). * * manual allocation of local buffers for sprintf() & packing. * * alternate static string arrays to replace fixed-length cases. * * I hope this shit works... :-Q * * Revision 1.9 1997/04/30 21:26:31 pvmsrc * SGI Compiler Warning Cleanup. * * Revision 1.8 1997/03/27 19:57:10 pvmsrc * Spanked in PvmNoSpawnParent flag usage. * - in tm_spawn(), don't set wxp->w_ptid if PvmNoSpawnParent set. * - in assign_tasks(), use wxp->w_ptid as parent tid instead of * snarfing it from wp->wa_tid... (Bob Hack) D-Oh... * * Revision 1.7 1997/02/13 15:10:05 pvmsrc * Removed unnecessary extern for struct waitc *waitlist. * - now in global.h. * * Revision 1.6 1997/01/28 19:27:49 pvmsrc * New Copyright Notice & Authors. * * Revision 1.5 1996/12/30 13:37:49 pvmsrc * Fixed closing comment in last log entry... * * Revision 1.4 1996/12/20 15:02:07 pvmsrc * Fixed missing comment end *-/ ... D-Oh! * * Revision 1.3 1996/10/25 13:58:08 pvmsrc * Replaced old #includes for protocol headers: * - , "ddpro.h", "tdpro.h" * With #include of new combined header: * - * * Revision 1.2 1996/10/24 22:11:04 pvmsrc * Moved #include "global.h" below other #include's for typing. * Added #include for tracing constants. * Added extern struct Pvmtracer pvmtracer for tracer info. * Added new tm_tracer() routine to handle tracer registration requests * from pvm_reg_tracer(). * In tm_conn2(), insert tracer info for tasks spawned from the shell. * - can't get env vars set here, so rely on mailbox for that info. * - use new tev_send_newtask() routine. * In assign_tasks(): * - replace inline trace event code with new tev_send_spntask(). * - check trctid / outtid with > 0, not non-zero, for new case where * task denies external collection. * Modified change_trace() to use new event routines: * - tev_send_newtask(), tev_send_spntask() & tev_send_endtask(). * * Revision 1.1 1996/09/23 23:44:45 pvmsrc * Initial revision * * Revision 1.9 1995/07/19 21:27:26 manchek * use new function pvmnametag instead of [dts]mname * * Revision 1.8 1995/07/03 19:11:40 manchek * added tickle #100 * * Revision 1.7 1995/05/17 16:55:20 manchek * changed global mytid to pvmmytid. * added TM_GETOPT message class * * Revision 1.6 1994/10/15 19:37:46 manchek * cast message tags for comparison as integers. * check newhosts when deleting host. * unset TF_FORKD if task reconnects with a different pid * * Revision 1.5 1994/06/21 18:30:00 manchek * subscript arith in tmname() broke with opt * * Revision 1.4 1994/06/04 21:45:54 manchek * misc * * Revision 1.3 1994/06/03 20:38:31 manchek * version 3.3.0 * * Revision 1.2 1993/11/30 15:56:23 manchek * tm_conn() complains if it can't write t-auth file (fs full?) * * Revision 1.1 1993/08/30 23:26:52 manchek * Initial revision * */ #include #ifdef IMA_TITN #include #else #include #endif #ifdef NEEDMENDIAN #include #endif #ifdef NEEDENDIAN #include #endif #ifdef NEEDSENDIAN #include #endif #include #if defined(WIN32) || defined(CYGWIN) #include "..\xdr\types.h" #include "..\xdr\xdr.h" #else #include #include #endif #ifdef WIN32 #include #else #include #include #include #endif #include #ifdef SYSVSTR #include #else #include #endif #include #include #include "pvmalloc.h" #include "pmsg.h" #include "task.h" #include "host.h" #include "waitc.h" #include "listmac.h" #include "bfunc.h" #include #include "global.h" #ifdef IMA_BEOLIN #include "pvmdmp.h" #endif #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif /*************** ** Globals ** ** ** ***************/ extern void task_dump(); char *debug_flags(); char *inadport_hex(); void i_dump(); void tev_send_newtask(); void tev_send_spntask(); void tev_send_endtask(); extern int pvmdebmask; /* from pvmd.c */ extern int hostertid; /* from pvmd.c */ extern struct htab *hosts; /* from pvmd.c */ extern int pvmmydsig; /* from pvmd.c */ extern int myhostpart; /* from pvmd.c */ extern int pvmmytid; /* from pvmd.c */ extern struct htab *newhosts; /* from pvmd.c */ extern int nopax; /* from pvmd.c */ extern int pvmudpmtu; /* from pvmd.c */ extern int pvmschedtid; /* from pvmd.c */ extern int taskertid; /* from pvmd.c */ extern struct Pvmtracer pvmtracer; /* from pvmd.c */ extern int tidhmask; /* from pvmd.c */ /*************** ** Private ** ** ** ***************/ int tm_addhost(); int tm_config(); int tm_conn2(); int tm_connect(); int tm_context(); int tm_db(); int tm_delhost(); int tm_exit(); int tm_getopt(); int tm_halt(); int tm_hoster(); int tm_hostsync(); int tm_mca(); int tm_mstat(); int tm_notify(); int tm_pstat(); int tm_sendsig(); int tm_sched(); int tm_setopt(); int tm_spawn(); int tm_task(); int tm_tasker(); int tm_tickle(); int tm_tracer(); int tm_shmconn(); int (*loclswitch[])() = { tm_connect, tm_conn2, tm_exit, tm_addhost, tm_delhost, tm_config, tm_mstat, tm_halt, tm_tickle, tm_spawn, tm_pstat, tm_sendsig, tm_task, tm_mca, tm_notify, tm_db, tm_sched, tm_tasker, tm_hoster, tm_tracer, tm_hostsync, tm_setopt, tm_getopt, tm_context, tm_shmconn, }; int loclentry(tp, mp) struct task *tp; struct pmsg *mp; { int c = mp->m_tag; if (pvmdebmask & PDMMESSAGE) { pvmlogprintf("loclentry() from t%x tag %s\n", mp->m_src, pvmnametag(c, (int *)0)); /* pvmhdump(mp->m_cfrag->fr_dat, mp->m_cfrag->fr_len, "frag: "); */ } /* if (mp->m_enc != 1) { pvmlogprintf("loclentry() message from t%x with bad enc %d\n", tp->t_tid, mp->m_enc); goto bail; } */ if (c < (int)TM_FIRST || c > (int)TM_LAST) { pvmlogprintf("loclentry() message from t%x with bogus tag %d\n", tp->t_tid, c); goto bail; } if ((!(tp->t_flag & TF_CONN) && c != TM_CONNECT && c != TM_CONN2 && c != TM_SHMCONN) || ((tp->t_flag & TF_AUTH) && c != TM_CONN2)) { pvmlogerror("loclentry() non-connect message from anon task\n"); tp->t_flag |= TF_CLOSE; goto bail; } c -= TM_FIRST; (loclswitch[c])(tp, mp); bail: pmsg_unref(mp); return 0; } /* replymessage() * * Construct reply message to sender with matching context, tag, wait id */ struct pmsg * replymessage(mp) struct pmsg *mp; { struct pmsg *rmp; if (rmp = mesg_new(0)) { rmp->m_dst = mp->m_src; rmp->m_ctx = mp->m_ctx; rmp->m_tag = mp->m_tag; rmp->m_wid = mp->m_wid; } return rmp; } /********************************* ** Task request entry points ** ** ** *********************************/ /* tm_connect() * * Task connecting to pvmd phase 1. * We assign it a context, write in t-auth file to prove our ident, * then make d-auth file for task to prove itself. * * TM_CONNECT * call { * int tdprotocol // t-d protocol number compiled into libpvm * string authfile // t-auth file pvmd must write * } * ret { * int tdprotocol // pvmd's td protocol version * int acknack // 1 if pvmd accepts connection * string authfile // d-auth file task must write * } */ int tm_connect(tp, mp) struct task *tp; struct pmsg *mp; { int ver; /* task's libpvm t-d proto version */ char authfn[PVMTMPNAMLEN]; /* t-auth file name */ int d; int cc; if (upkint(mp, &ver) || upkstr(mp, authfn, sizeof(authfn))) { pvmlogerror("tm_connect() bad msg format\n"); goto bail; } /* * if protocols are not compatible, send nack * context will get flushed after reply is sent */ if (ver != TDPROTOCOL) { pvmlogprintf("tm_connect() t-d protocol mismatch (%d/%d)\n", ver, TDPROTOCOL); mp = replymessage(mp); pkint(mp, TDPROTOCOL); pkint(mp, 0); pkstr(mp, ""); mp->m_flag |= MM_PRIO; mesg_to_task(tp, mp); pmsg_unref(mp); goto bail; } #ifdef NOPROT tp->t_authnam = TALLOC(PVMTMPNAMLEN, char, "auth"); (void)PVMTMPNAMFUN(tp->t_authnam); #else /* * write in t-auth file, create empty d-auth file that task * must write and we'll check later */ if ((d = open(authfn, O_WRONLY, 0)) == -1) { pvmlogperror("tm_connect() can't open t-auth file"); goto bail; } cc = write(d, authfn, 1); if (cc != 1) { if (cc == -1) pvmlogperror(authfn); pvmlogerror("tm_connect() can't write t-auth file\n"); } (void)close(d); tp->t_authnam = TALLOC(PVMTMPNAMLEN, char, "auth"); (void)PVMTMPNAMFUN(tp->t_authnam); #ifndef IMA_OS2 if ((tp->t_authfd = open(tp->t_authnam, O_RDONLY|O_CREAT|O_TRUNC, 0600)) #else if ((tp->t_authfd = open(tp->t_authnam, O_RDWR|O_CREAT|O_TRUNC, 0600)) #endif == -1) { pvmlogperror("tm_connect() can't create d-auth file"); PVM_FREE(tp->t_authnam); tp->t_authnam = 0; goto bail; } #endif /* * task's turn to auth */ tp->t_flag |= TF_AUTH; mp = replymessage(mp); pkint(mp, TDPROTOCOL); pkint(mp, 1); pkstr(mp, tp->t_authnam); mp->m_flag |= MM_PRIO; mesg_to_task(tp, mp); pmsg_unref(mp); return 0; bail: tp->t_flag |= TF_CLOSE; return 0; } /* tm_conn2() * * Task connecting to pvmd phase 2. * We check d-auth file and give it config info, attach to real context. * * TM_CONN2 * call { * int unixpid // real pid * int cookie // magic cookie inherited from pvmd (or 0) * (char *taskname) // (optional) task name specification * } * ret { * int acknack // 1 if pvmd accepts connection * int tid // task tid * int ptid // parent tid * int outtid // output dst * int outctx * int outtag * int trctid // trace dst * int trcctx * int trctag * int udpmax * int nativecode * string inaddr * int schedtid // scheduler tid * } */ int tm_conn2(tp, mp) struct task *tp; struct pmsg *mp; { int tid; int pid; /* real pid of task */ int cookie; /* cookie to identify task or 0 */ struct task *tp2; /* to search for existing context */ struct pmsg *mp2; int cc; char c; char *taskname = (char *) NULL; if (upkint(mp, &pid) || upkint(mp, &cookie)) { pvmlogerror("tm_conn2() bad msg format\n"); goto bail; } if (!cookie) cookie = pid; if (!(tp->t_flag & TF_AUTH)) { pvmlogprintf("tm_conn2() message from t%x, TF_AUTH not set\n", tp->t_tid); return 0; } /* * check that task could write d-auth file */ #ifndef NOPROT if ((cc = read(tp->t_authfd, &c, 1)) == -1) { pvmlogperror("tm_conn2() can't read d-auth file"); return 0; } if (cc != 1) { pvmlogerror("tm_conn2() task didn't validate itself\n"); goto bail; } (void)close(tp->t_authfd); tp->t_authfd = -1; (void)unlink(tp->t_authnam); #endif PVM_FREE(tp->t_authnam); tp->t_authnam = 0; /* * if task spawned by us, already has a context, * else make it one */ if ((tp2 = task_findpid(cookie)) && !(tp2->t_flag & (TF_AUTH|TF_CONN))) { if (pvmdebmask & PDMTASK) { pvmlogprintf("tm_conn2() reconnect task t%x\n", tp2->t_tid); } tp->t_sched = tp2->t_sched; #ifdef IMA_BEOLIN } else if ( (tp2 = mpp_find(tp)) && !(tp2->t_flag & (TF_AUTH|TF_CONN)) ) { if (pvmdebmask & PDMTASK) { pvmlogprintf( "tm_conn2() reconnect task t%x pid=%d name=%s\n", tp2->t_tid,tp2->t_pid, tp2->t_a_out ); } #endif } else { if ((tid = tid_new()) < 0) { pvmlogerror("tm_conn2() out of tids?\n"); goto bail; /* XXX should disconnect nicely */ } if ((tp2 = task_new(tid)) == NULL) { pvmlogerror("tm_conn2() too many tasks?\n"); goto bail; /* XXX should disconnect nicely */ } if ( !upkstralloc(mp, &taskname) ) { tp2->t_a_out = taskname; } if (pvmschedtid) { /* inform the scheduler about the new task */ tp->t_sched = pvmschedtid; mp2 = mesg_new(0); pkint(mp2, 1); pkint(mp2, tid); mp2->m_tag = SM_EXECACK; /* XXX yecch, overload */ mp2->m_dst = pvmschedtid; sendmessage(mp2); } /* check for tracer */ if (pvmtracer.trctid && pvmtracer.trctag) { tp2->t_trctid = pvmtracer.trctid; tp2->t_trcctx = pvmtracer.trcctx; tp2->t_trctag = pvmtracer.trctag; /* Note: can't get the trace mask or trace buffer size to task here, but this will be handled using mailbox */ /* trace start message */ /* XXX Note: we don't really know if we should send this because this task could have prohibited tracing by setting PvmSelfTraceTid to -1... */ tev_send_newtask( pvmtracer.trctid, pvmtracer.trcctx, pvmtracer.trctag, tid, -1, -1, tp->t_a_out ? tp->t_a_out : "-" ); } if (pvmtracer.outtid && pvmtracer.outtag) { tp2->t_outtid = pvmtracer.outtid; tp2->t_outctx = pvmtracer.outctx; tp2->t_outtag = pvmtracer.outtag; /* output start message */ /* Note: same deal here as for TEV_NEWTASK above... */ mp2 = mesg_new(0); mp2->m_dst = pvmtracer.outtid; mp2->m_ctx = pvmtracer.outctx; mp2->m_tag = pvmtracer.outtag; pkint(mp2, tid); pkint(mp2, TO_NEW); pkint(mp2, -1); sendmessage(mp2); } if (pvmdebmask & PDMTASK) { pvmlogprintf("tm_conn2() new task t%x\n", tp2->t_tid); } } /* * brundle-fly the contexts together */ tp2->t_sock = tp->t_sock; tp2->t_sad = tp->t_sad; tp2->t_salen = tp->t_salen; #ifdef NOPROT if (!TIDISNODE(tp2->t_tid)) { if (pvmdebmask & PDMTASK) { pvmlogprintf( "Setting pid of t%x to %d, same as t%x\n", tp2->t_tid, tp->t_pid, tp->t_tid ); } task_setpid(tp2, tp->t_pid); } #else if (tp2->t_pid != pid) task_setpid(tp2, pid); #endif tp2->t_rxp = tp->t_rxp; tp2->t_sched = tp->t_sched; tp->t_sock = -1; /* tp will be freed by loclinput() */ tp->t_rxp = 0; tp = tp2; if (cookie != pid) tp->t_flag &= ~TF_FORKD; /* * kick it in the butt; it's ready to go */ tp->t_flag &= ~TF_AUTH; tp->t_flag |= TF_CONN; mp = replymessage(mp); pkint(mp, 1); pkint(mp, tp->t_tid); pkint(mp, tp->t_ptid); pkint(mp, tp->t_outtid); pkint(mp, tp->t_outctx); pkint(mp, tp->t_outtag); pkint(mp, tp->t_trctid); pkint(mp, tp->t_trcctx); pkint(mp, tp->t_trctag); pkint(mp, pvmudpmtu); pkint(mp, pvmmydsig); pkstr(mp, inadport_hex(&(hosts->ht_hosts[hosts->ht_local]->hd_sad))); pkint(mp, pvmschedtid); mp->m_dst = tp->t_tid; mp->m_flag |= MM_PRIO; sendmessage(mp); return 0; bail: tp->t_flag |= TF_CLOSE; return 0; } /* tm_exit() * * Last message from a task. This is the nice way of disconnecting. * * TM_EXIT * call { } * ret { } */ int tm_exit(tp, mp) struct task *tp; struct pmsg *mp; { mp = replymessage(mp); tp->t_flag |= TF_CLOSE; sendmessage(mp); if (!(tp->t_flag & TF_FORKD)) task_cleanup(tp); return 0; } /* tm_pstat() * * Task wants status of another task. * * TM_PSTAT * call { * int tid * } * ret { * int status * } */ int tm_pstat(tp, mp) struct task *tp; struct pmsg *mp; { int tid; struct hostd *hp; struct waitc *wp; /* unpack and sanity check tid */ if (upkuint(mp, &tid)) { pvmlogerror("tm_pstat() bad msg format\n"); return 0; } if (!TIDISTASK(tid)) { pvmlogprintf("tm_pstat() bad tid %x\n", tid); return 0; } /* nack if no such host */ if (!(hp = tidtohost(hosts, tid))) { mp = replymessage(mp); pkint(mp, PvmNoTask); sendmessage(mp); return 0; } /* else make a wait context and send query */ wp = wait_new(WT_PSTAT); wp->wa_tid = tp->t_tid; wp->wa_on = hp->hd_hostpart; wp->wa_mesg = replymessage(mp); mp = mesg_new(0); mp->m_dst = hp->hd_hostpart | TIDPVMD; mp->m_tag = DM_PSTAT; mp->m_wid = wp->wa_wid; pkint(mp, tid); sendmessage(mp); return 0; } /* tm_addhost() * * Task requesting to add hosts to virtual machine. Exit point is * here or dm_addack(). * * TM_ADDHOST * call { * int nhosts * string names[nhosts] * } * ret { * int nhosts // or error code * int narches // if nhosts >= 0 * { * int tid // or error code * string name * string arch * int speed * int dsig * } [nhosts] * } */ int tm_addhost(tp, mp) struct task *tp; struct pmsg *mp; { int count; char *buf; struct waitc *wp; /* sanity check the message */ if (upkint(mp, &count)) goto bad; if (count < 1 || count > (tidhmask >> (ffs(tidhmask) - 1))) goto bad; while (count-- > 0) { if (upkstralloc(mp, &buf)) goto bad; else PVM_FREE(buf); } /* make a wait channel for the task */ wp = wait_new(WT_ADDHOST); wp->wa_tid = tp->t_tid; wp->wa_on = hosts->ht_hosts[hosts->ht_master]->hd_hostpart; wp->wa_mesg = replymessage(mp); /* forward message to master pvmd */ mp->m_ref++; mp->m_src = pvmmytid; mp->m_dst = hosts->ht_hosts[hosts->ht_master]->hd_hostpart | TIDPVMD; mp->m_tag = DM_ADD; mp->m_wid = wp->wa_wid; sendmessage(mp); return 0; bad: pvmlogprintf("tm_addhost() from t%x bad msg format\n", mp->m_src); return 0; } int free_wait_spawn(wxp) struct waitc_spawn *wxp; { int i; if (wxp->w_file) PVM_FREE(wxp->w_file); if (wxp->w_argv) { for (i = 0; i < wxp->w_argc; i++) if (wxp->w_argv[i]) PVM_FREE(wxp->w_argv[i]); PVM_FREE(wxp->w_argv); } if (wxp->w_env) { for (i = 0; i < wxp->w_nenv; i++) if (wxp->w_env[i]) PVM_FREE(wxp->w_env[i]); PVM_FREE(wxp->w_env); } if (wxp->w_ht) ht_free(wxp->w_ht); if (wxp->w_vec) PVM_FREE(wxp->w_vec); PVM_FREE(wxp); return 0; } /* tm_spawn() * * Task requesting to spawn other tasks. Exit point for this * request is here or dm_execack(). * * TM_SPAWN * call { * string file * int flags * string where * int count * int nargs * string argv[nargs] * int outtid * int outctx * int outtag * int trctid * int trcctx * int trctag * int nenv * string env[nenv] * } * ret { * int ntids // or nack * int tids[acknack] * } */ int tm_spawn(tp, mp) struct task *tp; struct pmsg *mp; { char *where = 0; /* location from req */ struct waitc *wp; /* 'seed' waitc */ struct waitc_spawn *wxp = 0; /* new task parameters */ struct htab *htp; /* set of usable hosts */ struct hostd *hp; int hh; int i; char *wd = 0; char *wdenv = 0; char *ptr; int sz; /* * unpack spawn command from task */ wxp = TALLOC(1, struct waitc_spawn, "waix"); BZERO((char*)wxp, sizeof(struct waitc_spawn)); if (upkstralloc(mp, &wxp->w_file) || upkint(mp, &wxp->w_flags) || upkstralloc(mp, &where) || upkint(mp, &wxp->w_veclen) || upkint(mp, &wxp->w_argc)) goto bad; if (wxp->w_veclen < 1) goto bad; wxp->w_argv = TALLOC(wxp->w_argc + 1, char*, "argv"); BZERO((char*)wxp->w_argv, (wxp->w_argc + 1) * sizeof(char*)); for (i = 0; i < wxp->w_argc; i++) if (upkstralloc(mp, &wxp->w_argv[i])) goto bad; if (upkuint(mp, &wxp->w_outtid) || upkuint(mp, &wxp->w_outctx) || upkuint(mp, &wxp->w_outtag) || upkuint(mp, &wxp->w_trctid) || upkuint(mp, &wxp->w_trcctx) || upkuint(mp, &wxp->w_trctag)) goto bad; /* * extract any working directory string from "where" */ ptr = where; while ( *ptr != ':' && *ptr != '\0' ) ptr++; if ( *ptr == ':' ) { *ptr++ = '\0'; /* close off actual "where" string */ wd = ptr; /* save ptr to working directory */ } /* * unpack environment from task */ if (upkuint(mp, &wxp->w_nenv)) goto bad; sz = wxp->w_nenv + 1 + (wd ? 1 : 0); wxp->w_env = TALLOC(sz, char*, "env"); BZERO((char*)wxp->w_env, sz * sizeof(char*)); for (i = 0; i < wxp->w_nenv; i++) if (upkstralloc(mp, &wxp->w_env[i])) goto bad; /* * add extra env string for working directory */ if ( wd ) { sz = strlen(wd) + strlen("PVMSPAWNWD=") + 1; wdenv = TALLOC(sz, char, "wdenv"); sprintf( wdenv, "PVMSPAWNWD=%s", wd ); wxp->w_env[ (wxp->w_nenv)++ ] = STRALLOC( wdenv ); } /* * make host set containing hosts (matching where option) */ if ((wxp->w_flags & (PvmTaskHost|PvmTaskArch)) && !where) goto bad; htp = ht_new(1); if (wxp->w_flags & PvmTaskHost) { /* given host */ if (hp = nametohost(hosts, where)) ht_insert(htp, hp); } else { if (wxp->w_flags & PvmTaskArch) { /* given arch */ for (hh = hosts->ht_last; hh > 0; hh--) if ((hp = hosts->ht_hosts[hh]) && !strcmp(where, hp->hd_arch)) ht_insert(htp, hp); #ifdef IMA_BEOLIN /* local pvmd for now */ } else if (wxp->w_flags & PvmMppFront) { hp = hosts->ht_hosts[hosts->ht_local]; ht_insert(htp, hp); #endif } else { /* anywhere */ ht_merge(htp, hosts); } } if (wxp->w_flags & PvmHostCompl) { for (hh = hosts->ht_last; hh > 0; hh--) { if (hh <= htp->ht_last && (hp = htp->ht_hosts[hh])) ht_delete(htp, hp); else if (hp = hosts->ht_hosts[hh]) ht_insert(htp, hp); } } if (pvmdebmask & PDMTASK) { pvmlogerror("tm_spawn() host set:\n"); ht_dump(htp); } if ( !(wxp->w_flags & PvmNoSpawnParent) ) { wxp->w_ptid = tp->t_tid; } else wxp->w_ptid = PvmParentNotSet; /* indicate task unset parent */ /* * assign each task to a host */ wxp->w_ht = htp; wxp->w_vec = TALLOC(wxp->w_veclen, int, "vec"); BZERO((char*)wxp->w_vec, wxp->w_veclen * sizeof(int)); wxp->w_togo = wxp->w_veclen; wp = wait_new(WT_SPAWN); wp->wa_tid = tp->t_tid; wp->wa_spec = (void*)wxp; wxp = 0; wp->wa_mesg = replymessage(mp); assign_tasks(wp); /* if already done, reply to task */ if (wp->wa_peer == wp) { assign_tasks(wp); } wait_delete(wp); goto cleanup; bad: pvmlogprintf("tm_spawn() from t%x bad msg format\n", mp->m_src); cleanup: if (where) PVM_FREE(where); if (wxp) free_wait_spawn(wxp); return 0; } /* assign_tasks() * * This is only called when no replies are pending (at the beginning * of the operation or when all pvmds have checked back in). */ assign_tasks(wp) struct waitc *wp; /* (any) waitc in peer group for this op */ { static int lasthh = -1; /* for assigning hosts */ struct waitc_spawn *wxp = (struct waitc_spawn*)wp->wa_spec; struct htab *htp; /* set of hosts to use */ int *vec; /* result/status vector */ int veclen; /* length of vector */ int count = 0; /* num of tasks to be assigned */ int nh; /* num of hosts to assign tasks */ int a = 0; /* accum for finding hosts */ int na = 0; /* num tasks assigned to a host */ struct waitc *wp2; struct hostd *hp; struct pmsg *mp; int t; int i; int tid; struct timeval now; if (!wxp) return 0; htp = wxp->w_ht; vec = wxp->w_vec; veclen = wxp->w_veclen; /* * if no hosts left, fill unassigned entries with PvmNoHost */ if (!htp->ht_cnt) for (t = veclen; t-- > 0; ) if (!vec[t]) vec[t] = PvmNoHost; /* * count tasks to be assigned, if none left reply to task */ for (t = veclen; t-- > 0; ) if (!vec[t]) count++; if (!count) { pkint(wp->wa_mesg, wxp->w_veclen); for (t = 0; t < wxp->w_veclen; t++) { tid = wxp->w_vec[t]; pkint(wp->wa_mesg, tid); if (TIDISTASK(tid) && wxp->w_trctid > 0) { tev_send_spntask( wxp->w_trctid, wxp->w_trcctx, wxp->w_trctag, tid, wxp->w_ptid ); } if (TIDISTASK(tid) && wxp->w_outtid > 0) { mp = mesg_new(0); mp->m_dst = wxp->w_outtid; mp->m_ctx = wxp->w_outctx; mp->m_tag = wxp->w_outtag; pkint(mp, tid); pkint(mp, TO_SPAWN); pkint(mp, wxp->w_ptid); sendmessage(mp); } } sendmessage(wp->wa_mesg); wp->wa_mesg = 0; free_wait_spawn(wxp); wp->wa_spec = 0; return 0; } /* * assign tasks to hosts */ nh = min(htp->ht_cnt, count); /* find first host to assign */ if (lasthh == -1) lasthh = hosts->ht_local + 1; if (lasthh > htp->ht_last) lasthh = 0; while (!htp->ht_hosts[lasthh]) if (++lasthh > htp->ht_last) lasthh = 1; hp = htp->ht_hosts[lasthh]; for (t = 0; t < veclen && vec[t]; t++); while (t < veclen) { /* pvmlogprintf("assign_tasks() %s <- %d\n", hp->hd_name, t); */ vec[t] = hp->hd_hostpart; na++; /* when enough tasks for this host, move to next */ if ((a += nh) >= count) { a -= count; wp2 = wait_new(WT_SPAWN); wp2->wa_tid = wp->wa_tid; wp2->wa_on = hp->hd_hostpart; wp2->wa_spec = wp->wa_spec; wp->wa_mesg->m_ref++; wp2->wa_mesg = wp->wa_mesg; LISTPUTBEFORE(wp, wp2, wa_peer, wa_rpeer); mp = mesg_new(0); pkint(mp, wxp->w_ptid); pkstr(mp, wxp->w_file); pkint(mp, wxp->w_flags); pkint(mp, na); pkint(mp, wxp->w_argc); for (i = 0; i < wxp->w_argc; i++) pkstr(mp, wxp->w_argv[i]); pkint(mp, wxp->w_outtid); pkint(mp, wxp->w_outctx); pkint(mp, wxp->w_outtag); pkint(mp, wxp->w_trctid); pkint(mp, wxp->w_trcctx); pkint(mp, wxp->w_trctag); pkint(mp, wxp->w_nenv); for (i = 0; i < wxp->w_nenv; i++) pkstr(mp, wxp->w_env[i]); pkint(mp, (t+1)-na); /* start proc location 0..count-1 */ pkint(mp, count); /* how many are there in total */ mp->m_dst = hp->hd_hostpart | TIDPVMD; mp->m_tag = DM_EXEC; mp->m_wid = wp2->wa_wid; do { if (++lasthh > htp->ht_last) lasthh = 1; } while (!htp->ht_hosts[lasthh]); sendmessage(mp); hp = htp->ht_hosts[lasthh]; na = 0; } for (t++ ; t < veclen && vec[t]; t++); } return 0; } /* tm_sendsig() * * Task sending a signal to another task. * * TM_SENDSIG * call { * int tid * int signum * } * ret { } */ int tm_sendsig(tp, mp) struct task *tp; struct pmsg *mp; { int tid; struct pmsg *mp2; if (upkuint(mp, &tid)) { pvmlogerror("tm_sendsig() bad msg format\n"); return 0; } if (!TIDISTASK(tid)) { pvmlogprintf("tm_sendsig() bad tid %x\n", tid); return 0; } mp2 = replymessage(mp); sendmessage(mp2); mp->m_ref++; mp->m_src = pvmmytid; mp->m_dst = (tid & TIDHOST) | TIDPVMD; mp->m_tag = DM_SENDSIG; mp->m_wid = 0; sendmessage(mp); return 0; } /* tm_config() * * Task wants machine configuration. * * TM_CONFIG * call { } * ret { * int nhosts * int narches * { * int tid * string name * string arch * int speed * int dsig * } [nhosts] * } */ int tm_config(tp, mp) struct task *tp; struct pmsg *mp; { int hh; struct hostd *hp; mp = replymessage(mp); pkint(mp, hosts->ht_cnt); pkint(mp, hosts->ht_narch); for (hh = 1; hh <= hosts->ht_last; hh++) { if (hp = hosts->ht_hosts[hh]) { pkint(mp, hp->hd_hostpart); pkstr(mp, hp->hd_name); pkstr(mp, hp->hd_arch ? hp->hd_arch : ""); pkint(mp, hp->hd_speed); pkint(mp, hp->hd_dsig); } } sendmessage(mp); return 0; } /* tm_halt() * * Command from task to stop master pvmd. * * TM_HALT * call { } * ret { } */ int tm_halt(tp, mp) struct task *tp; struct pmsg *mp; { mp = mesg_new(0); mp->m_tag = DM_HALT; mp->m_dst = hosts->ht_hosts[hosts->ht_master]->hd_hostpart | TIDPVMD; sendmessage(mp); return 0; } /* tm_task() * * Task wants a list of tasks. * If where is a host or task tid, give a list of matching tasks. * If where is zero, give all running tasks. * * TM_TASK * call { * int where * } * ret { * int errcode * { * int tid * int ptid * int hostpart * int flag * string a_out * int pid * } [count] // implied * } */ int tm_task(tp, mp) struct task *tp; struct pmsg *mp; { int where; struct pmsg *mp2; struct waitc *wp; struct waitc *wp2 = 0; /* master waitc of peer group */ int hh; struct hostd *hp; if (upkuint(mp, &where)) { pvmlogerror("tm_task() bad msg format\n"); return 0; } mp = replymessage(mp); mp->m_dst = tp->t_tid; mp->m_tag = TM_TASK; if (where) { /* specific host or task requested */ if (!(hp = tidtohost(hosts, where))) { pkint(mp, PvmNoHost); sendmessage(mp); return 0; } pkint(mp, 0); wp = wait_new(WT_TASK); wp->wa_mesg = mp; wp->wa_tid = tp->t_tid; wp->wa_on = hp->hd_hostpart; mp = mesg_new(0); mp->m_tag = DM_TASK; mp->m_dst = hp->hd_hostpart | TIDPVMD; mp->m_wid = wp->wa_wid; pkint(mp, where); sendmessage(mp); } else { /* all tasks requested */ pkint(mp, 0); wp2 = wait_new(WT_TASK); mp->m_ref++; wp2->wa_mesg = mp; wp2->wa_tid = tp->t_tid; mp2 = mesg_new(0); mp2->m_tag = DM_TASK; pkint(mp2, 0); for (hh = hosts->ht_last; hh > 0; hh--) { if (!hosts->ht_hosts[hh]) continue; wp = wait_new(WT_TASK); mp->m_ref++; wp->wa_mesg = mp; wp->wa_tid = tp->t_tid; wp->wa_on = hosts->ht_hosts[hh]->hd_hostpart; LISTPUTBEFORE(wp2, wp, wa_peer, wa_rpeer); mp2->m_dst = hosts->ht_hosts[hh]->hd_hostpart | TIDPVMD; mp2->m_wid = wp->wa_wid; mp2->m_ref++; sendmessage(mp2); } pmsg_unref(mp2); pmsg_unref(mp); /* send message if all waiters are in */ if (wp2->wa_peer == wp2) { mp->m_ref++; sendmessage(mp); } wait_delete(wp2); } return 0; } /* tm_tickle() * * Task wants to poke at pvmd. * * TM_TICKLE * call { * int nargs * int args[nargs] * } * ret { * int nresult * int results[nresult] * } */ int tm_tickle(tp, mp) struct task *tp; struct pmsg *mp; { int nar; int arg[10]; int i; char *p; struct hostd *hp; upkint(mp, &nar); if (nar < 1 || nar > 10) { pvmlogprintf("tm_tickle() bad msg format\n"); return 0; } for (i = 0; i < nar; i++) upkint(mp, &arg[i]); while (i < sizeof(arg)/sizeof(arg[0])) arg[i++] = 0; pvmlogprintf("tm_tickle() #"); for (i = 0; i < nar; i++) pvmlogprintf(" %d", arg[i]); pvmlogprintf("\n"); mp = replymessage(mp); switch (arg[0]) { case 0: i_dump(1); pkint(mp, 0); break; case 1: ht_dump(hosts); pkint(mp, 0); break; case 2: task_dump(); pkint(mp, 0); break; case 3: wait_dumpall(); pkint(mp, 0); break; case 4: mb_dumpall(); pkint(mp, 0); break; case 5: pkint(mp, 1); pkint(mp, pvmdebmask); break; case 6: pvmdebmask = arg[1]; pvmlogprintf("tm_tickle() debug mask is %x (%s)\n", pvmdebmask, debug_flags(pvmdebmask)); pkint(mp, 0); break; case 7: if (arg[1] > 0 && arg[1] < 50) { nopax = arg[1]; pvmlogprintf("tm_tickle() nopax is %d\n", nopax); } else pvmlogprintf("tm_tickle() bogus nopax %d\n", arg[1]); pkint(mp, 0); break; case 8: pkint(mp, 1); if ((hp = tidtohost(hosts, arg[1])) && hp != hosts->ht_hosts[hosts->ht_local]) { pvmlogprintf("tm_tickle() failing %s\n", hp->hd_name); hostfailentry(hp); ht_delete(hosts, hp); if (newhosts) ht_delete(newhosts, hp); pkint(mp, 1); } else { if (hp) pvmlogprintf("tm_tickle() can't fail %s\n", hp->hd_name); else pvmlogprintf("tm_tickle() no such host %x\n", arg[1]); pkint(mp, 0); } break; case 9: #ifdef STATISTICS dump_statistics(); if (arg[1]) reset_statistics(); #else pvmlogerror("tm_tickle() statistics not compiled in\n"); #endif pkint(mp, 0); break; case 100: #ifdef SHMEM peer_dump(); pidtid_dump(); #else pvmlogerror("tm_tickle() not using shared memory\n"); #endif pkint(mp, 0); break; case 20: { struct pmsg *mp2; int i, j; for (j = 0; j < arg[1]; j++) { mp2 = mesg_new(0); for (i = 0; i < 1000; i++) pkint(mp2, i); mp2->m_dst = arg[2]; mp2->m_tag = DM_NULL; sendmessage(mp2); } pkint(mp, 0); } break; default: pvmlogprintf("tm_tickle() don't know #%d\n", arg[0]); pkint(mp, 0); break; } sendmessage(mp); return 0; } /* tm_delhost() * * Task requesting to add hosts to virtual machine. Exit point is * here or dm_delhostack(). * * TM_DELHOST * call { * int nhosts * string names[nhosts] * } * ret { * int nhosts // or negative for error * int status[nhosts] // status of each host * } */ int tm_delhost(tp, mp) struct task *tp; struct pmsg *mp; { int count; char *buf; struct waitc *wp; /* sanity check the message */ if (upkint(mp, &count)) goto bad; if (count < 1 || count > (tidhmask >> (ffs(tidhmask) - 1))) goto bad; while (count-- > 0) if (upkstralloc(mp, &buf)) goto bad; else PVM_FREE(buf); /* make a wait channel for the task */ wp = wait_new(WT_DELHOST); wp->wa_tid = tp->t_tid; wp->wa_on = hosts->ht_hosts[hosts->ht_master]->hd_hostpart; wp->wa_mesg = replymessage(mp); /* forward message to master pvmd */ mp->m_ref++; mp->m_src = pvmmytid; mp->m_dst = hosts->ht_hosts[hosts->ht_master]->hd_hostpart | TIDPVMD; mp->m_tag = DM_DELHOST; mp->m_wid = wp->wa_wid; sendmessage(mp); return 0; bad: pvmlogprintf("tm_delhost() from t%x bad msg format\n", mp->m_src); return 0; } /* tm_mca() * * Task announces multicast address list for subsequent message. * * TM_MCA * call { * int count // number of addresses * int tids[count] // addresses * } * // No Return */ int tm_mca(tp, mp) struct task *tp; struct pmsg *mp; { struct mca *mcap; /* mca descriptor */ int ndst; /* num of dst tids */ int *dsts; /* dst tids */ int tid; int i, j; /* * unpack list of dst tids from message (expect it to be sorted). * discard tids to nonexistent foreign hosts. */ mcap = mca_new(); mcap->mc_tid = TIDGID | tp->t_tid; upkint(mp, &ndst); dsts = TALLOC(ndst, int, "dsts"); for ( i=0, j=0 ; i < ndst ; i++ ) { upkuint(mp, &tid); if ((tid & tidhmask) == myhostpart || tidtohost(hosts, tid)) dsts[j++] = tid; } ndst = j; if (ndst < 1) goto noguys; /* * send DM_MCA messages containing tids to destination hosts * make list of destination hosts for us */ mcap->mc_dsts = TALLOC(ndst, int, "mcal"); /* XXX cheat, too much space */ mcap->mc_ndst = 0; for (j = 0; j < ndst; ) { i = j; tid = dsts[i] & tidhmask; while (++j < ndst && tid == (dsts[j] & tidhmask)) ; mp = mesg_new(0); mp->m_dst = (tid |= TIDPVMD); mp->m_tag = DM_MCA; pkint(mp, mcap->mc_tid); pkint(mp, j - i); while (i < j) pkint(mp, dsts[i++]); sendmessage(mp); mcap->mc_dsts[mcap->mc_ndst++] = tid; } noguys: PVM_FREE(dsts); /* * tag task descriptor with mca desc and send mca back to task */ tp->t_mca = mcap; if (pvmdebmask & PDMMESSAGE) { pvmlogprintf("tm_mca() made mca %x for t%x\n", mcap->mc_tid, tp->t_tid); } return 0; } /* tm_notify() * * Task wants to be notified when an event happens. * * TM_NOTIFY * call { * int what // event type and flags * int ctx // message context to use in reply * int tag // message tag to use in reply * int count // number of addresses * int tids[count] // addresses * } * // No Return */ int tm_notify(tp, mp) struct task *tp; struct pmsg *mp; { int what, flags, ctx, tag, count, tid; struct hostd *hp; struct pmsg *mp2; struct waitc *wp; int i; if (upkint(mp, &what) || upkint(mp, &ctx) || upkint(mp, &tag) || upkint(mp, &count)) { pvmlogerror("tm_notify() bad msg format\n"); return 0; } flags = what; what &= 0xff; switch (what) { /* * TaskExit: make a wait context that hangs out until the task is * cleaned up. */ case PvmTaskExit: for (i = 0; i < count; i++) { if (upkuint(mp, &tid)) { pvmlogerror("tm_notify() bad msg format\n"); return 0; } if (flags & PvmNotifyCancel) { FORLIST (wp, waitlist, wa_link) if (wp->wa_kind == WT_TASKX && wp->wa_on == tid && wp->wa_tid == tp->t_tid && wp->wa_mesg->m_ctx == ctx && wp->wa_mesg->m_tag == tag) break; if (wp != waitlist) { sendmessage(wp->wa_mesg); wp->wa_mesg = 0; if ((hp = tidtohost(hosts, tid)) && hp->hd_hostpart != myhostpart) wp->wa_tid = 0; else wait_delete(wp); } } else { /* make reply message */ mp2 = mesg_new(0); mp2->m_dst = tp->t_tid; mp2->m_ctx = ctx; mp2->m_tag = tag; mp2->m_wid = mp->m_wid; pkint(mp2, tid); /* if task doesn't exist, reply immediately */ if (!(hp = tidtohost(hosts, tid)) || (hp->hd_hostpart == myhostpart && !task_find(tid))) sendmessage(mp2); else { /* otherwise make a wc for it */ wp = wait_new(WT_TASKX); wp->wa_on = tid; wp->wa_tid = tp->t_tid; wp->wa_dep = mp->m_wid; wp->wa_mesg = mp2; /* and if not on this host, pass on the request */ if (hp->hd_hostpart != myhostpart) { mp2 = mesg_new(0); pkint(mp2, what); pkint(mp2, tid); mp2->m_dst = hp->hd_hostpart | TIDPVMD; mp2->m_tag = DM_NOTIFY; mp2->m_wid = wp->wa_wid; sendmessage(mp2); } } } } break; case PvmHostDelete: for (i = 0; i < count; i++) { if (upkuint(mp, &tid)) { pvmlogerror("tm_notify() bad msg format\n"); return 0; } if (flags & PvmNotifyCancel) { if (hp = tidtohost(hosts, tid)) { FORLIST (wp, waitlist, wa_link) if (wp->wa_kind == WT_HOSTF && wp->wa_on == hp->hd_hostpart && wp->wa_tid == tp->t_tid && wp->wa_mesg->m_ctx == ctx && wp->wa_mesg->m_tag == tag) break; if (wp != waitlist) { sendmessage(wp->wa_mesg); wp->wa_mesg = 0; wait_delete(wp); } } } else { mp2 = mesg_new(0); mp2->m_dst = mp->m_src; mp2->m_ctx = ctx; mp2->m_tag = tag; pkint(mp2, tid); if (hp = tidtohost(hosts, tid)) { wp = wait_new(WT_HOSTF); wp->wa_tid = tp->t_tid; wp->wa_on = hp->hd_hostpart; wp->wa_mesg = mp2; } else { sendmessage(mp2); } } } break; case PvmHostAdd: FORLIST (wp, waitlist, wa_link) if (wp->wa_kind == WT_HOSTA && wp->wa_tid == tp->t_tid && wp->wa_mesg->m_ctx == ctx && wp->wa_mesg->m_tag == tag) break; /* if cancelling, delete possible existing waitc */ if (count == 0 || (flags & PvmNotifyCancel)) { if (wp != waitlist) wait_delete(wp); /* otherwise, update existing waitc or create new one */ } else { if (wp == waitlist) { wp = wait_new(WT_HOSTA); wp->wa_tid = tp->t_tid; wp->wa_on = tp->t_tid; wp->wa_mesg = mesg_new(0); wp->wa_mesg->m_dst = tp->t_tid; wp->wa_mesg->m_ctx = ctx; wp->wa_mesg->m_tag = tag; } wp->wa_count = count; } break; default: pvmlogprintf("tm_notify() unknown what=%d\n", what); break; } return 0; } /* tm_mstat() * * Task wants status of a host. * * TM_MSTAT * call { * string hostname * } * ret { * int status * } */ int tm_mstat(tp, mp) struct task *tp; struct pmsg *mp; { char *name; struct hostd *hp; struct waitc *wp; if (upkstralloc(mp, &name)) { pvmlogerror("tm_mstat() bad msg format\n"); return 0; } hp = nametohost(hosts, name); PVM_FREE(name); if (!hp) { mp = replymessage(mp); pkint(mp, PvmNoHost); sendmessage(mp); return 0; } wp = wait_new(WT_MSTAT); wp->wa_tid = tp->t_tid; wp->wa_on = hp->hd_hostpart; wp->wa_mesg = replymessage(mp); mp = mesg_new(0); mp->m_dst = hp->hd_hostpart | TIDPVMD; mp->m_tag = DM_PSTAT; mp->m_wid = wp->wa_wid; pkint(mp, hp->hd_hostpart | TIDPVMD); sendmessage(mp); return 0; } /* tm_db() * * Task wants a database op. * * TM_DB * call { * int opcode // insert, delete, lookup * string name * int index * int data // if 'insert' * } * ret { * int index // and status * int data // if 'lookup' * } */ int tm_db(tp, mp) struct task *tp; struct pmsg *mp; { struct waitc *wp; wp = wait_new(WT_DB); wp->wa_tid = tp->t_tid; wp->wa_on = hosts->ht_hosts[hosts->ht_master]->hd_hostpart; wp->wa_mesg = replymessage(mp); mp->m_ref++; mp->m_src = pvmmytid; mp->m_dst = hosts->ht_hosts[hosts->ht_master]->hd_hostpart | TIDPVMD; mp->m_tag = DM_DB; mp->m_wid = wp->wa_wid; sendmessage(mp); return 0; } /* tm_sched() * * Task wants to register as scheduler. * * TM_SCHED * call { * } * ret { * int oldschedtid * int tid // of master pvmd * string name * string arch * int speed * int dsig * } */ int tm_sched(tp, mp) struct task *tp; struct pmsg *mp; { struct pmsg *mp2; struct hostd *hp; mp2 = replymessage(mp); pkint(mp2, pvmschedtid); hp = hosts->ht_hosts[hosts->ht_master]; pkint(mp2, hp->hd_hostpart); pkstr(mp2, hp->hd_name); pkstr(mp2, hp->hd_arch ? hp->hd_arch : ""); pkint(mp2, hp->hd_speed); pkint(mp2, hp->hd_dsig); sendmessage(mp2); if (pvmdebmask & PDMSCHED) { pvmlogprintf("tm_sched() old t%x new t%x\n", pvmschedtid, tp->t_tid); } pvmschedtid = tp->t_tid; tp->t_flag |= TF_ISSCHED; return 0; } /* tm_tasker() * * Task registers as local task starter. * * TM_TASKER * call { * int regme // true to register, false to unregister * } * ret { * int code // 0 if okay, else error * } */ int tm_tasker(tp, mp) struct task *tp; struct pmsg *mp; { int regme; struct pmsg *mp2; if (upkint(mp, ®me)) { pvmlogerror("tm_tasker() bad msg format\n"); return 0; } mp2 = replymessage(mp); if (regme) { if (taskertid) { pkint(mp2, PvmAlready); } else { taskertid = tp->t_tid; tp->t_flag |= TF_ISTASKER; if (pvmdebmask & PDMTASK) { pvmlogprintf("tm_tasker() register t%x \n", tp->t_tid); } pkint(mp2, 0); } } else { if (taskertid == tp->t_tid) { taskertid = 0; tp->t_flag &= ~TF_ISTASKER; if (pvmdebmask & PDMTASK) { pvmlogprintf("tm_tasker() unregister t%x \n", tp->t_tid); } pkint(mp2, 0); } else { if (pvmdebmask & PDMTASK) { pvmlogprintf("tm_tasker() t%x tries to unregister?\n", tp->t_tid); } pkint(mp2, PvmNoTask); } } sendmessage(mp2); return 0; } /* tm_hoster() * * Task registers as slave pvmd starter. * * TM_HOSTER * int regme // true to register, false to unregister * call { * } * ret { * int code // 0 if okay, else error * } */ int tm_hoster(tp, mp) struct task *tp; struct pmsg *mp; { int regme; struct pmsg *mp2; if (upkint(mp, ®me)) { pvmlogerror("tm_hoster() bad msg format\n"); return 0; } mp2 = replymessage(mp); /* always wear 2 condoms, who knows if indices are enough... :) */ if (hosts->ht_hosts[hosts->ht_local]->hd_hostpart != hosts->ht_hosts[hosts->ht_master]->hd_hostpart) { pkint(mp2, PvmHostrNMstr); sendmessage(mp2); return 0; } if (regme) { if (hostertid) { pkint(mp2, PvmAlready); } else { hostertid = tp->t_tid; tp->t_flag |= TF_ISHOSTER; if (pvmdebmask & PDMSTARTUP) { pvmlogprintf("tm_hoster() register t%x \n", tp->t_tid); } pkint(mp2, 0); } } else { if (hostertid == tp->t_tid) { hostertid = 0; tp->t_flag &= ~TF_ISHOSTER; if (pvmdebmask & PDMSTARTUP) { pvmlogprintf("tm_hoster() unregister t%x \n", tp->t_tid); } pkint(mp2, 0); } else { if (pvmdebmask & PDMSTARTUP) { pvmlogprintf("tm_hoster() t%x tries to unregister?\n", tp->t_tid); } pkint(mp2, PvmNoTask); } } sendmessage(mp2); return 0; } /* tm_tracer() * * Task registers as task trace collector. * * TM_TRACER * call { * int regme // true to register, false to unregister * int tctx // if regme true, message ctxt for trace events * int ttag // if regme true, message tag for trace events * int octx // if regme true, message ctxt for output events * int otag // if regme true, message tag for output events * Pvmtmask tmask // if regme true, trace mask for tasks * int tbuf // if regme true, trace buffer size for tasks * int topt // if regme true, trace options for tasks * } * ret { * int code // 0 if okay, else error * } */ int tm_tracer(tp, mp) struct task *tp; struct pmsg *mp; { int regme; int tctx; int ttag; int octx; int otag; Pvmtmask tmask; int tbuf; int topt; struct pmsg *mp2; struct pmsg *mpd; int slconf; int hh; struct hostd *hp; char buf[512]; if (upkint(mp, ®me)) { pvmlogerror("tm_tracer() bad msg format\n"); return 0; } mp2 = replymessage(mp); slconf = 0; if (regme) { if (pvmtracer.trctid) { pkint(mp2, PvmAlready); } else { tp->t_flag |= TF_ISTRACER; upkint(mp, &tctx); upkint(mp, &ttag); upkint(mp, &octx); upkint(mp, &otag); upkstr(mp, tmask, TEV_MASK_LENGTH); upkint(mp, &tbuf); upkint(mp, &topt); pvmtracer.trctid = tp->t_tid; pvmtracer.trcctx = tctx; pvmtracer.trctag = ttag; pvmtracer.outtid = tp->t_tid; pvmtracer.outctx = octx; pvmtracer.outtag = otag; BCOPY(tmask,pvmtracer.tmask,TEV_MASK_LENGTH); pvmtracer.trcbuf = tbuf; pvmtracer.trcopt = topt; slconf++; if (pvmdebmask & PDMTRACE) { pvmlogprintf("tm_tracer() register t%x \n", tp->t_tid); } pkint(mp2, 0); } } else { if (pvmtracer.trctid == tp->t_tid) { tp->t_flag &= ~TF_ISTRACER; pvmtracer.trctid = 0; pvmtracer.trcctx = 0; pvmtracer.trctag = 0; pvmtracer.outtid = 0; pvmtracer.outctx = 0; pvmtracer.outtag = 0; TEV_MASK_INIT(pvmtracer.tmask); pvmtracer.trcbuf = 0; pvmtracer.trcopt = 0; slconf++; if (pvmdebmask & PDMTRACE) { pvmlogprintf("tm_tracer() unregister t%x \n", tp->t_tid); } pkint(mp2, 0); } else { if (pvmdebmask & PDMTRACE) { pvmlogprintf("tm_tracer() t%x tries to unregister?\n", tp->t_tid); } pkint(mp2, PvmNoTask); } } /* Update slave pvmds */ if ( slconf ) { for (hh = hosts->ht_last; hh > 0; hh--) { if (hp = hosts->ht_hosts[hh]) { mpd = mesg_new(0); mpd->m_tag = DM_SLCONF; mpd->m_dst = hp->hd_hostpart | TIDPVMD; pkint(mpd, DM_SLCONF_TRACE); sprintf(buf, "%x %d %d %x %d %d %d %d %s", pvmtracer.trctid, pvmtracer.trcctx, pvmtracer.trctag, pvmtracer.outtid, pvmtracer.outctx, pvmtracer.outtag, pvmtracer.trcbuf, pvmtracer.trcopt, pvmtracer.tmask); pkstr(mpd, buf); sendmessage(mpd); } } } /* Send response to requesting task */ sendmessage(mp2); return 0; } /* tm_hostsync() * * Task wants clock sample from host. * * TM_HOSTSYNC * call { * int where // pvmd tid * } * ret { * int status // 0 or error code * int sec // time of day clock * int usec * } */ int tm_hostsync(tp, mp) struct task *tp; struct pmsg *mp; { int where; struct hostd *hp; struct pmsg *mp2; struct waitc *wp; if (upkuint(mp, &where)) { pvmlogerror("tm_hostsync() bad msg format\n"); return 0; } mp2 = replymessage(mp); if (!(hp = tidtohost(hosts, where))) { pkint(mp2, PvmNoHost); sendmessage(mp2); return 0; } wp = wait_new(WT_HOSTSYNC); wp->wa_tid = mp->m_src; wp->wa_on = hp->hd_hostpart; wp->wa_mesg = mp2; mp2 = mesg_new(0); mp2->m_dst = where | TIDPVMD; mp2->m_tag = DM_HOSTSYNC; mp2->m_wid = wp->wa_wid; sendmessage(mp2); return 0; } /* tm_setopt() * * Set task parameters * * TM_SETOPT * call { * { * int what // which option * string value // option value * } [] // implied * } * ret { */ int tm_setopt(tp, mp) struct task *tp; struct pmsg *mp; { int what; char *val; int x; while (!upkint(mp, &what) && !upkstralloc(mp, &val)) { switch (what) { case TS_OUTTID: x = pvmxtoi(val); change_output(tp, x, tp->t_outctx, tp->t_outtag); break; case TS_OUTCTX: x = pvmxtoi(val); change_output(tp, tp->t_outtid, x, tp->t_outtag); break; case TS_OUTTAG: x = pvmxtoi(val); change_output(tp, tp->t_outtid, tp->t_outctx, x); break; case TS_TRCTID: x = pvmxtoi(val); change_trace(tp, x, tp->t_trcctx, tp->t_trctag); break; case TS_TRCCTX: x = pvmxtoi(val); change_trace(tp, tp->t_trctid, x, tp->t_trctag); break; case TS_TRCTAG: x = pvmxtoi(val); change_trace(tp, tp->t_trctid, tp->t_trcctx, x); break; default: pvmlogprintf("tm_setopt() ? option %d val <%s>\n", what, val); break; } if (val) PVM_FREE(val); } mp = replymessage(mp); sendmessage(mp); return 0; } /* change_output() * * Task sets its output sink parameters. * If new values are different we have to send close and open * messages, because the collector won't know what's going on. */ int change_output(tp, outtid, outctx, outtag) struct task *tp; int outtid, outctx, outtag; { struct pmsg *mp; if (tp->t_outtid != outtid || tp->t_outctx != outctx || tp->t_outtag != outtag) { if (tp->t_outtid > 0) { mp = mesg_new(0); mp->m_dst = tp->t_outtid; mp->m_ctx = tp->t_outctx; mp->m_tag = tp->t_outtag; pkint(mp, tp->t_tid); pkint(mp, TO_EOF); sendmessage(mp); } if (pvmdebmask & PDMTASK) { pvmlogprintf("t%x changes output from to \n", tp->t_tid, tp->t_outtid, tp->t_outctx, tp->t_outtag, outtid, outctx, outtag); } tp->t_outtid = outtid; tp->t_outctx = outctx; tp->t_outtag = outtag; if (tp->t_outtid > 0) { mp = mesg_new(0); mp->m_dst = tp->t_outtid; mp->m_ctx = tp->t_outctx; mp->m_tag = tp->t_outtag; pkint(mp, tp->t_tid); pkint(mp, TO_SPAWN); pkint(mp, tp->t_ptid); sendmessage(mp); mp = mesg_new(0); mp->m_dst = tp->t_outtid; mp->m_ctx = tp->t_outctx; mp->m_tag = tp->t_outtag; pkint(mp, tp->t_tid); pkint(mp, TO_NEW); pkint(mp, tp->t_ptid); sendmessage(mp); } } return 0; } /* tm_getopt() * * Connect message for shared memory apps to get trace & output parameters. * XXX hack, will be merged into something else in v3.4. * * TM_GETOPT * call { } * ret { * int tid // task tid * int ptid // parent tid * int outtid // output dst * int outctx * int outtag * int trctid // trace dst * int trcctx * int trctag * int udpmax * int nativecode * string inaddr * int schedtid // scheduler tid * } */ int tm_getopt(tp, mp) struct task *tp; struct pmsg *mp; { mp = replymessage(mp); pkint(mp, tp->t_tid); pkint(mp, tp->t_ptid); pkint(mp, tp->t_outtid); pkint(mp, tp->t_outctx); pkint(mp, tp->t_outtag); pkint(mp, tp->t_trctid); pkint(mp, tp->t_trcctx); pkint(mp, tp->t_trctag); pkint(mp, pvmudpmtu); pkint(mp, pvmmydsig); pkstr(mp, inadport_hex(&(hosts->ht_hosts[hosts->ht_local]->hd_sad))); pkint(mp, pvmschedtid); mp->m_flag |= MM_PRIO; /* set priority handling for this message */ sendmessage(mp); #if defined(SHMEM) /* now change connection to TF_SHMCONN and try send packets that have gathered in this tasks sendq */ tp->t_flag &= ~TF_PRESHMCONN; tp->t_flag |= TF_SHMCONN; shm_wrt_pkts(tp); /* write any waiting packets */ #endif return 0; } /* change_trace() * * Task sets its trace sink parameters. * If new values are different we have to send close and open * messages, because the collector won't know what's going on. */ int change_trace(tp, trctid, trcctx, trctag) struct task *tp; int trctid, trcctx, trctag; { struct pmsg *mp; if (tp->t_trctid != trctid || tp->t_trcctx != trcctx || tp->t_trctag != trctag) { if (tp->t_trctid > 0) { tev_send_endtask( tp->t_trctid, tp->t_trcctx, tp->t_trctag, tp->t_tid, tp->t_status, tp->t_utime.tv_sec, tp->t_utime.tv_usec, tp->t_stime.tv_sec, tp->t_stime.tv_usec ); } if (pvmdebmask & PDMTASK) { pvmlogprintf( "t%x changes trace from to \n", tp->t_tid, tp->t_trctid, tp->t_trcctx, tp->t_trctag, trctid, trcctx, trctag); } tp->t_trctid = trctid; tp->t_trcctx = trcctx; tp->t_trctag = trctag; if (tp->t_trctid > 0) { tev_send_spntask( tp->t_trctid, tp->t_trcctx, tp->t_trctag, tp->t_tid, tp->t_ptid ); tev_send_newtask( tp->t_trctid, tp->t_trcctx, tp->t_trctag, tp->t_tid, tp->t_ptid, 0 /* XXX lie */, tp->t_a_out ? tp->t_a_out : "" ); } } return 0; } /* tm_context() * * Assign task a communication context, or free one in use * * TM_CONTEXT * call { * int cid // to free, or zero if requesting one * } * ret { * int cid // new cid or status * } */ int tm_context(tp, mp) struct task *tp; struct pmsg *mp; { struct pmsg *mp2; struct ccon *cp; int cid; int cc; mp2 = replymessage(mp); if (upkuint(mp, &cid)) { cc = PvmBadParam; } else { if (cid == 0) { if (cp = ccon_new(tp)) cc = cp->c_cid; else cc = PvmOutOfRes; } else { cc = PvmNotFound; if (tp->t_ccs) { FORLIST (cp, tp->t_ccs, c_peer) { if (cp->c_cid == cid) { LISTDELETE(cp, c_link, c_rlink); LISTDELETE(cp, c_peer, c_rpeer); PVM_FREE(cp); cc = 0; break; } } } } } pkint(mp2, cc); sendmessage(mp2); return 0; } /* tm_shmconn() * * Task connecting to pvmd under the shmem system. * This is used to tie the task to the pvmd socket into the correct * task struct. This socket is a one-way only socket that is used * by the task to kick the daemon when the task has put a message * for it in its shared memory inbox segment. The socket is also * used to catch when the task dies.... * * There is no d-auth file checking. * Only data passed is the task's pid so we can match it with our * own table. * * TM_SHMCONN() * call { * int unixpid // real pid * } * ret { * } */ int tm_shmconn(tp, mp) struct task *tp; struct pmsg *mp; /* remember no return message */ { int tid; int pid; /* real pid of task */ int ppid; /* probable pid */ struct task *tp2; /* to search for real context */ struct pmsg *mp2; int cc; char c; int dummy_true = 1; /* not so harsh "always true"? */ if ( upkint( mp, &ppid ) ) { pvmlogerror( "tm_shmconn() bad msg format. Missing Unix pid??\n" ); goto bail; } #ifndef SHMEM if ( dummy_true ) { pvmlogerror( "tm_shmconn() shmem conn on non shmem sys? " ); pvmlogerror( "Bit bucket...\n" ); goto bail; } #endif /* * Task should already have a correct task struct. * Because TM_SHMCONN is passed after the shmem connect phase * in pvmbeatask() in lpvmshmem.c */ if ( tp2 = task_findpid( ppid ) ) { if ( pvmdebmask & PDMTASK ) { pvmlogprintf( "tm_shmconn() reconnect task t%x via sockets\n", tp2->t_tid); } /* tp->t_sched = tp2->t_sched; */ } else { pvmlogerror( "tm_shmconn() conn from non shmem connd task?\n"); goto bail; } /* * tp2 is now the real task.... * So we now update it with the correct socket descripter and then * mark the shadow one as dead. * */ tp2->t_sock = tp->t_sock; tp->t_sock = -1; /* tp will be freed by loclinput() */ tp->t_rxp = 0; tp->t_flag |= TF_CLOSE; /* stop work() complaining - dead socket? */ /* * kick it in the butt; it's ready to go */ /* We are happy to mark it as a shared memory connected process */ /* i.e. please use shmem (mpp_output) not my socket to talk to me */ /* the PRESHMCONN flag indicates that messages with MM_PRIO can be sent over shared memory, but no others. tm_getopt will set the flag to SHMCONN */ tp2->t_flag |= TF_PRESHMCONN; return 0; bail: /* i.e. kill it! */ tp->t_sock = -1; /* tp will be freed by loclinput() */ tp->t_rxp = 0; tp->t_flag |= TF_CLOSE; return 0; } ./pvm3/src/tev.c0100644007401100000360000005533407240353457012654 0ustar kohlgopher static char rcsid[] = "$Id: tev.c,v 1.10 2001/02/07 23:15:59 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * tev.c * * Tracing routines. * */ #include #include #if defined(WIN32) || defined(CYGWIN) #include "..\xdr\types.h" #include "..\xdr\xdr.h" #else #include #include #endif #ifdef SYSVSTR #include #else #include #endif #include "pmsg.h" #include "tvdefs.h" #include "lpvm.h" #include #include "tevmac.h" #include "global.h" /*************** ** Globals ** ** ** ***************/ struct pmsg *midtobuf(); /*************** ** Private ** ** ** ***************/ /* "High Performance" Direct Packing Guts Macros :-) */ #define PACK_BYTE( _vp, _cnt, _std ) \ (pvmtrcmp->m_codef->enc_byte) \ ( pvmtrcmp, (void *) _vp, _cnt, _std, 1 ) #define PACK_CPLX( _vp, _cnt, _std ) \ (pvmtrcmp->m_codef->enc_cplx) \ ( pvmtrcmp, (void *) _vp, _cnt, _std, sizeof(float) * 2 ) #define PACK_DCPLX( _vp, _cnt, _std ) \ (pvmtrcmp->m_codef->enc_dcplx) \ ( pvmtrcmp, (void *) _vp, _cnt, _std, sizeof(double) * 2 ) #define PACK_DOUBLE( _vp, _cnt, _std ) \ (pvmtrcmp->m_codef->enc_double) \ ( pvmtrcmp, (void *) _vp, _cnt, _std, sizeof(double) ) #define PACK_FLOAT( _vp, _cnt, _std ) \ (pvmtrcmp->m_codef->enc_float) \ ( pvmtrcmp, (void *) _vp, _cnt, _std, sizeof(float) ) #define PACK_INT( _vp, _cnt, _std ) \ (pvmtrcmp->m_codef->enc_int) \ ( pvmtrcmp, (void *) _vp, _cnt, _std, sizeof(int) ) #define PACK_UINT( _vp, _cnt, _std ) \ (pvmtrcmp->m_codef->enc_int) \ ( pvmtrcmp, (void *) _vp, _cnt, _std, sizeof(int) ) #define PACK_LONG( _vp, _cnt, _std ) \ (pvmtrcmp->m_codef->enc_long) \ ( pvmtrcmp, (void *) _vp, _cnt, _std, sizeof(long) ) #define PACK_ULONG( _vp, _cnt, _std ) \ (pvmtrcmp->m_codef->enc_long) \ ( pvmtrcmp, (void *) _vp, _cnt, _std, sizeof(long) ) #define PACK_SHORT( _vp, _cnt, _std ) \ (pvmtrcmp->m_codef->enc_short) \ ( pvmtrcmp, (void *) _vp, _cnt, _std, sizeof(short) ) #define PACK_USHORT( _vp, _cnt, _std ) \ (pvmtrcmp->m_codef->enc_short) \ ( pvmtrcmp, (void *) _vp, _cnt, _std, sizeof(short) ) #define PACK_STRING( _vp ) \ ( pvmtrctmp = strlen( _vp ) + 1, \ (pvmtrcmp->m_codef->enc_int) \ ( pvmtrcmp, (void *) &pvmtrctmp, 1, 1, sizeof(int) ), \ (pvmtrcmp->m_codef->enc_byte) \ ( pvmtrcmp, (void *) _vp, pvmtrctmp, 1, 1 ) ) /* Trace Event Data Packing Routines - Descriptor */ static int tev_pack_byte_desc( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int type; int cc; if ( (cc = PACK_INT( &did, 1, 1 )) ) return( cc ); type = TEV_DATA_BYTE | array; if ( (cc = PACK_INT( &type, 1, 1 )) ) return( cc ); if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_BYTE( datap, cnt, std ) ); } static int tev_pack_cplx_desc( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int type; int cc; if ( (cc = PACK_INT( &did, 1, 1 )) ) return( cc ); type = TEV_DATA_CPLX | array; if ( (cc = PACK_INT( &type, 1, 1 )) ) return( cc ); if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_CPLX( datap, cnt, std ) ); } static int tev_pack_dcplx_desc( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int type; int cc; if ( (cc = PACK_INT( &did, 1, 1 )) ) return( cc ); type = TEV_DATA_DCPLX | array; if ( (cc = PACK_INT( &type, 1, 1 )) ) return( cc ); if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_DCPLX( datap, cnt, std ) ); } static int tev_pack_double_desc( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int type; int cc; if ( (cc = PACK_INT( &did, 1, 1 )) ) return( cc ); type = TEV_DATA_DOUBLE | array; if ( (cc = PACK_INT( &type, 1, 1 )) ) return( cc ); if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_DOUBLE( datap, cnt, std ) ); } static int tev_pack_float_desc( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int type; int cc; if ( (cc = PACK_INT( &did, 1, 1 )) ) return( cc ); type = TEV_DATA_FLOAT | array; if ( (cc = PACK_INT( &type, 1, 1 )) ) return( cc ); if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_FLOAT( datap, cnt, std ) ); } static int tev_pack_int_desc( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int type; int cc; if ( (cc = PACK_INT( &did, 1, 1 )) ) return( cc ); type = TEV_DATA_INT | array; if ( (cc = PACK_INT( &type, 1, 1 )) ) return( cc ); if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_INT( datap, cnt, std ) ); } static int tev_pack_uint_desc( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int type; int cc; if ( (cc = PACK_INT( &did, 1, 1 )) ) return( cc ); type = TEV_DATA_UINT | array; if ( (cc = PACK_INT( &type, 1, 1 )) ) return( cc ); if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_UINT( datap, cnt, std ) ); } static int tev_pack_long_desc( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int type; int cc; if ( (cc = PACK_INT( &did, 1, 1 )) ) return( cc ); type = TEV_DATA_LONG | array; if ( (cc = PACK_INT( &type, 1, 1 )) ) return( cc ); if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_LONG( datap, cnt, std ) ); } static int tev_pack_ulong_desc( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int type; int cc; if ( (cc = PACK_INT( &did, 1, 1 )) ) return( cc ); type = TEV_DATA_ULONG | array; if ( (cc = PACK_INT( &type, 1, 1 )) ) return( cc ); if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_ULONG( datap, cnt, std ) ); } static int tev_pack_short_desc( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int type; int cc; if ( (cc = PACK_INT( &did, 1, 1 )) ) return( cc ); type = TEV_DATA_SHORT | array; if ( (cc = PACK_INT( &type, 1, 1 )) ) return( cc ); if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_SHORT( datap, cnt, std ) ); } static int tev_pack_ushort_desc( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int type; int cc; if ( (cc = PACK_INT( &did, 1, 1 )) ) return( cc ); type = TEV_DATA_USHORT | array; if ( (cc = PACK_INT( &type, 1, 1 )) ) return( cc ); if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_USHORT( datap, cnt, std ) ); } static int tev_pack_string_desc( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int type; int num; int cc; int i; if ( (cc = PACK_INT( &did, 1, 1 )) ) return( cc ); type = TEV_DATA_STRING | array; if ( (cc = PACK_INT( &type, 1, 1 )) ) return( cc ); if ( array == TEV_DATA_ARRAY ) { if ( std <= 0 ) return( PvmBadParam ); num = ( cnt + ( std - 1 ) ) / std; if ( (cc = PACK_INT( &num, 1, 1 )) ) return( cc ); for ( i=0 ; i < cnt ; i += std ) if ( (cc = PACK_STRING( ((char **) datap)[i] )) ) return( cc ); return( 0 ); } else return( PACK_STRING( (char *) datap ) ); } /* Trace Event Data Packing Routines - Raw */ static int tev_pack_byte_raw( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int cc; if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_BYTE( datap, cnt, std ) ); } static int tev_pack_cplx_raw( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int cc; if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_CPLX( datap, cnt, std ) ); } static int tev_pack_dcplx_raw( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int cc; if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_DCPLX( datap, cnt, std ) ); } static int tev_pack_double_raw( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int cc; if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_DOUBLE( datap, cnt, std ) ); } static int tev_pack_float_raw( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int cc; if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_FLOAT( datap, cnt, std ) ); } static int tev_pack_int_raw( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int cc; if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_INT( datap, cnt, std ) ); } static int tev_pack_uint_raw( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int cc; if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_UINT( datap, cnt, std ) ); } static int tev_pack_long_raw( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int cc; if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_LONG( datap, cnt, std ) ); } static int tev_pack_ulong_raw( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int cc; if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_ULONG( datap, cnt, std ) ); } static int tev_pack_short_raw( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int cc; if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_SHORT( datap, cnt, std ) ); } static int tev_pack_ushort_raw( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int cc; if ( array == TEV_DATA_ARRAY ) { if ( (cc = PACK_INT( &cnt, 1, 1 )) ) return( cc ); } return( PACK_USHORT( datap, cnt, std ) ); } static int tev_pack_string_raw( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { int num; int cc; int i; if ( array == TEV_DATA_ARRAY ) { if ( std <= 0 ) return( PvmBadParam ); num = ( cnt + ( std - 1 ) ) / std; if ( (cc = PACK_INT( &num, 1, 1 )) ) return( cc ); for ( i=0 ; i < cnt ; i += std ) if ( (cc = PACK_STRING( ((char **) datap)[i] )) ) return( cc ); return( 0 ); } else return( PACK_STRING( (char *) datap ) ); } /* ARGSUSED */ static int tev_pack_nop( did, array, datap, cnt, std ) int did; int array; void *datap; int cnt; int std; { return( 0 ); } /* Trace Descriptor Packing Vector */ static struct pvmtrcencvec pvmtrccodef_desc = { tev_pack_byte_desc, tev_pack_cplx_desc, tev_pack_dcplx_desc, tev_pack_double_desc, tev_pack_float_desc, tev_pack_int_desc, tev_pack_uint_desc, tev_pack_long_desc, tev_pack_ulong_desc, tev_pack_short_desc, tev_pack_ushort_desc, tev_pack_string_desc }; /* Trace Raw Packing Vector */ static struct pvmtrcencvec pvmtrccodef_raw = { tev_pack_byte_raw, tev_pack_cplx_raw, tev_pack_dcplx_raw, tev_pack_double_raw, tev_pack_float_raw, tev_pack_int_raw, tev_pack_uint_raw, tev_pack_long_raw, tev_pack_ulong_raw, tev_pack_short_raw, tev_pack_ushort_raw, tev_pack_string_raw }; /* Trace NOP Packing Vector */ static struct pvmtrcencvec pvmtrccodef_nop = { tev_pack_nop, tev_pack_nop, tev_pack_nop, tev_pack_nop, tev_pack_nop, tev_pack_nop, tev_pack_nop, tev_pack_nop, tev_pack_nop, tev_pack_nop, tev_pack_nop, tev_pack_nop }; /* * tev_init() * * Initialize Trace Status Vector. */ void tev_init() { int i; if ( pvmtrc.trctid > 0 && pvmmytid != pvmtrc.trctid ) { /* Reset Trace Descriptor Counts */ for ( i=TEV_FIRST ; i <= TEV_MAX ; i++ ) { pvmtevinfo[i].desc_status = 0; pvmtevinfo[i].mark.tv_sec = pvmtevinfo[i].mark.tv_usec = 0; pvmtevinfo[i].total.tv_sec = pvmtevinfo[i].total.tv_usec = 0; pvmtevinfo[i].count = 0; } } } /* * tev_begin() * * Trace Event Begin - create message, pack header */ int tev_begin( kind, entry_exit ) int kind; int entry_exit; { struct timeval timestamp; int tsec, tusec; int newbuffer; int tmp; /* Get Timestamp */ if ( pvmtrc.trcopt != PvmTraceCount ) { gettimeofday( ×tamp, (struct timezone *) 0 ); tsec = (int) timestamp.tv_sec; tusec = (int) timestamp.tv_usec; } switch ( pvmtrc.trcopt ) { case PvmTraceFull: { /* Check for Descriptor Dump (one each, begin/end events) */ if ( !( (pvmtevinfo[ kind - TEV_FIRST ].desc_status) & entry_exit ) ) { pvmtevinfo[ kind - TEV_FIRST ].desc_status |= entry_exit; /* Set Trace Event Packing Vector */ pvmtrccodef = &pvmtrccodef_desc; /* Set Descriptor Mode */ pvmtrcdesc = 1; } /* Set Regular Trace Event Packing & Mode */ else { pvmtrccodef = &pvmtrccodef_raw; pvmtrcdesc = 0; } /* Initialize Trace Event Message Buffer? */ newbuffer = 0; if ( !pvmtrcsbf ) { pvmtrcsbf = pvm_mkbuf( PvmDataDefault ); pvmtrcmp = midtobuf( pvmtrcsbf ); newbuffer++; } /* Select Trace Event Buffer (save current) */ pvmtrcsbfsave = pvm_setsbuf( pvmtrcsbf ); /* Pack Event Buffer Marker */ if ( newbuffer && pvmtrc.trcbuf ) { tmp = TEV_MARK_EVENT_BUFFER; pvm_pkint( &tmp, 1, 1 ); } /* Descriptor Header */ if ( pvmtrcdesc ) { /* Pack Event Marker */ tmp = TEV_MARK_EVENT_DESC; pvm_pkint( &tmp, 1, 1 ); /* Pack Descriptor Event ID & Event Name */ tmp = kind | entry_exit; pvm_pkint( &tmp, 1, 1 ); pvm_pkstr( pvmtevinfo[ kind - TEV_FIRST ].name ); } /* Regular Header */ else { /* Pack Event Marker */ tmp = TEV_MARK_EVENT_RECORD; pvm_pkint( &tmp, 1, 1 ); /* Pack Event ID */ tmp = kind | entry_exit; pvm_pkint( &tmp, 1, 1 ); } /* Pack Event Header */ TEV_PACK_INT( TEV_DID_TS, TEV_DATA_SCALAR, &tsec, 1, 1 ); TEV_PACK_INT( TEV_DID_TU, TEV_DATA_SCALAR, &tusec, 1, 1 ); TEV_PACK_INT( TEV_DID_TID, TEV_DATA_SCALAR, &pvmmytid, 1, 1 ); break; } case PvmTraceTime: pvmtrccodef = &pvmtrccodef_nop; pvmtevinfo[ kind - TEV_FIRST ].mark = timestamp; pvmtrcsavekind = kind; break; case PvmTraceCount: pvmtrccodef = &pvmtrccodef_nop; pvmtrcsavekind = kind; break; default: pvmlogprintf( "Uh-Oh! Bogus Tracing Option (%d) in tev_begin()...\n", pvmtrc.trcopt ); pvmtrccodef = &pvmtrccodef_nop; break; } return( 1 ); } /* * tev_fin() * * Trace Event End - send message (check trace buffering) */ int tev_fin() { struct timeval timestamp; int flush; int size; int tmp; switch ( pvmtrc.trcopt ) { case PvmTraceFull: { /* Pack End of Event Descriptor Marker */ if ( pvmtrcdesc ) { tmp = TEV_MARK_EVENT_DESC_END; pvm_pkint( &tmp, 1, 1 ); } /* Pack End of Event Marker */ else { tmp = TEV_MARK_EVENT_RECORD_END; pvm_pkint( &tmp, 1, 1 ); } /* Reset Send Buffer (Done Packing Stuff) */ pvm_setsbuf( pvmtrcsbfsave ); pvmtrcsbfsave = 0; /* Check for Trace Message Send */ /* (pvmtrc.trcbuf == 0 means no buffering) */ flush = 0; if ( !pvmtrc.trcbuf ) flush++; else { if ( pvm_bufinfo( pvmtrcsbf, &size, (int *) NULL, (int *) NULL ) ) { pvmlogerror( "tev_fin() error - get trace buffer size\n" ); size = -1; } if ( size >= pvmtrc.trcbuf ) flush++; } if ( flush ) tev_flush( 1 ); break; } case PvmTraceTime: gettimeofday( ×tamp, (struct timezone *) 0 ); TVXSUBY( &(pvmtevinfo[ pvmtrcsavekind - TEV_FIRST ].total), ×tamp, &(pvmtevinfo[ pvmtrcsavekind - TEV_FIRST ].mark) ); (pvmtevinfo[ pvmtrcsavekind - TEV_FIRST ].count)++; break; case PvmTraceCount: (pvmtevinfo[ pvmtrcsavekind - TEV_FIRST ].count)++; break; default: pvmlogprintf( "Uh-Oh! Bogus Tracing Option (%d) in tev_fin()...\n", pvmtrc.trcopt ); break; } return( 1 ); } /* * tev_flush( setflag ) * * setflag - indicates whether current send buffer is * already the trace buffer (0), or whether it needs * to be set (1). * * Trace Event Flush - send message, flush any trace buffer */ void tev_flush( setflag ) int setflag; { char *event_names[ TEV_MAX - TEV_FIRST + 1 ]; int timings_usec[ TEV_MAX - TEV_FIRST + 1 ]; int timings_sec[ TEV_MAX - TEV_FIRST + 1 ]; int counts[ TEV_MAX - TEV_FIRST + 1 ]; struct timeval timestamp; int tsec, tusec; int routetmp; int savebuf; int tmpbuf; int num; int tmp; int i; if ( pvmtrc.trctid <= 0 || pvmmytid == pvmtrc.trctid ) return; switch ( pvmtrc.trcopt ) { case PvmTraceFull: { if ( setflag ) { /* Verify Trace Record Message Buffer */ if ( !pvmtrcsbf ) return; /* Set Send Buffer */ savebuf = pvm_setsbuf( pvmtrcsbf ); } /* Pack End of Event Buffer Marker */ /* (pvmtrcbuf == 0 means no buffering) */ if ( pvmtrc.trcbuf ) { tmp = TEV_MARK_EVENT_BUFFER_END; pvm_pkint( &tmp, 1, 1 ); } break; } case PvmTraceTime: { /* Set Up Send Buffer */ pvmtrccodef = &pvmtrccodef_desc; pvmtrcsbf = pvm_mkbuf( PvmDataDefault ); pvmtrcmp = midtobuf( pvmtrcsbf ); savebuf = pvm_setsbuf( pvmtrcsbf ); /* Pack Event Marker */ tmp = TEV_MARK_EVENT_DESC; pvm_pkint( &tmp, 1, 1 ); /* Pack Descriptor Event ID & Event Name */ tmp = TEV_TIMING; pvm_pkint( &tmp, 1, 1 ); pvm_pkstr( pvmtevinfo[ TEV_TIMING - TEV_FIRST ].name ); /* Pack Event Header */ gettimeofday( ×tamp, (struct timezone *) 0 ); tsec = (int) timestamp.tv_sec; tusec = (int) timestamp.tv_usec; TEV_PACK_INT( TEV_DID_TS, TEV_DATA_SCALAR, &tsec, 1, 1 ); TEV_PACK_INT( TEV_DID_TU, TEV_DATA_SCALAR, &tusec, 1, 1 ); TEV_PACK_INT( TEV_DID_TID, TEV_DATA_SCALAR, &pvmmytid, 1, 1 ); /* Collect Timing Array */ num = 0; for ( i=TEV_FIRST ; i <= TEV_MAX ; i++ ) { if ( pvmtevinfo[i].count > 0 ) { event_names[num] = pvmtevinfo[i].name; timings_sec[num] = (int) pvmtevinfo[i].total.tv_sec; timings_usec[num] = (int) pvmtevinfo[i].total.tv_usec; counts[num] = pvmtevinfo[i].count; pvmtevinfo[i].total.tv_sec = pvmtevinfo[i].total.tv_usec = 0; pvmtevinfo[i].count = 0; num++; } } /* Pack Number of Events & Arrays */ TEV_PACK_INT( TEV_DID_VCT, TEV_DATA_SCALAR, &num, 1, 1 ); TEV_PACK_STRING( TEV_DID_VID, TEV_DATA_ARRAY, event_names, num, 1 ); TEV_PACK_INT( TEV_DID_TGS, TEV_DATA_ARRAY, timings_sec, num, 1 ); TEV_PACK_INT( TEV_DID_TGU, TEV_DATA_ARRAY, timings_usec, num, 1 ); TEV_PACK_INT( TEV_DID_PRF, TEV_DATA_ARRAY, counts, num, 1 ); /* Pack End of Descriptor Marker */ tmp = TEV_MARK_EVENT_DESC_END; pvm_pkint( &tmp, 1, 1 ); setflag = 1; break; } case PvmTraceCount: { /* Set Up Send Buffer */ pvmtrccodef = &pvmtrccodef_desc; pvmtrcsbf = pvm_mkbuf( PvmDataDefault ); pvmtrcmp = midtobuf( pvmtrcsbf ); savebuf = pvm_setsbuf( pvmtrcsbf ); /* Pack Event Marker */ tmp = TEV_MARK_EVENT_DESC; pvm_pkint( &tmp, 1, 1 ); /* Pack Descriptor Event ID & Event Name */ tmp = TEV_PROFILING; pvm_pkint( &tmp, 1, 1 ); pvm_pkstr( pvmtevinfo[ TEV_PROFILING - TEV_FIRST ].name ); /* Pack Event Header */ gettimeofday( ×tamp, (struct timezone *) 0 ); tsec = (int) timestamp.tv_sec; tusec = (int) timestamp.tv_usec; TEV_PACK_INT( TEV_DID_TS, TEV_DATA_SCALAR, &tsec, 1, 1 ); TEV_PACK_INT( TEV_DID_TU, TEV_DATA_SCALAR, &tusec, 1, 1 ); TEV_PACK_INT( TEV_DID_TID, TEV_DATA_SCALAR, &pvmmytid, 1, 1 ); /* Collect Profiling Array */ num = 0; for ( i=TEV_FIRST ; i <= TEV_MAX ; i++ ) { if ( pvmtevinfo[i].count > 0 ) { event_names[num] = pvmtevinfo[i].name; counts[num] = pvmtevinfo[i].count; pvmtevinfo[i].count = 0; num++; } } /* Pack Number of Events & Arrays */ TEV_PACK_INT( TEV_DID_VCT, TEV_DATA_SCALAR, &num, 1, 1 ); TEV_PACK_STRING( TEV_DID_VID, TEV_DATA_ARRAY, event_names, num, 1 ); TEV_PACK_INT( TEV_DID_PRF, TEV_DATA_ARRAY, counts, num, 1 ); /* Pack End of Descriptor Marker */ tmp = TEV_MARK_EVENT_DESC_END; pvm_pkint( &tmp, 1, 1 ); setflag = 1; break; } default: pvmlogprintf( "Uh-Oh! Bogus Tracing Option (%d) in tev_flush()...\n", pvmtrc.trcopt ); return; } /* Reset Send Buffer (Done Packing Stuff) */ if ( setflag ) pvm_setsbuf( savebuf ); /* Clear Out Trace Buffer Global Before Entering mroute()... */ /* (save in tmpbuf for sending, needed for mhf_invoke event) */ tmpbuf = pvmtrcsbf; pvmtrcsbf = 0; /* Send Message */ if ( (routetmp = pvmrouteopt) == PvmRouteDirect ) pvmrouteopt = PvmAllowDirect; pvmtrcmp->m_ctx = pvmtrc.trcctx; mroute( tmpbuf, pvmtrc.trctid, pvmtrc.trctag, &pvmtrcztv ); pvmrouteopt = routetmp; /* Clean-up */ pvm_freebuf( tmpbuf ); } /* * tev_do_trace() * * Export TEV_DO_TRACE() so user code doesn't have to import * masks and trace tid, etc. */ int tev_do_trace( kind, entry_exit ) int kind; int entry_exit; { TEV_DECLS return( TEV_DO_TRACE( kind, entry_exit ) ); } ./pvm3/src/waitc.c0100644007401100000360000002074007240353460013150 0ustar kohlgopher static char rcsid[] = "$Id: waitc.c,v 1.10 2001/02/07 23:16:00 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * waitc.c * * Wait context descriptors. * * $Log: waitc.c,v $ * Revision 1.10 2001/02/07 23:16:00 pvmsrc * 2nd Half of CYGWIN Check-ins... * (Spanker=kohl) * * Revision 1.9 2000/02/16 22:00:32 pvmsrc * Fixed up #include stuff... * - use for IMA_TITN... * - #include before any NEEDMENDIAN #includes... * (Spanker=kohl) * * Revision 1.8 1999/07/08 19:00:18 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.7 1998/11/20 20:04:19 pvmsrc * Changes so that win32 will compile & build. Also, common * Changes so that compiles & builds on NT. Also * common source on win32 & unix. * (Spanker=sscott) * * Revision 1.6 1997/06/27 17:32:59 pvmsrc * Updated for WIN32 header files & Authors. * * Revision 1.5 1997/03/06 21:50:24 pvmsrc * Yanked out #includes for and . * - dups with lpvm.h #includes... * * Revision 1.4 1997/01/28 19:27:52 pvmsrc * New Copyright Notice & Authors. * * Revision 1.3 1996/10/25 13:58:10 pvmsrc * Replaced old #includes for protocol headers: * - , "ddpro.h", "tdpro.h" * With #include of new combined header: * - * * Revision 1.2 1996/10/24 21:18:31 pvmsrc * Moved #include "global.h" to end of #include's for typing. * Added #include of new "lpvm.h" in place of explicitly extern-ed * globals... * * Revision 1.1 1996/09/23 23:44:47 pvmsrc * Initial revision * * Revision 1.6 1995/11/02 16:36:44 manchek * added NEEDSENDIAN switch * * Revision 1.5 1995/07/28 16:04:07 manchek * switch endian includes on flag, not arch name * * Revision 1.4 1995/07/19 21:27:33 manchek * use new function pvmnametag instead of [dts]mname * * Revision 1.3 1994/07/18 19:25:18 manchek * wait_get() checks hostpart, ignoring TIDPVMD. * added create/free logging * * Revision 1.2 1994/06/03 20:38:32 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:26:52 manchek * Initial revision * */ #include #ifdef IMA_TITN #include #else #include #endif #ifdef NEEDMENDIAN #include #endif #ifdef NEEDENDIAN #include #endif #ifdef NEEDSENDIAN #include #endif #include #if defined(WIN32) || defined(CYGWIN) #include "..\xdr\types.h" #include "..\xdr\xdr.h" #else #include #include #endif #ifndef WIN32 #include #include #endif #ifdef SYSVSTR #include #else #include #endif #include #include "pvmalloc.h" #include "pmsg.h" #include "listmac.h" #include "bfunc.h" #include "lpvm.h" #include "host.h" #include "waitc.h" #include "global.h" /*************** ** Globals ** ** ** ***************/ extern void pvmbailout(); char *pvmnametag(); /*************** ** Private ** ** ** ***************/ static int widbase = 0; static int widrange = ~0; static char *waitnames[] = { "addhost", "spawn", "hoststart", "task", "delhost", "htupd", "pstat", "taskx", "mstat", "db", "hostf", "hosta", "hostsync", "taskstart", "routea", "routed" }; static char * waitkind(kind) int kind; { if (kind < 1 || kind > sizeof(waitnames)/sizeof(waitnames[0])) return "???"; return waitnames[kind - 1]; } /***************** ** Interface ** ** ** *****************/ /* wait_init() * * Call this boy before any other wait stuff. */ void wait_init(base, range) int base; /* base value for wait context ids */ int range; /* mask for id generation */ { if (!waitlist) { widbase = base; widrange = range; waitlist = TALLOC(1, struct waitc, "wait"); BZERO((char*)waitlist, sizeof(struct waitc)); waitlist->wa_link = waitlist; waitlist->wa_rlink = waitlist; } } /* wait_new() * * Create new wait context of given kind with no peers. Add to * active list. */ struct waitc * wait_new(kind) int kind; { static int lastwid = 0; /* last wid assigned */ int startwid; /* to detect when we've tried all */ int wid; struct waitc *wp, *wp2; /* * find a unique wid by incrementing lastwid and stepping through * waitlist until we find a vacant slot. */ if (++lastwid > widrange) lastwid = 1; startwid = lastwid; wp = waitlist; while (1) { wid = widbase + lastwid; while (wp->wa_wid < wid) if ((wp = wp->wa_link) == waitlist) break; if (wp->wa_wid != wid) break; if (++lastwid > widrange) { lastwid = 1; wp = waitlist; } if (lastwid == startwid) { pvmlogprintf("wait_new() out of wids\n"); pvmbailout(0); /* XXX this is kinda harsh */ } } /* * initialze new w context and add to list */ if (!(wp2 = TALLOC(1, struct waitc, "wait"))) { pvmlogprintf("wait_new() can't get memory\n"); pvmbailout(0); } wp2->wa_wid = wid; wp2->wa_kind = kind; wp2->wa_peer = wp2->wa_rpeer = wp2; wp2->wa_on = wp2->wa_tid = wp2->wa_dep = 0; wp2->wa_mesg = 0; wp2->wa_count = 0; wp2->wa_spec = 0; LISTPUTBEFORE(wp, wp2, wa_link, wa_rlink); if (pvmdebmask & PDMWAITC) { pvmlogprintf("wait_new():\n"); wait_dump(wp2); } return wp2; } /* wait_find() * * Find a wait context in active list by id. Returns pointer * or 0 if not found. */ struct waitc * wait_find(wid) int wid; { struct waitc *wp; for (wp = waitlist->wa_link; wp != waitlist; wp = wp->wa_link) if (wp->wa_wid == wid) return wp; return (struct waitc*)0; } /* wait_delete() * * Remove a wait context from the active list, disassociate from * any peers and destroy it. */ void wait_delete(wp) struct waitc *wp; { if (pvmdebmask & PDMWAITC) { pvmlogprintf("wait_delete():\n"); wait_dump(wp); } if (wp->wa_mesg) pmsg_unref(wp->wa_mesg); if (wp->wa_link) { LISTDELETE(wp, wa_link, wa_rlink); } if (wp->wa_peer) { LISTDELETE(wp, wa_peer, wa_rpeer); } PVM_FREE(wp); } /* wait_get() * * Find the wait context in waitlist for a given message. * If hp != 0, check that message came from correct host. * If kind != 0, check that message is correct kind. */ struct waitc * wait_get(hp, mp, kind) struct hostd *hp; struct pmsg *mp; int kind; { struct waitc *wp; if (!mp->m_wid) return 0; if (!(wp = wait_find(mp->m_wid))) { pvmlogprintf("waitc_get() tag %s from t%x wid %d not found\n", pvmnametag(mp->m_tag, (int *)0), mp->m_src, mp->m_wid); return 0; } if (hp && hp->hd_hostpart != (wp->wa_on & TIDHOST)) { pvmlogprintf("waitc_get() tag %s from t%x wid %d wrong host\n", pvmnametag(mp->m_tag, (int *)0), mp->m_src, mp->m_wid); return 0; } if (kind && kind != wp->wa_kind) { pvmlogprintf("waitc_get() tag %s from t%x wid %d wrong kind: %s\n", pvmnametag(mp->m_tag, (int *)0), mp->m_src, mp->m_wid, waitkind(wp->wa_kind)); return 0; } return wp; } void wait_dump(wp) struct waitc *wp; { struct waitc *wp2; pvmlogprintf("wid %d kind %s on 0x%x tid 0x%x dep %d peer {", wp->wa_wid, waitkind(wp->wa_kind), wp->wa_on, wp->wa_tid, wp->wa_dep); for (wp2 = wp->wa_peer; wp2 != wp; wp2 = wp2->wa_peer) pvmlogprintf(" %d", wp2->wa_wid); pvmlogprintf(" } cnt %d\n", wp->wa_count); } void wait_dumpall() { struct waitc *wp; pvmlogprintf("wait_dumpall()\n"); for (wp = waitlist->wa_link; wp != waitlist; wp = wp->wa_link) wait_dump(wp); } ./pvm3/src/bfunc.h0100644007401100000360000000423506741172503013146 0ustar kohlgopher /* $Id: bfunc.h,v 1.4 1999/07/08 19:00:19 kohl Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * bfunc.h * * Bcopy/Memcpy patch. * * $Log: bfunc.h,v $ * Revision 1.4 1999/07/08 19:00:19 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.3 1997/06/25 22:08:42 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.2 1997/01/28 19:27:53 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:43:11 pvmsrc * Initial revision * * Revision 1.2 1994/06/03 20:38:12 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:26:46 manchek * Initial revision * */ #if defined(SYSVBFUNC) #include #define BZERO(d,n) memset(d,0,n) #define BCMP(s,d,n) memcmp(d,s,n) #define BCOPY(s,d,n) memcpy(d,s,n) #else #define BZERO(d,n) bzero(d,n) #define BCMP(s,d,n) bcmp(s,d,n) #define BCOPY(s,d,n) bcopy(s,d,n) #endif ./pvm3/src/global.h0100644007401100000360000002347407240353273013317 0ustar kohlgopher /* $Id: global.h,v 1.12 2001/02/07 23:14:03 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * global.h * * Generic includes. * * $Log: global.h,v $ * Revision 1.12 2001/02/07 23:14:03 pvmsrc * First Half of CYGWIN Check-ins... * (Spanker=kohl) * * Revision 1.11 1999/07/08 19:00:20 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.10 1999/01/28 18:54:58 pvmsrc * Added alternate WIN32 pvmd path define: * - WINPVMDPATH = "%PVM_ROOT%\\lib\\WIN32\\pvmd3.exe" * - allows retry for WIN32 hosts if $PVM_ROOT/lib/pvmd fails * (PVMDPATH). * (Spanker=kohl) * * Revision 1.9 1998/10/02 15:43:56 pvmsrc * Single source code merge of Win32 and Unix code. * (Spanker=sscott) * * Revision 1.8 1997/08/29 13:35:01 pvmsrc * OS2 Port Submitted by Bohumir Horeni, horeni@login.cz. * (Spanker=kohl) * * Revision 1.7 1997/06/25 22:08:44 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.6 1997/04/09 14:37:53 pvmsrc * PVM patches from the base 3.3.10 to 3.3.11 versions where applicable. * Originals by Bob Manchek. Altered by Graham Fagg where required. * * Revision 1.5 1997/04/08 19:57:50 pvmsrc * Promoted mbox static "classes" to public global "pvmmboxclasses". * - so pvmd can spank mboxes in ddpro.c... :-Q * - renamed everywhere, moved decl / extern to global.[ch]. * * Revision 1.4 1997/03/06 20:56:26 pvmsrc * add include host.h * * Revision 1.3 1997/01/28 19:27:55 pvmsrc * New Copyright Notice & Authors. * * Revision 1.2 1996/10/24 20:37:02 pvmsrc * Modified for New Tracing Facility: * - added new PDMTRACE constant for tracer debug tracing... * - moved in miscellaneous external declarations: * * PVM Error Globals: char *pvm_errlist[], int pvm_nerr, * int pvm_errno. * * wait list: struct waitc *waitlist. * * trace globals: struct Pvmtevdid pvmtevdidlist[], * struct Pvmtevinfo pvmtevinfo[]. * * Revision 1.1 1996/09/23 23:43:15 pvmsrc * Initial revision * * Revision 1.21 1996/05/13 20:24:52 manchek/GEF * changed DEFBINDIR to $HOME... * release patch 11 * * Revision 1.20 1995/11/02 16:00:37 manchek * version change * * Revision 1.19 1995/09/05 19:28:49 manchek * version change * * Revision 1.18 1995/07/24 18:24:19 manchek * added TIDISHERE macro * * Revision 1.17 1995/05/17 16:07:30 manchek * version 3.3.8 * * Revision 1.16 1995/02/03 16:46:47 manchek * version 3.3.7 * * Revision 1.15 1994/12/21 21:27:34 manchek * version 3.3.6 * * Revision 1.14 1994/10/15 19:05:01 manchek * version 3.3.5 * * Revision 1.13 1994/09/02 15:20:38 manchek * version 3.3.4 * * Revision 1.12 1994/07/18 19:20:00 manchek * version to 3.3.3 * * Revision 1.11 1994/07/01 15:08:02 manchek * version to 3.3.2 * * Revision 1.10 1994/06/21 18:30:26 manchek * to version 3.3.1 * * Revision 1.9 1994/06/03 20:38:55 manchek * oops * * Revision 1.8 1994/06/03 20:38:14 manchek * version 3.3.0 * * Revision 1.7 1993/12/20 15:42:26 manchek * version change * * Revision 1.6 1993/11/30 15:49:14 manchek * version change * * Revision 1.5 1993/10/27 17:32:16 manchek * version change * * Revision 1.4 1993/10/12 14:44:31 manchek * version change * * Revision 1.3 1993/09/23 20:53:50 manchek * version change * * Revision 1.2 1993/09/22 18:59:46 manchek * version change * * Revision 1.1 1993/08/30 23:26:47 manchek * Initial revision * */ /* UDPMAXLEN should be set to the largest UDP message length your system can handle. */ #ifndef UDPMAXLEN #if defined(IMA_CRAY) || defined(IMA_CRAY2) #include #define UDPMAXLEN UDPSENDSPACE/4 /* UDPSENDSPACE/2 whacks on some C-90s */ #endif #endif /*!UDPMAXLEN*/ /* 16 is the number of bytes taken by align_me, which is used to keep reference information to a da_buf. By subtracting this number from UDPMAXLEN, we can assure ourselves that da_bufs do not spill over a few bytes onto the next page of memory. Should keep us from *always* page faulting on a send */ #define KEEPONPAGE 16 #ifndef UDPMAXLEN #define UDPMAXLEN (4096 - KEEPONPAGE) /* generic max fragment length */ #endif /*DocThis*/ /* * TID definitions * * 3 2 1 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 * +---------------+---------------+---------------+---------------+ * | | | | | * +---------------+---------------+---------------+---------------+ * S G \__________ H ________/ \_______________ L _______________/ */ /*EndDocThis*/ #define TIDHOST 0x3ffc0000 #define TIDLOCAL 0x0003ffff #define TIDGID 0x40000000 #define TIDPVMD 0x80000000 #define TIDISTASK(x) (!((x)&(TIDGID|TIDPVMD)) && ((x)&TIDLOCAL)) #define TIDISPVMD(x) (((x)&(TIDGID|TIDPVMD)) == TIDPVMD && !((x)&TIDLOCAL)) #define TIDISMCA(x) (((x)&(TIDGID|TIDPVMD)) == TIDGID) #define TIDISHERE(x,me) (!((x) & TIDHOST) || !(((x) ^ (me)) & TIDHOST)) /* * Message header */ #define MSGHDRLEN 32 /*DocThis*/ /* * 0 1 2 3 * +---------------+---------------+---------------+---------------+ * 0| data signature | * +---------------------------------------------------------------+ * 4| tag | * +---------------------------------------------------------------+ * 8| context | * +---------------------------------------------------------------+ * 12| sequence number | * +---------------------------------------------------------------+ * 16| wait id | * +---------------------------------------------------------------+ * 20| checksum | * +---------------------------------------------------------------+ * 24| reserved | * +---------------------------------------------------------------+ * 28| reserved | * +---------------------------------------------------------------+ */ /*EndDocThis*/ /* frag and packet flags */ #define FFSOM 1 /* first frag of msg */ #define FFEOM 2 /* final frag of msg */ #define FFMCA 8 /* This is a multicast message */ #define FFMCAWH 16 /* Output should write the header of a mcast msg */ #ifdef IMA_OS2 #define DEFBINDIR "$HOME/pvm3/bin/$PVM_ARCH;$PVM_ROOT/bin/$PVM_ARCH" #endif #ifdef WIN32 #define DEFBINDIR "$PVM_ROOT\\bin\\$PVM_ARCH" #endif #ifdef CYGWIN #define DEFBINDIR "$HOME/pvm3/bin/$PVM_ARCH:$PVM_ROOT_U/bin/$PVM_ARCH" #endif #ifndef DEFBINDIR #define DEFBINDIR "$HOME/pvm3/bin/$PVM_ARCH:$PVM_ROOT/bin/$PVM_ARCH" #endif #ifndef DEFDEBUGGER #define DEFDEBUGGER "$PVM_ROOT/lib/debugger" #endif #ifdef IMA_OS2 #define PVMDFILE "lib/pvmd.cmd" #endif #ifdef CYGWIN #define PVMDFILE "lib/Win32/pvmd3.exe" #endif #ifndef PVMDFILE #define PVMDFILE "lib/pvmd" #endif #ifndef PVMDPATH #define PVMDPATH "$PVM_ROOT/lib/pvmd" #endif #ifndef WINPVMDPATH #define WINPVMDPATH "%PVM_ROOT%\\lib\\WIN32\\pvmd3.exe" #endif /* debug mask for pvmd and libpvm */ #define PDMPACKET 0x00001 /* packet tracing */ #define PDMMESSAGE 0x00002 /* message tracing */ #define PDMTASK 0x00004 /* task state */ #define PDMSTARTUP 0x00008 /* slave pvmd startup */ #define PDMHOST 0x00010 /* host table updates */ #define PDMSELECT 0x00020 /* select loop/fd set stuff */ #define PDMNET 0x00040 /* IP network stuff */ #define PDMNODE 0x00080 /* multiprocessor control */ #define PDMSCHED 0x00100 /* resource manager tasks stuff */ #define PDMAPPL 0x00200 /* application (scrapped msgs/stuff) */ #define PDMWAITC 0x00400 /* wait contexts */ #define PDMMEM 0x00800 /* shared memory */ #define PDMSEM 0x01000 /* semaphores */ #define PDMLOCK 0x02000 /* locks */ #define PDMROUTE 0x04000 /* message routing */ #define PDMMBOX 0x08000 /* message mailbox */ #define PDMTRACE 0x10000 /* tracer tracing */ #define PDMMCA 0x20000 /* multicast tracking */ /* General PVM Globals Declarations */ extern char *pvm_errlist[]; /* error messages for -pvm_errno */ extern int pvm_nerr; /* exported num of errors */ extern int pvm_errno; /* last err in PVM API funct */ extern struct waitc *waitlist; /* wait list */ extern struct pvmmclass *pvmmboxclasses; /* the mbox database */ /* General Trace Globals Declarations */ extern struct Pvmtevdid pvmtevdidlist[]; extern struct Pvmtevinfo pvmtevinfo[]; ./pvm3/src/host.h0100644007401100000360000001157507354463071013037 0ustar kohlgopher /* $Id: host.h,v 1.6 2001/09/26 23:35:21 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * host.h * * Host table data structures. * * $Log: host.h,v $ * Revision 1.6 2001/09/26 23:35:21 pvmsrc * Added new hd_vmid to hostd struct. * - use to override local PVM_VMID settings with hostfile "id=" option * (Spanker=kohl) * * Revision 1.5 1999/07/08 19:00:20 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.4 1997/06/25 22:08:45 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.3 1997/04/30 21:25:57 pvmsrc * SGI Compiler Warning Cleanup. * * Revision 1.2 1997/01/28 19:27:56 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:43:17 pvmsrc * Initial revision * * Revision 1.4 1995/05/17 16:10:01 manchek * added HF_OVERLOAD * * Revision 1.3 1994/06/21 18:30:47 manchek * added HF_SPEED flag * * Revision 1.2 1994/06/03 20:38:14 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:26:48 manchek * Initial revision * */ /* Host descriptor */ struct hostd { int hd_ref; /* num refs to this struct */ int hd_hostpart; /* host tid base */ char *hd_name; /* name */ char *hd_arch; /* cpu arch class */ char *hd_login; /* loginname [used master only] */ char *hd_dpath; /* daemon executable */ char *hd_epath; /* task exec search path */ char *hd_bpath; /* debugger executable */ char *hd_wdir; /* pvmd working dir */ char *hd_sopts; /* hoster options */ int hd_flag; int hd_dsig; /* data signature */ int hd_err; /* error code */ int hd_mtu; /* max snd/rcv length */ struct sockaddr_in hd_sad; /* UDP address/port */ int hd_rxseq; /* expected next seq num from host */ int hd_txseq; /* next tx seq num to host */ struct pkt *hd_txq; /* not-yet-sent packet queue to host */ struct pkt *hd_opq; /* outstanding packets to host */ int hd_nop; /* length of opq */ struct pkt *hd_rxq; /* packet reordering queue from host */ struct pmsg *hd_rxm; /* to-us msg reassembly from host */ struct timeval hd_rtt; /* estd round-trip time to host */ int hd_speed; /* cpu relative speed */ struct mca *hd_mcas; /* from-host mca cache */ char *hd_aname; /* name to use for network address */ char *hd_vmid; /* virtual machine id */ }; /* hd_flag values */ /* for advisory host table */ #define HF_NOSTART 0x100 /* don't start pvmd */ #define HF_SPEED 0x200 /* hd_speed is set */ #define HF_OVERLOAD 0x400 /* allow overloaded (>1 pvmd) host */ /* Host table */ struct htab { int ht_serial; /* serial number */ int ht_last; /* highest entry */ int ht_cnt; /* number of entries (not incl [0]) */ int ht_master; /* master host */ int ht_cons; /* console host */ int ht_local; /* this host */ int ht_narch; /* count of different data reps */ struct hostd **ht_hosts; /* hosts */ }; struct hostd *hd_new __ProtoGlarp__(( int )); void hd_free __ProtoGlarp__(( struct hostd * )); void hd_unref __ProtoGlarp__(( struct hostd * )); void hd_dump __ProtoGlarp__(( struct hostd * )); struct hostd *nametohost __ProtoGlarp__(( struct htab *, char * )); struct hostd *indtohost __ProtoGlarp__(( struct htab *, int )); struct hostd *tidtohost __ProtoGlarp__(( struct htab *, int )); struct htab *ht_new __ProtoGlarp__(( int )); void ht_insert __ProtoGlarp__(( struct htab *, struct hostd * )); void ht_delete __ProtoGlarp__(( struct htab *, struct hostd * )); void ht_free __ProtoGlarp__(( struct htab * )); struct htab *readhostfile __ProtoGlarp__(( char * )); int ht_merge __ProtoGlarp__(( struct htab *, struct htab * )); void ht_dump __ProtoGlarp__(( struct htab * )); ./pvm3/src/listmac.h0100644007401100000360000000517506741172505013513 0ustar kohlgopher /* $Id: listmac.h,v 1.5 1999/07/08 19:00:21 kohl Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * Listmac.h * * Dll macros. * * $Log: listmac.h,v $ * Revision 1.5 1999/07/08 19:00:21 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.4 1997/06/25 22:08:49 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.3 1997/04/09 14:39:33 pvmsrc * PVM patches from the base 3.3.10 to 3.3.11 versions where applicable. * Originals by Bob Manchek. Altered by Graham Fagg where required. * * Revision 1.2 1997/01/28 19:27:57 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:43:18 pvmsrc * Initial revision * * Revision 1.3 1996/05/13 20:27:36 manchek/GEF * added a few parens in LISTPUTAFTER, LISTPUTBEFORE * for picky (old) compilers * * Revision 1.2 1994/06/03 20:38:15 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:26:48 manchek * Initial revision * */ #define LISTPUTAFTER(o,n,f,r) { (n)->f=(o)->f; (n)->r=(o); (o)->f->r=(n); (o)->f=(n); } #define LISTPUTBEFORE(o,n,f,r) { (n)->r=(o)->r; (n)->f=(o); (o)->r->f=(n); (o)->r=(n); } #define LISTDELETE(e,f,r) { (e)->f->r=(e)->r; (e)->r->f=(e)->f; (e)->r=(e)->f=0; } #define LISTFIRST(h,f) ((h)->f == (h) ? 0 : (h)->f) #define LISTNEXT(p,h,f) ((p)->f == (h) ? 0 : (p)->f) #define FORLIST(p,h,f) for ((p) = (h)->f; (p) != (h); (p) = (p)->f) ./pvm3/src/lmsg.h0100644007401100000360000000377106354313363013020 0ustar kohlgopher /* $Id: lmsg.h,v 1.4 1997/06/25 22:08:51 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * lmsg.h * * structures and protos to handle message structures * */ #ifndef __LMSG_H__ #define __LMSG_H__ #include "mppmsg.h" struct msgid { int magic; /* magic number of this structure */ msgmid_t id; /* handle of message */ int tag; /* tag of message */ int otid; /* task id of "other" tid (sendto or recvfrom) */ int ctxt; /* context of the message */ int complete; /* message is complete */ int len; info_t info[MPPINFOSIZE]; char *ubuf; MSGFUNC_PTR mfunc; /* low level messaging used for this message id */ struct msgid *ms_link; /* might put these in a dll */ struct msgid *ms_rlink; }; struct msgid * msgid_new __ProtoGlarp__(( )); void msgid_free __ProtoGlarp__( (struct msgid *) ); #endif ./pvm3/src/lpvm.h0100644007401100000360000001560610001307620013013 0ustar kohlgopher /* $Id: lpvm.h,v 1.14 2004/01/14 18:50:56 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * lpvm.h * * Libpvm Globals Declarations. * * $Log: lpvm.h,v $ * Revision 1.14 2004/01/14 18:50:56 pvmsrc * Added new AIX5* arches. * (Spanker=kohl) * * Revision 1.13 2000/02/16 22:00:59 pvmsrc * Added #ifndef NO_NETINET_TCP_H around for * archs that can't handle it... :-) * (Spanker=kohl) * * Revision 1.12 1999/07/08 19:00:21 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.11 1997/09/22 21:13:28 pvmsrc * Added new pvmsettaskname() linkage (for shell-spawned tasks only!). * - call pvmsettaskname() before joining PVM, sends task name * (stored in new char *pvmmytaskname global) to pvmd in * TM_CONN2 message. * - appears in trace events and console ps. * (Spanker=kohl) * * Revision 1.10 1997/08/06 22:43:13 pvmsrc * Added new SGI6 and SGIMP6 arches. * * Revision 1.9 1997/06/27 19:53:55 pvmsrc * Fixed polltype/polltime bug in AIX4MP. * * Revision 1.8 1997/06/27 17:32:22 pvmsrc * Updated for WIN32 header files & Authors. * * Revision 1.7 1997/05/07 21:23:28 pvmsrc * Added new pvmupkstralloc() for dynamic string unpacking lunacy. * - with proto in header. * * Revision 1.6 1997/03/17 20:56:34 pvmsrc * include sys/types.h for SUNOS in.h problem. * * Revision 1.5 1997/03/06 21:06:58 pvmsrc * define struct ttpcb and TT states * added includes for this struct defn * * Revision 1.4 1997/02/13 23:35:42 pvmsrc * Added new PvmNoReset setopt/getopt option. * - added new pvmnoreset, pvmnoresetindex globals in lpvm.[ch]. * - to set use pvm_putinfo() -> PVMNORESETCLASS first avail w/lock, * save index in pvmnoresetindex. * - to unset use pvm_delinfo(). * * Revision 1.3 1997/01/28 19:27:58 pvmsrc * New Copyright Notice & Authors. * * Revision 1.2 1996/12/18 22:28:54 pvmsrc * Added new FILE *logfp decl. * - only #ifdef LOG. (previously only in shmem stuff) * - needed for now shared pvmlogerror() routine. * * Revision 1.1 1996/10/24 19:44:17 pvmsrc * Initial revision * * */ #include #ifndef WIN32 #include #ifndef NO_NETINET_TCP_H #include #endif #endif #ifdef IMA_MPP #include "mppchunk.h" #endif extern int pvmautoerr; /* whether to auto print err msgs */ extern struct Pvmtracer pvmctrc; /* child tracer info */ extern struct Pvmtracer pvmtrc; /* task tracer info */ extern int pvmmyptid; /* parent task id */ extern int pvmmytid; /* this task id */ extern int pvmmyupid; /* process unix pid */ extern int pvm_useruid; /* user's unix uid */ extern int pvmmydsig; /* native data enc, init XDR */ extern int pvmschedtid; /* scheduler task */ extern int pvmrescode; /* allow reserved tids, tags */ extern int pvmshowtaskid; /* catchout shows task ids */ extern int pvmtoplvl; /* funct called from outside lib */ extern int pvmdebmask; /* which debugging info */ extern int pvmrouteopt; /* task-task routing style */ extern int pvmnoreset; /* task reset override */ extern int pvmnoresetindex; /* task reset override mb index */ extern char *pvmmytaskname; /* task name */ extern int pvmfrgsiz; /* message frag length (to pack) */ extern int pvmudpmtu; /* local UDP MTU */ extern int pvmmyctx; /* current message context */ extern int pvmnsibs; /* number in our spawn group */ extern int *pvmsibtids; /* tids in our spawn group */ extern struct pmsg *pvmrxlist; /* not-recvd msg list */ extern struct pmsg *pvmrbuf; /* current recv/unpack message */ extern struct pmsg *pvmsbuf; /* current send/pack message */ #if defined(IMA_ALPHAMP) || defined(IMA_CSPP) || defined(IMA_HPPAMP) \ || defined(IMA_RS6KMP) || defined(IMA_SGIMP) \ || defined(IMA_SGIMP6) || defined(IMA_AIX4MP) \ || defined(IMA_AIX5MP) || defined(IMA_SGIMP64) \ || defined(IMA_SUNMP) extern int pvmpolltype; /* memory polling style */ extern int pvmpolltime; /* time value for poll wait */ #endif #ifdef LOG extern FILE *logfp; /* my own log file */ #endif /* Trace Globals Declarations */ extern struct pvmtrcencvec *pvmtrccodef; extern struct timeval pvmtrcztv; extern struct pmsg *pvmtrcmp; extern int pvmtrcsbfsave; extern int pvmtrcsbf; extern int pvmtrcdesc; extern int pvmtrctmp; extern int pvmtrcsavekind; /* Routines */ int pvm_tc_noop __ProtoGlarp__(( int )); int pvm_tc_settrace __ProtoGlarp__(( int )); int pvm_tc_settrcbuf __ProtoGlarp__(( int )); int pvm_tc_settrcopt __ProtoGlarp__(( int )); int pvm_tc_settmask __ProtoGlarp__(( int )); int pvm_tc_siblings __ProtoGlarp__(( int )); int pvmupkstralloc __ProtoGlarp__(( char ** )); /* * task-task or task-pvmd control block */ struct ttpcb { struct ttpcb *tt_link; /* dll of peers */ struct ttpcb *tt_rlink; int tt_tid; /* tid of peer or 0 if master of list */ int tt_state; int tt_fd; /* fd of connection or -1 */ struct sockaddr_in tt_sad; /* address of our socket */ struct sockaddr_in tt_osad; /* (authd) address of peer socket */ struct pmsg *tt_rxfrag; /* not-assembled incm msg */ struct frag *tt_rxf; /* partial incm frag */ #ifndef NOUNIXDOM char *tt_spath; /* socket path */ #endif #if defined(IMA_MPP) /* ordering structure for send/recv msgs */ MPP_DIRECTI_PTR mpdirect; #endif }; /* ttpcb states */ #define TTCONWAIT 1 /* requested, waiting for reply to connect */ #define TTGRNWAIT 2 /* granted, waiting for connect */ #define TTOPEN 3 /* connection running */ #define TTDENY 4 /* don't attempt connection */ #define TTDEAD 5 /* task dead; pcb should be cleared */ ./pvm3/src/lpvmmisc.h0100644007401100000360000000364706741172505013713 0ustar kohlgopher /* $Id: lpvmmisc.h,v 1.4 1999/07/08 19:00:21 kohl Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * lpvmmisc.h * * Misc library defines * * $Log: lpvmmisc.h,v $ * Revision 1.4 1999/07/08 19:00:21 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.3 1997/06/25 22:08:52 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.2 1997/01/28 19:27:59 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:43:20 pvmsrc * Initial revision * */ /* * keep a self - notify request */ struct notreq { struct notreq *n_link; /* chain or 0 */ struct notreq *n_rlink; int n_ctx; int n_tag; int n_count; }; ./pvm3/src/mppchunk.h0100644007401100000360000001407006360713643013677 0ustar kohlgopher /* $Id: mppchunk.h,v 1.5 1997/07/09 13:52:35 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ #ifndef __mppchunk_h__ #define __mppchunk_h__ #include "mppmsg.h" /* exportable parameters */ extern int MAXSEQ; /* from mppchunk.c */ /* Some parameters that should be made runtime/startup changeable */ #define TAGBASE #define NRBUFS 4 #define NSBUFS 4 #define DFN_MAXSEQ 0xffff #define INCRSEQ(_seq,_maxseq) (((_seq)++)&(_maxseq)) #define NEXTCHUNKSEQ(_seq, _delta) (((_seq) + (_delta)) & 0xffff ) /* array of mids of outstanding messages to be sent to backend */ #define NMPPSBUFMIDS 32 #define MPPMIDFREE -1 #define MPPMIDALLOCED -2 #if !defined(IMA_NODE) #define CHUNK struct pkt #define CHUNK_NEW pk_new #define CHUNK_NEXT pk_link #define CHUNK_PREV pk_rlink #define CHUNK_SEQ pk_seq #define CHUNK_SRC pk_src #define CHUNK_LEN pk_len #define CHUNK_DAT pk_dat #define CHUNK_MAX pk_max #define CHUNK_FREE pk_free #define CHUNK_RIP pk_rip #include "pkt.h" #else #define CHUNK struct frag #define CHUNK_NEW fr_new #define CHUNK_NEXT fr_link #define CHUNK_PREV fr_rlink #define CHUNK_SEQ fr_seq #define CHUNK_SRC fr_src #define CHUNK_LEN fr_len #define CHUNK_DAT fr_dat #define CHUNK_MAX fr_max #define CHUNK_FREE fr_unref #define CHUNK_RIP fr_rip #include "pvmfrag.h" #endif /* ======== Type declarations ========= */ typedef CHUNK *CHUNK_PTR; /* Information used for sending/receiving packets to/from tasks. Keeps track of the send sequence number and the tagbase used for ' sending data. Points to a pkt_order structure for receives so that reordering happens in a sane manner. */ struct mpp_directi { int rtid; /* task id of the remote task sender/receiver */ int rpid; /* pid of the remote proc, used by puma */ int appid; /* used for by PUMA for host to node send */ int tagbase; /* base for sending/receive messages */ int nbufs; /* nbuffers to use before wrap */ int sseq; /* sequence number to use for send */ struct chunk_order *ordering; /* ordering structure for receive sequencing */ }; typedef struct mpp_directi MPP_DIRECTI; typedef struct mpp_directi *MPP_DIRECTI_PTR; struct chunk_order { int seq; /* sequence number for this task */ int nbufs; /* number of buffers that we have to sequence */ int *bufseq; /* sequence number of the ith buffer for this task */ CHUNK *oochunks; /* list of out-of-order packets */ }; typedef struct chunk_order CHUNK_ORDER; typedef struct chunk_order *CHUNK_ORDER_PTR; struct msg_info { int mid; /* message id from message-passing substrate */ CHUNK *rchunk; /* posted chunk for receive */ int src; /* source for this message */ int tag; /* tag for this message */ int mxsize; /* max size of the message */ int hsize; /* size of header */ info_t info[MPPINFOSIZE]; /* info array 8 for pgons, 1 for MPI */ }; typedef struct msg_info MSG_INFO; typedef struct msg_info *MSG_INFO_PTR; /* ----- Prototype Declarations ------- */ /* ====== Functions that return MPP_DIRECTI_PTR structs ======= */ MPP_DIRECTI_PTR new_directstruct __ProtoGlarp__( (int, int) ); /* int nsbufs -- number of send buffers * int nrbufs -- number of receive buffers */ MPP_DIRECTI_PTR new_vdirectstruct __ProtoGlarp__( (int nstructs, int nsbufs, int nrbufs) ); /* int nstructs -- number of structures to alloc * int nsbufs -- number of send buffers * int nrbufs -- number of receive buffers */ /* ====== Functions that return CHUNK_ORDER_PTR ======= */ CHUNK_ORDER_PTR new_chunkostruct __ProtoGlarp__( (int nbufs) ); /* nbufs -- number of receive buffers */ CHUNK_ORDER_PTR new_vchunkostruct __ProtoGlarp__( (int nstructs, int nbufs) ); /* nstructs -- number of structures * nbufs -- number of receive buffers */ /* ====== Functions that return struct CHUNK * ======= */ CHUNK_PTR ochunk_delete __ProtoGlarp__( (CHUNK_ORDER_PTR) ); CHUNK_PTR read_chunk __ProtoGlarp__( (MSG_INFO_PTR, int *, int *, int *, int , int, MSGFUNC_PTR) ); /* ====== Functions that return MSG_INFO_PTR ======= */ MSG_INFO_PTR init_recv_list __ProtoGlarp__( (int, int, int, int, int, MSGFUNC_PTR) ); /* ====== Functions that return int ======= */ int init_directstruct __ProtoGlarp__( ( MPP_DIRECTI_PTR, int )); int order_chunk __ProtoGlarp__( (CHUNK_ORDER_PTR, int, CHUNK_PTR )); int ochunk_insert __ProtoGlarp__( (CHUNK_ORDER_PTR, CHUNK_PTR) ); int post_receive __ProtoGlarp__( (MSG_INFO_PTR , int, int, int, int, int, int, MSGFUNC_PTR) ); int post_send __ProtoGlarp__( (char * , int, MPP_DIRECTI_PTR, MSGFUNC_PTR) ); int update_seq_numbers __ProtoGlarp__( (CHUNK_ORDER_PTR) ); int pvm_init_asynch_list __ProtoGlarp__( (msgmid_t *, CHUNK_PTR *, int) ); int pvm_assign_chunk __ProtoGlarp__( (CHUNK_PTR *, CHUNK_PTR, int) ); int pvm_assign_mid __ProtoGlarp__( (msgmid_t *, int, int) ); int pvm_mpp_find_midx __ProtoGlarp__( (msgmid_t *, CHUNK_PTR *, int *, int, MSGFUNC_PTR) ); /* ====== Functions that return struct CHUNK * ======= */ #endif ./pvm3/src/mppmsg.h0100644007401100000360000001070410001307622013334 0ustar kohlgopher /* $Id: mppmsg.h,v 1.6 2004/01/14 18:50:58 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ #ifndef __mppmsg_h__ #define __mppmsg_h__ /* This library uses primitives of a native message passing system. Because * different routes may use different functions, the following documents * the call sequence expected. * int imsgsend(int appid, int tag, char *buffer, int len, int dest, int partid, msgmid_t *mid) appid - used for some host programs to identify application dest - destinations of message. tag - tag to use for sending the message datap - buffer to send len - length of buffer (in bytes) partid -partition id mid - message id of send message returns integer >= 0 on success. < 0 on failure. message id is returned in mid. int imsgrecv(int appid, int src, int tag, char *datap, int len, int partid, int *info, msgmid_t *mid) appid - used for some host programs to identify application src - src of message. -1 means any src tag - tag to match on message datap - buffer in which to receive message len - max length of buffer (in bytes) partid -partition id info - pointer to integer array of memory to store message information mid - pointer the recv message id returns integer >= 0 on success. < 0 on failure. message id returned in mid msgmid_t msgmerge(msgmid_t *mid1, msgmid_t *mid2) mid1 - message id of message 1 (-1 indicates no existing message ) mid2 - message id of message 2 (-1 indicates no existing message ) returns mid3, merged id of message 1 and 2, if possible int msgdone(int appid, msgmid_t mid, info_t *info) appid - used for some host programs to identify application mid - message id of an incoming message (imsgrecv) or outgoing (imsgsend) returns 0, message not complete; 1 - message complete, < 0 error int msgsrc(info_t *info) info - pointer to low-level message passing information block returns node of the message src int msglen(info_t *info) info - pointer to low-level message passing information block returns length of the message given in info block int msgtag(info_t *info) info - pointer to low-level message passing information block returns tag of the message */ #if ( defined(IMA_SP2MPI) || defined(IMA_AIX4SP2) \ || defined(IMA_AIX5SP2) ) && defined(IMA_NODE) #include #define msgmid_t MPI_Request #define info_t MPI_Status #define MPPINFOSIZE 1 #else #define msgmid_t int #define info_t int #define MPPINFOSIZE 8 #endif struct msgfunc { int (*imsgsend) __ProtoGlarp__( (int, int, char *, int, int, int, msgmid_t *) ); int (*imsgrecv) __ProtoGlarp__( (int, int, int, char *, int, int, int *, msgmid_t *) ); msgmid_t (*msgmerge) __ProtoGlarp__( (msgmid_t *, msgmid_t *) ); int (*msgdone) __ProtoGlarp__( (int, msgmid_t *, info_t *) ); int (*msglen) __ProtoGlarp__( (info_t *) ); int (*msgsrc) __ProtoGlarp__( (info_t *) ); int (*msgtag) __ProtoGlarp__( (info_t *) ); }; typedef struct msgfunc MSGFUNC; typedef struct msgfunc *MSGFUNC_PTR; /* ======= Function Protoypes ========= */ MSGFUNC_PTR pvm_nodemsgfunc __ProtoGlarp__(()); MSGFUNC_PTR pvm_hostmsgfunc __ProtoGlarp__(()); int pvm_mpp_message_init __ProtoGlarp__( (int *, int *, int *, int *) ); int pvm_mpp_message_stop __ProtoGlarp__( () ); #endif /* not defined __mppmsg_h */ ./pvm3/src/msgbox.h0100644007401100000360000000537006741172506013354 0ustar kohlgopher /* $Id: msgbox.h,v 1.5 1999/07/08 19:00:22 kohl Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * msgbox.h * * Message mailbox includes. * * $Log: msgbox.h,v $ * Revision 1.5 1999/07/08 19:00:22 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.4 1997/06/25 22:09:14 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.3 1997/04/10 17:53:55 pvmsrc * Externalized me_new()... * - for WT_RECVINFO usage... * * Revision 1.2 1997/04/08 19:41:12 pvmsrc * Added me_savetid to pvmmentry struct. * - for keeping track of original owner on persistent mboxes. * - allows more careful cleanup in a system reset, set me_tid to 0 * but save original tid in me_savetid first... :-) * * Revision 1.1 1997/04/08 18:44:27 pvmsrc * Initial revision * * */ /* * one of these for each name (class) in the database */ struct pvmmclass { struct pvmmclass *mc_link; /* dll of peers */ struct pvmmclass *mc_rlink; char *mc_name; /* class name or 0 if list master */ struct pvmmentry *mc_ent; /* entries in class */ }; /* * one of these for each index (entry) of a class */ struct pvmmentry { struct pvmmentry *me_link; /* dll of peers */ struct pvmmentry *me_rlink; int me_ind; /* index in class or -1 if master */ int me_tid; /* tid of owner */ int me_savetid; /* previous owner tid, now dead */ int me_flags; /* options */ struct pmsg *me_msg; /* value (message) */ }; struct pvmmentry *me_new __ProtoGlarp__(( int )); ./pvm3/src/patchlevel.h0100644007401100000360000000247206360713646014207 0ustar kohlgopher /* $Id: patchlevel.h,v 1.2 1997/07/09 13:52:38 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ #define PATCHLEVEL 340 ./pvm3/src/pkt.h0100644007401100000360000000660206741172506012652 0ustar kohlgopher /* $Id: pkt.h,v 1.6 1999/07/08 19:00:22 kohl Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pkt.h * * Packet buffers. * * $Log: pkt.h,v $ * Revision 1.6 1999/07/08 19:00:22 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.5 1997/06/25 22:09:17 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.4 1997/04/24 20:59:42 pvmsrc * added pk_rip structure member (used on mpps) * * Revision 1.3 1997/03/06 21:09:10 pvmsrc * - define __PKT_H__ so that multiple includes of pkt.h won't honk. * * Revision 1.2 1997/01/28 19:28:16 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:43:22 pvmsrc * Initial revision * * Revision 1.3 1995/07/24 18:26:09 manchek * added message header fields and cpos, removed PF_STARTED * * Revision 1.2 1994/06/03 20:38:20 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:26:49 manchek * Initial revision * */ #ifndef __PKT_H__ #define __PKT_H__ struct pkt { struct pkt *pk_link; /* queue or 0 */ struct pkt *pk_rlink; struct pkt *pk_tlink; /* scheduling queue or 0 */ struct pkt *pk_trlink; char *pk_buf; /* buffer or zero if master pkt */ char *pk_dat; /* data */ int pk_max; /* size of buffer */ int pk_len; /* length of data */ int pk_src; /* source tid */ int pk_dst; /* dest tid */ int pk_flag; /* fragment flags */ int pk_enc; /* message encoding */ int pk_tag; /* message type tag */ int pk_ctx; /* message context */ int pk_wid; /* message wait context id */ int pk_crc; /* message checksum */ int pk_nrt; /* retry count */ int pk_seq; /* seq num */ int pk_ack; /* ack num */ int pk_rip; /* received in place - used on mpps */ struct hostd *pk_hostd; /* receiving host */ struct timeval pk_rtv; /* time to retry */ struct timeval pk_rta; /* next-retry accumulator */ struct timeval pk_rto; /* total time spent on pkt */ struct timeval pk_at; /* time pkt first sent */ char *pk_cpos; /* write pointer for local protocol */ }; struct pkt *pk_new __ProtoGlarp__((int n)); void pk_free __ProtoGlarp__((struct pkt *p)); #endif ./pvm3/src/pmsg.h0100644007401100000360000000763107240353447013025 0ustar kohlgopher /* $Id: pmsg.h,v 1.5 2001/02/07 23:15:51 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pmsg.h * * Libpvm and pvmd message descriptors. * * $Log: pmsg.h,v $ * Revision 1.5 2001/02/07 23:15:51 pvmsrc * 2nd Half of CYGWIN Check-ins... * (Spanker=kohl) * * Revision 1.4 1999/07/08 19:00:22 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.3 1997/06/27 17:32:50 pvmsrc * Updated for WIN32 header files & Authors. * * Revision 1.2 1997/01/28 19:28:17 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:43:24 pvmsrc * Initial revision * * */ /* * vector of pack/unpack routines for an encoding */ #ifdef WIN32 #include "..\xdr\types.h" #include "..\xdr\xdr.h" #endif struct encvec { int (*enc_init)(); /* initialize write */ int (*dec_init)(); /* initialize read */ int (*enc_byte)(); /* encode bytes */ int (*dec_byte)(); /* decode bytes */ int (*enc_short)(); /* encode shorts */ int (*dec_short)(); /* ... */ int (*enc_int)(); int (*dec_int)(); int (*enc_long)(); int (*dec_long)(); int (*enc_ushort)(); int (*dec_ushort)(); int (*enc_uint)(); int (*dec_uint)(); int (*enc_ulong)(); int (*dec_ulong)(); int (*enc_float)(); int (*dec_float)(); int (*enc_double)(); int (*dec_double)(); int (*enc_cplx)(); int (*dec_cplx)(); int (*enc_dcplx)(); int (*dec_dcplx)(); }; /* * descriptor for a message */ struct pmsg { struct pmsg *m_link; /* chain or 0 */ struct pmsg *m_rlink; struct encvec *m_codef; /* data encoders/decoders */ struct frag *m_frag; /* master frag or 0 if we're list head */ struct frag *m_cfrag; /* pack/unpack position */ int m_ref; /* refcount */ int m_mid; /* message id */ int m_len; /* total body length */ int m_ctx; /* communication context */ int m_tag; /* type tag */ int m_wid; /* wait id */ int m_src; /* src address */ int m_dst; /* dst address */ int m_enc; /* encoding signature */ int m_flag; int m_cpos; /* pack/unpack position */ int m_crc; /* CRC from header */ XDR m_xdr; }; #define MM_PACK 1 /* initialized for packing */ #define MM_UPACK 2 /* initialized for unpacking */ #define MM_PRIO 4 /* put message at head of queue */ #ifdef IMA_CSPP #define MM_DIFFNODE 256 /* message came from different (node?) */ #endif int pvmgetdsig __ProtoGlarp__ (( )); struct pmsg * pmsg_new __ProtoGlarp__ (( int master )); void pmsg_unref __ProtoGlarp__ (( struct pmsg *mp )); int pmsg_extend __ProtoGlarp__ (( struct pmsg *mp )); int pmsg_decmore __ProtoGlarp__ (( struct pmsg *mp )); int pmsg_setlen __ProtoGlarp__ (( struct pmsg *mp )); int pmsg_setenc __ProtoGlarp__ (( struct pmsg *mp, int enc )); int pmsg_dump __ProtoGlarp__ (( struct pmsg *mp, int lvl )); ./pvm3/src/pvmalloc.h0100644007401100000360000000533506741172507013674 0ustar kohlgopher /* $Id: pvmalloc.h,v 1.4 1999/07/08 19:00:23 kohl Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmalloc.h * * Malloc filter interface. * * $Log: pvmalloc.h,v $ * Revision 1.4 1999/07/08 19:00:23 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.3 1997/06/25 22:09:19 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.2 1997/01/28 19:28:18 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:43:25 pvmsrc * Initial revision * * Revision 1.2 1994/06/03 20:38:21 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:26:50 manchek * Initial revision * */ #ifdef HASSTDLIB #include #endif #ifdef USE_PVM_ALLOC #define PVM_ALLOC(n,g) pvm_alloc((unsigned)(n),(g)) #define PVM_REALLOC(p,n) pvm_realloc((char*)(p),(unsigned)(n)) #define PVM_FREE(p) pvm_free((char*)(p)) #else #define PVM_ALLOC(n,g) malloc((unsigned)(n)) #define PVM_REALLOC(p,n) realloc((char*)(p),(unsigned)(n)) #define PVM_FREE(p) free((char*)(p)) #endif #define TALLOC(n,t,g) (t*)PVM_ALLOC((n)*sizeof(t),(g)) #define TREALLOC(p,n,t) (t*)PVM_REALLOC(p,(n)*sizeof(t)) #define STRALLOC(s) strcpy(TALLOC(strlen(s)+1,char,"str"),s) /* #define STRALLOC(s) strcpy((qq=TALLOC(strlen(s)+1,char,"str"),fprintf(stderr,"XXX STRALLOC %lx\n",qq),qq),s) char *qq; */ char *pvm_alloc __ProtoGlarp__((unsigned n, char *g)); char *pvm_realloc __ProtoGlarp__((char *p, unsigned n)); void pvm_free __ProtoGlarp__((char *p)); ./pvm3/src/pvmdabuf.h0100644007401100000360000000400406741172507013653 0ustar kohlgopher /* $Id: pvmdabuf.h,v 1.4 1999/07/08 19:00:23 kohl Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmdabuf.h * * Data buffer manip. * * $Log: pvmdabuf.h,v $ * Revision 1.4 1999/07/08 19:00:23 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.3 1997/06/25 22:09:32 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.2 1997/01/28 19:28:19 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:43:26 pvmsrc * Initial revision * * Revision 1.2 1994/06/03 20:38:23 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:26:50 manchek * Initial revision * */ char *da_new __ProtoGlarp__((int len)); void da_ref __ProtoGlarp__((char *p)); void da_unref __ProtoGlarp__((char *p)); ./pvm3/src/pvmdmp.h0100644007401100000360000000626307053100123013341 0ustar kohlgopher /* $Id: pvmdmp.h,v 1.6 2000/02/17 23:12:19 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmdmp.h * * $Log: pvmdmp.h,v $ * Revision 1.6 2000/02/17 23:12:19 pvmsrc * *** Changes for new BEOLIN port *** * - MPP-like, similar to SP2, etc. * - submitted by Paul Springer . * - format-checked & cleaned up by Jeembo... :-) * (Spanker=kohl) * * Revision 1.5 1999/07/08 19:00:23 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.4 1997/06/25 22:09:33 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.3 1997/03/06 21:10:59 pvmsrc * - moved TIDONNODE, TIDISNODE macro to pvmmimd.h * - mpp_load prototype changed * - mpp_input protoype changed * * Revision 1.2 1997/01/28 19:28:20 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:43:27 pvmsrc * Initial revision * * Revision 1.6 1995/07/25 17:37:26 manchek * mpp_output returns int * * Revision 1.5 1995/06/16 16:12:47 manchek * declare special mpp_load for PGON * * Revision 1.4 1995/05/30 17:48:30 manchek * mpp_free() takes struct task instead of tid. * Refined TIDISNODE macro * * Revision 1.3 1995/02/01 21:32:54 manchek * added nenv and envp args to mpp_load * */ #include "pvmmimd.h" #define TIMEOUT 10000 /* for select(); in usec */ void mpp_init __ProtoGlarp__((int *argc, char **argv)); void mpp_free __ProtoGlarp__((struct task *tp)); int mpp_load __ProtoGlarp__((struct waitc_spawn *wxp)); int mpp_input __ProtoGlarp__((void)); int mpp_mcast __ProtoGlarp__((struct pkt *pp, int *tids, int ntask)); int mpp_output __ProtoGlarp__((struct task *tp, struct pkt *pp)); int mpp_probe __ProtoGlarp__((void)); void mpp_kill __ProtoGlarp__((struct task *tp, int signum)); void mpp_cleanup __ProtoGlarp__((void)); #ifdef IMA_BEOLIN struct task *mpp_find __ProtoGlarp__((struct task *tp)); #endif void wakesig __ProtoGlarp__((int sig)); ./pvm3/src/pvmfrag.h0100644007401100000360000000644006741172510013511 0ustar kohlgopher /* $Id: pvmfrag.h,v 1.7 1999/07/08 19:00:24 kohl Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmfrag.h * * Frag buffer util. * * $Log: pvmfrag.h,v $ * Revision 1.7 1999/07/08 19:00:24 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.6 1997/06/25 22:09:38 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.5 1997/04/30 21:26:28 pvmsrc * SGI Compiler Warning Cleanup. * * Revision 1.4 1997/04/24 20:57:55 pvmsrc * added filed fr_rip to frag structure for frags received inplace * * Revision 1.3 1997/03/06 21:12:13 pvmsrc * added fr_seq and fr_src members to frag structure. * used by mppchunk.c for ordering. future for attached * sequence numbers on every fragment. * * Revision 1.2 1997/01/28 19:28:21 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:43:29 pvmsrc * Initial revision * * Revision 1.3 1995/05/17 16:43:54 manchek * added support for CSPP shared memory * * Revision 1.2 1994/06/03 20:38:25 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:26:51 manchek * Initial revision * */ struct frag { struct frag *fr_link; /* chain or 0 */ struct frag *fr_rlink; char *fr_buf; /* buffer or zero if master frag */ char *fr_dat; /* data */ int fr_max; /* size of buffer */ int fr_len; /* length of data */ struct { unsigned int ref : 16; /* refcount (of chain if master, */ /* else frag) */ unsigned int dab : 1; /* buffer is a databuf */ unsigned int spr : 1; /* sparse data (csz, lnc valid) */ } fr_u; int fr_csz; /* chunk size */ int fr_lnc; /* lead to next chunk */ int fr_seq; /* sequence number. Used for mpp machines */ int fr_src; /* message src. Used for mpp machines */ int fr_rip; /* received inplace, don't put on recvq */ #ifdef IMA_CSPP int fr_num_unpacked; /* so we know how much to flush */ #endif }; struct frag *fr_new __ProtoGlarp__(( int n )); struct frag *fr_snew __ProtoGlarp__(( char *cp, int n )); void fr_unref __ProtoGlarp__(( struct frag *f )); ./pvm3/src/pvmmagic.h0100644007401100000360000000566206354313574013666 0ustar kohlgopher /* $Id: pvmmagic.h,v 1.2 1997/06/25 22:11:08 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmmagic.h * * magic numbers for pvm data structures. * */ /* Magic #'s are segmented by use (magic segment) * Each segment defines it own use (magic category) */ #ifndef __PVMMAGIC_H__ #define __PVMMAGIC_H__ typedef unsigned int PVMMAGIC; #define MAGIC_SEGSHIFT 15 #define MAGICMASK 0xffff #define BADMAGIC(_ref,_test) ((_ref)!=(_test) ? 1 : 0) #define MAKE_MAGIC(_seg, _cat) ((((_seg) & MAGICMASK) << 15 ) \ | ((_cat) & MAGICMASK)) /* ------- Define magic segments ---------- */ /* Segment numbers should not change in a release. */ /* They can be added to */ #define MG_DDPRO_SEG 1 #define MG_GLOBAL_SEG 2 #define MG_HOST_SEG 3 #define MG_IMALLOC_SEG 4 #define MG_LPVM_SEG 5 #define MG_LPVMCAT_SEG 6 #define MG_LPVMGEN_SEG 7 #define MG_LPVMGLOB_SEG 8 #define MG_LPVMMIMD_SEG 9 #define MG_LMSG_SEG 10 #define MG_LPVMPACK_SEG 11 #define MG_LPVMSHMEM_SEG 12 #define MG_MSGBOX_SEG 13 #define MG_NMDCLASS_SEG 14 #define MG_PKT_SEG 15 #define MG_PMSG_SEG 16 #define MG_PVMALLOC_SEG 17 #define MG_PVMCRUFT_SEG 18 #define MG_PVMD_SEG 19 #define MG_PVMDABUF_SEG 20 #define MG_PVMDPACK_SEG 21 #define MG_PVMDSHMEM_SEG 22 #define MG_PVMDTEV_SEG 23 #define MG_PVMDUNIX_SEG 24 #define MG_PVMERR_SEG 25 #define MG_PVMFRAG_SEG 26 #define MG_PVMLOG_SEG 27 #define MG_PVMSHMEM_SEG 28 #define MG_SDPRO_SEG 29 #define MG_TASK_SEG 30 #define MG_TDPROC_SEG 31 #define MG_TEV_SEG 32 #define MG_WAITC_SEG 33 /* ----- Magic Categories ------- */ /* -- MG_LMSG_SEG -- */ #define LMSG_MSGID MAKE_MAGIC(MG_LMSG_SEG,1) /* ------ END of Magic Categories ----------- */ #endif /* ifndef __PVMMAGIC__ */ ./pvm3/src/pvmmimd.h0100644007401100000360000001472706741172510013527 0ustar kohlgopher /* $Id: pvmmimd.h,v 1.7 1999/07/08 19:00:24 kohl Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmmimd.h * * $Log: pvmmimd.h,v $ * Revision 1.7 1999/07/08 19:00:24 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.6 1997/06/25 22:11:09 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.5 1997/05/05 20:06:15 pvmsrc * Extend the size of the info array passed to mpp tasks on startup. * * Revision 1.4 1997/04/25 19:15:42 pvmsrc * added BUSYWAIT #def needed by shmem version (via lpvmglob.c) * * Revision 1.3 1997/03/06 21:12:58 pvmsrc * - Changed everything :-) * tid structure changed. * lots of macro changes * defines for message types. * reorganized. * * Revision 1.2 1997/01/28 19:28:22 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:43:30 pvmsrc * Initial revision * * Revision 1.8 1995/06/16 16:09:30 manchek * changed size of PGON host info array to 10 * * Revision 1.7 1995/06/12 18:24:20 manchek * SIZEHINFO only affects PGON for now * * Revision 1.6 1995/06/12 16:01:56 manchek * changed SIZEHINFO to 6 * * Revision 1.5 1995/05/30 17:50:23 manchek * Added new defines for SP2MPI architecture * * Revision 1.4 1994/11/08 19:19:23 manchek * mpp fixes * * Revision 1.3 1994/06/03 20:38:25 manchek * version 3.3.0 * * Revision 1.2 1993/12/20 15:39:44 manchek * patch 6 from wcj * * Revision 1.1 1993/08/30 23:26:51 manchek * Initial revision * */ #ifndef __PVMMIMD_H__ #define __PVMMIMD_H__ /* ====== SECTION I (STRUCTURE DEFINITIONS) ====== */ /* nodes in use */ struct nodeset { struct nodeset *n_link; /* linked list */ struct nodeset *n_rlink; int n_size; /* number of nodes */ int n_first; /* the first node in the set */ int n_ptype; /* (PGON) ptype of tasks on the nodes */ int n_alive; /* number of active nodes */ int n_ptid; /* tid of task who spawned us */ #ifdef IMA_I860 #define n_cid n_ptype /* the global qm_cubeid */ char *n_name; /* cube name */ #endif }; /* ====== SECTION II (TIDS) ====== */ /* PVM task identifiers are 32 bits. The first 18 bits are assigned * by the local pvmd. The following summarizes the pvm tid breakdown: * * |31 |30 |29 18|17 0| * | s | g | < host part > | | * * MPPs further break down the as follows: * * 17 16 14 13 0 * | n | | | * * bits 0 - 13 represent the physical node # --> 16384 nodes * bits 14 - 16 represent partition ids --> 8 simulatenous partitions * bit 17 - 17 task is a compute node (bit set) or service node (not set) */ #define NODEWIDTH 14 /* 14 bits for nodes - 16K nodes */ #define PARTWIDTH 3 /* 4 bits for partitions - 8 partitions */ #define CNODEWIDTH 1 /* 1 bit to indicate a node task */ /* --- * 18 <--- must sum to 18, unless tid defn changes */ #define MAXNODES (1 << NODEWIDTH ) /* 2^NODEWIDTH */ #define NPARTITIONS (1 << PARTWIDTH ) /* 2^PARTWIDTH */ #define NODESTATES (1 << CNODEWIDTH) /* 2^CNODEWIDTH */ /* Masks for the above information */ /* -- First NODEWIDTH bits, mask for the node number */ #define TIDNODE (MAXNODES - 1) /* -- next PARTWIDTH bits, mask for the partition identifier */ #define TIDPTYPE ((NPARTITIONS -1 ) << NODEWIDTH) /* -- next NODESTATES bits, mask for service/compute part residency */ #define TIDONNODE ((NODESTATES - 1) << (NODEWIDTH + PARTWIDTH)) /* #define TIDNODE 0x00003fff first NODEWIDTH BITS #define TIDPTYPE 0x0001c000 next PARTWIDTH BITS #define TIDONNODE 0x00020000 next CNODEWIDTH BITS */ /* ====== SECTION III (CONSTANTS, MESSAGE CONSTANTS) ====== */ #define MAXFRAGSIZE (0x00004000 - 16) /* max fragment size (16K - 16) */ #define MXPP 256 /* maximum number of pre-posted recv buffers */ #define MPPANY -1 #define MPPREPOST 1 #define PVMDPTYPE 0 /* process type of pvmd */ #define SIZEHINFO 20 /* size of hostinfo array */ /* need by lpvmglob */ #define BUSYWAIT 1000000 /* max wait cycles before backing off */ /* Packed messages arrive in pre-posted receive buffers with a certain * physical tag. For peer-peer communication, pvm message fragments * arrive in buffers with tags in the range [PMTPBASE, PMTPBASE+MXPP-1]. * Bodies of inplace messages arrive */ #define PMTCONF (MAXNODES+1) /* Initial configuration message */ #define PMTHOST (PMTCONF+1) /* tag for bcasting myhostpart (I860) */ #define PMTPHYS (PMTCONF+2) /* tag for physical node# (I860) */ #define PMTDBASE (PMTCONF+3) /* base tag for pre-posted recvs from pvmd*/ #define PMTPBASE (PMTDBASE+MXPP) /* base tag for pre-posted recvs from peer*/ /* ====== SECTION IV (MACROS) ====== */ /* determine if task is a node process */ #define TIDISNODE(x) (!((x)&(TIDGID|TIDPVMD)) && ((x)&TIDONNODE)) /* extract the ptype bits */ #define TIDTOTYPE(x) ((x)&TIDPTYPE)>>(NODEWIDTH) /* ====== SECTION V (Prototypes) ====== */ struct ttpcb * mpp_ttpcb_find __ProtoGlarp__( (int tid) ); struct frag * pvm_readfrompvmd __ProtoGlarp__( () ); struct frag * pvm_readfrompeer __ProtoGlarp__( () ); struct pmsg * pvm_mpp_pmsgs __ProtoGlarp__( () ); #endif ./pvm3/src/pvmshmem.h0100644007401100000360000003034110001307627013671 0ustar kohlgopher /* $Id: pvmshmem.h,v 1.9 2004/01/14 18:51:03 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM 3.0 was funded in part by the U.S. Department of Energy, the * National Science Foundation and the State of Tennessee. */ /* * pvmshmem.h * * $Log: pvmshmem.h,v $ * Revision 1.9 2004/01/14 18:51:03 pvmsrc * Added new AIX5* arches. * (Spanker=kohl) * * Revision 1.8 2000/02/10 20:45:49 pvmsrc * Replaced hard-coded /tmp usage with PVMSHMFILE. * - use pvmgettmp() routine now to determine PVM temp dir. * (Spanker=kohl) * * Revision 1.7 1999/07/08 19:00:24 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.6 1998/08/13 18:31:11 pvmsrc * Altered SUNMP to use test and set operations with semaphores * for page locking instead of MUTEX and cond vars. * Changes are mainly in pvmshmem.h, with lots of #ifdefs changes. * Makefile altered to use the PLOCKFILE to indicate the Page Locking * INLINE code used (from SUNMP.conf). * Some changes effect AIX MP versions which still use conditional * variables and may change to semaphores soon. * (Spanker=fagg) * * Revision 1.5 1997/08/06 22:43:23 pvmsrc * Added new SGI6 and SGIMP6 arches. * * Revision 1.4 1997/06/25 22:11:11 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.3 1997/05/21 16:01:56 pvmsrc * Updated ifdefs to include AIX4MP arch type. * * Revision 1.2 1997/01/28 19:28:23 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:43:33 pvmsrc * Initial revision * * Revision 1.13 1995/11/09 20:42:49 manchek * use add_then_test instead of test_then_add (SGI) * * Revision 1.12 1995/07/24 18:29:56 manchek * added message header fields to shmpkhdr * * Revision 1.11 1995/07/20 16:11:17 manchek * added ph_cod to packet header; isn't a shared value * * Revision 1.10 1995/07/05 16:17:49 manchek * added pidtid entry state ST_FINISH * * Revision 1.9 1995/07/03 19:14:24 manchek * added USERECVSEMAPHORE flag to simplify ifdefs. * added pt_key and pt_cond fields to pidtid table, p_key to struct peer * * Revision 1.8 1995/06/28 16:43:04 manchek * added mb_attached to struct msgboxhdr. * severe tidyup * * Revision 1.7 1995/06/12 16:26:28 manchek * changed SGI PAGEUNLOCK to test_and_set * * Revision 1.6 1995/05/24 19:08:52 manchek * changed HPPA shared memory name to HPPAMP * * Revision 1.5 1995/05/22 19:55:50 manchek * added ifdefs for RS6KMP * * Revision 1.4 1995/05/17 16:49:29 manchek * changes from Convex and SGI * * Revision 1.3 1994/11/08 15:38:05 manchek * shared memory damage control * */ /* * Page Layout * _________________ * | lock | \ * |_________________| \ PVMPAGEHDR * | ref count | / * |=================| / * | | * | frag | * | . | * | . | * | . | */ #ifdef IMA_SYMM #define PVMPAGEHDR 16 #define PVM_INITLOCK(cp) s_init_lock((slock_t)(cp)) #define PVM_LOCK(cp) s_lock((slock_t)(cp)) #define PVM_UNLOCK(cp) s_unlock((slock_t)(cp)) #endif /*IMA_SYMM*/ /* page header and incoming message box header */ #ifdef IMA_KSR1 struct shmpghdr { int pg_ref; /* count */ #define pg_lock pg_ref }; struct msgboxhdr { int mb_read; /* message last read */ int mb_last; /* message last received */ #define mb_lock mb_read int mb_attached; /* used for connection ack */ }; #define PVMPAGEHDR sizeof(struct shmpghdr) #define PAGELOCK(cp) _gspwt(cp) #define PAGEUNLOCK(cp) _rsp(cp) #define _SC_PAGESIZE _SC_PAGE_SIZE #endif /*IMA_KSR1*/ #ifdef IMA_ALPHAMP #include struct shmpghdr { msemaphore pg_lock; /* mutex lock */ int pg_priv; /* TRUE if page is private */ int pg_ref; /* reference count */ }; struct msgboxhdr { msemaphore mb_lock; /* mutex lock */ int mb_read; /* message last read */ int mb_last; /* message last received */ int mb_sleep; /* Is task blocked on a semaphore? */ int mb_attached; /* used for connection ack */ }; #define USERECVSEMAPHORE 1 #define PVMPAGEHDR sizeof(struct shmpghdr) #define PAGEINITLOCK(lp) msem_init((lp), MSEM_UNLOCKED) #define PAGELOCK(lp) msem_lock((lp), 0) #define PAGEUNLOCK(lp) msem_unlock((lp), 0) #endif /*IMA_ALPHAMP*/ #if defined(IMA_RS6KMP) || defined(IMA_AIX4MP) || defined(IMA_AIX5MP) #include struct shmpghdr { pthread_mutex_t pg_lock; /* mutex lock */ int pg_priv; /* TRUE if page is private */ int pg_ref; /* reference count */ }; struct msgboxhdr { pthread_mutex_t mb_lock; /* mutex lock */ int mb_read; /* message last read */ int mb_last; /* message last received */ int mb_sleep; /* Is task blocked on a semaphore? */ int mb_attached; /* used for connection ack */ pthread_cond_t mb_cond; /* condition to block on */ }; #define PVMPAGEHDR sizeof(struct shmpghdr) #define PAGEINITLOCK(lp) pthread_mutex_init((lp), NULL) #define PAGELOCK(lp) pthread_mutex_lock(lp) #define PAGEUNLOCK(lp) pthread_mutex_unlock(lp) #endif /*IMA_RS6KMP and AIX4MP and AIX5MP */ #ifdef IMA_SUNMP #include #include #include struct shmpghdr { #ifdef PVMUSEMUTEX mutex_t pg_lock; /* mutex lock */ #else volatile int pg_lock; /* shema lock */ #endif /* PVMUSEMUTEX */ int pg_priv; /* TRUE if page is private */ int pg_ref; /* reference count */ }; struct msgboxhdr { #ifdef PVMUSEMUTEX mutex_t mb_lock; /* mutex lock */ #else volatile int mb_lock; /* shema lock */ #endif /* PVMUSEMUTEX */ int mb_read; /* message last read */ int mb_last; /* message last received */ int mb_sleep; /* Is task blocked on a semaphore? */ int mb_attached; /* used for connection ack */ cond_t mb_cond; /* condition to block on */ }; #define PVMPAGEHDR sizeof(struct shmpghdr) #ifdef PVMUSEMUTEX /* If we use mutex and cond vars instead of semas */ #define PAGEINITLOCK(lp) mutex_init((lp), USYNC_PROCESS, 0) #define PAGELOCK(lp) mutex_lock(lp) #define PAGEUNLOCK(lp) mutex_unlock(lp) #endif /* PVMUSEMUTEX */ #ifndef PVMUSEMUTEX /* If no mutex then use Test And Set and semaphores */ #define USERECVSEMAPHORE 1 #define PAGEINITLOCK(lp) (*(lp) = 0) #define PAGELOCK(lp) while (Test_and_Set(lp, 1L)); #define PAGEUNLOCK(lp) Test_and_Set(lp,0L) #endif /* No PVMUSEMUTEX*/ #endif /*IMA_SUNMP*/ #if defined(IMA_SGIMP) || defined(IMA_SGIMP6) || defined(IMA_SGIMP64) #include struct shmpghdr { unsigned long pg_lock; int pg_priv; /* TRUE if page is private */ unsigned long pg_ref; /* reference count */ }; struct msgboxhdr { unsigned long mb_lock; /* mutex lock */ int mb_read; /* message last read */ int mb_last; /* message last received */ int mb_sleep; /* Is task blocked on a semaphore? */ int mb_attached; /* used for connection ack */ }; #define USERECVSEMAPHORE 1 #define PAGEINITLOCK(lp) (*(lp) = 0) #define PAGELOCK(lp) while (test_and_set(lp, 1L)) ; #define PAGEUNLOCK(lp) test_and_set(lp, 0L) #define TEST_ADD(addr,inc) add_then_test(addr, (long)inc) #define PVMPAGEHDR sizeof(struct shmpghdr) #endif /*IMA_SGIMP || IMA_SGIMP6 || IMA_SGIMP64*/ #if defined(IMA_CSPP) || defined(IMA_HPPAMP) #include #define _SC_PAGESIZE _SC_PAGE_SIZE /* shmat is guaranteed to return value that is page aligned, so lock is already aligned */ typedef struct pvmspplock_s { char lock [64]; } pvmspplock_t; struct shmpghdr { pvmspplock_t pg_lock; int pg_priv; /* TRUE if page is private */ int pg_ref; /* reference count */ }; struct msgboxhdr { pvmspplock_t mb_lock; int mb_read; /* message last read */ int mb_last; /* message last received */ int mb_sleep; /* Is task blocked on a semaphore? */ int mb_attached; /* used for connection ack */ }; #ifdef IMA_CSPP #include int cnx_getpattr(); int get_scid(); #endif key_t pvmkey __ProtoGlarp__((int)); void init_lock __ProtoGlarp__((pvmspplock_t *, char *, int)); int acquire_lock __ProtoGlarp__((pvmspplock_t *, char *, int)); int release_lock __ProtoGlarp__((pvmspplock_t *, char *, int)); int __ldcws32 __ProtoGlarp__((int *)); #define USERECVSEMAPHORE 1 #define PAGEINITLOCK(lp) init_lock(lp, __FILE__, __LINE__) #define PAGELOCK(lp) acquire_lock(lp, __FILE__, __LINE__) #define PAGEUNLOCK(lp) release_lock(lp, __FILE__, __LINE__) #define PVMPAGEHDR sizeof(struct shmpghdr) #endif /* IMA_CSPP || IMA_HPPAMP */ /* header of pid -> tid table */ struct pidtidhdr { int i_proto; /* t-d protocol */ int i_dsig; /* native data format */ int i_next; /* pointer to next (maybe) free pidtid */ int i_bufsiz; /* shared-memory buffer size */ int i_dpid; /* pvmd's Unix proc ID */ }; /* pid -> tid table entry */ struct pidtid { int pt_pid; /* Unix proc id */ int pt_tid; /* PVM task id */ int pt_ptid; /* PVM parent task id */ int pt_stat; /* Is it ready to recv msg? */ int pt_key; /* Shared memory segment key */ int pt_cond; /* Task status cue to pvmd */ #ifdef IMA_CSPP int pt_node; /* node number */ #endif }; #define ST_NOTREADY 0 /* not ready */ #define ST_SHMEM 1 /* has shared-memory buffer */ #define ST_SOCKET 2 /* has socket connection */ #define ST_FINISH 3 /* task exited */ #define ST_EXIT -1 /* misnomer for "slot not in use" */ /* packet header */ struct shmpkhdr { int ph_src; /* source tid */ int ph_dst; /* destination tid */ int ph_sdr; /* sender's tid */ int ph_dat; /* relative page address in sender's buf */ int ph_len; /* length of data (after assumed header pad) */ int ph_flag; /* fragment flags */ int ph_tag; /* message type tag */ int ph_ctx; /* message context */ int ph_enc; /* message encoding */ int ph_wid; /* message wait context id */ int ph_crc; /* message checksum */ }; /* tasks whose msg buf has been mapped into our address space */ struct peer { struct peer *p_link; /* dll */ struct peer *p_rlink; int p_tid; /* task ID */ int p_key; /* shared-memory/semaphore key */ int p_shmid; /* shared-memory ID of msg buffer */ int p_semid; /* semaphore ID */ char *p_buf; /* peer's msg buffer */ char *p_dbuf; /* my dynamic buffer for this guy */ int p_dlen; /* size of dynamic buffer */ int p_exited; /* task exit flag */ #ifdef IMA_CSPP int p_node; /* node number */ #endif }; #ifdef IMA_CSPP #define MAXFRAGSIZE 0x4000 /* max fragment size (16K) */ #define FRAGPAGE 4 /* number of pages in each fragment */ #define SHMBUFSIZE 0x180000 /* 1.5 MB of shared msg buffer for each task */ #else #define MAXFRAGSIZE 0x100000 /* max fragment size (4K) */ /* now... 256K? */ #define FRAGPAGE 1 /* number of pages in each fragment */ #define SHMBUFSIZE 0x100000 /* 1 MB of shared msg buffer for each task */ #endif #define INBOXPAGE 5 /* size of incoming box (number of pages) */ #define PERMS 0600 /* permissions for shared-memory msg buffers */ #define BUSYWAIT 1000000 /* max wait cycles before backing off */ #define PVMSHMFILE "%s/pvmshm.%d" /* file to map to shared memory */ struct peer *peer_conn __ProtoGlarp__((int tid, int *new_connection)); void peer_init __ProtoGlarp__((void)); void peer_wake __ProtoGlarp__((struct peer *pp)); void peer_cleanup __ProtoGlarp__((void)); ./pvm3/src/pvmshmmsg.h0100644007401100000360000001056406417163350014074 0ustar kohlgopher /* $Id: pvmshmmsg.h,v 1.1 1997/10/09 14:15:04 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmshmmsg.h * * structures and prototypes to handle asynchronous message primitives * for shared memory machines. * */ #ifndef __PVMSHMMSG_H__ #define __PVMSHMMSG_H__ #define NSHMMIDS 1024 /* Already define in pvmmimd.h * #define MAXNODES 128 */ #define NOBUFFER 0 #define ISRECVMSG 1 #define ISSENDMSG 2 #define BUFINFLUX 4 #define COMPLETE 8 #define ISALLOCED 16 #define SHM_OWNER 1 #define SHM_NOTOWNER 0 #define LOCK_OWNER 1 #define LOCK_NOTOWNER 0 #ifdef IMA_CSPP #define SHMIDPIDPART 0xfff #endif #ifndef SHMIDUIDPART #define SHMIDUIDPART 0xffff0000 #endif #ifndef SHMIDPIDPART #define SHMIDPIDPART 0xffff #endif #define PERMS 0600 #define CTRLPAGELEN MAXFRAGSIZE #define SHMSEGLEN 0x100000 /* 1 Meg Buffering */ #define MAXMSGS ((SHMSEGLEN/MAXFRAGSIZE)-1) #define TAGENTRY 0 #define LENENTRY 1 #define SRCENTRY 2 typedef int PVM_LOCK; struct shm_midlist { int ml_status; /* status? send, receive, complete */ int ml_src; /* source of the message, if recv */ int ml_dst; /* destination if send */ int ml_tag; /* tag of message */ char *ml_buf; /* buffer to send/recv */ int ml_len; /* length of the buffer */ int *ml_info; /* vector for src, tag, len on recv for caller */ struct segdesc *shmseg; /* shared segment to use */ int shm_msgnum; /* message num in the shared structure */ struct shm_midlist *ml_link; /* might put these in a list */ struct shm_midlist *ml_rlink; }; struct msginfo { int mi_status; int mi_src; int mi_tag; int mi_len; int mi_midlistId; int mi_offset; }; struct msgctrl { int nattach; /* number attached to this shared memory seg */ int len; /* total length of the this segment */ int nmsgs; /* how many msgs are posted for receive */ int maxmsgs; /* max number of receives that can be posted */ struct msginfo msgs[MAXMSGS]; }; struct segdesc { PVM_LOCK lock; char *start; int len; int segid; int bound; int iAmOwner; int (*pagelock) __ProtoGlarp__( (PVM_LOCK) ); int (*pageunlock) __ProtoGlarp__( (PVM_LOCK) ); struct msgctrl *segControl; struct shm_midlist *sendq; struct shm_midlist *recvq; }; struct keylist { key_t shared_key; key_t lock_key; }; /* -------- Prototypes --------- */ struct segdesc *pvm_shmget __ProtoGlarp__(( key_t, int, int )); char *pvm_shmat __ProtoGlarp__(( struct segdesc * )); int pvm_lockget __ProtoGlarp__(( key_t, struct segdesc *, int )); int pvm_lockdt __ProtoGlarp__(( struct segdesc * )); int pvm_msgctrlInit __ProtoGlarp__(( struct msgctrl *, int, int, int )); int pvm_shmdt __ProtoGlarp__(( struct segdesc * )); int pvm_shmlock __ProtoGlarp__(( PVM_LOCK )); int pvm_shmmsgdone __ProtoGlarp__(( int )); int pvm_shmmsginit __ProtoGlarp__(( key_t, struct segdesc * )); int pvm_shmunlock __ProtoGlarp__(( PVM_LOCK )); int pvm_irecvshm __ProtoGlarp__(( struct segdesc *, char *, int, int, int )); int pvm_isendshm __ProtoGlarp__(( struct segdesc *, char *, int, int, int, int * )); /* --------- ProtoTypes that should be supplied by the system ------- */ #if defined(IMA_SUN4) || defined(IMA_SUNMP) char * shmat __ProtoGlarp__(( int, char *, int)); #endif #endif /* __PVMSHMMSG_H__ */ ./pvm3/src/pvmwin.h0100644007401100000360000000637306651140121013365 0ustar kohlgopher /* $Id: pvmwin.h,v 1.2 1999/01/19 17:26:41 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer, * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* cruft file for different compiler specifications * like Watcom, Visual, Borland ... * * added __fortran stub 06/21/1997 Fischer */ #ifdef WIN32 #define __fortran __stdcall #endif #define STRICT #include #include #include #include #include /* WIN32 gets stdarg.h via pvm3.h -> pvmwin.h -> windows.h nice coding trail - NOT... since WIN32 is not a __STDC__ environment - it needs varargs.h so, this will cleanup the incorrect include order for var args from windows.h first must remove va_start va_end to avoid compiler warnings... Someone else must then include the varargs.h file or that will then cause error. uggghhhhh... this is ugly coding at its best */ #ifdef WIN32 #undef va_start #undef va_end #endif #include #include #ifndef HASSTDLIB #define HASSTDLIB #endif #ifndef SYSVBFUNC #define SYSVBFUNC #endif #ifndef SYSVSTR #define SYSVSTR #endif #ifndef HASERRORVARS #define HASERRORVARS #endif #ifndef NOWAIT3 #define NOWAIT3 #endif #ifndef NOGETDTBLSIZ #define NOGETDTBLSIZ #endif #ifndef ARCHCLASS #define ARCHCLASS "WIN32" #endif #ifndef NOUNIXDOM #define NOUNIXDOM #endif #ifndef NOTMPNAM #define NOTMPNAM #endif #ifndef HASERRORVARS #define HASERRORVARS #endif /* sys/param.h doesn't exist: */ #define MAXHOSTNAMELEN 64 #define MAXPATHLEN 64 #ifndef TIME #define TIME struct timezone { int tz_minuteswest; int tz_dsttime; }; #endif /* to keep the compiler satisfied */ extern int gettimeofday(struct timeval *, struct timezone *); extern char *MyGetUserName(); extern int kill(int,int, int); extern HANDLE win32_open_file( char *); extern HANDLE win32_create_file(char *s, int ); extern int win32_close_file(HANDLE); extern int win32_write_file(HANDLE,char *,int); extern int win32_read_file(HANDLE,char *, int); extern int win32_write_socket (SOCKET, const char FAR *, int); extern int win32_read_socket (SOCKET, char FAR *, int); extern void Wait(HANDLE id, DWORD *prv); ./pvm3/src/task.h0100644007401100000360000001522207122452565013014 0ustar kohlgopher /* $Id: task.h,v 1.10 2000/06/16 16:27:33 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * task.h * * Task descriptors. * * $Log: task.h,v $ * Revision 1.10 2000/06/16 16:27:33 pvmsrc * DAMN. The seemingly cool and efficient tp->t_flag / TF_MBNOTIFY * solution is not as cool as previously thought. * - each pvmd only keeps a *local* tasks table...! D-OH! * - need to just search the wait context list for an existing * WT_TASKX mbox notify, as previously feared. * - already checking wait context list for WT_RECVINFO, so this * is not too terrible... * - Damn, though... * Removed TF_MBNOTIFY contant - now fricking useless. * (Spanker=kohl) * * Revision 1.9 2000/06/13 22:37:25 pvmsrc * Added new task flag (tp->t_flag): * - TF_MBNOTIFY for marking whether a task has had a mbox notify * set up or not. * - to avoid a HUGE number of redundant notifies for multiple * inserts by the same task. D-Oh! * (Spanker=kohl) * * Revision 1.8 1999/07/08 19:00:25 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.7 1997/07/02 20:27:34 pvmsrc * Fixed startup race on shmem to that a shmem task can get fully * configured before getting any messages. * This involved adding two states * TF_PRESHMCONN and TF_SHM. TF_PRESHMCONN indicates that messages * with MM_PRIO set can be sent to a task, but regular messages are * queued. This allows shmem tasks to be completely configured * before any messages flow. When the daemon changes the state from * TF_PRESHMCONN to TF_SHMCONN it calls shm_wrt_pkts to write any * packets that were queued before task state changed to TF_SHMCONN. * * Revision 1.6 1997/06/27 20:05:58 pvmsrc * Integrated WIN32 changes. * * Revision 1.5 1997/06/27 19:22:09 pvmsrc * Task struct updated to hold message state info about its last message * to the RM. * Avoids duplicate messages and helps migrated/new RMs understand task * state. * * Revision 1.4 1997/05/27 14:44:11 pvmsrc * Added TF_SHMCONN for tasks that connect via shared memory instead * of sockets. * * Revision 1.3 1997/01/28 19:28:25 pvmsrc * New Copyright Notice & Authors. * * Revision 1.2 1996/10/24 21:47:19 pvmsrc * Added new TF_ISTRACER constant for tracer tasks. * * Revision 1.1 1996/09/23 23:43:35 pvmsrc * Initial revision * * Revision 1.4 1995/07/03 19:08:36 manchek * added TF_DEADSND flag * * Revision 1.3 1994/10/15 19:33:47 manchek * added TF_FORKD flag * * Revision 1.2 1994/06/03 20:38:28 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:26:52 manchek * Initial revision * */ /* descriptor for a pvm task */ struct task { struct task *t_link; /* complete list ordered by tid */ struct task *t_rlink; struct task *t_plink; /* partial list ordered by pid */ struct task *t_prlink; int t_tid; /* task id */ #ifdef WIN32 int t_handle; /* task handle */ #endif int t_ptid; /* parent task id */ int t_flag; /* status */ int t_pid; /* unix pid */ int t_sock; /* t-d tcp socket */ struct sockaddr_in t_sad; /* addr of sock */ int t_salen; /* addr length */ struct waitc *t_wait; /* wait channel */ struct pkt *t_txq; /* to task */ struct pkt *t_rxp; /* pkt reassembly from task */ struct pmsg *t_rxm; /* to-us msg reassembly from task */ int t_out; /* pipe from stdout/err */ char *t_authnam; /* d-auth file name */ int t_authfd; /* d-auth file desc */ char *t_a_out; /* a.out name (info only) */ struct mca *t_mca; /* mca currently in use by task */ int t_outtid; /* dst for stdout data */ int t_outctx; int t_outtag; int t_trctid; /* dst for trace data */ int t_trcctx; int t_trctag; int t_sched; /* scheduler responsible for task */ int t_schedlmsg; /* Last message to scheduler */ int t_status; /* unix exit status and code */ struct timeval t_utime; /* user time used */ struct timeval t_stime; /* system time used */ struct ccon *t_ccs; /* list of context ids owned by task */ }; /* to reserve communication contexts */ struct ccon { struct ccon *c_link; /* complete list ordered by cid */ struct ccon *c_rlink; struct ccon *c_peer; /* list attached to an owner */ struct ccon *c_rpeer; int c_cid; /* context id */ int c_tid; /* owner */ }; /* t_flag bits */ #define TF_FORKD 2 /* task process is child of pvmd */ #define TF_CONN 4 /* task is connected */ #define TF_AUTH 8 /* task needs to auth */ #define TF_CLOSE 16 /* should delete ctx after flush msgs */ #define TF_DEADSND 32 /* task is deadlocked needing shmem */ #define TF_SHMCONN 64 /* task is connected via shmem */ #define TF_ISSCHED 0x100 /* task is scheduler */ #define TF_ISHOSTER 0x200 /* task is hoster */ #define TF_ISTASKER 0x400 /* task is tasker */ #define TF_ISTRACER 0x800 /* task is tracer */ #define TF_PRESHMCONN 0x1000 /* task is pre-connected via shmem, */ /* can send msgs w/MM_PRIO flag set */ #define TF_SHM 0x2000 #define ISLOCLTASK(x) (((x)&tidhmask)==(hosts->ht_local<<(ffs(tidhmask)-1))) void task_init __ProtoGlarp__(( void )); int tid_new __ProtoGlarp__(( void )); struct task *task_new __ProtoGlarp__(( int tid )); struct task *task_find __ProtoGlarp__(( int tid )); struct task *task_findpid __ProtoGlarp__(( int pid )); void task_setpid __ProtoGlarp__(( struct task *tp, int pid )); void task_cleanup __ProtoGlarp__(( struct task *tp )); void task_free __ProtoGlarp__(( struct task *tp )); struct ccon *ccon_new __ProtoGlarp__(( struct task *tp )); ./pvm3/src/tevmac.h0100644007401100000360000001431706741172511013331 0ustar kohlgopher /* $Id: tevmac.h,v 1.8 1999/07/08 19:00:25 kohl Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * tevmac.h * * Tracing defs. * * $Log: tevmac.h,v $ * Revision 1.8 1999/07/08 19:00:25 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.7 1998/03/04 18:54:26 pvmsrc * Oops... better initialize pvmampushed to 0 in TEV_DECL. * - otherwise, TEV_AMPUSHED might reference it before set... :-Q * (Spanker=kohl) * * Revision 1.6 1997/12/23 20:24:43 pvmsrc * Added new TEV_PUSHTOP, TEV_AMPUSHED and TEV_POPTOP macros. * - to fake top level tracing, i.e. "push" the current tracing * depth and turn on full tracing again (until next "pop"). * - for things like message handler functions whose whole existence * is inside another PVM call. * Renamed "xamtraced" local trace var (TEV_DECLS). * -> "pvmamtraced", no chance of name clashes... (ha ha) * (Spanker=kohl) * * Revision 1.5 1997/06/25 22:11:13 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.4 1997/04/30 21:33:25 pvmsrc * SGI Compiler Warning Cleanup. * - stupid ##@%&@(... made explicit boolean expressions out of * assignments inside TEV_EXCLUSIVE conditional. :-Q * * Revision 1.3 1997/01/28 19:28:35 pvmsrc * New Copyright Notice & Authors. * * Revision 1.2 1996/10/24 21:49:50 pvmsrc * Modified for New Tracing Facility: * - added new struct pvmtrcencvec for trace event packing. * - modified tracing macros: * * TEV_DO_TRACE() requires 2 args now, kind & entry_exit. * * TEV_FIN(), tev_fin() now requires no args. * * TEV_DECLS, no need for xtrcbuf, xtrcsbf now. * - added TEV_PACK_*() macros for trace event contents, * for performance, uses enc_*() routines directly. * * Revision 1.1 1996/09/23 23:43:37 pvmsrc * Initial revision * * Revision 1.1 1994/06/03 20:38:32 manchek * Initial revision * */ /***************************** ** Internal Trace Structs ** ** ** *****************************/ struct pvmtrcencvec { int (*enc_byte)(); int (*enc_cplx)(); int (*enc_dcplx)(); int (*enc_double)(); int (*enc_float)(); int (*enc_int)(); int (*enc_uint)(); int (*enc_long)(); int (*enc_ulong)(); int (*enc_short)(); int (*enc_ushort)(); int (*enc_str)(); }; void tev_init(); void tev_flush(); /***************************** ** Internal Trace Macros ** ** ** *****************************/ /* to check that task is connected without a function call */ #define BEATASK ( pvmmytid == -1 ? pvmbeatask() : 0 ) /* check tracing on event kind */ #define TEV_CHECK_TRACE( _kind ) \ ( !BEATASK && pvmtrc.trctid > 0 && pvmtrc.trctid != pvmmytid \ && TEV_MASK_CHECK( pvmtrc.tmask, _kind ) ) /* check tracing and generate start message */ #define TEV_DO_TRACE( _kind, _entry_exit ) \ ( TEV_CHECK_TRACE( _kind ) && tev_begin( _kind, _entry_exit ) ) #define TEV_FIN tev_fin() #define TEV_DECLS int pvmamtraced; \ int pvmampushed = 0; \ int pvmtoplvlsave; #define TEV_EXCLUSIVE ( (pvmamtraced = pvmtoplvl) != 0 \ && (pvmtoplvl = 0) == 0 ) #define TEV_AMEXCL pvmamtraced #define TEV_ENDEXCL ( pvmtoplvl = pvmamtraced ) #define TEV_PUSHTOP ( pvmtoplvlsave = pvmtoplvl, pvmtoplvl = 1, \ pvmampushed = 1 ) #define TEV_AMPUSHED pvmampushed #define TEV_POPTOP ( pvmtoplvl = pvmtoplvlsave, pvmampushed = 0 ) /* packing macros */ #define TEV_PACK_BYTE( _did, _array, _datap, _cnt, _std ) \ (pvmtrccodef->enc_byte)( _did, _array, \ (void *)(_datap), _cnt, _std ) #define TEV_PACK_CPLX( _did, _array, _datap, _cnt, _std ) \ (pvmtrccodef->enc_cplx)( _did, _array, \ (void *)(_datap), _cnt, _std ) #define TEV_PACK_DCPLX( _did, _array, _datap, _cnt, _std ) \ (pvmtrccodef->enc_dcplx)( _did, _array, \ (void *)(_datap), _cnt, _std ) #define TEV_PACK_DOUBLE( _did, _array, _datap, _cnt, _std ) \ (pvmtrccodef->enc_double)( _did, _array, \ (void *)(_datap), _cnt, _std ) #define TEV_PACK_FLOAT( _did, _array, _datap, _cnt, _std ) \ (pvmtrccodef->enc_float)( _did, _array, \ (void *)(_datap), _cnt, _std ) #define TEV_PACK_INT( _did, _array, _datap, _cnt, _std ) \ (pvmtrccodef->enc_int)( _did, _array, \ (void *)(_datap), _cnt, _std ) #define TEV_PACK_UINT( _did, _array, _datap, _cnt, _std ) \ (pvmtrccodef->enc_uint)( _did, _array, \ (void *)(_datap), _cnt, _std ) #define TEV_PACK_LONG( _did, _array, _datap, _cnt, _std ) \ (pvmtrccodef->enc_long)( _did, _array, \ (void *)(_datap), _cnt, _std ) #define TEV_PACK_ULONG( _did, _array, _datap, _cnt, _std ) \ (pvmtrccodef->enc_ulong)( _did, _array, \ (void *)(_datap), _cnt, _std ) #define TEV_PACK_SHORT( _did, _array, _datap, _cnt, _std ) \ (pvmtrccodef->enc_short)( _did, _array, \ (void *)(_datap), _cnt, _std ) #define TEV_PACK_USHORT( _did, _array, _datap, _cnt, _std ) \ (pvmtrccodef->enc_ushort)( _did, _array, \ (void *)(_datap), _cnt, _std ) #define TEV_PACK_STRING( _did, _array, _datap, _cnt, _std ) \ (pvmtrccodef->enc_str)( _did, _array, \ (void *)(_datap), _cnt, _std ) ./pvm3/src/tvdefs.h0100644007401100000360000000554606741172512013352 0ustar kohlgopher /* $Id: tvdefs.h,v 1.4 1999/07/08 19:00:26 kohl Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * tvdefs.h * * Timeval manipulation stuff. * * $Log: tvdefs.h,v $ * Revision 1.4 1999/07/08 19:00:26 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.3 1997/06/25 22:11:14 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.2 1997/01/28 19:28:36 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:43:39 pvmsrc * Initial revision * * Revision 1.2 1994/06/03 20:38:32 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:26:52 manchek * Initial revision * */ #define TVCLEAR(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0) #define TVISSET(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) #define TVXLTY(xtv, ytv) \ ((xtv)->tv_sec < (ytv)->tv_sec || \ ((xtv)->tv_sec == (ytv)->tv_sec && (xtv)->tv_usec < (ytv)->tv_usec)) #define TVXADDY(ztv, xtv, ytv) \ if (((ztv)->tv_usec = (xtv)->tv_usec + (ytv)->tv_usec) < 1000000) { \ (ztv)->tv_sec = (xtv)->tv_sec + (ytv)->tv_sec; \ } else { \ (ztv)->tv_usec -= 1000000; \ (ztv)->tv_sec = (xtv)->tv_sec + (ytv)->tv_sec + 1; \ } #define TVXSUBY(ztv, xtv, ytv) \ if ((xtv)->tv_usec >= (ytv)->tv_usec) { \ (ztv)->tv_sec = (xtv)->tv_sec - (ytv)->tv_sec; \ (ztv)->tv_usec = (xtv)->tv_usec - (ytv)->tv_usec; \ } else { \ (ztv)->tv_sec = (xtv)->tv_sec - (ytv)->tv_sec - 1; \ (ztv)->tv_usec = (xtv)->tv_usec + 1000000 - (ytv)->tv_usec; \ } #define TVDIVN(ytv, xtv, n) { \ (ytv)->tv_usec = \ (((xtv)->tv_usec + 1000000 * ((xtv)->tv_sec % (n))) / (n)); \ (ytv)->tv_sec = ((xtv)->tv_sec / (n)); } ./pvm3/src/waitc.h0100644007401100000360000001221706741172512013157 0ustar kohlgopher /* $Id: waitc.h,v 1.8 1999/07/08 19:00:26 kohl Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * waitc.h * * Wait context descriptors. * * $Log: waitc.h,v $ * Revision 1.8 1999/07/08 19:00:26 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.7 1997/06/25 22:11:15 pvmsrc * Markus adds his frigging name to the author list of * every file he ever looked at... * * Revision 1.6 1997/06/16 13:39:11 pvmsrc * Updated struct waitc_spawn to include additional start info required * by the GRM. * * Revision 1.5 1997/04/10 17:51:39 pvmsrc * Added new wait context constant WT_RECVINFO. * - for blocking calls to pvm_recvinfo(). * * Revision 1.4 1997/04/08 17:27:26 pvmsrc * Added WT_RESET constant. * * Revision 1.3 1997/03/06 21:14:24 pvmsrc * take out names in prototype. * * Revision 1.2 1997/01/28 19:28:37 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:43:40 pvmsrc * Initial revision * * Revision 1.2 1994/06/03 20:38:33 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:26:52 manchek * Initial revision * */ /* Wait context info */ struct waitc { struct waitc *wa_link; /* list of all, ordered by wid */ struct waitc *wa_rlink; int wa_wid; /* unique identifier, >0 */ int wa_kind; /* why waiting */ int wa_on; /* entity waiting on */ int wa_tid; /* entity waiting */ int wa_dep; /* remote wait id that depends on us or 0 */ struct waitc *wa_peer; /* dll of peers, not sorted */ struct waitc *wa_rpeer; /* wait kind-specific stuff below */ struct pmsg *wa_mesg; /* message to be sent on completion */ int wa_count; /* number of times to trigger */ void *wa_spec; /* for kind-specific data */ }; /* Wait kinds */ #define WT_ADDHOST 1 /* hosts being added for us */ #define WT_SPAWN 2 /* tasks being spawned for us */ #define WT_HOSTSTART 3 /* hoster starting slaves for us */ #define WT_TASK 4 /* getting task list from other pvmds */ #define WT_DELHOST 5 /* hosts being deleted for us */ #define WT_HTUPD 6 /* host table update waiting to commit */ #define WT_PSTAT 7 /* query status of task */ #define WT_TASKX 8 /* waiting for task to exit */ #define WT_MSTAT 9 /* query status of host */ #define WT_DB 10 /* name-server query */ #define WT_HOSTF 11 /* waiting for host to fail */ #define WT_HOSTA 12 /* waiting for hosts to be added */ #define WT_HOSTSYNC 13 /* get remote time of day clock */ #define WT_TASKSTART 14 /* tasker starting task */ #define WT_ROUTEA 15 /* notify if route created */ #define WT_ROUTED 16 /* notify if route deleted */ #define WT_RESET 17 /* waiting for reset task to exit */ #define WT_RECVINFO 18 /* waiting for mbox entry put */ void wait_init __ProtoGlarp__(( int base, int range )); struct waitc *wait_new __ProtoGlarp__(( int kind )); struct waitc *wait_find __ProtoGlarp__(( int wid )); void wait_delete __ProtoGlarp__(( struct waitc *wp )); void wait_dump __ProtoGlarp__(( struct waitc *wp )); void wait_dumpall __ProtoGlarp__(( void )); struct waitc *wait_get __ProtoGlarp__(( struct hostd *, struct pmsg *, int )); struct waitc_spawn { char *w_file; /* executable name */ int w_flags; /* spawn flags */ int w_argc; /* length of argv */ char **w_argv; /* arg list */ struct htab *w_ht; /* set of usable hosts */ int *w_vec; /* result/status vector */ int w_veclen; /* length of wa_tids */ int w_togo; /* num of unresolved in vec */ int w_outtid; /* stdout dst */ int w_outctx; int w_outtag; int w_trctid; /* trace dst */ int w_trcctx; int w_trctag; int w_nenv; /* length of env */ char **w_env; /* envar list */ int w_ptid; /* parent task id */ int w_sched; /* task's scheduler */ int w_instance; /* we are the n'th task */ int w_hosttotal; /* how many on this host alone */ int w_outof; /* total to spawn */ }; struct waitc_add { int w_num; /* number of hosts */ struct hostd **w_hosts; /* vector of host entries */ }; ./pvm3/src/amem.s0100644007401100000360000000204706221620216012772 0ustar kohlgopher; $Id: amem.s,v 1.1 1996/09/23 23:43:10 pvmsrc Exp $ ; $CHeader: amem.s 1.3 1995/08/30 08:47:06 $ ; Copyright 1992 Convex Computer Corp. ; int __ldcws (void *addr) ; int __read32 (void *addr) ; int __synch () ; ; Note: addr must be on a 16 byte boundary. .space $TEXT$,sort=8 .subspa $CODE$,quad=0,align=8,access=44,code_only,sort=24 .export __ldcws32,entry,priv_lev=3,argw0=gr,rtnval=gr __ldcws32 .proc .callinfo caller,frame=0 .entry sync ldcws 0(0,%arg0),%ret0 nop bv %r0(%rp) .exit nop .procend .space $TEXT$ .subspa $CODE$ .export __read32,entry,priv_lev=3,argw0=gr,rtnval=gr __read32 .proc .callinfo caller,frame=0 .entry bv %r0(%rp) .exit ldws 0(0,%arg0),%ret0 .procend .space $TEXT$ .subspa $CODE$ .export __synch,entry,priv_lev=3,argw0=gr,rtnval=gr __synch .proc .callinfo caller,frame=0 .entry bv %r0(%rp) .exit sync .procend .end ./pvm3/src/tas.il0100644007401100000360000000015506564630045013015 0ustar kohlgopher .inline Test_and_Set,8 mov %o0,%o2 mov %o1,%o0 swap [%o2],%o0 .end ./pvm3/src/regex/0042755007401100000360000000000010117676455013022 5ustar kohlgopher./pvm3/src/regex/AUTHORS0100644007401100000360000000063006332404216014050 0ustar kohlgopherRichard Stallman -- original version and continuing revisions of regex.c and regex.h, and original version of the documentation. Karl Berry and Kathryn Hargreaves -- extensive modifications to above, and all test files. Jim Blandy -- original version of re_set_registers, revisions to regex.c. Joe Arceneaux, David MacKenzie, Mike Haertel, Charles Hannum, and probably others -- revisions to regex.c. ./pvm3/src/regex/COPYING0100644007401100000360000004307606332404217014047 0ustar kohlgopher GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ./pvm3/src/regex/configure0100755007401100000360000003000206332433724014711 0ustar kohlgopher#!/bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated automatically using autoconf. # Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # Usage: configure [--srcdir=DIR] [--host=HOST] [--gas] [--nfp] [--no-create] # [--prefix=PREFIX] [--exec-prefix=PREFIX] [--with-PACKAGE] [TARGET] # Ignores all args except --srcdir, --prefix, --exec-prefix, --no-create, and # --with-PACKAGE unless this script has special code to handle it. for arg do # Handle --exec-prefix with a space before the argument. if test x$next_exec_prefix = xyes; then exec_prefix=$arg; next_exec_prefix= # Handle --host with a space before the argument. elif test x$next_host = xyes; then next_host= # Handle --prefix with a space before the argument. elif test x$next_prefix = xyes; then prefix=$arg; next_prefix= # Handle --srcdir with a space before the argument. elif test x$next_srcdir = xyes; then srcdir=$arg; next_srcdir= else case $arg in # For backward compatibility, also recognize exact --exec_prefix. -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* | --exec=* | --exe=* | --ex=* | --e=*) exec_prefix=`echo $arg | sed 's/[-a-z_]*=//'` ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- | --exec | --exe | --ex | --e) next_exec_prefix=yes ;; -gas | --gas | --ga | --g) ;; -host=* | --host=* | --hos=* | --ho=* | --h=*) ;; -host | --host | --hos | --ho | --h) next_host=yes ;; -nfp | --nfp | --nf) ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre | --no-cr | --no-c | --no- | --no) no_create=1 ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=`echo $arg | sed 's/[-a-z_]*=//'` ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) next_prefix=yes ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=* | --s=*) srcdir=`echo $arg | sed 's/[-a-z_]*=//'` ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr | --s) next_srcdir=yes ;; -with-* | --with-*) package=`echo $arg|sed 's/-*with-//'` # Delete all the valid chars; see if any are left. if test -n "`echo $package|sed 's/[-a-zA-Z0-9_]*//g'`"; then echo "configure: $package: invalid package name" >&2; exit 1 fi eval "with_`echo $package|sed s/-/_/g`=1" ;; *) ;; esac fi done trap 'rm -f conftest* core; exit 1' 1 3 15 rm -f conftest* compile='${CC-cc} $CFLAGS $DEFS conftest.c -o conftest $LIBS >/dev/null 2>&1' # A filename unique to this package, relative to the directory that # configure is in, which we can look for to find out if srcdir is correct. unique_file=regex.c # Find the source files, if location was not specified. if test -z "$srcdir"; then srcdirdefaulted=yes # Try the directory containing this script, then `..'. prog=$0 confdir=`echo $prog|sed 's%/[^/][^/]*$%%'` test "X$confdir" = "X$prog" && confdir=. srcdir=$confdir if test ! -r $srcdir/$unique_file; then srcdir=.. fi fi if test ! -r $srcdir/$unique_file; then if test x$srcdirdefaulted = xyes; then echo "configure: Can not find sources in \`${confdir}' or \`..'." 1>&2 else echo "configure: Can not find sources in \`${srcdir}'." 1>&2 fi exit 1 fi # Preserve a srcdir of `.' to avoid automounter screwups with pwd. # But we can't avoid them for `..', to make subdirectories work. case $srcdir in .|/*|~*) ;; *) srcdir=`cd $srcdir; pwd` ;; # Make relative path absolute. esac if test -z "$CC"; then echo checking for gcc saveifs="$IFS"; IFS="${IFS}:" for dir in $PATH; do test -z "$dir" && dir=. if test -f $dir/gcc; then CC="gcc" break fi done IFS="$saveifs" fi test -z "$CC" && CC="cc" # Find out if we are using GNU C, under whatever name. cat > conftest.c < conftest.out 2>&1 if egrep yes conftest.out >/dev/null 2>&1; then GCC=1 # For later tests. fi rm -f conftest* # Make sure to not get the incompatible SysV /etc/install and # /usr/sbin/install, which might be in PATH before a BSD-like install, # or the SunOS /usr/etc/install directory, or the AIX /bin/install, # or the AFS install, which mishandles nonexistent args. (Sigh.) if test -z "$INSTALL"; then echo checking for install saveifs="$IFS"; IFS="${IFS}:" for dir in $PATH; do test -z "$dir" && dir=. case $dir in /etc|/usr/sbin|/usr/etc|/usr/afsws/bin) ;; *) if test -f $dir/install; then if grep dspmsg $dir/install >/dev/null 2>&1; then : # AIX else INSTALL="$dir/install -c" INSTALL_PROGRAM='$(INSTALL)' INSTALL_DATA='$(INSTALL) -m 644' break fi fi ;; esac done IFS="$saveifs" fi INSTALL=${INSTALL-cp} INSTALL_PROGRAM=${INSTALL_PROGRAM-'$(INSTALL)'} INSTALL_DATA=${INSTALL_DATA-'$(INSTALL)'} echo checking for AIX echo checking how to run the C preprocessor if test -z "$CPP"; then CPP='${CC-cc} -E' cat > conftest.c < EOF err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"` if test -z "$err"; then : else CPP=/lib/cpp fi rm -f conftest* fi cat > conftest.c < conftest.out 2>&1" if egrep "yes" conftest.out >/dev/null 2>&1; then DEFS="$DEFS -D_ALL_SOURCE=1" fi rm -f conftest* echo checking for DYNIX/ptx libseq cat > conftest.c < conftest.out 2>&1" if egrep "yes" conftest.out >/dev/null 2>&1; then SEQUENT=1 fi rm -f conftest* test -n "$SEQUENT" && test -f /usr/lib/libseq.a && LIBS="$LIBS -lseq" echo checking for POSIXized ISC if test -d /etc/conf/kconfig.d && grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1 then ISC=1 # If later tests want to check for ISC. DEFS="$DEFS -D_POSIX_SOURCE=1" if test -n "$GCC"; then CC="$CC -posix" else CC="$CC -Xp" fi fi echo checking for minix/config.h cat > conftest.c < EOF err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"` if test -z "$err"; then MINIX=1 fi rm -f conftest* # The Minix shell can't assign to the same variable on the same line! if test -n "$MINIX"; then DEFS="$DEFS -D_POSIX_SOURCE=1" DEFS="$DEFS -D_POSIX_1_SOURCE=2" DEFS="$DEFS -D_MINIX=1" fi echo checking for ANSI C header files cat > conftest.c < #include #include #include EOF err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"` if test -z "$err"; then # SunOS string.h does not declare mem*, contrary to ANSI. echo '#include ' > conftest.c eval "$CPP $DEFS conftest.c > conftest.out 2>&1" if egrep "memchr" conftest.out >/dev/null 2>&1; then # SGI's /bin/cc from Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. cat > conftest.c < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') #define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #define XOR(e,f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF eval $compile if test -s conftest && (./conftest; exit) 2>/dev/null; then DEFS="$DEFS -DSTDC_HEADERS=1" fi rm -f conftest* fi rm -f conftest* fi rm -f conftest* for hdr in string.h do trhdr=HAVE_`echo $hdr | tr '[a-z]./' '[A-Z]__'` echo checking for ${hdr} cat > conftest.c < EOF err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"` if test -z "$err"; then DEFS="$DEFS -D${trhdr}=1" fi rm -f conftest* done # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works # for constant arguments. Useless! echo checking for working alloca.h cat > conftest.c < main() { exit(0); } t() { char *p = alloca(2 * sizeof(int)); } EOF if eval $compile; then DEFS="$DEFS -DHAVE_ALLOCA_H=1" fi rm -f conftest* decl="#ifdef __GNUC__ #define alloca __builtin_alloca #else #if HAVE_ALLOCA_H #include #else #ifdef _AIX #pragma alloca #else char *alloca (); #endif #endif #endif " echo checking for alloca cat > conftest.c < conftest.c < config.status </dev/null`: # # $0 $* for arg do case "\$arg" in -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) exec /bin/sh $0 $* ;; *) echo "Usage: config.status --recheck" 2>&1; exit 1 ;; esac done #trap 'rm -f Makefile doc/Makefile test/Makefile; exit 1' 1 3 15 trap 'rm -f Makefile ; exit 1' 1 3 15 CC='$CC' INSTALL='$INSTALL' INSTALL_PROGRAM='$INSTALL_PROGRAM' INSTALL_DATA='$INSTALL_DATA' CPP='$CPP' ALLOCA='$ALLOCA' LIBS='$LIBS' srcdir='$srcdir' DEFS='$DEFS' prefix='$prefix' exec_prefix='$exec_prefix' prsub='$prsub' EOF cat >> config.status <<\EOF top_srcdir=$srcdir #for file in .. Makefile doc/Makefile test/Makefile; do if [ "x$file" != "x.." ]; then for file in .. Makefile ; do if [ "x$file" != "x.." ]; then srcdir=$top_srcdir # Remove last slash and all that follows it. Not all systems have dirname. dir=`echo $file|sed 's%/[^/][^/]*$%%'` if test "$dir" != "$file"; then test "$top_srcdir" != . && srcdir=$top_srcdir/$dir test ! -d $dir && mkdir $dir fi echo creating $file rm -f $file echo "# Generated automatically from `echo $file|sed 's|.*/||'`.in by configure." > $file sed -e " $prsub s%@CC@%$CC%g s%@INSTALL@%$INSTALL%g s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g s%@INSTALL_DATA@%$INSTALL_DATA%g s%@CPP@%$CPP%g s%@ALLOCA@%$ALLOCA%g s%@LIBS@%$LIBS%g s%@srcdir@%$srcdir%g s%@DEFS@%$DEFS% " $top_srcdir/${file}.in >> $file fi; done exit 0 EOF chmod +x config.status test -n "$no_create" || ./config.status ./pvm3/src/regex/configure.in0100644007401100000360000000066706332404222015320 0ustar kohlgopherdnl Process this file with autoconf to produce a configure script. AC_INIT(regex.c) AC_PROG_CC AC_PROG_INSTALL dnl I'm not sure if AC_AIX and AC_DYNIX_SEQ are really necessary. The dnl Autoconf documentation isn't specific about which BSD functions they dnl provide. AC_AIX AC_DYNIX_SEQ AC_ISC_POSIX AC_MINIX AC_STDC_HEADERS AC_HAVE_HEADERS(string.h) AC_ALLOCA AC_CONST AC_PREFIX(gcc) AC_OUTPUT(Makefile doc/Makefile test/Makefile) ./pvm3/src/regex/pvmregex.c0100644007401100000360000000531306427726460015021 0ustar kohlgopher static char rcsid[] = "$Id: pvmregex.c,v 1.3 1997/11/04 23:18:08 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ #include #include #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef STDC_HEADERS #include #else char *malloc (); char *realloc (); #endif #ifdef SYSVSTR #include #else #include #endif #include "regex.h" void * pvmcompileregex( pattern ) char *pattern; { struct re_pattern_buffer *pattbuff; char *patterr; pattbuff = (struct re_pattern_buffer *) malloc( sizeof( struct re_pattern_buffer ) ); pattbuff->translate = (char *) NULL; pattbuff->fastmap = (char *) NULL; pattbuff->buffer = (unsigned char *) NULL; pattbuff->allocated = (long) 0; patterr = (char *) re_compile_pattern( pattern, strlen( pattern ), pattbuff ); if ( patterr ) { printf( "Error Compiling Pattern \"%s\":\n\t%s\n", pattern, patterr ); return( (void *) NULL ); } return( (void *) pattbuff ); } int pvmmatchregex( vpattbuff, str ) void *vpattbuff; char *str; { struct re_pattern_buffer *pattbuff; int len; pattbuff = (struct re_pattern_buffer *) vpattbuff; len = strlen( str ); return( ( re_match( pattbuff, str, len, 0, (struct re_registers *) NULL ) == len ) ? 1 : 0 ); } void pvmfreeregex( vpattbuffp ) void **vpattbuffp; { struct re_pattern_buffer *pattbuff; if ( vpattbuffp == NULL ) return; pattbuff = (struct re_pattern_buffer *) *vpattbuffp; *vpattbuffp = (void *) NULL; regfree( (regex_t *) pattbuff ); free( pattbuff ); } ./pvm3/src/regex/regex.c0100644007401100000360000047422406651140150014272 0ustar kohlgopher/* Extended regular expression matching and search library, version 0.12. (Implements POSIX draft P10003.2/D11.2, except for internationalization features.) Copyright (C) 1993 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* AIX requires this to be the first thing in the file. */ #if defined (_AIX) && !defined (REGEX_MALLOC) #pragma alloca #endif #define _GNU_SOURCE /* We need this for `regex.h', and perhaps for the Emacs include files. */ #include #ifdef HAVE_CONFIG_H #include "config.h" #endif /* The `emacs' switch turns on certain matching commands that make sense only in Emacs. */ #ifdef emacs #include "lisp.h" #include "buffer.h" #include "syntax.h" /* Emacs uses `NULL' as a predicate. */ #undef NULL #else /* not emacs */ /* We used to test for `BSTRING' here, but only GCC and Emacs define `BSTRING', as far as I know, and neither of them use this code. */ #if HAVE_STRING_H || STDC_HEADERS #include #ifndef bcmp #define bcmp(s1, s2, n) memcmp ((s1), (s2), (n)) #endif #ifndef bcopy #define bcopy(s, d, n) memcpy ((d), (s), (n)) #endif #ifndef bzero #define bzero(s, n) memset ((s), 0, (n)) #endif #else #include #endif #ifdef STDC_HEADERS #include #else char *malloc (); char *realloc (); #endif /* Define the syntax stuff for \<, \>, etc. */ /* This must be nonzero for the wordchar and notwordchar pattern commands in re_match_2. */ #ifndef Sword #define Sword 1 #endif #ifdef SYNTAX_TABLE extern char *re_syntax_table; #else /* not SYNTAX_TABLE */ /* How many characters in the character set. */ #define CHAR_SET_SIZE 256 static char re_syntax_table[CHAR_SET_SIZE]; static void init_syntax_once () { register int c; static int done = 0; if (done) return; bzero (re_syntax_table, sizeof re_syntax_table); for (c = 'a'; c <= 'z'; c++) re_syntax_table[c] = Sword; for (c = 'A'; c <= 'Z'; c++) re_syntax_table[c] = Sword; for (c = '0'; c <= '9'; c++) re_syntax_table[c] = Sword; re_syntax_table['_'] = Sword; done = 1; } #endif /* not SYNTAX_TABLE */ #define SYNTAX(c) re_syntax_table[c] #endif /* not emacs */ /* Get the interface, including the syntax bits. */ #include "regex.h" /* isalpha etc. are used for the character classes. */ #include #ifndef isascii #define isascii(c) 1 #endif #ifdef isblank #define ISBLANK(c) (isascii (c) && isblank (c)) #else #define ISBLANK(c) ((c) == ' ' || (c) == '\t') #endif #ifdef isgraph #define ISGRAPH(c) (isascii (c) && isgraph (c)) #else #define ISGRAPH(c) (isascii (c) && isprint (c) && !isspace (c)) #endif #define ISPRINT(c) (isascii (c) && isprint (c)) #define ISDIGIT(c) (isascii (c) && isdigit (c)) #define ISALNUM(c) (isascii (c) && isalnum (c)) #define ISALPHA(c) (isascii (c) && isalpha (c)) #define ISCNTRL(c) (isascii (c) && iscntrl (c)) #define ISLOWER(c) (isascii (c) && islower (c)) #define ISPUNCT(c) (isascii (c) && ispunct (c)) #define ISSPACE(c) (isascii (c) && isspace (c)) #define ISUPPER(c) (isascii (c) && isupper (c)) #define ISXDIGIT(c) (isascii (c) && isxdigit (c)) #ifndef NULL #define NULL 0 #endif /* We remove any previous definition of `SIGN_EXTEND_CHAR', since ours (we hope) works properly with all combinations of machines, compilers, `char' and `unsigned char' argument types. (Per Bothner suggested the basic approach.) */ #undef SIGN_EXTEND_CHAR #if __STDC__ #define SIGN_EXTEND_CHAR(c) ((signed char) (c)) #else /* not __STDC__ */ /* As in Harbison and Steele. */ #define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128) #endif /* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we use `alloca' instead of `malloc'. This is because using malloc in re_search* or re_match* could cause memory leaks when C-g is used in Emacs; also, malloc is slower and causes storage fragmentation. On the other hand, malloc is more portable, and easier to debug. Because we sometimes use alloca, some routines have to be macros, not functions -- `alloca'-allocated space disappears at the end of the function it is called in. */ #ifdef REGEX_MALLOC #define REGEX_ALLOCATE malloc #define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize) #else /* not REGEX_MALLOC */ /* Emacs already defines alloca, sometimes. */ #ifndef alloca /* Make alloca work the best possible way. */ #ifdef __GNUC__ #define alloca __builtin_alloca #else /* not __GNUC__ */ #if HAVE_ALLOCA_H #include #else /* not __GNUC__ or HAVE_ALLOCA_H */ #ifndef _AIX /* Already did AIX, up at the top. */ char *alloca (); #endif /* not _AIX */ #endif /* not HAVE_ALLOCA_H */ #endif /* not __GNUC__ */ #endif /* not alloca */ #define REGEX_ALLOCATE alloca /* Assumes a `char *destination' variable. */ #define REGEX_REALLOCATE(source, osize, nsize) \ (destination = (char *) alloca (nsize), \ bcopy (source, destination, osize), \ destination) #endif /* not REGEX_MALLOC */ /* True if `size1' is non-NULL and PTR is pointing anywhere inside `string1' or just past its end. This works if PTR is NULL, which is a good thing. */ #define FIRST_STRING_P(ptr) \ (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) /* (Re)Allocate N items of type T using malloc, or fail. */ #define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t))) #define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) #define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) #define BYTEWIDTH 8 /* In bits. */ #define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b)) typedef char boolean; #define false 0 #define true 1 /* These are the command codes that appear in compiled regular expressions. Some opcodes are followed by argument bytes. A command code can specify any interpretation whatsoever for its arguments. Zero bytes may appear in the compiled regular expression. The value of `exactn' is needed in search.c (search_buffer) in Emacs. So regex.h defines a symbol `RE_EXACTN_VALUE' to be 1; the value of `exactn' we use here must also be 1. */ typedef enum { no_op = 0, /* Followed by one byte giving n, then by n literal bytes. */ exactn = 1, /* Matches any (more or less) character. */ anychar, /* Matches any one char belonging to specified set. First following byte is number of bitmap bytes. Then come bytes for a bitmap saying which chars are in. Bits in each byte are ordered low-bit-first. A character is in the set if its bit is 1. A character too large to have a bit in the map is automatically not in the set. */ charset, /* Same parameters as charset, but match any character that is not one of those specified. */ charset_not, /* Start remembering the text that is matched, for storing in a register. Followed by one byte with the register number, in the range 0 to one less than the pattern buffer's re_nsub field. Then followed by one byte with the number of groups inner to this one. (This last has to be part of the start_memory only because we need it in the on_failure_jump of re_match_2.) */ start_memory, /* Stop remembering the text that is matched and store it in a memory register. Followed by one byte with the register number, in the range 0 to one less than `re_nsub' in the pattern buffer, and one byte with the number of inner groups, just like `start_memory'. (We need the number of inner groups here because we don't have any easy way of finding the corresponding start_memory when we're at a stop_memory.) */ stop_memory, /* Match a duplicate of something remembered. Followed by one byte containing the register number. */ duplicate, /* Fail unless at beginning of line. */ begline, /* Fail unless at end of line. */ endline, /* Succeeds if at beginning of buffer (if emacs) or at beginning of string to be matched (if not). */ begbuf, /* Analogously, for end of buffer/string. */ endbuf, /* Followed by two byte relative address to which to jump. */ jump, /* Same as jump, but marks the end of an alternative. */ jump_past_alt, /* Followed by two-byte relative address of place to resume at in case of failure. */ on_failure_jump, /* Like on_failure_jump, but pushes a placeholder instead of the current string position when executed. */ on_failure_keep_string_jump, /* Throw away latest failure point and then jump to following two-byte relative address. */ pop_failure_jump, /* Change to pop_failure_jump if know won't have to backtrack to match; otherwise change to jump. This is used to jump back to the beginning of a repeat. If what follows this jump clearly won't match what the repeat does, such that we can be sure that there is no use backtracking out of repetitions already matched, then we change it to a pop_failure_jump. Followed by two-byte address. */ maybe_pop_jump, /* Jump to following two-byte address, and push a dummy failure point. This failure point will be thrown away if an attempt is made to use it for a failure. A `+' construct makes this before the first repeat. Also used as an intermediary kind of jump when compiling an alternative. */ dummy_failure_jump, /* Push a dummy failure point and continue. Used at the end of alternatives. */ push_dummy_failure, /* Followed by two-byte relative address and two-byte number n. After matching N times, jump to the address upon failure. */ succeed_n, /* Followed by two-byte relative address, and two-byte number n. Jump to the address N times, then fail. */ jump_n, /* Set the following two-byte relative address to the subsequent two-byte number. The address *includes* the two bytes of number. */ set_number_at, wordchar, /* Matches any word-constituent character. */ notwordchar, /* Matches any char that is not a word-constituent. */ wordbeg, /* Succeeds if at word beginning. */ wordend, /* Succeeds if at word end. */ wordbound, /* Succeeds if at a word boundary. */ notwordbound /* Succeeds if not at a word boundary. */ #ifdef emacs ,before_dot, /* Succeeds if before point. */ at_dot, /* Succeeds if at point. */ after_dot, /* Succeeds if after point. */ /* Matches any character whose syntax is specified. Followed by a byte which contains a syntax code, e.g., Sword. */ syntaxspec, /* Matches any character whose syntax is not that specified. */ notsyntaxspec #endif /* emacs */ } re_opcode_t; /* Common operations on the compiled pattern. */ /* Store NUMBER in two contiguous bytes starting at DESTINATION. */ #define STORE_NUMBER(destination, number) \ do { \ (destination)[0] = (number) & 0377; \ (destination)[1] = (number) >> 8; \ } while (0) /* Same as STORE_NUMBER, except increment DESTINATION to the byte after where the number is stored. Therefore, DESTINATION must be an lvalue. */ #define STORE_NUMBER_AND_INCR(destination, number) \ do { \ STORE_NUMBER (destination, number); \ (destination) += 2; \ } while (0) /* Put into DESTINATION a number stored in two contiguous bytes starting at SOURCE. */ #define EXTRACT_NUMBER(destination, source) \ do { \ (destination) = *(source) & 0377; \ (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \ } while (0) #ifdef DEBUG static void extract_number (dest, source) int *dest; unsigned char *source; { int temp = SIGN_EXTEND_CHAR (*(source + 1)); *dest = *source & 0377; *dest += temp << 8; } #ifndef EXTRACT_MACROS /* To debug the macros. */ #undef EXTRACT_NUMBER #define EXTRACT_NUMBER(dest, src) extract_number (&dest, src) #endif /* not EXTRACT_MACROS */ #endif /* DEBUG */ /* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. SOURCE must be an lvalue. */ #define EXTRACT_NUMBER_AND_INCR(destination, source) \ do { \ EXTRACT_NUMBER (destination, source); \ (source) += 2; \ } while (0) #ifdef DEBUG static void extract_number_and_incr (destination, source) int *destination; unsigned char **source; { extract_number (destination, *source); *source += 2; } #ifndef EXTRACT_MACROS #undef EXTRACT_NUMBER_AND_INCR #define EXTRACT_NUMBER_AND_INCR(dest, src) \ extract_number_and_incr (&dest, &src) #endif /* not EXTRACT_MACROS */ #endif /* DEBUG */ /* If DEBUG is defined, Regex prints many voluminous messages about what it is doing (if the variable `debug' is nonzero). If linked with the main program in `iregex.c', you can enter patterns and strings interactively. And if linked with the main program in `main.c' and the other test files, you can run the already-written tests. */ #ifdef DEBUG /* We use standard I/O for debugging. */ #include /* It is useful to test things that ``must'' be true when debugging. */ #include static int debug = 0; #define DEBUG_STATEMENT(e) e #define DEBUG_PRINT1(x) if (debug) printf (x) #define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2) #define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3) #define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4) #define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \ if (debug) print_partial_compiled_pattern (s, e) #define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \ if (debug) print_double_string (w, s1, sz1, s2, sz2) extern void printchar (); /* Print the fastmap in human-readable form. */ void print_fastmap (fastmap) char *fastmap; { unsigned was_a_range = 0; unsigned i = 0; while (i < (1 << BYTEWIDTH)) { if (fastmap[i++]) { was_a_range = 0; printchar (i - 1); while (i < (1 << BYTEWIDTH) && fastmap[i]) { was_a_range = 1; i++; } if (was_a_range) { printf ("-"); printchar (i - 1); } } } putchar ('\n'); } /* Print a compiled pattern string in human-readable form, starting at the START pointer into it and ending just before the pointer END. */ void print_partial_compiled_pattern (start, end) unsigned char *start; unsigned char *end; { int mcnt, mcnt2; unsigned char *p = start; unsigned char *pend = end; if (start == NULL) { printf ("(null)\n"); return; } /* Loop over pattern commands. */ while (p < pend) { switch ((re_opcode_t) *p++) { case no_op: printf ("/no_op"); break; case exactn: mcnt = *p++; printf ("/exactn/%d", mcnt); do { putchar ('/'); printchar (*p++); } while (--mcnt); break; case start_memory: mcnt = *p++; printf ("/start_memory/%d/%d", mcnt, *p++); break; case stop_memory: mcnt = *p++; printf ("/stop_memory/%d/%d", mcnt, *p++); break; case duplicate: printf ("/duplicate/%d", *p++); break; case anychar: printf ("/anychar"); break; case charset: case charset_not: { register int c; printf ("/charset%s", (re_opcode_t) *(p - 1) == charset_not ? "_not" : ""); assert (p + *p < pend); for (c = 0; c < *p; c++) { unsigned bit; unsigned char map_byte = p[1 + c]; putchar ('/'); for (bit = 0; bit < BYTEWIDTH; bit++) if (map_byte & (1 << bit)) printchar (c * BYTEWIDTH + bit); } p += 1 + *p; break; } case begline: printf ("/begline"); break; case endline: printf ("/endline"); break; case on_failure_jump: extract_number_and_incr (&mcnt, &p); printf ("/on_failure_jump/0/%d", mcnt); break; case on_failure_keep_string_jump: extract_number_and_incr (&mcnt, &p); printf ("/on_failure_keep_string_jump/0/%d", mcnt); break; case dummy_failure_jump: extract_number_and_incr (&mcnt, &p); printf ("/dummy_failure_jump/0/%d", mcnt); break; case push_dummy_failure: printf ("/push_dummy_failure"); break; case maybe_pop_jump: extract_number_and_incr (&mcnt, &p); printf ("/maybe_pop_jump/0/%d", mcnt); break; case pop_failure_jump: extract_number_and_incr (&mcnt, &p); printf ("/pop_failure_jump/0/%d", mcnt); break; case jump_past_alt: extract_number_and_incr (&mcnt, &p); printf ("/jump_past_alt/0/%d", mcnt); break; case jump: extract_number_and_incr (&mcnt, &p); printf ("/jump/0/%d", mcnt); break; case succeed_n: extract_number_and_incr (&mcnt, &p); extract_number_and_incr (&mcnt2, &p); printf ("/succeed_n/0/%d/0/%d", mcnt, mcnt2); break; case jump_n: extract_number_and_incr (&mcnt, &p); extract_number_and_incr (&mcnt2, &p); printf ("/jump_n/0/%d/0/%d", mcnt, mcnt2); break; case set_number_at: extract_number_and_incr (&mcnt, &p); extract_number_and_incr (&mcnt2, &p); printf ("/set_number_at/0/%d/0/%d", mcnt, mcnt2); break; case wordbound: printf ("/wordbound"); break; case notwordbound: printf ("/notwordbound"); break; case wordbeg: printf ("/wordbeg"); break; case wordend: printf ("/wordend"); #ifdef emacs case before_dot: printf ("/before_dot"); break; case at_dot: printf ("/at_dot"); break; case after_dot: printf ("/after_dot"); break; case syntaxspec: printf ("/syntaxspec"); mcnt = *p++; printf ("/%d", mcnt); break; case notsyntaxspec: printf ("/notsyntaxspec"); mcnt = *p++; printf ("/%d", mcnt); break; #endif /* emacs */ case wordchar: printf ("/wordchar"); break; case notwordchar: printf ("/notwordchar"); break; case begbuf: printf ("/begbuf"); break; case endbuf: printf ("/endbuf"); break; default: printf ("?%d", *(p-1)); } } printf ("/\n"); } void print_compiled_pattern (bufp) struct re_pattern_buffer *bufp; { unsigned char *buffer = bufp->buffer; print_partial_compiled_pattern (buffer, buffer + bufp->used); printf ("%d bytes used/%d bytes allocated.\n", bufp->used, bufp->allocated); if (bufp->fastmap_accurate && bufp->fastmap) { printf ("fastmap: "); print_fastmap (bufp->fastmap); } printf ("re_nsub: %d\t", bufp->re_nsub); printf ("regs_alloc: %d\t", bufp->regs_allocated); printf ("can_be_null: %d\t", bufp->can_be_null); printf ("newline_anchor: %d\n", bufp->newline_anchor); printf ("no_sub: %d\t", bufp->no_sub); printf ("not_bol: %d\t", bufp->not_bol); printf ("not_eol: %d\t", bufp->not_eol); printf ("syntax: %d\n", bufp->syntax); /* Perhaps we should print the translate table? */ } void print_double_string (where, string1, size1, string2, size2) const char *where; const char *string1; const char *string2; int size1; int size2; { unsigned this_char; if (where == NULL) printf ("(null)"); else { if (FIRST_STRING_P (where)) { for (this_char = where - string1; this_char < size1; this_char++) printchar (string1[this_char]); where = string2; } for (this_char = where - string2; this_char < size2; this_char++) printchar (string2[this_char]); } } #else /* not DEBUG */ #undef assert #define assert(e) #define DEBUG_STATEMENT(e) #define DEBUG_PRINT1(x) #define DEBUG_PRINT2(x1, x2) #define DEBUG_PRINT3(x1, x2, x3) #define DEBUG_PRINT4(x1, x2, x3, x4) #define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) #define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) #endif /* not DEBUG */ /* Set by `re_set_syntax' to the current regexp syntax to recognize. Can also be assigned to arbitrarily: each pattern buffer stores its own syntax, so it can be changed between regex compilations. */ reg_syntax_t re_syntax_options = RE_SYNTAX_EMACS; /* Specify the precise syntax of regexps for compilation. This provides for compatibility for various utilities which historically have different, incompatible syntaxes. The argument SYNTAX is a bit mask comprised of the various bits defined in regex.h. We return the old syntax. */ reg_syntax_t re_set_syntax (syntax) reg_syntax_t syntax; { reg_syntax_t ret = re_syntax_options; re_syntax_options = syntax; return ret; } /* This table gives an error message for each of the error codes listed in regex.h. Obviously the order here has to be same as there. */ static const char *re_error_msg[] = { NULL, /* REG_NOERROR */ "No match", /* REG_NOMATCH */ "Invalid regular expression", /* REG_BADPAT */ "Invalid collation character", /* REG_ECOLLATE */ "Invalid character class name", /* REG_ECTYPE */ "Trailing backslash", /* REG_EESCAPE */ "Invalid back reference", /* REG_ESUBREG */ "Unmatched [ or [^", /* REG_EBRACK */ "Unmatched ( or \\(", /* REG_EPAREN */ "Unmatched \\{", /* REG_EBRACE */ "Invalid content of \\{\\}", /* REG_BADBR */ "Invalid range end", /* REG_ERANGE */ "Memory exhausted", /* REG_ESPACE */ "Invalid preceding regular expression", /* REG_BADRPT */ "Premature end of regular expression", /* REG_EEND */ "Regular expression too big", /* REG_ESIZE */ "Unmatched ) or \\)", /* REG_ERPAREN */ }; /* Subroutine declarations and macros for regex_compile. */ static void store_op1 (), store_op2 (); static void insert_op1 (), insert_op2 (); static boolean at_begline_loc_p (), at_endline_loc_p (); static boolean group_in_compile_stack (); static reg_errcode_t compile_range (); /* Fetch the next character in the uncompiled pattern---translating it if necessary. Also cast from a signed character in the constant string passed to us by the user to an unsigned char that we can use as an array index (in, e.g., `translate'). */ #define PATFETCH(c) \ do {if (p == pend) return REG_EEND; \ c = (unsigned char) *p++; \ if (translate) c = translate[c]; \ } while (0) /* Fetch the next character in the uncompiled pattern, with no translation. */ #define PATFETCH_RAW(c) \ do {if (p == pend) return REG_EEND; \ c = (unsigned char) *p++; \ } while (0) /* Go backwards one character in the pattern. */ #define PATUNFETCH p-- /* If `translate' is non-null, return translate[D], else just D. We cast the subscript to translate because some data is declared as `char *', to avoid warnings when a string constant is passed. But when we use a character as a subscript we must make it unsigned. */ #define TRANSLATE(d) (translate ? translate[(unsigned char) (d)] : (d)) /* Macros for outputting the compiled pattern into `buffer'. */ /* If the buffer isn't allocated when it comes in, use this. */ #define INIT_BUF_SIZE 32 /* Make sure we have at least N more bytes of space in buffer. */ #define GET_BUFFER_SPACE(n) \ while (b - bufp->buffer + (n) > bufp->allocated) \ EXTEND_BUFFER () /* Make sure we have one more byte of buffer space and then add C to it. */ #define BUF_PUSH(c) \ do { \ GET_BUFFER_SPACE (1); \ *b++ = (unsigned char) (c); \ } while (0) /* Ensure we have two more bytes of buffer space and then append C1 and C2. */ #define BUF_PUSH_2(c1, c2) \ do { \ GET_BUFFER_SPACE (2); \ *b++ = (unsigned char) (c1); \ *b++ = (unsigned char) (c2); \ } while (0) /* As with BUF_PUSH_2, except for three bytes. */ #define BUF_PUSH_3(c1, c2, c3) \ do { \ GET_BUFFER_SPACE (3); \ *b++ = (unsigned char) (c1); \ *b++ = (unsigned char) (c2); \ *b++ = (unsigned char) (c3); \ } while (0) /* Store a jump with opcode OP at LOC to location TO. We store a relative address offset by the three bytes the jump itself occupies. */ #define STORE_JUMP(op, loc, to) \ store_op1 (op, loc, (to) - (loc) - 3) /* Likewise, for a two-argument jump. */ #define STORE_JUMP2(op, loc, to, arg) \ store_op2 (op, loc, (to) - (loc) - 3, arg) /* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */ #define INSERT_JUMP(op, loc, to) \ insert_op1 (op, loc, (to) - (loc) - 3, b) /* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */ #define INSERT_JUMP2(op, loc, to, arg) \ insert_op2 (op, loc, (to) - (loc) - 3, arg, b) /* This is not an arbitrary limit: the arguments which represent offsets into the pattern are two bytes long. So if 2^16 bytes turns out to be too small, many things would have to change. */ #define MAX_BUF_SIZE (1L << 16) /* Extend the buffer by twice its current size via realloc and reset the pointers that pointed into the old block to point to the correct places in the new one. If extending the buffer results in it being larger than MAX_BUF_SIZE, then flag memory exhausted. */ #define EXTEND_BUFFER() \ do { \ unsigned char *old_buffer = bufp->buffer; \ if (bufp->allocated == MAX_BUF_SIZE) \ return REG_ESIZE; \ bufp->allocated <<= 1; \ if (bufp->allocated > MAX_BUF_SIZE) \ bufp->allocated = MAX_BUF_SIZE; \ bufp->buffer = (unsigned char *) realloc (bufp->buffer, bufp->allocated);\ if (bufp->buffer == NULL) \ return REG_ESPACE; \ /* If the buffer moved, move all the pointers into it. */ \ if (old_buffer != bufp->buffer) \ { \ b = (b - old_buffer) + bufp->buffer; \ begalt = (begalt - old_buffer) + bufp->buffer; \ if (fixup_alt_jump) \ fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\ if (laststart) \ laststart = (laststart - old_buffer) + bufp->buffer; \ if (pending_exact) \ pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ } \ } while (0) /* Since we have one byte reserved for the register number argument to {start,stop}_memory, the maximum number of groups we can report things about is what fits in that byte. */ #define MAX_REGNUM 255 /* But patterns can have more than `MAX_REGNUM' registers. We just ignore the excess. */ typedef unsigned regnum_t; /* Macros for the compile stack. */ /* Since offsets can go either forwards or backwards, this type needs to be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */ typedef int pattern_offset_t; typedef struct { pattern_offset_t begalt_offset; pattern_offset_t fixup_alt_jump; pattern_offset_t inner_group_offset; pattern_offset_t laststart_offset; regnum_t regnum; } compile_stack_elt_t; typedef struct { compile_stack_elt_t *stack; unsigned size; unsigned avail; /* Offset of next open position. */ } compile_stack_type; #define INIT_COMPILE_STACK_SIZE 32 #define COMPILE_STACK_EMPTY (compile_stack.avail == 0) #define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size) /* The next available element. */ #define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail]) /* Set the bit for character C in a list. */ #define SET_LIST_BIT(c) \ (b[((unsigned char) (c)) / BYTEWIDTH] \ |= 1 << (((unsigned char) c) % BYTEWIDTH)) /* Get the next unsigned number in the uncompiled pattern. */ #define GET_UNSIGNED_NUMBER(num) \ { if (p != pend) \ { \ PATFETCH (c); \ while (ISDIGIT (c)) \ { \ if (num < 0) \ num = 0; \ num = num * 10 + c - '0'; \ if (p == pend) \ break; \ PATFETCH (c); \ } \ } \ } #define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ #define IS_CHAR_CLASS(string) \ (STREQ (string, "alpha") || STREQ (string, "upper") \ || STREQ (string, "lower") || STREQ (string, "digit") \ || STREQ (string, "alnum") || STREQ (string, "xdigit") \ || STREQ (string, "space") || STREQ (string, "print") \ || STREQ (string, "punct") || STREQ (string, "graph") \ || STREQ (string, "cntrl") || STREQ (string, "blank")) /* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX. Returns one of error codes defined in `regex.h', or zero for success. Assumes the `allocated' (and perhaps `buffer') and `translate' fields are set in BUFP on entry. If it succeeds, results are put in BUFP (if it returns an error, the contents of BUFP are undefined): `buffer' is the compiled pattern; `syntax' is set to SYNTAX; `used' is set to the length of the compiled pattern; `fastmap_accurate' is zero; `re_nsub' is the number of subexpressions in PATTERN; `not_bol' and `not_eol' are zero; The `fastmap' and `newline_anchor' fields are neither examined nor set. */ static reg_errcode_t regex_compile (pattern, size, syntax, bufp) const char *pattern; int size; reg_syntax_t syntax; struct re_pattern_buffer *bufp; { /* We fetch characters from PATTERN here. Even though PATTERN is `char *' (i.e., signed), we declare these variables as unsigned, so they can be reliably used as array indices. */ register unsigned char c, c1; /* A random tempory spot in PATTERN. */ const char *p1; /* Points to the end of the buffer, where we should append. */ register unsigned char *b; /* Keeps track of unclosed groups. */ compile_stack_type compile_stack; /* Points to the current (ending) position in the pattern. */ const char *p = pattern; const char *pend = pattern + size; /* How to translate the characters in the pattern. */ char *translate = bufp->translate; /* Address of the count-byte of the most recently inserted `exactn' command. This makes it possible to tell if a new exact-match character can be added to that command or if the character requires a new `exactn' command. */ unsigned char *pending_exact = 0; /* Address of start of the most recently finished expression. This tells, e.g., postfix * where to find the start of its operand. Reset at the beginning of groups and alternatives. */ unsigned char *laststart = 0; /* Address of beginning of regexp, or inside of last group. */ unsigned char *begalt; /* Place in the uncompiled pattern (i.e., the {) to which to go back if the interval is invalid. */ const char *beg_interval; /* Address of the place where a forward jump should go to the end of the containing expression. Each alternative of an `or' -- except the last -- ends with a forward jump of this sort. */ unsigned char *fixup_alt_jump = 0; /* Counts open-groups as they are encountered. Remembered for the matching close-group on the compile stack, so the same register number is put in the stop_memory as the start_memory. */ regnum_t regnum = 0; #ifdef DEBUG DEBUG_PRINT1 ("\nCompiling pattern: "); if (debug) { unsigned debug_count; for (debug_count = 0; debug_count < size; debug_count++) printchar (pattern[debug_count]); putchar ('\n'); } #endif /* DEBUG */ /* Initialize the compile stack. */ compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t); if (compile_stack.stack == NULL) return REG_ESPACE; compile_stack.size = INIT_COMPILE_STACK_SIZE; compile_stack.avail = 0; /* Initialize the pattern buffer. */ bufp->syntax = syntax; bufp->fastmap_accurate = 0; bufp->not_bol = bufp->not_eol = 0; /* Set `used' to zero, so that if we return an error, the pattern printer (for debugging) will think there's no pattern. We reset it at the end. */ bufp->used = 0; /* Always count groups, whether or not bufp->no_sub is set. */ bufp->re_nsub = 0; #if !defined (emacs) && !defined (SYNTAX_TABLE) /* Initialize the syntax table. */ init_syntax_once (); #endif if (bufp->allocated == 0) { if (bufp->buffer) { /* If zero allocated, but buffer is non-null, try to realloc enough space. This loses if buffer's address is bogus, but that is the user's responsibility. */ RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char); } else { /* Caller did not allocate a buffer. Do it for them. */ bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char); } if (!bufp->buffer) return REG_ESPACE; bufp->allocated = INIT_BUF_SIZE; } begalt = b = bufp->buffer; /* Loop through the uncompiled pattern until we're at the end. */ while (p != pend) { PATFETCH (c); switch (c) { case '^': { if ( /* If at start of pattern, it's an operator. */ p == pattern + 1 /* If context independent, it's an operator. */ || syntax & RE_CONTEXT_INDEP_ANCHORS /* Otherwise, depends on what's come before. */ || at_begline_loc_p (pattern, p, syntax)) BUF_PUSH (begline); else goto normal_char; } break; case '$': { if ( /* If at end of pattern, it's an operator. */ p == pend /* If context independent, it's an operator. */ || syntax & RE_CONTEXT_INDEP_ANCHORS /* Otherwise, depends on what's next. */ || at_endline_loc_p (p, pend, syntax)) BUF_PUSH (endline); else goto normal_char; } break; case '+': case '?': if ((syntax & RE_BK_PLUS_QM) || (syntax & RE_LIMITED_OPS)) goto normal_char; handle_plus: case '*': /* If there is no previous pattern... */ if (!laststart) { if (syntax & RE_CONTEXT_INVALID_OPS) return REG_BADRPT; else if (!(syntax & RE_CONTEXT_INDEP_OPS)) goto normal_char; } { /* Are we optimizing this jump? */ boolean keep_string_p = false; /* 1 means zero (many) matches is allowed. */ char zero_times_ok = 0, many_times_ok = 0; /* If there is a sequence of repetition chars, collapse it down to just one (the right one). We can't combine interval operators with these because of, e.g., `a{2}*', which should only match an even number of `a's. */ for (;;) { zero_times_ok |= c != '+'; many_times_ok |= c != '?'; if (p == pend) break; PATFETCH (c); if (c == '*' || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?'))) ; else if (syntax & RE_BK_PLUS_QM && c == '\\') { if (p == pend) return REG_EESCAPE; PATFETCH (c1); if (!(c1 == '+' || c1 == '?')) { PATUNFETCH; PATUNFETCH; break; } c = c1; } else { PATUNFETCH; break; } /* If we get here, we found another repeat character. */ } /* Star, etc. applied to an empty pattern is equivalent to an empty pattern. */ if (!laststart) break; /* Now we know whether or not zero matches is allowed and also whether or not two or more matches is allowed. */ if (many_times_ok) { /* More than one repetition is allowed, so put in at the end a backward relative jump from `b' to before the next jump we're going to put in below (which jumps from laststart to after this jump). But if we are at the `*' in the exact sequence `.*\n', insert an unconditional jump backwards to the ., instead of the beginning of the loop. This way we only push a failure point once, instead of every time through the loop. */ assert (p - 1 > pattern); /* Allocate the space for the jump. */ GET_BUFFER_SPACE (3); /* We know we are not at the first character of the pattern, because laststart was nonzero. And we've already incremented `p', by the way, to be the character after the `*'. Do we have to do something analogous here for null bytes, because of RE_DOT_NOT_NULL? */ if (TRANSLATE (*(p - 2)) == TRANSLATE ('.') && zero_times_ok && p < pend && TRANSLATE (*p) == TRANSLATE ('\n') && !(syntax & RE_DOT_NEWLINE)) { /* We have .*\n. */ STORE_JUMP (jump, b, laststart); keep_string_p = true; } else /* Anything else. */ STORE_JUMP (maybe_pop_jump, b, laststart - 3); /* We've added more stuff to the buffer. */ b += 3; } /* On failure, jump from laststart to b + 3, which will be the end of the buffer after this jump is inserted. */ GET_BUFFER_SPACE (3); INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump : on_failure_jump, laststart, b + 3); pending_exact = 0; b += 3; if (!zero_times_ok) { /* At least one repetition is required, so insert a `dummy_failure_jump' before the initial `on_failure_jump' instruction of the loop. This effects a skip over that instruction the first time we hit that loop. */ GET_BUFFER_SPACE (3); INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6); b += 3; } } break; case '.': laststart = b; BUF_PUSH (anychar); break; case '[': { boolean had_char_class = false; if (p == pend) return REG_EBRACK; /* Ensure that we have enough space to push a charset: the opcode, the length count, and the bitset; 34 bytes in all. */ GET_BUFFER_SPACE (34); laststart = b; /* We test `*p == '^' twice, instead of using an if statement, so we only need one BUF_PUSH. */ BUF_PUSH (*p == '^' ? charset_not : charset); if (*p == '^') p++; /* Remember the first position in the bracket expression. */ p1 = p; /* Push the number of bytes in the bitmap. */ BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH); /* Clear the whole map. */ bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH); /* charset_not matches newline according to a syntax bit. */ if ((re_opcode_t) b[-2] == charset_not && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) SET_LIST_BIT ('\n'); /* Read in characters and ranges, setting map bits. */ for (;;) { if (p == pend) return REG_EBRACK; PATFETCH (c); /* \ might escape characters inside [...] and [^...]. */ if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') { if (p == pend) return REG_EESCAPE; PATFETCH (c1); SET_LIST_BIT (c1); continue; } /* Could be the end of the bracket expression. If it's not (i.e., when the bracket expression is `[]' so far), the ']' character bit gets set way below. */ if (c == ']' && p != p1 + 1) break; /* Look ahead to see if it's a range when the last thing was a character class. */ if (had_char_class && c == '-' && *p != ']') return REG_ERANGE; /* Look ahead to see if it's a range when the last thing was a character: if this is a hyphen not at the beginning or the end of a list, then it's the range operator. */ if (c == '-' && !(p - 2 >= pattern && p[-2] == '[') && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') && *p != ']') { reg_errcode_t ret = compile_range (&p, pend, translate, syntax, b); if (ret != REG_NOERROR) return ret; } else if (p[0] == '-' && p[1] != ']') { /* This handles ranges made up of characters only. */ reg_errcode_t ret; /* Move past the `-'. */ PATFETCH (c1); ret = compile_range (&p, pend, translate, syntax, b); if (ret != REG_NOERROR) return ret; } /* See if we're at the beginning of a possible character class. */ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') { /* Leave room for the null. */ char str[CHAR_CLASS_MAX_LENGTH + 1]; PATFETCH (c); c1 = 0; /* If pattern is `[[:'. */ if (p == pend) return REG_EBRACK; for (;;) { PATFETCH (c); if (c == ':' || c == ']' || p == pend || c1 == CHAR_CLASS_MAX_LENGTH) break; str[c1++] = c; } str[c1] = '\0'; /* If isn't a word bracketed by `[:' and:`]': undo the ending character, the letters, and leave the leading `:' and `[' (but set bits for them). */ if (c == ':' && *p == ']') { int ch; boolean is_alnum = STREQ (str, "alnum"); boolean is_alpha = STREQ (str, "alpha"); boolean is_blank = STREQ (str, "blank"); boolean is_cntrl = STREQ (str, "cntrl"); boolean is_digit = STREQ (str, "digit"); boolean is_graph = STREQ (str, "graph"); boolean is_lower = STREQ (str, "lower"); boolean is_print = STREQ (str, "print"); boolean is_punct = STREQ (str, "punct"); boolean is_space = STREQ (str, "space"); boolean is_upper = STREQ (str, "upper"); boolean is_xdigit = STREQ (str, "xdigit"); if (!IS_CHAR_CLASS (str)) return REG_ECTYPE; /* Throw away the ] at the end of the character class. */ PATFETCH (c); if (p == pend) return REG_EBRACK; for (ch = 0; ch < 1 << BYTEWIDTH; ch++) { if ( (is_alnum && ISALNUM (ch)) || (is_alpha && ISALPHA (ch)) || (is_blank && ISBLANK (ch)) || (is_cntrl && ISCNTRL (ch)) || (is_digit && ISDIGIT (ch)) || (is_graph && ISGRAPH (ch)) || (is_lower && ISLOWER (ch)) || (is_print && ISPRINT (ch)) || (is_punct && ISPUNCT (ch)) || (is_space && ISSPACE (ch)) || (is_upper && ISUPPER (ch)) || (is_xdigit && ISXDIGIT (ch))) SET_LIST_BIT (ch); } had_char_class = true; } else { c1++; while (c1--) PATUNFETCH; SET_LIST_BIT ('['); SET_LIST_BIT (':'); had_char_class = false; } } else { had_char_class = false; SET_LIST_BIT (c); } } /* Discard any (non)matching list bytes that are all 0 at the end of the map. Decrease the map-length byte too. */ while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) b[-1]--; b += b[-1]; } break; case '(': if (syntax & RE_NO_BK_PARENS) goto handle_open; else goto normal_char; case ')': if (syntax & RE_NO_BK_PARENS) goto handle_close; else goto normal_char; case '\n': if (syntax & RE_NEWLINE_ALT) goto handle_alt; else goto normal_char; case '|': if (syntax & RE_NO_BK_VBAR) goto handle_alt; else goto normal_char; case '{': if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES) goto handle_interval; else goto normal_char; case '\\': if (p == pend) return REG_EESCAPE; /* Do not translate the character after the \, so that we can distinguish, e.g., \B from \b, even if we normally would translate, e.g., B to b. */ PATFETCH_RAW (c); switch (c) { case '(': if (syntax & RE_NO_BK_PARENS) goto normal_backslash; handle_open: bufp->re_nsub++; regnum++; if (COMPILE_STACK_FULL) { RETALLOC (compile_stack.stack, compile_stack.size << 1, compile_stack_elt_t); if (compile_stack.stack == NULL) return REG_ESPACE; compile_stack.size <<= 1; } /* These are the values to restore when we hit end of this group. They are all relative offsets, so that if the whole pattern moves because of realloc, they will still be valid. */ COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer; COMPILE_STACK_TOP.fixup_alt_jump = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0; COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer; COMPILE_STACK_TOP.regnum = regnum; /* We will eventually replace the 0 with the number of groups inner to this one. But do not push a start_memory for groups beyond the last one we can represent in the compiled pattern. */ if (regnum <= MAX_REGNUM) { COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2; BUF_PUSH_3 (start_memory, regnum, 0); } compile_stack.avail++; fixup_alt_jump = 0; laststart = 0; begalt = b; /* If we've reached MAX_REGNUM groups, then this open won't actually generate any code, so we'll have to clear pending_exact explicitly. */ pending_exact = 0; break; case ')': if (syntax & RE_NO_BK_PARENS) goto normal_backslash; if (COMPILE_STACK_EMPTY) if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) goto normal_backslash; else return REG_ERPAREN; handle_close: if (fixup_alt_jump) { /* Push a dummy failure point at the end of the alternative for a possible future `pop_failure_jump' to pop. See comments at `push_dummy_failure' in `re_match_2'. */ BUF_PUSH (push_dummy_failure); /* We allocated space for this jump when we assigned to `fixup_alt_jump', in the `handle_alt' case below. */ STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1); } /* See similar code for backslashed left paren above. */ if (COMPILE_STACK_EMPTY) if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) goto normal_char; else return REG_ERPAREN; /* Since we just checked for an empty stack above, this ``can't happen''. */ assert (compile_stack.avail != 0); { /* We don't just want to restore into `regnum', because later groups should continue to be numbered higher, as in `(ab)c(de)' -- the second group is #2. */ regnum_t this_group_regnum; compile_stack.avail--; begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset; fixup_alt_jump = COMPILE_STACK_TOP.fixup_alt_jump ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1 : 0; laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset; this_group_regnum = COMPILE_STACK_TOP.regnum; /* If we've reached MAX_REGNUM groups, then this open won't actually generate any code, so we'll have to clear pending_exact explicitly. */ pending_exact = 0; /* We're at the end of the group, so now we know how many groups were inside this one. */ if (this_group_regnum <= MAX_REGNUM) { unsigned char *inner_group_loc = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset; *inner_group_loc = regnum - this_group_regnum; BUF_PUSH_3 (stop_memory, this_group_regnum, regnum - this_group_regnum); } } break; case '|': /* `\|'. */ if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR) goto normal_backslash; handle_alt: if (syntax & RE_LIMITED_OPS) goto normal_char; /* Insert before the previous alternative a jump which jumps to this alternative if the former fails. */ GET_BUFFER_SPACE (3); INSERT_JUMP (on_failure_jump, begalt, b + 6); pending_exact = 0; b += 3; /* The alternative before this one has a jump after it which gets executed if it gets matched. Adjust that jump so it will jump to this alternative's analogous jump (put in below, which in turn will jump to the next (if any) alternative's such jump, etc.). The last such jump jumps to the correct final destination. A picture: _____ _____ | | | | | v | v a | b | c If we are at `b', then fixup_alt_jump right now points to a three-byte space after `a'. We'll put in the jump, set fixup_alt_jump to right after `b', and leave behind three bytes which we'll fill in when we get to after `c'. */ if (fixup_alt_jump) STORE_JUMP (jump_past_alt, fixup_alt_jump, b); /* Mark and leave space for a jump after this alternative, to be filled in later either by next alternative or when know we're at the end of a series of alternatives. */ fixup_alt_jump = b; GET_BUFFER_SPACE (3); b += 3; laststart = 0; begalt = b; break; case '{': /* If \{ is a literal. */ if (!(syntax & RE_INTERVALS) /* If we're at `\{' and it's not the open-interval operator. */ || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) || (p - 2 == pattern && p == pend)) goto normal_backslash; handle_interval: { /* If got here, then the syntax allows intervals. */ /* At least (most) this many matches must be made. */ int lower_bound = -1, upper_bound = -1; beg_interval = p - 1; if (p == pend) { if (syntax & RE_NO_BK_BRACES) goto unfetch_interval; else return REG_EBRACE; } GET_UNSIGNED_NUMBER (lower_bound); if (c == ',') { GET_UNSIGNED_NUMBER (upper_bound); if (upper_bound < 0) upper_bound = RE_DUP_MAX; } else /* Interval such as `{1}' => match exactly once. */ upper_bound = lower_bound; if (lower_bound < 0 || upper_bound > RE_DUP_MAX || lower_bound > upper_bound) { if (syntax & RE_NO_BK_BRACES) goto unfetch_interval; else return REG_BADBR; } if (!(syntax & RE_NO_BK_BRACES)) { if (c != '\\') return REG_EBRACE; PATFETCH (c); } if (c != '}') { if (syntax & RE_NO_BK_BRACES) goto unfetch_interval; else return REG_BADBR; } /* We just parsed a valid interval. */ /* If it's invalid to have no preceding re. */ if (!laststart) { if (syntax & RE_CONTEXT_INVALID_OPS) return REG_BADRPT; else if (syntax & RE_CONTEXT_INDEP_OPS) laststart = b; else goto unfetch_interval; } /* If the upper bound is zero, don't want to succeed at all; jump from `laststart' to `b + 3', which will be the end of the buffer after we insert the jump. */ if (upper_bound == 0) { GET_BUFFER_SPACE (3); INSERT_JUMP (jump, laststart, b + 3); b += 3; } /* Otherwise, we have a nontrivial interval. When we're all done, the pattern will look like: set_number_at set_number_at succeed_n jump_n (The upper bound and `jump_n' are omitted if `upper_bound' is 1, though.) */ else { /* If the upper bound is > 1, we need to insert more at the end of the loop. */ unsigned nbytes = 10 + (upper_bound > 1) * 10; GET_BUFFER_SPACE (nbytes); /* Initialize lower bound of the `succeed_n', even though it will be set during matching by its attendant `set_number_at' (inserted next), because `re_compile_fastmap' needs to know. Jump to the `jump_n' we might insert below. */ INSERT_JUMP2 (succeed_n, laststart, b + 5 + (upper_bound > 1) * 5, lower_bound); b += 5; /* Code to initialize the lower bound. Insert before the `succeed_n'. The `5' is the last two bytes of this `set_number_at', plus 3 bytes of the following `succeed_n'. */ insert_op2 (set_number_at, laststart, 5, lower_bound, b); b += 5; if (upper_bound > 1) { /* More than one repetition is allowed, so append a backward jump to the `succeed_n' that starts this interval. When we've reached this during matching, we'll have matched the interval once, so jump back only `upper_bound - 1' times. */ STORE_JUMP2 (jump_n, b, laststart + 5, upper_bound - 1); b += 5; /* The location we want to set is the second parameter of the `jump_n'; that is `b-2' as an absolute address. `laststart' will be the `set_number_at' we're about to insert; `laststart+3' the number to set, the source for the relative address. But we are inserting into the middle of the pattern -- so everything is getting moved up by 5. Conclusion: (b - 2) - (laststart + 3) + 5, i.e., b - laststart. We insert this at the beginning of the loop so that if we fail during matching, we'll reinitialize the bounds. */ insert_op2 (set_number_at, laststart, b - laststart, upper_bound - 1, b); b += 5; } } pending_exact = 0; beg_interval = NULL; } break; unfetch_interval: /* If an invalid interval, match the characters as literals. */ assert (beg_interval); p = beg_interval; beg_interval = NULL; /* normal_char and normal_backslash need `c'. */ PATFETCH (c); if (!(syntax & RE_NO_BK_BRACES)) { if (p > pattern && p[-1] == '\\') goto normal_backslash; } goto normal_char; #ifdef emacs /* There is no way to specify the before_dot and after_dot operators. rms says this is ok. --karl */ case '=': BUF_PUSH (at_dot); break; case 's': laststart = b; PATFETCH (c); BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]); break; case 'S': laststart = b; PATFETCH (c); BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]); break; #endif /* emacs */ case 'w': laststart = b; BUF_PUSH (wordchar); break; case 'W': laststart = b; BUF_PUSH (notwordchar); break; case '<': BUF_PUSH (wordbeg); break; case '>': BUF_PUSH (wordend); break; case 'b': BUF_PUSH (wordbound); break; case 'B': BUF_PUSH (notwordbound); break; case '`': BUF_PUSH (begbuf); break; case '\'': BUF_PUSH (endbuf); break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (syntax & RE_NO_BK_REFS) goto normal_char; c1 = c - '0'; if (c1 > regnum) return REG_ESUBREG; /* Can't back reference to a subexpression if inside of it. */ if (group_in_compile_stack (compile_stack, c1)) goto normal_char; laststart = b; BUF_PUSH_2 (duplicate, c1); break; case '+': case '?': if (syntax & RE_BK_PLUS_QM) goto handle_plus; else goto normal_backslash; default: normal_backslash: /* You might think it would be useful for \ to mean not to translate; but if we don't translate it it will never match anything. */ c = TRANSLATE (c); goto normal_char; } break; default: /* Expects the character in `c'. */ normal_char: /* If no exactn currently being built. */ if (!pending_exact /* If last exactn not at current position. */ || pending_exact + *pending_exact + 1 != b /* We have only one byte following the exactn for the count. */ || *pending_exact == (1 << BYTEWIDTH) - 1 /* If followed by a repetition operator. */ || *p == '*' || *p == '^' || ((syntax & RE_BK_PLUS_QM) ? *p == '\\' && (p[1] == '+' || p[1] == '?') : (*p == '+' || *p == '?')) || ((syntax & RE_INTERVALS) && ((syntax & RE_NO_BK_BRACES) ? *p == '{' : (p[0] == '\\' && p[1] == '{')))) { /* Start building a new exactn. */ laststart = b; BUF_PUSH_2 (exactn, 0); pending_exact = b - 1; } BUF_PUSH (c); (*pending_exact)++; break; } /* switch (c) */ } /* while p != pend */ /* Through the pattern now. */ if (fixup_alt_jump) STORE_JUMP (jump_past_alt, fixup_alt_jump, b); if (!COMPILE_STACK_EMPTY) return REG_EPAREN; free (compile_stack.stack); /* We have succeeded; set the length of the buffer. */ bufp->used = b - bufp->buffer; #ifdef DEBUG if (debug) { DEBUG_PRINT1 ("\nCompiled pattern: "); print_compiled_pattern (bufp); } #endif /* DEBUG */ return REG_NOERROR; } /* regex_compile */ /* Subroutines for `regex_compile'. */ /* Store OP at LOC followed by two-byte integer parameter ARG. */ static void store_op1 (op, loc, arg) re_opcode_t op; unsigned char *loc; int arg; { *loc = (unsigned char) op; STORE_NUMBER (loc + 1, arg); } /* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */ static void store_op2 (op, loc, arg1, arg2) re_opcode_t op; unsigned char *loc; int arg1, arg2; { *loc = (unsigned char) op; STORE_NUMBER (loc + 1, arg1); STORE_NUMBER (loc + 3, arg2); } /* Copy the bytes from LOC to END to open up three bytes of space at LOC for OP followed by two-byte integer parameter ARG. */ static void insert_op1 (op, loc, arg, end) re_opcode_t op; unsigned char *loc; int arg; unsigned char *end; { register unsigned char *pfrom = end; register unsigned char *pto = end + 3; while (pfrom != loc) *--pto = *--pfrom; store_op1 (op, loc, arg); } /* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */ static void insert_op2 (op, loc, arg1, arg2, end) re_opcode_t op; unsigned char *loc; int arg1, arg2; unsigned char *end; { register unsigned char *pfrom = end; register unsigned char *pto = end + 5; while (pfrom != loc) *--pto = *--pfrom; store_op2 (op, loc, arg1, arg2); } /* P points to just after a ^ in PATTERN. Return true if that ^ comes after an alternative or a begin-subexpression. We assume there is at least one character before the ^. */ static boolean at_begline_loc_p (pattern, p, syntax) const char *pattern, *p; reg_syntax_t syntax; { const char *prev = p - 2; boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\'; return /* After a subexpression? */ (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash)) /* After an alternative? */ || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash)); } /* The dual of at_begline_loc_p. This one is for $. We assume there is at least one character after the $, i.e., `P < PEND'. */ static boolean at_endline_loc_p (p, pend, syntax) const char *p, *pend; int syntax; { const char *next = p; boolean next_backslash = *next == '\\'; const char *next_next = p + 1 < pend ? p + 1 : NULL; return /* Before a subexpression? */ (syntax & RE_NO_BK_PARENS ? *next == ')' : next_backslash && next_next && *next_next == ')') /* Before an alternative? */ || (syntax & RE_NO_BK_VBAR ? *next == '|' : next_backslash && next_next && *next_next == '|'); } /* Returns true if REGNUM is in one of COMPILE_STACK's elements and false if it's not. */ static boolean group_in_compile_stack (compile_stack, regnum) compile_stack_type compile_stack; regnum_t regnum; { int this_element; for (this_element = compile_stack.avail - 1; this_element >= 0; this_element--) if (compile_stack.stack[this_element].regnum == regnum) return true; return false; } /* Read the ending character of a range (in a bracket expression) from the uncompiled pattern *P_PTR (which ends at PEND). We assume the starting character is in `P[-2]'. (`P[-1]' is the character `-'.) Then we set the translation of all bits between the starting and ending characters (inclusive) in the compiled pattern B. Return an error code. We use these short variable names so we can use the same macros as `regex_compile' itself. */ static reg_errcode_t compile_range (p_ptr, pend, translate, syntax, b) const char **p_ptr, *pend; char *translate; reg_syntax_t syntax; unsigned char *b; { unsigned this_char; const char *p = *p_ptr; int range_start, range_end; if (p == pend) return REG_ERANGE; /* Even though the pattern is a signed `char *', we need to fetch with unsigned char *'s; if the high bit of the pattern character is set, the range endpoints will be negative if we fetch using a signed char *. We also want to fetch the endpoints without translating them; the appropriate translation is done in the bit-setting loop below. */ range_start = ((unsigned char *) p)[-2]; range_end = ((unsigned char *) p)[0]; /* Have to increment the pointer into the pattern string, so the caller isn't still at the ending character. */ (*p_ptr)++; /* If the start is after the end, the range is empty. */ if (range_start > range_end) return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR; /* Here we see why `this_char' has to be larger than an `unsigned char' -- the range is inclusive, so if `range_end' == 0xff (assuming 8-bit characters), we would otherwise go into an infinite loop, since all characters <= 0xff. */ for (this_char = range_start; this_char <= range_end; this_char++) { SET_LIST_BIT (TRANSLATE (this_char)); } return REG_NOERROR; } /* Failure stack declarations and macros; both re_compile_fastmap and re_match_2 use a failure stack. These have to be macros because of REGEX_ALLOCATE. */ /* Number of failure points for which to initially allocate space when matching. If this number is exceeded, we allocate more space, so it is not a hard limit. */ #ifndef INIT_FAILURE_ALLOC #define INIT_FAILURE_ALLOC 5 #endif /* Roughly the maximum number of failure points on the stack. Would be exactly that if always used MAX_FAILURE_SPACE each time we failed. This is a variable only so users of regex can assign to it; we never change it ourselves. */ int re_max_failures = 2000; typedef const unsigned char *fail_stack_elt_t; typedef struct { fail_stack_elt_t *stack; unsigned size; unsigned avail; /* Offset of next open position. */ } fail_stack_type; #define FAIL_STACK_EMPTY() (fail_stack.avail == 0) #define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0) #define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) #define FAIL_STACK_TOP() (fail_stack.stack[fail_stack.avail]) /* Initialize `fail_stack'. Do `return -2' if the alloc fails. */ #define INIT_FAIL_STACK() \ do { \ fail_stack.stack = (fail_stack_elt_t *) \ REGEX_ALLOCATE (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \ \ if (fail_stack.stack == NULL) \ return -2; \ \ fail_stack.size = INIT_FAILURE_ALLOC; \ fail_stack.avail = 0; \ } while (0) /* Double the size of FAIL_STACK, up to approximately `re_max_failures' items. Return 1 if succeeds, and 0 if either ran out of memory allocating space for it or it was already too large. REGEX_REALLOCATE requires `destination' be declared. */ #define DOUBLE_FAIL_STACK(fail_stack) \ ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS \ ? 0 \ : ((fail_stack).stack = (fail_stack_elt_t *) \ REGEX_REALLOCATE ((fail_stack).stack, \ (fail_stack).size * sizeof (fail_stack_elt_t), \ ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \ \ (fail_stack).stack == NULL \ ? 0 \ : ((fail_stack).size <<= 1, \ 1))) /* Push PATTERN_OP on FAIL_STACK. Return 1 if was able to do so and 0 if ran out of memory allocating space to do so. */ #define PUSH_PATTERN_OP(pattern_op, fail_stack) \ ((FAIL_STACK_FULL () \ && !DOUBLE_FAIL_STACK (fail_stack)) \ ? 0 \ : ((fail_stack).stack[(fail_stack).avail++] = pattern_op, \ 1)) /* This pushes an item onto the failure stack. Must be a four-byte value. Assumes the variable `fail_stack'. Probably should only be called from within `PUSH_FAILURE_POINT'. */ #define PUSH_FAILURE_ITEM(item) \ fail_stack.stack[fail_stack.avail++] = (fail_stack_elt_t) item /* The complement operation. Assumes `fail_stack' is nonempty. */ #define POP_FAILURE_ITEM() fail_stack.stack[--fail_stack.avail] /* Used to omit pushing failure point id's when we're not debugging. */ #ifdef DEBUG #define DEBUG_PUSH PUSH_FAILURE_ITEM #define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_ITEM () #else #define DEBUG_PUSH(item) #define DEBUG_POP(item_addr) #endif /* Push the information about the state we will need if we ever fail back to it. Requires variables fail_stack, regstart, regend, reg_info, and num_regs be declared. DOUBLE_FAIL_STACK requires `destination' be declared. Does `return FAILURE_CODE' if runs out of memory. */ #define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \ do { \ char *destination; \ /* Must be int, so when we don't save any registers, the arithmetic \ of 0 + -1 isn't done as unsigned. */ \ int this_reg; \ \ DEBUG_STATEMENT (failure_id++); \ DEBUG_STATEMENT (nfailure_points_pushed++); \ DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \ DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\ DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\ \ DEBUG_PRINT2 (" slots needed: %d\n", NUM_FAILURE_ITEMS); \ DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \ \ /* Ensure we have enough space allocated for what we will push. */ \ while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \ { \ if (!DOUBLE_FAIL_STACK (fail_stack)) \ return failure_code; \ \ DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \ (fail_stack).size); \ DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\ } \ \ /* Push the info, starting with the registers. */ \ DEBUG_PRINT1 ("\n"); \ \ for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \ this_reg++) \ { \ DEBUG_PRINT2 (" Pushing reg: %d\n", this_reg); \ DEBUG_STATEMENT (num_regs_pushed++); \ \ DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ PUSH_FAILURE_ITEM (regstart[this_reg]); \ \ DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ PUSH_FAILURE_ITEM (regend[this_reg]); \ \ DEBUG_PRINT2 (" info: 0x%x\n ", reg_info[this_reg]); \ DEBUG_PRINT2 (" match_null=%d", \ REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \ DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \ DEBUG_PRINT2 (" matched_something=%d", \ MATCHED_SOMETHING (reg_info[this_reg])); \ DEBUG_PRINT2 (" ever_matched=%d", \ EVER_MATCHED_SOMETHING (reg_info[this_reg])); \ DEBUG_PRINT1 ("\n"); \ PUSH_FAILURE_ITEM (reg_info[this_reg].word); \ } \ \ DEBUG_PRINT2 (" Pushing low active reg: %d\n", lowest_active_reg);\ PUSH_FAILURE_ITEM (lowest_active_reg); \ \ DEBUG_PRINT2 (" Pushing high active reg: %d\n", highest_active_reg);\ PUSH_FAILURE_ITEM (highest_active_reg); \ \ DEBUG_PRINT2 (" Pushing pattern 0x%x: ", pattern_place); \ DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \ PUSH_FAILURE_ITEM (pattern_place); \ \ DEBUG_PRINT2 (" Pushing string 0x%x: `", string_place); \ DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \ size2); \ DEBUG_PRINT1 ("'\n"); \ PUSH_FAILURE_ITEM (string_place); \ \ DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \ DEBUG_PUSH (failure_id); \ } while (0) /* This is the number of items that are pushed and popped on the stack for each register. */ #define NUM_REG_ITEMS 3 /* Individual items aside from the registers. */ #ifdef DEBUG #define NUM_NONREG_ITEMS 5 /* Includes failure point id. */ #else #define NUM_NONREG_ITEMS 4 #endif /* We push at most this many items on the stack. */ #define MAX_FAILURE_ITEMS ((num_regs - 1) * NUM_REG_ITEMS + NUM_NONREG_ITEMS) /* We actually push this many items. */ #define NUM_FAILURE_ITEMS \ ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS \ + NUM_NONREG_ITEMS) /* How many items can still be added to the stack without overflowing it. */ #define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail) /* Pops what PUSH_FAIL_STACK pushes. We restore into the parameters, all of which should be lvalues: STR -- the saved data position. PAT -- the saved pattern position. LOW_REG, HIGH_REG -- the highest and lowest active registers. REGSTART, REGEND -- arrays of string positions. REG_INFO -- array of information about each subexpression. Also assumes the variables `fail_stack' and (if debugging), `bufp', `pend', `string1', `size1', `string2', and `size2'. */ #define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ { \ DEBUG_STATEMENT (fail_stack_elt_t failure_id;) \ int this_reg; \ const unsigned char *string_temp; \ \ assert (!FAIL_STACK_EMPTY ()); \ \ /* Remove failure points and point to how many regs pushed. */ \ DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \ DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \ DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \ \ assert (fail_stack.avail >= NUM_NONREG_ITEMS); \ \ DEBUG_POP (&failure_id); \ DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \ \ /* If the saved string location is NULL, it came from an \ on_failure_keep_string_jump opcode, and we want to throw away the \ saved NULL, thus retaining our current position in the string. */ \ string_temp = POP_FAILURE_ITEM (); \ if (string_temp != NULL) \ str = (const char *) string_temp; \ \ DEBUG_PRINT2 (" Popping string 0x%x: `", str); \ DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ DEBUG_PRINT1 ("'\n"); \ \ pat = (unsigned char *) POP_FAILURE_ITEM (); \ DEBUG_PRINT2 (" Popping pattern 0x%x: ", pat); \ DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ \ /* Restore register info. */ \ high_reg = (unsigned) ((long) POP_FAILURE_ITEM ()); \ DEBUG_PRINT2 (" Popping high active reg: %d\n", high_reg); \ \ low_reg = (unsigned) ((long) POP_FAILURE_ITEM ()); \ DEBUG_PRINT2 (" Popping low active reg: %d\n", low_reg); \ \ for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \ { \ DEBUG_PRINT2 (" Popping reg: %d\n", this_reg); \ \ reg_info[this_reg].word = POP_FAILURE_ITEM (); \ DEBUG_PRINT2 (" info: 0x%x\n", reg_info[this_reg]); \ \ regend[this_reg] = (const char *) POP_FAILURE_ITEM (); \ DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ \ regstart[this_reg] = (const char *) POP_FAILURE_ITEM (); \ DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ } \ \ DEBUG_STATEMENT (nfailure_points_popped++); \ } /* POP_FAILURE_POINT */ /* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible characters can start a string that matches the pattern. This fastmap is used by re_search to skip quickly over impossible starting points. The caller must supply the address of a (1 << BYTEWIDTH)-byte data area as BUFP->fastmap. We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in the pattern buffer. Returns 0 if we succeed, -2 if an internal error. */ int re_compile_fastmap (bufp) struct re_pattern_buffer *bufp; { int j, k; fail_stack_type fail_stack; #ifndef REGEX_MALLOC char *destination; #endif /* We don't push any register information onto the failure stack. */ unsigned num_regs = 0; register char *fastmap = bufp->fastmap; unsigned char *pattern = bufp->buffer; unsigned long size = bufp->used; const unsigned char *p = pattern; register unsigned char *pend = pattern + size; /* Assume that each path through the pattern can be null until proven otherwise. We set this false at the bottom of switch statement, to which we get only if a particular path doesn't match the empty string. */ boolean path_can_be_null = true; /* We aren't doing a `succeed_n' to begin with. */ boolean succeed_n_p = false; assert (fastmap != NULL && p != NULL); INIT_FAIL_STACK (); bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */ bufp->fastmap_accurate = 1; /* It will be when we're done. */ bufp->can_be_null = 0; while (p != pend || !FAIL_STACK_EMPTY ()) { if (p == pend) { bufp->can_be_null |= path_can_be_null; /* Reset for next path. */ path_can_be_null = true; p = fail_stack.stack[--fail_stack.avail]; } /* We should never be about to go beyond the end of the pattern. */ assert (p < pend); #ifdef SWITCH_ENUM_BUG switch ((int) ((re_opcode_t) *p++)) #else switch ((re_opcode_t) *p++) #endif { /* I guess the idea here is to simply not bother with a fastmap if a backreference is used, since it's too hard to figure out the fastmap for the corresponding group. Setting `can_be_null' stops `re_search_2' from using the fastmap, so that is all we do. */ case duplicate: bufp->can_be_null = 1; return 0; /* Following are the cases which match a character. These end with `break'. */ case exactn: fastmap[p[1]] = 1; break; case charset: for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) fastmap[j] = 1; break; case charset_not: /* Chars beyond end of map must be allowed. */ for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) fastmap[j] = 1; for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) fastmap[j] = 1; break; case wordchar: for (j = 0; j < (1 << BYTEWIDTH); j++) if (SYNTAX (j) == Sword) fastmap[j] = 1; break; case notwordchar: for (j = 0; j < (1 << BYTEWIDTH); j++) if (SYNTAX (j) != Sword) fastmap[j] = 1; break; case anychar: /* `.' matches anything ... */ for (j = 0; j < (1 << BYTEWIDTH); j++) fastmap[j] = 1; /* ... except perhaps newline. */ if (!(bufp->syntax & RE_DOT_NEWLINE)) fastmap['\n'] = 0; /* Return if we have already set `can_be_null'; if we have, then the fastmap is irrelevant. Something's wrong here. */ else if (bufp->can_be_null) return 0; /* Otherwise, have to check alternative paths. */ break; #ifdef emacs case syntaxspec: k = *p++; for (j = 0; j < (1 << BYTEWIDTH); j++) if (SYNTAX (j) == (enum syntaxcode) k) fastmap[j] = 1; break; case notsyntaxspec: k = *p++; for (j = 0; j < (1 << BYTEWIDTH); j++) if (SYNTAX (j) != (enum syntaxcode) k) fastmap[j] = 1; break; /* All cases after this match the empty string. These end with `continue'. */ case before_dot: case at_dot: case after_dot: continue; #endif /* not emacs */ case no_op: case begline: case endline: case begbuf: case endbuf: case wordbound: case notwordbound: case wordbeg: case wordend: case push_dummy_failure: continue; case jump_n: case pop_failure_jump: case maybe_pop_jump: case jump: case jump_past_alt: case dummy_failure_jump: EXTRACT_NUMBER_AND_INCR (j, p); p += j; if (j > 0) continue; /* Jump backward implies we just went through the body of a loop and matched nothing. Opcode jumped to should be `on_failure_jump' or `succeed_n'. Just treat it like an ordinary jump. For a * loop, it has pushed its failure point already; if so, discard that as redundant. */ if ((re_opcode_t) *p != on_failure_jump && (re_opcode_t) *p != succeed_n) continue; p++; EXTRACT_NUMBER_AND_INCR (j, p); p += j; /* If what's on the stack is where we are now, pop it. */ if (!FAIL_STACK_EMPTY () && fail_stack.stack[fail_stack.avail - 1] == p) fail_stack.avail--; continue; case on_failure_jump: case on_failure_keep_string_jump: handle_on_failure_jump: EXTRACT_NUMBER_AND_INCR (j, p); /* For some patterns, e.g., `(a?)?', `p+j' here points to the end of the pattern. We don't want to push such a point, since when we restore it above, entering the switch will increment `p' past the end of the pattern. We don't need to push such a point since we obviously won't find any more fastmap entries beyond `pend'. Such a pattern can match the null string, though. */ if (p + j < pend) { if (!PUSH_PATTERN_OP (p + j, fail_stack)) return -2; } else bufp->can_be_null = 1; if (succeed_n_p) { EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */ succeed_n_p = false; } continue; case succeed_n: /* Get to the number of times to succeed. */ p += 2; /* Increment p past the n for when k != 0. */ EXTRACT_NUMBER_AND_INCR (k, p); if (k == 0) { p -= 4; succeed_n_p = true; /* Spaghetti code alert. */ goto handle_on_failure_jump; } continue; case set_number_at: p += 4; continue; case start_memory: case stop_memory: p += 2; continue; default: abort (); /* We have listed all the cases. */ } /* switch *p++ */ /* Getting here means we have found the possible starting characters for one path of the pattern -- and that the empty string does not match. We need not follow this path further. Instead, look at the next alternative (remembered on the stack), or quit if no more. The test at the top of the loop does these things. */ path_can_be_null = false; p = pend; } /* while p */ /* Set `can_be_null' for the last path (also the first path, if the pattern is empty). */ bufp->can_be_null |= path_can_be_null; return 0; } /* re_compile_fastmap */ /* Set REGS to hold NUM_REGS registers, storing them in STARTS and ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use this memory for recording register information. STARTS and ENDS must be allocated using the malloc library routine, and must each be at least NUM_REGS * sizeof (regoff_t) bytes long. If NUM_REGS == 0, then subsequent matches should allocate their own register data. Unless this function is called, the first search or match using PATTERN_BUFFER will allocate its own register data, without freeing the old data. */ void re_set_registers (bufp, regs, num_regs, starts, ends) struct re_pattern_buffer *bufp; struct re_registers *regs; unsigned num_regs; regoff_t *starts, *ends; { if (num_regs) { bufp->regs_allocated = REGS_REALLOCATE; regs->num_regs = num_regs; regs->start = starts; regs->end = ends; } else { bufp->regs_allocated = REGS_UNALLOCATED; regs->num_regs = 0; /* wintel does not like this line regs->start = regs->end = (regoff_t) 0; */ regs->start = (regoff_t *) 0; regs->end = (regoff_t *) 0; } } /* Searching routines. */ /* Like re_search_2, below, but only one string is specified, and doesn't let you say where to stop matching. */ int re_search (bufp, string, size, startpos, range, regs) struct re_pattern_buffer *bufp; const char *string; int size, startpos, range; struct re_registers *regs; { return re_search_2 (bufp, NULL, 0, string, size, startpos, range, regs, size); } /* Using the compiled pattern in BUFP->buffer, first tries to match the virtual concatenation of STRING1 and STRING2, starting first at index STARTPOS, then at STARTPOS + 1, and so on. STRING1 and STRING2 have length SIZE1 and SIZE2, respectively. RANGE is how far to scan while trying to match. RANGE = 0 means try only at STARTPOS; in general, the last start tried is STARTPOS + RANGE. In REGS, return the indices of the virtual concatenation of STRING1 and STRING2 that matched the entire BUFP->buffer and its contained subexpressions. Do not consider matching one past the index STOP in the virtual concatenation of STRING1 and STRING2. We return either the position in the strings at which the match was found, -1 if no match, or -2 if error (such as failure stack overflow). */ int re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop) struct re_pattern_buffer *bufp; const char *string1, *string2; int size1, size2; int startpos; int range; struct re_registers *regs; int stop; { int val; register char *fastmap = bufp->fastmap; register char *translate = bufp->translate; int total_size = size1 + size2; int endpos = startpos + range; /* Check for out-of-range STARTPOS. */ if (startpos < 0 || startpos > total_size) return -1; /* Fix up RANGE if it might eventually take us outside the virtual concatenation of STRING1 and STRING2. */ if (endpos < -1) range = -1 - startpos; else if (endpos > total_size) range = total_size - startpos; /* If the search isn't to be a backwards one, don't waste time in a search for a pattern that must be anchored. */ if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == begbuf && range > 0) { if (startpos > 0) return -1; else range = 1; } /* Update the fastmap now if not correct already. */ if (fastmap && !bufp->fastmap_accurate) if (re_compile_fastmap (bufp) == -2) return -2; /* Loop through the string, looking for a place to start matching. */ for (;;) { /* If a fastmap is supplied, skip quickly over characters that cannot be the start of a match. If the pattern can match the null string, however, we don't need to skip characters; we want the first null string. */ if (fastmap && startpos < total_size && !bufp->can_be_null) { if (range > 0) /* Searching forwards. */ { register const char *d; register int lim = 0; int irange = range; if (startpos < size1 && startpos + range >= size1) lim = range - (size1 - startpos); d = (startpos >= size1 ? string2 - size1 : string1) + startpos; /* Written out as an if-else to avoid testing `translate' inside the loop. */ if (translate) while (range > lim && !fastmap[(unsigned char) translate[(unsigned char) *d++]]) range--; else while (range > lim && !fastmap[(unsigned char) *d++]) range--; startpos += irange - range; } else /* Searching backwards. */ { register char c = (size1 == 0 || startpos >= size1 ? string2[startpos - size1] : string1[startpos]); if (!fastmap[(unsigned char) TRANSLATE (c)]) goto advance; } } /* If can't match the null string, and that's all we have left, fail. */ if (range >= 0 && startpos == total_size && fastmap && !bufp->can_be_null) return -1; val = re_match_2 (bufp, string1, size1, string2, size2, startpos, regs, stop); if (val >= 0) return startpos; if (val == -2) return -2; advance: if (!range) break; else if (range > 0) { range--; startpos++; } else { range++; startpos--; } } return -1; } /* re_search_2 */ /* Declarations and macros for re_match_2. */ static int bcmp_translate (); static boolean alt_match_null_string_p (), common_op_match_null_string_p (), group_match_null_string_p (); /* Structure for per-register (a.k.a. per-group) information. This must not be longer than one word, because we push this value onto the failure stack. Other register information, such as the starting and ending positions (which are addresses), and the list of inner groups (which is a bits list) are maintained in separate variables. We are making a (strictly speaking) nonportable assumption here: that the compiler will pack our bit fields into something that fits into the type of `word', i.e., is something that fits into one item on the failure stack. */ typedef union { fail_stack_elt_t word; struct { /* This field is one if this group can match the empty string, zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */ #define MATCH_NULL_UNSET_VALUE 3 unsigned match_null_string_p : 2; unsigned is_active : 1; unsigned matched_something : 1; unsigned ever_matched_something : 1; } bits; } register_info_type; #define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p) #define IS_ACTIVE(R) ((R).bits.is_active) #define MATCHED_SOMETHING(R) ((R).bits.matched_something) #define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something) /* Call this when have matched a real character; it sets `matched' flags for the subexpressions which we are currently inside. Also records that those subexprs have matched. */ #define SET_REGS_MATCHED() \ do \ { \ unsigned r; \ for (r = lowest_active_reg; r <= highest_active_reg; r++) \ { \ MATCHED_SOMETHING (reg_info[r]) \ = EVER_MATCHED_SOMETHING (reg_info[r]) \ = 1; \ } \ } \ while (0) /* This converts PTR, a pointer into one of the search strings `string1' and `string2' into an offset from the beginning of that string. */ #define POINTER_TO_OFFSET(ptr) \ ( (int) (FIRST_STRING_P (ptr) ? (long) (ptr) - (long) string1 \ : (long) (ptr) - (long) string2 + size1) ) /* Registers are set to a sentinel when they haven't yet matched. */ #define REG_UNSET_VALUE ((char *) -1) #define REG_UNSET(e) ((e) == REG_UNSET_VALUE) /* Macros for dealing with the split strings in re_match_2. */ #define MATCHING_IN_FIRST_STRING (dend == end_match_1) /* Call before fetching a character with *d. This switches over to string2 if necessary. */ #define PREFETCH() \ while (d == dend) \ { \ /* End of string2 => fail. */ \ if (dend == end_match_2) \ goto fail; \ /* End of string1 => advance to string2. */ \ d = string2; \ dend = end_match_2; \ } /* Test if at very beginning or at very end of the virtual concatenation of `string1' and `string2'. If only one string, it's `string2'. */ #define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2) #define AT_STRINGS_END(d) ((d) == end2) /* Test if D points to a character which is word-constituent. We have two special cases to check for: if past the end of string1, look at the first character in string2; and if before the beginning of string2, look at the last character in string1. */ #define WORDCHAR_P(d) \ (SYNTAX ((d) == end1 ? *string2 \ : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ == Sword) /* Test if the character before D and the one at D differ with respect to being word-constituent. */ #define AT_WORD_BOUNDARY(d) \ (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \ || WORDCHAR_P (d - 1) != WORDCHAR_P (d)) /* Free everything we malloc. */ #ifdef REGEX_MALLOC #define FREE_VAR(var) if (var) free (var); var = NULL #define FREE_VARIABLES() \ do { \ FREE_VAR (fail_stack.stack); \ FREE_VAR (regstart); \ FREE_VAR (regend); \ FREE_VAR (old_regstart); \ FREE_VAR (old_regend); \ FREE_VAR (best_regstart); \ FREE_VAR (best_regend); \ FREE_VAR (reg_info); \ FREE_VAR (reg_dummy); \ FREE_VAR (reg_info_dummy); \ } while (0) #else /* not REGEX_MALLOC */ /* Some MIPS systems (at least) want this to free alloca'd storage. */ #define FREE_VARIABLES() alloca (0) #endif /* not REGEX_MALLOC */ /* These values must meet several constraints. They must not be valid register values; since we have a limit of 255 registers (because we use only one byte in the pattern for the register number), we can use numbers larger than 255. They must differ by 1, because of NUM_FAILURE_ITEMS above. And the value for the lowest register must be larger than the value for the highest register, so we do not try to actually save any registers when none are active. */ #define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH) #define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1) /* Matching routines. */ #ifndef emacs /* Emacs never uses this. */ /* re_match is like re_match_2 except it takes only a single string. */ int re_match (bufp, string, size, pos, regs) struct re_pattern_buffer *bufp; const char *string; int size, pos; struct re_registers *regs; { return re_match_2 (bufp, NULL, 0, string, size, pos, regs, size); } #endif /* not emacs */ /* re_match_2 matches the compiled pattern in BUFP against the the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1 and SIZE2, respectively). We start matching at POS, and stop matching at STOP. If REGS is non-null and the `no_sub' field of BUFP is nonzero, we store offsets for the substring each group matched in REGS. See the documentation for exactly how many groups we fill. We return -1 if no match, -2 if an internal error (such as the failure stack overflowing). Otherwise, we return the length of the matched substring. */ int re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) struct re_pattern_buffer *bufp; const char *string1, *string2; int size1, size2; int pos; struct re_registers *regs; int stop; { /* General temporaries. */ int mcnt; unsigned char *p1; /* Just past the end of the corresponding string. */ const char *end1, *end2; /* Pointers into string1 and string2, just past the last characters in each to consider matching. */ const char *end_match_1, *end_match_2; /* Where we are in the data, and the end of the current string. */ const char *d, *dend; /* Where we are in the pattern, and the end of the pattern. */ unsigned char *p = bufp->buffer; register unsigned char *pend = p + bufp->used; /* We use this to map every character in the string. */ char *translate = bufp->translate; /* Failure point stack. Each place that can handle a failure further down the line pushes a failure point on this stack. It consists of restart, regend, and reg_info for all registers corresponding to the subexpressions we're currently inside, plus the number of such registers, and, finally, two char *'s. The first char * is where to resume scanning the pattern; the second one is where to resume scanning the strings. If the latter is zero, the failure point is a ``dummy''; if a failure happens and the failure point is a dummy, it gets discarded and the next next one is tried. */ fail_stack_type fail_stack; #ifdef DEBUG static unsigned failure_id = 0; unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0; #endif /* We fill all the registers internally, independent of what we return, for use in backreferences. The number here includes an element for register zero. */ unsigned num_regs = bufp->re_nsub + 1; /* The currently active registers. */ unsigned lowest_active_reg = NO_LOWEST_ACTIVE_REG; unsigned highest_active_reg = NO_HIGHEST_ACTIVE_REG; /* Information on the contents of registers. These are pointers into the input strings; they record just what was matched (on this attempt) by a subexpression part of the pattern, that is, the regnum-th regstart pointer points to where in the pattern we began matching and the regnum-th regend points to right after where we stopped matching the regnum-th subexpression. (The zeroth register keeps track of what the whole pattern matches.) */ const char **regstart, **regend; /* If a group that's operated upon by a repetition operator fails to match anything, then the register for its start will need to be restored because it will have been set to wherever in the string we are when we last see its open-group operator. Similarly for a register's end. */ const char **old_regstart, **old_regend; /* The is_active field of reg_info helps us keep track of which (possibly nested) subexpressions we are currently in. The matched_something field of reg_info[reg_num] helps us tell whether or not we have matched any of the pattern so far this time through the reg_num-th subexpression. These two fields get reset each time through any loop their register is in. */ register_info_type *reg_info; /* The following record the register info as found in the above variables when we find a match better than any we've seen before. This happens as we backtrack through the failure points, which in turn happens only if we have not yet matched the entire string. */ unsigned best_regs_set = false; const char **best_regstart, **best_regend; /* Logically, this is `best_regend[0]'. But we don't want to have to allocate space for that if we're not allocating space for anything else (see below). Also, we never need info about register 0 for any of the other register vectors, and it seems rather a kludge to treat `best_regend' differently than the rest. So we keep track of the end of the best match so far in a separate variable. We initialize this to NULL so that when we backtrack the first time and need to test it, it's not garbage. */ const char *match_end = NULL; /* Used when we pop values we don't care about. */ const char **reg_dummy; register_info_type *reg_info_dummy; #ifdef DEBUG /* Counts the total number of registers pushed. */ unsigned num_regs_pushed = 0; #endif DEBUG_PRINT1 ("\n\nEntering re_match_2.\n"); INIT_FAIL_STACK (); /* Do not bother to initialize all the register variables if there are no groups in the pattern, as it takes a fair amount of time. If there are groups, we include space for register 0 (the whole pattern), even though we never use it, since it simplifies the array indexing. We should fix this. */ if (bufp->re_nsub) { regstart = REGEX_TALLOC (num_regs, const char *); regend = REGEX_TALLOC (num_regs, const char *); old_regstart = REGEX_TALLOC (num_regs, const char *); old_regend = REGEX_TALLOC (num_regs, const char *); best_regstart = REGEX_TALLOC (num_regs, const char *); best_regend = REGEX_TALLOC (num_regs, const char *); reg_info = REGEX_TALLOC (num_regs, register_info_type); reg_dummy = REGEX_TALLOC (num_regs, const char *); reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type); if (!(regstart && regend && old_regstart && old_regend && reg_info && best_regstart && best_regend && reg_dummy && reg_info_dummy)) { FREE_VARIABLES (); return -2; } } #ifdef REGEX_MALLOC else { /* We must initialize all our variables to NULL, so that `FREE_VARIABLES' doesn't try to free them. */ regstart = regend = old_regstart = old_regend = best_regstart = best_regend = reg_dummy = NULL; reg_info = reg_info_dummy = (register_info_type *) NULL; } #endif /* REGEX_MALLOC */ /* The starting position is bogus. */ if (pos < 0 || pos > size1 + size2) { FREE_VARIABLES (); return -1; } /* Initialize subexpression text positions to -1 to mark ones that no start_memory/stop_memory has been seen for. Also initialize the register information struct. */ for (mcnt = 1; mcnt < num_regs; mcnt++) { regstart[mcnt] = regend[mcnt] = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE; REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE; IS_ACTIVE (reg_info[mcnt]) = 0; MATCHED_SOMETHING (reg_info[mcnt]) = 0; EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0; } /* We move `string1' into `string2' if the latter's empty -- but not if `string1' is null. */ if (size2 == 0 && string1 != NULL) { string2 = string1; size2 = size1; string1 = 0; size1 = 0; } end1 = string1 + size1; end2 = string2 + size2; /* Compute where to stop matching, within the two strings. */ if (stop <= size1) { end_match_1 = string1 + stop; end_match_2 = string2; } else { end_match_1 = end1; end_match_2 = string2 + stop - size1; } /* `p' scans through the pattern as `d' scans through the data. `dend' is the end of the input string that `d' points within. `d' is advanced into the following input string whenever necessary, but this happens before fetching; therefore, at the beginning of the loop, `d' can be pointing at the end of a string, but it cannot equal `string2'. */ if (size1 > 0 && pos <= size1) { d = string1 + pos; dend = end_match_1; } else { d = string2 + pos - size1; dend = end_match_2; } DEBUG_PRINT1 ("The compiled pattern is: "); DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend); DEBUG_PRINT1 ("The string to match is: `"); DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2); DEBUG_PRINT1 ("'\n"); /* This loops over pattern commands. It exits by returning from the function if the match is complete, or it drops through if the match fails at this starting point in the input data. */ for (;;) { DEBUG_PRINT2 ("\n0x%x: ", p); if (p == pend) { /* End of pattern means we might have succeeded. */ DEBUG_PRINT1 ("end of pattern ... "); /* If we haven't matched the entire string, and we want the longest match, try backtracking. */ if (d != end_match_2) { DEBUG_PRINT1 ("backtracking.\n"); if (!FAIL_STACK_EMPTY ()) { /* More failure points to try. */ boolean same_str_p = (FIRST_STRING_P (match_end) == MATCHING_IN_FIRST_STRING); /* If exceeds best match so far, save it. */ if (!best_regs_set || (same_str_p && d > match_end) || (!same_str_p && !MATCHING_IN_FIRST_STRING)) { best_regs_set = true; match_end = d; DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); for (mcnt = 1; mcnt < num_regs; mcnt++) { best_regstart[mcnt] = regstart[mcnt]; best_regend[mcnt] = regend[mcnt]; } } goto fail; } /* If no failure points, don't restore garbage. */ else if (best_regs_set) { restore_best_regs: /* Restore best match. It may happen that `dend == end_match_1' while the restored d is in string2. For example, the pattern `x.*y.*z' against the strings `x-' and `y-z-', if the two strings are not consecutive in memory. */ DEBUG_PRINT1 ("Restoring best registers.\n"); d = match_end; dend = ((d >= string1 && d <= end1) ? end_match_1 : end_match_2); for (mcnt = 1; mcnt < num_regs; mcnt++) { regstart[mcnt] = best_regstart[mcnt]; regend[mcnt] = best_regend[mcnt]; } } } /* d != end_match_2 */ DEBUG_PRINT1 ("Accepting match.\n"); /* If caller wants register contents data back, do it. */ if (regs && !bufp->no_sub) { /* Have the register data arrays been allocated? */ if (bufp->regs_allocated == REGS_UNALLOCATED) { /* No. So allocate them with malloc. We need one extra element beyond `num_regs' for the `-1' marker GNU code uses. */ regs->num_regs = MAX (RE_NREGS, num_regs + 1); regs->start = TALLOC (regs->num_regs, regoff_t); regs->end = TALLOC (regs->num_regs, regoff_t); if (regs->start == NULL || regs->end == NULL) return -2; bufp->regs_allocated = REGS_REALLOCATE; } else if (bufp->regs_allocated == REGS_REALLOCATE) { /* Yes. If we need more elements than were already allocated, reallocate them. If we need fewer, just leave it alone. */ if (regs->num_regs < num_regs + 1) { regs->num_regs = num_regs + 1; RETALLOC (regs->start, regs->num_regs, regoff_t); RETALLOC (regs->end, regs->num_regs, regoff_t); if (regs->start == NULL || regs->end == NULL) return -2; } } else assert (bufp->regs_allocated == REGS_FIXED); /* Convert the pointer data in `regstart' and `regend' to indices. Register zero has to be set differently, since we haven't kept track of any info for it. */ if (regs->num_regs > 0) { regs->start[0] = pos; regs->end[0] = (int) (MATCHING_IN_FIRST_STRING ? (long) d - (long) string1 : (long) d - (long) string2 + size1); } /* Go through the first `min (num_regs, regs->num_regs)' registers, since that is all we initialized. */ for (mcnt = 1; mcnt < MIN (num_regs, regs->num_regs); mcnt++) { if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt])) regs->start[mcnt] = regs->end[mcnt] = -1; else { regs->start[mcnt] = POINTER_TO_OFFSET (regstart[mcnt]); regs->end[mcnt] = POINTER_TO_OFFSET (regend[mcnt]); } } /* If the regs structure we return has more elements than were in the pattern, set the extra elements to -1. If we (re)allocated the registers, this is the case, because we always allocate enough to have at least one -1 at the end. */ for (mcnt = num_regs; mcnt < regs->num_regs; mcnt++) regs->start[mcnt] = regs->end[mcnt] = -1; } /* regs && !bufp->no_sub */ FREE_VARIABLES (); DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n", nfailure_points_pushed, nfailure_points_popped, nfailure_points_pushed - nfailure_points_popped); DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed); mcnt = d - pos - (MATCHING_IN_FIRST_STRING ? string1 : string2 - size1); DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); return mcnt; } /* Otherwise match next pattern command. */ #ifdef SWITCH_ENUM_BUG switch ((int) ((re_opcode_t) *p++)) #else switch ((re_opcode_t) *p++) #endif { /* Ignore these. Used to ignore the n of succeed_n's which currently have n == 0. */ case no_op: DEBUG_PRINT1 ("EXECUTING no_op.\n"); break; /* Match the next n pattern characters exactly. The following byte in the pattern defines n, and the n bytes after that are the characters to match. */ case exactn: mcnt = *p++; DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt); /* This is written out as an if-else so we don't waste time testing `translate' inside the loop. */ if (translate) { do { PREFETCH (); if (translate[(unsigned char) *d++] != (char) *p++) goto fail; } while (--mcnt); } else { do { PREFETCH (); if (*d++ != (char) *p++) goto fail; } while (--mcnt); } SET_REGS_MATCHED (); break; /* Match any character except possibly a newline or a null. */ case anychar: DEBUG_PRINT1 ("EXECUTING anychar.\n"); PREFETCH (); if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n') || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000')) goto fail; SET_REGS_MATCHED (); DEBUG_PRINT2 (" Matched `%d'.\n", *d); d++; break; case charset: case charset_not: { register unsigned char c; boolean not = (re_opcode_t) *(p - 1) == charset_not; DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : ""); PREFETCH (); c = TRANSLATE (*d); /* The character to match. */ /* Cast to `unsigned' instead of `unsigned char' in case the bit list is a full 32 bytes long. */ if (c < (unsigned) (*p * BYTEWIDTH) && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) not = !not; p += 1 + *p; if (!not) goto fail; SET_REGS_MATCHED (); d++; break; } /* The beginning of a group is represented by start_memory. The arguments are the register number in the next byte, and the number of groups inner to this one in the next. The text matched within the group is recorded (in the internal registers data structure) under the register number. */ case start_memory: DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]); /* Find out if this group can match the empty string. */ p1 = p; /* To send to group_match_null_string_p. */ if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE) REG_MATCH_NULL_STRING_P (reg_info[*p]) = group_match_null_string_p (&p1, pend, reg_info); /* Save the position in the string where we were the last time we were at this open-group operator in case the group is operated upon by a repetition operator, e.g., with `(a*)*b' against `ab'; then we want to ignore where we are now in the string in case this attempt to match fails. */ old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) ? REG_UNSET (regstart[*p]) ? d : regstart[*p] : regstart[*p]; DEBUG_PRINT2 (" old_regstart: %d\n", POINTER_TO_OFFSET (old_regstart[*p])); regstart[*p] = d; DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p])); IS_ACTIVE (reg_info[*p]) = 1; MATCHED_SOMETHING (reg_info[*p]) = 0; /* This is the new highest active register. */ highest_active_reg = *p; /* If nothing was active before, this is the new lowest active register. */ if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) lowest_active_reg = *p; /* Move past the register number and inner group count. */ p += 2; break; /* The stop_memory opcode represents the end of a group. Its arguments are the same as start_memory's: the register number, and the number of inner groups. */ case stop_memory: DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]); /* We need to save the string position the last time we were at this close-group operator in case the group is operated upon by a repetition operator, e.g., with `((a*)*(b*)*)*' against `aba'; then we want to ignore where we are now in the string in case this attempt to match fails. */ old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) ? REG_UNSET (regend[*p]) ? d : regend[*p] : regend[*p]; DEBUG_PRINT2 (" old_regend: %d\n", POINTER_TO_OFFSET (old_regend[*p])); regend[*p] = d; DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p])); /* This register isn't active anymore. */ IS_ACTIVE (reg_info[*p]) = 0; /* If this was the only register active, nothing is active anymore. */ if (lowest_active_reg == highest_active_reg) { lowest_active_reg = NO_LOWEST_ACTIVE_REG; highest_active_reg = NO_HIGHEST_ACTIVE_REG; } else { /* We must scan for the new highest active register, since it isn't necessarily one less than now: consider (a(b)c(d(e)f)g). When group 3 ends, after the f), the new highest active register is 1. */ unsigned char r = *p - 1; while (r > 0 && !IS_ACTIVE (reg_info[r])) r--; /* If we end up at register zero, that means that we saved the registers as the result of an `on_failure_jump', not a `start_memory', and we jumped to past the innermost `stop_memory'. For example, in ((.)*) we save registers 1 and 2 as a result of the *, but when we pop back to the second ), we are at the stop_memory 1. Thus, nothing is active. */ if (r == 0) { lowest_active_reg = NO_LOWEST_ACTIVE_REG; highest_active_reg = NO_HIGHEST_ACTIVE_REG; } else highest_active_reg = r; } /* If just failed to match something this time around with a group that's operated on by a repetition operator, try to force exit from the ``loop'', and restore the register information for this group that we had before trying this last match. */ if ((!MATCHED_SOMETHING (reg_info[*p]) || (re_opcode_t) p[-3] == start_memory) && (p + 2) < pend) { boolean is_a_jump_n = false; p1 = p + 2; mcnt = 0; switch ((re_opcode_t) *p1++) { case jump_n: is_a_jump_n = true; case pop_failure_jump: case maybe_pop_jump: case jump: case dummy_failure_jump: EXTRACT_NUMBER_AND_INCR (mcnt, p1); if (is_a_jump_n) p1 += 2; break; default: /* do nothing */ ; } p1 += mcnt; /* If the next operation is a jump backwards in the pattern to an on_failure_jump right before the start_memory corresponding to this stop_memory, exit from the loop by forcing a failure after pushing on the stack the on_failure_jump's jump in the pattern, and d. */ if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump && (re_opcode_t) p1[3] == start_memory && p1[4] == *p) { /* If this group ever matched anything, then restore what its registers were before trying this last failed match, e.g., with `(a*)*b' against `ab' for regstart[1], and, e.g., with `((a*)*(b*)*)*' against `aba' for regend[3]. Also restore the registers for inner groups for, e.g., `((a*)(b*))*' against `aba' (register 3 would otherwise get trashed). */ if (EVER_MATCHED_SOMETHING (reg_info[*p])) { unsigned r; EVER_MATCHED_SOMETHING (reg_info[*p]) = 0; /* Restore this and inner groups' (if any) registers. */ for (r = *p; r < *p + *(p + 1); r++) { regstart[r] = old_regstart[r]; /* xx why this test? */ if ((long) old_regend[r] >= (long) regstart[r]) regend[r] = old_regend[r]; } } p1++; EXTRACT_NUMBER_AND_INCR (mcnt, p1); PUSH_FAILURE_POINT (p1 + mcnt, d, -2); goto fail; } } /* Move past the register number and the inner group count. */ p += 2; break; /* \ has been turned into a `duplicate' command which is followed by the numeric value of as the register number. */ case duplicate: { register const char *d2, *dend2; int regno = *p++; /* Get which register to match against. */ DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno); /* Can't back reference a group which we've never matched. */ if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno])) goto fail; /* Where in input to try to start matching. */ d2 = regstart[regno]; /* Where to stop matching; if both the place to start and the place to stop matching are in the same string, then set to the place to stop, otherwise, for now have to use the end of the first string. */ dend2 = ((FIRST_STRING_P (regstart[regno]) == FIRST_STRING_P (regend[regno])) ? regend[regno] : end_match_1); for (;;) { /* If necessary, advance to next segment in register contents. */ while (d2 == dend2) { if (dend2 == end_match_2) break; if (dend2 == regend[regno]) break; /* End of string1 => advance to string2. */ d2 = string2; dend2 = regend[regno]; } /* At end of register contents => success */ if (d2 == dend2) break; /* If necessary, advance to next segment in data. */ PREFETCH (); /* How many characters left in this segment to match. */ mcnt = dend - d; /* Want how many consecutive characters we can match in one shot, so, if necessary, adjust the count. */ if (mcnt > dend2 - d2) mcnt = dend2 - d2; /* Compare that many; failure if mismatch, else move past them. */ if (translate ? bcmp_translate (d, d2, mcnt, translate) : bcmp (d, d2, mcnt)) goto fail; d += mcnt, d2 += mcnt; } } break; /* begline matches the empty string at the beginning of the string (unless `not_bol' is set in `bufp'), and, if `newline_anchor' is set, after newlines. */ case begline: DEBUG_PRINT1 ("EXECUTING begline.\n"); if (AT_STRINGS_BEG (d)) { if (!bufp->not_bol) break; } else if (d[-1] == '\n' && bufp->newline_anchor) { break; } /* In all other cases, we fail. */ goto fail; /* endline is the dual of begline. */ case endline: DEBUG_PRINT1 ("EXECUTING endline.\n"); if (AT_STRINGS_END (d)) { if (!bufp->not_eol) break; } /* We have to ``prefetch'' the next character. */ else if ((d == end1 ? *string2 : *d) == '\n' && bufp->newline_anchor) { break; } goto fail; /* Match at the very beginning of the data. */ case begbuf: DEBUG_PRINT1 ("EXECUTING begbuf.\n"); if (AT_STRINGS_BEG (d)) break; goto fail; /* Match at the very end of the data. */ case endbuf: DEBUG_PRINT1 ("EXECUTING endbuf.\n"); if (AT_STRINGS_END (d)) break; goto fail; /* on_failure_keep_string_jump is used to optimize `.*\n'. It pushes NULL as the value for the string on the stack. Then `pop_failure_point' will keep the current value for the string, instead of restoring it. To see why, consider matching `foo\nbar' against `.*\n'. The .* matches the foo; then the . fails against the \n. But the next thing we want to do is match the \n against the \n; if we restored the string value, we would be back at the foo. Because this is used only in specific cases, we don't need to check all the things that `on_failure_jump' does, to make sure the right things get saved on the stack. Hence we don't share its code. The only reason to push anything on the stack at all is that otherwise we would have to change `anychar's code to do something besides goto fail in this case; that seems worse than this. */ case on_failure_keep_string_jump: DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump"); EXTRACT_NUMBER_AND_INCR (mcnt, p); DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt); PUSH_FAILURE_POINT (p + mcnt, NULL, -2); break; /* Uses of on_failure_jump: Each alternative starts with an on_failure_jump that points to the beginning of the next alternative. Each alternative except the last ends with a jump that in effect jumps past the rest of the alternatives. (They really jump to the ending jump of the following alternative, because tensioning these jumps is a hassle.) Repeats start with an on_failure_jump that points past both the repetition text and either the following jump or pop_failure_jump back to this on_failure_jump. */ case on_failure_jump: on_failure: DEBUG_PRINT1 ("EXECUTING on_failure_jump"); EXTRACT_NUMBER_AND_INCR (mcnt, p); DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt); /* If this on_failure_jump comes right before a group (i.e., the original * applied to a group), save the information for that group and all inner ones, so that if we fail back to this point, the group's information will be correct. For example, in \(a*\)*\1, we need the preceding group, and in \(\(a*\)b*\)\2, we need the inner group. */ /* We can't use `p' to check ahead because we push a failure point to `p + mcnt' after we do this. */ p1 = p; /* We need to skip no_op's before we look for the start_memory in case this on_failure_jump is happening as the result of a completed succeed_n, as in \(a\)\{1,3\}b\1 against aba. */ while (p1 < pend && (re_opcode_t) *p1 == no_op) p1++; if (p1 < pend && (re_opcode_t) *p1 == start_memory) { /* We have a new highest active register now. This will get reset at the start_memory we are about to get to, but we will have saved all the registers relevant to this repetition op, as described above. */ highest_active_reg = *(p1 + 1) + *(p1 + 2); if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) lowest_active_reg = *(p1 + 1); } DEBUG_PRINT1 (":\n"); PUSH_FAILURE_POINT (p + mcnt, d, -2); break; /* A smart repeat ends with `maybe_pop_jump'. We change it to either `pop_failure_jump' or `jump'. */ case maybe_pop_jump: EXTRACT_NUMBER_AND_INCR (mcnt, p); DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt); { register unsigned char *p2 = p; /* Compare the beginning of the repeat with what in the pattern follows its end. If we can establish that there is nothing that they would both match, i.e., that we would have to backtrack because of (as in, e.g., `a*a') then we can change to pop_failure_jump, because we'll never have to backtrack. This is not true in the case of alternatives: in `(a|ab)*' we do need to backtrack to the `ab' alternative (e.g., if the string was `ab'). But instead of trying to detect that here, the alternative has put on a dummy failure point which is what we will end up popping. */ /* Skip over open/close-group commands. */ while (p2 + 2 < pend && ((re_opcode_t) *p2 == stop_memory || (re_opcode_t) *p2 == start_memory)) p2 += 3; /* Skip over args, too. */ /* If we're at the end of the pattern, we can change. */ if (p2 == pend) { /* Consider what happens when matching ":\(.*\)" against ":/". I don't really understand this code yet. */ p[-3] = (unsigned char) pop_failure_jump; DEBUG_PRINT1 (" End of pattern: change to `pop_failure_jump'.\n"); } else if ((re_opcode_t) *p2 == exactn || (bufp->newline_anchor && (re_opcode_t) *p2 == endline)) { register unsigned char c = *p2 == (unsigned char) endline ? '\n' : p2[2]; p1 = p + mcnt; /* p1[0] ... p1[2] are the `on_failure_jump' corresponding to the `maybe_finalize_jump' of this case. Examine what follows. */ if ((re_opcode_t) p1[3] == exactn && p1[5] != c) { p[-3] = (unsigned char) pop_failure_jump; DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", c, p1[5]); } else if ((re_opcode_t) p1[3] == charset || (re_opcode_t) p1[3] == charset_not) { int not = (re_opcode_t) p1[3] == charset_not; if (c < (unsigned char) (p1[4] * BYTEWIDTH) && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) not = !not; /* `not' is equal to 1 if c would match, which means that we can't change to pop_failure_jump. */ if (!not) { p[-3] = (unsigned char) pop_failure_jump; DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); } } } } p -= 2; /* Point at relative address again. */ if ((re_opcode_t) p[-1] != pop_failure_jump) { p[-1] = (unsigned char) jump; DEBUG_PRINT1 (" Match => jump.\n"); goto unconditional_jump; } /* Note fall through. */ /* The end of a simple repeat has a pop_failure_jump back to its matching on_failure_jump, where the latter will push a failure point. The pop_failure_jump takes off failure points put on by this pop_failure_jump's matching on_failure_jump; we got through the pattern to here from the matching on_failure_jump, so didn't fail. */ case pop_failure_jump: { /* We need to pass separate storage for the lowest and highest registers, even though we don't care about the actual values. Otherwise, we will restore only one register from the stack, since lowest will == highest in `pop_failure_point'. */ unsigned dummy_low_reg, dummy_high_reg; unsigned char *pdummy; const char *sdummy; DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n"); POP_FAILURE_POINT (sdummy, pdummy, dummy_low_reg, dummy_high_reg, reg_dummy, reg_dummy, reg_info_dummy); } /* Note fall through. */ /* Unconditionally jump (without popping any failure points). */ case jump: unconditional_jump: EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */ DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt); p += mcnt; /* Do the jump. */ DEBUG_PRINT2 ("(to 0x%x).\n", p); break; /* We need this opcode so we can detect where alternatives end in `group_match_null_string_p' et al. */ case jump_past_alt: DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n"); goto unconditional_jump; /* Normally, the on_failure_jump pushes a failure point, which then gets popped at pop_failure_jump. We will end up at pop_failure_jump, also, and with a pattern of, say, `a+', we are skipping over the on_failure_jump, so we have to push something meaningless for pop_failure_jump to pop. */ case dummy_failure_jump: DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n"); /* It doesn't matter what we push for the string here. What the code at `fail' tests is the value for the pattern. */ PUSH_FAILURE_POINT (0, 0, -2); goto unconditional_jump; /* At the end of an alternative, we need to push a dummy failure point in case we are followed by a `pop_failure_jump', because we don't want the failure point for the alternative to be popped. For example, matching `(a|ab)*' against `aab' requires that we match the `ab' alternative. */ case push_dummy_failure: DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n"); /* See comments just above at `dummy_failure_jump' about the two zeroes. */ PUSH_FAILURE_POINT (0, 0, -2); break; /* Have to succeed matching what follows at least n times. After that, handle like `on_failure_jump'. */ case succeed_n: EXTRACT_NUMBER (mcnt, p + 2); DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt); assert (mcnt >= 0); /* Originally, this is how many times we HAVE to succeed. */ if (mcnt > 0) { mcnt--; p += 2; STORE_NUMBER_AND_INCR (p, mcnt); DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p, mcnt); } else if (mcnt == 0) { DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", p+2); p[2] = (unsigned char) no_op; p[3] = (unsigned char) no_op; goto on_failure; } break; case jump_n: EXTRACT_NUMBER (mcnt, p + 2); DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt); /* Originally, this is how many times we CAN jump. */ if (mcnt) { mcnt--; STORE_NUMBER (p + 2, mcnt); goto unconditional_jump; } /* If don't have to jump any more, skip over the rest of command. */ else p += 4; break; case set_number_at: { DEBUG_PRINT1 ("EXECUTING set_number_at.\n"); EXTRACT_NUMBER_AND_INCR (mcnt, p); p1 = p + mcnt; EXTRACT_NUMBER_AND_INCR (mcnt, p); DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt); STORE_NUMBER (p1, mcnt); break; } case wordbound: DEBUG_PRINT1 ("EXECUTING wordbound.\n"); if (AT_WORD_BOUNDARY (d)) break; goto fail; case notwordbound: DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); if (AT_WORD_BOUNDARY (d)) goto fail; break; case wordbeg: DEBUG_PRINT1 ("EXECUTING wordbeg.\n"); if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1))) break; goto fail; case wordend: DEBUG_PRINT1 ("EXECUTING wordend.\n"); if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1) && (!WORDCHAR_P (d) || AT_STRINGS_END (d))) break; goto fail; #ifdef emacs #ifdef emacs19 case before_dot: DEBUG_PRINT1 ("EXECUTING before_dot.\n"); if (PTR_CHAR_POS ((unsigned char *) d) >= point) goto fail; break; case at_dot: DEBUG_PRINT1 ("EXECUTING at_dot.\n"); if (PTR_CHAR_POS ((unsigned char *) d) != point) goto fail; break; case after_dot: DEBUG_PRINT1 ("EXECUTING after_dot.\n"); if (PTR_CHAR_POS ((unsigned char *) d) <= point) goto fail; break; #else /* not emacs19 */ case at_dot: DEBUG_PRINT1 ("EXECUTING at_dot.\n"); if (PTR_CHAR_POS ((unsigned char *) d) + 1 != point) goto fail; break; #endif /* not emacs19 */ case syntaxspec: DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt); mcnt = *p++; goto matchsyntax; case wordchar: DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n"); mcnt = (int) Sword; matchsyntax: PREFETCH (); if (SYNTAX (*d++) != (enum syntaxcode) mcnt) goto fail; SET_REGS_MATCHED (); break; case notsyntaxspec: DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt); mcnt = *p++; goto matchnotsyntax; case notwordchar: DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n"); mcnt = (int) Sword; matchnotsyntax: PREFETCH (); if (SYNTAX (*d++) == (enum syntaxcode) mcnt) goto fail; SET_REGS_MATCHED (); break; #else /* not emacs */ case wordchar: DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n"); PREFETCH (); if (!WORDCHAR_P (d)) goto fail; SET_REGS_MATCHED (); d++; break; case notwordchar: DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n"); PREFETCH (); if (WORDCHAR_P (d)) goto fail; SET_REGS_MATCHED (); d++; break; #endif /* not emacs */ default: abort (); } continue; /* Successfully executed one pattern command; keep going. */ /* We goto here if a matching operation fails. */ fail: if (!FAIL_STACK_EMPTY ()) { /* A restart point is known. Restore to that state. */ DEBUG_PRINT1 ("\nFAIL:\n"); POP_FAILURE_POINT (d, p, lowest_active_reg, highest_active_reg, regstart, regend, reg_info); /* If this failure point is a dummy, try the next one. */ if (!p) goto fail; /* If we failed to the end of the pattern, don't examine *p. */ assert (p <= pend); if (p < pend) { boolean is_a_jump_n = false; /* If failed to a backwards jump that's part of a repetition loop, need to pop this failure point and use the next one. */ switch ((re_opcode_t) *p) { case jump_n: is_a_jump_n = true; case maybe_pop_jump: case pop_failure_jump: case jump: p1 = p + 1; EXTRACT_NUMBER_AND_INCR (mcnt, p1); p1 += mcnt; if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n) || (!is_a_jump_n && (re_opcode_t) *p1 == on_failure_jump)) goto fail; break; default: /* do nothing */ ; } } if (d >= string1 && d <= end1) dend = end_match_1; } else break; /* Matching at this starting point really fails. */ } /* for (;;) */ if (best_regs_set) goto restore_best_regs; FREE_VARIABLES (); return -1; /* Failure to match. */ } /* re_match_2 */ /* Subroutine definitions for re_match_2. */ /* We are passed P pointing to a register number after a start_memory. Return true if the pattern up to the corresponding stop_memory can match the empty string, and false otherwise. If we find the matching stop_memory, sets P to point to one past its number. Otherwise, sets P to an undefined byte less than or equal to END. We don't handle duplicates properly (yet). */ static boolean group_match_null_string_p (p, end, reg_info) unsigned char **p, *end; register_info_type *reg_info; { int mcnt; /* Point to after the args to the start_memory. */ unsigned char *p1 = *p + 2; while (p1 < end) { /* Skip over opcodes that can match nothing, and return true or false, as appropriate, when we get to one that can't, or to the matching stop_memory. */ switch ((re_opcode_t) *p1) { /* Could be either a loop or a series of alternatives. */ case on_failure_jump: p1++; EXTRACT_NUMBER_AND_INCR (mcnt, p1); /* If the next operation is not a jump backwards in the pattern. */ if (mcnt >= 0) { /* Go through the on_failure_jumps of the alternatives, seeing if any of the alternatives cannot match nothing. The last alternative starts with only a jump, whereas the rest start with on_failure_jump and end with a jump, e.g., here is the pattern for `a|b|c': /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6 /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3 /exactn/1/c So, we have to first go through the first (n-1) alternatives and then deal with the last one separately. */ /* Deal with the first (n-1) alternatives, which start with an on_failure_jump (see above) that jumps to right past a jump_past_alt. */ while ((re_opcode_t) p1[mcnt-3] == jump_past_alt) { /* `mcnt' holds how many bytes long the alternative is, including the ending `jump_past_alt' and its number. */ if (!alt_match_null_string_p (p1, p1 + mcnt - 3, reg_info)) return false; /* Move to right after this alternative, including the jump_past_alt. */ p1 += mcnt; /* Break if it's the beginning of an n-th alternative that doesn't begin with an on_failure_jump. */ if ((re_opcode_t) *p1 != on_failure_jump) break; /* Still have to check that it's not an n-th alternative that starts with an on_failure_jump. */ p1++; EXTRACT_NUMBER_AND_INCR (mcnt, p1); if ((re_opcode_t) p1[mcnt-3] != jump_past_alt) { /* Get to the beginning of the n-th alternative. */ p1 -= 3; break; } } /* Deal with the last alternative: go back and get number of the `jump_past_alt' just before it. `mcnt' contains the length of the alternative. */ EXTRACT_NUMBER (mcnt, p1 - 2); if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info)) return false; p1 += mcnt; /* Get past the n-th alternative. */ } /* if mcnt > 0 */ break; case stop_memory: assert (p1[1] == **p); *p = p1 + 2; return true; default: if (!common_op_match_null_string_p (&p1, end, reg_info)) return false; } } /* while p1 < end */ return false; } /* group_match_null_string_p */ /* Similar to group_match_null_string_p, but doesn't deal with alternatives: It expects P to be the first byte of a single alternative and END one byte past the last. The alternative can contain groups. */ static boolean alt_match_null_string_p (p, end, reg_info) unsigned char *p, *end; register_info_type *reg_info; { int mcnt; unsigned char *p1 = p; while (p1 < end) { /* Skip over opcodes that can match nothing, and break when we get to one that can't. */ switch ((re_opcode_t) *p1) { /* It's a loop. */ case on_failure_jump: p1++; EXTRACT_NUMBER_AND_INCR (mcnt, p1); p1 += mcnt; break; default: if (!common_op_match_null_string_p (&p1, end, reg_info)) return false; } } /* while p1 < end */ return true; } /* alt_match_null_string_p */ /* Deals with the ops common to group_match_null_string_p and alt_match_null_string_p. Sets P to one after the op and its arguments, if any. */ static boolean common_op_match_null_string_p (p, end, reg_info) unsigned char **p, *end; register_info_type *reg_info; { int mcnt; boolean ret; int reg_no; unsigned char *p1 = *p; switch ((re_opcode_t) *p1++) { case no_op: case begline: case endline: case begbuf: case endbuf: case wordbeg: case wordend: case wordbound: case notwordbound: #ifdef emacs case before_dot: case at_dot: case after_dot: #endif break; case start_memory: reg_no = *p1; assert (reg_no > 0 && reg_no <= MAX_REGNUM); ret = group_match_null_string_p (&p1, end, reg_info); /* Have to set this here in case we're checking a group which contains a group and a back reference to it. */ if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE) REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret; if (!ret) return false; break; /* If this is an optimized succeed_n for zero times, make the jump. */ case jump: EXTRACT_NUMBER_AND_INCR (mcnt, p1); if (mcnt >= 0) p1 += mcnt; else return false; break; case succeed_n: /* Get to the number of times to succeed. */ p1 += 2; EXTRACT_NUMBER_AND_INCR (mcnt, p1); if (mcnt == 0) { p1 -= 4; EXTRACT_NUMBER_AND_INCR (mcnt, p1); p1 += mcnt; } else return false; break; case duplicate: if (!REG_MATCH_NULL_STRING_P (reg_info[*p1])) return false; break; case set_number_at: p1 += 4; default: /* All other opcodes mean we cannot match the empty string. */ return false; } *p = p1; return true; } /* common_op_match_null_string_p */ /* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN bytes; nonzero otherwise. */ static int bcmp_translate (s1, s2, len, translate) unsigned char *s1, *s2; register int len; char *translate; { register unsigned char *p1 = s1, *p2 = s2; while (len) { if (translate[*p1++] != translate[*p2++]) return 1; len--; } return 0; } /* Entry points for GNU code. */ /* re_compile_pattern is the GNU regular expression compiler: it compiles PATTERN (of length SIZE) and puts the result in BUFP. Returns 0 if the pattern was valid, otherwise an error string. Assumes the `allocated' (and perhaps `buffer') and `translate' fields are set in BUFP on entry. We call regex_compile to do the actual compilation. */ const char * re_compile_pattern (pattern, length, bufp) const char *pattern; int length; struct re_pattern_buffer *bufp; { reg_errcode_t ret; /* GNU code is written to assume at least RE_NREGS registers will be set (and at least one extra will be -1). */ bufp->regs_allocated = REGS_UNALLOCATED; /* And GNU code determines whether or not to get register information by passing null for the REGS argument to re_match, etc., not by setting no_sub. */ bufp->no_sub = 0; /* Match anchors at newline. */ bufp->newline_anchor = 1; ret = regex_compile (pattern, length, re_syntax_options, bufp); return re_error_msg[(int) ret]; } /* Entry points compatible with 4.2 BSD regex library. We don't define them if this is an Emacs or POSIX compilation. */ #if !defined (emacs) && !defined (_POSIX_SOURCE) /* BSD has one and only one pattern buffer. */ static struct re_pattern_buffer re_comp_buf; char * re_comp (s) const char *s; { reg_errcode_t ret; if (!s) { if (!re_comp_buf.buffer) return "No previous regular expression"; return 0; } if (!re_comp_buf.buffer) { re_comp_buf.buffer = (unsigned char *) malloc (200); if (re_comp_buf.buffer == NULL) return "Memory exhausted"; re_comp_buf.allocated = 200; re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH); if (re_comp_buf.fastmap == NULL) return "Memory exhausted"; } /* Since `re_exec' always passes NULL for the `regs' argument, we don't need to initialize the pattern buffer fields which affect it. */ /* Match anchors at newlines. */ re_comp_buf.newline_anchor = 1; ret = regex_compile (s, (int) strlen(s), re_syntax_options, &re_comp_buf); /* Yes, we're discarding `const' here. */ return (char *) re_error_msg[(int) ret]; } int re_exec (s) const char *s; { const int len = strlen (s); return 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0); } #endif /* not emacs and not _POSIX_SOURCE */ /* POSIX.2 functions. Don't define these for Emacs. */ #ifndef emacs /* regcomp takes a regular expression as a string and compiles it. PREG is a regex_t *. We do not expect any fields to be initialized, since POSIX says we shouldn't. Thus, we set `buffer' to the compiled pattern; `used' to the length of the compiled pattern; `syntax' to RE_SYNTAX_POSIX_EXTENDED if the REG_EXTENDED bit in CFLAGS is set; otherwise, to RE_SYNTAX_POSIX_BASIC; `newline_anchor' to REG_NEWLINE being set in CFLAGS; `fastmap' and `fastmap_accurate' to zero; `re_nsub' to the number of subexpressions in PATTERN. PATTERN is the address of the pattern string. CFLAGS is a series of bits which affect compilation. If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we use POSIX basic syntax. If REG_NEWLINE is set, then . and [^...] don't match newline. Also, regexec will try a match beginning after every newline. If REG_ICASE is set, then we considers upper- and lowercase versions of letters to be equivalent when matching. If REG_NOSUB is set, then when PREG is passed to regexec, that routine will report only success or failure, and nothing about the registers. It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for the return codes and their meanings.) */ int regcomp (preg, pattern, cflags) regex_t *preg; const char *pattern; int cflags; { reg_errcode_t ret; unsigned syntax = (cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC; /* regex_compile will allocate the space for the compiled pattern. */ preg->buffer = 0; preg->allocated = 0; /* Don't bother to use a fastmap when searching. This simplifies the REG_NEWLINE case: if we used a fastmap, we'd have to put all the characters after newlines into the fastmap. This way, we just try every character. */ preg->fastmap = 0; if (cflags & REG_ICASE) { unsigned i; preg->translate = (char *) malloc (CHAR_SET_SIZE); if (preg->translate == NULL) return (int) REG_ESPACE; /* Map uppercase characters to corresponding lowercase ones. */ for (i = 0; i < CHAR_SET_SIZE; i++) preg->translate[i] = ISUPPER (i) ? tolower (i) : i; } else preg->translate = NULL; /* If REG_NEWLINE is set, newlines are treated differently. */ if (cflags & REG_NEWLINE) { /* REG_NEWLINE implies neither . nor [^...] match newline. */ syntax &= ~RE_DOT_NEWLINE; syntax |= RE_HAT_LISTS_NOT_NEWLINE; /* It also changes the matching behavior. */ preg->newline_anchor = 1; } else preg->newline_anchor = 0; preg->no_sub = !!(cflags & REG_NOSUB); /* POSIX says a null character in the pattern terminates it, so we can use strlen here in compiling the pattern. */ ret = regex_compile (pattern, (int) strlen(pattern), syntax, preg); /* POSIX doesn't distinguish between an unmatched open-group and an unmatched close-group: both are REG_EPAREN. */ if (ret == REG_ERPAREN) ret = REG_EPAREN; return (int) ret; } /* regexec searches for a given pattern, specified by PREG, in the string STRING. If NMATCH is zero or REG_NOSUB was set in the cflags argument to `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at least NMATCH elements, and we set them to the offsets of the corresponding matched substrings. EFLAGS specifies `execution flags' which affect matching: if REG_NOTBOL is set, then ^ does not match at the beginning of the string; if REG_NOTEOL is set, then $ does not match at the end. We return 0 if we find a match and REG_NOMATCH if not. */ int regexec (preg, string, nmatch, pmatch, eflags) const regex_t *preg; const char *string; size_t nmatch; regmatch_t pmatch[]; int eflags; { int ret; struct re_registers regs; regex_t private_preg; int len = strlen (string); boolean want_reg_info = !preg->no_sub && nmatch > 0; private_preg = *preg; private_preg.not_bol = !!(eflags & REG_NOTBOL); private_preg.not_eol = !!(eflags & REG_NOTEOL); /* The user has told us exactly how many registers to return information about, via `nmatch'. We have to pass that on to the matching routines. */ private_preg.regs_allocated = REGS_FIXED; if (want_reg_info) { regs.num_regs = nmatch; regs.start = TALLOC (nmatch, regoff_t); regs.end = TALLOC (nmatch, regoff_t); if (regs.start == NULL || regs.end == NULL) return (int) REG_NOMATCH; } /* Perform the searching operation. */ ret = re_search (&private_preg, string, len, /* start: */ 0, /* range: */ len, want_reg_info ? ®s : (struct re_registers *) 0); /* Copy the register information to the POSIX structure. */ if (want_reg_info) { if (ret >= 0) { unsigned r; for (r = 0; r < nmatch; r++) { pmatch[r].rm_so = regs.start[r]; pmatch[r].rm_eo = regs.end[r]; } } /* If we needed the temporary register info, free the space now. */ free (regs.start); free (regs.end); } /* We want zero return to mean success, unlike `re_search'. */ return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH; } /* Returns a message corresponding to an error code, ERRCODE, returned from either regcomp or regexec. We don't use PREG here. */ size_t regerror (errcode, preg, errbuf, errbuf_size) int errcode; const regex_t *preg; char *errbuf; size_t errbuf_size; { const char *msg; size_t msg_size; if (errcode < 0 || errcode >= (sizeof (re_error_msg) / sizeof (re_error_msg[0]))) /* Only error codes returned by the rest of the code should be passed to this routine. If we are given anything else, or if other regex code generates an invalid error code, then the program has a bug. Dump core so we can fix it. */ abort (); msg = re_error_msg[errcode]; /* POSIX doesn't require that we do anything in this case, but why not be nice. */ if (! msg) msg = "Success"; msg_size = strlen (msg) + 1; /* Includes the null. */ if (errbuf_size != 0) { if (msg_size > errbuf_size) { strncpy (errbuf, msg, errbuf_size - 1); errbuf[errbuf_size - 1] = 0; } else strcpy (errbuf, msg); } return msg_size; } /* Free dynamically allocated space used by PREG. */ void regfree (preg) regex_t *preg; { if (preg->buffer != NULL) free (preg->buffer); preg->buffer = NULL; preg->allocated = 0; preg->used = 0; if (preg->fastmap != NULL) free (preg->fastmap); preg->fastmap = NULL; preg->fastmap_accurate = 0; if (preg->translate != NULL) free (preg->translate); preg->translate = NULL; } #endif /* not emacs */ /* Local variables: make-backup-files: t version-control: t trim-versions-without-asking: nil End: */ ./pvm3/src/regex/regex.h0100644007401100000360000004441606332404231014272 0ustar kohlgopher/* Definitions for data structures and routines for the regular expression library, version 0.12. Copyright (C) 1985, 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __REGEXP_LIBRARY_H__ #define __REGEXP_LIBRARY_H__ /* POSIX says that must be included (by the caller) before . */ #ifdef VMS /* VMS doesn't have `size_t' in , even though POSIX says it should be there. */ #include #endif /* The following bits are used to determine the regexp syntax we recognize. The set/not-set meanings are chosen so that Emacs syntax remains the value 0. The bits are given in alphabetical order, and the definitions shifted by one from the previous bit; thus, when we add or remove a bit, only one other definition need change. */ typedef unsigned reg_syntax_t; /* If this bit is not set, then \ inside a bracket expression is literal. If set, then such a \ quotes the following character. */ #define RE_BACKSLASH_ESCAPE_IN_LISTS (1) /* If this bit is not set, then + and ? are operators, and \+ and \? are literals. If set, then \+ and \? are operators and + and ? are literals. */ #define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1) /* If this bit is set, then character classes are supported. They are: [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. If not set, then character classes are not supported. */ #define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) /* If this bit is set, then ^ and $ are always anchors (outside bracket expressions, of course). If this bit is not set, then it depends: ^ is an anchor if it is at the beginning of a regular expression or after an open-group or an alternation operator; $ is an anchor if it is at the end of a regular expression, or before a close-group or an alternation operator. This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because POSIX draft 11.2 says that * etc. in leading positions is undefined. We already implemented a previous draft which made those constructs invalid, though, so we haven't changed the code back. */ #define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) /* If this bit is set, then special characters are always special regardless of where they are in the pattern. If this bit is not set, then special characters are special only in some contexts; otherwise they are ordinary. Specifically, * + ? and intervals are only special when not after the beginning, open-group, or alternation operator. */ #define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) /* If this bit is set, then *, +, ?, and { cannot be first in an re or immediately after an alternation or begin-group operator. */ #define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) /* If this bit is set, then . matches newline. If not set, then it doesn't. */ #define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) /* If this bit is set, then . doesn't match NUL. If not set, then it does. */ #define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) /* If this bit is set, nonmatching lists [^...] do not match newline. If not set, they do. */ #define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1) /* If this bit is set, either \{...\} or {...} defines an interval, depending on RE_NO_BK_BRACES. If not set, \{, \}, {, and } are literals. */ #define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) /* If this bit is set, +, ? and | aren't recognized as operators. If not set, they are. */ #define RE_LIMITED_OPS (RE_INTERVALS << 1) /* If this bit is set, newline is an alternation operator. If not set, newline is literal. */ #define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) /* If this bit is set, then `{...}' defines an interval, and \{ and \} are literals. If not set, then `\{...\}' defines an interval. */ #define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) /* If this bit is set, (...) defines a group, and \( and \) are literals. If not set, \(...\) defines a group, and ( and ) are literals. */ #define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) /* If this bit is set, then \ matches . If not set, then \ is a back-reference. */ #define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) /* If this bit is set, then | is an alternation operator, and \| is literal. If not set, then \| is an alternation operator, and | is literal. */ #define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) /* If this bit is set, then an ending range point collating higher than the starting range point, as in [z-a], is invalid. If not set, then when ending range point collates higher than the starting range point, the range is ignored. */ #define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1) /* If this bit is set, then an unmatched ) is ordinary. If not set, then an unmatched ) is invalid. */ #define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1) /* This global variable defines the particular regexp syntax to use (for some interfaces). When a regexp is compiled, the syntax used is stored in the pattern buffer, so changing this does not affect already-compiled regexps. */ extern reg_syntax_t re_syntax_options; /* Define combinations of the above bits for the standard possibilities. (The [[[ comments delimit what gets put into the Texinfo file, so don't delete them!) */ /* [[[begin syntaxes]]] */ #define RE_SYNTAX_EMACS 0 #define RE_SYNTAX_AWK \ (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \ | RE_NO_BK_PARENS | RE_NO_BK_REFS \ | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ | RE_UNMATCHED_RIGHT_PAREN_ORD) #define RE_SYNTAX_POSIX_AWK \ (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS) #define RE_SYNTAX_GREP \ (RE_BK_PLUS_QM | RE_CHAR_CLASSES \ | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \ | RE_NEWLINE_ALT) #define RE_SYNTAX_EGREP \ (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \ | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \ | RE_NEWLINE_ALT | RE_NO_BK_PARENS \ | RE_NO_BK_VBAR) #define RE_SYNTAX_POSIX_EGREP \ (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES) /* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */ #define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC #define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC /* Syntax bits common to both basic and extended POSIX regex syntax. */ #define _RE_SYNTAX_POSIX_COMMON \ (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ | RE_INTERVALS | RE_NO_EMPTY_RANGES) #define RE_SYNTAX_POSIX_BASIC \ (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM) /* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this isn't minimal, since other operators, such as \`, aren't disabled. */ #define RE_SYNTAX_POSIX_MINIMAL_BASIC \ (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS) #define RE_SYNTAX_POSIX_EXTENDED \ (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \ | RE_NO_BK_PARENS | RE_NO_BK_VBAR \ | RE_UNMATCHED_RIGHT_PAREN_ORD) /* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS replaces RE_CONTEXT_INDEP_OPS and RE_NO_BK_REFS is added. */ #define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \ (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \ | RE_NO_BK_PARENS | RE_NO_BK_REFS \ | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) /* [[[end syntaxes]]] */ /* Maximum number of duplicates an interval can allow. Some systems (erroneously) define this in other header files, but we want our value, so remove any previous define. */ #ifdef RE_DUP_MAX #undef RE_DUP_MAX #endif #define RE_DUP_MAX ((1 << 15) - 1) /* POSIX `cflags' bits (i.e., information for `regcomp'). */ /* If this bit is set, then use extended regular expression syntax. If not set, then use basic regular expression syntax. */ #define REG_EXTENDED 1 /* If this bit is set, then ignore case when matching. If not set, then case is significant. */ #define REG_ICASE (REG_EXTENDED << 1) /* If this bit is set, then anchors do not match at newline characters in the string. If not set, then anchors do match at newlines. */ #define REG_NEWLINE (REG_ICASE << 1) /* If this bit is set, then report only success or fail in regexec. If not set, then returns differ between not matching and errors. */ #define REG_NOSUB (REG_NEWLINE << 1) /* POSIX `eflags' bits (i.e., information for regexec). */ /* If this bit is set, then the beginning-of-line operator doesn't match the beginning of the string (presumably because it's not the beginning of a line). If not set, then the beginning-of-line operator does match the beginning of the string. */ #define REG_NOTBOL 1 /* Like REG_NOTBOL, except for the end-of-line. */ #define REG_NOTEOL (1 << 1) /* If any error codes are removed, changed, or added, update the `re_error_msg' table in regex.c. */ typedef enum { REG_NOERROR = 0, /* Success. */ REG_NOMATCH, /* Didn't find a match (for regexec). */ /* POSIX regcomp return error codes. (In the order listed in the standard.) */ REG_BADPAT, /* Invalid pattern. */ REG_ECOLLATE, /* Not implemented. */ REG_ECTYPE, /* Invalid character class name. */ REG_EESCAPE, /* Trailing backslash. */ REG_ESUBREG, /* Invalid back reference. */ REG_EBRACK, /* Unmatched left bracket. */ REG_EPAREN, /* Parenthesis imbalance. */ REG_EBRACE, /* Unmatched \{. */ REG_BADBR, /* Invalid contents of \{\}. */ REG_ERANGE, /* Invalid range end. */ REG_ESPACE, /* Ran out of memory. */ REG_BADRPT, /* No preceding re for repetition op. */ /* Error codes we've added. */ REG_EEND, /* Premature end. */ REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */ REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ } reg_errcode_t; /* This data structure represents a compiled pattern. Before calling the pattern compiler, the fields `buffer', `allocated', `fastmap', `translate', and `no_sub' can be set. After the pattern has been compiled, the `re_nsub' field is available. All other fields are private to the regex routines. */ struct re_pattern_buffer { /* [[[begin pattern_buffer]]] */ /* Space that holds the compiled pattern. It is declared as `unsigned char *' because its elements are sometimes used as array indexes. */ unsigned char *buffer; /* Number of bytes to which `buffer' points. */ unsigned long allocated; /* Number of bytes actually used in `buffer'. */ unsigned long used; /* Syntax setting with which the pattern was compiled. */ reg_syntax_t syntax; /* Pointer to a fastmap, if any, otherwise zero. re_search uses the fastmap, if there is one, to skip over impossible starting points for matches. */ char *fastmap; /* Either a translate table to apply to all characters before comparing them, or zero for no translation. The translation is applied to a pattern when it is compiled and to a string when it is matched. */ char *translate; /* Number of subexpressions found by the compiler. */ size_t re_nsub; /* Zero if this pattern cannot match the empty string, one else. Well, in truth it's used only in `re_search_2', to see whether or not we should use the fastmap, so we don't set this absolutely perfectly; see `re_compile_fastmap' (the `duplicate' case). */ unsigned can_be_null : 1; /* If REGS_UNALLOCATED, allocate space in the `regs' structure for `max (RE_NREGS, re_nsub + 1)' groups. If REGS_REALLOCATE, reallocate space if necessary. If REGS_FIXED, use what's there. */ #define REGS_UNALLOCATED 0 #define REGS_REALLOCATE 1 #define REGS_FIXED 2 unsigned regs_allocated : 2; /* Set to zero when `regex_compile' compiles a pattern; set to one by `re_compile_fastmap' if it updates the fastmap. */ unsigned fastmap_accurate : 1; /* If set, `re_match_2' does not return information about subexpressions. */ unsigned no_sub : 1; /* If set, a beginning-of-line anchor doesn't match at the beginning of the string. */ unsigned not_bol : 1; /* Similarly for an end-of-line anchor. */ unsigned not_eol : 1; /* If true, an anchor at a newline matches. */ unsigned newline_anchor : 1; /* [[[end pattern_buffer]]] */ }; typedef struct re_pattern_buffer regex_t; /* search.c (search_buffer) in Emacs needs this one opcode value. It is defined both in `regex.c' and here. */ #define RE_EXACTN_VALUE 1 /* Type for byte offsets within the string. POSIX mandates this. */ typedef int regoff_t; /* This is the structure we store register match data in. See regex.texinfo for a full description of what registers match. */ struct re_registers { unsigned num_regs; regoff_t *start; regoff_t *end; }; /* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer, `re_match_2' returns information about at least this many registers the first time a `regs' structure is passed. */ #ifndef RE_NREGS #define RE_NREGS 30 #endif /* POSIX specification for registers. Aside from the different names than `re_registers', POSIX uses an array of structures, instead of a structure of arrays. */ typedef struct { regoff_t rm_so; /* Byte offset from string's start to substring's start. */ regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ } regmatch_t; /* Declarations for routines. */ /* To avoid duplicating every routine declaration -- once with a prototype (if we are ANSI), and once without (if we aren't) -- we use the following macro to declare argument types. This unfortunately clutters up the declarations a bit, but I think it's worth it. */ #if __STDC__ #define _RE_ARGS(args) args #else /* not __STDC__ */ #define _RE_ARGS(args) () #endif /* not __STDC__ */ /* Sets the current default syntax to SYNTAX, and return the old syntax. You can also simply assign to the `re_syntax_options' variable. */ extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax)); /* Compile the regular expression PATTERN, with length LENGTH and syntax given by the global `re_syntax_options', into the buffer BUFFER. Return NULL if successful, and an error string if not. */ extern const char *re_compile_pattern _RE_ARGS ((const char *pattern, int length, struct re_pattern_buffer *buffer)); /* Compile a fastmap for the compiled pattern in BUFFER; used to accelerate searches. Return 0 if successful and -2 if was an internal error. */ extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer)); /* Search in the string STRING (with length LENGTH) for the pattern compiled into BUFFER. Start searching at position START, for RANGE characters. Return the starting position of the match, -1 for no match, or -2 for an internal error. Also return register information in REGS (if REGS and BUFFER->no_sub are nonzero). */ extern int re_search _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, int length, int start, int range, struct re_registers *regs)); /* Like `re_search', but search in the concatenation of STRING1 and STRING2. Also, stop searching at index START + STOP. */ extern int re_search_2 _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, int length1, const char *string2, int length2, int start, int range, struct re_registers *regs, int stop)); /* Like `re_search', but return how many characters in STRING the regexp in BUFFER matched, starting at position START. */ extern int re_match _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, int length, int start, struct re_registers *regs)); /* Relates to `re_match' as `re_search_2' relates to `re_search'. */ extern int re_match_2 _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, int length1, const char *string2, int length2, int start, struct re_registers *regs, int stop)); /* Set REGS to hold NUM_REGS registers, storing them in STARTS and ENDS. Subsequent matches using BUFFER and REGS will use this memory for recording register information. STARTS and ENDS must be allocated with malloc, and must each be at least `NUM_REGS * sizeof (regoff_t)' bytes long. If NUM_REGS == 0, then subsequent matches should allocate their own register data. Unless this function is called, the first search or match using PATTERN_BUFFER will allocate its own register data, without freeing the old data. */ extern void re_set_registers _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs, unsigned num_regs, regoff_t *starts, regoff_t *ends)); /* 4.2 bsd compatibility. */ extern char *re_comp _RE_ARGS ((const char *)); extern int re_exec _RE_ARGS ((const char *)); /* POSIX compatibility. */ extern int regcomp _RE_ARGS ((regex_t *preg, const char *pattern, int cflags)); extern int regexec _RE_ARGS ((const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags)); extern size_t regerror _RE_ARGS ((int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)); extern void regfree _RE_ARGS ((regex_t *preg)); #endif /* not __REGEXP_LIBRARY_H__ */ /* Local variables: make-backup-files: t version-control: t trim-versions-without-asking: nil End: */ ./pvm3/src/regex/Makefile.in0100644007401100000360000000564006333421767015066 0ustar kohlgopher# Makefile for regex. # # Copyright (C) 1992, 1993 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. version = 0.12 # You can define CPPFLAGS on the command line. Aside from system-specific # flags, you can define: # -DREGEX_MALLOC to use malloc/realloc/free instead of alloca. # -DDEBUG to enable the compiled pattern disassembler and execution # tracing; code runs substantially slower. # -DEXTRACT_MACROS to use the macros EXTRACT_* (as opposed to # the corresponding C procedures). If not -DDEBUG, the macros # are used. CPPFLAGS = # Likewise, you can override CFLAGS to optimize, use -Wall, etc. CFLAGS = -g # Ditto for LDFLAGS and LOADLIBES. LDFLAGS = LOADLIBES = srcdir = @srcdir@ VPATH = @srcdir@ CC = @CC@ DEFS = @DEFS@ SHELL = /bin/sh subdirs = doc test default all:: pvmregex.o regex.o .PHONY: default all pvmregex.o: pvmregex.c regex.h $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) -I. -I$(srcdir) -c $< regex.o: regex.c regex.h $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) -I. -I$(srcdir) -c $< clean mostlyclean:: rm -f *.o distclean:: clean rm -f Makefile config.status extraclean:: distclean rm -f patch* *~* *\#* *.orig *.rej *.bak core a.out configure: configure.in autoconf config.status: configure sh configure --no-create Makefile: Makefile.in config.status sh config.status makeargs = $(MFLAGS) CPPFLAGS='$(CPPFLAGS)' CFLAGS='$(CFLAGS)' CC='$(CC)' \ DEFS='$(DEFS)' LDFLAGS='$(LDFLAGS)' LOADLIBES='$(LOADLIBES)' default all install \ mostlyclean clean distclean extraclean realclean \ TAGS check:: for d in $(subdirs); do (cd $$d; $(MAKE) $(makeargs) $@); done .PHONY: install mostlyclean clean distclean extraclean realclean TAGS check # Prevent GNU make 3 from overflowing arg limit on system V. .NOEXPORT: distfiles = AUTHORS ChangeLog COPYING INSTALL NEWS README \ *.in configure regex.c regex.h distdir = regex-$(version) distargs = version=$(version) distdir=../$(distdir)/$$d dist: TAGS configure @echo "Version numbers in: Makefile.in, ChangeLog, NEWS," @echo " regex.c, regex.h," @echo " and doc/xregex.texi (if modified)." rm -rf $(distdir) mkdir $(distdir) ln $(distfiles) $(distdir) for d in $(subdirs); do (cd $$d; $(MAKE) $(distargs) dist); done tar czhf $(distdir).tar.Z $(distdir) rm -rf $(distdir) .PHONY: dist ./pvm3/src/AIX4MP/0042755007401100000360000000000010117676455012652 5ustar kohlgopher./pvm3/src/AIX4MP/Makefile0100644007401100000360000000061206604767727014315 0ustar kohlgopher# # $Id: Makefile,v 1.3 1998/10/01 21:10:47 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/src PVM_ARCH = AIX4MP CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) all: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk all-shm install: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install-shm clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean ./pvm3/src/AIX4SP2/0042755007401100000360000000000010117676455012742 5ustar kohlgopher./pvm3/src/AIX4SP2/Makefile0100644007401100000360000000060406474365276014404 0ustar kohlgopher# # $Id: Makefile,v 1.1 1998/02/23 21:31:42 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/src PVM_ARCH = AIX4SP2 CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) all: make -f $(CONFFILE) -f $(SDIR)/Makefile.aimk all-mpp install: make -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install-mpp clean: make -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean ./pvm3/src/AIX4SP2/pvmdmimd.c0100644007401100000360000005777407435300145014727 0ustar kohlgopher static char rcsid[] = "$Id: pvmdmimd.c,v 1.4 2002/02/21 23:19:01 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmdmimd.c * * MPP interface. * * void mpp_init(int argc, char **argv): * Initialization. Create a table to keep track of active nodes. * argc, argv: passed from main. * * int mpp_load( struct waitc_spawn *wxp ) * * Load executable onto nodes; create new entries in task table, * encode node number and process type into task IDs, etc. * * Construction of Task ID: * * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 * +-+-+-----------------------+-+-----+--------------------------+ * |s|g| host index |n| prt | node # (16384) | * +-+-+-----------------------+-+-----+--------------------------+ * * The "n" bit is set for node task but clear for host task. * * flags: exec options; * name: executable to be loaded; * argv: command line argument for executable * count: number of tasks to be created; * tids: array to store new task IDs; * ptid: parent task ID. * * mpp_new(int count, int ptid): * Allocate a set of nodes. (called by mpp_load()) * count: number of nodes; ptid: parent task ID. * * int mpp_output(): * Send all pending packets to nodes via native send. Node number * and process type are extracted from task ID. * * int mpp_mcast(int src, struct pkt pp, int tids[], int ntask): * Global send. * src: source task ID; * pp: packet; * tids: list of destination task IDs; * ntask: how many. * * int mpp_probe(): * Probe for pending packets from nodes (non-blocking). Returns * 1 if packets are dectected, otherwise 0. * * void mpp_input(): * Receive pending packets (from nodes) via native recv. * * struct task *mpp_find(int pid): * Find a task in task table by its Unix pid. * * void mpp_free(struct task *tp): * Remove node/process-type from active list. * tp: task pointer. * $Log: pvmdmimd.c,v $ Revision 1.4 2002/02/21 23:19:01 pvmsrc Added new (not to be documented!) PVM_MAX_TASKS env var support. - for Mahir Lokvancic . - forcefully limits the number of tasks that can attach to a pvmd, required on Solaris in rare circumstances when hard FD_SETSIZE limit is reached, and all hell breaks loose... - check return for task_new() call, can now produce NULL ptr, indicating PvmOutOfRes... (Spanker=kohl) Revision 1.3 2001/09/25 21:19:00 pvmsrc Minor TMPNAMFUN()/tmpnam() cleanup. - moved macro def to pvm3.h, renamed PVMTNPMAN(). - same for LEN_OF_TMP_NAM -> PVMTMPNAMLEN. - mostly a huge waste of time, since *both* tmpnam() & mktemp() produce the same "dangerous" warning message in Linux/gcc... - damn. (Spanker=kohl) Revision 1.2 2000/02/17 21:10:16 pvmsrc Cleaned up comments... mpp_load() args... (Spanker=kohl) * Revision 1.1 1998/02/23 21:31:44 pvmsrc * Copied from SP2MPI. * * Revision 1.10 1997/10/01 15:36:06 pvmsrc * Removed unnecessary #include "fromlib.h" header. * - all consts now included in pvm3.h... * - header file eliminated. * (Spanker=kohl) * * Revision 1.9 1997/08/27 20:18:58 pvmsrc * Added blank args (0,0,0) in mpp_load() to make it call forkexec correctly. * Protocol needs to be changed to allow taskers to access IBM poe directly. * (Spanker=fagg) * * Revision 1.8 1997/07/09 13:54:58 pvmsrc * Fixed Author Header. * * Revision 1.7 1997/06/02 13:48:38 pvmsrc * Moved #include host.h above #include waitc.h. * Removed old mesg.h include... gone baby. * * Revision 1.6 1997/05/06 20:14:36 pvmsrc * Catch stdout/stderr correctly and redirect to outtid,tag,ctx * * Revision 1.5 1997/05/05 20:08:56 pvmsrc * Pass outctx and trcctx to mpp tasks. * * Revision 1.4 1997/05/02 13:52:50 pvmsrc * Start up MPI jobs correctly and get them configured. * * Revision 1.3 1997/03/25 15:52:21 pvmsrc * PVM patches from the base 3.3.10 to 3.3.11 versions where applicable. * Originals by Bob Manchek. Altered by Graham Fagg where required. * -IP enabled over switch * -RMPOOL env can be used instead of host list * * Revision 1.2 1997/01/28 19:30:57 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:15:09 pvmsrc * Initial revision * * Revision 1.3 1996/05/14 14:35:59 manchek * inc'd changes from chulho@kgn.ibm.com * * Revision 1.2 1995/07/25 17:41:27 manchek * mpp_output returns int * * Revision 1.1 1995/05/30 17:23:56 manchek * Initial revision * * Revision 1.3 1994/06/03 20:54:24 manchek * version 3.3.0 * * Revision 1.2 1993/12/20 15:39:47 manchek * patch 6 from wcj * * Revision 1.1 1993/08/30 23:35:09 manchek * Initial revision * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef SYSVSTR #include #define CINDEX(s,c) strchr(s,c) #else #include #define CINDEX(s,c) index(s,c) #endif #include #include #include "global.h" #include "host.h" #include "waitc.h" #include "pvmalloc.h" #include "pkt.h" #include "task.h" #include "listmac.h" #include "pvmdmp.h" #include "pvmmimd.h" #include "bfunc.h" #define MPICOMM "/usr/bin/poe" #define MPIOPT1 "-procs" #define MPIOPT2 "-euilib" #define MPIOPT3 "-hfile" #define MPIOPT4 "-rmpool" #define MPIOPARG2 "us" /* options: -procs # -euilib us */ #define MPIOPARG3 "ip" /* Enable IP over switch */ #define MPIARGC 7 /* number of command line arguments */ char *getenv(); /* Global */ extern int pvmdebmask; /* from pvmd.c */ extern char **epaths; /* from pvmd.c */ extern int myhostpart; /* from pvmd.c */ extern int tidhmask; /* from pvmd.c */ extern int ourudpmtu; /* from pvmd.c */ extern struct htab *hosts; /* from pvmd.c */ extern struct task *locltasks; /* from task.c */ int tidtmask = TIDPTYPE; /* mask for ptype field of tids */ int tidnmask = TIDNODE; /* mask for node field of tids */ /* private */ static int myndf = 0; static struct nodeset *busynodes; /* active nodes; ordered by proc type */ static char pvmtxt[512]; /* scratch for error log */ static int ptypemask; /* mask; we use these bits of ptype in tids */ static char nodefile[PVMTMPNAMLEN]; /* tmp node file */ static char **nodelist = 0; /* default poe node list */ static int partsize = 0; /* number of nodes allocated */ static int hostfileused = TRUE; /* Check if MP_HOSTFILE used */ static char defaultpool[64]="1"; /* default MP_POOL if not set */ static char mpiadapter[]={MPIOPARG2}; /* default User-Space */ static int sp2pvminfo[SIZEHINFO]; void mpp_init(argc, argv) int *argc; char **argv; { struct stat sb; char *hfn; /* host file name */ char nname[128]; /* node name */ FILE *hfp; int i; if ((hfn = getenv("LOADLBATCH"))) { if (strcmp(hfn, "yes") == 0) { if ((hfn = getenv("LOADL_PROCESSOR_LIST"))) { sprintf(pvmtxt, "LOADL_PROCESSOR_LIST=%s.\n",hfn); pvmlogperror(pvmtxt); hostfileused=FALSE; for (hfn;*hfn!='\0';hfn++) { if (*hfn == ' ') partsize++; } } else { sprintf(pvmtxt, "LOADL_PROCESSOR_LIST=%s - is not set\n",hfn); pvmlogperror(pvmtxt); exit(PvmHostFail); } } else { sprintf(pvmtxt,"LOADLBATCH=%s - not set to yes\n",hfn); pvmlogperror(pvmtxt); exit(PvmHostFail); } } else if ((hfn = getenv("MP_PROCS"))) { if ((partsize = atoi(hfn)) < 1) { sprintf(pvmtxt,"MP_PROCS=%d must be >= to 1\n",partsize); pvmlogperror(pvmtxt); exit(PvmHostFail); } hostfileused=FALSE; if ((hfn = getenv("MP_RMPOOL"))) { if (atoi(hfn) < 0) { sprintf(pvmtxt, "MP_RMPOOL=%d must be >= to 0\n",defaultpool); pvmlogperror(pvmtxt); exit(PvmHostFail); } strcpy(defaultpool,hfn); } } else if ((hfn = getenv("MP_HOSTFILE"))) { if (!(hfp = fopen(hfn, "r"))) { sprintf(pvmtxt, "sp2hostfile() fopen %s\n", hfn); pvmlogperror(pvmtxt); exit(PvmHostFail); } hostfileused=TRUE; while (fscanf(hfp, "%s", nname) != EOF) partsize++; nodelist = TALLOC(partsize, char*, "nname"); rewind(hfp); for (i = 0; i < partsize; i++) { fscanf(hfp, "%s", nname); nodelist[i] = STRALLOC(nname); } fclose(hfp); } else { pvmlogerror("mpp_init() no POE host file.\n"); pvmlogerror("mpp_init() MP_PROCS, MP_RMPOOL or MP_HOSTFILE must be set.\n"); exit(PvmHostFail); } if ((hfn = getenv("MP_EUILIB"))) { if (strcmp(hfn, "ip") == 0) { strcpy(mpiadapter,MPIOPARG3); /* IP over switch */ } } sprintf(pvmtxt, "%d nodes allocated.\n", partsize); pvmlogerror(pvmtxt); busynodes = TALLOC(1, struct nodeset, "nsets"); BZERO((char*)busynodes, sizeof(struct nodeset)); busynodes->n_link = busynodes; busynodes->n_rlink = busynodes; ptypemask = tidtmask >> (ffs(tidtmask) - 1); } /* create tmp poe host file from default */ char * sp2hostfile(first, count) int first; /* first node in the set */ int count; /* number of nodes requested */ { int i; FILE *tmpfp; if (partsize < count) { sprintf(pvmtxt, "sp2hostfile() need at least %d nodes\n", count+1); pvmlogperror(pvmtxt); return (char *)0; } (void)PVMTMPNAMFUN(nodefile); if (!(tmpfp = fopen(nodefile, "w"))) { sprintf(pvmtxt, "sp2hostfile() fopen %s", nodefile); pvmlogperror(pvmtxt); return (char *)0; } if (pvmdebmask & PDMNODE) { sprintf(pvmtxt, "sp2hostfile() POE host file: %s\n", nodefile); pvmlogerror(pvmtxt); } for (i = first; i < count + first; i++) fprintf(tmpfp, "%s\n", nodelist[i]); fclose(tmpfp); return nodefile; } /* * find a set of free nodes from nodelist; assign ptype sequentially, * only tasks spawned together get the same ptype */ struct nodeset * mpp_new(count, ptid) int count; /* number of nodes requested */ int ptid; /* parent's tid */ { struct nodeset *sp, *newp, *sp2; int last = -1; int ptype = 0; if (!(newp = TALLOC(1, struct nodeset, "nsets"))) { pvmlogerror("mpp_new() can't get memory\n"); pvmbailout(0); } BZERO((char*)newp, sizeof(struct nodeset)); newp->n_size = count; for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link) { if (sp->n_first - last > count) break; last = sp->n_first + sp->n_size - 1; /* if (sp->n_link == busynodes && partsize - last > count) break; */ if (ptype <= sp->n_ptype) ptype = sp->n_ptype + 1; } if (sp == busynodes && partsize - last <= count) { pvmlogerror("mpp_new() not enough nodes in partition\n"); PVM_FREE(newp); return (struct nodeset *)0; } for (sp2 = busynodes->n_link; sp2 != busynodes; sp2 = sp2->n_link) if ((sp2->n_ptype & ptypemask) == (ptype & ptypemask)) break; if (sp2 != busynodes || ptype == NPARTITIONS) { for (ptype = 0; ptype < NPARTITIONS; ptype++) { for (sp2 = busynodes->n_link; sp2 != busynodes; sp2 = sp2->n_link) if ((sp2->n_ptype & ptypemask) == (ptype & ptypemask)) break; if (sp2 == busynodes) break; } if (ptype == NPARTITIONS) { pvmlogerror("mpp_new() out of ptypes: too many spawns\n"); return (struct nodeset *)0; } } done: if (pvmdebmask & PDMNODE) { sprintf(pvmtxt, "mpp_new() %d nodes %d ... ptype=%d ptid=%x\n", count, last+1, ptype, ptid); pvmlogerror(pvmtxt); } newp->n_first = last + 1; if (hostfileused) { if (!sp2hostfile(newp->n_first, count)) { PVM_FREE(newp); return (struct nodeset *)0; } } newp->n_ptype = ptype; newp->n_ptid = ptid; newp->n_alive = count - 1; LISTPUTBEFORE(sp, newp, n_link, n_rlink); return newp; } /* * remove node/ptype from active list; if tid is the last to go, shutdown * pvmhost's socket, but do not destroy the node set because pvmhost may * not exit immediately. To avoid a race condition, let mpp_output() * do the cleanup. */ void mpp_free(tp) struct task *tp; { struct nodeset *sp; int ptype; struct task *tp2; int tid = tp->t_tid; if (!TIDISNODE(tid)) return; ptype = TIDTOTYPE(tid); tp->t_txq = 0; /* don't free pvmhost's txq */ for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link) { if ((sp->n_ptype & ptypemask) == ptype) { if (pvmdebmask & PDMNODE) { sprintf(pvmtxt, "mpp_free() t%x type=%ld alive=%d\n", tid, sp->n_ptype, sp->n_alive); pvmlogerror(pvmtxt); } if (--sp->n_alive == 0) { if (tp2 = task_find(sp->n_ptid)) { tp2->t_flag |= TF_CLOSE; if (tp2->t_sock != -1) { /* wrk_fds_delete(tp2->t_sock, 3); (void)close(tp2->t_sock); tp2->t_sock = -1; */ shutdown(tp2->t_sock, 1); /* close stdout after pvmhost dies */ tp2->t_out = tp->t_out; } } /* LISTDELETE(sp, n_link, n_rlink); PVM_FREE(sp); */ } tp->t_out = -1; /* don't free shared stdout if alive > 0 */ return; } } sprintf(pvmtxt, "mpp_free() t%x not active\n", tid); pvmlogerror(pvmtxt); return; } /* load executable onto the given set of nodes */ int mpp_load( wxp ) struct waitc_spawn *wxp; { int flags = 0; /* exec options */ char *name; /* executable */ char **argv; /* arg list (argv[-1] must be there) */ int count; /* how many */ int *tids; /* array to store new tids */ int ptid; /* parent task ID */ int nenv; /* length of environment */ char **envp; /* environment strings */ int ptypepart; /* type field */ int j; struct task *tp; struct pkt *hosttxq; /* out-going queue of pvmhost */ int err = 0; struct nodeset *sp; char c[128]; /* buffer to store count, name.host */ char **ar = 0; int nargs; char **ep, **eplist; char path[MAXPATHLEN]; struct stat sb; char **av; int hostout; /* stdout of pvmhost */ struct hostd *hp = hosts->ht_hosts[hosts->ht_local]; int hostpid; /* Unix pid of pvmhost */ char htid[128]; /* buffer to store pvmhost tid */ char *p; static char *nullep[] = { "", 0 }; /* -- initialize some variables from the waitc_spawn struct -- */ name = wxp->w_argv[0]; argv = wxp->w_argv; count = wxp->w_veclen; tids = wxp->w_vec; ptid = wxp->w_ptid; nenv = wxp->w_nenv; envp = wxp->w_env; eplist = CINDEX(name, '/') ? nullep : epaths; for (ep = eplist; *ep; ep++) { /* search for file */ (void)strcpy(path, *ep); if (path[0]) (void)strcat(path, "/"); (void)strncat(path, name, sizeof(path) - strlen(path) - 1); if (stat(path, &sb) == -1 || ((sb.st_mode & S_IFMT) != S_IFREG) || !(sb.st_mode & S_IEXEC)) { if (pvmdebmask & PDMTASK) { sprintf(pvmtxt, "mpp_load() stat failed <%s>\n", path); pvmlogerror(pvmtxt); } continue; } if (!(sp = mpp_new(count+1, ptid))) { err = PvmOutOfRes; goto done; } ptypepart = (sp->n_ptype << (ffs(tidtmask) - 1)) | TIDONNODE; if (argv) for (nargs = 0; argv[nargs]; nargs++); else nargs = 0; /* ar[-1], poe, -procs, #, -euilib, us, -hfile fname */ nargs += MPIARGC + 1; av = TALLOC(nargs + 1, char*, "argv"); av++; /* reserve room for debugger */ BZERO((char*)av, nargs * sizeof(char*)); av[0] = MPICOMM; av[1] = path; av[--nargs] = 0; if (hostfileused) { av[--nargs] = nodefile; av[--nargs] = MPIOPT3; } else { av[--nargs] = defaultpool; av[--nargs] = MPIOPT4; } av[--nargs] = mpiadapter; av[--nargs] = MPIOPT2; sprintf(c, "%d", count+1); av[--nargs] = c; av[--nargs] = MPIOPT1; for (j = 2; j < nargs; j++) av[j] = argv[j - 1]; /* poe name argv -procs # -euilib us */ /* if ((sock = mksock()) == -1) { err = PvmSysErr; goto done; } */ if (flags & PvmTaskDebug) av++; /* pdbx name -procs # -euilib us */ /* if (err = forkexec(flags, av[0], av, 0, (char **)0, &tp)) */ if (err = forkexec(flags, av[0], av, 0, (char **)0, 0, 0, 0, &tp)) goto done; tp->t_ptid = ptid; PVM_FREE(tp->t_a_out); sprintf(c, "%s.host", name); tp->t_a_out = STRALLOC(c); sp->n_ptid = tp->t_tid; /* pvmhost's tid */ hosttxq = tp->t_txq; hostout = tp->t_out; hostpid = tp->t_pid; tp->t_out = -1; sprintf(htid, "PVMHTID=%d", tp->t_tid); p = STRALLOC(htid); pvmputenv(p); sp2pvminfo[0] = TDPROTOCOL; sp2pvminfo[1] = myhostpart + ptypepart; sp2pvminfo[2] = ptid; sp2pvminfo[3] = MAXFRAGSIZE; sp2pvminfo[4] = myndf; sp2pvminfo[5] = partsize; sp2pvminfo[6] = wxp->w_outtid; sp2pvminfo[7] = wxp->w_outtag; sp2pvminfo[8] = wxp->w_outctx; sp2pvminfo[9] = wxp->w_trctid; sp2pvminfo[10] = wxp->w_trctag; sp2pvminfo[11] = wxp->w_trcctx; /* if (sockconn(sock, tp, pvminfo) == -1) { err = PvmSysErr; task_free(tp); goto done; } */ /* XXX task may not be on same host; can't do auth with tmp file */ tp->t_flag |= TF_CONN; if (pvmdebmask & PDMTASK) { sprintf(pvmtxt, "mpp_load() %d type=%d ptid=%x t%x...\n", count, sp->n_ptype, ptid, myhostpart + ptypepart); pvmlogerror(pvmtxt); } /* create new task structs */ for (j = 0; j < count; j++) { if ((tp = task_new(myhostpart + ptypepart + j)) == NULL) { err = PvmOutOfRes; goto done; } tp->t_a_out = STRALLOC(name); tp->t_ptid = ptid; tp->t_flag |= TF_CONN; /* no need for the auth crap */ tids[j] = tp->t_tid; PVM_FREE(tp->t_txq); tp->t_txq = hosttxq; /* node tasks share pvmhost's txq */ tp->t_out = hostout; /* and stdout */ tp->t_pid = hostpid; /* pvm_kill should kill pvmhost */ tp->t_outtid = wxp->w_outtid; /* catch stdout/stderr */ tp->t_outtag = wxp->w_outtag; tp->t_outctx = wxp->w_outctx; } return 0; } if (pvmdebmask & PDMTASK) { sprintf(pvmtxt, "mpp_load() didn't find <%s>\n", name); pvmlogerror(pvmtxt); } err = PvmNoFile; done: for (j = 0; j < count; j++) tids[j] = err; return err; } #if 0 /* kill poe process */ void sp2kill(a_out, node) char *a_out; int node; { FILE *fp; int i; char nname[128]; /* node name */ char comm[512]; /* command to issue */ char *hfn; /* host file name */ struct stat sb; char *av[8]; /* for rsh args */ int ac; int pid = -1; /* pid of rsh */ node++; if ((hfn = getenv("MP_HOSTFILE")) || stat(hfn = "host.list", &sb) != -1) { if (fp = fopen(hfn, "r")) { for (i = 0; i < node; i++) fscanf(fp, "%s", nname); fclose(hfn); if ((pid = fork()) == -1) { pvmlogperror("sp2kill() fork"); return; } if (!pid) { ac = 0; av[ac++] = "/usr/bin/rsh"; av[ac++] = nname; av[ac++] = "poekill"; av[ac++] = a_out; av[ac++] = 0; for (i = getdtablesize(); --i > 2; ) (void)close(i); execvp(av[0], av); _exit(1); } } else pvmlogperror("sp2kill() fopen"); return; } pvmlogerror("sp2kill() no host file"); } #endif /*0*/ void mpp_kill(tp, signum) struct task *tp; int signum; { if (TIDISNODE(tp->t_tid)) { if (signum == SIGTERM || signum == SIGKILL) { /* sp2kill(tp->t_a_out, tp->t_tid & tidnmask); */ (void)kill(tp->t_pid, signum); mpp_free(tp); task_cleanup(tp); task_free(tp); } else { sprintf(pvmtxt,"mpp_kill() signal %d to node t%x ignored\n", signum, tp->t_tid); pvmlogerror(pvmtxt); } } else (void)kill(tp->t_pid, signum); } /* * Add pvmhost's socket to wfds if there are packets waiting to * be sent to a related node task. Node tasks have no sockets; * they share pvmhost's packet queue (txq). Pvmhost simply * forwards any packets it receives to the appropriate node. */ int mpp_output(dummy1, dummy2) struct task *dummy1; struct pkt *dummy2; { struct nodeset *sp, *sp2; struct task *tp; int ptype; for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link) if ((tp = task_find(sp->n_ptid))) { if (tp->t_txq->pk_link->pk_buf && tp->t_sock != -1) wrk_fds_add(tp->t_sock, 2); } else { if (sp->n_alive) { sprintf(pvmtxt, "mpp_output() pvmhost %d died!\n", sp->n_ptype); pvmlogerror(pvmtxt); /* clean up tasks it serves */ ptype = sp->n_ptype & ptypemask; for (tp = locltasks->t_link; tp != locltasks; tp = tp->t_link) if (TIDISNODE(tp->t_tid) && TIDTOTYPE(tp->t_tid) == ptype) { tp->t_txq = 0; tp = tp->t_rlink; task_cleanup(tp->t_link); task_free(tp->t_link); } } /* pvmhost has died, destroy the node set */ sp2 = sp; sp = sp->n_rlink; LISTDELETE(sp2, n_link, n_rlink); PVM_FREE(sp2); } return 0; } /* replace tm_connect and tm_conn2 */ int mpp_conn(tp, tp2) struct task *tp; struct task *tp2; { struct nodeset *sp; int pvminfo[SIZEHINFO]; /* host info */ int ptypepart; /* type field */ if (pvmdebmask & PDMNODE) { sprintf(pvmtxt, "mpp_conn() pvmhost %x", tp2->t_tid); pvmlogerror(pvmtxt); } tp2->t_sock = tp->t_sock; tp2->t_sad = tp->t_sad; tp2->t_salen = tp->t_salen; tp2->t_flag |= TF_CONN; tp->t_sock = -1; for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link) if (sp->n_ptid == tp2->t_tid) break; if (sp == busynodes) { pvmlogerror("mpp_conn() task is not pvmhost\n"); return -1; } ptypepart = (sp->n_ptype << (ffs(tidtmask) - 1)) | TIDONNODE; if (write(tp2->t_sock, sp2pvminfo, sizeof(sp2pvminfo)) != sizeof(sp2pvminfo)) { pvmlogperror("mpp_conn() write"); return -1; } return 0; } #if 0 /* * Create socket to talk to pvmhost. * Return socket descriptor if successful, -1 otherwise. */ int mksock() { struct hostd *hp = hosts->ht_hosts[hosts->ht_local]; struct sockaddr_in sin; char buf[128]; char *p; int cc; int sock; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { pvmlogperror("mksock() socket"); return -1; } sin = hp->hd_sad; if (bind(sock, (struct sockaddr*)&sin, sizeof(sin)) == -1) { pvmlogperror("mksock() bind"); (void)close(sock); return -1; } cc = sizeof(sin); if (getsockname(sock, (struct sockaddr*)&sin, &cc) == -1) { pvmlogperror("mksock() getsockname"); (void)close(sock); return -1; } if (listen(sock, 1) == -1) { pvmlogperror("mksock() listen"); (void)close(sock); return -1; } p = inadport_hex(&sin); sprintf(buf, "PVMSOCK=%s", p); p = STRALLOC(buf); pvmputenv(p); return sock; } /* * Wait for connect request from pvmhost and establish connection. * Return 0 if successful, -1 otherwise. * Close listening socket. */ int sockconn(sock, tp, hinfo) int sock; /* listening post */ struct task *tp; /* pvm host */ int hinfo[]; /* host info to pass along */ { int i; if ((tp->t_sock = accept(sock, (struct sockaddr*)&tp->t_sad, &tp->t_salen)) == -1) { pvmlogperror("sockconn() accept"); return -1; } else { if (pvmdebmask & (PDMPACKET|PDMTASK)) { sprintf(pvmtxt, "sockconn() accept from %s sock %d\n", inadport_decimal(&tp->t_sad), tp->t_sock); pvmlogerror(pvmtxt); } close(sock); #ifndef NOSOCKOPT i = 1; if (setsockopt(tp->t_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&i, sizeof(int)) == -1) pvmlogperror("sockconn() setsockopt"); #endif } if (write(tp->t_sock, hinfo, SIZEHINFO*sizeof(int)) != SIZEHINFO*sizeof(int)) { pvmlogperror("sockconn: write"); return -1; } if ((i = fcntl(tp->t_sock, F_GETFL, 0)) == -1) pvmlogperror("sockconn: fcntl"); else { i |= O_NDELAY; (void)fcntl(tp->t_sock, F_SETFL, i); } wrk_fds_add(tp->t_sock, 1); return 0; } #endif /*0*/ ./pvm3/src/AIX5MP/0042755007401100000360000000000010117676455012653 5ustar kohlgopher./pvm3/src/AIX5MP/Makefile0100644007401100000360000000061210001276431014263 0ustar kohlgopher# # $Id: Makefile,v 1.1 2004/01/14 17:32:09 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/src PVM_ARCH = AIX5MP CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) all: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk all-shm install: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install-shm clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean ./pvm3/src/AIX5SP2/0042755007401100000360000000000010117676455012743 5ustar kohlgopher./pvm3/src/AIX5SP2/Makefile0100644007401100000360000000060410001276643014361 0ustar kohlgopher# # $Id: Makefile,v 1.1 2004/01/14 17:34:27 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/src PVM_ARCH = AIX5SP2 CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) all: make -f $(CONFFILE) -f $(SDIR)/Makefile.aimk all-mpp install: make -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install-mpp clean: make -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean ./pvm3/src/AIX5SP2/pvmdmimd.c0100644007401100000360000006011010001276643014700 0ustar kohlgopher static char rcsid[] = "$Id: pvmdmimd.c,v 1.1 2004/01/14 17:34:27 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmdmimd.c * * MPP interface. * * void mpp_init(int argc, char **argv): * Initialization. Create a table to keep track of active nodes. * argc, argv: passed from main. * * int mpp_load( struct waitc_spawn *wxp ) * * Load executable onto nodes; create new entries in task table, * encode node number and process type into task IDs, etc. * * Construction of Task ID: * * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 * +-+-+-----------------------+-+-----+--------------------------+ * |s|g| host index |n| prt | node # (16384) | * +-+-+-----------------------+-+-----+--------------------------+ * * The "n" bit is set for node task but clear for host task. * * flags: exec options; * name: executable to be loaded; * argv: command line argument for executable * count: number of tasks to be created; * tids: array to store new task IDs; * ptid: parent task ID. * * mpp_new(int count, int ptid): * Allocate a set of nodes. (called by mpp_load()) * count: number of nodes; ptid: parent task ID. * * int mpp_output(): * Send all pending packets to nodes via native send. Node number * and process type are extracted from task ID. * * int mpp_mcast(int src, struct pkt pp, int tids[], int ntask): * Global send. * src: source task ID; * pp: packet; * tids: list of destination task IDs; * ntask: how many. * * int mpp_probe(): * Probe for pending packets from nodes (non-blocking). Returns * 1 if packets are dectected, otherwise 0. * * void mpp_input(): * Receive pending packets (from nodes) via native recv. * * struct task *mpp_find(int pid): * Find a task in task table by its Unix pid. * * void mpp_free(struct task *tp): * Remove node/process-type from active list. * tp: task pointer. * $Log: pvmdmimd.c,v $ Revision 1.1 2004/01/14 17:34:27 pvmsrc New AIX5SP2 arch. (Spanker=kohl) Revision 1.4 2002/02/21 23:19:01 pvmsrc Added new (not to be documented!) PVM_MAX_TASKS env var support. - for Mahir Lokvancic . - forcefully limits the number of tasks that can attach to a pvmd, required on Solaris in rare circumstances when hard FD_SETSIZE limit is reached, and all hell breaks loose... - check return for task_new() call, can now produce NULL ptr, indicating PvmOutOfRes... (Spanker=kohl) Revision 1.3 2001/09/25 21:19:00 pvmsrc Minor TMPNAMFUN()/tmpnam() cleanup. - moved macro def to pvm3.h, renamed PVMTNPMAN(). - same for LEN_OF_TMP_NAM -> PVMTMPNAMLEN. - mostly a huge waste of time, since *both* tmpnam() & mktemp() produce the same "dangerous" warning message in Linux/gcc... - damn. (Spanker=kohl) Revision 1.2 2000/02/17 21:10:16 pvmsrc Cleaned up comments... mpp_load() args... (Spanker=kohl) * Revision 1.1 1998/02/23 21:31:44 pvmsrc * Copied from SP2MPI. * * Revision 1.10 1997/10/01 15:36:06 pvmsrc * Removed unnecessary #include "fromlib.h" header. * - all consts now included in pvm3.h... * - header file eliminated. * (Spanker=kohl) * * Revision 1.9 1997/08/27 20:18:58 pvmsrc * Added blank args (0,0,0) in mpp_load() to make it call forkexec correctly. * Protocol needs to be changed to allow taskers to access IBM poe directly. * (Spanker=fagg) * * Revision 1.8 1997/07/09 13:54:58 pvmsrc * Fixed Author Header. * * Revision 1.7 1997/06/02 13:48:38 pvmsrc * Moved #include host.h above #include waitc.h. * Removed old mesg.h include... gone baby. * * Revision 1.6 1997/05/06 20:14:36 pvmsrc * Catch stdout/stderr correctly and redirect to outtid,tag,ctx * * Revision 1.5 1997/05/05 20:08:56 pvmsrc * Pass outctx and trcctx to mpp tasks. * * Revision 1.4 1997/05/02 13:52:50 pvmsrc * Start up MPI jobs correctly and get them configured. * * Revision 1.3 1997/03/25 15:52:21 pvmsrc * PVM patches from the base 3.3.10 to 3.3.11 versions where applicable. * Originals by Bob Manchek. Altered by Graham Fagg where required. * -IP enabled over switch * -RMPOOL env can be used instead of host list * * Revision 1.2 1997/01/28 19:30:57 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:15:09 pvmsrc * Initial revision * * Revision 1.3 1996/05/14 14:35:59 manchek * inc'd changes from chulho@kgn.ibm.com * * Revision 1.2 1995/07/25 17:41:27 manchek * mpp_output returns int * * Revision 1.1 1995/05/30 17:23:56 manchek * Initial revision * * Revision 1.3 1994/06/03 20:54:24 manchek * version 3.3.0 * * Revision 1.2 1993/12/20 15:39:47 manchek * patch 6 from wcj * * Revision 1.1 1993/08/30 23:35:09 manchek * Initial revision * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef SYSVSTR #include #define CINDEX(s,c) strchr(s,c) #else #include #define CINDEX(s,c) index(s,c) #endif #include #include #include "global.h" #include "host.h" #include "waitc.h" #include "pvmalloc.h" #include "pkt.h" #include "task.h" #include "listmac.h" #include "pvmdmp.h" #include "pvmmimd.h" #include "bfunc.h" #define MPICOMM "/usr/bin/poe" #define MPIOPT1 "-procs" #define MPIOPT2 "-euilib" #define MPIOPT3 "-hfile" #define MPIOPT4 "-rmpool" #define MPIOPARG2 "us" /* options: -procs # -euilib us */ #define MPIOPARG3 "ip" /* Enable IP over switch */ #define MPIARGC 7 /* number of command line arguments */ char *getenv(); /* Global */ extern int pvmdebmask; /* from pvmd.c */ extern char **epaths; /* from pvmd.c */ extern int myhostpart; /* from pvmd.c */ extern int tidhmask; /* from pvmd.c */ extern int ourudpmtu; /* from pvmd.c */ extern struct htab *hosts; /* from pvmd.c */ extern struct task *locltasks; /* from task.c */ int tidtmask = TIDPTYPE; /* mask for ptype field of tids */ int tidnmask = TIDNODE; /* mask for node field of tids */ /* private */ static int myndf = 0; static struct nodeset *busynodes; /* active nodes; ordered by proc type */ static char pvmtxt[512]; /* scratch for error log */ static int ptypemask; /* mask; we use these bits of ptype in tids */ static char nodefile[PVMTMPNAMLEN]; /* tmp node file */ static char **nodelist = 0; /* default poe node list */ static int partsize = 0; /* number of nodes allocated */ static int hostfileused = TRUE; /* Check if MP_HOSTFILE used */ static char defaultpool[64]="1"; /* default MP_POOL if not set */ static char mpiadapter[]={MPIOPARG2}; /* default User-Space */ static int sp2pvminfo[SIZEHINFO]; void mpp_init(argc, argv) int *argc; char **argv; { struct stat sb; char *hfn; /* host file name */ char nname[128]; /* node name */ FILE *hfp; int i; if ((hfn = getenv("LOADLBATCH"))) { if (strcmp(hfn, "yes") == 0) { if ((hfn = getenv("LOADL_PROCESSOR_LIST"))) { sprintf(pvmtxt, "LOADL_PROCESSOR_LIST=%s.\n",hfn); pvmlogperror(pvmtxt); hostfileused=FALSE; for (hfn;*hfn!='\0';hfn++) { if (*hfn == ' ') partsize++; } } else { sprintf(pvmtxt, "LOADL_PROCESSOR_LIST=%s - is not set\n",hfn); pvmlogperror(pvmtxt); exit(PvmHostFail); } } else { sprintf(pvmtxt,"LOADLBATCH=%s - not set to yes\n",hfn); pvmlogperror(pvmtxt); exit(PvmHostFail); } } else if ((hfn = getenv("MP_PROCS"))) { if ((partsize = atoi(hfn)) < 1) { sprintf(pvmtxt,"MP_PROCS=%d must be >= to 1\n",partsize); pvmlogperror(pvmtxt); exit(PvmHostFail); } hostfileused=FALSE; if ((hfn = getenv("MP_RMPOOL"))) { if (atoi(hfn) < 0) { sprintf(pvmtxt, "MP_RMPOOL=%d must be >= to 0\n",defaultpool); pvmlogperror(pvmtxt); exit(PvmHostFail); } strcpy(defaultpool,hfn); } } else if ((hfn = getenv("MP_HOSTFILE"))) { if (!(hfp = fopen(hfn, "r"))) { sprintf(pvmtxt, "sp2hostfile() fopen %s\n", hfn); pvmlogperror(pvmtxt); exit(PvmHostFail); } hostfileused=TRUE; while (fscanf(hfp, "%s", nname) != EOF) partsize++; nodelist = TALLOC(partsize, char*, "nname"); rewind(hfp); for (i = 0; i < partsize; i++) { fscanf(hfp, "%s", nname); nodelist[i] = STRALLOC(nname); } fclose(hfp); } else { pvmlogerror("mpp_init() no POE host file.\n"); pvmlogerror("mpp_init() MP_PROCS, MP_RMPOOL or MP_HOSTFILE must be set.\n"); exit(PvmHostFail); } if ((hfn = getenv("MP_EUILIB"))) { if (strcmp(hfn, "ip") == 0) { strcpy(mpiadapter,MPIOPARG3); /* IP over switch */ } } sprintf(pvmtxt, "%d nodes allocated.\n", partsize); pvmlogerror(pvmtxt); busynodes = TALLOC(1, struct nodeset, "nsets"); BZERO((char*)busynodes, sizeof(struct nodeset)); busynodes->n_link = busynodes; busynodes->n_rlink = busynodes; ptypemask = tidtmask >> (ffs(tidtmask) - 1); } /* create tmp poe host file from default */ char * sp2hostfile(first, count) int first; /* first node in the set */ int count; /* number of nodes requested */ { int i; FILE *tmpfp; if (partsize < count) { sprintf(pvmtxt, "sp2hostfile() need at least %d nodes\n", count+1); pvmlogperror(pvmtxt); return (char *)0; } (void)PVMTMPNAMFUN(nodefile); if (!(tmpfp = fopen(nodefile, "w"))) { sprintf(pvmtxt, "sp2hostfile() fopen %s", nodefile); pvmlogperror(pvmtxt); return (char *)0; } if (pvmdebmask & PDMNODE) { sprintf(pvmtxt, "sp2hostfile() POE host file: %s\n", nodefile); pvmlogerror(pvmtxt); } for (i = first; i < count + first; i++) fprintf(tmpfp, "%s\n", nodelist[i]); fclose(tmpfp); return nodefile; } /* * find a set of free nodes from nodelist; assign ptype sequentially, * only tasks spawned together get the same ptype */ struct nodeset * mpp_new(count, ptid) int count; /* number of nodes requested */ int ptid; /* parent's tid */ { struct nodeset *sp, *newp, *sp2; int last = -1; int ptype = 0; if (!(newp = TALLOC(1, struct nodeset, "nsets"))) { pvmlogerror("mpp_new() can't get memory\n"); pvmbailout(0); } BZERO((char*)newp, sizeof(struct nodeset)); newp->n_size = count; for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link) { if (sp->n_first - last > count) break; last = sp->n_first + sp->n_size - 1; /* if (sp->n_link == busynodes && partsize - last > count) break; */ if (ptype <= sp->n_ptype) ptype = sp->n_ptype + 1; } if (sp == busynodes && partsize - last <= count) { pvmlogerror("mpp_new() not enough nodes in partition\n"); PVM_FREE(newp); return (struct nodeset *)0; } for (sp2 = busynodes->n_link; sp2 != busynodes; sp2 = sp2->n_link) if ((sp2->n_ptype & ptypemask) == (ptype & ptypemask)) break; if (sp2 != busynodes || ptype == NPARTITIONS) { for (ptype = 0; ptype < NPARTITIONS; ptype++) { for (sp2 = busynodes->n_link; sp2 != busynodes; sp2 = sp2->n_link) if ((sp2->n_ptype & ptypemask) == (ptype & ptypemask)) break; if (sp2 == busynodes) break; } if (ptype == NPARTITIONS) { pvmlogerror("mpp_new() out of ptypes: too many spawns\n"); return (struct nodeset *)0; } } done: if (pvmdebmask & PDMNODE) { sprintf(pvmtxt, "mpp_new() %d nodes %d ... ptype=%d ptid=%x\n", count, last+1, ptype, ptid); pvmlogerror(pvmtxt); } newp->n_first = last + 1; if (hostfileused) { if (!sp2hostfile(newp->n_first, count)) { PVM_FREE(newp); return (struct nodeset *)0; } } newp->n_ptype = ptype; newp->n_ptid = ptid; newp->n_alive = count - 1; LISTPUTBEFORE(sp, newp, n_link, n_rlink); return newp; } /* * remove node/ptype from active list; if tid is the last to go, shutdown * pvmhost's socket, but do not destroy the node set because pvmhost may * not exit immediately. To avoid a race condition, let mpp_output() * do the cleanup. */ void mpp_free(tp) struct task *tp; { struct nodeset *sp; int ptype; struct task *tp2; int tid = tp->t_tid; if (!TIDISNODE(tid)) return; ptype = TIDTOTYPE(tid); tp->t_txq = 0; /* don't free pvmhost's txq */ for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link) { if ((sp->n_ptype & ptypemask) == ptype) { if (pvmdebmask & PDMNODE) { sprintf(pvmtxt, "mpp_free() t%x type=%ld alive=%d\n", tid, sp->n_ptype, sp->n_alive); pvmlogerror(pvmtxt); } if (--sp->n_alive == 0) { if (tp2 = task_find(sp->n_ptid)) { tp2->t_flag |= TF_CLOSE; if (tp2->t_sock != -1) { /* wrk_fds_delete(tp2->t_sock, 3); (void)close(tp2->t_sock); tp2->t_sock = -1; */ shutdown(tp2->t_sock, 1); /* close stdout after pvmhost dies */ tp2->t_out = tp->t_out; } } /* LISTDELETE(sp, n_link, n_rlink); PVM_FREE(sp); */ } tp->t_out = -1; /* don't free shared stdout if alive > 0 */ return; } } sprintf(pvmtxt, "mpp_free() t%x not active\n", tid); pvmlogerror(pvmtxt); return; } /* load executable onto the given set of nodes */ int mpp_load( wxp ) struct waitc_spawn *wxp; { int flags = 0; /* exec options */ char *name; /* executable */ char **argv; /* arg list (argv[-1] must be there) */ int count; /* how many */ int *tids; /* array to store new tids */ int ptid; /* parent task ID */ int nenv; /* length of environment */ char **envp; /* environment strings */ int ptypepart; /* type field */ int j; struct task *tp; struct pkt *hosttxq; /* out-going queue of pvmhost */ int err = 0; struct nodeset *sp; char c[128]; /* buffer to store count, name.host */ char **ar = 0; int nargs; char **ep, **eplist; char path[MAXPATHLEN]; struct stat sb; char **av; int hostout; /* stdout of pvmhost */ struct hostd *hp = hosts->ht_hosts[hosts->ht_local]; int hostpid; /* Unix pid of pvmhost */ char htid[128]; /* buffer to store pvmhost tid */ char *p; static char *nullep[] = { "", 0 }; /* -- initialize some variables from the waitc_spawn struct -- */ name = wxp->w_argv[0]; argv = wxp->w_argv; count = wxp->w_veclen; tids = wxp->w_vec; ptid = wxp->w_ptid; nenv = wxp->w_nenv; envp = wxp->w_env; eplist = CINDEX(name, '/') ? nullep : epaths; for (ep = eplist; *ep; ep++) { /* search for file */ (void)strcpy(path, *ep); if (path[0]) (void)strcat(path, "/"); (void)strncat(path, name, sizeof(path) - strlen(path) - 1); if (stat(path, &sb) == -1 || ((sb.st_mode & S_IFMT) != S_IFREG) || !(sb.st_mode & S_IEXEC)) { if (pvmdebmask & PDMTASK) { sprintf(pvmtxt, "mpp_load() stat failed <%s>\n", path); pvmlogerror(pvmtxt); } continue; } if (!(sp = mpp_new(count+1, ptid))) { err = PvmOutOfRes; goto done; } ptypepart = (sp->n_ptype << (ffs(tidtmask) - 1)) | TIDONNODE; if (argv) for (nargs = 0; argv[nargs]; nargs++); else nargs = 0; /* ar[-1], poe, -procs, #, -euilib, us, -hfile fname */ nargs += MPIARGC + 1; av = TALLOC(nargs + 1, char*, "argv"); av++; /* reserve room for debugger */ BZERO((char*)av, nargs * sizeof(char*)); av[0] = MPICOMM; av[1] = path; av[--nargs] = 0; if (hostfileused) { av[--nargs] = nodefile; av[--nargs] = MPIOPT3; } else { av[--nargs] = defaultpool; av[--nargs] = MPIOPT4; } av[--nargs] = mpiadapter; av[--nargs] = MPIOPT2; sprintf(c, "%d", count+1); av[--nargs] = c; av[--nargs] = MPIOPT1; for (j = 2; j < nargs; j++) av[j] = argv[j - 1]; /* poe name argv -procs # -euilib us */ /* if ((sock = mksock()) == -1) { err = PvmSysErr; goto done; } */ if (flags & PvmTaskDebug) av++; /* pdbx name -procs # -euilib us */ /* if (err = forkexec(flags, av[0], av, 0, (char **)0, &tp)) */ if (err = forkexec(flags, av[0], av, 0, (char **)0, 0, 0, 0, &tp)) goto done; tp->t_ptid = ptid; PVM_FREE(tp->t_a_out); sprintf(c, "%s.host", name); tp->t_a_out = STRALLOC(c); sp->n_ptid = tp->t_tid; /* pvmhost's tid */ hosttxq = tp->t_txq; hostout = tp->t_out; hostpid = tp->t_pid; tp->t_out = -1; sprintf(htid, "PVMHTID=%d", tp->t_tid); p = STRALLOC(htid); pvmputenv(p); sp2pvminfo[0] = TDPROTOCOL; sp2pvminfo[1] = myhostpart + ptypepart; sp2pvminfo[2] = ptid; sp2pvminfo[3] = MAXFRAGSIZE; sp2pvminfo[4] = myndf; sp2pvminfo[5] = partsize; sp2pvminfo[6] = wxp->w_outtid; sp2pvminfo[7] = wxp->w_outtag; sp2pvminfo[8] = wxp->w_outctx; sp2pvminfo[9] = wxp->w_trctid; sp2pvminfo[10] = wxp->w_trctag; sp2pvminfo[11] = wxp->w_trcctx; /* if (sockconn(sock, tp, pvminfo) == -1) { err = PvmSysErr; task_free(tp); goto done; } */ /* XXX task may not be on same host; can't do auth with tmp file */ tp->t_flag |= TF_CONN; if (pvmdebmask & PDMTASK) { sprintf(pvmtxt, "mpp_load() %d type=%d ptid=%x t%x...\n", count, sp->n_ptype, ptid, myhostpart + ptypepart); pvmlogerror(pvmtxt); } /* create new task structs */ for (j = 0; j < count; j++) { if ((tp = task_new(myhostpart + ptypepart + j)) == NULL) { err = PvmOutOfRes; goto done; } tp->t_a_out = STRALLOC(name); tp->t_ptid = ptid; tp->t_flag |= TF_CONN; /* no need for the auth crap */ tids[j] = tp->t_tid; PVM_FREE(tp->t_txq); tp->t_txq = hosttxq; /* node tasks share pvmhost's txq */ tp->t_out = hostout; /* and stdout */ tp->t_pid = hostpid; /* pvm_kill should kill pvmhost */ tp->t_outtid = wxp->w_outtid; /* catch stdout/stderr */ tp->t_outtag = wxp->w_outtag; tp->t_outctx = wxp->w_outctx; } return 0; } if (pvmdebmask & PDMTASK) { sprintf(pvmtxt, "mpp_load() didn't find <%s>\n", name); pvmlogerror(pvmtxt); } err = PvmNoFile; done: for (j = 0; j < count; j++) tids[j] = err; return err; } #if 0 /* kill poe process */ void sp2kill(a_out, node) char *a_out; int node; { FILE *fp; int i; char nname[128]; /* node name */ char comm[512]; /* command to issue */ char *hfn; /* host file name */ struct stat sb; char *av[8]; /* for rsh args */ int ac; int pid = -1; /* pid of rsh */ node++; if ((hfn = getenv("MP_HOSTFILE")) || stat(hfn = "host.list", &sb) != -1) { if (fp = fopen(hfn, "r")) { for (i = 0; i < node; i++) fscanf(fp, "%s", nname); fclose(hfn); if ((pid = fork()) == -1) { pvmlogperror("sp2kill() fork"); return; } if (!pid) { ac = 0; av[ac++] = "/usr/bin/rsh"; av[ac++] = nname; av[ac++] = "poekill"; av[ac++] = a_out; av[ac++] = 0; for (i = getdtablesize(); --i > 2; ) (void)close(i); execvp(av[0], av); _exit(1); } } else pvmlogperror("sp2kill() fopen"); return; } pvmlogerror("sp2kill() no host file"); } #endif /*0*/ void mpp_kill(tp, signum) struct task *tp; int signum; { if (TIDISNODE(tp->t_tid)) { if (signum == SIGTERM || signum == SIGKILL) { /* sp2kill(tp->t_a_out, tp->t_tid & tidnmask); */ (void)kill(tp->t_pid, signum); mpp_free(tp); task_cleanup(tp); task_free(tp); } else { sprintf(pvmtxt,"mpp_kill() signal %d to node t%x ignored\n", signum, tp->t_tid); pvmlogerror(pvmtxt); } } else (void)kill(tp->t_pid, signum); } /* * Add pvmhost's socket to wfds if there are packets waiting to * be sent to a related node task. Node tasks have no sockets; * they share pvmhost's packet queue (txq). Pvmhost simply * forwards any packets it receives to the appropriate node. */ int mpp_output(dummy1, dummy2) struct task *dummy1; struct pkt *dummy2; { struct nodeset *sp, *sp2; struct task *tp; int ptype; for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link) if ((tp = task_find(sp->n_ptid))) { if (tp->t_txq->pk_link->pk_buf && tp->t_sock != -1) wrk_fds_add(tp->t_sock, 2); } else { if (sp->n_alive) { sprintf(pvmtxt, "mpp_output() pvmhost %d died!\n", sp->n_ptype); pvmlogerror(pvmtxt); /* clean up tasks it serves */ ptype = sp->n_ptype & ptypemask; for (tp = locltasks->t_link; tp != locltasks; tp = tp->t_link) if (TIDISNODE(tp->t_tid) && TIDTOTYPE(tp->t_tid) == ptype) { tp->t_txq = 0; tp = tp->t_rlink; task_cleanup(tp->t_link); task_free(tp->t_link); } } /* pvmhost has died, destroy the node set */ sp2 = sp; sp = sp->n_rlink; LISTDELETE(sp2, n_link, n_rlink); PVM_FREE(sp2); } return 0; } /* replace tm_connect and tm_conn2 */ int mpp_conn(tp, tp2) struct task *tp; struct task *tp2; { struct nodeset *sp; int pvminfo[SIZEHINFO]; /* host info */ int ptypepart; /* type field */ if (pvmdebmask & PDMNODE) { sprintf(pvmtxt, "mpp_conn() pvmhost %x", tp2->t_tid); pvmlogerror(pvmtxt); } tp2->t_sock = tp->t_sock; tp2->t_sad = tp->t_sad; tp2->t_salen = tp->t_salen; tp2->t_flag |= TF_CONN; tp->t_sock = -1; for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link) if (sp->n_ptid == tp2->t_tid) break; if (sp == busynodes) { pvmlogerror("mpp_conn() task is not pvmhost\n"); return -1; } ptypepart = (sp->n_ptype << (ffs(tidtmask) - 1)) | TIDONNODE; if (write(tp2->t_sock, sp2pvminfo, sizeof(sp2pvminfo)) != sizeof(sp2pvminfo)) { pvmlogperror("mpp_conn() write"); return -1; } return 0; } #if 0 /* * Create socket to talk to pvmhost. * Return socket descriptor if successful, -1 otherwise. */ int mksock() { struct hostd *hp = hosts->ht_hosts[hosts->ht_local]; struct sockaddr_in sin; char buf[128]; char *p; int cc; int sock; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { pvmlogperror("mksock() socket"); return -1; } sin = hp->hd_sad; if (bind(sock, (struct sockaddr*)&sin, sizeof(sin)) == -1) { pvmlogperror("mksock() bind"); (void)close(sock); return -1; } cc = sizeof(sin); if (getsockname(sock, (struct sockaddr*)&sin, &cc) == -1) { pvmlogperror("mksock() getsockname"); (void)close(sock); return -1; } if (listen(sock, 1) == -1) { pvmlogperror("mksock() listen"); (void)close(sock); return -1; } p = inadport_hex(&sin); sprintf(buf, "PVMSOCK=%s", p); p = STRALLOC(buf); pvmputenv(p); return sock; } /* * Wait for connect request from pvmhost and establish connection. * Return 0 if successful, -1 otherwise. * Close listening socket. */ int sockconn(sock, tp, hinfo) int sock; /* listening post */ struct task *tp; /* pvm host */ int hinfo[]; /* host info to pass along */ { int i; if ((tp->t_sock = accept(sock, (struct sockaddr*)&tp->t_sad, &tp->t_salen)) == -1) { pvmlogperror("sockconn() accept"); return -1; } else { if (pvmdebmask & (PDMPACKET|PDMTASK)) { sprintf(pvmtxt, "sockconn() accept from %s sock %d\n", inadport_decimal(&tp->t_sad), tp->t_sock); pvmlogerror(pvmtxt); } close(sock); #ifndef NOSOCKOPT i = 1; if (setsockopt(tp->t_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&i, sizeof(int)) == -1) pvmlogperror("sockconn() setsockopt"); #endif } if (write(tp->t_sock, hinfo, SIZEHINFO*sizeof(int)) != SIZEHINFO*sizeof(int)) { pvmlogperror("sockconn: write"); return -1; } if ((i = fcntl(tp->t_sock, F_GETFL, 0)) == -1) pvmlogperror("sockconn: fcntl"); else { i |= O_NDELAY; (void)fcntl(tp->t_sock, F_SETFL, i); } wrk_fds_add(tp->t_sock, 1); return 0; } #endif /*0*/ ./pvm3/src/ALPHAMP/0042755007401100000360000000000010117676455012772 5ustar kohlgopher./pvm3/src/ALPHAMP/Makefile0100644007401100000360000000061306604767745014436 0ustar kohlgopher# # $Id: Makefile,v 1.4 1998/10/01 21:11:01 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/src PVM_ARCH = ALPHAMP CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) all: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk all-shm install: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install-shm clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean ./pvm3/src/BEOLIN/0042755007401100000360000000000010117676455012660 5ustar kohlgopher./pvm3/src/BEOLIN/Makefile0100644007401100000360000000061407053060737014307 0ustar kohlgopher# # $Id: Makefile,v 1.1 2000/02/17 21:02:23 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/src PVM_ARCH = BEOLIN CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) all: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk all-beo install: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install-beo clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean ./pvm3/src/BEOLIN/pvmdmimd.c0100644007401100000360000004163507435300163014632 0ustar kohlgopher /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmdmimd.c * * MPP interface. * * void mpp_init(int argc, char **argv): * Initialization. Create a table to keep track of active nodes. * argc, argv: passed from main. * * int mpp_load( struct waitc_spawn *wxp ) * * Load executable onto nodes; create new entries in task table, * encode node number and process type into task IDs, etc. * * Construction of Task ID: * * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 * +-+-+-----------------------+-+-----+--------------------------+ * |s|g| host index |n| prt | node # (16384) | * +-+-+-----------------------+-+-----+--------------------------+ * * The "n" bit is set for node task but clear for host task. * * flags: exec options; * name: executable to be loaded; * argv: command line argument for executable * count: number of tasks to be created; * tids: array to store new task IDs; * ptid: parent task ID. * * mpp_new(int count, int ptid): * Allocate a set of nodes. (called by mpp_load()) * count: number of nodes; ptid: parent task ID. * * int mpp_output(): * Send all pending packets to nodes via native send. Node number * and process type are extracted from task ID. * * struct task *mpp_find(int pid): * Find a task in task table by its Unix pid. * * void mpp_free(struct task *tp): * Remove node/process-type from active list. * tp: task pointer. * $Log: pvmdmimd.c,v $ Revision 1.2 2002/02/21 23:19:15 pvmsrc Added new (not to be documented!) PVM_MAX_TASKS env var support. - for Mahir Lokvancic . - forcefully limits the number of tasks that can attach to a pvmd, required on Solaris in rare circumstances when hard FD_SETSIZE limit is reached, and all hell breaks loose... - check return for task_new() call, can now produce NULL ptr, indicating PvmOutOfRes... (Spanker=kohl) Revision 1.1 2000/02/17 21:02:24 pvmsrc Architecture-specific Makefile and Pvmd code. - submitted by Paul Springer . - hacked a little by Jeembo for convention compliance... :-) (Spanker=kohl) * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef SYSVSTR #include #define CINDEX(s,c) strchr(s,c) #else #include #define CINDEX(s,c) index(s,c) #endif #include #include #include "global.h" #include "host.h" #include "waitc.h" #include "pvmalloc.h" #include "pkt.h" #include "task.h" #include "listmac.h" #if 0 #include "tvdefs.h" #endif #include "pvmdmp.h" #include "pvmmimd.h" #include "bfunc.h" #define BLCOMM "/usr/bin/rsh" #define BLARGC 3 char *getenv(); /* Global */ extern int pvmdebmask; /* from pvmd.c */ extern char **epaths; /* from pvmd.c */ extern int myhostpart; /* from pvmd.c */ extern int myndf; /* from pvmd.c */ extern struct htab *hosts; /* from pvmd.c */ extern struct task *locltasks; /* from task.c */ extern int pvmmydsig; /* from pvmd.c */ extern int pvmudpmtu; /* from pvmd.c */ int tidtmask = TIDPTYPE; /* mask for ptype field of tids */ int tidnmask = TIDNODE; /* mask for node field of tids */ /* private */ static char rcsid[] = "$Id: pvmdmimd.c,v 1.2 2002/02/21 23:19:15 pvmsrc Exp $"; static struct nodeset *busynodes; /* active nodes; ordered by proc type */ static char pvmtxt[512]; /* scratch for error log */ static int ptypemask; /* mask; we use these bits of ptype in tids */ static u_long *nodeaddr = 0; static char **nodelist = 0; /* default poe node list */ static int partsize = 0; /* total number of nodes allocated */ static int mpppvminfo[SIZEHINFO]; void mpp_init(argc, argv) int *argc; char **argv; { struct hostent *hostaddr; int i; int n; struct in_addr node_sin_addr; char nname[128]; /* node name */ char *p, *q; char *plist; /* processor list */ if ((plist = getenv("PROC_LIST"))) { sprintf(pvmtxt, "PROC_LIST=%s\n",plist); pvmlogerror(pvmtxt); p = plist; while (1) { while (*p == ':') p++; if (!*p) break; n = (q = CINDEX(p, ':')) ? q - p : strlen(p); partsize++; p += n; } nodeaddr = TALLOC(partsize, u_long, "nodeaddr"); nodelist = TALLOC(partsize, char*, "nname"); p = plist; i = 0; while (1) { /* now get the node names */ while (*p == ':') p++; if (!*p) break; n = (q = CINDEX(p, ':')) ? q - p : strlen(p); strncpy(nname, p, n); nname[n] = 0; if (!(hostaddr = gethostbyname( nname ))) { sprintf( pvmtxt, "mpp_init() can't gethostbyname() for %s\n", nname ); pvmlogerror( pvmtxt ); } else { /* got addr, now save it */ BCOPY( hostaddr->h_addr_list[0], (char*)&node_sin_addr, sizeof(struct in_addr)); } nodeaddr[i] = node_sin_addr.s_addr; nodelist[i++] = STRALLOC(nname); p += n; } } else pvmlogerror("mpp_init() PROC_LIST must be set for parallelism.\n"); sprintf(pvmtxt, "%d nodes in list.\n", partsize); pvmlogerror(pvmtxt); busynodes = TALLOC(1, struct nodeset, "nsets"); BZERO((char*)busynodes, sizeof(struct nodeset)); busynodes->n_link = busynodes; busynodes->n_rlink = busynodes; ptypemask = tidtmask >> (ffs(tidtmask) - 1); } /* * find a set of free nodes from nodelist; assign ptype sequentially, * only tasks spawned together get the same ptype */ struct nodeset * mpp_new(count, ptid) int count; /* number of nodes requested */ int ptid; /* parent's tid */ { struct nodeset *sp, *newp, *sp2; int last = -1; int ptype = 0; if (!(newp = TALLOC(1, struct nodeset, "nsets"))) { pvmlogerror("mpp_new() can't get memory\n"); pvmbailout(0); } BZERO((char*)newp, sizeof(struct nodeset)); newp->n_size = count; for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link) { if (sp->n_first - last > count) break; last = sp->n_first + sp->n_size - 1; /* if (sp->n_link == busynodes && partsize - last > count) break; */ if (ptype <= sp->n_ptype) ptype = sp->n_ptype + 1; } if (sp == busynodes && partsize - last <= count) { pvmlogerror("mpp_new() not enough nodes in partition\n"); PVM_FREE(newp); return (struct nodeset *)0; } for (sp2 = busynodes->n_link; sp2 != busynodes; sp2 = sp2->n_link) if ((sp2->n_ptype & ptypemask) == (ptype & ptypemask)) break; if (sp2 != busynodes || ptype == NPARTITIONS) { for (ptype = 0; ptype < NPARTITIONS; ptype++) { for (sp2 = busynodes->n_link; sp2 != busynodes; sp2 = sp2->n_link) if ((sp2->n_ptype & ptypemask) == (ptype & ptypemask)) break; if (sp2 == busynodes) break; } if (ptype == NPARTITIONS) { pvmlogerror("mpp_new() out of ptypes: too many spawns\n"); return (struct nodeset *)0; } } done: if (pvmdebmask & PDMNODE) { sprintf(pvmtxt, "mpp_new() %d nodes %d ... ptype=%d ptid=%x\n", count, last+1, ptype, ptid); pvmlogerror(pvmtxt); } newp->n_first = last + 1; newp->n_ptype = ptype; newp->n_ptid = ptid; newp->n_alive = count; sprintf( pvmtxt, "mpp_new() sp=%x sp->n_link=%x\n", sp, sp->n_link ); pvmlogerror( pvmtxt ); LISTPUTBEFORE(sp, newp, n_link, n_rlink); sprintf( pvmtxt, "mpp_new() sp=%x sp->n_link=%x\n", sp, sp->n_link ); pvmlogerror( pvmtxt ); return newp; } /* * remove node/ptype from active list; if tid is the last to go, shutdown * pvmhost's socket, but do not destroy the node set because pvmhost may * not exit immediately. To avoid a race condition, let mpp_output() * do the cleanup. */ void mpp_free(tp) struct task *tp; { struct nodeset *sp; int ptype; #if 0 struct timeval tout; #endif struct task *tp2; int tid = tp->t_tid; if (!TIDISNODE(tid)) return; ptype = TIDTOTYPE(tid); tp->t_txq = 0; /* don't free pvmhost's txq */ sp = busynodes->n_link; sprintf( pvmtxt, "mpp_free() sp=%x sp->n_link=%x\n", sp, sp->n_link ); pvmlogerror( pvmtxt ); for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link) { sprintf(pvmtxt, "mpp_free() n_ptype = %d, ptype = %d\n", sp->n_ptype, ptype ); pvmlogerror(pvmtxt); if ((sp->n_ptype & ptypemask) == ptype) { if (pvmdebmask & PDMNODE) { sprintf(pvmtxt, "mpp_free() t%x type=%ld alive=%d\n", tid, sp->n_ptype, sp->n_alive); pvmlogerror(pvmtxt); } if (sp->n_alive == 0) { sprintf( pvmtxt, "mpp_free called for dead task t%x\n", tid ); pvmlogerror( pvmtxt ); return; } if (tp2 = task_findpid(tp->t_pid)) { /* find corresponding pvmhost and shut it down */ tp2->t_flag |= TF_CLOSE; #if 0 pvmlogprintf( "mpp_free() Marked t%x for closure\n", tp2->t_tid ); #endif if (tp2->t_sock != -1) { /* wrk_fds_delete(tp2->t_sock, 3); (void)close(tp2->t_sock); tp2->t_sock = -1; */ shutdown(tp2->t_sock, 1); } /* close stdout after pvmhost dies */ tp2->t_out = tp->t_out; #if 0 pvmlogprintf( "mpp_free() Set t%x t_tout to %d\n", tp2->t_tid, tp->t_out ); #endif } if (--sp->n_alive == 0) { /* LISTDELETE(sp, n_link, n_rlink); PVM_FREE(sp); */ } #if 0 if (tp->t_out >= 0) { fd_set rfds; FD_ZERO(&rfds); FD_SET(tp->t_out, &rfds); TVCLEAR(&tout); if (select(tp->t_out + 1, (fd_set *)&rfds, (fd_set *)0, (fd_set *)0, &tout) == 1) { pvmlogprintf( "mpp_free() unprinted stdout on t%x\n", tp->t_tid ); loclstout( tp ); } else pvmlogprintf( "mpp_free() no stdout on t%x\n", tp->t_tid ); } #endif tp->t_out = -1; /* don't free shared stdout if alive > 0 */ return; } } sprintf(pvmtxt, "mpp_free() t%x not active\n", tid); pvmlogerror(pvmtxt); return; } /* load executable onto the given set of nodes */ int mpp_load( wxp ) struct waitc_spawn *wxp; { int flags = 0; /* exec options */ char *name; /* executable */ char **argv; /* arg list (argv[-1] must be there) */ int count; /* how many */ int *tids; /* array to store new tids */ int ptid; /* parent task ID */ int ptypepart; /* type field */ int j; struct task *tp; struct pkt *hosttxq; /* out-going queue of pvmhost */ int err = 0; struct nodeset *sp; char c[128]; /* buffer to store count, name.host */ int nargs; char **ep, **eplist; char path[MAXPATHLEN]; struct stat sb; char **av; int hostout; /* stdout of pvmhost */ int hostpid; /* Unix pid of pvmhost */ static char *nullep[] = { "", 0 }; /* -- initialize some variables from the waitc_spawn struct -- */ name = wxp->w_argv[0]; argv = wxp->w_argv; count = wxp->w_veclen; tids = wxp->w_vec; ptid = wxp->w_ptid; eplist = CINDEX(name, '/') ? nullep : epaths; for (ep = eplist; *ep; ep++) { /* search for file */ (void)strcpy(path, *ep); if (path[0]) (void)strcat(path, "/"); (void)strncat(path, name, sizeof(path) - strlen(path) - 1); if (stat(path, &sb) == -1 || ((sb.st_mode & S_IFMT) != S_IFREG) || !(sb.st_mode & S_IEXEC)) { if (pvmdebmask & PDMTASK) { sprintf(pvmtxt, "mpp_load() stat failed <%s>\n", path); pvmlogerror(pvmtxt); } continue; } if (!(sp = mpp_new(count, ptid))) { err = PvmOutOfRes; goto done; } ptypepart = (0 << (ffs(tidtmask) - 1)) | TIDONNODE; if (argv) for (nargs = 0; argv[nargs]; nargs++); else nargs = 0; /* ar[-1], rsh, host, command */ nargs += BLARGC + 1; av = TALLOC(nargs + 1, char*, "argv"); av++; /* reserve room for debugger */ BZERO((char*)av, nargs * sizeof(char*)); av[0] = BLCOMM; av[2] = path; av[--nargs] = 0; for (j = 3; j < nargs; j++) av[j] = argv[j - 2]; /* poe name argv -procs # -euilib us */ /* if ((sock = mksock()) == -1) { err = PvmSysErr; goto done; } */ if (flags & PvmTaskDebug) av++; /* pdbx name -procs # -euilib us */ for (j = 0; j < count; j++) { av[1] = nodelist[sp->n_first + j]; sprintf(pvmtxt, "mppload(): Forking to %s\n", av[1]); pvmlogerror(pvmtxt); /* if (err = forkexec(flags, av[0], av, 0, (char **)0, &tp)) */ if (err = forkexec(flags, av[0], av, 0, (char **)0, 0, 0, 0, &tp)) goto done; tp->t_ptid = ptid; PVM_FREE(tp->t_a_out); sprintf(c, "%s.host", name); tp->t_a_out = STRALLOC(c); if (pvmdebmask & PDMNODE) pvmlogprintf( "mpp_load() setting n_ptid to %x\n", tp->t_tid ); sp->n_ptid = tp->t_tid; /* pvmhost's tid */ hosttxq = tp->t_txq; hostout = tp->t_out; hostpid = tp->t_pid; tp->t_out = -1; mpppvminfo[0] = TDPROTOCOL; mpppvminfo[1] = myhostpart + ptypepart; mpppvminfo[2] = ptid; mpppvminfo[3] = wxp->w_outtid; mpppvminfo[4] = wxp->w_outtag; mpppvminfo[5] = wxp->w_outctx; mpppvminfo[6] = wxp->w_trctid; mpppvminfo[7] = wxp->w_trctag; mpppvminfo[8] = wxp->w_trcctx; mpppvminfo[9] = pvmudpmtu; mpppvminfo[10] = pvmmydsig; /* pvminfo[0] = TDPROTOCOL; pvminfo[1] = myhostpart + ptypepart; pvminfo[2] = ptid; pvminfo[3] = MAXFRAGSIZE; pvminfo[4] = myndf; if (sockconn(sock, tp, pvminfo) == -1) { err = PvmSysErr; task_free(tp); goto done; } */ if (pvmdebmask & PDMTASK) { sprintf(pvmtxt, "mpp_load() %d type=%d ptid=%x t%x...\n", count, 0, ptid, myhostpart + ptypepart + sp->n_first + j); pvmlogerror(pvmtxt); } /* create new task structs */ if ((tp = task_new(myhostpart + ptypepart + sp->n_first + j)) == NULL) { err = PvmOutOfRes; goto done; } tp->t_a_out = STRALLOC(name); tp->t_ptid = ptid; tids[j] = tp->t_tid; PVM_FREE(tp->t_txq); tp->t_txq = hosttxq; /* node tasks share pvmhost's txq */ tp->t_out = hostout; /* and stdout */ #if 0 pvmlogprintf( "Setting t%x pid to p%d\n", tp->t_tid, hostpid ); #endif tp->t_pid = hostpid; /* pvm_kill should kill pvmhost */ tp->t_outtid = wxp->w_outtid; /* catch stdout/stderr */ tp->t_outtag = wxp->w_outtag; tp->t_outctx = wxp->w_outctx; } return 0; } if (pvmdebmask & PDMTASK) { sprintf(pvmtxt, "mpp_load() didn't find <%s>\n", name); pvmlogerror(pvmtxt); } err = PvmNoFile; done: for (j = 0; j < count; j++) tids[j] = err; return err; } /* Find task by socket address */ struct task *mpp_find( tp ) struct task *tp; { int i; struct task *nodetp = 0; int ptypepart; for (i = 0; i < partsize; i++) if (nodeaddr[i] == tp->t_sad.sin_addr.s_addr) { ptypepart = (0 << (ffs(tidtmask) - 1)) | TIDONNODE; sprintf(pvmtxt, "mpp_find looking for t%x\n", myhostpart + ptypepart + i); pvmlogerror(pvmtxt); if (nodetp = task_find( myhostpart + ptypepart + i )) break; /* found match */ } if (!nodetp) pvmlogerror( "mpp_find: Task not found\n" ); return nodetp; } /* mpp_find() */ /* * Add pvmhost's socket to wfds if there are packets waiting to * be sent to a related node task. Node tasks have no sockets; * they share pvmhost's packet queue (txq). Pvmhost simply * forwards any packets it receives to the appropriate node. */ int mpp_output(dummy1, dummy2) struct task *dummy1; struct pkt *dummy2; { struct nodeset *sp, *sp2; struct task *tp; int ptype; sp = busynodes->n_link; for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link) if ((tp = task_find(sp->n_ptid))) { if (tp->t_txq->pk_link->pk_buf && tp->t_sock != -1) wrk_fds_add(tp->t_sock, 2); } else { if (sp->n_alive) { sprintf(pvmtxt, "mpp_output() pvmhost %d died!\n", sp->n_ptype); pvmlogerror(pvmtxt); /* clean up tasks it serves */ ptype = sp->n_ptype & ptypemask; for (tp = locltasks->t_link; tp != locltasks; tp = tp->t_link) if (TIDISNODE(tp->t_tid) && TIDTOTYPE(tp->t_tid) == ptype) { tp->t_txq = 0; tp = tp->t_rlink; task_cleanup(tp->t_link); task_free(tp->t_link); } } /* pvmhost has died, destroy the node set */ sp2 = sp; sp = sp->n_rlink; LISTDELETE(sp2, n_link, n_rlink); PVM_FREE(sp2); } return 0; } ./pvm3/src/CSPP/0042755007401100000360000000000010117676455012455 5ustar kohlgopher./pvm3/src/CSPP/Makefile0100644007401100000360000000061006604767764014117 0ustar kohlgopher# # $Id: Makefile,v 1.4 1998/10/01 21:11:16 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/src PVM_ARCH = CSPP CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) all: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk all-shm install: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install-shm clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean ./pvm3/src/HPPAMP/0042755007401100000360000000000010117676455012675 5ustar kohlgopher./pvm3/src/HPPAMP/Makefile0100644007401100000360000000061206604770002014314 0ustar kohlgopher# # $Id: Makefile,v 1.4 1998/10/01 21:11:30 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/src PVM_ARCH = HPPAMP CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) all: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk all-shm install: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install-shm clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean ./pvm3/src/OS2/0042755007401100000360000000000010117676455012313 5ustar kohlgopher./pvm3/src/OS2/Makefile0100644007401100000360000000065106401374702013737 0ustar kohlgopher# # $Id: Makefile,v 1.1 1997/08/28 22:20:50 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/src PVM_ARCH = OS2 CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) all: make LIBPREFIX="" -f $(CONFFILE) -f $(SDIR)/Makefile.aimk all-os2 install: make LIBPREFIX="" \ -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install-os2 clean: make LIBPREFIX="" -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean ./pvm3/src/OS2/Makefile.reg0100644007401100000360000000560606401541644014521 0ustar kohlgopher# Makefile for regex. # # Copyright (C) 1992, 1993 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. version = 0.12 # You can define CPPFLAGS on the command line. Aside from system-specific # flags, you can define: # -DREGEX_MALLOC to use malloc/realloc/free instead of alloca. # -DDEBUG to enable the compiled pattern disassembler and execution # tracing; code runs substantially slower. # -DEXTRACT_MACROS to use the macros EXTRACT_* (as opposed to # the corresponding C procedures). If not -DDEBUG, the macros # are used. CPPFLAGS = # Likewise, you can override CFLAGS to optimize, use -Wall, etc. CFLAGS = -g # Ditto for LDFLAGS and LOADLIBES. LDFLAGS = LOADLIBES = srcdir = . VPATH = . CC = gcc DEFS = SHELL = /bin/ksh subdirs = doc test default all:: pvmregex.o regex.o .PHONY: default all pvmregex.o: pvmregex.c regex.h $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) -I. -I$(srcdir) -c $< regex.o: regex.c regex.h $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) -I. -I$(srcdir) -c $< clean mostlyclean:: rm -f *.o distclean:: clean rm -f Makefile extraclean:: distclean rm -f patch* *~* *\#* *.orig *.rej *.bak core a.out #configure: configure.in # autoconf #config.status: configure # sh configure --no-create #Makefile: Makefile.in config.status # sh config.status makeargs = $(MFLAGS) CPPFLAGS='$(CPPFLAGS)' CFLAGS='$(CFLAGS)' CC='$(CC)' \ DEFS='$(DEFS)' LDFLAGS='$(LDFLAGS)' LOADLIBES='$(LOADLIBES)' default all install \ mostlyclean clean distclean extraclean realclean \ TAGS check:: for d in $(subdirs); do (cd $$d; $(MAKE) $(makeargs) $@); done .PHONY: install mostlyclean clean distclean extraclean realclean TAGS check # Prevent GNU make 3 from overflowing arg limit on system V. .NOEXPORT: distfiles = AUTHORS ChangeLog COPYING INSTALL NEWS README \ *.in configure regex.c regex.h distdir = regex-$(version) distargs = version=$(version) distdir=../$(distdir)/$$d dist: TAGS configure @echo "Version numbers in: Makefile.in, ChangeLog, NEWS," @echo " regex.c, regex.h," @echo " and doc/xregex.texi (if modified)." rm -rf $(distdir) mkdir $(distdir) ln $(distfiles) $(distdir) for d in $(subdirs); do (cd $$d; $(MAKE) $(distargs) dist); done tar czhf $(distdir).tar.Z $(distdir) rm -rf $(distdir) .PHONY: dist ./pvm3/src/OS2/src/0042755007401100000360000000000010117676455013102 5ustar kohlgopher./pvm3/src/OS2/src/deathapi.c0100644007401100000360000000213206401367007015005 0ustar kohlgopher/* Copyright (C)1996 by Holger.Veit@gmd.de */ /* This code may be freely used in own software */ #define INCL_DOS #define INCL_ERRORS #include #include /* #include "death.h" */ #include static APIRET death(PID pid) { APIRET rc; HFILE hfd; ULONG action,plen; USHORT param; if ((rc=DosOpen((PSZ)"/dev/fastio$", (PHFILE)&hfd, (PULONG)&action, (ULONG)0, FILE_SYSTEM, FILE_OPEN, OPEN_SHARE_DENYNONE|OPEN_FLAGS_NOINHERIT|OPEN_ACCESS_READONLY, (ULONG)0))) { fputs("Error opening fastio$ driver...\n",stderr); fputs("Please install xf86sup.sys in config.sys!\n",stderr); return rc; } param = pid; if ((rc=DosDevIOCtl(hfd, (ULONG)0x76, (ULONG)0x65, (PULONG*)¶m,sizeof(USHORT),&plen, NULL, 0, NULL)) != 0) { fprintf(stderr,"fastio$ driver: kill(%i,9) failed rc=%i\n",pid,rc); DosClose(hfd); return rc; } DosClose(hfd); return 0; } int os2_kill(int pid, int sig) { if(sig==SIGTERM||sig==SIGKILL||sig==SIGINT||sig==SIGBREAK||sig==SIGHUP) return death(pid); else return kill(pid,sig); } ./pvm3/src/OS2/src/os2spawn.c0100644007401100000360000000135306401367010015000 0ustar kohlgopher#include #include #include int os2_spawn( char *path, char **argv, int nenv, char **env, char *debugger) //----------------------------------------------------------- { char *Arg[1024],*Env[1024],**d,**s,*idstr="PVMEPID=",buf[32]; sprintf(buf,"%s%i",idstr,0); d=Arg; s=argv; if (debugger) { *d = getenv("PVM_DEBUGGER"); if(*d==0)*d=debugger; d++; } *d++=path; s++; while(*s)*d++=*s++; *d=0; d=Env; s=environ; while(*s) { if(strncmp(*s,idstr,strlen(idstr)))*d++=*s; else *d++=buf; s++; } s=env; while(nenv--)*d++=*s++; *d=0; return spawnve(P_NOWAIT,path,Arg,Env); } ./pvm3/src/OS2/src/rexec.c0100644007401100000360000001046306401367011014335 0ustar kohlgopher/* * Copyright (c) 1980, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)rexec.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include #include #include #include #include #include int rexecoptions; int rexec(ahost, rport, name, pass, cmd, fd2p) char **ahost; int rport; const char *name, *pass, *cmd; int *fd2p; { int s, timo = 1, s3; struct sockaddr_in sin, sin2, from; char c; u_short port; struct hostent *hp; static char savename[256]; hp = gethostbyname(*ahost); if (hp == 0) { fprintf(stderr, "%s: unknown host\n", *ahost); return (-1); } sin.sin_family = hp->h_addrtype; sin.sin_port = rport; memcpy ((caddr_t)&sin.sin_addr, hp->h_addr, hp->h_length); strncpy((*ahost = savename), hp->h_name, sizeof(savename) -1); ruserpass(*ahost, &name, &pass); /* stdlog("rexec: %s %s %s %s\n",*ahost,name,pass,cmd); */ retry: s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) { perror("rexec: socket"); return (-1); } if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { if (errno == ECONNREFUSED && timo <= 16) { (void) close(s); sleep(timo); timo *= 2; goto retry; } perror(*ahost); return (-1); } if (fd2p == 0) { (void) write(s, "", 1); port = 0; } else { char num[8]; int s2, sin2len; s2 = socket(AF_INET, SOCK_STREAM, 0); if (s2 < 0) { (void) close(s); return (-1); } sin2len = sizeof (sin2); sin2.sin_addr.s_addr = INADDR_ANY; sin2.sin_family = sin.sin_family; bind(s2, (struct sockaddr *) &sin2, sin2len); listen(s2, 1); if (getsockname(s2, (struct sockaddr *)&sin2, &sin2len) < 0 || sin2len != sizeof (sin2)) { perror("getsockname"); (void) close(s2); goto bad; } port = ntohs((u_short)sin2.sin_port); (void) sprintf(num, "%u", port); (void) write(s, num, strlen(num)+1); { int len = sizeof (from); s3 = accept(s2, (struct sockaddr *)&from, &len); close(s2); if (s3 < 0) { perror("accept"); port = 0; goto bad; } } *fd2p = s3; } (void) write(s, name, strlen(name) + 1); /* should public key encypt the password here */ (void) write(s, pass, strlen(pass) + 1); (void) write(s, cmd, strlen(cmd) + 1); if (read(s, &c, 1) != 1) { perror(*ahost); goto bad; } if (c != 0) { while (read(s, &c, 1) == 1) { (void) write(2, &c, 1); if (c == '\n') break; } goto bad; } return (s); bad: if (port) (void) close(*fd2p); (void) close(s); return (-1); } ./pvm3/src/OS2/src/ruserpas.c0100644007401100000360000004300106401367012015066 0ustar kohlgopher/* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)ruserpass.c 5.5 (Berkeley) 6/27/88"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include #include #include #include #include #include #include static void renv(const char *host, char **aname, char **apass); static char * renvlook(const char *host); /*static struct utmp *getutmp(char *sttyname);*/ static FILE *cfile; static void rnetrc(const char *host, char **aname, char **apass); static void mkpwclear(char *spasswd, char mch, char *sencpasswd); static int token(); void ruserpass(const char *host, char **aname, char **apass) { static char namebuf [256]; struct hostent *hp; char name[256]; /* a temp name buffer to avoid overlayyed */ strncpy(name, host, sizeof(name) - 1); if (hp = gethostbyname (name)) strncpy(name,hp->h_name, sizeof(name) - 1); renv(name, aname, apass); if (*aname == 0 || *apass == 0) rnetrc(name,aname,apass); /*rnetrc would call gethostbyname */ if (*aname == 0) { *aname = getlogin(); if (*aname == NULL) { struct passwd *pp = getpwuid(getuid()); if (pp != NULL) *aname = pp->pw_name; } printf("Name (%s:%s): ", host, *aname); fflush(stdout); if (read(2, namebuf, sizeof (namebuf)) <= 0) { perror ("read"); exit(1); } if (namebuf [0] != '\n') { char *ptr; *aname = namebuf; namebuf [sizeof (namebuf) - 1] = '0'; if (ptr = index(namebuf, '\n')) *ptr = 0; } } if (*aname && *apass == 0) { printf("Password (%s:%s): ", host, *aname); fflush(stdout); *apass = getpass(""); } } static void renv(const char *host, char **aname, char **apass) { register char *cp; char *comma; cp = renvlook(host); if (cp == NULL) return; if (!isalpha(cp[0])) return; comma = index(cp, ','); if (comma == 0) return; if (*aname == 0) { *aname = (char*)malloc(comma - cp + 1); strncpy(*aname, cp, comma - cp); } else if (strncmp(*aname, cp, comma - cp)) return; comma++; cp = (char *)malloc(strlen(comma)+1); strcpy(cp, comma); *apass = (char*)malloc(16); mkpwclear(cp, host[0], *apass); } #if !defined(HAVE_GNU_LD) && !defined (__ELF__) #define __environ environ #endif static char * renvlook(const char *host) { register char *cp, **env; extern char **__environ; for (env = __environ; *env != NULL; env++) if (!strncmp(*env, "MACH", 4)) { cp = index(*env, '='); if (cp == 0) continue; if (strncmp(*env+4, host, cp-(*env+4))) continue; return (cp+1); } return (NULL); } #define DEFAULT 1 #define LOGIN 2 #define PASSWD 3 #define NOTIFY 4 #define WRITE 5 #define YES 6 #define NO 7 #define COMMAND 8 #define FORCE 9 #define ID 10 #define MACHINE 11 static char tokval[100]; static struct toktab { char *tokstr; int tval; } toktab[]= { "default", DEFAULT, "login", LOGIN, "password", PASSWD, "notify", NOTIFY, "write", WRITE, "yes", YES, "y", YES, "no", NO, "n", NO, "command", COMMAND, "force", FORCE, "machine", MACHINE, 0, 0 }; static void rnetrc(const char *host, char **aname, char **apass) { char *hdir, buf[BUFSIZ]; int t; struct stat stb; struct hostent *hp; hdir = getenv("HOME"); if (hdir == NULL) hdir = "."; (void)sprintf(buf, "%s/.netrc", hdir); cfile = fopen(buf, "r"); if (cfile == NULL) { if (errno != ENOENT) perror(buf); return; } next: while ((t = token())) switch(t) { case DEFAULT: (void) token(); continue; case MACHINE: if (token() != ID) continue; if(hp = gethostbyname (tokval)) { if (strcmp(host, hp->h_name)) continue; } else if (strcmp(host, tokval)) continue; while ((t = token()) && t != MACHINE) switch(t) { case LOGIN: if (token()) if (*aname == 0) { *aname = (char*)malloc(strlen(tokval) + 1); strcpy(*aname, tokval); } else { if (strcmp(*aname, tokval)) goto next; } break; case PASSWD: #ifndef __EMX__ if (fstat(fileno(cfile), &stb) >= 0 && (stb.st_mode & 077) != 0) { fprintf(stderr, "Error - .netrc file not correct mode.\n"); fprintf(stderr, "Remove password or correct mode.\n"); exit(1); } #endif if (token() && *apass == 0) { *apass = malloc(strlen(tokval) + 1); strcpy(*apass, tokval); } break; case COMMAND: case NOTIFY: case WRITE: case FORCE: (void) token(); break; default: fprintf(stderr, "Unknown .netrc option %s\n", tokval); break; } goto done; } done: fclose(cfile); } static int token() { char *cp; int c; struct toktab *t; if (feof(cfile)) return (0); #if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_REENTRANT) #undef getc #define getc getc_unlocked flockfile (cfile); #endif while ((c = getc(cfile)) != EOF && (c == '\n' || c == '\t' || c == ' ' || c == ',')) continue; if (c == EOF) return (0); cp = tokval; if (c == '"') { while ((c = getc(cfile)) != EOF && c != '"') { if (c == '\\') c = getc(cfile); *cp++ = c; } } else { *cp++ = c; while ((c = getc(cfile)) != EOF && c != '\n' && c != '\t' && c != ' ' && c != ',') { if (c == '\\') c = getc(cfile); *cp++ = c; } } #if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_REENTRANT) funlockfile (cfile); #endif *cp = 0; if (tokval[0] == 0) return (0); for (t = toktab; t->tokstr; t++) if (!strcmp(t->tokstr, tokval)) return (t->tval); return (ID); } /* rest is nbs.c stolen from berknet */ #if 0 static char *nbsencrypt(char *str, char *key, char *result); static char *nbs8encrypt(char *str, char *key); static char *deblknot(char *blk); #endif static char *nbsdecrypt(char *cpt, char *key, char *result); static char *nbs8decrypt(char *crp, char *key); static void enblkclr(char *blk, char *str); static char *deblkclr(char *blk); static void enblknot(char *blk, char *crp); static void nbssetkey(char *key); static void blkencrypt(char *block, int edflag); static char E[48]; /* * The E bit-selection table. */ static char e[] = { 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9,10,11,12,13, 12,13,14,15,16,17, 16,17,18,19,20,21, 20,21,22,23,24,25, 24,25,26,27,28,29, 28,29,30,31,32, 1, }; #if 0 static char *nbsencrypt(str,key,result) char *str, *key; char *result; { static char buf[20],oldbuf[20]; register int j; result[0] = 0; strcpy(oldbuf,key); while(*str){ for(j=0;j<10;j++)buf[j] = 0; for(j=0;j<8 && *str;j++)buf[j] = *str++; strcat(result,nbs8encrypt(buf,oldbuf)); strcat(result,"$"); strcpy(oldbuf,buf); } return(result); } #endif static char *nbsdecrypt(cpt,key,result) char *cpt,*key; char *result; { char *s; char c,oldbuf[20]; result[0] = 0; strcpy(oldbuf,key); while(*cpt){ for(s = cpt;*s && *s != '$';s++); c = *s; *s = 0; strcpy(oldbuf,nbs8decrypt(cpt,oldbuf)); strcat(result,oldbuf); if(c == 0)break; cpt = s + 1; } return(result); } #if 0 static char *nbs8encrypt(str,key) char *str, *key; { static char keyblk[100], blk[100]; register int i; enblkclr(keyblk,key); nbssetkey(keyblk); for(i=0;i<48;i++) E[i] = e[i]; enblkclr(blk,str); blkencrypt(blk,0); /* forward dir */ return(deblknot(blk)); } #endif static char *nbs8decrypt(crp,key) char *crp, *key; { static char keyblk[100], blk[100]; register int i; enblkclr(keyblk,key); nbssetkey(keyblk); for(i=0;i<48;i++) E[i] = e[i]; enblknot(blk,crp); blkencrypt(blk,1); /* backward dir */ return(deblkclr(blk)); } static void enblkclr(blk,str) /* ignores top bit of chars in string str */ char *blk,*str; { register int i,j; char c; for(i=0;i<70;i++)blk[i] = 0; for(i=0; (c= *str) && i<64; str++){ for(j=0; j<7; j++, i++) blk[i] = (c>>(6-j)) & 01; i++; } } static char *deblkclr(blk) char *blk; { register int i,j; char c; static char iobuf[30]; for(i=0; i<10; i++){ c = 0; for(j=0; j<7; j++){ c <<= 1; c |= blk[8*i+j]; } iobuf[i] = c; } iobuf[i] = 0; return(iobuf); } static void enblknot(blk,crp) char *blk; char *crp; { register int i,j; char c; for(i=0;i<70;i++)blk[i] = 0; for(i=0; (c= *crp) && i<64; crp++){ if(c>'Z') c -= 6; if(c>'9') c -= 7; c -= '.'; for(j=0; j<6; j++, i++) blk[i] = (c>>(5-j)) & 01; } } #if 0 static char *deblknot(blk) char *blk; { register int i,j; char c; static char iobuf[30]; for(i=0; i<11; i++){ c = 0; for(j=0; j<6; j++){ c <<= 1; c |= blk[6*i+j]; } c += '.'; if(c > '9')c += 7; if(c > 'Z')c += 6; iobuf[i] = c; } iobuf[i] = 0; return(iobuf); } #endif /* * This program implements the * Proposed Federal Information Processing * Data Encryption Standard. * See Federal Register, March 17, 1975 (40FR12134) */ /* * Initial permutation, */ static char IP[] = { 58,50,42,34,26,18,10, 2, 60,52,44,36,28,20,12, 4, 62,54,46,38,30,22,14, 6, 64,56,48,40,32,24,16, 8, 57,49,41,33,25,17, 9, 1, 59,51,43,35,27,19,11, 3, 61,53,45,37,29,21,13, 5, 63,55,47,39,31,23,15, 7, }; /* * Final permutation, FP = IP^(-1) */ static char FP[] = { 40, 8,48,16,56,24,64,32, 39, 7,47,15,55,23,63,31, 38, 6,46,14,54,22,62,30, 37, 5,45,13,53,21,61,29, 36, 4,44,12,52,20,60,28, 35, 3,43,11,51,19,59,27, 34, 2,42,10,50,18,58,26, 33, 1,41, 9,49,17,57,25, }; /* * Permuted-choice 1 from the key bits * to yield C and D. * Note that bits 8,16... are left out: * They are intended for a parity check. */ static char PC1_C[] = { 57,49,41,33,25,17, 9, 1,58,50,42,34,26,18, 10, 2,59,51,43,35,27, 19,11, 3,60,52,44,36, }; static char PC1_D[] = { 63,55,47,39,31,23,15, 7,62,54,46,38,30,22, 14, 6,61,53,45,37,29, 21,13, 5,28,20,12, 4, }; /* * Sequence of shifts used for the key schedule. */ static char shifts[] = { 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1, }; /* * Permuted-choice 2, to pick out the bits from * the CD array that generate the key schedule. */ static char PC2_C[] = { 14,17,11,24, 1, 5, 3,28,15, 6,21,10, 23,19,12, 4,26, 8, 16, 7,27,20,13, 2, }; static char PC2_D[] = { 41,52,31,37,47,55, 30,40,51,45,33,48, 44,49,39,56,34,53, 46,42,50,36,29,32, }; /* * The C and D arrays used to calculate the key schedule. */ static char C[28]; static char D[28]; /* * The key schedule. * Generated from the key. */ static char KS[16][48]; /* * Set up the key schedule from the key. */ static void nbssetkey(key) char *key; { register i, j, k; int t; /* * First, generate C and D by permuting * the key. The low order bit of each * 8-bit char is not used, so C and D are only 28 * bits apiece. */ for (i=0; i<28; i++) { C[i] = key[PC1_C[i]-1]; D[i] = key[PC1_D[i]-1]; } /* * To generate Ki, rotate C and D according * to schedule and pick up a permutation * using PC2. */ for (i=0; i<16; i++) { /* * rotate. */ for (k=0; k>3)&01; f[t+1] = (k>>2)&01; f[t+2] = (k>>1)&01; f[t+3] = (k>>0)&01; } /* * The new R is L ^ f(R, K). * The f here has to be permuted first, though. */ for (j=0; j<32; j++) R[j] = L[j] ^ f[P[j]-1]; /* * Finally, the new L (the original R) * is copied back. */ for (j=0; j<32; j++) L[j] = tempL[j]; } /* * The output L and R are reversed. */ for (j=0; j<32; j++) { t = L[j]; L[j] = R[j]; R[j] = t; } /* * The final output * gets the inverse permutation of the very original. */ for (j=0; j<64; j++) block[j] = L[FP[j]-1]; } /* getutmp() return a pointer to the system utmp structure associated with terminal sttyname, e.g. "/dev/tty3" Is version independent-- will work on v6 systems return NULL if error */ #ifndef __EMX__ static struct utmp *getutmp(char *sttyname) { static struct utmp utmpstr; FILE *fdutmp; if(sttyname == NULL || sttyname[0] == 0)return(NULL); fdutmp = fopen(_PATH_UTMP,"r"); if(fdutmp == NULL)return(NULL); while(fread(&utmpstr,1,sizeof utmpstr,fdutmp) == sizeof utmpstr) if(strcmp(utmpstr.ut_line,sttyname+5) == 0){ fclose(fdutmp); return(&utmpstr); } fclose(fdutmp); return(NULL); } #endif static void sreverse(sto, sfrom) register char *sto, *sfrom; { register int i; i = strlen(sfrom); while (i >= 0) *sto++ = sfrom[i--]; } static char *mkenvkey(char mch) { #ifndef __EMX__ static char skey[40]; register struct utmp *putmp; char stemp[40], stemp1[40], sttyname[30]; register char *sk,*p; if (isatty(2)) strcpy(sttyname,ttyname(2)); else if (isatty(0)) strcpy(sttyname,ttyname(0)); else if (isatty(1)) strcpy(sttyname,ttyname(1)); else #endif return (NULL); #ifndef __EMX__ putmp = getutmp(sttyname); if (putmp == NULL) return (NULL); sk = skey; p = putmp->ut_line; while (*p) *sk++ = *p++; *sk++ = mch; (void)sprintf(stemp, "%ld", putmp->ut_time); sreverse(stemp1, stemp); p = stemp1; while (*p) *sk++ = *p++; *sk = 0; return (skey); #endif } #if 0 static void mkpwunclear(spasswd,mch,sencpasswd) char *spasswd, mch, *sencpasswd; { register char *skey; if (spasswd[0] == 0) { sencpasswd[0] = 0; return; } skey = mkenvkey(mch); if (skey == NULL) { fprintf(stderr, "Can't make key\n"); exit(1); } nbsencrypt(spasswd, skey, sencpasswd); } #endif static void mkpwclear(sencpasswd,mch,spasswd) char *spasswd, mch, *sencpasswd; { register char *skey; if (sencpasswd[0] == 0) { spasswd[0] = 0; return; } skey = mkenvkey(mch); if (skey == NULL) { fprintf(stderr, "Can't make key\n"); exit(1); } nbsdecrypt(sencpasswd, skey, spasswd); } ./pvm3/src/OS2/src/stdlog.c0100644007401100000360000000047306401367014014526 0ustar kohlgopher#include #include void stdlog(char *fmt,...) /*======================*/ { FILE *F; char buf[4086]=""; va_list argptr; va_start(argptr, fmt); vsprintf(buf, fmt, argptr); va_end(argptr); F=fopen("c:/tmp/log.pvm","at"); if(F){ fprintf(F,buf); fclose(F); } } ./pvm3/src/OS2/src/sthoster.c0100644007401100000360000000444206401367015015106 0ustar kohlgopher#include #include #include #include #include #include #include #include #include #include #include "../../pmsg.h" #include "../../task.h" #include "../../pvmalloc.h" extern int hostertid; /* from pvmd.c */ extern int pvmmytid; /* from pvmd.c */ static int hosterforkexec(tid,name, tpp) int tid; /* tid given by hosterexectask */ char *name; /* filename */ struct task **tpp; /* return task context */ { int pid=-1; /* task pid */ char *argv[2]; struct task *tp; /* new task context */ char *expected_pid; char buf[32]; char *myenv[100]; char **p, **q; struct stat sb; extern int *ptr_nfp; /* XXX fix this */ if (stat(name, &sb) == -1) return PvmNoFile; tp = task_new(tid); p = myenv; q = environ; while (*q) { *p++ = *q++; } /* copy all the environment for socket stuff and more */ expected_pid=malloc(20 * sizeof(char)); sprintf(expected_pid, "PVMEPID=%d", *ptr_nfp); *p++ = expected_pid; *p=0; pvmputenv(expected_pid); argv[0]=name; argv[1]=0; pid = spawnve(P_NOWAIT,name,argv,myenv); if (pid == -1) { pvmlogperror("forkexec_hoster() _spawnve"); /* task_free(&tp); */ pvmbailout(0); return PvmOutOfRes; } task_setpid(tp,*ptr_nfp); *ptr_nfp=*ptr_nfp + 1; tp->t_flag |= TF_FORKD; tp->t_a_out = STRALLOC(name); *tpp = tp; return 0; } static int hostexectasker(file, tid) char *file; int tid; { int tids = 0; /* tid from hosterforkexec */ struct pmsg *rmp; struct task *tp = 0; int err = 0; /* error code from forkexec */ rmp = mesg_new(0); rmp->m_dst = pvmmytid; rmp->m_src = pvmmytid; rmp->m_tag = DM_EXECACK; if (err = hosterforkexec(tid,file, &tp)) { tids = err; } else { tp->t_ptid = 0; tp->t_outtid = 0; tp->t_trctid = 0; tp->t_sched = 0; tids = tp->t_tid; } pkint(rmp, 1); pkint(rmp, tids); sendmessage(rmp); return err; } /* start_hoster() * forkexec the hoster process which * will start other pvmd's. * acts like pvmd' ***/ int start_hoster(int reserved_tid) { char hosterpath[128]; strcpy(hosterpath,(char*)pvmgetroot()); strcat(hosterpath,"/bin/OS2/hoster.exe"); if (hostexectasker(hosterpath,reserved_tid)) { return -1; } return 0; } ./pvm3/src/PGON/0042755007401100000360000000000010117676455012453 5ustar kohlgopher./pvm3/src/PGON/Makefile0100644007401100000360000000061206604770017014100 0ustar kohlgopher# # $Id: Makefile,v 1.5 1998/10/01 21:11:43 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/src PVM_ARCH = PGON CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) all: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk all-mpp install: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install-mpp clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean ./pvm3/src/PGON/pvmdmimd.c0100644007401100000360000007002607435300200014411 0ustar kohlgopher static char rcsid[] = "$Id: pvmdmimd.c,v 1.10 2002/02/21 23:19:28 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmdmimd.c * * MPP interface. * * void mpp_init(int argc, char **argv): * Initialization. Create a table to keep track of active nodes. * argc, argv: passed from main. * * int mpp_load( struct waitc_spawn *wxp ) * * Load executable onto nodes; create new entries in task table, * encode node number and process type into task IDs, etc. * * Construction of Task ID: * * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 * +-+-+-----------------------+-+-----+--------------------------+ * |s|g| host index |n| prt | node # (16384) | * +-+-+-----------------------+-+-----+--------------------------+ * * The "n" bit is set for node task but clear for host task. * * flags: exec options; * name: executable to be loaded; * argv: command line argument for executable * count: number of tasks to be created; * tids: array to store new task IDs; * ptid: parent task ID. * * mpp_new(int count, int ptid): * Allocate a set of nodes. (called by mpp_load()) * count: number of nodes; ptid: parent task ID. * * int mpp_output(): * Send all pending packets to nodes via native send. Node number * and process type are extracted from task ID. * * int mpp_mcast(int src, struct pkt pp, int tids[], int ntask): * Global send. * src: source task ID; * pp: packet; * tids: list of destination task IDs; * ntask: how many. * * int mpp_probe(): * Probe for pending packets from nodes (non-blocking). Returns * 1 if packets are dectected, otherwise 0. * * void mpp_input(): * Receive pending packets (from nodes) via native recv. * * struct task *mpp_find(int pid): * Find a task in task table by its Unix pid. * * void mpp_free(struct task *tp): * Remove node/process-type from active list. * tp: task pointer. * */ /* * * $Log: pvmdmimd.c,v $ * Revision 1.10 2002/02/21 23:19:28 pvmsrc * Added new (not to be documented!) PVM_MAX_TASKS env var support. * - for Mahir Lokvancic . * - forcefully limits the number of tasks that can attach to a * pvmd, required on Solaris in rare circumstances when hard * FD_SETSIZE limit is reached, and all hell breaks loose... * - check return for task_new() call, can now produce NULL ptr, * indicating PvmOutOfRes... * (Spanker=kohl) * * Revision 1.9 2000/02/17 21:10:31 pvmsrc * Cleaned up comments... mpp_load() args... * (Spanker=kohl) * * Revision 1.8 1999/07/08 19:00:27 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.7 1997/07/09 13:54:32 pvmsrc * Fixed Author Header. * * Revision 1.6 1997/06/02 13:49:06 pvmsrc * Moved #include waitc.h below #include host.h. * * Revision 1.5 1997/05/05 20:07:48 pvmsrc * Fix so that output is collected properly. One bug remains: * tasks can exit before all of the output is collected. Hmm. * * Revision 1.4 1997/04/29 20:30:27 pvmsrc * Use new call sequences defined in mppmsg.h * Use the asynchronous send list management functions. * * Revision 1.3 1997/03/06 21:19:42 pvmsrc * Wholesale changes to this code. Tried for simplification. * still needs work. * * Revision 1.2 1997/01/28 19:30:31 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:13:45 pvmsrc * Initial revision * * Revision 1.12 1995/11/02 15:59:01 manchek * fixed so spawned tasks inherit pvmd environment plus parent task env * * Revision 1.11 1995/07/28 20:30:38 manchek * pvmtxt should have been etext * * Revision 1.10 1995/07/25 17:40:26 manchek * mpp_output returns int * * Revision 1.9 1995/07/24 20:03:15 manchek * message header no longer part of packet data, goes in pkt struct. * drivers must strip and reconstitute headers * * Revision 1.8 1995/06/16 16:16:06 manchek * mpp_load passes trace and output sink to task * * Revision 1.7 1995/06/12 16:03:20 manchek * added PGON partition size to pvminfo array * * Revision 1.6 1995/05/30 17:21:41 manchek * Handle absolute path name properly in mpp_load() (changes from forkexec). * mpp_free() takes struct task instead of tid. * Declare partsize static. * Fixed bug in node allocation in mpp_new(). * mpp_new() opens pipe to collect stdout * * Revision 1.5 1995/02/01 20:51:05 manchek * added nenv and envp args to mpp_load * * Sat Dec 3 14:54:20 EST 1994 * copy new code that handles absolute filename to mpp_load() * from forkexec() * * Revision 1.4 1994/11/07 21:30:45 manchek * Modify mpp_output() and mpp_mcast() to send a null packet to alert precv(). * Modify mpp_input() to handle DataInPlace properly. * mpp_new() should return PvmOutOfRes when it runs out of nodes. * Fix a bug in the way ptype is computed in mpp_mcast() * * Revision 1.3 1994/06/03 20:54:52 manchek * version 3.3.0 * * Revision 1.2 1993/12/20 15:39:49 manchek * patch 6 from wcj * * Revision 1.1 1993/08/30 23:36:09 manchek * Initial revision * * Jul 12 23:57:07 EDT 1993 * deleted loclinput(), and merged loclinpkt() into pvmd.c */ #include #include #include #include #include #include #include #include #ifdef SYSVSTR #include #define CINDEX(s,c) strchr(s,c) #else #include #define CINDEX(s,c) index(s,c) #endif #if defined(IMA_PGON) #include #endif #if defined(IMA_PGONPUMA) #include #endif #include #include #include "global.h" #include "pvmalloc.h" #include "host.h" #include "waitc.h" #include "pkt.h" #include "task.h" #include "listmac.h" #include "pvmdmp.h" #include "pvmmimd.h" #include "bfunc.h" #include "lmsg.h" #include "mppchunk.h" #include "mppmsg.h" #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif #if defined(IMA_PGONPUMA) #include #endif /* Global */ extern char **pvmcopyenv(); extern int pvmenvinsert(); extern int pvmfreeenv(); extern char **environ; extern int pvmdebmask; /* from pvmd.c */ extern char **epaths; /* from pvmd.c */ extern int myhostpart; /* from pvmd.c */ extern struct htab *hosts; /* from pvmd.c */ extern int tidhmask; /* from pvmd.c */ extern int ourudpmtu; /* from pvmd.c */ int tidtmask = TIDPTYPE; /* mask for ptype field of tids */ int tidnmask = TIDNODE; /* mask for node field of tids */ #if defined(IMA_PGONPUMA) static short phystolmap[2048]; /* XXX HACK. match physical to logical node*/ #endif /* private */ static struct nodeset *busynodes; /* active nodes; ordered by proc type */ static char etext[512]; /* scratch for error log */ static int ptypemask; /* mask; we use these bits of ptype in tids */ static long isendmid = -1; /* msg ID returned by isend() */ static struct pkt *outpkt = 0; /* packet being sent */ static int partsize; /* size of partition */ static int taskstdout; /* stdout/stderr of pvmd and node tasks */ static int myndf = 0; /* obsolete. Fix this from pvmd.c */ /* information to handle multiple recv bufs */ static MPP_DIRECTI_PTR mpdirect = (MPP_DIRECTI_PTR) NULL; /* the receive buffers, themselves */ static MSG_INFO_PTR mprecvbufs = (MSG_INFO_PTR) NULL; /* need to keep track of packets that need to be written to tasks */ static struct pkt *mppopq = (struct pkt *) NULL; /* array of mids of outstanding messages to be sent to backend */ #define NMPPSBUFMIDS 32 #define MPPMIDFREE -1 #define MPPMIDALLOCED -2 static msgmid_t mppsendmids[NMPPSBUFMIDS]; static struct pkt *mppoutpkts[NMPPSBUFMIDS]; static int lastidx = 0; static int appid = -1; static int killing_appid = 0; void mpp_init(argc, argv) int *argc; char **argv; { int i; int cc; #if defined(IMA_PGON) if ((partsize = nx_initve((char *)0, 0, "", argc, argv)) < 0) { pvmlogperror("mpp_init() nx_initve\n"); pvmbailout(); } sprintf(etext, "using %d nodes\n", partsize); pvmlogerror(etext); #endif #if defined(IMA_PGONPUMA) if ( (cc = host_lib_init()) < 0) { pvmlogperror("mpp_init(): host_lib_int\n"); pvmbailout(); } for (i=0; i < (sizeof(phystolmap)/sizeof(short)); i++) phystolmap[i] = -1; #endif busynodes = TALLOC(1, struct nodeset, "nsets"); BZERO((char*)busynodes, sizeof(struct nodeset)); busynodes->n_link = busynodes; busynodes->n_rlink = busynodes; ptypemask = tidtmask >> (ffs(tidtmask) - 1); /* need a list of packets that have been sent */ mppopq = TALLOC(1, struct pkt , "mppopq"); mppopq->pk_link = mppopq; mppopq->pk_rlink = mppopq;; pvm_init_asynch_list( mppsendmids, (CHUNK_PTR *) mppoutpkts, NMPPSBUFMIDS); } /* * allocate a set of nodes; ptype is always 0, so all tasks can exchange * messages directly, bypassing pvmd * * Node sets are allocated in blocks. When count processes are needed, * There must be a contiguous range of free nodes of size count */ struct nodeset * mpp_new(count, ptid) int count; /* number of nodes requested */ int ptid; /* parent's tid */ { static int first = 1; int i; int last = -1; int pfd[2]; /* pipe to read stdout */ long ptype = busynodes->n_ptype; struct nodeset *sp, *newp; ptype = 0; #if defined(IMA_PGONPUMA) /* XXX Only run a single PUMA partition for now */ if (appid != -1) { pvmlogerror("mpp_new() only one partition allowed, sorry\n"); return (struct nodeset *) 0; } partsize = count; #endif if (first) /* take care of task input/output */ { if (pipe(pfd) != -1) /* pfd[0] is a read, pfd[1] is a write */ { dup2(pfd[1], 1); /* send standard output write end of pipe */ dup2(1, 2); /* and stderr to write end of pipe */ taskstdout = pfd[0]; wrk_fds_add(taskstdout, 1); } else { pvmlogperror("mpp_new() pipe"); } first = 0; } if (!(newp = TALLOC(1, struct nodeset, "nsets"))) { pvmlogerror("nodes_new() can't get memory\n"); pvmbailout(0); } BZERO((char*)newp, sizeof(struct nodeset)); newp->n_size = count; /* this loop is bypassed on the first mpp_new */ for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link) { if (sp->n_ptype == ptype) { if (sp->n_first - last > count) goto done; else { last = sp->n_first + sp->n_size - 1; if (sp->n_link == busynodes && partsize - last > count) goto done; } } else if (sp->n_ptype > ptype) { if (partsize - last > count) goto done; else { ptype = sp->n_ptype; /* go to the next layer */ last = -1; } } } /* end the for loop */ if (partsize - last <= count) { pvmlogerror("mpp_new() not enough nodes in partition\n"); PVM_FREE(newp); return (struct nodeset *) 0; } done: if (pvmdebmask & PDMNODE) { sprintf(etext, "mpp_new() %d nodes %d ... ptype=%d ptid=%x\n", count, last+1, ptype, ptid); pvmlogerror(etext); } newp->n_first = last + 1; newp->n_ptype = ptype; newp->n_alive = count; newp->n_ptid = ptid; LISTPUTAFTER(sp, newp, n_link, n_rlink); return newp; } /* remove nodes/ptype from active list */ void mpp_free(tp) struct task *tp; { struct nodeset *sp; int i; int node; int ptype; int tid = tp->t_tid; if (!TIDISNODE(tid)) return; node = tid & tidnmask; ptype = TIDTOTYPE(tid); tp->t_out = -1; for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link) { if ((sp->n_ptype & ptypemask) == ptype && node >= sp->n_first && node - sp->n_first < sp->n_size) { if (pvmdebmask & PDMNODE) { sprintf(etext, "mpp_free() t%x type=%ld alive=%d\n", tid, sp->n_ptype, sp->n_alive); pvmlogerror(etext); } if (--sp->n_alive == 0) { LISTDELETE(sp, n_link, n_rlink); PVM_FREE(sp); #if defined(IMA_PGONPUMA) if (pvmdebmask & PDMNODE) { sprintf(etext, "mpp_free() freeing %d recv bufs \n", NRBUFS); pvmlogerror(etext); } for (i=0; i < NRBUFS; i++) { pk_free(mprecvbufs->rpkt); mprecvbufs++; } mprecvbufs = (MSG_INFO_PTR) NULL; if (pvmdebmask & PDMNODE) { sprintf(etext, "mpp_free() mprecvbufs is %x \n", mprecvbufs); pvmlogerror(etext); } for (i=0; i < partsize; i++) { if (mpdirect->ordering) PVM_FREE(mpdirect->ordering); PVM_FREE(mpdirect); mpdirect ++; } mpdirect = (MPP_DIRECTI_PTR) NULL; partsize = -1; if (!killing_appid) kill_app(appid); disc_app(appid); appid = -1; killing_appid = 0; #endif } return; } } sprintf(etext, "mpp_free() t%x not active\n", tid); pvmlogerror(etext); return; } /* load executable onto the given set of nodes */ int mpp_load( wxp ) struct waitc_spawn *wxp; { int flags; /* exec options */ char *name; /* executable */ char **argv; /* arg list (argv[-1] must be there) */ int count; /* how many */ int *tids; /* array to store new tids */ int ptid; /* parent task ID */ int nenv; /* length of environment */ char **envp; /* environment strings */ int outtid; /* output tid */ int outcod; /* output code */ int trctid; /* tid for trace messages */ int trccod; /* code to use on trace messages */ char **ep, **eplist; static char *nullep[] = { "", 0 }; char path[MAXPATHLEN]; char **cenv; int i, cc; int err = 0; static int first = 1; int j; int cnode; int cpid; int pvminfo[SIZEHINFO]; /* proto, myset, parent tid, frag size, NDF */ int ptypepart; int *pids = 0; /* array of OSF/1 process IDs */ int *nodes = 0; int nnodes; /* number of nodes to needed */ msgmid_t mid; info_t minfo[MPPINFOSIZE]; struct nodeset *sp; struct stat sb; struct task *tp; MPP_DIRECTI_PTR tdirect; MSGFUNC_PTR mfunc; /* -- initialize some variables from the struct waitc_spawn struct -- */ name = wxp->w_argv[0]; argv = wxp->w_argv; count = wxp->w_veclen; tids = wxp->w_vec; ptid = wxp->w_ptid; nenv = wxp->w_nenv; envp = wxp->w_env; mfunc = pvm_hostmsgfunc(); eplist = CINDEX(name, '/') ? nullep : epaths; /* -- look for the executable name in the executable path (ep) -- */ for (ep = eplist; *ep; ep++) { strcpy(path, *ep); /* search for file */ if (path[0]) (void)strcat(path, "/"); strncat(path, name, sizeof(path) - strlen(path) - 1); if (stat(path, &sb) == -1 || ((sb.st_mode & S_IFMT) != S_IFREG) || !(sb.st_mode & S_IEXEC)) { if (pvmdebmask & PDMTASK) { sprintf(etext, "mpp_load() stat failed <%s>\n", path); pvmlogerror(etext); } continue; /* try next path element */ } /* Here we have found an executable -- try to start it */ if ( !(pids = TALLOC(count, int, "pids")) || !(nodes = TALLOC(count, int, "nodes"))) { err = PvmNoMem; goto done; } if (!(sp = mpp_new(count, ptid))) { err = PvmOutOfRes; goto done; } for (j = 0; j < count; j++) nodes[j] = sp->n_first + j; /* copy the pvmd's environment, augment with what is passed to us */ cenv = pvmcopyenv(environ); while (nenv > 0) pvmenvinsert(&cenv, envp[--nenv]); /* Do the load, return how many were actually started */ err = nx_loadve((long *) nodes, (long) count, (long) sp->n_ptype, (long *)pids, path, argv, cenv); pvmfreeenv(cenv); /* free the copied environment */ if (err < count) /* loadve yacked ?? */ { sprintf(etext, "mpp_load() loaded only %d <%s>\n", err, path); pvmlogerror(etext); err = PvmDSysErr; goto done; } if (first) /* first time through, do some initialization */ { if ( _setptype(PVMDPTYPE) < 0) pvmlogperror("mpp_load() setptype to PVMDPTYPE"); first = 0; /* Set up the prealloced buffers */ mpdirect = new_vdirectstruct( partsize, NRBUFS, NSBUFS ); mprecvbufs = init_recv_list(NRBUFS, PMTDBASE, MAXFRAGSIZE, 0, MPPANY, mfunc); } /* configure the tasks /* alright, send some important information to the tasks that we just started */ ptypepart = ((sp->n_ptype & ptypemask) << (ffs(tidtmask) - 1)) | TIDONNODE; pvminfo[0] = TDPROTOCOL; pvminfo[1] = myhostpart + ptypepart; pvminfo[2] = ptid; pvminfo[3] = MAXFRAGSIZE; pvminfo[4] = myndf; sprintf(etext, "partsize is %d\n",partsize); pvmlogerror(etext); pvminfo[5] = partsize; pvminfo[6] = wxp->w_outtid; pvminfo[7] = wxp->w_outtag; pvminfo[8] = wxp->w_outctx; pvminfo[9] = wxp->w_trctid; pvminfo[10] = wxp->w_trctag; pvminfo[11] = wxp->w_trcctx; if (pvmdebmask & PDMTASK) { sprintf(etext, "mpp_load() %d type=%ld ptid=%x pid%ld... t%x...\n", count, sp->n_ptype, ptid, pids[0], myhostpart + ptypepart + sp->n_first); pvmlogerror(etext); } pvmlogerror("Starting configuration Message send Loop\n"); for (i = 0; i < count; i ++ ) { cnode = nodes[i]; if ( (*mfunc->imsgsend)(appid, PMTCONF, (char *) pvminfo, sizeof(pvminfo), cnode, PVMDPTYPE, &mid) < 0) { pvmlogperror("mpp_load() configuration message"); err = PvmDSysErr; goto done; } while (! ((*mfunc->msgdone)(appid, &mid, minfo))); } pvmlogerror("Finished Message send Loop\n"); /* create new task structs */ for (j = 0; j < count; j++) { if (pids[j] > 0) { if ((tp = task_new(myhostpart + ptypepart + sp->n_first + j)) == NULL) { err = PvmOutOfRes; goto done; } task_setpid(tp, pids[j]); tp->t_a_out = STRALLOC(name); tp->t_ptid = ptid; tp->t_flag |= TF_CONN; /* no need for the authorization */ tp->t_out = taskstdout; tp->t_outtid = wxp->w_outtid; pvmlogprintf("setting output context of %x to %x\n", tp->t_tid, tp->t_outtid); tp->t_outctx = wxp->w_outctx; tp->t_outtag = wxp->w_outtag; tp->t_trctid = wxp->w_trctid; tp->t_trcctx = wxp->w_trcctx; tp->t_trctag = wxp->w_trctag; tids[j] = tp->t_tid; /* initialize the sequence numbers for this task */ fill_directstruct (mpdirect + nodes[j], NSBUFS, tp->t_tid, pids[j], PMTDBASE, 0, appid); init_chunkostruct( (mpdirect + nodes[j])->ordering, NRBUFS); } else tids[j] = PvmDSysErr; } if (pids) PVM_FREE(pids); if (nodes) PVM_FREE(nodes); return 0; } /* here, only if there is an error in the way things were spawned */ if (pvmdebmask & PDMTASK) { sprintf(etext, "mpp_load() didn't find <%s>\n", name); pvmlogerror(etext); } err = PvmNoFile; done: for (j = 0; j < count; j++) tids[j] = err; if (pids) PVM_FREE(pids); return err; } /* input from node tasks */ int mpp_input() { static int cbuf = 0; struct pkt *pp = 0; int buf; /* buffer we are working on */ int mxbufs = NRBUFS; /* maximum number of buffers we will proc on read */ int npkts = 0; int tsrc, src; int tag; int pid = 0; int mid; MPP_DIRECTI_PTR tcon; static CHUNK_PTR readyList = (CHUNK_PTR) NULL; struct pkt *hdr; if ( mprecvbufs == (MSG_INFO_PTR) NULL ) { /* we haven't alloc'ed any buffers. No tasks loaded */ return npkts; } for (buf = 0; buf < mxbufs; buf++) /* limit #of packets to read */ { if (pp = (struct pkt *) pvm_chunkReady(mprecvbufs, mxbufs, pvm_hostmsgfunc(), mpdirect, partsize, &cbuf, &readyList) ) { #if defined(IMA_PGONPUMA) src = extract_lnid(src); #endif npkts ++; /* Step 2) extract header information from the packet */ pp->pk_dst = pvmget32(pp->pk_dat); pp->pk_src = pvmget32(pp->pk_dat + 4); pp->pk_flag = pvmget8(pp->pk_dat + 12); pp->pk_len -= TDFRAGHDR; pp->pk_dat += TDFRAGHDR; if (pp->pk_flag & FFSOM) { if (pp->pk_len < MSGHDRLEN) { sprintf(etext, "mpp_input() SOM pkt src t%x dst t%x short\n", pp->pk_src, pp->pk_dst); pvmlogerror(etext); pk_free(pp); return; } pp->pk_enc = pvmget32(pp->pk_dat); pp->pk_tag = pvmget32(pp->pk_dat + 4); pp->pk_ctx = pvmget32(pp->pk_dat + 8); pp->pk_wid = pvmget32(pp->pk_dat + 16); pp->pk_crc = pvmget32(pp->pk_dat + 20); pp->pk_len -= MSGHDRLEN; pp->pk_dat += MSGHDRLEN; } /* Step 3) Deliver packet to the PVM processing input stream */ loclinpkt((struct task *)0, pp); } else break; /* no packets to read */ } return npkts; } /* output to node tasks */ /* this is supposed to be like pkt_to_task from the pvmd. if pp is NULL then mpp_output should try to write any packets that are on the output queue */ int mpp_output(tp, pp) struct task *tp; struct pkt *pp; { char *cp; int len; long node; /* node number */ long ptype; /* process type */ struct nodeset *sp; int cc; int i; int idx1; int tag; struct pkt * delpkt; struct pkt * npkt; struct pkt * pp2; struct pkt * tstpkt; struct task *tp2; MPP_DIRECTI_PTR tdirect; MSGFUNC_PTR mfunc; mfunc = pvm_hostmsgfunc(); /* check if we have any packets to queue up and send */ if (tp && pp ) { node = tp->t_tid & tidnmask; ptype = (tp->t_tid & tidtmask) >> (ffs(tidtmask) - 1); #if defined(IMA_PGON) /* XXX ptype is not used for PUMA host-node communication */ for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link) { if ((sp->n_ptype & ptypemask) == ptype) { ptype = sp->n_ptype; break; } } if (sp == busynodes) { sprintf(etext, "mpp_output() pkt to t%x scrapped (no ptype %ld)\n", tp->t_tid, ptype); pvmlogerror(etext); pk_free(pp); goto done; } #endif cp = pp->pk_dat; len = pp->pk_len; if (pp->pk_flag & FFSOM) { cp -= MSGHDRLEN; len += MSGHDRLEN; if (cp < pp->pk_buf) { pvmlogerror("mpp_output() no headroom for message header\n"); pk_free(pp); goto done; } /* If we are not an MCA'ed pkt OR FFMCAWH (MCA write hdr) is set, then write the header */ if ( !(pp->pk_flag & FFMCA) || pp->pk_flag & FFMCAWH) { pvmput32(cp, pp->pk_enc); pvmput32(cp + 4, pp->pk_tag); pvmput32(cp + 8, pp->pk_ctx); pvmput32(cp + 16, pp->pk_wid); pvmput32(cp + 20, pp->pk_crc); if (pvmdebmask & PDMMCA) { sprintf(etext, "mpp_output wrt TDMSGHDR for %x\n", pp->pk_buf); pvmlogerror(etext); } } } if (pvmdebmask & PDMPACKET) { sprintf(etext, "mpp_output() src t%x dst t%x ff %x len %d ptype %d\n", pp->pk_src, pp->pk_dst, pp->pk_flag & (FFSOM|FFEOM), len, ptype); pvmlogerror(etext); } cp -= TDFRAGHDR; if (cp < pp->pk_buf) { pvmlogerror("mpp_output() no headroom for packet header\n"); pk_free(pp); goto done; } /* If we are not an MCA'ed pkt OR FFMCAWH (MCA write hdr) is set, then write the header */ if ( !(pp->pk_flag & FFMCA) || pp->pk_flag & FFMCAWH) { pvmput32(cp, pp->pk_dst); pvmput32(cp + 4, pp->pk_src); pvmput32(cp + 8, len); pvmput32(cp + 12, 0); pvmput8(cp + 12, pp->pk_flag & (FFSOM|FFEOM|FFMCA)); if (pvmdebmask & PDMMCA) { sprintf(etext, "mpp_output wrt TDFRAGHDR for %x\n", pp->pk_buf); pvmlogerror(etext); } } len += TDFRAGHDR; pp->pk_dat = cp; /* store where the data starts */ pp->pk_len = len; /* store the length of the buffer */ /* okay we've done everything to the packet, now put it on the output queue */ LISTPUTBEFORE(mppopq, pp, pk_link, pk_rlink); } tstpkt = mppopq -> pk_link; while (tstpkt != mppopq) { /* find free index */ if ( (idx1 = pvm_mpp_find_midx(mppsendmids, (CHUNK_PTR *) mppoutpkts, &lastidx, NMPPSBUFMIDS, mfunc) ) >= 0 ) { node = tstpkt->pk_dst & tidnmask; tdirect = mpdirect + node; ptype = (tstpkt->pk_dst & tidtmask) >> (ffs(tidtmask) - 1); tag = PMTDBASE + tdirect->sseq; if (++(tdirect->sseq) >= tdirect->nbufs) tdirect->sseq = 0; /* send the actual packet of information */ /* Hmm, should check here for long packets ... ?? */ /* XXX appid needs to be checked here for PUMA */ #if defined(IMA_PGONPUMA) ptype = extract_pid(appid, node); node = extract_nid(appid, node); #endif len = tstpkt->pk_len; if (len < 16) { sprintf(etext,"mpp_output() bogus len %d? (dst %x, ff %d)\n", len, tstpkt->pk_dst, tstpkt->pk_flag); pvmlogperror(etext); } (*mfunc->imsgsend)(appid, tag, tstpkt->pk_dat, len, node, ptype, &cc); pvm_assign_mid(mppsendmids, cc, idx1); if (cc < 0 ) { sprintf(etext,"mpp_output() can't send to t%x", tstpkt->pk_dst); pvmlogperror(etext); /* clear the output queue of packets for this tid in the output queue */ npkt = tstpkt->pk_link; while (npkt != tstpkt) { if ( npkt->pk_dst == tstpkt->pk_dst) { delpkt = npkt; npkt = npkt->pk_link; LISTDELETE(delpkt,pk_link, pk_rlink); pk_free(delpkt); } else npkt = npkt->pk_link; } /* mppopq queue is cleared */ delpkt = tstpkt; tstpkt = tstpkt->pk_link; LISTDELETE(delpkt, pk_link, pk_rlink); tp2 = task_find(delpkt->pk_dst); pk_free(delpkt); mpp_free(tp); tp2 = tp2->t_rlink; task_cleanup(tp2->t_link); task_free(tp2->t_link); } else /* isend was ok, remember the pkt, go onto the next one */ { pvm_assign_chunk((CHUNK_PTR *) mppoutpkts, (CHUNK_PTR) tstpkt, idx1); if (pvmdebmask & (PDMPACKET | PDMNODE)) { sprintf(etext, "mpp_output() from mppopq src t%x dst t%x len %d ptype %d flags %s\n", tstpkt->pk_src, tstpkt->pk_dst, len, ptype, pkt_flags(tstpkt->pk_flag)); pvmlogerror(etext); } /* remove the packet from the mppopq */ delpkt = tstpkt; tstpkt = tstpkt->pk_link; LISTDELETE(delpkt,pk_link,pk_rlink); } } else { if (pvmdebmask & PDMPACKET) { sprintf(etext, "mpp_output() no free send message ids.\n"); pvmlogerror(etext); } pvmlogerror("(*)\n"); return 0; } } done: if (tp && tp->t_flag & TF_CLOSE) { mpp_free(tp); tp = tp->t_rlink; /* XXX tm_exit() also calls task_cleanup(); should only be done once */ task_cleanup(tp->t_link); task_free(tp->t_link); } return 0; } /* probe for messages from node tasks */ int mpp_probe() { if (busynodes->n_link != busynodes) { return 1; /* don't probe messages -- can do this in one-shot at recv*/ } else /* task queue empty */ return 0; } #if defined(IMA_PGONPUMA) int extract_lnid(pnid) int pnid; { if (pnid >=0 && pnid < (sizeof(phystolmap)/sizeof(short))) return phystolmap[pnid]; else return -1; } void mpp_kill(tp, signum) struct task *tp; int signum; { struct nodeset *sp; int cid; if (TIDISNODE(tp->t_tid)) { if (signum == SIGKILL || signum == SIGTERM) { mpp_free(tp); /* XXX tm_exit() also calls task_cleanup(); should only be done once */ tp = tp->t_rlink; task_cleanup(tp->t_link); task_free(tp->t_link); } else { sprintf(etext,"mpp_kill() signal %d to node t%x ignored\n", signum, tp->t_tid); pvmlogerror(etext); } } else /* Not a node */ (void)kill(tp->t_pid, signum); } #endif /* ----------- find_direct ---------- */ /* this is a hack to find the correct ordering structure for a node. */ MPP_DIRECTI_PTR pvm_find_direct (dlist, nstruct, node) MPP_DIRECTI_PTR dlist; int nstruct; int node; { node = node & TIDNODE; /* make sure this is a node */ if ( dlist && dlist == mpdirect ) { return dlist + node; } } struct msgid * pvm_mpp_get_precvids() { return (struct msgid *) NULL; } ./pvm3/src/RS6KMP/0042755007401100000360000000000010117676455012672 5ustar kohlgopher./pvm3/src/RS6KMP/Makefile0100644007401100000360000000061206604770036014320 0ustar kohlgopher# # $Id: Makefile,v 1.4 1998/10/01 21:11:58 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/src PVM_ARCH = RS6KMP CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) all: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk all-shm install: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install-shm clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean ./pvm3/src/SGIMP64/0042755007401100000360000000000010117676455012741 5ustar kohlgopher./pvm3/src/SGIMP64/Makefile0100644007401100000360000000061306604770111014362 0ustar kohlgopher# # $Id: Makefile,v 1.4 1998/10/01 21:12:41 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/src PVM_ARCH = SGIMP64 CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) all: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk all-shm install: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install-shm clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean ./pvm3/src/SGIMP6/0042755007401100000360000000000010117676455012655 5ustar kohlgopher./pvm3/src/SGIMP6/Makefile0100644007401100000360000000061206604770073014304 0ustar kohlgopher# # $Id: Makefile,v 1.2 1998/10/01 21:12:27 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/src PVM_ARCH = SGIMP6 CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) all: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk all-shm install: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install-shm clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean ./pvm3/src/SGIMP/0042755007401100000360000000000010117676455012567 5ustar kohlgopher./pvm3/src/SGIMP/Makefile0100644007401100000360000000061106604770054014214 0ustar kohlgopher# # $Id: Makefile,v 1.4 1998/10/01 21:12:12 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/src PVM_ARCH = SGIMP CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) all: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk all-shm install: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install-shm clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean ./pvm3/src/SP2MPI/0042755007401100000360000000000010117676455012662 5ustar kohlgopher./pvm3/src/SP2MPI/Makefile0100644007401100000360000000061406604770127014313 0ustar kohlgopher# # $Id: Makefile,v 1.6 1998/10/01 21:12:55 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/src PVM_ARCH = SP2MPI CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) all: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk all-mpp install: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install-mpp clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean ./pvm3/src/SP2MPI/pvmdmimd.c0100644007401100000360000006016307435300215014627 0ustar kohlgopher static char rcsid[] = "$Id: pvmdmimd.c,v 1.14 2002/02/21 23:19:41 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmdmimd.c * * MPP interface. * * void mpp_init(int argc, char **argv): * Initialization. Create a table to keep track of active nodes. * argc, argv: passed from main. * * int mpp_load( struct waitc_spawn *wxp ) * * Load executable onto nodes; create new entries in task table, * encode node number and process type into task IDs, etc. * * Construction of Task ID: * * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 * +-+-+-----------------------+-+-----+--------------------------+ * |s|g| host index |n| prt | node # (16384) | * +-+-+-----------------------+-+-----+--------------------------+ * * The "n" bit is set for node task but clear for host task. * * flags: exec options; * name: executable to be loaded; * argv: command line argument for executable * count: number of tasks to be created; * tids: array to store new task IDs; * ptid: parent task ID. * * mpp_new(int count, int ptid): * Allocate a set of nodes. (called by mpp_load()) * count: number of nodes; ptid: parent task ID. * * int mpp_output(): * Send all pending packets to nodes via native send. Node number * and process type are extracted from task ID. * * int mpp_mcast(int src, struct pkt pp, int tids[], int ntask): * Global send. * src: source task ID; * pp: packet; * tids: list of destination task IDs; * ntask: how many. * * int mpp_probe(): * Probe for pending packets from nodes (non-blocking). Returns * 1 if packets are dectected, otherwise 0. * * void mpp_input(): * Receive pending packets (from nodes) via native recv. * * struct task *mpp_find(int pid): * Find a task in task table by its Unix pid. * * void mpp_free(struct task *tp): * Remove node/process-type from active list. * tp: task pointer. * * $Log: pvmdmimd.c,v $ * Revision 1.14 2002/02/21 23:19:41 pvmsrc * Added new (not to be documented!) PVM_MAX_TASKS env var support. * - for Mahir Lokvancic . * - forcefully limits the number of tasks that can attach to a * pvmd, required on Solaris in rare circumstances when hard * FD_SETSIZE limit is reached, and all hell breaks loose... * - check return for task_new() call, can now produce NULL ptr, * indicating PvmOutOfRes... * (Spanker=kohl) * * Revision 1.13 2001/09/25 21:19:28 pvmsrc * Minor TMPNAMFUN()/tmpnam() cleanup. * - moved macro def to pvm3.h, renamed PVMTNPMAN(). * - same for LEN_OF_TMP_NAM -> PVMTMPNAMLEN. * - mostly a huge waste of time, since *both* tmpnam() & mktemp() * produce the same "dangerous" warning message in Linux/gcc... * - damn. * (Spanker=kohl) * * Revision 1.12 2000/02/17 21:10:44 pvmsrc * Cleaned up comments... mpp_load() args... * (Spanker=kohl) * * Revision 1.11 1999/07/08 19:00:28 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.10 1997/10/01 15:36:06 pvmsrc * Removed unnecessary #include "fromlib.h" header. * - all consts now included in pvm3.h... * - header file eliminated. * (Spanker=kohl) * * Revision 1.9 1997/08/27 20:18:58 pvmsrc * Added blank args (0,0,0) in mpp_load() to make it call forkexec correctly. * Protocol needs to be changed to allow taskers to access IBM poe directly. * (Spanker=fagg) * * Revision 1.8 1997/07/09 13:54:58 pvmsrc * Fixed Author Header. * * Revision 1.7 1997/06/02 13:48:38 pvmsrc * Moved #include host.h above #include waitc.h. * Removed old mesg.h include... gone baby. * * Revision 1.6 1997/05/06 20:14:36 pvmsrc * Catch stdout/stderr correctly and redirect to outtid,tag,ctx * * Revision 1.5 1997/05/05 20:08:56 pvmsrc * Pass outctx and trcctx to mpp tasks. * * Revision 1.4 1997/05/02 13:52:50 pvmsrc * Start up MPI jobs correctly and get them configured. * * Revision 1.3 1997/03/25 15:52:21 pvmsrc * PVM patches from the base 3.3.10 to 3.3.11 versions where applicable. * Originals by Bob Manchek. Altered by Graham Fagg where required. * -IP enabled over switch * -RMPOOL env can be used instead of host list * * Revision 1.2 1997/01/28 19:30:57 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/09/23 23:15:09 pvmsrc * Initial revision * * Revision 1.3 1996/05/14 14:35:59 manchek * inc'd changes from chulho@kgn.ibm.com * * Revision 1.2 1995/07/25 17:41:27 manchek * mpp_output returns int * * Revision 1.1 1995/05/30 17:23:56 manchek * Initial revision * * Revision 1.3 1994/06/03 20:54:24 manchek * version 3.3.0 * * Revision 1.2 1993/12/20 15:39:47 manchek * patch 6 from wcj * * Revision 1.1 1993/08/30 23:35:09 manchek * Initial revision * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef SYSVSTR #include #define CINDEX(s,c) strchr(s,c) #else #include #define CINDEX(s,c) index(s,c) #endif #include #include #include "global.h" #include "host.h" #include "waitc.h" #include "pvmalloc.h" #include "pkt.h" #include "task.h" #include "listmac.h" #include "pvmdmp.h" #include "pvmmimd.h" #include "bfunc.h" #define MPICOMM "/usr/bin/poe" #define MPIOPT1 "-procs" #define MPIOPT2 "-euilib" #define MPIOPT3 "-hfile" #define MPIOPT4 "-rmpool" #define MPIOPARG2 "us" /* options: -procs # -euilib us */ #define MPIOPARG3 "ip" /* Enable IP over switch */ #define MPIARGC 7 /* number of command line arguments */ char *getenv(); /* Global */ extern int pvmdebmask; /* from pvmd.c */ extern char **epaths; /* from pvmd.c */ extern int myhostpart; /* from pvmd.c */ extern int tidhmask; /* from pvmd.c */ extern int ourudpmtu; /* from pvmd.c */ extern struct htab *hosts; /* from pvmd.c */ extern struct task *locltasks; /* from task.c */ int tidtmask = TIDPTYPE; /* mask for ptype field of tids */ int tidnmask = TIDNODE; /* mask for node field of tids */ /* private */ static int myndf = 0; static struct nodeset *busynodes; /* active nodes; ordered by proc type */ static char pvmtxt[512]; /* scratch for error log */ static int ptypemask; /* mask; we use these bits of ptype in tids */ static char nodefile[PVMTMPNAMLEN]; /* tmp node file */ static char **nodelist = 0; /* default poe node list */ static int partsize = 0; /* number of nodes allocated */ static int hostfileused = TRUE; /* Check if MP_HOSTFILE used */ static char defaultpool[64]="1"; /* default MP_POOL if not set */ static char mpiadapter[]={MPIOPARG2}; /* default User-Space */ static int sp2pvminfo[SIZEHINFO]; void mpp_init(argc, argv) int *argc; char **argv; { struct stat sb; char *hfn; /* host file name */ char nname[128]; /* node name */ FILE *hfp; int i; if ((hfn = getenv("LOADLBATCH"))) { if (strcmp(hfn, "yes") == 0) { if ((hfn = getenv("LOADL_PROCESSOR_LIST"))) { sprintf(pvmtxt, "LOADL_PROCESSOR_LIST=%s.\n",hfn); pvmlogperror(pvmtxt); hostfileused=FALSE; for (hfn;*hfn!='\0';hfn++) { if (*hfn == ' ') partsize++; } } else { sprintf(pvmtxt, "LOADL_PROCESSOR_LIST=%s - is not set\n",hfn); pvmlogperror(pvmtxt); exit(PvmHostFail); } } else { sprintf(pvmtxt,"LOADLBATCH=%s - not set to yes\n",hfn); pvmlogperror(pvmtxt); exit(PvmHostFail); } } else if ((hfn = getenv("MP_PROCS"))) { if ((partsize = atoi(hfn)) < 1) { sprintf(pvmtxt,"MP_PROCS=%d must be >= to 1\n",partsize); pvmlogperror(pvmtxt); exit(PvmHostFail); } hostfileused=FALSE; if ((hfn = getenv("MP_RMPOOL"))) { if (atoi(hfn) < 0) { sprintf(pvmtxt, "MP_RMPOOL=%d must be >= to 0\n",defaultpool); pvmlogperror(pvmtxt); exit(PvmHostFail); } strcpy(defaultpool,hfn); } } else if ((hfn = getenv("MP_HOSTFILE"))) { if (!(hfp = fopen(hfn, "r"))) { sprintf(pvmtxt, "sp2hostfile() fopen %s\n", hfn); pvmlogperror(pvmtxt); exit(PvmHostFail); } hostfileused=TRUE; while (fscanf(hfp, "%s", nname) != EOF) partsize++; nodelist = TALLOC(partsize, char*, "nname"); rewind(hfp); for (i = 0; i < partsize; i++) { fscanf(hfp, "%s", nname); nodelist[i] = STRALLOC(nname); } fclose(hfp); } else { pvmlogerror("mpp_init() no POE host file.\n"); pvmlogerror("mpp_init() MP_PROCS, MP_RMPOOL or MP_HOSTFILE must be set.\n"); exit(PvmHostFail); } if ((hfn = getenv("MP_EUILIB"))) { if (strcmp(hfn, "ip") == 0) { strcpy(mpiadapter,MPIOPARG3); /* IP over switch */ } } sprintf(pvmtxt, "%d nodes allocated.\n", partsize); pvmlogerror(pvmtxt); busynodes = TALLOC(1, struct nodeset, "nsets"); BZERO((char*)busynodes, sizeof(struct nodeset)); busynodes->n_link = busynodes; busynodes->n_rlink = busynodes; ptypemask = tidtmask >> (ffs(tidtmask) - 1); } /* create tmp poe host file from default */ char * sp2hostfile(first, count) int first; /* first node in the set */ int count; /* number of nodes requested */ { int i; FILE *tmpfp; if (partsize < count) { sprintf(pvmtxt, "sp2hostfile() need at least %d nodes\n", count+1); pvmlogperror(pvmtxt); return (char *)0; } (void)PVMTMPNAMFUN(nodefile); if (!(tmpfp = fopen(nodefile, "w"))) { sprintf(pvmtxt, "sp2hostfile() fopen %s", nodefile); pvmlogperror(pvmtxt); return (char *)0; } if (pvmdebmask & PDMNODE) { sprintf(pvmtxt, "sp2hostfile() POE host file: %s\n", nodefile); pvmlogerror(pvmtxt); } for (i = first; i < count + first; i++) fprintf(tmpfp, "%s\n", nodelist[i]); fclose(tmpfp); return nodefile; } /* * find a set of free nodes from nodelist; assign ptype sequentially, * only tasks spawned together get the same ptype */ struct nodeset * mpp_new(count, ptid) int count; /* number of nodes requested */ int ptid; /* parent's tid */ { struct nodeset *sp, *newp, *sp2; int last = -1; int ptype = 0; if (!(newp = TALLOC(1, struct nodeset, "nsets"))) { pvmlogerror("mpp_new() can't get memory\n"); pvmbailout(0); } BZERO((char*)newp, sizeof(struct nodeset)); newp->n_size = count; for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link) { if (sp->n_first - last > count) break; last = sp->n_first + sp->n_size - 1; /* if (sp->n_link == busynodes && partsize - last > count) break; */ if (ptype <= sp->n_ptype) ptype = sp->n_ptype + 1; } if (sp == busynodes && partsize - last <= count) { pvmlogerror("mpp_new() not enough nodes in partition\n"); PVM_FREE(newp); return (struct nodeset *)0; } for (sp2 = busynodes->n_link; sp2 != busynodes; sp2 = sp2->n_link) if ((sp2->n_ptype & ptypemask) == (ptype & ptypemask)) break; if (sp2 != busynodes || ptype == NPARTITIONS) { for (ptype = 0; ptype < NPARTITIONS; ptype++) { for (sp2 = busynodes->n_link; sp2 != busynodes; sp2 = sp2->n_link) if ((sp2->n_ptype & ptypemask) == (ptype & ptypemask)) break; if (sp2 == busynodes) break; } if (ptype == NPARTITIONS) { pvmlogerror("mpp_new() out of ptypes: too many spawns\n"); return (struct nodeset *)0; } } done: if (pvmdebmask & PDMNODE) { sprintf(pvmtxt, "mpp_new() %d nodes %d ... ptype=%d ptid=%x\n", count, last+1, ptype, ptid); pvmlogerror(pvmtxt); } newp->n_first = last + 1; if (hostfileused) { if (!sp2hostfile(newp->n_first, count)) { PVM_FREE(newp); return (struct nodeset *)0; } } newp->n_ptype = ptype; newp->n_ptid = ptid; newp->n_alive = count - 1; LISTPUTBEFORE(sp, newp, n_link, n_rlink); return newp; } /* * remove node/ptype from active list; if tid is the last to go, shutdown * pvmhost's socket, but do not destroy the node set because pvmhost may * not exit immediately. To avoid a race condition, let mpp_output() * do the cleanup. */ void mpp_free(tp) struct task *tp; { struct nodeset *sp; int ptype; struct task *tp2; int tid = tp->t_tid; if (!TIDISNODE(tid)) return; ptype = TIDTOTYPE(tid); tp->t_txq = 0; /* don't free pvmhost's txq */ for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link) { if ((sp->n_ptype & ptypemask) == ptype) { if (pvmdebmask & PDMNODE) { sprintf(pvmtxt, "mpp_free() t%x type=%ld alive=%d\n", tid, sp->n_ptype, sp->n_alive); pvmlogerror(pvmtxt); } if (--sp->n_alive == 0) { if (tp2 = task_find(sp->n_ptid)) { tp2->t_flag |= TF_CLOSE; if (tp2->t_sock != -1) { /* wrk_fds_delete(tp2->t_sock, 3); (void)close(tp2->t_sock); tp2->t_sock = -1; */ shutdown(tp2->t_sock, 1); /* close stdout after pvmhost dies */ tp2->t_out = tp->t_out; } } /* LISTDELETE(sp, n_link, n_rlink); PVM_FREE(sp); */ } tp->t_out = -1; /* don't free shared stdout if alive > 0 */ return; } } sprintf(pvmtxt, "mpp_free() t%x not active\n", tid); pvmlogerror(pvmtxt); return; } /* load executable onto the given set of nodes */ int mpp_load( wxp ) struct waitc_spawn *wxp; { int flags = 0; /* exec options */ char *name; /* executable */ char **argv; /* arg list (argv[-1] must be there) */ int count; /* how many */ int *tids; /* array to store new tids */ int ptid; /* parent task ID */ int nenv; /* length of environment */ char **envp; /* environment strings */ int ptypepart; /* type field */ int j; struct task *tp; struct pkt *hosttxq; /* out-going queue of pvmhost */ int err = 0; struct nodeset *sp; char c[128]; /* buffer to store count, name.host */ char **ar = 0; int nargs; char **ep, **eplist; char path[MAXPATHLEN]; struct stat sb; char **av; int hostout; /* stdout of pvmhost */ struct hostd *hp = hosts->ht_hosts[hosts->ht_local]; int hostpid; /* Unix pid of pvmhost */ char htid[128]; /* buffer to store pvmhost tid */ char *p; static char *nullep[] = { "", 0 }; /* -- initialize some variables from the waitc_spawn struct -- */ name = wxp->w_argv[0]; argv = wxp->w_argv; count = wxp->w_veclen; tids = wxp->w_vec; ptid = wxp->w_ptid; nenv = wxp->w_nenv; envp = wxp->w_env; eplist = CINDEX(name, '/') ? nullep : epaths; for (ep = eplist; *ep; ep++) { /* search for file */ (void)strcpy(path, *ep); if (path[0]) (void)strcat(path, "/"); (void)strncat(path, name, sizeof(path) - strlen(path) - 1); if (stat(path, &sb) == -1 || ((sb.st_mode & S_IFMT) != S_IFREG) || !(sb.st_mode & S_IEXEC)) { if (pvmdebmask & PDMTASK) { sprintf(pvmtxt, "mpp_load() stat failed <%s>\n", path); pvmlogerror(pvmtxt); } continue; } if (!(sp = mpp_new(count+1, ptid))) { err = PvmOutOfRes; goto done; } ptypepart = (sp->n_ptype << (ffs(tidtmask) - 1)) | TIDONNODE; if (argv) for (nargs = 0; argv[nargs]; nargs++); else nargs = 0; /* ar[-1], poe, -procs, #, -euilib, us, -hfile fname */ nargs += MPIARGC + 1; av = TALLOC(nargs + 1, char*, "argv"); av++; /* reserve room for debugger */ BZERO((char*)av, nargs * sizeof(char*)); av[0] = MPICOMM; av[1] = path; av[--nargs] = 0; if (hostfileused) { av[--nargs] = nodefile; av[--nargs] = MPIOPT3; } else { av[--nargs] = defaultpool; av[--nargs] = MPIOPT4; } av[--nargs] = mpiadapter; av[--nargs] = MPIOPT2; sprintf(c, "%d", count+1); av[--nargs] = c; av[--nargs] = MPIOPT1; for (j = 2; j < nargs; j++) av[j] = argv[j - 1]; /* poe name argv -procs # -euilib us */ /* if ((sock = mksock()) == -1) { err = PvmSysErr; goto done; } */ if (flags & PvmTaskDebug) av++; /* pdbx name -procs # -euilib us */ /* if (err = forkexec(flags, av[0], av, 0, (char **)0, &tp)) */ if (err = forkexec(flags, av[0], av, 0, (char **)0, 0, 0, 0, &tp)) goto done; tp->t_ptid = ptid; PVM_FREE(tp->t_a_out); sprintf(c, "%s.host", name); tp->t_a_out = STRALLOC(c); sp->n_ptid = tp->t_tid; /* pvmhost's tid */ hosttxq = tp->t_txq; hostout = tp->t_out; hostpid = tp->t_pid; tp->t_out = -1; sprintf(htid, "PVMHTID=%d", tp->t_tid); p = STRALLOC(htid); pvmputenv(p); sp2pvminfo[0] = TDPROTOCOL; sp2pvminfo[1] = myhostpart + ptypepart; sp2pvminfo[2] = ptid; sp2pvminfo[3] = MAXFRAGSIZE; sp2pvminfo[4] = myndf; sp2pvminfo[5] = partsize; sp2pvminfo[6] = wxp->w_outtid; sp2pvminfo[7] = wxp->w_outtag; sp2pvminfo[8] = wxp->w_outctx; sp2pvminfo[9] = wxp->w_trctid; sp2pvminfo[10] = wxp->w_trctag; sp2pvminfo[11] = wxp->w_trcctx; /* if (sockconn(sock, tp, pvminfo) == -1) { err = PvmSysErr; task_free(tp); goto done; } */ /* XXX task may not be on same host; can't do auth with tmp file */ tp->t_flag |= TF_CONN; if (pvmdebmask & PDMTASK) { sprintf(pvmtxt, "mpp_load() %d type=%d ptid=%x t%x...\n", count, sp->n_ptype, ptid, myhostpart + ptypepart); pvmlogerror(pvmtxt); } /* create new task structs */ for (j = 0; j < count; j++) { if ((tp = task_new(myhostpart + ptypepart + j)) == NULL) { err = PvmOutOfRes; goto done; } tp->t_a_out = STRALLOC(name); tp->t_ptid = ptid; tp->t_flag |= TF_CONN; /* no need for the auth crap */ tids[j] = tp->t_tid; PVM_FREE(tp->t_txq); tp->t_txq = hosttxq; /* node tasks share pvmhost's txq */ tp->t_out = hostout; /* and stdout */ tp->t_pid = hostpid; /* pvm_kill should kill pvmhost */ tp->t_outtid = wxp->w_outtid; /* catch stdout/stderr */ tp->t_outtag = wxp->w_outtag; tp->t_outctx = wxp->w_outctx; } return 0; } if (pvmdebmask & PDMTASK) { sprintf(pvmtxt, "mpp_load() didn't find <%s>\n", name); pvmlogerror(pvmtxt); } err = PvmNoFile; done: for (j = 0; j < count; j++) tids[j] = err; return err; } #if 0 /* kill poe process */ void sp2kill(a_out, node) char *a_out; int node; { FILE *fp; int i; char nname[128]; /* node name */ char comm[512]; /* command to issue */ char *hfn; /* host file name */ struct stat sb; char *av[8]; /* for rsh args */ int ac; int pid = -1; /* pid of rsh */ node++; if ((hfn = getenv("MP_HOSTFILE")) || stat(hfn = "host.list", &sb) != -1) { if (fp = fopen(hfn, "r")) { for (i = 0; i < node; i++) fscanf(fp, "%s", nname); fclose(hfn); if ((pid = fork()) == -1) { pvmlogperror("sp2kill() fork"); return; } if (!pid) { ac = 0; av[ac++] = "/usr/bin/rsh"; av[ac++] = nname; av[ac++] = "poekill"; av[ac++] = a_out; av[ac++] = 0; for (i = getdtablesize(); --i > 2; ) (void)close(i); execvp(av[0], av); _exit(1); } } else pvmlogperror("sp2kill() fopen"); return; } pvmlogerror("sp2kill() no host file"); } #endif /*0*/ void mpp_kill(tp, signum) struct task *tp; int signum; { if (TIDISNODE(tp->t_tid)) { if (signum == SIGTERM || signum == SIGKILL) { /* sp2kill(tp->t_a_out, tp->t_tid & tidnmask); */ (void)kill(tp->t_pid, signum); mpp_free(tp); task_cleanup(tp); task_free(tp); } else { sprintf(pvmtxt,"mpp_kill() signal %d to node t%x ignored\n", signum, tp->t_tid); pvmlogerror(pvmtxt); } } else (void)kill(tp->t_pid, signum); } /* * Add pvmhost's socket to wfds if there are packets waiting to * be sent to a related node task. Node tasks have no sockets; * they share pvmhost's packet queue (txq). Pvmhost simply * forwards any packets it receives to the appropriate node. */ int mpp_output(dummy1, dummy2) struct task *dummy1; struct pkt *dummy2; { struct nodeset *sp, *sp2; struct task *tp; int ptype; for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link) if ((tp = task_find(sp->n_ptid))) { if (tp->t_txq->pk_link->pk_buf && tp->t_sock != -1) wrk_fds_add(tp->t_sock, 2); } else { if (sp->n_alive) { sprintf(pvmtxt, "mpp_output() pvmhost %d died!\n", sp->n_ptype); pvmlogerror(pvmtxt); /* clean up tasks it serves */ ptype = sp->n_ptype & ptypemask; for (tp = locltasks->t_link; tp != locltasks; tp = tp->t_link) if (TIDISNODE(tp->t_tid) && TIDTOTYPE(tp->t_tid) == ptype) { tp->t_txq = 0; tp = tp->t_rlink; task_cleanup(tp->t_link); task_free(tp->t_link); } } /* pvmhost has died, destroy the node set */ sp2 = sp; sp = sp->n_rlink; LISTDELETE(sp2, n_link, n_rlink); PVM_FREE(sp2); } return 0; } /* replace tm_connect and tm_conn2 */ int mpp_conn(tp, tp2) struct task *tp; struct task *tp2; { struct nodeset *sp; int pvminfo[SIZEHINFO]; /* host info */ int ptypepart; /* type field */ if (pvmdebmask & PDMNODE) { sprintf(pvmtxt, "mpp_conn() pvmhost %x", tp2->t_tid); pvmlogerror(pvmtxt); } tp2->t_sock = tp->t_sock; tp2->t_sad = tp->t_sad; tp2->t_salen = tp->t_salen; tp2->t_flag |= TF_CONN; tp->t_sock = -1; for (sp = busynodes->n_link; sp != busynodes; sp = sp->n_link) if (sp->n_ptid == tp2->t_tid) break; if (sp == busynodes) { pvmlogerror("mpp_conn() task is not pvmhost\n"); return -1; } ptypepart = (sp->n_ptype << (ffs(tidtmask) - 1)) | TIDONNODE; if (write(tp2->t_sock, sp2pvminfo, sizeof(sp2pvminfo)) != sizeof(sp2pvminfo)) { pvmlogperror("mpp_conn() write"); return -1; } return 0; } #if 0 /* * Create socket to talk to pvmhost. * Return socket descriptor if successful, -1 otherwise. */ int mksock() { struct hostd *hp = hosts->ht_hosts[hosts->ht_local]; struct sockaddr_in sin; char buf[128]; char *p; int cc; int sock; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { pvmlogperror("mksock() socket"); return -1; } sin = hp->hd_sad; if (bind(sock, (struct sockaddr*)&sin, sizeof(sin)) == -1) { pvmlogperror("mksock() bind"); (void)close(sock); return -1; } cc = sizeof(sin); if (getsockname(sock, (struct sockaddr*)&sin, &cc) == -1) { pvmlogperror("mksock() getsockname"); (void)close(sock); return -1; } if (listen(sock, 1) == -1) { pvmlogperror("mksock() listen"); (void)close(sock); return -1; } p = inadport_hex(&sin); sprintf(buf, "PVMSOCK=%s", p); p = STRALLOC(buf); pvmputenv(p); return sock; } /* * Wait for connect request from pvmhost and establish connection. * Return 0 if successful, -1 otherwise. * Close listening socket. */ int sockconn(sock, tp, hinfo) int sock; /* listening post */ struct task *tp; /* pvm host */ int hinfo[]; /* host info to pass along */ { int i; if ((tp->t_sock = accept(sock, (struct sockaddr*)&tp->t_sad, &tp->t_salen)) == -1) { pvmlogperror("sockconn() accept"); return -1; } else { if (pvmdebmask & (PDMPACKET|PDMTASK)) { sprintf(pvmtxt, "sockconn() accept from %s sock %d\n", inadport_decimal(&tp->t_sad), tp->t_sock); pvmlogerror(pvmtxt); } close(sock); #ifndef NOSOCKOPT i = 1; if (setsockopt(tp->t_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&i, sizeof(int)) == -1) pvmlogperror("sockconn() setsockopt"); #endif } if (write(tp->t_sock, hinfo, SIZEHINFO*sizeof(int)) != SIZEHINFO*sizeof(int)) { pvmlogperror("sockconn: write"); return -1; } if ((i = fcntl(tp->t_sock, F_GETFL, 0)) == -1) pvmlogperror("sockconn: fcntl"); else { i |= O_NDELAY; (void)fcntl(tp->t_sock, F_SETFL, i); } wrk_fds_add(tp->t_sock, 1); return 0; } #endif /*0*/ ./pvm3/src/SUNMP/0042755007401100000360000000000010117676455012612 5ustar kohlgopher./pvm3/src/SUNMP/Makefile0100644007401100000360000000061106604770145014240 0ustar kohlgopher# # $Id: Makefile,v 1.4 1998/10/01 21:13:09 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/src PVM_ARCH = SUNMP CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) all: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk all-shm install: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install-shm clean: $(MAKE) -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean ./pvm3/tracer/0042755007401100000360000000000010117676455012401 5ustar kohlgopher./pvm3/tracer/cygwin.mak0100644007401100000360000000337007240355113014355 0ustar kohlgopher#*****************************************************************************# # # makefile # for the PVM tracer # #*****************************************************************************# include $(PVM_ROOT_U)/conf/win32cygwin.def LIBS = $(PVM_ARCH)/libpvmtracer.a $(LIB) OBJS = $(PVM_ARCH)/cmd.o \ $(PVM_ARCH)/trcglob.o \ $(PVM_ARCH)/tracer.o LIBOBJS = $(PVM_ARCH)/trcmess.o \ $(PVM_ARCH)/trcfile.o \ $(PVM_ARCH)/trccompat.o \ $(PVM_ARCH)/trccompatglob.o \ $(PVM_ARCH)/trcutil.o \ $(PVM_ARCH)/trclib.o all: $(PVM_ARCH)/libpvmtracer.a $(PVM_ARCH)/tracer.exe $(PVM_ARCH)/libpvmtracer.a: $(LIBOBJS) ar -rs $(PVM_ARCH)/libpvmtracer.a $(LIBOBJS) $(PVM_ARCH)/tracer.exe: $(OBJS) $(PVM_ARCH)/libpvmtracer.a $(CC) -o $(PVM_ARCH)/tracer $(OBJS) $(LIBS) $(LINK_FLAGS) $(PVM_ARCH)/cmd.o: cmd.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/cmd.o cmd.c $(PVM_ARCH)/trcglob.o: trcglob.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/trcglob.o trcglob.c $(PVM_ARCH)/tracer.o: tracer.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/tracer.o tracer.c # LIB $(PVM_ARCH)/trcmess.o: trcmess.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/trcmess.o trcmess.c $(PVM_ARCH)/trcfile.o: trcfile.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/trcfile.o trcfile.c $(PVM_ARCH)/trccompat.o: trccompat.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/trccompat.o trccompat.c $(PVM_ARCH)/trccompatglob.o: trccompatglob.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/trccompatglob.o trccompatglob.c $(PVM_ARCH)/trcutil.o: trcutil.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/trcutil.o trcutil.c $(PVM_ARCH)/trclib.o: trclib.c $(CC) $(CFLAGS) $(CDEBUG) \ -o $(PVM_ARCH)/trclib.o trclib.c # Clean up everything but the .EXEs clean : -rm -f $(PVM_ARCH)/*.o ./pvm3/tracer/Makefile0100644007401100000360000000074406334376156014042 0ustar kohlgopher# # $Id: Makefile,v 4.3 1997/05/08 16:16:46 pvmsrc Exp $ # PVMDIR = $(PVM_ROOT) #CC = cc #CFLOPTS = -g PVMOPTS = CC=$(CC) CFLOPTS=$(CFLOPTS) PVMDIR=$(PVMDIR) default: local install: $(PVMDIR)/lib/aimk $(PVMOPTS) install @ ctags -w *.c *.h & local: $(PVMDIR)/lib/aimk $(PVMOPTS) local @ ctags -w *.c *.h & objs: $(PVMDIR)/lib/aimk $(PVMOPTS) objs again: $(PVMDIR)/lib/aimk $(PVMOPTS) again clean: $(PVMDIR)/lib/aimk clean veryclean: $(PVMDIR)/lib/aimk veryclean ./pvm3/tracer/Makefile.aimk0100644007401100000360000000723706604770164014763 0ustar kohlgopher# # $Id: Makefile.aimk,v 4.23 1998/10/01 21:13:24 pvmsrc Exp $ # # # Enforce Proper Shell Environment # SHELL = /bin/sh # # Version Compatibility Flags & Compiler Options # PVMVERSION = #PVMVERSION = -DUSE_PVM_33 CFLOPTS = -O #CFLOPTS = -g #CC = cc #CC = gcc CFLAGS = $(CFLOPTS) $(PVMVERSION) -DIMA_$(PVM_ARCH) $(ARCHCFLAGS) # # Source Directory # PVMDIR = ../.. TRCDIR = $(PVMDIR)/tracer SRCDIR = $(TRCDIR) PVMBDIR = $(PVMDIR)/bin PVMXDIR = $(PVMBDIR)/$(PVM_ARCH) PVMLDIR = $(PVMDIR)/lib/$(PVM_ARCH) # # Libraries # PVMLIBDIR = -L$(PVMDIR)/lib/$(PVM_ARCH) TRCLIBDIR = -L$(TRCDIR)/$(PVM_ARCH) LIBDIRS = $(PVMLIBDIR) $(TRCLIBDIR) SYSLIBS = $(ARCHLIB) LIBPREFIX = lib PVMLIB = pvm3 PVMLIBDEP = $(PVMLDIR)/$(LIBPREFIX)$(PVMLIB).a TRCLIB = pvmtrc LIBPVMTRC = $(LIBPREFIX)$(TRCLIB).a TRCLIBDEP = $(PVMLDIR)/$(LIBPVMTRC) LIBS = $(LIBDIRS) -l$(TRCLIB) -l$(PVMLIB) $(SYSLIBS) # # Include Directories # PVMINCL = -I$(PVMDIR)/include TRCINCL = -I$(TRCDIR) INCL = -I$(SRCDIR) $(PVMINCL) $(TRCINCL) # # Object Files # OBJS = tracer.o cmd.o trcglob.o TRCOBJS = trcmess.o trcfile.o trccompat.o trccompatglob.o \ trcutil.o trclib.o HEADERS = $(SRCDIR)/tracer.h $(SRCDIR)/trcglob.h \ $(TRCDIR)/trcdef.h $(TRCDIR)/trctype.h \ $(TRCDIR)/trcproto.h \ $(PVMDIR)/include/pvm3.h $(PVMDIR)/include/pvmtev.h TRCHEADERS = $(TRCDIR)/trclib.h $(TRCDIR)/trctype.h \ $(TRCDIR)/trcproto.h \ $(TRCDIR)/trccompat.h $(TRCDIR)/trccompatrev.h \ $(PVMDIR)/include/pvm3.h $(PVMDIR)/include/pvmtev.h PROGS = $(PVMXDIR)/tracer$(EXESFX) $(PVMXDIR)/trcsort$(EXESFX) # # Targets # default: local install: $(PVMXDIR) $(PVMLDIR) $(PROGS) $(PVMXDIR)/tracer$(EXESFX): tracer$(EXESFX) @ cp tracer$(EXESFX) $(PVMXDIR) $(PVMXDIR)/trcsort$(EXESFX): trcsort$(EXESFX) @ cp trcsort$(EXESFX) $(PVMXDIR) local: tracer$(EXESFX) trcsort$(EXESFX) tracer$(EXESFX): $(OBJS) $(TRCLIBDEP) $(PVMLIBDEP) $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) objs: $(OBJS) trcsort$(EXESFX): trcsort.o $(TRCLIBDEP) $(PVMLIBDEP) $(CC) $(CFLAGS) -o $@ trcsort.o $(LIBS) trcsort.o: $(SRCDIR)/trcsort.c $(CC) $(CFLAGS) -c $(INCL) $(SRCDIR)/trcsort.c $(TRCLIBDEP): $(LIBPVMTRC) @ cp $(LIBPVMTRC) $(PVMLDIR) $(LIBPVMTRC): $(TRCOBJS) $(PVMLDIR) $(AR) rcv $(LIBPVMTRC) $(TRCOBJS) @ case x$(HASRANLIB) in \ xt ) echo "ranlib $(LIBPVMTRC)"; ranlib $(LIBPVMTRC) ;; \ xf ) echo "No Ranlib Necessary." ;; esac $(PVMXDIR): - mkdir $(PVMBDIR) - mkdir $(PVMXDIR) $(PVMLDIR): - mkdir $(PVMLDIR) again: cd $(SRCDIR) ; touch *.c *.h ; $(MAKE) clean: - rm -f *.o veryclean: clean - rm -f tracer$(EXESFX) trcsort$(EXESFX) $(LIBPVMTRC) # # C Dependencies # tracer.o: $(SRCDIR)/tracer.c $(HEADERS) @ touch tracer.o $(CC) $(CFLAGS) -c $(INCL) $(SRCDIR)/tracer.c cmd.o: $(SRCDIR)/cmd.c $(HEADERS) @ touch cmd.o $(CC) $(CFLAGS) -c $(INCL) $(SRCDIR)/cmd.c trcglob.o: $(SRCDIR)/trcglob.c $(HEADERS) @ touch trcglob.o $(CC) $(CFLAGS) -c $(INCL) $(SRCDIR)/trcglob.c # # Library Objects # trcmess.o: $(TRCDIR)/trcmess.c $(TRCHEADERS) @ touch trcmess.o $(CC) $(CFLAGS) -c $(INCL) $(TRCDIR)/trcmess.c trcfile.o: $(TRCDIR)/trcfile.c $(TRCHEADERS) @ touch trcfile.o $(CC) $(CFLAGS) -c $(INCL) $(TRCDIR)/trcfile.c trccompat.o: $(TRCDIR)/trccompat.c $(TRCHEADERS) @ touch trccompat.o $(CC) $(CFLAGS) -c $(INCL) $(TRCDIR)/trccompat.c trccompatglob.o: $(TRCDIR)/trccompatglob.c $(TRCHEADERS) @ touch trccompatglob.o $(CC) $(CFLAGS) -c $(INCL) $(TRCDIR)/trccompatglob.c trcutil.o: $(TRCDIR)/trcutil.c $(TRCHEADERS) @ touch trcutil.o $(CC) $(CFLAGS) -c $(INCL) $(TRCDIR)/trcutil.c trclib.o: $(TRCDIR)/trclib.c $(TRCHEADERS) @ touch trclib.o $(CC) $(CFLAGS) -c $(INCL) $(TRCDIR)/trclib.c ./pvm3/tracer/Makefile.mak0100644007401100000360000000431706670012102014566 0ustar kohlgopher#*************************************************************# # # $Id: Makefile.mak,v 4.7 1999/03/05 17:28:34 pvmsrc Exp $ # # Nmake file for the PVM tracer # # PVM_ARCH = the official pvm-name of your processor # ARCHCFLAGS = special cc flags # # USER installation specific part -- to be modified !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !include $(PVM_ROOT)\conf\$(PVM_ARCH).def INCL = /I $(PVM_ROOT)\include /I $(PVM_ROOT)\tracer \ /I $(PVM_ROOT)\src LIBS = $(PVM_ARCH)\libpvmtracer.lib \ $(PVM_ROOT)\lib\$(PVM_ARCH)\libpvm3.lib OBJS = $(PVM_ARCH)\cmd.obj $(PVM_ARCH)\trcglob.obj \ $(PVM_ARCH)\tracer.obj LIBOBJS = $(PVM_ARCH)\trcmess.obj $(PVM_ARCH)\trcfile.obj \ $(PVM_ARCH)\trccompat.obj $(PVM_ARCH)\trccompatglob.obj \ $(PVM_ARCH)\trcutil.obj $(PVM_ARCH)\trclib.obj all: paths $(PVM_ARCH)\libpvmtracer.lib tracer.exe paths: if not exist "$(PVM_ARCH)\$(NULL)" mkdir "$(PVM_ARCH)" if not exist "..\lib\$(PVM_ARCH)\$(NULL)" mkdir "..\lib\$(PVM_ARCH)" $(PVM_ARCH)\libpvmtracer.lib: $(LIBOBJS) $(linklib) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\tracer\$(PVM_ARCH)\libpvmtracer.lib \ $(LIBOBJS) tracer.exe: $(OBJS) $(PVM_ARCH)\libpvmtracer.lib $(linkexe) $(OUTBIN)$(PVM_ROOT)\tracer\$(PVM_ARCH)\tracer.exe \ $(OBJS) $(LIBS) $(link_flags) $(PVM_ARCH)\cmd.obj: cmd.c $(cc) $(cflags) -c $(INCL) $(OUT)$(PVM_ARCH)\cmd.obj cmd.c $(PVM_ARCH)\trcglob.obj: trcglob.c $(cc) $(cflags) -c $(INCL) $(OUT)$(PVM_ARCH)\trcglob.obj trcglob.c $(PVM_ARCH)\tracer.obj: tracer.c $(cc) $(cflags) -c $(INCL) $(OUT)$(PVM_ARCH)\tracer.obj tracer.c # LIB $(PVM_ARCH)\trcmess.obj: trcmess.c $(cc) $(cflags) -c $(INCL) $(OUT)$(PVM_ARCH)\trcmess.obj trcmess.c $(PVM_ARCH)\trcfile.obj: trcfile.c $(cc) $(cflags) -c $(INCL) $(OUT)$(PVM_ARCH)\trcfile.obj trcfile.c $(PVM_ARCH)\trccompat.obj: trccompat.c $(cc) $(cflags) -c $(INCL) $(OUT)$(PVM_ARCH)\trccompat.obj \ trccompat.c $(PVM_ARCH)\trccompatglob.obj: trccompatglob.c $(cc) $(cflags) -c $(INCL) $(OUT)$(PVM_ARCH)\trccompatglob.obj \ trccompatglob.c $(PVM_ARCH)\trcutil.obj: trcutil.c $(cc) $(cflags) -c $(INCL) $(OUT)$(PVM_ARCH)\trcutil.obj trcutil.c $(PVM_ARCH)\trclib.obj: trclib.c $(cc) $(cflags) -c $(INCL) $(OUT)$(PVM_ARCH)\trclib.obj trclib.c ./pvm3/tracer/cmd.c0100644007401100000360000001525606625347627013321 0ustar kohlgopher static char rcsid[] = "$Id: cmd.c,v 4.8 1998/11/20 20:22:47 pvmsrc Exp $"; /* * Tracer version 1.0: A Trace File Generator for PVM * Oak Ridge National Laboratory, Oak Ridge TN. * Authors: James Arthur Kohl and G. A. Geist * (C) 1994 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear * in supporting documentation. * * Neither the Institution, Oak Ridge National Laboratory, nor the * Authors make any representations about the suitability of this * software for any purpose. This software is provided ``as is'' * without express or implied warranty. * * Tracer was funded by the U.S. Department of Energy. */ /* Tracer Headers */ #include "tracer.h" #include "trcglob.h" #ifdef SYSVSTR #include #else #include #endif /* Command Routines */ int mask_proc( ac, av ) int ac; char **av; { char name[255]; int on_off; int set; int e; int i; /* No Args */ if ( ac == 1 ) { printf( "\nTrace Mask:\n\n" ); trc_print_tmask( TRACE_MASK ); printf( "\n" ); return( TRC_TRUE ); } /* Parse Command Args */ on_off = TRC_TRUE; set = 0; for ( i=1 ; i < ac ; i++ ) { if ( !strcmp( av[i], "+" ) ) on_off = TRC_TRUE; else if ( !strcmp( av[i], "-" ) ) on_off = TRC_FALSE; else if ( !strcmp( av[i], "default" ) || !strcmp( av[i], "xpvm" ) || !strcmp( av[i], "XPVM" ) ) { TEV_MASK_INIT( TRACE_MASK ); TEV_MASK_SET( TRACE_MASK, TEV_BARRIER ); TEV_MASK_SET( TRACE_MASK, TEV_BCAST ); TEV_MASK_SET( TRACE_MASK, TEV_JOINGROUP ); TEV_MASK_SET( TRACE_MASK, TEV_LVGROUP ); TEV_MASK_SET( TRACE_MASK, TEV_MYTID ); TEV_MASK_SET( TRACE_MASK, TEV_PARENT ); TEV_MASK_SET( TRACE_MASK, TEV_SPAWN ); TEV_MASK_SET( TRACE_MASK, TEV_SENDSIG ); TEV_MASK_SET( TRACE_MASK, TEV_KILL ); TEV_MASK_SET( TRACE_MASK, TEV_EXIT ); TEV_MASK_SET( TRACE_MASK, TEV_MCAST ); TEV_MASK_SET( TRACE_MASK, TEV_SEND ); TEV_MASK_SET( TRACE_MASK, TEV_RECV ); TEV_MASK_SET( TRACE_MASK, TEV_RECVF ); TEV_MASK_SET( TRACE_MASK, TEV_NRECV ); TEV_MASK_SET( TRACE_MASK, TEV_PSEND ); TEV_MASK_SET( TRACE_MASK, TEV_PRECV ); TEV_MASK_SET( TRACE_MASK, TEV_TRECV ); TEV_MASK_SET( TRACE_MASK, TEV_PROBE ); TEV_MASK_SET( TRACE_MASK, TEV_USER_DEFINED ); set++; } else if ( !strcmp( av[i], "*" ) ) { for ( e=TEV_FIRST ; e <= TEV_MAX ; e++ ) { if ( on_off ) TEV_MASK_SET( TRACE_MASK, e ); else TEV_MASK_UNSET( TRACE_MASK, e ); } set++; } else { if ( !strncmp( av[i], "pvm_", 4 ) ) strcpy( name, av[i] + 4 ); else strcpy( name, av[i] ); for ( e=TEV_FIRST ; e <= TEV_MAX ; e++ ) { if ( !strcmp( pvmtevinfo[e].name, name ) || !strcmp( pvmtevinfo[e].name, av[i] ) ) { break; } } if ( e <= TEV_MAX ) { if ( on_off ) TEV_MASK_SET( TRACE_MASK, e ); else TEV_MASK_UNSET( TRACE_MASK, e ); set++; } else printf( "No such event \"%s\"\n", av[i] ); } } /* Install New Trace Mask */ if ( set ) { pvm_settmask( PvmTaskChild, TRACE_MASK ); printf( "\nNew Trace Mask:\n\n" ); trc_print_tmask( TRACE_MASK ); printf( "\n" ); re_register_tracer(); } return( TRC_TRUE ); } int buffer_proc( ac, av ) int ac; char **av; { int nbytes; if ( ac == 1 ) { printf( "\nCurrent Trace Buffer Size is %d Bytes\n\n", TRACE_BUF ); return( TRC_TRUE ); } nbytes = atoi( av[1] ); nbytes = nbytes < 0 ? 0 : nbytes; TRACE_BUF = nbytes; pvm_setopt( PvmTraceBuffer, TRACE_BUF ); re_register_tracer(); return( TRC_TRUE ); } int options_proc( ac, av ) int ac; char **av; { int cc = TRC_TRUE; if ( ac == 1 ) { printf( "\nCurrent Tracing Option is " ); switch ( TRACE_OPT ) { case PvmTraceFull: printf( "full.\n\n" ); break; case PvmTraceTime: printf( "time.\n\n" ); break; case PvmTraceCount: printf( "count.\n\n" ); break; default: printf( "undefined!\n\n" ); cc = TRC_FALSE; } return( cc ); } if ( !strcmp( av[1], "full" ) ) TRACE_OPT = PvmTraceFull; else if ( !strcmp( av[1], "time" ) ) TRACE_OPT = PvmTraceTime; else if ( !strcmp( av[1], "count" ) ) TRACE_OPT = PvmTraceCount; else { printf( "\nUnknown Trace Option \"%s\".\n\n", av[1] ); return( TRC_FALSE ); } pvm_setopt( PvmTraceOptions, TRACE_OPT ); re_register_tracer(); return( cc ); } void re_register_tracer() { /* Re-Register Tracer */ if ( TRACER_REGISTERED ) { if ( pvm_reg_tracer( -1, -1, -1, -1, CLEAR_MASK, -1, -1 ) > 0 ) { printf( "Error Unregistering Tracer... Exiting.\n" ); exit( -1 ); } else TRACER_REGISTERED = TRC_FALSE; } if ( pvm_reg_tracer( pvm_getcontext(), 666, pvm_getcontext(), 667, TRACE_MASK, TRACE_BUF, TRACE_OPT ) < 0 ) { printf( "Tracer Already Connected... Exiting.\n" ); exit( -1 ); } else TRACER_REGISTERED = TRC_TRUE; } int help_proc( ac, av ) int ac; char **av; { int i; /* General Help */ if ( ac == 1 ) { printf( "\nTracer %s\n\n", TRC_VERSION ); printf( "mask - display or modify the trace mask.\n" ); printf( "trace - display or modify the trace mask.\n" ); printf( "buffer - display or set the trace buffer size.\n" ); printf( "options - display or set the trace options.\n" ); printf( "help - display this help information.\n" ); printf( "help cmd - display help information for cmd.\n" ); printf( "quit - close trace file and exit tracer.\n" ); printf( "\n" ); return( TRC_TRUE ); } /* Dump Usage for Command */ for ( i=1 ; i < ac ; i++ ) { if ( !strcmp( av[i], "mask" ) ) { printf( "usage: mask [ [+|-] [ event | * ] ] [ default | xpvm ]\n" ); } else if ( !strcmp( av[i], "trace" ) ) { printf( "usage: trace [ [+|-] [ event | * ] ] [ default | xpvm ]\n" ); } else if ( !strcmp( av[i], "buffer" ) ) printf( "usage: buffer [ nbytes ]\n" ); else if ( !strcmp( av[i], "options" ) ) printf( "usage: options [ full | time | count ]\n" ); else { printf( "No Help Available for \"%s\"\n", av[i] ); return( TRC_FALSE ); } } return( TRC_TRUE ); } void quit_proc() { printf( "Quitting Tracer.\n" ); if ( TRACER_REGISTERED ) pvm_reg_tracer( -1, -1, -1, -1, CLEAR_MASK, -1, -1 ); if ( ID->trace_out != NULL && ID->trace_out != stdout ) fclose( ID->trace_out ); exit( -1 ); } void quit_cmd_proc( ac, av ) int ac; char **av; { quit_proc(); } void quit_sig_proc( sig ) int sig; { quit_proc(); } ./pvm3/tracer/tracer.c0100644007401100000360000002607707354172266014034 0ustar kohlgopher static char rcsid[] = "$Id: tracer.c,v 4.16 2001/09/25 21:18:46 pvmsrc Exp $"; /* * Tracer version 1.0: A Trace File Generator for PVM * Oak Ridge National Laboratory, Oak Ridge TN. * Authors: James Arthur Kohl and G. A. Geist * (C) 1994 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear * in supporting documentation. * * Neither the Institution, Oak Ridge National Laboratory, nor the * Authors make any representations about the suitability of this * software for any purpose. This software is provided ``as is'' * without express or implied warranty. * * Tracer was funded by the U.S. Department of Energy. */ /* Tracer Headers */ #include "tracer.h" #include "trcglob.h" #ifdef NEEDSSELECTH #include #endif #ifdef SYSVSTR #include #else #include #endif #include /* Event Receiving Loop Limit */ #define EVENT_COUNT 20 /* Command Routines */ #ifdef WIN32 void quit_sig_proc( int ); void quit_cmd_proc( int, char** ); #else void quit_sig_proc(); void quit_cmd_proc(); #endif void quit_proc(); int mask_proc(); /* Handler Routines */ void my_status_msg(); void program_init(); void read_args(); void pvm_init(); void trc_init(); void usage(); void work(); /* MAIN */ int main( argc, argv ) int argc; char **argv; { /* Read Command Line Args */ read_args( argc, argv ); /* Initialize Program Constants & Structs */ program_init(); /* Initialize PVM */ pvm_init(); /* Initialize Tracer Globals */ trc_init(); /* Do Tracer-like Stuff */ work(); } void work() { struct timeval more_events; struct timeval *timeout; char cmd[1024]; char *prompt; #ifdef FDSETNOTSTRUCT fd_set rfds; fd_set fds; #else struct fd_set rfds; struct fd_set fds; #endif int *np; int nfds; int more; int max; int in; int n; int i; #ifdef WIN32 #define read _read HANDLE hStdin; struct timeval zerotimeout = { 0, 0 }; hStdin = GetStdHandle(STD_INPUT_HANDLE); #endif /* Initialize File Descriptors */ FD_ZERO( &rfds ); /* Get stdin input */ #ifndef WIN32 in = fileno( stdin ); FD_SET( in, &rfds ); nfds = 1; #else i=0; #endif /* Get PVM Sockets */ if ( pvm_getfds( &np ) > 0 ) { FD_SET( np[0], &rfds ); nfds = np[0] + 1; } /* Initialize Select Timeout - For Events Still Pending */ more_events.tv_sec = 0; more_events.tv_usec = 0; /* Print Initial Prompt */ prompt = "tracer> "; printf( prompt ); fflush( stdout ); /* Process Events Messages and User Input */ while ( 1 ) { /* Check for Event Messages */ more = recv_events(); if ( more ) timeout = &more_events; else #ifndef WIN32 timeout = (struct timeval *) NULL; #else timeout = &zerotimeout; #endif /* Wait for Input */ fds = rfds; if ( (n = SELECT( nfds, &fds, NULL, NULL, timeout )) == -1 ) perror( "select" ); #ifdef WIN32 else if (WAIT_TIMEOUT == WaitForSingleObject(hStdin,2000) ) continue; /* no input */ #else else if ( n > 0 && FD_ISSET( in, &fds ) ) #endif { #ifndef WIN32 if ( (n = read(in, cmd, sizeof( cmd ) - 1 )) < 1 ) #else /* even if I set in=0 -> read(in, ...) fails. must be explicityly 0 ! am I missing something ? */ if ( (n = read(0, cmd, sizeof( cmd ) - 1 )) < 1 ) #endif { printf( "Quit\n" ); quit_proc(); } else { cmd[ n ] = '\0'; handle_cmd( cmd ); printf( prompt ); fflush( stdout ); } } } } int handle_cmd( cmd ) char *cmd; { char *av[128]; int ac; ac = ( sizeof( av ) / sizeof( av[0] ) ) - 1; if ( acav( cmd, &ac, av ) ) { printf( "\nError: Command Too Long...\n\n" ); return( TRC_FALSE ); } /* "Ugly Parse" Command Ops */ if ( ac >= 1 ) { if ( !strcmp( av[0], "mask" ) || !strcmp( av[0], "trace" ) ) mask_proc( ac, av ); else if ( !strcmp( av[0], "buffer" ) || !strcmp( av[0], "buf" ) ) { buffer_proc( ac, av ); } else if ( !strcmp( av[0], "options" ) || !strcmp( av[0], "opt" ) ) { options_proc( ac, av ); } else if ( !strcmp( av[0], "help" ) || !strcmp( av[0], "h" ) || !strcmp( av[0], "?" ) ) { help_proc( ac, av ); } else if ( !strcmp( av[0], "q" ) || !strcmp( av[0], "quit" ) || !strcmp( av[0], "x" ) || !strcmp( av[0], "exit" ) ) { quit_cmd_proc( ac, av ); } else { printf( "Unknown Command \"%s\".\n", av[0] ); return( TRC_FALSE ); } } return( TRC_TRUE ); } int recv_events() { int status; int ecnt; ecnt = trc_recv_messages( ID, EVENT_COUNT, &status ); if ( ecnt < 0 ) exit( -1 ); if ( ecnt ) fflush( ID->trace_out ); return( status & TRC_MSG_STATUS_MORE ); } void read_args( argc, argv ) int argc; char **argv; { char tmp[1024]; int i, j, k; int do_usage; int len; OUTPUT_FILE = (char *) NULL; TRACE_FILE = (char *) NULL; TRACE_BUF = 0; TRACE_OPT = PvmTraceFull; vflag = 0; do_usage = 0; for ( i=1 ; i < argc ; i++ ) { if ( argv[i][0] == '-' ) { k = i + 1; len = strlen( argv[i] ); for ( j=0 ; j < len ; j++ ) { switch ( argv[i][j] ) { case 'H': case 'h': usage(); break; case 'T': { if ( TRACE_FILE != NULL ) free( TRACE_FILE ); TRACE_FILE = trc_copy_str( argv[k++] ); break; } case 'O': { if ( OUTPUT_FILE != NULL ) free( OUTPUT_FILE ); OUTPUT_FILE = trc_copy_str( argv[k++] ); break; } case 'B': { TRACE_BUF = atoi( argv[k++] ); break; } case 'v': vflag++; break; case '-': break; default: { printf( "Unknown Option -%c\n", argv[i][j] ); do_usage++; break; } } } i = k - 1; } else { if ( !strcmp( argv[i], "full" ) ) TRACE_OPT = PvmTraceFull; else if ( !strcmp( argv[i], "time" ) ) TRACE_OPT = PvmTraceTime; else if ( !strcmp( argv[i], "count" ) ) TRACE_OPT = PvmTraceCount; else { printf( "Unknown Option %s\n", argv[i] ); do_usage++; } } } if ( do_usage ) usage(); } void usage() { printf( "\nusage: tracer [ -T tracefile ] [ -O outfile ] " ); printf( "[ full | time | count ] [ -Hhev ]\n\n" ); printf( "where:\n" ); printf( "------\n" ); printf( "-T file\t = Use \"file\" as Trace File\n" ); printf( "-O file\t = Use \"file\" as Additional Output File\n" ); printf( "-B nbytes\t = Set Trace Buffer Size to nbytes\n" ); printf( "full\t = Set Tracing Option to Full\n" ); printf( "time\t = Set Tracing Option to Timing\n" ); printf( "count\t = Set Tracing Option to Count\n" ); printf( "-H/h\t = Print This Help Information\n" ); printf( "-e\t = Dump Raw PVM Event Text\n" ); printf( "-v\t = Verbose Operation\n" ); printf( "\n" ); exit( 0 ); } void program_init() { struct passwd *pw; char hname[1024]; char pvstr[255]; char tmp[2048]; #ifdef WIN32 char *username = 0; char *pstr; #endif char *stripped; char *uppered; char *pvmtmp; char *home; int entry_exit; int release; int version; int fmt; int i; /* Get User Name for Trace File */ if ( TRACE_FILE == NULL ) { pvmtmp = pvmgettmp(); #ifndef WIN32 if ( (pw = getpwuid( getuid() )) != NULL ) sprintf( tmp, "%s/tracefile.%s", pvmtmp, pw->pw_name ); #else if ( !username ) username = (char *) MyGetUserName(); if ( username ) sprintf( tmp, "%s\\tracefile.%s", pvmtmp, username ); #endif else #ifndef WIN32 sprintf( tmp, "%s/tracefile.%d", pvmtmp, getpid() ); #else { fprintf( stderr, "You are not logged onto the machine! Exiting.\n"); exit( -1 ); } #endif TRACE_FILE = trc_copy_str( tmp ); } /* Initialize Globals & Flags */ TRACER_REGISTERED = TRC_FALSE; } void pvm_init() { char *av[2]; int inum; int se; int cc; int i; /* Options */ pvm_setopt( PvmResvTids, 1 ); pvm_setopt( PvmRoute, PvmDontRoute ); /* Get My TID */ MYTID = pvm_mytid(); if ( MYTID < 0 ) { pvm_perror( "Error Joining PVM" ); exit( -1 ); } else printf( "\nTracer connected as tid=0x%x.\n", MYTID ); /* Set Desired Signals */ pvm_setopt( PvmNoReset, 1 ); #ifndef WIN32 signal( SIGALRM, SIG_IGN ); signal( SIGQUIT, (vfp) quit_sig_proc ); signal( SIGINT, (vfp) quit_sig_proc ); #endif signal( SIGINT, quit_sig_proc ); /* Set Trace Masks */ TEV_MASK_INIT( CLEAR_MASK ); av[0] = "mask"; av[1] = "xpvm"; mask_proc( 2, av ); pvm_settmask( PvmTaskChild, TRACE_MASK ); /* Set Trace Buffering */ pvm_setopt( PvmTraceBuffer, TRACE_BUF ); /* Set Tracing Options */ pvm_setopt( PvmTraceOptions, TRACE_OPT ); } void trc_init() { /* Initialize Tracer */ trc_tracer_init(); /* Set Tracer Globals */ TRC_HOST_ADD_NOTIFY_CODE = 99; TRC_HOST_DEL_NOTIFY_CODE = 100; TRC_VERSION = MYVERSION; TRC_NAME = "Tracer"; TRC_TID = MYTID; /* Get Tracer ID */ ID = trc_get_tracer_id(); /* Set Local Handler Routines */ ID->status_msg = my_status_msg; /* Set Trace Event Message Codes */ ID->event_ctx = pvm_getcontext(); ID->event_tag = 666; ID->output_ctx = pvm_getcontext(); ID->output_tag = 667; /* Set PVM Tracing Options */ trc_set_tracing_codes( ID ); /* Open Trace File */ trc_set_trace_file( ID, TRACE_FILE ); if ( !trc_reset_trace_file( ID ) ) exit( -1 ); /* Check Hosts */ trc_initialize_hosts( ID ); /* Dump Host Status Events */ trc_save_host_status_events( ID ); /* Open Additional Output File */ if ( OUTPUT_FILE != NULL ) { trc_set_output_file( ID, OUTPUT_FILE ); trc_open_output_file( ID ); } } /* Status Message Handler */ void my_status_msg( ID, msg ) TRC_ID ID; char *msg; { printf( "%s\n", msg ); } /* Stolen from regular PVM console... :-) */ /* acav() * * Parse a string into words separated by whitespace. * Max number of words is original value of *acp. * * Trashes out the original string. * Returns 0 with av[0]..av[*acp - 1] pointing to the words. * Returns 1 if too many words. * Returns -1 if unbalanced quote. */ int acav(s, acp, av) char *s; /* the string to parse */ int *acp; /* max num words in, num words found out */ char **av; /* pointers to words */ { int ac = 0; /* number of words found */ char *p = s; /* input scanner */ char *q; /* output */ int n = *acp; /* max number of words allowed */ int mode = 0; /* quote mode */ while (*p) { while (isspace(*p)) p++; if (*p) { if (*p == '#') break; if (ac >= n) { *acp = ac; return 1; } q = p; av[ac++] = p; while (*p) { if (mode) { if (mode == '\\') { *q++ = *p; mode = 0; } else if (mode == *p) { mode = 0; } else *q++ = *p; } else { if (isspace(*p)) break; switch (*p) { case '"': case '\'': case '\\': mode = *p; break; default: *q++ = *p; break; } } p++; } if (*p) p++; if (*q) *q = 0; if (mode) { printf("unmatched %c\n", (char)mode); return -1; } } } *acp = ac; return 0; } ./pvm3/tracer/trccompat.c0100644007401100000360000004371307011606023014523 0ustar kohlgopher static char rcsid[] = "$Id: trccompat.c,v 4.6 1999/11/08 17:44:51 pvmsrc Exp $"; /* * Tracer version 1.0: A Trace File Generator for PVM * Oak Ridge National Laboratory, Oak Ridge TN. * Authors: James Arthur Kohl and G. A. Geist * (C) 1994 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear * in supporting documentation. * * Neither the Institution, Oak Ridge National Laboratory, nor the * Authors make any representations about the suitability of this * software for any purpose. This software is provided ``as is'' * without express or implied warranty. * * Tracer was funded by the U.S. Department of Energy. */ /* Tracer Headers */ #include "trclib.h" #include "trccompat.h" #ifdef SYSVSTR #include #else #include #endif /* Old Trace File Generation Routines - For Compatibility */ /* Trace Lookup Trie Init Routines */ void trc_init_old_events() { int i; TRC_OLD_EVENT_TRIE = trc_create_triestack(); for ( i=TRC_OLD_TEV_FIRST ; i < TRC_OLD_TRACE_MAX ; i++ ) { if ( strcmp( TRC_OLD_TEV_TRACE_NAMES[i], "" ) ) { trc_add_to_trie( TRC_OLD_EVENT_TRIE, TRC_OLD_TEV_TRACE_NAMES[i], (void *) ( ( i - TRC_OLD_TEV_FIRST ) + 1 ) ); } TRC_OLD_TEV_TRACE[i] = 0; } } int trc_process_old_trace_event( ID, name ) TRC_ID ID; char *name; { long tmp; int tusec; int tsec; int flag; int eid; int tid; if ( !trc_find_event_str( ID, "{" ) ) return( TRC_FALSE ); /* } to match above */ flag = fscanf( ID->trace_in, "%d, %d, %d", &tsec, &tusec, &tid ); if ( flag != 3 ) { printf( "Incomplete Trace Record\n" ); return( TRC_FALSE ); } if ( tmp = (long) trc_lookup_trie( TRC_OLD_EVENT_TRIE, name ) ) { eid = (int) tmp; eid = ( eid - 1 ) + TRC_OLD_TEV_FIRST; if ( ID->handle_old_event ) (ID->handle_old_event)( ID, eid, tsec, tusec, tid ); else trc_find_event_end( ID ); return( TRC_TRUE ); } else { printf( "Error: Event \"%s\" Not Found\n", name ); trc_find_event_end( ID ); return( TRC_FALSE ); } } int trc_store_old_trace_event( ID, tsec, tusec, tid, eid ) TRC_ID ID; int tsec; int tusec; int tid; int eid; { static int *tids = (int *) NULL; static int ntids = 0; TRC_TEVTASK TT; char where[4096]; char name[4096]; char msg[255]; int msgtag; int nbytes; int ignore; int count; int flags; int addr; int ecnt; int host; int type; int ptid; int dtid; int stid; int omit; int len; int buf; int num; int cc; int i; /* Set Leftover Event Omit Flag */ TT = trc_get_tevtask_tid( ID, tid ); omit = ( ID->trace_out == NULL || ( TT != NULL && TRC_TASK_OMIT( TT ) ) ) ? TRC_TRUE : TRC_FALSE; /* Initialize Event Counter */ ecnt = 0; if ( !omit ) { /* Output Trace Event Descriptor (if necessary) */ if ( !( TRC_OLD_TEV_TRACE[ eid ] ) ) { fprintf( ID->trace_out, "\n" ); if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, tid ); fprintf( ID->trace_out, "#%d: %s\n", eid + 1, TRC_OLD_TRACE_DESCRIPTORS[ eid ] ); (TRC_OLD_TEV_TRACE[ eid ])++; } /* Update Trace Time */ trc_update_trace_time( tsec, tusec ); /* Output Trace Event Header */ if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, tid ); fprintf( ID->trace_out, "\"%s\" { %d, %d, %d", TRC_OLD_TEV_TRACE_NAMES[ eid ], tsec, tusec, tid ); /* } */ } /* Convert Trace to Output File */ switch ( eid ) { case TRC_OLD_TEV_NEWTASK: { if ( omit ) break; pvm_upkint( &ptid, 1, 1 ); pvm_upkint( &flags, 1, 1 ); pvm_upkstr( name ); if ( !strcmp( name, "" ) ) strcpy( name, "-" ); host = pvm_tidtohost( tid ); fprintf( ID->trace_out, ", %d, %d, %d", ptid, host, flags ); trc_dump_trace_str( ID, name, TRC_TRUE ); ignore = 0; if ( !(ID->group_tasks) && TRC_GROUPTASK( name ) ) ignore++; if ( TT == NULL ) { if ( !ignore ) { sprintf( msg, "Task TID=0x%x Connected to %s", tid, TRC_NAME ); trc_status_msg( ID, msg ); } TT = trc_create_tevtask(); TT->tid = tid; TT->outstatus = TRC_TASK_NOOUT; TT->next = ID->tevtask_list; ID->tevtask_list = TT; } if ( !ignore ) TT->tevstatus = TRC_TASK_ALIVE; else TT->tevstatus = TRC_TASK_IGNORE; break; } case TRC_OLD_TEV_SPNTASK: { if ( omit ) break; trc_dump_old_pvm_event_fmt( ID, eid ); if ( TT == NULL ) { sprintf( msg, "Task TID=0x%x Connected to %s", tid, TRC_NAME ); trc_status_msg( ID, msg ); TT = trc_create_tevtask(); TT->tid = tid; TT->tevstatus = TRC_TASK_ALIVE; TT->outstatus = TRC_TASK_NOOUT; TT->next = ID->tevtask_list; ID->tevtask_list = TT; } break; } case TRC_OLD_TEV_ENDTASK: { if ( !omit ) trc_dump_old_pvm_event_fmt( ID, eid ); if ( TT != NULL ) { if ( TT->tevstatus == TRC_TASK_ALIVE ) { TT->tevstatus = TRC_TASK_DEAD; trc_check_for_dead_host( ID, TT ); if ( !trc_tevtasks_alive( ID ) ) trc_end_trace( ID ); } else TT->tevstatus = TRC_TASK_DEAD; } else if ( !omit ) { printf( "\nWarning: ENDTASK Unknown Task TID=0x%x.\n\n", tid ); } break; } case TRC_OLD_TEV_ADDHOSTS0: { if ( omit ) break; pvm_upkint( &num, 1, 1 ); fprintf( ID->trace_out, ", %d, [%d][100] { ", num, num ); for ( i=0 ; i < num ; i++ ) { pvm_upkstr( name ); if ( i != num - 1 ) fprintf( ID->trace_out, "\"%s\", ", name ); else fprintf( ID->trace_out, "\"%s\" }", name ); } break; } case TRC_OLD_TEV_ADDHOSTS1: { if ( omit ) break; pvm_upkint( &cc, 1, 1 ); fprintf( ID->trace_out, ", %d", cc ); break; } case TRC_OLD_TEV_SPAWN0: { if ( omit ) break; pvm_upkstr( name ); pvm_upkint( &flags, 1, 1 ); pvm_upkstr( where ); pvm_upkint( &count, 1, 1 ); trc_dump_trace_str( ID, name, TRC_TRUE ); fprintf( ID->trace_out, ", %d", flags ); trc_dump_trace_str( ID, where, TRC_TRUE ); fprintf( ID->trace_out, ", %d", count ); break; } case TRC_OLD_TEV_SPAWN1: { if ( omit ) break; pvm_upkint( &num, 1, 1 ); fprintf( ID->trace_out, ", %d, [%d] {", num, num ); if ( num > 0 ) { if ( num > ntids ) { ntids = num * 2; if ( tids != NULL ) free( tids ); tids = (int *) malloc( (unsigned) ntids * sizeof(int) ); trc_memcheck( tids, "Spawn TIDs" ); } pvm_upkint( tids, num, 1 ); for ( i=0 ; i < num ; i++ ) { if ( i ) fprintf( ID->trace_out, ", %d", tids[i] ); else fprintf( ID->trace_out, " %d", tids[i] ); } } fprintf( ID->trace_out, " }" ); break; } case TRC_OLD_TEV_SEND0: { if ( omit ) break; pvm_upkint( &dtid, 1, 1 ); pvm_upkint( &msgtag, 1, 1 ); fprintf( ID->trace_out, ", %d, %d", dtid, msgtag ); break; } case TRC_OLD_TEV_MCAST0: { if ( omit ) break; pvm_upkint( &num, 1, 1 ); pvm_upkint( &msgtag, 1, 1 ); fprintf( ID->trace_out, ", %d, %d, [%d] {", num, msgtag, num ); if ( num > 0 ) { if ( num > ntids ) { ntids = num * 2; if ( tids != NULL ) free( tids ); tids = (int *) malloc( (unsigned) ntids * sizeof(int) ); trc_memcheck( tids, "Mcast TIDs" ); } pvm_upkint( tids, num, 1 ); for ( i=0 ; i < num ; i++ ) { if ( i ) fprintf( ID->trace_out, ", %d", tids[i] ); else fprintf( ID->trace_out, " %d", tids[i] ); } } fprintf( ID->trace_out, " }" ); break; } case TRC_OLD_TEV_PSEND0: { if ( omit ) break; pvm_upkint( &dtid, 1, 1 ); pvm_upkint( &msgtag, 1, 1 ); pvm_upkint( &addr, 1, 1 ); pvm_upkint( &len, 1, 1 ); pvm_upkint( &type, 1, 1 ); fprintf( ID->trace_out, ", %d, %d, %d, %d, %d", dtid, msgtag, addr, len, type ); break; } case TRC_OLD_TEV_RECV1: case TRC_OLD_TEV_TRECV1: { if ( omit ) break; pvm_upkint( &buf, 1, 1 ); pvm_upkint( &nbytes, 1, 1 ); if ( nbytes >= 0 ) { pvm_upkint( &msgtag, 1, 1 ); pvm_upkint( &stid, 1, 1 ); } else msgtag = stid = -1; fprintf( ID->trace_out, ", %d, %d, %d, %d", buf, nbytes, msgtag, stid ); break; } case TRC_OLD_TEV_PRECV1: { if ( omit ) break; pvm_upkint( &buf, 1, 1 ); fprintf( ID->trace_out, ", %d, 0, 0, 0", buf ); break; } case TRC_OLD_TEV_NRECV1: { if ( omit ) break; pvm_upkint( &buf, 1, 1 ); if ( buf > 0 ) { pvm_upkint( &nbytes, 1, 1 ); if ( nbytes >= 0 ) { pvm_upkint( &msgtag, 1, 1 ); pvm_upkint( &stid, 1, 1 ); } else msgtag = stid = -1; } else nbytes = msgtag = stid = -1; fprintf( ID->trace_out, ", %d, %d, %d, %d", buf, nbytes, msgtag, stid ); break; } default: { if ( !omit ) trc_dump_old_pvm_event_fmt( ID, eid ); } } if ( !omit ) { /* Finish Off Trace Event ({) */ fprintf( ID->trace_out, " };;\n" ); ecnt++; } return( ecnt ); } void trc_dump_old_pvm_event_fmt( ID, eid ) TRC_ID ID; int eid; { char buf[4096]; char *fmt; int keeplist[10]; int veclen; int index; int nkeep; int keep; int ival; fmt = trc_old_tev_formats[ eid ].fmt; if ( fmt != NULL ) { nkeep = 0; while ( *fmt ) { if ( *fmt == '%' ) { fmt++; if ( *fmt == '*' ) { keep = TRC_TRUE; fmt++; } else keep = TRC_FALSE; if ( *fmt == '$' ) { fmt++; index = *fmt - '0'; fmt++; veclen = ( index >= 0 && index < nkeep ) ? keeplist[index] : 0; } else veclen = 1; while ( veclen > 0 ) { veclen--; switch ( *fmt ) { case 'R': case 'd': case 'r': case 'x': { pvm_upkint( &ival, 1, 1 ); fprintf( ID->trace_out, ", %d", ival ); break; } case 'S': { pvm_upkstr( buf ); trc_dump_trace_str( ID, buf, TRC_TRUE ); break; } default: break; } } if ( *fmt ) fmt++; if ( keep ) { keeplist[nkeep] = ival < 0 ? 0 : ival; nkeep++; } } else fmt++; } } } void trc_write_old_output_event( ID, tid, str ) TRC_ID ID; int tid; char *str; { if ( !( TRC_OLD_TEV_TRACE[ TRC_OLD_TRACE_OUTPUT ] ) ) { fprintf( ID->trace_out, "\n" ); if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, tid ); fprintf( ID->trace_out, "#%d: %s\n", TRC_OLD_TRACE_OUTPUT + 1, TRC_OLD_TRACE_DESCRIPTORS[ TRC_OLD_TRACE_OUTPUT ] ); (TRC_OLD_TEV_TRACE[ TRC_OLD_TRACE_OUTPUT ])++; } if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, tid ); fprintf( ID->trace_out, "\"%s\" { %d, %ld, %d", TRC_OLD_TEV_TRACE_NAMES[ TRC_OLD_TRACE_OUTPUT ], TRC_TRACE_TIME.tv_sec, TRC_TRACE_TIME.tv_usec, tid ); trc_dump_trace_str( ID, str, TRC_TRUE ); fprintf( ID->trace_out, " };;\n" ); } void trc_write_old_host_add_event( ID, H ) TRC_ID ID; TRC_HOST H; { if ( !( TRC_OLD_TEV_TRACE[ TRC_OLD_TRACE_HOST_ADD ] ) ) { fprintf( ID->trace_out, "\n" ); if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, H->pvmd_tid ); fprintf( ID->trace_out, "#%d: %s\n", TRC_OLD_TRACE_HOST_ADD + 1, TRC_OLD_TRACE_DESCRIPTORS[ TRC_OLD_TRACE_HOST_ADD ] ); (TRC_OLD_TEV_TRACE[ TRC_OLD_TRACE_HOST_ADD ])++; } if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, H->pvmd_tid ); fprintf( ID->trace_out, "\"%s\" { %d, %ld, %d", TRC_OLD_TEV_TRACE_NAMES[ TRC_OLD_TRACE_HOST_ADD ], TRC_TRACE_TIME.tv_sec, TRC_TRACE_TIME.tv_usec, H->pvmd_tid ); trc_dump_trace_str( ID, H->refname, TRC_TRUE ); trc_dump_trace_str( ID, H->alias, TRC_TRUE ); trc_dump_trace_str( ID, H->arch, TRC_TRUE ); fprintf( ID->trace_out, ", %d };;\n", H->speed ); } void trc_write_old_host_del_event( ID, H, tid ) TRC_ID ID; TRC_HOST H; int tid; { char tmp[1024]; if ( !( TRC_OLD_TEV_TRACE[ TRC_OLD_TRACE_HOST_DEL ] ) ) { fprintf( ID->trace_out, "\n" ); if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, tid ); fprintf( ID->trace_out, "#%d: %s\n", TRC_OLD_TRACE_HOST_DEL + 1, TRC_OLD_TRACE_DESCRIPTORS[ TRC_OLD_TRACE_HOST_DEL ] ); (TRC_OLD_TEV_TRACE[ TRC_OLD_TRACE_HOST_DEL ])++; } if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, tid ); fprintf( ID->trace_out, "\"%s\" { %d, %ld, %d", TRC_OLD_TEV_TRACE_NAMES[ TRC_OLD_TRACE_HOST_DEL ], TRC_TRACE_TIME.tv_sec, TRC_TRACE_TIME.tv_usec, tid ); if ( strcmp( H->refname, "" ) ) { sscanf( H->refname, "%s", tmp ); trc_dump_trace_str( ID, tmp, TRC_TRUE ); } else trc_dump_trace_str( ID, H->refname, TRC_TRUE ); fprintf( ID->trace_out, " };;\n" ); } void trc_write_old_host_sync_event( ID, H ) TRC_ID ID; TRC_HOST H; { if ( !( TRC_OLD_TEV_TRACE[ TRC_OLD_TRACE_HOST_SYNC ] ) ) { fprintf( ID->trace_out, "\n" ); if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, H->pvmd_tid ); fprintf( ID->trace_out, "#%d: %s\n", TRC_OLD_TRACE_HOST_SYNC + 1, TRC_OLD_TRACE_DESCRIPTORS[ TRC_OLD_TRACE_HOST_SYNC ] ); (TRC_OLD_TEV_TRACE[ TRC_OLD_TRACE_HOST_SYNC ])++; } if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, H->pvmd_tid ); fprintf( ID->trace_out, "\"%s\" { %d, %ld, %d, %d, %ld };;\n", TRC_OLD_TEV_TRACE_NAMES[ TRC_OLD_TRACE_HOST_SYNC ], TRC_TRACE_TIME.tv_sec, TRC_TRACE_TIME.tv_usec, H->pvmd_tid, H->delta.tv_sec, H->delta.tv_usec ); H->last_time.tv_sec = TRC_TRACE_TIME.tv_sec; H->last_time.tv_usec = TRC_TRACE_TIME.tv_usec; } char * trc_old_pvm_event_string( ID, eid ) TRC_ID ID; int eid; { char result[4096]; char tmp[2048]; char buf[1024]; char *fmt; char *str; int keeplist[10]; int vecflag; int veclen; int index; int nkeep; int keep; int ival; int sep; fmt = trc_old_tev_formats[ eid ].fmt; if ( fmt != NULL ) { nkeep = 0; if ( *fmt != '=' ) sprintf( result, "%s", trc_old_tev_formats[ eid ].name ); else sprintf( result, "%s() ", trc_old_tev_formats[ eid ].name ); while ( *fmt ) { if ( *fmt == '%' ) { fmt++; if ( *fmt == '*' ) { keep = TRC_TRUE; fmt++; } else keep = TRC_FALSE; if ( *fmt == '$' ) { fmt++; index = *fmt - '0'; fmt++; veclen = ( index >= 0 && index < nkeep ) ? keeplist[index] : 0; vecflag = TRC_TRUE; sep = TRC_FALSE; } else { veclen = 1; vecflag = TRC_FALSE; } while ( veclen > 0 ) { veclen--; if ( vecflag ) { if ( sep ) trc_append_str( result, " ", 4096 ); sep = TRC_TRUE; } switch ( *fmt ) { case 'd': { fscanf( ID->trace_in, ", %d", &ival ); sprintf( tmp, " %d", ival ); trc_append_str( result, tmp, 4096 ); break; } /* decimal result code */ case 'R': { fscanf( ID->trace_in, ", %d", &ival ); sprintf( tmp, " %d", ival ); trc_append_str( result, tmp, 4096 ); if ( ival < 0 ) { if ( ival <= 0 && ival > -trc_old_pvm_nerr ) { sprintf( tmp, " (%s)", trc_old_pvm_errlist[ -ival ] ); } else { sprintf( tmp, " %d (Unknown Error)", ival ); } trc_append_str( result, tmp, 4096 ); } break; } /* hex result code / decimal if negative */ case 'r': { fscanf( ID->trace_in, ", %d", &ival ); if ( ival < 0 ) { if ( ival <= 0 && ival > -trc_old_pvm_nerr ) { sprintf( tmp, " %d (%s)", ival, trc_old_pvm_errlist[ -ival ] ); } else { sprintf( tmp, " %d (Unknown Error)", ival ); } } else sprintf( tmp, " 0x%x", ival ); trc_append_str( result, tmp, 4096 ); break; } case 'x': { fscanf( ID->trace_in, ", %d", &ival ); sprintf( tmp, " 0x%x", ival ); trc_append_str( result, tmp, 4096 ); break; } case 'S': { trc_read_old_trace_str( ID, buf, 1024, TRC_TRUE ); sprintf( tmp, " \"%s\"", buf ); trc_append_str( result, tmp, 4096 ); break; } default: { sprintf( tmp, "%%%c", *fmt ); trc_append_str( result, tmp, 4096 ); break; } } } if ( *fmt ) fmt++; if ( keep ) { keeplist[nkeep] = ival < 0 ? 0 : ival; nkeep++; } } else { sprintf( tmp, "%c", *fmt++ ); trc_append_str( result, tmp, 4096 ); } } } else sprintf( result, "%s()", trc_old_tev_formats[ eid ].name ); trc_find_event_end( ID ); str = trc_copy_str( result ); return( str ); } int trc_read_old_trace_str( ID, str, size, end_flag ) TRC_ID ID; char *str; int size; int end_flag; { char c; int i; *str = '\0'; if ( !trc_find_event_str( ID, "\"" ) ) return( TRC_FALSE ); i = 0; while ( (c = getc( ID->trace_in )) != (char) EOF && c != '"' && i < size - 1 ) { str[i++] = c; } str[i] = '\0'; TRC_CKEOF( c, "EOF Reading Trace String\n", return( TRC_FALSE ) ); if ( c != '"' ) { if ( !trc_find_event_str( ID, "\"" ) ) return( TRC_FALSE ); } if ( end_flag ) { /* Matching { */ if ( !trc_find_event_str( ID, "}" ) ) return( TRC_FALSE ); } return( TRC_TRUE ); } void trc_dump_old_sddf_headers() { int i; printf( "\n" ); printf( "XPVM Trace Format Descriptors for PVM 3.3 - SDDF:\n" ); printf( "=================================================\n" ); for ( i=TRC_OLD_TEV_FIRST ; i < TRC_OLD_TRACE_MAX ; i++ ) { if ( strcmp( TRC_OLD_TRACE_DESCRIPTORS[i], "" ) ) { printf( "\n#%d: %s\n", i + 1, TRC_OLD_TRACE_DESCRIPTORS[i] ); } } exit( 0 ); } void trc_reset_old_descriptors() { int i; for ( i=TRC_OLD_TEV_FIRST ; i < TRC_OLD_TRACE_MAX ; i++ ) TRC_OLD_TEV_TRACE[i] = 0; } ./pvm3/tracer/trccompatglob.c0100644007401100000360000015764206236210164015403 0ustar kohlgopher static char rcsid[] = "$Id: trccompatglob.c,v 4.1 1996/10/31 20:47:48 pvmsrc Exp $"; /* * Tracer version 1.0: A Trace File Generator for PVM * Oak Ridge National Laboratory, Oak Ridge TN. * Authors: James Arthur Kohl and G. A. Geist * (C) 1994 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear * in supporting documentation. * * Neither the Institution, Oak Ridge National Laboratory, nor the * Authors make any representations about the suitability of this * software for any purpose. This software is provided ``as is'' * without express or implied warranty. * * Tracer was funded by the U.S. Department of Energy. */ /* Tracer Library Header */ #include "trclib.h" #include "trccompat.h" /* Old PVM 3.3 Trace Event Descriptors */ char *TRC_OLD_TRACE_DESCRIPTORS[TRC_OLD_TRACE_MAX] = { "\"addhosts0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Count\" \"Number of Hosts to Add\"\n\ int \"count\";\n\ // \"Names\" \"Names of Hosts to Add\"\n\ char \"names\"[][];\n\ };;\n", "\"addhosts1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"barrier0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Group\" \"Name of Group\"\n\ char \"group\"[];\n\ // \"Count\" \"Number of Members to Wait\"\n\ int \"count\";\n\ };;\n", "\"barrier1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"bcast0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Group\" \"Name of Group\"\n\ char \"group\"[];\n\ // \"Code\" \"Message Type\"\n\ int \"code\";\n\ };;\n", "\"bcast1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"bufinfo0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"MID\" \"Message Buffer\"\n\ int \"mid\";\n\ };;\n", "\"bufinfo1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ // \"Length\" \"Number of Bytes\"\n\ int \"length\";\n\ // \"Code\" \"Message Type\"\n\ int \"code\";\n\ // \"Src\" \"Message Source TID\"\n\ int \"src\";\n\ };;\n", "\"config0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"config1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ // \"Nhost\" \"Number of Hosts\"\n\ int \"nhost\";\n\ // \"Narch\" \"Number of Architectures\"\n\ int \"narch\";\n\ };;\n", "\"delete0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Name\" \"Class Name\"\n\ char \"name\"[];\n\ // \"Req\" \"Class Index\"\n\ int \"req\";\n\ };;\n", "\"delete1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"delhosts0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Count\" \"Number of Hosts to Delete\"\n\ int \"count\";\n\ // \"Names\" \"Names of Hosts to Delete\"\n\ char \"names\"[][];\n\ };;\n", "\"delhosts1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"exit0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"exit1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"freebuf0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"MID\" \"Message Buffer\"\n\ int \"mid\";\n\ };;\n", "\"freebuf1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"getfds0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"getfds1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"NFDS\" \"# of File Descriptors\"\n\ int \"nfds\";\n\ // \"FDS\" \"File Descriptors\"\n\ int \"fds\"[];\n\ };;\n", "\"getinst0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Group\" \"Name of Group\"\n\ char \"group\"[];\n\ // \"Instance\" \"Instance Number in Group\"\n\ int \"instance\";\n\ };;\n", "\"getinst1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"getopt0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Option\" \"Option Code\"\n\ int \"option\";\n\ };;\n", "\"getopt1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"getrbuf0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"getrbuf1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"getsbuf0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"getsbuf1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"gettid0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Group\" \"Name of Group\"\n\ char \"group\"[];\n\ // \"Instance\" \"Instance Number in Group\"\n\ int \"instance\";\n\ };;\n", "\"gettid1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"gsize0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Group\" \"Name of Group\"\n\ char \"group\"[];\n\ };;\n", "\"gsize1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"halt0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"halt1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"initsend0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Encoding\" \"Message Encoding\"\n\ int \"encoding\";\n\ };;\n", "\"initsend1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"insert0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Name\" \"Class Name\"\n\ char \"name\"[];\n\ // \"Req\" \"Class Index\"\n\ int \"req\";\n\ // \"Data\" \"Data for Insert\"\n\ int \"data\";\n\ };;\n", "\"insert1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"joingroup0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Group\" \"Name of Group\"\n\ char \"group\"[];\n\ };;\n", "\"joingroup1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"kill0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Dst\" \"Destination Task ID\"\n\ int \"dst\";\n\ };;\n", "\"kill1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"lookup0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Name\" \"Class Name\"\n\ char \"name\"[];\n\ // \"Req\" \"Class Index\"\n\ int \"req\";\n\ };;\n", "\"lookup1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"lvgroup0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Group\" \"Name of Group\"\n\ char \"group\"[];\n\ };;\n", "\"lvgroup1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"mcast0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Count\" \"Number of Tasks\"\n\ int \"count\";\n\ // \"Code\" \"Message Type\"\n\ int \"code\";\n\ // \"TIDs\" \"Destination Task IDs\"\n\ int \"tids\"[];\n\ };;\n", "\"mcast1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"mkbuf0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Encoding\" \"Message Encoding\"\n\ int \"encoding\";\n\ };;\n", "\"mkbuf1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"mstat0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Host\" \"Name of Host\"\n\ char \"host\"[];\n\ };;\n", "\"mstat1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"mytid0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"mytid1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"notify0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"What\" \"Specific Notify Event\"\n\ int \"what\";\n\ // \"Code\" \"Notify Code\"\n\ int \"code\";\n\ // \"Count\" \"Notify Count\"\n\ int \"count\";\n\ // \"Val\" \"Notify Values\"\n\ int \"vals\"[];\n\ };;\n", "\"notify1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"nrecv0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Src\" \"Message Source TID\"\n\ int \"src\";\n\ // \"Code\" \"Message Type\"\n\ int \"code\";\n\ };;\n", "\"nrecv1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ // \"Nbytes\" \"Number of Bytes Received\"\n\ int \"nbytes\";\n\ // \"Code\" \"Message Type\"\n\ int \"code\";\n\ // \"Src\" \"Message Source TID\"\n\ int \"src\";\n\ };;\n", "\"parent0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"parent1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"perror0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"LocStr\" \"Error Location String\"\n\ char \"locstr\"[];\n\ };;\n", "\"perror1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"pkbyte0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Pack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Pack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"pkbyte1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"pkcplx0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Pack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Pack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"pkcplx1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"pkdcplx0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Pack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Pack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"pkdcplx1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"pkdouble0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Pack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Pack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"pkdouble1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"pkfloat0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Pack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Pack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"pkfloat1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"pkint0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Pack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Pack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"pkint1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"pkuint0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Pack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Pack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"pkuint1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"pklong0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Pack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Pack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"pklong1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"pkulong0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Pack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Pack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"pkulong1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"pkshort0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Pack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Pack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"pkshort1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"pkushort0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Pack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Pack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"pkushort1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"pkstr0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Pack\"\n\ int \"addr\";\n\ };;\n", "\"pkstr1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"probe0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Src\" \"Message Source TID\"\n\ int \"src\";\n\ // \"Code\" \"Message Type\"\n\ int \"code\";\n\ };;\n", "\"probe1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"pstat0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Dst\" \"TID of Task to Pstat\"\n\ int \"dst\";\n\ };;\n", "\"pstat1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"recv0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Src\" \"Message Source TID\"\n\ int \"src\";\n\ // \"Code\" \"Message Type\"\n\ int \"code\";\n\ };;\n", "\"recv1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ // \"Nbytes\" \"Number of Bytes Received\"\n\ int \"nbytes\";\n\ // \"Code\" \"Message Type\"\n\ int \"code\";\n\ // \"Src\" \"Message Source TID\"\n\ int \"src\";\n\ };;\n", "\"recvf0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"recvf1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"send0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Dst\" \"Message Destination TID\"\n\ int \"dst\";\n\ // \"Code\" \"Message Type\"\n\ int \"code\";\n\ };;\n", "\"send1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"sendsig0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Dst\" \"Signal Destination TID\"\n\ int \"dst\";\n\ // \"Sig\" \"Signal Number to Raise\"\n\ int \"sig\";\n\ };;\n", "\"sendsig1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"setopt0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"What\" \"Option to Set\"\n\ int \"what\";\n\ // \"Value\" \"Value to Set Option\"\n\ int \"val\";\n\ };;\n", "\"setopt1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"setrbuf0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"MID\" \"Message Buffer\"\n\ int \"mid\";\n\ };;\n", "\"setrbuf1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"setsbuf0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"MID\" \"Message Buffer\"\n\ int \"mid\";\n\ };;\n", "\"setsbuf1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"spawn0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"File\" \"Executable File\"\n\ char \"file\"[];\n\ // \"Flags\" \"Spawn Flags\"\n\ int \"flags\";\n\ // \"Where\" \"Host or Arch for Spawn\"\n\ char \"where\"[];\n\ // \"Count\" \"Number of Tasks to Spawn\"\n\ int \"count\";\n\ };;\n", "\"spawn1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"NTID\" \"Number of TIDs Spawned\"\n\ int \"cc\";\n\ // \"TIDs\" \"Task IDs of Spawned Tasks\"\n\ int \"tids\"[];\n\ };;\n", "\"start_pvmd0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Argc\" \"Number of Args\"\n\ int \"argc\";\n\ // \"Argv\" \"Argument Strings\"\n\ char \"argv\"[][];\n\ // \"Block\" \"Block Flag\"\n\ int \"block\";\n\ };;\n", "\"start_pvmd1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"tasks0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Where\" \"Which Hosts to Check\"\n\ int \"where\";\n\ };;\n", "\"tasks1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ // \"Ntask\" \"Number of Tasks Found\"\n\ int \"ntask\";\n\ };;\n", "\"tickle0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Narg\" \"Number of Arguments\"\n\ int \"narg\";\n\ // \"Args\" \"Argument Array\"\n\ int \"args\"[];\n\ };;\n", "\"tickle1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ // \"Nres\" \"Number of Responses\"\n\ int \"nres\";\n\ };;\n", "\"tidtohost0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"tidtohost1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"trecv0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Src\" \"Message Source TID\"\n\ int \"src\";\n\ // \"Code\" \"Message Type\"\n\ int \"code\";\n\ };;\n", "\"trecv1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ // \"Nbytes\" \"Number of Bytes Received\"\n\ int \"nbytes\";\n\ // \"Code\" \"Message Type\"\n\ int \"code\";\n\ // \"Src\" \"Message Source TID\"\n\ int \"src\";\n\ };;\n", "\"upkbyte0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Unpack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Unpack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"upkbyte1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"upkcplx0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Unpack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Unpack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"upkcplx1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"upkdcplx0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Unpack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Unpack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"upkdcplx1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"upkdouble0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Unpack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Unpack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"upkdouble1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"upkfloat0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Unpack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Unpack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"upkfloat1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"upkint0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Unpack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Unpack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"upkint1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"upkuint0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Unpack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Unpack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"upkuint1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"upklong0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Unpack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Unpack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"upklong1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"upkulong0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Unpack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Unpack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"upkulong1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"upkshort0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Unpack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Unpack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"upkshort1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"upkushort0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Unpack\"\n\ int \"addr\";\n\ // \"Count\" \"Number of Items to Unpack\"\n\ int \"count\";\n\ // \"Stride\" \"Stride Among Items\"\n\ int \"stride\";\n\ };;\n", "\"upkushort1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"upkstr0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Address\" \"Address of Stuff to Unpack\"\n\ int \"addr\";\n\ };;\n", "\"upkstr1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"version0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"version1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Version\" \"PVM Version String\"\n\ char \"version\"[];\n\ };;\n", "\"reg_hoster0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"reg_hoster1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"reg_rm0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"reg_rm1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"reg_tasker0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"reg_tasker1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"newtask\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"PTID\" \"Parent Task ID\"\n\ int \"ptid\";\n\ // \"Host\" \"PVMD TID of Host\"\n\ int \"host\";\n\ // \"Flags\" \"Task Spawn Flags\"\n\ int \"flags\";\n\ // \"Aout\" \"Executable File\"\n\ char \"aout\"[];\n\ };;\n", "", "\"endtask\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Status\" \"Task Exit Status\"\n\ int \"status\";\n\ // \"Usec\" \"User Usage Secs\"\n\ int \"usersec\";\n\ // \"Uusec\" \"User Usage Usecs\"\n\ int \"userusec\";\n\ // \"Ssec\" \"System Usage Secs\"\n\ int \"syssec\";\n\ // \"Susec\" \"System Usage Usecs\"\n\ int \"sysusec\";\n\ };;\n", "", "\"spntask\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Parent\" \"Parent Task ID\"\n\ int \"parent\";\n\ };;\n", "", "\"archcode0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"archcode1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"catchout0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"catchout1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"getmwid0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"MID\" \"Message Buffer\"\n\ int \"mid\";\n\ };;\n", "\"getmwid1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"gettmask0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"gettmask1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"hostsync0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"hostsync1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"packf0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Format\" \"Format String\"\n\ char \"fmt\"[];\n\ };;\n", "\"packf1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"precv0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Src\" \"Message Source TID\"\n\ int \"src\";\n\ // \"Code\" \"Message Type\"\n\ int \"code\";\n\ // \"Address\" \"Address of Stuff to Pack\"\n\ int \"addr\";\n\ // \"Length\" \"Number of Bytes\"\n\ int \"length\";\n\ // \"Type\" \"Data Type to Which Buffer Points\"\n\ int \"type\";\n\ };;\n", "\"precv1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"psend0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Dst\" \"Message Destination TID\"\n\ int \"dst\";\n\ // \"Code\" \"Message Type\"\n\ int \"code\";\n\ // \"Address\" \"Address of Stuff to Pack\"\n\ int \"addr\";\n\ // \"Length\" \"Number of Bytes\"\n\ int \"length\";\n\ // \"Type\" \"Data Type to Which Buffer Points\"\n\ int \"type\";\n\ };;\n", "\"psend1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"reduce0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Group\" \"Name of Group\"\n\ char \"group\"[];\n\ // \"Code\" \"Message Type\"\n\ int \"code\";\n\ };;\n", "\"reduce1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"setmwid0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"MID\" \"Message Buffer\"\n\ int \"mid\";\n\ // \"WID\" \"Wait Message ID\"\n\ int \"wid\";\n\ };;\n", "\"setmwid1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"settmask0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"settmask1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ };;\n", "\"unpackf0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Format\" \"Format String\"\n\ char \"fmt\"[];\n\ };;\n", "\"unpackf1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"gather0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Group\" \"Name of Group\"\n\ char \"group\"[];\n\ // \"Code\" \"Message Type\"\n\ int \"code\";\n\ };;\n", "\"gather1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"scatter0\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Group\" \"Name of Group\"\n\ char \"group\"[];\n\ // \"Code\" \"Message Type\"\n\ int \"code\";\n\ };;\n", "\"scatter1\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"CC\" \"Condition Code\"\n\ int \"cc\";\n\ };;\n", "\"output\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Task ID\"\n\ int \"tid\";\n\ // \"Out\" \"Task Output\"\n\ char \"out\"[];\n\ };;\n", "\"host_add\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Host PVMD Task ID\"\n\ int \"tid\";\n\ // \"Name\" \"Host Name\"\n\ char \"name\"[];\n\ // \"Alias\" \"Host Alias\"\n\ char \"alias\"[];\n\ // \"Arch\" \"Host Arch\"\n\ char \"arch\"[];\n\ // \"Speed\" \"Relative Host Speed\"\n\ int \"speed\";\n\ };;\n", "\"host_del\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Host PVMD Task ID\"\n\ int \"tid\";\n\ // \"Name\" \"Host Name\"\n\ char \"name\"[];\n\ };;\n", "\"host_sync\"\n\ {\n\ // \"Time\" \"Seconds\"\n\ int \"sec\";\n\ // \"Time\" \"Micro Seconds\"\n\ int \"usec\";\n\ // \"TID\" \"Host PVMD Task ID\"\n\ int \"tid\";\n\ // \"DSec\" \"Host Clock Synchronization Delta Seconds\"\n\ int \"dsec\";\n\ // \"DUSec\" \"Host Clock Synchronization Delta Microseconds\"\n\ int \"dusec\";\n\ };;\n" }; /* Old PVM 3.3 Trace Event Names */ char *TRC_OLD_TEV_TRACE_NAMES[TRC_OLD_TRACE_MAX] = { "addhosts0", "addhosts1", "barrier0", "barrier1", "bcast0", "bcast1", "bufinfo0", "bufinfo1", "config0", "config1", "delete0", "delete1", "delhosts0", "delhosts1", "exit0", "exit1", "freebuf0", "freebuf1", "getfds0", "getfds1", "getinst0", "getinst1", "getopt0", "getopt1", "getrbuf0", "getrbuf1", "getsbuf0", "getsbuf1", "gettid0", "gettid1", "gsize0", "gsize1", "halt0", "halt1", "initsend0", "initsend1", "insert0", "insert1", "joingroup0", "joingroup1", "kill0", "kill1", "lookup0", "lookup1", "lvgroup0", "lvgroup1", "mcast0", "mcast1", "mkbuf0", "mkbuf1", "mstat0", "mstat1", "mytid0", "mytid1", "notify0", "notify1", "nrecv0", "nrecv1", "parent0", "parent1", "perror0", "perror1", "pkbyte0", "pkbyte1", "pkcplx0", "pkcplx1", "pkdcplx0", "pkdcplx1", "pkdouble0", "pkdouble1", "pkfloat0", "pkfloat1", "pkint0", "pkint1", "pkuint0", "pkuint1", "pklong0", "pklong1", "pkulong0", "pkulong1", "pkshort0", "pkshort1", "pkushort0", "pkushort1", "pkstr0", "pkstr1", "probe0", "probe1", "pstat0", "pstat1", "recv0", "recv1", "recvf0", "recvf1", "send0", "send1", "sendsig0", "sendsig1", "setopt0", "setopt1", "setrbuf0", "setrbuf1", "setsbuf0", "setsbuf1", "spawn0", "spawn1", "start_pvmd0", "start_pvmd1", "tasks0", "tasks1", "tickle0", "tickle1", "tidtohost0", "tidtohost1", "trecv0", "trecv1", "upkbyte0", "upkbyte1", "upkcplx0", "upkcplx1", "upkdcplx0", "upkdcplx1", "upkdouble0", "upkdouble1", "upkfloat0", "upkfloat1", "upkint0", "upkint1", "upkuint0", "upkuint1", "upklong0", "upklong1", "upkulong0", "upkulong1", "upkshort0", "upkshort1", "upkushort0", "upkushort1", "upkstr0", "upkstr1", "version0", "version1", "reg_hoster0", "reg_hoster1", "reg_rm0", "reg_rm1", "reg_tasker0", "reg_tasker1", "newtask", "", "endtask", "", "spntask", "", "archcode0", "archcode1", "catchout0", "catchout1", "getmwid0", "getmwid1", "gettmask0", "gettmask1", "hostsync0", "hostsync1", "packf0", "packf1", "precv0", "precv1", "psend0", "psend1", "reduce0", "reduce1", "setmwid0", "setmwid1", "settmask0", "settmask1", "unpackf0", "unpackf1", "gather0", "gather1", "scatter0", "scatter1", "output", "host_add", "host_del", "host_sync", }; /* Old PVM 3.3 Trace Event Formats */ struct trc_old_tevfmt trc_old_tev_formats[] = { { "pvm_addhosts0", "(%*d, [%$0S])" }, { "pvm_addhosts1", "=%R" }, { "pvm_barrier0", "(%S, %d)" }, { "pvm_barrier1", "=%R" }, { "pvm_bcast0", "(%S, %d)" }, { "pvm_bcast1", "=%R" }, { "pvm_bufinfo0", "(%d)" }, { "pvm_bufinfo1", "=%R, %d, %d, %d" }, { "pvm_config0", "()" }, { "pvm_config1", "=%R, %d, %d" }, { "pvm_delete0", "(%S, %d)" }, { "pvm_delete1", "=%R" }, { "pvm_delhosts0", "(%*d, [%$0S])" }, { "pvm_delhosts1", "=%R" }, { "pvm_exit0", "()" }, { "pvm_exit1", 0 }, { "pvm_freebuf0", "(%d)" }, { "pvm_freebuf1", "=%R" }, { "pvm_getfds0", "()" }, { "pvm_getfds1", "=%*R [%$0d]" }, { "pvm_getinst0", "(%S, %d)" }, { "pvm_getinst1", "=%R" }, { "pvm_getopt0", "(%d)" }, { "pvm_getopt1", "=%R" }, { "pvm_getrbuf0", "()" }, { "pvm_getrbuf1", "=%R" }, { "pvm_getsbuf0", "()" }, { "pvm_getsbuf1", "=%R" }, { "pvm_gettid0", "(%S, %d)" }, { "pvm_gettid1", "=%R" }, { "pvm_gsize0", "(%S)" }, { "pvm_gsize1", "=%R" }, { "pvm_halt0", "()" }, { "pvm_halt1", 0 }, { "pvm_initsend0", "(%d)" }, { "pvm_initsend1", "=%R" }, { "pvm_insert0", "(%S, %d, %x)" }, { "pvm_insert1", "=%R" }, { "pvm_joingroup0", "(%S)" }, { "pvm_joingroup1", "=%R" }, { "pvm_kill0", "(%x)" }, { "pvm_kill1", "=%R" }, { "pvm_lookup0", "(%S, %d)" }, { "pvm_lookup1", "=%R" }, { "pvm_lvgroup0", "(%S)" }, { "pvm_lvgroup1", "=%R" }, { "pvm_mcast0", "(%*d, %d, [%$0x])" }, { "pvm_mcast1", "=%R" }, { "pvm_mkbuf0", "(%d)" }, { "pvm_mkbuf1", "=%R" }, { "pvm_mstat0", "(%S)" }, { "pvm_mstat1", "=%R" }, { "pvm_mytid0", "()" }, { "pvm_mytid1", "=%r" }, { "pvm_notify0", "(%d, %d, %d, ...)" }, { "pvm_notify1", "=%R" }, { "pvm_nrecv0", "(%x, %d)" }, { "pvm_nrecv1", "=%R, ..." }, { "pvm_parent0", "()" }, { "pvm_parent1", "=%r" }, { "pvm_perror0", "(%S %d)" }, { "pvm_perror1", 0 }, { "pvm_pkbyte0", "(%x, %d, %d)" }, { "pvm_pkbyte1", "=%R" }, { "pvm_pkcplx0", "(%x, %d, %d)" }, { "pvm_pkcplx1", "=%R" }, { "pvm_pkdcplx0", "(%x, %d, %d)" }, { "pvm_pkdcplx1", "=%R" }, { "pvm_pkdouble0", "(%x, %d, %d)" }, { "pvm_pkdouble1", "=%R" }, { "pvm_pkfloat0", "(%x, %d, %d)" }, { "pvm_pkfloat1", "=%R" }, { "pvm_pkint0", "(%x, %d, %d)" }, { "pvm_pkint1", "=%R" }, { "pvm_pkuint0", "(%x, %d, %d)" }, { "pvm_pkuint1", "=%R" }, { "pvm_pklong0", "(%x, %d, %d)" }, { "pvm_pklong1", "=%R" }, { "pvm_pkulong0", "(%x, %d, %d)" }, { "pvm_pkulong1", "=%R" }, { "pvm_pkshort0", "(%x, %d, %d)" }, { "pvm_pkshort1", "=%R" }, { "pvm_pkushort0", "(%x, %d, %d)" }, { "pvm_pkushort1", "=%R" }, { "pvm_pkstr0", "(%x)" }, { "pvm_pkstr1", "=%R" }, { "pvm_probe0", "(%x, %d)" }, { "pvm_probe1", "=%R" }, { "pvm_pstat0", "(%x)" }, { "pvm_pstat1", "=%R" }, { "pvm_recv0", "(%x, %d)" }, { "pvm_recv1", "=%R, %d, ..." }, { "pvm_recvf0", "(...)" }, { "pvm_recvf1", 0 }, { "pvm_send0", "(%x, %d)" }, { "pvm_send1", "=%R" }, { "pvm_sendsig0", "(%x, %d)" }, { "pvm_sendsig1", "=%R" }, { "pvm_setopt0", "(%d, %d)" }, { "pvm_setopt1", "=%R" }, { "pvm_setrbuf0", "(%d)" }, { "pvm_setrbuf1", "=%R" }, { "pvm_setsbuf0", "(%d)" }, { "pvm_setsbuf1", "=%R" }, { "pvm_spawn0", "(%S, ?, %d, %S, %d, ...)" }, { "pvm_spawn1", "=%*R [%$0r]" }, { "pvm_start_pvmd0","%d, %d, ..." }, { "pvm_start_pvmd1","=%R" }, { "pvm_tasks0", "(%x)" }, { "pvm_tasks1", "=%R, %d" }, { "pvm_tickle0", "(%*d, [%$0d])" }, { "pvm_tickle1", "=%R, %d" }, { "pvm_tidtohost0", "(%x)" }, { "pvm_tidtohost1", "=%r" }, { "pvm_trecv0", "(%x, %d, [%d %d])" }, { "pvm_trecv1", "=%R, %d, ..." }, { "pvm_upkbyte0", "(%x, %d, %d)" }, { "pvm_upkbyte1", "=%R" }, { "pvm_upkcplx0", "(%x, %d, %d)" }, { "pvm_upkcplx1", "=%R" }, { "pvm_upkdcplx0", "(%x, %d, %d)" }, { "pvm_upkdcplx1", "=%R" }, { "pvm_upkdouble0", "(%x, %d, %d)" }, { "pvm_upkdouble1", "=%R" }, { "pvm_upkfloat0", "(%x, %d, %d)" }, { "pvm_upkfloat1", "=%R" }, { "pvm_upkint0", "(%x, %d, %d)" }, { "pvm_upkint1", "=%R" }, { "pvm_upkuint0", "(%x, %d, %d)" }, { "pvm_upkuint1", "=%R" }, { "pvm_upklong0", "(%x, %d, %d)" }, { "pvm_upklong1", "=%R" }, { "pvm_upkulong0", "(%x, %d, %d)" }, { "pvm_upkulong1", "=%R" }, { "pvm_upkshort0", "(%x, %d, %d)" }, { "pvm_upkshort1", "=%R" }, { "pvm_upkushort0", "(%x, %d, %d)" }, { "pvm_upkushort1", "=%R" }, { "pvm_upkstr0", "(%x)" }, { "pvm_upkstr1", "=%R" }, { "pvm_version0", "()" }, { "pvm_version1", "=%S" }, { "pvm_reg_hoster0", "()" }, { "pvm_reg_hoster1", "=%R" }, { "pvm_reg_rm0", "()" }, { "pvm_reg_rm1", "=%R" }, { "pvm_reg_tasker0", "()" }, { "pvm_reg_tasker1", "=%R" }, { "newtask", " %x, %d, %S" }, { "", 0 }, { "endtask", " %x u %d,%d s %d,%d" }, { "", 0 }, { "spntask", " %x" }, { "", 0 }, { "pvm_archcode0", 0 /*"(%S)"*/ }, { "pvm_archcode1", 0 /*"=%R"*/ }, { "pvm_catchout0", 0 /*"(...)"*/ }, { "pvm_catchout1", 0 /*"=%R"*/ }, { "pvm_getmwid0", "(%d)" }, { "pvm_getmwid1", "=%R" }, { "pvm_gettmask0", 0 /*"(%d, )"*/ }, { "pvm_gettmask1", 0 /*"=%R"*/ }, { "pvm_hostsync0", 0 /*"(%d, ...)"*/ }, { "pvm_hostsync1", 0 /*"=%R"*/ }, { "pvm_packf0", "(%S, ...)" }, { "pvm_packf1", "=%R" }, { "pvm_precv0", "(%x, %d, %x, %d, %d, ...)" }, { "pvm_precv1", "=%R" }, { "pvm_psend0", "(%x, %d, %x, %d, %d)" }, { "pvm_psend1", "=%R" }, { "pvm_reduce0", 0 /*"(...)"*/ }, { "pvm_reduce1", 0 /*"=%R"*/ }, { "pvm_setmwid0", "(%d, %d)" }, { "pvm_setmwid1", "=%R" }, { "pvm_settmask0", 0 /*"(%d, %S)"*/ }, { "pvm_settmask1", 0 /*"=%R"*/ }, { "pvm_unpackf0", "(%S, ...)" }, { "pvm_unpackf1", "=%R" }, { "pvm_gather0", 0 }, { "pvm_gather1", 0 }, { "pvm_scatter0", 0 }, { "pvm_scatter1", 0 } }; /* Old PVM 3.3 Trace Event Descriptor Flags */ int TRC_OLD_TEV_TRACE[TRC_OLD_TRACE_MAX]; /* Old PVM 3.3 Error Messages for -pvm_errno */ char *trc_old_pvm_errlist[] = { "Error 0", "Error 1", "Bad parameter", "Count mismatch", "Value too large", "End of buffer", "No such host", "No such file", "Error 8", /* not used */ "Error 9", /* not used */ "Malloc failed", "Error 11", /* not used */ "Can't decode message", "Error 13", /* not used */ "Can't contact local daemon", "No current buffer", "No such buffer", "Null group name", "Already in group", "No such group", "Not in group", "No such instance", "Host failed", "No parent task", "Not implemented", "Pvmd system error", "Version mismatch", "Out of resources", "Duplicate host", "Can't start pvmd", "Already in progress", "No such task", "No such entry", "Duplicate entry", }; /* Old PVM 3.3 Exported Num of Errors */ int trc_old_pvm_nerr = sizeof(trc_old_pvm_errlist) / sizeof(trc_old_pvm_errlist[0]); #ifdef USE_PVM_33 /* Reverse Compatibility Declarations for PVM 3.3 */ struct Pvmtevinfo pvmtevinfo[] = { "dummy", 0, { 0, 0 }, { 0, 0 }, 0 }; struct Pvmtevdid pvmtevdidlist[] = { "XXX", "Dummy" }; #endif ./pvm3/tracer/trcfile.c0100644007401100000360000017223206617341515014173 0ustar kohlgopher static char rcsid[] = "$Id: trcfile.c,v 4.15 1998/11/02 14:35:57 pvmsrc Exp $"; /* * Tracer version 1.0: A Trace File Generator for PVM * Oak Ridge National Laboratory, Oak Ridge TN. * Authors: James Arthur Kohl and G. A. Geist * (C) 1994 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear * in supporting documentation. * * Neither the Institution, Oak Ridge National Laboratory, nor the * Authors make any representations about the suitability of this * software for any purpose. This software is provided ``as is'' * without express or implied warranty. * * Tracer was funded by the U.S. Department of Energy. */ /* Tracer Library Header */ #include "trclib.h" #ifdef SYSVSTR #include #else #include #endif /* Trace Lookup Trie Init Routines */ void trc_init_did_trie() { TRC_DID dptr; int i; TRC_DID_TRIE = trc_create_triestack(); for ( i=TEV_DID_FIRST ; i <= TEV_DID_MAX ; i++ ) { dptr = trc_create_did(); dptr->id = i; dptr->name = trc_copy_str( pvmtevdidlist[i].did ); dptr->desc = trc_copy_str( pvmtevdidlist[i].desc ); dptr->next = TRC_DID_LIST; TRC_DID_LIST = dptr; trc_add_to_trie( TRC_DID_TRIE, dptr->name, (void *) dptr ); TRC_LOCAL_DID[i] = dptr; } } /* Trace File Generation Routines */ void trc_set_didlist( H, D ) TRC_HOST H; TRC_DID D; { if ( H != NULL ) { trc_check_listsize( &(H->didlist), &(H->didsize), D->id ); H->didlist[ D->id ] = (void *) D; } else printf( "Error: No Host for TEV Semantic Identifier List\n" ); } TRC_DID trc_get_did( H, id ) TRC_HOST H; int id; { TRC_DID D; D = (TRC_DID) NULL; /* Use Host Lookup */ if ( H != NULL && H->didlist != NULL && id < H->didsize ) D = (TRC_DID) (H->didlist[ id ]); /* Use Default Local Lookup */ else if ( id >= TEV_DID_FIRST && id <= TEV_DID_MAX ) D = TRC_LOCAL_DID[ id ]; return( D ); } int trc_add_tevdesc( ID, TDptr, tid, omit ) TRC_ID ID; TRC_TEVDESC *TDptr; int tid; int omit; { TRC_TEVDESC *newlist; TRC_TEVDESC tdptr; TRC_TEVDESC last; int newsize; int index; int eid; int i; /* Verify Descriptor List is Large Enough */ eid = (*TDptr)->eid; if ( eid >= TRC_TEVDESC_SIZE ) { newsize = 2 * ( eid + 1 ); newlist = (TRC_TEVDESC *) malloc( (unsigned) newsize * sizeof( TRC_TEVDESC ) ); trc_memcheck( newlist, "New TRC_TEVDESC Pointer List" ); for ( i=0 ; i < TRC_TEVDESC_SIZE ; i++ ) { newlist[i] = TRC_TEVDESC_LIST[i]; TRC_TEVDESC_LIST[i] = (TRC_TEVDESC) NULL; } i = ( TRC_TEVDESC_SIZE >= 0 ) ? TRC_TEVDESC_SIZE : 0; while ( i < newsize ) { newlist[i] = (TRC_TEVDESC) NULL; i++; } free( TRC_TEVDESC_LIST ); TRC_TEVDESC_LIST = newlist; TRC_TEVDESC_SIZE = newsize; } /* Search for Existing Descriptor */ tdptr = TRC_TEVDESC_LIST[ eid ]; last = (TRC_TEVDESC) NULL; index = 0; while ( tdptr != NULL ) { if ( trc_cmp_tevdesc( *TDptr, tdptr ) ) { if ( !omit && tdptr->dump && ID != NULL ) trc_dump_tevdesc( ID, tdptr, tid ); (*TDptr)->index = tdptr->index; if ( ID != NULL ) trc_store_data_values( ID, *TDptr, tid, omit ); trc_free_tevdesc( TDptr ); *TDptr = tdptr; (tdptr->refcount)++; return( TRC_FALSE ); } index++; last = tdptr; tdptr = tdptr->next; } /* Add New Descriptor */ if ( last != NULL ) last->next = *TDptr; else TRC_TEVDESC_LIST[ eid ] = *TDptr; (*TDptr)->index = index; if ( omit ) (*TDptr)->dump = TRC_FALSE; else (*TDptr)->dump = TRC_TRUE; return( TRC_TRUE ); } void trc_set_tevlist( TT, H, TD ) TRC_TEVTASK TT; TRC_HOST H; TRC_TEVDESC TD; { if ( TT != NULL ) { trc_check_listsize( &(TT->tevlist), &(TT->tevsize), TRC_TEVINDEX_OF( TD->eid, TRC_MAX_TEV ) ); TT->tevlist[ TRC_TEVINDEX_OF( TD->eid, TD->entry_exit ) ] = (void *) TD; } else if ( H != NULL ) { trc_check_listsize( &(H->tevlist), &(H->tevsize), TRC_TEVINDEX_OF( TD->eid, TRC_MAX_TEV ) ); H->tevlist[ TRC_TEVINDEX_OF( TD->eid, TD->entry_exit ) ] = (void *) TD; } else printf( "Error: No Task or Host for TEV Index List\n" ); } TRC_TEVDESC trc_get_tevdesc( TT, H, eid, entry_exit ) TRC_TEVTASK TT; TRC_HOST H; int eid; int entry_exit; { TRC_TEVDESC TD; if ( TT != NULL ) { TD = (TRC_TEVDESC) (TT->tevlist[ TRC_TEVINDEX_OF(eid,entry_exit) ]); } else if ( H != NULL ) { TD = (TRC_TEVDESC) (H->tevlist[ TRC_TEVINDEX_OF(eid,entry_exit) ]); } else TD = (TRC_TEVDESC) NULL; return( TD ); } void trc_dump_tevdesc( ID, TD, tid ) TRC_ID ID; TRC_TEVDESC TD; int tid; { TRC_DATADESC DD; TRC_DID D; int user_defined; int dummy; if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, tid ); fprintf( ID->trace_out, "\n" ); if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, tid ); if ( TD->index >= 0 ) { fprintf( ID->trace_out, "#%d: \"%s(", /* ) */ ( 1000 * ( TD->index + 1 ) ) + ( 2 * TD->eid ) + ( ( TD->entry_exit == TRC_EXIT_TEV ) ? 1 : 0 ), TD->name ); if ( TD->entry_exit == TRC_ENTRY_TEV ) fprintf( ID->trace_out, "0." ); else if ( TD->entry_exit == TRC_EXIT_TEV ) fprintf( ID->trace_out, "1." ); fprintf( ID->trace_out, "%d", TD->index ); fprintf( ID->trace_out, /* ( */ ")\"\n" ); } else fprintf( ID->trace_out, "#%d: \"%s\"\n", TD->eid, TD->name ); if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, tid ); fprintf( ID->trace_out, "{\n" ); if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, tid ); /* Sneak in Task ID for User Defined Events */ user_defined = !strcmp( TD->name, "user_defined" ); if ( user_defined ) { D = trc_get_did( (TRC_HOST) NULL, TEV_DID_TID ); fprintf( ID->trace_out, "\t// \"%s\" \"%s\"\n", D->name, D->desc ); if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, tid ); fprintf( ID->trace_out, "\t%s \"%s\";\n", TRC_TYPE_STRS[ TEV_DATA_INT ], D->name ); if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, tid ); } /* Dump (Remainder) of Descriptor */ DD = TD->ddesc; dummy = 0; while ( DD != NULL ) { if ( !user_defined || DD->did != NULL ) { fprintf( ID->trace_out, "\t// \"%s\" \"%s\"\n", DD->did->name, DD->did->desc ); } else { fprintf( ID->trace_out, "\t// \"USR%d\" \"User Defined Value #%d\"\n", dummy, dummy ); } if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, tid ); if ( !user_defined || DD->did != NULL ) { fprintf( ID->trace_out, "\t%s \"%s\"", TRC_TYPE_STRS[ DD->dt ], DD->did->name ); } else { fprintf( ID->trace_out, "\t%s \"USR%d\"", TRC_TYPE_STRS[ DD->dt ], dummy ); dummy++; } if ( DD->array == TEV_DATA_ARRAY ) fprintf( ID->trace_out, "[]" ); if ( DD->dt == TEV_DATA_STRING ) fprintf( ID->trace_out, "[]" ); fprintf( ID->trace_out, ";\n" ); if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, tid ); DD = DD->next; } fprintf( ID->trace_out, "};;\n" ); if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, tid ); fprintf( ID->trace_out, "\n" ); TD->dump = TRC_FALSE; } void trc_check_listsize( list, size, index ) void ***list; int *size; int index; { void **newlist; int newsize; int i; if ( index >= *size ) { newsize = 2 * index; newsize = newsize ? newsize : 100; newlist = (void **) malloc( (unsigned) newsize * sizeof(void *) ); trc_memcheck( newlist, "New TRC_TEVDESC Index List" ); for ( i=0 ; i < *size ; i++ ) { newlist[i] = (*list)[i]; (*list)[i] = (void *) NULL; } for ( i=( ((*size) >= 0) ? (*size) : 0 ) ; i < newsize ; i++ ) newlist[i] = (void *) NULL; if ( *list ) free( *list ); *list = newlist; *size = newsize; } } void trc_store_event_header( ID, TD, tid ) TRC_ID ID; TRC_TEVDESC TD; int tid; { if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, tid ); if ( TD->index >= 0 ) { fprintf( ID->trace_out, "\"%s(", TD->name ); if ( TD->entry_exit == TRC_ENTRY_TEV ) fprintf( ID->trace_out, "0." ); else if ( TD->entry_exit == TRC_EXIT_TEV ) fprintf( ID->trace_out, "1." ); fprintf( ID->trace_out, "%d", TD->index ); fprintf( ID->trace_out, ")\" { " ); /* matching } */ } else fprintf( ID->trace_out, "\"%s\" { ", TD->name ); /* matching } */ } void trc_store_data_values( ID, TD, tid, omit ) TRC_ID ID; TRC_TEVDESC TD; int tid; int omit; { TRC_DATADESC DD; TRC_TEVTASK TT; char msg[1024]; char *str; int user_defined; int newtask; int endtask; int maxlen; int ignore; int tusec; int tsec; int len; int i; /* Set New/End Task Flags */ TT = (TRC_TEVTASK) NULL; tsec = tusec = -1; user_defined = TRC_FALSE; newtask = TRC_FALSE; endtask = TRC_FALSE; if ( !strcmp( TD->name, "newtask" ) || !strcmp( TD->name, "spntask" ) ) { newtask = TRC_TRUE; } else if ( !strcmp( TD->name, "endtask" ) ) endtask = TRC_TRUE; else if ( !strcmp( TD->name, "user_defined" ) ) user_defined = TRC_TRUE; ignore = TRC_FALSE; if ( !omit ) { /* Store Event Header */ trc_store_event_header( ID, TD, tid ); /* Sneak in Task ID for User Defined Events */ if ( user_defined ) fprintf( ID->trace_out, "%d, ", tid ); } /* Store Data Values */ DD = TD->ddesc; while ( DD != NULL ) { /* Dump Data Value */ if ( !omit && DD->array == TEV_DATA_ARRAY ) { if ( DD->dt == TEV_DATA_CPLX || DD->dt == TEV_DATA_DCPLX ) fprintf( ID->trace_out, "[%d] { ", DD->num * 2 ); /* matching } */ else if ( DD->dt == TEV_DATA_STRING ) fprintf( ID->trace_out, "[%d] ", DD->num ); else if ( DD->dt == TEV_DATA_BYTE ) fprintf( ID->trace_out, "[%d] { ", DD->num + 1 ); else fprintf( ID->trace_out, "[%d] { ", DD->num ); /* matching } } */ } switch ( DD->dt ) { case TEV_DATA_NULL: break; case TEV_DATA_BYTE: { if ( omit ) break; if ( DD->array == TEV_DATA_ARRAY ) fprintf( ID->trace_out, "\"" ); for ( i=0 ; i < DD->num ; i++ ) { fprintf( ID->trace_out, "%c", TRC_ARR_VALUE_OF( DD->data, char, i ) ); } if ( DD->array == TEV_DATA_ARRAY ) fprintf( ID->trace_out, "\"" ); break; } case TEV_DATA_CPLX: { if ( omit ) break; for ( i=0 ; i < DD->num ; i++ ) { fprintf( ID->trace_out, "%f, %f", TRC_ARR_VALUE_OF( DD->data, float, 2 * i ), TRC_ARR_VALUE_OF( DD->data, float, (2 * i) + 1 ) ); if ( i < DD->num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_DCPLX: { if ( omit ) break; for ( i=0 ; i < DD->num ; i++ ) { fprintf( ID->trace_out, "%lf, %lf", TRC_ARR_VALUE_OF( DD->data, double, 2 * i ), TRC_ARR_VALUE_OF( DD->data, double, (2 * i) + 1 ) ); if ( i < DD->num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_DOUBLE: { if ( omit ) break; for ( i=0 ; i < DD->num ; i++ ) { fprintf( ID->trace_out, "%lf", TRC_ARR_VALUE_OF( DD->data, double, i ) ); if ( i < DD->num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_FLOAT: { if ( omit ) break; for ( i=0 ; i < DD->num ; i++ ) { fprintf( ID->trace_out, "%f", TRC_ARR_VALUE_OF( DD->data, float, i ) ); if ( i < DD->num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_INT: { if ( !omit ) { for ( i=0 ; i < DD->num ; i++ ) { fprintf( ID->trace_out, "%d", TRC_ARR_VALUE_OF( DD->data, int, i ) ); if ( i < DD->num - 1 ) fprintf( ID->trace_out, ", " ); } } if ( ( newtask || endtask ) && !strcmp( DD->did->name, "TID" ) ) { if ( !omit && newtask ) { TT = trc_get_tevtask_tid( ID, TRC_VALUE_OF( DD->data, int ) ); if ( TT == NULL ) { if ( !ignore ) { sprintf( msg, "Task TID=0x%x Connected to %s", TRC_VALUE_OF( DD->data, int ), TRC_NAME ); trc_status_msg( ID, msg ); } TT = trc_create_tevtask(); TT->tid = TRC_VALUE_OF( DD->data, int ); TT->outstatus = TRC_TASK_NOOUT; TT->next = ID->tevtask_list; ID->tevtask_list = TT; } if ( !ignore ) TT->tevstatus = TRC_TASK_ALIVE; else TT->tevstatus = TRC_TASK_IGNORE; } if ( endtask ) { TT = trc_get_tevtask_tid( ID, TRC_VALUE_OF( DD->data, int ) ); if ( TT != NULL ) { if ( TT->tevstatus == TRC_TASK_ALIVE ) { TT->tevstatus = TRC_TASK_DEAD; trc_check_for_dead_host( ID, TT ); if ( !trc_tevtasks_alive( ID ) ) trc_end_trace( ID ); } else TT->tevstatus = TRC_TASK_DEAD; } else if ( !omit ) { printf( "\nWarning: ENDTASK Unknown Task TID=0x%x.\n\n", TRC_VALUE_OF( DD->data, int ) ); } } } else if ( !user_defined && !strcmp( DD->did->name, "TS" ) ) { tsec = TRC_VALUE_OF( DD->data, int ); } else if ( !user_defined && !strcmp( DD->did->name, "TU" ) ) { tusec = TRC_VALUE_OF( DD->data, int ); } break; } case TEV_DATA_UINT: { if ( omit ) break; for ( i=0 ; i < DD->num ; i++ ) { fprintf( ID->trace_out, "%u", (unsigned) TRC_ARR_VALUE_OF( DD->data, int, i ) ); if ( i < DD->num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_LONG: { if ( omit ) break; for ( i=0 ; i < DD->num ; i++ ) { fprintf( ID->trace_out, "%ld", TRC_ARR_VALUE_OF( DD->data, long, i ) ); if ( i < DD->num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_ULONG: { if ( omit ) break; for ( i=0 ; i < DD->num ; i++ ) { fprintf( ID->trace_out, "%ld", TRC_ARR_VALUE_OF( DD->data, long, i ) ); if ( i < DD->num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_SHORT: { if ( omit ) break; for ( i=0 ; i < DD->num ; i++ ) { fprintf( ID->trace_out, "%d", TRC_ARR_VALUE_OF( DD->data, short, i ) ); if ( i < DD->num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_USHORT: { if ( omit ) break; for ( i=0 ; i < DD->num ; i++ ) { fprintf( ID->trace_out, "%u", TRC_ARR_VALUE_OF( DD->data, short, i ) ); if ( i < DD->num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_STRING: { if ( omit ) break; if ( DD->num < 1 ) break; maxlen = 0; for ( i=0 ; i < DD->num ; i++ ) { len = strlen( TRC_ARR_VALUE_OF( DD->data, char *, i ) ); if ( len > maxlen ) maxlen = len; } if ( newtask && !strcmp( DD->did->name, "TN" ) ) { if ( !(ID->group_tasks) && TRC_GROUPTASK( (char *) DD->data ) ) { ignore = TRC_TRUE; if ( TT != NULL ) { sprintf( msg, "Ignoring Task \"%s\"\n", (char *) DD->data ); trc_status_msg( ID, msg ); TT->tevstatus = TRC_TASK_IGNORE; } } } fprintf( ID->trace_out, "[%d] { ", maxlen + 1 ); for ( i=0 ; i < DD->num ; i++ ) { str = TRC_ARR_VALUE_OF( DD->data, char *, i ); TRC_ARR_VALUE_OF( DD->data, char *, i ) = (char *) NULL; fprintf( ID->trace_out, "\"%s\"", str ); if ( i < DD->num - 1 ) fprintf( ID->trace_out, ", " ); free( str ); } if ( DD->array == TEV_DATA_SCALAR ) fprintf( ID->trace_out, " }" ); break; } case TEV_DATA_STRUCT_START: case TEV_DATA_STRUCT_END: case TEV_DATA_DEFERRED: { if ( !omit ) printf( "DT %d Not Impl\n", DD->dt ); break; } default: { if ( !omit ) printf( "DT %d Unknown\n", DD->dt ); } } if ( !omit ) { /* matching { */ if ( DD->array == TEV_DATA_ARRAY ) fprintf( ID->trace_out, " }" ); if ( DD->next != NULL ) fprintf( ID->trace_out, ", " ); } /* Free Data Value */ free( DD->data ); DD->data = (TRC_VALUE) NULL; DD->num = -1; /* Next Data Value */ DD = DD->next; } if ( !omit ) { /* matching { */ fprintf( ID->trace_out, " };;\n" ); if ( tsec != -1 && tusec != -1 ) trc_update_trace_time( tsec, tusec ); } } int trc_store_trace_event( ID, TD, tid, omit ) TRC_ID ID; TRC_TEVDESC TD; int tid; int omit; { TRC_DATADESC DD; TRC_TEVTASK TT; char upk_byte[TRC_MAX_UNPACK_ARR_SIZE]; float upk_float[TRC_MAX_UNPACK_ARR_SIZE * 2]; double upk_double[TRC_MAX_UNPACK_ARR_SIZE * 2]; int upk_int[TRC_MAX_UNPACK_ARR_SIZE]; long upk_long[TRC_MAX_UNPACK_ARR_SIZE]; short upk_short[TRC_MAX_UNPACK_ARR_SIZE]; char upk_str[TRC_MAX_UNPACK_ARR_SIZE]; char **strarr; char msg[1024]; int newtask; int endtask; int marker; int maxlen; int ignore; int tusec; int tsec; int len; int num; int i; /* Dump Descriptor (if necessary) */ if ( !omit && TD->dump ) trc_dump_tevdesc( ID, TD, tid ); /* Set New Task Flag */ TT = (TRC_TEVTASK) NULL; tsec = tusec = -1; newtask = TRC_FALSE; endtask = TRC_FALSE; if ( !strcmp( TD->name, "newtask" ) || !strcmp( TD->name, "spntask" ) ) { newtask = TRC_TRUE; } else if ( !strcmp( TD->name, "endtask" ) ) endtask = TRC_TRUE; ignore = TRC_FALSE; /* Store Event Header */ if ( !omit ) trc_store_event_header( ID, TD, tid ); /* Store Remainder of Event */ DD = TD->ddesc; while ( DD != NULL ) { if ( DD->array == TEV_DATA_ARRAY ) { TRC_PVMCKERR( pvm_upkint( &num, 1, 1 ), "Array Unpack", return( TRC_FALSE ) ); if ( num > TRC_MAX_UNPACK_ARR_SIZE && DD->dt != TEV_DATA_STRING ) { if ( !omit ) printf( "Error: Unpack Size %d Too Large\n", num ); return( TRC_FALSE ); } if ( !omit ) { if ( DD->dt == TEV_DATA_CPLX || DD->dt == TEV_DATA_DCPLX ) { fprintf( ID->trace_out, "[%d] { ", num * 2 ); /* matching } */ } else if ( DD->dt == TEV_DATA_STRING ) fprintf( ID->trace_out, "[%d] ", num ); else if ( DD->dt == TEV_DATA_BYTE ) { fprintf( ID->trace_out, "[%d] { ", num + 1 ); /* matching } */ } else { fprintf( ID->trace_out, "[%d] { ", num ); /* matching } */ } } } else num = 1; switch ( DD->dt ) { case TEV_DATA_NULL: break; case TEV_DATA_BYTE: { TRC_PVMCKERR( pvm_upkbyte( upk_byte, num, 1 ), "Event BYTE Unpack", return( TRC_FALSE ) ); if ( omit ) break; if ( DD->array == TEV_DATA_ARRAY ) fprintf( ID->trace_out, "\"" ); for ( i=0 ; i < num ; i++ ) fprintf( ID->trace_out, "%c", upk_byte[i] ); if ( DD->array == TEV_DATA_ARRAY ) fprintf( ID->trace_out, "\"" ); break; } case TEV_DATA_CPLX: { TRC_PVMCKERR( pvm_upkfloat( upk_float, num * 2, 1 ), "Event CPLX Unpack", return( TRC_FALSE ) ); if ( omit ) break; for ( i=0 ; i < num ; i++ ) { fprintf( ID->trace_out, "%f, %f", upk_float[ 2 * i ], upk_float[ (2 * i) + 1 ] ); if ( i < num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_DCPLX: { TRC_PVMCKERR( pvm_upkdouble( upk_double, num * 2, 1 ), "Event DCPLX Unpack", return( TRC_FALSE ) ); if ( omit ) break; for ( i=0 ; i < num ; i++ ) { fprintf( ID->trace_out, "%lf, %lf", upk_double[ 2 * i ], upk_double[ (2 * i) + 1 ] ); if ( i < num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_DOUBLE: { TRC_PVMCKERR( pvm_upkdouble( upk_double, num, 1 ), "Event DOUBLE Unpack", return( TRC_FALSE ) ); if ( omit ) break; for ( i=0 ; i < num ; i++ ) { fprintf( ID->trace_out, "%lf", upk_double[i] ); if ( i < num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_FLOAT: { TRC_PVMCKERR( pvm_upkfloat( upk_float, num, 1 ), "Event FLOAT Unpack", return( TRC_FALSE ) ); if ( omit ) break; for ( i=0 ; i < num ; i++ ) { fprintf( ID->trace_out, "%f", upk_float[i] ); if ( i < num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_INT: { TRC_PVMCKERR( pvm_upkint( upk_int, num, 1 ), "Event INT Unpack", return( TRC_FALSE ) ); if ( !omit ) { for ( i=0 ; i < num ; i++ ) { fprintf( ID->trace_out, "%d", upk_int[i] ); if ( i < num - 1 ) fprintf( ID->trace_out, ", " ); } } if ( ( newtask || endtask ) && !strcmp( DD->did->name, "TID" ) ) { if ( !omit && newtask ) { TT = trc_get_tevtask_tid( ID, upk_int[0] ); if ( TT == NULL ) { if ( !ignore ) { sprintf( msg, "Task TID=0x%x Connected to %s", upk_int[0], TRC_NAME ); trc_status_msg( ID, msg ); } TT = trc_create_tevtask(); TT->tid = upk_int[0]; TT->outstatus = TRC_TASK_NOOUT; TT->next = ID->tevtask_list; ID->tevtask_list = TT; } if ( !ignore ) TT->tevstatus = TRC_TASK_ALIVE; else TT->tevstatus = TRC_TASK_IGNORE; } if ( endtask ) { TT = trc_get_tevtask_tid( ID, upk_int[0] ); if ( TT != NULL ) { if ( TT->tevstatus == TRC_TASK_ALIVE ) { TT->tevstatus = TRC_TASK_DEAD; trc_check_for_dead_host( ID, TT ); if ( !trc_tevtasks_alive( ID ) ) trc_end_trace( ID ); } else TT->tevstatus = TRC_TASK_DEAD; } else if ( !omit ) { printf( "\nWarning: ENDTASK Unknown Task TID=0x%x.\n\n", upk_int[0] ); } } } else if ( !strcmp( DD->did->name, "TS" ) ) tsec = upk_int[0]; else if ( !strcmp( DD->did->name, "TU" ) ) tusec = upk_int[0]; break; } case TEV_DATA_UINT: { TRC_PVMCKERR( pvm_upkint( upk_int, num, 1 ), "Event UINT Unpack", return( TRC_FALSE ) ); if ( omit ) break; for ( i=0 ; i < num ; i++ ) { fprintf( ID->trace_out, "%u", (unsigned) upk_int[i] ); if ( i < num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_LONG: { TRC_PVMCKERR( pvm_upklong( upk_long, num, 1 ), "Event LONG Unpack", return( TRC_FALSE ) ); if ( omit ) break; for ( i=0 ; i < num ; i++ ) { fprintf( ID->trace_out, "%ld", upk_long[i] ); if ( i < num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_ULONG: { TRC_PVMCKERR( pvm_upklong( upk_long, num, 1 ), "Event ULONG Unpack", return( TRC_FALSE ) ); if ( omit ) break; for ( i=0 ; i < num ; i++ ) { fprintf( ID->trace_out, "%ld", upk_long[i] ); if ( i < num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_SHORT: { TRC_PVMCKERR( pvm_upkshort( upk_short, num, 1 ), "Event SHORT Unpack", return( TRC_FALSE ) ); if ( omit ) break; for ( i=0 ; i < num ; i++ ) { fprintf( ID->trace_out, "%d", upk_short[i] ); if ( i < num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_USHORT: { TRC_PVMCKERR( pvm_upkshort( upk_short, num, 1 ), "Event USHORT Unpack", return( TRC_FALSE ) ); if ( omit ) break; for ( i=0 ; i < num ; i++ ) { fprintf( ID->trace_out, "%u", upk_short[i] ); if ( i < num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_STRING: { if ( num < 1 ) break; strarr = (char **) malloc( (unsigned) num * sizeof(char *) ); trc_memcheck( strarr, "String Array" ); maxlen = 0; for ( i=0 ; i < num ; i++ ) { TRC_PVMCKERR( pvm_upkstr( upk_str ), "Event STRING Unpack", return( TRC_FALSE ) ); if ( (len = strlen( upk_str )) > maxlen ) maxlen = len; strarr[i] = trc_copy_str( upk_str ); } if ( !omit && newtask && !strcmp( DD->did->name, "TN" ) ) { if ( !(ID->group_tasks) && TRC_GROUPTASK( upk_str ) ) { ignore = TRC_TRUE; if ( TT != NULL ) { sprintf( msg, "Ignoring Task \"%s\"", upk_str ); trc_status_msg( ID, msg ); TT->tevstatus = TRC_TASK_IGNORE; } } } if ( !omit ) { fprintf( ID->trace_out, "[%d] { ", maxlen + 1 ); for ( i=0 ; i < num ; i++ ) { fprintf( ID->trace_out, "\"%s\"", strarr[i] ); if ( i < num - 1 ) fprintf( ID->trace_out, ", " ); free( strarr[i] ); } if ( DD->array == TEV_DATA_SCALAR ) fprintf( ID->trace_out, " }" ); } else { for ( i=0 ; i < num ; i++ ) free( strarr[i] ); } free( strarr ); break; } case TEV_DATA_STRUCT_START: case TEV_DATA_STRUCT_END: case TEV_DATA_DEFERRED: { if ( !omit ) printf( "DT Not Impl\n" ); break; } default: { if ( !omit ) printf( "DT Unknown\n" ); } } if ( !omit ) { /* matching { */ if ( DD->array == TEV_DATA_ARRAY ) fprintf( ID->trace_out, " }" ); if ( DD->next != NULL ) fprintf( ID->trace_out, ", " ); } DD = DD->next; } TRC_PVMCKERR( pvm_upkint( &marker, 1, 1 ), "Data ID Message", return( TRC_FALSE ) ); if ( !omit ) { /* matching { */ if ( marker == TEV_MARK_EVENT_RECORD_END ) fprintf( ID->trace_out, " };;\n" ); else { printf( "Error: No Event End Marker\n" ); return( TRC_FALSE ); } if ( tsec != -1 && tusec != -1 ) trc_update_trace_time( tsec, tusec ); return( TRC_TRUE ); } else return( TRC_FALSE ); } trc_unpack_data_value( DD ) TRC_DATADESC DD; { char upk_str[TRC_MAX_UNPACK_ARR_SIZE]; int num; int i; if ( DD->array == TEV_DATA_ARRAY ) { TRC_PVMCKERR( pvm_upkint( &num, 1, 1 ), "Array Unpack", return( TRC_FALSE ) ); } else num = 1; DD->data = trc_make_value( DD->dt, num ); DD->num = num; switch ( DD->dt ) { case TEV_DATA_NULL: break; case TEV_DATA_BYTE: { TRC_PVMCKERR( pvm_upkbyte( DD->data, num, 1 ), "Event BYTE Unpack", return( TRC_FALSE ) ); break; } case TEV_DATA_CPLX: { TRC_PVMCKERR( pvm_upkfloat( DD->data, num * 2, 1 ), "Event CPLX Unpack", return( TRC_FALSE ) ); break; } case TEV_DATA_DCPLX: { TRC_PVMCKERR( pvm_upkdouble( DD->data, num * 2, 1 ), "Event DCPLX Unpack", return( TRC_FALSE ) ); break; } case TEV_DATA_DOUBLE: { TRC_PVMCKERR( pvm_upkdouble( DD->data, num, 1 ), "Event DOUBLE Unpack", return( TRC_FALSE ) ); break; } case TEV_DATA_FLOAT: { TRC_PVMCKERR( pvm_upkfloat( DD->data, num, 1 ), "Event FLOAT Unpack", return( TRC_FALSE ) ); break; } case TEV_DATA_INT: { TRC_PVMCKERR( pvm_upkint( DD->data, num, 1 ), "Event INT Unpack", return( TRC_FALSE ) ); break; } case TEV_DATA_UINT: { TRC_PVMCKERR( pvm_upkint( DD->data, num, 1 ), "Event UINT Unpack", return( TRC_FALSE ) ); break; } case TEV_DATA_LONG: { TRC_PVMCKERR( pvm_upklong( DD->data, num, 1 ), "Event LONG Unpack", return( TRC_FALSE ) ); break; } case TEV_DATA_ULONG: { TRC_PVMCKERR( pvm_upklong( DD->data, num, 1 ), "Event ULONG Unpack", return( TRC_FALSE ) ); break; } case TEV_DATA_SHORT: { TRC_PVMCKERR( pvm_upkshort( DD->data, num, 1 ), "Event SHORT Unpack", return( TRC_FALSE ) ); break; } case TEV_DATA_USHORT: { TRC_PVMCKERR( pvm_upkshort( DD->data, num, 1 ), "Event USHORT Unpack", return( TRC_FALSE ) ); break; } case TEV_DATA_STRING: { if ( num < 1 ) break; DD->data = (TRC_VALUE) malloc( (unsigned) num * sizeof(char *) ); trc_memcheck( DD->data, "String Array" ); for ( i=0 ; i < num ; i++ ) { TRC_PVMCKERR( pvm_upkstr( upk_str ), "Event STRING Unpack", return( TRC_FALSE ) ); ((char **) DD->data)[i] = trc_copy_str( upk_str ); } break; } case TEV_DATA_STRUCT_START: case TEV_DATA_STRUCT_END: case TEV_DATA_DEFERRED: printf( "DT %d Not Impl\n", DD->dt ); break; default: printf( "DT %d Unknown\n", DD->dt ); } return( TRC_TRUE ); } void trc_store_tevrec( ID, TD, TR, tid ) TRC_ID ID; TRC_TEVDESC TD; TRC_TEVREC TR; int tid; { TRC_DATADESC DD; TRC_TEVREC trptr; char *str; int user_defined; int maxlen; int len; int i; /* Set New/End Task Flags */ user_defined = TRC_FALSE; if ( !strcmp( TD->name, "user_defined" ) ) user_defined = TRC_TRUE; /* Store Event Header */ trc_store_event_header( ID, TD, tid ); /* Sneak in Task ID for User Defined Events */ if ( user_defined ) fprintf( ID->trace_out, "%d, ", tid ); /* Store Data Values */ DD = TD->ddesc; trptr = TR; while ( DD != NULL ) { /* Dump Data Value */ if ( DD->array == TEV_DATA_ARRAY ) { if ( DD->dt == TEV_DATA_STRING ) fprintf( ID->trace_out, "[%d] ", trptr->num ); else fprintf( ID->trace_out, "[%d] { ", trptr->num ); /* matching } */ } switch ( DD->dt ) { case TEV_DATA_NULL: break; case TEV_DATA_BYTE: { if ( DD->array == TEV_DATA_ARRAY ) fprintf( ID->trace_out, "\"" ); for ( i=0 ; i < trptr->num - 1 ; i++ ) { fprintf( ID->trace_out, "%c", TRC_ARR_VALUE_OF( trptr->value, char, i ) ); } if ( DD->array == TEV_DATA_ARRAY ) fprintf( ID->trace_out, "\"" ); break; } case TEV_DATA_CPLX: case TEV_DATA_FLOAT: { for ( i=0 ; i < trptr->num ; i++ ) { fprintf( ID->trace_out, "%f", TRC_ARR_VALUE_OF( trptr->value, float, i ) ); if ( i < DD->num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_DCPLX: case TEV_DATA_DOUBLE: { for ( i=0 ; i < trptr->num ; i++ ) { fprintf( ID->trace_out, "%lf", TRC_ARR_VALUE_OF( trptr->value, double, i ) ); if ( i < trptr->num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_INT: { for ( i=0 ; i < trptr->num ; i++ ) { fprintf( ID->trace_out, "%d", TRC_ARR_VALUE_OF( trptr->value, int, i ) ); if ( i < trptr->num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_UINT: { for ( i=0 ; i < trptr->num ; i++ ) { fprintf( ID->trace_out, "%u", (unsigned) TRC_ARR_VALUE_OF( trptr->value, int, i ) ); if ( i < trptr->num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_LONG: { for ( i=0 ; i < trptr->num ; i++ ) { fprintf( ID->trace_out, "%ld", TRC_ARR_VALUE_OF( trptr->value, long, i ) ); if ( i < trptr->num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_ULONG: { for ( i=0 ; i < trptr->num ; i++ ) { fprintf( ID->trace_out, "%ld", TRC_ARR_VALUE_OF( trptr->value, long, i ) ); if ( i < trptr->num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_SHORT: { for ( i=0 ; i < trptr->num ; i++ ) { fprintf( ID->trace_out, "%d", TRC_ARR_VALUE_OF( trptr->value, short, i ) ); if ( i < trptr->num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_USHORT: { for ( i=0 ; i < trptr->num ; i++ ) { fprintf( ID->trace_out, "%u", TRC_ARR_VALUE_OF( trptr->value, short, i ) ); if ( i < trptr->num - 1 ) fprintf( ID->trace_out, ", " ); } break; } case TEV_DATA_STRING: { if ( trptr->num < 1 ) break; maxlen = 0; for ( i=0 ; i < trptr->num ; i++ ) { len = strlen( TRC_ARR_VALUE_OF( trptr->value, char *, i ) ); if ( len > maxlen ) maxlen = len; } fprintf( ID->trace_out, "[%d] { ", maxlen + 1 ); for ( i=0 ; i < trptr->num ; i++ ) { str = TRC_ARR_VALUE_OF( trptr->value, char *, i ); fprintf( ID->trace_out, "\"%s\"", str ); if ( i < trptr->num - 1 ) fprintf( ID->trace_out, ", " ); free( str ); } if ( DD->array == TEV_DATA_SCALAR ) fprintf( ID->trace_out, " }" ); break; } case TEV_DATA_STRUCT_START: case TEV_DATA_STRUCT_END: case TEV_DATA_DEFERRED: { printf( "DT %d Not Impl\n", DD->dt ); break; } default: { printf( "DT %d Unknown\n", DD->dt ); } } /* matching { */ if ( DD->array == TEV_DATA_ARRAY ) fprintf( ID->trace_out, " }" ); if ( DD->next != NULL ) fprintf( ID->trace_out, ", " ); /* Next Data Value */ DD = DD->next; trptr = trptr->next; } /* matching { */ fprintf( ID->trace_out, " };;\n" ); } trc_store_output_event( ID, tid, str, len ) TRC_ID ID; int tid; char *str; int len; { TRC_TEVTASK TT; char tmp[4096]; int index; int num; int i; num = 0; TT = trc_get_tevtask_tid( ID, tid ); if ( TT != NULL && TT->output != NULL ) { strcpy( tmp, TT->output ); free( TT->output ); TT->output = (char *) NULL; if ( !strcmp( str, "GOTEOF\n" ) ) { trc_write_output_event( ID, tid, tmp ); index = 0; num++; } else index = strlen( tmp ); } else index = 0; for ( i=0 ; i < len ; i++ ) { if ( str[i] != '\n' ) tmp[index++] = str[i]; else { tmp[index] = '\0'; trc_write_output_event( ID, tid, tmp ); index = 0; num++; } } if ( index ) { tmp[index] = '\0'; if ( TT != NULL ) TT->output = trc_copy_str( tmp ); else { printf( "Warning: Partial Task Output Line\n" ); trc_write_output_event( ID, tid, tmp ); num++; } } return( num ); } TRC_TEVDESC_INFO_STRUCT TRC_OUTPUT_INFO[] = { { TEV_DID_TS, TEV_DATA_INT, TEV_DATA_SCALAR }, { TEV_DID_TU, TEV_DATA_INT, TEV_DATA_SCALAR }, { TEV_DID_TID, TEV_DATA_INT, TEV_DATA_SCALAR }, { TEV_DID_OS, TEV_DATA_STRING, TEV_DATA_SCALAR } }; void trc_write_output_event( ID, tid, str ) TRC_ID ID; int tid; char *str; { #ifdef USE_PVM_33 trc_write_old_output_event( ID, tid, str ); #else /* Dump Task Output Into Trace File */ if ( TRC_OUTPUT_TEVDESC->dump ) trc_dump_tevdesc( ID, TRC_OUTPUT_TEVDESC, tid ); trc_store_event_header( ID, TRC_OUTPUT_TEVDESC, tid ); fprintf( ID->trace_out, "%d, %ld, %d", TRC_TRACE_TIME.tv_sec, TRC_TRACE_TIME.tv_usec, tid ); trc_dump_trace_str( ID, str, TRC_TRUE ); /* matching { */ fprintf( ID->trace_out, " };;\n" ); #endif /* Dump Into Separate Output File If Requested */ trc_task_output( ID, tid, str ); } int trc_save_host_status_events( ID ) TRC_ID ID; { TRC_HOST H; int num; if ( ID->trace_out == NULL ) return( 0 ); H = TRC_HOST_LIST; num = 0; while ( H != NULL ) { trc_write_host_add_event( ID, H ); num++; if ( H->delta.tv_sec != 0 || H->delta.tv_usec != 0 ) { trc_write_host_sync_event( ID, H ); num++; } H = H->next; } if ( num ) fflush( ID->trace_out ); return( num ); } TRC_TEVDESC_INFO_STRUCT TRC_HOST_ADD_INFO[] = { { TEV_DID_TS, TEV_DATA_INT, TEV_DATA_SCALAR }, { TEV_DID_TU, TEV_DATA_INT, TEV_DATA_SCALAR }, { TEV_DID_TID, TEV_DATA_INT, TEV_DATA_SCALAR }, { TEV_DID_HN, TEV_DATA_STRING, TEV_DATA_SCALAR }, { TEV_DID_HNA, TEV_DATA_STRING, TEV_DATA_SCALAR }, { TEV_DID_HA, TEV_DATA_STRING, TEV_DATA_SCALAR }, { TEV_DID_HSP, TEV_DATA_INT, TEV_DATA_SCALAR } }; void trc_write_host_add_event( ID, H ) TRC_ID ID; TRC_HOST H; { #ifdef USE_PVM_33 trc_write_old_host_add_event( ID, H ); #else if ( TRC_HOST_ADD_TEVDESC->dump ) trc_dump_tevdesc( ID, TRC_HOST_ADD_TEVDESC, H->pvmd_tid ); trc_store_event_header( ID, TRC_HOST_ADD_TEVDESC, H->pvmd_tid ); fprintf( ID->trace_out, "%d, %ld, %d", TRC_TRACE_TIME.tv_sec, TRC_TRACE_TIME.tv_usec, H->pvmd_tid ); trc_dump_trace_str( ID, H->refname, TRC_TRUE ); trc_dump_trace_str( ID, H->alias, TRC_TRUE ); trc_dump_trace_str( ID, H->arch, TRC_TRUE ); /* matching { */ fprintf( ID->trace_out, ", %d };;\n", H->speed ); #endif } TRC_TEVDESC_INFO_STRUCT TRC_HOST_DEL_INFO[] = { { TEV_DID_TS, TEV_DATA_INT, TEV_DATA_SCALAR }, { TEV_DID_TU, TEV_DATA_INT, TEV_DATA_SCALAR }, { TEV_DID_TID, TEV_DATA_INT, TEV_DATA_SCALAR }, { TEV_DID_HN, TEV_DATA_STRING, TEV_DATA_SCALAR } }; void trc_write_host_del_event( ID, H, tid ) TRC_ID ID; TRC_HOST H; int tid; { #ifdef USE_PVM_33 trc_write_old_host_del_event( ID, H, tid ); #else char tmp[1024]; if ( TRC_HOST_DEL_TEVDESC->dump ) trc_dump_tevdesc( ID, TRC_HOST_DEL_TEVDESC, tid ); trc_store_event_header( ID, TRC_HOST_DEL_TEVDESC, tid ); fprintf( ID->trace_out, "%d, %ld, %d", TRC_TRACE_TIME.tv_sec, TRC_TRACE_TIME.tv_usec, tid ); if ( strcmp( H->refname, "" ) ) { sscanf( H->refname, "%s", tmp ); trc_dump_trace_str( ID, tmp, TRC_TRUE ); } else trc_dump_trace_str( ID, H->refname, TRC_TRUE ); /* matching { */ fprintf( ID->trace_out, " };;\n" ); #endif } TRC_TEVDESC_INFO_STRUCT TRC_HOST_SYNC_INFO[] = { { TEV_DID_TS, TEV_DATA_INT, TEV_DATA_SCALAR }, { TEV_DID_TU, TEV_DATA_INT, TEV_DATA_SCALAR }, { TEV_DID_TID, TEV_DATA_INT, TEV_DATA_SCALAR }, { TEV_DID_HDS, TEV_DATA_INT, TEV_DATA_SCALAR }, { TEV_DID_HDU, TEV_DATA_INT, TEV_DATA_SCALAR }, }; void trc_write_host_sync_event( ID, H ) TRC_ID ID; TRC_HOST H; { #ifdef USE_PVM_33 trc_write_old_host_sync_event( ID, H ); #else if ( TRC_HOST_SYNC_TEVDESC->dump ) trc_dump_tevdesc( ID, TRC_HOST_SYNC_TEVDESC, H->pvmd_tid ); trc_store_event_header( ID, TRC_HOST_SYNC_TEVDESC, H->pvmd_tid ); /* matching { */ fprintf( ID->trace_out, "%d, %ld, %d, %d, %ld };;\n", TRC_TRACE_TIME.tv_sec, TRC_TRACE_TIME.tv_usec, H->pvmd_tid, H->delta.tv_sec, H->delta.tv_usec ); #endif H->last_time.tv_sec = TRC_TRACE_TIME.tv_sec; H->last_time.tv_usec = TRC_TRACE_TIME.tv_usec; } void trc_define_special_descriptors() { unsigned info_size = sizeof( struct trc_tevdesc_info_struct ); TRC_OUTPUT_TEVDESC = trc_make_tevdesc( (TRC_ID) NULL, TRC_OUTPUT, TRC_IGNORE_TEV, "output", TRC_OUTPUT_INFO, (int) ( sizeof(TRC_OUTPUT_INFO) / info_size ) ); TRC_HOST_ADD_TEVDESC = trc_make_tevdesc( (TRC_ID) NULL, TRC_HOST_ADD, TRC_IGNORE_TEV, "host_add", TRC_HOST_ADD_INFO, (int) ( sizeof(TRC_HOST_ADD_INFO) / info_size ) ); TRC_HOST_DEL_TEVDESC = trc_make_tevdesc( (TRC_ID) NULL, TRC_HOST_DEL, TRC_IGNORE_TEV, "host_del", TRC_HOST_DEL_INFO, (int) ( sizeof(TRC_HOST_DEL_INFO) / info_size ) ); TRC_HOST_SYNC_TEVDESC = trc_make_tevdesc( (TRC_ID) NULL, TRC_HOST_SYNC, TRC_IGNORE_TEV, "host_sync", TRC_HOST_SYNC_INFO, (int) ( sizeof(TRC_HOST_SYNC_INFO) / info_size ) ); } TRC_TEVDESC trc_make_tevdesc( ID, eid, entry_exit, name, info, ninfo ) TRC_ID ID; int eid; int entry_exit; char *name; TRC_TEVDESC_INFO info; int ninfo; { TRC_TEVDESC_INFO TI; TRC_DATADESC DD; TRC_TEVDESC TD; int i; /* New Descriptor */ TD = trc_create_tevdesc(); TD->refcount = 1; TD->eid = eid; TD->entry_exit = entry_exit; TD->name = trc_copy_str( name ); /* Semantic IDs / Data Types */ for ( i=0 ; i < ninfo ; i++ ) { TI = &(info[i]); if ( TD->ddesc == NULL ) DD = TD->ddesc = trc_create_datadesc(); else DD = DD->next = trc_create_datadesc(); DD->did = trc_get_did( (TRC_HOST) NULL, TI->id ); DD->dt = TI->dt; DD->array = TI->array; } trc_add_tevdesc( ID, &TD, TRC_TID, TRC_FALSE ); return( TD ); } /* Handle Task Output */ void trc_task_output( ID, tid, str ) TRC_ID ID; int tid; char *str; { char tmp[4096]; if ( ID->output_fp == NULL ) return; if ( !strcmp( str, "GOTEOF" ) ) { if ( ID->output_dump_hdr ) { (ID->output_dump_hdr)( ID, tid ); fprintf( ID->output_fp, "EOF\n" ); } else fprintf( ID->output_fp, "[0x%x] EOF\n", tid ); fflush( ID->output_fp ); } else if ( strcmp( str, "CREATION" ) && strcmp( str, "GOTSPAWN" ) ) { if ( ID->output_dump_hdr ) { (ID->output_dump_hdr)( ID, tid ); fprintf( ID->output_fp, "%s\n", str ); } else fprintf( ID->output_fp, "[0x%x] %s\n", tid, str ); fflush( ID->output_fp ); } } /* Time Routines */ void trc_update_trace_time( sec, usec ) int sec; int usec; { struct timeval tm; if ( sec == -1 ) { gettimeofday( &tm, (struct timezone *) NULL ); sec = tm.tv_sec; usec = tm.tv_usec; } if ( sec > TRC_TRACE_TIME.tv_sec || ( sec == TRC_TRACE_TIME.tv_sec && usec > TRC_TRACE_TIME.tv_usec ) ) { TRC_TRACE_TIME.tv_sec = sec; TRC_TRACE_TIME.tv_usec = usec; } } /* Trace Utility Routines */ void trc_dump_trace_header( ID ) TRC_ID ID; { char *ds; if ( ID->trace_out == NULL ) return; if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, TRC_TID ); fprintf( ID->trace_out, "/*\n" ); if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, TRC_TID ); ds = trc_date_str(); fprintf( ID->trace_out, " * \"Creation Date\" \"%s\"\n", ds ); free( ds ); if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, TRC_TID ); fprintf( ID->trace_out, " * \"Machine\" \"%s %s (PVM %s)\"\n", TRC_NAME, TRC_VERSION, pvm_version() ); if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, TRC_TID ); fprintf( ID->trace_out, " */ ;;\n" ); if ( ID->event_dump_hdr ) (ID->event_dump_hdr)( ID, TRC_TID ); fprintf( ID->trace_out, "\n" ); } void trc_dump_trace_str( ID, str, comma_flag ) TRC_ID ID; char *str; int comma_flag; { if ( comma_flag ) { fprintf( ID->trace_out, ", [%u] { \"%s\" }", (unsigned) ( strlen( str ) + 1 ), str ); } else { fprintf( ID->trace_out, "[%u] { \"%s\" }", (unsigned) ( strlen( str ) + 1 ), str ); } } /* Trace Processing Routines */ int trc_read_trace_event( ID, eof ) TRC_ID ID; int *eof; { TRC_TEVDESC TD; char tmp[4096]; char c; int entry_exit; int dummy; int index; int code; int flag; int eid; int ee; int i; *eof = TRC_FALSE; if ( ID->trace_in == NULL ) return( TRC_FALSE ); while ( TRC_TRUE ) { c = getc( ID->trace_in ); if ( c != (char) EOF ) { switch ( c ) { /* Record Descriptor Packet */ case '#': { /* Get event ID */ flag = fscanf( ID->trace_in, "%d", &code ); if ( flag != 1 ) { printf( "Error Reading Event ID\n" ); return( TRC_FALSE ); } /* Get event name */ if ( !trc_find_event_str( ID, "\"" ) ) return( TRC_FALSE ); i = 0; while ( (c = getc( ID->trace_in )) != (char) EOF && c != '"' && c != '(' ) { tmp[i++] = c; } TRC_CKEOF( c, "EOF Reading Event Descriptor Name\n", return( TRC_FALSE ) ); tmp[i] = '\0'; /* PVM 3.4 Trace */ if ( c == '(' ) { /* Decode event ID */ index = ( code / 1000 ) - 1; eid = ( code - ((index + 1) * 1000) ) / 2; ee = code - ((index + 1) * 1000) - (2 * eid); /* Read in entry/exit or index value */ flag = fscanf( ID->trace_in, "%d", &dummy ); if ( flag != 1 ) { printf( "Error Reading Event Index\n" ); return( TRC_FALSE ); } /* Read in next char for parsing context */ c = getc( ID->trace_in ); TRC_CKEOF( c, "EOF Reading Event Descriptor\n", return( TRC_FALSE ) ); if ( c == '.' ) { if ( ee != dummy ) { printf( "Warning: " ); printf( "Entry/Exit Mismatch " ); printf( "%d != %d\n", ee, dummy ); } entry_exit = TRC_IGNORE_TEV; if ( dummy == 0 ) entry_exit = TRC_ENTRY_TEV; else if ( dummy == 1 ) entry_exit = TRC_EXIT_TEV; flag = fscanf( ID->trace_in, "%d", &dummy ); if ( flag != 1 ) { printf( "Error Reading Event Index\n" ); return( TRC_FALSE ); } if ( index != dummy ) { printf( "Warning: " ); printf( "Descriptor Index Mismatch " ); printf( "%d != %d\n", index, dummy ); index = dummy; } if ( !trc_find_event_str( ID, ")" ) ) return( TRC_FALSE ); } else { entry_exit = TRC_IGNORE_TEV; if ( ee == 1 ) { printf( "Warning: " ); printf( "Entry/Exit Mismatch " ); printf( "%d != %d\n", ee, entry_exit ); } if ( index != dummy ) { printf( "Warning: " ); printf( "Descriptor Index Mismatch " ); printf( "%d != %d\n", index, dummy ); index = dummy; } } if ( !trc_find_event_str( ID, "\"" ) ) return( TRC_FALSE ); if ( !(TD = trc_read_descriptor( ID, eid, tmp, entry_exit, index )) ) { return( TRC_FALSE ); } if ( ID->handle_descriptor ) (ID->handle_descriptor)( ID, TD ); } /* PVM 3.3 Trace - Ignore Descriptor */ else { eid = code; if ( tmp[ i - 1 ] == '0' ) entry_exit = TRC_ENTRY_TEV; else if ( tmp[ i - 1 ] == '1' ) entry_exit = TRC_EXIT_TEV; else entry_exit = TRC_IGNORE_TEV; if ( !(TD = trc_read_descriptor( ID, eid, tmp, entry_exit, -1 )) ) { return( TRC_FALSE ); } if ( ID->handle_old_descriptor ) (ID->handle_old_descriptor)( ID, TD ); } break; } /* Record Data Packet */ case '"': { i = 0; while ( (c = getc( ID->trace_in )) != (char) EOF && c != '"' && c != '(' ) { tmp[i++] = c; } TRC_CKEOF( c, "EOF Reading Event Record Name\n", return( TRC_FALSE ) ); tmp[i] = '\0'; /* PVM 3.4 Trace */ if ( c == '(' ) { /* Read in entry/exit or index value */ flag = fscanf( ID->trace_in, "%d", &dummy ); if ( flag != 1 ) { printf( "Error Reading Event Index\n" ); return( TRC_FALSE ); } /* Read in next char for parsing context */ c = getc( ID->trace_in ); TRC_CKEOF( c, "EOF Reading Event Record\n", return( TRC_FALSE ) ); if ( c == '.' ) { entry_exit = TRC_IGNORE_TEV; if ( dummy == 0 ) entry_exit = TRC_ENTRY_TEV; else if ( dummy == 1 ) entry_exit = TRC_EXIT_TEV; flag = fscanf( ID->trace_in, "%d", &index ); if ( flag != 1 ) { printf( "Error Reading Event Index\n" ); return( TRC_FALSE ); } if ( !trc_find_event_str( ID, ")" ) ) return( TRC_FALSE ); } else { entry_exit = TRC_IGNORE_TEV; index = dummy; } if ( !trc_find_event_str( ID, "\"" ) ) return( TRC_FALSE ); return( trc_process_trace_event( ID, tmp, entry_exit, index ) ); } /* PVM 3.3 Trace */ else { return( trc_process_old_trace_event( ID, tmp ) ); } /* break; unreachable */ } /* Command Packet */ case '%': { tmp[0] = '%'; if ( !trc_find_event_end_ret( ID, tmp + 1, 4095 ) ) return( TRC_FALSE ); if ( ID->handle_command ) (ID->handle_command)( ID, tmp ); break; } /* Stream Attribute Packet */ case '/': { c = getc( ID->trace_in ); TRC_CKEOF( c, "EOF Reading Trace Comment\n", return( TRC_FALSE ) ); if ( c != '*' ) { printf( "\nError Reading Trace File\n" ); printf( "\t- '*' expected (/* */)\n\n" ); } strcpy( tmp, "/*" ); if ( !trc_find_event_end_ret( ID, tmp + 2, 4094 ) ) return( TRC_FALSE ); if ( ID->handle_comment ) (ID->handle_comment)( ID, tmp ); break; } /* White Space */ case ' ': case '\t': case '\n': { break; } } } else { *eof = TRC_TRUE; return( TRC_FALSE ); } } } TRC_TEVDESC trc_read_descriptor( ID, eid, name, entry_exit, index ) TRC_ID ID; int eid; char *name; int entry_exit; int index; { TRC_DATADESC DD; TRC_TEVDESC TD; TRC_TEVDESC tdptr; char diddesc[1024]; char dtstr[255]; char did[8]; char last; char c; long tmp; int done; int i; /* Find first bracket */ if ( !trc_find_event_str( ID, "{" ) ) return( (TRC_TEVDESC) NULL ); /* matching } */ /* Create Descriptor Structure */ TD = trc_create_tevdesc(); TD->refcount = 1; TD->name = trc_copy_str( name ); TD->eid = eid; TD->entry_exit = entry_exit; TD->index = index; /* Read in Data Descriptor Statements */ done = 0; do { /* matching { */ while ( (c = getc( ID->trace_in )) != (char) EOF && c != '/' && c != '}' ); TRC_CKEOF( c, "EOF Reading Event Descriptor\n", return( (TRC_TEVDESC) NULL ) ); /* Another Descriptor Statement */ if ( c == '/' ) { if ( TD->ddesc == NULL ) DD = TD->ddesc = trc_create_datadesc(); else DD = DD->next = trc_create_datadesc(); /* Get Second '/' */ c = getc( ID->trace_in ); TRC_CKEOF( c, "EOF Reading Event Descriptor\n", return( (TRC_TEVDESC) NULL ) ); if ( c != '/' ) { printf( "Error Parsing Event Descriptor\n" ); return( (TRC_TEVDESC) NULL ); } /* Read in TRC_DID Name */ if ( !trc_find_event_str( ID, "\"" ) ) return( (TRC_TEVDESC) NULL ); i = 0; while ( (c = getc( ID->trace_in )) != (char) EOF && c != '"' && i < 8 ) { did[i++] = c; } TRC_CKEOF( c, "EOF Reading Event Descriptor\n", return( (TRC_TEVDESC) NULL ) ); if ( c != '"' ) { printf( "Error Parsing Event Descriptor\n" ); return( (TRC_TEVDESC) NULL ); } did[i] = '\0'; /* Read in TRC_DID Description */ if ( !trc_find_event_str( ID, "\"" ) ) return( (TRC_TEVDESC) NULL ); i = 0; while ( (c = getc( ID->trace_in )) != (char) EOF && c != '"' && i < 1024 ) { diddesc[i++] = c; } TRC_CKEOF( c, "EOF Reading Event Descriptor\n", return( (TRC_TEVDESC) NULL ) ); if ( c != '"' ) { printf( "Error Parsing Event Descriptor\n" ); return( (TRC_TEVDESC) NULL ); } diddesc[i] = '\0'; /* Get Descriptor TRC_DID struct */ DD->did = (TRC_DID) trc_lookup_trie( TRC_DID_TRIE, (void *) did ); if ( DD->did == NULL ) { DD->did = trc_create_did(); DD->did->name = trc_copy_str( did ); DD->did->desc = trc_copy_str( diddesc ); } /* Get Data Type */ while ( (c = getc( ID->trace_in )) != (char) EOF && ( c == ' ' || c == '\t' || c == '\n' ) ); TRC_CKEOF( c, "EOF Reading Event Descriptor\n", return( (TRC_TEVDESC) NULL ) ); dtstr[0] = c; i = 1; while ( (c = getc( ID->trace_in )) != (char) EOF && c != ' ' && c != '\t' && c != '\n' && c != '"' ) { dtstr[i++] = c; } TRC_CKEOF( c, "EOF Reading Event Descriptor\n", return( (TRC_TEVDESC) NULL ) ); dtstr[i] = '\0'; DD->dt = trc_get_dt_str( dtstr ); if ( DD->dt < 0 ) { printf( "Error: Unknown Data Type \"%s\".\n", dtstr ); return( (TRC_TEVDESC) NULL ); } /* Skip over var name */ if ( c != '"' ) { if ( !trc_find_event_str( ID, "\"" ) ) return( (TRC_TEVDESC) NULL ); } if ( !trc_find_event_str( ID, "\"" ) ) return( (TRC_TEVDESC) NULL ); /* Check for Data Array */ c = getc( ID->trace_in ); TRC_CKEOF( c, "EOF Reading Event Descriptor\n", return( (TRC_TEVDESC) NULL ) ); if ( c == '[' ) { if ( DD->dt == TEV_DATA_BYTE || DD->dt == TEV_DATA_STRING ) { /* Get closing ']' */ c = getc( ID->trace_in ); TRC_CKEOF( c, "EOF Reading Event Descriptor\n", return( (TRC_TEVDESC) NULL ) ); if ( c != ']' ) { printf( "Error Parsing Event Descriptor\n" ); return( (TRC_TEVDESC) NULL ); } /* Check for another [] */ c = getc( ID->trace_in ); TRC_CKEOF( c, "EOF Reading Event Descriptor\n", return( (TRC_TEVDESC) NULL ) ); /* [][] -> STRING[] */ if ( c == '[' ) { if ( DD->dt == TEV_DATA_BYTE ) DD->dt = TEV_DATA_STRING; DD->array = TEV_DATA_ARRAY; } /* [] -> BYTE[] */ else { if ( DD->dt == TEV_DATA_STRING ) DD->dt = TEV_DATA_BYTE; DD->array = TEV_DATA_ARRAY; } } else DD->array = TEV_DATA_ARRAY; } else DD->array = TEV_DATA_SCALAR; } /* End of Descriptor */ else { if ( !trc_find_event_end( ID ) ) return( (TRC_TEVDESC) NULL ); done++; } } while ( !done ); tdptr = (TRC_TEVDESC) trc_lookup_trie( TRC_EVENT_TRIE, name ); if ( tdptr == NULL ) trc_add_to_trie( TRC_EVENT_TRIE, name, (void *) TD ); else { while ( tdptr->next != NULL ) { /* Use index, too - trace file events will... D-Oh! */ if ( trc_cmp_tevdesc( TD, tdptr ) && TD->index == tdptr->index ) { trc_free_tevdesc( &TD ); return( tdptr ); } tdptr = tdptr->next; } /* Use index, too - trace file events will... D-Oh! */ if ( trc_cmp_tevdesc( TD, tdptr ) && TD->index == tdptr->index ) { trc_free_tevdesc( &TD ); return( tdptr ); } else tdptr->next = TD; } /* Set Handle ID */ tmp = (long) trc_lookup_trie( TRC_HANDLE_TRIE, TD->name ); TD->hid = (int) tmp; return( TD ); } int trc_process_trace_event( ID, name, entry_exit, index ) TRC_ID ID; char *name; int entry_exit; int index; { TRC_DATADESC DD; TRC_TEVDESC TD; TRC_TEVREC TR; TRC_TEVREC trptr; char read_str[TRC_MAX_UNPACK_ARR_SIZE]; unsigned short read_ushort; unsigned long read_ulong; unsigned int read_uint; double read_double; float read_float; short read_short; long read_long; int read_int; char c; int i, j; int flag; int num; if ( !(ID->handle_event) ) { trc_find_event_end( ID ); return( TRC_TRUE ); } TD = (TRC_TEVDESC) trc_lookup_trie( TRC_EVENT_TRIE, name ); while ( TD != NULL && ( TD->entry_exit != entry_exit || TD->index != index ) ) { TD = TD->next; } if ( TD == NULL ) { printf( "Error: Event \"%s\" Descriptor Not Found\n", name ); trc_find_event_end( ID ); return( TRC_FALSE ); } if ( !trc_find_event_str( ID, "{" ) ) return( TRC_FALSE ); /* matching } */ DD = TD->ddesc; TR = (TRC_TEVREC) NULL; while ( DD != NULL ) { if ( TR == NULL ) trptr = TR = trc_create_tevrec(); else trptr = trptr->next = trc_create_tevrec(); trptr->ddesc = DD; if ( DD->array == TEV_DATA_ARRAY ) { if ( !trc_find_event_str( ID, "[" ) ) return( TRC_FALSE ); flag = fscanf( ID->trace_in, "%d", &num ); if ( flag != 1 ) { printf( "Error Parsing Event Record\n" ); trc_find_event_end( ID ); return( TRC_FALSE ); } if ( !trc_find_event_str( ID, "{" ) ) return( TRC_FALSE ); /* matching } */ } else num = 1; trptr->value = trc_make_value( DD->dt, ( num > 0 ) ? num : 1 ); if ( trptr->value == NULL ) { printf( "Error Allocating Value dt=%d num=%d\n", DD->dt, num ); return( TRC_FALSE ); } trptr->num = num; switch ( DD->dt ) { case TEV_DATA_NULL: break; case TEV_DATA_BYTE: { if ( DD->array == TEV_DATA_ARRAY ) { if ( !trc_find_event_str( ID, "\"" ) ) return( TRC_FALSE ); i = 0; while ( i < num && (c = getc( ID->trace_in )) != (char) EOF && c != '"' ) { TRC_ARR_VALUE_OF( trptr->value, char, i++ ) = c; } TRC_CKEOF( c, "EOF Parsing Event Record\n", return( TRC_FALSE ) ); if ( i == num ) { printf( "Error: Character Overflow\n" ); return( TRC_FALSE ); } TRC_ARR_VALUE_OF( trptr->value, char, i ) = '\0'; } else { while ( (c = getc( ID->trace_in )) != (char) EOF && ( c == ' ' || c == '\t' || c == '\n' ) ); TRC_CKEOF( c, "EOF Parsing Event Record\n", return( TRC_FALSE ) ); TRC_VALUE_OF( trptr->value, char ) = c; } break; } case TEV_DATA_CPLX: case TEV_DATA_FLOAT: { for ( i=0 ; i < num ; i++ ) { flag = fscanf( ID->trace_in, "%f", &read_float ); if ( flag != 1 ) { printf( "Error Parsing Event Record\n" ); trc_find_event_end( ID ); return( TRC_FALSE ); } TRC_ARR_VALUE_OF( trptr->value, float, i ) = read_float; if ( i < num - 1 ) { if ( !trc_find_event_str( ID, "," ) ) return( TRC_FALSE ); } } break; } case TEV_DATA_DCPLX: case TEV_DATA_DOUBLE: { for ( i=0 ; i < num ; i++ ) { flag = fscanf( ID->trace_in, "%lf", &read_double ); if ( flag != 1 ) { printf( "Error Parsing Event Record\n" ); trc_find_event_end( ID ); return( TRC_FALSE ); } TRC_ARR_VALUE_OF( trptr->value, double, i ) = read_double; if ( i < num - 1 ) { if ( !trc_find_event_str( ID, "," ) ) return( TRC_FALSE ); } } break; } case TEV_DATA_INT: { for ( i=0 ; i < num ; i++ ) { flag = fscanf( ID->trace_in, "%d", &read_int ); if ( flag != 1 ) { printf( "Error Parsing Event Record\n" ); trc_find_event_end( ID ); return( TRC_FALSE ); } TRC_ARR_VALUE_OF( trptr->value, int, i ) = read_int; if ( i < num - 1 ) { if ( !trc_find_event_str( ID, "," ) ) return( TRC_FALSE ); } } break; } case TEV_DATA_UINT: { for ( i=0 ; i < num ; i++ ) { flag = fscanf( ID->trace_in, "%u", &read_uint ); if ( flag != 1 ) { printf( "Error Parsing Event Record\n" ); trc_find_event_end( ID ); return( TRC_FALSE ); } TRC_ARR_VALUE_OF( trptr->value, unsigned int, i ) = read_uint; if ( i < num - 1 ) { if ( !trc_find_event_str( ID, "," ) ) return( TRC_FALSE ); } } break; } case TEV_DATA_LONG: { for ( i=0 ; i < num ; i++ ) { flag = fscanf( ID->trace_in, "%ld", &read_long ); if ( flag != 1 ) { printf( "Error Parsing Event Record\n" ); trc_find_event_end( ID ); return( TRC_FALSE ); } TRC_ARR_VALUE_OF( trptr->value, long, i ) = read_long; if ( i < num - 1 ) { if ( !trc_find_event_str( ID, "," ) ) return( TRC_FALSE ); } } break; } case TEV_DATA_ULONG: { for ( i=0 ; i < num ; i++ ) { flag = fscanf( ID->trace_in, "%lu", &read_ulong ); if ( flag != 1 ) { printf( "Error Parsing Event Record\n" ); trc_find_event_end( ID ); return( TRC_FALSE ); } TRC_ARR_VALUE_OF( trptr->value, unsigned long, i ) = read_ulong; if ( i < num - 1 ) { if ( !trc_find_event_str( ID, "," ) ) return( TRC_FALSE ); } } break; } case TEV_DATA_SHORT: { for ( i=0 ; i < num ; i++ ) { flag = fscanf( ID->trace_in, "%hd", &read_short ); if ( flag != 1 ) { printf( "Error Parsing Event Record\n" ); trc_find_event_end( ID ); return( TRC_FALSE ); } TRC_ARR_VALUE_OF( trptr->value, short, i ) = read_short; if ( i < num - 1 ) { if ( !trc_find_event_str( ID, "," ) ) return( TRC_FALSE ); } } break; } case TEV_DATA_USHORT: { for ( i=0 ; i < num ; i++ ) { flag = fscanf( ID->trace_in, "%hu", &read_ushort ); if ( flag != 1 ) { printf( "Error Parsing Event Record\n" ); trc_find_event_end( ID ); return( TRC_FALSE ); } TRC_ARR_VALUE_OF( trptr->value, unsigned short, i ) = read_ushort; if ( i < num - 1 ) { if ( !trc_find_event_str( ID, "," ) ) return( TRC_FALSE ); } } break; } case TEV_DATA_STRING: { if ( DD->array == TEV_DATA_SCALAR ) { if ( !trc_find_event_str( ID, "{" ) ) return( TRC_FALSE ); } for ( i=0 ; i < num ; i++ ) { if ( !trc_find_event_str( ID, "\"" ) ) return( TRC_FALSE ); j = 0; while ( (c = getc( ID->trace_in )) != (char) EOF && c != '"' ) { read_str[j++] = c; } TRC_CKEOF( c, "EOF Parsing Event Record\n", return( TRC_FALSE ) ); read_str[j] = '\0'; TRC_ARR_VALUE_OF( trptr->value, char *, i ) = trc_copy_str( read_str ); if ( i < num - 1 ) { if ( !trc_find_event_str( ID, "," ) ) return( TRC_FALSE ); } } if ( DD->array == TEV_DATA_SCALAR ) { if ( !trc_find_event_str( ID, "}" ) ) return( TRC_FALSE ); } break; } case TEV_DATA_STRUCT_START: case TEV_DATA_STRUCT_END: case TEV_DATA_DEFERRED: { printf( "DT Not Impl\n" ); trc_find_event_end( ID ); return( TRC_FALSE ); } default: { printf( "DT Unknown\n" ); trc_find_event_end( ID ); return( TRC_FALSE ); } } if ( DD->array == TEV_DATA_ARRAY ) { /* matching { */ if ( !trc_find_event_str( ID, "}" ) ) return( TRC_FALSE ); } if ( DD->next != NULL ) { if ( !trc_find_event_str( ID, "," ) ) return( TRC_FALSE ); } DD = DD->next; } (ID->handle_event)( ID, TD, TR ); trc_free_tevrec( &TR ); return( TRC_TRUE ); } int trc_find_event_str_ret( ID, str, retstr, retlen ) TRC_ID ID; char *str; char *retstr; int retlen; { char tmp[1024]; char c; int index; int i, j; int nope; int len; int r; len = strlen( str ); for ( i=0 ; i < len ; i++ ) tmp[i] = '\0'; r = 0; i = 0; while ( (c = getc( ID->trace_in )) != (char) EOF ) { if ( retstr && r < retlen - 1 ) retstr[r++] = c; tmp[i] = c; nope = 0; for ( j=0 ; j < len && !nope ; j++ ) { index = i - len + j + 1; index = index < 0 ? index + len : index; if ( tmp[index] != str[j] ) nope++; } if ( !nope ) { if ( retstr ) retstr[r] = '\0'; return( TRC_TRUE ); } i = ( i + 1 ) % len; } printf( "EOF Reading Trace File - \"%s\" not found.\n", str ); if ( retstr ) retstr[r] = '\0'; return( TRC_FALSE ); } int trc_find_event_str( ID, str ) TRC_ID ID; char *str; { return( trc_find_event_str_ret( ID, str, (char *) NULL, 0 ) ); } int trc_find_event_end_ret( ID, retstr, retlen ) TRC_ID ID; char *retstr; int retlen; { return( trc_find_event_str_ret( ID, ";;", retstr, retlen ) ); } int trc_find_event_end( ID ) TRC_ID ID; { return( trc_find_event_end_ret( ID, (char *) NULL, 0 ) ); } ./pvm3/tracer/trcglob.c0100644007401100000360000000231506354310500014155 0ustar kohlgopher static char rcsid[] = "$Id: trcglob.c,v 4.2 1997/06/25 21:44:32 pvmsrc Exp $"; /* * Tracer version 1.0: A Trace File Generator for PVM * Oak Ridge National Laboratory, Oak Ridge TN. * Authors: James Arthur Kohl and G. A. Geist * (C) 1994 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear * in supporting documentation. * * Neither the Institution, Oak Ridge National Laboratory, nor the * Authors make any representations about the suitability of this * software for any purpose. This software is provided ``as is'' * without express or implied warranty. * * Tracer was funded by the U.S. Department of Energy. */ /* Tracer Header */ #include "tracer.h" /* Globals Variables */ TRC_ID ID; Pvmtmask TRACE_MASK; Pvmtmask CLEAR_MASK; char *OUTPUT_FILE; char *TRACE_FILE; int TRACER_REGISTERED; int TRACE_BUF; int TRACE_OPT; int MYTID; int vflag; ./pvm3/tracer/trclib.c0100644007401100000360000000371006236210201013774 0ustar kohlgopher static char rcsid[] = "$Id: trclib.c,v 4.1 1996/10/31 20:48:01 pvmsrc Exp $"; /* * Tracer version 1.0: A Trace File Generator for PVM * Oak Ridge National Laboratory, Oak Ridge TN. * Authors: James Arthur Kohl and G. A. Geist * (C) 1994 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear * in supporting documentation. * * Neither the Institution, Oak Ridge National Laboratory, nor the * Authors make any representations about the suitability of this * software for any purpose. This software is provided ``as is'' * without express or implied warranty. * * Tracer was funded by the U.S. Department of Energy. */ /* Tracer Library Header */ #include "trclib.h" /* Global Variables */ struct timeval TRC_TRACE_TIME; TRC_TEVDESC TRC_OUTPUT_TEVDESC; TRC_TEVDESC TRC_HOST_ADD_TEVDESC; TRC_TEVDESC TRC_HOST_DEL_TEVDESC; TRC_TEVDESC TRC_HOST_SYNC_TEVDESC; TRC_TEVDESC *TRC_TEVDESC_LIST; int TRC_TEVDESC_SIZE; TRC_TEVREC TRC_TMP_TR; TRC_TRIE TRC_OLD_EVENT_TRIE; TRC_TRIE TRC_HANDLE_TRIE; TRC_TRIE TRC_EVENT_TRIE; TRC_TRIE TRC_DID_TRIE; TRC_DID TRC_LOCAL_DID[ TEV_DID_MAX - TEV_DID_FIRST + 1 ]; TRC_DID TRC_DID_LIST; TRC_ID TRC_DEAD_ID_LIST; TRC_ID TRC_ID_LIST; char *TRC_TYPE_STRS[16] = { "void", "char", "float", "double", "double", "float", "int", "int", "int", "int", "int", "int", "char", "void", "void", "void" }; char *TRC_VERSION; char *TRC_NAME; char *TRC_TMP_HOST; TRC_HOST TRC_HOST_LIST; char *TRC_HOST_NAME; char *TRC_HOST_ALIAS; int TRC_HOST_ADD_NOTIFY_CODE; int TRC_HOST_DEL_NOTIFY_CODE; int TRC_TID; int TRC_TMP_CMP; int TRC_TMP_CC; ./pvm3/tracer/trcmess.c0100644007401100000360000004020306463734355014222 0ustar kohlgopher static char rcsid[] = "$Id: trcmess.c,v 4.7 1998/01/28 23:02:05 pvmsrc Exp $"; /* * Tracer version 1.0: A Trace File Generator for PVM * Oak Ridge National Laboratory, Oak Ridge TN. * Authors: James Arthur Kohl and G. A. Geist * (C) 1994 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear * in supporting documentation. * * Neither the Institution, Oak Ridge National Laboratory, nor the * Authors make any representations about the suitability of this * software for any purpose. This software is provided ``as is'' * without express or implied warranty. * * Tracer was funded by the U.S. Department of Energy. */ /* Tracer Library Header */ #include "trclib.h" #ifdef SYSVSTR #include #else #include #endif /* Routines */ int trc_recv_messages( ID, max_count, status ) TRC_ID ID; int max_count; int *status; { static int *tids = (int *) NULL; static int ntids = 0; TRC_HOST H; TRC_ID DEAD_ID_last; TRC_ID DEAD_ID_next; TRC_ID DEAD_ID; int msgtag; int others; int ecnt; int cnt; int len; int mid; int num; int tid; int src; int tmp; int cc; int i; /* Verify Message Codes Set */ if ( TRC_HOST_ADD_NOTIFY_CODE == -1 || TRC_HOST_DEL_NOTIFY_CODE == -1 #ifndef USE_PVM_33 || ID->event_ctx == -1 || ID->output_ctx == -1 #endif || ID->event_tag == -1 || ID->output_tag == -1 ) { printf( "Error: Message Codes Not Set - %d %d %d %d %d %d\n", TRC_HOST_ADD_NOTIFY_CODE, TRC_HOST_DEL_NOTIFY_CODE, ID->event_ctx, ID->output_ctx, ID->event_tag, ID->output_tag ); return( -1 ); } /* Clear Out Flags */ if ( status != NULL ) *status = TRC_MSG_STATUS_NONE; /* Init Event Counter */ ecnt = 0; /* Check for Host Sync Updates */ ecnt += trc_check_host_sync( ID ); /* Receive Stuff */ cnt = 0; while ( cnt < max_count && (mid = trc_get_msg( ID, &len, &msgtag, &src, &others )) > 0 ) { /* Set Activity Flag */ if ( status != NULL ) *status |= TRC_MSG_STATUS_ACTIVE; /* Host Added */ if ( msgtag == TRC_HOST_ADD_NOTIFY_CODE && src == 0x80000000 ) { cc = pvm_upkint( &num, 1, 1 ); if ( cc < 0 ) pvm_perror( "Error Unpacking Host Add Notify" ); else { if ( num > ntids ) { ntids = num * 2; if ( tids ) free( tids ); tids = (int *) malloc( (unsigned) ntids * sizeof(int) ); trc_memcheck( tids, "Host Add Notify Tids Array" ); } cc = pvm_upkint( tids, num, 1 ); if ( cc < 0 ) pvm_perror( "Error Unpacking Host Add TIDs" ); else { pvm_notify( PvmHostDelete, TRC_HOST_DEL_NOTIFY_CODE, num, tids ); ecnt += trc_handle_host_add_notify( ID, tids, num ); } } } /* Host Deleted */ else if ( msgtag == TRC_HOST_DEL_NOTIFY_CODE && src == 0x80000000 ) { cc = pvm_upkint( &tid, 1, 1 ); if ( cc < 0 ) pvm_perror( "Error Unpacking Host Delete Notify" ); else ecnt += trc_handle_host_del_notify( ID, tid ); } /* PVM Trace Event */ else if ( msgtag == ID->event_tag ) { ecnt += trc_handle_trace_message( ID, src ); if ( status != NULL ) { if ( ecnt ) *status |= TRC_MSG_STATUS_OVERWRITE; else *status |= TRC_MSG_STATUS_CLEANUP; } } /* PVM Output Event */ else if ( msgtag == ID->output_tag ) { ecnt += trc_handle_output_message( ID ); if ( status != NULL ) { if ( ecnt ) *status |= TRC_MSG_STATUS_OVERWRITE; else *status |= TRC_MSG_STATUS_CLEANUP; } } /* Unknown Message */ else { fprintf( stderr, "Tracer: msg from 0x%x code %d len %d ?\n", src, msgtag, len ); } if ( pvm_freebuf( mid ) < 0 ) pvm_perror( "Error Freeing Message Buffer" ); cnt++; } if ( mid < 0 ) { pvm_perror( "PVM System Failure" ); printf( "Tracer exiting...\n" ); return( -1 ); } if ( status != NULL ) { if ( cnt == max_count ) *status |= TRC_MSG_STATUS_MORE; } /* Try Flushing Dead IDs */ if ( others ) { DEAD_ID = TRC_DEAD_ID_LIST; DEAD_ID_last = (TRC_ID ) NULL; while ( DEAD_ID != NULL ) { trc_recv_messages( DEAD_ID, 1, &tmp ); if ( status != NULL ) *status |= tmp; if ( trc_tevtasks_dead( DEAD_ID ) ) { DEAD_ID_next = DEAD_ID->next; if ( DEAD_ID_last != NULL ) DEAD_ID_last->next = DEAD_ID_next; else TRC_DEAD_ID_LIST = DEAD_ID_next; trc_free_tracer_id( &DEAD_ID ); DEAD_ID = DEAD_ID_next; } else { DEAD_ID_last = DEAD_ID; DEAD_ID = DEAD_ID->next; } } } return( ecnt ); } int trc_get_msg( ID, len, msgtag, src, others ) TRC_ID ID; int *len; int *msgtag; int *src; int *others; { int mid; int tag; /* Reset "Others" Flag */ if ( others != NULL ) *others = TRC_FALSE; /* Check for Host Add */ if ( (mid = pvm_nrecv( -1, TRC_HOST_ADD_NOTIFY_CODE )) > 0 ) { if ( pvm_bufinfo( mid, len, msgtag, src ) < 0 ) { pvm_perror( "Error Checking Message Buffer" ); return( -1 ); } return( mid ); } else if ( mid < 0 ) { pvm_perror( "Error Checking Host Add Notify Message" ); return( -1 ); } /* Check for Host Delete */ if ( (mid = pvm_nrecv( -1, TRC_HOST_DEL_NOTIFY_CODE )) > 0 ) { if ( pvm_bufinfo( mid, len, msgtag, src ) < 0 ) { pvm_perror( "Error Checking Message Buffer" ); return( -1 ); } return( mid ); } else if ( mid < 0 ) { pvm_perror( "Error Checking Host Delete Notify Message" ); return( -1 ); } /* Any message at all? */ if ( (mid = pvm_probe( -1, -1 )) > 0 ) { if ( pvm_bufinfo( mid, len, &tag, src ) < 0 ) { pvm_perror( "Error Checking Message Buffer" ); return( -1 ); } if ( msgtag != NULL ) *msgtag = tag; /* The next one's for us... */ if ( tag == ID->event_tag || tag == ID->output_tag ) { pvm_recv( -1, -1 ); return( mid ); } /* Or not... */ else { if ( others != NULL ) *others = TRC_TRUE; return( 0 ); } } /* System Error */ else if ( mid < 0 ) { pvm_perror( "Error Probing for Trace / Output Messages" ); return( -1 ); } /* No Messages */ else return( 0 ); } int trc_handle_trace_message( ID, src ) TRC_ID ID; int src; { TRC_DATADESC DD; TRC_TEVDESC TD; TRC_TEVTASK TT; TRC_HOST H; TRC_DID dptr; char diddesc[1024]; char tmp[1024]; char did[8]; int desc_done; int did_done; int done; int omit; int entry_exit; int dump_event; int pvmd_tid; int did_int; int tusec; int tsec; int ecnt; int eid; int tid; int dt; int marker; int nest; ecnt = 0; TRC_PVMCKERR( pvm_upkint( &marker, 1, 1 ), "Unpacking Trace Message", return( ecnt ) ); /* Old PVM 3.3 Trace Format */ if ( marker > 0 ) { tsec = marker; TRC_PVMCKERR( pvm_upkint( &tusec, 1, 1 ), "Event Parse Error", return( ecnt ) ); TRC_PVMCKERR( pvm_upkint( &tid, 1, 1 ), "Event Parse Error", return( ecnt ) ); TRC_PVMCKERR( pvm_upkint( &eid, 1, 1 ), "Event Parse Error", return( ecnt ) ); ecnt += trc_store_old_trace_event( ID, tsec, tusec, tid, eid ); return( ecnt ); } /* New PVM 3.4 Format */ /* Get Task & Host Info */ TT = trc_get_tevtask_tid( ID, src ); pvmd_tid = pvm_tidtohost( src ); if ( !pvmd_tid ) pvmd_tid = pvm_tidtohost( TRC_TID ); H = trc_get_host_tid( pvmd_tid ); /* Set Leftover Event Omit Flag */ omit = ( ID->trace_out == NULL || ( TT != NULL && TRC_TASK_OMIT( TT ) ) ) ? TRC_TRUE : TRC_FALSE; /* Process Event Message */ nest = 0; done = 0; do { switch ( marker ) { case TEV_MARK_EVENT_BUFFER: { nest++; break; } case TEV_MARK_EVENT_BUFFER_END: { if ( !(--nest) ) done++; break; } case TEV_MARK_DATA_ID: { did_done = 0; do { TRC_PVMCKERR( pvm_upkint( &did_int, 1, 1 ), "Data ID Message", return( ecnt ) ); if ( did_int != TEV_MARK_DATA_ID_END ) { TRC_PVMCKERR( pvm_upkstr( did ), "Data ID Name", return( ecnt ) ); TRC_PVMCKERR( pvm_upkstr( diddesc ), "Data ID Description", return( ecnt ) ); dptr = (TRC_DID) trc_lookup_trie( TRC_DID_TRIE, did ); if ( dptr == NULL || dptr->id != did_int || strcmp( dptr->desc, diddesc ) ) { dptr = trc_create_did(); dptr->id = did_int; dptr->name = trc_copy_str( did ); dptr->desc = trc_copy_str( diddesc ); dptr->next = TRC_DID_LIST; TRC_DID_LIST = dptr; trc_add_to_trie( TRC_DID_TRIE, dptr->name, (void *) dptr ); } trc_set_didlist( H, dptr ); } else did_done++; } while ( !did_done ); if ( !nest ) done++; break; } case TEV_MARK_EVENT_DESC: { TD = trc_create_tevdesc(); TD->refcount = 1; TRC_PVMCKERR( pvm_upkint( &eid, 1, 1 ), "Event Descriptor ID", return( ecnt ) ); TD->eid = eid & ~( TEV_EVENT_ENTRY | TEV_EVENT_EXIT ); if ( eid & TEV_EVENT_ENTRY ) TD->entry_exit = TRC_ENTRY_TEV; else if ( eid & TEV_EVENT_EXIT ) TD->entry_exit = TRC_EXIT_TEV; else TD->entry_exit = TRC_IGNORE_TEV; TRC_PVMCKERR( pvm_upkstr( tmp ), "Event Descriptor Name", return( ecnt ) ); TD->name = trc_copy_str( tmp ); desc_done = 0; do { TRC_PVMCKERR( pvm_upkint( &did_int, 1, 1 ), "Semantic Data ID", return( ecnt ) ); if ( did_int != TEV_MARK_EVENT_DESC_END ) { if ( TD->ddesc == NULL ) DD = TD->ddesc = trc_create_datadesc(); else DD = DD->next = trc_create_datadesc(); if ( H->didlist == NULL ) { printf( "Warning: Missing DID List For Host %s\n", H->name ); } DD->did = trc_get_did( H, did_int ); if ( DD->did == NULL ) { printf( "Error: DID=%d Not Found\n", did_int ); trc_free_tevdesc( &TD ); return( ecnt ); } TRC_PVMCKERR( pvm_upkint( &dt, 1, 1 ), "Data Type", return( ecnt ) ); DD->dt = dt & ~( TEV_DATA_SCALAR | TEV_DATA_ARRAY ); DD->array = dt & ( TEV_DATA_SCALAR | TEV_DATA_ARRAY ); if ( !trc_unpack_data_value( DD ) ) { trc_free_tevdesc( &TD ); return( ecnt ); } } else desc_done++; } while ( !desc_done ); dump_event = trc_add_tevdesc( ID, &TD, src, omit ); trc_set_tevlist( TT, H, TD ); if ( TD->dump ) trc_dump_tevdesc( ID, TD, src ); if ( dump_event ) trc_store_data_values( ID, TD, src, omit ); if ( !omit ) ecnt++; if ( !nest ) done++; break; } case TEV_MARK_USER_EVENT_RECORD: { TD = trc_create_tevdesc(); TD->refcount = 1; TRC_PVMCKERR( pvm_upkint( &eid, 1, 1 ), "Event Descriptor ID", return( ecnt ) ); TD->eid = eid & ~( TEV_EVENT_ENTRY | TEV_EVENT_EXIT ); if ( eid & TEV_EVENT_ENTRY ) TD->entry_exit = TRC_ENTRY_TEV; else if ( eid & TEV_EVENT_EXIT ) TD->entry_exit = TRC_EXIT_TEV; else TD->entry_exit = TRC_IGNORE_TEV; TRC_PVMCKERR( pvm_upkstr( tmp ), "Event Descriptor Name", return( ecnt ) ); TD->name = trc_copy_str( tmp ); /* Yank Out Hardwired Timestamp */ DD = TD->ddesc = trc_create_datadesc(); DD->did = trc_get_did( (TRC_HOST) NULL, TEV_DID_TS ); DD->dt = TEV_DATA_INT; DD->array = TEV_DATA_SCALAR; if ( !trc_unpack_data_value( DD ) ) { trc_free_tevdesc( &TD ); return( ecnt ); } DD = DD->next = trc_create_datadesc(); DD->did = trc_get_did( (TRC_HOST) NULL, TEV_DID_TU ); DD->dt = TEV_DATA_INT; DD->array = TEV_DATA_SCALAR; if ( !trc_unpack_data_value( DD ) ) { trc_free_tevdesc( &TD ); return( ecnt ); } desc_done = 0; do { TRC_PVMCKERR( pvm_upkint( &dt, 1, 1 ), "Data Type", return( ecnt ) ); if ( dt != TEV_MARK_USER_EVENT_RECORD_END ) { DD = DD->next = trc_create_datadesc(); DD->dt = dt & ~( TEV_DATA_SCALAR | TEV_DATA_ARRAY ); DD->array = dt & ( TEV_DATA_SCALAR | TEV_DATA_ARRAY ); if ( !trc_unpack_data_value( DD ) ) { trc_free_tevdesc( &TD ); return( ecnt ); } } else desc_done++; } while ( !desc_done ); dump_event = trc_add_tevdesc( ID, &TD, src, omit ); if ( TD->dump ) trc_dump_tevdesc( ID, TD, src ); if ( dump_event ) trc_store_data_values( ID, TD, src, omit ); if ( !omit ) ecnt++; if ( !nest ) done++; break; } case TEV_MARK_EVENT_RECORD: { TRC_PVMCKERR( pvm_upkint( &eid, 1, 1 ), "Event ID", return( ecnt ) ); if ( eid & TEV_EVENT_ENTRY ) entry_exit = TRC_ENTRY_TEV; else if ( eid & TEV_EVENT_EXIT ) entry_exit = TRC_EXIT_TEV; else entry_exit = TRC_IGNORE_TEV; eid &= ~( TEV_EVENT_ENTRY | TEV_EVENT_EXIT ); TD = trc_get_tevdesc( TT, H, eid, entry_exit ); if ( TD != NULL ) { if ( trc_store_trace_event( ID, TD, src, omit ) ) ecnt++; } else { printf( "Error: Event ID %d(%d) %s T(%d/%x) H(%d/%x)\n", eid, entry_exit, "Descriptor Not Found", TT->tid, TT->tid, H->pvmd_tid, H->pvmd_tid ); } if ( !nest ) done++; break; } } if ( !done ) { TRC_PVMCKERR( pvm_upkint( &marker, 1, 1 ), "Unpacking Trace Message", return( ecnt ) ); } } while ( !done ); return( ecnt ); } int trc_handle_output_message( ID ) TRC_ID ID; { TRC_TEVTASK TT; char tmp[255]; char msg[255]; char *output; int ecnt; int omit; int len; int tid; ecnt = 0; TRC_PVMCKERR( pvm_upkint( &tid, 1, 1 ), "Error Unpacking Output Message", return( ecnt ) ); TRC_PVMCKERR( pvm_upkint( &len, 1, 1 ), "Error Unpacking Output Length", return( ecnt ) ); /* Set Leftover Event Omit Flag */ TT = trc_get_tevtask_tid( ID, tid ); omit = ( ID->trace_out == NULL || ( TT != NULL && TRC_TASK_OMIT( TT ) ) ) ? TRC_TRUE : TRC_FALSE; /* Unpack Output */ if ( len > 0 ) { output = (char *) malloc( (unsigned) ( len + 1 ) * sizeof(char) ); trc_memcheck( output, "PVM Output String" ); TRC_PVMCKERR( pvm_upkbyte( output, len, 1 ), "Error Unpacking Task Output", free(output); return( ecnt ) ); output[ len ] = '\0'; if ( !omit ) ecnt = trc_store_output_event( ID, tid, output, len ); free( output ); } else { switch ( len ) { case 0: { if ( !omit ) { sprintf( tmp, "GOTEOF\n" ); ecnt = trc_store_output_event( ID, tid, tmp, strlen(tmp) ); } if ( TT != NULL ) { if ( TT->tevstatus == TRC_TASK_ALIVE ) { TT->outstatus = TRC_TASK_EOF; trc_check_for_dead_host( ID, TT ); if ( !trc_tevtasks_alive( ID ) ) trc_end_trace( ID ); } else TT->outstatus = TRC_TASK_EOF; } else if ( !omit ) { printf( "\nWarning: GOTEOF Unknown Task TID=0x%x.\n\n", tid ); } break; } case -1: { if ( omit ) break; sprintf( tmp, "GOTSPAWN\n" ); ecnt = trc_store_output_event( ID, tid, tmp, strlen(tmp) ); if ( TT == NULL ) { sprintf( msg, "Task TID=0x%x Connected to %s", tid, TRC_NAME ); trc_status_msg( ID, msg ); TT = trc_create_tevtask(); TT->tid = tid; TT->outstatus = TRC_TASK_OUT; TT->tevstatus = TRC_TASK_NOLIFE; TT->next = ID->tevtask_list; ID->tevtask_list = TT; } else TT->outstatus = TRC_TASK_OUT; break; } case -2: { if ( omit ) break; sprintf( tmp, "CREATION\n" ); ecnt = trc_store_output_event( ID, tid, tmp, strlen(tmp) ); if ( TT == NULL ) { sprintf( msg, "Task TID=0x%x Connected to %s", tid, TRC_NAME ); trc_status_msg( ID, msg ); TT = trc_create_tevtask(); TT->tid = tid; TT->outstatus = TRC_TASK_OUT; TT->tevstatus = TRC_TASK_NOLIFE; TT->next = ID->tevtask_list; ID->tevtask_list = TT; } else TT->outstatus = TRC_TASK_OUT; break; } default: { if ( !omit ) { fprintf( stderr, "Console: unknown output msg 0x%x?\n", tid ); } } } } return( ecnt ); } ./pvm3/tracer/trcsort.c0100644007401100000360000004075507452415136014246 0ustar kohlgopher static char rcsid[] = "$Id: trcsort.c,v 4.13 2002/04/02 20:53:50 pvmsrc Exp $"; /* * Trcsort version 1.0: A Trace File Sorter for PVM * Oak Ridge National Laboratory, Oak Ridge TN. * Authors: James Arthur Kohl and G. A. Geist * (C) 1994 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear * in supporting documentation. * * Neither the Institution, Oak Ridge National Laboratory, nor the * Authors make any representations about the suitability of this * software for any purpose. This software is provided ``as is'' * without express or implied warranty. * * Tracer was funded by the U.S. Department of Energy. */ /* Tracer Headers */ #include #include #include #ifdef HASSTDLIB #include #else #ifndef IMA_MACOSX #include #endif #endif #ifdef SYSVSTR #include #else #include #endif #include #include #include "trcdef.h" /* Constants */ #define HANDLE_HOST_SYNC 1 #define MAX_OPEN_FP 10 /* Macros */ #define TIME_COMPARE( _t1, _t2 ) \ ( \ ( (_t1).tv_sec > (_t2).tv_sec \ || ( (_t1).tv_sec == (_t2).tv_sec \ && (_t1).tv_usec > (_t2).tv_usec ) ) ? 1 : \ ( ( (_t1).tv_sec == (_t2).tv_sec \ && (_t1).tv_usec == (_t2).tv_usec ) ? 0 : -1 ) \ ) \ \ /* Data Structures */ struct fp_buffer_struct { FILE *fp; char *rwstr; /* TMPFILE */ struct tmpfile_struct *tmpfile; /* FPBUF */ struct fp_buffer_struct *next; }; typedef struct fp_buffer_struct *FPBUF; struct tmpfile_struct { FPBUF fpbuf; char *fname; long lastseek; TRC_TEVDESC savetd; TRC_TEVREC savetr; int tid; struct timeval nexttime; struct timeval lasttime; struct timeval delta; int valid; int eof; /* TMPFILE */ struct tmpfile_struct *next; }; typedef struct tmpfile_struct *TMPFILE; /* Handler Routines */ TRC_TEVREC save_tevrec(); TMPFILE create_tmpfile(); TMPFILE get_tmpfile(); FPBUF create_fpbuf(); void get_tevrec_tmpfile(); void handle_event_split(); void handle_event_join(); void handle_passthru(); void my_status_msg(); void program_init(); void free_fpbuf(); void read_args(); void sync_time(); void close_fp(); void trc_init(); void cleanup(); void usage(); void bail(); int verify_fp(); /* Globals */ TMPFILE CURRENTTF; TMPFILE LASTTF; TMPFILE TMPF; FPBUF FPS; int NFPS; TRC_ID ID; char DIRNAME[255]; char *TRACE_OUTFILE; char *TRACE_INFILE; char *OUTPUT_FILE; int vflag; /* MAIN */ int main( argc, argv ) int argc; char **argv; { TMPFILE NEXTTF; TMPFILE HOSTTF; TMPFILE TF; static struct timeval tmpt = { -1, -1 }; int host; int done; int eof; /* Read Command Line Args */ read_args( argc, argv ); /* Initialize Program Constants & Structs */ program_init(); /* Initialize Tracer Globals */ trc_init(); /* Parse Input Trace, Create Subfiles */ while ( trc_read_trace_event( ID, &eof ) ); fclose( ID->trace_in ); /* Flush Temporary File Ptrs, Reset Subfiles for Reading */ TF = TMPF; while ( TF != NULL ) { close_fp( TF ); TF->eof = TRC_FALSE; TF = TF->next; } /* Reset Pass Thru -> All Goes to Output Trace Now */ LASTTF = (TMPFILE) NULL; /* Set Event Handling for Joining */ ID->handle_event = handle_event_join; /* Read In First Event From Each Subfile (Prime Pump) */ TF = TMPF; while ( TF != NULL ) { /* Check Setting of Time Stamp Delta */ host = pvm_tidtohost( TF->tid ); if ( host != TF->tid ) { HOSTTF = get_tmpfile( host, &tmpt, TRC_FALSE ); if ( HOSTTF != NULL ) { TF->delta.tv_sec = HOSTTF->delta.tv_sec; TF->delta.tv_usec = HOSTTF->delta.tv_usec; } } /* Get First Event (Record) */ TF->valid = TRC_FALSE; do { get_tevrec_tmpfile( TF ); } while( !(TF->valid) && !(TF->eof) ); if ( TF->eof ) close_fp( TF ); TF = TF->next; } /* Read In Subfiles, Dump Sorted Trace */ do { done = TRC_TRUE; /* Find "Next" Trace Event */ NEXTTF = (TMPFILE) NULL; TF = TMPF; while ( TF != NULL ) { if ( TF->valid ) { if ( NEXTTF != NULL ) { if ( TIME_COMPARE( TF->nexttime, NEXTTF->nexttime ) < 0 || ( TIME_COMPARE( TF->nexttime, NEXTTF->nexttime ) == 0 && TF->tid < NEXTTF->tid ) ) { NEXTTF = TF; } } else NEXTTF = TF; done = TRC_FALSE; } TF = TF->next; } /* Dump It */ if ( NEXTTF != NULL ) { trc_store_tevrec( ID, NEXTTF->savetd, NEXTTF->savetr, NEXTTF->tid ); /* Get Next Event for Task */ NEXTTF->valid = TRC_FALSE; do { get_tevrec_tmpfile( NEXTTF ); } while( !(NEXTTF->valid) && !(NEXTTF->eof) ); if ( NEXTTF->eof ) close_fp( NEXTTF ); } } while ( !done ); fclose( ID->trace_out ); cleanup(); exit( 0 ); } void handle_event_split( trcid, TD, TR ) TRC_ID trcid; TRC_TEVDESC TD; TRC_TEVREC TR; { TMPFILE TFptr; TMPFILE TF; FILE *fpsave; struct timeval tmpt; int tid; if ( trcid != ID ) { printf( "Error: Unknown Trace ID\n" ); return; } /* Grab Task ID from Event */ tid = TRC_GET_TEVREC_VALUE( TR, "TID", int ); tmpt.tv_sec = TRC_GET_TEVREC_VALUE( TR, "TS", int ); tmpt.tv_usec = TRC_GET_TEVREC_VALUE( TR, "TU", int ); /* Key Off of TID & Time Stamp to Select Temp File */ TF = get_tmpfile( tid, &tmpt, TRC_TRUE ); if ( TF == NULL ) { printf( "\nError Creating Temporary Trace File\n\n" ); bail(); } /* Set Time Stamp Marker */ TF->lasttime.tv_sec = tmpt.tv_sec; TF->lasttime.tv_usec = tmpt.tv_usec; /* Check for Host Sync */ if ( TD->hid == HANDLE_HOST_SYNC ) { TF->delta.tv_sec = TRC_GET_TEVREC_VALUE( TR, "HDS", int ); TF->delta.tv_usec = TRC_GET_TEVREC_VALUE( TR, "HDU", int ); TFptr = TMPF; while ( TFptr != NULL ) { if ( TFptr->tid == TF->tid && TFptr != TF ) { TFptr->delta.tv_sec = TF->delta.tv_sec; TFptr->delta.tv_usec = TF->delta.tv_usec; } TFptr = TFptr->next; } } /* Check for Descriptor Dump */ if ( TD->dump ) trc_dump_tevdesc( ID, TD, -1 ); /* Write Event to Temp File */ if ( !verify_fp( TF, "a" ) ) bail(); fpsave = ID->trace_out; ID->trace_out = TF->fpbuf->fp; trc_store_tevrec( ID, TD, TR, tid ); ID->trace_out = fpsave; /* Save Last Temp File Ptr for Pass Thru */ LASTTF = TF; } void handle_event_join( trcid, TD, TR ) TRC_ID trcid; TRC_TEVDESC TD; TRC_TEVREC TR; { if ( trcid != ID ) { printf( "Error: Unknown Trace ID\n" ); return; } if ( CURRENTTF == NULL ) { printf( "Warning: Current Temp File Not Set...\n" ); return; } CURRENTTF->nexttime.tv_sec = TRC_GET_TEVREC_VALUE( TR, "TS", int ); CURRENTTF->nexttime.tv_usec = TRC_GET_TEVREC_VALUE( TR, "TU", int ); sync_time( CURRENTTF ); CURRENTTF->savetd = TD; CURRENTTF->savetr = save_tevrec( TR ); CURRENTTF->valid = TRC_TRUE; } void handle_passthru( trcid, str ) TRC_ID trcid; char *str; { if ( trcid != ID ) { printf( "Error: Unknown Trace ID\n" ); return; } if ( LASTTF != NULL ) { if ( !verify_fp( LASTTF, "a" ) ) bail(); fprintf( LASTTF->fpbuf->fp, "%s\n", str ); } else fprintf( ID->trace_out, "%s\n", str ); } void read_args( argc, argv ) int argc; char **argv; { char tmp[1024]; int i, j, k; int do_usage; int len; TRACE_OUTFILE = (char *) NULL; TRACE_INFILE = (char *) NULL; OUTPUT_FILE = (char *) NULL; vflag = 0; do_usage = 0; for ( i=1 ; i < argc ; i++ ) { if ( argv[i][0] == '-' ) { k = i + 1; len = strlen( argv[i] ); for ( j=0 ; j < len ; j++ ) { switch ( argv[i][j] ) { case 'o': { if ( TRACE_OUTFILE != NULL ) free( TRACE_OUTFILE ); TRACE_OUTFILE = trc_copy_str( argv[ k++ ] ); break; } case 'O': { if ( OUTPUT_FILE != NULL ) free( OUTPUT_FILE ); OUTPUT_FILE = trc_copy_str( argv[ k++ ] ); break; } case 'H': case 'h': usage(); break; case 'v': vflag++; break; case '-': break; default: { printf( "Unknown Option -%c\n", argv[i][j] ); do_usage++; break; } } } i = k - 1; } else { if ( TRACE_INFILE != NULL ) free( TRACE_INFILE ); TRACE_INFILE = trc_copy_str( argv[i] ); } } if ( do_usage ) usage(); } void usage() { printf( "\nusage: trcsort [ ] " ); printf( "[ -o ] " ); printf( "[ -O ] " ); printf( "[ -v ] " ); printf( "\n\n" ); printf( "where:\n" ); printf( "------\n" ); printf( " = " ); printf( "trace file to be sorted (default is stdin)\n" ); printf( " = " ); printf( "file to store sorted trace (default is stdout)\n" ); printf( " = " ); printf( "file to store separate copy of any task output\n" ); printf( "-v = " ); printf( "display dynamic open file usage\n" ); printf( "\n" ); exit( 0 ); } void program_init() { /* Create Temp Directory for Subfiles */ sprintf( DIRNAME, "tmpsort.%d", (int) getpid() ); if ( mkdir( DIRNAME, S_IRWXU | S_IRWXG | S_IRWXO ) ) { printf( "\nError Creating Temporary Directory \"%s\".\n\n", DIRNAME ); exit( -1 ); } /* Initialize Temporary File Ptrs */ LASTTF = (TMPFILE) NULL; TMPF = (TMPFILE) NULL; FPS = (FPBUF) NULL; NFPS = 0; } void trc_init() { /* Initialize Tracer */ trc_tracer_init(); /* Get Tracer ID */ ID = trc_get_tracer_id(); /* Set Local Handler Routines */ ID->handle_command = handle_passthru; ID->handle_comment = handle_passthru; ID->handle_event = handle_event_split; ID->status_msg = my_status_msg; /* Set Up Handle ID for Host Sync Events */ trc_add_to_trie( TRC_HANDLE_TRIE, "host_sync", (void *) HANDLE_HOST_SYNC ); /* Create In & Out Trace File Ptrs */ if ( TRACE_INFILE != NULL ) { ID->trace_in = fopen( TRACE_INFILE, "r" ); if ( !trc_filecheck( ID->trace_in, TRACE_INFILE ) ) bail(); } else ID->trace_in = stdin; if ( TRACE_OUTFILE != NULL ) { ID->trace_out = fopen( TRACE_OUTFILE, "w" ); if ( !trc_filecheck( ID->trace_out, TRACE_OUTFILE ) ) bail(); } else ID->trace_out = stdout; /* Open Additional Output File */ if ( OUTPUT_FILE != NULL ) { trc_set_output_file( ID, OUTPUT_FILE ); trc_open_output_file( ID ); } } /* Status Message Handler */ void my_status_msg( ID, msg ) TRC_ID ID; char *msg; { printf( "%s\n", msg ); } /* TRC_TEVREC Routines */ TRC_TEVREC save_tevrec( TR ) /* actually, more like "steal_tevrec" :-) */ TRC_TEVREC TR; { TRC_TEVREC tmp; tmp = trc_create_tevrec(); tmp->ddesc = TR->ddesc; TR->ddesc = (TRC_DATADESC) NULL; tmp->value = TR->value; TR->value = (TRC_VALUE) NULL; tmp->num = TR->num; TR->num = -1; tmp->next = TR->next; TR->next = (TRC_TEVREC) NULL; return( tmp ); } /* TMPFILE Routines */ TMPFILE create_tmpfile() { TMPFILE tmp; tmp = (TMPFILE) malloc( sizeof( struct tmpfile_struct ) ); trc_memcheck( tmp, "Temporary File Structure" ); tmp->fpbuf = (FPBUF) NULL; tmp->fname = (char *) NULL; tmp->lastseek = (long) 0; tmp->savetr = (TRC_TEVREC) NULL; tmp->tid = -1; tmp->nexttime.tv_sec = -1; tmp->nexttime.tv_usec = -1; tmp->lasttime.tv_sec = -1; tmp->lasttime.tv_usec = -1; tmp->delta.tv_sec = 0; tmp->delta.tv_usec = 0; tmp->valid = -1; tmp->eof = -1; tmp->next = (TMPFILE) NULL; return( tmp ); } TMPFILE get_tmpfile( tid, tmptp, createflag ) int tid; struct timeval *tmptp; int createflag; { TMPFILE TF; static struct timeval delta = { 0, 0 }; char fname[255]; int index; TF = TMPF; index = 1; while ( TF != NULL ) { if ( TF->tid == tid ) { if ( ( tmptp->tv_sec == -1 && tmptp->tv_usec == -1 ) || TIME_COMPARE( *tmptp, TF->lasttime ) >= 0 ) { return( TF ); } delta.tv_sec = TF->delta.tv_sec; delta.tv_usec = TF->delta.tv_usec; index++; } TF = TF->next; } if ( !createflag ) return( (TMPFILE) NULL ); TF = create_tmpfile(); TF->tid = tid; if ( index > 1 ) sprintf( fname, "%s/tmp.%x.%d", DIRNAME, tid, index ); else sprintf( fname, "%s/tmp.%x", DIRNAME, tid ); TF->fname = trc_copy_str( fname ); if ( !verify_fp( TF, "w" ) ) { free( TF ); return( (TMPFILE) NULL ); } if ( index > 1 ) { TF->delta.tv_sec = delta.tv_sec; TF->delta.tv_usec = delta.tv_usec; } TF->next = TMPF; TMPF = TF; return( TF ); } void get_tevrec_tmpfile( TF ) TMPFILE TF; { FILE *savefp; if ( TF->eof ) return; CURRENTTF = TF; if ( !verify_fp( TF, "r" ) ) bail(); savefp = ID->trace_in; ID->trace_in = TF->fpbuf->fp; trc_read_trace_event( ID, &(TF->eof) ); ID->trace_in = savefp; } void sync_time( TF ) TMPFILE TF; { TF->nexttime.tv_sec += TF->delta.tv_sec; TF->nexttime.tv_usec += TF->delta.tv_usec; if ( TF->nexttime.tv_usec > 1000000 ) { TF->nexttime.tv_usec -= 1000000; (TF->nexttime.tv_sec)++; } else if ( TF->nexttime.tv_usec < 0 ) { TF->nexttime.tv_usec += 1000000; (TF->nexttime.tv_sec)--; } } /* FPBUF Routines */ FPBUF create_fpbuf() { FPBUF tmp; tmp = (FPBUF) malloc( sizeof( struct fp_buffer_struct ) ); trc_memcheck( tmp, "File Buffer Structure" ); tmp->fp = (FILE *) NULL; tmp->rwstr = (char *) NULL; tmp->tmpfile = (TMPFILE) NULL; tmp->next = (FPBUF) NULL; if ( vflag ) { printf( "+" ); fflush( stdout ); } return( tmp ); } void free_fpbuf( ptr ) FPBUF *ptr; { FPBUF FPB; if ( ptr == NULL || *ptr == NULL ) return; FPB = *ptr; /* Close Any Open File Ptr */ if ( FPB->fp != NULL ) { if ( FPB->tmpfile != NULL ) FPB->tmpfile->lastseek = ftell( FPB->fp ); fclose( FPB->fp ); FPB->fp = (FILE *) NULL; } FPB->rwstr = (char *) NULL; if ( FPB->tmpfile != NULL ) { FPB->tmpfile->fpbuf = (FPBUF) NULL; FPB->tmpfile = (TMPFILE) NULL; } FPB->next = (FPBUF) NULL; free( FPB ); *ptr = (FPBUF) NULL; if ( vflag ) { printf( "\b \b" ); fflush( stdout ); } } int verify_fp( TF, rwstr ) TMPFILE TF; char *rwstr; { FPBUF FPBlast; FPBUF FPBptr; FPBUF FPB; /* File Ptr Buffer Already There */ if ( TF->fpbuf ) { /* Verify Same Mode */ if ( !strcmp( TF->fpbuf->rwstr, rwstr ) ) { /* Move to Top of List */ if ( FPS != TF->fpbuf ) { if ( FPS == NULL ) { printf( "Warning: Empty File Ptr Buffer List\n" ); return( TRC_TRUE ); } FPB = FPS; while ( FPB->next != NULL ) { if ( FPB->next == TF->fpbuf ) { FPB->next = TF->fpbuf->next; TF->fpbuf->next = FPS; FPS = TF->fpbuf; return( TRC_TRUE ); } FPB = FPB->next; } printf( "Warning: Verify File Ptr Buffer Not Found\n" ); } return( TRC_TRUE ); } /* Switching File Modes, Close File Ptr */ else close_fp( TF ); } /* Check for Flush */ if ( NFPS >= MAX_OPEN_FP ) { FPBptr = FPS; FPBlast = (FPBUF) NULL; while ( FPBptr->next != NULL ) { FPBlast = FPBptr; FPBptr = FPBptr->next; } if ( FPBlast != NULL ) free_fpbuf( &(FPBlast->next) ); else free_fpbuf( &(FPS) ); NFPS--; } /* Create New File Ptr Buffer */ FPB = create_fpbuf(); FPB->fp = fopen( TF->fname, rwstr ); if ( !trc_filecheck( FPB->fp, TF->fname ) ) { free_fpbuf( &FPB ); return( TRC_FALSE ); } else { /* Add File Ptr Buffer to List */ FPB->rwstr = rwstr; FPB->tmpfile = TF; TF->fpbuf = FPB; FPB->next = FPS; FPS = FPB; NFPS++; /* Check for File Seek */ if ( TF->lastseek != 0 ) { if ( fseek( FPB->fp, TF->lastseek, 0 ) ) { printf( "\nError in fseek() of Temp File\n\n" ); bail(); } } /* Success */ return( TRC_TRUE ); } } void close_fp( TF ) TMPFILE TF; { FPBUF FPBlast; FPBUF FPB; int flag; /* Check for Null File Ptr Buffer */ if ( TF->fpbuf == NULL ) { TF->lastseek = (long) 0; return; } /* Remove Buffer From List */ if ( FPS != NULL ) { if ( FPS == TF->fpbuf ) { FPS = TF->fpbuf->next; NFPS--; } else { FPB = FPS; flag = 0; while ( FPB->next != NULL && !flag ) { if ( FPB->next == TF->fpbuf ) { FPB->next = TF->fpbuf->next; NFPS--; flag++; } else FPB = FPB->next; } if ( !flag ) { printf( "Warning: Close File Ptr Buffer Not Found.\n" ); } } } free_fpbuf( &(TF->fpbuf) ); TF->lastseek = (long) 0; } /* Clean Up Temp Directory */ void cleanup() { TMPFILE TF; TF = TMPF; while ( TF != NULL ) { if ( TF->fname != NULL ) unlink( TF->fname ); TF = TF->next; } unlink( DIRNAME ); } void bail() { cleanup(); exit( -1 ); } ./pvm3/tracer/trcutil.c0100644007401100000360000013147406675460406014241 0ustar kohlgopher static char rcsid[] = "$Id: trcutil.c,v 4.15 1999/03/22 15:25:58 pvmsrc Exp $"; /* * Tracer version 1.0: A Trace File Generator for PVM * Oak Ridge National Laboratory, Oak Ridge TN. * Authors: James Arthur Kohl and G. A. Geist * (C) 1994 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear * in supporting documentation. * * Neither the Institution, Oak Ridge National Laboratory, nor the * Authors make any representations about the suitability of this * software for any purpose. This software is provided ``as is'' * without express or implied warranty. * * Tracer was funded by the U.S. Department of Energy. */ #include "trclib.h" #ifdef WIN32 #include #endif #ifdef SYSVSTR #include #else #include #endif #ifdef CTIMEISTIMET #define PVM_TIMET time_t #else #define PVM_TIMET long #endif extern struct Pvmtevinfo pvmtevinfo[]; void trc_tracer_init() { char hname[1024]; /* Host Name */ TRC_HOST_ALIAS = (char *) NULL; TRC_HOST_NAME = (char *) NULL; if ( gethostname( hname, 1023 ) == -1 ) perror( "Getting Hostname" ); else { TRC_HOST_NAME = trc_copy_str( hname ); TRC_HOST_ALIAS = trc_host_alias_str( TRC_HOST_NAME ); } /* TRC_DID Semantic Identifier List */ TRC_DID_LIST = (TRC_DID) NULL; /* Tracer ID List */ TRC_DEAD_ID_LIST = (TRC_ID) NULL; TRC_ID_LIST = (TRC_ID) NULL; /* TEV Descriptor List */ TRC_TEVDESC_LIST = (TRC_TEVDESC *) NULL; TRC_TEVDESC_SIZE = -1; /* Set Up Semantic Identifier Lookup Trie */ trc_init_did_trie(); /* Initialize Event Processing Tries */ TRC_HANDLE_TRIE = trc_create_triestack(); TRC_EVENT_TRIE = trc_create_triestack(); /* Define Special Event Descriptors */ trc_define_special_descriptors(); /* Initialize Time Vars */ gettimeofday( &TRC_TRACE_TIME, (struct timezone *) NULL ); /* Initialize Other Trace Globals */ TRC_VERSION = (char *) NULL; TRC_NAME = (char *) NULL; TRC_HOST_ADD_NOTIFY_CODE = -1; TRC_HOST_DEL_NOTIFY_CODE = -1; TRC_TID = -1; /* Initialize Old PVM 3.3 Trace Event Handling Stuff */ trc_init_old_events(); } TRC_ID trc_get_tracer_id() { TRC_ID ID; ID = trc_create_tracer_id(); /* Initialize Flags */ ID->group_tasks = TRC_FALSE; /* Add to List */ ID->next = TRC_ID_LIST; TRC_ID_LIST = ID; return( ID ); } void trc_set_tracing_codes( ID ) TRC_ID ID; { #ifndef USE_PVM_33 pvm_setopt( PvmTraceContext, ID->event_ctx ); #endif pvm_setopt( PvmTraceCode, ID->event_tag ); pvm_setopt( PvmTraceTid, TRC_TID ); #ifndef USE_PVM_33 pvm_setopt( PvmOutputContext, ID->output_ctx ); #endif pvm_setopt( PvmOutputCode, ID->output_tag ); pvm_setopt( PvmOutputTid, TRC_TID ); } int trc_set_trace_file( ID, trace_file ) TRC_ID ID; char *trace_file; { if ( trace_file != NULL ) { if ( ID->trace_file != NULL ) free( ID->trace_file ); ID->trace_file = trc_copy_str( trace_file ); return( TRC_TRUE ); } else { trc_status_msg( ID, "Error: Null Trace File Name" ); return( TRC_FALSE ); } } int trc_reset_trace_file( ID ) TRC_ID ID; { TRC_TEVDESC TD; int i; /* Close Any Existing Trace File */ if ( ID->trace_out != NULL && ID->trace_out != stdout ) fclose( ID->trace_out ); /* Clean Up Any Leftover Tasks */ trc_free_tevtask_list( &(ID->tevtask_list) ); /* Clean Up Any Dead Hosts */ trc_cleanup_dead_hosts(); /* Verify Trace File Set */ if ( ID->trace_file == NULL ) { trc_status_msg( ID, "Trace File Has Not Been Set." ); return( TRC_FALSE ); } /* Open Trace File */ if ( strcmp( ID->trace_file, "" ) ) { ID->trace_out = fopen( ID->trace_file, "w" ); if ( !trc_filecheck( ID->trace_out, ID->trace_file ) ) return( TRC_FALSE ); } else ID->trace_out = stdout; /* Dump Initial Trace File Header */ trc_dump_trace_header( ID ); /* Reset Event Name Lookup Trie */ trc_free_event_descriptors( TRC_EVENT_TRIE ); trc_free_triestack( &TRC_EVENT_TRIE ); TRC_EVENT_TRIE = trc_create_triestack(); /* Reset System Trace Descriptors */ for ( i=0 ; i < TRC_TEVDESC_SIZE ; i++ ) { TD = TRC_TEVDESC_LIST[i]; while ( TD != NULL ) { TD->dump = TRC_TRUE; TD = TD->next; } } /* Reset Time Vars */ gettimeofday( &TRC_TRACE_TIME, (struct timezone *) NULL ); /* Reset Old PVM 3.3 Trace Descriptor Flags */ trc_reset_old_descriptors(); /* Set Trace File Complete Flag */ ID->complete = TRC_FALSE; /* Successful Reset */ return( TRC_TRUE ); } int trc_set_output_file( ID, output_file ) TRC_ID ID; char *output_file; { if ( output_file != NULL ) { if ( ID->output_file != NULL ) free( ID->output_file ); ID->output_file = trc_copy_str( output_file ); return( TRC_TRUE ); } else { trc_status_msg( ID, "Error: Null Output File Name" ); return( TRC_FALSE ); } } int trc_open_output_file( ID ) TRC_ID ID; { /* Close Any Existing Output File */ if ( ID->output_fp != NULL && ID->output_fp != stdout ) fclose( ID->output_fp ); /* Verify Output File Set */ if ( ID->output_file == NULL ) { trc_status_msg( ID, "Output File Has Not Been Set." ); return( TRC_FALSE ); } /* Open Output File */ if ( strcmp( ID->output_file, "" ) ) { ID->output_fp = fopen( ID->output_file, "w" ); if ( !trc_filecheck( ID->output_fp, ID->output_file ) ) return( TRC_FALSE ); } else ID->output_fp = stdout; /* Successful Opening */ return( TRC_TRUE ); } void trc_print_tmask( tmask ) Pvmtmask tmask; { static int indices[ TEV_MAX + 1 ]; static int ncols = -1; static int nrows = -1; static int ntev = -1; static char fmt[64]; int i, j, k; int maxlen; int width; int index; int flag; int len; int b; int c; int x; if ( ntev == -1 ) { maxlen = -1; x = 0; for ( i=TEV_FIRST ; i <= TEV_MAX ; i++ ) { /* Skip Internal Events */ if ( strcmp( pvmtevinfo[i].name, "newtask" ) && strcmp( pvmtevinfo[i].name, "spntask" ) && strcmp( pvmtevinfo[i].name, "endtask" ) && strcmp( pvmtevinfo[i].name, "timing" ) && strcmp( pvmtevinfo[i].name, "profiling" ) ) { /* Determine Max Name Length */ len = strlen( pvmtevinfo[i].name ); if ( len > maxlen || maxlen == -1 ) maxlen = len; /* Sort 'Em Ugly Like */ flag = 0; for ( j=0 ; j < x && !flag ; j++ ) { if ( strcmp( pvmtevinfo[i].name, pvmtevinfo[ indices[j] ].name ) < 0 ) { for ( k=x+1 ; k > j ; k-- ) indices[k] = indices[k - 1]; indices[j] = i; x++; flag++; } } if ( !flag ) indices[x++] = i; } } ntev = x; maxlen += 4; ncols = 79 / maxlen; width = (79 / ncols) - 4; sprintf( fmt, " %%c %%-%ds%%c", width ); nrows = ( ntev + ncols - 1 ) / ncols; } for ( i=0 ; i < nrows ; i++ ) { for ( c=0 ; c < ncols ; c++ ) { index = i + (c * nrows); if ( index < ntev ) { x = indices[ index ]; b = TEV_MASK_CHECK( tmask, x ); printf( fmt, (b ? '*' : ' '), pvmtevinfo[x].name, (c == ncols - 1 ? '\n' : ' ') ); } else printf( "\n" ); } } } TRC_TRIE trc_create_triestack() { TRC_TRIE tptr; TRC_TRIE tmp; int i; tmp = (TRC_TRIE) malloc( (unsigned) TRC_TRIE_SIZE * sizeof( struct trc_trie_struct ) ); trc_memcheck( tmp, "Trie Structure" ); for ( i=0 ; i < TRC_TRIE_SIZE ; i++ ) { tptr = &(tmp[i]); tptr->valid = TRC_FALSE; tptr->str = (char *) NULL; tptr->value = (void *) NULL; tptr->next = (TRC_TRIE) NULL; } return( tmp ); } void trc_free_triestack( ptr ) TRC_TRIE *ptr; { TRC_TRIE T; TRC_TRIE tptr; int i; if ( ptr == NULL || *ptr == NULL ) return; T = *ptr; for ( i=0 ; i < TRC_TRIE_SIZE ; i++ ) { tptr = &(T[i]); tptr->valid = TRC_FALSE; if ( tptr->str != NULL ) free( tptr->str ); tptr->str = (char *) NULL; tptr->value = (void *) NULL; if ( tptr->next != NULL ) trc_free_triestack( &(tptr->next) ); } free( T ); *ptr = (TRC_TRIE) NULL; } int trc_add_to_trie( T, str, value ) TRC_TRIE T; char *str; void *value; { TRC_TRIE tptr; char *bump; int bumpindex; int marked; int index; int len; int i; if ( T == NULL ) { printf( "\nError in trc_add_to_trie(): Null Trie\n\n" ); return( TRC_FALSE ); } if ( str == NULL || !strcmp( str, "" ) ) { printf( "\nError in trc_add_to_trie(): Empty String\n\n" ); return( TRC_FALSE ); } len = strlen( str ) - 1; marked = 0; for ( i=0 ; i < len && !marked ; i++ ) { index = trc_trie_index( str[i] ); tptr = &(T[index]); if ( tptr->next != NULL ) T = tptr->next; else { if ( !tptr->valid ) { tptr->valid = TRC_TRUE; tptr->str = trc_copy_str( str ); tptr->value = value; marked++; } else { tptr->next = trc_create_triestack(); T = tptr->next; bump = tptr->str; if ( strlen( bump ) > i + 1 ) { bumpindex = trc_trie_index( bump[ i + 1 ] ); T[bumpindex].valid = TRC_TRUE; T[bumpindex].str = bump; T[bumpindex].value = tptr->value; tptr->valid = TRC_FALSE; tptr->str = (char *) NULL; tptr->value = (void *) NULL; } } } } if ( !marked ) { index = trc_trie_index( str[len] ); tptr = &(T[index]); if ( tptr->valid ) { bump = tptr->str; if ( strlen( bump ) > len + 1 ) { if ( tptr->next == NULL ) tptr->next = trc_create_triestack(); T = tptr->next; bumpindex = trc_trie_index( bump[ len + 1 ] ); T[bumpindex].valid = TRC_TRUE; T[bumpindex].str = bump; T[bumpindex].value = tptr->value; } else { printf( "\nError: Duplicate %s (%lx)\n\n", bump, (long) tptr->value ); return( TRC_FALSE ); } } tptr->valid = TRC_TRUE; tptr->str = trc_copy_str( str ); tptr->value = value; } return( TRC_TRUE ); } void * trc_lookup_trie( T, str ) TRC_TRIE T; char *str; { TRC_TRIE tptr; char *ptr; int len; int i; len = strlen( str ) - 1; ptr = str; for ( i=0 ; i < len ; i++ ) { tptr = &(T[ trc_trie_index( *ptr++ ) ]); if ( tptr->next != NULL ) T = tptr->next; else { if ( tptr->valid && !strcmp( tptr->str, str ) ) return( tptr->value ); else return( (void *) NULL ); } } tptr = &(T[ trc_trie_index( *ptr ) ]); if ( tptr->valid && !strcmp( tptr->str, str ) ) return( tptr->value ); else return( (void *) NULL ); } int trc_trie_index( c ) char c; { int index; if ( c >= 'a' && c <= 'z' ) index = (int) ( c - 'a' ); else if ( c >= 'A' && c <= 'Z' ) index = (int) ( c - 'A' ); else if ( c >= '0' && c <= '9' ) index = 26 + (int) ( c - '0' ); else index = TRC_TRIE_SIZE - 1; return( index ); } TRC_DID trc_create_did() { TRC_DID tmp; tmp = (TRC_DID) malloc( sizeof( struct trc_did_struct ) ); trc_memcheck( tmp, "Semantic Data ID Structure" ); tmp->id = -1; tmp->name = (char *) NULL; tmp->desc = (char *) NULL; tmp->next = (TRC_DID) NULL; return( tmp ); } void trc_free_did( ptr ) TRC_DID *ptr; { TRC_DID D; if ( ptr == NULL || *ptr == NULL ) return; D = *ptr; D->id = -1; if ( D->name != NULL ) { free( D->name ); D->name = (char *) NULL; } if ( D->desc != NULL ) { free( D->desc ); D->desc = (char *) NULL; } D->next = (TRC_DID) NULL; free( D ); *ptr = (TRC_DID) NULL; } int trc_cmp_did( did1, did2 ) TRC_DID did1; TRC_DID did2; { if ( did1->id != did2->id ) return( TRC_FALSE ); if ( strcmp( did1->name, did2->name ) ) return( TRC_FALSE ); if ( strcmp( did1->desc, did2->desc ) ) return( TRC_FALSE ); return( TRC_TRUE ); } TRC_DATADESC trc_create_datadesc() { TRC_DATADESC tmp; tmp = (TRC_DATADESC) malloc( sizeof( struct trc_datadesc_struct ) ); trc_memcheck( tmp, "Data Description Structure" ); tmp->did = (TRC_DID) NULL; tmp->dt = -1; tmp->array = -1; tmp->data = (TRC_VALUE) NULL; tmp->num = -1; tmp->next = (TRC_DATADESC) NULL; return( tmp ); } void trc_free_datadesc( ptr ) TRC_DATADESC *ptr; { TRC_DATADESC DD; if ( ptr == NULL || *ptr == NULL ) return; DD = *ptr; DD->did = (TRC_DID) NULL; DD->dt = -1; DD->array = -1; if ( DD->data != NULL ) { free( DD->data ); DD->data = (TRC_VALUE) NULL; } DD->num = -1; DD->next = (TRC_DATADESC) NULL; free( DD ); *ptr = (TRC_DATADESC) NULL; } int trc_cmp_datadesc( DD1, DD2 ) TRC_DATADESC DD1; TRC_DATADESC DD2; { TRC_DID D1, D2; D1 = DD1->did; D2 = DD2->did; if ( D1 != NULL && D2 != NULL ) { if ( !trc_cmp_did( DD1->did, DD2->did ) ) return( TRC_FALSE ); } else { if ( D1 != NULL || D2 != NULL ) return( TRC_FALSE ); } if ( DD1->dt != DD2->dt || DD1->array != DD2->array ) return( TRC_FALSE ); return( TRC_TRUE ); } int trc_get_dt_str( dtstr ) char *dtstr; { int i; for ( i=0 ; i < 16 ; i++ ) { if ( !strcmp( TRC_TYPE_STRS[i], dtstr ) ) return( i ); } return( -1 ); } TRC_TEVDESC trc_create_tevdesc() { TRC_TEVDESC tmp; tmp = (TRC_TEVDESC) malloc( sizeof( struct trc_tevdesc_struct ) ); trc_memcheck( tmp, "Trace Event Descriptor Structure" ); tmp->name = (char *) NULL; tmp->eid = -1; tmp->entry_exit = -1; tmp->index = -1; tmp->hid = -1; tmp->dump = -1; tmp->ddesc = (TRC_DATADESC) NULL; tmp->refcount = -1; tmp->next = (TRC_TEVDESC) NULL; return( tmp ); } int trc_free_tevdesc( ptr ) TRC_TEVDESC *ptr; { TRC_TEVDESC TD; TRC_DATADESC DD; TRC_DATADESC DDnext; if ( ptr == NULL || *ptr == NULL ) return( TRC_FALSE ); TD = *ptr; (TD->refcount)--; if ( TD->refcount > 0 ) return( TRC_FALSE ); if ( TD->name != NULL ) free( TD->name ); TD->name = (char *) NULL; TD->eid = -1; TD->entry_exit = -1; TD->index = -1; TD->hid = -1; TD->dump = -1; DD = TD->ddesc; while ( DD != NULL ) { DDnext = DD->next; trc_free_datadesc( &DD ); DD = DDnext; } TD->ddesc = (TRC_DATADESC) NULL; TD->refcount = -1; TD->next = (TRC_TEVDESC) NULL; free( TD ); *ptr = (TRC_TEVDESC) NULL; return( TRC_TRUE ); } int trc_cmp_tevdesc( TD1, TD2 ) TRC_TEVDESC TD1; TRC_TEVDESC TD2; { TRC_DATADESC DD1, DD2; if ( strcmp( TD1->name, TD2->name ) ) return( TRC_FALSE ); if ( TD1->eid != TD2->eid || TD1->entry_exit != TD2->entry_exit ) return( TRC_FALSE ); /* Ignore index & hid & dump */ DD1 = TD1->ddesc; DD2 = TD2->ddesc; while ( DD1 != NULL && DD2 != NULL ) { if ( !trc_cmp_datadesc( DD1, DD2 ) ) return( TRC_FALSE ); DD1 = DD1->next; DD2 = DD2->next; } if ( DD1 != NULL || DD2 != NULL ) return( TRC_FALSE ); return( TRC_TRUE ); } void trc_remove_tevdesc( ptr, index ) TRC_TEVDESC *ptr; int index; { TRC_TEVDESC TDnext; TRC_TEVDESC TDlast; TRC_TEVDESC TDptr; TRC_TEVDESC TD; int eid; if ( ptr == NULL || *ptr == NULL ) return; /* Save Its Location */ TD = *ptr; TDnext = TD->next; /* Try To Free It */ if ( trc_free_tevdesc( ptr ) ) { /* Fix Up Descriptor List */ eid = TRC_TEVEID_OF( index ); TDptr = TRC_TEVDESC_LIST[ eid ]; TDlast = (TRC_TEVDESC) NULL; while ( TDptr != NULL ) { if ( TDptr == TD ) { if ( TDlast != NULL ) TDlast->next = TDnext; else TRC_TEVDESC_LIST[ eid ] = TDnext; return; } else { TDlast = TDptr; TDptr = TDptr->next; } } } } void trc_free_event_descriptors( T ) TRC_TRIE T; { TRC_TRIE tptr; int i; if ( T == NULL ) return; for ( i=0 ; i < TRC_TRIE_SIZE ; i++ ) { tptr = &(T[i]); if ( tptr->value != NULL ) trc_free_tevdesc( (TRC_TEVDESC *) &(tptr->value) ); if ( tptr->next != NULL ) trc_free_event_descriptors( tptr->next ); } } TRC_TEVDESC_INFO trc_create_tevdesc_info() { TRC_TEVDESC_INFO tmp; tmp = (TRC_TEVDESC_INFO) malloc( sizeof( struct trc_tevdesc_info_struct ) ); trc_memcheck( tmp, "Trace Event Descriptor Info Structure" ); tmp->id = -1; tmp->dt = -1; tmp->array = -1; return( tmp ); } void trc_free_tevdesc_info( ptr ) TRC_TEVDESC_INFO *ptr; { TRC_TEVDESC_INFO TI; if ( ptr == NULL || *ptr == NULL ) return; TI = *ptr; TI->id = -1; TI->dt = -1; TI->array = -1; free( TI ); *ptr = (TRC_TEVDESC_INFO) NULL; } TRC_TEVREC trc_create_tevrec() { TRC_TEVREC tmp; tmp = (TRC_TEVREC) malloc( sizeof( struct trc_tevrec_struct ) ); trc_memcheck( tmp, "Trace Event Record Structure" ); tmp->ddesc = (TRC_DATADESC) NULL; tmp->value = (TRC_VALUE) NULL; tmp->num = -1; tmp->next = (TRC_TEVREC) NULL; return( tmp ); } void trc_free_tevrec( ptr ) TRC_TEVREC *ptr; { TRC_TEVREC TR; if ( ptr == NULL || *ptr == NULL ) return; TR = *ptr; TR->ddesc = (TRC_DATADESC) NULL; if ( TR->value != NULL ) free( TR->value ); TR->value = (TRC_VALUE) NULL; TR->num = -1; if ( TR->next != NULL ) trc_free_tevrec( &(TR->next) ); free( *ptr ); *ptr = (TRC_TEVREC) NULL; } TRC_TEVREC trc_get_tevrec( TR, did ) TRC_TEVREC TR; char *did; { TRC_TEVREC trptr; trptr = TR; while ( trptr != NULL ) { if ( !strcmp( did, trptr->ddesc->did->name ) ) return( trptr ); trptr = trptr->next; } return( trptr ); } char * trc_tevrec_string( TD, TR, tid, tsec, tusec ) TRC_TEVDESC TD; TRC_TEVREC TR; int tid; int tsec; int tusec; { TRC_DATADESC DD; TRC_TEVREC trptr; char event_str[2048]; char tmp[2048]; char *tusec_pad; char *ptr; int first; int i; /* Dump Header Text */ tusec_pad = trc_pad_num( tusec, 6 ); if ( TD->entry_exit != TRC_IGNORE_TEV ) { sprintf( event_str, "%s(%d.%d) @ %d.%s", TD->name, TD->entry_exit, TD->index, tsec, tusec_pad ); } else { sprintf( event_str, "%s(%d) @ %d.%s", TD->name, TD->index, tsec, tusec_pad ); } free( tusec_pad ); /* Dump Event Data */ first = TRC_TRUE; trptr = TR; while ( trptr != NULL ) { DD = trptr->ddesc; /* Skip Over TS, TU, and TID */ if ( strcmp( DD->did->name, "TS" ) && strcmp( DD->did->name, "TU" ) && strcmp( DD->did->name, "TID" ) ) { /* Check for first data item -> put out : */ if ( first ) { trc_append_str( event_str, ": ", 2048 ); first = TRC_FALSE; } /* Get Data Name */ ptr = DD->did->name; i = 0; while ( *ptr != '\0' ) tmp[i++] = *ptr++; tmp[i++] = '='; tmp[i++] = '\0'; trc_append_str( event_str, tmp, 2048 ); /* Get Data Itself */ switch( DD->dt ) { case TEV_DATA_NULL: break; case TEV_DATA_BYTE: { sprintf( tmp, "{%s}", (char *) trptr->value ); trc_append_str( event_str, tmp, 2048 ); break; } case TEV_DATA_CPLX: case TEV_DATA_FLOAT: { if ( trptr->num > 1 ) { trc_append_str( event_str, "{ ", 2048 ); } for ( i=0 ; i < trptr->num ; i++ ) { if ( i < trptr->num - 1 ) { sprintf( tmp, "%f, ", TRC_ARR_VALUE_OF( trptr->value, float, i ) ); } else { sprintf( tmp, "%f", TRC_ARR_VALUE_OF( trptr->value, float, i ) ); } trc_append_str( event_str, tmp, 2048 ); } if ( trptr->num > 1 ) trc_append_str( event_str, " }", 2048 ); break; } case TEV_DATA_DCPLX: case TEV_DATA_DOUBLE: { if ( trptr->num > 1 ) trc_append_str( event_str, "{ ", 2048 ); for ( i=0 ; i < trptr->num ; i++ ) { if ( i < trptr->num - 1 ) { sprintf( tmp, "%lf, ", TRC_ARR_VALUE_OF( trptr->value, double, i ) ); } else { sprintf( tmp, "%lf", TRC_ARR_VALUE_OF( trptr->value, double, i ) ); } trc_append_str( event_str, tmp, 2048 ); } if ( trptr->num > 1 ) trc_append_str( event_str, " }", 2048 ); break; } case TEV_DATA_INT: { if ( trptr->num > 1 ) trc_append_str( event_str, "{ ", 2048 ); for ( i=0 ; i < trptr->num ; i++ ) { if ( i < trptr->num - 1 ) { sprintf( tmp, "%d, ", TRC_ARR_VALUE_OF( trptr->value, int, i ) ); } else { sprintf( tmp, "%d", TRC_ARR_VALUE_OF( trptr->value, int, i ) ); } trc_append_str( event_str, tmp, 2048 ); } if ( trptr->num > 1 ) trc_append_str( event_str, " }", 2048 ); break; } case TEV_DATA_UINT: { if ( trptr->num > 1 ) trc_append_str( event_str, "{ ", 2048 ); for ( i=0 ; i < trptr->num ; i++ ) { if ( i < trptr->num - 1 ) { sprintf( tmp, "%u, ", TRC_ARR_VALUE_OF( trptr->value, unsigned, i ) ); } else { sprintf( tmp, "%u", TRC_ARR_VALUE_OF( trptr->value, unsigned, i ) ); } trc_append_str( event_str, tmp, 2048 ); } if ( trptr->num > 1 ) trc_append_str( event_str, " }", 2048 ); break; } case TEV_DATA_LONG: case TEV_DATA_ULONG: { if ( trptr->num > 1 ) trc_append_str( event_str, "{ ", 2048 ); for ( i=0 ; i < trptr->num ; i++ ) { if ( i < trptr->num - 1 ) { sprintf( tmp, "%ld, ", TRC_ARR_VALUE_OF( trptr->value, long, i ) ); } else { sprintf( tmp, "%ld", TRC_ARR_VALUE_OF( trptr->value, long, i ) ); } trc_append_str( event_str, tmp, 2048 ); } if ( trptr->num > 1 ) trc_append_str( event_str, " }", 2048 ); break; } case TEV_DATA_SHORT: { if ( trptr->num > 1 ) trc_append_str( event_str, "{ ", 2048 ); for ( i=0 ; i < trptr->num ; i++ ) { if ( i < trptr->num - 1 ) { sprintf( tmp, "%d, ", TRC_ARR_VALUE_OF( trptr->value, short, i ) ); } else { sprintf( tmp, "%d", TRC_ARR_VALUE_OF( trptr->value, short, i ) ); } trc_append_str( event_str, tmp, 2048 ); } if ( trptr->num > 1 ) trc_append_str( event_str, " }", 2048 ); break; } case TEV_DATA_USHORT: { if ( trptr->num > 1 ) trc_append_str( event_str, "{ ", 2048 ); for ( i=0 ; i < trptr->num ; i++ ) { if ( i < trptr->num - 1 ) { sprintf( tmp, "%d, ", TRC_ARR_VALUE_OF( trptr->value, short, i ) ); } else { sprintf( tmp, "%d", TRC_ARR_VALUE_OF( trptr->value, short, i ) ); } trc_append_str( event_str, tmp, 2048 ); } if ( trptr->num > 1 ) trc_append_str( event_str, " }", 2048 ); break; } case TEV_DATA_STRING: { if ( trptr->num > 1 ) trc_append_str( event_str, "{ ", 2048 ); for ( i=0 ; i < trptr->num ; i++ ) { if ( i < trptr->num - 1 ) { sprintf( tmp, "{%s}, ", TRC_ARR_VALUE_OF( trptr->value, char *, i ) ); } else { sprintf( tmp, "{%s}", TRC_ARR_VALUE_OF( trptr->value, char *, i ) ); } trc_append_str( event_str, tmp, 2048 ); } if ( trptr->num > 1 ) trc_append_str( event_str, " }", 2048 ); break; } case TEV_DATA_STRUCT_START: case TEV_DATA_STRUCT_END: case TEV_DATA_DEFERRED: { sprintf( tmp, "
" ); trc_append_str( event_str, tmp, 2048 ); } default: { sprintf( tmp, "
" ); trc_append_str( event_str, tmp, 2048 ); } } if ( trptr->next != NULL ) { sprintf( tmp, ", " ); trc_append_str( event_str, tmp, 2048 ); } } trptr = trptr->next; } trc_append_str( event_str, ".", 2048 ); return( trc_copy_str( event_str ) ); } TRC_VALUE trc_make_value( dt, num ) int dt; int num; { TRC_VALUE tmp; int i; if ( num < 1 ) return( (TRC_VALUE) NULL ); tmp = (TRC_VALUE) NULL; switch ( dt ) { case TEV_DATA_NULL: break; case TEV_DATA_BYTE: { tmp = (TRC_VALUE) malloc( (unsigned) num * sizeof( char ) ); trc_memcheck( tmp, "Character Data Pointer" ); break; } case TEV_DATA_STRING: { tmp = (TRC_VALUE) malloc( (unsigned) num * sizeof( char * ) ); trc_memcheck( tmp, "String Data Pointer" ); break; } case TEV_DATA_DCPLX: case TEV_DATA_DOUBLE: { tmp = (TRC_VALUE) malloc( (unsigned) num * sizeof( double ) ); trc_memcheck( tmp, "Double Data Pointer" ); break; } case TEV_DATA_CPLX: case TEV_DATA_FLOAT: { tmp = (TRC_VALUE) malloc( (unsigned) num * sizeof( float ) ); trc_memcheck( tmp, "Float Data Pointer" ); break; } case TEV_DATA_INT: case TEV_DATA_UINT: { tmp = (TRC_VALUE) malloc( (unsigned) num * sizeof( int ) ); trc_memcheck( tmp, "Integer Data Pointer" ); break; } case TEV_DATA_LONG: case TEV_DATA_ULONG: { tmp = (TRC_VALUE) malloc( (unsigned) num * sizeof( long ) ); trc_memcheck( tmp, "Long Integer Data Pointer" ); break; } case TEV_DATA_SHORT: case TEV_DATA_USHORT: { tmp = (TRC_VALUE) malloc( (unsigned) num * sizeof( short ) ); trc_memcheck( tmp, "Short Integer Data Pointer" ); break; } case TEV_DATA_STRUCT_START: case TEV_DATA_STRUCT_END: case TEV_DATA_DEFERRED: { printf( "Value Data Type %d Not Implemented\n", dt ); break; } default: printf( "Warning: Unknown Value Data Type %d\n", dt ); } return( tmp ); } TRC_VALUE trc_copy_value( V, dt, num ) TRC_VALUE V; int dt; int num; { TRC_VALUE tmp; int i; if ( V == NULL || num < 1 ) return( (TRC_VALUE) NULL ); tmp = (TRC_VALUE) NULL; switch ( dt ) { case TEV_DATA_NULL: break; case TEV_DATA_BYTE: { tmp = (TRC_VALUE) malloc( (unsigned) num * sizeof( char ) ); trc_memcheck( tmp, "Character Data Pointer" ); for ( i=0 ; i < num ; i++ ) { TRC_ARR_VALUE_OF( tmp, char, i ) = TRC_ARR_VALUE_OF( V, char, i ); } break; } case TEV_DATA_STRING: { tmp = (TRC_VALUE) malloc( (unsigned) num * sizeof( char * ) ); trc_memcheck( tmp, "String Data Pointer" ); for ( i=0 ; i < num ; i++ ) { TRC_ARR_VALUE_OF( tmp, char *, i ) = trc_copy_str( TRC_ARR_VALUE_OF( V, char *, i ) ); } break; } case TEV_DATA_DCPLX: case TEV_DATA_DOUBLE: { tmp = (TRC_VALUE) malloc( (unsigned) num * sizeof( double ) ); trc_memcheck( tmp, "Double Data Pointer" ); for ( i=0 ; i < num ; i++ ) { TRC_ARR_VALUE_OF( tmp, double, i ) = TRC_ARR_VALUE_OF( V, double, i ); } break; } case TEV_DATA_CPLX: case TEV_DATA_FLOAT: { tmp = (TRC_VALUE) malloc( (unsigned) num * sizeof( float ) ); trc_memcheck( tmp, "Float Data Pointer" ); for ( i=0 ; i < num ; i++ ) { TRC_ARR_VALUE_OF( tmp, float, i ) = TRC_ARR_VALUE_OF( V, float, i ); } break; } case TEV_DATA_INT: case TEV_DATA_UINT: { tmp = (TRC_VALUE) malloc( (unsigned) num * sizeof( int ) ); trc_memcheck( tmp, "Integer Data Pointer" ); for ( i=0 ; i < num ; i++ ) { TRC_ARR_VALUE_OF( tmp, int, i ) = TRC_ARR_VALUE_OF( V, int, i ); } break; } case TEV_DATA_LONG: case TEV_DATA_ULONG: { tmp = (TRC_VALUE) malloc( (unsigned) num * sizeof( long ) ); trc_memcheck( tmp, "Long Integer Data Pointer" ); for ( i=0 ; i < num ; i++ ) { TRC_ARR_VALUE_OF( tmp, long, i ) = TRC_ARR_VALUE_OF( V, long, i ); } break; } case TEV_DATA_SHORT: case TEV_DATA_USHORT: { tmp = (TRC_VALUE) malloc( (unsigned) num * sizeof( short ) ); trc_memcheck( tmp, "Short Integer Data Pointer" ); for ( i=0 ; i < num ; i++ ) { TRC_ARR_VALUE_OF( tmp, short, i ) = TRC_ARR_VALUE_OF( V, short, i ); } break; } case TEV_DATA_STRUCT_START: case TEV_DATA_STRUCT_END: case TEV_DATA_DEFERRED: { printf( "Value Data Type %d Not Implemented\n", dt ); break; } default: printf( "Warning: Unknown Value Data Type %d\n", dt ); } return( tmp ); } TRC_TEVTASK trc_create_tevtask() { TRC_TEVTASK tmp; tmp = (TRC_TEVTASK) malloc( sizeof( struct trc_tevtask_struct ) ); trc_memcheck( tmp, "TEV Task Structure" ); tmp->tid = -1; tmp->tevstatus = -1; tmp->outstatus = -1; tmp->tevlist = (void **) NULL; tmp->tevsize = -1; tmp->output = (char *) NULL; tmp->next = (TRC_TEVTASK) NULL; return( tmp ); } void trc_check_for_dead_host( ID, TT ) TRC_ID ID; TRC_TEVTASK TT; { TRC_TEVTASK TTptr; TRC_HOST Hlast; TRC_HOST H; int pvmd_tid; int alive; int tmp; /* Get Host Task ID, See if Host is "Dead" */ pvmd_tid = pvm_tidtohost( TT->tid ); H = trc_get_host_tid_last( pvmd_tid, &Hlast ); if ( H->in_pvm != TRC_NOT_IN_PVM ) return; /* Look for any living tasks on that host */ TTptr = ID->tevtask_list; alive = 0; while ( TTptr != NULL && !alive ) { tmp = pvm_tidtohost( TTptr->tid ); if ( tmp == pvmd_tid && ( TTptr->tevstatus == TRC_TASK_ALIVE || TTptr->outstatus == TRC_TASK_OUT ) ) { alive++; } TTptr = TTptr->next; } /* Host can finally rest in peace... */ if ( !alive ) { if ( Hlast != NULL ) Hlast->next = H->next; else TRC_HOST_LIST = H->next; trc_free_host( &H ); } } void trc_free_tevtask( ptr ) TRC_TEVTASK *ptr; { TRC_TEVTASK TT; int i; if ( ptr == NULL || *ptr == NULL ) return; TT = *ptr; TT->tid = -1; TT->tevstatus = -1; TT->outstatus = -1; if ( TT->tevlist != NULL ) { for ( i=0 ; i < TT->tevsize ; i++ ) TT->tevlist[i] = (void *) NULL; free( TT->tevlist ); TT->tevlist = (void **) NULL; } TT->tevsize = -1; if ( TT->output != NULL ) { free( TT->output ); TT->output = (char *) NULL; } TT->next = (TRC_TEVTASK) NULL; free( TT ); *ptr = (TRC_TEVTASK) NULL; } void trc_free_tevtask_list( tevtask_list ) TRC_TEVTASK *tevtask_list; { TRC_TEVTASK TTnext; TRC_TEVTASK TT; int i; TT = *tevtask_list; *tevtask_list = (TRC_TEVTASK) NULL; while ( TT != NULL ) { /* Save Next Ptr */ TTnext = TT->next; /* Wipe Out Traced Tasks */ if ( TT->tevstatus == TRC_TASK_DEAD && TT->outstatus == TRC_TASK_EOF ) { /* Wipe Out Associated Trace Event Descriptors */ for ( i=0 ; i < TT->tevsize ; i++ ) { if ( TT->tevlist[i] != NULL ) { trc_remove_tevdesc( (TRC_TEVDESC *) &(TT->tevlist[i]), i ); } } /* Free Traced Task */ trc_free_tevtask( &TT ); } /* Save Leftover Tasks Still In Progress */ else { /* Set Event and Output Status Flags */ if ( TT->tevstatus != TRC_TASK_DEAD ) TT->tevstatus = TRC_TASK_WAITEND; if ( TT->outstatus != TRC_TASK_EOF ) TT->outstatus = TRC_TASK_WAITEOF; /* Add Back On List */ TT->next = *tevtask_list; *tevtask_list = TT; } /* Next Task */ TT = TTnext; } } TRC_TEVTASK trc_get_tevtask_tid( ID, tid ) TRC_ID ID; int tid; { TRC_TEVTASK TT; TT = ID->tevtask_list; while ( TT != NULL ) { if ( TT->tid == tid ) return( TT ); TT = TT->next; } return( (TRC_TEVTASK) NULL ); } int trc_tevtasks_alive( ID ) TRC_ID ID; { TRC_TEVTASK TT; TT = ID->tevtask_list; while ( TT != NULL ) { if ( TT->tevstatus == TRC_TASK_ALIVE || TT->outstatus == TRC_TASK_OUT ) { return( TRC_TRUE ); } TT = TT->next; } return( TRC_FALSE ); } int trc_tevtasks_dead( ID ) TRC_ID ID; { TRC_TEVTASK TT; TT = ID->tevtask_list; while ( TT != NULL ) { if ( TT->tevstatus != TRC_TASK_DEAD || TT->outstatus != TRC_TASK_EOF ) { return( TRC_FALSE ); } TT = TT->next; } return( TRC_TRUE ); } void trc_end_trace( ID ) TRC_ID ID; { if ( ID->trace_out != NULL ) trc_status_msg( ID, "Trace File Complete" ); trc_free_tevtask_list( &(ID->tevtask_list) ); trc_cleanup_dead_hosts(); ID->complete = TRC_TRUE; } TRC_HOST trc_create_host() { TRC_HOST tmp; int i; tmp = (TRC_HOST) malloc( sizeof( struct trc_host_struct ) ); trc_memcheck( tmp, "Host Structure" ); tmp->name = (char *) NULL; tmp->alias = (char *) NULL; tmp->refname = (char *) NULL; tmp->arch = (char *) NULL; tmp->delta.tv_usec = 0; tmp->delta.tv_sec = 0; tmp->last_time.tv_usec = 0; tmp->last_time.tv_sec = 0; tmp->pvmd_tid = -1; tmp->speed = -1; /* Tracing Info */ tmp->tevlist = (void **) NULL; tmp->tevsize = -1; tmp->didlist = (void **) NULL; tmp->didsize = -1; tmp->ext = (void *) NULL; tmp->next = (TRC_HOST) NULL; return( tmp ); } void trc_free_host( ptr ) TRC_HOST *ptr; { TRC_HOST H; int i; if ( ptr == NULL || *ptr == NULL ) return; H = *ptr; if ( H->name != NULL ) { free( H->name ); H->name = (char *) NULL; } if ( H->alias != NULL ) { free( H->alias ); H->alias = (char *) NULL; } if ( H->refname != NULL ) { free( H->refname ); H->refname = (char *) NULL; } if ( H->arch != NULL ) { free( H->arch ); H->arch = (char *) NULL; } H->delta.tv_usec = 0; H->delta.tv_sec = 0; H->last_time.tv_usec = 0; H->last_time.tv_sec = 0; H->pvmd_tid = -1; H->speed = -1; /* Tracing Info */ if ( H->tevlist != NULL ) { for ( i=0 ; i < H->tevsize ; i++ ) H->tevlist[i] = (void *) NULL; free( H->tevlist ); H->tevlist = (void **) NULL; } H->tevsize = -1; if ( H->didlist != NULL ) { for ( i=0 ; i < H->didsize ; i++ ) H->didlist[i] = (void *) NULL; free( H->didlist ); H->didlist = (void **) NULL; } H->didsize = -1; H->ext = (void *) NULL; H->next = (TRC_HOST) NULL; free( H ); *ptr = (TRC_HOST) NULL; } void trc_cleanup_dead_hosts() { TRC_HOST Hlast; TRC_HOST Hnext; TRC_HOST H; H = TRC_HOST_LIST; Hlast = (TRC_HOST) NULL; while ( H != NULL ) { Hnext = H->next; if ( H->in_pvm == TRC_NOT_IN_PVM ) { if ( Hlast != NULL ) Hlast->next = Hnext; else TRC_HOST_LIST = Hnext; trc_free_host( &H ); } else Hlast = H; H = Hnext; } } TRC_HOST trc_get_host_name( name ) char *name; { TRC_HOST H; H = TRC_HOST_LIST; while ( H != NULL ) { if ( TRC_HOST_COMPARE( H, name ) ) return( H ); H = H->next; } return( (TRC_HOST) NULL ); } TRC_HOST trc_get_host_tid( tid ) int tid; { TRC_HOST H; H = TRC_HOST_LIST; while ( H != NULL ) { if ( H->pvmd_tid == tid ) return( H ); H = H->next; } return( (TRC_HOST) NULL ); } TRC_HOST trc_get_host_tid_last( tid, last ) int tid; TRC_HOST *last; { TRC_HOST H; H = TRC_HOST_LIST; *last = (TRC_HOST) NULL; while ( H != NULL ) { if ( H->pvmd_tid == tid ) return( H ); else { *last = H; H = H->next; } } return( (TRC_HOST) NULL ); } int trc_check_host_sync( ID ) TRC_ID ID; { #ifdef PIGS_FLY TRC_HOST H; int elapsed; int ecnt; H = TRC_HOST_LIST; ecnt = 0; while ( H != NULL ) { if ( H->in_pvm == TRC_IN_PVM && !TRC_LOCALHOST( H->name ) ) { elapsed = TRC_TIME_ELAPSED( H->last_time, TRC_TRACE_TIME ); if ( elapsed > 10000000 ) ecnt += trc_do_host_sync( ID, H, TRC_TRUE ); } H = H->next; } return( ecnt ); #else return( 0 ); #endif } int trc_do_host_sync( ID, H, dump_event ) TRC_ID ID; TRC_HOST H; int dump_event; { static struct timeval hi = { 0, 0 }; static struct timeval lo = { 0, 0 }; struct timeval delta; struct timeval avg; int hiset, loset; int force; int valid; int ecnt; int i; if ( trc_compare( "0x", H->name ) ) return( 0 ); force = TRC_FALSE; valid = TRC_TRUE; hiset = loset = 0; ecnt = 0; avg.tv_sec = 0; avg.tv_usec = 0; for ( i=0 ; i < 10 && valid ; i++ ) { TRC_PVMCKERR( pvm_hostsync( H->pvmd_tid, (struct timeval *) NULL, &delta ), "Host Sync", valid = TRC_FALSE ); if ( valid ) { if ( TRC_TIME_COMPARE( delta, hi ) > 0 || !hiset ) { hi.tv_sec = delta.tv_sec; hi.tv_usec = delta.tv_usec; hiset++; } if ( TRC_TIME_COMPARE( delta, lo ) < 0 || !loset ) { lo.tv_sec = delta.tv_sec; lo.tv_usec = delta.tv_usec; loset++; } avg.tv_sec += delta.tv_sec; avg.tv_usec += delta.tv_usec; } } if ( valid ) { if ( H->delta.tv_sec != 0 || H->delta.tv_usec != 0 ) force = TRC_TRUE; avg.tv_sec -= hi.tv_sec + lo.tv_sec; avg.tv_usec -= hi.tv_usec + lo.tv_usec; avg.tv_sec /= 8; avg.tv_usec /= 8; H->delta.tv_sec = avg.tv_sec; H->delta.tv_usec = avg.tv_usec; if ( H->delta.tv_usec < 0 ) { H->delta.tv_usec += 1000000; (H->delta.tv_sec)--; } if ( dump_event && ( force || H->delta.tv_sec != 0 || H->delta.tv_usec != 0 ) ) { trc_write_host_sync_event( ID, H ); ecnt++; } else { H->last_time.tv_sec = TRC_TRACE_TIME.tv_sec; H->last_time.tv_usec = TRC_TRACE_TIME.tv_usec; } } return( ecnt ); } TRC_ID trc_create_tracer_id() { TRC_ID tmp; tmp = (TRC_ID) malloc( sizeof( struct trc_id_struct ) ); trc_memcheck( tmp, "Tracer ID Structure" ); tmp->complete = -1; tmp->group_tasks = -1; tmp->event_ctx = -1; tmp->event_tag = -1; tmp->output_ctx = -1; tmp->output_tag = -1; tmp->tevtask_list = (TRC_TEVTASK) NULL; tmp->trace_file = (char *) NULL; tmp->trace_out = (FILE *) NULL; tmp->trace_in = (FILE *) NULL; tmp->output_file = (char *) NULL; tmp->output_fp = (FILE *) NULL; tmp->status_msg = (trc_vfp) NULL; tmp->event_dump_hdr = (trc_vfp) NULL; tmp->output_dump_hdr = (trc_vfp) NULL; tmp->handle_host_add_notify = (trc_vfp) NULL; tmp->handle_host_del_notify = (trc_vfp) NULL; tmp->handle_descriptor = (trc_vfp) NULL; tmp->handle_old_descriptor = (trc_vfp) NULL; tmp->handle_event = (trc_vfp) NULL; tmp->handle_old_event = (trc_vfp) NULL; tmp->handle_command = (trc_vfp) NULL; tmp->handle_comment = (trc_vfp) NULL; tmp->next = (TRC_ID) NULL; return( tmp ); } void trc_free_tracer_id( ptr ) TRC_ID *ptr; { TRC_ID ID; if ( ptr == NULL || *ptr == NULL ) return; ID = *ptr; if ( ID->tevtask_list != NULL ) { trc_free_tevtask_list( &(ID->tevtask_list) ); /* Still Some Unfinished Tasks - Save It */ if ( ID->tevtask_list != NULL ) { ID->next = TRC_DEAD_ID_LIST; TRC_DEAD_ID_LIST = ID; *ptr = (TRC_ID) NULL; return; } } ID->complete = -1; ID->group_tasks = -1; ID->event_ctx = -1; ID->event_tag = -1; ID->output_ctx = -1; ID->output_tag = -1; if ( ID->trace_file != NULL ) { free( ID->trace_file ); ID->trace_file = (char *) NULL; } if ( ID->trace_out != NULL ) { if ( ID->trace_out != stdout ) fclose( ID->trace_out ); ID->trace_out = (FILE *) NULL; } if ( ID->trace_in != NULL ) { if ( ID->trace_in != stdin ) fclose( ID->trace_in ); ID->trace_in = (FILE *) NULL; } if ( ID->output_file != NULL ) { free( ID->output_file ); ID->output_file = (char *) NULL; } if ( ID->output_fp != NULL ) { if ( ID->output_fp != stdout ) fclose( ID->output_fp ); ID->output_fp = (FILE *) NULL; } ID->status_msg = (trc_vfp) NULL; ID->event_dump_hdr = (trc_vfp) NULL; ID->output_dump_hdr = (trc_vfp) NULL; ID->handle_host_add_notify = (trc_vfp) NULL; ID->handle_host_del_notify = (trc_vfp) NULL; ID->handle_descriptor = (trc_vfp) NULL; ID->handle_old_descriptor = (trc_vfp) NULL; ID->handle_event = (trc_vfp) NULL; ID->handle_old_event = (trc_vfp) NULL; ID->handle_command = (trc_vfp) NULL; ID->handle_comment = (trc_vfp) NULL; ID->next = (TRC_ID) NULL; free( ID ); *ptr = (TRC_ID) NULL; } void trc_initialize_hosts( ID ) TRC_ID ID; { TRC_HOST H; struct pvmhostinfo *hostp; int narch; int nhost; int host; int i, j; int new; /* Set Up Host Add Notifies */ pvm_notify( PvmHostAdd, TRC_HOST_ADD_NOTIFY_CODE, -1, (int *) NULL ); /* Get Existing Configuration */ TRC_PVMCKERR( pvm_config( &nhost, &narch, &hostp ), "Error Checking Existing Configuration", exit( -1 ) ); /* Set up Host Delete Notify's */ for ( i=0 ; i < nhost ; i++ ) pvm_notify( PvmHostDelete, TRC_HOST_DEL_NOTIFY_CODE, 1, &(hostp[i].hi_tid) ); /* Process Hosts */ for ( i=0 ; i < nhost ; i++ ) { new = trc_update_host( &H, hostp, i, -1 ); /* Invoke User Custom Handler */ if ( new && ID != NULL && ID->handle_host_add_notify ) (ID->handle_host_add_notify)( H ); } /* Fix TRC_LOCALHOST / TRC_HOST_NAME - Network Name in use... */ host = pvm_tidtohost( TRC_TID ); H = trc_get_host_tid( host ); if ( H != NULL ) { if ( TRC_HOST_NAME != NULL ) free( TRC_HOST_NAME ); TRC_HOST_NAME = trc_copy_str( H->name ); if ( TRC_HOST_ALIAS != NULL ) free( TRC_HOST_ALIAS ); TRC_HOST_ALIAS = trc_copy_str( H->alias ); /* Verify Host Delay Cleared */ H->delta.tv_sec = H->delta.tv_usec = 0; } } int trc_handle_host_add_notify( ID, tids, num ) TRC_ID ID; int *tids; int num; { TRC_HOST H; struct pvmhostinfo *hostp; int found; int narch; int nhost; int ecnt; int i, j; int new; ecnt = 0; TRC_PVMCKERR( pvm_config( &nhost, &narch, &hostp ), "Error Checking Existing Configuration", exit( -1 ) ); /* Look For New Hosts */ for ( i=0 ; i < num ; i++ ) { /* Find Hostinfo Struct */ found = -1; for ( j=0 ; j < nhost && found < 0 ; j++ ) { if ( hostp[j].hi_tid == tids[i] ) found = j; } new = trc_update_host( &H, hostp, found, tids[i] ); if ( new ) { /* Invoke User Custom Handler */ if ( ID->handle_host_add_notify ) (ID->handle_host_add_notify)( H ); /* Save Host Add Event to Trace File */ if ( ID->trace_out != NULL ) { trc_update_trace_time( -1, -1 ); trc_write_host_add_event( ID, H ); ecnt++; if ( H->delta.tv_sec != 0 || H->delta.tv_usec != 0 ) { trc_write_host_sync_event( ID, H ); ecnt++; } } } } return( ecnt ); } int trc_handle_host_del_notify( ID, tid ) TRC_ID ID; int tid; { TRC_HOST Hlast; TRC_HOST H; int ecnt; ecnt = 0; /* Lookup Dead Host */ H = trc_get_host_tid_last( tid, &Hlast ); if ( H != NULL ) { /* Mark Host as Dead */ H->in_pvm = TRC_NOT_IN_PVM; /* Invoke User Custom Handler */ if ( ID->handle_host_del_notify ) (ID->handle_host_del_notify)( H ); /* Save Host Delete Event to Trace File */ if ( ID->trace_out != NULL ) { trc_update_trace_time( -1, -1 ); trc_write_host_del_event( ID, H, tid ); ecnt++; } } else printf( "Missing Host for Notify Delete, TID=0x%x\n", tid ); return( ecnt ); } int trc_update_host( Hret, hostp, index, tid ) TRC_HOST *Hret; struct pvmhostinfo *hostp; int index; int tid; { TRC_HOST Hlast; TRC_HOST H; struct pvmhostinfo *HP; char tmp[1024]; char tmp2[1024]; int too_quick; int found; int i, j; int new; too_quick = 0; new = 0; if ( index >= 0 ) { HP = &(hostp[index]); tid = HP->hi_tid; } else too_quick++; /* Check Host List */ H = trc_get_host_tid_last( tid, &Hlast ); /* Host Not Found, Add to Hosts List */ if ( H == NULL ) { if ( Hlast != NULL ) H = Hlast->next = trc_create_host(); else H = TRC_HOST_LIST = trc_create_host(); if ( !too_quick ) { H->name = trc_copy_str( HP->hi_name ); H->alias = trc_host_alias_str( H->name ); H->refname = trc_copy_str( HP->hi_name ); H->arch = trc_copy_str( HP->hi_arch ); H->pvmd_tid = HP->hi_tid; H->speed = HP->hi_speed; } else { sprintf( tmp, "0x%x", tid ); H->name = trc_copy_str( tmp ); H->alias = trc_copy_str( tmp ); H->refname = trc_copy_str( "" ); H->arch = trc_copy_str( "DUMMY" ); H->pvmd_tid = tid; H->speed = 0; } new++; } H->in_pvm = TRC_IN_PVM; /* Set Host Delay */ if ( !TRC_LOCALHOST( H->name ) ) trc_do_host_sync( (TRC_ID) NULL, H, TRC_FALSE ); *Hret = H; return( new ); } void trc_status_msg( ID, msg ) TRC_ID ID; char *msg; { if ( ID->status_msg ) (ID->status_msg)( ID, msg ); else fprintf( stderr, "%s\n", msg ); } char * trc_date_str() { char tmp[255]; char *result; PVM_TIMET t; time( &t ); sprintf( tmp, "%s", ctime( &t ) ); result = tmp; while ( *result != '\n' && *result != '\0' ) result++; *result = '\0'; result = trc_copy_str( tmp ); return( result ); } int trc_append_str( result, str, maxlen ) char *result; char *str; int maxlen; { int rlen; int len; int rc; int i; rlen = strlen( result ); len = rlen + strlen( str ) + 1; rc = TRC_TRUE; if ( len <= maxlen ) strcat( result, str ); else { i = rlen; while ( i < maxlen - 4 ) { result[i] = str[ i - rlen ]; i++; } sprintf( (char *) (result + (maxlen - 4)), "..." ); rc = TRC_FALSE; } return( rc ); } char * trc_host_alias_str( name ) char *name; { char *ptr; char *tmp; char c; if ( name == NULL ) return( (char *) NULL ); ptr = name; while ( *ptr != '\0' && *ptr != '.' ) ptr++; if ( *ptr == '.' ) { c = *ptr; *ptr = '\0'; tmp = trc_copy_str( name ); *ptr = c; } else tmp = trc_copy_str( name ); return( tmp ); } char * trc_pad_num( num, max ) long num; long max; { char tmp[1024]; char *ptr; char *str; int nd; int nz; int i; sprintf( tmp, "%ld", num ); nd = strlen( tmp ); nz = max - nd; str = (char *) malloc( (unsigned) (max + 1) * sizeof(char) ); trc_memcheck( str, "Numerical Pad String" ); ptr = str; for ( i=0 ; i < nz ; i++ ) *ptr++ = '0'; sprintf( (char *) (str + nz), "%ld", num ); return( str ); } char * trc_copy_str( str ) char *str; { char *tmp; tmp = (char *) malloc( (unsigned) (strlen(str) + 1) * sizeof(char) ); trc_memcheck(tmp,"Copy String"); strcpy( tmp, str ); return( tmp ); } int trc_filecheck( fp, name ) FILE *fp; char *name; { if ( fp == NULL ) { fprintf( stderr, "\nError Opening File \"%s\"\n\n", name ); return( TRC_FALSE ); } return( TRC_TRUE ); } void trc_memcheck( ptr, name ) void *ptr; char *name; { if ( ptr == NULL ) { fprintf( stderr, "\nError Allocating Memory for \"%s\"\n\n", name ); exit( -1 ); } } int trc_compare( x, y ) char *x; char *y; { while ( *x != '\0' ) { if ( *x != *y ) return( TRC_FALSE ); x++; y++; } return( TRC_TRUE ); } ./pvm3/tracer/tracer.h0100644007401100000360000000422607452415136014024 0ustar kohlgopher /* $Id: tracer.h,v 4.6 2002/04/02 20:53:50 pvmsrc Exp $ */ /* * Tracer version 1.0: A Trace File Generator for PVM * Oak Ridge National Laboratory, Oak Ridge TN. * Authors: James Arthur Kohl and G. A. Geist * (C) 1994 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear * in supporting documentation. * * Neither the Institution, Oak Ridge National Laboratory, nor the * Authors make any representations about the suitability of this * software for any purpose. This software is provided ``as is'' * without express or implied warranty. * * Tracer was funded by the U.S. Department of Energy. */ /* System Header Files */ #include #ifdef SYSVSTR #include #else #include #endif #include #ifndef WIN32 #include #include #else #include "pvmwin.h" #include #endif #ifdef HASSTDLIB #include #else #ifndef IMA_MACOSX #include #endif #endif #include #include /* Header Files */ #include #ifdef USE_PVM_33 #include "../src/tdpro.h" #else #include #endif #include #include "trcdef.h" typedef void (*vfp)(); typedef int (*ifp)(); /* Defined Constants & Macros */ /* This Tracer's Version */ #define MYVERSION "1.0.0" /* Select Macro (based on FDSETISINT) */ #ifdef FDSETISINT #define SELECT( _nfds, _rfdsp, _wfdsp, _efdsp, _tvalp ) \ select( (_nfds), \ (int *) (_rfdsp), (int *) (_wfdsp), (int *) (_efdsp), \ (struct timeval *) (_tvalp) ) #else #define SELECT( _nfds, _rfdsp, _wfdsp, _efdsp, _tvalp ) \ select( (_nfds), \ (fd_set *) (_rfdsp), (fd_set *) (_wfdsp), (fd_set *) (_efdsp), \ (struct timeval *) (_tvalp) ) #endif /* Routines */ FILE *fopen(); void re_register_tracer(); /* Externals */ extern struct Pvmtevinfo pvmtevinfo[]; extern int errno; ./pvm3/tracer/trccompat.h0100644007401100000360000001703106236210161014524 0ustar kohlgopher /* $Id: trccompat.h,v 4.1 1996/10/31 20:47:45 pvmsrc Exp $ */ /* * Tracer version 1.0: A Trace File Generator for PVM * Oak Ridge National Laboratory, Oak Ridge TN. * Authors: James Arthur Kohl and G. A. Geist * (C) 1994 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear * in supporting documentation. * * Neither the Institution, Oak Ridge National Laboratory, nor the * Authors make any representations about the suitability of this * software for any purpose. This software is provided ``as is'' * without express or implied warranty. * * Tracer was funded by the U.S. Department of Energy. */ /* Old PVM 3.3 Libpvm tracing includes. */ /* Trace Event Constants */ #define TRC_OLD_TEV_FIRST 0 #define TRC_OLD_TEV_ADDHOSTS0 0 #define TRC_OLD_TEV_ADDHOSTS1 1 #define TRC_OLD_TEV_BARRIER0 2 #define TRC_OLD_TEV_BARRIER1 3 #define TRC_OLD_TEV_BCAST0 4 #define TRC_OLD_TEV_BCAST1 5 #define TRC_OLD_TEV_BUFINFO0 6 #define TRC_OLD_TEV_BUFINFO1 7 #define TRC_OLD_TEV_CONFIG0 8 #define TRC_OLD_TEV_CONFIG1 9 #define TRC_OLD_TEV_DELETE0 10 #define TRC_OLD_TEV_DELETE1 11 #define TRC_OLD_TEV_DELHOSTS0 12 #define TRC_OLD_TEV_DELHOSTS1 13 #define TRC_OLD_TEV_EXIT0 14 #define TRC_OLD_TEV_EXIT1 15 #define TRC_OLD_TEV_FREEBUF0 16 #define TRC_OLD_TEV_FREEBUF1 17 #define TRC_OLD_TEV_GETFDS0 18 #define TRC_OLD_TEV_GETFDS1 19 #define TRC_OLD_TEV_GETINST0 20 #define TRC_OLD_TEV_GETINST1 21 #define TRC_OLD_TEV_GETOPT0 22 #define TRC_OLD_TEV_GETOPT1 23 #define TRC_OLD_TEV_GETRBUF0 24 #define TRC_OLD_TEV_GETRBUF1 25 #define TRC_OLD_TEV_GETSBUF0 26 #define TRC_OLD_TEV_GETSBUF1 27 #define TRC_OLD_TEV_GETTID0 28 #define TRC_OLD_TEV_GETTID1 29 #define TRC_OLD_TEV_GSIZE0 30 #define TRC_OLD_TEV_GSIZE1 31 #define TRC_OLD_TEV_HALT0 32 #define TRC_OLD_TEV_HALT1 33 #define TRC_OLD_TEV_INITSEND0 34 #define TRC_OLD_TEV_INITSEND1 35 #define TRC_OLD_TEV_INSERT0 36 #define TRC_OLD_TEV_INSERT1 37 #define TRC_OLD_TEV_JOINGROUP0 38 #define TRC_OLD_TEV_JOINGROUP1 39 #define TRC_OLD_TEV_KILL0 40 #define TRC_OLD_TEV_KILL1 41 #define TRC_OLD_TEV_LOOKUP0 42 #define TRC_OLD_TEV_LOOKUP1 43 #define TRC_OLD_TEV_LVGROUP0 44 #define TRC_OLD_TEV_LVGROUP1 45 #define TRC_OLD_TEV_MCAST0 46 #define TRC_OLD_TEV_MCAST1 47 #define TRC_OLD_TEV_MKBUF0 48 #define TRC_OLD_TEV_MKBUF1 49 #define TRC_OLD_TEV_MSTAT0 50 #define TRC_OLD_TEV_MSTAT1 51 #define TRC_OLD_TEV_MYTID0 52 #define TRC_OLD_TEV_MYTID1 53 #define TRC_OLD_TEV_NOTIFY0 54 #define TRC_OLD_TEV_NOTIFY1 55 #define TRC_OLD_TEV_NRECV0 56 #define TRC_OLD_TEV_NRECV1 57 #define TRC_OLD_TEV_PARENT0 58 #define TRC_OLD_TEV_PARENT1 59 #define TRC_OLD_TEV_PERROR0 60 #define TRC_OLD_TEV_PERROR1 61 #define TRC_OLD_TEV_PKBYTE0 62 #define TRC_OLD_TEV_PKBYTE1 63 #define TRC_OLD_TEV_PKCPLX0 64 #define TRC_OLD_TEV_PKCPLX1 65 #define TRC_OLD_TEV_PKDCPLX0 66 #define TRC_OLD_TEV_PKDCPLX1 67 #define TRC_OLD_TEV_PKDOUBLE0 68 #define TRC_OLD_TEV_PKDOUBLE1 69 #define TRC_OLD_TEV_PKFLOAT0 70 #define TRC_OLD_TEV_PKFLOAT1 71 #define TRC_OLD_TEV_PKINT0 72 #define TRC_OLD_TEV_PKINT1 73 #define TRC_OLD_TEV_PKUINT0 74 #define TRC_OLD_TEV_PKUINT1 75 #define TRC_OLD_TEV_PKLONG0 76 #define TRC_OLD_TEV_PKLONG1 77 #define TRC_OLD_TEV_PKULONG0 78 #define TRC_OLD_TEV_PKULONG1 79 #define TRC_OLD_TEV_PKSHORT0 80 #define TRC_OLD_TEV_PKSHORT1 81 #define TRC_OLD_TEV_PKUSHORT0 82 #define TRC_OLD_TEV_PKUSHORT1 83 #define TRC_OLD_TEV_PKSTR0 84 #define TRC_OLD_TEV_PKSTR1 85 #define TRC_OLD_TEV_PROBE0 86 #define TRC_OLD_TEV_PROBE1 87 #define TRC_OLD_TEV_PSTAT0 88 #define TRC_OLD_TEV_PSTAT1 89 #define TRC_OLD_TEV_RECV0 90 #define TRC_OLD_TEV_RECV1 91 #define TRC_OLD_TEV_RECVF0 92 #define TRC_OLD_TEV_RECVF1 93 #define TRC_OLD_TEV_SEND0 94 #define TRC_OLD_TEV_SEND1 95 #define TRC_OLD_TEV_SENDSIG0 96 #define TRC_OLD_TEV_SENDSIG1 97 #define TRC_OLD_TEV_SETOPT0 98 #define TRC_OLD_TEV_SETOPT1 99 #define TRC_OLD_TEV_SETRBUF0 100 #define TRC_OLD_TEV_SETRBUF1 101 #define TRC_OLD_TEV_SETSBUF0 102 #define TRC_OLD_TEV_SETSBUF1 103 #define TRC_OLD_TEV_SPAWN0 104 #define TRC_OLD_TEV_SPAWN1 105 #define TRC_OLD_TEV_START_PVMD0 106 #define TRC_OLD_TEV_START_PVMD1 107 #define TRC_OLD_TEV_TASKS0 108 #define TRC_OLD_TEV_TASKS1 109 #define TRC_OLD_TEV_TICKLE0 110 #define TRC_OLD_TEV_TICKLE1 111 #define TRC_OLD_TEV_TIDTOHOST0 112 #define TRC_OLD_TEV_TIDTOHOST1 113 #define TRC_OLD_TEV_TRECV0 114 #define TRC_OLD_TEV_TRECV1 115 #define TRC_OLD_TEV_UPKBYTE0 116 #define TRC_OLD_TEV_UPKBYTE1 117 #define TRC_OLD_TEV_UPKCPLX0 118 #define TRC_OLD_TEV_UPKCPLX1 119 #define TRC_OLD_TEV_UPKDCPLX0 120 #define TRC_OLD_TEV_UPKDCPLX1 121 #define TRC_OLD_TEV_UPKDOUBLE0 122 #define TRC_OLD_TEV_UPKDOUBLE1 123 #define TRC_OLD_TEV_UPKFLOAT0 124 #define TRC_OLD_TEV_UPKFLOAT1 125 #define TRC_OLD_TEV_UPKINT0 126 #define TRC_OLD_TEV_UPKINT1 127 #define TRC_OLD_TEV_UPKUINT0 128 #define TRC_OLD_TEV_UPKUINT1 129 #define TRC_OLD_TEV_UPKLONG0 130 #define TRC_OLD_TEV_UPKLONG1 131 #define TRC_OLD_TEV_UPKULONG0 132 #define TRC_OLD_TEV_UPKULONG1 133 #define TRC_OLD_TEV_UPKSHORT0 134 #define TRC_OLD_TEV_UPKSHORT1 135 #define TRC_OLD_TEV_UPKUSHORT0 136 #define TRC_OLD_TEV_UPKUSHORT1 137 #define TRC_OLD_TEV_UPKSTR0 138 #define TRC_OLD_TEV_UPKSTR1 139 #define TRC_OLD_TEV_VERSION0 140 #define TRC_OLD_TEV_VERSION1 141 #define TRC_OLD_TEV_REG_HOSTER0 142 #define TRC_OLD_TEV_REG_HOSTER1 143 #define TRC_OLD_TEV_REG_RM0 144 #define TRC_OLD_TEV_REG_RM1 145 #define TRC_OLD_TEV_REG_TASKER0 146 #define TRC_OLD_TEV_REG_TASKER1 147 #define TRC_OLD_TEV_NEWTASK 148 #define TRC_OLD_TEV_ENDTASK 150 #define TRC_OLD_TEV_SPNTASK 152 #define TRC_OLD_TEV_ARCHCODE0 154 #define TRC_OLD_TEV_ARCHCODE1 155 #define TRC_OLD_TEV_CATCHOUT0 156 #define TRC_OLD_TEV_CATCHOUT1 157 #define TRC_OLD_TEV_GETMWID0 158 #define TRC_OLD_TEV_GETMWID1 159 #define TRC_OLD_TEV_GETTMASK0 160 #define TRC_OLD_TEV_GETTMASK1 161 #define TRC_OLD_TEV_HOSTSYNC0 162 #define TRC_OLD_TEV_HOSTSYNC1 163 #define TRC_OLD_TEV_PACKF0 164 #define TRC_OLD_TEV_PACKF1 165 #define TRC_OLD_TEV_PRECV0 166 #define TRC_OLD_TEV_PRECV1 167 #define TRC_OLD_TEV_PSEND0 168 #define TRC_OLD_TEV_PSEND1 169 #define TRC_OLD_TEV_REDUCE0 170 #define TRC_OLD_TEV_REDUCE1 171 #define TRC_OLD_TEV_SETMWID0 172 #define TRC_OLD_TEV_SETMWID1 173 #define TRC_OLD_TEV_SETTMASK0 174 #define TRC_OLD_TEV_SETTMASK1 175 #define TRC_OLD_TEV_UNPACKF0 176 #define TRC_OLD_TEV_UNPACKF1 177 #define TRC_OLD_TEV_GATHER0 178 #define TRC_OLD_TEV_GATHER1 179 #define TRC_OLD_TEV_SCATTER0 180 #define TRC_OLD_TEV_SCATTER1 181 #define TRC_OLD_TEV_MAX 181 #define TRC_OLD_TRACE_OUTPUT (TRC_OLD_TEV_MAX + 1) #define TRC_OLD_TRACE_HOST_ADD (TRC_OLD_TEV_MAX + 2) #define TRC_OLD_TRACE_HOST_DEL (TRC_OLD_TEV_MAX + 3) #define TRC_OLD_TRACE_HOST_SYNC (TRC_OLD_TEV_MAX + 4) #define TRC_OLD_TRACE_MAX (TRC_OLD_TEV_MAX + 5) /* Old PVM 3.3 Event Format Structure */ struct trc_old_tevfmt { char *name; char *fmt; }; /* Globals */ extern char *TRC_OLD_TRACE_DESCRIPTORS[]; extern char *TRC_OLD_TEV_TRACE_NAMES[]; extern struct trc_old_tevfmt trc_old_tev_formats[]; extern int TRC_OLD_TEV_TRACE[TRC_OLD_TRACE_MAX]; extern char *trc_old_pvm_errlist[]; extern int trc_old_pvm_nerr; ./pvm3/tracer/trccompatrev.h0100644007401100000360000000613006236210170015237 0ustar kohlgopher /* $Id: trccompatrev.h,v 4.1 1996/10/31 20:47:52 pvmsrc Exp $ */ /* * Tracer version 1.0: A Trace File Generator for PVM * Oak Ridge National Laboratory, Oak Ridge TN. * Authors: James Arthur Kohl and G. A. Geist * (C) 1994 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear * in supporting documentation. * * Neither the Institution, Oak Ridge National Laboratory, nor the * Authors make any representations about the suitability of this * software for any purpose. This software is provided ``as is'' * without express or implied warranty. * * Tracer was funded by the U.S. Department of Energy. */ /* * trccompatrev.h * * New PVM 3.4 Libpvm tracing includes for 3.3 compilation. * */ #define TEV_FIRST 0 #define TEV_MAX 0 #define TEV_HEADER 0 #define TEV_DID_FIRST 0 #define TEV_DID_HN 0 #define TEV_DID_HNA 0 #define TEV_DID_HA 0 #define TEV_DID_HSP 0 #define TEV_DID_HDS 0 #define TEV_DID_HDU 0 #define TEV_DID_OS 0 #define TEV_DID_TID 0 #define TEV_DID_TS 0 #define TEV_DID_TU 0 #define TEV_DID_MAX 0 #define TEV_EVENT_ENTRY 0x4000 #define TEV_EVENT_EXIT 0x8000 /* Trace Event Info Structures */ struct Pvmtevinfo { char *name; int desc_status; struct timeval mark; struct timeval total; int count; }; extern struct Pvmtevinfo pvmtevinfo[]; struct Pvmtevdid { char *did; char *desc; }; extern struct Pvmtevdid pvmtevdidlist[]; /* Trace Markers */ #define TEV_MARK_EVENT_BUFFER -1 #define TEV_MARK_EVENT_BUFFER_END -2 #define TEV_MARK_DATA_ID -3 #define TEV_MARK_DATA_ID_END -4 #define TEV_MARK_EVENT_DESC -5 #define TEV_MARK_EVENT_DESC_END -6 #define TEV_MARK_EVENT_RECORD -7 #define TEV_MARK_EVENT_RECORD_END -8 #define TEV_MARK_USER_EVENT_RECORD -9 #define TEV_MARK_USER_EVENT_RECORD_END -10 /* Trace Event Data Types */ #define TEV_DATA_NULL 0 #define TEV_DATA_BYTE 1 #define TEV_DATA_CPLX 2 #define TEV_DATA_DCPLX 3 #define TEV_DATA_DOUBLE 4 #define TEV_DATA_FLOAT 5 #define TEV_DATA_INT 6 #define TEV_DATA_UINT 7 #define TEV_DATA_LONG 8 #define TEV_DATA_ULONG 9 #define TEV_DATA_SHORT 10 #define TEV_DATA_USHORT 11 #define TEV_DATA_STRING 12 #define TEV_DATA_STRUCT_START 13 #define TEV_DATA_STRUCT_END 14 #define TEV_DATA_DEFERRED 15 #define TEV_DATA_SCALAR 0x00 #define TEV_DATA_ARRAY 0x80 /* Trace Mask Macros & Constants */ #define TEV_MASK_LENGTH 32 typedef char Pvmtmask[TEV_MASK_LENGTH]; #define TEV_MASK_SET( m, k ) ( m[ (k) / 4 ] |= ( 1 << ((k) & 3) ) ) #define TEV_MASK_UNSET( m, k ) ( m[ (k) / 4 ] &= ~( 1 << ((k) & 3) ) ) #define TEV_MASK_CHECK( m, k ) ( m[ (k) / 4 ] & (1 << ((k) & 3) ) ) #define TEV_MASK_INIT( m ) \ { \ int tev_init_mask_i = TEV_MASK_LENGTH - 1; \ m[ tev_init_mask_i ] = 0; \ while ( tev_init_mask_i-- > 0 ) \ m[ tev_init_mask_i ] = '@'; \ } ./pvm3/tracer/trcdef.h0100644007401100000360000000326506236210172014005 0ustar kohlgopher /* $Id: trcdef.h,v 4.1 1996/10/31 20:47:54 pvmsrc Exp $ */ /* * Tracer version 1.0: A Trace File Generator for PVM * Oak Ridge National Laboratory, Oak Ridge TN. * Authors: James Arthur Kohl and G. A. Geist * (C) 1994 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear * in supporting documentation. * * Neither the Institution, Oak Ridge National Laboratory, nor the * Authors make any representations about the suitability of this * software for any purpose. This software is provided ``as is'' * without express or implied warranty. * * Tracer was funded by the U.S. Department of Energy. */ /* Tracer Data Types Header */ #include "trctype.h" #ifdef USE_PVM_33 /* Backwards Compatibility Header for PVM 3.3 Usage */ #include "trccompatrev.h" #endif /* Routine Prototypes */ #include "trcproto.h" /* External Variables */ extern struct timeval TRC_TRACE_TIME; extern TRC_TEVREC TRC_TMP_TR; extern TRC_TRIE TRC_OLD_EVENT_TRIE; extern TRC_TRIE TRC_HANDLE_TRIE; extern TRC_TRIE TRC_EVENT_TRIE; extern TRC_TRIE TRC_DID_TRIE; extern TRC_HOST TRC_HOST_LIST; extern char *TRC_HOST_NAME; extern char *TRC_HOST_ALIAS; extern char *TRC_TMP_HOST; extern char *TRC_VERSION; extern char *TRC_NAME; extern int TRC_HOST_ADD_NOTIFY_CODE; extern int TRC_HOST_DEL_NOTIFY_CODE; extern int TRC_TMP_CMP; extern int TRC_TID; ./pvm3/tracer/trcglob.h0100644007401100000360000000232306354310501014162 0ustar kohlgopher /* $Id: trcglob.h,v 4.2 1997/06/25 21:44:33 pvmsrc Exp $ */ /* * Tracer version 1.0: A Trace File Generator for PVM * Oak Ridge National Laboratory, Oak Ridge TN. * Authors: James Arthur Kohl and G. A. Geist * (C) 1994 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear * in supporting documentation. * * Neither the Institution, Oak Ridge National Laboratory, nor the * Authors make any representations about the suitability of this * software for any purpose. This software is provided ``as is'' * without express or implied warranty. * * Tracer was funded by the U.S. Department of Energy. */ /* Global Variables */ extern TRC_ID ID; extern Pvmtmask TRACE_MASK; extern Pvmtmask CLEAR_MASK; extern char *OUTPUT_FILE; extern char *TRACE_FILE; extern int TRACER_REGISTERED; extern int TRACE_BUF; extern int TRACE_OPT; extern int MYTID; extern int vflag; ./pvm3/tracer/trclib.h0100644007401100000360000001110007452415136014010 0ustar kohlgopher /* $Id: trclib.h,v 4.7 2002/04/02 20:53:50 pvmsrc Exp $ */ /* * Tracer version 1.0: A Trace File Generator for PVM * Oak Ridge National Laboratory, Oak Ridge TN. * Authors: James Arthur Kohl and G. A. Geist * (C) 1994 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear * in supporting documentation. * * Neither the Institution, Oak Ridge National Laboratory, nor the * Authors make any representations about the suitability of this * software for any purpose. This software is provided ``as is'' * without express or implied warranty. * * Tracer was funded by the U.S. Department of Energy. */ /* System Header Files */ #include #include #ifndef WIN32 #include #else #include "pvmwin.h" #endif #include #ifdef HASSTDLIB #include #else #ifndef IMA_MACOSX #include #endif #endif /* PVM Header File */ #include /* PVM Trace Header File */ #ifdef USE_PVM_33 /* Backwards Compatibility Header for PVM 3.3 Usage */ #include "trccompatrev.h" #else #include #endif /* Tracer Data Type Header */ #include "trctype.h" /* Define Maximum Trace Message Unpacking Array Size */ #define TRC_MAX_UNPACK_ARR_SIZE 1024 /* PVM Error Check Macro */ #define TRC_NOP (TRC_TMP_CC = TRC_TMP_CC) #define TRC_PVMCKERR( _cmd, _str, _handle ) \ { \ TRC_TMP_CC = _cmd; \ \ if ( TRC_TMP_CC < 0 ) \ { \ pvm_perror( _str ); \ \ _handle; \ } \ } \ \ /* Trace File EOF Check Macro */ #define TRC_CKEOF( _c, _str, _handle ) \ { \ if ( _c == (char) EOF ) \ { \ printf( _str ); \ \ _handle; \ } \ } \ \ /* Time Value Macros */ #define TRC_TIME_COMPARE( _t1, _t2 ) \ ( \ ( (_t1).tv_sec > (_t2).tv_sec \ || ( (_t1).tv_sec == (_t2).tv_sec \ && (_t1).tv_usec > (_t2).tv_usec ) ) ? 1 : \ ( ( (_t1).tv_sec == (_t2).tv_sec \ && (_t1).tv_usec == (_t2).tv_usec ) ? 0 : -1 ) \ ) \ \ #define TRC_TIME_ELAPSED( _t1, _t2 ) \ ( \ ( ( (_t2).tv_sec - (_t1).tv_sec ) * 1000000 ) \ + ( (_t2).tv_usec - (_t1).tv_usec ) \ ) \ \ /* Task Status Constants */ #define TRC_TASK_NOLIFE 0 #define TRC_TASK_ALIVE 1 #define TRC_TASK_DEAD 2 #define TRC_TASK_IGNORE 3 #define TRC_TASK_WAITEND 4 /* Task Output Status Constants */ #define TRC_TASK_NOOUT 0 #define TRC_TASK_OUT 1 #define TRC_TASK_EOF 2 #define TRC_TASK_WAITEOF 3 /* Task Omission Condition Macro */ #define TRC_TASK_OMIT( _tevtask ) \ ( (_tevtask)->tevstatus == TRC_TASK_WAITEND \ || (_tevtask)->outstatus == TRC_TASK_WAITEOF ) /* TRC_TRIE Size */ #define TRC_TRIE_SIZE 37 /* Trace Event Descriptor Index Lookup Macro */ #define TRC_TEVINDEX_OF( _eid, _entry_exit ) \ ( ( (_eid) * TRC_MAX_TEV ) + (_entry_exit) ) #define TRC_TEVEID_OF( _index ) \ ( (_index) / TRC_MAX_TEV ) /* Internal Trace Event Constants */ #define TRC_RESERVED_INTERNAL 0x0190 /* ((400+n) * 2) + 1 < 1000 */ #define TRC_HOST_ADD (TRC_RESERVED_INTERNAL + 1) #define TRC_HOST_DEL (TRC_RESERVED_INTERNAL + 2) #define TRC_HOST_SYNC (TRC_RESERVED_INTERNAL + 3) #define TRC_OUTPUT (TRC_RESERVED_INTERNAL + 4) #define TRC_MAX (TRC_RESERVED_INTERNAL + 5) /* Externals */ #ifndef USE_PVM_33 extern struct Pvmtevdid pvmtevdidlist[]; #endif /* Routine Prototypes */ #include "trcproto.h" /* Global Variables */ extern struct timeval TRC_TRACE_TIME; extern TRC_TEVDESC TRC_OUTPUT_TEVDESC; extern TRC_TEVDESC TRC_HOST_ADD_TEVDESC; extern TRC_TEVDESC TRC_HOST_DEL_TEVDESC; extern TRC_TEVDESC TRC_HOST_SYNC_TEVDESC; extern TRC_TEVDESC *TRC_TEVDESC_LIST; extern int TRC_TEVDESC_SIZE; extern TRC_TEVREC TRC_TMP_TR; extern TRC_TRIE TRC_OLD_EVENT_TRIE; extern TRC_TRIE TRC_HANDLE_TRIE; extern TRC_TRIE TRC_EVENT_TRIE; extern TRC_TRIE TRC_DID_TRIE; extern TRC_DID TRC_LOCAL_DID[TEV_DID_MAX - TEV_DID_FIRST + 1]; extern TRC_DID TRC_DID_LIST; extern TRC_ID TRC_DEAD_ID_LIST; extern TRC_ID TRC_ID_LIST; extern char *TRC_TYPE_STRS[16]; extern char *TRC_VERSION; extern char *TRC_NAME; extern char *TRC_TMP_HOST; extern TRC_HOST TRC_HOST_LIST; extern char *TRC_HOST_NAME; extern char *TRC_HOST_ALIAS; extern int TRC_HOST_ADD_NOTIFY_CODE; extern int TRC_HOST_DEL_NOTIFY_CODE; extern int TRC_TID; extern int TRC_TMP_CMP; extern int TRC_TMP_CC; ./pvm3/tracer/trcproto.h0100644007401100000360000002003006341107476014410 0ustar kohlgopher /* $Id: trcproto.h,v 4.3 1997/05/22 18:23:58 pvmsrc Exp $ */ /* * Tracer version 1.0: A Trace File Generator for PVM * Oak Ridge National Laboratory, Oak Ridge TN. * Authors: James Arthur Kohl and G. A. Geist * (C) 1994 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear * in supporting documentation. * * Neither the Institution, Oak Ridge National Laboratory, nor the * Authors make any representations about the suitability of this * software for any purpose. This software is provided ``as is'' * without express or implied warranty. * * Tracer was funded by the U.S. Department of Energy. */ /* Tracer Library Routine Prototypes */ TRC_TRIE trc_create_triestack __ProtoGlarp__(( void )); void *trc_lookup_trie __ProtoGlarp__(( TRC_TRIE, char * )); TRC_DID trc_create_did __ProtoGlarp__(( void )); TRC_DID trc_get_did __ProtoGlarp__(( TRC_HOST, int )); TRC_ID trc_create_tracer_id __ProtoGlarp__(( void )); TRC_ID trc_get_tracer_id __ProtoGlarp__(( void )); TRC_DATADESC trc_create_datadesc __ProtoGlarp__(( void )); TRC_TEVDESC_INFO trc_create_tevdesc_info __ProtoGlarp__(( void )); TRC_TEVDESC trc_create_tevdesc __ProtoGlarp__(( void )); TRC_TEVDESC trc_get_tevdesc __ProtoGlarp__(( TRC_TEVTASK, TRC_HOST, int, int )); TRC_TEVDESC trc_make_tevdesc __ProtoGlarp__(( TRC_ID, int, int, char *, TRC_TEVDESC_INFO, int )); TRC_TEVDESC trc_read_descriptor __ProtoGlarp__(( TRC_ID, int, char *, int, int )); TRC_TEVREC trc_create_tevrec __ProtoGlarp__(( void )); TRC_TEVREC trc_get_tevrec __ProtoGlarp__(( TRC_TEVREC, char * )); TRC_VALUE trc_make_value __ProtoGlarp__(( int, int )); TRC_VALUE trc_copy_value __ProtoGlarp__(( TRC_VALUE, int, int )); TRC_TEVTASK trc_create_tevtask __ProtoGlarp__(( void )); TRC_TEVTASK trc_get_tevtask_tid __ProtoGlarp__(( TRC_ID, int )); TRC_HOST trc_create_host __ProtoGlarp__(( void )); TRC_HOST trc_get_host_name __ProtoGlarp__(( char * )); TRC_HOST trc_get_host_tid __ProtoGlarp__(( int )); TRC_HOST trc_get_host_tid_last __ProtoGlarp__(( int, TRC_HOST * )); void trc_check_for_dead_host __ProtoGlarp__(( TRC_ID, TRC_TEVTASK )); void trc_check_listsize __ProtoGlarp__(( void ***, int *, int )); void trc_cleanup_dead_hosts __ProtoGlarp__(( void )); void trc_define_special_descriptors __ProtoGlarp__(( void )); void trc_dump_old_pvm_event_fmt __ProtoGlarp__(( TRC_ID, int )); void trc_dump_old_sddf_headers __ProtoGlarp__(( void )); void trc_dump_tevdesc __ProtoGlarp__(( TRC_ID, TRC_TEVDESC, int )); void trc_dump_trace_header __ProtoGlarp__(( TRC_ID )); void trc_dump_trace_str __ProtoGlarp__(( TRC_ID, char *, int )); void trc_end_trace __ProtoGlarp__(( TRC_ID )); void trc_free_datadesc __ProtoGlarp__(( TRC_DATADESC * )); void trc_free_did __ProtoGlarp__(( TRC_DID * )); void trc_free_event_descriptors __ProtoGlarp__(( TRC_TRIE )); void trc_free_host __ProtoGlarp__(( TRC_HOST * )); void trc_free_tevdesc_info __ProtoGlarp__(( TRC_TEVDESC_INFO * )); void trc_free_tevrec __ProtoGlarp__(( TRC_TEVREC * )); void trc_free_tevtask __ProtoGlarp__(( TRC_TEVTASK * )); void trc_free_tevtask_list __ProtoGlarp__(( TRC_TEVTASK * )); void trc_free_tracer_id __ProtoGlarp__(( TRC_ID * )); void trc_free_triestack __ProtoGlarp__(( TRC_TRIE * )); void trc_init_did_trie __ProtoGlarp__(( void )); void trc_init_old_events __ProtoGlarp__(( void )); void trc_initialize_hosts __ProtoGlarp__(( TRC_ID )); void trc_memcheck __ProtoGlarp__(( void *, char * )); void trc_print_tmask __ProtoGlarp__(( Pvmtmask )); void trc_remove_tevdesc __ProtoGlarp__(( TRC_TEVDESC *, int )); void trc_reset_old_descriptors __ProtoGlarp__(( void )); void trc_set_didlist __ProtoGlarp__(( TRC_HOST, TRC_DID )); void trc_set_tevlist __ProtoGlarp__(( TRC_TEVTASK, TRC_HOST, TRC_TEVDESC )); void trc_set_tracing_codes __ProtoGlarp__(( TRC_ID )); void trc_status_msg __ProtoGlarp__(( TRC_ID, char * )); void trc_store_data_values __ProtoGlarp__(( TRC_ID, TRC_TEVDESC, int, int )); void trc_store_event_header __ProtoGlarp__(( TRC_ID, TRC_TEVDESC, int )); void trc_task_output __ProtoGlarp__(( TRC_ID, int, char * )); void trc_tracer_init __ProtoGlarp__(( void )); void trc_update_trace_time __ProtoGlarp__(( int, int )); void trc_write_host_add_event __ProtoGlarp__(( TRC_ID, TRC_HOST )); void trc_write_host_del_event __ProtoGlarp__(( TRC_ID, TRC_HOST, int )); void trc_write_host_sync_event __ProtoGlarp__(( TRC_ID, TRC_HOST )); void trc_write_old_host_add_event __ProtoGlarp__(( TRC_ID, TRC_HOST )); void trc_write_old_host_del_event __ProtoGlarp__(( TRC_ID, TRC_HOST, int )); void trc_write_old_host_sync_event __ProtoGlarp__(( TRC_ID, TRC_HOST )); void trc_write_old_output_event __ProtoGlarp__(( TRC_ID, int, char * )); void trc_write_output_event __ProtoGlarp__(( TRC_ID, int, char * )); char *trc_old_pvm_event_string __ProtoGlarp__(( TRC_ID, int )); char *trc_host_alias_str __ProtoGlarp__(( char * )); char *trc_tevrec_string __ProtoGlarp__(( TRC_TEVDESC, TRC_TEVREC, int, int, int )); char *trc_copy_str __ProtoGlarp__(( char * )); char *trc_date_str __ProtoGlarp__(( void )); char *trc_pad_num __ProtoGlarp__(( long, long )); int trc_add_tevdesc __ProtoGlarp__(( TRC_ID, TRC_TEVDESC *, int, int )); int trc_add_to_trie __ProtoGlarp__(( TRC_TRIE, char *, void * )); int trc_append_str __ProtoGlarp__(( char *, char *, int )); int trc_check_host_sync __ProtoGlarp__(( TRC_ID )); int trc_cmp_datadesc __ProtoGlarp__(( TRC_DATADESC, TRC_DATADESC )); int trc_cmp_did __ProtoGlarp__(( TRC_DID, TRC_DID )); int trc_cmp_tevdesc __ProtoGlarp__(( TRC_TEVDESC, TRC_TEVDESC )); int trc_compare __ProtoGlarp__(( char *, char * )); int trc_do_host_sync __ProtoGlarp__(( TRC_ID, TRC_HOST, int )); int trc_filecheck __ProtoGlarp__(( FILE *, char * )); int trc_find_event_end_ret __ProtoGlarp__(( TRC_ID, char *, int )); int trc_find_event_str_ret __ProtoGlarp__(( TRC_ID, char *, char *, int )); int trc_find_event_end __ProtoGlarp__(( TRC_ID )); int trc_find_event_str __ProtoGlarp__(( TRC_ID, char * )); int trc_free_tevdesc __ProtoGlarp__(( TRC_TEVDESC * )); int trc_get_dt_str __ProtoGlarp__(( char * )); int trc_get_msg __ProtoGlarp__(( TRC_ID, int *, int *, int *, int * )); int trc_handle_host_add_notify __ProtoGlarp__(( TRC_ID, int *, int )); int trc_handle_host_del_notify __ProtoGlarp__(( TRC_ID, int )); int trc_handle_output_message __ProtoGlarp__(( TRC_ID )); int trc_handle_trace_message __ProtoGlarp__(( TRC_ID, int )); int trc_open_output_file __ProtoGlarp__(( TRC_ID )); int trc_process_old_trace_event __ProtoGlarp__(( TRC_ID, char * )); int trc_process_trace_event __ProtoGlarp__(( TRC_ID, char *, int, int )); int trc_read_trace_event __ProtoGlarp__(( TRC_ID, int * )); int trc_read_old_trace_str __ProtoGlarp__(( TRC_ID, char *, int, int )); int trc_recv_messages __ProtoGlarp__(( TRC_ID, int, int * )); int trc_reset_trace_file __ProtoGlarp__(( TRC_ID )); int trc_save_host_status_events __ProtoGlarp__(( TRC_ID )); int trc_set_output_file __ProtoGlarp__(( TRC_ID, char * )); int trc_set_trace_file __ProtoGlarp__(( TRC_ID, char * )); int trc_store_old_trace_event __ProtoGlarp__(( TRC_ID, int, int, int, int )); int trc_store_trace_event __ProtoGlarp__(( TRC_ID, TRC_TEVDESC, int, int )); int trc_tevtasks_alive __ProtoGlarp__(( TRC_ID )); int trc_tevtasks_dead __ProtoGlarp__(( TRC_ID )); int trc_update_host __ProtoGlarp__(( TRC_HOST *, struct pvmhostinfo *, int, int )); ./pvm3/tracer/trctype.h0100644007401100000360000001214306446562372014242 0ustar kohlgopher /* $Id: trctype.h,v 4.3 1997/12/19 21:19:54 pvmsrc Exp $ */ /* * Tracer version 1.0: A Trace File Generator for PVM * Oak Ridge National Laboratory, Oak Ridge TN. * Authors: James Arthur Kohl and G. A. Geist * (C) 1994 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear * in supporting documentation. * * Neither the Institution, Oak Ridge National Laboratory, nor the * Authors make any representations about the suitability of this * software for any purpose. This software is provided ``as is'' * without express or implied warranty. * * Tracer was funded by the U.S. Department of Energy. */ /* Host Name Macros */ #define TRC_LOCALHOST( _name ) \ \ ( TRC_HOST_NAME != NULL && TRC_HOST_ALIAS != NULL \ && ( !strcmp( TRC_HOST_NAME, _name ) \ || !strcmp( TRC_HOST_ALIAS, _name ) \ || ( TRC_TMP_HOST = trc_host_alias_str( _name ), \ TRC_TMP_CMP = !strcmp( TRC_HOST_NAME, TRC_TMP_HOST ), \ free( TRC_TMP_HOST ), \ TRC_TMP_CMP ) ) ) \ \ #define TRC_HOST_COMPARE( _host, _name ) \ \ ( !strcmp( (_host)->name, _name ) \ || !strcmp( (_host)->alias, _name ) \ || ( TRC_TMP_HOST = trc_host_alias_str( _name ), \ TRC_TMP_CMP = !strcmp( (_host)->name, TRC_TMP_HOST ), \ free( TRC_TMP_HOST ), \ TRC_TMP_CMP ) ) \ \ /* Group Task Check Macro */ #define TRC_GROUPTASK( _name ) \ ( trc_compare( "pvmg", _name ) || trc_compare( "pvmcg", _name ) ) /* Trace Event Record Access Macros */ #define TRC_GET_TEVREC( _tr, _trptr, _did ) \ \ ( (_trptr) = trc_get_tevrec( _tr, _did ), \ (_trptr) != NULL ) \ \ #define TRC_GET_TEVREC_VALUE( _tr, _did, _dtype ) \ \ ( (TRC_TMP_TR = trc_get_tevrec( _tr, _did )) != NULL ? \ TRC_VALUE_OF( TRC_TMP_TR->value, _dtype ) : (_dtype) -1 ) \ \ #define TRC_ARR_VALUE_OF( _ptr, _dtype, _index ) \ ( ((_dtype *) (_ptr))[_index] ) #define TRC_VALUE_OF( _ptr, _dtype ) ( *( (_dtype *) (_ptr) ) ) /* Host Life Status Constants */ #define TRC_NOT_IN_PVM 0 #define TRC_IN_PVM 1 /* TEV Type Constants */ #define TRC_ENTRY_TEV 0 #define TRC_EXIT_TEV 1 #define TRC_IGNORE_TEV 2 #define TRC_MAX_TEV 3 /* Trace Message Status Constants */ #define TRC_MSG_STATUS_NONE 0 #define TRC_MSG_STATUS_ACTIVE 1 #define TRC_MSG_STATUS_MORE 2 #define TRC_MSG_STATUS_OVERWRITE 4 #define TRC_MSG_STATUS_CLEANUP 8 /* General Constants */ #define TRC_FALSE 0 #define TRC_TRUE 1 /* Tracer Data Structures & Types */ typedef void (*trc_vfp)(); struct trc_trie_struct { int valid; char *str; void *value; /* TRC_TRIE */ struct trc_trie_struct *next; }; typedef struct trc_trie_struct *TRC_TRIE; struct trc_did_struct { int id; char *name; char *desc; /* TRC_DID */ struct trc_did_struct *next; }; typedef struct trc_did_struct *TRC_DID; typedef void *TRC_VALUE; struct trc_datadesc_struct { TRC_DID did; int dt; int array; TRC_VALUE data; int num; /* TRC_DATADESC */ struct trc_datadesc_struct *next; }; typedef struct trc_datadesc_struct *TRC_DATADESC; struct trc_tevdesc_struct { char *name; int eid; int entry_exit; int index; int hid; int dump; TRC_DATADESC ddesc; int refcount; /* TRC_TEVDESC */ struct trc_tevdesc_struct *next; }; typedef struct trc_tevdesc_struct *TRC_TEVDESC; struct trc_tevdesc_info_struct { int id; int dt; int array; }; typedef struct trc_tevdesc_info_struct TRC_TEVDESC_INFO_STRUCT; typedef TRC_TEVDESC_INFO_STRUCT *TRC_TEVDESC_INFO; struct trc_tevtask_struct { int tid; int tevstatus; int outstatus; void **tevlist; int tevsize; char *output; /* TRC_TEVTASK */ struct trc_tevtask_struct *next; }; typedef struct trc_tevtask_struct *TRC_TEVTASK; struct trc_tevrec_struct { TRC_DATADESC ddesc; TRC_VALUE value; int num; /* TRC_TEVREC */ struct trc_tevrec_struct *next; }; typedef struct trc_tevrec_struct *TRC_TEVREC; struct trc_host_struct { char *name; char *alias; char *refname; char *arch; struct timeval delta; struct timeval last_time; int pvmd_tid; int speed; int in_pvm; /* Tracing Info */ void **tevlist; int tevsize; void **didlist; int didsize; /* Extension Structure for Drawing, Etc. */ void *ext; /* TRC_HOST */ struct trc_host_struct *next; }; typedef struct trc_host_struct *TRC_HOST; struct trc_id_struct { int complete; int group_tasks; int event_ctx; int event_tag; int output_ctx; int output_tag; TRC_TEVTASK tevtask_list; char *trace_file; FILE *trace_out; FILE *trace_in; char *output_file; FILE *output_fp; trc_vfp status_msg; trc_vfp event_dump_hdr; trc_vfp output_dump_hdr; trc_vfp handle_host_add_notify; trc_vfp handle_host_del_notify; trc_vfp handle_descriptor; trc_vfp handle_old_descriptor; trc_vfp handle_event; trc_vfp handle_old_event; trc_vfp handle_command; trc_vfp handle_comment; /* TRC_ID */ struct trc_id_struct *next; }; typedef struct trc_id_struct *TRC_ID; ./pvm3/tracer/OS2/0042755007401100000360000000000010117676455013004 5ustar kohlgopher./pvm3/tracer/OS2/Makefile0100644007401100000360000000053306401553370014427 0ustar kohlgopher# # $Id: Makefile,v 1.1 1997/08/29 14:04:40 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/tracer PVM_ARCH = OS2 CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) install: make LIBPREFIX="" -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install clean: make LIBPREFIX="" -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean ./pvm3/conf/0042755007401100000360000000000010117676455012046 5ustar kohlgopher./pvm3/conf/AFX8.def0100644007401100000360000000017306604766701013230 0ustar kohlgopherARCHCFLAGS = -DNOSTRCASE -DNOUNIXDOM ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t PVM_ARCH = AFX8 AR = ar MAKE = make ./pvm3/conf/AIX46K64.def0100644007401100000360000000046710001307370013563 0ustar kohlgopherARCHCFLAGS = -DSOCKLENISUINT -DSYSVSIGNAL \ -DRSHCOMMAND=\"/usr/bin/rsh\" -DSOCKADHASLEN \ -DNEEDSSELECTH \ -g -q64 -qmaxmem=-1 -qarch=ppc -DHASSTDLIB ARCHFFLAGS = -q64 ARCHDLIB = -lbsd ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar -X64 LOPT = -g -q64 PVM_ARCH = AIX46K64 NEEDF2M4 = t MAKE = make ./pvm3/conf/AIX46K.def0100644007401100000360000000033506604766701013430 0ustar kohlgopherARCHCFLAGS = -DSOCKLENISUINT -DSYSVSIGNAL \ -DRSHCOMMAND=\"/usr/bin/rsh\" -DSOCKADHASLEN \ -DNEEDSSELECTH ARCHDLIB = -lbsd ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = AIX46K NEEDF2M4 = t MAKE = make ./pvm3/conf/AIX4MP.def0100644007401100000360000000036306604766702013466 0ustar kohlgopherARCHCFLAGS = -DSOCKLENISUINT -DSYSVSIGNAL -DNOUNIXDOM -D_BSD \ -DRSHCOMMAND=\"/usr/bin/rsh\" -DNEEDSSELECTH -DSHMEM ARCHDLIB = -lbsd -lpthreads ARCHDOBJ = ARCHLIB = -lbsd -lpthreads HASRANLIB = t PVM_ARCH = AIX4MP AR = ar MAKE = make ./pvm3/conf/AIX4SP2.def0100644007401100000360000000040007240566201013533 0ustar kohlgopherARCHCFLAGS = -DSOCKLENISUINT -DSYSVSIGNAL -DNOUNIXDOM -DNEEDSSELECTH ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t PVM_ARCH = AIX4SP2 AR_FRONT = ar AR_NODE = ar AR = ar CC = cc NODECC = mpcc NEEDF2M4 = t FORTRAN = f77 NODEFORT = mpxlf MAKE = make ./pvm3/conf/AIX56K64.def0100644007401100000360000000047010001307370013556 0ustar kohlgopherARCHCFLAGS = -DSOCKLENISUINT -DSYSVSIGNAL \ -DRSHCOMMAND=\"/usr/bin/rsh\" -DSOCKADHASLEN \ -DNEEDSSELECTH \ -g -q64 -qmaxmem=-1 -qarch=pwr3 -DHASSTDLIB ARCHFFLAGS = -q64 ARCHDLIB = -lbsd ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar -X64 LOPT = -g -q64 PVM_ARCH = AIX56K64 NEEDF2M4 = t MAKE = make ./pvm3/conf/AIX56K.def0100644007401100000360000000033510001307371013405 0ustar kohlgopherARCHCFLAGS = -DSOCKLENISUINT -DSYSVSIGNAL \ -DRSHCOMMAND=\"/usr/bin/rsh\" -DSOCKADHASLEN \ -DNEEDSSELECTH ARCHDLIB = -lbsd ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = AIX56K NEEDF2M4 = t MAKE = make ./pvm3/conf/AIX5MP.def0100644007401100000360000000036310001307372013443 0ustar kohlgopherARCHCFLAGS = -DSOCKLENISUINT -DSYSVSIGNAL -DNOUNIXDOM -D_BSD \ -DRSHCOMMAND=\"/usr/bin/rsh\" -DNEEDSSELECTH -DSHMEM ARCHDLIB = -lbsd -lpthreads ARCHDOBJ = ARCHLIB = -lbsd -lpthreads HASRANLIB = t PVM_ARCH = AIX5MP AR = ar MAKE = make ./pvm3/conf/AIX5SP2.def0100644007401100000360000000040010001307372013523 0ustar kohlgopherARCHCFLAGS = -DSOCKLENISUINT -DSYSVSIGNAL -DNOUNIXDOM -DNEEDSSELECTH ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t PVM_ARCH = AIX5SP2 AR_FRONT = ar AR_NODE = ar AR = ar CC = cc NODECC = mpcc NEEDF2M4 = t FORTRAN = f77 NODEFORT = mpxlf MAKE = make ./pvm3/conf/ALPHA.def0100644007401100000360000000076407240075023013340 0ustar kohlgopher# # Note: The -DCTIMEISTIMET flag in the ARCHCFLAGS definition may not # be required on all Alpha systems... # # Similarly, to fix an XDR bug on some Alpha systems, add the # -DUSE_XDR_LONGLONG flag to ARCHCFLAGS... # ARCHCFLAGS = -DHASSTDLIB -DCTIMEISTIMET #ARCHCFLAGS = -DHASSTDLIB -DCTIMEISTIMET -DUSE_XDR_LONGLONG ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t PVM_ARCH = ALPHA AR = ar # PVMDEPPATH Not Needed on *All* DEC Alpha Systems #PVMDEPPATH = PVMDEPPATH = ALPHA/ MAKE = make ./pvm3/conf/ALPHAMP.def0100644007401100000360000000054507044071700013572 0ustar kohlgopher# # Note: The -DCTIMEISTIMET flag in the ARCHCFLAGS definition may not # be required on all Alpha systems... # ARCHCFLAGS = -DHASSTDLIB -DNOUNIXDOM -DSHMEM -DCTIMEISTIMET ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = ALPHAMP # PVMDEPPATH Not Needed on *All* DEC Alpha Systems #PVMDEPPATH = PVMDEPPATH = ALPHAMP/ MAKE = make ./pvm3/conf/APOLLO.def0100644007401100000360000000026106604766705013512 0ustar kohlgopherARCHCFLAGS = -DSYSVSIGNAL -DNOWAIT3 -DNOGETDTBLSIZ \ -DRSHCOMMAND=\"/usr/bin/remsh\" ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = f AR = ar PVM_ARCH = APOLLO MAKE = make ./pvm3/conf/ATT.def0100644007401100000360000000046606604766705013163 0ustar kohlgopherARCHCFLAGS = -DHASSTDLIB -DNOUNIXDOM -DNOGETDTBLSIZ -DNOWAIT3 \ -DRSHCOMMAND=\"/usr/bin/remsh\" -DSYSVBFUNC \ -DSYSVSIGNAL -DSYSVSTR -DNEEDSENDIAN ARCHDLIB = -lnsl -lsocket -L/usr/ucblib -lucb ARCHDOBJ = ARCHLIB = -lnsl -lsocket -L/usr/ucblib -lucb HASRANLIB = f AR = ar PVM_ARCH = ATT MAKE = make ./pvm3/conf/BAL.def0100644007401100000360000000015606604766706013126 0ustar kohlgopherARCHCFLAGS = -DNOUNIXDOM ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = BAL MAKE = make ./pvm3/conf/BEOLIN.def0100644007401100000360000000055007053052665013465 0ustar kohlgopherARCHCFLAGS = -DSYSVSIGNAL -DNOWAIT3 -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DNEEDENDIAN -DFDSETNOTSTRUCT -DHASERRORVARS \ -DCTIMEISTIMET -DSYSERRISCONST -DNOTMPNAM \ -DNOUNIXDOM -DNOPROT ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t PVM_ARCH = LINUX AR_FRONT = ar AR_NODE = ar AR = ar CC = cc NODECC = cc FORTRAN = f77 NODEFORT = f77 MAKE = make ./pvm3/conf/BEOSCYLD.def0100644007401100000360000000117307354714344013726 0ustar kohlgopher# # Notes on readline Usage: # # If your Linux system has readline, then you may append the # following flags to the defines below: # # ARCHCFLAGS = . . . -DHASREADLINE # ARCHLIB = . . . -lreadline # # and recompile PVM. # # On some Linux systems, readline requires ncurses, so you # must also add "-lncurses" to the ARCHLIB define. # ARCHCFLAGS = -DSYSVSIGNAL -DNOWAIT3 -DRSHCOMMAND=\"/usr/bin/bpsh\" \ -DNEEDENDIAN -DFDSETNOTSTRUCT -DHASERRORVARS \ -DCTIMEISTIMET -DSYSERRISCONST -DNOTMPNAM ARCHDLIB = /usr/lib/libbproc.a ARCHDOBJ = ARCHLIB = /usr/lib/libbproc.a HASRANLIB = t AR = ar PVM_ARCH = BEOSCYLD MAKE = make ./pvm3/conf/BFLY.def0100644007401100000360000000015706604766707013266 0ustar kohlgopherARCHCFLAGS = -DNOUNIXDOM ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = BFLY MAKE = make ./pvm3/conf/BSD386.def0100644007401100000360000000032206606706522013364 0ustar kohlgopherARCHCFLAGS = -DSOCKADHASLEN -DNOREXEC -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DHASSTDLIB -DNEEDMENDIAN -DHASERRORVARS ARCHDLIB = ARCHDOBJ = ARCHLIB = -lrpc HASRANLIB = t AR = ar PVM_ARCH = BSD386 MAKE = gmake ./pvm3/conf/CNVX.def0100644007401100000360000000021406604766720013275 0ustar kohlgopherARCHCFLAGS = -no -fi -DNOUNIXDOM ARCHFFLAGS = -no -fi ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = CNVX MAKE = make ./pvm3/conf/CNVXN.def0100644007401100000360000000016006604766721013414 0ustar kohlgopherARCHCFLAGS = -DNOUNIXDOM ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = CNVXN MAKE = make ./pvm3/conf/CRAY2.def0100644007401100000360000000023306604766722013342 0ustar kohlgopherARCHCFLAGS = -DSYSVSIGNAL -DNOWAIT3 -DRSHCOMMAND=\"/usr/ucb/remsh\" ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = f AR = ar PVM_ARCH = CRAY2 MAKE = make ./pvm3/conf/CRAY.def0100644007401100000360000000023206604766721013256 0ustar kohlgopherARCHCFLAGS = -DSYSVSIGNAL -DNOWAIT3 -DRSHCOMMAND=\"/usr/ucb/remsh\" ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = f AR = ar PVM_ARCH = CRAY MAKE = make ./pvm3/conf/CRAYSMP.def0100644007401100000360000000014606604766722013643 0ustar kohlgopherARCHCFLAGS = ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = CRAYSMP MAKE = make ./pvm3/conf/CSPP.def0100644007401100000360000000367706604766723013307 0ustar kohlgopher# NOTES: # # 1 - When building with the HP compilers or GNU compilers, make sure # that /bin appears in the PATH environment varaible before the # Convex compilers or loader (e.g. /usr/convex/bin). Otherwise # the Convex compiler will be used and an incompatible crt0.o # will be used to link the executables, resulting in unresolved # symbols. # # 2 - When building with the Convex compilers be sure that # /usr/convex/bin appears before /bin in the PATH environment # variable. # # 3 - When compiling on an HP workstation for an Exemplar target using # the Convex compilers, use the '-Wl,+tmspp1' flag to tell the # compiler to use the Exemplar instruction set. The HP # workstation being used for the build will also require # /lib/libcnx_syscall.a and /lib/libail.sl files to be installed # from an Exemplar. # # 4 - When building libraries with the Convex C compiler that must be # compatible with GNU C and HP C objects, compile with the # -U_REENTRANT flag. This turns off the multi-threading of # 'errno'. # # # --------------------- Build with GNU C ----------------------- #CC = gcc -g #F77 = fort77 #FFLAGS = -g # --------------------- Build with Convex C ------------------- #CC = /opt/ansic/bin/cc #C_OPT = -U_REENTRANT +DA1.1 +DS1.1 -Wl,+tm,hpux #F77 = /opt/fortran/bin/f77 #AS = /usr/ccs/bin/as # --------------------- Standard Stuff ------------------------------ ARCHCFLAGS = $(C_OPT) -DSHMEM -DSYSVSIGNAL -DNOWAIT3 -DNOGETDTBLSIZ \ -DRSHCOMMAND=\"/usr/bin/remsh\" -DNOUNIXDOM \ -DCLUMP_ALLOC -DHASSTDLIB -DSUBCOMPLEX_SUPPORT \ -DFDSETISINT -DBALANCED_SPAWN ARCHOBJ = -lcnx_syscall /lib/libail.sl ARCHDOBJ = ARCHDLIB = $(ARCHOBJ) ARCHLIB = $(ARCHLDFLAGS) $(ARCHOBJ) ARCHFLIB = $(ARCHLDFFLAGS) $(ARCHOBJ) HASRANLIB = f LD = $(CC) PVM_ARCH = CSPP #AR = /usr/bin/ar AR = ar LOPT = -Wl,-aarchive NEEDF2M4 = t AMEMOBJ = amem.o MAKE = make ./pvm3/conf/CYGWIN.def0100644007401100000360000000073507337303752013523 0ustar kohlgopherARCHCFLAGS = -DCYGWIN -DHASSTDLIB -DSYSVSTR -DSYSVSIGNAL \ -DNOTMPNAM -DHASREADLINE -DFDSETNOTSTRUCT -DNOUNIXDOM \ -DSTDC_HEADERS -DARCHCLASS=\"WIN32\" \ -DRSHCOMMAND=\"rsh\" -DNEEDSFFS -DSYSVBFUNC -DNOWAIT3 \ -DNOGETDTBLSIZ -DNOREXEC -DNO_NETINET_TCP_H \ -DUSESTRERROR -I/usr/local/include ARCHDLIB = -L/usr/local/lib -lrpclib ARCHDOBJ = ARCHLIB = -L/usr/local/lib -lrpclib HASRANLIB = t AR = ar PVM_ARCH = CYGWIN MAKE = make EXESFX = .exe FC = g77 ./pvm3/conf/DARWIN.def0100644007401100000360000000057010106413556013474 0ustar kohlgopherARCHCFLAGS = -DSOCKADHASLEN -DNOREXEC \ -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DHASSTDLIB -DNEEDMENDIAN -DHASERRORVARS \ -DFAKEXDRFLOAT -DSYSERRISCONST \ -I/usr/include/malloc \ -I/System/Library/Frameworks/System.framework/Headers/bsd/sys # this last -I flag needed for tracer build... ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = DARWIN MAKE = make ./pvm3/conf/DGAV.def0100644007401100000360000000030206604766724013242 0ustar kohlgopherARCHCFLAGS = -DNOSTRCASE -DSYSVSIGNAL -DNOWAIT3 -DSYSVSTR \ -DRSHCOMMAND=\"/usr/ucb/remsh\" -DNOUNIXDOM ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = f AR = ar PVM_ARCH = DGAV MAKE = make ./pvm3/conf/DGIX.def0100644007401100000360000000035006740730161013242 0ustar kohlgopherARCHCFLAGS = -DNOSTRCASE -DSYSVSIGNAL -DNOWAIT3 -DSYSVSTR \ -DRSHCOMMAND=\"/usr/bin/rsh\" -DNOUNIXDOM ARCHDLIB = -lnsl -lsocket ARCHDOBJ = ARCHLIB = -lnsl -lsocket HASRANLIB = f AR = ar PVM_ARCH = DGIX MAKE = make ./pvm3/conf/E88K.def0100644007401100000360000000020506604766724013202 0ustar kohlgopherARCHCFLAGS = -DNOUNIXDOM -DNET_IF_IN_SYS ARCHDLIB = ARCHDOBJ = ARCHLIB = -lrpc HASRANLIB = f AR = ar PVM_ARCH = E88K MAKE = make ./pvm3/conf/FREEBSD.def0100644007401100000360000000037206604766725013603 0ustar kohlgopherARCHCFLAGS = -DSOCKADHASLEN -DNOREXEC -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DHASSTDLIB -DNEEDMENDIAN -DHASERRORVARS \ -DFAKEXDRFLOAT -DSYSERRISCONST ARCHDLIB = ARCHDOBJ = ARCHLIB = -lrpcsvc HASRANLIB = t AR = ar PVM_ARCH = FREEBSD MAKE = make ./pvm3/conf/HP300.def0100644007401100000360000000026006604766741013255 0ustar kohlgopherARCHCFLAGS = -DSYSVSIGNAL -DNOWAIT3 -DNOGETDTBLSIZ \ -DRSHCOMMAND=\"/usr/bin/remsh\" ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = f AR = ar PVM_ARCH = HP300 MAKE = make ./pvm3/conf/HPPA.def0100644007401100000360000000152607300024306013233 0ustar kohlgopher# --------------------- Build with HP C ------------------- #CC = /opt/ansic/bin/cc #C_OPT = -U_REENTRANT +DA1.1 +DS1.1 -Wl,+tm,hpux #F77 = /opt/fortran/bin/f77 #AS = /usr/ccs/bin/as # --------------------- Standard Stuff ------------------------ ARCHCFLAGS = -DSYSVSIGNAL -DNOWAIT3 -DNOGETDTBLSIZ \ -DRSHCOMMAND=\"/usr/bin/remsh\" -DFDSETISINT # remove -DFDSETISINT above for HP-UX 11.0...? # replace -DFDSETISINT with -DFDSETNOTSTRUCT for HP-UX 10.20... ARCHDLIB = # ARCHDLIB = -lnsl -ldld # for HP-UX 11.0 ARCHDOBJ = ARCHLIB = # ARCHLIB = -lnsl -ldld # for HP-UX 11.0 HASRANLIB = f PVM_ARCH = HPPA FC = fort77 #AR = /usr/bin/ar AR = ar LOPT = -Wl,-aarchive # LOPT = -Wl,-ashared # for HP-UX 11.0 # LOPT = -Wl,-adefault # alternate, for HP-UX 11.0 # LOPT = -Wl,-ashared_archive # for HP-UX B.11.00 A 9000/785 NEEDF2M4 = t MAKE = make ./pvm3/conf/HPPAMP.def0100644007401100000360000000124007004131154013462 0ustar kohlgopher# --------------------- Build with HP C ------------------- #CC = /opt/ansic/bin/cc #C_OPT = -U_REENTRANT +DA1.1 +DS1.1 -Wl,+tm,hpux #F77 = /opt/fortran/bin/f77 #AS = /usr/ccs/bin/as # --------------------- Standard Stuff --------------------------------- ARCHCFLAGS = -DSHMEM -DSYSVSIGNAL -DNOWAIT3 -DNOGETDTBLSIZ \ -DRSHCOMMAND=\"/usr/bin/remsh\" -DNOUNIXDOM \ -DCLUMP_ALLOC -DHASSTDLIB -DFDSETISINT # remove -DFDSETISINT above for HP-UX 11.0...? ARCHDLIB = # ARCHDLIB = -lnsl # for HP-UX 11.0 ARCHDOBJ = # ARCHLIB = -lnsl # for HP-UX 11.0 HASRANLIB = f PVM_ARCH = HPPAMP #AR = /usr/bin/ar AR = ar FC = fort77 NEEDF2M4 = t AMEMOBJ = amem.o MAKE = make ./pvm3/conf/IPSC2.def0100644007401100000360000000032406604766743013346 0ustar kohlgopherARCHCFLAGS = -DSYSVSIGNAL -DNOWAIT3 -DNOWAITPID -DSYSVSTR \ -DRSHCOMMAND=\"/usr/ucb/rcmd\" -DNOUNIXDOM ARCHDLIB = -lsocket ARCHDOBJ = ARCHLIB = -lsocket HASRANLIB = f AR = ar PVM_ARCH = IPSC2 MAKE = make ./pvm3/conf/LINUX64.def0100644007401100000360000000174507354447043013577 0ustar kohlgopher# # Notes on readline Usage: # # If your Linux system has readline, then you may append the # following flags to the defines below: # # ARCHCFLAGS = . . . -DHASREADLINE # ARCHLIB = . . . -lreadline # # and recompile PVM. # # On some Linux systems, readline requires ncurses, so you # must also add "-lncurses" to the ARCHLIB define. # # Add define of HASSTDLIB for LINUX64 (copied from the LINUX template) # new definitions to allow, at least, "malloc.h" heder file include # and thus not generate 32-bits truncating (thru "sxt4" assembly # instruction ...) code, leading to Linux64 Virtual Memory addresses # to be corrupted ("segments" bits are located in the highest weighted # word/bits !!), on IA-64/Linux64 platforms. # ARCHCFLAGS = -DSYSVSIGNAL -DNOWAIT3 -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DNEEDENDIAN -DFDSETNOTSTRUCT -DHASERRORVARS \ -DHASSTDLIB -DCTIMEISTIMET -DSYSERRISCONST -DNOTMPNAM ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = LINUX64 MAKE = make ./pvm3/conf/LINUXALPHA.def0100644007401100000360000000117707354447043014172 0ustar kohlgopher# # Notes on readline Usage: # # If your Linux system has readline, then you may append the # following flags to the defines below: # # ARCHCFLAGS = . . . -DHASREADLINE # ARCHLIB = . . . -lreadline # # and recompile PVM. # # On some Linux systems, readline requires ncurses, so you # must also add "-lncurses" to the ARCHLIB define. # ARCHCFLAGS = -DNOWAIT3 -DNOUNIXDOM -DCTIMEISTIMET -DSYSERRISCONST \ -DRSHCOMMAND=\"/usr/bin/rsh\" -DNEEDENDIAN \ -DHASSTDLIB -DSYSVSTR -DHASERRORVARS -DFDSETNOTSTRUCT \ -DSOCKLENISUINT -DNOTMPNAM ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = LINUXALPHA MAKE = make ./pvm3/conf/LINUXARM.def0100644007401100000360000000112207354447044013753 0ustar kohlgopher# # Notes on readline Usage: # # If your Linux system has readline, then you may append the # following flags to the defines below: # # ARCHCFLAGS = . . . -DHASREADLINE # ARCHLIB = . . . -lreadline # # and recompile PVM. # # On some Linux systems, readline requires ncurses, so you # must also add "-lncurses" to the ARCHLIB define. # ARCHCFLAGS = -DSYSVSIGNAL -DNOWAIT3 -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DNEEDENDIAN -DFDSETNOTSTRUCT -DHASERRORVARS \ -DCTIMEISTIMET -DSYSERRISCONST -DNOTMPNAM ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = LINUXARM MAKE = make ./pvm3/conf/LINUXATARI.def0100644007401100000360000000104107354447044014174 0ustar kohlgopher# # Notes on readline Usage: # # If your Linux system has readline, then you may append the # following flags to the defines below: # # ARCHCFLAGS = . . . -DHASREADLINE # ARCHLIB = . . . -lreadline # # and recompile PVM. # # On some Linux systems, readline requires ncurses, so you # must also add "-lncurses" to the ARCHLIB define. # ARCHCFLAGS = -DRSHCOMMAND=\"/usr/bin/rsh\" -DNEEDENDIAN \ -DHASERRORVARS -DSYSERRISCONST -DNOREXEC -DNOTMPNAM ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = LINUXATARI MAKE = make ./pvm3/conf/LINUX.def0100644007401100000360000000133607722441561013417 0ustar kohlgopher# # Notes on readline Usage: # # If your Linux system has readline, then you may append the # following flags to the defines below: # # ARCHCFLAGS = . . . -DHASREADLINE # ARCHLIB = . . . -lreadline # # and recompile PVM. # # On some Linux systems, readline requires ncurses, so you # must also add "-lncurses" to the ARCHLIB define. # ARCHCFLAGS = -DSYSVSIGNAL -DNOWAIT3 -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DNEEDENDIAN -DFDSETNOTSTRUCT -DHASERRORVARS \ -DCTIMEISTIMET -DSYSERRISCONST -DNOTMPNAM -DUSESTRERROR # # For Absoft Fortran 95 Compiler: # ARCHFFLAGS = -B108 -YEXT_NAMES="LCS" # (submitted by Reggie Chang ) # ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = LINUX MAKE = make ./pvm3/conf/LINUXHPPA.def0100644007401100000360000000112307354447044014065 0ustar kohlgopher# # Notes on readline Usage: # # If your Linux system has readline, then you may append the # following flags to the defines below: # # ARCHCFLAGS = . . . -DHASREADLINE # ARCHLIB = . . . -lreadline # # and recompile PVM. # # On some Linux systems, readline requires ncurses, so you # must also add "-lncurses" to the ARCHLIB define. # ARCHCFLAGS = -DSYSVSIGNAL -DNOWAIT3 -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DNEEDENDIAN -DFDSETNOTSTRUCT -DHASERRORVARS \ -DCTIMEISTIMET -DSYSERRISCONST -DNOTMPNAM ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = LINUXHPPA MAKE = make ./pvm3/conf/LINUXPPC.def0100644007401100000360000000102607354447044013761 0ustar kohlgopher# # Notes on readline Usage: # # If your Linux system has readline, then you may append the # following flags to the defines below: # # ARCHCFLAGS = . . . -DHASREADLINE # ARCHLIB = . . . -lreadline # # and recompile PVM. # # On some Linux systems, readline requires ncurses, so you # must also add "-lncurses" to the ARCHLIB define. # ARCHCFLAGS = -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DNEEDENDIAN -DFDSETNOTSTRUCT -DHASERRORVARS -DNOTMPNAM ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = LINUXPPC MAKE = make ./pvm3/conf/LINUXSPARC.def0100644007401100000360000000110407354447044014204 0ustar kohlgopher# # Notes on readline Usage: # # If your Linux system has readline, then you may append the # following flags to the defines below: # # ARCHCFLAGS = . . . -DHASREADLINE # ARCHLIB = . . . -lreadline # # and recompile PVM. # # On some Linux systems, readline requires ncurses, so you # must also add "-lncurses" to the ARCHLIB define. # ARCHCFLAGS = -DSYSVSIGNAL -DNOWAIT3 -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DNEEDENDIAN -DCTIMEISTIMET -DFDSETNOTSTRUCT \ -DHASERRORVARS -DNOTMPNAM ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = LINUXSPARC MAKE = make ./pvm3/conf/M88K.def0100644007401100000360000000031506604766747013221 0ustar kohlgopherARCHCFLAGS = -DNEEDSFFS -DNOUNIXDOM -DNOWAIT3 -DSHAREDTMP \ -DSTATISTICS -DNOGETDTBLSIZ -DREALIX -DMAXPATHLEN=1024 ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = f AR = ar PVM_ARCH = M88K MAKE = make ./pvm3/conf/MACOSX.def0100644007401100000360000000030007277053522013501 0ustar kohlgopherARCHCFLAGS = -DHASERRORVARS -DSYSERRISCONST -DNOREXEC \ -DRSHCOMMAND=\"/usr/bin/rsh\" ARCHDLIB = ARCHDOBJS = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = MACOSX MAKE = make CC = cc ./pvm3/conf/MASPAR.def0100644007401100000360000000014506604766757013517 0ustar kohlgopherARCHCFLAGS = ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = MASPAR MAKE = make ./pvm3/conf/MIPS.def0100644007401100000360000000027506604766760013302 0ustar kohlgopherARCHCFLAGS = -I/usr/include/bsd -DSYSVSIGNAL -DNOWAIT3 ARCHDLIB = -lrpcsvc -lsun -lbsd -lgen ARCHDOBJ = ARCHLIB = -lrpcsvc -lsun -lbsd HASRANLIB = t AR = ar PVM_ARCH = MIPS MAKE = make ./pvm3/conf/NETBSDALPHA.def0100644007401100000360000000034307052612130014226 0ustar kohlgopherARCHCFLAGS = -DSOCKADHASLEN -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DHASERRORVARS -DNOREXEC -DNEEDMENDIAN -DSYSERRISCONST ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = NETBSDALPHA MAKE = make #MAKE = gmake ./pvm3/conf/NETBSDAMIGA.def0100644007401100000360000000041707052611773014235 0ustar kohlgopher# Warning: Now Subsumed By NETBSDM68K arch. ARCHCFLAGS = -DSOCKADHASLEN -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DHASERRORVARS -DNOREXEC -DNEEDMENDIAN -DSYSERRISCONST ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = NETBSDAMIGA MAKE = make #MAKE = gmake ./pvm3/conf/NETBSDARM32.def0100644007401100000360000000034307052612131014166 0ustar kohlgopherARCHCFLAGS = -DSOCKADHASLEN -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DHASERRORVARS -DNOREXEC -DNEEDMENDIAN -DSYSERRISCONST ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = NETBSDARM32 MAKE = make #MAKE = gmake ./pvm3/conf/NETBSDHP300.def0100644007401100000360000000041707052611774014152 0ustar kohlgopher# Warning: Now Subsumed By NETBSDM68K arch. ARCHCFLAGS = -DSOCKADHASLEN -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DHASERRORVARS -DNOREXEC -DNEEDMENDIAN -DSYSERRISCONST ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = NETBSDHP300 MAKE = make #MAKE = gmake ./pvm3/conf/NETBSDI386.def0100644007401100000360000000034207052611774014046 0ustar kohlgopherARCHCFLAGS = -DSOCKADHASLEN -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DHASERRORVARS -DNOREXEC -DNEEDMENDIAN -DSYSERRISCONST ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = NETBSDI386 MAKE = make #MAKE = gmake ./pvm3/conf/NETBSDM68K.def0100644007401100000360000000034207052612132014067 0ustar kohlgopherARCHCFLAGS = -DSOCKADHASLEN -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DHASERRORVARS -DNOREXEC -DNEEDMENDIAN -DSYSERRISCONST ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = NETBSDM68K MAKE = make #MAKE = gmake ./pvm3/conf/NETBSDMAC68K.def0100644007401100000360000000042007052611774014303 0ustar kohlgopher# Warning: Now Subsumed By NETBSDM68K arch. ARCHCFLAGS = -DSOCKADHASLEN -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DHASERRORVARS -DNOREXEC -DNEEDMENDIAN -DSYSERRISCONST ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = NETBSDMAC68K MAKE = make #MAKE = gmake ./pvm3/conf/NETBSDMIPSEB.def0100644007401100000360000000034407052612134014365 0ustar kohlgopherARCHCFLAGS = -DSOCKADHASLEN -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DHASERRORVARS -DNOREXEC -DNEEDMENDIAN -DSYSERRISCONST ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = NETBSDMIPSEB MAKE = make #MAKE = gmake ./pvm3/conf/NETBSDMIPSEL.def0100644007401100000360000000034407052612137014402 0ustar kohlgopherARCHCFLAGS = -DSOCKADHASLEN -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DHASERRORVARS -DNOREXEC -DNEEDMENDIAN -DSYSERRISCONST ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = NETBSDMIPSEL MAKE = make #MAKE = gmake ./pvm3/conf/NETBSDNS32K.def0100644007401100000360000000034307052612146014210 0ustar kohlgopherARCHCFLAGS = -DSOCKADHASLEN -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DHASERRORVARS -DNOREXEC -DNEEDMENDIAN -DSYSERRISCONST ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = NETBSDNS32K MAKE = make #MAKE = gmake ./pvm3/conf/NETBSDPMAX.def0100644007401100000360000000042007052611774014157 0ustar kohlgopher# Warning: Now Subsumed By NETBSDMIPSEL arch. ARCHCFLAGS = -DSOCKADHASLEN -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DHASERRORVARS -DNOREXEC -DNEEDMENDIAN -DSYSERRISCONST ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = NETBSDPMAX MAKE = make #MAKE = gmake ./pvm3/conf/NETBSDPOWERPC.def0100644007401100000360000000034507052612151014525 0ustar kohlgopherARCHCFLAGS = -DSOCKADHASLEN -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DHASERRORVARS -DNOREXEC -DNEEDMENDIAN -DSYSERRISCONST ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = NETBSDPOWERPC MAKE = make #MAKE = gmake ./pvm3/conf/NETBSDSH3.def0100644007401100000360000000034107052612212013775 0ustar kohlgopherARCHCFLAGS = -DSOCKADHASLEN -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DHASERRORVARS -DNOREXEC -DNEEDMENDIAN -DSYSERRISCONST ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = NETBSDSH3 MAKE = make #MAKE = gmake ./pvm3/conf/NETBSDSPARC64.def0100644007401100000360000000034507052612213014427 0ustar kohlgopherARCHCFLAGS = -DSOCKADHASLEN -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DHASERRORVARS -DNOREXEC -DNEEDMENDIAN -DSYSERRISCONST ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = NETBSDSPARC64 MAKE = make #MAKE = gmake ./pvm3/conf/NETBSDSPARC.def0100644007401100000360000000052207052611775014266 0ustar kohlgopher# # Note: some versions of NetBSD for Sparc may require the # -DNEEDMENDIAN flag in the ARCHCFLAGS definition. # ARCHCFLAGS = -DSOCKADHASLEN -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DHASERRORVARS -DNOREXEC -DSYSERRISCONST ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = NETBSDSPARC MAKE = make #MAKE = gmake ./pvm3/conf/NETBSDSUN3.def0100644007401100000360000000041607052611775014150 0ustar kohlgopher# Warning: Now Subsumed By NETBSDM68K arch. ARCHCFLAGS = -DSOCKADHASLEN -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DHASERRORVARS -DNOREXEC -DNEEDMENDIAN -DSYSERRISCONST ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = NETBSDSUN3 MAKE = make #MAKE = gmake ./pvm3/conf/NETBSDVAX.def0100644007401100000360000000034107052612214014040 0ustar kohlgopherARCHCFLAGS = -DSOCKADHASLEN -DRSHCOMMAND=\"/usr/bin/rsh\" \ -DHASERRORVARS -DNOREXEC -DNEEDMENDIAN -DSYSERRISCONST ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = NETBSDVAX MAKE = make #MAKE = gmake ./pvm3/conf/NEXT.def0100644007401100000360000000015706604766765013314 0ustar kohlgopherARCHCFLAGS = -DNOTMPNAM ARCHDLIB = ARCHDOBJS = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = NEXT MAKE = make ./pvm3/conf/OS2.def0100644007401100000360000000067006604766773013140 0ustar kohlgopherARCHCFLAGS = -D__ST_MT_ERRNO__ -Zsysv-signals -DSYSVSIGNAL \ -DHASERRORVARS -DNEEDMENDIAN -DHASSTDLIB -DSYSVSTR \ -DNOGETDTBLSIZ -DNOTMPNAM -DNOWAIT3 -DNOUNIXDOM \ -DNOSOCKOPT -DNOWAITPID -DRSHCOMMAND=\"rsh\" \ -DMAXHOSTNAMELEN=256 -DFAKEXDRFLOAT -DFDSETNOTSTRUCT \ -DSYSERRISCONST ARCHDLIB = -lsocket -lrpc ARCHDOBJ = ARCHLIB = -lsocket -lrpc HASRANLIB = f PVM_ARCH = OS2 EXESFX = .exe CC = gcc MAKE = make ./pvm3/conf/PGON.def0100644007401100000360000000040106604766774013271 0ustar kohlgopherARCHCFLAGS = -DNOWAIT3 -DNOUNIXDOM ARCHDLIB = -lrpc -lnx ARCHDOBJ = ARCHLIB = -lrpc -lnx HASRANLIB = f PVM_ARCH = PGON AR_FRONT = ar860 AR_NODE = ar860 AR = ar860 CC = icc NODECC = icc FORTRAN = if77 NODEFORT = if77 PVMDEPPATH = PGON/ MAKE = make ./pvm3/conf/PMAX.def0100644007401100000360000000014306604766775013277 0ustar kohlgopherARCHCFLAGS = ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = PMAX MAKE = make ./pvm3/conf/RS6K.def0100644007401100000360000000033306604766775013260 0ustar kohlgopherARCHCFLAGS = -DSOCKLENISUINT -DSYSVSIGNAL \ -DRSHCOMMAND=\"/usr/bin/rsh\" -DSOCKADHASLEN \ -DNEEDSSELECTH ARCHDLIB = -lbsd ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = RS6K NEEDF2M4 = t MAKE = make ./pvm3/conf/RS6KMP.def0100644007401100000360000000041006604766776013512 0ustar kohlgopherARCHCFLAGS = -DSOCKLENISUINT -DSYSVSIGNAL -DNOUNIXDOM -D_BSD \ -DRSHCOMMAND=\"/usr/bin/rsh\" -DSOCKADHASLEN \ -DNEEDSSELECTH -DSHMEM ARCHDLIB = -lbsd -lpthreads ARCHDOBJ = ARCHLIB = -lbsd -lpthreads HASRANLIB = t AR = ar PVM_ARCH = RS6KMP MAKE = make ./pvm3/conf/RT.def0100644007401100000360000000014106604766777013057 0ustar kohlgopherARCHCFLAGS = ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = RT MAKE = make ./pvm3/conf/SCO.def0100644007401100000360000000036706604766777013170 0ustar kohlgopherARCHCFLAGS = -DSYSVSTR -DSYSVSIGNAL -DNOUNIXDOM \ -DRSHCOMMAND=\"/usr/bin/rcmd\" -DNEEDSFFS \ -DSYSVBFUNC -DNOWAIT3 -DNOGETDTBLSIZ ARCHDLIB = -lsocket ARCHDOBJ = ARCHLIB = -lrpc -lsocket HASRANLIB = AR = ar PVM_ARCH = SCO MAKE = make ./pvm3/conf/SGI5.def0100644007401100000360000000024406604767001013222 0ustar kohlgopherARCHCFLAGS = -DSYSVSIGNAL -DRSHCOMMAND=\"/usr/bsd/rsh\" -DNOWAIT3 ARCHDLIB = -lsun ARCHDOBJ = ARCHLIB = -lsun HASRANLIB = f AR = ar PVM_ARCH = SGI5 MAKE = make ./pvm3/conf/SGI64.def0100644007401100000360000000034706604767010013313 0ustar kohlgopherARCHCFLAGS = -DSYSVSIGNAL -DRSHCOMMAND=\"/usr/bsd/rsh\" -DNOWAIT3 \ -64 -woff 1174 -DHASSTDLIB -DCTIMEISTIMET ARCHFFLAGS = -64 #ARCHDLIB = -lsun ARCHDOBJ = #ARCHLIB = -lsun AR = ar HASRANLIB = f PVM_ARCH = SGI64 MAKE = make ./pvm3/conf/SGI6.def0100644007401100000360000000026506604767001013226 0ustar kohlgopherARCHCFLAGS = -n32 -DSYSVSIGNAL -DRSHCOMMAND=\"/usr/bsd/rsh\" \ -DNOWAIT3 ARCHFFLAGS = -n32 ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = f AR = ar PVM_ARCH = SGI6 MAKE = make ./pvm3/conf/SGI.def0100644007401100000360000000024306604767000013133 0ustar kohlgopherARCHCFLAGS = -DSYSVSIGNAL -DRSHCOMMAND=\"/usr/bsd/rsh\" -DNOWAIT3 ARCHDLIB = -lsun ARCHDOBJ = ARCHLIB = -lsun HASRANLIB = f AR = ar PVM_ARCH = SGI MAKE = make ./pvm3/conf/SGIMP64.def0100644007401100000360000000037106604767012013547 0ustar kohlgopherARCHCFLAGS = -DSYSVSIGNAL -DRSHCOMMAND=\"/usr/bsd/rsh\" \ -DNOUNIXDOM -64 -woff 1174 -DHASSTDLIB -DSHMEM \ -DCTIMEISTIMET ARCHFFLAGS = -64 #ARCHDLIB = -lsun ARCHDOBJ = #ARCHLIB = -lsun HASRANLIB = f AR = ar PVM_ARCH = SGIMP64 MAKE = make ./pvm3/conf/SGIMP6.def0100644007401100000360000000030106604767011013453 0ustar kohlgopherARCHCFLAGS = -n32 -DSYSVSIGNAL -DRSHCOMMAND=\"/usr/bsd/rsh\" \ -DNOUNIXDOM -DSHMEM ARCHFFLAGS = -n32 ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = f AR = ar PVM_ARCH = SGIMP6 MAKE = make ./pvm3/conf/SGIMP.def0100644007401100000360000000026506604767010013375 0ustar kohlgopherARCHCFLAGS = -DSYSVSIGNAL -DRSHCOMMAND=\"/usr/bsd/rsh\" -DNOUNIXDOM \ -DSHMEM ARCHDLIB = -lsun ARCHDOBJ = ARCHLIB = -lsun HASRANLIB = f AR = ar PVM_ARCH = SGIMP MAKE = make ./pvm3/conf/SP2MPI.def0100644007401100000360000000044206604767012013467 0ustar kohlgopherARCHCFLAGS = -DSYSVSIGNAL -DNOUNIXDOM -DSOCKADHASLEN \ -DRSHCOMMAND=\"/usr/bin/rsh\" -DNEEDSSELECTH ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t PVM_ARCH = SP2MPI AR_FRONT = ar AR_NODE = ar AR = ar CC = cc NODECC = mpcc NEEDF2M4 = t FORTRAN = f77 NODEFORT = mpxlf MAKE = make ./pvm3/conf/SUN3.def0100644007401100000360000000015306604767013013245 0ustar kohlgopherARCHCFLAGS = -f68881 ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = SUN3 MAKE = make ./pvm3/conf/SUN4.def0100644007401100000360000000014306604767014013246 0ustar kohlgopherARCHCFLAGS = ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = SUN4 MAKE = make ./pvm3/conf/SUN4SOL2.def0100644007401100000360000000063307432766472013721 0ustar kohlgopher# # Note: for 64-bit systems, add the following flags to ARCHCFLAGS: # # -DHASSTDLIB -xarch=v9 -KPIC # # (-KPIC used for building shared dynamic libraries...) # ARCHCFLAGS = -DSYSVBFUNC -DSYSVSTR -DNOGETDTBLSIZ -DSYSVSIGNAL \ -DNOWAIT3 -DRSHCOMMAND=\"/usr/bin/rsh\" -DUSESTRERROR ARCHDLIB = -lnsl -lsocket ARCHDOBJ = ARCHLIB = -lnsl -lsocket HASRANLIB = f AR = ar PVM_ARCH = SUN4SOL2 MAKE = make ./pvm3/conf/SUNMP.def0100644007401100000360000000110407337304405013410 0ustar kohlgopherARCHCFLAGS = -DSYSVBFUNC -DSYSVSTR -DNOGETDTBLSIZ -DSYSVSIGNAL \ -DNOWAIT3 -DRSHCOMMAND=\"/usr/bin/rsh\" -DNOUNIXDOM \ -DUSESTRERROR -DSHMEM # -DUSESTRERROR -DSHMEM -DPVMUSEMUTEX # If you want to use MUTEX instead of Semaphores set -DPVMUSEMUTEX here # and remove the PLOCKFILE definition below # Note some older machines cannot use the v8plus directive PLOCKFILE = ../tas.il -xarch=v8plusa # Test And Set In Line code #PLOCKFILE = ARCHDLIB = -lnsl -lsocket -lthread ARCHDOBJ = ARCHLIB = -lnsl -lsocket -lthread HASRANLIB = f AR = ar PVM_ARCH = SUNMP MAKE = make ./pvm3/conf/SX3.def0100644007401100000360000000026206604767016013136 0ustar kohlgopherARCHCFLAGS = -DSYSVSIGNAL -DNOWAIT3 -DNOGETDTBLSIZ -DNOSTRCASE \ -DNOWAITPID -DHASSTDLIB ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = f AR = ar PVM_ARCH = SX3 MAKE = make ./pvm3/conf/SYMM.def0100644007401100000360000000015606604767024013307 0ustar kohlgopherARCHCFLAGS = -DNOTMPNAM ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = SYMM MAKE = make ./pvm3/conf/TITN.def0100644007401100000360000000030606604767025013276 0ustar kohlgopherARCHCFLAGS = -DNOGETDTBLSIZ -DSYSVSIGNAL -DNOWAIT3 -DSYSVSTR \ -DNOREXEC -DNOSOCKOPT -DNOUNIXDOM -DNEEDSFFS ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = f AR = ar PVM_ARCH = TITN MAKE = make ./pvm3/conf/U370.def0100644007401100000360000000014606604767026013161 0ustar kohlgopherARCHCFLAGS = -DNOUNIXDOM ARCHDLIBS = ARCHDOBJS = HASRANLIB = t AR = ar PVM_ARCH = U370 MAKE = make ./pvm3/conf/UTS2.def0100644007401100000360000000030506604767026013255 0ustar kohlgopherARCHCFLAGS = -eft -DSYSVSTR -DNOUNIXDOM -DNET_IF_IN_SYS ARCHDLIB = -lnsl -lsocket -lbsd -lrpc ARCHLIB = -lnsl -lsocket -lbsd -lrpc ARCHDOBJS = AR = ar HASRANLIB = f PVM_ARCH = UTS2 MAKE = make ./pvm3/conf/UVAX.def0100644007401100000360000000014306604767027013304 0ustar kohlgopherARCHCFLAGS = ARCHDLIB = ARCHDOBJ = ARCHLIB = HASRANLIB = t AR = ar PVM_ARCH = UVAX MAKE = make ./pvm3/conf/UWARE.def0100644007401100000360000000050306604767030013376 0ustar kohlgopherARCHCFLAGS = -DSYSVBFUNC -DSYSVSTR -DNOGETDTBLSIZ \ -DSYSVSIGNAL -DNOWAIT3 -DNOUNIXDOM \ -DRSHCOMMAND=\"/bin/rsh\" \ -DHASSTDLIB -DNOREXEC -DNOWAIT3 -UNOWAITPID \ -DNOSTRCASE -USOCKADHASLEN ARCHDOBJ = ARCHDLIB = -lnsl -lsocket ARCHLIB = -lnsl -lsocket HASRANLIB = f AR = ar PVM_ARCH = UWARE MAKE = make ./pvm3/conf/UXPM.def0100644007401100000360000000035506604767030013311 0ustar kohlgopherARCHCFLAGS = -DSYSVBFUNC -DSYSVSTR -DNOGETDTBLSIZ -DSYSVSIGNAL \ -DNOWAIT3 -DNOUNIXDOM -DRSHCOMMAND=\"/usr/bin/rsh\" ARCHDLIB = -lsocket -lnsl ARCHDOBJ = ARCHLIB = -lsocket -lnsl HASRANLIB = f AR = ar PVM_ARCH = UXPM MAKE = make ./pvm3/conf/UXPV.def0100644007401100000360000000037506604767031013325 0ustar kohlgopherARCHCFLAGS = -DSYSVBFUNC -DSYSVSTR -DNOGETDTBLSIZ -DSYSVSIGNAL \ -DNOWAIT3 -DNOUNIXDOM -DRSHCOMMAND=\"/usr/bin/rsh\" ARCHDLIB = -lsocket -lnsl -Wl,-dy ARCHDOBJ = ARCHLIB = -lsocket -lnsl -Wl,-dy HASRANLIB = f AR = ar PVM_ARCH = UXPV MAKE = make ./pvm3/conf/win32cygwin.def0100644007401100000360000000131207337303752014676 0ustar kohlgopher#*****************************************************************************# # # Definitions # for cygwin.mak files # #*****************************************************************************# PVM_ARCH = win32 LINK_FLAGS = LINK_MULTITHREAD = ARCHCFLAGS = -DCYGWIN -DHASSTDLIB -DSYSVBFUNC -DNOTMPNAM -DHASREADLINE \ -DSYSVSTR -DNOGETDTBLSIZ -DNOUNIXDOM -DNOREXEC -DFDSETNOTSTRUCT \ -DNEEDSFFS -DSTDC_HEADERS -DARCHCLASS=\"WIN32\" -DRSHCOMMAND=\"rsh\" \ -DNO_NETINET_TCP_H -DUSESTRERROR LIB = $(PVM_ROOT_U)/lib/$(PVM_ARCH)/libpvm3.a GLIB = $(PVM_ROOT_U)/lib/$(PVM_ARCH)/libgpvm3.a CFLAGS = -c $(ARCHCFLAGS) -I$(PVM_ROOT_U)/include -I$(PVM_ROOT_U)/src \ -I$(PVM_ROOT_U)/tracer CDEBUG = -g -O ./pvm3/conf/WIN32.def0100644007401100000360000000154406673301045013317 0ustar kohlgopher############################################### # Get the information captured during setup ! ############################################### ARCHCFLAGS = -DHASSTDLIB -DWIN32 -DSYSVBFUNC -DSYSVSTR \ -DHASERRORVARS -DNOWAIT3 -DNOGETDTBLSIZ -DNOUNIXDOM \ -DNOTMPNAM -DMAXHOSTNAMELEN=64 -DMAXPATHLEN=64 \ -DNEEDSFFS # for the defines in the workspace declaration # HASSTDLIB, WIN32, SYSVBFUNC, SYSVSTR, HASERRORVARS, NOWAIT3, # NOGETDTBLSIZ, NOUNIXDOM, NOTMPNAM, MAXHOSTNAMELEN=64, MAXPATHLEN=64, # NEEDSFFS, STDC_HEADERS, REGEX_MALLOC ARCHDLIB = ARCHDOBJ = ARCHLIB = MAKE = make ################################################ # We are ready to go: # compilerswitch ################################################ !IF "$(PVM_CCOMPILER)" == "WATCOMC++" !include $(PVM_ROOT)\conf\win32watcom.def !else !include $(PVM_ROOT)\conf\win32visual.def !endif ./pvm3/conf/win32visual.def0100644007401100000360000000537706672276506014727 0ustar kohlgopher# # $Id: win32visual.def,v 1.4 1999/03/12 20:47:02 pvmsrc Exp $ # ####################################################### # For Alpha ####################################################### !if "$(PROCESSOR_ARCHITECTURE)" == "ALPHA" cc = cl.exe fc = f77.exe conflags = /MACHINE:ALPHA /NOLOGO ####################################################### # For Intel ####################################################### !else cc = cl.exe fc = df.exe conflags = /MACHINE:IX86 /NOLOGO !endif OUT = /Fo OUTBIN = -out: OUTLIB = -out: OUTDLL = -out: MAKE = nmake EXESFX = .exe linkexe = link linklib = link -lib linkdll = link -dll link_flags = $(PVM_CLIBDIR)\wsock32.lib \ $(PVM_CLIBDIR)\kernel32.lib\ $(PVM_CLIBDIR)\libc.lib \ $(PVM_CLIBDIR)\gdi32.lib \ $(PVM_CLIBDIR)\winspool.lib \ $(PVM_CLIBDIR)\comdlg32.lib \ $(PVM_CLIBDIR)\advapi32.lib \ $(PVM_CLIBDIR)\shell32.lib \ $(PVM_CLIBDIR)\ole32.lib \ $(PVM_CLIBDIR)\oleaut32.lib \ $(PVM_CLIBDIR)\uuid.lib \ $(PVM_CLIBDIR)\oldnames.lib \ /nodefaultlib:"LIBCMT.LIB" fl32_link = $(PVM_CLIBDIR)\wsock32.lib \ $(PVM_CLIBDIR)\kernel32.lib \ $(PVM_CLIBDIR)\gdi32.lib \ $(PVM_CLIBDIR)\winspool.lib \ $(PVM_CLIBDIR)\comdlg32.lib \ $(PVM_CLIBDIR)\advapi32.lib \ $(PVM_CLIBDIR)\shell32.lib \ $(PVM_CLIBDIR)\ole32.lib \ $(PVM_CLIBDIR)\oleaut32.lib \ $(PVM_CLIBDIR)\uuid.lib \ $(PVM_CLIBDIR)\oldnames.lib link_multithread = $(PVM_CLIBDIR)\wsock32.lib \ $(PVM_CLIBDIR)\kernel32.lib \ $(PVM_CLIBDIR)\libcmt.lib \ $(PVM_CLIBDIR)\gdi32.lib \ $(PVM_CLIBDIR)\winspool.lib \ $(PVM_CLIBDIR)\comdlg32.lib \ $(PVM_CLIBDIR)\advapi32.lib \ $(PVM_CLIBDIR)\shell32.lib \ $(PVM_CLIBDIR)\ole32.lib \ $(PVM_CLIBDIR)\oleaut32.lib \ $(PVM_CLIBDIR)\uuid.lib \ $(PVM_CLIBDIR)\oldnames.lib \ $(PVM_CLIBDIR)\libcpmt.lib conlibs = $(libc) ######################################################## # Optimized Code ######################################################## cflags = /c /WX $(ARCHCFLAGS) /nologo /GX /O2 /D "NDEBUG" \ /D "_CONSOLE" -I$(PVM_CINCLUDE) -I$(PVM_ROOT)\include \ -I$(PVM_ROOT)\tracer -I$(PVM_ROOT)\src fflags = /c $(ARCHCFLAGS) /nologo /D "NDEBUG" /D "_CONSOLE" \ -I $(PVM_CINCLUDE) -I $(PVM_ROOT)\include \ -I $(PVM_ROOT)\src ######################################################## # Debugging mode ######################################################## #cflags = /c /W2 $(ARCHCFLAGS) /nologo /MTd /Gm /GX /Zi /Od /D \ # "_DEBUG" /D "_CONSOLE" \ # -I$(PVM_CINCLUDE) -I$(PVM_ROOT)\include \ # -I$(PVM_ROOT)\tracer -I$(PVM_ROOT)\src ######################################################## libpvm3dll = libpvm3.dll libgpvm3dll = libgpvm3.dll pvmd3exe = visual_pvmd3.exe ./pvm3/conf/win32watcom.def0100644007401100000360000000121006604767041014666 0ustar kohlgopher# # $Id: win32watcom.def,v 1.2 1998/10/01 21:03:29 pvmsrc Exp $ # cc = wcc386 -wcd=301 -wcd=202 fc = wfc386 -noreference conflags = OUT = -FO= OUTBIN = /fe= OUTLIB = -o = OUTDLL = -o= FORTRANLIB = linkexe = wcl386 linklib = wlib -b -n linkdll = wlib -b -n /bd FILE = file link_flags = SEPARATOR = " " BEGIN = { END = } link_multithread = conlibs = CFLAGS = -bt=nt !ifeq CFLAGS -zW CFLAGS += -i=$(%WATCOM)\h;$(%WATCOM)\h\win !else CFLAGS += -i=$(%WATCOM)\h;$(%WATCOM)\h\nt !endif CFLAGS += $(ARCHCFLAGS) -DWIN32 -DIMA_WIN32_WATCOM -i=..\include \ -i=..\src -i=..\tracer -oaxt -d2 -db -w4 -hw MAKE = make ./pvm3/conf/X86SOL2.def0100644007401100000360000000036006604767032013543 0ustar kohlgopherARCHCFLAGS = -DSYSVBFUNC -DSYSVSTR -DNOGETDTBLSIZ -DSYSVSIGNAL \ -DNOWAIT3 -DNOUNIXDOM -DRSHCOMMAND=\"/usr/bin/rsh\" ARCHDLIB = -lnsl -lsocket ARCHDOBJ = ARCHLIB = -lnsl -lsocket HASRANLIB = f AR = ar PVM_ARCH = X86SOL2 MAKE = make ./pvm3/conf/AIX46K64.m40100644007401100000360000000143610001307370013342 0ustar kohlgopherdivert(-1) undefine(`len') # # This generates two copies of each libfpvm function, one with # a trailing underscore and one without, so the resulting libfpvm # works whether or not you use -qextname. # For more comments, see the HPPA m4 file. define(`FUNCTION',ifdef(`USCORYES',`$1_',`$1')) #define(`FUNCTION',`$1') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/AIX46K.m40100644007401100000360000000143606233733703013207 0ustar kohlgopherdivert(-1) undefine(`len') # # This generates two copies of each libfpvm function, one with # a trailing underscore and one without, so the resulting libfpvm # works whether or not you use -qextname. # For more comments, see the HPPA m4 file. define(`FUNCTION',ifdef(`USCORYES',`$1_',`$1')) #define(`FUNCTION',`$1') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/AIX4MP.m40100644007401100000360000000143606763561340013247 0ustar kohlgopherdivert(-1) undefine(`len') # # This generates two copies of each libfpvm function, one with # a trailing underscore and one without, so the resulting libfpvm # works whether or not you use -qextname. # For more comments, see the HPPA m4 file. define(`FUNCTION',ifdef(`USCORYES',`$1_',`$1')) #define(`FUNCTION',`$1') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/AIX4SP2.m40100644007401100000360000000143606233733753013340 0ustar kohlgopherdivert(-1) undefine(`len') # # This generates two copies of each libfpvm function, one with # a trailing underscore and one without, so the resulting libfpvm # works whether or not you use -qextname. # For more comments, see the HPPA m4 file. define(`FUNCTION',ifdef(`USCORYES',`$1_',`$1')) #define(`FUNCTION',`$1') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/AIX56K64.m40100644007401100000360000000143610001307371013344 0ustar kohlgopherdivert(-1) undefine(`len') # # This generates two copies of each libfpvm function, one with # a trailing underscore and one without, so the resulting libfpvm # works whether or not you use -qextname. # For more comments, see the HPPA m4 file. define(`FUNCTION',ifdef(`USCORYES',`$1_',`$1')) #define(`FUNCTION',`$1') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/AIX56K.m40100644007401100000360000000143610001307371013172 0ustar kohlgopherdivert(-1) undefine(`len') # # This generates two copies of each libfpvm function, one with # a trailing underscore and one without, so the resulting libfpvm # works whether or not you use -qextname. # For more comments, see the HPPA m4 file. define(`FUNCTION',ifdef(`USCORYES',`$1_',`$1')) #define(`FUNCTION',`$1') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/AIX5MP.m40100644007401100000360000000143610001307372013227 0ustar kohlgopherdivert(-1) undefine(`len') # # This generates two copies of each libfpvm function, one with # a trailing underscore and one without, so the resulting libfpvm # works whether or not you use -qextname. # For more comments, see the HPPA m4 file. define(`FUNCTION',ifdef(`USCORYES',`$1_',`$1')) #define(`FUNCTION',`$1') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/AIX5SP2.m40100644007401100000360000000143610001307373013320 0ustar kohlgopherdivert(-1) undefine(`len') # # This generates two copies of each libfpvm function, one with # a trailing underscore and one without, so the resulting libfpvm # works whether or not you use -qextname. # For more comments, see the HPPA m4 file. define(`FUNCTION',ifdef(`USCORYES',`$1_',`$1')) #define(`FUNCTION',`$1') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/ALPHA.m40100644007401100000360000000110206221570120013101 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/ALPHAMP.m40100644007401100000360000000110206221570121013337 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/APOLLO.m40100644007401100000360000000107706310023131013247 0ustar kohlgopherdivert(-1) undefine(`len') # # do nothing special to FORTRAN function names # define(`FUNCTION',`$1') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/ATT.m40100644007401100000360000000110206221570123012707 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/BAL.m40100644007401100000360000000110206221570124012656 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/BEOLIN.m40100644007401100000360000000110207053052665013241 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/BEOSCYLD.m40100644007401100000360000000110207354714345013501 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/BFLY.m40100644007401100000360000000110206221570125013015 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/BSD386.m40100644007401100000360000000045306604472265013155 0ustar kohlgopherdivert(-1) undefine(`len') define(`FUNCTION',`$1_') define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/CNVX.m40100644007401100000360000000110206221570133013036 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/CNVXN.m40100644007401100000360000000110206221570134013155 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/CRAY2.m40100644007401100000360000000045106221570137013112 0ustar kohlgopher#include undefine(`len') define(`FUNCTION',`translit($1,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ)') define(`STRING_ARG',`$1_fcd') define(`STRING_ARG_DECL',`_fcd $1_fcd') define(`STRING_LEN',`_fcdlen($1_fcd)') define(`STRING_PTR',`_fcdtocp($1_fcd)') define(`ARGS',`($1)') ./pvm3/conf/CRAY.m40100644007401100000360000000045106221570136013027 0ustar kohlgopher#include undefine(`len') define(`FUNCTION',`translit($1,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ)') define(`STRING_ARG',`$1_fcd') define(`STRING_ARG_DECL',`_fcd $1_fcd') define(`STRING_LEN',`_fcdlen($1_fcd)') define(`STRING_PTR',`_fcdtocp($1_fcd)') define(`ARGS',`($1)') ./pvm3/conf/CRAYSMP.m40100644007401100000360000000110206221570140013374 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/CSPP.m40100644007401100000360000000143606221570142013037 0ustar kohlgopherdivert(-1) undefine(`len') # # This generates two copies of each libfpvm function, one with # a trailing underscore and one without, so the resulting libfpvm # works whether or not you use -qextname. # For more comments, see the HPPA m4 file. define(`FUNCTION',ifdef(`USCORYES',`$1_',`$1')) #define(`FUNCTION',`$1') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/CYGWIN.m40100644007401100000360000000110207052615441013265 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/DARWIN.m40100644007401100000360000000110207277034060013252 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/DGIX.m40100644007401100000360000000126306740730161013030 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') #define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG',`$1_ptr') #define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_ARG_DECL',`char * $1_ptr') #define(`STRING_LEN',`$1_len') define(`STRING_LEN',`strlen($1_ptr)') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/FREEBSD.m40100644007401100000360000000045306221570143013343 0ustar kohlgopherdivert(-1) undefine(`len') define(`FUNCTION',`$1_') define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/HP300.m40100644007401100000360000000107706221570145013030 0ustar kohlgopherdivert(-1) undefine(`len') # # do nothing special to FORTRAN function names # define(`FUNCTION',`$1') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/HPPA.m40100644007401100000360000000244506221570146013027 0ustar kohlgopherdivert(-1) undefine(`len') # # the HP Snake does nothing special to FORTRAN function names # # The preceding statement is not QUITE true.... If one invokes # certain options for the HP compiler, THEN subprogram names take # on the form.... "abcedf_" as opposed to "abcdef" as stated above. # There seems to be no clean solution. MY answer is to create TWO # separate libaries, one WITH underscores in the names and one WITHOUT. # Each routinme is compiled twice, once with an underscore in the # routine name and once without. Thus, each ".o" file actually # contains two routines. The resulting library lets the loader # pick and choose whichever the perverted HP system wants at THAT # particular time..... -RWB 1/5/93 define(`FUNCTION',ifdef(`USCORYES',`$1_',`$1')) #define(`FUNCTION',`$1') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/HPPAMP.m40100644007401100000360000000244506221570150013257 0ustar kohlgopherdivert(-1) undefine(`len') # # the HP Snake does nothing special to FORTRAN function names # # The preceding statement is not QUITE true.... If one invokes # certain options for the HP compiler, THEN subprogram names take # on the form.... "abcedf_" as opposed to "abcdef" as stated above. # There seems to be no clean solution. MY answer is to create TWO # separate libaries, one WITH underscores in the names and one WITHOUT. # Each routinme is compiled twice, once with an underscore in the # routine name and once without. Thus, each ".o" file actually # contains two routines. The resulting library lets the loader # pick and choose whichever the perverted HP system wants at THAT # particular time..... -RWB 1/5/93 define(`FUNCTION',ifdef(`USCORYES',`$1_',`$1')) #define(`FUNCTION',`$1') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/IPSC2.m40100644007401100000360000000110206221570153013102 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/LINUX64.m40100644007401100000360000000110207240567543013346 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/LINUXALPHA.m40100644007401100000360000000110206427710727013742 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/LINUXARM.m40100644007401100000360000000110207051071753013525 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/LINUXATARI.m40100644007401100000360000000110207171104623013742 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/LINUXHPPA.m40100644007401100000360000000110206463677153013652 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/LINUX.m40100644007401100000360000000110206221570156013164 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/LINUXPPC.m40100644007401100000360000000110206474362273013540 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/LINUXSPARC.m40100644007401100000360000000110206334440246013756 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/M88K.m40100644007401100000360000000122206221570157012760 0ustar kohlgopherdivert(-1) undefine(`len') # # FORTRAN function names are in upper case # define(`FUNCTION',`translit($1,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ)') # # FORTRAN character strings are passed as follows: # XXX is this right? # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/MACOSX.m40100644007401100000360000000150007471215162013262 0ustar kohlgopherdivert(-1) undefine(`len') # # For g77, do nothing special to FORTRAN function names # define(`FUNCTION',`$1') # # For the Absoft Compiler, FORTRAN function names are in upper case, # so use this line instead (from Drew McCormack cormack@chem.vu.nl): # # define(`FUNCTION',`translit($1,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ) # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # XXX I hope... # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/MASPAR.m40100644007401100000360000000110206221570161013244 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/MIPS.m40100644007401100000360000000110206221570162013032 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/NETBSDALPHA.m40100644007401100000360000000110207052612131014003 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/NETBSDAMIGA.m40100644007401100000360000000122206221570163014004 0ustar kohlgopherdivert(-1) undefine(`len') # # FORTRAN function names are in upper case # define(`FUNCTION',`translit($1,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ)') # # FORTRAN character strings are passed as follows: # XXX is this right? # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/NETBSDARM32.m40100644007401100000360000000110207052612132013743 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/NETBSDHP300.m40100644007401100000360000000122206221570165013722 0ustar kohlgopherdivert(-1) undefine(`len') # # FORTRAN function names are in upper case # define(`FUNCTION',`translit($1,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ)') # # FORTRAN character strings are passed as follows: # XXX is this right? # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/NETBSDI386.m40100644007401100000360000000110207052611774013623 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/NETBSDM68K.m40100644007401100000360000000110207052612133013645 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/NETBSDMAC68K.m40100644007401100000360000000122206221570170014055 0ustar kohlgopherdivert(-1) undefine(`len') # # FORTRAN function names are in upper case # define(`FUNCTION',`translit($1,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ)') # # FORTRAN character strings are passed as follows: # XXX is this right? # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/NETBSDMIPSEB.m40100644007401100000360000000110207052612136014142 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/NETBSDMIPSEL.m40100644007401100000360000000110207052612140014147 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/NETBSDNS32K.m40100644007401100000360000000110207052612150013757 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/NETBSDPMAX.m40100644007401100000360000000122206221570171013732 0ustar kohlgopherdivert(-1) undefine(`len') # # FORTRAN function names are in upper case # define(`FUNCTION',`translit($1,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ)') # # FORTRAN character strings are passed as follows: # XXX is this right? # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/NETBSDPOWERPC.m40100644007401100000360000000110207052612151014277 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/NETBSDSH3.m40100644007401100000360000000110207052612213013554 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/NETBSDSPARC64.m40100644007401100000360000000110207052612214014202 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/NETBSDSPARC.m40100644007401100000360000000110207052611775014043 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/NETBSDSUN3.m40100644007401100000360000000122206221570174013720 0ustar kohlgopherdivert(-1) undefine(`len') # # FORTRAN function names are in upper case # define(`FUNCTION',`translit($1,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ)') # # FORTRAN character strings are passed as follows: # XXX is this right? # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/NETBSDVAX.m40100644007401100000360000000110207052612215013617 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/NEXT.m40100644007401100000360000000112106221570175013045 0ustar kohlgopherdivert(-1) undefine(`len') # # do nothing special to FORTRAN function names # define(`FUNCTION',`$1') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # XXX I hope... # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/OS2.m40100644007401100000360000000110206401331673012667 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/PGON.m40100644007401100000360000000110206221570177013033 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/PMAX.m40100644007401100000360000000110206221570200013020 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/RS6K.m40100644007401100000360000000143606221570201013013 0ustar kohlgopherdivert(-1) undefine(`len') # # This generates two copies of each libfpvm function, one with # a trailing underscore and one without, so the resulting libfpvm # works whether or not you use -qextname. # For more comments, see the HPPA m4 file. define(`FUNCTION',ifdef(`USCORYES',`$1_',`$1')) #define(`FUNCTION',`$1') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/RS6KMP.m40100644007401100000360000000110206221570203013240 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/RT.m40100644007401100000360000000110206221570204012604 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/SGI5.m40100644007401100000360000000110206221570207012771 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/SGI64.m40100644007401100000360000000110206221570211013051 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/SGI6.m40100644007401100000360000000110206372172214012775 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/SGI.m40100644007401100000360000000110206221570205012702 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/SGIMP64.m40100644007401100000360000000110206221570214013311 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/SGIMP6.m40100644007401100000360000000110206372172221013230 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/SGIMP.m40100644007401100000360000000110206221570213013136 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/SP2MPI.m40100644007401100000360000000143606221570216013246 0ustar kohlgopherdivert(-1) undefine(`len') # # This generates two copies of each libfpvm function, one with # a trailing underscore and one without, so the resulting libfpvm # works whether or not you use -qextname. # For more comments, see the HPPA m4 file. define(`FUNCTION',ifdef(`USCORYES',`$1_',`$1')) #define(`FUNCTION',`$1') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/SUN3.m40100644007401100000360000000110206221570217013013 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/SUN4.m40100644007401100000360000000110206221570220013006 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/SUN4SOL2.m40100644007401100000360000000110206221570222013450 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/SUNMP.m40100644007401100000360000000110206221570223013162 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/SX3.m40100644007401100000360000000114406221570224012704 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`INT_ARG_DECL',`int * $1') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/SYMM.m40100644007401100000360000000110206221570226013050 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/TITN.m40100644007401100000360000000102006221570227013041 0ustar kohlgopherdivert(-1) undefine(`len') # # FORTRAN function names are in upper case # define(`FUNCTION',`translit($1,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ)') # # The Titan uses a special string descriptor to pass strings in FORTRAN. # The descriptor is passed by reference. # divert(0) typedef struct { char *ptr; int length; } FSD; divert(-1) define(`STRING_ARG',`$1_fsd') define(`STRING_ARG_DECL',`FSD * $1_fsd') define(`STRING_LEN',`($1_fsd)->length') define(`STRING_PTR',`($1_fsd)->ptr') define(`ARGS',`($1)') divert(0) ./pvm3/conf/U370.m40100644007401100000360000000033406221570231012723 0ustar kohlgopherundefine(`len') define(`FUNCTION',`$1_') define(`STRING_ARG',`$1_ptr, $1_len') define(`STRING_ARG_DECL',`char * $1_ptr; int * $1_len') define(`STRING_LEN',`(*$1_len)') define(`STRING_PTR',`$1_ptr') define(`ARGS',`($1)') ./pvm3/conf/UTS2.m40100644007401100000360000000033406221570232013023 0ustar kohlgopherundefine(`len') define(`FUNCTION',`$1_') define(`STRING_ARG',`$1_ptr, $1_len') define(`STRING_ARG_DECL',`char * $1_ptr; int * $1_len') define(`STRING_LEN',`(*$1_len)') define(`STRING_PTR',`$1_ptr') define(`ARGS',`($1)') ./pvm3/conf/UVAX.m40100644007401100000360000000110206221570233013044 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/UWARE.m40100644007401100000360000000121006300703533013143 0ustar kohlgopherdivert(-1) undefine(`len') # # FORTRAN function names are in upper case # define(`FUNCTION',`translit($1,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ)') # # FORTRAN character strings are passed as follows: # XXX is this right? # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr, $1_len') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/UXPM.m40100644007401100000360000000110206221570235013054 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/UXPV.m40100644007401100000360000000110206365411444013072 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/X86SOL2.m40100644007401100000360000000110206221570236013311 0ustar kohlgopherdivert(-1) undefine(`len') # # append an underscore to FORTRAN function names # define(`FUNCTION',`$1_') # # FORTRAN character strings are passed as follows: # a pointer to the base of the string is passed in the normal # argument list, and the length is passed by value as an extra # argument, after all of the other arguments. # define(`ARGS',`($1`'undivert(1))') define(`SAVE',`divert(1)$1`'divert(0)') define(`STRING_ARG',`$1_ptr`'SAVE(`, $1_len')') define(`STRING_ARG_DECL',`char * $1_ptr; int $1_len') define(`STRING_LEN',`$1_len') define(`STRING_PTR',`$1_ptr') divert(0) ./pvm3/conf/win32.bat0100644007401100000360000000040306625342661013466 0ustar kohlgopherPVM_ROOT= C:\PROGRA~1\PVM3.4 PVM_ARCH= WIN32 CCOMPILER= VISUALC++ FCOMPILER= DigitalFortran FLIBDIR= C:\PROGRA~1\DEVSTU~1\DF\LIB FINCLUDE= C:\PROGRA~1\DEVSTU~1\DF\INCLUDE CLIBDIR= C:\PROGRA~1\DEVSTU~1\VC\LIB CINCLUDE= C:\PROGRA~1\DEVSTU~1\VC\INCLUDE ./pvm3/gexamples/0042755007401100000360000000000010117676455013106 5ustar kohlgopher./pvm3/gexamples/Makefile0100644007401100000360000000351506604767561014552 0ustar kohlgopher# # $Id: Makefile,v 1.4 1998/10/01 21:09:05 pvmsrc Exp $ # # Makefile for PVM group library example programs. # # Set PVM_ROOT to the path where PVM includes and libraries are installed. # Set PVM_ARCH to your architecture type (SUN4, HP9K, RS6K, SGI, etc.) # Set ARCHLIB to any special libs needed on PVM_ARCH (-lrpc, -lsocket, etc.) # otherwise leave ARCHLIB blank # # PVM_ARCH and ARCHLIB, among other things, are set for you if you # use "$PVM_ROOT/lib/aimk" instead of "make". # #PVM_ROOT = #PVM_ARCH = #ARCHCFLAGS = SHELL = /bin/sh PVMDIR = $(PVM_ROOT) SDIR = $(PVMDIR)/gexamples PVMIDIR = $(PVMDIR)/include PVMLDIR = $(PVMDIR)/lib/$(PVM_ARCH) PVMLIB = -lgpvm3 -lpvm3 CFLOPTS = -g CFLAGS = $(CFLOPTS) -I$(PVMIDIR) -L$(PVMLDIR) $(ARCHCFLAGS) #BDIR = $(HOME)/pvm3/bin BDIR = $(PVMDIR)/bin XDIR = $(BDIR)/$(PVM_ARCH) F77 = f77 FFLOPTS = -g FFLAGS = $(FFLOPTS) PVMFLIB = -lfpvm3 $(PVMLIB) all: gexamp tst thb tnb ge tjl tjf gs joinleave: $(SDIR)/joinleave.c $(CC) $(CFLAGS) -o joinleave joinleave.c $(PVMLIB) tst: $(SDIR)/tst.c $(CC) $(CFLAGS) -o tst tst.c $(PVMLIB) cp tst $(XDIR) gs: $(SDIR)/gs.c $(CC) $(CFLAGS) -o gs gs.c $(PVMLIB) cp gs $(XDIR) ge: $(SDIR)/ge.c $(CC) $(CFLAGS) -o ge ge.c $(PVMLIB) cp ge $(XDIR) gexamp: $(SDIR)/gexamp.c $(CC) $(CFLAGS) -o gexamp gexamp.c $(PVMLIB) cp gexamp $(XDIR) thb: $(SDIR)/thb.c $(CC) $(CFLAGS) -o thb thb.c $(PVMLIB) cp thb $(XDIR) tnb: $(SDIR)/tnb.c $(CC) $(CFLAGS) -o tnb tnb.c $(PVMLIB) cp tnb $(XDIR) tjl: $(SDIR)/tjl.c $(CC) $(CFLAGS) -o tjl tjl.c $(PVMLIB) cp tjl $(XDIR) tjf: $(SDIR)/tjf.c $(CC) $(CFLAGS) -o tjf tjf.c $(PVMLIB) cp tjf $(XDIR) trsg: $(SDIR)/trsg.c $(CC) $(CFLAGS) -o trsg trsg.c $(PVMLIB) cp trsg $(XDIR) frsg: $(SDIR)/frsg.f $(F77) $(FFLAGS) -o frsg frsg.f $(PVMFLIB) cp frsg $(XDIR) clean: rm -f *.o tst thb tnb tjl tjf ge gexamp gs joinleave trsg frsg ./pvm3/gexamples/Makefile.aimk0100644007401100000360000000456707052615465015473 0ustar kohlgopher# # $Id: Makefile.aimk,v 1.7 2000/02/16 21:48:37 pvmsrc Exp $ # # Makefile for PVM group library example programs. # # Set PVM_ROOT to the path where PVM includes & libraries are installed. # Set PVM_ARCH to your architecture type (SUN4, HP9K, RS6K, SGI, etc.) # Set ARCHLIB to any special libs needed on PVM_ARCH (-lrpc, -lsocket, # etc.) # otherwise leave ARCHLIB blank # # PVM_ARCH and ARCHLIB, among other things, are set for you if you # use "$PVM_ROOT/lib/aimk" instead of "make". # #PVM_ROOT = #PVM_ARCH = #ARCHCFLAGS = SHELL = /bin/sh PVMDIR = ../.. PVMIDIR = $(PVMDIR)/include PVMLDIR = $(PVMDIR)/lib/$(PVM_ARCH) PVMLIB = $(LOPT) -L$(PVMLDIR) -lgpvm3 -lpvm3 $(ARCHLIB) CFLOPTS = -g CFLAGS = $(CFLOPTS) -I$(PVMIDIR) $(ARCHCFLAGS) SDIR = $(PVMDIR)/gexamples BDIR = $(PVMDIR)/bin XDIR = $(BDIR)/$(PVM_ARCH) #F77 = f77 FORT = `case "$(FC)@$(F77)" in @) echo f77 ;; *@) echo $(FC) ;; @*) echo $(F77) ;; *) echo $(FC) ;; esac` FFLOPTS = -g FFLAGS = $(FFLOPTS) -I$(PVMIDIR) $(ARCHFFLAGS) PVMFLIB = $(LOPT) -L$(PVMLDIR) -lfpvm3 $(PVMLIB) $(ARCHLIB) PROGS = joinleave$(EXESFX) gexamp$(EXESFX) tst$(EXESFX) \ thb$(EXESFX) tnb$(EXESFX) ge$(EXESFX) tjl$(EXESFX) \ tjf$(EXESFX) trsg$(EXESFX) frsg$(EXESFX) gs$(EXESFX) all: $(PROGS) joinleave$(EXESFX): $(SDIR)/joinleave.c $(CC) $(CFLAGS) -o $@ $(SDIR)/joinleave.c $(PVMLIB) cp joinleave$(EXESFX) $(XDIR) tst$(EXESFX): $(SDIR)/tst.c $(CC) $(CFLAGS) -o $@ $(SDIR)/tst.c $(PVMLIB) cp tst$(EXESFX) $(XDIR) gs$(EXESFX): $(SDIR)/gs.c $(CC) $(CFLAGS) -o $@ $(SDIR)/gs.c $(PVMLIB) cp gs$(EXESFX) $(XDIR) ge$(EXESFX): $(SDIR)/ge.c $(CC) $(CFLAGS) -o $@ $(SDIR)/ge.c $(PVMLIB) cp ge$(EXESFX) $(XDIR) gexamp$(EXESFX): $(SDIR)/gexamp.c $(CC) $(CFLAGS) -o $@ $(SDIR)/gexamp.c $(PVMLIB) cp gexamp$(EXESFX) $(XDIR) thb$(EXESFX): $(SDIR)/thb.c $(CC) $(CFLAGS) -o $@ $(SDIR)/thb.c $(PVMLIB) cp thb$(EXESFX) $(XDIR) tnb$(EXESFX): $(SDIR)/tnb.c $(CC) $(CFLAGS) -o $@ $(SDIR)/tnb.c $(PVMLIB) cp tnb$(EXESFX) $(XDIR) tjl$(EXESFX): $(SDIR)/tjl.c $(CC) $(CFLAGS) -o $@ $(SDIR)/tjl.c $(PVMLIB) cp tjl$(EXESFX) $(XDIR) tjf$(EXESFX): $(SDIR)/tjf.c $(CC) $(CFLAGS) -o $@ $(SDIR)/tjf.c $(PVMLIB) cp tjf$(EXESFX) $(XDIR) trsg$(EXESFX): $(SDIR)/trsg.c $(CC) $(CFLAGS) -o $@ $(SDIR)/trsg.c $(PVMLIB) cp trsg$(EXESFX) $(XDIR) frsg$(EXESFX): $(SDIR)/frsg.f $(FORT) $(FFLAGS) -o $@ $(SDIR)/frsg.f $(PVMFLIB) cp frsg$(EXESFX) $(XDIR) clean: rm -f *.o $(PROGS) ./pvm3/gexamples/Makefile.mak0100644007401100000360000001305606673300246015307 0ustar kohlgopher# # $Id: Makefile.mak,v 1.3 1999/03/15 21:50:30 pvmsrc Exp $ # #*************************************************************# #** **# #** PVM Group Examples: **# #** c: joinleave, tst, gs, ge, gexamp, thb, **# #** tnb, tjl, tjf, trsg **# #** **# #** f: frsg **# #*************************************************************# !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !include $(PVM_ROOT)\conf\$(PVM_ARCH).def SDIR = $(PVM_ROOT)\gexamples CPROGS = joinleave tst gs ge gexamp thb tnb tjl tjf trsg FPROGS = frsg LIB = $(PVM_ROOT)\lib\$(PVM_ARCH)\libpvm3.lib GLIB = $(PVM_ROOT)\lib\$(PVM_ARCH)\libgpvm3.lib FLIB = $(PVM_ROOT)\libfpvm\$(PVM_ARCH)\libfpvm3.lib FLIBPATH = /LIBPATH:$(PVM_FLIBDIR) \ /LIBPATH:$(PVM_CLIBDIR) default: all all: bin $(CPROGS) $(FPROGS) c-all: bin $(CPROGS) f-all: bin $(FPROGS) ############################################################### # C ############################################################### bin: if not exist "$(PVM_ARCH)\$(NULL)" mkdir "$(PVM_ARCH)" if not exist "$(PVM_ROOT)\bin\$(NULL)" mkdir "$(PVM_ROOT)\bin" if not exist "$(PVM_ROOT)\bin\$(PVM_ARCH)\$(NULL)" \ mkdir "$(PVM_ROOT)\bin\$(PVM_ARCH)" joinleave: $(PVM_ARCH)/joinleave.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\joinleave.exe \ $(PVM_ARCH)\joinleave.obj $(LIB) $(GLIB) $(link_flags) tst: $(PVM_ARCH)/tst.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\tst.exe \ $(PVM_ARCH)\tst.obj $(LIB) $(GLIB) $(link_flags) gs: $(PVM_ARCH)/gs.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\gs.exe \ $(PVM_ARCH)\gs.obj $(LIB) $(GLIB) $(link_flags) ge: $(PVM_ARCH)/ge.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\ge.exe \ $(PVM_ARCH)\ge.obj $(LIB) $(GLIB) $(link_flags) gexamp: $(PVM_ARCH)/gexamp.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\gexamp.exe \ $(PVM_ARCH)\gexamp.obj $(LIB) $(GLIB) $(link_flags) thb: $(PVM_ARCH)/thb.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\thb.exe \ $(PVM_ARCH)\thb.obj $(LIB) $(GLIB) $(link_flags) tnb: $(PVM_ARCH)/tnb.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\tnb.exe \ $(PVM_ARCH)\tnb.obj $(LIB) $(GLIB) $(link_flags) tjl: $(PVM_ARCH)/tjl.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\tjl.exe \ $(PVM_ARCH)\tjl.obj $(LIB) $(GLIB) $(link_flags) tjf: $(PVM_ARCH)/tjf.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\tjf.exe \ $(PVM_ARCH)\tjf.obj $(LIB) $(GLIB) $(link_flags) trsg: $(PVM_ARCH)/trsg.obj $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\trsg.exe \ $(PVM_ARCH)\trsg.obj $(LIB) $(GLIB) $(link_flags) ############# # C OBJS ############# $(PVM_ARCH)\joinleave.obj: $(SDIR)\joinleave.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\joinleave.obj $(SDIR)\joinleave.c $(PVM_ARCH)\tst.obj: $(SDIR)\tst.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\tst.obj $(SDIR)\tst.c $(PVM_ARCH)\gs.obj: $(SDIR)\gs.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\gs.obj $(SDIR)\gs.c $(PVM_ARCH)\ge.obj: $(SDIR)\ge.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\ge.obj $(SDIR)\ge.c $(PVM_ARCH)\gexamp.obj: $(SDIR)\gexamp.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\gexamp.obj $(SDIR)\gexamp.c $(PVM_ARCH)\thb.obj: $(SDIR)\thb.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\thb.obj $(SDIR)\thb.c $(PVM_ARCH)\tnb.obj: $(SDIR)\tnb.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\tnb.obj $(SDIR)\tnb.c $(PVM_ARCH)\tjl.obj: $(SDIR)\tjl.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\tjl.obj $(SDIR)\tjl.c $(PVM_ARCH)\tjf.obj: $(SDIR)\tjf.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\tjf.obj $(SDIR)\tjf.c $(PVM_ARCH)\trsg.obj: $(SDIR)\trsg.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\trsg.obj $(SDIR)\trsg.c ############################################################# # FORTRAN ############################################################# frsg: $(PVM_ARCH)\frsg.obj $(linkexe) $(conflags) $(FLIBPATH) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\frsg.exe \ $(PVM_ARCH)\frsg.obj $(LIB) $(GLIB) $(FLIB) $(link_flags) ############## # FORTRAN OBJS ############## $(PVM_ARCH)\frsg.obj: $(SDIR)\frsg.f $(fc) $(cdebug) /Fo$(PVM_ARCH)\frsg.obj $(fflags) $(cvars) \ $(SDIR)\frsg.f # Clean all Fortran example codes - .OBJ and .EXE tidy-f: -del $(PVM_ARCH)\frsg.obj -del $(PVM_ROOT)\bin\$(PVM_ARCH)\frsg.exe # Clean all C example codes - .OBJ and .EXE tidy-c: -del $(PVM_ARCH)\joinleave.obj -del $(PVM_ARCH)\tst.obj -del $(PVM_ARCH)\gs.obj -del $(PVM_ARCH)\ge.obj -del $(PVM_ARCH)\gexamp.obj -del $(PVM_ARCH)\thb.obj -del $(PVM_ARCH)\tnb.obj -del $(PVM_ARCH)\tjl.obj -del $(PVM_ARCH)\tjf.obj -del $(PVM_ARCH)\trsg.obj -del $(PVM_ROOT)\bin\$(PVM_ARCH)\joinleave.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\tst.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\gs.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\ge.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\gexamp.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\thb.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\tnb.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\tjl.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\tjf.exe -del $(PVM_ROOT)\bin\$(PVM_ARCH)\trsg.exe # Clean up everything but the .EXEs clean: -del *.obj -del *.pdb ./pvm3/gexamples/Readme0100644007401100000360000000471406221575322014217 0ustar kohlgopherDirectory: pvm3/gexamples This directory contains several example programs for using dynamic group services. The following is a list with short descriptions of what each program illustrates: frsg.f - Fortran example of reduce, scatter, and gather operations. Sum of sqaures for first N integers. N defaults to 20 with 4 processors if frsg is spawned from the console. Synopsis: frsg trsg.c - C version of the frsg program Synopsis: trsg gexamp.c - Instance 0 spawns nproc-1 copies of gexamp. All group members then perform a barrier. All members broadcast a copy of their tid and instance to the entire. Each process checks the incoming message against its own data. Synopsis: gexamp joinleave.c - One process continually joins and leaves the same group. A diagnostic is printed every 100 join/leave pairs. Will join and leave the group 10000 times, unless a different count is specified on the command line. Synopsis: joinleave [njoins] thb.c tnb.c - thb joins 32 different groups. It checks the group server for consistency using pvm_gettinst and pvm_gettid. It then spawns tnb process and sends them some intialization information. The tnb processes receive the initialization data and then perform a barrier with themselves and the thb process. Synopsis: thb HOW TO COMPILE $PVM_ROOT/lib should be in your path so that the aimk program can be located. Then, % aimk all # make all the test programs % aimk frsg # make just frsg NOTES FOR PARAGON USERS All the codes are compiled to run as compute node programs. You must therefore spawn the programs from the pvm console. For example to run the gexamp program type at the pvm console % pvm # start a pvm console, in $PVM_ROOT/lib/$PVM_ARCH/pvm pvm> spawn -> gexamp <4> The -> redirects all output of the tasks to the pvm console window. ./pvm3/gexamples/ge.c0100644007401100000360000000702606360710734013637 0ustar kohlgopher static char rcsid[] = "$Id: ge.c,v 1.2 1997/07/09 13:27:56 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* Typical group example 20 Mar 1993, modified example to reflect change in pvm_bcast() */ #include #include "pvm3.h" int main(argc, argv) int argc; char *argv[]; { int mytid, mygid, ctid[32]; int nproc, i, indx; int cc; mytid = pvm_mytid(); fprintf(stderr, "%s 0x%x enrolled\n", "ge", mytid); if (mytid < 0) { pvm_perror(argv[0]); return -1; } if (pvm_parent() == PvmNoParent) { if (argc != 2) goto usage; if ((nproc = atoi(argv[1])) < 0) goto usage; if (nproc > 32) goto usage; } /* join a group */ mygid = pvm_joingroup("ge"); fprintf(stderr, "%s 0x%x %d\n", "ge", mytid, mygid); /* if I'm the first to join then start the others */ if (mygid == 0) { /* start a bunch of children */ if ((nproc-1) != pvm_spawn(argv[0], (char**) 0, 0, "", nproc-1, ctid)) pvm_perror("spawn1"); /* check them */ for (i = 0; i < nproc-1; i++) fprintf(stderr, "0x%x\n", ctid[i]); /* tell them how many sibs */ pvm_initsend(PvmDataDefault); pvm_pkint(&nproc, 1, 1); pvm_mcast(ctid, nproc-1, 15); } else { /* find out the number of sibs */ pvm_recv(pvm_parent(), 15); pvm_upkint(&nproc, 1, 1); fprintf(stderr,"nproc %d\n",nproc); } /* sync on a barrier */ if (pvm_barrier("ge", nproc) < 0) { pvm_perror("barrier"); pvm_lvgroup("ge"); pvm_exit(); return -1; } fprintf(stderr, "group %s size %d gid %d: sync\n", "ge", pvm_gsize("ge"), mygid); /* everyone broadcast their gids and tids */ pvm_initsend(PvmDataDefault); pvm_pkint(&mygid, 1, 1); pvm_pkint(&mytid, 1, 1); pvm_bcast("ge", 63); /* recv all the gids and tids (except from myself) */ for (i = 0; i < nproc-1; i++) { pvm_recv(-1, 63); pvm_upkint(&indx, 1, 1); pvm_upkint(ctid+indx, 1, 1); } /* set my tid too */ ctid[mygid] = mytid; /* check to make sure the gids and tids are correct */ for (i = 0; i < nproc; i++) { if (i != pvm_getinst("ge", ctid[i])) { fprintf(stderr, "gid %d doesn't match up!\n", i); } if (ctid[i] != pvm_gettid("ge", i)) { fprintf(stderr, "gid %d doesn't match up!\n", i); } } /* leave the group */ if(pvm_lvgroup("ge") < 0) pvm_perror("leave"); pvm_exit(); printf("done\n"); return 0; usage: pvm_exit(); fprintf(stderr, "usage: %s \n", argv[0]); return -1; } ./pvm3/gexamples/gexamp.c0100644007401100000360000000655606360710735014535 0ustar kohlgopher static char rcsid[] = "$Id: gexamp.c,v 1.2 1997/07/09 13:27:57 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* Typical group example */ #include #ifdef SYSVSTR #include #define RINDEX(s,c) strrchr(s,c) #else #include #define RINDEX(s,c) rindex(s,c) #endif #include "pvm3.h" int main(argc, argv) int argc; char *argv[]; { int mytid, mygid, ctid[32]; int nproc, i, indx; char *gp; mytid = pvm_mytid(); fprintf(stderr, "%s 0x%x enrolled\n", argv[0], mytid); if (mytid < 0) { pvm_perror(argv[0]); return -1; } if (argc != 2) goto usage; if ((nproc = atoi(argv[1])) < 1) goto usage; if (nproc > 32) goto usage; /* join a group */ /* the group name is the last path of the path name */ gp = RINDEX(argv[0],'/'); if (gp == 0) gp = argv[0]; else gp++; mygid = pvm_joingroup(gp); fprintf(stderr, "%s 0x%x %d\n", gp, mytid, mygid); if (mygid < 0) { pvm_exit(); return -1; } /* if I'm the first to join then start the others */ if (mygid == 0) { /* start a bunch of children */ pvm_spawn(gp, argv+1, PvmTaskDefault, "", nproc-1, ctid); /* check them */ for (i = 0; i < nproc-1; i++) fprintf(stderr, "0x%x\n", ctid[i]); } /* sync on a barrier */ if (pvm_barrier(gp, nproc) < 0) { pvm_perror(argv[0]); pvm_lvgroup(argv[0]); pvm_exit(); return -1; } fprintf(stderr, "%s %d: sync\n", argv[0], mygid); /* everyone broadcast their gids and tids */ pvm_initsend(PvmDataDefault); pvm_pkint(&mygid, 1, 1); pvm_pkint(&mytid, 1, 1); pvm_bcast(gp, 63); /* recv all the gids and tids (except from myself) */ ctid[mygid] = mytid; for (i = 0; i < nproc-1; i++) { pvm_recv(-1, 63); pvm_upkint(&indx, 1, 1); pvm_upkint(ctid+indx, 1, 1); } /* check to make sure the gids and tids are correct */ for (i = 0; i < nproc; i++) { if (i != pvm_getinst(gp, ctid[i])) { fprintf(stderr, "gid %d doesn't match up!\n", i); } if (ctid[i] != pvm_gettid(gp, i)) { fprintf(stderr, "gid %d doesn't match up!\n", i); } } /* leave the group */ pvm_barrier(gp,nproc); if(pvm_lvgroup(gp) < 0) pvm_perror(gp); pvm_exit(); return 0; usage: fprintf(stderr, "usage: %s \n", argv[0]); return -1; } ./pvm3/gexamples/gs.c0100644007401100000360000000451206373622026013652 0ustar kohlgopher static char rcsid[] = "$Id: gs.c,v 1.3 1997/08/11 14:39:18 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* Using pvm_gsize() */ #include #include "pvm3.h" #define GSGROUP "gsgroup" int main(argc, argv) int argc; char *argv[]; { int mytid, mygid, ctid[32]; int nproc, i; mytid = pvm_mytid(); fprintf(stderr, "%s 0x%x enrolled\n", argv[0], mytid); if (mytid < 0) { pvm_perror(argv[0]); return -1; } if (argc != 2) goto usage; if ((nproc = atoi(argv[1])) < 1) goto usage; if (nproc > 32) goto usage; /* join a group */ mygid = pvm_joingroup(GSGROUP); /* if I'm the first to join then start the others */ if (mygid == 0) { /* start a bunch of children */ pvm_spawn(argv[0], argv+1, 0, "", nproc-1, ctid); /* check them */ for (i = 0; i < nproc-1; i++) fprintf(stderr, "0x%x\n", ctid[i]); } while(pvm_gsize(GSGROUP) < nproc) if (mygid == 0) fputs("waiting on kids to join\n", stderr); /* sync */ pvm_barrier(GSGROUP, nproc); /* leave the group */ if(pvm_lvgroup(GSGROUP) < 0) pvm_perror(argv[0]); pvm_exit(); return 0; usage: fprintf(stderr, "usage: %s \n", argv[0]); return -1; } ./pvm3/gexamples/joinleave.c0100644007401100000360000000400106672252622015211 0ustar kohlgopher static char rcsid[] = "$Id: joinleave.c,v 1.3 1999/03/12 17:57:38 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* join and leave a lot */ #include #include "pvm3.h" #define MAXJOINS 10000 int main(argc, argv) int argc; char *argv[]; { int mytid, mygid, njoins; int cnt = 0; mytid = pvm_mytid(); fprintf(stderr, "%s 0x%x enrolled\n", argv[0], mytid); if (mytid < 0) { pvm_perror(argv[0]); return -1; } if (argc > 1) njoins = atoi(argv[1]); else njoins = MAXJOINS; /* join a group */ while (cnt++ <= njoins) { if((mygid = pvm_joingroup("JoinLeave")) < 0) { pvm_perror("JoinLeave"); break; } if((mygid = pvm_lvgroup("JoinLeave")) < 0) { pvm_perror("JoinLeave"); break; } if ((cnt%100)==0) printf("Joined %d times\n", cnt); } return 0; } ./pvm3/gexamples/thb.c0100644007401100000360000000653406672252621014026 0ustar kohlgopher static char rcsid[] = "$Id: thb.c,v 1.3 1999/03/12 17:57:37 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* Join a bunch of groups and do some barriers */ #include #include "pvm3.h" #define MAXGNAME 32 /* used to be a constant, length not important */ #define MAXGTIDS 32 /* used to be a constant, Number not important */ #define MAXNGROUPS 32 /* used to be constant, Number not important */ int main(argc, argv) int argc; char *argv[]; { int mytid, ctid[MAXGTIDS]; int nproc; char g[MAXGNAME]; int cc; int gid[MAXNGROUPS], gs; int i; if (argc != 2) goto usage; if ((nproc = atoi(argv[1])) < 1) goto usage; mytid = pvm_mytid(); if (mytid < 0) { pvm_perror(argv[0]); return -1; } /* join a bunch of groups */ for (i = 0; i < MAXNGROUPS; i++) { sprintf(g, "group%d", i); if((gid[i] = pvm_joingroup(g)) < 0) { pvm_perror("joining"); } fprintf(stderr, "joined %s\n", g); } /* test that i'm in the groups */ for (i = MAXNGROUPS-1; i >= 0; i--) { sprintf(g, "group%d", i); if(gid[i] != (cc = pvm_getinst(g, mytid))) { fprintf(stderr, "I'm not myself %d %s\n", cc, g); pvm_perror("getinst"); } if(mytid != (cc = pvm_gettid(g, gid[i]))) { fprintf(stderr, "I'm not myself %d %s\n", cc, g); pvm_perror("gettid"); } } /* start a bunch of children */ printf("spawning ... "); pvm_spawn("tnb", (char**)0, 0, "", nproc, ctid); for (i = 0; i < nproc; i++) { if (ctid[i] < 0) { fprintf(stderr, "trouble on spawn number %d\n", ctid[i]); pvm_perror("th:"); } else { int foo; foo = nproc+1; /* send a group name to the child */ pvm_initsend(PvmDataDefault); pvm_pkstr(g); pvm_pkint(&foo, 1, 1); pvm_send(ctid[i], 5); } } printf ("barrier on %s \n", g); pvm_barrier(g, nproc+1); pvm_initsend(PvmDataDefault); pvm_bcast(g, 77); printf(" leaving all the groups \n"); /* leave the groups */ for (i = 0; i < MAXNGROUPS; i++) { sprintf(g, "group%d", i); if(pvm_lvgroup(g) < 0) pvm_perror("pvm_lvgroup"); } pvm_exit(); printf("done.\n"); return 0; usage: fprintf(stderr, "usage: %s \n", argv[0]); return -1; } ./pvm3/gexamples/tjf.c0100644007401100000360000000500206672252617014026 0ustar kohlgopher static char rcsid[] = "$Id: tjf.c,v 1.3 1999/03/12 17:57:35 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* test join fail, cause join to fail */ #include #include "pvm3.h" #define MAXGNAME 32 /* used to be a constant, length not important */ #define MAXGTIDS 32 /* used to be a constant, Number not important */ #define MAXNGROUPS 32 /* used to be constant, Number not important */ int main(argc, argv) int argc; char *argv[]; { int mytid, ctid[MAXGTIDS]; char g[MAXGNAME]; int cc; int gid[MAXGTIDS], gs; int i; mytid = pvm_mytid(); if (mytid < 0) { pvm_perror("th"); return -1; } /* join one too many groups */ for (i = 0; i < MAXNGROUPS+1; i++) { sprintf(g, "group%d", i); if((gid[i] = pvm_joingroup(g)) < 0) { pvm_perror("joining"); } fprintf(stderr, "joined %s\n", g); } /* test that i'm in the groups */ for (i = MAXNGROUPS-1; i >= 0; i--) { sprintf(g, "group%d", i); if(gid[i] != (cc = pvm_getinst(g, mytid))) { fprintf(stderr, "I'm not myself %d %s\n", cc, g); pvm_perror("getinst"); } if(mytid != (cc = pvm_gettid(g, gid[i]))) { fprintf(stderr, "I'm not myself %d %s\n", cc, g); pvm_perror("gettid"); } } for (i = 0; i < MAXNGROUPS; i++) { sprintf(g, "group%d", i); if(pvm_lvgroup(g) < 0) pvm_perror("pvm_lvgroup"); } pvm_exit(); return 0; } ./pvm3/gexamples/tjl.c0100644007401100000360000000474706672252620014045 0ustar kohlgopher static char rcsid[] = "$Id: tjl.c,v 1.3 1999/03/12 17:57:36 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* test join/leave */ #include #include "pvm3.h" #define MAXGNAME 32 /* used to be constant, length not important */ #define MAXGTIDS 32 /* used to be constant, Number not important */ #define MAXNGROUPS 32 /* used to be constant, Number not important */ int main(argc, argv) int argc; char *argv[]; { int mytid, ctid[MAXGTIDS]; char g[MAXGNAME]; int cc; int gid[MAXGTIDS], gs; int i; mytid = pvm_mytid(); if (mytid < 0) { pvm_perror("th"); return -1; } /* join a bunch of groups */ for (i = 0; i < MAXNGROUPS; i++) { sprintf(g, "group%d", i); if((gid[i] = pvm_joingroup(g)) < 0) { pvm_perror("joining"); } fprintf(stderr, "joined %s\n", g); } /* test that i'm in the groups */ for (i = MAXNGROUPS-1; i >= 0; i--) { sprintf(g, "group%d", i); if(gid[i] != (cc = pvm_getinst(g, mytid))) { fprintf(stderr, "I'm not myself %d %s\n", cc, g); pvm_perror("getinst"); } if(mytid != (cc = pvm_gettid(g, gid[i]))) { fprintf(stderr, "I'm not myself %d %s\n", cc, g); pvm_perror("gettid"); } } for (i = 0; i < MAXNGROUPS; i++) { sprintf(g, "group%d", i); if(pvm_lvgroup(g) < 0) pvm_perror("pvm_lvgroup"); } pvm_exit(); return 0; } ./pvm3/gexamples/tnb.c0100644007401100000360000000323706360710745014031 0ustar kohlgopher static char rcsid[] = "$Id: tnb.c,v 1.2 1997/07/09 13:28:05 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* test bcast node */ #include #include "pvm3.h" int main(argc, argv) int argc; char *argv[]; { int mytid; char g[32]; int cc, ngroup; int gid; mytid = pvm_mytid(); pvm_recv(pvm_parent(), 5); pvm_upkstr(g); pvm_upkint(&ngroup, 1, 1); gid = pvm_joingroup(g); pvm_barrier(g, ngroup); pvm_recv(pvm_parent(), 77); pvm_lvgroup(g); pvm_exit(); } ./pvm3/gexamples/trsg.c0100644007401100000360000001605406673254714014234 0ustar kohlgopher static char rcsid[] = "$Id: trsg.c,v 1.5 1999/03/15 19:04:44 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * Example of group Reduce, Scatter, and Gather functions - J.M. Donato * * This example calculates the sum of squares of the first N integers * in three different ways where * * N = (number of processors)*(number of elements per row) * * Note: This is obviously not an efficient way to compute the * sum of squares, but it is a cutesy example and test case. */ #include #include "pvm3.h" #define MAXNDATA 20 #define MAXNPROCS 16 #define DFLTNDATA 5 #define DFLTNPROCS 4 #define TASK_NAME "trsg" #ifdef WIN32 #undef min #undef max #endif #define min(x,y) ( ((x)<(y))? (x) : (y) ) #define max(x,y) ( ((x)>(y))? (x) : (y) ) extern void PvmMin(); extern void PvmMax(); extern void PvmSum(); extern void PvmProduct(); void MaxWithLoc(); main() { int myginst, i, j, gsize, count, nprocs, msgtag, datatype; int info_product, info_user; int tids[MAXNPROCS], myrow[MAXNDATA], matrix[MAXNDATA*MAXNPROCS]; float values[2]; int midpoint, bigN, Sum1=0, Sum2=0, SumSquares, rootginst; int PSum = 0, PartSums[MAXNPROCS], dupls[MAXNDATA]; char *gname = "group_rsg"; /* join the group */ myginst = pvm_joingroup(gname); pvm_setopt(PvmAutoErr, 1); /* I am the first group member, get input, start up copies of myself */ if ( myginst == 0 ) { if (pvm_parent() == PvmNoParent) { printf("\n *** Example use of PVM Reduce, Scatter, and Gather *** "); printf("\n Number of processors to use (1-%d)? : ", MAXNPROCS); scanf("%d", &nprocs); if (nprocs > MAXNPROCS) nprocs = MAXNPROCS; printf(" Number of elements per row to use (1-%d)? : ", MAXNDATA); scanf("%d", &count); if (count > MAXNDATA) count = MAXNDATA; printf(" INPUT values: nprocs = %d, count = %d \n", nprocs, count); } else { count = DFLTNDATA; nprocs = DFLTNPROCS; } tids[0] = pvm_mytid(); if (nprocs > 1) pvm_spawn(TASK_NAME, (char**)0, 0, "", nprocs-1, &tids[1]); /* wait until they have all started, then send input values */ while (gsize = pvm_gsize(gname) < nprocs) pvmsleep(1); pvm_initsend(PvmDataDefault); pvm_pkint(&nprocs, 1, 1); pvm_pkint(&count, 1, 1); pvm_bcast(gname, msgtag=17); } else { /* receive the input values */ pvm_recv(-1, msgtag=17); pvm_upkint(&nprocs, 1, 1); pvm_upkint(&count, 1, 1); } rootginst = 0; /* determine the group root */ /* init the matrix values on the root processor */ if (myginst == rootginst) for (j=0; j x[i]) { x[i] = y[i]; x[i+count] = y[i+count]; } else if (y[i] == x[i]) x[i+count] = min(x[i+count], y[i+count]); *info = PvmOk; return; } /* end MaxWithLoc() */ ./pvm3/gexamples/tst.c0100644007401100000360000000332106360710747014054 0ustar kohlgopher static char rcsid[] = "$Id: tst.c,v 1.2 1997/07/09 13:28:07 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* test groups */ int main(argc, argv) int argc; char *argv[]; { int mytid, mygid1, mygid2, mygid3; mytid = pvm_mytid(); mygid1 = pvm_joingroup("prognosis"); mygid2 = pvm_joingroup("negative"); printf("joined prognosis %d, negative %d\n", mygid1, mygid2); mygid1 = pvm_lvgroup("prognosis"); mygid2 = pvm_lvgroup("negative"); printf("left prognosis %d, negative %d\n", mygid1, mygid2); pvm_exit(); } ./pvm3/gexamples/frsg.f0100644007401100000360000001600306673254715014214 0ustar kohlgopherc c $Id: frsg.f,v 1.3 1999/03/15 19:04:45 pvmsrc Exp $ c c*---------------------------------------------------------------------- c* Example of group Reduce, Scatter, and Gather functions - J.M. Donato c* c* This example calculates the sum of squares of the first N integers c* in three different ways where c* c* N = (number of processors)*(number of elements per row) c* c* Note: This is obviously not an efficient way to compute the c* sum of squares, but it is a cutesy example and test case. c*---------------------------------------------------------------------- program main implicit none include '../include/fpvm3.h' external PvmMin external PvmMax external PvmSum external PvmProduct external MaxWithLoc integer MAXNDATA, MAXNPROCS, DFLTNDATA, DFLTNPROCS character*10 GROUP, TASK_NAME parameter (MAXNDATA = 20, MAXNPROCS = 16, & DFLTNDATA = 5, DFLTNPROCS = 4, & GROUP = 'grp_frsg', TASK_NAME = 'frsg') integer myginst, i, j, gsize, count, nprocs, msgtag, datatype, & buffer, info, info_product, info_user, & tids(MAXNPROCS), myrow(MAXNDATA), matrix(MAXNDATA*MAXNPROCS), & midpoint, bigN, Sum1, Sum2, SumSquares, rootginst, & PSum, PartSums(MAXNPROCS), dupls(MAXNDATA) double precision values(2) data Sum1/0/, Sum2/0/ c* join the group call PvmfJoinGroup(GROUP, myginst) c* I am the first group member, get input, start up copies of myself if ( myginst.eq.0 ) then call PvmfMyTid(tids(1)) call PvmfParent(i) if (i .eq. PvmNoParent) then print *, '/ * Example: PVM Reduce, Scatter, and Gather * ', & '/ Number of processors to use (1-', MAXNPROCS,')? : ' read *, nprocs if (nprocs.gt.MAXNPROCS) nprocs = MAXNPROCS print *, ' Number of elements per row to use (1-', & MAXNDATA, ')? : ' read *, count if (count.gt.MAXNDATA) count = MAXNDATA else nprocs = DFLTNPROCS count = DFLTNDATA endif print *, ' INPUT values: nprocs = ', nprocs, ', count = ', count if ( nprocs.gt.1 ) then call PvmfSpawn(TASK_NAME, PvmDefault, '*', & nprocs-1, tids(2), info) c* wait until they have all started, then send input values call PvmfGsize(GROUP, gsize) 9000 continue if ( gsize.lt.nprocs) then call PvmfSleep(1) call PvmfGsize(GROUP, gsize) go to 9000 end if call PvmfInitsend(PvmDataDefault, buffer) call PvmfPack(INTEGER4, nprocs, 1, 1, info) call PvmfPack(INTEGER4, count, 1, 1, info) msgtag = 17 call PvmfBcast(GROUP, msgtag, info) end if else c* receive the input values if child node msgtag = 17 call PvmfRecv(-1, msgtag, info) call PvmfUnpack(INTEGER4, nprocs, 1, 1, info) call PvmfUnpack(INTEGER4, count, 1, 1, info) end if c* determine the group root rootginst = 0 c* init the matrix values on the root processor if ( myginst.eq.rootginst ) then do j=1, nprocs do i=1, count matrix((j-1)*count + i) = (j-1)*count + i end do end do end if c* scatter rows of matrix to each processor msgtag = 19 call PvmfScatter(myrow, matrix, count, INTEGER4, msgtag, & GROUP, rootginst, info) c* this should end up squaring each value on each processor do i=1, count dupls(i) = myginst*count + i end do datatype = INTEGER4 call PvmProduct(datatype, myrow, dupls, count, info_product) if ((myginst.eq.rootginst).and.(info_product.lt.0)) & print *, ' ERROR: ', info_product, ' on PvmProduct call ' c* do partial sum on each proc do i=1, count PSum = PSum + myrow(i) end do c* gather partial sums to the rootginst msgtag = 21 call PvmfGather(PartSums, PSum, 1, INTEGER4, msgtag, & GROUP, rootginst, info) c* do a global sum over myrow, the result goes to rootginst msgtag = 23 call PvmfReduce(PvmSum, myrow, count, INTEGER4, msgtag, & GROUP, rootginst, info) c* init values and include location information on each processor midpoint = nprocs/2 values(1) = -(myginst - midpoint)*(myginst-midpoint) + count values(2) = myginst c* use a user-defined function in reduce, send answer to rootginst msgtag = 25 call PvmfReduce(MaxWithLoc, values, 2, REAL8, & msgtag, GROUP, rootginst, info_user) bigN = nprocs*count if (myginst.eq.rootginst) then c* Complete the Sum of Squares using different methods do i=1, nprocs Sum1 = Sum1 + PartSums(i) end do do i=1, count Sum2 = Sum2 + myrow(i) end do SumSquares = bigN*(bigN+1)*(2*bigN+1)/6 if ( (Sum1.eq.SumSquares) .and. (Sum2.eq.SumSquares)) then print *, '/ Test OK: Sum of Squares of first ', bigN, & ' integers is ', Sum1 else print *, '/ ERROR: The Sum of Squares of the first ', bigN, & ' integers / was calculated by Sum1 as ', Sum1, & ' and by Sum2 as ', Sum2, & ' for both it should have been ', SumSquares end if if (info_user.lt.0) & print *, ' ERROR: ', info_user, ' on User Reduce Function' if ((values(1).ne.count) .or. (values(2).ne.midpoint)) then print *, ' ERROR: Should have (', count, ', ', midpoint, & '), but have (', values(1), ',', values(2) else print *, ' Test Ok: Received (', values(1), ',', & values(2), ') ' end if end if c* sync up again, leave group, exit pvm call PvmfBarrier(GROUP, nprocs, info) call PvmfLvgroup(GROUP, info) call PvmfExit(info) stop end c* c* This function returns the elementwise maximum of two vectors c* along with location information. c* c* The first num/2 values of x and y are the data values to compare. c* The second num/2 values of x and y are location information c* which is kept with the maximum value determined. c* c* In the case of a tie in data values, the smaller location c* is kept to insure the associativity of the operation. c* subroutine MaxWithLoc(datatype, x, y, num, info) implicit none integer datatype, num, info double precision x(*), y(*) include '../include/fpvm3.h' integer i, count count = num/2 if (datatype.ne.REAL8) then info = PvmBadParam return end if do i=1, count if (y(i).gt.x(i)) then x(i) = y(i) x(i+count) = y(i+count) elseif (y(i).eq.x(i)) then x(i+count) = min(x(i+count), y(i+count)) end if end do info = PvmOk return end ./pvm3/gexamples/CSPP/0042755007401100000360000000000010117676455013653 5ustar kohlgopher./pvm3/gexamples/CSPP/Makefile0100644007401100000360000000405506604767600015311 0ustar kohlgopher# # $Id: Makefile,v 1.4 1998/10/01 21:09:20 pvmsrc Exp $ # # Makefile for PVM group library example programs. # # Set PVM_ROOT to the path where PVM includes and libraries are installed. # Set PVM_ARCH to your architecture type (SUN4, HP9K, RS6K, SGI, etc.) # Set ARCHLIB to any special libs needed on PVM_ARCH (-lrpc, -lsocket, etc.) # otherwise leave ARCHLIB blank # # PVM_ARCH and ARCHLIB, among other things, are set for you if you # use "$PVM_ROOT/lib/aimk" instead of "make". # PVM_ARCH = CSPP ARCHLIB = -lcnx_syscall /lib/libail.sl PVMDIR = ../.. SDIR = $(PVMDIR)/gexamples BDIR = $(PVMDIR)/bin XDIR = $(BDIR)/$(PVM_ARCH) PVMIDIR = $(PVMDIR)/include PVMLDIR = $(PVMDIR)/lib/$(PVM_ARCH) PVMLIB = -Wl,-aarchive -lgpvm3 -lpvm3 $(ARCHLIB) CC = /usr/convex/bin/cc -Wl,+tmspp1 CFLAGS = $(CFLOPTS) -cxdb -no -I$(PVMIDIR) -L$(PVMLDIR) FORT = /usr/convex/bin/fc -Wl,+tmspp1 FFLAGS = $(FFLOPTS) -cxdb -no -I$(PVMIDIR) -L$(PVMLDIR) PVMFLIB = -Wl,-aarchive -lfpvm3 $(PVMLIB) all: joinleave gexamp tst thb tnb ge tjl tjf trsg frsg gs joinleave: $(SDIR)/joinleave.c $(CC) $(CFLAGS) -o joinleave $(SDIR)/joinleave.c $(PVMLIB) mv joinleave $(XDIR) tst: $(SDIR)/tst.c $(CC) $(CFLAGS) -o tst $(SDIR)/tst.c $(PVMLIB) mv tst $(XDIR) gs: $(SDIR)/gs.c $(CC) $(CFLAGS) -o gs $(SDIR)/gs.c $(PVMLIB) mv gs $(XDIR) ge: $(SDIR)/ge.c $(CC) $(CFLAGS) -o ge $(SDIR)/ge.c $(PVMLIB) mv ge $(XDIR) gexamp: $(SDIR)/gexamp.c $(CC) $(CFLAGS) -o gexamp $(SDIR)/gexamp.c $(PVMLIB) mv gexamp $(XDIR) thb: $(SDIR)/thb.c $(CC) $(CFLAGS) -o thb $(SDIR)/thb.c $(PVMLIB) mv thb $(XDIR) tnb: $(SDIR)/tnb.c $(CC) $(CFLAGS) -o tnb $(SDIR)/tnb.c $(PVMLIB) mv tnb $(XDIR) tjl: $(SDIR)/tjl.c $(CC) $(CFLAGS) -o tjl $(SDIR)/tjl.c $(PVMLIB) mv tjl $(XDIR) tjf: $(SDIR)/tjf.c $(CC) $(CFLAGS) -o tjf $(SDIR)/tjf.c $(PVMLIB) mv tjf $(XDIR) trsg: $(SDIR)/trsg.c $(CC) $(CFLAGS) -o trsg $(SDIR)/trsg.c $(PVMLIB) mv trsg $(XDIR) frsg: $(SDIR)/frsg.f $(FORT) $(FFLAGS) -o frsg $(SDIR)/frsg.f $(PVMFLIB) mv frsg $(XDIR) clean: rm -f *.o tst thb tnb tjl tjf ge gexamp gs joinleave trsg frsg ./pvm3/gexamples/OS2/0042755007401100000360000000000010117676455013511 5ustar kohlgopher./pvm3/gexamples/OS2/Makefile0100644007401100000360000000050506401362514015131 0ustar kohlgopher# # $Id: Makefile,v 1.2 1997/08/28 20:53:32 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/gexamples PVM_ARCH = OS2 CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) all: make FORT=g77 -f $(CONFFILE) -f $(SDIR)/Makefile.aimk all clean: make -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean ./pvm3/gexamples/PGON/0042755007401100000360000000000010117676455013651 5ustar kohlgopher./pvm3/gexamples/PGON/Makefile0100644007401100000360000000342406334375153015304 0ustar kohlgopher# # $Id: Makefile,v 1.3 1997/05/08 16:08:11 pvmsrc Exp $ # # Custom section # Set ARCH to your architecture type (SUN4, HP9K, RS6K, SGI, etc) # if ARCH = BSD386 then set ARCHLIB = -lrpc # if ARCH = SGI then set ARCHLIB = -lsun # if ARCH = I860 then set ARCHLIB = -lrpc -lsocket # if ARCH = IPSC2 then set ARCHLIB = -lrpc -lsocket # otherwise leave ARCHLIB blank # # ARCH and ARCHLIB are set for you if you use 'aimk'. # #PVM_ARCH = PGON ARCHLIB = -lrpc -lnx # END of custom section - leave this line here # PVMDIR = ../.. PVMLIB = $(PVMDIR)/lib/$(PVM_ARCH)/libpvm3.a PVMPELIB = $(PVMDIR)/lib/$(PVM_ARCH)/libpvm3pe.a SDIR = $(PVMDIR)/gexamples BDIR = $(PVMDIR)/bin XDIR = $(BDIR)/$(PVM_ARCH) CC = icc CFLOPTS = -O CFLAGS = $(CFLOPTS) -I$(PVMDIR)/include LIBS = $(PVMLIB) $(ARCHLIB) NODELIBS = $(PVMPELIB) $(ARCHLIB) GLIBS = $(PVMDIR)/lib/$(PVM_ARCH)/libgpvm3.a F77 = if77 FFLOPTS = -O FFLAGS = $(FFLOPTS) FLIBS = $(PVMDIR)/lib/$(PVM_ARCH)/libfpvm3.a FPELIBS = $(FLIBS) default: gexamp all: joinleave gexamp thb tnb trsg frsg $(XDIR): $(BDIR) - mkdir $(XDIR) $(BDIR): - mkdir $(BDIR) joinleave: $(SDIR)/joinleave.c $(CC) $(CFLAGS) -o joinleave $(SDIR)/joinleave.c $(GLIBS) $(NODELIBS) mv joinleave $(XDIR) gexamp: $(SDIR)/gexamp.c $(CC) $(CFLAGS) -o gexamp $(SDIR)/gexamp.c $(GLIBS) $(NODELIBS) mv gexamp $(XDIR) thb: $(SDIR)/thb.c $(CC) $(CFLAGS) -o thb $(SDIR)/thb.c $(GLIBS) $(NODELIBS) mv thb $(XDIR) tnb: $(SDIR)/tnb.c $(CC) $(CFLAGS) -o tnb $(SDIR)/tnb.c $(GLIBS) $(NODELIBS) mv tnb $(XDIR) trsg: $(SDIR)/trsg.c $(CC) $(CFLAGS) -o trsg $(SDIR)/trsg.c $(GLIBS) $(NODELIBS) mv trsg $(XDIR) frsg: $(SDIR)/frsg.f $(F77) $(FFLAGS) -o frsg $(SDIR)/frsg.f $(FPELIBS) $(GLIBS) $(NODELIBS) mv frsg $(XDIR) clean: rm -f *.o thb tnb gexamp joinleave trsg frsg ./pvm3/hoster/0042755007401100000360000000000010117676455012425 5ustar kohlgopher./pvm3/hoster/Makefile.aimk0100644007401100000360000000245206401351735014773 0ustar kohlgopher# # $Id: Makefile.aimk,v 1.8 1997/08/28 19:39:09 pvmsrc Exp $ # # Generic Makefile body to be concatenated to config header. # # Imports: # PVM_ARCH = the official pvm-name of your processor # ARCHCFLAGS = special cc flags # ARCHLIB = special libs needed for daemon # SHELL = /bin/sh PVMDIR = ../.. PVMIDIR = $(PVMDIR)/include PVMSDIR = $(PVMDIR)/src PVMLDIR = $(PVMDIR)/lib/$(PVM_ARCH) PVMLIB = pvm3 LIBPREFIX = lib PVMLIBDEP = $(PVMLDIR)/$(LIBPREFIX)$(PVMLIB).a SDIR = $(PVMDIR)/hoster BDIR = $(PVMDIR)/bin XDIR = $(BDIR)/$(PVM_ARCH) CFLOPTS = -O CFLAGS = $(CFLOPTS) -I$(PVMIDIR) -I$(PVMSDIR) -DIMA_$(PVM_ARCH) \ $(ARCHCFLAGS) LIBS = -L$(PVMLDIR) -l$(PVMLIB) $(ARCHLIB) HEADERS = $(PVMIDIR)/pvm3.h $(PVMIDIR)/pvmproto.h REXECOBJ = default: all all: $(XDIR)/hoster$(EXESFX) $(XDIR): - mkdir $(BDIR) - mkdir $(XDIR) $(XDIR)/hoster$(EXESFX): $(XDIR) hoster$(EXESFX) cp hoster$(EXESFX) $(XDIR) hoster$(EXESFX): $(SDIR)/hoster.c $(HEADERS) $(PVMLIBDEP) $(REXECOBJ) $(CC) $(CFLAGS) -o $@ $(SDIR)/hoster.c $(REXECOBJ) $(LIBS) rexec.o: $(PVMDIR)/src/$(PVM_ARCH)/src/rexec.c $(CC) $(CFLAGS) -c $(PVMDIR)/src/$(PVM_ARCH)/src/rexec.c ruserpas.o: $(PVMDIR)/src/$(PVM_ARCH)/src/ruserpas.c $(CC) $(CFLAGS) -c $(PVMDIR)/src/$(PVM_ARCH)/src/ruserpas.c clean: rm -f *.o hoster$(EXESFX) ./pvm3/hoster/Makefile.mak0100644007401100000360000000313506670011723014617 0ustar kohlgopher# # $Id: Makefile.mak,v 1.7 1999/03/05 17:26:43 pvmsrc Exp $ # #*************************************************************# #** **# #** Nmake file for the PVM hoster **# #** hoster.exe **# #** **# #** **# #*************************************************************# !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !include $(PVM_ROOT)\conf\$(PVM_ARCH).def SDIR = $(PVM_ROOT)\src HDIR = $(PVM_ROOT)\hoster OBJS = $(PVM_ARCH)\hoster.obj $(PVM_ARCH)\pvmwinrexec.obj \ $(PVM_ARCH)\pvmwinrsh.obj all: paths hoster.exe # paths: if not exist "$(PVM_ROOT)\bin\$(PVM_ARCH)\$(NULL)" mkdir "$(PVM_ROOT)\bin\$(PVM_ARCH)" if not exist "$(PVM_ARCH)\$(NULL)" mkdir "$(PVM_ARCH)" hoster.exe: $(OBJS) $(linkexe) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\bin\$(PVM_ARCH)\hoster.exe \ $(OBJS) $(PVM_ROOT)\lib\$(PVM_ARCH)\libpvm3.lib \ $(link_multithread) /nodefaultlib:libc.lib $(PVM_ARCH)\hoster.obj: $(HDIR)\hoster.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\hoster.obj $(HDIR)\hoster.c $(PVM_ARCH)\pvmwinrexec.obj: $(HDIR)\pvmwinrexec.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmwinrexec.obj \ $(HDIR)\pvmwinrexec.c $(PVM_ARCH)\pvmwinrsh.obj: $(HDIR)\pvmwinrsh.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmwinrsh.obj \ $(HDIR)\pvmwinrsh.c # Clean up everything but the .EXEs clean : -del *.obj -del *.pdb ./pvm3/hoster/Readme0100644007401100000360000000043006221575517013533 0ustar kohlgopher Example hoster program 01 Mar 1994 ________________________________________________________________________ This is an example hoster (slave pvmd starter) program. It worked at one point and I think still does, but it's not supported or anything, just here as an example. b ./pvm3/hoster/hoster.c0100644007401100000360000005466207354443345014104 0ustar kohlgopher static char rcsid[] = "$Id: hoster.c,v 1.18 2001/09/26 21:21:41 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * hoster.c * * Example hoster task to demonstrate and verify the protocol. * This code was cut out of the pvmd default hoster in startup.c, * and minimally modified to make it compile here. * * 24 Jan 1994 Manchek */ #ifdef HASSTDLIB #include #endif #include #include #include #ifndef WIN32 #include #include #endif #ifdef NEEDSSELECTH #include #endif #ifdef SYSVSTR #include #define CINDEX(s,c) strchr(s,c) #else #include #define CINDEX(s,c) index(s,c) #endif #include #include #include "bfunc.h" #ifdef WIN32 #include "pvmwin.h" #endif #ifndef RSHTIMEOUT #define RSHTIMEOUT 100 #endif /* if > 1, uses parallel startup strategy */ #ifndef RSHNPLL #define RSHNPLL 5 #endif #ifndef max #define max(a,b) ((a)>(b)?(a):(b)) #endif #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif #ifdef WIN32 #define close(fd) _close(fd) #endif #define TALLOC(n,t,g) (t*)malloc((n)*sizeof(t)) #define FREE(p) free((char *)p) #define STRALLOC(s) strcpy(TALLOC(strlen(s)+1,char,"str"),s) #define LISTPUTAFTER(o,n,f,r) \ { (n)->f=(o)->f; (n)->r=(o); (o)->f->r=(n); (o)->f=(n); } #define LISTPUTBEFORE(o,n,f,r) \ { (n)->r=(o)->r; (n)->f=(o); (o)->r->f=(n); (o)->r=(n); } #define LISTDELETE(e,f,r) \ { (e)->f->r=(e)->r; (e)->r->f=(e)->f; (e)->r=(e)->f=0; } #define TVCLEAR(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0) #define TVISSET(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) #define TVXLTY(xtv, ytv) \ ((xtv)->tv_sec < (ytv)->tv_sec || \ ((xtv)->tv_sec == (ytv)->tv_sec && (xtv)->tv_usec < (ytv)->tv_usec)) #define TVXADDY(ztv, xtv, ytv) \ if (((ztv)->tv_usec = (xtv)->tv_usec + (ytv)->tv_usec) < 1000000) { \ (ztv)->tv_sec = (xtv)->tv_sec + (ytv)->tv_sec; \ } else { \ (ztv)->tv_usec -= 1000000; \ (ztv)->tv_sec = (xtv)->tv_sec + (ytv)->tv_sec + 1; \ } #define TVXSUBY(ztv, xtv, ytv) \ if ((xtv)->tv_usec >= (ytv)->tv_usec) { \ (ztv)->tv_sec = (xtv)->tv_sec - (ytv)->tv_sec; \ (ztv)->tv_usec = (xtv)->tv_usec - (ytv)->tv_usec; \ } else { \ (ztv)->tv_sec = (xtv)->tv_sec - (ytv)->tv_sec - 1; \ (ztv)->tv_usec = (xtv)->tv_usec + 1000000 - (ytv)->tv_usec; \ } /* * for keeping state assoc. with a host */ struct hst { int h_tid; char *h_name; char *h_login; char *h_sopts; int h_flag; #define HST_PASSWORD 1 /* ask for a password */ #define HST_MANUAL 2 /* do manual startup */ char *h_cmd; char *h_wincmd; /* alternate WIN32 default pvmd cmd */ char *h_vmid; /* optional virtual machine ID */ char *h_result; }; struct slot { struct slot *s_link, *s_rlink; /* free/active list */ struct hst *s_hst; /* host table entry */ struct timeval s_bail; /* timeout time */ int s_rfd, s_wfd, s_efd; /* slave stdin/out/err */ char s_buf[256]; /* stdout from host */ char s_ebuf[256]; /* stderr from host */ int s_len; /* length of s_buf */ int s_elen; /* length of s_ebuf */ }; /*************** ** Globals ** ** ** ***************/ #ifndef HASERRORVARS extern int errno; #endif /* 0 turns off -- set to 1 to activate error messages in hoster */ int debugmask = 0; #ifndef WIN32 char *username = 0; #else extern char* username; extern int rsh( char *hostname, char *username, char *command, char *retresult ); #endif char *pvmgetrsh(); /*************** ** Private ** ** ** ***************/ static struct slot slots[RSHNPLL+2]; /* state var/ctx each slot */ static struct slot *slfree = 0; /* free list of slots */ int main(argc, argv) int argc; char **argv; { #ifdef WIN32 static int init = 0; static int needed = 1; #else struct passwd *pe; int uid; if ((uid = getuid()) == -1) { fprintf(stderr, "main() can't getuid()\n"); exit(1); } if (pe = getpwuid(uid)) username = STRALLOC(pe->pw_name); else fprintf(stderr, "main() can't getpwuid\n"); endpwent(); #endif pvm_mytid(); pvm_reg_hoster(); pvm_setopt(PvmResvTids, 1); #ifndef WIN32 printf("*** PVM pvmd starter ***\n"); #endif while (pvm_recv(-1, SM_STHOST) > 0) { #ifdef WIN32 AllocConsole(); GetStdHandle(STD_OUTPUT_HANDLE); if (init) printf( "***need more ? ***\n"); #endif hoster(); #ifdef WIN32 if (!init) { printf( "*** PVM %s pvmd starter ***\n", PVM_VER); printf( "*** This window will show what your 'add command' is doing. ***\n"); printf( "*** Also, if required, this is where you type in passwords. ***\n"); printf( "*** This window will display each time you add machines. ***\n"); Sleep(15000); FreeConsole(); init=1; } Sleep(1500); FreeConsole(); #endif } pvm_exit(); exit(0); #ifdef WIN32 return(0); #endif } /* hoster() * * Unpack host table from message, attempt to start 'em up, * send reply message. */ hoster() { int num; int i; struct hst **hostlist; struct hst *hp; char *p; char sopts[64]; char lognam[256]; char cmd[512]; char wincmd[512]; char vmid[256]; int fromtid; int wid; struct pvmminfo minfo; /* * unpack the startup message */ pvm_bufinfo(pvm_getrbuf(), (int *)0, (int *)0, &fromtid); pvm_unpackf("%d", &num); pvm_getminfo(pvm_getrbuf(), &minfo); wid = minfo.wid; printf("hoster() %d to start, wait id %d\n", num, wid); if (num > 0) { hostlist = TALLOC(num, struct hst *, "xxx"); for (i = 0; i < num; i++) { hp = TALLOC(1, struct hst, "xxx"); hostlist[i] = hp; hp->h_flag = 0; hp->h_result = 0; if (pvm_unpackf("%d %s %s %s %s %s", &hp->h_tid, sopts, lognam, cmd, wincmd, vmid)) { printf("hoster() bad message format\n"); pvm_exit(); exit(1); } hp->h_sopts = STRALLOC(sopts); hp->h_login = STRALLOC(lognam); hp->h_cmd = STRALLOC(cmd); /* Check for (possible) alternate WIN32 pvmd cmd */ if (!strcmp(wincmd,"")) hp->h_wincmd = 0; else hp->h_wincmd = STRALLOC(wincmd); /* Check for (optional) virtual machine ID */ if (!strcmp(vmid,"")) hp->h_vmid = 0; else hp->h_vmid = STRALLOC(vmid); printf("%d. t%x %s so=\"%s\"\n", i, hp->h_tid, hp->h_login, hp->h_sopts); if (p = CINDEX(hp->h_login, '@')) { hp->h_name = STRALLOC(p + 1); *p = 0; p = STRALLOC(hp->h_login); FREE(hp->h_login); hp->h_login = p; } else { hp->h_name = hp->h_login; hp->h_login = 0; } if (!strcmp(hp->h_sopts, "pw")) hp->h_flag |= HST_PASSWORD; if (!strcmp(hp->h_sopts, "ms")) hp->h_flag |= HST_MANUAL; } } /* * do it */ pl_startup(num, hostlist); /* * send results back to pvmd */ pvm_packf("%+ %d", PvmDataFoo, num); for (i = 0; i < num; i++) { pvm_packf("%d", hostlist[i]->h_tid); pvm_packf("%s", hostlist[i]->h_result ? hostlist[i]->h_result : "PvmDSysErr"); } /* printf("hoster() sending back host table\n"); */ pvm_getminfo(pvm_getsbuf(), &minfo); minfo.wid = wid; pvm_setminfo(pvm_getsbuf(), &minfo); pvm_send(fromtid, SM_STHOSTACK); return 0; } close_slot(sp) struct slot *sp; { if (sp->s_wfd != -1) (void)close(sp->s_wfd); if (sp->s_rfd != -1) (void)close(sp->s_rfd); if (sp->s_efd != -1) (void)close(sp->s_efd); LISTDELETE(sp, s_link, s_rlink); LISTPUTBEFORE(slfree, sp, s_link, s_rlink); return 0; } pl_startup(num, hostlist) int num; struct hst **hostlist; { int nxth = 0; /* next host in list to start */ struct slot *slact = 0; /* active list of slots */ struct hst *hp; struct slot *sp, *sp2; struct timeval tnow; struct timeval tout; #ifdef FDSETNOTSTRUCT fd_set rfds; #else struct fd_set rfds; #endif int nfds; int i; int n; char *p; char c; /* init slot free list */ slfree = &slots[RSHNPLL+1]; slfree->s_link = slfree->s_rlink = slfree; slact = &slots[RSHNPLL]; slact->s_link = slact->s_rlink = slact; for (i = RSHNPLL; i-- > 0; ) { LISTPUTAFTER(slfree, &slots[i], s_link, s_rlink); } /* * keep at this until all hosts in table are completed */ for (; ; ) { /* * if empty slots, start on new hosts */ for (; ; ) { /* find a host for slot */ if (slfree->s_link != slfree && nxth < num) hp = hostlist[nxth++]; else break; sp = slfree->s_link; LISTDELETE(sp, s_link, s_rlink); sp->s_hst = hp; sp->s_len = 0; sp->s_elen = 0; if (debugmask) { fprintf(stderr, "pl_startup() trying %s\n", hp->h_name); } phase1(sp); if (hp->h_result) { /* error or fully started (manual startup) */ if (debugmask) { fprintf(stderr, "pl_startup() got result \"%s\" for %s phase1()\n", hp->h_result, hp->h_name); } if (!strcmp(hp->h_result,"PvmCantStart") && hp->h_wincmd) { if (debugmask) { fprintf(stderr, "pl_startup() re-trying %s as WIN32\n", hp->h_name); } hp->h_cmd = sp->s_hst->h_wincmd; hp->h_wincmd = 0; FREE(hp->h_result); hp->h_result = 0; phase1(sp); if (hp->h_result) { if (debugmask) { fprintf(stderr, "pl_startup() got result \"%s\" for %s phase1()\n", hp->h_result, hp->h_name); } } else { /* partially started */ LISTPUTBEFORE(slact, sp, s_link, s_rlink); gettimeofday(&sp->s_bail, (struct timezone*)0); tout.tv_sec = RSHTIMEOUT; tout.tv_usec = 0; TVXADDY(&sp->s_bail, &sp->s_bail, &tout); } } else { LISTPUTBEFORE(slfree, sp, s_link, s_rlink); } } else { /* partially started */ LISTPUTBEFORE(slact, sp, s_link, s_rlink); gettimeofday(&sp->s_bail, (struct timezone*)0); tout.tv_sec = RSHTIMEOUT; tout.tv_usec = 0; TVXADDY(&sp->s_bail, &sp->s_bail, &tout); } } /* if no hosts in progress, we are finished */ if (slact->s_link == slact) break; /* * until next timeout, get output from any slot */ FD_ZERO(&rfds); nfds = 0; TVCLEAR(&tout); gettimeofday(&tnow, (struct timezone*)0); for (sp = slact->s_link; sp != slact; sp = sp->s_link) { if (TVXLTY(&sp->s_bail, &tnow)) { fprintf(stderr, "pl_startup() giving up on host %s after %d secs\n", sp->s_hst->h_name, RSHTIMEOUT); sp->s_hst->h_result = STRALLOC("PvmCantStart"); sp2 = sp->s_rlink; close_slot(sp); sp = sp2; continue; } if (!TVISSET(&tout) || TVXLTY(&sp->s_bail, &tout)) tout = sp->s_bail; if (sp->s_rfd >= 0) FD_SET(sp->s_rfd, &rfds); if (sp->s_rfd > nfds) nfds = sp->s_rfd; if (sp->s_efd >= 0) FD_SET(sp->s_efd, &rfds); if (sp->s_efd > nfds) nfds = sp->s_efd; } if (slact->s_link == slact) break; nfds++; if (TVXLTY(&tnow, &tout)) { TVXSUBY(&tout, &tout, &tnow); } else { TVCLEAR(&tout); } if (debugmask) { fprintf(stderr, "pl_startup() select timeout is %d.%06ld\n", tout.tv_sec, tout.tv_usec); } if ((n = select(nfds, #ifdef FDSETISINT (int *)&rfds, (int *)0, (int *)0, #else (fd_set *)&rfds, (fd_set *)0, (fd_set *)0, #endif &tout)) == -1) { if (errno != EINTR) { #ifdef WIN32 pvmlogperror("pl_startup() select"); #else perror("pl_startup() select"); #endif pvmbailout(0); } } if (debugmask) { fprintf(stderr, "pl_startup() select returns %d\n", n); } if (n < 1) { if (n == -1 && errno != EINTR) { #ifdef WIN32 pvmlogperror("pl_startup() select"); #else perror("pl_startup() select"); #endif pvmbailout(0); /* XXX this is too harsh */ } continue; } /* * check for response on stdout or stderr of any slave. */ for (sp = slact->s_link; sp != slact; sp = sp->s_link) { /* * stderr ready. log output with remote's host name. */ if (sp->s_efd >= 0 && FD_ISSET(sp->s_efd, &rfds)) { #ifdef WIN32 n = win32_read_socket(sp->s_efd, sp->s_ebuf + sp->s_elen, sizeof(sp->s_ebuf) - sp->s_elen - 1); #else n = read(sp->s_efd, sp->s_ebuf + sp->s_elen, sizeof(sp->s_ebuf) - sp->s_elen - 1); #endif if (n > 0) { sp->s_elen += n; sp->s_ebuf[sp->s_elen] = 0; #ifdef WIN32 p = sp->s_ebuf + sp->s_elen - n; fprintf(stderr, "stderr@%s: ", sp->s_hst->h_name); while (c = *p++ & 0x7f) { if (isprint(c)) fputc(c, stderr); else { fputc('^', stderr); fputc((c + '@') & 0x7f, stderr); } } fputc('\n', stderr); #else while (p = CINDEX(sp->s_ebuf, '\n')) { *p = 0; fprintf(stderr, "stderr@%s: %s\n", sp->s_hst->h_name, sp->s_ebuf); p++; sp->s_elen -= p - sp->s_ebuf; if (sp->s_elen > 0) { BCOPY(p, sp->s_ebuf, sp->s_elen); sp->s_ebuf[sp->s_elen] = 0; } } if (sp->s_elen == sizeof(sp->s_ebuf) - 1) { fprintf(stderr, "stderr@%s: %s\n", sp->s_hst->h_name, sp->s_ebuf); sp->s_elen = 0; } #endif } else { #ifndef WIN32 if (sp->s_elen > 0) { fprintf(stderr, "stderr@%s: %s\n", sp->s_hst->h_name, sp->s_ebuf); sp->s_elen = 0; } #endif (void)close(sp->s_efd); sp->s_efd = -1; } } /* * stdout ready. * look for a complete line starting with "ddpro". */ if (sp->s_rfd >= 0 && FD_ISSET(sp->s_rfd, &rfds)) { #ifdef WIN32 n = win32_read_socket(sp->s_rfd, sp->s_buf + sp->s_len, sizeof(sp->s_buf) - sp->s_len - 1); #else n = read(sp->s_rfd, sp->s_buf + sp->s_len, sizeof(sp->s_buf) - sp->s_len - 1); #endif if (n > 0) { sp->s_len += n; #ifdef WIN32 if (sp->s_len >= sizeof(sp->s_buf)) { fprintf(stderr, "pl_startup() pvmd@%s: big read\n", sp->s_hst->h_name); sp->s_hst->h_result = STRALLOC("PvmCantStart"); } #endif sp->s_buf[sp->s_len] = 0; #ifdef WIN32 if (p = CINDEX(sp->s_buf + sp->s_len - n, '\n')) { if (debugmask) { fprintf(stderr, "pvmd@%s: %s", sp->s_hst->h_name, sp->s_buf); } *p = 0; sp->s_hst->h_result = STRALLOC(sp->s_buf); } #else while (p = CINDEX(sp->s_buf, '\n')) { *p = 0; if (!strncmp(sp->s_buf, "ddpro", 5)) { if (debugmask) { fprintf(stderr, "stdout@%s: %s\n", sp->s_hst->h_name, sp->s_buf); } sp->s_hst->h_result = STRALLOC(sp->s_buf); break; } else { fprintf(stderr, "stdout@%s: %s\n", sp->s_hst->h_name, sp->s_buf); p++; sp->s_len -= p - sp->s_buf; if (sp->s_len > 0) { BCOPY(p, sp->s_buf, sp->s_len); sp->s_buf[sp->s_len] = 0; } } } if (sp->s_len == sizeof(sp->s_buf) - 1) { fprintf(stderr, "stdout@%s: %s\n", sp->s_hst->h_name, sp->s_buf); sp->s_len = 0; } #endif } else { #ifndef WIN32 if (sp->s_len > 0) { fprintf(stderr, "stdout@%s: %s\n", sp->s_hst->h_name, sp->s_buf); sp->s_len = 0; } #endif if (n) { fprintf(stderr, "pl_startup() stdout@%s\n", sp->s_hst->h_name); } else { fprintf(stderr, "pl_startup() stdout@%s: EOF\n", sp->s_hst->h_name); } #ifndef WIN32 if (sp->s_elen > 0) { fprintf(stderr, "stderr@%s: %s\n", sp->s_hst->h_name, sp->s_ebuf); sp->s_elen = 0; } #endif /* before failing, check for alternate WIN32 cmd */ if (sp->s_hst->h_wincmd) { if (debugmask) { fprintf(stderr, "pl_startup() re-trying %s as WIN32\n", hp->h_name); } sp->s_hst->h_cmd = sp->s_hst->h_wincmd; sp->s_hst->h_wincmd = 0; FREE(sp->s_hst->h_result); sp->s_hst->h_result = 0; phase1(sp); if (!(sp->s_hst->h_result)) { /* partially started */ gettimeofday(&sp->s_bail, (struct timezone *) 0); tout.tv_sec = RSHTIMEOUT; tout.tv_usec = 0; TVXADDY(&sp->s_bail, &sp->s_bail, &tout); } } else { sp->s_hst->h_result = STRALLOC("PvmCantStart"); } } if (sp->s_hst->h_result) { sp2 = sp->s_rlink; close_slot(sp); sp = sp2; continue; } } } } return 0; } phase1(sp) struct slot *sp; { struct hst *hp; char *hn; char *av[16]; /* for rsh args */ int ac; char buf[512]; int pid = -1; /* pid of rsh */ char *p; #ifdef WIN32 char do_cmd[128]; char *val=0; FILE *faked_stream; #endif #ifndef NOREXEC struct servent *se; static u_short execport = 0; if (!execport) { if (!(se = getservbyname("exec", "tcp"))) { fprintf(stderr, "phase1() can't getservbyname(): %s\n", "exec"); pvmbailout(0); } execport = se->s_port; #ifndef WIN32 endservent(); #endif } #endif hp = sp->s_hst; hn = hp->h_name; sp->s_rfd = sp->s_wfd = sp->s_efd = -1; /* * XXX manual startup hack... this is if we can't use rexec or rsh */ if (hp->h_flag & HST_MANUAL) { fprintf(stderr, "*** Manual startup ***\n"); fprintf(stderr, "Login to \"%s\" and type:\n", hn); fprintf(stderr, "%s\n", hp->h_cmd); if (hp->h_wincmd) { fprintf(stderr, "\nor, if that command fails, " ); fprintf(stderr, "for WIN32 hosts try:\n"); fprintf(stderr, "%s\n\n", hp->h_wincmd); } /* get version */ fprintf(stderr, "Type response: "); fflush(stderr); if (!(fgets(buf, sizeof(buf), stdin))) { fprintf(stderr, "host %s read error\n", hn); goto oops; } p = buf + strlen(buf) - 1; if (*p == '\n') *p = 0; hp->h_result = STRALLOC(buf); /* send vmid, if set */ if (hp->h_vmid) { fprintf(stderr, "Now Type the Virtual Machine ID on %s:\n", hn); fprintf(stderr, "%s\n", hp->h_vmid); } /* done */ fprintf(stderr, "Thanks\n"); fflush(stderr); return 0; } /* * XXX end manual startup hack */ if (!(hp->h_flag & HST_PASSWORD)) { /* use rsh to start */ int wpfd[2], rpfd[2], epfd[2]; int i; if (debugmask) { fprintf(stderr, "phase1() trying rsh to %s\n", hn); } /* fork an rsh to startup the slave pvmd */ #ifdef IMA_TITN if (socketpair(AF_UNIX, SOCK_STREAM, 0, wpfd) == -1 || socketpair(AF_UNIX, SOCK_STREAM, 0, rpfd) == -1 || socketpair(AF_UNIX, SOCK_STREAM, 0, epfd) == -1) { perror("phase1() socketpair"); goto oops; } #else #ifndef WIN32 if (pipe(wpfd) == -1 || pipe(rpfd) == -1 || pipe(epfd) == -1) { perror("phase1() pipe"); goto oops; } #endif #endif #ifndef WIN32 if (debugmask) { fprintf(stderr, "phase1() pipes: %d %d %d %d %d %d\n", wpfd[0], wpfd[1], rpfd[0], rpfd[1], epfd[0], epfd[1]); } if ((pid = fork()) == -1) { perror("phase1() fork"); pvmbailout(0); } if (!pid) { (void)dup2(wpfd[0], 0); (void)dup2(rpfd[1], 1); (void)dup2(epfd[1], 2); for (i = getdtablesize(); --i > 2; ) (void)close(i); #else { #endif ac = 0; av[ac++] = pvmgetrsh(); av[ac++] = hn; if (hp->h_login) { av[ac++] = "-l"; av[ac++] = hp->h_login; } #ifdef WIN32 else { hp->h_login=username; av[ac++] = "-l"; av[ac++] = hp->h_login; } #endif av[ac++] = hp->h_cmd; /* av[ac++] = "-u"; WIN32 */ /* av[ac++] = username; WIN32 */ av[ac++] = 0; if (debugmask) { for (ac = 0; av[ac]; ac++) fprintf(stderr, "av[%d]=\"%s\" ", ac, av[ac]); fputc('\n', stderr); } #ifndef WIN32 execvp(av[0], av); fputs("phase1() execvp failed\n", stderr); fflush(stderr); _exit(1); #else sp->s_hst->h_result = malloc (512 * sizeof(char)); if (!rsh(hn,(hp->h_login ? hp->h_login : username), hp->h_cmd,sp->s_hst->h_result)) { fprintf(stderr, "phase1() rsh failed for host %s\n", hn); goto oops; } /* old code using popen ... */ /* faked_stream=_popen(do_cmd,"r"); if (faked_stream != NULL) { while (1) { fgets(buf,100,faked_stream); if (strstr(buf,"ddpro")) { if (!val) val = malloc(sizeof (buf) * sizeof(char)); strcpy(val,buf); sp->s_hst->h_result=val; break; } if (strcmp(buf,"PvmDupHost")){ if (!val) val = malloc(sizeof (buf) * sizeof(char)); strcpy(val,buf); sp->s_hst->h_result=val; break; } } } */ #endif } #ifndef WIN32 (void)close(wpfd[0]); (void)close(rpfd[1]); (void)close(epfd[1]); sp->s_wfd = wpfd[1]; sp->s_rfd = rpfd[0]; sp->s_efd = epfd[0]; #endif } else { /* use rexec to start */ #ifdef NOREXEC #ifdef WIN32 fprintf(stderr, "slconfg() sorry, no rexec()\n"); #else fprintf(stderr, "slconfg() hoster was built without rexec support, can't take passwords\n"); #endif goto oops; #else if (debugmask) { fprintf(stderr, "phase1() rexec \"%s\"\n", hp->h_cmd); } #ifndef WIN32 if ((sp->s_wfd = sp->s_rfd = rexec(&hn, execport, (hp->h_login ? hp->h_login : username), (char*)0, hp->h_cmd, &sp->s_efd)) == -1) { fprintf(stderr, "phase1() rexec failed for host %s\n", hn); goto oops; } #else sp->s_hst->h_result = malloc (512 * sizeof(char)); if (!rexec(hn,(hp->h_login ? hp->h_login : username), hp->h_cmd,sp->s_hst->h_result)) { fprintf(stderr, "phase1() rexec failed for host %s\n", hn); goto oops; } #endif #endif } /* send vmid, if set */ if (sp->s_hst->h_vmid && sp->s_wfd >= 0) { #ifdef WIN32 win32_write_socket(sp->s_wfd, "PVM_VMID=", 9); win32_write_socket(sp->s_wfd, sp->s_hst->h_vmid, strlen(sp->s_hst->h_vmid)); win32_write_socket(sp->s_wfd, "\n", 1); #else write(sp->s_wfd, "PVM_VMID=", 9); write(sp->s_wfd, sp->s_hst->h_vmid, strlen(sp->s_hst->h_vmid)); write(sp->s_wfd, "\n", 1); #endif } return 0; oops: hp->h_result = STRALLOC("PvmCantStart"); if (sp->s_wfd != -1) close(sp->s_wfd); if (sp->s_rfd != -1) close(sp->s_rfd); if (sp->s_efd != -1) close(sp->s_efd); sp->s_wfd = sp->s_rfd = sp->s_efd = -1; return 1; } ./pvm3/hoster/pvmwinrexec.c0100644007401100000360000002370107620016507015125 0ustar kohlgopher static char rcsid[] = "$Id: pvmwinrexec.c,v 1.4 2003/02/04 20:06:31 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ #include #pragma warning(disable: 4699) #define STRICT #pragma warning(disable: 4201) #include #pragma warning(default: 4201) #include #include #include #include #include static DWORD WINAPI PassOutputThread(LPVOID); static DWORD WINAPI PassErrorThread(LPVOID); HANDLE hStdIn, hStdOut, hStdErr; static char *GetPassword(void); int MyOpenService(const char *remote_host); static void Cleanup(void); static HANDLE PassOutput(void); static HANDLE PassError(void); static BOOL SendZString(const char *); static BOOL GetErrString(char *, size_t); extern void Wait(HANDLE, DWORD *); static SOCKET sIO = INVALID_SOCKET; static SOCKET sErr = INVALID_SOCKET; char *res; char *hn; int found_mess=0; int errno; int rexec(char *hostname, char *username, char *command,char *retresult) { char *password; size_t cmdlen; int i; HANDLE idIn = 0; HANDLE idOut, idErr; DWORD rvIn, rvOut, rvErr; res=malloc(512*sizeof(char)); hn=hostname; hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); hStdErr = GetStdHandle(STD_ERROR_HANDLE); password = NULL; if (!username) { username = (char *)MyGetUserName(); } if (!password) { password = GetPassword(); } if (!MyOpenService(hostname)) return 0; SendZString(username); SendZString(password); memset (password, '\0', strlen(password)); SendZString(command); if (!GetErrString(command, sizeof command)) { fprintf(stderr, "Remote aborted connection without initiating protocol: %d.\n", WSAGetLastError()); return 0; } if (*command != '\0') { char *p = command; if (*p == '\001') { p++; } fprintf(stderr, "Remote aborted connection: %s\n", p); return 0; } if (shutdown(sIO, 1) == SOCKET_ERROR) { fprintf(stderr, "Failed to shutdown from input socket: error = %d.\n", WSAGetLastError()); return 0; } idOut = PassOutput(); idErr = PassError(); Wait(idOut, &rvOut); Wait(idErr, &rvErr); strcpy(retresult,res); return (int)rvOut; } static char *GetPassword() { static char password[30]; char *p; HANDLE hConIn, hConOut; DWORD dwMode; DWORD cbRead, cbWritten; hConIn = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); if (hConIn == INVALID_HANDLE_VALUE) { fprintf(stderr, "Can't open Console for input: %lu\n", GetLastError()); exit(1); } hConOut = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); if (hConOut == INVALID_HANDLE_VALUE) { fprintf(stderr, "Can't open Console for output: %lu\n", GetLastError()); exit(1); } (void) WriteFile(hConOut, "Password: ", 10, &cbWritten, 0); if (!GetConsoleMode(hConIn, &dwMode)) { fprintf(stderr, "Can't Console input mode: %lu\n", GetLastError()); exit(1); } dwMode &= ~(ENABLE_ECHO_INPUT); (void) signal(SIGINT, SIG_IGN); (void)SetConsoleMode(hConIn, dwMode); (void)ReadFile(hConIn, password, sizeof password, &cbRead, 0); dwMode |= ENABLE_ECHO_INPUT; (void)SetConsoleMode(hConIn, dwMode); (void) signal(SIGINT, SIG_DFL); (void) WriteFile(hConOut, "\r\n", 2, &cbWritten, 0); (void) CloseHandle(hConIn); (void) CloseHandle(hConOut); if ((p=strchr(password, '\r')) != NULL) { *p = '\0'; } if ((p=strchr(password, '\n')) != NULL) { *p = '\0'; } return password; } static HANDLE PassOutput() { HANDLE id; DWORD threadId; id = (HANDLE)CreateThread(NULL,0,PassOutputThread, NULL, 0, &threadId); if ((long)id == -1) { fprintf(stderr, "Could not start output passing thread: error = %lu\n", GetLastError()); exit(1); } return id; } extern int debugmask; static DWORD WINAPI PassOutputThread(LPVOID nothing) { DWORD retval = 1; int count=0; char *buf; int noresult; int i=0; buf = malloc(512*sizeof (char)); while ((count=recv(sIO, &buf[i], sizeof buf, 0)) > 0) { i+=count; } buf[i]=0; if (noresult = (strncmp(buf, "ddpro", 5) == 0)) { sprintf(res,"stdout@%s: %s\n",hn,buf); retval=0; } if (!noresult) retval =1; if (count == -1) { fprintf(stderr, "Error passing standard output from socket: error = %d.\n", WSAGetLastError()); retval = 1; } if (count != -1) { if (shutdown(sIO, 0) == SOCKET_ERROR) { fprintf(stderr, "Failed to shutdown standard output socket: error = %d.\n", WSAGetLastError()); retval = 1; } } free(buf); final: ExitThread(retval); return retval; } static HANDLE PassError() { HANDLE id; DWORD threadId; id = (HANDLE)CreateThread(NULL,0,PassErrorThread, NULL, 0, &threadId); if ((long)id == -1) { fprintf(stderr, "Could not start error passing thread: error = %lu\n", GetLastError()); exit(1); } return id; } static DWORD WINAPI PassErrorThread(LPVOID nothing) { DWORD retval = 0; int count=0; char *buf; buf=malloc(4096*sizeof(char)); while ((count=recv(sErr, buf, sizeof buf, 0)) > 0) { if (!win32_write_file(hStdErr, buf, count)) { fprintf(stderr, "Error writing to standard error: error = %lu.\n", GetLastError()); retval = 1; break; } } if (count == -1) { fprintf(stderr, "Error passing standard error from socket: error = %d.\n", WSAGetLastError()); retval = 1; } if (count != -1) { if (shutdown(sErr, 0) == SOCKET_ERROR) { fprintf(stderr, "Failed to shutdown standard error socket: error = %d.\n", WSAGetLastError()); retval = 1; } } ExitThread(retval); return retval; } int MyOpenService(const char *remote_host) { WSADATA wsadata; struct sockaddr_in server_addr, my_err_addr, junk_addr; struct servent *sv; struct hostent *hent; static char portbuf[30]; SOCKET sTmp; int addr_len; if (WSAStartup(MAKEWORD(1,1), &wsadata) != 0) { fprintf(stderr, "Failed to initialize TCP/IP: error=%d.\n", WSAGetLastError()); return(0); } if (LOBYTE(wsadata.wVersion) != 1 || HIBYTE(wsadata.wVersion) != 1) { fprintf(stderr, "Old version of TCP/IP: error=%d.\n", WSAGetLastError()); return (0); } if (atexit(Cleanup) != 0) { WSACleanup(); fprintf(stderr, "Could not register TCP/IP cleanup function.\n"); return(0); } hent = gethostbyname(remote_host); if(!hent) { fprintf(stderr, "Lookup of server hostname failed: error=%d.\n", WSAGetLastError()); return (0); } sv=getservbyname("exec", "tcp"); if (!sv) { fprintf(stderr, "Lookup of port number for rexec service failed: error=%d.\n", WSAGetLastError()); return(0); } memcpy((char *)&server_addr.sin_addr, hent->h_addr, hent->h_length); server_addr.sin_family = hent->h_addrtype; server_addr.sin_port = sv->s_port; if((sIO=socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { fprintf(stderr, "I/O socket creation failed: error=%d.\n", WSAGetLastError()); return(0); } if(connect(sIO, (struct sockaddr *)&server_addr, sizeof server_addr) == SOCKET_ERROR) { fprintf(stderr, "I/O socket connection failed: error=%d.\n", WSAGetLastError()); return(0); } memset(&my_err_addr, '\0', sizeof my_err_addr); my_err_addr.sin_addr.s_addr = htonl(INADDR_ANY); my_err_addr.sin_family = AF_INET; my_err_addr.sin_port = 0; if ((sTmp=socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { fprintf(stderr, "Error socket creation failed: error=%d.\n", WSAGetLastError()); return(0); } if (bind(sTmp, (struct sockaddr *)&my_err_addr, sizeof my_err_addr) == SOCKET_ERROR) { fprintf(stderr, "Error socket bind failed: error=%d.\n", WSAGetLastError()); (void) closesocket(sTmp); return(0); } if (listen(sTmp, 1) == SOCKET_ERROR) { fprintf(stderr, "Error socket listen failed: error=%d.\n", WSAGetLastError()); (void) closesocket(sTmp); return(0); } addr_len = sizeof my_err_addr; if (getsockname(sTmp, (struct sockaddr *)&my_err_addr, &addr_len) == SOCKET_ERROR) { fprintf(stderr, "Error socket bind failed: error=%d.\n", WSAGetLastError()); (void) closesocket(sTmp); return(0); } sprintf(portbuf, "%hu", ntohs(my_err_addr.sin_port)); SendZString(portbuf); addr_len = sizeof junk_addr; if ((sErr = accept(sTmp, (struct sockaddr *)&junk_addr, &addr_len)) == INVALID_SOCKET) { fprintf(stderr, "Error socket accept failed: error=%d.\n", WSAGetLastError()); (void) closesocket(sTmp); return(0); } (void) closesocket(sTmp); return 1; } static void Cleanup(void) { if (sIO != INVALID_SOCKET) { (void)closesocket(sIO); } if (sErr != INVALID_SOCKET) { (void)closesocket(sErr); } WSACleanup(); } static BOOL SendZString(const char *str) { return win32_write_socket(sIO, str, strlen(str)+1); } static BOOL GetErrString(char *str, size_t len) { size_t pos = 0; while (pos < len) { char ch; if (recv(sIO, &ch, 1, 0) != 1) { return FALSE; } str[pos++] = ch; if (ch == '\0') { return TRUE; } if (ch == '\n') { return TRUE; } } return FALSE; } ./pvm3/hoster/pvmwinrsh.c0100644007401100000360000002130406673300403014606 0ustar kohlgopher static char rcsid[] = "$Id: pvmwinrsh.c,v 1.5 1999/03/15 21:52:03 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ #include #include struct sockaddr_in anaddr; // local socket address structure struct sockaddr_in saddr; // server socket address structure u_short rshPort; // the local rsh port; determined dynamically u_short rshErrPort; // the local rsh port for client stderr output u_short rshSPort; // the remote rsh port; basically, the 'shell' port from services u_short rshProto; // the rsh protocol ("tcp") SOCKET rshClient = INVALID_SOCKET; // rsh client socket for outgoing connections SOCKET rshClientErr = INVALID_SOCKET; // rsh client socket for stderr input char ruserName[64]; // user name given with option 'lo' char luserName[64]; // user logged onto the machine char cmd[4096]; int stderrFlag=1; // set when a connection has been detected on the stderr channel // socket options variables int on=1; struct linger linger; LPPROTOENT lpProto; char *res; // our return string int rresvport (u_short *alport, int sProto) { struct sockaddr_in sin; int s; sin.sin_family=AF_INET; sin.sin_addr.s_addr=INADDR_ANY; s=socket(AF_INET, SOCK_STREAM, sProto); if(s<0) return -1; for(*alport=IPPORT_RESERVED-1; *alport>IPPORT_RESERVED/2; (*alport)--) { sin.sin_port=htons((u_short)*alport); if(bind(s, (struct sockaddr*)&sin, sizeof(sin))==0) return s; if(WSAGetLastError()!=WSAEADDRINUSE) break; } closesocket(s); return -1; } void sendsocket (const char* buff, int bufflen, SOCKET rshClient) { if(send(rshClient, buff, bufflen, 0) < bufflen) fprintf(stdout,"error sending command."); } // receive //////////////////////////////////////////////////////////// // // receive a string from the given socket // int receivesocket (SOCKET rshClient, char* buff2, int blen,char *hostname) { int bufflen; int totallen=0; int noresult=0; int i=0; char *b= malloc(128 * sizeof(char)); char *buff = malloc(512 * sizeof(char)); memset( buff, 0, 512 ); strcpy(buff,""); while ((bufflen=recv(rshClient, b,sizeof b, 0)) > 0) { b[bufflen]='\0'; strcat(buff,b); totallen+=bufflen; if (noresult = (strncmp(buff, "ddpro", 5) == 0)) { sprintf(res,"stdout@%s: %s\n",hostname,buff); if (strlen(buff)>=66) return 1; } } if(bufflen==SOCKET_ERROR) { fprintf(stdout,"error in receive on socket: %s\n", GetLastErrorToStr(GetLastError())); return bufflen; } return 0; } int verify_hostname (const char* hostname) { memset(&saddr, 0, sizeof(saddr)); saddr.sin_addr.s_addr=inet_addr(hostname); if(saddr.sin_addr.s_addr==(u_long)INADDR_NONE) { // must have gotten host name instead of IP address; resolve! struct hostent* hostInfo=gethostbyname(hostname); if(!hostInfo) { fprintf(stdout,"Invalid hostname!"); return 0; } memcpy((void*)&saddr.sin_addr.s_addr, hostInfo->h_addr, hostInfo->h_length); } return 1; } // initSocket ///////////////////////////////////////////////////////// // // standard socket initialization procedure // void initSocket () { // get port number for rsh struct servent FAR* sp=getservbyname("shell", "tcp"); if(sp==NULL) fprintf(stdout, "Cannot determine port number for the rsh client."); rshSPort=htons(sp->s_port); lpProto=getprotobyname("tcp"); rshProto=lpProto->p_proto; // create socket rshClient=rresvport(&rshPort, rshProto); if(rshClient==INVALID_SOCKET) fprintf(stdout,"Cannot allocate socket for the rsh client."); if(setsockopt(rshClient, SOL_SOCKET, SO_KEEPALIVE, (char*)&on, sizeof(on))<0) fprintf(stdout,"Cannot set SO_KEEPALIVE!\n", 0); linger.l_onoff=1; linger.l_linger=60; if(setsockopt(rshClient, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(linger))<0) fprintf(stdout,"Cannot set SO_LINGER!\n"); } // openErrSocket ////////////////////////////////////////////////////// // // an additional socket is created for stderr output // int initErrSocket () { // create the new socket and bind it to the client stderr port rshErrPort=IPPORT_RESERVED-1; rshClientErr=rresvport(&rshErrPort,0); if(rshClientErr==INVALID_SOCKET) { fprintf(stdout,"Cannot create stderr socket!"); return 1; } if(setsockopt(rshClientErr, SOL_SOCKET, SO_KEEPALIVE, (char*)&on, sizeof(on))<0) fprintf(stdout,"Cannot set SO_KEEPALIVE!"); linger.l_onoff=0; linger.l_linger=60; setsockopt(rshClientErr, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(linger)); if(listen(rshClientErr, 5)) fprintf(stdout,"Cannot listen!"); return 1; } // command //////////////////////////////////////////////////////////// // // pass the command string to the rsh server and retrieve the results // int do_command (const char* cmd,char *hostname) { char cmdbuff[2048]; char buff[2048]; int retval=0; int cmdbufflen=0; int noresult=0; sprintf(cmdbuff+cmdbufflen, "%d", rshErrPort); // local stderr port cmdbufflen=strlen(cmdbuff)+1; strcpy(cmdbuff+cmdbufflen, luserName); // locuser cmdbufflen+=strlen(luserName)+1; strcpy(cmdbuff+cmdbufflen, ruserName); // remuser cmdbufflen+=strlen(ruserName)+1; strcpy(cmdbuff+cmdbufflen, cmd); // command cmdbufflen+=strlen(cmd)+1; sendsocket(cmdbuff, cmdbufflen, rshClient); if (receivesocket(rshClient, buff, 2047,hostname)) return 1; return 0; } long clientThread () { SOCKET rshServer; char buff[2048]; struct sockaddr anaddr; int len=sizeof(anaddr); rshServer=accept(rshClientErr, (struct sockaddr FAR*)&anaddr, &len); if(rshServer==INVALID_SOCKET) { fprintf(stdout,"Error connecting to the stderr server port!"); return 0; } stderrFlag=1; // mark connection made while(receivesocket(rshServer, buff, 2047,"")>0) fprintf(stderr, buff); shutdown(rshClientErr, 2); closesocket(rshClientErr); return 1; } HANDLE threadHnd; void th_start (HANDLE threadHnd) { initSocket(); if(!initErrSocket()) fprintf(stdout,"Cannot create error socket!"); saddr.sin_family=AF_INET; saddr.sin_port=rshSPort; if(connect(rshClient, (struct sockaddr FAR*)&saddr, sizeof(saddr))) fprintf(stdout,"Cannot connect to RSH port!\n"); if(rshClientErr!=INVALID_SOCKET) { DWORD threadID; threadHnd= CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)clientThread, (LPVOID)0, 0, (LPDWORD)&threadID); if(!threadHnd) fprintf(stdout,"Cannot start client thread..."); } } int th_stop(HANDLE threadHnd) { if (shutdown(rshClient, 2)) fprintf(stdout,"could not shut down rsh client socket \n"); closesocket(rshClient); if(threadHnd) { DWORD exitCode=0; GetExitCodeThread(threadHnd, &exitCode); while(exitCode==STILL_ACTIVE && stderrFlag) { Sleep(50); GetExitCodeThread(threadHnd, &exitCode); } CloseHandle(threadHnd); } return 0; } int rsh (char *hostname, char *username, char *command,char *retresult) { res=malloc(512*sizeof(char)); strcpy(ruserName,username); strcpy(luserName,(char *)MyGetUserName()); if (!verify_hostname(hostname)) { fprintf(stdout,"Could not verify hostname: No such host \n"); return 0; } th_start(threadHnd); if (!do_command(command,hostname)) { th_stop(threadHnd); return 0; } th_stop(threadHnd); strcpy(retresult,res); return(1); } ./pvm3/hoster/pvmfgetminfo.30100644007401100000360000000012706221604504015170 0ustar kohlgopher.\" $Id: pvmfgetminfo.3,v 1.1 1996/09/23 22:03:48 pvmsrc Exp $ .so man3/pvm_setminfo.3 ./pvm3/hoster/pvmfsetminfo.30100644007401100000360000000012706221605051015202 0ustar kohlgopher.\" $Id: pvmfsetminfo.3,v 1.1 1996/09/23 22:07:37 pvmsrc Exp $ .so man3/pvm_setminfo.3 ./pvm3/hoster/pvm_getminfo.30100644007401100000360000000012706221604263015163 0ustar kohlgopher.\" $Id: pvm_getminfo.3,v 1.1 1996/09/23 22:01:23 pvmsrc Exp $ .so man3/pvm_setminfo.3 ./pvm3/hoster/pvm_setminfo.30100644007401100000360000000437106221604726015210 0ustar kohlgopher.\" $Id: pvm_setminfo.3,v 1.1 1996/09/23 22:06:14 pvmsrc Exp $ .TH SETMINFO 3PVM "13 March, 1996" "" "PVM Version 3.4" .SH NAME pvm_getminfo, pvm_setminfo \- Get or set header information of a message. .SH SYNOPSIS .nf .ft B C int info = pvm_getminfo( int bufid, struct pvmminfo *mi ) .br int info = pvm_setminfo( int bufid, struct pvmminfo *mi ) .br Fortran call pvmfgetminfo( bufid, len, ctx, tag, wid, enc, crc, src, dst, info ) call pvmfsetminfo( bufid, ctx, tag, wid, src, dst, info ) .fi .SH PARAMETERS .IP bufid 0.8i Message buffer identifier. .IP mi Struct containing header information. .IP info Result code. .PP For a description of the Fortran parameters, see below. .SH DESCRIPTION These functions read and set information passed in message headers, which may be of interest to certain applications. Typically, they will be used when it is necessary to get the message context or wait id to use the same values in a reply message. The fields affected are: .IP len The length in bytes of the body of the message. This will be equal to the actual size of the data packed, if \fIPvmDataRaw\fR is used, otherwise it may include pad bytes. .IP ctx The context sent with the message. .IP tag The tag sent with the message. .IP wid Wait Identifier, used to match a reply message to the corresponding request. .IP enc Message Encoding, either the \fIdata signature\fR of the sender, or 0x10000000 for XDR. .IP crc The CRC checksum of the message body. .IP src The tid of the sender. .IP dst The tid of the destination. .PP All fields may be read, but only \fIctx\fR, \fItag\fR, \fIwid\fR, \fIsrc\fR and \fIdst\fR may be set. pvm_getmwid and pvm_setmwid return PvmOk if successful, or else a negative error code. .SH EXAMPLES .nf /* return a message to a caller with the same tag and wait id */ struct pvmminfo mi1, mi2; pvm_recv(-1, -1); /* ... process, compose reply message */ pvm_getminfo(pvm_getrbuf(), &mi1); pvm_getminfo(pvm_getsbuf(), &mi2); mi2.wid = mi1.wid; pvm_send(mi1.src, mi1.tag); .SH ERRORS The following error conditions can be returned by pvm_getmwid or pvm_setmwid: .IP PvmBadParam Invalid value for \fIbufid\fR or \fImi\fR argument. .IP PvmNoSuchBuf Message buffer \fIbufid\fR doesn't exist. .PP .SH SEE ALSO pvm_bufinfo(3PVM) ./pvm3/hoster/OS2/0042755007401100000360000000000010117676455013030 5ustar kohlgopher./pvm3/hoster/OS2/Makefile0100644007401100000360000000055006401362535014453 0ustar kohlgopher# # $Id: Makefile,v 1.2 1997/08/28 20:53:49 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/hoster PVM_ARCH = OS2 CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) all: make LIBPREFIX="" REXECOBJ="rexec.o ruserpas.o" \ -f $(CONFFILE) -f $(SDIR)/Makefile.aimk all clean: make -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean ./pvm3/include/0042755007401100000360000000000010117676455012544 5ustar kohlgopher./pvm3/include/fpvm3.h0100644007401100000360000002231007050647544013740 0ustar kohlgopherc c $Id: fpvm3.h,v 1.15 2000/02/10 23:53:08 pvmsrc Exp $ c c ------------------------------------------------------------------- c PVM version 3.4: Parallel Virtual Machine System c University of Tennessee, Knoxville TN. c Oak Ridge National Laboratory, Oak Ridge TN. c Emory University, Atlanta GA. c Authors: J. J. Dongarra, G. E. Fagg, M. Fischer c G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, c P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam c (C) 1997 All Rights Reserved c c NOTICE c c Permission to use, copy, modify, and distribute this software and c its documentation for any purpose and without fee is hereby granted c provided that the above copyright notice appear in all copies and c that both the copyright notice and this permission notice appear in c supporting documentation. c c Neither the Institutions (Emory University, Oak Ridge National c Laboratory, and University of Tennessee) nor the Authors make any c representations about the suitability of this software for any c purpose. This software is provided ``as is'' without express or c implied warranty. c c PVM version 3 was funded in part by the U.S. Department of Energy, c the National Science Foundation and the State of Tennessee. c ------------------------------------------------------------------- c ---------------------------------- c fpvm3.h c c Definitions to be included with c User Fortran application c ---------------------------------- integer PVMTASKDEFAULT, PVMTASKHOST, PVMTASKARCH, PVMTASKDEBUG integer PVMTASKTRACE, PVMMPPFRONT, PVMHOSTCOMPL, PVMNOSPAWNPARENT integer PVMHOST, PVMARCH, PVMDEBUG, PVMTRACE integer PVMDATADEFAULT, PVMDATARAW, PVMDATAINPLACE integer PVMDATATRACE integer PVMDEFAULT, PVMRAW, PVMINPLACE integer PVMTASKEXIT, PVMHOSTDELETE, PVMHOSTADD, PVMROUTEADD integer PVMROUTEDELETE, PVMNOTIFYCANCEL integer PVMROUTE, PVMDEBUGMASK, PVMAUTOERR integer PVMOUTPUTTID, PVMOUTPUTCODE, PVMRESVTIDS integer PVMTRACETID, PVMTRACECODE, PVMTRACEBUFFER integer PVMTRACEOPTIONS, PVMFRAGSIZE, PVMSHOWTIDS, PVMNORESET integer PVMTRACEFULL, PVMTRACETIME, PVMTRACECOUNT integer PVMSOUTPUTTID, PVMSOUTPUTCODE, PVMSTRACETID integer PVMSTRACECODE, PVMSTRACEBUFFER, PVMSTRACEOPTIONS integer PVMOUTPUTCTX, PVMTRACECTX, PVMSOUTPUTCTX, PVMSTRACECTX integer PVMDONTROUTE, PVMALLOWDIRECT, PVMROUTEDIRECT integer PVMPOLLTYPE, PVMPOLLTIME, PVMPOLLCONSTANT, PVMPOLLSLEEP integer PVMMBOXDEFAULT, PVMMBOXPERSISTENT, PVMMBOXMULTIINSTANCE integer PVMMBOXOVERWRITABLE, PVMMBOXFIRSTAVAIL integer PVMMBOXREADANDDELETE, PVMMBOXWAITFORINFO integer STRING, BYTE1, INTEGER2, INTEGER4, INTEGER8 integer REAL4, COMPLEX8, REAL8, COMPLEX16 integer PvmOk, PvmSysErr, PvmBadParam, PvmMismatch integer PvmNoData, PvmNoHost, PvmNoFile, PvmNoMem integer PvmBadMsg, PvmNoBuf, PvmNoSuchBuf integer PvmNullGroup, PvmDupGroup, PvmNoGroup integer PvmNotInGroup, PvmNoInst, PvmHostFail, PvmNoParent integer PvmNotImpl, PvmDSysErr, PvmBadVersion, PvmOutOfRes integer PvmDupHost, PvmCantStart, PvmAlready, PvmNoTask integer PvmNoEntry, PvmDupEntry, PvmOverflow, PvmDenied integer PvmNotFound, PvmExists, PvmHostrNMstr, PvmParentNotSet integer PvmIPLoopback c -------------------- c spawn 'flag' options c -------------------- parameter( PVMTASKDEFAULT = 0) parameter( PVMTASKHOST = 1) parameter( PVMTASKARCH = 2) parameter( PVMTASKDEBUG = 4) parameter( PVMTASKTRACE = 8) parameter( PVMMPPFRONT = 16) parameter( PVMHOSTCOMPL = 32) parameter( PVMNOSPAWNPARENT = 64) c -------------------------------- c old option names still supported c -------------------------------- parameter( PVMHOST = 1) parameter( PVMARCH = 2) parameter( PVMDEBUG = 4) parameter( PVMTRACE = 8) c ------------------------- c buffer 'encoding' options c ------------------------- parameter( PVMDATADEFAULT = 0) parameter( PVMDATARAW = 1) parameter( PVMDATAINPLACE = 2) parameter( PVMDATATRACE = 4) c -------------------------------- c old option names still supported c -------------------------------- parameter( PVMDEFAULT = 0) parameter( PVMRAW = 1) parameter( PVMINPLACE = 2) c ---------------------- c notify 'about' options c ---------------------- parameter( PVMTASKEXIT = 1 ) parameter( PVMHOSTDELETE = 2 ) parameter( PVMHOSTADD = 3 ) parameter( PVMROUTEADD = 4 ) parameter( PVMROUTEDELETE = 5 ) parameter( PVMNOTIFYCANCEL = 256 ) c -------------------------------- c packing/unpacking 'what' options c -------------------------------- parameter( STRING = 0) parameter( BYTE1 = 1) parameter( INTEGER2 = 2) parameter( INTEGER4 = 3) parameter( REAL4 = 4) parameter( COMPLEX8 = 5) parameter( REAL8 = 6) parameter( COMPLEX16= 7) parameter( INTEGER8 = 8) c -------------------------------- c setopt/getopt options for 'what' c -------------------------------- parameter( PVMROUTE = 1) parameter( PVMDEBUGMASK = 2) parameter( PVMAUTOERR = 3) parameter( PVMOUTPUTTID = 4) parameter( PVMOUTPUTCODE = 5) parameter( PVMTRACETID = 6) parameter( PVMTRACECODE = 7) parameter( PVMTRACEBUFFER = 8) parameter( PVMTRACEOPTIONS = 9) parameter( PVMFRAGSIZE = 10) parameter( PVMRESVTIDS = 11) parameter( PVMSOUTPUTTID = 12) parameter( PVMSOUTPUTCODE = 13) parameter( PVMSTRACETID = 14) parameter( PVMSTRACECODE = 15) parameter( PVMSTRACEBUFFER = 16) parameter( PVMSTRACEOPTIONS = 17) parameter( PVMSHOWTIDS = 18) parameter( PVMPOLLTYPE = 19) parameter( PVMPOLLTIME = 20) parameter( PVMOUTPUTCTX = 21) parameter( PVMTRACECTX = 22) parameter( PVMSOUTPUTCTX = 23) parameter( PVMSTRACECTX = 24) parameter( PVMNORESET = 25) c -------------------------------------------- c tracing option values for setopt function c -------------------------------------------- parameter( PVMTRACEFULL = 1) parameter( PVMTRACETIME = 2) parameter( PVMTRACECOUNT = 3) c -------------------------------------------- c poll type options for 'how' in setopt function c -------------------------------------------- parameter( PVMPOLLCONSTANT = 1) parameter( PVMPOLLSLEEP = 2) c -------------------------------------------- c for message mailbox operations c -------------------------------------------- parameter( PVMMBOXDEFAULT = 0) parameter( PVMMBOXPERSISTENT = 1) parameter( PVMMBOXMULTIINSTANCE = 2) parameter( PVMMBOXOVERWRITABLE = 4) parameter( PVMMBOXFIRSTAVAIL = 8) parameter( PVMMBOXREADANDDELETE = 16) parameter( PVMMBOXWAITFORINFO = 32) c -------------------------------------------- c routing options for 'how' in setopt function c -------------------------------------------- parameter( PVMDONTROUTE = 1) parameter( PVMALLOWDIRECT= 2) parameter( PVMROUTEDIRECT= 3) c -------------------------- c error 'info' return values c -------------------------- parameter( PvmOk = 0) parameter( PvmBadParam = -2) parameter( PvmMismatch = -3) parameter( PvmOverflow = -4) parameter( PvmNoData = -5) parameter( PvmNoHost = -6) parameter( PvmNoFile = -7) parameter( PvmDenied = -8) parameter( PvmNoMem = -10) parameter( PvmBadMsg = -12) parameter( PvmSysErr = -14) parameter( PvmNoBuf = -15) parameter( PvmNoSuchBuf = -16) parameter( PvmNullGroup = -17) parameter( PvmDupGroup = -18) parameter( PvmNoGroup = -19) parameter( PvmNotInGroup = -20) parameter( PvmNoInst = -21) parameter( PvmHostFail = -22) parameter( PvmNoParent = -23) parameter( PvmNotImpl = -24) parameter( PvmDSysErr = -25) parameter( PvmBadVersion = -26) parameter( PvmOutOfRes = -27) parameter( PvmDupHost = -28) parameter( PvmCantStart = -29) parameter( PvmAlready = -30) parameter( PvmNoTask = -31) parameter( PvmNotFound = -32) parameter( PvmExists = -33) parameter( PvmHostrNMstr = -34) parameter( PvmParentNotSet = -35) parameter( PvmIPLoopback = -36) c -------------------------- c these are going away in the next version. c use the replacements c -------------------------- parameter( PvmNoEntry = -32) parameter( PvmDupEntry = -33) c Uncomment this include for use with the WIN32 WATCOM fortran compiler c c include '../include/fpvm3_watcom.h' c ./pvm3/include/fpvm3_watcom.h0100644007401100000360000000702506673257303015320 0ustar kohlgopherc c $Id: fpvm3_watcom.h,v 1.2 1999/03/15 19:25:55 pvmsrc Exp $ c c ------------------------------------------------------------------- c PVM version 3.4: Parallel Virtual Machine System c University of Tennessee, Knoxville TN. c Oak Ridge National Laboratory, Oak Ridge TN. c Emory University, Atlanta GA. c Authors: J. J. Dongarra, G. E. Fagg, M. Fischer c G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, c P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam c (C) 1997 All Rights Reserved c c NOTICE c c Permission to use, copy, modify, and distribute this software and c its documentation for any purpose and without fee is hereby granted c provided that the above copyright notice appear in all copies and c that both the copyright notice and this permission notice appear in c supporting documentation. c c Neither the Institutions (Emory University, Oak Ridge National c Laboratory, and University of Tennessee) nor the Authors make any c representations about the suitability of this software for any c purpose. This software is provided ``as is'' without express or c implied warranty. c c PVM version 3 was funded in part by the U.S. Department of Energy, c the National Science Foundation and the State of Tennessee. c ------------------------------------------------------------------- c ---------------------------------- c fpvm3_watcom.h c c c For the WIN32 WATCOM fortran compiler... c c To activate throughout your code - uncomment this line c of code in the ../pvm3.4/include/fpvm3.h file c c include '../include/fpvm3_watcom.h' c c ---------------------------------- *$pragma aux pvmfmytid "!_" *$pragma aux pvmfaddhost "!_" *$pragma aux pvmfaddmhf "!_" *$pragma aux pvmfarchcode "!_" *$pragma aux pvmfbarrier "!_" *$pragma aux pvmfbcast "!_" *$pragma aux pvmfbufinfo "!_" *$pragma aux pvmfcatchout "!_" *$pragma aux pvmfconfig "!_" *$pragma aux pvmfdelhost "!_" *$pragma aux pvmfdelinfo "!_" *$pragma aux pvmfdelmhf "!_" *$pragma aux pvmfgather "!_" *$pragma aux pvmffreebuf "!_" *$pragma aux pvmfgetcontext "!_" *$pragma aux pvmffreecontext "!_" *$pragma aux pvmffreezegroup "!_" *$pragma aux pvmfgetmboxinfo "!_" *$pragma aux pvmfgetinst "!_" *$pragma aux pvmfgetopt "!_" *$pragma aux pvmfgetrbuf "!_" *$pragma aux pvmfgetsbuf "!_" *$pragma aux pvmfgettid "!_" *$pragma aux pvmfgsize "!_" *$pragma aux pvmfhalt "!_" *$pragma aux pvmfhostsync "!_" *$pragma aux pvmfinitsend "!_" *$pragma aux pvmfjoingroup "!_" *$pragma aux pvmfkill "!_" *$pragma aux pvmflvgroup "!_" *$pragma aux pvmfmcast "!_" *$pragma aux pvmfmkbuf "!_" *$pragma aux pvmfstat "!_" *$pragma aux pvmfmytid "!_" *$pragma aux pvmfnewcontext "!_" *$pragma aux pvmfnotify "!_" *$pragma aux pvmfnrecv "!_" *$pragma aux pvmfpack "!_" *$pragma aux pvmfperror "!_" *$pragma aux pvmfparent "!_" *$pragma aux pvmfprecv "!_" *$pragma aux pvmfprobe "!_" *$pragma aux pvmfpsend "!_" *$pragma aux pvmfpstat "!_" *$pragma aux pvmfputinfo "!_" *$pragma aux pvmfrecv "!_" *$pragma aux pvmfexit "!_" *$pragma aux pvmfrecvinfo "!_" *$pragma aux pvmfreduce "!_" *$pragma aux pvmfscatter "!_" *$pragma aux pvmfsend "!_" *$pragma aux pvmfsendsig "!_" *$pragma aux pvmfsetopt "!_" *$pragma aux pvmfsetcontext "!_" *$pragma aux pvmfsetrbuf "!_" *$pragma aux pvmfsetsbuf "!_" *$pragma aux pvmfsiblings "!_" *$pragma aux pvmfsleep "!_" *$pragma aux pvmfspawn "!_" *$pragma aux pvmfstartpvmd "!_" *$pragma aux pvmftasks "!_" *$pragma aux pvmftrecv "!_" *$pragma aux pvmfunpack "!_" ./pvm3/include/pvm3.h0100644007401100000360000006027610117661413013574 0ustar kohlgopher /* $Id: pvm3.h,v 1.52 2004/09/08 19:52:43 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvm3.h * * Libpvm3 includes. * * $Log: pvm3.h,v $ * Revision 1.52 2004/09/08 19:52:43 pvmsrc * Upped to PVM version 3.4.5 (how sequential... :) * (Spanker=kohl) * * Revision 1.51 2001/09/27 21:24:18 pvmsrc * Increased default PVMTMPNAMLEN to 64... * - suggested by BEOSCYLD / Joe Vitale * - seems like a good idea. :-) * (Spanker=kohl) * * Revision 1.50 2001/09/27 18:24:39 pvmsrc * Upped version to 3.4.4. * (Spanker=kohl) * * Revision 1.49 2001/09/26 21:55:51 pvmsrc * Oops... fixed function proto for pvmtmpnam()... * - leftover bogus cruft... * (Spanker=kohl) * * Revision 1.48 2001/09/25 21:17:49 pvmsrc * Minor TMPNAMFUN()/tmpnam() cleanup. * - moved macro def to pvm3.h, renamed PVMTNPMAN(). * - same for LEN_OF_TMP_NAM -> PVMTMPNAMLEN. * - mostly a huge waste of time, since *both* tmpnam() & mktemp() * produce the same "dangerous" warning message in Linux/gcc... * - damn. * (Spanker=kohl) * * Revision 1.47 2001/06/18 18:38:23 pvmsrc * Added missing function prototype for pvm_freezegroup()... * (Spanker=kohl) * * Revision 1.46 2000/02/16 22:50:01 pvmsrc * Upped version to 3.4.3 so I don't forget later. * (Spanker=kohl) * * Revision 1.45 2000/02/10 23:53:09 pvmsrc * Added new PvmIPLoopback error code. * - Master Host IP Address tied to Loopback. * (Spanker=kohl) * * Revision 1.44 1999/11/08 17:21:32 pvmsrc * Added PvmMboxDirectIndex stuff: * - PvmMboxMaxFlag: capped regular flags to squeeze in direct index... * - PvmMboxDirectIndexShift: # of bits to shift index in flags * - PvmMboxMaxDirectIndex: max direct index value, for error checking * - PvmMboxDirectIndex(): macro to convert direct index into flag bits * - PvmMboxDirectIndexOf(): macro to decode direct index from flags * (Spanker=kohl) * * Revision 1.43 1999/10/27 18:48:40 pvmsrc * Fixed (yet again) the prototype for pvm_recvf(). * - hopefully got it right this time... :-Q * (Spanker=kohl) * * Revision 1.42 1999/10/22 13:34:55 pvmsrc * Fixed prototype for pvm_recvf(). * - reported by "Ed D'Azevedo" . * (Spanker=kohl) * * Revision 1.41 1999/10/18 21:22:00 pvmsrc * Added function prototypes for: * - pvm_pkmesg(), pvm_pkmesgbody(), pvm_upkmesg(). * (Spanker=kohl) * * Revision 1.40 1999/08/19 16:07:14 pvmsrc * Upped version to 3.4.2. * (Spanker=kohl) * * Revision 1.39 1999/07/08 18:59:47 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.38 1999/06/07 20:06:53 pvmsrc * Upped version to 3.4.1. * (Spanker=kohl) * * Revision 1.37 1999/03/03 19:00:36 pvmsrc * Added new define PVM_PATCH_VERSION. * - the "0" in "3.4.0". * - to go along with PVM_MAJOR_VERSION & PVM_MINOR_VERSION. * (Spanker=kohl) * * Revision 1.36 1999/01/19 18:02:17 pvmsrc * Bumped PVM_VER to 3.4.0. * (Spanker=kohl) * * Revision 1.35 1999/01/13 00:03:19 pvmsrc * Fixed backwards compat. * - redefine old pvm_insert/lookup/delete() consts: * * PvmNoEntry -> PvmNotFound * * PvmDupEntry -> PvmDenied * - remove #ifdef PVM33COMPAT... O.K. in general. * (Spanker=kohl) * * Revision 1.34 1998/08/27 15:17:14 pvmsrc * Time to bump up to beta 7... * (Spanker=kohl) * * Revision 1.33 1997/12/30 18:15:32 pvmsrc * Oops... better skip directly to beta 6 instead of beta 5... * - separate WIN32 release is beta 5... * (Spanker=kohl) * * Revision 1.32 1997/12/29 19:53:51 pvmsrc * Upgraded from beta4 to beta5. * (Spanker=kohl) * * Revision 1.31 1997/09/15 20:54:29 pvmsrc * Fixed PVM_MAJOR_VERSION and PVM_MINOR_VERSION defines. * - VER -> VERSION. * - MAJOR = 3, MINOR = 4 (3.4.*). * (Spanker=kohl) * * Revision 1.30 1997/09/02 13:05:37 pvmsrc * Upgraded PVM_VER to 3.4 beta 4. * (Spanker=kohl) * * Revision 1.29 1997/07/09 13:29:36 pvmsrc * Fixed Author Header. * * Revision 1.28 1997/07/01 17:19:03 pvmsrc * The real real beta version number according to Garp. * * Revision 1.27 1997/07/01 15:54:35 pvmsrc * Trying again on the version. * - just straight 3.4.0. * * Revision 1.26 1997/07/01 14:17:26 pvmsrc * Set version for beta release to 3.4.1.0. * * Revision 1.25 1997/06/26 19:36:22 pvmsrc * Added error constant "PvmParentNotSet" so that * tc_siblings can get sibling tids even if the spawn flags * had parent as PvmNoParent. * * Revision 1.24 1997/06/25 19:41:02 pvmsrc * WIN32 fixes from Markus. * * Revision 1.23 1997/06/23 21:08:42 pvmsrc * Added new error code "PvmHostrNMstr" / -34. * - Hoster run on non-master host. * * Revision 1.22 1997/06/10 16:38:53 pvmsrc * Minor text cleanup. * * Revision 1.21 1997/05/06 18:58:56 pvmsrc * Upped version to 3.4.0.16. * * Revision 1.20 1997/04/17 12:52:28 pvmsrc * rename of pvm_mboxinfo() to include word "get" * * Revision 1.19 1997/04/10 20:09:57 pvmsrc * Fixed prototype for pvm_mboxinfo(). * - pvm_getnames() is history. * * Revision 1.18 1997/04/10 19:34:57 pvmsrc * Added new pvmmboxinfo structure. * - for pvm_mboxinfo(). * * Revision 1.17 1997/04/09 20:21:51 pvmsrc * Added PvmMboxWaitForInfo/PVMMBOXWAITFORINFO constants. * * Revision 1.16 1997/04/07 20:50:48 pvmsrc * pvm_addmhf() protoglarp set to new parameter interface * * Revision 1.15 1997/04/03 18:19:02 pvmsrc * Added a define for PvmBaseContext - this is 3.3 compatible context. * codes that don't ever set their context should operate in this context. * * Revision 1.14 1997/04/01 16:46:09 pvmsrc * Fixed protos for pvm_putinfo(), pvm_recvinfo() (formerly pvm_getinfo()). * * Revision 1.13 1997/03/31 21:38:05 pvmsrc * Replaced original mbox constants with new syntax: * - gone: PvmExclusive, PvmFirstAvail, PvmLock, PvmSticky. * - new: PvmMboxDefault, PvmMboxPersistent, PvmMboxMultiInstance, * PvmMboxOverWritable, PvmMboxFirstAvail, PvmMboxReadAndDelete. * - fortran equivalents. * - checked in for sscott. * * Revision 1.12 1997/03/26 21:51:55 pvmsrc * Added "PvmNoSpawnParent" spawn option constant. * - PVMNOSPAWNPARENT for Fortran. * * Revision 1.11 1997/03/07 14:41:10 pvmsrc * PVM patches from the base 3.3.10 to 3.3.11 versions where applicable. * Originals by Bob Manchek. Altered by Graham Fagg where required. * * added pvm_export / pvm_unexport to user API. * * Revision 1.10 1997/03/04 19:44:11 pvmsrc * Added system message mailbox class name #defines: * - PVMHOSTERCLASS, PVMTASKERCLASS, PVMTRACERCLASS, PVMRMCLASS. * * Revision 1.9 1997/02/17 18:47:51 pvmsrc * Oops... must pass ptr to tids array for pvm_getnoresets(). * * Revision 1.8 1997/02/17 16:30:11 pvmsrc * Added proto for new pvm_getnoresets() routine. * - note: not an official interface routine... * * Revision 1.7 1997/02/13 23:12:41 pvmsrc * Added PVMNORESETCLASS class name for PvmNoReset. * * Revision 1.6 1997/02/13 23:05:22 pvmsrc * Added new PvmNoReset setopt/getopt constant. * * Revision 1.5 1997/01/28 19:14:20 pvmsrc * New Copyright Notice & Authors. * * Revision 1.4 1996/10/24 19:33:48 pvmsrc * Modified for New Tracing Facility: * - added user-defined message encoding, PvmDataTrace. * - added new option constants: * PvmTraceBuffer, PvmTraceOptions, * PvmSelfTraceBuffer & PvmSelfTraceOptions, * - added PvmTraceFull, PvmTraceTime & PvmTraceCount for trace opts. * - added function prototype for new pvm_reg_tracer() routine. * * Revision 1.3 1996/10/11 17:01:52 pvmsrc * Replaced references to pvm_remove() with pvm_delinfo(): renamed. * * Revision 1.2 1996/10/08 18:30:30 pvmsrc * Renamed routines: * - pvm_put() -> pvm_putinfo(). * - pvm_get() -> pvm_getinfo(). * * Revision 1.1 1996/09/23 21:06:31 pvmsrc * Initial revision * */ #ifndef _PVM3_H_ #define _PVM3_H_ /* * Release version */ #define PVM_VER "3.4.5" #define PVM_MAJOR_VERSION 3 #define PVM_MINOR_VERSION 4 #define PVM_PATCH_VERSION 5 #ifndef WIN32 #include #else #include "pvmwin.h" #include #include #endif /* * Data packing styles for pvm_initsend() */ #define PvmDataDefault 0 /* XDR encoding */ #define PvmDataRaw 1 /* Raw data copy */ #define PvmDataInPlace 2 /* Raw data, left in place */ #define PvmDataFoo PvmDataDefault /* Internal use */ #define PvmDataTrace 4 /* User-Defined Trace Encoding */ /* * pvm_spawn options */ #define PvmTaskDefault 0 #define PvmTaskHost 1 /* specify host */ #define PvmTaskArch 2 /* specify architecture */ #define PvmTaskDebug 4 /* start task in debugger */ #define PvmTaskTrace 8 /* process generates trace data */ /* for MPP ports */ #define PvmMppFront 16 /* spawn task on service node */ #define PvmHostCompl 32 /* complement host set */ /* for parent-less spawning */ #define PvmNoSpawnParent 64 /* * pvm_notify kinds */ #define PvmTaskExit 1 /* on task exit */ #define PvmHostDelete 2 /* on host fail/delete */ #define PvmHostAdd 3 /* on host startup */ #define PvmRouteAdd 4 /* new task-task route opened */ #define PvmRouteDelete 5 /* task-task route closed */ /* flags combined with notify kind */ #define PvmNotifyCancel 256 /* cancel (complete immediately) notifies */ /* * for pvm_setopt and pvm_getopt */ #define PvmRoute 1 /* routing policy */ #define PvmDontRoute 1 /* don't allow direct task-task links */ #define PvmAllowDirect 2 /* allow direct links, but don't request */ #define PvmRouteDirect 3 /* request direct links */ #define PvmDebugMask 2 /* debugmask */ #define PvmAutoErr 3 /* auto error reporting */ #define PvmOutputTid 4 /* stdout destination for children */ #define PvmOutputCode 5 /* stdout message tag */ #define PvmTraceTid 6 /* trace destination for children */ #define PvmTraceCode 7 /* trace message tag */ #define PvmTraceBuffer 8 /* trace buffering for children */ #define PvmTraceOptions 9 /* trace options for children */ #define PvmTraceFull 1 /* do full trace events */ #define PvmTraceTime 2 /* only do PVM routine timings */ #define PvmTraceCount 3 /* only do PVM routine profiling */ #define PvmFragSize 10 /* message fragment size */ #define PvmResvTids 11 /* allow reserved message tids and codes */ #define PvmSelfOutputTid 12 /* stdout destination for task */ #define PvmSelfOutputCode 13 /* stdout message tag */ #define PvmSelfTraceTid 14 /* trace destination for task */ #define PvmSelfTraceCode 15 /* trace message tag */ #define PvmSelfTraceBuffer 16 /* trace buffering for task */ #define PvmSelfTraceOptions 17 /* trace options for task */ #define PvmShowTids 18 /* pvm_catchout prints task ids with output */ #define PvmPollType 19 /* shared memory wait method */ #define PvmPollConstant 1 #define PvmPollSleep 2 #define PvmPollTime 20 /* time before sleep if PvmPollSleep */ #define PvmOutputContext 21 /* stdout message context */ #define PvmTraceContext 22 /* trace message context */ #define PvmSelfOutputContext 23 /* stdout message context */ #define PvmSelfTraceContext 24 /* trace message context */ #define PvmNoReset 25 /* do not kill task on reset */ /* * for pvm_[sg]ettmask */ #define PvmTaskSelf 0 /* this task */ #define PvmTaskChild 1 /* (future) child tasks */ /* * Need to have PvmBaseContext defined */ #define PvmBaseContext 0 /* * for message mailbox operations: pvm_putinfo and pvm_recvinfo */ #define PvmMboxDefault 0 /* put: single locked instance */ /* recv: 1st entry */ /* start w/index=0 */ #define PvmMboxPersistent 1 /* entry remains after owner exit */ #define PvmMboxMultiInstance 2 /* multiple entries in class */ #define PvmMboxOverWritable 4 /* can write over this entry */ #define PvmMboxFirstAvail 8 /* select 1st index >= specified */ #define PvmMboxReadAndDelete 16 /* atomic read / delete */ /* requires read & delete rights */ #define PvmMboxWaitForInfo 32 /* for blocking recvinfo */ #define PvmMboxMaxFlag 512 /* maximum mbox flag bit value */ #define PvmMboxDirectIndexShift 10 /* log2(PvmMboxMaxFlag) + 1 */ #define PvmMboxMaxDirectIndex \ ( (unsigned) 1 << ( 31 - PvmMboxDirectIndexShift ) ) #define PvmMboxDirectIndexOf( _flags ) \ ( ( (_flags) & \ ( ( PvmMboxMaxDirectIndex - 1 ) << PvmMboxDirectIndexShift ) ) \ >> PvmMboxDirectIndexShift ) #define PvmMboxDirectIndex( _index ) \ ( ( (_index) >= PvmMboxMaxDirectIndex ) ? \ ( fprintf( stderr, "Mbox Direct Index Too Large: %d >= %d\n", \ (_index), PvmMboxMaxDirectIndex ), 0 ) \ : ( (_index) << PvmMboxDirectIndexShift ) ) /* * pre-defined system message mailbox classes */ #define PVMNORESETCLASS "###_PVM_NO_RESET_###" #define PVMHOSTERCLASS "###_PVM_HOSTER_###" #define PVMTASKERCLASS "###_PVM_TASKER_###" #define PVMTRACERCLASS "###_PVM_TRACER_###" #define PVMRMCLASS "###_PVM_RM_###" /* * Libpvm error codes */ #define PvmOk 0 /* Success */ #define PvmBadParam -2 /* Bad parameter */ #define PvmMismatch -3 /* Parameter mismatch */ #define PvmOverflow -4 /* Value too large */ #define PvmNoData -5 /* End of buffer */ #define PvmNoHost -6 /* No such host */ #define PvmNoFile -7 /* No such file */ #define PvmDenied -8 /* Permission denied */ #define PvmNoMem -10 /* Malloc failed */ #define PvmBadMsg -12 /* Can't decode message */ #define PvmSysErr -14 /* Can't contact local daemon */ #define PvmNoBuf -15 /* No current buffer */ #define PvmNoSuchBuf -16 /* No such buffer */ #define PvmNullGroup -17 /* Null group name */ #define PvmDupGroup -18 /* Already in group */ #define PvmNoGroup -19 /* No such group */ #define PvmNotInGroup -20 /* Not in group */ #define PvmNoInst -21 /* No such instance */ #define PvmHostFail -22 /* Host failed */ #define PvmNoParent -23 /* No parent task */ #define PvmNotImpl -24 /* Not implemented */ #define PvmDSysErr -25 /* Pvmd system error */ #define PvmBadVersion -26 /* Version mismatch */ #define PvmOutOfRes -27 /* Out of resources */ #define PvmDupHost -28 /* Duplicate host */ #define PvmCantStart -29 /* Can't start pvmd */ #define PvmAlready -30 /* Already in progress */ #define PvmNoTask -31 /* No such task */ #define PvmNotFound -32 /* Not Found */ #define PvmExists -33 /* Already exists */ #define PvmHostrNMstr -34 /* Hoster run on non-master host */ #define PvmParentNotSet -35 /* Spawning parent set PvmNoSpawnParent */ #define PvmIPLoopback -36 /* Master Host's IP is Loopback */ /* * crusty error constants from 3.3, now redefined... */ #define PvmNoEntry PvmNotFound /* No such entry */ #define PvmDupEntry PvmDenied /* Duplicate entry */ /* * Data types for pvm_reduce(), pvm_psend(), pvm_precv() */ #define PVM_STR 0 /* string */ #define PVM_BYTE 1 /* byte */ #define PVM_SHORT 2 /* short */ #define PVM_INT 3 /* int */ #define PVM_FLOAT 4 /* real */ #define PVM_CPLX 5 /* complex */ #define PVM_DOUBLE 6 /* double */ #define PVM_DCPLX 7 /* double complex */ #define PVM_LONG 8 /* long integer */ #define PVM_USHORT 9 /* unsigned short int */ #define PVM_UINT 10 /* unsigned int */ #define PVM_ULONG 11 /* unsigned long int */ /* * returned by pvm_config() */ struct pvmhostinfo { int hi_tid; /* pvmd tid */ char *hi_name; /* host name */ char *hi_arch; /* host arch */ int hi_speed; /* cpu relative speed */ int hi_dsig; /* data signature */ }; /* * returned by pvm_tasks() */ struct pvmtaskinfo { int ti_tid; /* task id */ int ti_ptid; /* parent tid */ int ti_host; /* pvmd tid */ int ti_flag; /* status flags */ char *ti_a_out; /* a.out name */ int ti_pid; /* task (O/S dependent) process id */ }; /* * for pvm_getminfo(), pvm_setminfo() */ struct pvmminfo { int len; /* message length */ int ctx; /* context */ int tag; /* tag */ int wid; /* wait id */ int enc; /* encoding */ int crc; /* crc checksum */ int src; /* source tid */ int dst; /* destination tid */ }; /* * returned by pvm_getmboxinfo() */ struct pvmmboxinfo { char *mi_name; /* class name */ int mi_nentries; /* # of entries for this class */ int *mi_indices; /* mbox entry indices */ int *mi_owners; /* mbox entry owner tids */ int *mi_flags; /* mbox entry flags */ }; /* * temporary file name function / macro * (since there are so many choices, but so little time, * and since gcc now complains about tmpnam()... :-Q) */ #ifdef NOTMPNAM #define PVMTMPNAMFUN(x) pvmtmpnam(x) #define PVMTMPNAMLEN 64 #else #define PVMTMPNAMFUN(x) tmpnam(x) #ifdef L_tmpnam #define PVMTMPNAMLEN L_tmpnam #else #define PVMTMPNAMLEN 64 #endif #endif /* * function prototypes */ #ifdef __ProtoGlarp__ #undef __ProtoGlarp__ #endif #if defined(__STDC__) || defined(__cplusplus) #define __ProtoGlarp__(x) x #else #define __ProtoGlarp__(x) () #endif #ifdef __cplusplus extern "C" { #endif #ifdef NOTMPNAM char *pvmtmpnam __ProtoGlarp__(( char * )); #endif char *pvmgetrsh __ProtoGlarp__(( void )); char *pvmgettmp __ProtoGlarp__(( void )); int pvm_addhosts __ProtoGlarp__(( char **, int, int * )); int pvm_addmhf __ProtoGlarp__(( int, int, int, int (*) (int) )); int pvm_archcode __ProtoGlarp__(( char * )); int pvm_barrier __ProtoGlarp__(( char *, int )); int pvm_bcast __ProtoGlarp__(( char *, int )); int pvm_bufinfo __ProtoGlarp__(( int, int *, int *, int * )); #if defined(EOF) int pvm_catchout __ProtoGlarp__(( FILE * )); #endif int pvm_config __ProtoGlarp__(( int *, int *, struct pvmhostinfo ** )); int pvm_delhosts __ProtoGlarp__(( char **, int, int * )); int pvm_delinfo __ProtoGlarp__(( char *, int, int )); int pvm_delmhf __ProtoGlarp__(( int )); int pvm_exit __ProtoGlarp__(( void )); int pvm_export __ProtoGlarp__(( char * )); int pvm_freebuf __ProtoGlarp__(( int )); int pvm_freecontext __ProtoGlarp__(( int )); int pvm_freezegroup __ProtoGlarp__(( char *, int )); int pvm_gather __ProtoGlarp__(( void*, void*, int, int, int, char*, int)); int pvm_getcontext __ProtoGlarp__(( void )); int pvm_getfds __ProtoGlarp__(( int ** )); int pvm_getinst __ProtoGlarp__(( char *, int )); int pvm_getminfo __ProtoGlarp__(( int, struct pvmminfo * )); int pvm_getnoresets __ProtoGlarp__(( int **, int * )); int pvm_getopt __ProtoGlarp__(( int )); int pvm_getrbuf __ProtoGlarp__(( void )); int pvm_getsbuf __ProtoGlarp__(( void )); int pvm_gettid __ProtoGlarp__(( char *, int )); int pvm_gsize __ProtoGlarp__(( char * )); int pvm_halt __ProtoGlarp__(( void )); int pvm_hostsync __ProtoGlarp__(( int, struct timeval *, struct timeval * )); int pvm_initsend __ProtoGlarp__(( int )); int pvm_joingroup __ProtoGlarp__(( char * )); int pvm_kill __ProtoGlarp__(( int )); int pvm_lvgroup __ProtoGlarp__(( char * )); int pvm_getmboxinfo __ProtoGlarp__(( char *, int *, struct pvmmboxinfo ** )); int pvm_mcast __ProtoGlarp__(( int *, int, int )); int pvm_mkbuf __ProtoGlarp__(( int )); int pvm_mstat __ProtoGlarp__(( char * )); int pvm_mytid __ProtoGlarp__(( void )); int pvm_newcontext __ProtoGlarp__(( void )); int pvm_notify __ProtoGlarp__(( int, int, int, int * )); int pvm_nrecv __ProtoGlarp__(( int, int )); int pvm_packf __ProtoGlarp__(( const char *, ... )); int pvm_parent __ProtoGlarp__(( void )); int pvm_perror __ProtoGlarp__(( char * )); int pvm_pkbyte __ProtoGlarp__(( char *, int, int )); int pvm_pkcplx __ProtoGlarp__(( float *, int, int )); int pvm_pkdcplx __ProtoGlarp__(( double *, int, int )); int pvm_pkdouble __ProtoGlarp__(( double *, int, int )); int pvm_pkfloat __ProtoGlarp__(( float *, int, int )); int pvm_pkint __ProtoGlarp__(( int *, int, int )); int pvm_pklong __ProtoGlarp__(( long *, int, int )); int pvm_pkshort __ProtoGlarp__(( short *, int, int )); int pvm_pkstr __ProtoGlarp__(( char * )); int pvm_pkuint __ProtoGlarp__(( unsigned int *, int, int )); int pvm_pkulong __ProtoGlarp__(( unsigned long *, int, int )); int pvm_pkushort __ProtoGlarp__(( unsigned short *, int, int )); int pvm_pkmesg __ProtoGlarp__(( int )); int pvm_pkmesgbody __ProtoGlarp__(( int )); int pvm_precv __ProtoGlarp__(( int, int, void *, int, int, int *, int *, int * )); int pvm_probe __ProtoGlarp__(( int, int )); int pvm_psend __ProtoGlarp__(( int, int, void *, int, int )); int pvm_pstat __ProtoGlarp__(( int )); int pvm_putinfo __ProtoGlarp__(( char *, int, int )); int pvm_recv __ProtoGlarp__(( int, int )); int (*pvm_recvf __ProtoGlarp__(( int (*)(int, int, int) )) ) __ProtoGlarp__(( int (*)(int, int, int) )); int pvm_recvinfo __ProtoGlarp__(( char *, int, int )); int pvm_reduce __ProtoGlarp__(( void (*)(int*, void*, void*, int*, int*), void *, int, int, int, char *, int )); /* * Predefined pvm_reduce functions */ void PvmMax __ProtoGlarp__(( int *, void *, void *, int *, int * )); void PvmMin __ProtoGlarp__(( int *, void *, void *, int *, int * )); void PvmSum __ProtoGlarp__(( int *, void *, void *, int *, int * )); void PvmProduct __ProtoGlarp__(( int *, void *, void *, int *, int * )); int pvm_reg_hoster __ProtoGlarp__(( void )); int pvm_reg_rm __ProtoGlarp__(( struct pvmhostinfo ** )); int pvm_reg_tasker __ProtoGlarp__(( void )); int pvm_reg_tracer __ProtoGlarp__(( int, int, int, int, char*, int, int )); int pvm_scatter __ProtoGlarp__(( void*, void*, int, int, int, char*, int)); int pvm_send __ProtoGlarp__(( int, int )); int pvm_sendsig __ProtoGlarp__(( int, int )); int pvm_setcontext __ProtoGlarp__(( int )); int pvm_setminfo __ProtoGlarp__(( int, struct pvmminfo * )); int pvm_setopt __ProtoGlarp__(( int, int )); int pvm_setrbuf __ProtoGlarp__(( int )); int pvm_setsbuf __ProtoGlarp__(( int )); int pvm_siblings __ProtoGlarp__(( int ** )); int pvm_spawn __ProtoGlarp__(( char *, char **, int, char *, int, int * )); int pvm_start_pvmd __ProtoGlarp__(( int, char **, int )); int pvm_tasks __ProtoGlarp__(( int, int *, struct pvmtaskinfo ** )); int pvm_tickle __ProtoGlarp__(( int, int *, int *, int * )); int pvm_tidtohost __ProtoGlarp__(( int )); int pvm_trecv __ProtoGlarp__(( int, int, struct timeval * )); int pvm_unexport __ProtoGlarp__(( char * )); int pvm_unpackf __ProtoGlarp__(( const char *, ... )); int pvm_upkbyte __ProtoGlarp__(( char *, int, int )); int pvm_upkcplx __ProtoGlarp__(( float *, int, int )); int pvm_upkdcplx __ProtoGlarp__(( double *, int, int )); int pvm_upkdouble __ProtoGlarp__(( double *, int, int )); int pvm_upkfloat __ProtoGlarp__(( float *, int, int )); int pvm_upkint __ProtoGlarp__(( int *, int, int )); int pvm_upklong __ProtoGlarp__(( long *, int, int )); int pvm_upkshort __ProtoGlarp__(( short *, int, int )); int pvm_upkstr __ProtoGlarp__(( char * )); int pvm_upkuint __ProtoGlarp__(( unsigned int *, int, int )); int pvm_upkulong __ProtoGlarp__(( unsigned long *, int, int )); int pvm_upkushort __ProtoGlarp__(( unsigned short *, int, int )); int pvm_upkmesg __ProtoGlarp__(( void )); char *pvm_version __ProtoGlarp__(( void )); /* * these are going away in the next version. * use the replacements */ #ifdef PVM33COMPAT int pvm_getmwid __ProtoGlarp__(( int )); int pvm_setmwid __ProtoGlarp__(( int, int )); #endif /* these are now backwards compatible -> they use mbox interface... */ int pvm_delete __ProtoGlarp__(( char *, int )); int pvm_insert __ProtoGlarp__(( char *, int, int )); int pvm_lookup __ProtoGlarp__(( char *, int, int * )); #ifdef __cplusplus } #endif #endif /*_PVM3_H_*/ ./pvm3/include/pvmproto.h0100644007401100000360000003636007050621412014567 0ustar kohlgopher /* $Id: pvmproto.h,v 1.18 2000/02/10 20:43:54 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmproto.h * * PVM protocol definitions. * * $Log: pvmproto.h,v $ * Revision 1.18 2000/02/10 20:43:54 pvmsrc * Removed hard-coded /tmp in TDSOCKNAME / TDSOCKNAME_CSPP. * - use pvmgettmp() routine now to determine PVM temp dir. * (Spanker=kohl) * * Revision 1.17 1999/07/08 18:59:48 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.16 1998/01/12 21:12:01 pvmsrc * Added task output collection op defines. * - TO_NEW, TO_SPAWN, TO_EOF. * (Spanker=kohl) * * Revision 1.15 1997/10/22 22:08:16 pvmsrc * Added SYSCTX_DG constant for dynamic group context. * (Spanker=kohl) * * Revision 1.14 1997/10/01 15:34:49 pvmsrc * Fixed TM_LAST decl. * - should be same as last entry, not last + 1... * (Spanker=kohl) * * Revision 1.13 1997/07/09 13:29:37 pvmsrc * Fixed Author Header. * * Revision 1.12 1997/06/10 16:38:55 pvmsrc * Minor text cleanup. * * Revision 1.11 1997/05/29 15:15:05 pvmsrc * Fixed decl of SM_FIRST: * - some compilers too stupid to know it's an (int)0x80040001... * - D-Oh. * * Revision 1.10 1997/05/27 14:40:58 pvmsrc * Added new TM message: * TM_SHMCONN. This allows socket and shmem task structs to be merged. * Also when exchanged sets new TF flag TF_SHMCONN. * * Revision 1.9 1997/04/09 14:37:17 pvmsrc * PVM patches from the base 3.3.10 to 3.3.11 versions where applicable. * Originals by Bob Manchek. Altered by Graham Fagg where required. * * Revision 1.8 1997/04/08 19:18:11 pvmsrc * Damn. Added matching DM_RESETACK constant... :-Q * * Revision 1.7 1997/04/08 19:05:51 pvmsrc * Added DM_RESET constant. * - for reset of system, cleanup of persistent message mboxes. * * Revision 1.6 1997/04/07 18:20:15 pvmsrc * Added TMDB_RESET constant. * - for resetting mbox db on pvmreset()... * * Revision 1.5 1997/04/04 15:45:03 pvmsrc * Typos CTXT -> CTX for consistency. Affects task.c, too * * Revision 1.4 1997/04/03 19:15:52 pvmsrc * Added some system defined contexts for use by TM, TC messages * * Revision 1.3 1997/04/03 16:12:38 pvmsrc * Added correct macro for sequence number wrap-around comparison. * This is on SEQLESSTHAN and is useful for 16 bit sequence numbers * * Revision 1.2 1997/01/28 19:14:22 pvmsrc * New Copyright Notice & Authors. * * Revision 1.1 1996/10/25 13:43:38 pvmsrc * Initial revision * * */ #ifndef _PVMPROTO_H_ #define _PVMPROTO_H_ /* protocol version */ #ifndef SDPROTOCOL #define SDPROTOCOL 4302 #endif /* * t - task * d - pvmd * R - resource manager * H - hoster * T - tasker */ #define SM_FIRST (int)0x80040001 /* first SM_ message */ #define SM_SPAWN (SM_FIRST+0) /* t<>R like TM_SPAWN */ #define SM_EXEC (SM_FIRST+1) /* R->d like DM_EXEC */ #define SM_EXECACK (SM_FIRST+2) /* d->R like DM_EXECACK */ #define SM_TASK (SM_FIRST+3) /* t<>R like TM_TASK */ #define SM_CONFIG (SM_FIRST+4) /* t<>R like TM_CONFIG */ #define SM_ADDHOST (SM_FIRST+5) /* t<>R like TM_ADDHOST */ #define SM_DELHOST (SM_FIRST+6) /* t<>R like TM_DELHOST */ #define SM_ADD (SM_FIRST+7) /* R->d like DM_ADD */ #define SM_ADDACK (SM_FIRST+8) /* d->R like DM_ADDACK */ #define SM_NOTIFY (SM_FIRST+9) /* t->R like TM_NOTIFY */ #define SM_TASKX (SM_FIRST+10) /* d->R notify of task exit */ #define SM_HOSTX (SM_FIRST+11) /* d->R notify sched of host delete */ #define SM_HANDOFF (SM_FIRST+12) /* R->d pvmd to new sched */ #define SM_SCHED (SM_FIRST+13) /* t<>R like TM_SCHED */ #define SM_STHOST (SM_FIRST+14) /* d->H start slave pvmds */ #define SM_STHOSTACK (SM_FIRST+15) /* H->d like DM_STARTACK */ #define SM_STTASK (SM_FIRST+16) /* d->T start task */ #define SM_LAST (SM_FIRST+16) /* last SM_ message */ /* * ddpro.h * * Pvmd-pvmd protocol * * Revision 1.5 1996/05/13 20:24:06 manchek * [GEF pvm3.3.10to11 patch updates] * added PVMDISTASK * * Revision 1.4 1995/05/17 16:06:18 manchek * cast DM_FIRST to int. * added debugging classes * * Revision 1.3 1994/07/18 19:19:27 manchek * added PDMWAITC * * Revision 1.2 1994/06/03 20:38:13 manchek * version 3.3.0 * * Revision 1.1 1993/08/30 23:26:47 manchek * Initial revision * */ /* protocol version */ #ifndef DDPROTOCOL #define DDPROTOCOL 2316 #endif #define DDMINRETRIES 10 #define DDMAXRTT 9 /* seconds */ #define DDMINTIMEOUT (DDMINRETRIES*DDMAXRTT*2) /* seconds */ #define DDERRRETRY 300000 /* uSec */ #define DDPINGTIME 60 /* (sec) between keepalive pings */ #define DDBAILTIME 300 /* (sec) for new slave to bail if no config */ #define NEXTSEQNUM(x) (((x)+1)&0xffff) #define SEQNUMCOMPARE(x,y) ((x)<(y)||(((x)>0x8000)&&((y)<0x8000))) #define SEQLESSTHAN(x,y)( ((x)<(y) && (y)-(x) < 32768) ||\ ((x)>(y) && (x)-(y) >= 32768) ) /*DocThis*/ /* * Pvmd-pvmd packet header * * 0 1 2 3 * +---------------------------------------------------------------+ * 0| dst | * +---------------------------------------------------------------+ * 4| src | * +-------------------------------+-------------------------------+ * 8| seq | ack | * +---------------+---------------+-------------------------------+ * 12| flags | | * +---------------+-----------------------------------------------+ */ /*EndDocThis*/ #define DDFRAGHDR 16 /* frag flags */ #define FFDAT 4 /* packet contains data, seq num is valid */ #define FFFIN 8 /* sender closing connection */ #define FFACK 16 /* ack num is valid */ /* d-d message flavors */ #define DM_FIRST (int)0x80020001 /* first DM_ message */ #define DM_ADD (DM_FIRST+0) /* add hosts to machine */ #define DM_ADDACK (DM_FIRST+1) #define DM_EXEC (DM_FIRST+2) /* start tasks */ #define DM_EXECACK (DM_FIRST+3) #define DM_SENDSIG (DM_FIRST+4) /* signal a task */ #define DM_HTUPD (DM_FIRST+5) /* define new host table */ #define DM_HTUPDACK (DM_FIRST+6) #define DM_HTCOMMIT (DM_FIRST+7) /* switch to new host table */ #define DM_SLCONF (DM_FIRST+8) /* config slave pvmd */ #define DM_STARTACK (DM_FIRST+9) /* pvmd' completed slave startup */ #define DM_TASK (DM_FIRST+10) /* get list of tasks */ #define DM_TASKACK (DM_FIRST+11) #define DM_DELHOST (DM_FIRST+12) /* delete hosts from machine */ #define DM_DELHOSTACK (DM_FIRST+13) #define DM_NULL (DM_FIRST+14) /* null message */ #define DM_TASKOUT (DM_FIRST+15) /* task standard out/err data */ #define DM_PSTAT (DM_FIRST+16) /* query status of task */ #define DM_PSTATACK (DM_FIRST+17) #define DM_HALT (DM_FIRST+18) /* request master pvmd to halt */ #define DM_MCA (DM_FIRST+19) /* define multicast tid */ #define DM_NOTIFY (DM_FIRST+20) /* request notify */ #define DM_NOTIFYACK (DM_FIRST+21) #define DM_DB (DM_FIRST+22) /* message-mailbox request */ #define DM_DBACK (DM_FIRST+23) #define DM_RESET (DM_FIRST+24) /* reset linkage (mbox tidy) */ #define DM_RESETACK (DM_FIRST+25) #define DM_HTDEL (DM_FIRST+26) /* delete hosts from host table */ #define DM_HOSTSYNC (DM_FIRST+27) /* request clock sample */ #define DM_HOSTSYNCACK (DM_FIRST+28) #define DM_LAST (DM_FIRST+28) /* last DM_ message */ /* DM_SLCONF fields - don't use 0 */ #define DM_SLCONF_EP 1 /* set epath */ #define DM_SLCONF_BP 2 /* set bpath */ #define DM_SLCONF_WD 3 /* set wdir */ #define DM_SLCONF_SCHED 4 /* set scheduler tid */ #define DM_SLCONF_TRACE 5 /* set tracer info */ /* pvmd run states */ #define PVMDNORMAL 1 /* normal running state */ #define PVMDHTUPD 2 /* getting host table update */ #define PVMDSTARTUP 3 /* slave just started, not fully configured */ #define PVMDPRIME 4 /* am pvmd' */ #define PVMDHALTING 5 /* stopping rsn */ #define PVMDSHUTDOWN 6 /* in timeout to halt, waiting for FIN|ACK */ #define PVMDISTASK 7 /* between fork and exec to spawn task */ /* used to cache multicast addresses */ struct mca { struct mca *mc_link; /* dll of peers */ struct mca *mc_rlink; int mc_tid; /* the multicast tid */ int mc_ndst; /* number of dsts */ int *mc_dsts; /* dst tids (local tasks or foreign pvmds) */ }; struct mca *mca_new __ProtoGlarp__(( void )); void mca_free __ProtoGlarp__((struct mca *mcap)); struct pmsg *mesg_new __ProtoGlarp__(( int master )); /* * tdpro.h * * Task-pvmd protocol * * Revision 1.5 1995/06/28 15:32:29 manchek * added TC_SHMAT * * Revision 1.4 1995/05/17 16:56:06 manchek * added support for CSPP subcomplexes (/tmp file naming). * case TM_FIRST, TC_FIRST to int * add TM_GETOPT message * * Revision 1.3 1994/06/03 20:38:31 manchek * version 3.3.0 * * Revision 1.2 1993/10/04 20:30:50 manchek * added alternate TDSOCKNAME if SHAREDTMP is defined * * Revision 1.1 1993/08/30 23:26:52 manchek * Initial revision * */ /* protocol version */ #ifndef TDPROTOCOL #define TDPROTOCOL 1318 #endif /*DocThis*/ /* * Task-task, task-pvmd fragment header * * 0 1 2 3 * +---------------------------------------------------------------+ * 0| dst | * +---------------------------------------------------------------+ * 4| src | * +---------------------------------------------------------------+ * 8| length | * +---------------+-----------------------------------------------+ * 12| flags | | * +---------------+-----------------------------------------------+ */ /*EndDocThis*/ #define TDFRAGHDR 16 /* * Maximum size of all headers in system */ #define MAXHDR ((DDFRAGHDR > TDFRAGHDR ? DDFRAGHDR : TDFRAGHDR) \ + MSGHDRLEN) /* file with task->pvmd sockaddr */ #ifdef SHAREDTMP #define TDSOCKNAME "%s/pvmd.%d.%s" #else #define TDSOCKNAME "%s/pvmd.%d" #endif #ifdef IMA_CSPP #ifdef SHAREDTMP #define TDSOCKNAME_CSPP "%s/pvmd.%d.%d.%s" #else #define TDSOCKNAME_CSPP "%s/pvmd.%d.%d" #endif #endif /*IMA_CSPP*/ #define TM_FIRST (int)0x80010001 /* first TM_ message */ #define TM_CONNECT (TM_FIRST+0) /* task connects */ #define TM_CONN2 (TM_FIRST+1) /* 2nd round of connect */ #define TM_EXIT (TM_FIRST+2) /* task disconnects */ #define TM_ADDHOST (TM_FIRST+3) /* add hosts to machine */ #define TM_DELHOST (TM_FIRST+4) /* delete hosts from machine */ #define TM_CONFIG (TM_FIRST+5) /* get machine config */ #define TM_MSTAT (TM_FIRST+6) /* get host status */ #define TM_HALT (TM_FIRST+7) /* halt machine */ #define TM_TICKLE (TM_FIRST+8) /* tickle pvmd */ #define TM_SPAWN (TM_FIRST+9) /* spawn new tasks */ #define TM_PSTAT (TM_FIRST+10) /* get task status */ #define TM_SENDSIG (TM_FIRST+11) /* signal a task */ #define TM_TASK (TM_FIRST+12) /* list tasks */ #define TM_MCA (TM_FIRST+13) /* request multicast tid */ #define TM_NOTIFY (TM_FIRST+14) /* request notification */ #define TM_DB (TM_FIRST+15) /* message-mailbox request */ #define TM_SCHED (TM_FIRST+16) /* register task as scheduler */ #define TM_TASKER (TM_FIRST+17) /* register task as task starter */ #define TM_HOSTER (TM_FIRST+18) /* register task as pvmd starter */ #define TM_TRACER (TM_FIRST+19) /* register task as task tracer */ #define TM_HOSTSYNC (TM_FIRST+20) /* get clock delta to host */ #define TM_SETOPT (TM_FIRST+21) /* set task parameters */ #define TM_GETOPT (TM_FIRST+22) /* get all task parameters */ #define TM_CONTEXT (TM_FIRST+23) /* allocate or free a context id */ #define TM_SHMCONN (TM_FIRST+24) /* shmem task connect */ #define TM_LAST (TM_FIRST+24) /* last TM_ message */ /* * for TM_DB */ #define TMDB_PUT 1 /* insert message */ #define TMDB_REMOVE 2 /* delete entry */ #define TMDB_GET 3 /* retrieve entry */ #define TMDB_NAMES 4 /* get list of all names defined */ #define TMDB_RESET 5 /* wipe out mbox db entries */ /* * for TM_SETOPT */ #define TS_OUTTID 1 /* stdout dst */ #define TS_OUTCTX 2 /* stdout message context */ #define TS_OUTTAG 3 /* stdout message tag */ #define TS_TRCTID 4 /* trace dst */ #define TS_TRCCTX 5 /* trace message context */ #define TS_TRCTAG 6 /* trace message tag */ #define TC_FIRST (int)0x80030001 /* first TC_ message */ #define TC_CONREQ (TC_FIRST+0) /* connection request */ #define TC_CONACK (TC_FIRST+1) /* connection request ack */ #define TC_TASKEXIT (TC_FIRST+2) /* task exited/doesn't exist */ #define TC_NOOP (TC_FIRST+3) /* do nothing */ #define TC_OUTPUT (TC_FIRST+4) /* child stdout data */ #define TC_SETTRACE (TC_FIRST+5) /* set task tracing */ #define TC_SETTMASK (TC_FIRST+6) /* set task trace mask */ #define TC_SETTRCBUF (TC_FIRST+7) /* set task trace buffer */ #define TC_SETTRCOPT (TC_FIRST+8) /* set task trace options */ #define TC_SHMAT (TC_FIRST+9) /* shmem connect handshake */ #define TC_OUTPUTX (TC_FIRST+10) /* (not sent) flush out coll */ #define TC_SIBLINGS (TC_FIRST+11) /* parent announce spawn grp */ #define TC_LAST (TC_FIRST+11) /* last TC_ message */ /* * for Task Output Ops */ #define TO_EOF 0 #define TO_SPAWN -1 #define TO_NEW -2 /* Contexts Used by Some System Calls - these are allocated from the top of the context space */ #define SYSCTX_FIRST (int) 0x0007ffff /* first system context */ #define SYSCTX_TC (SYSCTX_FIRST-0) /* ctxt for TC messages */ #define SYSCTX_TM (SYSCTX_FIRST-1) /* ctxt for TM messages */ #define SYSCTX_SG (SYSCTX_FIRST-2) /* ctxt for static group formation*/ #define SYSCTX_DG (SYSCTX_FIRST-3) /* ctxt for dynamic groups */ #define SYSCTX_RS4 (SYSCTX_FIRST-4) /* Reserved system context */ #define SYSCTX_RS5 (SYSCTX_FIRST-5) /* Reserved system context */ #define SYSCTX_RS6 (SYSCTX_FIRST-6) /* Reserved system context */ #define SYSCTX_RS7 (SYSCTX_FIRST-7) /* Reserved system context */ #define SYSCTX_RS8 (SYSCTX_FIRST-8) /* Reserved system context */ #define SYSCTX_RS9 (SYSCTX_FIRST-9) /* Reserved system context */ #define SYSCTX_LAST (SYSCTX_FIRST-9) #define NUM_SYSCTX (SYSCTX_FIRST-SYSCTX_LAST+1) #define BASECONTEXT (int) 0 #endif /*_PVMPROTO_H_*/ ./pvm3/include/pvmtev.h0100644007401100000360000003162206741172444014232 0ustar kohlgopher /* $Id: pvmtev.h,v 1.13 1999/07/08 18:59:48 kohl Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvmtev.h * * Libpvm tracing includes. * * $Log: pvmtev.h,v $ * Revision 1.13 1999/07/08 18:59:48 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.12 1997/12/31 22:13:39 pvmsrc * Renamed TEV_REMOVE -> TEV_DELINFO. D-Oh. * (Spanker=kohl) * * Revision 1.11 1997/12/23 20:26:22 pvmsrc * Added new TEV_MHF_INVOKE event id. * - for message handler function invocation. * (Spanker=kohl) * * Revision 1.10 1997/12/17 22:17:19 pvmsrc * Added new tracing constants for mhf stuff. * - TEV_DID_MHI message handler index. * - TEV_ADDMHF & TEV_DELMHF trace event indices. * (Spanker=kohl) * * Revision 1.9 1997/10/24 15:16:01 pvmsrc * Added TEV_DID_RCX constant for Receiving message context. * (Spanker=kohl) * * Revision 1.8 1997/10/24 14:20:20 pvmsrc * Added TEV_DID_MCX constant, Message Context. * (Spanker=kohl) * * Revision 1.7 1997/07/09 13:29:39 pvmsrc * Fixed Author Header. * * Revision 1.6 1997/05/01 20:16:50 pvmsrc * Renamed TEV_MBOXINFO -> TEV_GETMBOXINFO. * * Revision 1.5 1997/04/10 20:25:52 pvmsrc * TEV_GETNAMES -> TEV_MBOXINFO. * * Revision 1.4 1997/02/17 21:26:44 pvmsrc * Fixed comments for Steve (who actually reads them, hahahaha). * - decls for pvmtevdidlist[] & pvmtevinfo[] are now in global.c. * * Revision 1.3 1997/01/28 19:14:23 pvmsrc * New Copyright Notice & Authors. * * Revision 1.2 1996/10/24 19:35:12 pvmsrc * Modified for New Tracing Facility: * - added trace buffer marker constants, TEV_MARK_*. * - added dummy user-defined trace tid & message code, * PVM_TRACE_TID & PVM_TRACE_CODE. * - added trace event data types, TEV_DATA_*. * - added semantic data IDs, TEV_DID_*, with new struct Pvmtevdid. * - replaced old trace event IDs, no longer TEV_*0 / TEV_*1, * use TEV_EVENT_ENTRY & TEV_EVENT_EXIT to distinguish. * - added new struct Pvmtevinfo. * - modified trace mask defn & macros, fix length large enough for * compatible growth. * - renamed macros for consistency -> TEV_MASK_*(). * - added new struct Pvmtracer. * * Revision 1.1 1996/09/23 21:06:34 pvmsrc * Initial revision * */ #ifndef _PVMTEV_H_ #define _PVMTEV_H_ /* Trace Markers */ #define TEV_MARK_EVENT_BUFFER -1 #define TEV_MARK_EVENT_BUFFER_END -2 #define TEV_MARK_DATA_ID -3 #define TEV_MARK_DATA_ID_END -4 #define TEV_MARK_EVENT_DESC -5 #define TEV_MARK_EVENT_DESC_END -6 #define TEV_MARK_EVENT_RECORD -7 #define TEV_MARK_EVENT_RECORD_END -8 #define TEV_MARK_USER_EVENT_RECORD -9 #define TEV_MARK_USER_EVENT_RECORD_END -10 /* Dummy Trace Tid & Code for User Defined Events */ #define PVM_TRACE_TID -1111 #define PVM_TRACE_CODE -2222 /* Trace Event Data Types */ #define TEV_DATA_NULL 0 #define TEV_DATA_BYTE 1 #define TEV_DATA_CPLX 2 #define TEV_DATA_DCPLX 3 #define TEV_DATA_DOUBLE 4 #define TEV_DATA_FLOAT 5 #define TEV_DATA_INT 6 #define TEV_DATA_UINT 7 #define TEV_DATA_LONG 8 #define TEV_DATA_ULONG 9 #define TEV_DATA_SHORT 10 #define TEV_DATA_USHORT 11 #define TEV_DATA_STRING 12 #define TEV_DATA_STRUCT_START 13 #define TEV_DATA_STRUCT_END 14 #define TEV_DATA_DEFERRED 15 #define TEV_DATA_SCALAR 0x00 #define TEV_DATA_ARRAY 0x80 /* Trace Event Data Identifier ID Constants */ /************* PLEASE NOTE ******************/ /* */ /* When Adding or Changing, ALWAYS Update: */ /* struct Pvmtevdid pvmtevdidlist[]; */ /* in file $PVM_ROOT/src/global.c */ /* */ /************* PLEASE NOTE ******************/ #define TEV_DID_FIRST 0 #define TEV_DID_AN 0 #define TEV_DID_AC 1 #define TEV_DID_AS 2 #define TEV_DID_BF 3 #define TEV_DID_CC 4 #define TEV_DID_CN 5 #define TEV_DID_CI 6 #define TEV_DID_CF 7 #define TEV_DID_CD 8 #define TEV_DID_CR 9 #define TEV_DID_CL 10 #define TEV_DID_CDA 11 #define TEV_DID_CDT 12 #define TEV_DID_CDX 13 #define TEV_DID_CDC 14 #define TEV_DID_CGI 15 #define TEV_DID_CRF 16 #define TEV_DID_CXC 17 #define TEV_DID_CXF 18 #define TEV_DID_CXN 19 #define TEV_DID_CXS 20 #define TEV_DID_ERI 21 #define TEV_DID_ERR 22 #define TEV_DID_FDS 23 #define TEV_DID_FP 24 #define TEV_DID_GN 25 #define TEV_DID_GI 26 #define TEV_DID_GT 27 #define TEV_DID_GS 28 #define TEV_DID_GBC 29 #define TEV_DID_HN 30 #define TEV_DID_HNL 31 #define TEV_DID_HNA 32 #define TEV_DID_HPT 33 #define TEV_DID_HA 34 #define TEV_DID_HSP 35 #define TEV_DID_HIS 36 #define TEV_DID_HCS 37 #define TEV_DID_HCU 38 #define TEV_DID_HDS 39 #define TEV_DID_HDU 40 #define TEV_DID_HS 41 #define TEV_DID_INB 42 #define TEV_DID_IMC 43 #define TEV_DID_IST 44 #define TEV_DID_MC 45 #define TEV_DID_MCX 46 #define TEV_DID_MB 47 #define TEV_DID_MNB 48 #define TEV_DID_SRC 49 #define TEV_DID_DST 50 #define TEV_DID_MDL 51 #define TEV_DID_MTS 52 #define TEV_DID_MTU 53 #define TEV_DID_MRF 54 #define TEV_DID_MRB 55 #define TEV_DID_MSB 56 #define TEV_DID_ME 57 #define TEV_DID_MHI 58 #define TEV_DID_AST 59 #define TEV_DID_AMC 60 #define TEV_DID_AML 61 #define TEV_DID_NE 62 #define TEV_DID_NMC 63 #define TEV_DID_NCT 64 #define TEV_DID_NTL 65 #define TEV_DID_NH 66 #define TEV_DID_NA 67 #define TEV_DID_OPT 68 #define TEV_DID_OPV 69 #define TEV_DID_OS 70 #define TEV_DID_PDA 71 #define TEV_DID_PDT 72 #define TEV_DID_PC 73 #define TEV_DID_PSD 74 #define TEV_DID_PSG 75 #define TEV_DID_PF 76 #define TEV_DID_PRF 77 #define TEV_DID_RST 78 #define TEV_DID_RMC 79 #define TEV_DID_RCX 80 #define TEV_DID_SN 81 #define TEV_DID_SE 82 #define TEV_DID_SF 83 #define TEV_DID_SW 84 #define TEV_DID_SC 85 #define TEV_DID_STL 86 #define TEV_DID_SIB 87 #define TEV_DID_TID 88 #define TEV_DID_PT 89 #define TEV_DID_MT 90 #define TEV_DID_TF 91 #define TEV_DID_TN 92 #define TEV_DID_PID 93 #define TEV_DID_TT 94 #define TEV_DID_TW 95 #define TEV_DID_TIS 96 #define TEV_DID_TNT 97 #define TEV_DID_TST 98 #define TEV_DID_TUS 99 #define TEV_DID_TUU 100 #define TEV_DID_TSS 101 #define TEV_DID_TSU 102 #define TEV_DID_TES 103 #define TEV_DID_TA 104 #define TEV_DID_TR 105 #define TEV_DID_TS 106 #define TEV_DID_TU 107 #define TEV_DID_TGS 108 #define TEV_DID_TGU 109 #define TEV_DID_TMW 110 #define TEV_DID_TM 111 #define TEV_DID_TRC 112 #define TEV_DID_TRT 113 #define TEV_DID_TRX 114 #define TEV_DID_TRO 115 #define TEV_DID_TRM 116 #define TEV_DID_TRB 117 #define TEV_DID_TRL 118 #define TEV_DID_VER 119 #define TEV_DID_VCT 120 #define TEV_DID_VID 121 #define TEV_DID_WID 122 #define TEV_DID_MAX 122 /* Trace Data Identifier Structure */ struct Pvmtevdid { char *did; /* Semantic Data ID */ char *desc; /* Semantic Data Description */ }; /* Trace Event ID Constants */ /************* PLEASE NOTE ******************/ /* */ /* When Adding or Changing, ALWAYS Update: */ /* struct Pvmtevinfo pvmtevinfo[]; */ /* in file $PVM_ROOT/src/global.c */ /* */ /************* PLEASE NOTE ******************/ #define TEV_FIRST 0 #define TEV_ADDHOSTS 0 #define TEV_BARRIER 1 #define TEV_BCAST 2 #define TEV_BUFINFO 3 #define TEV_CONFIG 4 #define TEV_DELETE 5 #define TEV_DELHOSTS 6 #define TEV_EXIT 7 #define TEV_FREEBUF 8 #define TEV_GETFDS 9 #define TEV_GETINST 10 #define TEV_GETOPT 11 #define TEV_GETRBUF 12 #define TEV_GETSBUF 13 #define TEV_GETTID 14 #define TEV_GSIZE 15 #define TEV_HALT 16 #define TEV_INITSEND 17 #define TEV_INSERT 18 #define TEV_JOINGROUP 19 #define TEV_KILL 20 #define TEV_LOOKUP 21 #define TEV_LVGROUP 22 #define TEV_MCAST 23 #define TEV_MKBUF 24 #define TEV_MSTAT 25 #define TEV_MYTID 26 #define TEV_NOTIFY 27 #define TEV_NRECV 28 #define TEV_PARENT 29 #define TEV_PERROR 30 #define TEV_PKBYTE 31 #define TEV_PKCPLX 32 #define TEV_PKDCPLX 33 #define TEV_PKDOUBLE 34 #define TEV_PKFLOAT 35 #define TEV_PKINT 36 #define TEV_PKUINT 37 #define TEV_PKLONG 38 #define TEV_PKULONG 39 #define TEV_PKSHORT 40 #define TEV_PKUSHORT 41 #define TEV_PKSTR 42 #define TEV_PROBE 43 #define TEV_PSTAT 44 #define TEV_RECV 45 #define TEV_RECVF 46 #define TEV_SEND 47 #define TEV_SENDSIG 48 #define TEV_SETOPT 49 #define TEV_SETRBUF 50 #define TEV_SETSBUF 51 #define TEV_SPAWN 52 #define TEV_START_PVMD 53 #define TEV_TASKS 54 #define TEV_TICKLE 55 #define TEV_TIDTOHOST 56 #define TEV_TRECV 57 #define TEV_UPKBYTE 58 #define TEV_UPKCPLX 59 #define TEV_UPKDCPLX 60 #define TEV_UPKDOUBLE 61 #define TEV_UPKFLOAT 62 #define TEV_UPKINT 63 #define TEV_UPKUINT 64 #define TEV_UPKLONG 65 #define TEV_UPKULONG 66 #define TEV_UPKSHORT 67 #define TEV_UPKUSHORT 68 #define TEV_UPKSTR 69 #define TEV_VERSION 70 #define TEV_REG_HOSTER 71 #define TEV_REG_RM 72 #define TEV_REG_TASKER 73 #define TEV_REG_TRACER 74 #define TEV_NEWTASK 75 #define TEV_ENDTASK 76 #define TEV_SPNTASK 77 #define TEV_ARCHCODE 78 #define TEV_CATCHOUT 79 #define TEV_GETMWID 80 #define TEV_GETTMASK 81 #define TEV_HOSTSYNC 82 #define TEV_PACKF 83 #define TEV_PRECV 84 #define TEV_PSEND 85 #define TEV_REDUCE 86 #define TEV_SETMWID 87 #define TEV_SETTMASK 88 #define TEV_UNPACKF 89 #define TEV_GATHER 90 #define TEV_SCATTER 91 #define TEV_PUTINFO 92 #define TEV_GETINFO 93 #define TEV_DELINFO 94 #define TEV_GETMBOXINFO 95 #define TEV_NEWCONTEXT 96 #define TEV_FREECONTEXT 97 #define TEV_SETCONTEXT 98 #define TEV_GETCONTEXT 99 #define TEV_SIBLINGS 100 #define TEV_GETMINFO 101 #define TEV_SETMINFO 102 #define TEV_ADDMHF 103 #define TEV_DELMHF 104 #define TEV_MHF_INVOKE 105 #define TEV_TIMING 106 #define TEV_PROFILING 107 #define TEV_USER_DEFINED 108 #define TEV_MAX 108 #define TEV_EVENT_ENTRY 0x4000 #define TEV_EVENT_EXIT 0x8000 /* Trace Event Info Structure */ struct Pvmtevinfo { char *name; /* trace event name */ int desc_status; /* trace descriptor status */ struct timeval mark; /* trace time marker */ struct timeval total; /* trace cumulative time */ int count; /* trace invocation counter */ }; /* Trace Mask Definitions */ /****************************************************************/ /* */ /* Fix Length Larger Than Necessary to Allow Interoperability */ /* with Different Effective Mask Lengths: */ /* */ /* -> for TEV_MAX of 101, Min Length is (101/4 + 2) = 26. */ /* => bump to 36, sufficient for TEV_MAX up to 139. */ /* */ /****************************************************************/ #define TEV_MASK_LENGTH 36 /* Trace Event Mask Kept as Ascii String */ typedef char Pvmtmask[TEV_MASK_LENGTH]; /* Trace Mask Macros */ #define TEV_MASK_SET( m, k ) ( m[ (k) / 4 ] |= ( 1 << ((k) & 3) ) ) #define TEV_MASK_UNSET( m, k ) ( m[ (k) / 4 ] &= ~( 1 << ((k) & 3) ) ) #define TEV_MASK_CHECK( m, k ) ( m[ (k) / 4 ] & ( 1 << ((k) & 3) ) ) #define TEV_MASK_INIT( m ) \ { \ int tev_init_mask_i = TEV_MASK_LENGTH - 1; \ m[ tev_init_mask_i ] = 0; \ while ( tev_init_mask_i-- > 0 ) \ m[ tev_init_mask_i ] = '@'; \ } /* Tracer Info Structure */ struct Pvmtracer { int trctid; /* trace dst */ int trcctx; /* trace context */ int trctag; /* trace message tag */ int outtid; /* stdout dst */ int outctx; /* stdout context */ int outtag; /* stdout message tag */ int trcbuf; /* trace buffering */ int trcopt; /* trace options */ Pvmtmask tmask; /* trace bitmask */ }; #ifdef __ProtoGlarp__ #undef __ProtoGlarp__ #endif #if defined(__STDC__) || defined(__cplusplus) #define __ProtoGlarp__(x) x #else #define __ProtoGlarp__(x) () #endif #ifdef __cplusplus extern "C" { #endif int pvm_gettmask __ProtoGlarp__(( int, Pvmtmask )); int pvm_settmask __ProtoGlarp__(( int, Pvmtmask )); #ifdef __cplusplus } #endif #endif /*_PVMTEV_H_*/ ./pvm3/lib/0042755007401100000360000000000010117676455011667 5ustar kohlgopher./pvm3/lib/aimk0100755007401100000360000000421406604772454012534 0ustar kohlgopher#!/bin/sh # # $Id: aimk,v 1.3 1998/10/01 21:33:32 pvmsrc Exp $ # # aimk.sh # # Make wrapper for multiple arch. builds. # # Automatically sets PVM_ARCH for $MAKE to use. # # Action depends on makefile locations: # 1. If $PVM_ARCH/Makefile or $PVM_ARCH/makefile exists, # chdir to $PVM_ARCH and exec $MAKE there. # # 2. Else if ./Makefile.aimk exists, # chdir to $PVM_ARCH and exec $MAKE # with -f $PVM_ROOT/conf/$PVM_ARCH.def # and -f $AIMK_SRC/Makefile.aimk PVM_ARCH=$PVM_ARCH # $AIMK_SRC is the original working directory before the chdir. # # 3. Else will simply exec $MAKE in cwd. # # usage: # aimk [-here] [ make args ... ] # # 09 Apr 1993 Manchek # makeincwd=0 found=1 while [ $# -ge 1 -a $found = 1 ]; do found=0 case "$1" in -here ) makeincwd=1; shift; found=1 ;; esac done case "x$PVM_ROOT" in x ) # if [ -d $HOME/pvm3 ]; then # PVM_ROOT=$HOME/pvm3 # else echo aimk: PVM_ROOT not defined >&2 exit 1 # fi ;; esac case "x$PVM_ARCH" in x | xUNKNOWN ) PVM_ARCH="`$PVM_ROOT/lib/pvmgetarch`" case "x$PVM_ARCH" in x ) echo 'aimk: no pvmgetarch - is $PVM_ROOT set correctly?' >&2 exit 1 ;; esac ;; esac export PVM_ARCH export PVM_ROOT # # use *.def file to get $MAKE define. # MAKEDEF=`grep MAKE $PVM_ROOT/conf/$PVM_ARCH.def \ | sed -e "s/ //g" -e "s/ //g"` eval $MAKEDEF # # run $MAKE in cwd or subdir if exists. # if [ $makeincwd = 0 -a \( -f $PVM_ARCH/Makefile -o -f $PVM_ARCH/makefile \) ]; then echo making in $PVM_ARCH/ for $PVM_ARCH cd $PVM_ARCH if [ "$*" = "" ]; then exec $MAKE PVM_ARCH=$PVM_ARCH else exec $MAKE PVM_ARCH=$PVM_ARCH "$@" fi else if [ $makeincwd = 0 -a -f Makefile.aimk ]; then if [ ! -d $PVM_ARCH ]; then mkdir $PVM_ARCH fi echo making in $PVM_ARCH/ for $PVM_ARCH AIMK_SRC=`pwd` export AIMK_SRC cd $PVM_ARCH if [ "$*" = "" ]; then exec $MAKE -f $PVM_ROOT/conf/$PVM_ARCH.def -f $AIMK_SRC/Makefile.aimk PVM_ARCH=$PVM_ARCH else exec $MAKE -f $PVM_ROOT/conf/$PVM_ARCH.def -f $AIMK_SRC/Makefile.aimk PVM_ARCH=$PVM_ARCH "$@" fi else echo making in . for $PVM_ARCH if [ "$*" = "" ]; then exec $MAKE PVM_ARCH=$PVM_ARCH else exec $MAKE PVM_ARCH=$PVM_ARCH "$@" fi fi fi exit 1 ./pvm3/lib/bashrc.stub0100644007401100000360000000161106552405230014007 0ustar kohlgopher # # append this file to your .bashrc to set path according to machine # type. you may wish to use this for your own programs (edit the last # part to point to a different directory f.e. ~/bin/_$PVM_ARCH. # if [ -z $PVM_ROOT ]; then if [ -d ~/pvm3 ]; then export PVM_ROOT=~/pvm3 else echo "Warning - PVM_ROOT not defined" echo "To use PVM, define PVM_ROOT and rerun your .bashrc" fi fi if [ -n $PVM_ROOT ]; then export PVM_ARCH=`$PVM_ROOT/lib/pvmgetarch` # # uncomment one of the following lines if you want the PVM commands # directory to be added to your shell path. # # export PATH=$PATH:$PVM_ROOT/lib # generic # export PATH=$PATH:$PVM_ROOT/lib/$PVM_ARCH # arch-specific # # uncomment the following line if you want the PVM executable directory # to be added to your shell path. # # export PATH=$PATH:$PVM_ROOT/bin/$PVM_ARCH fi ./pvm3/lib/cshrc.stub0100755007401100000360000000152106221576771013666 0ustar kohlgopher # # append this file to your .cshrc to set path according to machine type. # you may wish to use this for your own programs (edit the last part to # point to a different directory f.e. ~/bin/_$PVM_ARCH. # if (! $?PVM_ROOT) then if (-d ~/pvm3) then setenv PVM_ROOT ~/pvm3 else echo "Warning - PVM_ROOT not defined" echo "To use PVM, define PVM_ROOT and rerun your .cshrc" endif endif if ($?PVM_ROOT) then setenv PVM_ARCH `$PVM_ROOT/lib/pvmgetarch` # # uncomment one of the following lines if you want the PVM commands directory # to be added to your shell path. # # set path=($path $PVM_ROOT/lib) # generic # set path=($path $PVM_ROOT/lib/$PVM_ARCH) # arch-specific # # uncomment the following line if you want the PVM executable directory # to be added to your shell path. # # set path=($path $PVM_ROOT/bin/$PVM_ARCH) endif ./pvm3/lib/kshrc.stub0100644007401100000360000000162206310024610013650 0ustar kohlgopher # # append this file to your .profile to set path according to machine # type. you may wish to use this for your own programs (edit the last # part to point to a different directory f.e. ~/bin/_$PVM_ARCH. # if [[ -z $PVM_ROOT ]]; then if [[ -d ~/pvm3 ]] then export PVM_ROOT=~/pvm3 else print "Warning - PVM_ROOT not defined" print "To use PVM, define PVM_ROOT and rerun your .profile" fi fi if [[ -n $PVM_ROOT ]]; then export PVM_ARCH=`$PVM_ROOT/lib/pvmgetarch` # # uncomment one of the following lines if you want the PVM commands # directory to be added to your shell path. # # export PATH=$PATH:$PVM_ROOT/lib # generic # export PATH=$PATH:$PVM_ROOT/lib/$PVM_ARCH # arch-specific # # uncomment the following line if you want the PVM executable directory # to be added to your shell path. # # export PATH=$PATH:$PVM_ROOT/bin/$PVM_ARCH fi ./pvm3/lib/debugger0100755007401100000360000000105706221576773013402 0ustar kohlgopher#!/bin/csh -f # # $Id: debugger,v 1.1 1996/09/23 21:15:39 pvmsrc Exp $ # # debugger.csh # # this script is invoked by the pvmd when a task is spawned with # the PvmTaskDebug flag set. it execs an xterm with script # debugger2 running inside. # # 06 Apr 1993 Manchek # if ($#argv < 1) then echo "usage: debugger command [args]" exit 1 endif set noglob if ($PVM_ARCH == "SUN4SOL2" || $PVM_ARCH == "SUNMP" || $PVM_ARCH == "X86SOL2") then set hn=`uname -n` else set hn=`hostname` endif exec xterm -title "${hn}:$argv[1]" -e $PVM_ROOT/lib/debugger2 $argv ./pvm3/lib/debugger20100755007401100000360000000307410001307226013435 0ustar kohlgopher#!/bin/csh -f # # $Id: debugger2,v 1.8 2004/01/14 18:46:46 pvmsrc Exp $ # # debugger2.csh # # this script is invoked in an xterm by the generic debugger script. # it starts the debugger and waits when it exits to prevent the # window from closing. # # it expects the pvmd to set envar PVM_ARCH. # # 06 Apr 1993 Manchek # set noglob # scratch file for debugger commands set TEMPCMD=debugger2.$$ # default debugger and flags set DBCMD="dbx" set DBFF="-c $TEMPCMD" # # try to pick the debugger by arch name # switch ($PVM_ARCH) case SUN2: case SUN3: case SUN4: set DBFF="-s $TEMPCMD" breaksw case HPPA: set DBCMD="xdb" set DBFF="-p $TEMPCMD" breaksw case TITN: set DBCMD="dbg" set DBFF="" breaksw case LINUX: case LINUX64: case LINUXALPHA: case LINUXHPPA: case LINUXSPARC: case LINUXATARI: case NEXT: set DBCMD="gdb" set DBFF="-q -x $TEMPCMD" breaksw case KSR1: set DBCMD="udb" set DBFF="-W $TEMPCMD" breaksw case CNVX: case CNVXN: set DBCMD="csd" set DBFF="" breaksw case AIX5SP2: case AIX4SP2: case SP2MPI: set DBCMD="pdbx $argv[1-]" breaksw case CSPP: set DBCMD="cxdb" set DBFF="-nw " breaksw case CRAY: set DBCMD="totalview" breaksw default: # ALPHA PMAX SYMM RS6K breaksw endsw # # run the debugger # echo use: echo run $argv[2-] echo __________________________________________________ echo "" #echo run $argv[2-] > $TEMPCMD #echo $DBCMD $DBFF $argv[1] #$DBCMD $DBFF $argv[1] $DBCMD $argv[1] #rm -f $TEMPCMD # # wait to go away # #reset #sleep 1 echo "********" echo "$DBCMD terminated" echo -n "hit return to close window:" set a="$<" exit 0 ./pvm3/lib/ipcfree0100755007401100000360000000122006662570636013224 0ustar kohlgopher#!/bin/sh # # $Id: ipcfree,v 1.2 1999/02/17 16:43:10 pvmsrc Exp $ # # ipcfree # # Delete any shared memory, semaphores and message queues lying around after # a PVM # program bombs out or is killed ungracefully. # Run it if you're getting error messages like: # semget: ... No space left on device # shmget: ... No space left on device # when using one of the *MP PVM architectures. # Or when using the pvm_shmd shared memory daemon. # if [ "$USER" = "" ]; then USER=` whoami ` fi m=` ipcs | awk '$1~/^[msq]$/ && $5~/'$USER'/ {print "-"$1, $2}' ` case "$m" in ?*) echo "deleting $m" ipcrm $m ;; *) echo "didn't find anything" ;; esac exit 0 ./pvm3/lib/pvm0100755007401100000360000000272306401355663012412 0ustar kohlgopher#!/bin/sh # # $Id: pvm,v 1.2 1997/08/28 20:12:35 pvmsrc Exp $ # # Start the appropriate pvm console. # If PVM_ROOT is not set in environment, # we try to guess it by combining the working directory with # argv[0], otherwise it defaults to $HOME/pvm3. # If PVM_ARCH is not set, # we get it by execing $PVMROOT/lib/pvmgetarch. # Called with "-exe" flag executes "pvm.exe" instead of "pvm" (OS2). # # 09 Apr 1993 Manchek # case "x$PVM_ROOT" in x ) case "$0" in /*) PVM_ROOT="$0" ;; *) PVM_ROOT=`pwd`/"$0" ;; esac PVM_ROOT=`echo "$PVM_ROOT" | sed -e 's/\/lib\/pvm//'` if [ -d $PVM_ROOT ]; then export PVM_ROOT else if [ -d $HOME/pvm3 ]; then PVM_ROOT=$HOME/pvm3 export PVM_ROOT else echo pvm: PVM_ROOT not defined >&2 exit 1 fi fi ;; esac # # these lines let you set environment variables on systems # where a shell profile doesn't get read when rshing in. # if [ -f $PVM_ROOT/.pvmprofile ]; then . $PVM_ROOT/.pvmprofile fi if [ -f $HOME/.pvmprofile ]; then . $HOME/.pvmprofile fi case "x$PVM_ARCH" in x | xUNKNOWN ) PVM_ARCH="`$PVM_ROOT/lib/pvmgetarch`" case "x$PVM_ARCH" in x ) echo pvm: can\'t set arch >&2 exit 1 ;; esac ;; esac if [ "$1" = '-exe' ]; then sfx=".exe" shift else sfx="" fi if [ ! -f $PVM_ROOT/lib/$PVM_ARCH/pvm$sfx ]; then echo "pvm: $PVM_ROOT/lib/$PVM_ARCH/pvm$sfx doesn't exist." >&2 echo "Make sure PVM is built and PVM_ROOT is set correctly" >&2 exit 1 fi export PVM_ARCH exec $PVM_ROOT/lib/$PVM_ARCH/pvm$sfx $@ exit 1 ./pvm3/lib/pvm.bat0100644007401100000360000000004606354526536013156 0ustar kohlgopher%PVM_ROOT%\console\%PVM_ARCH%\pvm.exe ./pvm3/lib/pvm.cmd0100644007401100000360000000005706401355631013142 0ustar kohlgopher@ksh %PVM_ROOT%/lib/pvm -exe %HOME%/.pvm_hosts ./pvm3/lib/pvm.cygwin.bat0100644007401100000360000000006607240352744014450 0ustar kohlgopher@echo OFF SET CYGWIN=tty %PVM_ROOT%\console\win32\pvm ./pvm3/lib/pvmd0100755007401100000360000000452407052062755012557 0ustar kohlgopher#!/bin/sh # # $Id: pvmd,v 1.5 2000/02/14 20:30:37 pvmsrc Exp $ # # Start the appropriate pvmd3. # If PVM_ROOT is not set in environment, # we try to guess it by combining the working directory with # argv[0], otherwise it defaults to $HOME/pvm3. # If PVM_ARCH is not set, # we get it by execing $PVMROOT/lib/pvmgetarch. # Called with "-exe" flag executes "pvm.exe" instead of "pvm" (OS2). # # 03 Jun 1994 Manchek # case "x$PVM_ROOT" in x ) case "$0" in /*) PVM_ROOT="$0" ;; *) PVM_ROOT=`pwd`/"$0" ;; esac PVM_ROOT=`echo "$PVM_ROOT" | sed -e 's/\/lib\/pvmd//'` if [ -d $PVM_ROOT ]; then export PVM_ROOT else if [ -d $HOME/pvm3 ]; then PVM_ROOT=$HOME/pvm3 export PVM_ROOT else echo pvmd: PVM_ROOT not defined >&2 exit 1 fi fi ;; esac # # these lines let you set environment variables on systems # where a shell profile doesn't get read when rshing in. # if [ -f $PVM_ROOT/.pvmprofile ]; then . $PVM_ROOT/.pvmprofile fi if [ -f $HOME/.pvmprofile ]; then . $HOME/.pvmprofile fi case "x$PVM_ARCH" in x | xUNKNOWN ) PVM_ARCH="`$PVM_ROOT/lib/pvmgetarch`" case "x$PVM_ARCH" in x ) echo pvmd: can\'t set arch >&2 exit 1 ;; esac ;; esac export PVM_ARCH # make a joyful noise. case "x$PVM_ARCH" in xSGI | xSGI5 | xSGI6 | xSGIMP | xSGIMP6 | xSGI64 | xSGIMP64 ) trap '' 2 ;; xPGON ) # for PGONs with pexec PEXEC=/bin/pexec # change this if pexec resides elsewhere if [ -x $PEXEC ]; then if [ "x$NX_DFLT_SIZE" = x ]; then NX_DFLT_SIZE=1; fi for args do if [ "$args" = "-s" -o "$args" = "-S" ]; then PGONSLAVE="-f"; fi if [ "$CLSIZE" = "t" ]; then CLSIZE="f"; NX_DFLT_SIZE=$args; fi if [ "$args" = "-sz" ]; then CLSIZE="t"; fi done PGONCALL="$PVM_ROOT/lib/$PVM_ARCH/pvmd3 $PGONSLAVE $*" exec $PEXEC "$PGONCALL" -sz $NX_DFLT_SIZE exit 1 fi ;; esac if [ "$1" = '-exe' ]; then sfx=".exe" shift else sfx="" fi if [ ! -f $PVM_ROOT/lib/$PVM_ARCH/pvmd3$sfx ]; then echo "pvmd: $PVM_ROOT/lib/$PVM_ARCH/pvmd3$sfx doesn't exist." >&2 echo "Make sure PVM is built and PVM_ROOT is set correctly" >&2 exit 1 fi case "x$PVMD_NOHOLD" in x | xNO ) exec $PVM_ROOT/lib/$PVM_ARCH/pvmd3$sfx $@ ;; * ) # Don't hold shell - put pvmd3 in background # (apparently helps with init scripts in RedHat Linux) # - change submitted by "Mike Wangsmo" $PVM_ROOT/lib/$PVM_ARCH/pvmd3$sfx $@ & ;; esac exit 0 ./pvm3/lib/pvmd.bat0100644007401100000360000000004406354526540013313 0ustar kohlgopher%PVM_ROOT%\lib\%PVM_ARCH%\pvmd3.exe ./pvm3/lib/pvmd.cmd0100644007401100000360000000006406401355705013306 0ustar kohlgopher@ksh %PVM_ROOT%/lib/pvmd.os2 -exe %HOME%/.pvm_hosts ./pvm3/lib/pvmgetarch0100755007401100000360000001567210010000225013723 0ustar kohlgopher#!/bin/sh # # $Id: pvmgetarch,v 1.27 2004/02/03 20:12:05 pvmsrc Exp $ # # pvmgetarch.sh # # Generate PVM architecture string. # # This is a heuristic thing that may need to be tuned from time # to time. I don't know of a real solution to determining the # machine type. # # Notes: # 1. Local people mess with things. # 2. It's good to try a few things for robustness. # 3. Don't use test -x # # 08 Apr 1993 Robert Manchek manchek@CS.UTK.EDU. # 24 Aug 1994 last revision # 28 Jul 1995 release 3.3.8 # # # begin section that may need to be tuned. # ARCH=UNKNOWN # # determine the machine type from scratch # if [ -f /bin/uname -o -f /usr/bin/uname \ -o -f /bin/uname.exe -o -f /usr/bin/uname.exe ]; then if [ -f /bin/uname ]; then os="`/bin/uname -s`" ht="`/bin/uname -m`" ov="`/bin/uname -v`" elif [ -f /usr/bin/uname ]; then os="`/usr/bin/uname -s`" ht="`/usr/bin/uname -m`" ov="`/usr/bin/uname -v`" elif [ -f /bin/uname.exe ]; then os="`/bin/uname.exe -s`" ht="`/bin/uname.exe -m`" ov="`/bin/uname.exe -v`" else os="`/usr/bin/uname.exe -s`" ht="`/usr/bin/uname.exe -m`" ov="`/usr/bin/uname.exe -v`" fi case "$os,$ht" in SunOS,sun3* ) ARCH=SUN3 ;; SunOS,sun4* ) ARCH=SUN4 ;; SunOS,i86pc ) ARCH=X86SOL2 ;; ULTRIX,RISC ) ARCH=PMAX ;; ULTRIX,VAX ) ARCH=UVAX ;; AIX*,* ) ARCH=RS6K ;; *HP*,9000/[2345]* ) ARCH=HP300 ;; *HP*,9000/[78]* ) ARCH=HPPA ;; *HP*,ia64 ) ARCH=HPPA ;; IRIX,* ) ARCH=SGI ;; IRIX64,* ) ARCH=SGI64 ;; *OSF*,alpha ) ARCH=ALPHA ;; CRSOS,smp ) ARCH=CRAYSMP ;; *,paragon ) ARCH=PGON ;; dgux,AViiON ) ARCH=DGAV ;; *,88k ) ARCH=E88K ;; *,mips ) ARCH=MIPS ;; *,CRAY-2 ) ARCH=CRAY2 ;; Linux,i[3456]86 ) ARCH=LINUX ;; Linux,ia64 ) ARCH=LINUX64 ;; Linux,x86_64 ) ARCH=LINUX64 ;; Linux,alpha ) ARCH=LINUXALPHA ;; Linux,arm* ) ARCH=LINUXARM ;; Linux,sparc* ) ARCH=LINUXSPARC ;; Linux,hp_pa ) ARCH=LINUXHPPA ;; Linux,ppc ) ARCH=LINUXPPC ;; Linux,m68k ) ARCH=LINUXATARI ;; BSD/OS,i[3456]86 ) ARCH=BSD386 ;; FreeBSD,i[3456]86 ) ARCH=FREEBSD ;; FreeBSD,alpha ) ARCH=FREEBSD ;; SUPER-UX,SX-3 ) ARCH=SX3 ;; uts,* ) ARCH=UTS2 ;; realix,M88* ) ARCH=M88K ;; DomainOS,DN* ) ARCH=APOLLO ;; OS/2,i[3456]86 ) ARCH=OS2 ;; CYGWIN*,i[3456]86 ) ARCH=CYGWIN ;; Darwin,* ) ARCH=DARWIN ;; Rhapsody,"Power Macintosh" ) ARCH=MACOSX ;; esac fi # there is no other way to detect DG/intel than to run 'uname -a' if [ "$ARCH" = DGAV ]; then if uname -a | grep 'PentiumPro$' > /dev/null ; then ARCH=DGIX fi fi if [ "$ARCH" = UNKNOWN ]; then if [ -f /bin/arch ]; then case "`/bin/arch`" in ksr1 ) ARCH=KSR1 ;; sun2 ) ARCH=SUN2 ;; sun3 ) ARCH=SUN3 ;; sun4 ) ARCH=SUN4 ;; esac fi fi if [ "$ARCH" = UNKNOWN ]; then if [ -f /usr/etc/RELDEF ]; then ARCH=ATT; fi if [ -f /ultrixboot ]; then if [ -f /pcs750.bin ]; then ARCH=UVAX else ARCH=PMAX fi else if [ -f /pcs750.bin ]; then ARCH=VAX; fi fi if [ -d /usr/alliant ]; then ARCH=AFX8; fi if [ -f /usr/bin/cluster ]; then ARCH=BFLY; fi if [ -d /usr/convex ]; then ARCH=CNVX; fi if [ -f /unicos ]; then ARCH=CRAY; fi if [ -f /hp-ux ]; then ARCH=HP300; fi if [ -f /usr/bin/getcube ]; then ARCH=I860; fi if [ -f /usr/bin/asm56000 ]; then ARCH=NEXT; fi if [ -f /etc/vg ]; then ARCH=RS6K; fi if [ -d /usr/include/caif ]; then ARCH=RT; fi if [ -f /bin/4d ]; then ARCH=SGI; fi if [ -f /dynix ]; then ARCH=SYMM; fi if [ -f /bin/titan ]; then ARCH=TITN; fi if [ -f /netbsd ]; then # amiga) ARCH=NETBSDAMIGA ;; --> NETBSDM68K # hp300) ARCH=NETBSDHP300 ;; --> NETBSDM68K # mac68k) ARCH=NETBSDMAC68K ;; --> NETBSDM68K # pmax) ARCH=NETBSDPMAX ;; --> NETBSDMIPSEL # sun3) ARCH=NETBSDSUN3 ;; --> NETBSDM68K case "`/usr/bin/uname -p`" in alpha) ARCH=NETBSDALPHA ;; arm32) ARCH=NETBSDARM32 ;; i386) ARCH=NETBSDI386 ;; m68k) ARCH=NETBSDM68K ;; mipseb) ARCH=NETBSDMIPSEB ;; mipsel) ARCH=NETBSDMIPSEL ;; ns32k) ARCH=NETBSDNS32K ;; powerpc) ARCH=NETBSDPOWERPC ;; sh3) ARCH=NETBSDSH3 ;; sparc) ARCH=NETBSDSPARC ;; sparc64) ARCH=NETBSDSPARC64 ;; vax) ARCH=NETBSDVAX ;; esac elif [ -f /usr/bin/machine ]; then case "`/usr/bin/machine`" in i386 ) ARCH=BSD386 ;; esac fi if [ -f /usr/bin/uxpm ] && /usr/bin/uxpm ; then ARCH=UXPM fi if [ -f /usr/bin/uxpv ] && /usr/bin/uxpv ; then ARCH=UXPV fi fi if [ "$ARCH" = UNKNOWN ]; then if [ -f /bin/uname -o -f /usr/bin/uname ]; then if [ -f /bin/uname ]; then os="`/bin/uname -s`" ht="`/bin/uname -m`" rv="`/bin/uname -r`" else os="`/usr/bin/uname -s`" ht="`/usr/bin/uname -m`" rv="`/usr/bin/uname -r`" fi case "$os,$ht" in *,i[3456]86 ) case "$rv" in 4.*) ARCH=UWARE ;; *) ARCH=SCO ;; esac esac fi fi # # update the machine type to derive subclasses # if [ "$ARCH" = SUN4 ]; then rel="`/bin/uname -r`" case "$rel" in 5.* ) ARCH=SUN4SOL2 ;; esac fi if [ "$ARCH" = SUN4SOL2 ]; then nproc="`/bin/mpstat | wc -l`" if [ $nproc -gt 2 -a "$PVM_SHMEM" = ON ]; then ARCH=SUNMP; fi fi if [ "$ARCH" = ALPHA ]; then rel="`/usr/bin/uname -r`" case "$rel" in *[34].*) nproc="`/usr/sbin/sizer -p`" if [ $nproc -gt 1 -a "$PVM_SHMEM" = ON ]; then ARCH=ALPHAMP; fi ;; esac fi if [ "$ARCH" = SGI ]; then rel="`/bin/uname -r`" case "$rel" in 5.* ) ARCH=SGI5 ;; 6.* ) ARCH=SGI6 ;; esac fi if [ "$ARCH" = SGI64 ]; then nproc="`/usr/sbin/mpadmin -n | wc -w`" if [ $nproc -gt 1 -a "$PVM_SHMEM" = ON ]; then ARCH=SGIMP64; fi fi if [ "$ARCH" = SGI5 ]; then nproc="`/usr/sbin/mpadmin -n | wc -w`" if [ $nproc -gt 1 -a "$PVM_SHMEM" = ON ]; then ARCH=SGIMP; fi fi if [ "$ARCH" = SGI6 ]; then nproc="`/usr/sbin/mpadmin -n | wc -w`" if [ $nproc -gt 1 -a "$PVM_SHMEM" = ON ]; then ARCH=SGIMP6; fi fi if [ "$ARCH" = SUN4 -a -f /dev/cm ]; then ARCH=CM2; fi if [ "$ARCH" = SUN4 -a -f /dev/cmni ]; then ARCH=CM5; fi if [ "$ARCH" = CNVX ]; then if /usr/convex/getsysinfo -f native_default; then ARCH=CNVXN fi fi if [ "$ARCH" = PMAX -a -d /usr/maspar ]; then ARCH=MASPAR; fi if [ "$ARCH" = RS6K ]; then case "$os,$ov" in AIX*,4 ) nproc="`/usr/sbin/lsdev -C -c processor | wc -l`" if [ $nproc -gt 1 -a "$PVM_SHMEM" = ON ]; then ARCH=AIX4MP; else ARCH=AIX46K; fi ;; AIX*,5 ) nproc="`/usr/sbin/lsdev -C -c processor | wc -l`" if [ $nproc -gt 1 -a "$PVM_SHMEM" = ON ]; then ARCH=AIX5MP; else ARCH=AIX56K; fi ;; esac fi if [ "$ARCH" = HPPA -a -f /bin/sysinfo ]; then ARCH=CSPP; fi if [ "$ARCH" = HPPA ]; then nproc="`/usr/bin/vmstat -n | wc -l`" if [ $nproc -gt 8 -a "$PVM_SHMEM" = ON ]; then ARCH=HPPAMP; fi fi if [ "$ARCH" = LINUX ]; then rel="`/bin/uname -r`" case "$rel" in *.beo* ) ARCH=BEOSCYLD ;; esac fi # # ugh, done. # echo $ARCH exit ./pvm3/lib/pvmgetarch.cmd0100644007401100000360000000003606401360325014471 0ustar kohlgopher@sh %PVM_ROOT%/lib/pvmgetarch ./pvm3/lib/pvmtmparch0100755007401100000360000000053306340066310013754 0ustar kohlgopher#!/bin/sh # # $Id: pvmtmparch,v 1.1 1997/05/19 15:07:52 pvmsrc Exp $ # # pvmtmparch.sh # # Generate temporary PVM architecture string. # # First check for existing env var $PVM_ARCH. # # If not set, then just call "pvmgetarch". # if [ "#$PVM_ARCH#" != "##" ]; then echo "$PVM_ARCH" else here="`dirname $0`" echo "`$here/pvmgetarch`" fi exit ./pvm3/lib/xpvm0100755007401100000360000000203706221577006012575 0ustar kohlgopher#!/bin/sh # # $Id: xpvm,v 1.1 1996/09/23 21:15:50 pvmsrc Exp $ # # Start XPVM. # If PVM_ROOT is not set in environment, # we try to guess it by combining the working directory with argv[0], # otherwise it defaults to ~/pvm3. # If PVM_ARCH is not set, # we get it by execing $PVMROOT/lib/pvmgetarch. # If XPVM_ROOT is not set, # set it to $PVM_ROOT/xpvm # # 11 May 1995 Manchek, from Convex version # case "x$PVM_ROOT" in x ) case "$0" in /*) PVM_ROOT="$0" ;; *) PVM_ROOT=`pwd`/"$0" ;; esac PVM_ROOT=`echo "$PVM_ROOT" | sed -e 's/\/lib\/xpvm//'` if [ -d $PVM_ROOT ]; then export PVM_ROOT else if [ -d $HOME/pvm3 ]; then PVM_ROOT=$HOME/pvm3 export PVM_ROOT else echo xpvm: PVM_ROOT not defined >&2 exit 1 fi fi ;; esac case "x$PVM_ARCH" in x | xUNKNOWN ) PVM_ARCH="`$PVM_ROOT/lib/pvmgetarch`" case "x$PVM_ARCH" in x ) echo xpvm: can\'t set arch >&2 exit 1 ;; esac export PVM_ARCH ;; esac case "x$XPVM_ROOT" in x ) XPVM_ROOT=$PVM_ROOT/xpvm export XPVM_ROOT ;; esac exec $XPVM_ROOT/src/$PVM_ARCH/xpvm $@ exit 1 ./pvm3/libfpvm/0042755007401100000360000000000010117676455012560 5ustar kohlgopher./pvm3/libfpvm/Makefile.aimk0100644007401100000360000004062106673254747015146 0ustar kohlgopher# # $Id: Makefile.aimk,v 1.19 1999/03/15 19:05:11 pvmsrc Exp $ # # # Generic Makefile body to be concatenated to config header. # SHELL = /bin/sh PVMDIR = ../.. SDIR = $(PVMDIR)/libfpvm CFLAGS = $(CFLOPTS) -c -DIMA_$(PVM_ARCH) \ -I$(SDIR) -I$(PVMDIR)/include -I$(PVMDIR)/src \ $(CDEBUGFLAGS) $(ARCHCFLAGS) RM = rm -f M4 = m4 M4FILE = $(PVMDIR)/conf/$(PVM_ARCH).m4 PVMLDIR = $(PVMDIR)/lib/$(PVM_ARCH) RWBSPECIAL = |sed '/^.include \"pvm3.h\"/d' \ |sed '/^.include \"pvm_consts.h\"/d' M4A = `case x$(NEEDF2M4) in xt) echo "$(M4) -DUSCORYES $(M4FILE)";; x) echo "$(M4) $(M4FILE)";; esac` M4B1 = case x$(NEEDF2M4) in xt) $(M4) $(M4FILE) M4B2 = ;; esac PVMHEADERS = $(PVMDIR)/include/pvm3.h \ $(SDIR)/pvm_consts.h PVMALLOCH = $(PVMDIR)/src/pvmalloc.h PVMBFUNCH = $(PVMDIR)/src/bfunc.h PVMBFHEADERS = $(PVMHEADERS) $(PVMBFUNCH) LIBPREFIX = lib LIBFPVM = $(LIBPREFIX)fpvm3.a LOBS = pvmfaddhost.o \ pvmfaddmhf.o \ pvmfarchcode.o \ pvmfbarrier.o \ pvmfbcast.o \ pvmfbufinfo.o \ pvmfcatchout.o \ pvmfconfig.o \ pvmfdelhost.o \ pvmfdelinfo.o \ pvmfdelmhf.o \ pvmfexit.o \ pvmffreebuf.o \ pvmffreectx.o \ pvmffrzgrp.o \ pvmfgather.o \ pvmfgetctx.o \ pvmfgetinfo.o \ pvmfgetinst.o \ pvmfgetopt.o \ pvmfgetrbuf.o \ pvmfgetsbuf.o \ pvmfgettid.o \ pvmfgsize.o \ pvmfhalt.o \ pvmfhostsync.o \ pvmfinitsend.o \ pvmfjoingrp.o \ pvmfkill.o \ pvmflvgrp.o \ pvmfmcast.o \ pvmfmkbuf.o \ pvmfmstat.o \ pvmfmytid.o \ pvmfnewctx.o \ pvmfnotify.o \ pvmfnrecv.o \ pvmfpack.o \ pvmfparent.o \ pvmfperror.o \ pvmfprecv.o \ pvmfprobe.o \ pvmfpsend.o \ pvmfpstat.o \ pvmfputinfo.o \ pvmfrecv.o \ pvmfrecvinfo.o \ pvmfreduce.o \ pvmfscatter.o \ pvmfsend.o \ pvmfsendsig.o \ pvmfsetctx.o \ pvmfsetopt.o \ pvmfsetrbuf.o \ pvmfsetsbuf.o \ pvmfsiblings.o \ pvmfsleep.o \ pvmfspawn.o \ pvmfstartpvmd.o \ pvmftasks.o \ pvmftidtoh.o \ pvmftrecv.o \ pvmfunpack.o default: $(LIBFPVM) install: $(PVMLDIR) $(PVMLDIR)/$(LIBFPVM) $(PVMLDIR): - mkdir $(PVMLDIR) $(PVMLDIR)/$(LIBFPVM): $(LIBFPVM) cp $(LIBFPVM) $(PVMLDIR) $(LIBFPVM): $(LOBS) ftocstr.o $(AR) cr $(LIBFPVM) $? case x$(HASRANLIB) in xt ) echo ranlib; ranlib $(LIBFPVM) ;; esac clean: rm -f $(LOBS) ftocstr.o $(LIBFPVM) tidy: rm -f $(LOBS) ftocstr.o: $(SDIR)/ftocstr.c $(PVMBFUNCH) $(CC) $(CFLAGS) $(SDIR)/ftocstr.c pvmfaddhost.o: $(SDIR)/pvmfaddhost.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfaddhost.m4 > pvmfaddhost.c $(M4B1) $(SDIR)/pvmfaddhost.m4 $(RWBSPECIAL) >> pvmfaddhost.c $(M4B2) $(CC) $(CFLAGS) pvmfaddhost.c $(RM) pvmfaddhost.c pvmfaddmhf.o: $(SDIR)/pvmfaddmhf.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfaddmhf.m4 > pvmfaddmhf.c $(M4B1) $(SDIR)/pvmfaddmhf.m4 $(RWBSPECIAL) >> pvmfaddmhf.c $(M4B2) $(CC) $(CFLAGS) pvmfaddmhf.c $(RM) pvmfaddmhf.c pvmfarchcode.o: $(SDIR)/pvmfarchcode.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfarchcode.m4 > pvmfarchcode.c $(M4B1) $(SDIR)/pvmfarchcode.m4 $(RWBSPECIAL) >> pvmfarchcode.c $(M4B2) $(CC) $(CFLAGS) pvmfarchcode.c $(RM) pvmfarchcode.c pvmfbarrier.o: $(SDIR)/pvmfbarrier.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfbarrier.m4 > pvmfbarrier.c $(M4B1) $(SDIR)/pvmfbarrier.m4 $(RWBSPECIAL) >> pvmfbarrier.c $(M4B2) $(CC) $(CFLAGS) pvmfbarrier.c $(RM) pvmfbarrier.c pvmfbcast.o: $(SDIR)/pvmfbcast.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfbcast.m4 > pvmfbcast.c $(M4B1) $(SDIR)/pvmfbcast.m4 $(RWBSPECIAL) >> pvmfbcast.c $(M4B2) $(CC) $(CFLAGS) pvmfbcast.c $(RM) pvmfbcast.c pvmfbufinfo.o: $(SDIR)/pvmfbufinfo.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfbufinfo.m4 > pvmfbufinfo.c $(M4B1) $(SDIR)/pvmfbufinfo.m4 $(RWBSPECIAL) >> pvmfbufinfo.c $(M4B2) $(CC) $(CFLAGS) pvmfbufinfo.c $(RM) pvmfbufinfo.c pvmfcatchout.o: $(SDIR)/pvmfcatchout.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfcatchout.m4 > pvmfcatchout.c $(M4B1) $(SDIR)/pvmfcatchout.m4 $(RWBSPECIAL) >> pvmfcatchout.c $(M4B2) $(CC) $(CFLAGS) pvmfcatchout.c $(RM) pvmfcatchout.c pvmfconfig.o: $(SDIR)/pvmfconfig.m4 $(M4FILE) $(PVMBFHEADERS) $(M4A) $(SDIR)/pvmfconfig.m4 > pvmfconfig.c $(M4B1) $(SDIR)/pvmfconfig.m4 $(RWBSPECIAL) >> pvmfconfig.c $(M4B2) $(CC) $(CFLAGS) pvmfconfig.c $(RM) pvmfconfig.c pvmfdelhost.o: $(SDIR)/pvmfdelhost.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfdelhost.m4 > pvmfdelhost.c $(M4B1) $(SDIR)/pvmfdelhost.m4 $(RWBSPECIAL) >> pvmfdelhost.c $(M4B2) $(CC) $(CFLAGS) pvmfdelhost.c $(RM) pvmfdelhost.c pvmfdelinfo.o: $(SDIR)/pvmfdelinfo.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfdelinfo.m4 > pvmfdelinfo.c $(M4B1) $(SDIR)/pvmfdelinfo.m4 $(RWBSPECIAL) >> pvmfdelinfo.c $(M4B2) $(CC) $(CFLAGS) pvmfdelinfo.c $(RM) pvmfdelinfo.c pvmfdelmhf.o: $(SDIR)/pvmfdelmhf.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfdelmhf.m4 > pvmfdelmhf.c $(M4B1) $(SDIR)/pvmfdelmhf.m4 $(RWBSPECIAL) >> pvmfdelmhf.c $(M4B2) $(CC) $(CFLAGS) pvmfdelmhf.c $(RM) pvmfdelmhf.c pvmfexit.o: $(SDIR)/pvmfexit.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfexit.m4 > pvmfexit.c $(M4B1) $(SDIR)/pvmfexit.m4 $(RWBSPECIAL) >> pvmfexit.c $(M4B2) $(CC) $(CFLAGS) pvmfexit.c $(RM) pvmfexit.c pvmffreebuf.o: $(SDIR)/pvmffreebuf.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmffreebuf.m4 > pvmffreebuf.c $(M4B1) $(SDIR)/pvmffreebuf.m4 $(RWBSPECIAL) >> pvmffreebuf.c $(M4B2) $(CC) $(CFLAGS) pvmffreebuf.c $(RM) pvmffreebuf.c pvmffreectx.o: $(SDIR)/pvmffreectx.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmffreectx.m4 > pvmffreectx.c $(M4B1) $(SDIR)/pvmffreectx.m4 $(RWBSPECIAL) >> pvmffreectx.c $(M4B2) $(CC) $(CFLAGS) pvmffreectx.c $(RM) pvmffreectx.c pvmffrzgrp.o: $(SDIR)/pvmffrzgrp.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmffrzgrp.m4 > pvmffrzgrp.c $(M4B1) $(SDIR)/pvmffrzgrp.m4 $(RWBSPECIAL) >> pvmffrzgrp.c $(M4B2) $(CC) $(CFLAGS) pvmffrzgrp.c $(RM) pvmffrzgrp.c pvmfgather.o: $(SDIR)/pvmfgather.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfgather.m4 > pvmfgather.c $(M4B1) $(SDIR)/pvmfgather.m4 $(RWBSPECIAL) >> pvmfgather.c $(M4B2) $(CC) $(CFLAGS) pvmfgather.c $(RM) pvmfgather.c pvmfgetctx.o: $(SDIR)/pvmfgetctx.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfgetctx.m4 > pvmfgetctx.c $(M4B1) $(SDIR)/pvmfgetctx.m4 $(RWBSPECIAL) >> pvmfgetctx.c $(M4B2) $(CC) $(CFLAGS) pvmfgetctx.c $(RM) pvmfgetctx.c pvmfgetinfo.o: $(SDIR)/pvmfgetinfo.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfgetinfo.m4 > pvmfgetinfo.c $(M4B1) $(SDIR)/pvmfgetinfo.m4 $(RWBSPECIAL) >> pvmfgetinfo.c $(M4B2) $(CC) $(CFLAGS) pvmfgetinfo.c $(RM) pvmfgetinfo.c pvmfgetinst.o: $(SDIR)/pvmfgetinst.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfgetinst.m4 > pvmfgetinst.c $(M4B1) $(SDIR)/pvmfgetinst.m4 $(RWBSPECIAL) >> pvmfgetinst.c $(M4B2) $(CC) $(CFLAGS) pvmfgetinst.c $(RM) pvmfgetinst.c pvmfgetopt.o: $(SDIR)/pvmfgetopt.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfgetopt.m4 > pvmfgetopt.c $(M4B1) $(SDIR)/pvmfgetopt.m4 $(RWBSPECIAL) >> pvmfgetopt.c $(M4B2) $(CC) $(CFLAGS) pvmfgetopt.c $(RM) pvmfgetopt.c pvmfgetrbuf.o: $(SDIR)/pvmfgetrbuf.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfgetrbuf.m4 > pvmfgetrbuf.c $(M4B1) $(SDIR)/pvmfgetrbuf.m4 $(RWBSPECIAL) >> pvmfgetrbuf.c $(M4B2) $(CC) $(CFLAGS) pvmfgetrbuf.c $(RM) pvmfgetrbuf.c pvmfgetsbuf.o: $(SDIR)/pvmfgetsbuf.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfgetsbuf.m4 > pvmfgetsbuf.c $(M4B1) $(SDIR)/pvmfgetsbuf.m4 $(RWBSPECIAL) >> pvmfgetsbuf.c $(M4B2) $(CC) $(CFLAGS) pvmfgetsbuf.c $(RM) pvmfgetsbuf.c pvmfgettid.o: $(SDIR)/pvmfgettid.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfgettid.m4 > pvmfgettid.c $(M4B1) $(SDIR)/pvmfgettid.m4 $(RWBSPECIAL) >> pvmfgettid.c $(M4B2) $(CC) $(CFLAGS) pvmfgettid.c $(RM) pvmfgettid.c pvmfgsize.o: $(SDIR)/pvmfgsize.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfgsize.m4 > pvmfgsize.c $(M4B1) $(SDIR)/pvmfgsize.m4 $(RWBSPECIAL) >> pvmfgsize.c $(M4B2) $(CC) $(CFLAGS) pvmfgsize.c $(RM) pvmfgsize.c pvmfhalt.o: $(SDIR)/pvmfhalt.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfhalt.m4 > pvmfhalt.c $(M4B1) $(SDIR)/pvmfhalt.m4 $(RWBSPECIAL) >> pvmfhalt.c $(M4B2) $(CC) $(CFLAGS) pvmfhalt.c $(RM) pvmfhalt.c pvmfhostsync.o: $(SDIR)/pvmfhostsync.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfhostsync.m4 > pvmfhostsync.c $(M4B1) $(SDIR)/pvmfhostsync.m4 $(RWBSPECIAL) >> pvmfhostsync.c $(M4B2) $(CC) $(CFLAGS) pvmfhostsync.c $(RM) pvmfhostsync.c pvmfinitsend.o: $(SDIR)/pvmfinitsend.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfinitsend.m4 > pvmfinitsend.c $(M4B1) $(SDIR)/pvmfinitsend.m4 $(RWBSPECIAL) >> pvmfinitsend.c $(M4B2) $(CC) $(CFLAGS) pvmfinitsend.c $(RM) pvmfinitsend.c pvmfjoingrp.o: $(SDIR)/pvmfjoingrp.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfjoingrp.m4 > pvmfjoingrp.c $(M4B1) $(SDIR)/pvmfjoingrp.m4 $(RWBSPECIAL) >> pvmfjoingrp.c $(M4B2) $(CC) $(CFLAGS) pvmfjoingrp.c $(RM) pvmfjoingrp.c pvmfkill.o: $(SDIR)/pvmfkill.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfkill.m4 > pvmfkill.c $(M4B1) $(SDIR)/pvmfkill.m4 $(RWBSPECIAL) >> pvmfkill.c $(M4B2) $(CC) $(CFLAGS) pvmfkill.c $(RM) pvmfkill.c pvmflvgrp.o: $(SDIR)/pvmflvgrp.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmflvgrp.m4 > pvmflvgrp.c $(M4B1) $(SDIR)/pvmflvgrp.m4 $(RWBSPECIAL) >> pvmflvgrp.c $(M4B2) $(CC) $(CFLAGS) pvmflvgrp.c $(RM) pvmflvgrp.c pvmfmcast.o: $(SDIR)/pvmfmcast.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfmcast.m4 > pvmfmcast.c $(M4B1) $(SDIR)/pvmfmcast.m4 $(RWBSPECIAL) >> pvmfmcast.c $(M4B2) $(CC) $(CFLAGS) pvmfmcast.c $(RM) pvmfmcast.c pvmfmkbuf.o: $(SDIR)/pvmfmkbuf.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfmkbuf.m4 > pvmfmkbuf.c $(M4B1) $(SDIR)/pvmfmkbuf.m4 $(RWBSPECIAL) >> pvmfmkbuf.c $(M4B2) $(CC) $(CFLAGS) pvmfmkbuf.c $(RM) pvmfmkbuf.c pvmfmstat.o: $(SDIR)/pvmfmstat.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfmstat.m4 > pvmfmstat.c $(M4B1) $(SDIR)/pvmfmstat.m4 $(RWBSPECIAL) >> pvmfmstat.c $(M4B2) $(CC) $(CFLAGS) pvmfmstat.c $(RM) pvmfmstat.c pvmfmytid.o: $(SDIR)/pvmfmytid.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfmytid.m4 > pvmfmytid.c $(M4B1) $(SDIR)/pvmfmytid.m4 $(RWBSPECIAL) >> pvmfmytid.c $(M4B2) $(CC) $(CFLAGS) pvmfmytid.c $(RM) pvmfmytid.c pvmfnewctx.o: $(SDIR)/pvmfnewctx.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfnewctx.m4 > pvmfnewctx.c $(M4B1) $(SDIR)/pvmfnewctx.m4 $(RWBSPECIAL) >> pvmfnewctx.c $(M4B2) $(CC) $(CFLAGS) pvmfnewctx.c $(RM) pvmfnewctx.c pvmfnotify.o: $(SDIR)/pvmfnotify.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfnotify.m4 > pvmfnotify.c $(M4B1) $(SDIR)/pvmfnotify.m4 $(RWBSPECIAL) >> pvmfnotify.c $(M4B2) $(CC) $(CFLAGS) pvmfnotify.c $(RM) pvmfnotify.c pvmfnrecv.o: $(SDIR)/pvmfnrecv.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfnrecv.m4 > pvmfnrecv.c $(M4B1) $(SDIR)/pvmfnrecv.m4 $(RWBSPECIAL) >> pvmfnrecv.c $(M4B2) $(CC) $(CFLAGS) pvmfnrecv.c $(RM) pvmfnrecv.c pvmfpack.o: $(SDIR)/pvmfpack.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfpack.m4 > pvmfpack.c $(M4B1) $(SDIR)/pvmfpack.m4 $(RWBSPECIAL) >> pvmfpack.c $(M4B2) $(CC) $(CFLAGS) pvmfpack.c $(RM) pvmfpack.c pvmfparent.o: $(SDIR)/pvmfparent.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfparent.m4 > pvmfparent.c $(M4B1) $(SDIR)/pvmfparent.m4 $(RWBSPECIAL) >> pvmfparent.c $(M4B2) $(CC) $(CFLAGS) pvmfparent.c $(RM) pvmfparent.c pvmfperror.o: $(SDIR)/pvmfperror.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfperror.m4 > pvmfperror.c $(M4B1) $(SDIR)/pvmfperror.m4 $(RWBSPECIAL) >> pvmfperror.c $(M4B2) $(CC) $(CFLAGS) pvmfperror.c $(RM) pvmfperror.c pvmfprecv.o: $(SDIR)/pvmfprecv.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfprecv.m4 > pvmfprecv.c $(M4B1) $(SDIR)/pvmfprecv.m4 $(RWBSPECIAL) >> pvmfprecv.c $(M4B2) $(CC) $(CFLAGS) pvmfprecv.c $(RM) pvmfprecv.c pvmfprobe.o: $(SDIR)/pvmfprobe.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfprobe.m4 > pvmfprobe.c $(M4B1) $(SDIR)/pvmfprobe.m4 $(RWBSPECIAL) >> pvmfprobe.c $(M4B2) $(CC) $(CFLAGS) pvmfprobe.c $(RM) pvmfprobe.c pvmfpsend.o: $(SDIR)/pvmfpsend.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfpsend.m4 > pvmfpsend.c $(M4B1) $(SDIR)/pvmfpsend.m4 $(RWBSPECIAL) >> pvmfpsend.c $(M4B2) $(CC) $(CFLAGS) pvmfpsend.c $(RM) pvmfpsend.c pvmfpstat.o: $(SDIR)/pvmfpstat.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfpstat.m4 > pvmfpstat.c $(M4B1) $(SDIR)/pvmfpstat.m4 $(RWBSPECIAL) >> pvmfpstat.c $(M4B2) $(CC) $(CFLAGS) pvmfpstat.c $(RM) pvmfpstat.c pvmfputinfo.o: $(SDIR)/pvmfputinfo.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfputinfo.m4 > pvmfputinfo.c $(M4B1) $(SDIR)/pvmfputinfo.m4 $(RWBSPECIAL) >> pvmfputinfo.c $(M4B2) $(CC) $(CFLAGS) pvmfputinfo.c $(RM) pvmfputinfo.c pvmfrecv.o: $(SDIR)/pvmfrecv.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfrecv.m4 > pvmfrecv.c $(M4B1) $(SDIR)/pvmfrecv.m4 $(RWBSPECIAL) >> pvmfrecv.c $(M4B2) $(CC) $(CFLAGS) pvmfrecv.c $(RM) pvmfrecv.c pvmfrecvinfo.o: $(SDIR)/pvmfrecvinfo.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfrecvinfo.m4 > pvmfrecvinfo.c $(M4B1) $(SDIR)/pvmfrecvinfo.m4 $(RWBSPECIAL) >> pvmfrecvinfo.c $(M4B2) $(CC) $(CFLAGS) pvmfrecvinfo.c $(RM) pvmfrecvinfo.c pvmfreduce.o: $(SDIR)/pvmfreduce.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfreduce.m4 > pvmfreduce.c $(M4B1) $(SDIR)/pvmfreduce.m4 $(RWBSPECIAL) >> pvmfreduce.c $(M4B2) $(CC) $(CFLAGS) pvmfreduce.c $(RM) pvmfreduce.c pvmfscatter.o: $(SDIR)/pvmfscatter.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfscatter.m4 > pvmfscatter.c $(M4B1) $(SDIR)/pvmfscatter.m4 $(RWBSPECIAL) >> pvmfscatter.c $(M4B2) $(CC) $(CFLAGS) pvmfscatter.c $(RM) pvmfscatter.c pvmfsend.o: $(SDIR)/pvmfsend.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfsend.m4 > pvmfsend.c $(M4B1) $(SDIR)/pvmfsend.m4 $(RWBSPECIAL) >> pvmfsend.c $(M4B2) $(CC) $(CFLAGS) pvmfsend.c $(RM) pvmfsend.c pvmfsendsig.o: $(SDIR)/pvmfsendsig.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfsendsig.m4 > pvmfsendsig.c $(M4B1) $(SDIR)/pvmfsendsig.m4 $(RWBSPECIAL) >> pvmfsendsig.c $(M4B2) $(CC) $(CFLAGS) pvmfsendsig.c $(RM) pvmfsendsig.c pvmfsetctx.o: $(SDIR)/pvmfsetctx.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfsetctx.m4 > pvmfsetctx.c $(M4B1) $(SDIR)/pvmfsetctx.m4 $(RWBSPECIAL) >> pvmfsetctx.c $(M4B2) $(CC) $(CFLAGS) pvmfsetctx.c $(RM) pvmfsetctx.c pvmfsetopt.o: $(SDIR)/pvmfsetopt.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfsetopt.m4 > pvmfsetopt.c $(M4B1) $(SDIR)/pvmfsetopt.m4 $(RWBSPECIAL) >> pvmfsetopt.c $(M4B2) $(CC) $(CFLAGS) pvmfsetopt.c $(RM) pvmfsetopt.c pvmfsetrbuf.o: $(SDIR)/pvmfsetrbuf.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfsetrbuf.m4 > pvmfsetrbuf.c $(M4B1) $(SDIR)/pvmfsetrbuf.m4 $(RWBSPECIAL) >> pvmfsetrbuf.c $(M4B2) $(CC) $(CFLAGS) pvmfsetrbuf.c $(RM) pvmfsetrbuf.c pvmfsetsbuf.o: $(SDIR)/pvmfsetsbuf.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfsetsbuf.m4 > pvmfsetsbuf.c $(M4B1) $(SDIR)/pvmfsetsbuf.m4 $(RWBSPECIAL) >> pvmfsetsbuf.c $(M4B2) $(CC) $(CFLAGS) pvmfsetsbuf.c $(RM) pvmfsetsbuf.c pvmfsiblings.o: $(SDIR)/pvmfsiblings.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfsiblings.m4 > pvmfsiblings.c $(M4B1) $(SDIR)/pvmfsiblings.m4 $(RWBSPECIAL) >> pvmfsiblings.c $(M4B2) $(CC) $(CFLAGS) pvmfsiblings.c $(RM) pvmfsiblings.c pvmfsleep.o: $(SDIR)/pvmfsleep.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfsleep.m4 > pvmfsleep.c $(M4B1) $(SDIR)/pvmfsleep.m4 $(RWBSPECIAL) >> pvmfsleep.c $(M4B2) $(CC) $(CFLAGS) pvmfsleep.c $(RM) pvmfsleep.c pvmfspawn.o: $(SDIR)/pvmfspawn.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfspawn.m4 > pvmfspawn.c $(M4B1) $(SDIR)/pvmfspawn.m4 $(RWBSPECIAL) >> pvmfspawn.c $(M4B2) $(CC) $(CFLAGS) pvmfspawn.c $(RM) pvmfspawn.c pvmfstartpvmd.o: $(SDIR)/pvmfstartpvmd.m4 $(M4FILE) $(PVMHEADERS) $(PVMALLOCH) $(M4A) $(SDIR)/pvmfstartpvmd.m4 > pvmfstartpvmd.c $(M4B1) $(SDIR)/pvmfstartpvmd.m4 $(RWBSPECIAL) >> pvmfstartpvmd.c $(M4B2) $(CC) $(CFLAGS) pvmfstartpvmd.c $(RM) pvmfstartpvmd.c pvmftasks.o: $(SDIR)/pvmftasks.m4 $(M4FILE) $(PVMBFHEADERS) $(M4A) $(SDIR)/pvmftasks.m4 > pvmftasks.c $(M4B1) $(SDIR)/pvmftasks.m4 $(RWBSPECIAL) >> pvmftasks.c $(M4B2) $(CC) $(CFLAGS) pvmftasks.c $(RM) pvmftasks.c pvmftidtoh.o: $(SDIR)/pvmftidtoh.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmftidtoh.m4 > pvmftidtoh.c $(M4B1) $(SDIR)/pvmftidtoh.m4 $(RWBSPECIAL) >> pvmftidtoh.c $(M4B2) $(CC) $(CFLAGS) pvmftidtoh.c $(RM) pvmftidtoh.c pvmftrecv.o: $(SDIR)/pvmftrecv.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmftrecv.m4 > pvmftrecv.c $(M4B1) $(SDIR)/pvmftrecv.m4 $(RWBSPECIAL) >> pvmftrecv.c $(M4B2) $(CC) $(CFLAGS) pvmftrecv.c $(RM) pvmftrecv.c pvmfunpack.o: $(SDIR)/pvmfunpack.m4 $(M4FILE) $(PVMHEADERS) $(M4A) $(SDIR)/pvmfunpack.m4 > pvmfunpack.c $(M4B1) $(SDIR)/pvmfunpack.m4 $(RWBSPECIAL) >> pvmfunpack.c $(M4B2) $(CC) $(CFLAGS) pvmfunpack.c $(RM) pvmfunpack.c ./pvm3/libfpvm/Makefile.mak0100644007401100000360000003627506673254751015002 0ustar kohlgopher# # $Id: Makefile.mak,v 1.6 1999/03/15 19:05:13 pvmsrc Exp $ # #*************************************************************# #** **# #** Nmake file for libfpvm.lib **# #** libfpvm.lib **# #** **# #** **# #*************************************************************# !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !include $(PVM_ROOT)\conf\$(PVM_ARCH).def # PVM_ROOT is set during installation in WIN32.def ! SDIR = $(PVM_ROOT)\libfpvm\win32 LOBS = $(PVM_ARCH)\pvmfaddhost.obj \ $(PVM_ARCH)\pvmfaddmhf.obj \ $(PVM_ARCH)\pvmfarchcode.obj \ $(PVM_ARCH)\pvmfbarrier.obj \ $(PVM_ARCH)\pvmfbcast.obj \ $(PVM_ARCH)\pvmfbufinfo.obj \ $(PVM_ARCH)\pvmfcatchout.obj \ $(PVM_ARCH)\pvmfconfig.obj \ $(PVM_ARCH)\pvmfdelhost.obj \ $(PVM_ARCH)\pvmfdelinfo.obj \ $(PVM_ARCH)\pvmfdelmhf.obj \ $(PVM_ARCH)\pvmfexit.obj \ $(PVM_ARCH)\pvmffreebuf.obj \ $(PVM_ARCH)\pvmffreectx.obj \ $(PVM_ARCH)\pvmffrzgrp.obj \ $(PVM_ARCH)\pvmfgather.obj \ $(PVM_ARCH)\pvmfgetctx.obj \ $(PVM_ARCH)\pvmfgetinfo.obj \ $(PVM_ARCH)\pvmfgetinst.obj \ $(PVM_ARCH)\pvmfgetopt.obj \ $(PVM_ARCH)\pvmfgetrbuf.obj \ $(PVM_ARCH)\pvmfgetsbuf.obj \ $(PVM_ARCH)\pvmfgettid.obj \ $(PVM_ARCH)\pvmfgsize.obj \ $(PVM_ARCH)\pvmfhalt.obj \ $(PVM_ARCH)\pvmfhostsync.obj \ $(PVM_ARCH)\pvmfinitsend.obj \ $(PVM_ARCH)\pvmfjoingrp.obj \ $(PVM_ARCH)\pvmfkill.obj \ $(PVM_ARCH)\pvmflvgrp.obj \ $(PVM_ARCH)\pvmfmcast.obj \ $(PVM_ARCH)\pvmfmkbuf.obj \ $(PVM_ARCH)\pvmfmstat.obj \ $(PVM_ARCH)\pvmfmytid.obj \ $(PVM_ARCH)\pvmfnewctx.obj \ $(PVM_ARCH)\pvmfnotify.obj \ $(PVM_ARCH)\pvmfnrecv.obj \ $(PVM_ARCH)\pvmfpack.obj \ $(PVM_ARCH)\pvmfparent.obj \ $(PVM_ARCH)\pvmfperror.obj \ $(PVM_ARCH)\pvmfprecv.obj \ $(PVM_ARCH)\pvmfprobe.obj \ $(PVM_ARCH)\pvmfpsend.obj \ $(PVM_ARCH)\pvmfpstat.obj \ $(PVM_ARCH)\pvmfputinfo.obj \ $(PVM_ARCH)\pvmfrecv.obj \ $(PVM_ARCH)\pvmfrecvinfo.obj \ $(PVM_ARCH)\pvmfreduce.obj \ $(PVM_ARCH)\pvmfscatter.obj \ $(PVM_ARCH)\pvmfsend.obj \ $(PVM_ARCH)\pvmfsendsig.obj \ $(PVM_ARCH)\pvmfsetctx.obj \ $(PVM_ARCH)\pvmfsetopt.obj \ $(PVM_ARCH)\pvmfsetrbuf.obj \ $(PVM_ARCH)\pvmfsetsbuf.obj \ $(PVM_ARCH)\pvmfsiblings.obj \ $(PVM_ARCH)\pvmfsleep.obj \ $(PVM_ARCH)\pvmfspawn.obj \ $(PVM_ARCH)\pvmfstartpvmd.obj \ $(PVM_ARCH)\pvmftasks.obj \ $(PVM_ARCH)\pvmftidtoh.obj \ $(PVM_ARCH)\pvmftrecv.obj \ $(PVM_ARCH)\pvmfunpack.obj \ all: libfpvm3.dll libfpvm3.lib libfpvm3.lib: $(LOBS) $(PVM_ARCH)\ftocstr.obj $(linklib) $(libspec) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\libfpvm\$(PVM_ARCH)\libfpvm3.lib \ $(LOBS) $(PVM_ARCH)\ftocstr.obj copy $(PVM_ARCH)\libfpvm3.lib $(PVM_ROOT)\lib\$(PVM_ARCH) libfpvm3.dll: $(LOBS) $(PVM_ARCH)\ftocstr.obj $(linkdll) $(dllspec) $(conflags) \ $(OUTBIN)$(PVM_ROOT)\libfpvm\$(PVM_ARCH)\libfpvm3.dll \ $(LOBS) $(PVM_ARCH)\ftocstr.obj \ $(PVM_CLIBDIR)\oldnames.lib \ $(PVM_CLIBDIR)\kernel32.lib \ $(PVM_CLIBDIR)\libcpmtd.lib \ $(PVM_CLIBDIR)\wsock32.lib \ $(PVM_CLIBDIR)\libc.lib \ $(PVM_CLIBDIR)\gdi32.lib $(PVM_CLIBDIR)\winspool.lib \ $(PVM_CLIBDIR)\comdlg32.lib \ $(PVM_CLIBDIR)\advapi32.lib \ $(PVM_CLIBDIR)\shell32.lib \ $(PVM_CLIBDIR)\ole32.lib \ $(PVM_CLIBDIR)\oleaut32.lib \ $(PVM_CLIBDIR)\uuid.lib \ $(PVM_CLIBDIR)\oldnames.lib \ ..\lib\WIN32\libpvm3.lib \ ..\lib\WIN32\libgpvm3.lib \ /DEBUG /nodefaultlib:"LIBCMTD.LIB" copy $(PVM_ARCH)\libfpvm3.dll $(PVM_ROOT)\lib\$(PVM_ARCH) $(PVM_ARCH)\ftocstr.obj: $(SDIR)\ftocstr.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\ftocstr.obj $(SDIR)\ftocstr.c $(PVM_ARCH)\pvmfaddhost.obj: $(SDIR)\pvmfaddhost.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfaddhost.obj $(SDIR)\pvmfaddhost.c $(PVM_ARCH)\pvmfaddmhf.obj: $(SDIR)\pvmfaddmhf.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfaddmhf.obj $(SDIR)\pvmfaddmhf.c $(PVM_ARCH)\pvmfarchcode.obj: $(SDIR)\pvmfarchcode.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfarchcode.obj $(SDIR)\pvmfarchcode.c $(PVM_ARCH)\pvmfbarrier.obj: $(SDIR)\pvmfbarrier.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfbarrier.obj $(SDIR)\pvmfbarrier.c $(PVM_ARCH)\pvmfbcast.obj: $(SDIR)\pvmfbcast.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfbcast.obj $(SDIR)\pvmfbcast.c $(PVM_ARCH)\pvmfbufinfo.obj: $(SDIR)\pvmfbufinfo.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfbufinfo.obj $(SDIR)\pvmfbufinfo.c $(PVM_ARCH)\pvmfcatchout.obj: $(SDIR)\pvmfcatchout.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfcatchout.obj $(SDIR)\pvmfcatchout.c $(PVM_ARCH)\pvmfconfig.obj: $(SDIR)\pvmfconfig.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfconfig.obj $(SDIR)\pvmfconfig.c $(PVM_ARCH)\pvmfdelhost.obj: $(SDIR)\pvmfdelhost.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfdelhost.obj $(SDIR)\pvmfdelhost.c $(PVM_ARCH)\pvmfdelinfo.obj: $(SDIR)\pvmfdelinfo.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfdelinfo.obj $(SDIR)\pvmfdelinfo.c $(PVM_ARCH)\pvmfdelmhf.obj: $(SDIR)\pvmfdelmhf.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfdelmhf.obj $(SDIR)\pvmfdelmhf.c $(PVM_ARCH)\pvmfexit.obj: $(SDIR)\pvmfexit.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfexit.obj $(SDIR)\pvmfexit.c $(PVM_ARCH)\pvmffreebuf.obj: $(SDIR)\pvmffreebuf.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmffreebuf.obj $(SDIR)\pvmffreebuf.c $(PVM_ARCH)\pvmffreectx.obj: $(SDIR)\pvmffreectx.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmffreectx.obj $(SDIR)\pvmffreectx.c $(PVM_ARCH)\pvmffrzgrp.obj: $(SDIR)\pvmffrzgrp.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmffrzgrp.obj $(SDIR)\pvmffrzgrp.c $(PVM_ARCH)\pvmfgather.obj: $(SDIR)\pvmfgather.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfgather.obj $(SDIR)\pvmfgather.c $(PVM_ARCH)\pvmfgetctx.obj: $(SDIR)\pvmfgetctx.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfgetctx.obj $(SDIR)\pvmfgetctx.c $(PVM_ARCH)\pvmfgetinfo.obj: $(SDIR)\pvmfgetinfo.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfgetinfo.obj $(SDIR)\pvmfgetinfo.c $(PVM_ARCH)\pvmfgetinst.obj: $(SDIR)\pvmfgetinst.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfgetinst.obj $(SDIR)\pvmfgetinst.c $(PVM_ARCH)\pvmfgetopt.obj: $(SDIR)\pvmfgetopt.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfgetopt.obj $(SDIR)\pvmfgetopt.c $(PVM_ARCH)\pvmfgetrbuf.obj: $(SDIR)\pvmfgetrbuf.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfgetrbuf.obj $(SDIR)\pvmfgetrbuf.c $(PVM_ARCH)\pvmfgetsbuf.obj: $(SDIR)\pvmfgetsbuf.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfgetsbuf.obj $(SDIR)\pvmfgetsbuf.c $(PVM_ARCH)\pvmfgettid.obj: $(SDIR)\pvmfgettid.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfgettid.obj $(SDIR)\pvmfgettid.c $(PVM_ARCH)\pvmfgsize.obj: $(SDIR)\pvmfgsize.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfgsize.obj $(SDIR)\pvmfgsize.c $(PVM_ARCH)\pvmfhalt.obj: $(SDIR)\pvmfhalt.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfhalt.obj $(SDIR)\pvmfhalt.c $(PVM_ARCH)\pvmfhostsync.obj: $(SDIR)\pvmfhostsync.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfhostsync.obj $(SDIR)\pvmfhostsync.c $(PVM_ARCH)\pvmfinitsend.obj: $(SDIR)\pvmfinitsend.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfinitsend.obj $(SDIR)\pvmfinitsend.c $(PVM_ARCH)\pvmfjoingrp.obj: $(SDIR)\pvmfjoingrp.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfjoingrp.obj $(SDIR)\pvmfjoingrp.c $(PVM_ARCH)\pvmfkill.obj: $(SDIR)\pvmfkill.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfkill.obj $(SDIR)\pvmfkill.c $(PVM_ARCH)\pvmflvgrp.obj: $(SDIR)\pvmflvgrp.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmflvgrp.obj $(SDIR)\pvmflvgrp.c $(PVM_ARCH)\pvmfmcast.obj: $(SDIR)\pvmfmcast.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfmcast.obj $(SDIR)\pvmfmcast.c $(PVM_ARCH)\pvmfmkbuf.obj: $(SDIR)\pvmfmkbuf.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfmkbuf.obj $(SDIR)\pvmfmkbuf.c $(PVM_ARCH)\pvmfmstat.obj: $(SDIR)\pvmfmstat.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfmstat.obj $(SDIR)\pvmfmstat.c $(PVM_ARCH)\pvmfmytid.obj: $(SDIR)\pvmfmytid.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfmytid.obj $(SDIR)\pvmfmytid.c $(PVM_ARCH)\pvmfnewctx.obj: $(SDIR)\pvmfnewctx.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfnewctx.obj $(SDIR)\pvmfnewctx.c $(PVM_ARCH)\pvmfnotify.obj: $(SDIR)\pvmfnotify.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfnotify.obj $(SDIR)\pvmfnotify.c $(PVM_ARCH)\pvmfnrecv.obj: $(SDIR)\pvmfnrecv.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfnrecv.obj $(SDIR)\pvmfnrecv.c $(PVM_ARCH)\pvmfpack.obj: $(SDIR)\pvmfpack.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfpack.obj $(SDIR)\pvmfpack.c $(PVM_ARCH)\pvmfparent.obj: $(SDIR)\pvmfparent.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfparent.obj $(SDIR)\pvmfparent.c $(PVM_ARCH)\pvmfperror.obj: $(SDIR)\pvmfperror.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfperror.obj $(SDIR)\pvmfperror.c $(PVM_ARCH)\pvmfprecv.obj: $(SDIR)\pvmfprecv.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfprecv.obj $(SDIR)\pvmfprecv.c $(PVM_ARCH)\pvmfprobe.obj: $(SDIR)\pvmfprobe.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfprobe.obj $(SDIR)\pvmfprobe.c $(PVM_ARCH)\pvmfpsend.obj: $(SDIR)\pvmfpsend.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfpsend.obj $(SDIR)\pvmfpsend.c $(PVM_ARCH)\pvmfpstat.obj: $(SDIR)\pvmfpstat.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfpstat.obj $(SDIR)\pvmfpstat.c $(PVM_ARCH)\pvmfputinfo.obj: $(SDIR)\pvmfputinfo.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfputinfo.obj $(SDIR)\pvmfputinfo.c $(PVM_ARCH)\pvmftrecv.obj: $(SDIR)\pvmftrecv.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmftrecv.obj $(SDIR)\pvmftrecv.c $(PVM_ARCH)\pvmfrecvinfo.obj: $(SDIR)\pvmfrecvinfo.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfrecvinfo.obj $(SDIR)\pvmfrecvinfo.c $(PVM_ARCH)\pvmfreduce.obj: $(SDIR)\pvmfreduce.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfreduce.obj $(SDIR)\pvmfreduce.c $(PVM_ARCH)\pvmfscatter.obj: $(SDIR)\pvmfscatter.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfscatter.obj $(SDIR)\pvmfscatter.c $(PVM_ARCH)\pvmfsend.obj: $(SDIR)\pvmfsend.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfsend.obj $(SDIR)\pvmfsend.c $(PVM_ARCH)\pvmfsendsig.obj: $(SDIR)\pvmfsendsig.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfsendsig.obj $(SDIR)\pvmfsendsig.c $(PVM_ARCH)\pvmfsetctx.obj: $(SDIR)\pvmfsetctx.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfsetctx.obj $(SDIR)\pvmfsetctx.c $(PVM_ARCH)\pvmfsetopt.obj: $(SDIR)\pvmfsetopt.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfsetopt.obj $(SDIR)\pvmfsetopt.c $(PVM_ARCH)\pvmfsetrbuf.obj: $(SDIR)\pvmfsetrbuf.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfsetrbuf.obj $(SDIR)\pvmfsetrbuf.c $(PVM_ARCH)\pvmfsetsbuf.obj: $(SDIR)\pvmfsetsbuf.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfsetsbuf.obj $(SDIR)\pvmfsetsbuf.c $(PVM_ARCH)\pvmfsiblings.obj: $(SDIR)\pvmfsiblings.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfsiblings.obj $(SDIR)\pvmfsiblings.c $(PVM_ARCH)\pvmfsleep.obj: $(SDIR)\pvmfsleep.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfsleep.obj $(SDIR)\pvmfsleep.c $(PVM_ARCH)\pvmfspawn.obj: $(SDIR)\pvmfspawn.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfspawn.obj $(SDIR)\pvmfspawn.c $(PVM_ARCH)\pvmfstartpvmd.obj: $(SDIR)\pvmfstartpvmd.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfstartpvmd.obj $(SDIR)\pvmfstartpvmd.c $(PVM_ARCH)\pvmftasks.obj: $(SDIR)\pvmftasks.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmftasks.obj $(SDIR)\pvmftasks.c $(PVM_ARCH)\pvmftidtoh.obj: $(SDIR)\pvmftidtoh.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmftidtoh.obj $(SDIR)\pvmftidtoh.c $(PVM_ARCH)\pvmfrecv.obj: $(SDIR)\pvmfrecv.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfrecv.obj $(SDIR)\pvmfrecv.c $(PVM_ARCH)\pvmfunpack.obj: $(SDIR)\pvmfunpack.c $(cc) $(cdebug) $(cflags) $(cvars) \ $(OUT)$(PVM_ARCH)\pvmfunpack.obj $(SDIR)\pvmfunpack.c # Clean up everything but the .EXEs clean: cd WIN32 -del *.obj -del *.pdb -del lib*.* ./pvm3/libfpvm/ftocstr.c0100644007401100000360000000410706427714201014374 0ustar kohlgopher static char rcsid[] = "$Id: ftocstr.c,v 1.3 1997/11/04 21:49:53 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ #include "../src/bfunc.h" #ifndef min #define min(i,j) ((i)<(j)?(i):(j)) #endif #ifdef SYSVSTR #include #else #include #endif ftocstr(ds, dl, ss, sl) char *ds, *ss; /* dst, src ptrs */ int dl; /* dst max len */ int sl; /* src len */ { char *p; for (p = ss + sl; --p >= ss && *p == ' '; ) ; sl = p - ss + 1; dl--; ds[0] = 0; if (sl > dl) return 1; strncat(ds, ss, min(sl, dl)); return 0; } ctofstr(ds, dl, ss) char *ds; /* dest space */ int dl; /* max dest length */ char *ss; /* src string (0-term) */ { int sl = strlen(ss); if (dl <= sl) BCOPY(ss, ds, dl); else { BCOPY(ss, ds, sl); dl -= sl; ds += sl; while (dl-- > 0) *ds++ = ' '; } return 0; } ./pvm3/libfpvm/pvm_consts.h0100644007401100000360000000327007024215211015077 0ustar kohlgopher /* $Id: pvm_consts.h,v 1.4 1999/12/10 15:21:45 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ #include #include #define MAX_ARCH_NAME 31 #define MAX_EVENT_NAME 31 #define MAX_HOST_NAME 256 #define MAX_PROC_NAME 256 #define MAX_GRP_NAME 31 #define MAX_HOSTS 256 #define MAX_MBOX_NAME 256 #define STRING 0 #define BYTE1 1 #define INTEGER2 2 #define INTEGER4 3 #define REAL4 4 #define COMPLEX8 5 #define REAL8 6 #define COMPLEX16 7 #define INTEGER8 8 ./pvm3/libfpvm/pvmfaddhost.m40100644007401100000360000000102206225226275015323 0ustar kohlgopher /* $Id: pvmfaddhost.m4,v 1.2 1996/10/04 15:26:53 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfaddhost) ARGS(`STRING_ARG(host), info') STRING_ARG_DECL(host); int *info; { int dtid; char thost[MAX_HOST_NAME + 1]; char *ptr = thost; /* * Copy the host name to make sure there's * a NUL at the end. */ if (ftocstr(thost, sizeof(thost), STRING_PTR(host), STRING_LEN(host))) { *info = PvmBadParam; return; } *info = pvm_addhosts(&ptr, 1, &dtid); if (*info >= 0) *info = dtid; } ./pvm3/libfpvm/pvmfaddmhf.m40100644007401100000360000000074606365413377015142 0ustar kohlgopher /* $Id: pvmfaddmhf.m4,v 1.5 1997/07/23 14:36:47 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfaddmhf) ARGS(`src, tag, ctx, mid, foo, info') #if defined(IMA_UXPM) || defined(IMA_UXPV) int (**foo)(); /* correction for Fujitsu FORTRAN77 EX */ #else int (*foo)(); #endif int *src, *tag, *ctx, *mid, *info; { #if defined(IMA_UXPM) || defined(IMA_UXPV) *info = pvm_addmhf(*src, *tag, *ctx, *foo); #else *info = pvm_addmhf(*src, *tag, *ctx, foo); #endif } ./pvm3/libfpvm/pvmfarchcode.m40100644007401100000360000000071206225226276015453 0ustar kohlgopher /* $Id: pvmfarchcode.m4,v 1.2 1996/10/04 15:26:54 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfarchcode) ARGS(`STRING_ARG(arch), code') STRING_ARG_DECL(arch); int *code; { char tarch[MAX_HOST_NAME + 1]; /* * Copy the arch name to make sure there's * a NUL at the end. */ if (ftocstr(tarch, sizeof(tarch), STRING_PTR(arch), STRING_LEN(arch))) { *code = PvmBadParam; return; } *code = pvm_archcode(tarch); } ./pvm3/libfpvm/pvmfbarrier.m40100644007401100000360000000074506225226277015340 0ustar kohlgopher /* $Id: pvmfbarrier.m4,v 1.2 1996/10/04 15:26:55 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfbarrier) ARGS(`STRING_ARG(group), count, info') STRING_ARG_DECL(group); int *count, *info; { char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's * a NUL at the end. */ if (ftocstr(tgroup, sizeof(tgroup), STRING_PTR(group), STRING_LEN(group))){ *info = PvmBadParam; return; } *info = pvm_barrier(tgroup, *count); } ./pvm3/libfpvm/pvmfbcast.m40100644007401100000360000000074206225226300014766 0ustar kohlgopher /* $Id: pvmfbcast.m4,v 1.2 1996/10/04 15:26:56 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfbcast) ARGS(`STRING_ARG(group), msgtag, info') STRING_ARG_DECL(group); int *msgtag, *info; { char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's * a NUL at the end. */ if (ftocstr(tgroup, sizeof(tgroup), STRING_PTR(group), STRING_LEN(group))){ *info = PvmBadParam; return; } *info = pvm_bcast(tgroup, *msgtag); } ./pvm3/libfpvm/pvmfbufinfo.m40100644007401100000360000000040006225226301015312 0ustar kohlgopher /* $Id: pvmfbufinfo.m4,v 1.2 1996/10/04 15:26:57 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfbufinfo) ARGS(`mid, len, type, tid, info') int *mid, *len, *type, *tid, *info; { *info = pvm_bufinfo(*mid, len, type, tid); } ./pvm3/libfpvm/pvmfcatchout.m40100644007401100000360000000036706225226302015511 0ustar kohlgopher /* $Id: pvmfcatchout.m4,v 1.2 1996/10/04 15:26:58 pvmsrc Exp $ */ #include #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfcatchout) ARGS(`yesno, info') int *yesno, *info; { *info = pvm_catchout(*yesno ? stdout : 0); } ./pvm3/libfpvm/pvmfconfig.m40100644007401100000360000000224606334142342015144 0ustar kohlgopher /* $Id: pvmfconfig.m4,v 1.4 1997/05/07 18:07:30 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" #include "../src/bfunc.h" void FUNCTION(pvmfconfig) ARGS(`nhostp, narchp, tidp, STRING_ARG(name), STRING_ARG(arch), speedp, infop') int *nhostp, *narchp, *tidp, *speedp, *infop; STRING_ARG_DECL(name); STRING_ARG_DECL(arch); { static struct pvmhostinfo *hip = 0; static int nhost = 0; static int narch = 0; static int next = 0; int nh; int cc; /* if user sets nhostp to -1 then pvmfconfig() will be reset */ if ( nhost && nhostp && (*nhostp == -1) ) nhost = 0; if ( !nhost ) { if ( (cc = pvm_config( &nh, &narch, &hip )) < 0 ) { *infop = cc; return; } nhost = nh; next = 0; } if ( next < nhost ) { if ( nhostp ) *nhostp = nhost; if ( narchp ) *narchp = narch; if ( tidp ) *tidp = hip[ next ].hi_tid; if ( STRING_PTR(name) ) ctofstr( STRING_PTR(name), STRING_LEN(name), hip[ next ].hi_name ); if ( STRING_PTR(arch) ) ctofstr( STRING_PTR(arch), STRING_LEN(arch), hip[ next ].hi_arch ); if ( speedp ) *speedp = hip[ next ].hi_speed; *infop = 1; next++; } if ( next == nhost ) nhost = 0; } ./pvm3/libfpvm/pvmfdelhost.m40100644007401100000360000000101306225226304015330 0ustar kohlgopher /* $Id: pvmfdelhost.m4,v 1.2 1996/10/04 15:27:00 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfdelhost) ARGS(`STRING_ARG(host), info') STRING_ARG_DECL(host); int *info; { char thost[MAX_HOST_NAME + 1]; char *ptr = thost; int cc; /* * Copy the host name to make sure there's * a NUL at the end. */ if (ftocstr(thost, sizeof(thost), STRING_PTR(host), STRING_LEN(host))) { *info = PvmBadParam; return; } *info = pvm_delhosts(&ptr, 1, &cc); if (*info >= 0) *info = cc; } ./pvm3/libfpvm/pvmfdelinfo.m40100644007401100000360000000100406320266275015315 0ustar kohlgopher /* $Id: pvmfdelinfo.m4,v 1.1 1997/04/01 20:14:53 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfdelinfo) ARGS(`STRING_ARG(name), mbx_index, flags, info') STRING_ARG_DECL(name); int *mbx_index, *flags, *info; { char tname[MAX_MBOX_NAME + 1]; /* * Copy the mailbox name to make sure there is * a NUL at the end. */ if (ftocstr(tname, sizeof(tname), STRING_PTR(name), STRING_LEN(name))) { *info = PvmBadParam; return; } *info = pvm_delinfo(tname, *mbx_index, *flags); } ./pvm3/libfpvm/pvmfdelmhf.m40100644007401100000360000000031506336125740015136 0ustar kohlgopher /* $Id: pvmfdelmhf.m4,v 1.2 1997/05/13 17:58:56 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfdelmhf) ARGS(`mhid, info') int *mhid, *info; { *info = pvm_delmhf(*mhid); } ./pvm3/libfpvm/pvmfexit.m40100644007401100000360000000026606225226305014651 0ustar kohlgopher /* $Id: pvmfexit.m4,v 1.2 1996/10/04 15:27:01 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfexit) ARGS(`info') int *info; { *info = pvm_exit(); } ./pvm3/libfpvm/pvmffreebuf.m40100644007401100000360000000032006225226306015306 0ustar kohlgopher /* $Id: pvmffreebuf.m4,v 1.2 1996/10/04 15:27:02 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmffreebuf) ARGS(`mbuf, info') int *mbuf, *info; { *info = pvm_freebuf(*mbuf); } ./pvm3/libfpvm/pvmffreectx.m40100644007401100000360000000032406336125742015341 0ustar kohlgopher /* $Id: pvmffreectx.m4,v 1.2 1997/05/13 17:58:58 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmffreecontext) ARGS(`ctx, info') int *ctx, *info; { *info = pvm_setcontext(*ctx); } ./pvm3/libfpvm/pvmffrzgrp.m40100644007401100000360000000075406225226307015216 0ustar kohlgopher /* $Id: pvmffrzgrp.m4,v 1.2 1996/10/04 15:27:03 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmffreezegroup) ARGS(`STRING_ARG(group), count, info') STRING_ARG_DECL(group); int *count, *info; { char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's * a NUL at the end. */ if (ftocstr(tgroup, sizeof(tgroup), STRING_PTR(group), STRING_LEN(group))){ *info = PvmBadParam; return; } *info = pvm_freezegroup(tgroup, *count); } ./pvm3/libfpvm/pvmfgather.m40100644007401100000360000000122006225226310015135 0ustar kohlgopher /* $Id: pvmfgather.m4,v 1.2 1996/10/04 15:27:04 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfgather) ARGS(`result, data, count, datatype, msgtag, STRING_ARG(gname), rootinst, info') void *result, *data; int *count, *datatype, *msgtag, *rootinst, *info; STRING_ARG_DECL(gname); { char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's a NUL at the end. */ if (ftocstr(tgroup,sizeof(tgroup),STRING_PTR(gname),STRING_LEN(gname))) { *info = PvmBadParam; return; } *info = pvm_gather(result, data, *count, *datatype, *msgtag, tgroup, *rootinst); } ./pvm3/libfpvm/pvmfgetctx.m40100644007401100000360000000030006336125743015172 0ustar kohlgopher /* $Id: pvmfgetctx.m4,v 1.2 1997/05/13 17:58:59 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfgetcontext) ARGS(`ctx') int *ctx; { *ctx = pvm_getcontext(); } ./pvm3/libfpvm/pvmfgetinfo.m40100644007401100000360000000326006334353010015323 0ustar kohlgopher /* $Id: pvmfgetinfo.m4,v 1.4 1997/05/08 13:32:56 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfgetmboxinfo) ARGS(`STRING_ARG(pattern), STRING_ARG(name), nclassesp, nentriesp, indexp, ownerp, flagp, infop') STRING_ARG_DECL(pattern); STRING_ARG_DECL(name); int *nclassesp, *nentriesp, *indexp, *ownerp, *flagp, *infop; { static struct pvmmboxinfo *classes = (struct pvmmboxinfo *) 0; static int nclasses = 0; static int next = 0; char tpattern[MAX_MBOX_NAME + 1]; int nc; int cc; int i; /* if user sets nclassesp to -1 then pvmfgetmboxinfo() will be reset */ if ( nclasses && nclassesp && (*nclassesp == -1) ) nclasses = 0; if ( !nclasses ) { /* * Copy the pattern to make sure there is * a NUL at the end. */ if ( ftocstr( tpattern, sizeof(tpattern), STRING_PTR(pattern), STRING_LEN(pattern) ) ) { *infop = PvmBadParam; return; } if ( (cc = pvm_getmboxinfo( tpattern, &nc, &classes )) < 0 ) { *infop = cc; return; } nclasses = nc; next = 0; if ( !nclasses ) *infop = PvmNotFound; } if ( next < nclasses ) { if ( STRING_PTR(name) ) ctofstr( STRING_PTR(name), STRING_LEN(name), classes[ next ].mi_name ); if ( nentriesp ) *nentriesp = classes[ next ].mi_nentries; if ( indexp ) { for ( i=0 ; i < classes[ next ].mi_nentries ; i++ ) indexp[i] = classes[ next ].mi_indices[i]; } if ( ownerp ) { for ( i=0 ; i < classes[ next ].mi_nentries ; i++ ) ownerp[i] = classes[ next ].mi_owners[i]; } if ( flagp ) { for ( i=0 ; i < classes[ next ].mi_nentries ; i++ ) flagp[i] = classes[ next ].mi_flags[i]; } } if ( next == nclasses ) nclasses = 0; } ./pvm3/libfpvm/pvmfgetinst.m40100644007401100000360000000073706225226311015355 0ustar kohlgopher /* $Id: pvmfgetinst.m4,v 1.2 1996/10/04 15:27:05 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfgetinst) ARGS(`STRING_ARG(group), tid, inum') STRING_ARG_DECL(group); int *inum, *tid; { char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's * a NUL at the end. */ if (ftocstr(tgroup, sizeof(tgroup), STRING_PTR(group), STRING_LEN(group))){ *inum = PvmBadParam; return; } *inum = pvm_getinst(tgroup, *tid); } ./pvm3/libfpvm/pvmfgetopt.m40100644007401100000360000000031506225226312015173 0ustar kohlgopher /* $Id: pvmfgetopt.m4,v 1.2 1996/10/04 15:27:06 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfgetopt) ARGS(`what, val') int *what, *val; { *val = pvm_getopt(*what); } ./pvm3/libfpvm/pvmfgetrbuf.m40100644007401100000360000000027606225226313015336 0ustar kohlgopher /* $Id: pvmfgetrbuf.m4,v 1.2 1996/10/04 15:27:07 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfgetrbuf) ARGS(`mbuf') int *mbuf; { *mbuf = pvm_getrbuf(); } ./pvm3/libfpvm/pvmfgetsbuf.m40100644007401100000360000000027606225226314015340 0ustar kohlgopher /* $Id: pvmfgetsbuf.m4,v 1.2 1996/10/04 15:27:08 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfgetsbuf) ARGS(`mbuf') int *mbuf; { *mbuf = pvm_getsbuf(); } ./pvm3/libfpvm/pvmfgettid.m40100644007401100000360000000073306225226315015160 0ustar kohlgopher /* $Id: pvmfgettid.m4,v 1.2 1996/10/04 15:27:09 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfgettid) ARGS(`STRING_ARG(group), inum, tid') STRING_ARG_DECL(group); int *inum, *tid; { char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's * a NUL at the end. */ if (ftocstr(tgroup, sizeof(tgroup), STRING_PTR(group), STRING_LEN(group))){ *tid = PvmBadParam; return; } *tid = pvm_gettid(tgroup, *inum); } ./pvm3/libfpvm/pvmfgsize.m40100644007401100000360000000071006225226316015015 0ustar kohlgopher /* $Id: pvmfgsize.m4,v 1.2 1996/10/04 15:27:10 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfgsize) ARGS(`STRING_ARG(group), size') STRING_ARG_DECL(group); int *size; { char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's * a NUL at the end. */ if (ftocstr(tgroup, sizeof(tgroup), STRING_PTR(group), STRING_LEN(group))){ *size = PvmBadParam; return; } *size = pvm_gsize(tgroup); } ./pvm3/libfpvm/pvmfhalt.m40100644007401100000360000000026606225226317014633 0ustar kohlgopher /* $Id: pvmfhalt.m4,v 1.2 1996/10/04 15:27:11 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfhalt) ARGS(`info') int *info; { *info = pvm_halt(); } ./pvm3/libfpvm/pvmfhostsync.m40100644007401100000360000000064506225226320015550 0ustar kohlgopher /* $Id: pvmfhostsync.m4,v 1.2 1996/10/04 15:27:12 pvmsrc Exp $ */ #include #include #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfhostsync) ARGS(`host, sec, usec, dsec, dusec, info') int *host, *sec, *usec, *dsec, *dusec, *info; { struct timeval t, dt; *info = pvm_hostsync(*host, &t, &dt); *sec = t.tv_sec; *usec = t.tv_usec; *dsec = dt.tv_sec; *dusec = dt.tv_usec; } ./pvm3/libfpvm/pvmfinitsend.m40100644007401100000360000000032006225226321015502 0ustar kohlgopher /* $Id: pvmfinitsend.m4,v 1.2 1996/10/04 15:27:13 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfinitsend) ARGS(`tid, info') int *tid, *info; { *info = pvm_initsend(*tid); } ./pvm3/libfpvm/pvmfjoingrp.m40100644007401100000360000000072206225226322015344 0ustar kohlgopher /* $Id: pvmfjoingrp.m4,v 1.2 1996/10/04 15:27:14 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfjoingroup) ARGS(`STRING_ARG(group), inum') STRING_ARG_DECL(group); int *inum; { char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's * a NUL at the end. */ if (ftocstr(tgroup, sizeof(tgroup), STRING_PTR(group), STRING_LEN(group))){ *inum = PvmBadParam; return; } *inum = pvm_joingroup(tgroup); } ./pvm3/libfpvm/pvmfkill.m40100644007401100000360000000030406225226323014624 0ustar kohlgopher /* $Id: pvmfkill.m4,v 1.2 1996/10/04 15:27:15 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfkill) ARGS(`tid, info') int *tid, *info; { *info = pvm_kill(*tid); } ./pvm3/libfpvm/pvmflvgrp.m40100644007401100000360000000071406225226324015031 0ustar kohlgopher /* $Id: pvmflvgrp.m4,v 1.2 1996/10/04 15:27:16 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmflvgroup) ARGS(`STRING_ARG(group), info') STRING_ARG_DECL(group); int *info; { char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's * a NUL at the end. */ if (ftocstr(tgroup, sizeof(tgroup), STRING_PTR(group), STRING_LEN(group))){ *info = PvmBadParam; return; } *info = pvm_lvgroup(tgroup); } ./pvm3/libfpvm/pvmfmcast.m40100644007401100000360000000036706225226325015013 0ustar kohlgopher /* $Id: pvmfmcast.m4,v 1.2 1996/10/04 15:27:17 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfmcast) ARGS(`ntid, tids, msgtag, info') int *ntid, *tids, *msgtag, *info; { *info = pvm_mcast(tids, *ntid, *msgtag); } ./pvm3/libfpvm/pvmfmkbuf.m40100644007401100000360000000032606225226326015004 0ustar kohlgopher /* $Id: pvmfmkbuf.m4,v 1.2 1996/10/04 15:27:18 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfmkbuf) ARGS(`encoding, mbuf') int *encoding, *mbuf; { *mbuf = pvm_mkbuf(*encoding); } ./pvm3/libfpvm/pvmfmstat.m40100644007401100000360000000070506225226327015032 0ustar kohlgopher /* $Id: pvmfmstat.m4,v 1.2 1996/10/04 15:27:19 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfmstat) ARGS(`STRING_ARG(host), mstat') STRING_ARG_DECL(host); int *mstat; { char thost[MAX_HOST_NAME + 1]; /* * Copy the host name to make sure there's * a NUL at the end. */ if (ftocstr(thost, sizeof(thost), STRING_PTR(host), STRING_LEN(host))) { *mstat = PvmBadParam; return; } *mstat = pvm_mstat(thost); } ./pvm3/libfpvm/pvmfmytid.m40100644007401100000360000000026506225226330015023 0ustar kohlgopher /* $Id: pvmfmytid.m4,v 1.2 1996/10/04 15:27:20 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfmytid) ARGS(`tid') int *tid; { *tid = pvm_mytid(); } ./pvm3/libfpvm/pvmfnewctx.m40100644007401100000360000000030006336125745015206 0ustar kohlgopher /* $Id: pvmfnewctx.m4,v 1.2 1997/05/13 17:59:01 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfnewcontext) ARGS(`ctx') int *ctx; { *ctx = pvm_newcontext(); } ./pvm3/libfpvm/pvmfnotify.m40100644007401100000360000000042106225226331015200 0ustar kohlgopher /* $Id: pvmfnotify.m4,v 1.2 1996/10/04 15:27:21 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfnotify) ARGS(`about, msgtag, ntid, tids, info') int *about, *ntid, *tids, *msgtag, *info; { *info = pvm_notify(*about, *msgtag, *ntid, tids); } ./pvm3/libfpvm/pvmfnrecv.m40100644007401100000360000000034106225226333015010 0ustar kohlgopher /* $Id: pvmfnrecv.m4,v 1.2 1996/10/04 15:27:23 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfnrecv) ARGS(`tid, msgtag, info') int *tid, *msgtag, *info; { *info = pvm_nrecv(*tid, *msgtag); } ./pvm3/libfpvm/pvmfpack.m40100644007401100000360000000167107024215212014610 0ustar kohlgopher /* $Id: pvmfpack.m4,v 1.3 1999/12/10 15:21:46 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfpack) ARGS(`what, vp, cnt, std, info') int *what, *cnt, *std, *info; #ifdef __STDC__ void *vp; #else char *vp; #endif { switch( *what ) { case BYTE1: *info = pvm_pkbyte((char*)vp, *cnt, *std); break; case INTEGER2: *info = pvm_pkshort((short*)vp, *cnt, *std); break; case INTEGER4: *info = pvm_pkint((int*)vp, *cnt, *std); break; case INTEGER8: *info = pvm_pklong((long*)vp, *cnt, *std); break; case REAL4: *info = pvm_pkfloat((float*)vp, *cnt, *std); break; case COMPLEX8: *info = pvm_pkcplx((float*)vp, *cnt, *std); break; case REAL8: *info = pvm_pkdouble((double*)vp, *cnt, *std); break; case COMPLEX16: *info = pvm_pkdcplx((double*)vp, *cnt, *std); break; case STRING: *info = pvm_pkbyte((char*)vp, *cnt, *std); break; default: *info = PvmBadParam; break; } } ./pvm3/libfpvm/pvmfparent.m40100644007401100000360000000027006225226335015167 0ustar kohlgopher /* $Id: pvmfparent.m4,v 1.2 1996/10/04 15:27:25 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfparent) ARGS(`tid') int *tid; { *tid = pvm_parent(); } ./pvm3/libfpvm/pvmfperror.m40100644007401100000360000000176706225226336015224 0ustar kohlgopher /* $Id: pvmfperror.m4,v 1.2 1996/10/04 15:27:26 pvmsrc Exp $ */ #include #include "pvm3.h" #include "pvm_consts.h" #define MAX(a,b) ((a) > (b) ? (a) : (b)) void FUNCTION(pvmfperror) ARGS(`STRING_ARG(p), info') STRING_ARG_DECL(p); int *info; { static char *buf = 0; static int buflen = 0; char *malloc(); /* * Have to have a NUL at the end of the string, and * the only way to do this portably is to copy the whole string * into a malloc'ed buffer. We keep the buffer around for * future use rather than free'ing it each time we're done. */ if (!buf) buf = malloc(buflen = STRING_LEN(p) + 1); else if (STRING_LEN(p) + 1 > buflen) { buflen = MAX(STRING_LEN(p) + 1, buflen * 2); /* don't use realloc; it might cause old data to be copied */ free(buf); buf = malloc(buflen); } if (!buf) { fprintf(stderr, "pvmfperror PvmNoMem"); *info = PvmNoMem; return; } strncpy(buf, STRING_PTR(p), STRING_LEN(p)); buf[STRING_LEN(p)] = '\0'; *info = pvm_perror(buf); } ./pvm3/libfpvm/pvmfprecv.m40100644007401100000360000000052006225226337015015 0ustar kohlgopher /* $Id: pvmfprecv.m4,v 1.2 1996/10/04 15:27:27 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfprecv) ARGS(`tid, msgtag, buf, len, dt, atid, atag, alen, info') int *tid, *msgtag, *len, *dt, *atid, *atag, *alen, *info; char *buf; { *info = pvm_precv(*tid, *msgtag, buf, *len, *dt, atid, atag, alen); } ./pvm3/libfpvm/pvmfprobe.m40100644007401100000360000000034106225226340015000 0ustar kohlgopher /* $Id: pvmfprobe.m4,v 1.2 1996/10/04 15:27:28 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfprobe) ARGS(`tid, msgtag, info') int *tid, *msgtag, *info; { *info = pvm_probe(*tid, *msgtag); } ./pvm3/libfpvm/pvmfpsend.m40100644007401100000360000000042706225226341015010 0ustar kohlgopher /* $Id: pvmfpsend.m4,v 1.2 1996/10/04 15:27:29 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfpsend) ARGS(`tid, msgtag, buf, len, dt, info') int *tid, *msgtag, *len, *dt, *info; char *buf; { *info = pvm_psend(*tid, *msgtag, buf, *len, *dt); } ./pvm3/libfpvm/pvmfpstat.m40100644007401100000360000000031206225226342015024 0ustar kohlgopher /* $Id: pvmfpstat.m4,v 1.2 1996/10/04 15:27:30 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfpstat) ARGS(`tid, pstat') int *tid, *pstat; { *pstat = pvm_pstat(*tid); } ./pvm3/libfpvm/pvmfputinfo.m40100644007401100000360000000101406320273422015352 0ustar kohlgopher /* $Id: pvmfputinfo.m4,v 1.2 1997/04/01 20:58:58 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfputinfo) ARGS(`STRING_ARG(name), bufid, flags, mbx_index') STRING_ARG_DECL(name); int *bufid, *flags, *mbx_index; { char tname[MAX_MBOX_NAME + 1]; /* * Copy the mailbox name to make sure there is * a NUL at the end. */ if (ftocstr(tname, sizeof(tname), STRING_PTR(name), STRING_LEN(name))) { *mbx_index = PvmBadParam; return; } *mbx_index = pvm_putinfo(tname, *bufid, *flags); } ./pvm3/libfpvm/pvmfrecvinfo.m40100644007401100000360000000101306320273705015504 0ustar kohlgopher /* $Id: pvmfrecvinfo.m4,v 1.2 1997/04/01 21:01:57 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfrecvinfo) ARGS(`STRING_ARG(name), mbx_index, flags, bufid') STRING_ARG_DECL(name); int *mbx_index, *flags, *bufid; { char tname[MAX_MBOX_NAME + 1]; /* * Copy the mailbox name to make sure there is * a NUL at the end. */ if (ftocstr(tname, sizeof(tname), STRING_PTR(name), STRING_LEN(name))) { *bufid = PvmBadParam; return; } *bufid = pvm_recvinfo(tname, *mbx_index, *flags); } ./pvm3/libfpvm/pvmfrecv.m40100644007401100000360000000033606225226343014637 0ustar kohlgopher /* $Id: pvmfrecv.m4,v 1.2 1996/10/04 15:27:31 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfrecv) ARGS(`tid, msgtag, info') int *tid, *msgtag, *info; { *info = pvm_recv(*tid, *msgtag); } ./pvm3/libfpvm/pvmfreduce.m40100644007401100000360000000317306365413400015146 0ustar kohlgopher /* $Id: pvmfreduce.m4,v 1.4 1997/07/23 14:36:48 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfreduce) ARGS(`func, data,count, datatype, msgtag, STRING_ARG(gname), rootinst, info') #if defined(IMA_UXPM) || defined(IMA_UXPV) void (**func)(); /* correction for Fujitsu FORTRAN77 EX */ #else void (*func)(); #endif void *data; int *count, *datatype, *msgtag, *rootinst, *info; STRING_ARG_DECL(gname); { char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's a NUL at the end. */ if (ftocstr(tgroup, sizeof(tgroup), STRING_PTR(gname), STRING_LEN(gname))){ *info = PvmBadParam; return; } #if defined(IMA_UXPM) || defined(IMA_UXPV) *info = pvm_reduce(*func, data, *count, *datatype, *msgtag, tgroup, *rootinst); #else *info = pvm_reduce(func, data, *count, *datatype, *msgtag, tgroup, *rootinst); #endif } /* various reduction functions are defined here */ void FUNCTION(pvmmax) ARGS(`datatype, data, work, count, info') int *datatype; void *data, *work; int *count, *info; { PvmMax(datatype, data, work, count, info); } void FUNCTION(pvmmin) ARGS(`datatype, data, work, count, info') int *datatype; void *data, *work; int *count, *info; { PvmMin(datatype, data, work, count, info); } void FUNCTION(pvmsum) ARGS(`datatype, data, work, count, info') int *datatype; void *data, *work; int *count, *info; { PvmSum(datatype, data, work, count, info); } void FUNCTION(pvmproduct) ARGS(`datatype, data, work, count, info') int *datatype; void *data, *work; int *count, *info; { PvmProduct(datatype, data, work, count, info); } ./pvm3/libfpvm/pvmfscatter.m40100644007401100000360000000122406225226345015344 0ustar kohlgopher /* $Id: pvmfscatter.m4,v 1.2 1996/10/04 15:27:33 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfscatter) ARGS(`result, data, count, datatype, msgtag, STRING_ARG(gname), rootinst, info') void *result, *data; int *count, *datatype, *msgtag, *rootinst, *info; STRING_ARG_DECL(gname); { char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's a NUL at the end. */ if (ftocstr(tgroup,sizeof(tgroup),STRING_PTR(gname),STRING_LEN(gname))) { *info = PvmBadParam; return; } *info = pvm_scatter(result, data, *count, *datatype, *msgtag, tgroup, *rootinst); } ./pvm3/libfpvm/pvmfsend.m40100644007401100000360000000033606225226346014634 0ustar kohlgopher /* $Id: pvmfsend.m4,v 1.2 1996/10/04 15:27:34 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfsend) ARGS(`tid, msgtag, info') int *tid, *msgtag, *info; { *info = pvm_send(*tid, *msgtag); } ./pvm3/libfpvm/pvmfsendsig.m40100644007401100000360000000034706225226347015342 0ustar kohlgopher /* $Id: pvmfsendsig.m4,v 1.2 1996/10/04 15:27:35 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfsendsig) ARGS(`tid, signum, info') int *tid, *signum, *info; { *info = pvm_sendsig(*tid, *signum); } ./pvm3/libfpvm/pvmfsetctx.m40100644007401100000360000000034706336125746015224 0ustar kohlgopher /* $Id: pvmfsetctx.m4,v 1.2 1997/05/13 17:59:02 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfsetcontext) ARGS(`new_ctx, old_ctx') int *new_ctx, *old_ctx; { *old_ctx = pvm_setcontext(*new_ctx); } ./pvm3/libfpvm/pvmfsetopt.m40100644007401100000360000000033606225226351015215 0ustar kohlgopher /* $Id: pvmfsetopt.m4,v 1.2 1996/10/04 15:27:37 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfsetopt) ARGS(`what, val, info') int *what, *val, *info; { *info = pvm_setopt(*what, *val); } ./pvm3/libfpvm/pvmfsetrbuf.m40100644007401100000360000000032606225226352015351 0ustar kohlgopher /* $Id: pvmfsetrbuf.m4,v 1.2 1996/10/04 15:27:38 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfsetrbuf) ARGS(`mbuf, oldbuf') int *mbuf, *oldbuf; { *oldbuf = pvm_setrbuf(*mbuf); } ./pvm3/libfpvm/pvmfsetsbuf.m40100644007401100000360000000032606225226353015353 0ustar kohlgopher /* $Id: pvmfsetsbuf.m4,v 1.2 1996/10/04 15:27:39 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfsetsbuf) ARGS(`mbuf, oldbuf') int *mbuf, *oldbuf; { *oldbuf = pvm_setsbuf(*mbuf); } ./pvm3/libfpvm/pvmfsiblings.m40100644007401100000360000000076607502372403015517 0ustar kohlgopher /* $Id: pvmfsiblings.m4,v 1.3 2002/06/14 13:52:03 pvmsrc Exp $ */ #include #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfsiblings) ARGS(`nsiblings, sibidx, stid') int *nsiblings, *sibidx, *stid; { static int nsib = -1; static int *sibs; if (nsib == -1) nsib = pvm_siblings(&sibs); if ( nsiblings != NULL ) *nsiblings = nsib; if ( sibidx != NULL && stid != NULL ) { if (*sibidx >= 0 && *sibidx< nsib) *stid = sibs[*sibidx]; else *stid = PvmNoTask; } } ./pvm3/libfpvm/pvmfsleep.m40100644007401100000360000000026406673254612015017 0ustar kohlgopher /* $Id: pvmfsleep.m4,v 1.1 1999/03/15 19:03:38 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfsleep) ARGS(`secs') int *secs; { pvmsleep(*secs); } ./pvm3/libfpvm/pvmfspawn.m40100644007401100000360000000172206225226354015032 0ustar kohlgopher /* $Id: pvmfspawn.m4,v 1.2 1996/10/04 15:27:40 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfspawn) ARGS(`STRING_ARG(aout), flag, STRING_ARG(where), count, tids, info') STRING_ARG_DECL(aout); STRING_ARG_DECL(where); int *flag, *count, *tids, *info; { char taout[MAX_PROC_NAME + 1]; char twhere[MAX_HOST_NAME + 1]; /* * Copy the program and where names to make sure there's * a NUL at the end. */ if (ftocstr(taout, sizeof(taout), STRING_PTR(aout), STRING_LEN(aout))) { *info = PvmBadParam; return; } /* * if the where parameter is '*', pass a NULL pointer to * initiate which will allow execution on any machine. */ if (*(STRING_PTR(where)) == '*') { *info = pvm_spawn(taout, (char**)0, *flag, "", *count, tids); } else { if (ftocstr(twhere, sizeof(twhere), STRING_PTR(where), STRING_LEN(where))) { *info = PvmBadParam; return; } *info = pvm_spawn(taout, (char**)0, *flag, twhere, *count, tids); } } ./pvm3/libfpvm/pvmfstartpvmd.m40100644007401100000360000001032306225226355015724 0ustar kohlgopher /* $Id: pvmfstartpvmd.m4,v 1.2 1996/10/04 15:27:41 pvmsrc Exp $ */ /* *---------------------------------------------------------------------- * Time-stamp: "1995/11/21 13:31:32 thibaud@kether.cgd.ucar.edu" *---------------------------------------------------------------------- */ /* *---------------------------------------------------------------------- * pvmfstartpvmd.m4 * * Interface to Fortran for pvm_start_pvmd() *---------------------------------------------------------------------- */ #include #include "pvm3.h" #include "pvm_consts.h" #include "pvmalloc.h" void FUNCTION(pvmfstartpvmd) ARGS(`STRING_ARG(args), block, info') STRING_ARG_DECL(args); int *block; int *info; { char *nargs; /* args (null terminated) */ int ac = 0; /* # of agruments initialize to 0 */ char **av; /* argument vector */ register char *ch; /* temp char pointer */ register char *beg; /* pointer to begining of word */ register char *end; /* pointer to end of word */ register int len; /* length of word */ register int i; /* loop index */ #if ( DEBUG ) /* printout incoming nargs */ printf( "%d \"%s\"\n", STRING_LEN(args), STRING_PTR(args) ); #endif /* Some Fortran compilers allow for strings of zero length */ if ( STRING_LEN(args) == 0 ) { /* null args */ av = (char **)0; /* make av a null pointer */ goto pvmd; } else { /* something in args */ if ( ( nargs = TALLOC( STRING_LEN(args) + 1, char, "nargs" ) ) == NULL ) { pvmlogerror("pvmfstartpvmd() can't get memory\n"); goto bail; } /* copy args (ftocptr() could have been used for that) */ strncpy( nargs, STRING_PTR(args), STRING_LEN(args) ); nargs[STRING_LEN(args)] = '\0'; /* terminate with null */ } ch = nargs; /* pointer at the begining of nargs */ /* assume a max of 32 args (8 should be OK from pvmd3(3PVM)) */ if ( ( av = TALLOC( 32, char *, "av" ) ) == NULL ) { pvmlogerror("pvmfstartpvmd() can't get memory\n"); PVM_FREE( nargs ); /* avoid memory leeks */ goto bail; } /* at this point nargs contain at least 1 char */ for ( ; ; ) { /* move forward until no space nor tab */ for( ; *ch == ' ' || *ch == '\t'; ch++ ); beg = ch; /* that's the begining of a word */ /* move forward until space, tab or null */ for( ; *ch != ' ' && *ch != '\t' && *ch != '\0'; ch++ ); end = ch; /* that's the end of a word */ len = end - beg; /* length of the word */ /* if nothing else then space, tab or null has been found */ /* then end of nargs is reached (exit point of loop) */ if ( len == 0 ) break; /* allocate memory for word in agument vector */ if ( ( av[ac] = TALLOC( len + 1, char, "av[ac]" ) ) == NULL ) { pvmlogerror("pvmfstartpvmd() can't get memory\n"); PVM_FREE( nargs ); /* avoid memory leeks */ for ( i = 0; i < ac; i++ ) PVM_FREE( av[i] ); goto bail; } strncpy( av[ac], beg, len ); /* copy word to arg vector */ *( av[ac] + len ) = '\0'; /* null terminate word */ ac++; /* increment arg counter */ } #if ( DEBUG ) printf( "ac is %d\n", ac ); #endif if ( ac == 0 ) { /* no args found */ PVM_FREE( av ); /* free allocated memory */ av = (char **)0; /* make av a NULL pointer */ #if ( DEBUG ) } else { /* printout result */ for ( i = 0; i < ac; i++ ) printf( "av[%2d] is \"%s\"\n", i, av[i] ); #endif } PVM_FREE( nargs ); /* free allocated memory */ pvmd: /* hopefully pvm_start_pvmd is freeing allocated mem for av */ *info = pvm_start_pvmd( ac, av, *block ); return; bail: *info = -1; return; } /* *---------------------------------------------------------------------- * RCS identification *---------------------------------------------------------------------- * $Author: pvmsrc $ * $Date: 1996/10/04 15:27:41 $ * $Locker: $ * $Revision: 1.2 $ * $Source: /home/nfs/pvmsrc/.CVS/PVM/pvm3.4/libfpvm/pvmfstartpvmd.m4,v $ * $State: Exp $ *---------------------------------------------------------------------- * For GNU Emacs: *---------------------------------------------------------------------- * Local Variables: * mode: C * abbrev-mode: t * comment-column: 40 * version-control: t * End: *---------------------------------------------------------------------- */ ./pvm3/libfpvm/pvmftasks.m40100644007401100000360000000227706334142344015032 0ustar kohlgopher /* $Id: pvmftasks.m4,v 1.4 1997/05/07 18:07:32 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" #include "../src/bfunc.h" void FUNCTION(pvmftasks) ARGS(`where, ntaskp, tidp, ptidp, hostp, flagp, STRING_ARG(a_out), infop') int *where, *ntaskp, *tidp, *ptidp, *hostp, *flagp, *infop; STRING_ARG_DECL(a_out); { static struct pvmtaskinfo *tip = 0; static int ntask = 0; static int next = 0; int nt; int cc; /* if user sets ntaskp to -1 then pvmftasks() will be reset */ if ( ntask && ntaskp && (*ntaskp == -1) ) ntask = 0; if ( !ntask ) { if ( (cc = pvm_tasks( *where, &nt, &tip )) < 0 ) { *infop = cc; return; } ntask = nt; next = 0; } if ( next < ntask ) { if ( ntaskp ) *ntaskp = ntask; if ( tidp ) *tidp = tip[ next ].ti_tid; if ( ptidp ) *ptidp = tip[ next ].ti_ptid; if ( hostp ) *hostp = tip[ next ].ti_host; if ( flagp ) *flagp = tip[ next ].ti_flag; if ( STRING_PTR(a_out) ) ctofstr( STRING_PTR(a_out), STRING_LEN(a_out), tip[ next ].ti_a_out ); *infop = 1; next++; } /* cannot return ti_pid without changing interface */ /* users needing this will have to use C */ if ( next == ntask ) ntask = 0; } ./pvm3/libfpvm/pvmftidtoh.m40100644007401100000360000000032306225226357015174 0ustar kohlgopher /* $Id: pvmftidtoh.m4,v 1.2 1996/10/04 15:27:43 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmftidtohost) ARGS(`tid, dtid') int *dtid, *tid; { *dtid = pvm_tidtohost(*tid); } ./pvm3/libfpvm/pvmftrecv.m40100644007401100000360000000061106225226360015016 0ustar kohlgopher /* $Id: pvmftrecv.m4,v 1.2 1996/10/04 15:27:44 pvmsrc Exp $ */ #include #include #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmftrecv) ARGS(`tid, msgtag, sec, usec, info') int *tid, *msgtag, *sec, *usec, *info; { struct timeval t; t.tv_sec = *sec; t.tv_usec = *usec; *info = pvm_trecv(*tid, *msgtag, (*sec == -1 ? (struct timeval *)0 : &t)); } ./pvm3/libfpvm/pvmfunpack.m40100644007401100000360000000170607024271332015157 0ustar kohlgopher /* $Id: pvmfunpack.m4,v 1.4 1999/12/10 21:38:34 pvmsrc Exp $ */ #include "pvm3.h" #include "pvm_consts.h" void FUNCTION(pvmfunpack) ARGS(`what, vp, cnt, std, info') int *what, *cnt, *std, *info; #ifdef __STDC__ void *vp; #else char *vp; #endif { switch( *what ) { case BYTE1: *info = pvm_upkbyte((char*)vp, *cnt, *std); break; case INTEGER2: *info = pvm_upkshort((short*)vp, *cnt, *std); break; case INTEGER4: *info = pvm_upkint((int*)vp, *cnt, *std); break; case INTEGER8: *info = pvm_upklong((long*)vp, *cnt, *std); break; case REAL4: *info = pvm_upkfloat((float*)vp, *cnt, *std); break; case COMPLEX8: *info = pvm_upkcplx((float*)vp, *cnt, *std); break; case REAL8: *info = pvm_upkdouble((double*)vp, *cnt, *std); break; case COMPLEX16: *info = pvm_upkdcplx((double*)vp, *cnt, *std); break; case STRING: *info = pvm_upkbyte((char*)vp, *cnt, *std); break; default: *info = PvmBadParam; break; } } ./pvm3/libfpvm/OS2/0042755007401100000360000000000010117676455013163 5ustar kohlgopher./pvm3/libfpvm/OS2/Makefile0100644007401100000360000000063506401362560014610 0ustar kohlgopher# # $Id: Makefile,v 1.2 1997/08/28 20:54:08 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/libfpvm PVM_ARCH = OS2 CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) # install: default $(LIBDIR) default: make LIBPREFIX="" -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install clean: make LIBPREFIX="" -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean $(LIBDIR): mkdir $(LIBDIR) ./pvm3/libfpvm/WIN32/0042755007401100000360000000000010117676455013362 5ustar kohlgopher./pvm3/libfpvm/WIN32/ftocstr.c0100644007401100000360000000164006354762550015206 0ustar kohlgopher /* $Id: ftocstr.c,v 1.1 1997/06/27 16:08:08 pvmsrc Exp $ */ #include #include #include "../../src/bfunc.h" #ifndef min #define min(i,j) ((i)<(j)?(i):(j)) #endif ftocstr(ds, dl, ss, sl) char *ds, *ss; /* dst, src ptrs */ int dl; /* dst max len */ int sl; /* src len */ { char *p; for (p = ss + sl; --p >= ss && *p == ' '; ) ; sl = p - ss + 1; dl--; ds[0] = 0; if (sl > dl) return 1; strncat(ds, ss, min(sl, dl)); return 0; } ctofstr(ds, dl, ss) char *ds; /* dest space */ int dl; /* max dest length */ char *ss; /* src string (0-term) */ { int sl = strlen(ss); if (dl <= sl) BCOPY(ss, ds, dl); else { if ((ds=malloc(sizeof(char)*sl)) == 0) fprintf(stderr,"malloc in ctofstr failed \n"); memcpy(ds,ss,sl); return 0; dl -= sl; ds += sl; while (dl-- > 0) *ds++ = ' '; } return 0; } ./pvm3/libfpvm/WIN32/Pvmfaddhost.c0100644007401100000360000000136506601533067015777 0ustar kohlgopher /* $Id: Pvmfaddhost.c,v 1.2 1998/09/21 20:25:27 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\src\pvmwin.h" #endif #include "pvm3.h" #include "pvm_consts.h" #ifdef IMA_WIN32_WATCOM #include "watforstr.h" pvmfaddhost (host_str,info) WatcomFortranStr* host_str; int *info; { char *host_ptr=host_str->strP; int host_len=host_str->len; #else void __fortran PVMFADDHOST (host_ptr, info, host_len) char * host_ptr; int host_len; int *info; { #endif int dtid; char thost[MAX_HOST_NAME + 1]; char *ptr = thost; /* * Copy the host name to make sure there's * a NUL at the end. */ if (ftocstr(thost, sizeof(thost), host_ptr, host_len)) { *info = PvmBadParam; return; } *info = pvm_addhosts(&ptr, 1, &dtid); if (*info >= 0) *info = dtid; } ./pvm3/libfpvm/WIN32/Pvmfaddmhf.c0100644007401100000360000000061306601533071015562 0ustar kohlgopher /* $Id: Pvmfaddmhf.c,v 1.2 1998/09/21 20:25:29 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\src\pvmwin.h" #endif #include "pvm3.h" #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfaddmhf (src, tag, ctx, mid, foo, info) #else __fortran PVMFADDMHF (src, tag, ctx, mid, foo, info) #endif int (*foo)(); int *src, *tag, *ctx, *mid, *info; { *info = pvm_addmhf(*src, *tag, *ctx, foo); } ./pvm3/libfpvm/WIN32/Pvmfarchcode.c0100644007401100000360000000110206601533072016102 0ustar kohlgopher /* $Id: Pvmfarchcode.c,v 1.2 1998/09/21 20:25:30 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\src\pvmwin.h" #endif #include "pvm3.h" #include "pvm_consts.h" #ifdef IMA_WIN32_WATCOM void pvmfarchcode (arch_ptr, code, arch_len) #else void __fortran PVMFARCHCODE (arch_ptr, code, arch_len) #endif char * arch_ptr; int arch_len; int *code; { char tarch[MAX_HOST_NAME + 1]; /* * Copy the arch name to make sure there's * a NUL at the end. */ if (ftocstr(tarch, sizeof(tarch), arch_ptr, arch_len)) { *code = PvmBadParam; return; } *code = pvm_archcode(tarch); } ./pvm3/libfpvm/WIN32/Pvmfbarrier.c0100644007401100000360000000140706601533074015772 0ustar kohlgopher /* $Id: Pvmfbarrier.c,v 1.2 1998/09/21 20:25:32 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\src\pvmwin.h" #endif #include "pvm3.h" #include "pvm_consts.h" #ifdef IMA_WIN32_WATCOM #include "watforstr.h" void pvmfbarrier (group_str, count, info) WatcomFortranStr* group_str; int *count, *info; { char* group_ptr = group_str->strP; int group_len = group_str->len; #else void __stdcall PVMFBARRIER (group_ptr,group_len, count, info) char * group_ptr; int group_len; int *count, *info; { #endif char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's * a NUL at the end. */ if (ftocstr(tgroup, sizeof(tgroup), group_ptr, group_len)){ *info = PvmBadParam; return; } *info = pvm_barrier(tgroup, *count); } ./pvm3/libfpvm/WIN32/Pvmfbcast.c0100644007401100000360000000145406601533076015444 0ustar kohlgopher /* $Id: Pvmfbcast.c,v 1.2 1998/09/21 20:25:34 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" #ifdef IMA_WIN32_WATCOM #include "watforstr.h" void pvmfbcast (group_str, msgtag, info) WatcomFortranStr* group_str; int *msgtag, *info; { char* group_ptr = group_str->strP; int group_len = group_str->len; #else void __stdcall PVMFBCAST (group_ptr,group_len, msgtag, info) char * group_ptr; int group_len; int *msgtag, *info; { #endif char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's * a NUL at the end. */ if (ftocstr(tgroup, sizeof(tgroup), group_ptr, group_len)){ *info = PvmBadParam; return; } *info = pvm_bcast(tgroup, *msgtag); } ./pvm3/libfpvm/WIN32/Pvmfbufinfo.c0100644007401100000360000000064006601533077015775 0ustar kohlgopher /* $Id: Pvmfbufinfo.c,v 1.2 1998/09/21 20:25:35 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" #ifdef IMA_WIN32_WATCOM void pvmfbufinfo(mid, len, type, tid, info) #else __stdcall PVMFBUFINFO (mid, len, type, tid, info) #endif int *mid, *len, *type, *tid, *info; { *info = pvm_bufinfo(*mid, len, type, tid); } ./pvm3/libfpvm/WIN32/Pvmfcatchout.c0100644007401100000360000000061206601533101016142 0ustar kohlgopher /* $Id: Pvmfcatchout.c,v 1.2 1998/09/21 20:25:37 pvmsrc Exp $ */ #include #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfcatchout (yesno,info) #else __fortran PVMFCATCHOUT (yesno, info) #endif int *yesno, *info; { *info = pvm_catchout(*yesno ? stdout : 0); } ./pvm3/libfpvm/WIN32/Pvmfconfig.c0100644007401100000360000000315307452625054015616 0ustar kohlgopher /* $Id: Pvmfconfig.c,v 1.4 2002/04/03 16:13:32 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" #include "../../src/bfunc.h" void #ifdef IMA_WIN32_WATCOM pvmfconfig(nhostp, narchp, tidp, name_ptr,name_len, arch_ptr,arch_len speedp, infop) int *nhostp, *narchp, *tidp, *speedp, *infop; char * name_ptr; int name_len; char * arch_ptr; int arch_len; #else __fortran PVMFCONFIG (nhostp, narchp, /* rd narchp,arch_len, */ tidp, name_ptr,name_len, /* rd arch_ptr, */ arch_ptr,arch_len, speedp, infop) int *nhostp, *narchp, *tidp, *speedp, *infop; char * name_ptr; int name_len; char * arch_ptr; int arch_len; #endif { static struct pvmhostinfo *hip = 0; static int nhost = 0; static int narch = 0; static int next = 0; int cc; struct pvmhostinfo *hip2; #ifndef WIN32 char *malloc(); #endif /* if user sets nhostp to -1 then pvmfconfig() will be reset */ if (hip && (*nhostp == -1)) { free((char*)hip); hip = 0; } if (!hip) { if ((cc = pvm_config(&nhost, &narch, &hip2)) < 0) { *infop = cc; return; } hip = (struct pvmhostinfo*)malloc(nhost * sizeof(struct pvmhostinfo)); BCOPY((char*)hip2, (char*)hip, nhost * sizeof(struct pvmhostinfo)); next = 0; } if (next < nhost) { *nhostp = nhost; *narchp = narch; *tidp = hip[next].hi_tid; ctofstr(name_ptr, name_len, hip[next].hi_name); ctofstr(arch_ptr, arch_len, hip[next].hi_arch); *speedp = hip[next].hi_speed; *infop = 1; next++; } if (next == nhost) { free((char*)hip); hip = 0; } } ./pvm3/libfpvm/WIN32/Pvmfdelhost.c0100644007401100000360000000155206601533104016001 0ustar kohlgopher /* $Id: Pvmfdelhost.c,v 1.2 1998/09/21 20:25:40 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" #ifdef IMA_WIN32_WATCOM #include "watforstr.h" #endif #ifdef IMA_WIN32_WATCOM void pvmfdelhost (host_str,info) WatcomFortranStr* host_str; int *info; { char* host_ptr = host_str->strP; int host_len = host_str->len; #else void __fortran PVMDELHOST (host_ptr,host_len, info) char * host_ptr; int host_len; int *info; { #endif char thost[MAX_HOST_NAME + 1]; char *ptr = thost; int cc; /* * Copy the host name to make sure there's * a NUL at the end. */ if (ftocstr(thost, sizeof(thost), host_ptr, host_len)) { *info = PvmBadParam; return; } *info = pvm_delhosts(&ptr, 1, &cc); if (*info >= 0) *info = cc; } ./pvm3/libfpvm/WIN32/Pvmfdelinfo.c0100644007401100000360000000121206601533106015752 0ustar kohlgopher /* $Id: Pvmfdelinfo.c,v 1.2 1998/09/21 20:25:42 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\src\pvmwin.h" #endif #include "pvm3.h" #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfdelinfo (name_ptr, mbx_index, flags, info, name_len) #else __fortran PVMFDELINFO (name_ptr, mbx_index, flags, info, name_len) #endif char * name_ptr; int name_len; int *mbx_index, *flags, *info; { char tname[MAX_MBOX_NAME + 1]; /* * Copy the mailbox name to make sure there is * a NUL at the end. */ if (ftocstr(tname, sizeof(tname), name_ptr, name_len)) { *info = PvmBadParam; return; } *info = pvm_delinfo(tname, *mbx_index, *flags); } ./pvm3/libfpvm/WIN32/Pvmfdelmhf.c0100644007401100000360000000046706601533117015606 0ustar kohlgopher /* $Id: Pvmfdelmhf.c,v 1.2 1998/09/21 20:25:51 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\src\pvmwin.h" #endif #include "pvm3.h" #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfdelmhf (mhid, info) #else __fortran PVMFDELMHF (mhid, info) #endif int *mhid, *info; { *info = pvm_delmhf(*mhid); } ./pvm3/libfpvm/WIN32/Pvmfexit.c0100644007401100000360000000047506601533120015311 0ustar kohlgopher /* $Id: Pvmfexit.c,v 1.2 1998/09/21 20:25:52 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfexit(info) #else __fortran PVMFEXIT (info) #endif int *info; { *info = pvm_exit(); } ./pvm3/libfpvm/WIN32/Pvmffreebuf.c0100644007401100000360000000054206601533122015753 0ustar kohlgopher /* $Id: Pvmffreebuf.c,v 1.2 1998/09/21 20:25:54 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmffreebuf (mbuf, info) #else __fortran PVMFFREEBUF (mbuf, info) #endif int *mbuf, *info; { *info = pvm_freebuf(*mbuf); } ./pvm3/libfpvm/WIN32/Pvmffreectx.c0100644007401100000360000000050006601533124015771 0ustar kohlgopher /* $Id: Pvmffreectx.c,v 1.2 1998/09/21 20:25:56 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\src\pvmwin.h" #endif #include "pvm3.h" #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmffreecontext (ctx,info) #else __fortran PVMFFREECONTEXT (ctx, info) #endif int *ctx, *info; { *info = pvm_setcontext(*ctx); } ./pvm3/libfpvm/WIN32/Pvmffrzgrp.c0100644007401100000360000000147206601533125015655 0ustar kohlgopher /* $Id: Pvmffrzgrp.c,v 1.2 1998/09/21 20:25:57 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" #ifdef IMA_WIN32_WATCOM #include "watforstr.h" void pvmffreezegroup (group_str, count, info) WatcomFortranStr* group_str; int *count, *info; { char* group_ptr = group_str->strP; int group_len = group_str->len; #else void __stdcall PVMFFREEZEGROUP (group_ptr,group_len, count, info) char * group_ptr; int group_len; int *count, *info; { #endif char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's * a NUL at the end. */ if (ftocstr(tgroup, sizeof(tgroup), group_ptr, group_len)){ *info = PvmBadParam; return; } *info = pvm_freezegroup(tgroup, *count); } ./pvm3/libfpvm/WIN32/Pvmfgather.c0100644007401100000360000000203706601533127015615 0ustar kohlgopher /* $Id: Pvmfgather.c,v 1.2 1998/09/21 20:25:59 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" #ifdef IMA_WIN32_WATCOM #include "watforstr.h" void pvmfgather (result, data, count, datatype, msgtag, gname_str, rootinst, info) void *result, *data; int *count, *datatype, *msgtag, *rootinst, *info; WatcomFortranStr* gname_str; { char* gname_ptr = gname_str->strP; int gname_len = gname_str->len; #else void __stdcall PVMFGATHER (result, data, count, datatype, msgtag, gname_ptr,gname_len, rootinst, info) void *result, *data; int *count, *datatype, *msgtag, *rootinst, *info; char * gname_ptr; int gname_len; { #endif char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's a NUL at the end. */ if (ftocstr(tgroup,sizeof(tgroup),gname_ptr,gname_len)) { *info = PvmBadParam; return; } *info = pvm_gather(result, data, *count, *datatype, *msgtag, tgroup, *rootinst); } ./pvm3/libfpvm/WIN32/Pvmfgetctx.c0100644007401100000360000000044706601533130015636 0ustar kohlgopher /* $Id: Pvmfgetctx.c,v 1.2 1998/09/21 20:26:00 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\src\pvmwin.h" #endif #include "pvm3.h" #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfgetcontext (ctx) #else __fortran PVMFGETCONTEXT (ctx) #endif int *ctx; { *ctx = pvm_getcontext(); } ./pvm3/libfpvm/WIN32/Pvmfgetinfo.c0100644007401100000360000000356406601533132016000 0ustar kohlgopher /* $Id: Pvmfgetinfo.c,v 1.2 1998/09/21 20:26:02 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\src\pvmwin.h" #endif #include "pvm3.h" #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfgetmboxinfo (pattern_ptr, name_ptr, nclassesp, nentriesp, indexp, ownerp, flagp, infop, pattern_len, name_len) #else __fortran PVMFGETMBOXINFO (pattern_ptr, name_ptr, nclassesp, nentriesp, indexp, ownerp, flagp, infop, pattern_len, name_len) #endif char * pattern_ptr; int pattern_len; char * name_ptr; int name_len; int *nclassesp, *nentriesp, *indexp, *ownerp, *flagp, *infop; { static struct pvmmboxinfo *classes = (struct pvmmboxinfo *) 0; static int nclasses = 0; static int next = 0; char tpattern[MAX_MBOX_NAME + 1]; int nc; int cc; int i; /* if user sets nclassesp to -1 then pvmfgetmboxinfo() will be reset */ if ( nclasses && nclassesp && (*nclassesp == -1) ) nclasses = 0; if ( !nclasses ) { /* * Copy the pattern to make sure there is * a NUL at the end. */ if ( ftocstr( tpattern, sizeof(tpattern), pattern_ptr, pattern_len ) ) { *infop = PvmBadParam; return; } if ( (cc = pvm_getmboxinfo( tpattern, &nc, &classes )) < 0 ) { *infop = cc; return; } nclasses = nc; next = 0; if ( !nclasses ) *infop = PvmNotFound; } if ( next < nclasses ) { if ( name_ptr ) ctofstr( name_ptr, name_len, classes[ next ].mi_name ); if ( nentriesp ) *nentriesp = classes[ next ].mi_nentries; if ( indexp ) { for ( i=0 ; i < classes[ next ].mi_nentries ; i++ ) indexp[i] = classes[ next ].mi_indices[i]; } if ( ownerp ) { for ( i=0 ; i < classes[ next ].mi_nentries ; i++ ) ownerp[i] = classes[ next ].mi_owners[i]; } if ( flagp ) { for ( i=0 ; i < classes[ next ].mi_nentries ; i++ ) flagp[i] = classes[ next ].mi_flags[i]; } } if ( next == nclasses ) nclasses = 0; } ./pvm3/libfpvm/WIN32/Pvmfgetinst.c0100644007401100000360000000144606601533134016021 0ustar kohlgopher /* $Id: Pvmfgetinst.c,v 1.2 1998/09/21 20:26:04 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" #ifdef IMA_WIN32_WATCOM #include "watforstr.h" void pvmfgetinst (group_str, tid, inum) WatcomFortranStr* group_str; int *inum, *tid; { char* group_ptr = group_str->strP; int group_len = group_str->len; #else void __stdcall PVMFGETINST (group_ptr,group_len, tid, inum) char * group_ptr; int group_len; int *inum, *tid; { #endif char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's * a NUL at the end. */ if (ftocstr(tgroup, sizeof(tgroup), group_ptr, group_len)){ *inum = PvmBadParam; return; } *inum = pvm_getinst(tgroup, *tid); } ./pvm3/libfpvm/WIN32/Pvmfgetopt.c0100644007401100000360000000053506601533135015645 0ustar kohlgopher /* $Id: Pvmfgetopt.c,v 1.2 1998/09/21 20:26:05 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfgetopt (what, val) #else __fortran PVMFGETOPT (what, val) #endif int *what, *val; { *val = pvm_getopt(*what); } ./pvm3/libfpvm/WIN32/Pvmfgetrbuf.c0100644007401100000360000000051206601533146015776 0ustar kohlgopher /* $Id: Pvmfgetrbuf.c,v 1.2 1998/09/21 20:26:14 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfgetrbuf (mbuf) #else __fortran PVMFGETRBUF (mbuf) #endif int *mbuf; { *mbuf = pvm_getrbuf(); } ./pvm3/libfpvm/WIN32/Pvmfgetsbuf.c0100644007401100000360000000051306601533147016001 0ustar kohlgopher /* $Id: Pvmfgetsbuf.c,v 1.2 1998/09/21 20:26:15 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfgetsbuf (mbuf) #else __fortran PVMFGETSBUF (mbuf) #endif int *mbuf; { *mbuf = pvm_getsbuf(); } ./pvm3/libfpvm/WIN32/Pvmfgettid.c0100644007401100000360000000144306601533151015620 0ustar kohlgopher /* $Id: Pvmfgettid.c,v 1.2 1998/09/21 20:26:17 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" #ifdef IMA_WIN32_WATCOM #include "watforstr.h" void pvmfgettid (group_str, inum, tid) WatcomFortranStr* group_str; int *inum, *tid; { char* group_ptr = group_str->strP; int group_len = group_str->len; #else void __stdcall PVMFGETTID (group_ptr,group_len, inum, tid) char * group_ptr; int group_len; int *inum, *tid; { #endif char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's * a NUL at the end. */ if (ftocstr(tgroup, sizeof(tgroup), group_ptr, group_len)){ *tid = PvmBadParam; return; } *tid = pvm_gettid(tgroup, *inum); } ./pvm3/libfpvm/WIN32/Pvmfgsize.c0100644007401100000360000000140106601533153015455 0ustar kohlgopher /* $Id: Pvmfgsize.c,v 1.2 1998/09/21 20:26:19 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" #ifdef IMA_WIN32_WATCOM #include "watforstr.h" void pvmfgsize (group_str, size) WatcomFortranStr* group_str; int *size; { char* group_ptr = group_str->strP; int group_len = group_str->len; #else void __stdcall PVMFGSIZE (group_ptr,group_len, size) char * group_ptr; int group_len; int *size; { #endif char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's * a NUL at the end. */ if (ftocstr(tgroup, sizeof(tgroup), group_ptr, group_len)){ *size = PvmBadParam; return; } *size = pvm_gsize(tgroup); } ./pvm3/libfpvm/WIN32/Pvmfhalt.c0100644007401100000360000000047706601533155015302 0ustar kohlgopher /* $Id: Pvmfhalt.c,v 1.2 1998/09/21 20:26:21 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfhalt (info) #else __fortran PVMFHALT (info) #endif int *info; { *info = pvm_halt(); } ./pvm3/libfpvm/WIN32/Pvmfhostsync.c0100644007401100000360000000114406601533157016216 0ustar kohlgopher /* $Id: Pvmfhostsync.c,v 1.2 1998/09/21 20:26:23 pvmsrc Exp $ */ #include #ifndef WIN32 #include #include "pvm3.h" #else #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #include #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfhostsync (host, sec, usec, dsec, dusec, info) #else __fortran PVMFHOSTSYNC (host, sec, usec, dsec, dusec, info) #endif int *host, *sec, *usec, *dsec, *dusec, *info; { struct timeval t, dt; *info = pvm_hostsync(*host, &t, &dt); *sec = t.tv_sec; *usec = t.tv_usec; *dsec = dt.tv_sec; *dusec = dt.tv_usec; } ./pvm3/libfpvm/WIN32/Pvmfinitsend.c0100644007401100000360000000054206601533160016154 0ustar kohlgopher /* $Id: Pvmfinitsend.c,v 1.2 1998/09/21 20:26:24 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfinitsend (tid, info) #else __fortran PVMFINITSEND (tid, info) #endif int *tid, *info; { *info = pvm_initsend(*tid); } ./pvm3/libfpvm/WIN32/Pvmfjoingrp.c0100644007401100000360000000130706625343625016022 0ustar kohlgopher /* $Id: Pvmfjoingrp.c,v 1.3 1998/11/20 19:48:37 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\src\pvmwin.h" #endif #include "pvm3.h" #include "pvm_consts.h" #ifdef IMA_WIN32_WATCOM #include "watforstr.h" pvmfjoingroup (group_str, inum) WatcomFortranStr* group_str; int *inum; { char* group_ptr = group_str->strP; int group_len = group_str->len; #else void __fortran PVMFJOINGROUP (group_ptr,group_len, inum) char * group_ptr; int group_len; int *inum; { #endif char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's * a NUL at the end. */ if (ftocstr(tgroup, sizeof(tgroup), group_ptr, group_len)){ *inum = PvmBadParam; return; } *inum = pvm_joingroup(tgroup); } ./pvm3/libfpvm/WIN32/Pvmfkill.c0100644007401100000360000000052206601533164015274 0ustar kohlgopher /* $Id: Pvmfkill.c,v 1.2 1998/09/21 20:26:28 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfkill (tid, info) #else __fortran PVMFKILL (tid, info) #endif int *tid, *info; { *info = pvm_kill(*tid); } ./pvm3/libfpvm/WIN32/Pvmflvgrp.c0100644007401100000360000000141206601533165015473 0ustar kohlgopher /* $Id: Pvmflvgrp.c,v 1.2 1998/09/21 20:26:29 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" #ifdef IMA_WIN32_WATCOM #include "watforstr.h" void pvmflvgroup (group_str, info) WatcomFortranStr* group_str; int *info; { char* group_ptr = group_str->strP; int group_len = group_str->len; #else void __stdcall PVMFLVGROUP (group_ptr,group_len, info) char * group_ptr; int group_len; int *info; { #endif char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's * a NUL at the end. */ if (ftocstr(tgroup, sizeof(tgroup), group_ptr, group_len)){ *info = PvmBadParam; return; } *info = pvm_lvgroup(tgroup); } ./pvm3/libfpvm/WIN32/Pvmfmcast.c0100644007401100000360000000062606601533206015452 0ustar kohlgopher /* $Id: Pvmfmcast.c,v 1.2 1998/09/21 20:26:46 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfmcast (ntid, tids, msgtag, info) #else __fortran PVMFMCAST (ntid, tids, msgtag, info) #endif int *ntid, *tids, *msgtag, *info; { *info = pvm_mcast(tids, *ntid, *msgtag); } ./pvm3/libfpvm/WIN32/Pvmfmkbuf.c0100644007401100000360000000055206601533207015446 0ustar kohlgopher /* $Id: Pvmfmkbuf.c,v 1.2 1998/09/21 20:26:47 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfmkbuf (encoding, mbuf) #else __fortran PVMFMKBUF (encoding, mbuf) #endif int *encoding, *mbuf; { *mbuf = pvm_mkbuf(*encoding); } ./pvm3/libfpvm/WIN32/Pvmfmstat.c0100644007401100000360000000136706601533211015472 0ustar kohlgopher /* $Id: Pvmfmstat.c,v 1.2 1998/09/21 20:26:49 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" #ifdef IMA_WIN32_WATCOM #include "watforstr.h" void pvmfstat (host_str, mstat) WatcomFortranStr* host_str; int *mstat; { char* host_ptr = host_str->strP; int host_len = host_str->len; #else void __stdcall PVMFMSTAT (host_ptr,host_len, mstat) char * host_ptr; int host_len; int *mstat; { #endif char thost[MAX_HOST_NAME + 1]; /* * Copy the host name to make sure there's * a NUL at the end. */ if (ftocstr(thost, sizeof(thost), host_ptr, host_len)) { *mstat = PvmBadParam; return; } *mstat = pvm_mstat(thost); } ./pvm3/libfpvm/WIN32/Pvmfmytid.c0100644007401100000360000000047406601533213015470 0ustar kohlgopher /* $Id: Pvmfmytid.c,v 1.2 1998/09/21 20:26:51 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" #ifdef IMA_WIN32_WATCOM void pvmfmytid (tid) #else __fortran PVMFMYTID (tid) #endif int *tid; { *tid = pvm_mytid(); } ./pvm3/libfpvm/WIN32/Pvmfnewctx.c0100644007401100000360000000044406601533215015651 0ustar kohlgopher /* $Id: Pvmfnewctx.c,v 1.2 1998/09/21 20:26:53 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\src\pvmwin.h" #endif #include "pvm3.h" #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfnewcontext(ctx) #else __fortran PVMFNEWCONTEXT(ctx) #endif int *ctx; { *ctx = pvm_newcontext(); } ./pvm3/libfpvm/WIN32/Pvmfnotify.c0100644007401100000360000000067006601533216015653 0ustar kohlgopher /* $Id: Pvmfnotify.c,v 1.2 1998/09/21 20:26:54 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfnotify (about, msgtag, ntid, tids, info) #else __fortran PVMFNOTIFY (about, msgtag, ntid, tids, info) #endif int *about, *ntid, *tids, *msgtag, *info; { *info = pvm_notify(*about, *msgtag, *ntid, tids); } ./pvm3/libfpvm/WIN32/Pvmfnrecv.c0100644007401100000360000000057006601533220015452 0ustar kohlgopher /* $Id: Pvmfnrecv.c,v 1.2 1998/09/21 20:26:56 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfnrecv (tid, msgtag, info) #else __fortran PVMFNRECV (tid, msgtag, info) #endif int *tid, *msgtag, *info; { *info = pvm_nrecv(*tid, *msgtag); } ./pvm3/libfpvm/WIN32/Pvmfpack.c0100644007401100000360000000216407024215246015261 0ustar kohlgopher /* $Id: Pvmfpack.c,v 1.3 1999/12/10 15:22:14 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfpack (what, vp, cnt, std, info) int *what, *cnt, *std, *info; #else __fortran PVMFPACK (what, vp, cnt, std, info) int *what, *cnt, *std, *info; #endif #ifdef __STDC__ void *vp; #else char *vp; #endif { switch( *what ) { case BYTE1: *info = pvm_pkbyte((char*)vp, *cnt, *std); break; case INTEGER2: *info = pvm_pkshort((short*)vp, *cnt, *std); break; case INTEGER4: *info = pvm_pkint((int*)vp, *cnt, *std); break; case INTEGER8: *info = pvm_pklong((long*)vp, *cnt, *std); break; case REAL4: *info = pvm_pkfloat((float*)vp, *cnt, *std); break; case COMPLEX8: *info = pvm_pkcplx((float*)vp, *cnt, *std); break; case REAL8: *info = pvm_pkdouble((double*)vp, *cnt, *std); break; case COMPLEX16: *info = pvm_pkdcplx((double*)vp, *cnt, *std); break; case STRING: *info = pvm_pkbyte((char*)vp, *cnt, *std); break; default: *info = PvmBadParam; break; } } ./pvm3/libfpvm/WIN32/Pvmfparent.c0100644007401100000360000000050306601533223015625 0ustar kohlgopher /* $Id: Pvmfparent.c,v 1.2 1998/09/21 20:26:59 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfparent (tid) #else __fortran PVMFPARENT (tid) #endif int *tid; { *tid = pvm_parent(); } ./pvm3/libfpvm/WIN32/Pvmfperror.c0100644007401100000360000000231106601533225015646 0ustar kohlgopher /* $Id: Pvmfperror.c,v 1.2 1998/09/21 20:27:01 pvmsrc Exp $ */ #include #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" #define MAX(a,b) ((a) > (b) ? (a) : (b)) void #ifdef IMA_WIN32_WATCOM pvmfperror (p_ptr,p_len, info) #else __fortran PVMFPERROR (p_ptr,p_len, info) #endif char * p_ptr; int p_len; int *info; { static char *buf = 0; static int buflen = 0; #ifndef WIN32 char *malloc(); #endif /* * Have to have a NUL at the end of the string, and * the only way to do this portably is to copy the whole string * into a malloc'ed buffer. We keep the buffer around for * future use rather than free'ing it each time we're done. */ if (!buf) buf = malloc(buflen = p_len + 1); else if (p_len + 1 > buflen) { buflen = MAX(p_len + 1, buflen * 2); /* don't use realloc; it might cause old data to be copied */ free(buf); buf = malloc(buflen); } if (!buf) { fprintf(stderr, "pvmfperror PvmNoMem"); *info = PvmNoMem; return; } strncpy(buf, p_ptr, p_len); buf[p_len] = '\0'; *info = pvm_perror(buf); } ./pvm3/libfpvm/WIN32/Pvmfprecv.c0100644007401100000360000000105106601533235015455 0ustar kohlgopher /* $Id: Pvmfprecv.c,v 1.2 1998/09/21 20:27:09 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfprecv (tid, msgtag, buf,buf_len, len, dt, atid, atag, alen, info) #else __fortran PVMFPRECV (tid, msgtag, buf,buf_len, len, dt, atid, atag, alen, info) #endif int *tid, *msgtag, *len, *dt, *atid, *atag, *alen, *info; char *buf;int buf_len; { *info = pvm_precv(*tid, *msgtag, buf, *len, *dt, atid, atag, alen); } ./pvm3/libfpvm/WIN32/Pvmfprobe.c0100644007401100000360000000057306601533237015457 0ustar kohlgopher /* $Id: Pvmfprobe.c,v 1.2 1998/09/21 20:27:11 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfprobe (tid, msgtag, info) #else __fortran PVMFPROBE (tid, msgtag, info) #endif int *tid, *msgtag, *info; { *info = pvm_probe(*tid, *msgtag); } ./pvm3/libfpvm/WIN32/Pvmfpsend.c0100644007401100000360000000073706601533241015456 0ustar kohlgopher /* $Id: Pvmfpsend.c,v 1.2 1998/09/21 20:27:13 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfpsend (tid, msgtag, buf,buf_len, len, dt, info) #else __fortran PVMFPSEND (tid, msgtag, buf,buf_len, len, dt, info) #endif int *tid, *msgtag, *len, *dt, *info; char *buf;int buf_len; { *info = pvm_psend(*tid, *msgtag, buf, *len, *dt); } ./pvm3/libfpvm/WIN32/Pvmfpstat.c0100644007401100000360000000053406601533242015474 0ustar kohlgopher /* $Id: Pvmfpstat.c,v 1.2 1998/09/21 20:27:14 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfpstat (tid, pstat) #else __fortran PVMFPSTAT (tid, pstat) #endif int *tid, *pstat; { *pstat = pvm_pstat(*tid); } ./pvm3/libfpvm/WIN32/Pvmfputinfo.c0100644007401100000360000000122006601533244016020 0ustar kohlgopher /* $Id: Pvmfputinfo.c,v 1.2 1998/09/21 20:27:16 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\src\pvmwin.h" #endif #include "pvm3.h" #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfputinfo (name_ptr, bufid, flags, mbx_index, name_len) #else __fortran PVMFPUTINFO(name_ptr, bufid, flags, mbx_index, name_len) #endif char * name_ptr; int name_len; int *bufid, *flags, *mbx_index; { char tname[MAX_MBOX_NAME + 1]; /* * Copy the mailbox name to make sure there is * a NUL at the end. */ if (ftocstr(tname, sizeof(tname), name_ptr, name_len)) { *mbx_index = PvmBadParam; return; } *mbx_index = pvm_putinfo(tname, *bufid, *flags); } ./pvm3/libfpvm/WIN32/Pvmfrecv.c0100644007401100000360000000056606601533246015311 0ustar kohlgopher /* $Id: Pvmfrecv.c,v 1.2 1998/09/21 20:27:18 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfrecv (tid, msgtag, info) #else __fortran PVMFRECV (tid, msgtag, info) #endif int *tid, *msgtag, *info; { *info = pvm_recv(*tid, *msgtag); } ./pvm3/libfpvm/WIN32/Pvmfrecvinfo.c0100644007401100000360000000122206601533247016154 0ustar kohlgopher /* $Id: Pvmfrecvinfo.c,v 1.2 1998/09/21 20:27:19 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\src\pvmwin.h" #endif #include "pvm3.h" #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfrecvinfo (name_ptr, mbx_index, flags, bufid, name_len) #else __fortran PVMFRECVINFO (name_ptr, mbx_index, flags, bufid, name_len) #endif char * name_ptr; int name_len; int *mbx_index, *flags, *bufid; { char tname[MAX_MBOX_NAME + 1]; /* * Copy the mailbox name to make sure there is * a NUL at the end. */ if (ftocstr(tname, sizeof(tname), name_ptr, name_len)) { *bufid = PvmBadParam; return; } *bufid = pvm_recvinfo(tname, *mbx_index, *flags); } ./pvm3/libfpvm/WIN32/Pvmfreduce.c0100644007401100000360000000440006673277456015631 0ustar kohlgopher /* $Id: Pvmfreduce.c,v 1.3 1999/03/15 21:44:14 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" #ifdef IMA_WIN32_WATCOM #include "watforstr.h" void pvmfreduce (func, data,count, datatype, msgtag, gname_str, rootinst, info) void (*func)(); void *data; int *count, *datatype, *msgtag, *rootinst, *info; WatcomFortranStr* gname_str; { char* gname_ptr = gname_str->strP; int gname_len = gname_str->len; #else void __stdcall PVMFREDUCE (func, data,count, datatype, msgtag, gname_ptr,gname_len, rootinst, info) #ifdef UXPM void (**func)(); /* correction for Fujitsu FORTRAN77 EX */ #else void (*func)(); #endif void *data; int *count, *datatype, *msgtag, *rootinst, *info; char * gname_ptr; int gname_len; { #endif char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's a NUL at the end. */ if (ftocstr(tgroup, sizeof(tgroup), gname_ptr, gname_len)){ *info = PvmBadParam; return; } #ifdef UXPM *info = pvm_reduce(*func, data, *count, *datatype, *msgtag, tgroup, *rootinst); #else *info = pvm_reduce(func, data, *count, *datatype, *msgtag, tgroup, *rootinst); #endif } /* various reduction functions are defined here */ void #ifdef IMA_WIN32_WATCOM pvmmax (datatype, data, work, count, info) #else __fortran PVMMAX (datatype, data, work, count, info) #endif int *datatype; void *data, *work; int *count, *info; { PvmMax(datatype, data, work, count, info); } void #ifdef IMA_WIN32_WATCOM pvmmin (datatype, data, work, count, info) #else __fortran PVMMIN (datatype, data, work, count, info) #endif int *datatype; void *data, *work; int *count, *info; { PvmMin(datatype, data, work, count, info); } void #ifdef IMA_WIN32_WATCOM pvmsum (datatype, data, work, count, info) #else __fortran PVMSUM (datatype, data, work, count, info) #endif int *datatype; void *data, *work; int *count, *info; { PvmSum(datatype, data, work, count, info); } void #ifdef IMA_WIN32_WATCOM pvmproduct (datatype, data, work, count, info) #else __fortran PVMPRODUCT (datatype, data, work, count, info) #endif int *datatype; void *data, *work; int *count, *info; { PvmProduct(datatype, data, work, count, info); } ./pvm3/libfpvm/WIN32/Pvmfscatter.c0100644007401100000360000000204306601533253016005 0ustar kohlgopher /* $Id: Pvmfscatter.c,v 1.2 1998/09/21 20:27:23 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" #ifdef IMA_WIN32_WATCOM #include "watforstr.h" void pvmfscatter (result, data, count, datatype, msgtag, gname_str, rootinst, info) void *result, *data; int *count, *datatype, *msgtag, *rootinst, *info; WatcomFortranStr* gname_str; { char* gname_ptr = gname_str->strP; int gname_len = gname_str->len; #else void __fortran PVMFSCATTER (result, data, count, datatype, msgtag, gname_ptr,gname_len, rootinst, info) void *result, *data; int *count, *datatype, *msgtag, *rootinst, *info; char * gname_ptr; int gname_len; { #endif char tgroup[MAX_GRP_NAME + 1]; /* * Copy the group name to make sure there's a NUL at the end. */ if (ftocstr(tgroup,sizeof(tgroup),gname_ptr,gname_len)) { *info = PvmBadParam; return; } *info = pvm_scatter(result, data, *count, *datatype, *msgtag, tgroup, *rootinst); } ./pvm3/libfpvm/WIN32/Pvmfsend.c0100644007401100000360000000056706601533255015304 0ustar kohlgopher /* $Id: Pvmfsend.c,v 1.2 1998/09/21 20:27:25 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfsend (tid, msgtag, info) #else __fortran PVMFSEND (tid, msgtag, info) #endif int *tid, *msgtag, *info; { *info = pvm_send(*tid, *msgtag); } ./pvm3/libfpvm/WIN32/Pvmfsendsig.c0100644007401100000360000000060306601533266016000 0ustar kohlgopher /* $Id: Pvmfsendsig.c,v 1.2 1998/09/21 20:27:34 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfsendsig (tid, signum, info) #else __fortran PVMFSENDSIG (tid, signum, info) #endif int *tid, *signum, *info; { *info = pvm_sendsig(*tid, *signum); } ./pvm3/libfpvm/WIN32/Pvmfsetctx.c0100644007401100000360000000053306601533270015653 0ustar kohlgopher /* $Id: Pvmfsetctx.c,v 1.2 1998/09/21 20:27:36 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\src\pvmwin.h" #endif #include "pvm3.h" #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfsetcontext (new_ctx, old_ctx) #else __fortran PVMFSETCONTEXT (new_ctx, old_ctx) #endif int *new_ctx, *old_ctx; { *old_ctx = pvm_setcontext(*new_ctx); } ./pvm3/libfpvm/WIN32/Pvmfsetopt.c0100644007401100000360000000056706601533271015667 0ustar kohlgopher /* $Id: Pvmfsetopt.c,v 1.2 1998/09/21 20:27:37 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfsetopt (what, val, info) #else __fortran PVMFSETOPT (what, val, info) #endif int *what, *val, *info; { *info = pvm_setopt(*what, *val); } ./pvm3/libfpvm/WIN32/Pvmfsetrbuf.c0100644007401100000360000000055506601533273016022 0ustar kohlgopher /* $Id: Pvmfsetrbuf.c,v 1.2 1998/09/21 20:27:39 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfsetrbuf (mbuf, oldbuf) #else __fortran PVMFSETRBUF (mbuf, oldbuf) #endif int *mbuf, *oldbuf; { *oldbuf = pvm_setrbuf(*mbuf); } ./pvm3/libfpvm/WIN32/Pvmfsetsbuf.c0100644007401100000360000000055506601533274016024 0ustar kohlgopher /* $Id: Pvmfsetsbuf.c,v 1.2 1998/09/21 20:27:40 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfsetsbuf (mbuf, oldbuf) #else __fortran PVMFSETSBUF (mbuf, oldbuf) #endif int *mbuf, *oldbuf; { *oldbuf = pvm_setsbuf(*mbuf); } ./pvm3/libfpvm/WIN32/Pvmfsiblings.c0100644007401100000360000000115707502372421016156 0ustar kohlgopher /* $Id: Pvmfsiblings.c,v 1.4 2002/06/14 13:52:17 pvmsrc Exp $ */ #include #ifdef WIN32 #include "..\..\src\pvmwin.h" #endif #include "pvm3.h" #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfsiblings (nsiblings, sibidx, stid) #else __fortran PVMFSIBLINGS (nsiblings, sibidx, stid) #endif int *nsiblings, *sibidx, *stid; { static int nsib = -1; static int *sibs; if (nsib == -1) nsib = pvm_siblings(&sibs); if ( nsiblings != NULL ) *nsiblings = nsib; if ( sibidx != NULL && stid != NULL ) { if (*sibidx >= 0 && *sibidx< nsib) *stid = sibs[*sibidx]; else *stid = PvmNoTask; } } ./pvm3/libfpvm/WIN32/Pvmfsleep.c0100644007401100000360000000047606673254567015501 0ustar kohlgopher /* $Id: Pvmfsleep.c,v 1.1 1999/03/15 19:03:19 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfsleep (secs) #else __fortran PVMFSLEEP (secs) #endif int *secs; { pvmsleep(*secs); } ./pvm3/libfpvm/WIN32/Pvmfspawn.c0100644007401100000360000000255706601533300015473 0ustar kohlgopher /* $Id: Pvmfspawn.c,v 1.2 1998/09/21 20:27:44 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" #ifdef IMA_WIN32_WATCOM #include "watforstr.h" void pvmfspawn (WatcomFortranStr *aout_str, int *flag, WatcomFortranStr *where_str, int *count, int *tids, int *info) { char* aout_ptr = aout_str->strP; int aout_len = aout_str->len; char* where_ptr = where_str->strP; int where_len = where_str->len; #else void __stdcall PVMFSPAWN (char *aout_ptr,int aout_len, int *flag, char *where_ptr,int where_len, int *count, int *tids, int *info) { #endif char taout[MAX_PROC_NAME + 1]; char twhere[MAX_HOST_NAME + 1]; /* * Copy the program and where names to make sure there's * a NUL at the end. */ if (ftocstr(taout, sizeof(taout), aout_ptr, aout_len)) { *info = PvmBadParam; return; } /* * if the where parameter is '*', pass a NULL pointer to * initiate which will allow execution on any machine. */ if (*(where_ptr) == '*') { *info = pvm_spawn(taout, (char**)0, *flag, "", *count, tids); } else { if (ftocstr(twhere, sizeof(twhere), where_ptr, where_len)) { *info = PvmBadParam; return; } *info = pvm_spawn(taout, (char**)0, *flag, twhere, *count, tids); } } ./pvm3/libfpvm/WIN32/Pvmfstartpvmd.c0100644007401100000360000000752406601533301016367 0ustar kohlgopher /* $Id: Pvmfstartpvmd.c,v 1.2 1998/09/21 20:27:45 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\src\pvmwin.h" #endif #include #include "pvm3.h" #include "pvm_consts.h" #include "pvmalloc.h" void #ifdef IMA_WIN32_WATCOM __fortran PVMFSTARTPVMD #else pvmfstartpvmd #endif (args_ptr, block, info, args_len) char * args_ptr; int args_len; int *block; int *info; { char *nargs; /* args (null terminated) */ int ac = 0; /* # of agruments initialize to 0 */ char **av; /* argument vector */ register char *ch; /* temp char pointer */ register char *beg; /* pointer to begining of word */ register char *end; /* pointer to end of word */ register int len; /* length of word */ register int i; /* loop index */ #if ( DEBUG ) /* printout incoming nargs */ printf( "%d \"%s\"\n", args_len, args_ptr ); #endif /* Some Fortran compilers allow for strings of zero length */ if ( args_len == 0 ) { /* null args */ av = (char **)0; /* make av a null pointer */ goto pvmd; } else { /* something in args */ if ( ( nargs = TALLOC( args_len + 1, char, "nargs" ) ) == NULL ) { pvmlogerror("pvmfstartpvmd() can't get memory\n"); goto bail; } /* copy args (ftocptr() could have been used for that) */ strncpy( nargs, args_ptr, args_len ); nargs[args_len] = '\0'; /* terminate with null */ } ch = nargs; /* pointer at the begining of nargs */ /* assume a max of 32 args (8 should be OK from pvmd3(3PVM)) */ if ( ( av = TALLOC( 32, char *, "av" ) ) == NULL ) { pvmlogerror("pvmfstartpvmd() can't get memory\n"); PVM_FREE( nargs ); /* avoid memory leeks */ goto bail; } /* at this point nargs contain at least 1 char */ for ( ; ; ) { /* move forward until no space nor tab */ for( ; *ch == ' ' || *ch == '\t'; ch++ ); beg = ch; /* that's the begining of a word */ /* move forward until space, tab or null */ for( ; *ch != ' ' && *ch != '\t' && *ch != '\0'; ch++ ); end = ch; /* that's the end of a word */ len = end - beg; /* length of the word */ /* if nothing else then space, tab or null has been found */ /* then end of nargs is reached (exit point of loop) */ if ( len == 0 ) break; /* allocate memory for word in agument vector */ if ( ( av[ac] = TALLOC( len + 1, char, "av[ac]" ) ) == NULL ) { pvmlogerror("pvmfstartpvmd() can't get memory\n"); PVM_FREE( nargs ); /* avoid memory leeks */ for ( i = 0; i < ac; i++ ) PVM_FREE( av[i] ); goto bail; } strncpy( av[ac], beg, len ); /* copy word to arg vector */ *( av[ac] + len ) = '\0'; /* null terminate word */ ac++; /* increment arg counter */ } #if ( DEBUG ) printf( "ac is %d\n", ac ); #endif if ( ac == 0 ) { /* no args found */ PVM_FREE( av ); /* free allocated memory */ av = (char **)0; /* make av a NULL pointer */ #if ( DEBUG ) } else { /* printout result */ for ( i = 0; i < ac; i++ ) printf( "av[%2d] is \"%s\"\n", i, av[i] ); #endif } PVM_FREE( nargs ); /* free allocated memory */ pvmd: /* hopefully pvm_start_pvmd is freeing allocated mem for av */ *info = pvm_start_pvmd( ac, av, *block ); return; bail: *info = -1; return; } /* *---------------------------------------------------------------------- * RCS identification *---------------------------------------------------------------------- * $Author: pvmsrc $ * $Date: 1998/09/21 20:27:45 $ * $Locker: $ * $Revision: 1.2 $ * $Source: /home/nfs/pvmsrc/.CVS/PVM/pvm3.4/libfpvm/WIN32/Pvmfstartpvmd.c,v $ * $State: Exp $ *---------------------------------------------------------------------- * For GNU Emacs: *---------------------------------------------------------------------- * Local Variables: * mode: C * abbrev-mode: t * comment-column: 40 * version-control: t * End: *---------------------------------------------------------------------- */ ./pvm3/libfpvm/WIN32/Pvmftasks.c0100644007401100000360000000306106601533303015462 0ustar kohlgopher /* $Id: Pvmftasks.c,v 1.2 1998/09/21 20:27:47 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" #include "../../src/bfunc.h" void #ifdef IMA_WIN32_WATCOM __fortran PVMFTASKS #else pvmftasks #endif (where, ntaskp, tidp, ptidp, hostp, flagp, a_out_ptr,a_out_len, infop) int *where, *ntaskp, *tidp, *ptidp, *hostp, *flagp, *infop; char * a_out_ptr; int a_out_len; { static struct pvmtaskinfo *tip = 0; static int ntask = 0; static int next = 0; int cc; struct pvmtaskinfo *tip2; #ifndef WIN32 char *malloc(); #endif /* if user sets ntaskp to -1 then pvmftasks() will be reset */ if (tip && (*ntaskp == -1)) { free((char*)tip); tip = 0; } if (!tip) { if ((cc = pvm_tasks(*where, &ntask, &tip2)) < 0) { *infop = cc; return; } tip = (struct pvmtaskinfo*)malloc(ntask * sizeof(struct pvmtaskinfo)); BCOPY((char*)tip2, (char*)tip, ntask * sizeof(struct pvmtaskinfo)); next = 0; } if (next < ntask) { *ntaskp = ntask; *tidp = tip[next].ti_tid; *ptidp = tip[next].ti_ptid; *hostp = tip[next].ti_host; *flagp = tip[next].ti_flag; ctofstr(a_out_ptr, a_out_len, tip[next].ti_a_out); *infop = 1; next++; } /* can not return ti_pid without changing interface */ /* users needing this will have to use C */ if (next == ntask) { free((char*)tip); tip = 0; } } ./pvm3/libfpvm/WIN32/Pvmftidtoh.c0100644007401100000360000000054606601533305015637 0ustar kohlgopher /* $Id: Pvmftidtoh.c,v 1.2 1998/09/21 20:27:49 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\include\pvm3.h" #include "..\..\src\pvmwin.h" #else #include "pvm3.h" #endif #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmftidtohost (tid,dtid) #else __fortran PVMFTIDTOHOST (tid, dtid) #endif int *dtid, *tid; { *dtid = pvm_tidtohost(*tid); } ./pvm3/libfpvm/WIN32/Pvmftrecv.c0100644007401100000360000000105006601533314015456 0ustar kohlgopher /* $Id: Pvmftrecv.c,v 1.2 1998/09/21 20:27:56 pvmsrc Exp $ */ #include #ifdef WIN32 #include "..\..\src\pvmwin.h" #include #else #include #endif #include "pvm3.h" #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmftrecv (tid, msgtag, sec, usec, info) #else __fortran PVMFTRECV (tid, msgtag, sec, usec, info) #endif int *tid, *msgtag, *sec, *usec, *info; { struct timeval t; t.tv_sec = *sec; t.tv_usec = *usec; *info = pvm_trecv(*tid, *msgtag, (*sec == -1 ? (struct timeval *)0 : &t)); } ./pvm3/libfpvm/WIN32/Pvmfunpack.c0100644007401100000360000000227307024215246015625 0ustar kohlgopher /* $Id: Pvmfunpack.c,v 1.3 1999/12/10 15:22:14 pvmsrc Exp $ */ #ifdef WIN32 #include "..\..\src\pvmwin.h" #include #endif #include "pvm3.h" #include "pvm_consts.h" void #ifdef IMA_WIN32_WATCOM pvmfunpack (what, vp, cnt, std, info) #else __fortran PVMFUNPACK (what, vp, cnt, std, info) #endif int *what, *cnt, *std, *info; #ifdef __STDC__ void *vp; #else char *vp; #endif { switch( *what ) { case BYTE1: *info = pvm_upkbyte((char*)vp, *cnt, *std); break; case INTEGER2: *info = pvm_upkshort((short*)vp, *cnt, *std); break; case INTEGER4: *info = pvm_upkint((int*)vp, *cnt, *std); break; case INTEGER8: *info = pvm_upklong((long*)vp, *cnt, *std); break; case REAL4: *info = pvm_upkfloat((float*)vp, *cnt, *std); break; case COMPLEX8: *info = pvm_upkcplx((float*)vp, *cnt, *std); break; case REAL8: *info = pvm_upkdouble((double*)vp, *cnt, *std); break; case COMPLEX16: *info = pvm_upkdcplx((double*)vp, *cnt, *std); break; case STRING: *info = pvm_upkbyte((char*)vp, *cnt, *std); break; default: *info = PvmBadParam; break; } } ./pvm3/libfpvm/WIN32/pvm_consts.h0100644007401100000360000000072707024215246015715 0ustar kohlgopher /* $Id: pvm_consts.h,v 1.2 1999/12/10 15:22:14 pvmsrc Exp $ */ #include #include #define MAX_ARCH_NAME 31 #define MAX_EVENT_NAME 31 #define MAX_HOST_NAME 256 #define MAX_PROC_NAME 256 #define MAX_GRP_NAME 31 #define MAX_HOSTS 256 #define MAX_MBOX_NAME 256 #define STRING 0 #define BYTE1 1 #define INTEGER2 2 #define INTEGER4 3 #define REAL4 4 #define COMPLEX8 5 #define REAL8 6 #define COMPLEX16 7 #define INTEGER8 8 ./pvm3/libfpvm/WIN32/watforstr.h0100644007401100000360000000043506354557605015566 0ustar kohlgopher /* $Id: watforstr.h,v 1.1 1997/06/26 21:30:45 pvmsrc Exp $ */ #ifndef WATFORSTR_H #define WATFORSTR_H /* This is the structure the Watcom-Fortran compiler uses to pass strings */ typedef struct WatcomFortranStrDef { char* strP; int len; } WatcomFortranStr; #endif ./pvm3/man/0042755007401100000360000000000010117676455011674 5ustar kohlgopher./pvm3/man/man1/0042755007401100000360000000000010117676455012530 5ustar kohlgopher./pvm3/man/man1/aimk.10100644007401100000360000000602206221603036013510 0ustar kohlgopher.\" $Id: aimk.1,v 1.1 1996/09/23 21:50:22 pvmsrc Exp $ .TH AIMK 1PVM "02 May, 1994" "" "PVM Version 3.4" .SH NAME aimk \- Portable make wrapper script .SH SYNOPSIS .ft B aimk [ \-here ] [ make arguments ] .ft R .SH DESCRIPTION \fIaimk\fR is a wrapper program for \fImake\fR, used to portably select options to build PVM and PVM applications on various machines. Each port of PVM is assigned an \fIarchitecture name\fR. The name is used both during compilation (to conditionally switch in code) and at runtime (to select an executable or host). aimk uses the value of environment variable \fI$PVM_ARCH\fR if it is set, otherwise it calls \fI$PVM_ROOT/pvmgetarch\fR to determine the architecture name. pvmgetarch is a script that sniffs at various parts of the system to determine the correct architecture name. It is updated as new PVM ports are defined, and can be augmented locally. aimk determines the machine architecture and execs make, passing it the architecture and a configuration file along with arguments supplied to aimk. It runs make in a subdirectory to prevent executables from becoming intermixed and to permit overlapping compiles. A different makefile can be placed in each subdirectory or a single makefile, \fIMakefile.aimk\fR, can be shared between architectures. Per-architecture definitions from the $PVM_ROOT/conf directory are appended to the common makefile. aimk calls make is called in one of three ways, depending on what makefiles are present: .IP i. 6 If $PVM_ARCH/Makefile or $PVM_ARCH/makefile exists, change directory to $PVM_ARCH and exec make there: (cd $PVM_ARCH ; make PVM_ARCH=$PVM_ARCH < aimk args >) .IP ii. Else if Makefile.aimk exists, create $PVM_ARCH directory if it doesn't exist, then: (cd $PVM_ARCH ; \\ .br make -f $PVM_ROOT/conf/$PVM_ARCH.def \\ .br -f ../Makefile.aimk PVM_ARCH=$PVM_ARCH < aimk args >) .IP iii. Else just exec make in current directory: make PVM_ARCH=$PVM_ARCH < aimk args > .PP If aimk succeeds in calling make, the exit status is that of make, otherwise it is 1. .SH FLAGS .IP \-here 6 Forces aimk to run make in the current directory, e.g. converts case i. to case iii. .PP .SH EXAMPLES The following Makefile.aimk file builds and installs \fIhello\fR, creating the PVM binary directory if it doesn't exist. It can be run concurrently on machines of different types, sharing the same source directory. .nf LDIR = -L$(PVM_ROOT)/lib/$(PVM_ARCH) PVMLIB = -lpvm3 SDIR = .. BDIR = $(HOME)/pvm3/bin XDIR = $(BDIR)/$(PVM_ARCH) CFLAGS = -g -I$(PVM_ROOT)/include LIBS = $(LDIR) $(PVMLIB) $(ARCHLIB) $(XDIR): - mkdir $(BDIR) $(XDIR) hello: $(SDIR)/hello.c $(XDIR) $(CC) $(CFLAGS) -o $@ $(SDIR)/$@.c $(LIBS) mv $@ $(XDIR) .fi .SH ENVIRONMENT .nf .ta 4 16 $PVM_ROOT Root path of PVM installation. $PVM_ARCH PVM architecture name for machine. .fi .SH FILES .ta 4 40 .nf $PVM_ROOT/lib/aimk The aimk program $PVM_ROOT/conf/$PVM_ARCH.def Arch config file .fi .SH SEE ALSO pvm_intro(1PVM) ./pvm3/man/man1/pvm.10100644007401100000360000000546606221603040013377 0ustar kohlgopher.\" $Id: pvm.1,v 1.1 1996/09/23 21:50:24 pvmsrc Exp $ .TH PVM 1PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm \- PVM version 3 console .SH SYNOPSIS .ft B pvm [ \-options ] [ hostfile ] .ft R .SH DESCRIPTION .I Pvm is a stand alone PVM task which allows the user to interactively query and modify the virtual machine. The console can be started and stopped multiple times on any of the hosts in the virtual machine without affecting PVM or any applications that may be running. .PP When started \fIpvm\fR determines if PVM is already running and if not automatically executes pvmd3 on this host, passing pvmd3 the command line options and host file. Thus PVM need not be running to start the console. Once started the console prints the prompt: .br pvm> The following console commands are available: .nf add hostname(s) \- Add hosts to virtual machine alias \- Define/list command aliases conf \- List virtual machine configuration delete hostname(s) \- Delete hosts from virtual machine echo \- Echo arguments export \- Add environment variables to spawn export list halt \- Stop pvmds help [command] \- Print helpful information about a command id \- Print console task id jobs \- List running jobs kill task\-tid \- Terminate tasks mstat host\-tid \- Show status of hosts ps \-a \- List all PVM tasks pstat task\-tid \- Show status of tasks quit \- Exit console reset \- Kill all tasks setenv \- Display/set environment variables sig signum task \- Send signal to task spawn [opt] a.out \- Spawn task opts are: \-(count) number of tasks, default is 1 \-(host) spawn on host, default is any \-(ARCH) spawn on hosts of ARCH \-? enable debugging \-> redirect task output to console \-> file redirect task output to file \->>file redirect task output append to file trace \- Set/display trace event mask unexport \- Remove environment variables from spawn export list unalias \- Undefine command alias version \- Show libpvm version .fi .PP .I pvm reads $HOME/.pvmrc before reading commands from the tty, so it can be used to customize the console environment, for example: .nf alias ? help alias j jobs setenv PVM_EXPORT DISPLAY # print my id echo new pvm shell id .fi .SH EXAMPLES pvm .br Starts up pvmd3 on the local host or connects to running pvmd3. pvm hostfile .br Starts up console and pvmd3, which inturn reads the host file and adds the listed computers to the virtual machine. .SH SEE ALSO pvm_intro(1PVM), pvmd3(1PVM) ./pvm3/man/man1/PVM.10100644007401100000360000000011307012304103013214 0ustar kohlgopher.\" $Id: PVM.1,v 1.1 1999/11/10 14:59:15 pvmsrc Exp $ .so man1/pvm_intro.1 ./pvm3/man/man1/pvmd.10100644007401100000360000000011006221603042013522 0ustar kohlgopher.\" $Id: pvmd.1,v 1.1 1996/09/23 21:50:26 pvmsrc Exp $ .so man1/pvmd3.1 ./pvm3/man/man1/pvmd3.10100644007401100000360000002465410014452400013623 0ustar kohlgopher.\" $Id: pvmd3.1,v 1.5 2004/02/17 17:53:04 pvmsrc Exp $ .TH PVMD 1PVM "06 May, 1994" "" "PVM Version 3.4" .SH NAME pvmd, pvmd3 \- PVM daemon .SH SYNOPSIS .ft B pvmd [ \-options ] [ hostfile ] .ft R .SH DESCRIPTION .I Pvmd3 is a daemon process which coordinates unix hosts in a virtual machine. One \fIpvmd3\fR must run on each host in the group. They provide the communication and process control functions needed by the user's PVM processes. The daemon can be started manually with a host file argument that will automatically start the remote pvmds. The local and remote pvmds can also be started from the PVM console program \fIpvm\fR. The name of the daemon executable is \fIpvmd3\fR. It is usually started by a shell script, \fI$PVM_ROOT/lib/pvmd\fR. [v3.4 and later] Before running pvmd3, pvmd sources any commands in \fI$HOME/.pvmprofile\fR if this file exists. .SH OPTIONS The following options may be specified on the command line when starting the master pvmd or PVM console: .TP 8 -d\fImask\fR Set pvmd debug mask. Used to debug the pvmd or libpvm (not intended to be used to debug application programs). \fIMask\fR is the \fIsum\fR of the following bits and can be specified in hexadecimal (0x...), octal (0...) or decimal: .RS 12 .PD 0 .TP 8 Bit Information .TP 0x1 Packet routing .TP 0x2 Message routing and entry points .TP 0x4 Task state .TP 0x8 Slave pvmd startup .TP 0x10 Host table updates .TP 0x20 Select loop (below packet layer) .TP 0x40 IP network .TP 0x80 Multiprocessor nodes .TP 0x100 Resource manager interface .TP 0x200 Application (messages with no destination, etc.) .TP 0x400 Wait contexts .TP 0x800 Shared memory operations .TP 0x1000 Semaphores .TP 0x2000 Locks .TP 0x4000 Message route control .PD .RE .TP 8 -n\fIname\fR Specify an alternate hostname for the master pvmd to use. Useful when \fIgethostname()\fR returns a name not assigned to any network interface. .PP The following options are used by the master pvmd when starting slaves and are only of interest to someone writing a \fIhoster\fR. Don't just go using them, now. .TP -s Start pvmd in slave mode. Hostfile cannot be used, five additional parameters must be supplied: master pvmd index, master IP, master MTU, slave pvmd index, and slave IP. .TP -S Same as -s, but slave pvmd doesn't wait for its \fIstdin\fR to be closed after printing its parameters. Used for manual startup. .TP -f Slave doesn't fork after configuration (useful if the slave is to be controlled or monitored by some process). .PP .SH HOST FILE FORMAT Each host in the virtual machine must have an entry in the host file. Lines beginning with a splat ( # ), optionally preceded by whitespace, are ignored. A simple host file might look like: # my first host file .br thud .br fred .br wilma .br barney .br betty This specifies the names of five hosts to be configured in the virtual machine. The master \fIpvmd\fR for a group is started by hand on the localhost, and it starts slaves on each of the remaining hosts using the \fIrsh\fR or \fIrexec\fR command. The master host may appear on any line of the host file. Host names cannot be numeric (IP) addresses, because they are passed to rsh and rexec(), which usually don't accept addresses. The simple format above works fine if you have the same login name on all five machines and the name of the master host in your .rhosts files on the other four. There are several host file options available: .RS .TP 10 lo=NAME Specifies an alternate login name (NAME) to use. .TP so=pw This is necessary when the remote host cannot trust the master. Causes the master pvmd to prompt for a password for the remote host in the tty of the pvmd (note you can't start the master using the console or background it when using this option) you will see: .br Password (honk.cs.utk.edu:manchek): .br you should type your password for the remote host. The startup will then continue as normal. .TP dx=FILE Specifies the path of the pvmd executable. FILE may be a simple filename, an absolute pathname, or a path relative to the user's home directory on the remote host. This is mainly useful to aid in debugging new versions of PVM, but may have other uses. .TP ep=PATH Specifies a path for the \fIpvmd\fR to search for executable program components when spawning a new process. The path may have multiple elements, separated by colons ( : ). .TP wd=PATH Specifies a working directory in which all spawned tasks on this host will execute. .TP sp=VALUE Specifies the relative computational speed of this host compared to other hosts in the configuration. VALUE is an integer in the range [1 - 1000000] .TP bx=PATH Specifies the debugger program path. Note: the environment variable PVM_DEBUGGER can also be set. .TP ip=NAME Specifies an alternate IP address to use for the host. As with host names (when ip= is not used), the address must be a host name, not a numeric address, because it is passed to rsh and rexec(). This option allows one to pick a specific network interface for a machine without using the interface's name. It can also be used to create a virtual machine using symbolic (instead of actual) host names. .TP so=ms Rarely used. Causes the master pvmd to request user to manually perform the startup of a pvmd on a slave host when rsh and rexec network services are disabled but IP connectivity exists. See section "MANUAL STARTUP". .TP id=VMID A new feature in PVM 3.4.4 is the concept of a "Virtual Machine ID". You can now set the VMID to an arbitrary string and this will distinguish and allow multiple virtual machines to run on the same set of hosts under the same userid. (This feature was originally introduced by SGI in their commercial PVM product, and has now been generalized for the public PVM system.) This feature seems to be something that people often want, and the "id=" hostfile option (or $PVM_VMID environment variable) is the cleanest way to provide this functionality, rather than overloading the SHAREDTMP compiler flag and other internals. .sp *** Make Sure *** that you appropriately set the $PVM_VMID environment variable in any shells from which PVM application tasks or the "pvm" console will be run, or else they won't know .I which virtual machine to attach to! .sp By default, all hosts which are added to the virtual machine will inherit the same VMID. If hosts are added to the virtual machine which are running older versions of PVM (prior to 3.4.4), then the VMID will be ignored for those hosts, and hence these machines can only be added to one virtual machine for the given user. The VMID need not be consistent on every host in a virtual machine (although this is not necessarily advisable). .RE .PP A dollar sign ( $ ) in an option introduces a variable name, for example \fI$PVM_ARCH\fR. Names are expanded from environment variables by each pvmd. Each of the flags above has a default value. These are: .RS .PD 0 .TP 8 lo The loginname on the master host. .TP 8 so Nothing .TP 8 dx $PVM_ROOT/lib/pvmd (or environment variable PVM_DPATH) .TP 8 ep $HOME/pvm3/bin/$PVM_ARCH:$PVM_ROOT/bin/$PVM_ARCH .TP 8 wd $HOME .TP 8 sp 1000 .TP 8 bx $PVM_ROOT/lib/debugger .PD .RE .PP You can change these by adding a line with a star ( * ) in the first field followed by the options, for example: * lo=afriend so=pw This sets new default values for 'lo' and 'so' for the remainder of the host file, or until the next '*' line. Options set on the last '*' line also apply to hosts added dynamically using \fIpvm_addhosts()\fR. Host options can be set without starting the hosts automatically. Information on host file lines beginning with '&' is stored, but the hosts are not started until added using \fIpvm_addhosts()\fR. Example host file: .nf # host file for testing on various platforms fonebone refuge # installed in /usr/local here sigi.cs dx=/usr/local/pvm3/lib/pvmd # borrowed accts, "guest", don't trust fonebone * lo=guest so=pw sn666.jrandom.com cubie.misc.edu # really painful one, must start it by hand and share a homedir & igor.firewall.com lo=guest2 so=ms ep=bob/pvm3/bin/$PVM_ARCH .fi .SH MANUAL STARTUP When adding a host with this option set you will see on the tty of the pvmd: .nf .\" [t80040000] ready Fri Aug 27 18:47:47 1993 *** Manual startup *** Login to "honk" and type: $PVM_ROOT/lib/pvmd -S -d0 -nhonk 1 80a9ca95:0cb6 4096 2 80a95c43:0000 Type response: .fi after typing the given command on host \fIhonk\fR, you should see a line like: .nf ddpro<2312> arch ip<80a95c43:0a8e> mtu<4096> .fi type this line on the tty of the master pvmd. You should then see: .nf Thanks .fi and the two pvmds should be able to communicate. Note you can't start the master using the console or background it when using this option. .SH OVERLOADING HOSTS You can force PVM to overload a host (start more than one pvmd on it) by putting a '$' before the host name in the host file. This is not recommended unless you know what you're doing and have a good reason for it. You must build the PVM source with option OVERLOADHOST defined for it to work. You may also need to use the ip= hostfile option to define several names with the same IP address. If two or more hosts in a PVM have the same name, they cannot be identified uniquely. .SH STOPPING PVMD3 .\"When pvmd3 starts up it prints the single line: .\"[t800xxxxxxx] ready .\".PP The preferred method of stopping all the pvmds is to give the \fIhalt\fR command in the PVM console. This kills all PVM tasks, all the remote daemons, the local daemon, and finally the console itself. If the master pvmd is killed manually it should be sent a SIGTERM signal to allow it to kill the remote pvmds and clean up various files. .PP The pvmd can be killed in a manner that leaves the file /tmp/pvmd.\fIuid\fR behind on one or more hosts. \fIUid\fR is the numeric user ID (from /etc/passwd) of the user. This will prevent PVM from restarting on that host. Deletion of this file will fix this problem: .nf rm `( grep $user /etc/passwd || ypmatch $user passwd ) | awk -F: '{print "/tmp/pvmd."$3; exit}'` .fi .SH FILES .ta 4 40 .nf $PVM_ROOT/lib/pvmd PVM daemon startup script $PVM_ROOT/lib/$PVM_ARCH/pvmd3 PVM daemon executable $HOME/.pvmprofile Shell commands read by pvmd before running pvmd3 $HOME/pvm3/bin/$PVM_ARCH Private PVM executable directory $PVM_ROOT/pvm3/bin/$PVM_ARCH System PVM executable directory /tmp/pvmd.\fIuid\fR Pvmd local socket address /tmp/pvml.\fIuid\fR Pvmd runtime error log $HOME/.rhosts File allowing access to a host from other hosts .fi .SH SEE ALSO pvm(1PVM), pvm_intro(1PVM), rhosts(5) ./pvm3/man/man1/pvm_intro.10100644007401100000360000003064307354664013014624 0ustar kohlgopher.\" $Id: pvm_intro.1,v 1.6 2001/09/27 17:55:23 pvmsrc Exp $ .TH PVM_INTRO 1PVM "11 April, 1995" "" "PVM Version 3.4" .SH NAME PVM, pvm_intro \- Parallel Virtual Machine System Version 3 .SH DESCRIPTION .I PVM is a software system that enables a collection of heterogeneous computers to be used as a coherent and flexible concurrent computational resource. The individual computers may be shared- or local-memory multiprocessors, vector supercomputers, specialized graphics engines, or scalar workstations, that may be interconnected by a variety of networks, such as ethernet, FDDI. User programs written in C, C++ or Fortran access PVM through library routines (\fIlibpvm3.a\fR and \fIlibfpvm3.a\fR). Daemon programs (\fIpvmd3\fR) provide communication and process control between computers. .SH MACHINE ARCHITECTURE In the PVM system, machines are assigned a short string to identify their architectures (this includes operating system type as well as CPU type). The types currently predefined in the distribution are: .RS .PD 0 .TP 14 AFX8 Alliant FX/8 .TP ALPHA DEC Alpha/OSF-1 .TP ALPHAMP DEC Alpha/OSF-1 / using shared memory .TP AIX46K IBM/RS6000 / AIX 4.x .TP AIX4MP IBM SMP / shared memory transport / AIX 4.x .TP AIX4SP2 IBM SP-2 / using MPI / AIX 4.x .TP APOLLO HP 300 running Domain/OS .TP ATT AT&T/NCR 3600 running SysVR4 .TP BAL Sequent Balance .TP BFLY BBN Butterfly TC2000 .TP BSD386 80[345]86 running BSDI or BSD386 .TP CM2 Thinking Machines CM-2 Sun front-end .TP CM5 Thinking Machines CM-5 .TP CNVX Convex using IEEE floating-point .TP CNVXN Convex using native f.p. .TP CRAY Cray .TP CRAY2 Cray-2 .TP CRAYSMP Cray S-MP .TP CSPP Convex Exemplar .TP CYGWIN POSIX emulation layer on top of Windows32 .TP DGAV,DGIX Data General Aviion .TP E88K Encore 88000 .TP FREEBSD 80[345]86 running FreeBSD .TP HP300 HP 9000 68000 cpu .TP HPPA HP 9000 PA-Risc .TP HPPAMP HP 9000 PA-Risc / shared memory transport .TP KSR1 Kendall Square .TP I860 Intel RX Hypercube .TP IPSC2 Intel IPSC/2 .TP LINUX 80[345]86 running Linux .TP LINUXALPHA DEC Alpha running Linux .TP LINUXARM Strogarm running Linux .TP LINUXHPPA HP 9000 running Linux .TP LINUXPPC PowerPC running Linux .TP LINUXSPARC Sparc running Linux .TP M88K Motorola M88100 running Real/IX .TP M88K Motorola M88100 running Real/IX .TP MASPAR Maspar .TP MIPS Mips .TP NETBSDALPHA DEC Alpha running NetBSD .TP NETBSDAMIGA Amiga running NetBSD .TP NETBSDARM32 Strongarm running NetBSD .TP NETBSDHP300 HP 300 running NetBSD .TP NETBSDI386 80[345]86 running NetBSD .TP NETBSDM68K Any Motorola 68K running NetBSD .TP NETBSDMAC68K Macintosh running NetBSD .TP NETBSDMIPSEB Mips EB running NetBSD .TP NETBSDMIPSEL Mips EL running NetBSD .TP NETBSDNS32K NS32K running NetBSD .TP NETBSDPMAX DEC Pmax running NetBSD .TP NETBSDPOWERPC PowerPC running NetBSD .TP NETBSDSH3 SH3 running NetBSD .TP NETBSDSPARC Sparc running NetBSD .TP NETBSDSPARC64 Sparc64 running NetBSD .TP NETBSDSUN3 SUN 3 running NetBSD .TP NETBSDVAX Vax running NetBSD .TP NEXT NeXT .TP OS2 OS/2 .TP PGON Intel Paragon .TP PMAX DEC/Mips arch (3100, 5000, etc.) .TP RS6K IBM/RS6000 / AIX 3.x .TP RS6KMP IBM SMP / shared memory transport / AIX 3.x .TP RT IBM/RT .TP SCO 80[345]86 running SCO Unix .TP SGI Silicon Graphics IRIS .TP SGI5 Silicon Graphics IRIS running OS 5.0 .TP SGI6 Silicon Graphics IRIS running OS >= 6.0 .TP SGI64 Silicon Graphics IRIS running 64 bit .TP SGIMP Silicon Graphics IRIS / OS 5.x / using shared memory .TP SGIMP6 Silicon Graphics IRIS / OS 6.x / using shared memory .TP SGIMP64 Silicon Graphics IRIS / 64 bit / using shared memory .TP SP2MPI IBM SP-2 / using MPI / AIX 3.x .TP SUN3 Sun 3 .TP SUN4 Sun 4, 4c, sparc, etc. .TP SUN4SOL2 Sun 4 running Solaris 2.x .TP SUNMP Sun 4 / using shared memory / Solaris 2.x .TP SX3 NEC SX-3 .TP SYMM Sequent Symmetry .TP TITN Stardent Titan .TP U370 IBM 3090 running AIX .TP UTS2 Amdahl running UTS .TP UVAX DEC/Microvax .TP UWARE Uware .TP UXPM Fujitsu running UXP/M .TP VCM2 Thinking Machines CM-2 Vax front-end .TP WIN32 Windows 95/98/NT .TP X86SOL2 80[345]86 running Solaris 2.x .PD .RE .\".SH INSTALLING .SH ENVIRONMENT VARIABLES The following environment variables are read by PVM and may be set in order to customize your PVM environment. To set them, you can add commands to your \fI.cshrc\fR or \fI.profile\fR or equivalent shell startup file. See the manual page for the shell you normally use for information about how to do this. You can also include an appropriate shell startup file stub to set PVM environment variables and to add PVM directories to your execution path. Inert the matching stub file, pvm3/lib/cshrc.stub, pvm3/lib/kshrc.stub or pvm3/lib/bashrc.stub, after your declaration of PVM_ROOT in your shell startup file. For \fIcsh\fR users: Note that setting them in \fI.login\fR does not have the same effect. The .login script file is only read when you are actually logging in, whereas .cshrc is read every time csh starts up. PVM needs to have environment variables set when it starts a slave pvmd with "rsh host pvmd ...", so they must be set in .cshrc. For those using a shell that doesn't always read a startup script (e.g. \fIsh\fR, \fIksh\fR), there is another way to set environment variables for PVM. Before running the PVM executables, the \fIpvm\fR and \fIpvmd\fR startup scripts source any commands in \fI$HOME/.pvmprofile\fR if this file exists. The following environment variables are supported by PVM 3.4.4: .IP PVM_ROOT The path where PVM libraries and system programs are installed, for example /usr/local/pvm3 or $HOME/pvm3. This variable must be set on each host where PVM is used in order for PVM to function. There is no default value. .IP PVM_TMP The path for PVM temporary files, such as the daemon socket file pvmd. and the log file pvml.. Use this environment variable to use a directory other than /tmp (or C:\\TEMP on Win32), or to introduce added security by using a protected subdirectory in /tmp that is owned by your userid and cannot be easily corrupted. .IP PVM_RSH The path to the "rsh" program on your system, if different than that defined in the $PVM_ROOT/conf/$PVM_ARCH.def configuration file. This environment variable can also be used to replace "rsh" with "ssh" for added security. .IP PVM_PATH The execution path to be searched for PVM programs on your system. By default, PVM looks in $HOME/pvm3/bin/$PVM_ARCH and $PVM_ROOT/bin/$PVM_ARCH for your PVM applications. This environment variable does \fBnot\fR override the \fIep=\fR host file option. .IP PVM_WD The working directory for spawned PVM programs on your system. By default, PVM spawns your PVM applications in $HOME, but for convenience in accessing data or input files using relative path names, an alternate working directory can be specified. This environment variable does \fBnot\fR override the \fIwd=\fR host file option. .IP PVM_EXPORT Names of environment variables to export from a parent task to children tasks through \fIpvm_spawn()\fR. Multiple names must be separated by ':'. If PVM_EXPORT is not set, no environment is exported. .IP PVM_DEBUGGER The debugger script to use when \fIpvm_spawn()\fR is called with \fIPvmTaskDebug\fR set. The default is $PVM_ROOT/lib/debugger. .IP PVM_DPATH The path of the pvmd startup script (default is $PVM_ROOT/lib/pvmd). It is overridden by host file option \fIdx=\fR. This variable is useful if you use a shell that doesn't automatically execute a startup script (such as .cshrc) to allow setting PVM_ROOT on slave (added) hosts. If you set it to the absolute or relative path of the pvmd startup script (for example /usr/local/pvm3/lib/pvmd or pvm3/lib/pvmd), the script will automatically set PVM_ROOT. Note that for this to work, you must set it to run the pvmd script, not the pvmd3 executable itself. .IP PVM_WINDPATH This variable serves the same purpose as the PVM_DPATH above, but specifically for Win32 systems. This second environment variable allows for alternate specification of the path to the pvmd3.exe daemon executable using appropriate DOS file path syntax and environment variables (e.g. %PVM_ROOT%\\lib\\WIN32\\pvmd3.exe). .IP PVMHOSTFILE Specifies the path to an optional host file to be used by default when starting PVM. This alleviates the need to manually pass a host file path argument to the "pvm" console or "pvmd" script when starting PVM. .IP PVMDLOGMAX Sets the maximum length of the pvmd error log file. Default value is the PVMDLOGMAX parameter in the source, 1 Mbyte. .IP PVMDDEBUG Sets the default pvmd debugging mask (as does the pvmd -d option). Value can be in hexadecimal (0x...), octal (0...) or decimal. Used to debug the pvmd (not intended to be used to debug application programs). .IP PVMTASKDEBUG Sets the default libpvm debugging mask (as does pvm_setopt(PvmDebugMask, x)). Value can be in hexadecimal (0x...), octal (0...) or decimal. Used to debug libpvm (not intended to be used to debug application programs). .IP PVMTASK Sets additional flag bits for the pvm_spawn() library call. Allows override at run time of flags compiled into the pvm_spawn() calls in PVM application, e.g. to turn on PvmTaskDebug for popping up child tasks in a debugger window. .IP PVMBUFSIZE Sets the size of the shared memory buffers used by libpvm and the pvmd. The default value is 1048576. If your program composes messages longer than this size, you must increase it. .IP PVM_VMID A new feature in PVM 3.4.4 is the concept of a "Virtual Machine ID". You can now set the PVM_VMID environment variable to an arbitrary string (or use the "id=" option in a host file, see man page for pvmd3), and this will distinguish and allow multiple virtual machines to run on the same set of hosts under the same userid. (This feature was originally introduced by SGI in their commercial PVM product, and has now been generalized for the public PVM system.) This feature seems to be something that people often want, and the PVM_VMID is the cleanest way to provide this functionality, rather than overloading the SHAREDTMP compiler flag and other internals. .br Setting the PVM_VMID environment variable before starting PVM will create an encapsulated virtual machine with the given VMID name. By default, all other hosts which are added to this virtual machine will inherit the same VMID. If hosts are added to the virtual machine which are running older versions of PVM (prior to 3.4.4), then the VMID will be ignored for those hosts, and hence these machines can only be added to one virtual machine for the given user. The VMID need not be consistent on every host in a virtual machine (although this is not necessarily advisable), and the VMID can be set for individual hosts using the "id=" host file option (see man page for pvmd3). .PP The following environment variables are used by PVM internally. With the exception of PVM_ARCH, their values should not be modified. This is for information only. .IP PVM_ARCH The PVM architecture name of the host on which it is set, used to distinguish between machines with different executable (a.out) formats. Copies of a program for different architectures are installed in parallel directories named for PVM architectures. .IP PVMSOCK Is passed from pvmd to spawned task, and gives the address of the pvmd local socket. .IP PVMEPID Holds the expected process id of a spawned task exec'd by the pvmd. This is a magic cookie used by the task to identify itself when reconnecting to the pvmd, in order to get the correct task slot. .IP PVMTMASK The libpvm trace mask, passed from the pvmd to spawned tasks. .IP PVMTRCBUF The libpvm trace buffer size. If specified determines the number of bytes of trace event message buffer to be collected before sending to front-end tracer program. .IP PVMTRCOPT The libpvm trace option setting. Determines the level of tracing to be performed on invocations of PVM library calls. .IP PVMINPLACEDELAY Used to optimize sending of PvmDataInPlace messages on MPP systems. .IP PVMKEY PVM uses this value, combined with the process id, to generate shared-memory segment keys. The default value is your numeric uid. PVM automatically detects collisions when generating a key and picks a new key, so it should almost never need to be set explicitly. .PP .SH SEE ALSO aimk(1PVM), pvm(1PVM), pvmd3(1PVM), PVM 3.3 User's Guide and Reference Manual .SH AUTHORS A. L. Beguelin [4,5], J. J. Dongarra [1,2], G. A. Geist [2], W. C. Jiang [1], R. J. Manchek [1], B. K. Moore [1], V. S. Sunderam [3] 1. University of Tennessee, Knoxville TN. .br 2. Oak Ridge National Laboratory, Oak Ridge TN. .br 3. Emory University, Atlanta GA. .br 4. Carnegie Mellon University, Pittsburgh PA .br 5. Pittsburgh Supercomputer Center, Pittsburgh PA ./pvm3/man/man1/pvm_shmd.10100644007401100000360000001126310014452401014400 0ustar kohlgopher.\" $Id: pvm_shmd.1,v 1.2 2004/02/17 17:53:05 pvmsrc Exp $ .TH PVM_SHMD 1PVM "11 March, 1999" "G.E.Fagg" "PVM Version 3.4" .SH NAME pvm_shmd \- PVM shared memory (2) daemon .SH SYNOPSIS .ft B pvm_shmd [ \-options ] [ hostfile ] .ft R .SH DESCRIPTION .I Pvm_shmd is a daemon process which maintains and handles the usage of shared memory resources (memory segments, semaphores, message queues) on a particular PVM host. One \fIpvm_shmd\fR must run on each host in a virtual machine that wants to use the shmd shared memory message passing layer. The \fIshmd\fR message passing layer allows local processes to a host to use shared memory for message passing on that host ONLY. See the shmd directory README for further notes and restrictions. The daemon can be started manually as with any other PVM task. Only one \fIpvm_shmd\fR can be active per host. If the \fIpvm_shmd\fR detects another \fIpvm_shmd\fR it will shutdown. The \fIpvm_shmd\fR can be killed from the PVM console by using the reset command. Local and remote pvm_shmds can also be started from the PVM console program \fIpvm\fR. The name of the daemon executable is \fIpvm_shmd\fR. .SH Shared Resource Usage The \fIpvm_shmd\fR will attempt to create upto \fIMAXSEG\fR shared memory segments of upto \fIMAXPAGES\fR memory pages in size. The size of each memory page is architecture dependent(see getpagesize(3C)). The segments are then numbered 0..N-1 where N is the number of segments created. The first segement (0) has the shared memory control structure placed in its head. This structure allows alien processes to located the other shared memory segments and any required controlling information. The message passing layer, allocates memory from these segments asynchronously without any interaction with the \fIpvm_shmd\fR using semaphores to protect data during updates to any associated structures. For each segment there is an associated page map of which processes have currently locked a page. Each page map for a segment has a separate semaphore protecting it. The semaphores are accessed with the SEM_UNDO flag set so that if a process holding a semaphore should die, the OS (should) reset the semaphore automatically, thus allowing any waiting/blocked processes to continue. The \fIpvm_shmd\fR only maintains the segments and their allocation page map(s). Thus if a process allocated pages in a segment and then exits, it is the \fIpvm_shmd\fR that detects this and then frees the allocated pages. The \fIpvm_shmd\fR can have its status checked at any time by using the \fIpvm_shmd_stat\fR process to kick it into reporting onto either stdio or the pvm log file (pvml.uid) its internal state. The shared memory and all associated processes can be cleared by sending the \fIpvm_shmd\fR a HUP signal. Sending the \fIpvm_shmd\fR a TERM signal will just cause it to clear any shared resources and then exit. The \fIpvm_shmd\fR cannot catch the KILL signal. If the \fIpvm_shmd\fR is killed without clearing all of its shared resources these can be cleared by calling \fIipcfree\fR which resides in the pvm3/lib directory. .PP .SH Message Passing using SHMD The \fIpvm_shmd\fR handles resources that are used by special versions of pvm_psend() and pvm_precv() stored in the libpvmshmd.a library. Thus to use these facilities, applications have to link to this library instead of the usual libpvm3.a library. .PP .SH OPTIONS The following options may be specified on the command line when starting the pvm_shmd: .TP 8 -debug=\fIlevel\fR Sets the \fIpvm_shmd\fR debug level. Used to debug the pvm_shmd or libpvmshmd (not intended to be used to debug application programs). .PP .TP 8 -maxsegs=\fImaxsegs\fR Sets the maximum number of segments that the \fIpvm_shmd\fR can create. This is used to over-ride the compiled in value from shmd.h. Note that the value cannot be above the MAXSEGS in the shmd.h file. .TP 8 -maxpages=\fImaxpages\fR Sets the maximum segment size to \fImaxpages\fR pages of memory. This value cannot be above the compiled value MAXPAGES in shmd.h or the actual OS defined limit. .SH NOTES Remember that \fIpvm_shmd\fR allocated memory from the VM available on the machine. Allocating more segements improves performance as there is less sharing of segments (semaphores for their page maps). Although you must remember to leave some memory available for normal program and OS system usage, as the \fIpvm_shmd\fR allocated memory is *ONLY* used for message passing. .SH FILES .ta 4 40 .nf $PVM_ROOT/lib/$PVM_ARCH/pvm_shmd PVM shared memory daemon executable $PVM_ROOT/shmd/shmd.h Shared Memory hard limits header file /tmp/pvml.\fIuid\fR Pvmd runtime error log .fi .SH SEE ALSO pvm(1PVM), pvmd(1PVM), getpagesize(3C), ipcs(1), msgctl(2), semctl(2), shmctl(2), signal(5) ./pvm3/man/man3/0042755007401100000360000000000010117676455012532 5ustar kohlgopher./pvm3/man/man3/libfpvm.30100644007401100000360000000011406221604140014223 0ustar kohlgopher.\" $Id: libfpvm.3,v 1.1 1996/09/23 22:00:00 pvmsrc Exp $ .so man3/libpvm.3 ./pvm3/man/man3/libpvm.30100644007401100000360000001171106221604142014064 0ustar kohlgopher.\" $Id: libpvm.3,v 1.1 1996/09/23 22:00:02 pvmsrc Exp $ .TH LIBPVM 3PVM "27 June, 1994" "" "PVM Version 3.4" .SH NAME libpvm3.a, libfpvm3.a \- PVM C and Fortran programming libraries .SH DESCRIPTION All PVM applications must be linked with the libpvm library to allow them to communicate with other entities in the PVM system. The base library (libpvm3.a) is written in C and directly supports C and C++ applications. The Fortran library (libfpvm3.a) consists of wrapper functions to convert Fortran calling sequences to C. Applications written in C must be linked with at least the base PVM library, libpvm3.a. Fortran applications must be linked with both libfpvm3.a and libpvm3.a. On some operating systems, PVM programs must be linked with other vendor-provided libraries (containing for example, socket or XDR functions). Programs that use group functions must also be linked with libgpvm3.a. .SH SUBROUTINES The libpvm subroutines can be divided into roughly five classes: .IP Message\ Passing pvm_bufinfo, pvm_freebuf, pvm_getrbuf, pvm_getsbuf, pvm_initsend, pvm_mcast, pvm_mkbuf, pvm_nrecv, pvm_pack, pvm_precv, pvm_probe, pvm_psend, pvm_recv, pvm_recvf, pvm_send, pvm_sendsig, pvm_setmwid, pvm_setrbuf, pvm_setsbuf, pvm_trecv, pvm_unpack .IP Task\ Control pvm_exit, pvm_kill, pvm_mytid, pvm_parent, pvm_pstat, pvm_spawn, pvm_tasks .IP Group\ Library\ Functions pvm_barrier, pvm_bcast, pvm_gather, pvm_getinst, pvm_gettid, pvm_gsize, pvm_joingroup, pvm_lvgroup, pvm_reduce, pvm_scatter .IP Virtual\ Machine\ Control pvm_addhosts, pvm_config, pvm_delhosts, pvm_halt, pvm_mstat, pvm_reg_hoster, pvm_reg_rm, pvm_reg_tasker, pvm_start_pvmd .IP Miscellaneous pvm_archcode, pvm_catchout, pvm_getopt, pvm_hostsync, pvm_notify, pvm_perror, pvm_setopt, pvm_settmask, pvm_tidtohost .PP .SH ERRORS On success, most libpvm functions return the constant PvmOk. The following error conditions can be returned by libpvm functions: .IP PvmAlready The requested operation requires exclusive access, and another was already in progress. .IP PvmBadMsg The received messages has a data format native to another machine, which cannot be decoded by libpvm. .IP PvmBadParam A bad parameter was passed to the function. .IP PvmBadVersion Two PVM components (pvmd and task, two pvmds or two tasks) have incompatible protocol versions and cannot interoperate. Version mismatch .IP PvmCantStart A pvmd could not be started on the local host, or a slave pvmd could not be started on a remote host. .IP PvmDSysErr Some internal mechanism in the pvmd failed during the requested operation. .IP PvmDupEntry The class server already has an entry matching the insert request. [In Version 3.4: Relaced by PvmExists] .IP PvmDupGroup The task has already a member of the group it attempted to join. .IP PvmDupHost An attempt was made to add the same host to a virtual machine more than once, or to add a host already a member of another virtual machine owned by the same user. .IP PvmDenied Operation is refused due to locking, permissions, etc. .IP PvmExists There is already an entry matching the insert request. .IP PvmHostFail A foreign host in the virtual machine failed during the requested operation. .IP PvmMismatch A parameter does not match a corresponding one. .IP PvmNoBuf There is no current message buffer to pack or unpack. .IP PvmNoData The end of a message buffer was reached while trying to unpack data. .IP PvmNoEntry The class server has no entry matching the lookup request. .br [In Version 3.4: Relaced by PvmNotFound] .IP PvmNoFile The named executable does not exist. .IP PvmNoGroup The named group does not exist. .IP PvmNoHost There is no host in the virtual machine with the given name, or the name could not be resolved to an address. .IP PvmNoInst The named group has no member with this instance. .IP PvmNoMem Malloc failed to get memory for libpvm. .IP PvmNoParent This task has no parent task. .IP PvmNoSuchBuf There is no message buffer with the given buffer handle. .IP PvmNoTask No task exists with the given tid. .IP PvmNotFound No entry matching the lookup request was found. .IP PvmNotImpl This libpvm function or option is not implemented. .IP PvmNotInGroup The named group has no such member task. .IP PvmNullGroup A null group name was passed to a function. .IP PvmOutOfRes The requested operation could not be completed due to lack of resources. .IP PvmOverflow A value is too large to be packed or unpacked. .IP PvmSysErr Libpvm could not contact a pvmd on the local host, or the pvmd failed during an operation. .PP .SH FILES .IP $PVM_ROOT/include/fpvm3.h Fortran header file .IP $PVM_ROOT/include/pvm3.h C header file .IP $PVM_ROOT/include/pvmsdpro.h Header file for tasker, hoster and resource manager tasks .IP $PVM_ROOT/include/pvmtev.h Header file for tasks manipulating trace events .IP $PVM_ROOT/lib/$PVM_ARCH/libpvm3.a C (base) library .IP $PVM_ROOT/lib/$PVM_ARCH/libfpvm3.a Fortran wrapper library .IP $PVM_ROOT/lib/$PVM_ARCH/libgpvm3.a Group function library .PP .SH SEE ALSO aimk(1PVM), pvm(1PVM), pvm_intro(1PVM), pvmd3(1PVM) ./pvm3/man/man3/pvm_addhosts.30100644007401100000360000000621106221604231015264 0ustar kohlgopher.\" $Id: pvm_addhosts.3,v 1.1 1996/09/23 22:00:57 pvmsrc Exp $ .TH ADDHOSTS 3PVM "22 February, 1994" "" "PVM Version 3.4" .SH NAME pvm_addhosts \- Add hosts to the virtual machine. .SH SYNOPSIS .nf .ft B C int info = pvm_addhosts( char **hosts, int nhost, int *infos ) .br Fortran call pvmfaddhost( host, info ) .fi .SH PARAMETERS .IP hosts 0.8i An array of strings naming the hosts to be added. Pvmd must already be installed and the user must have an account on the specified hosts. .br .IP nhost Integer specifying the length of array hosts. .br .IP infos Integer array of length .I nhost which returns the status for each host. Values less than zero indicate an error, while positive values are TIDs of the new hosts. .br .IP host Character string naming the host to be added. .br .IP info Integer status code returned by the routine. Values less than \fInhost\fR indicate partial failure, and values less than 1 indicate total failure. .SH DESCRIPTION The routine .I pvm_addhosts adds the computers named in .I hosts to the configuration of computers making up the virtual machine. The names should have the same syntax as lines of a pvmd hostfile (see man page for pvmd3): A hostname followed by options of the form xx=y. .PP If pvm_addhosts is successful, .I info will be equal to .I nhost. Partial success is indicated by 0 < info < nhost, and total failure by info < 1. The array .I infos can be checked to determine which host caused the error. .PP The Fortran routine .I pvmfaddhost adds a single host to the configuration with each call. .I info will be 1 if successful or < 0 if error. .PP .\"If a host fails, the PVM system will continue to function. .\"The user can use this routine to increase the fault tolerance .\"of his PVM application. The status of hosts can be requested by the application using \fIpvm_mstat\fR and \fIpvm_config\fR. If a host fails it will be automatically deleted from the configuration. Using pvm_addhosts a replacement host can be added by the application, however it is the responsibility of the application developer to make his application tolerant of host failure. Another use of this feature would be to add more hosts as they become available, for example on a weekend, or if the application dynamically determines it could use more computational power. .\".PP .\"pvm_addhosts requires the synchronization of the entire virtual machine. .SH EXAMPLES .nf C: static char *hosts[] = { "sparky", "thud.cs.utk.edu", }; info = pvm_addhosts( hosts, 2, infos ); .sp Fortran: CALL PVMFADDHOST( 'azure', INFO ) .fi .SH ERRORS The following error conditions can be returned by \fIpvm_addhosts\fR: .IP PvmBadParam giving an invalid argument value. .IP PvmAlready another task is currently adding hosts. .IP PvmSysErr local pvmd is not responding. .PP and in the \fIinfos\fR vector: .IP PvmBadParam bad hostname syntax. .IP PvmNoHost no such host. .IP PvmCantStart failed to start pvmd on host. .IP PvmDupHost host already configured. .IP PvmBadVersion pvmd protocol versions don't match. .IP PvmOutOfRes PVM has run out of system resources. .PP .SH SEE ALSO pvm_pvmd3(1PVM), pvm_delhosts(3PVM), pvm_start_pvmd(3PVM), pvm_config(3PVM), pvm_mstat(3PVM) ./pvm3/man/man3/pvm_addmhf.30100644007401100000360000000705410014452415014704 0ustar kohlgopher.\" $Id: pvm_addmhf.3,v 1.8 2004/02/17 17:53:17 pvmsrc Exp $ .TH ADDMHF 3PVM "1 April, 1997" "" "PVM Version 3.4" .SH NAME pvm_addmhf, pvm_delmhf \- Install or remove message-handler functions. .SH SYNOPSIS .nf .ft B C int mhid = pvm_addmhf( int src, int tag, int ctx, int (*func)(int mid) ) .br int info = pvm_delmhf( int mhid ) .br Fortran Not available .fi .SH PARAMETERS .IP src The tid of the sender. .IP tag The tag sent with the message. .IP ctx The context sent with the message. .IP func Function to call when message received. .IP mhid Message handler id. .IP info Result code. .IP mid Message buffer identifier for new active receive buffer. .SH DESCRIPTION pvm_addmhf specifies a function that will be called whenever libpvm copies in a message whose header fields of \fIsrc\fR, \fItag\fR, and \fIctx\fR match those provided to pvm_addmhf(). The src and tag fields may be left unspecified (wildcard) by setting to -1. The calling sequence of the message handler function is: .nf int handler( int mid ) .fi Where \fImid\fR is the bufid of the received message. The handler function can be used to unpack and process the received message buffer. PVM automatically saves the current send and receive buffers, so the handler need not worry about interfering with message buffers in the regular program flow. PVM also sets the current receive buffer to the received message (using pvm_setrbuf()) before invoking the message handler, so the message can be unpacked directly. PVM will free this message buffer when the message handler returns, if the handler has not already done so. But, any other message buffers created by the handler routine should be freed using pvm_freebuf() before returning. Note: Operation in the message handler context is somewhat restricted. The function may call some PVM functions, but not others. For example, it may compose and send a reply message as shown: .nf pvm_packf( "%+ %s", PvmDataDefault, "got your message" ); pvm_send( tid, tag ); pvm_freebuf( pvm_setsbuf( 0 ) ); .fi or equivalently: .nf pvm_setsbuf( pvm_mkbuf( PvmDataDefault ) ); pvm_pkstr( "got your message" ); pvm_send( tid, tag ); pvm_freebuf( pvm_setsbuf( 0 ) ); .fi but is not allowed to call certain other PVM communication functions, such as multicast or receive. pvm_addmhf returns the id number of the newly created message handler if successful; this number may be passed to pvm_delmhf to remove the entry. There is no guarantee to the ordering of id values returned by pvm_addmhf, or to the order in which message handlers will be invoked. PvmExists is returned if the handler already exists. pvm_delmhf returns PvmOk if successful. PvmBadParam if pvm_delmhf is passed a negative id value. PvmNotFound if the id value is not found. .SH EXAMPLES .nf /* Print a message when hosts are added to virtual machine */ int hostAdded( int mid ) { int n; pvm_unpackf( "%d", &n ); printf( "*** %d new hosts just added ***\\n", n ); } void main() { int src, tag, ctx; . . . src = -1; tag = 99; ctx = -1; pvm_addmhf( src, tag, ctx, hostAdded ); pvm_notify( PvmHostAdd, 99, -1, (int *) NULL ); . . . } .fi .SH ERRORS The following error conditions can be returned by pvm_addmhf(): .IP PvmExists Can't insert as handler already exists with same (tag, ctx, src) including "wild-cards" (those set to -1) .PP The following error conditions can be returned by pvm_delmhf(): .IP PvmBadParam Invalid (negative) \fImhid\fR passed in. .IP PvmNotFound Message handler \fImhid\fR does not exist. .PP .SH SEE ALSO pvm_setrbuf(3PVM), pvm_setsbuf(3PVM), pvm_freebuf(3PVM) ./pvm3/man/man3/pvm_advise.30100644007401100000360000000367706221604234014746 0ustar kohlgopher.\" $Id: pvm_advise.3,v 1.1 1996/09/23 22:01:00 pvmsrc Exp $ .TH ADVISE 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_advise() \- Controls use of direct task-to-task routing. .br [In Version 3.2: Replaced by pvm_setopt] .SH SYNOPSIS .nf .ft B C int info = pvm_advise( int route ) .br Fortran call pvmfadvise( route, info ) .fi .SH PARAMETERS .IP route 0.8i Integer advising PVM to set up direct task-to-task links. .br .ce .I route options .ta 2.0i 2.5i .nf PvmDontRoute 1 Don't allow direct links to this task PvmAllowDirect 2 Allow but don't request direct links PvmRouteDirect 3 Request direct links .fi .IP info Integer returning error status. .SH DESCRIPTION The routine .I pvm_advise advises PVM on whether or not to set up direct task-to-task links (using TCP) for all subsequent communication. Once a link is established it remains until the application finishes. If a direct link can not be established because one of the two tasks has requested .I PvmDontRoute or because no resources are available, then the default route through the PVM daemons is used. pvm_advise can be called multiple times to selectively establish direct links, but is typically set only once near the beginning of each task. .I PvmAllowDirect is the default advise setting. This setting on task A allows other tasks to set up direct links to A. Once a direct link is established between tasks both tasks will use it for sending messages. pvm_advise returns the error status in .I info. The performance of direct task-to-task links can be up to a factor of two better than the default route. The draw back is a lack of scalability of the direct links. Some versions of UNIX limit the number of links to no more than 30. .SH EXAMPLES .nf C: info = pvm_advise( PvmRouteDirect ); .sp Fortran: CALL PVMFADVISE( PVMROUTEDIRECT, INFO ) .fi .SH ERRORS This error condition can be returned by .I pvm_advise .IP PvmBadParam giving an invalid route value. .PP .SH SEE ALSO pvm_setopt(3PVM) ./pvm3/man/man3/pvm_archcode.30100644007401100000360000000404406654364642015250 0ustar kohlgopher.\" $Id: pvm_archcode.3,v 1.2 1999/01/29 17:02:26 pvmsrc Exp $ .TH ARCHCODE 3PVM "15 March, 1994" "" "PVM Version 3.4" .SH NAME pvm_archcode \- Returns the data representation code for a PVM architecture name. .SH SYNOPSIS .nf .ft B C int cod = pvm_archcode( char *arch ) .br Fortran call pvmfarchcode( arch, cod ) .fi .SH PARAMETERS .IP arch 0.8i Character string containing the architecture name. .br .IP cod Integer returning architecture code. .SH DESCRIPTION The routine .I pvm_archcode returns an integer given an architecture name. The code returned identifies machines with compatible binary data formats. For example, SUN4 and RS6K have the same code, while ALPHA has a different one (because a few datatypes have different sizes). This lets you know when you can get away with using \fIPvmDataRaw\fR instead of \fIPvmDataDefault\fR encoding to pass messages between tasks on two machines. .PP Naturally, you shouldn't assume the values returned by pvm_archcode are etched in stone; the numbers have no intrinsic meaning except that if two different arch names map to the same value then they're compatible. .PP This routine is actually obsolete in the sense that the architecture codes returned are already available in the \fIhi_dsig\fR field of the pvmhostinfo structure returned by pvm_config(), as shown in the below example. The routine is maintained for backwards compatibility only. .SH EXAMPLES .nf C: struct pvmhostinfo *hip; int i; pvm_config((int *)0, (int *)0, &hip); i = pvm_archcode(hip[0].hi_arch); /* or you could just do: i = hip[0].hi_dsig; */ .sp Fortran: CALL PVMFARCHCODE( 'RS6K', k ) .fi .SH ERRORS On success, \fIpvm_archcode\fR returns a positive integer data signature. The following error conditions can be returned as well: .IP PvmBadParam giving an invalid architecture name. .IP PvmNotFound there is no host with the given architecture name in the current virtual machine configuration. .IP PvmSysErr pvmd not responding. .SH SEE ALSO pvm_config(3PVM), pvm_initsend(3PVM), pvm_notify(3PVM), pvm_tasks(3PVM), pvm_tidtohost(3PVM) ./pvm3/man/man3/pvm_barrier.30100644007401100000360000000420506221604236015107 0ustar kohlgopher.\" $Id: pvm_barrier.3,v 1.1 1996/09/23 22:01:02 pvmsrc Exp $ .TH BARRIER 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_barrier \- Blocks the calling process until all processes in a group have called it. .SH SYNOPSIS .nf .ft B C int info = pvm_barrier( char *group, int count ) .br Fortran call pvmfbarrier( group, count, info ) .fi .SH PARAMETERS .IP group 0.8i Character string group name. The group must exist and the calling process must be a member of the group. .br .IP count Integer specifying the number of group members that must call pvm_barrier before they are all released. Though not required, count is expected to be the total number of members of the specified group. .br .IP info Integer status code returned by the routine. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_barrier blocks the calling process until .I count members of the .I group have called pvm_barrier. The count argument is required because processes could be joining the given group after other processes have called pvm_barrier. Thus PVM doesn't know how many group members to wait for at any given instant. Although count can be set less, it is typically the total number of members of the group. So the logical function of the pvm_barrier call is to provide a group synchronization. During any given barrier call all participating group members must call barrier with the same count value. Once a given barrier has been successfully passed, pvm_barrier can be called again by the same group using the same group name. .PP If pvm_barrier is successful, .I info will be 0. If some error occurs then .I info will be < 0. .SH EXAMPLES .nf C: inum = pvm_joingroup( "worker" ); . . info = pvm_barrier( "worker", 5 ); .sp Fortran: CALL PVMFJOINGROUP( "shakers", INUM ) COUNT = 10 CALL PVMFBARRIER( "shakers", COUNT, INFO ) .fi .SH ERRORS These error conditions can be returned by .I pvm_barrier .IP PvmSysErr pvmd was not started or has crashed. .IP PvmBadParam giving a count < 1. .IP PvmNoGroup giving a non-existent group name. .IP PvmNotInGroup calling process is not in specified group. .PP .SH SEE ALSO pvm_joingroup(3PVM) ./pvm3/man/man3/pvm_bcast.30100644007401100000360000000463406221604240014556 0ustar kohlgopher.\" $Id: pvm_bcast.3,v 1.1 1996/09/23 22:01:04 pvmsrc Exp $ .TH BCAST 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_bcast \- Broadcasts the data in the active message buffer to a group of processes. .SH SYNOPSIS .nf .ft B C int info = pvm_bcast( char *group, int msgtag ) .br Fortran call pvmfbcast( group, msgtag, info ) .fi .SH PARAMETERS .IP group 0.8i Character string group name of an existing group. .br .IP msgtag Integer message tag supplied by the user. msgtag should be >= 0. It allows the user's program to distinguish between different kinds of messages . .br .I info integer status code returned by the routine. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_bcast broadcasts a message stored in the active send buffer to all the members of .I group. In PVM 3.2 and later the broadcast message is not sent back to the sender. Any PVM task can call pvm_bcast(), it need not be a member of the group. The content of the message can be distinguished by .I msgtag. If pvm_bcast is successful, .I info will be 0. If some error occurs then .I info will be < 0. .PP pvm_bcast is asynchronous. Computation on the sending processor resumes as soon as the message is safely on its way to the receiving processors. This is in contrast to synchronous communication, during which computation on the sending processor halts until a matching receive is executed by all the receiving processors. .PP pvm_bcast first determines the tids of the group members by checking a group data base. A multicast is performed to these tids. If the group is changed during a broadcast the change will not be reflected in the broadcast. Multicasting is not supported by most multiprocessor vendors. Typically their native calls only support broadcasting to \fIall\fR the user's processes on a multiprocessor. Because of this omission, pvm_bcast may not be an efficient communication method on some multiprocessors. .SH EXAMPLES .nf C: info = pvm_initsend( PvmDataRaw ); info = pvm_pkint( array, 10, 1 ); msgtag = 5 ; info = pvm_bcast( "worker", msgtag ); .sp Fortran: CALL PVMFINITSEND( PVMDEFAULT ) CALL PVMFPKFLOAT( DATA, 100, 1, INFO ) CALL PVMFBCAST( 'worker', 5, INFO ) .fi .SH ERRORS These error conditions can be returned by .I pvm_bcast .IP PvmSysErr pvmd was not started or has crashed. .IP PvmBadParam giving a negative msgtag. .IP PvmNoGroup giving a non-existent group name. .PP .SH SEE ALSO pvm_joingroup(3PVM) ./pvm3/man/man3/pvm_bufinfo.30100644007401100000360000000351306221604241015106 0ustar kohlgopher.\" $Id: pvm_bufinfo.3,v 1.1 1996/09/23 22:01:05 pvmsrc Exp $ .TH BUFINFO 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_bufinfo() \- Returns information about a message buffer. .SH SYNOPSIS .nf .ft B C int info = pvm_bufinfo( int bufid, int *bytes, int *msgtag, int *tid ) .br Fortran call pvmfbufinfo( bufid, bytes, msgtag, tid, info ) .fi .SH PARAMETERS .IP bufid 0.8i Integer specifying a particular message buffer identifier. .br .IP bytes Integer returning the length in bytes of the body of the message. This will be equal to the actual size of the data packed, if \fIPvmDataRaw\fR is used, otherwise it may include pad bytes. .br .IP msgtag Integer returning the message label. Useful when the message was received with a wildcard msgtag. .br .IP tid Integer returning the source of the message. Useful when the message was received with a wildcard tid. .br .IP info Integer status code returned by the routine. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_bufinfo returns information about the requested message buffer. Typically it is used to determine facts about the last received message such as its size or source. pvm_bufinfo is especially useful when an application is able to receive any incoming message, and the action taken depends on the source .I tid and the .I msgtag associated with the message that comes in first. If pvm_bufinfo is successful, .I info will be 0. If some error occurs then .I info will be < 0. .SH EXAMPLES .nf C: bufid = pvm_recv( -1, -1 ); info = pvm_bufinfo( bufid, &bytes, &type, &source ); .sp Fortran: CALL PVMFRECV( -1, -1, BUFID ) CALL PVMFBUFINFO( BUFID, BYTES, TYPE, SOURCE, INFO ) .SH ERRORS This error condition can be returned by .I pvm_bufinfo. .IP PvmNoSuchBuf specified buffer does not exist. .IP PvmBadParam invalid argument .PP .SH SEE ALSO pvm_recv(3PVM) ./pvm3/man/man3/pvm_catchout.30100644007401100000360000000463507354672464015322 0ustar kohlgopher.\" $Id: pvm_catchout.3,v 1.2 2001/09/27 18:51:32 pvmsrc Exp $ .TH CATCHOUT 3PVM "13 July, 1994" "" "PVM Version 3.4" .SH NAME pvm_catchout \- Catch output from child tasks. .SH SYNOPSIS .ft B .nf C #include int info = pvm_catchout( FILE *ff ) .br Fortran call pvmfcatchout( onoff, info ) .fi .SH PARAMETERS .IP ff 0.8i File descriptor on which to write collected output. .br .IP onoff 0.8i Integer parameter. Turns output collection on or off. .br .IP info Integer status code returned by the routine. Values less than zero indicate an error. .SH DESCRIPTION The routine \fIpvm_catchout\fR causes the calling task (the parent) to catch output from any tasks spawned after the call to \fIpvm_catchout\fR. Characters printed on \fIstdout\fR or \fIstderr\fR in children tasks are collected by the pvmds and sent in control messages to the parent task, which tags each line and appends it to the specified file. Output from grandchildren (spawned by children) tasks is also collected, provided the children don't reset their \fIPvmOutputTid\fR. .PP If option \fIPvmShowTids\fR (see \fIpvm_setopt\fR) is true (nonzero), output is printed as shown below, tagged with the task id where the output originated: .nf [txxxxx] BEGIN [txxxxx] (text from child task) [txxxxx] END .fi The output from each task includes one BEGIN line and one END line, with whatever the task prints in between. If PvmShowTids is false, raw output is printed with no additional information. .PP In C, the output file descriptor may be specified. Giving a null pointer turns output collection off for any subsequently spawned child tasks. (Any existing output collection will still proceed at the child tasks, until they exit or change their\fIPvmOutputTid\fR or related settings - see man page for pvm_setopt().) In Fortran, output collection can only be turned on or off (again only for subsequently spawned child tasks), and is always logged to the stdout of the parent task. .PP If \fIpvm_exit\fR is called while output collection is in effect, it will block in order to print all the output, until all tasks sending the given task output have exited. To avoid this, output collection can be turned off by calling pvm_catchout(0) before calling pvm_exit. .PP pvm_catchout() always returns 0. .SH EXAMPLES .nf C: #include pvm_catchout(stdout); .sp Fortran: CALL PVMFCATCHOUT( 1, INFO ) .fi .SH SEE ALSO pvm_exit(3PVM), pvm_setopt(3PVM), pvm_spawn(3PVM) ./pvm3/man/man3/pvm_config.30100644007401100000360000000500506221604244014724 0ustar kohlgopher.\" $Id: pvm_config.3,v 1.1 1996/09/23 22:01:08 pvmsrc Exp $ .TH CONFIG 3PVM "31 August, 1994" "" "PVM Version 3.4" .SH NAME pvm_config \- Returns information about the present virtual machine configuration. .SH SYNOPSIS .nf .ft B C int info = pvm_config( int *nhost, int *narch, struct pvmhostinfo **hostp ) .br struct pvmhostinfo { .br int hi_tid; .br char *hi_name; .br char *hi_arch; .br int hi_speed; .br }; .br Fortran call pvmfconfig( nhost, narch, dtid, name, arch, speed, info ) .fi .SH PARAMETERS .IP nhost 0.8i Integer returning the number of hosts (pvmds) in the virtual machine. .br .IP narch Integer returning the number of different data formats being used. .br .IP hostp Returns pointer to an array of structures which contain information about each host including its pvmd task ID, name, architecture, and relative speed. .br .IP dtid Integer returning pvmd task ID for host .br .IP name Character string returning name of host .br .IP arch Character string returning architecture name of host .br .IP speed Integer returning relative speed of host. Default value is 1000. .br .IP info Integer status code returned by the routine. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_config returns information about the present virtual machine. The information returned is similar to that available from the console command .I conf. .PP The C function returns information about the entire virtual machine in one call. The Fortran function returns information about one host per call and cycles through all the hosts. Thus, if .I pvmfconfig is called nhost times, the entire virtual machine will be represented. Note that in C the hostp array is allocated and owned by libpvm. It is automatically freed or reused on the next call to pvm_config. Note that in Fortran the reported value of nhost and the host configuration do not change until the function resets at the end of a complete cycle. The user can reset pvmfconfig() at any time by calling it with .I nhost = -1. If pvm_config is successful, .I info will be 0. If some error occurs then .I info will be < 0. .SH EXAMPLES .nf C: struct pvmhostinfo *hostp; int i, nhost, narch; info = pvm_config( &nhost, &narch, &hostp ); for (i = 0; i < nhost; i++) printf("%s\\n", hostp[i].hi_name); .sp Fortran: Do i=1, NHOST CALL PVMFCONFIG( NHOST,NARCH,DTID(i),HOST(i),ARCH(i),SPEED(i),INFO ) Enddo .fi .SH ERRORS The following error condition can be returned by .I pvm_config .IP PvmSysErr pvmd not responding. .PP .SH SEE ALSO pvm_tasks(3PVM) ./pvm3/man/man3/pvm_delete.30100644007401100000360000000151506227476436014743 0ustar kohlgopher.\" $Id: pvm_delete.3,v 1.2 1996/10/11 17:00:14 pvmsrc Exp $ .TH DELETE 3PVM "27 June, 1994" "" "PVM Version 3.4" .SH NAME pvm_delete \- delete data from pvmd database .br [In Version 3.4: Relaced by pvm_delinfo] .SH SYNOPSIS .nf .ft B C int cc = pvm_delete( char *name, int index ) .br Fortran Not available .fi .SH PARAMETERS .IP name 0.8i The class name, a null-terminated string. .IP index 0.8i The class index, >= 0. .SH DESCRIPTION See pvm_insert(3PVM) for a description of this database. \fIpvm_delete\fR deletes entry from the database. .\".SH EXAMPLES .SH ERRORS If successful, pvm_delete returns PvmOk, otherwise it returns a negative error code: .IP PvmBadParam giving an invalid argument value. .IP PvmNoEntry the requested pair does not exist. .PP .SH SEE ALSO pvm_insert(3PVM), pvm_lookup(3PVM) ./pvm3/man/man3/pvm_delhosts.30100644007401100000360000000423606430122561015310 0ustar kohlgopher.\" $Id: pvm_delhosts.3,v 1.2 1997/11/05 16:57:21 pvmsrc Exp $ .TH DELHOSTS 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_delhosts \- Deletes hosts from the virtual machine. .SH SYNOPSIS .nf .ft B C int info = pvm_delhosts( char **hosts, int nhost, int *infos ) .br Fortran call pvmfdelhost( host, info ) .fi .SH PARAMETERS .IP hosts 0.8i An array of pointers to character strings containing the names of the machines to be deleted. .br .IP nhost Integer specifying the number of hosts to be deleted. .br .IP infos Integer array of length .I nhost which contains the status code returned by the routine for the individual hosts. Values less than zero indicate an error. .br .IP host Character string containing the name of the machine to be deleted. .br .IP info Integer status code returned by the routine. Values less than nhost indicate partial failure, values less than 1 indicate total failure. .SH DESCRIPTION The routine .I pvm_delhosts deletes the computers pointed to in .I hosts from the existing configuration of computers making up the virtual machine. All PVM processes and the pvmd running on these computers are killed as the computer is deleted. If pvm_delhosts is successful, .I info will be .I nhost. Partial success is indicated by 1<= info < nhost, and total failure by info < 1. The array .I infos can be checked to determine which host caused the error. .PP The Fortran routine .I pvmfdelhost deletes a single host from the configuration with each call. .PP If a host fails, the PVM system will continue to function and will automatically delete this host from the virtual machine. An application can be notified of a host failure by calling pvm_notify. It is still the responsibility of the application developer to make his application tolerant of host failure. .SH EXAMPLES .nf C: static char *hosts[] = { "sparky", "thud.cs.utk.edu", }; int status[2]; info = pvm_delhosts( hosts, 2, status ); .sp Fortran: CALL PVMFDELHOST( 'azure', INFO ) .SH ERRORS These error conditions can be returned by .I pvm_delhosts .IP PvmBadParam giving an invalid argument value. .IP PvmSysErr local pvmd not responding. .PP .SH SEE ALSO pvm_addhosts(3PVM), pvm_notify(3PVM) ./pvm3/man/man3/pvm_delinfo.30100644007401100000360000000012506227476531015111 0ustar kohlgopher.\" $Id: pvm_delinfo.3,v 1.1 1996/10/11 17:01:13 pvmsrc Exp $ .so man3/pvm_putinfo.3 ./pvm3/man/man3/pvm_delmhf.30100644007401100000360000000012306221604247014715 0ustar kohlgopher.\" $Id: pvm_delmhf.3,v 1.1 1996/09/23 22:01:11 pvmsrc Exp $ .so man3/pvm_addmhf.3 ./pvm3/man/man3/pvm_exit.30100644007401100000360000000165206221604251014432 0ustar kohlgopher.\" $Id: pvm_exit.3,v 1.1 1996/09/23 22:01:13 pvmsrc Exp $ .TH EXIT 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_exit \- Tells the local pvmd that this process is leaving PVM. .SH SYNOPSIS .nf .ft B C int info = pvm_exit( void ) .br Fortran call pvmfexit( info ) .fi .SH PARAMETERS .IP info 0.8i Integer status code returned by the routine. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_exit tells the local pvmd that this process is leaving PVM. This routine does not kill the process, which can continue to perform tasks just like any other serial process. .PP pvm_exit should be called by all PVM processes before they stop or exit for good. It \fImust\fR be called by processes that were not started with pvm_spawn. .SH EXAMPLES .nf C: /* Program done */ pvm_exit(); exit(); .sp Fortran: CALL PVMFEXIT(INFO) STOP .fi .SH ERRORS .IP PvmSysErr pvmd not responding .PP .SH SEE ALSO ./pvm3/man/man3/pvm_export.30100644007401100000360000000231006313337366015006 0ustar kohlgopher.\" $Id: pvm_export.3,v 1.2 1997/03/17 22:00:22 pvmsrc Exp $ .TH EXPORT 3PVM "15 May, 1996" .SH NAME pvm_export, pvm_unexport \- Mark environment variables to export through spawn .SH SYNOPSIS .nf .ft B C int cc = pvm_export( char *name ) int cc = pvm_unexport( char *name ) .br Fortran Not available .fi .SH PARAMETERS .IP name 0.8i Name of an environment variable to add to or delete from export list. .SH DESCRIPTION The routines .I pvm_export and .I pvm_unexport are provided for convenience in editing environment variable .I PVM_EXPORT, while maintaining the colon-separated list syntax it requires. The variable can be modified by other means, and at the same time by the pvm_export functions. .PP pvm_export checks to see if a name is already in PVM_EXPORT before including it, and exporting a name more than once is not considered an error. Likewise, pvm_unexport will not complain if you specify a name not in PVM_EXPORT. .SH EXAMPLES .nf C: /* PVM_EXPORT=SHELL:HOME */ pvm_export("DISPLAY"); pvm_export("TERM"); pvm_unexport("HOME"); /* PVM_EXPORT=SHELL:DISPLAY:TERM */ .fi .SH ERRORS No error conditions are currently returned by pvm_export and pvm_unexport. .SH SEE ALSO pvm(1PVM) pvm_spawn(3PVM) ./pvm3/man/man3/pvmfaddhost.30100644007401100000360000000012606221604326015114 0ustar kohlgopher.\" $Id: pvmfaddhost.3,v 1.1 1996/09/23 22:01:58 pvmsrc Exp $ .so man3/pvm_addhosts.3 ./pvm3/man/man3/pvmfaddmhf.30100644007401100000360000000002606320304141014700 0ustar kohlgopher.so man3/pvm_addmhf.3 ./pvm3/man/man3/pvmfadvise.30100644007401100000360000000012306221604327014737 0ustar kohlgopher.\" $Id: pvmfadvise.3,v 1.1 1996/09/23 22:01:59 pvmsrc Exp $ .so man3/pvm_advise.3 ./pvm3/man/man3/pvmfarchcode.30100644007401100000360000000012706221604330015232 0ustar kohlgopher.\" $Id: pvmfarchcode.3,v 1.1 1996/09/23 22:02:00 pvmsrc Exp $ .so man3/pvm_archcode.3 ./pvm3/man/man3/pvmfbarrier.30100644007401100000360000000012506221604366015117 0ustar kohlgopher.\" $Id: pvmfbarrier.3,v 1.1 1996/09/23 22:02:30 pvmsrc Exp $ .so man3/pvm_barrier.3 ./pvm3/man/man3/pvmfbcast.30100644007401100000360000000012106221604367014562 0ustar kohlgopher.\" $Id: pvmfbcast.3,v 1.1 1996/09/23 22:02:31 pvmsrc Exp $ .so man3/pvm_bcast.3 ./pvm3/man/man3/pvmfbufinfo.30100644007401100000360000000012506221604370015114 0ustar kohlgopher.\" $Id: pvmfbufinfo.3,v 1.1 1996/09/23 22:02:32 pvmsrc Exp $ .so man3/pvm_bufinfo.3 ./pvm3/man/man3/pvmfcatchout.30100644007401100000360000000012706221604371015301 0ustar kohlgopher.\" $Id: pvmfcatchout.3,v 1.1 1996/09/23 22:02:33 pvmsrc Exp $ .so man3/pvm_catchout.3 ./pvm3/man/man3/pvmfconfig.30100644007401100000360000000012306221604372014731 0ustar kohlgopher.\" $Id: pvmfconfig.3,v 1.1 1996/09/23 22:02:34 pvmsrc Exp $ .so man3/pvm_config.3 ./pvm3/man/man3/pvmfdelhost.30100644007401100000360000000012606221604474015134 0ustar kohlgopher.\" $Id: pvmfdelhost.3,v 1.1 1996/09/23 22:03:40 pvmsrc Exp $ .so man3/pvm_delhosts.3 ./pvm3/man/man3/pvmfdelinfo.30100644007401100000360000000002706320231370015101 0ustar kohlgopher.so man3/pvm_putinfo.3 ./pvm3/man/man3/pvmfdelmhf.30100644007401100000360000000002606320304142014715 0ustar kohlgopher.so man3/pvm_addmhf.3 ./pvm3/man/man3/pvmfexit.30100644007401100000360000000011706221604475014444 0ustar kohlgopher.\" $Id: pvmfexit.3,v 1.1 1996/09/23 22:03:41 pvmsrc Exp $ .so man3/pvm_exit.3 ./pvm3/man/man3/pvmffreebuf.30100644007401100000360000000012506221604476015111 0ustar kohlgopher.\" $Id: pvmffreebuf.3,v 1.1 1996/09/23 22:03:42 pvmsrc Exp $ .so man3/pvm_freebuf.3 ./pvm3/man/man3/pvmffreecontext.30100644007401100000360000000013406326677312016026 0ustar kohlgopher.\" $Id: pvmffreecontext.3,v 1.1 1997/04/21 14:50:50 pvmsrc Exp $ .so man3/pvm_newcontext.3 ./pvm3/man/man3/pvmffrzgrp.30100644007401100000360000000013006221604500014765 0ustar kohlgopher.\" $Id: pvmffrzgrp.3,v 1.1 1996/09/23 22:03:44 pvmsrc Exp $ .so man3/pvm_freezegroup.3 ./pvm3/man/man3/pvmfgather.30100644007401100000360000000012306221604501014730 0ustar kohlgopher.\" $Id: pvmfgather.3,v 1.1 1996/09/23 22:03:45 pvmsrc Exp $ .so man3/pvm_gather.3 ./pvm3/man/man3/pvmfgetcontext.30100644007401100000360000000013306326677314015665 0ustar kohlgopher.\" $Id: pvmfgetcontext.3,v 1.1 1997/04/21 14:50:52 pvmsrc Exp $ .so man3/pvm_newcontext.3 ./pvm3/man/man3/pvmfgetinst.30100644007401100000360000000012506221604502015136 0ustar kohlgopher.\" $Id: pvmfgetinst.3,v 1.1 1996/09/23 22:03:46 pvmsrc Exp $ .so man3/pvm_getinst.3 ./pvm3/man/man3/pvmfgetmboxinfo.30100644007401100000360000000013006325420143016000 0ustar kohlgopher.\"$Id: pvmfgetmboxinfo.3,v 1.1 1997/04/17 13:06:43 pvmsrc Exp $ .so man3/pvm_putinfo.3 ./pvm3/man/man3/pvmfgetopt.30100644007401100000360000000012306221604505014764 0ustar kohlgopher.\" $Id: pvmfgetopt.3,v 1.1 1996/09/23 22:03:49 pvmsrc Exp $ .so man3/pvm_getopt.3 ./pvm3/man/man3/pvmfgetrbuf.30100644007401100000360000000012506221604506015123 0ustar kohlgopher.\" $Id: pvmfgetrbuf.3,v 1.1 1996/09/23 22:03:50 pvmsrc Exp $ .so man3/pvm_getrbuf.3 ./pvm3/man/man3/pvmfgetsbuf.30100644007401100000360000000012506221604507015125 0ustar kohlgopher.\" $Id: pvmfgetsbuf.3,v 1.1 1996/09/23 22:03:51 pvmsrc Exp $ .so man3/pvm_getsbuf.3 ./pvm3/man/man3/pvmfgettid.30100644007401100000360000000012306221604511014737 0ustar kohlgopher.\" $Id: pvmfgettid.3,v 1.1 1996/09/23 22:03:53 pvmsrc Exp $ .so man3/pvm_gettid.3 ./pvm3/man/man3/pvmfgsize.30100644007401100000360000000012106221604512014577 0ustar kohlgopher.\" $Id: pvmfgsize.3,v 1.1 1996/09/23 22:03:54 pvmsrc Exp $ .so man3/pvm_gsize.3 ./pvm3/man/man3/pvmfhalt.30100644007401100000360000000011706221604514014415 0ustar kohlgopher.\" $Id: pvmfhalt.3,v 1.1 1996/09/23 22:03:56 pvmsrc Exp $ .so man3/pvm_halt.3 ./pvm3/man/man3/pvmfhostsync.30100644007401100000360000000012706221604516015342 0ustar kohlgopher.\" $Id: pvmfhostsync.3,v 1.1 1996/09/23 22:03:58 pvmsrc Exp $ .so man3/pvm_hostsync.3 ./pvm3/man/man3/pvmfinitsend.30100644007401100000360000000012706221605011015274 0ustar kohlgopher.\" $Id: pvmfinitsend.3,v 1.1 1996/09/23 22:07:05 pvmsrc Exp $ .so man3/pvm_initsend.3 ./pvm3/man/man3/pvmfjoingrp.30100644007401100000360000000012706221605013015131 0ustar kohlgopher.\" $Id: pvmfjoingrp.3,v 1.1 1996/09/23 22:07:07 pvmsrc Exp $ .so man3/pvm_joingroup.3 ./pvm3/man/man3/pvmfkill.30100644007401100000360000000011706221605014014414 0ustar kohlgopher.\" $Id: pvmfkill.3,v 1.1 1996/09/23 22:07:08 pvmsrc Exp $ .so man3/pvm_kill.3 ./pvm3/man/man3/pvmflvgrp.30100644007401100000360000000012306221605015014611 0ustar kohlgopher.\" $Id: pvmflvgrp.3,v 1.1 1996/09/23 22:07:09 pvmsrc Exp $ .so man3/pvm_lvgroup.3 ./pvm3/man/man3/pvmfmcast.30100644007401100000360000000012106221605017014566 0ustar kohlgopher.\" $Id: pvmfmcast.3,v 1.1 1996/09/23 22:07:11 pvmsrc Exp $ .so man3/pvm_mcast.3 ./pvm3/man/man3/pvmfmkbuf.30100644007401100000360000000012106221605020014555 0ustar kohlgopher.\" $Id: pvmfmkbuf.3,v 1.1 1996/09/23 22:07:12 pvmsrc Exp $ .so man3/pvm_mkbuf.3 ./pvm3/man/man3/pvmfmstat.30100644007401100000360000000012106221605021014602 0ustar kohlgopher.\" $Id: pvmfmstat.3,v 1.1 1996/09/23 22:07:13 pvmsrc Exp $ .so man3/pvm_mstat.3 ./pvm3/man/man3/pvmfmytid.30100644007401100000360000000012106221605022014601 0ustar kohlgopher.\" $Id: pvmfmytid.3,v 1.1 1996/09/23 22:07:14 pvmsrc Exp $ .so man3/pvm_mytid.3 ./pvm3/man/man3/pvmfnewcontext.30100644007401100000360000000013306326677310015673 0ustar kohlgopher.\" $Id: pvmfnewcontext.3,v 1.1 1997/04/21 14:50:48 pvmsrc Exp $ .so man3/pvm_newcontext.3 ./pvm3/man/man3/pvmfnotify.30100644007401100000360000000012306221605024014767 0ustar kohlgopher.\" $Id: pvmfnotify.3,v 1.1 1996/09/23 22:07:16 pvmsrc Exp $ .so man3/pvm_notify.3 ./pvm3/man/man3/pvmfnrecv.30100644007401100000360000000012106221605025014573 0ustar kohlgopher.\" $Id: pvmfnrecv.3,v 1.1 1996/09/23 22:07:17 pvmsrc Exp $ .so man3/pvm_nrecv.3 ./pvm3/man/man3/pvmfpack.30100644007401100000360000000011706221605026014402 0ustar kohlgopher.\" $Id: pvmfpack.3,v 1.1 1996/09/23 22:07:18 pvmsrc Exp $ .so man3/pvm_pack.3 ./pvm3/man/man3/pvmfparent.30100644007401100000360000000012306221605027014753 0ustar kohlgopher.\" $Id: pvmfparent.3,v 1.1 1996/09/23 22:07:19 pvmsrc Exp $ .so man3/pvm_parent.3 ./pvm3/man/man3/pvmfperror.30100644007401100000360000000012306221605031014766 0ustar kohlgopher.\" $Id: pvmfperror.3,v 1.1 1996/09/23 22:07:21 pvmsrc Exp $ .so man3/pvm_perror.3 ./pvm3/man/man3/pvmfpkmesg.30100644007401100000360000000012306221605032014744 0ustar kohlgopher.\" $Id: pvmfpkmesg.3,v 1.1 1996/09/23 22:07:22 pvmsrc Exp $ .so man3/pvm_pkmesg.3 ./pvm3/man/man3/pvmfpkmesgbody.30100644007401100000360000000012706221605033015627 0ustar kohlgopher.\" $Id: pvmfpkmesgbody.3,v 1.1 1996/09/23 22:07:23 pvmsrc Exp $ .so man3/pvm_pkmesg.3 ./pvm3/man/man3/pvmfprecv.30100644007401100000360000000012106221605034014575 0ustar kohlgopher.\" $Id: pvmfprecv.3,v 1.1 1996/09/23 22:07:24 pvmsrc Exp $ .so man3/pvm_precv.3 ./pvm3/man/man3/pvmfprobe.30100644007401100000360000000012106221605036014567 0ustar kohlgopher.\" $Id: pvmfprobe.3,v 1.1 1996/09/23 22:07:26 pvmsrc Exp $ .so man3/pvm_probe.3 ./pvm3/man/man3/pvmfpsend.30100644007401100000360000000012106221605037014572 0ustar kohlgopher.\" $Id: pvmfpsend.3,v 1.1 1996/09/23 22:07:27 pvmsrc Exp $ .so man3/pvm_psend.3 ./pvm3/man/man3/pvmfpstat.30100644007401100000360000000012106221605040014606 0ustar kohlgopher.\" $Id: pvmfpstat.3,v 1.1 1996/09/23 22:07:28 pvmsrc Exp $ .so man3/pvm_pstat.3 ./pvm3/man/man3/pvmfputinfo.30100644007401100000360000000002706320231366015152 0ustar kohlgopher.so man3/pvm_putinfo.3 ./pvm3/man/man3/pvmfrecv.30100644007401100000360000000011706221605041014420 0ustar kohlgopher.\" $Id: pvmfrecv.3,v 1.1 1996/09/23 22:07:29 pvmsrc Exp $ .so man3/pvm_recv.3 ./pvm3/man/man3/pvmfrecvinfo.30100644007401100000360000000002706320231373015277 0ustar kohlgopher.so man3/pvm_putinfo.3 ./pvm3/man/man3/pvmfreduce.30100644007401100000360000000012306221605042014726 0ustar kohlgopher.\" $Id: pvmfreduce.3,v 1.1 1996/09/23 22:07:30 pvmsrc Exp $ .so man3/pvm_reduce.3 ./pvm3/man/man3/pvm_freebuf.30100644007401100000360000000425206221604254015101 0ustar kohlgopher.\" $Id: pvm_freebuf.3,v 1.1 1996/09/23 22:01:16 pvmsrc Exp $ .TH FREEBUF 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_freebuf \- Disposes of a message buffer. .SH SYNOPSIS .nf .ft B C int info = pvm_freebuf( int bufid ) .br Fortran call pvmffreebuf( bufid, info ) .fi .SH PARAMETERS .IP bufid 0.8i Integer message buffer identifier. .br .IP info Integer status code returned by the routine. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_freebuf frees the memory associated with the message buffer identified by .I bufid. Message buffers are created by pvm_mkbuf, pvm_initsend, and pvm_recv. If pvm_freebuf is successful, .I info will be 0. If some error occurs then .I info will be < 0. .PP pvm_freebuf can be called for a send buffer created by pvm_mkbuf after the message has been sent and is no longer needed. .PP Receive buffers typically do not have to be freed unless they have been saved in the course of using multiple buffers. But pvm_freebuf can be used to destroy receive buffers as well. So messages that arrive but are no longer needed can be destroyed so they will not consume buffer space. .PP Typically multiple send and receive buffers are not needed and the user can simply use the pvm_initsend routine to reset the default send buffer. .PP There are several cases where multiple buffers are useful. One example where multiple message buffers are needed involves libraries or graphical interfaces that use PVM and interact with a running PVM application but do not want to interfere with the application's own communication. .PP When multiple buffers are used they generally are made and freed for each message that is packed. In fact, pvm_initsend simply does a pvm_freebuf followed by a pvm_mkbuf for the default buffer. .SH EXAMPLES .nf C: bufid = pvm_mkbuf( PvmDataDefault ); : info = pvm_freebuf( bufid ); .sp Fortran: CALL PVMFMKBUF( PVMDEFAULT, BUFID ) : CALL PVMFFREEBUF( BUFID, INFO ) .fi .SH ERRORS These error conditions can be returned by .I pvm_freebuf .IP PvmBadParam giving an invalid argument value. .IP PvmNoSuchBuf giving an invalid bufid value. .PP .SH SEE ALSO pvm_mkbuf(3PVM), pvm_initsend(3PVM), pvm_recv(3PVM) ./pvm3/man/man3/pvm_freecontext.30100644007401100000360000000013406322753062016010 0ustar kohlgopher.\" $Id: pvm_freecontext.3,v 1.1 1997/04/09 17:47:30 pvmsrc Exp $ .so man3/pvm_newcontext.3 ./pvm3/man/man3/pvm_freezegroup.30100644007401100000360000000544206221604255016023 0ustar kohlgopher.\" $Id: pvm_freezegroup.3,v 1.1 1996/09/23 22:01:17 pvmsrc Exp $ .TH FREEZEGROUP 3PVM "16 March 1995" "" "PVM Version 3.4" .SH NAME pvm_freezegroup \- Freezes dynamic group membership and caches info locally .SH SYNOPSIS .nf .ft B C int info = pvm_freezegroup( char *group , int size) .br Fortran call pvmffreezegroup( group, size, info ) .fi .SH PARAMETERS .IP group 0.8i Character string group name of an existing group. .br .IP size Size of the group when it is frozen .IP info size of group on success. Values less than 0 indicate and error. .SH DESCRIPTION The routine .I pvm_freezegroup makes a dynamic group named .I group static. The group information is then "cached" by all group members. pvm_freezegroup is a synchronizing routine and must be called by all group members to complete. .I size indicates the size the dynamic group should be when made static. A value of -1 indicates that the current size of the group should be used. .I info returns error information. .PP Once a dynamic group has been frozen with .I pvm_freezegroup , all subsequent operations that can be satisfied with local data use the locally held information. For processes that are outside of the group, the first group call, e.g., pvm_bcast(), will cause the static group information to be copied to the calling process. Subsequent operations then use the local information. Barriers are still arbitrated by the group server. .PP Group members should call \fI pvm_lvgroup \fR to leave the group and free any allocated structures that hold the group information. Processes not in the group may call \fI pvm_lvgroup \fR to free any locally allocated structures. In this case, an error code of PvmNotInGroup or PvmNoGroup will be returned to the caller. Barrier are always arbitrated by the group server, even if the group has been made static with \fIpvm_freezegroup\fR. If a process leaves a static group while other process are waiting at a barrier, then \fIPvmNoGroup\fR is returned to all processes waiting at the barrier. Future barrier calls with the defunct static group, return the same error. .SH EXAMPLES .nf C: inum = pvm_joingroup("worker"); info = pvm_freezegroup( "worker", size ); .sp Fortran: CALL PVMFJOINGROUP('group2', inum) CALL PVMFFREEZEGROUP( 'group2', size, info ) .fi .SH ERRORS These error conditions can be returned by .I pvm_freezegroup .IP PvmSysErr pvmd was not started or has crashed. .IP PvmBadParam giving a NULL group name. .IP PvmDupGroup trying to freeze a group that is already frozen. .IP PvmNotInGroup trying to freeze a group that you are not in. .PP .SH BUGS There is no way to unfreeze a group. Processes are not notified if a frozen group becomes invalid. Having a non-member process call pvm_lvgroup to free structures is a bit strange. .SH SEE ALSO pvm_barrier(3PVM), pvm_lvgroup(3PVM) ./pvm3/man/man3/pvmfscatter.30100644007401100000360000000012506221605044015130 0ustar kohlgopher.\" $Id: pvmfscatter.3,v 1.1 1996/09/23 22:07:32 pvmsrc Exp $ .so man3/pvm_scatter.3 ./pvm3/man/man3/pvmfsend.30100644007401100000360000000011706221605045014416 0ustar kohlgopher.\" $Id: pvmfsend.3,v 1.1 1996/09/23 22:07:33 pvmsrc Exp $ .so man3/pvm_send.3 ./pvm3/man/man3/pvmfsendsig.30100644007401100000360000000012506221605046015121 0ustar kohlgopher.\" $Id: pvmfsendsig.3,v 1.1 1996/09/23 22:07:34 pvmsrc Exp $ .so man3/pvm_sendsig.3 ./pvm3/man/man3/pvmfserror.30100644007401100000360000000012306221605050014772 0ustar kohlgopher.\" $Id: pvmfserror.3,v 1.1 1996/09/23 22:07:36 pvmsrc Exp $ .so man3/pvm_serror.3 ./pvm3/man/man3/pvmfsetcontext.30100644007401100000360000000013306326677311015676 0ustar kohlgopher.\" $Id: pvmfsetcontext.3,v 1.1 1997/04/21 14:50:49 pvmsrc Exp $ .so man3/pvm_newcontext.3 ./pvm3/man/man3/pvmfsetopt.30100644007401100000360000000012306221605052014776 0ustar kohlgopher.\" $Id: pvmfsetopt.3,v 1.1 1996/09/23 22:07:38 pvmsrc Exp $ .so man3/pvm_setopt.3 ./pvm3/man/man3/pvmfsetrbuf.30100644007401100000360000000012506221605053015135 0ustar kohlgopher.\" $Id: pvmfsetrbuf.3,v 1.1 1996/09/23 22:07:39 pvmsrc Exp $ .so man3/pvm_setrbuf.3 ./pvm3/man/man3/pvmfsetsbuf.30100644007401100000360000000012506221605055015140 0ustar kohlgopher.\" $Id: pvmfsetsbuf.3,v 1.1 1996/09/23 22:07:41 pvmsrc Exp $ .so man3/pvm_setsbuf.3 ./pvm3/man/man3/pvmfsiblings.30100644007401100000360000000012706354544444015314 0ustar kohlgopher.\" $Id: pvmfsiblings.3,v 1.1 1997/06/26 19:55:16 pvmsrc Exp $ .so man3/pvm_siblings.3 ./pvm3/man/man3/pvmfspawn.30100644007401100000360000000012106221605056014612 0ustar kohlgopher.\" $Id: pvmfspawn.3,v 1.1 1996/09/23 22:07:42 pvmsrc Exp $ .so man3/pvm_spawn.3 ./pvm3/man/man3/pvmfstartpvmd.30100644007401100000360000000013206221605057015511 0ustar kohlgopher.\" $Id: pvmfstartpvmd.3,v 1.1 1996/09/23 22:07:43 pvmsrc Exp $ .so man3/pvm_start_pvmd.3 ./pvm3/man/man3/pvmftasks.30100644007401100000360000000012106221605060014602 0ustar kohlgopher.\" $Id: pvmftasks.3,v 1.1 1996/09/23 22:07:44 pvmsrc Exp $ .so man3/pvm_tasks.3 ./pvm3/man/man3/pvmftidtoh.30100644007401100000360000000012606221605062014757 0ustar kohlgopher.\" $Id: pvmftidtoh.3,v 1.1 1996/09/23 22:07:46 pvmsrc Exp $ .so man3/pvm_tidtohost.3 ./pvm3/man/man3/pvmftrecv.30100644007401100000360000000012106221605063014603 0ustar kohlgopher.\" $Id: pvmftrecv.3,v 1.1 1996/09/23 22:07:47 pvmsrc Exp $ .so man3/pvm_trecv.3 ./pvm3/man/man3/pvmfunpack.30100644007401100000360000000012306221605064014744 0ustar kohlgopher.\" $Id: pvmfunpack.3,v 1.1 1996/09/23 22:07:48 pvmsrc Exp $ .so man3/pvm_unpack.3 ./pvm3/man/man3/pvmfupkmesg.30100644007401100000360000000012406221605065015140 0ustar kohlgopher.\" $Id: pvmfupkmesg.3,v 1.1 1996/09/23 22:07:49 pvmsrc Exp $ .so man3/pvm_pkmesg.3 ./pvm3/man/man3/pvm_gather.30100644007401100000360000000751506221604256014744 0ustar kohlgopher.\" $Id: pvm_gather.3,v 1.1 1996/09/23 22:01:18 pvmsrc Exp $ .TH GATHER 3PVM "21 April, 1994" "" "PVM Version 3.4" .SH NAME pvm_gather \- A specified member of the group receives messages from each member of the group and gathers these messages into a single array. .SH SYNOPSIS .nf .ft B C int info = pvm_gather( void *result, void *data, .br int count, int datatype, int msgtag, .br char *group, int rootginst) .br Fortran call pvmfgather(result, data, count, datatype, .br msgtag, group, rootginst, info) .fi .SH PARAMETERS .IP result 0.8i On the root this is a pointer to the starting address of an array .I datatype of local values which are to be accumulated from the members of the group. If n if the number of members in the group, then this array of .I datatype should be of length at least n*\fIcount\fR. This argument is meaningful only on the root. .br .IP data For each group member this is a pointer to the starting address of an array of length .I count of .I datatype which will be sent to the specified root member of the group. .br .IP count Integer specifying the number of elements of .I datatype to be sent by each member of the group to the root. .br .IP datatype Integer specifying the type of the entries in the result and data arrays. (See below for defined types.) .IP msgtag Integer message tag supplied by the user. msgtag should be >= 0. It allows the user's program to distinguish between different kinds of messages. .br .IP group Character string group name of an existing group. .br .IP rootginst Integer instance number of group member who performs the gather of the messages from the members of the group. .br .IP info Integer status code returned by the routine. Values less than zero indicate an error. .SH DESCRIPTION .I pvm_gather() performs a send of messages from each member of the group to the specified root member of the group. All group members must call pvm_gather(), each sends its array .I data of length .I count of .I datatype to the root which accumulates these messages into its .I result array. It is as if the root receives .I count elements of .I datatype from the ith member of the group and places these values in its .I result array starting with offset i*\fIcount\fR from the beginning of the .I result array. The root task is identified by its instance number in the group. .PP C and Fortran defined .I datatypes are: .nf C datatypes FORTRAN datatypes ----------------------------------- PVM_BYTE BYTE1 PVM_SHORT INTEGER2 PVM_INT INTEGER4 PVM_FLOAT REAL4 PVM_CPLX COMPLEX8 PVM_DOUBLE REAL8 PVM_DCPLX COMPLEX16 PVM_LONG .fi .PP In using the scatter and gather routines, keep in mind that C stores multidimensional arrays in row order, typically starting with an initial index of 0; whereas, Fortran stores arrays in column order, typically starting with an offset of 1. .PP Note: pvm_gather() does not block. If a task calls pvm_gather and then leaves the group before the root has called pvm_gather an error may occur. .PP The current algorithm is very simple and robust. A future implementation may make more efficient use of the architecture to allow greater parallelism. .SH EXAMPLES .nf C: info = pvm_gather(&getmatrix, &myrow, 10, PVM_INT, msgtag, "workers", rootginst); .sp Fortran: CALL PVMFGATHER(GETMATRIX, MYCOLUMN, COUNT, INTEGER4, & MTAG, 'workers', ROOT, INFO) .fi .SH ERRORS These error conditions can be returned by .I pvm_gather .IP PvmNoInst Calling task is not in the group .IP PvmBadParam The datatype specified is not appropriate .IP PvmSysErr Pvm system error .PP .SH SEE ALSO pvm_bcast(3PVM), pvm_barrier(3PVM), pvm_psend(3PVM) ./pvm3/man/man3/pvm_getcontext.30100644007401100000360000000013306322753063015646 0ustar kohlgopher.\" $Id: pvm_getcontext.3,v 1.1 1997/04/09 17:47:31 pvmsrc Exp $ .so man3/pvm_newcontext.3 ./pvm3/man/man3/pvm_getfds.30100644007401100000360000000446006221604261014736 0ustar kohlgopher.\" $Id: pvm_getfds.3,v 1.1 1996/09/23 22:01:21 pvmsrc Exp $ .TH GETFDS 3PVM "22 Nov, 1994" "" "PVM Version 3.4" .SH NAME pvm_getfds \- Get file descriptors in use by PVM. .SH SYNOPSIS .nf .ft B C int nfds = pvm_getfds( int **fds ) .br Fortran Not Available .fi .SH PARAMETERS .IP fds 0.8i Returns integer array of file descriptors. .SH DESCRIPTION A PVM task uses sockets to communicate between libpvm and other tasks or the pvmd. It is sometimes useful to know the file descriptor numbers of the sockets in order to wait from input from either PVM messages or an external source. For example, the PVM console waits on both keyboard input and notify messages. Input can be multiplexed by polling all sources, but this wastes cpu cycles. Instead, the select() system call can be used to wait until one or more sources of input are ready. If it completes successfully, pvm_getfds returns the number of sockets in use, and the file descriptor numbers in an array (allocated and freed by libpvm). At least one socket always exists (from task to pvmd), and its descriptor is always fds[0]. The number of sockets varies as direct routes are established to other tasks. It can be difficult to track the set of file descriptors if direct routing is enabled, because routes are created as messages are either sent or received. The simplest approach is to disable direct routing. When select returns with a PVM file descriptor ready, a complete message may be ready to be received, or instead only a fragment may be waiting. pvm_nrecv or pvm_probe should be used test without blocking. .SH RESTRICTIONS pvm_getfds is only available when running PVM on a Unix or similar system. .SH EXAMPLES The following program fragment waits until either keyboard input is available, or a PVM message has arrived. .nf int *d; fd_set r; pvm_setopt(PvmRoute, PvmDontRoute); pvm_getfds(&d); FD_ZERO(&r); FD_SET(0, &r); FD_SET(d[0], &r); while (1) { if (select(d[0] + 1, &r, (fd_set*)0, (fd_set*)0, (struct timeval*)0) > 0) { if (FD_ISSET(0, &r)) ... /* read keyboard input */ if (FD_ISSET(d[0], &r) && pvm_nrecv(-1, -1) > 0) ... /* got a PVM message */ } } .fi .SH ERRORS The following error condition can be returned by pvm_getfds: .IP PvmSysErr pvmd not responding. .PP .SH SEE ALSO pvm_notify(3PVM), pvm_trecv(3PVM) ./pvm3/man/man3/pvm_getinst.30100644007401100000360000000265606221604262015145 0ustar kohlgopher.\" $Id: pvm_getinst.3,v 1.1 1996/09/23 22:01:22 pvmsrc Exp $ .TH GETINST 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_getinst \- Returns the instance number in a group of a PVM process. .SH SYNOPSIS .nf .ft B C int inum = pvm_getinst( char *group, int tid ) .br Fortran call pvmfgetinst( group, tid, inum ) .fi .SH PARAMETERS .IP group 0.8i Character string group name of an existing group. .br .IP tid Integer task identifier of a PVM process. .br .IP inum Integer instance number returned by the routine. Instance numbers start at 0 and count up. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_getinst takes a group name .I group and a PVM task identifier .I tid and returns the unique instance number that corresponds to the input. It can be called by any task whether in the group or not. If pvm_getinst is successful, .I inum will be >= 0. If some error occurs then .I inum will be < 0. .SH EXAMPLES .nf C: inum = pvm_getinst( "worker", pvm_mytid() ); -------- inum = pvm_getinst( "worker", tid[i] ); .sp Fortran: CALL PVMFGETINST( 'GROUP3', TID, INUM ) .fi .SH ERRORS These error conditions can be returned by .I pvm_getinst .IP PvmSysErr pvmd was not started or has crashed. .IP PvmBadParam giving an invalid tid value. .IP PvmNoGroup giving a non-existent group name. .IP PvmNotInGroup specifying a group in which the tid is not a member. .PP .SH SEE ALSO pvm_joingroup(3PVM), pvm_gettid(3PVM) ./pvm3/man/man3/pvm_getmboxinfo.30100644007401100000360000000013006325420144015772 0ustar kohlgopher.\"$Id: pvm_getmboxinfo.3,v 1.1 1997/04/17 13:06:44 pvmsrc Exp $ .so man3/pvm_putinfo.3 ./pvm3/man/man3/pvm_getmwid.30100644007401100000360000000012506221604265015120 0ustar kohlgopher.\" $Id: pvm_getmwid.3,v 1.1 1996/09/23 22:01:25 pvmsrc Exp $ .so man3/pvm_setmwid.3 ./pvm3/man/man3/pvm_getopt.30100644007401100000360000000430007051106366014762 0ustar kohlgopher.\" $Id: pvm_getopt.3,v 1.2 2000/02/11 22:28:06 pvmsrc Exp $ .TH GETOPT 3PVM "4 April, 1994" "" "PVM Version 3.4" .SH NAME pvm_getopt \- Returns the value of libpvm options. .SH SYNOPSIS .nf .ft B C int val = pvm_getopt( int what ) .br Fortran call pvmfgetopt( what, val ) .fi .SH PARAMETERS .IP what 0.8i Integer defining option to get. One of: .nf PvmRoute 1 Message routing policy PvmDebugMask 2 Libpvm debug mask PvmAutoErr 3 Auto error reporting PvmOutputTid 4 Stdout destination for children PvmOutputCode 5 Output message tag for children PvmTraceTid 6 Trace data destination for children PvmTraceCode 7 Trace message tag for children PvmTraceBuffer 8 Trace buffer size for children PvmTraceOptions 9 Trace collection options for children PvmFragSize 10 Message fragment size PvmResvTids 11 Allow messages to reserved tags and TIDs PvmSelfOutputTid 12 Stdout destination PvmSelfOutputCode 13 Output message tag PvmSelfTraceTid 14 Trace data destination PvmSelfTraceCode 15 Trace message tag PvmSelfTraceBuffer 16 Trace buffer size PvmSelfTraceOptions 17 Trace collection options PvmShowTids 18 pvm_catchout prints task ids with output PvmPollType 19 Message wait policy (shared memory) PvmPollTime 20 Message spinwait duration PvmOutputContext 21 Output message context for children PvmTraceContext 22 Trace message context for children PvmSelfOutputContext 23 Output message context PvmSelfTraceContext 24 Trace message context PvmNoReset 25 Do not kill task on reset .fi .br .IP val Integer returning the value of the option. .SH DESCRIPTION The routine .I pvm_getopt returns the value of the specified option in PVM. For a discussion of options and values, see \fIpvm_setopt\fR. If an error occurs, the PVM error code is returned in place of the option value. .SH EXAMPLES .nf C: val = pvm_getopt( PvmFragSize ); Fortran: CALL PVMFGETOPT( PVMAUTOERR, VAL ) .SH ERRORS This error condition can be returned .IP PvmBadParam giving an invalid value. .PP .SH SEE ALSO pvm_setopt(3PVM) ./pvm3/man/man3/pvm_getrbuf.30100644007401100000360000000136606221604267015130 0ustar kohlgopher.\" $Id: pvm_getrbuf.3,v 1.1 1996/09/23 22:01:27 pvmsrc Exp $ .TH GETRBUF 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_getrbuf \- Returns the message buffer identifier for the active receive buffer. .SH SYNOPSIS .nf .ft B C int bufid = pvm_getrbuf( void ) .br Fortran call pvmfgetrbuf( bufid ) .fi .SH PARAMETERS .IP bufid 0.8i Integer returning message buffer identifier for the active receive buffer. .SH DESCRIPTION The routine .I pvm_getrbuf returns the message buffer identifier .I bufid for the active receive buffer or 0 if there is no current buffer. .SH EXAMPLES .nf C: bufid = pvm_getrbuf(); .sp Fortran: CALL PVMFGETRBUF( BUFID ) .fi .SH ERRORS No error conditions are returned by .I pvm_getrbuf .SH SEE ALSO pvm_getsbuf(3PVM) ./pvm3/man/man3/pvm_getsbuf.30100644007401100000360000000135506221604271015122 0ustar kohlgopher.\" $Id: pvm_getsbuf.3,v 1.1 1996/09/23 22:01:29 pvmsrc Exp $ .TH GETSBUF 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_getsbuf \- Returns the message buffer identifier for the active send buffer. .SH SYNOPSIS .nf .ft B C int bufid = pvm_getsbuf( void ) .br Fortran call pvmfgetsbuf( bufid ) .fi .SH PARAMETERS .IP bufid 0.8i Integer returning message buffer identifier for the active send buffer. .SH DESCRIPTION The routine .I pvm_getsbuf returns the message buffer identifier .I bufid for the active send buffer or 0 if there is no current buffer. .SH EXAMPLES .nf C: bufid = pvm_getsbuf(); .sp Fortran: CALL PVMFGETSBUF( BUFID ) .fi .SH ERRORS No error conditions are returned by .I pvm_getsbuf .SH SEE ALSO pvm_getrbuf(3PVM) ./pvm3/man/man3/pvm_gettid.30100644007401100000360000000235206221604272014742 0ustar kohlgopher.\" $Id: pvm_gettid.3,v 1.1 1996/09/23 22:01:30 pvmsrc Exp $ .TH GETTID 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_gettid \- Returns the tid of the process identified by a group name and instance number. .SH SYNOPSIS .nf .ft B C int tid = pvm_gettid( char *group, int inum ) .br Fortran call pvmfgettid( group, inum, tid ) .fi .SH PARAMETERS .IP group 0.8i Character string that contains the name of an existing group. .br .IP inum Integer instance number of the process in the group. .br .IP tid Integer task identifier returned. .SH DESCRIPTION The routine .I pvm_gettid returns the tid of the PVM process identified by the group name .I group and the instance number .I inum. If pvm_gettid is successful, .I tid will be > 0. If some error occurs then .I tid will be < 0. .SH EXAMPLES .nf C: tid = pvm_gettid("worker",0); .sp Fortran: CALL PVMFGETTID('worker',5,TID) .fi .SH ERRORS These error conditions can be returned by .I pvm_gettid. .IP PvmSysErr Can not contact the local pvmd; most likely it is not running. .IP PvmBadParam Bad Parameter most likely a NULL character string. .IP PvmNoGroup No group exists by that name. .IP PvmNoInst No such instance in the group. .PP .SH SEE ALSO pvm_joingroup(3PVM), pvm_getinst(3PVM) ./pvm3/man/man3/pvm_gettmask.30100644007401100000360000000012706221604273015300 0ustar kohlgopher.\" $Id: pvm_gettmask.3,v 1.1 1996/09/23 22:01:31 pvmsrc Exp $ .so man3/pvm_settmask.3 ./pvm3/man/man3/pvm_gsize.30100644007401100000360000000230206221604274014600 0ustar kohlgopher.\" $Id: pvm_gsize.3,v 1.1 1996/09/23 22:01:32 pvmsrc Exp $ .TH GSIZE 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_gsize \- Returns the number of members presently in the named group. .SH SYNOPSIS .nf .ft B C int size = pvm_gsize( char *group ) .br Fortran call pvmfgsize( group, size ) .fi .SH PARAMETERS .IP group 0.8i Character string group name of an existing group. .br .IP size Integer returning the number of members presently in the group. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_gsize returns the size of the group named .I group. If there is an error .I size will be negative. .PP Since groups can change dynamically in PVM 3.0, this routine can only guarantee to return the instantaneous size of a given group. .\" It is the user's responsibility .\" to make sure the group members are not changing dynamically .\" during the call to pvm_gsize. .SH EXAMPLES .nf C: size = pvm_gsize( "worker" ); .sp Fortran: CALL PVMFGSIZE( 'group2', SIZE ) .fi .SH ERRORS These error conditions can be returned by .I pvm_gsize .IP PvmSysErr pvmd was not started or has crashed. .IP PvmBadParam giving an invalid group name. .PP .SH SEE ALSO pvm_joingroup(3PVM) ./pvm3/man/man3/pvm_halt.30100644007401100000360000000143106221604276014413 0ustar kohlgopher.\" $Id: pvm_halt.3,v 1.1 1996/09/23 22:01:34 pvmsrc Exp $ .TH HALT 3PVM "06 May, 1994" "" "PVM Version 3.4" .SH NAME pvm_halt \- Shuts down the entire PVM system. .SH SYNOPSIS .nf .ft B C int info = pvm_halt( void ) .br Fortran call pvmfhalt( info ) .fi .SH PARAMETERS .br .IP info 0.8i Integer returns the error status. .SH DESCRIPTION The routine .I pvm_halt shuts down the entire PVM system including remote tasks, remote pvmds, the local tasks (including the calling task) and the local pvmd. The task calling pvm_halt() must ignore or catch signal \fISIGTERM\fR or it will be killed along with all the others. .SH ERRORS The following error conditions can be returned .IP PvmSysErr local pvmd is not responding. .PP .SH SEE ALSO pvm_delhosts(3PVM), pvm_kill(3PVM), pvm_exit(3PVM) ./pvm3/man/man3/pvm_hostsync.30100644007401100000360000000333106221604277015337 0ustar kohlgopher.\" $Id: pvm_hostsync.3,v 1.1 1996/09/23 22:01:35 pvmsrc Exp $ .TH HOSTSYNC 3PVM "20 February, 1994" "" "PVM Version 3.4" .SH NAME pvm_hostsync \- Get time-of-day clock from PVM host. .SH SYNOPSIS .nf .ft B .nf C #include .br int info = pvm_hostsync( int host, struct timeval *clk, .br struct timeval *delta ) .br Fortran call pvmfhostsync( host, clksec, clkusec, deltasec, deltausec, info ) .fi .SH PARAMETERS .IP host 0.8i TID of host. .br .IP clk (or \fIclksec\fR and \fIclkusec\fR) Returns time-of-day clock sample from host. .br .IP delta (or \fIdeltasec\fR and \fIdeltausec\fR) Returns difference between local clock and remote host clock. .SH DESCRIPTION \fIpvm_hostsync\fR samples the time-of day clock of a host in the virtual machine and returns both the clock value and the difference between local and remote clocks. .PP To reduce the delta error due to message transit time, local clock samples are taken before and after reading the remote clock. Delta is the difference between the mean local clocks and remote clock. .PP Note that the delta time can be negative. The microseconds field is always normalized to 0..999999, while the sign of the seconds field gives the sign of the delta. For example: .br 3.25 Sec = 3,250000 .br 0 = 0,0 .br -1 uSec = -1,999999 .br -1 Sec = -1,000000 .br -1.1 Sec = -2,999000 .PP In C, if \fIclk\fR or \fIdelta\fR is a null pointer, that parameter is not returned. .SH ERRORS If pvm_hostsync is successful, it returns PvmOk. These error conditions can be returned by .I pvm_hostsync .IP PvmSysErr pvmd not responding. .IP PvmNoHost specified host not in virtual machine. .IP PvmHostFail host is unreachable (and thus possibly failed) .PP .SH SEE ALSO pvm_config(3PVM) ./pvm3/man/man3/pvm_initsend.30100644007401100000360000000477006221604627015311 0ustar kohlgopher.\" $Id: pvm_initsend.3,v 1.1 1996/09/23 22:05:11 pvmsrc Exp $ .TH INITSEND 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_initsend \- Clear default send buffer and specify message encoding. .SH SYNOPSIS .nf .ft B C int bufid = pvm_initsend( int encoding ) .br Fortran call pvmfinitsend( encoding, bufid ) .fi .SH PARAMETERS .IP encoding 0.8i Integer specifying the next message's encoding scheme. .ta 0.5i 2.5i 3.0i .nf Options in C are: Encoding value MEANING PvmDataDefault 0 XDR PvmDataRaw 1 no encoding PvmDataInPlace 2 data left in place Option names are in Fortran are: Encoding value MEANING PVMDEFAULT 0 XDR PVMRAW 1 no encoding PVMINPLACE 2 data left in place .fi .IP bufid Integer returned containing the message buffer identifier. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_initsend clears the send buffer and prepares it for packing a new message. The encoding scheme used for the packing is set by .I encoding. XDR encoding is used by default because PVM can not know if the user is going to add a heterogeneous machine before this message is sent. If the user knows that the next message will only be sent to a machine that understands the native format, then he can use \fIPvmDataRaw\fR encoding and save on encoding costs. .PP PvmDataInPlace encoding specifies that data be left in place during packing. The message buffer only contains the sizes and pointers to the items to be sent. When pvm_send is called the items are copied directly out of the user's memory. This option decreases the number of times a message is copied at the expense of requiring the user to not modify the items between the time they are packed and the time they are sent. .PP If pvm_initsend is successful, then .I bufid will contain the message buffer identifier. If some error occurs then .I bufid will be < 0. .SH RESTRICTIONS PvmDataInPlace allows only dense (stride = 1) data in version 3.3. It cannot be used on shared memory (*MP) architectures; a PvmNotImpl error will occur at send time. .SH EXAMPLES .nf C: bufid = pvm_initsend( PvmDataDefault ); info = pvm_pkint( array, 10, 1 ); msgtag = 3 ; info = pvm_send( tid, msgtag ); .sp Fortran: CALL PVMFINITSEND(PVMRAW, BUFID) CALL PVMFPACK( REAL4, DATA, 100, 1, INFO ) CALL PVMFSEND( TID, 3, INFO ) .fi .SH ERRORS These error conditions can be returned by .I pvm_initsend .IP PvmBadParam giving an invalid encoding value .IP PvmNoMem Malloc has failed. There is not enough memory to create the buffer .PP .SH SEE ALSO pvm_mkbuf(3PVM) ./pvm3/man/man3/pvm_insert.30100644007401100000360000000332206226517200014763 0ustar kohlgopher.\" $Id: pvm_insert.3,v 1.2 1996/10/08 18:33:36 pvmsrc Exp $ .TH INSERT 3PVM "27 June, 1994" "" "PVM Version 3.4" .SH NAME pvm_insert \- store data in pvmd database .br [In Version 3.4: Relaced by pvm_putinfo] .SH SYNOPSIS .nf .ft B C int cc = pvm_insert( char *name, int index, int data ) .br Fortran Not available .fi .SH PARAMETERS .IP name 0.8i The class name, a null-terminated string. .IP index 0.8i The class index, >= 0 or -1 for first available. .IP data 0.8i Data to store in the entry. .SH DESCRIPTION The master pvmd maintains a simple database, which can be used to store values such as tids and make them accessible anywhere within a virtual machine. This is useful when building an application such as the group server, which must advertise its task id so clients can register send messages to register. The database stores integer data, indexed by pairs. The name may be any null-terminated string and the index any non-negative integer. Database entries are grouped by name into classes; index may be specified as -1 to store or retrieve the first available instance in a class. These functions are not part of the group library, but are the underlying mechanism used to implement it. \fIpvm_insert\fR stores data at the given index. If index is -1, the data is stored at the first available index in the named class, starting at 0. .\".SH EXAMPLES .SH ERRORS If successful, pvm_insert returns the index at which the data was stored, otherwise it returns a negative result. The following error conditions can be returned: .IP PvmBadParam giving an invalid argument value. .IP PvmDupEntry the requested pair is already in use. .PP .SH SEE ALSO pvm_delete(3PVM), pvm_lookup(3PVM) ./pvm3/man/man3/pvm_joingroup.30100644007401100000360000000311706221604632015476 0ustar kohlgopher.\" $Id: pvm_joingroup.3,v 1.1 1996/09/23 22:05:14 pvmsrc Exp $ .TH JOINGROUP 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_joingroup \- Enrolls the calling process in a named group. .SH SYNOPSIS .nf .ft B C int inum = pvm_joingroup( char *group ) .br Fortran call pvmfjoingroup( group, inum ) .fi .SH PARAMETERS .IP group 0.8i Character string group name of an existing group. .br .IP inum Integer instance number returned by the routine. Instance numbers start at 0 and count up. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_joingroup enrolls the calling task in the group named .I group and returns the instance number .I inum of this task in this group. If there is an error .I inum will be negative. .PP Instance numbers start at 0 and count up. When using groups a (group, inum) pair uniquely identifies a PVM process. This is consistent with the PVM 2.4 naming schemes. If a task leaves a group by calling pvm_lvgroup and later rejoins the same group, the task is not guaranteed to get the same instance number. PVM attempts to reuse old instance numbers, so when a task joins a group it will get the lowest available instance number. A task can be a member of multiple groups simultaneously. .SH EXAMPLES .nf C: inum = pvm_joingroup( "worker" ); .sp Fortran: CALL PVMFJOINGROUP( 'group2', INUM ) .fi .SH ERRORS These error conditions can be returned by .I pvm_joingroup .IP PvmSysErr pvmd was not started or has crashed. .IP PvmBadParam giving a NULL group name. .IP PvmDupGroup trying to join a group you are already in. .PP .SH SEE ALSO pvm_lvgroup(3PVM) ./pvm3/man/man3/pvm_kill.30100644007401100000360000000235106221604633014415 0ustar kohlgopher.\" $Id: pvm_kill.3,v 1.1 1996/09/23 22:05:15 pvmsrc Exp $ .TH KILL 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_kill \- Terminates a specified PVM process. .SH SYNOPSIS .nf .ft B C int info = pvm_kill( int tid ) .br Fortran call pvmfkill( tid, info ) .fi .SH PARAMETERS .IP tid 0.8i Integer task identifier of the PVM process to be killed (not yourself). .br .IP info Integer status code returned by the routine. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_kill sends a terminate (SIGTERM) signal to the PVM process identified by .I tid. In the case of multiprocessors the terminate signal is replaced with a host dependent method for killing a process. If pvm_kill is successful, .I info will be 0. If some error occurs then .I info will be < 0. .PP pvm_kill is not designed to kill the calling process. To kill yourself in C call pvm_exit() followed by exit(). To kill yourself in Fortran call pvmfexit followed by stop. .SH EXAMPLES .nf C: info = pvm_kill( tid ); .sp Fortran: CALL PVMFKILL( TID, INFO ) .fi .SH ERRORS These error conditions can be returned by .I pvm_kill .IP PvmBadParam giving an invalid tid value. .IP PvmSysErr pvmd not responding. .PP .SH SEE ALSO pvm_exit(3PVM), pvm_halt(3PVM) ./pvm3/man/man3/pvm_lookup.30100644007401100000360000000211106226517201014764 0ustar kohlgopher.\" $Id: pvm_lookup.3,v 1.2 1996/10/08 18:33:37 pvmsrc Exp $ .TH LOOKUP 3PVM "27 June, 1994" "" "PVM Version 3.4" .SH NAME pvm_lookup \- retrieve data from pvmd database .br [In Version 3.4: Relaced by pvm_getinfo] .SH SYNOPSIS .nf .ft B C int cc = pvm_lookup( char *name, int index, int *data ) .br Fortran Not available .fi .SH PARAMETERS .IP name 0.8i The class name, a null-terminated string. .IP index 0.8i The class index, >= 0 or -1 for first available. .IP data 0.8i Returns the data stored in the entry. .SH DESCRIPTION See pvm_insert(3PVM) for a description of this database. \fIpvm_lookup\fR retrieves data stored in the location given by . If index is -1, the data stored at the first existing index in the named class is returned. .\".SH EXAMPLES .SH ERRORS If successful, pvm_lookup returns the index at which the data was stored (>= 0), otherwise it returns a negative error code: .IP PvmBadParam giving an invalid argument value. .IP PvmNoEntry the requested pair does not exist. .PP .SH SEE ALSO pvm_delete(3PVM), pvm_insert(3PVM) ./pvm3/man/man3/pvm_lvgroup.30100644007401100000360000000237306221604636015167 0ustar kohlgopher.\" $Id: pvm_lvgroup.3,v 1.1 1996/09/23 22:05:18 pvmsrc Exp $ .TH LVGROUP 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_lvgroup \- Unenrolls the calling process from a named group. .SH SYNOPSIS .nf .ft B C int info = pvm_lvgroup( char *group ) .br Fortran call pvmflvgroup( group, info ) .fi .SH PARAMETERS .IP group 0.8i Character string group name of an existing group. .br .IP info Integer status code returned by the routine. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_lvgroup unenrolls the calling process from the group named .I group. If there is an error .I info will be negative. .PP If a process leaves a group by calling either pvm_lvgroup or pvm_exit, and later rejoins the same group, the process may be assigned a new instance number. Old instance numbers are reassigned to processes calling pvm_joingroup. .SH EXAMPLES .nf C: info = pvm_lvgroup( "worker" ); .sp Fortran: CALL PVMFLVGROUP( 'group2', INFO ) .fi .SH ERRORS These error conditions can be returned by .I pvm_lvgroup .IP PvmSysErr pvmd not responding. .IP PvmBadParam giving a NULL group name. .IP PvmNoGroup giving a non-existent group name. .IP PvmNotInGroup asking to leave a group you are not a member of. .PP .SH SEE ALSO pvm_joingroup(3PVM) ./pvm3/man/man3/pvm_mcast.30100644007401100000360000000524506221604637014602 0ustar kohlgopher.\" $Id: pvm_mcast.3,v 1.1 1996/09/23 22:05:19 pvmsrc Exp $ .TH MCAST 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_mcast \- Multicasts the data in the active message buffer to a set of tasks. .SH SYNOPSIS .nf .ft B C int info = pvm_mcast( int *tids, int ntask, int msgtag ) .br Fortran call pvmfmcast( ntask, tids, msgtag, info ) .fi .SH PARAMETERS .IP ntask 0.8i Integer specifying the number of tasks to be sent to. .br .IP tids Integer array of length .I ntask containing the task IDs of the tasks to be sent to. .br .IP msgtag Integer message tag supplied by the user. msgtag should be >= 0. It allows the user's program to distinguish between different kinds of messages . .br .IP info Integer status code returned by the routine. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_mcast multicasts a message stored in the active send buffer to .I ntask tasks specified in the .I tids array. The message is not sent to the caller even if listed in the array of tids. The content of the message can be distinguished by .I msgtag. If pvm_mcast is successful, .I info will be 0. If some error occurs then .I info will be < 0. .PP The receiving processes can call either pvm_recv or pvm_nrecv to receive their copy of the multicast. pvm_mcast is asynchronous and based on a minimum spanning tree algorithm between the pvmds. Computation on the sending processor resumes as soon as the message is safely on its way to the receiving processors. This is in contrast to synchronous communication, during which computation on the sending processor halts until the matching receive is executed by the receiving processor. .PP pvm_mcast first determines which other pvmds contain the specified tasks. Then passes the message to these pvmds which in turn distribute the message to their local tasks without further network traffic. .PP Multicasting is not supported by most multiprocessor vendors. Typically their native calls only support broadcasting to {\em all the user's processes on a multiprocessor. Because of this omission, pvm_mcast may not be an efficient communication method on some multiprocessors except in the special case of broadcasting to all PVM processes. .SH EXAMPLES .nf C: info = pvm_initsend( PvmDataRaw ); info = pvm_pkint( array, 10, 1 ); msgtag = 5 ; info = pvm_mcast( tids, ntask, msgtag ); .sp Fortran: CALL PVMFINITSEND(PVMDEFAULT) CALL PVMFPACK( REAL4, DATA, 100, 1, INFO ) CALL PVMFMCAST( NPROC, TIDS, 5, INFO ) .fi .SH ERRORS These error conditions can be returned by .I pvm_mcast .IP PvmBadParam giving a msgtag < 0. .IP PvmSysErr pvmd not responding. .IP PvmNoBuf no send buffer. .PP .SH SEE ALSO pvm_psend(3PVM), pvm_recv(3PVM), pvm_send(3PVM) ./pvm3/man/man3/pvm_mkbuf.30100644007401100000360000000674306221604641014576 0ustar kohlgopher.\" $Id: pvm_mkbuf.3,v 1.1 1996/09/23 22:05:21 pvmsrc Exp $ .TH MKBUF 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_mkbuf \- Creates a new message buffer. .SH SYNOPSIS .nf .ft B C int bufid = pvm_mkbuf( int encoding ) .br Fortran call pvmfmkbuf( encoding, bufid ) .fi .SH PARAMETERS .IP encoding 0.8i Integer specifying the buffer's encoding scheme. .ta 0.5i 2.5i 3.0i .nf Options in C are: Encoding value MEANING PvmDataDefault 0 XDR PvmDataRaw 1 no encoding PvmDataInPlace 2 data left in place Option names in Fortran are: Encoding value MEANING PVMDEFAULT 0 XDR PVMRAW 1 no encoding PVMINPLACE 2 data left in place .fi .IP bufid Integer message buffer identifier returned. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_mkbuf creates a new message buffer and sets its encoding status to .I encoding. If pvm_mkbuf is successful, .I bufid will be the identifier for the new buffer, which can be used as a send buffer. If some error occurs then .I bufid will be < 0. .PP With the default setting XDR encoding is used when packing the message because PVM can not know if the user is going to add a heterogeneous machine before this message is sent. The other options to encoding allow the user to take advantage of knowledge about his virtual machine even when it is heterogeneous. For example, if the user knows that the next message will only be sent to a machine that understands the native format, then he can use \fIPvmDataRaw\fR encoding and save on encoding costs. .PP PvmDataInPlace encoding specifies that data be left in place during packing. The message buffer only contains the sizes and pointers to the items to be sent. When pvm_send is called the items are copied directly out of the user's memory. This option decreases the number of times a message is copied at the expense of requiring the user to not modify the items between the time they are packed and the time they are sent. .PP pvm_mkbuf is required if the user wishes to manage multiple message buffers and should be used in conjunction with pvm_freebuf. pvm_freebuf should be called for a send buffer after a message has been sent and is no longer needed. .PP Receive buffers are created automatically by the pvm_recv and pvm_nrecv routines and do not have to be freed unless they have been explicitly saved with pvm_setrbuf. .PP Typically multiple send and receive buffers are not needed and the user can simply use the pvm_initsend routine to reset the default send buffer. .PP There are several cases where multiple buffers are useful. One example where multiple message buffers are needed involves libraries or graphical interfaces that use PVM and interact with a running PVM application but do not want to interfere with the application's own communication. .PP When multiple buffers are used they generally are made and freed for each message that is packed. .SH RESTRICTIONS PvmDataInPlace allows only dense (stride = 1) data in version 3.3. It cannot be used on shared memory (*MP) architectures; a PvmNotImpl error will occur at send time. .SH EXAMPLES .nf C: bufid = pvm_mkbuf( PvmDataRaw ); /* send message */ info = pvm_freebuf( bufid ); .sp Fortran: CALL PVMFMKBUF(PVMDEFAULT, MBUF) * SEND MESSAGE HERE CALL PVMFFREEBUF( MBUF, INFO ) .fi .SH ERRORS These error conditions can be returned by .I pvm_mkbuf .ta 0.5i 2.0i .nf PvmBadParam giving an invalid encoding value. PvmNoMem Malloc has failed. There is not enough memory to create the buffer .fi .SH SEE ALSO pvm_initsend(3PVM), pvm_freebuf(3PVM) ./pvm3/man/man3/pvm_mstat.30100644007401100000360000000245206221604642014614 0ustar kohlgopher.\" $Id: pvm_mstat.3,v 1.1 1996/09/23 22:05:22 pvmsrc Exp $ .TH MSTAT 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_mstat \- Returns the status of a host in the virtual machine. .SH SYNOPSIS .nf .ft B C int mstat = pvm_mstat( char *host ) .br Fortran call pvmfmstat( host, mstat ) .fi .SH PARAMETERS .IP host 0.8i Character string containing the host name. .br .IP mstat Integer returning machine status: .ta 0.5i 2.5i .nf value MEANING PvmOk host is OK PvmNoHost host is not in virtual machine PvmHostFail host is unreachable (and thus possibly failed) .fi .SH DESCRIPTION The routine .I pvm_mstat returns the status .I mstat of the computer named .I host with respect to running PVM processes. This routine can be used to determine if a particular host has failed and if the virtual machine needs to be reconfigured. The function pvm_notify() can also be used to notify the caller that a host has failed. .SH EXAMPLES .nf C: mstat = pvm_mstat( "msr.ornl.gov" ); .sp Fortran: CALL PVMFMSTAT( 'msr.ornl.gov', MSTAT ) .fi .SH ERRORS These error conditions can be returned by .I pvm_mstat .IP PvmSysErr pvmd not responding. .IP PvmNoHost giving a host name not in the virtual machine. .IP PvmHostFail host is unreachable (and thus possibly failed). .PP .SH SEE ALSO pvm_notify(3PVM), pvm_config(3PVM) ./pvm3/man/man3/pvm_mytid.30100644007401100000360000000315706221604643014616 0ustar kohlgopher.\" $Id: pvm_mytid.3,v 1.1 1996/09/23 22:05:23 pvmsrc Exp $ .TH MYTID 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_mytid \- Returns the \fItid\fR of the calling process. .SH SYNOPSIS .nf .ft B C int tid = pvm_mytid( void ) .br Fortran call pvmfmytid( tid ) .fi .SH PARAMETERS .IP tid 0.8i Integer returning the task identifier of the calling PVM process. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_mytid enrolls this process into PVM on its first call. It also generates a unique .I tid if this process was not created by pvm_spawn. pvm_mytid returns the .I tid of the calling process and can be called multiple times in an application. .PP Any PVM system call (not just pvm_mytid) will enroll a task in PVM if the task is not enrolled before the call. .PP The tid is a 32 bit positive integer created by the local pvmd. The 32 bits are divided into fields that encode various information about this process such as its location in the virtual machine (i.e. local pvmd address), the CPU number in the case where the process is on a multiprocessor, and a process ID field. This information is used by PVM and is not expected to be used by applications. Applications should not attempt to predict or interpret the tid with the exception of calling tidtohost() .PP If PVM has not been started before an application calls pvm_mytid the returned .I tid will be < 0. .SH EXAMPLES .nf C: tid = pvm_mytid( ); .sp Fortran: CALL PVMFMYTID( TID ) .fi .SH ERRORS This error condition can be returned by .I pvm_mytid .IP PvmSysErr pvmd not responding. .PP .SH SEE ALSO pvm_tidtohost(3PVM), pvm_parent(3PVM) ./pvm3/man/man3/pvm_newcontext.30100644007401100000360000000577306327651572015706 0ustar kohlgopher.\" $Id: pvm_newcontext.3,v 1.2 1997/04/24 12:35:06 pvmsrc Exp $ .TH CONTEXT 3PVM "8 April, 1997" "" "PVM Version 3.4" .SH NAME pvm_newcontext \- Request new context. .br pvm_setcontext \- Change context. .br pvm_freecontext \- Free existing context. .br pvm_getcontext \- Get current context. .SH SYNOPSIS .nf .ft B C int ctx = pvm_newcontext( void ) .br int old_ctx = pvm_setcontext( int new_ctx ) .br int info = pvm_freecontext( ctx ) .br int ctx = pvm_getcontext( void ) .br Fortran .br call pvmfnewcontext( ctx ) .br call pvmfsetcontext( new_ctx, old_ctx ) .br call pvmffreecontext( ctx, info ) .br call pvmfgetcontext( ctx ) .br .fi .SH PARAMETERS .IP ctx .br Context value. .IP new_ctx .br New context value. .IP old_ctx .br Prior context value. .IP info .br Result code. .SH DESCRIPTION The context functions provide a system-wide unique context and the means to manipulate this context. Contexts provide the ability for communicating tasks to automatically differentiate messages by the context in which they were sent. Thus a message sent in context A by the sender must be received in context A by the recipient. A sender may send in any context. However, a recipient will not accept a message sent in a context that differs from its own. One such use of contexts is with library routines. Using contexts, library routine inter-communication may be logically seperated from the user's application inter-communication. This will prevent the inadvertent receipt of one another's messages. Spawned tasks inherit the spawn-time context of their parent. Existing PVM applications work unchanged using the default context. pvm_newcontext returns a newly allocated context. However, this new context is not yet active. pvm_setcontext changes the current context from \fIold_ctx\fR to \fInew_ctx\fR. pvm_freecontext frees \fIctx\fR so that it may be reused. Contexts are a system resource that will be exhausted if not recycled. pvm_getcontext returns the current context of the requesting task. .SH EXAMPLES .nf /* parent task with context */ int cc, context0, context1; char buf[25]; context0 = pvm_getcontext(); /* get my current context */ context1 = pvm_newcontext(); /* get a new context */ pvm_setcontext(context1); /* set my context to new context */ printf("My context is: %d", context1); pvm_spawn("child", (char**)0, PvmTaskDefault, "", 1, &tid); cc = pvm_recv(-1, -1); /* receive message from child - in context1 */ pvm_upkstr(buf); printf("%s", buf); pvm_setcontext(context0); /* reset my context to my original context0 */ /* child task with context - child inherits parent's context as default */ int context; int ptid; char buf[25]; ptid = pvm_parent(); context = pvm_getcontext(); /* get my current context */ sprintf(buf, "Greetings from child who's context is: %d.", context); pvm_initsend(PvmDataDefault); pvm_pkstr(buf); pvm_send(ptid, 1); .fi .SH ERRORS Only system resource errors will be returned as the context programs themselves do not generate errors. .PP .SH SEE ALSO ./pvm3/man/man3/pvm_notify.30100644007401100000360000000625607345703153015007 0ustar kohlgopher.\" $Id: pvm_notify.3,v 1.2 2001/09/06 14:21:31 pvmsrc Exp $ .TH NOTIFY 3PVM "31 January, 1994" "" "PVM Version 3.4" .SH NAME pvm_notify \- Request notification of PVM event such as host failure. .SH SYNOPSIS .nf .ft B C int info = pvm_notify( int what, int msgtag, int cnt, int *tids ) .br Fortran call pvmfnotify( what, msgtag, cnt, tids, info ) .fi .SH PARAMETERS .IP what 0.8i Type of event to trigger the notification. Presently one of: .ta 0.5i 2.5i .nf Value Meaning PvmTaskExit Task exits or is killed PvmHostDelete Host is deleted or crashes PvmHostAdd New host is added .fi .IP msgtag Message tag to be used in notification. .br .IP cnt For \fIPvmTaskExit\fR and \fIPvmHostDelete\fR, specifies the length of the \fItids\fR array. For \fIPvmHostAdd\fR, specifies the number of times to notify. .br .IP tids For \fIPvmTaskExit\fR and \fIPvmHostDelete\fR, an array of length .I cnt of task or pvmd TIDs to be notified about. The array is not used with the \fIPvmHostAdd\fR option. .br .IP info Integer status code returned by the routine. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_notify requests PVM to notify the caller on detecting certain events. One or more notify messages (see below) are sent by PVM back to the calling task. The messages have tag \fImsgtag\fR supplied to notify. The notification messages have the following format: .IP PvmTaskExit One notify message for each TID requested. The message body contains a single TID of exited task. .sp .IP PvmHostDelete One notify message for each TID requested. The message body contains a single pvmd-TID of exited pvmd. .sp .IP PvmHostAdd \fIcnt\fR notify messages are sent, one each time the local pvmd's host table is updated. The message body contains an integer length followed by a list of pvmd-TIDs of new pvmds. The counter of \fIPvmHostAdd\fR messages yet to be sent is replaced by successive calls to \fIpvm_notify\fR. Specifying a \fIcnt\fR of -1 turns on \fIPvmHostAdd\fR messages until a future notify; a count of zero disables them. .PP TIDs in the notify messages are packed as integers. .PP The calling task is responsible for receiving messages with the specified tag and taking appropriate action. .PP Future versions of PVM may expand the list of available notification events. .SH EXAMPLES .nf C: info = pvm_notify( PvmTaskExit, 9999, ntask, tids ); .sp Fortran: CALL PVMFNOTIFY( PVMHOSTDELETE, 1111, NUMHOSTS, DTIDS, INFO ) .fi .PP To "cancel" a notify request in PVM, the .I pvm_notify routine can be re-invoked with an additional .I PvmNotifyCancel flag in the .I what argument. The remaining arguments to this cancelling invocation must match the original invocation exactly, aside from the additional .I PvmNotifyCancel which can be added(+) or OR-ed(|) to the .I what argument: .nf pvm_notify( PvmTaskExit, 9999, ntask, tids ); . . . pvm_notify( PvmTaskExit | PvmNotifyCancel, 9999, ntask, tids ); .fi Note that when a notify is cancelled, the notify message is \fIdelivered\fR, as if the given event (i.e. task exit, host add or delete) had occurred. .SH ERRORS .IP PvmSysErr pvmd not responding. .IP PvmBadParam giving an invalid argument value. .PP .SH SEE ALSO pvm_tasks(3PVM), pvm_config(3PVM) ./pvm3/man/man3/pvm_nrecv.30100644007401100000360000000574406221604646014614 0ustar kohlgopher.\" $Id: pvm_nrecv.3,v 1.1 1996/09/23 22:05:26 pvmsrc Exp $ .TH NRECV 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_nrecv \- Non-blocking receive. .SH SYNOPSIS .nf .ft B C int bufid = pvm_nrecv( int tid, int msgtag ) .br Fortran call pvmfnrecv( tid, msgtag, bufid ) .fi .SH PARAMETERS .IP tid 0.8i Integer task identifier of sending process supplied by the user. .br .IP msgtag Integer message tag supplied by the user. msgtag should be >= 0. .br .IP bufid Integer returning the value of the new active receive buffer identifier. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_nrecv checks to see if a message with label .I msgtag has arrived from .I tid. and also clears the current receive buffer if any, If a matching message has arrived pvm_nrecv immediately places the message in a new \fIactive\fR receive buffer, and returns the buffer identifier in .I bufid. .PP If the requested message has not arrived, then pvm_nrecv immediately returns with a 0 in .I bufid. If some error occurs .I bufid will be < 0. .PP A -1 in .I msgtag or .I tid matches anything. This allows the user the following options. If tid = -1 and msgtag is defined by the user, then pvm_nrecv will accept a message from any process which has a matching msgtag. If msgtag = -1 and tid is defined by the user, then pvm_nrecv will accept any message that is sent from process tid. If tid = -1 and msgtag = -1, then pvm_nrecv will accept any message from any process. .PP The PVM model guarantees the following about message order. If task 1 sends message A to task 2, then task 1 sends message B to task 2, message A will arrive at task 2 before message B. Moreover, if both messages arrive before task 2 does a receive, then a wildcard receive will always return message A. .PP pvm_nrecv is non-blocking in the sense that the routine always returns immediately either with the message or with the information that the message has not arrived at the local pvmd yet. pvm_nrecv can be called multiple times to check if a given message has arrived yet. In addition the blocking receive pvm_recv can be called for the same message if the application runs out of work it could do before the data arrives. .PP If pvm_nrecv returns with the message, then the data in the message can be unpacked into the user's memory using the unpack routines. .SH EXAMPLES .nf C: tid = pvm_parent(); msgtag = 4 ; arrived = pvm_nrecv( tid, msgtag ); if ( arrived > 0) info = pvm_upkint( tid_array, 10, 1 ); else /* go do other computing */ .sp Fortran: CALL PVMFNRECV( -1, 4, ARRIVED ) IF ( ARRIVED .gt. 0 ) THEN CALL PVMFUNPACK( INTEGER4, TIDS, 25, 1, INFO ) CALL PVMFUNPACK( REAL8, MATRIX, 100, 100, INFO ) ELSE * GO DO USEFUL WORK ENDIF .fi .SH ERRORS These error conditions can be returned by .I pvm_nrecv. .IP PvmBadParam giving an invalid tid value or msgtag. .IP PvmSysErr pvmd not responding. .PP .SH SEE ALSO pvm_bufinfo(3PVM), pvm_getminfo(3PVM), pvm_recv(3PVM), pvm_unpack(3PVM), pvm_send(3PVM), pvm_mcast(3PVM) ./pvm3/man/man3/pvm_pack.30100644007401100000360000001456606221604647014420 0ustar kohlgopher.\" $Id: pvm_pack.3,v 1.1 1996/09/23 22:05:27 pvmsrc Exp $ .TH PACK 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_pack \- Pack the active message buffer with arrays of prescribed data type. .SH SYNOPSIS .nf .ft B C .br int info = pvm_packf( const char *fmt, ... ) .br int info = pvm_pkbyte( char *xp, int nitem, int stride ) .br int info = pvm_pkcplx( float *cp, int nitem, int stride ) .br int info = pvm_pkdcplx( double *zp, int nitem, int stride ) .br int info = pvm_pkdouble( double *dp, int nitem, int stride ) .br int info = pvm_pkfloat( float *fp, int nitem, int stride ) .br int info = pvm_pkint( int *ip, int nitem, int stride ) .br int info = pvm_pkuint( unsigned int *ip, int nitem, int stride ) .br int info = pvm_pkushort( unsigned short *ip, int nitem, int stride ) .br int info = pvm_pkulong( unsigned long *ip, int nitem, int stride ) .br int info = pvm_pklong( long *ip, int nitem, int stride ) .br int info = pvm_pkshort( short *jp, int nitem, int stride ) .br int info = pvm_pkstr( char *sp ) Fortran .br call pvmfpack( what, xp, nitem, stride, info ) .fi .SH PARAMETERS .IP fmt 0.8i Printf\-like format expression specifying what to pack. (See discussion). .br .IP nitem The total number of \fIitems\fR to be packed (not the number of bytes). .\" For example, if nitem = 5 in pvm_pkdouble, then 5 double precision .\" floating point values will be packed. .br .IP stride The stride to be used when packing the items. For example, if stride = 2 in pvm_pkcplx, then every other complex number will be packed. .br .IP xp Pointer to the beginning of a block of bytes. Can be any data type, but must match the corresponding unpack data type. .br .IP cp Complex array at least nitem*stride items long. .br .IP zp Double precision complex array at least nitem*stride items long. .br .IP dp Double precision real array at least nitem*stride items long. .br .IP fp Real array at least nitem*stride items long. .br .IP ip Integer array at least nitem*stride items long. .br .IP jp Integer*2 array at least nitem*stride items long. .br .IP sp Pointer to a null terminated character string. .br .IP what Integer specifying the type of data being packed. .ta 0.5i 2.0i 2.5i 4.0i .nf \fIwhat\fR options STRING 0 REAL4 4 BYTE1 1 COMPLEX8 5 INTEGER2 2 REAL8 6 INTEGER4 3 COMPLEX16 7 .fi .IP info Integer status code returned by the routine. Values less than zero indicate an error. .SH DESCRIPTION Each of the pvm_pk* routines packs an array of the given data type into the active send buffer. The arguments for each of the routines are a pointer to the first item to be packed, .I nitem which is the total number of items to pack from this array, and .I stride which is the stride to use when packing. .PP An exception is pvm_pkstr() which by definition packs a NULL terminated character string and thus does not need .I nitem or .I stride arguments. The Fortran routine pvmfpack( STRING, ... ) expects .I nitem to be the number of characters in the string and .I stride to be 1. .PP A null string ("") can be packed; this is just a string with no characters before the terminating '\\0'. However, packing a null string pointer, (char *)0, is not allowed. .PP If the packing is successful, .I info will be 0. If some error occurs then .I info will be < 0. .PP A single variable (not an array) can be packed by setting .I nitem = 1 and .I stride = 1. .PP The routine pvm_packf() uses a printf\-like format expression to specify what and how to pack data into the send buffer. All variables are passed as addresses if count and stride are specified otherwise, variables are assumed to be values. A BNF-like description of the format syntax is: .br format : null | init | format fmt .br init : null | '%' '+' .br fmt : '%' count stride modifiers fchar .br fchar : 'c' | 'd' | 'f' | 'x' | 's' .br count : null | [0-9]+ | '*' .br stride : null | '.' ( [0-9]+ | '*' ) .br modifiers : null | modifiers mchar .br mchar : 'h' | 'l' | 'u' Formats: .nf + means initsend - must match an int (how) in the param list. c pack/unpack bytes d integers f float x complex float s string Modifiers: h short (int) l long (int, float, complex float) u unsigned (int) '*' count or stride must match an int in the param list. .fi .PP Future extensions to the .I what argument in pvmfpack will include 64 bit types when XDR encoding of these types is available. Meanwhile users should be aware that precision can be lost when passing data from a 64 bit machine like a Cray to a 32 bit machine like a SPARCstation. As a mnemonic the .I what argument name includes the number of bytes of precision to expect. By setting encoding to PVMRAW (see pvmfinitsend) data can be transferred between two 64 bit machines with full precision even if the PVM configuration is heterogeneous. .PP Messages should be unpacked exactly like they were packed to insure data integrity. Packing integers and unpacking them as floats will often fail because a type encoding will have occurred transferring the data between heterogeneous hosts. Packing 10 integers and 100 floats then trying to unpack only 3 integers and the 100 floats will also fail. .SH EXAMPLES .nf C: info = pvm_initsend( PvmDataDefault ); info = pvm_pkstr( "initial data" ); info = pvm_pkint( &size, 1, 1 ); info = pvm_pkint( array, size, 1 ); info = pvm_pkdouble( matrix, size*size, 1 ); msgtag = 3 ; info = pvm_send( tid, msgtag ); .sp int count, *iarry; double darry[4]; pvm_packf("%+ %d %*d %4lf", PvmDataRaw, count, count, iarry, darry); .sp Fortran: CALL PVMFINITSEND(PVMRAW, INFO) CALL PVMFPACK( INTEGER4, NSIZE, 1, 1, INFO ) CALL PVMFPACK( STRING, 'row 5 of NXN matrix', 19, 1, INFO ) CALL PVMFPACK( REAL8, A(5,1), NSIZE, NSIZE , INFO ) CALL PVMFSEND( TID, MSGTAG, INFO ) .fi .SH WARNINGS Strings cannot be packed when using the PvmDataInPlace encoding, due to limitations in the implementation. Attempting to pack a string using pvm_pkstr or pvm_packf will cause error code PvmNotImpl to be returned. .SH ERRORS .IP PvmNoMem Malloc has failed. Message buffer size has exceeded the available memory on this host. .IP PvmNoBuf There is no active send buffer to pack into. Try calling pvm_initsend before packing message. .IP PvmOverflow Attempt to pack a value too large. E.g. packing an 8-byte long with XDR encoding if the value won't fit into 4 bytes. .PP .SH SEE ALSO pvm_initsend(3PVM), pvm_unpack(3PVM), pvm_send(3PVM), pvm_recv(3PVM), pvm_pkmesg(3PVM) ./pvm3/man/man3/pvm_packf.30100644007401100000360000000012006221604651014536 0ustar kohlgopher.\" $Id: pvm_packf.3,v 1.1 1996/09/23 22:05:29 pvmsrc Exp $ .so man3/pvm_pack.3 ./pvm3/man/man3/pvm_parent.30100644007401100000360000000167706221604652014766 0ustar kohlgopher.\" $Id: pvm_parent.3,v 1.1 1996/09/23 22:05:30 pvmsrc Exp $ .TH PARENT 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_parent \- Returns the tid of the process that spawned the calling process. .SH SYNOPSIS .nf .ft B C int tid = pvm_parent( void ) .br Fortran call pvmfparent( tid ) .fi .SH PARAMETERS .IP tid 0.8i Integer returns the task identifier of the parent of the calling process. If the calling process was not created with pvm_spawn, then tid = PvmNoParent. .SH DESCRIPTION The routine .I pvm_parent returns the .I tid of the process that spawned the calling process. If the calling process was not created with pvm_spawn, then .I tid is set to PvmNoParent. .SH EXAMPLES .nf C: tid = pvm_parent(); .sp Fortran: CALL PVMFPARENT( TID ) .fi .SH ERRORS This error condition can be returned by .I pvm_parent. .IP PvmNoParent The calling process was not created with pvm_spawn. .IP PvmSysErr Can't contact local pvmd. .PP .SH SEE ALSO ./pvm3/man/man3/pvm_perror.30100644007401100000360000000207106221604653014774 0ustar kohlgopher.\" $Id: pvm_perror.3,v 1.1 1996/09/23 22:05:31 pvmsrc Exp $ .TH PERROR 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_perror \- Prints message describing the last error returned by a PVM call. .SH SYNOPSIS .nf .ft B C int info = pvm_perror( char *msg ) .br Fortran call pvmfperror( msg, info ) .fi .SH PARAMETERS .IP msg 0.8i Character string supplied by the user which will be prepended to the error message of the last PVM call. .br .IP info Integer status code returned by the routine. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_perror returns the error message of the last PVM call. The user can use .I msg to add additional information to the error message, for example, its location. .PP Unless redirected, all stdout and stderr messages are placed in the file /tmp/pvml. on the master host. .SH EXAMPLES .nf C: if ( pvm_send( tid, msgtag ) ) pvm_perror(); .sp Fortran: CALL PVMFSEND( TID, MSGTAG ) IF( INFO .LT. 0 ) CALL PVMFPERROR( 'Step 6', INFO ) .fi .SH ERRORS No error condition is returned by .I pvm_perror. ./pvm3/man/man3/pvm_pkbyte.30100644007401100000360000000012106221604656014756 0ustar kohlgopher.\" $Id: pvm_pkbyte.3,v 1.1 1996/09/23 22:05:34 pvmsrc Exp $ .so man3/pvm_pack.3 ./pvm3/man/man3/pvm_pkcplx.30100644007401100000360000000012106221604657014762 0ustar kohlgopher.\" $Id: pvm_pkcplx.3,v 1.1 1996/09/23 22:05:35 pvmsrc Exp $ .so man3/pvm_pack.3 ./pvm3/man/man3/pvm_pkdcplx.30100644007401100000360000000012206221604661015122 0ustar kohlgopher.\" $Id: pvm_pkdcplx.3,v 1.1 1996/09/23 22:05:37 pvmsrc Exp $ .so man3/pvm_pack.3 ./pvm3/man/man3/pvm_pkdouble.30100644007401100000360000000012306221604662015264 0ustar kohlgopher.\" $Id: pvm_pkdouble.3,v 1.1 1996/09/23 22:05:38 pvmsrc Exp $ .so man3/pvm_pack.3 ./pvm3/man/man3/pvm_pkfloat.30100644007401100000360000000012206221604663015117 0ustar kohlgopher.\" $Id: pvm_pkfloat.3,v 1.1 1996/09/23 22:05:39 pvmsrc Exp $ .so man3/pvm_pack.3 ./pvm3/man/man3/pvm_pkint.30100644007401100000360000000012006221604665014604 0ustar kohlgopher.\" $Id: pvm_pkint.3,v 1.1 1996/09/23 22:05:41 pvmsrc Exp $ .so man3/pvm_pack.3 ./pvm3/man/man3/pvm_pklong.30100644007401100000360000000012106221604666014753 0ustar kohlgopher.\" $Id: pvm_pklong.3,v 1.1 1996/09/23 22:05:42 pvmsrc Exp $ .so man3/pvm_pack.3 ./pvm3/man/man3/pvm_pkmesg.30100644007401100000360000000534406221604667014764 0ustar kohlgopher.\" $Id: pvm_pkmesg.3,v 1.1 1996/09/23 22:05:43 pvmsrc Exp $ .TH PKMESG 3PVM "10 February, 1995" "" "PVM Version 3.4" .SH NAME pvm_pkmesg, pvm_pkmesgbody, pvm_upkmesg \- Pack messages into other messages. .SH SYNOPSIS .nf .ft B C int info = pvm_pkmesg( int bufid ) .br int info = pvm_pkmesgbody( int bufid ) .br int newbufid = pvm_upkmesg( ) .br Fortran call pvmfpkmesg( bufid, info ) call pvmfpkmesgbody( bufid, info ) call pvmfupkmesg( bufid, newbufid ) .fi .SH PARAMETERS .IP bufid 1.0i Message buffer to pack. .IP newbufid New message buffer unpacked or result code. .IP info Result code. .SH DESCRIPTION These functions are used to include messages in other messages, as data elements. .I pvm_pkmesg packs the specified message into the current send buffer. The entire body of the message is packed, along with header attributes: .nf length context tag message tag wait identifier encoding checksum source and destination addresses .fi The buffer specified must not be the same as the current send buffer. Multiple messages can be packed into a single message, and packed messages can be mixed with any other data types. .I pvm_upkmesg unpacks a message from the current receive buffer, allocating a new message buffer for it. The body of the newly created message, and header attributes listed above, match the one originally packed using pvm_pkmesg. .I pvm_pkmesgbody is similar to pvm_pkmesg, but packs only the body of the specified message, omitting the header fields. In other words, it splices the messages together (the included message is left unaltered). When calling pvm_pkmesgbody, the encoding types of the two messages must match because the included message body is simply appended to the send buffer. Calls to pvm_pkmesgbody can be mixed with calls to pack any other data types. Note: \fIpvm_upkmesgbody\fR doesn't exist, because PVM doesn't keep track of the boundary between the two messages. .SH EXAMPLES .nf pvm_recv(-1, -1); pvm_initsend(PvmDataDefault); pvm_pkstr("here is the message I received..."); pvm_pkmesg(pvm_getrbuf()); .fi .SH ERRORS The following error conditions can be returned by pvm_pkmesg, pvm_pkmesgbody or pvm_upkmesg: .IP PvmBadParam An invalid value was specified for \fIbufid\fR argument, or bufid is the current send buffer. .IP PvmNoSuchBuf Message buffer \fIbufid\fR doesn't exist. .IP PvmNoMem Libpvm is unable to allocate memory to pack data. .IP PvmNoData The end of the message has been reached, perhaps because pack and unpack calls were mismatched. .IP PvmNoBuf There is no current send (or receive) buffer. .IP PvmMismatch \fIpvm_pkmesgbody\fR was called and the encoding types of \fIbufid\fR and the current send buffer don't match. .PP .SH SEE ALSO pvm_getrbuf(3PVM), pvm_getsbuf(3PVM), pvm_pack(3PVM), ./pvm3/man/man3/pvm_pkmesgbody.30100644007401100000360000000012706221604670015626 0ustar kohlgopher.\" $Id: pvm_pkmesgbody.3,v 1.1 1996/09/23 22:05:44 pvmsrc Exp $ .so man3/pvm_pkmesg.3 ./pvm3/man/man3/pvm_pkshort.30100644007401100000360000000012206221604672015151 0ustar kohlgopher.\" $Id: pvm_pkshort.3,v 1.1 1996/09/23 22:05:46 pvmsrc Exp $ .so man3/pvm_pack.3 ./pvm3/man/man3/pvm_pkstr.30100644007401100000360000000012006221604673014621 0ustar kohlgopher.\" $Id: pvm_pkstr.3,v 1.1 1996/09/23 22:05:47 pvmsrc Exp $ .so man3/pvm_pack.3 ./pvm3/man/man3/pvm_pkuint.30100644007401100000360000000012106221604674014772 0ustar kohlgopher.\" $Id: pvm_pkuint.3,v 1.1 1996/09/23 22:05:48 pvmsrc Exp $ .so man3/pvm_pack.3 ./pvm3/man/man3/pvm_pkulong.30100644007401100000360000000012206221604675015141 0ustar kohlgopher.\" $Id: pvm_pkulong.3,v 1.1 1996/09/23 22:05:49 pvmsrc Exp $ .so man3/pvm_pack.3 ./pvm3/man/man3/pvm_pkushort.30100644007401100000360000000012306221604677015344 0ustar kohlgopher.\" $Id: pvm_pkushort.3,v 1.1 1996/09/23 22:05:51 pvmsrc Exp $ .so man3/pvm_pack.3 ./pvm3/man/man3/pvm_precv.30100644007401100000360000001030606221604700014573 0ustar kohlgopher.\" $Id: pvm_precv.3,v 1.1 1996/09/23 22:05:52 pvmsrc Exp $ .TH PRECV 3PVM "15 March, 1994" "" "PVM Version 3.4" .SH NAME pvm_precv \- Receive a message directly into a buffer. .SH SYNOPSIS .nf .ft B C int info = pvm_precv( int tid, int msgtag, char *buf, .br int len, int datatype, int *atid, .br int *atag, int *alen ) .br Fortran call pvmfprecv( tid, msgtag, buf, len, datatype, .br atid, atag, alen, info ) .fi .SH PARAMETERS .IP tid 0.8i Integer task identifier of sending process (to match). .br .IP msgtag Integer message tag (to match). msgtag should be >= 0. .br .IP buf Pointer to a buffer to receive into. .br .IP len Length of buffer (in multiple of data type size). .br .IP datatype Type of data to which buf points (see below). .br .IP atid Returns actual TID of sender. .br .IP atag Returns actual message tag. .br .IP alen Returns actual message length. .br .IP info Returns PvmOk on success. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_precv blocks the process until a message with label .I msgtag has arrived from \fItid\fR. pvm_precv then places the contents of the message in the supplied buffer, \fIbuf\fR, up to a maximum length of \fIlen\fR * (size of data type). .PP pvm_precv can receive messages sent by pvm_psend, pvm_send, pvm_mcast, or pvm_bcast. .PP A -1 in .I msgtag or .I tid matches anything. This allows the user the following options. If tid = -1 and msgtag is defined by the user, then pvm_precv will accept a message from any process which has a matching msgtag. If msgtag = -1 and tid is defined by the user, then pvm_precv will accept any message that is sent from process tid. If tid = -1 and msgtag = -1, then pvm_precv will accept any message from any process. .PP In C the \fIdatatype\fR parameter must be one of the following, depending on the type of data to be unpacked: [Version 3.3.0 - This parameter only determines message length, not data conversion. It only unpacks raw bytes] .ta 4 16 .nf \fIdatatype\fR Data Type PVM_STR string PVM_BYTE byte PVM_SHORT short PVM_INT int PVM_FLOAT real PVM_CPLX complex PVM_DOUBLE double PVM_DCPLX double complex PVM_LONG long integer PVM_USHORT unsigned short int PVM_UINT unsigned int PVM_ULONG unsigned long int .fi In Fortran the same data types specified for unpack should be used. .PP The PVM model guarantees the following about message order. If task 1 sends message A to task 2, then task 1 sends message B to task 2, message A will arrive at task 2 before message B. Moreover, if both messages arrive before task 2 does a receive, then a wildcard receive will always return message A. .PP If pvm_precv is successful, .I info will be = 0. If some error occurs then info will be < 0. .PP pvm_precv is blocking which means the routine waits until a message matching the user specified tid and msgtag arrives at the local pvmd. If the message has already arrived then pvm_precv returns immediately with the message. .PP pvm_precv does not affect the state of the current receive message buffer (created by the other receive functions). .SH WARNINGS In some versions of PVM (CM5, I860 and PGON), messages sent using pvm_psend must be received only by pvm_precv, likewise those sent with pvm_send must be received by pvm_recv, pvm_nrecv or pvm_trecv. pvm_psend is not compatible with pvm_recv (nor pvm_send with pvm_precv). In addition, pvm_probe is not interoperable with pvm_psend. .PP This problem occurs because nonstandard message headers are used for efficiency in the pvm_psend function. In the generic Unix version of PVM, the calls are fully interoperable. .PP The message tag space is shared between pvm_send and pvm_psend, so you must be careful to avoid selecting the wrong message (for example by using a wildcard to match the message). .SH EXAMPLES .nf C: info = pvm_precv( tid, msgtag, array, cnt, PVM_FLOAT, &src, &rtag, &rlen ); .sp Fortran: CALL PVMFPRECV( -1, 4, BUF, CNT, REAL4, > SRC, RTAG, RCNT, INFO ) .fi .SH ERRORS These error conditions can be returned by .I pvm_precv .IP PvmBadParam giving an invalid tid, msgtag, or datatype. .IP PvmSysErr pvmd not responding. .PP .SH SEE ALSO pvm_psend(3PVM), pvm_recv(3PVM) ./pvm3/man/man3/pvm_probe.30100644007401100000360000000442406221604701014570 0ustar kohlgopher.\" $Id: pvm_probe.3,v 1.1 1996/09/23 22:05:53 pvmsrc Exp $ .TH PROBE 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_probe \- Check if message has arrived. .SH SYNOPSIS .nf .ft B C int bufid = pvm_probe( int tid, int msgtag ) .br Fortran call pvmfprobe( tid, msgtag, bufid ) .fi .SH PARAMETERS .IP tid 0.8i Integer task identifier of sending process supplied by the user. .br .IP msgtag Integer message tag supplied by the user. msgtag should be >= 0. .br .IP bufid Integer returning the value of the new active receive buffer identifier. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_probe checks to see if a message with label .I msgtag has arrived from .I tid. If a matching message has arrived pvm_probe returns a buffer identifier in .I bufid. This .I bufid can be used with pvm_bufinfo to determine information about the message such as its source and length. .PP If the requested message has not arrived, then pvm_probe returns with a 0 in .I bufid. If some error occurs .I bufid will be < 0. .PP A -1 in .I msgtag or .I tid matches anything. This allows the user the following options. If tid = -1 and msgtag is defined by the user, then pvm_probe will accept a message from any process which has a matching msgtag. If msgtag = -1 and tid is defined by the user, then pvm_probe will accept any message that is sent from process tid. If tid = -1 and msgtag = -1, then pvm_probe will accept any message from any process. .PP pvm_probe can be called multiple times to check if a given message has arrived yet. After the message has arrived, pvm_recv must be called before the message can be unpacked into the user's memory using the unpack routines. .SH EXAMPLES .nf C: tid = pvm_parent(); msgtag = 4 ; arrived = pvm_probe( tid, msgtag ); if ( arrived ) info = pvm_bufinfo( arrived, &len, &tag, &tid ); else /* go do other computing */ .sp Fortran: CALL PVMFPROBE( -1, 4, ARRIVED ) IF ( ARRIVED .GT. 0 ) THEN CALL PVMFBUFINFO( ARRIVED, LEN, TAG, TID, INFO ) ELSE * GO DO USEFUL WORK ENDIF .fi .SH ERRORS These error conditions can be returned by .I pvm_probe. .IP PvmBadParam giving an invalid tid value or msgtag. .IP PvmSysErr pvmd not responding. .PP .SH SEE ALSO pvm_bufinfo(3PVM), pvm_getminfo(3PVM), pvm_nrecv(3PVM), pvm_recv(3PVM), pvm_unpack(3PVM) ./pvm3/man/man3/pvm_psend.30100644007401100000360000000701006221604703014566 0ustar kohlgopher.\" $Id: pvm_psend.3,v 1.1 1996/09/23 22:05:55 pvmsrc Exp $ .TH PSEND 3PVM "15 March, 1994" "" "PVM Version 3.4" .SH NAME pvm_psend \- Pack and send data in one call. .SH SYNOPSIS .nf .ft B C int info = pvm_psend( int tid, int msgtag, char *buf, .br int len, int datatype ) .br Fortran call pvmfpsend( tid, msgtag, buf, len, datatype, .br info ) .fi .SH PARAMETERS .IP tid 0.8i Integer task identifier of destination process. .br .IP msgtag Integer message tag supplied by the user. msgtag should be >= 0. .br .IP buf Pointer to a buffer to send. .br .IP len Length of buffer (in multiple of data type size). .br .IP datatype Type of data to which buf points (see below). .br .IP info Integer status code returned by the routine. .SH DESCRIPTION The routine .I pvm_psend takes a pointer to a buffer .I buf its length .I len and its data type .I datatype and sends this data directly to the PVM task identified by .I tid. .I msgtag is used to label the content of the message. If pvm_psend is successful, .I info will be 0. If some error occurs then .I info will be < 0. .PP pvm_psend data can be received by pvm_precv, pvm_recv, pvm_trecv, or pvm_nrecv. .PP The pvm_psend routine is asynchronous. Computation on the sending processor resumes as soon as the buffer is safe for reuse. This is in contrast to synchronous communication, during which computation on the sending processor halts until the matching receive is executed by the receiving processor. .PP In C the \fIdatatype\fR parameter must be one of the following, depending on the type of data to be sent: [Version 3.3.0 - This parameter only determines message length, not data conversion. It only sends raw bytes] .ta 4 16 .nf \fIdatatype\fR Data Type PVM_STR string PVM_BYTE byte PVM_SHORT short PVM_INT int PVM_FLOAT real PVM_CPLX complex PVM_DOUBLE double PVM_DCPLX double complex PVM_LONG long integer PVM_USHORT unsigned short int PVM_UINT unsigned int PVM_ULONG unsigned long int .fi In Fortran the same data types specified for pack should be used. .PP The PVM model guarantees the following about message order. If task 1 sends message A to task 2, then task 1 sends message B to task 2, message A will arrive at task 2 before message B. Moreover, if both messages arrive before task 2 does a receive, then a wildcard receive will always return message A. .PP pvm_psend does not affect the state of the current outgoing message buffer (created by pvm_initsend and used by pvm_send). .SH WARNINGS In some versions of PVM (CM5, I860 and PGON), messages sent using pvm_psend must be received only by pvm_precv, likewise those sent with pvm_send must be received by pvm_recv, pvm_nrecv or pvm_trecv. pvm_psend is not compatible with pvm_recv (nor pvm_send with pvm_precv). In addition, pvm_probe is not interoperable with pvm_psend. .PP This problem occurs because nonstandard message headers are used for efficiency in the pvm_psend function. In the generic Unix version of PVM, the calls are fully interoperable. .PP The message tag space is shared between pvm_send and pvm_psend, so you must be careful to avoid selecting the wrong message (for example by using a wildcard to match the message). .SH EXAMPLES .nf C: info = pvm_psend( tid, msgtag, array, 1000, PVM_FLOAT ); .sp Fortran: CALL PVMFPSEND( TID, MSGTAG, BUF, CNT, REAL4, INFO ) .fi .SH ERRORS These error conditions can be returned by .I pvm_psend .IP PvmBadParam giving an invalid tid, msgtag, or datatype. .IP PvmSysErr pvmd not responding. .PP .SH SEE ALSO pvm_precv(3PVM), pvm_send(3PVM) ./pvm3/man/man3/pvm_pstat.30100644007401100000360000000213706221604704014616 0ustar kohlgopher.\" $Id: pvm_pstat.3,v 1.1 1996/09/23 22:05:56 pvmsrc Exp $ .TH PSTAT 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_pstat \- Returns the status of the specified PVM process. .SH SYNOPSIS .nf .ft B C int status = pvm_pstat( tid ) .br Fortran call pvmfpstat( tid, status ) .fi .SH PARAMETERS .IP tid 0.8i Integer task identifier of the PVM process in question. .br .IP status Integer returns the status of the PVM process identified by .I tid. Status is PvmOk if the task is running, PvmNoTask if not, and PvmBadParam if the .I tid is bad. .SH DESCRIPTION The routine .I pvm_pstat returns the status of the process identified by .I tid. Also note that pvm_notify() can be used to notify the caller that a task has failed. .SH EXAMPLES .nf C: tid = pvm_parent(); status = pvm_pstat( tid ); .sp Fortran: CALL PVMFPARENT( TID ) CALL PVMFPSTAT( TID, STATUS ) .fi .SH ERRORS The following error conditions can be returned by .I pvm_pstat. .IP PvmBadParam Bad Parameter, most likely an invalid tid value. .IP PvmSysErr pvmd not responding. .IP PvmNoTask Task not running. .PP .SH SEE ALSO pvm_notify(3PVM) ./pvm3/man/man3/pvm_putinfo.30100644007401100000360000001667007065766621015174 0ustar kohlgopher.\" $Id: pvm_putinfo.3,v 1.10 2000/03/21 21:45:53 pvmsrc Exp $ .TH PUTINFO 3PVM "22 May, 1997" "" "PVM Version 3.4" .SH NAME pvm_putinfo, pvm_recvinfo, pvm_getmboxinfo, pvm_delinfo \- Store and retrieve messages in global mailbox. .SH SYNOPSIS .nf .ft B C int index = pvm_putinfo( char *name, int bufid, int flags ) .br int bufid = pvm_recvinfo( char *name, int index, int flags ) .br int info = pvm_delinfo( char *name, int index, int flags ) .br int info = pvm_getmboxinfo( char *pattern, int *nclasses, struct pvmmboxinfo **classes ) .br struct pvmmboxinfo { char *mi_name; /* class name */ int mi_nentries; /* # of entries for this class */ int *mi_indices; /* mbox entry indices */ int *mi_owners; /* mbox entry owner tids */ int *mi_flags; /* mbox entry flags */ }; Fortran .br call pvmfputinfo( name, bufid, flags, index ) .br call pvmfrecvinfo( name, index, flags, bufid ) .br call pvmfdelinfo( name, index, flags, info ) .br call pvmfgetmboxinfo( pattern, name, nclasses, nentries, index, owner, flags, info ) .fi .SH PARAMETERS .IP name .br Database key (class name), any null-terminated string. .IP index .br Database key (class index), >= 0. Default index = 0. .IP flags .br User specified options. (see below) .IP bufid .br Handle of message buffer to put in database, or message returned. A returned bufid < 0 indicates an error. .IP info .br Resulting status code. .IP pattern .br GNU regular expression (pattern) to match on names in mailbox database. Additionally, the singular "*" will match on all names. .IP nclasses .br Number of classes matching pattern. .IP classes .br Array of pvmmboxinfo mailbox entries matching pattern. .IP nentries .br Number of entries for a given class. .IP owner .br Task id that inserted entry into mailbox database. .SH DESCRIPTION These functions implement a "message mailbox" database that can be used by PVM tasks to advertise information to other PVM tasks. An example would be to advertise names or locations of services. Another example would be to advertise a common "context" on which two tasks may communicate. The database entries are PVM messages keyed by a user specified name and an optional index value. The name may be any null-terminated string and the index a non-negative integer. The index value is assigned by PVM and is used to uniquely identify one of multiple named instances within the database. Entries are "owned" by the task that created them. An entry is automatically removed from the database when the owner task exits unless the database entry was created with flag PvmMboxPersistent. When a task exits and leaves an entry in the mailbox, the owner tid of that entry is marked as zero (0) to indicate that there is no longer an active owner task. .I \fIpvm_putinfo\fR inserts a record in the database, given a key and data (message). It returns mailbox index number if the record is successfully stored, PvmExists if a record with the given key already exists, or PvmDenied if an attempt is made to overwrite a locked record. The following options are added together as the flags parameter to pvm_putinfo. .IP PvmMboxDefault Inserts entry as the only named instance for a given name. This entry may only be modified and deleted by its owner. It is automatically deleted when its owner exits. .IP PvmMboxPersistent Entry remains in the database when the owner task exits. Entries are removed from the database when PVM is halted or a reset is issued from the console. .IP PvmMboxMultiInstance Permits multiple entry instances of the same name. PVM will assign an index key to each instance. .IP PvmMboxOverWritable Permits other tasks to overwrite and delete this database entry. .IP PvmMboxDirectIndex( index ) Performs an atomic delete and re-insert for the mailbox entry at the given index. Valid index values for this macro are limited to the range [ 0 .. \fIPvmMboxMaxDirectIndex\fR ). The given mailbox entry must have been created with the \fIPvmMboxOverWritable\fR flag set. If \fIindex\fR is greater than 0, then the mailbox must also have been created with the \fIPvmMboxMultiInstance\fR flag set. .PP .I \fIpvm_recvinfo\fR operates just like a pvm_recv() except the message is coming from the database. The message should be unpacked after pvm_recvinfo(). Like pvm_recv, pvm_recvinfo returns a pointer to a message buffer containing the record matching the key from the database. Returned value < 0 indicates an error. The following options are added together as the flags parameter to pvm_recvinfo. .IP PvmMboxDefault Exact match on key is returned. Returns PvmNotFound if exact match not found. .IP PvmMboxFirstAvail The first entry in with index greater than or equal to the specified index parameter is retuned. PvmMboxFirstAvail with index = 0 will produce the same results as using PvmMboxDefault. .IP PvmMboxReadAndDelete Return entry and delete from database. Task must be permitted to do both read and delete otherwise an error will occur. bufid returns PvmNotFound if entry does not exist and will return PvmDenied if the record exists but may not be deleted. .PP .I \fIpvm_delinfo\fR deletes database entry specified by the key . Returns PvmOK if the record was deleted, PvmNotFound if the record does not exist, or PvmDenied if an attempt is made to remove a "locked" record. There are no flags presently specified for pvm_delinfo. .I \fIpvm_getmboxinfo\fR returns an array of pvmmboxinfo for all class names in the database. This is used, for example, by programs that clean up the database or for applications to find out what is available. \fIclasses\fR returns a pointer to the array allocated by libpvm and freed on the next call to pvm_getmboxinfo. The Fortran function returns information on one entry per call. Thus, if called repeatedly until an info value of .I PvmNotFound is returned, all entries matching the given pattern will have been returned. If a new pattern is desired, calling pvmfgetnames() with info = -1 will reset the entry name list and obtain a new list for the given pattern. .SH EXAMPLES .nf C: /* * create and insert mailbox entry */ sprintf( service, "Task_A_service" ); sprintf( message, "Greetings from task A." ); pvm_initsend( PvmDataDefault ); pvm_pkint( &mytid, 1, 1 ); pvm_pkint( &context, 1, 1 ); pvm_pkstr( message ); if (( pvm_putinfo( service, pvm_getsbuf(), PvmMboxDefault )) == PvmExists ){ printf( "can't register - service already running\n" ); exit( -1 ); } /* * look for and retrieve specified mailbox */ sprintf( service, "Task_A_service" ); if (( msg_buf = pvm_recvinfo(service, 0, PvmMboxFirstAvail )) >= 0 ){ pvm_setrbuf( msg_buf ); pvm_upkint( &their_tid, 1, 1 ); pvm_upkint( &their_context, 1, 1 ); pvm_upkstr( message ); } Fortran: we need the fortran examples... .fi .SH ERRORS The following error conditions can be returned by one or more of these functions: .IP PvmBadParam An invalid value was specified for \fIbufid\fR argument. .IP PvmNoSuchBuf Message buffer \fIbufid\fR doesn't exist. .IP PvmNoMem Libpvm is unable to allocate memory to pack data. .IP PvmExists The requested key is already in use (pvm_putinfo). .IP PvmNotFound The requested key does not exist (pvm_recvinfo, pvm_delinfo). .IP PvmDenied The key is locked by another task and cannot be replaced or deleted. .SH SEE ALSO pvm_initsend(3PVM), pvm_getsbuf(3PVM), pvm_pack(3PVM), ./pvm3/man/man3/pvm_recv.30100644007401100000360000000523306221604707014425 0ustar kohlgopher.\" $Id: pvm_recv.3,v 1.1 1996/09/23 22:05:59 pvmsrc Exp $ .TH RECV 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_recv \- Receive a message. .SH SYNOPSIS .nf .ft B C int bufid = pvm_recv( int tid, int msgtag ) .br Fortran call pvmfrecv( tid, msgtag, bufid ) .fi .SH PARAMETERS .IP tid 0.8i Integer task identifier of sending process supplied by the user. .br .IP msgtag Integer message tag supplied by the user. msgtag should be >= 0. .br .IP bufid Integer returns the value of the new active receive buffer identifier. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_recv blocks the process until a message with label .I msgtag has arrived from .I tid. pvm_recv then places the message in a new \fIactive\fR receive buffer, which also clears the current receive buffer. .PP A -1 in .I msgtag or .I tid matches anything. This allows the user the following options. If tid = -1 and msgtag is defined by the user, then pvm_recv will accept a message from any process which has a matching msgtag. If msgtag = -1 and tid is defined by the user, then pvm_recv will accept any message that is sent from process tid. If tid = -1 and msgtag = -1, then pvm_recv will accept any message from any process. .PP The PVM model guarantees the following about message order. If task 1 sends message A to task 2, then task 1 sends message B to task 2, message A will arrive at task 2 before message B. Moreover, if both messages arrive before task 2 does a receive, then a wildcard receive will always return message A. .PP If pvm_recv is successful, .I bufid will be the value of the new active receive buffer identifier. If some error occurs then .I bufid will be < 0. .PP pvm_recv is blocking which means the routine waits until a message matching the user specified tid and msgtag values arrives at the local pvmd. If the message has already arrived then pvm_recv returns immediately with the message. .PP Once pvm_recv returns, the data in the message can be unpacked into the user's memory using the unpack routines. .SH EXAMPLES .nf C: tid = pvm_parent(); msgtag = 4 ; bufid = pvm_recv( tid, msgtag ); info = pvm_upkint( tid_array, 10, 1 ); info = pvm_upkint( problem_size, 1, 1 ); info = pvm_upkfloat( input_array, 100, 1 ); .sp Fortran: CALL PVMFRECV( -1, 4, BUFID ) CALL PVMFUNPACK( INTEGER4, TIDS, 25, 1, INFO ) CALL PVMFUNPACK( REAL8, MATRIX, 100, 100, INFO ) .fi .SH ERRORS These error conditions can be returned by .I pvm_recv .IP PvmBadParam giving an invalid tid value, or msgtag < -1. .IP PvmSysErr pvmd not responding. .PP .SH SEE ALSO pvm_bufinfo(3PVM), pvm_getminfo(3PVM), pvm_nrecv(3PVM), pvm_unpack(3PVM), pvm_probe(3PVM), pvm_send(3PVM), pvm_mcast(3PVM) ./pvm3/man/man3/pvm_recvf.30100644007401100000360000000445706221604710014574 0ustar kohlgopher.\" $Id: pvm_recvf.3,v 1.1 1996/09/23 22:06:00 pvmsrc Exp $ .TH RECVF 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_recvf \- Redefines the comparison function used to accept messages. .SH SYNOPSIS .nf .ft B C int (*old)() = pvm_recvf( int (*new)( int bufid, int tid, int tag )) .br Fortran NOT AVAILABLE .fi .SH DESCRIPTION The routine .I pvm_recvf defines the comparison function to be used by the pvm_recv, pvm_nrecv, and pvm_probe functions. It is available as a means to customize PVM message passing. pvm_recvf sets a user supplied comparison function to evaluate messages for receiving. .PP recvf returns the old value of the matching function, or 0 if the old function was the default matcher .PP pvm_recvf is intended for sophisticated C programmers who understand the function of such routines (like signal) and who require a receive routine that can match on more complex message contexts than the default provides. .SH MATCHING FUNCTION The default comparison function evaluates the source and message tag associated with all incoming messages. .SH PARAMETERS .IP tid 0.8i Integer task identifier of sending process supplied by the user. .br .IP tag Integer message tag supplied by the user. .br .IP bufid Integer message buffer identifier. .PP The matching function should return: .ta 0.5i 1.5i .nf Value Action taken < 0 Return immediately with this error code. 0 Do not pick this message. 1 Pick this message and do not scan the rest. > 1 Pick this highest ranked message after scanning them all. .fi .bp .SH EXAMPLES Implementing message probe with recvf, using our matching function to return information in a global variable. .ta 0.5i 1.0i 1.5i .nf #include static int foundit = 0; static int foo_match(mid, tid, tag) int mid; int tid; int tag; { int t, c; struct pvmminfo header; pvm_getminfo(mid, &header); if ((tid == -1 || tid == header.src) && (tag == -1 || tag == header.tag)) foundit = 1; return 0; } int probe(src, tag) { int (*omatch)(); int cc; omatch = pvm_recvf(foo_match); foundit = 0; if ((cc = pvm_nrecv(src, tag)) < 0) return cc; pvm_recvf(omatch); return foundit; } .fi .SH ERRORS No error conditions are returned by .I pvm_recvf .SH SEE ALSO pvm_bufinfo(3PVM), pvm_getminfo(3PVM), pvm_recv(3PVM), pvm_nrecv(3PVM), pvm_probe(3PVM), pvm_trecv(3PVM) ./pvm3/man/man3/pvm_recvinfo.30100644007401100000360000000002706320231363015267 0ustar kohlgopher.so man3/pvm_putinfo.3 ./pvm3/man/man3/pvm_reduce.30100644007401100000360000001431006221604711014724 0ustar kohlgopher.\" $Id: pvm_reduce.3,v 1.1 1996/09/23 22:06:01 pvmsrc Exp $ .TH REDUCE 3PVM "6 February, 1995" "" "PVM Version 3.4" .SH NAME pvm_reduce \- Performs a reduction operation over members of the specified group. .SH SYNOPSIS .ft B C int info = pvm_reduce( void (*func)(), .br void *data, int count, int datatype, .br int msgtag, char *group, int rootginst) .br Fortran call pvmfreduce(func, data, count, datatype, .br msgtag, group, rootginst, info) .fi .SH PARAMETERS .IP func 0.8i Function which defines the operation performed on the global data. Predefined are PvmMax, PvmMin, PvmSum, and PvmProduct. Users can define their own function. .br SYNOPSIS for func .nf .br C void func(int *datatype, void *x, void *y, .br int *num, int *info) .br Fortran call func(datatype, x, y, num, info) .br .IP data Pointer to the starting address of an array of local values. On return, the data array on the root will be overwritten with the result of the reduce operation over the group. For the other (non-root) members of the group the values of the data array upon return from the reduce operation are not defined; the values may be different than those originally passed to pvm_reduce. .br .IP count Integer specifying the number of elements of .I datatype in the data array. The value of count should agree between all members of the group. .br .IP datatype Integer specifying the type of the entries in the data array. (See below for defined types.) .IP msgtag Integer message tag supplied by the user. msgtag should be >= 0. It allows the user's program to distinguish between different kinds of messages. .br .IP group Character string group name of an existing group. .br .IP rootginst Integer instance number of group member who gets the result. .br .IP info Integer status code returned by the routine. Values less than zero indicate an error. .SH DESCRIPTION .I pvm_reduce() performs global operations such as max, min, sum, or a user provided operation on the data provided by the members of a group. All group members call pvm_reduce with the same size local .I data array which may contain one or more entries. The .I root task is identified by its instance number in the group. .PP The inner workings of the pvm_reduce call are implementation dependent; however, when the pvm_reduce call completes, the root's data array will be equal to the specified operation applied element-wise to the data arrays of all the group members. .PP A broadcast by the root can be used if the other members of the group need the resultant value(s). .PP PVM supplies the following predefined functions that can be specified in .I func. .nf PvmMin PvmMax PvmSum PvmProduct .fi PvmMax and PvmMin are implemented for all the datatypes listed below. For complex values the minimum [maximum] is that complex pair with the minimum [maximum] modulus. PvmSum and PvmProduct are implemented for all the datatypes listed below with the exception of PVM_BYTE and BYTE1. .PP C and Fortran defined .I datatypes are: .nf C datatypes FORTRAN datatypes ----------------------------------- PVM_BYTE BYTE1 PVM_SHORT INTEGER2 PVM_INT INTEGER4 PVM_FLOAT REAL4 PVM_CPLX COMPLEX8 PVM_DOUBLE REAL8 PVM_DCPLX COMPLEX16 PVM_LONG .fi .PP A user defined function may be used in .I func. The argument func is a function with four arguments. It is the base function used for the reduction operation. Both x and y are arrays of type specified by datatype with num entries. The arguments datatype and info are as specified above. The arguments x and num correspond to data and count above. The argument y contains received values. .PP Caveat: pvm_reduce() does not block, a call to pvm_barrier may be necessary. For example, an error may occur if a task calls pvm_reduce and then leaves the group before the root has completed its call to pvm_reduce. Similarly, an error may occur if a task joins the group after the root has issued its call to pvm_reduce. Synchronization of the tasks (such as a call to pvm_barrier) was not included within the pvm_reduce implementation since this overhead is unnecessary in many user codes (which may already synchronize the tasks for other purposes). .PP The current algorithm is very simple and robust. A future implementation may make more efficient use of the architecture to allow greater parallelism. .SH ILLUSTRATION .PP The following example illustrates a call to pvm_reduce. Suppose you have three group members (instance numbers 0, 1, 2) with an array called Idata with 5 values as specified: .PP .nf instance the 5 values in the integer array 0 1, 2, 3, 4, 5 1 10, 20, 30, 40, 50 2 100, 200, 300, 400, 500 .fi .PP And, suppose that a call to reduce (such as the ones following) are issued where the root is the group member with instance value of 1: .PP .nf C: root = 1; info = pvm_reduce(PvmSum, &Idata, 5, PVM_INT, msgtag, "worker", root); Fortran: root = 1 call pvmfreduce(PvmSum, Idata, 5, INTEGER4, msgtag, "worker", root, info) .fi .PP Then, upon completion of the reduce call, the following will result: .PP .nf instance the 5 values in the integer array 0 .... not defined....... 1 111, 222, 333, 444, 555 2 .... not defined ...... .fi .SH EXAMPLES .nf C: info = pvm_reduce(PvmMax, &myvals, 10, PVM_FLOAT, msgtag, "worker", rootginst); .sp Fortran: CALL PVMFREDUCE(PvmMax, MYVALS, COUNT, REAL4, & MTAG, 'worker', ROOT, INFO) .fi .SH ERRORS These error conditions can be returned by .I pvm_reduce .IP PvmNoInst Calling task is not in the group .IP PvmBadParam The datatype specified is not appropriate for the specified reduction function. .IP PvmSysErr Pvm system error .PP .SH SEE ALSO pvm_bcast(3PVM), pvm_barrier(3PVM), pvm_psend(3PVM) ./pvm3/man/man3/pvm_reg_hoster.30100644007401100000360000000574106221604713015630 0ustar kohlgopher.\" $Id: pvm_reg_hoster.3,v 1.1 1996/09/23 22:06:03 pvmsrc Exp $ .TH REG_HOSTER 3PVM "4 March, 1994" "" "PVM Version 3.4" .SH NAME pvm_reg_hoster \- Register task as PVM slave starter. .SH SYNOPSIS .nf .ft B C #include int cc = pvm_reg_hoster() .br Fortran Not Available .fi .SH DESCRIPTION Registers the calling task as a PVM slave pvmd starter. When the master pvmd receives a DM_ADD message, instead of starting the new slave pvmd processes itself, it passes a message to the hoster, which does the dirty work and sends a message back to the pvmd. Note: This function isn't for beginners. If you don't grok what it does, you probably don't need it. For a more complete explanation of what's going on here, you should refer to the PVM source code and/or user guide section on implementation; this is just a man page. That said... When the master pvmd receives a \fIDM_ADD\fR message (request to add hosts to the virtual machine), it looks up the new host IP addresses, gets parameters from the host file if it was started with one, and sets default parameters. It then either attempts to start the processes (using \fIrsh\fR or \fIrexec()\fR) or, if a hoster has registered, sends it a \fISM_STHOST\fR message. The format of the SM_STHOST message is: .ta 4 8 30 .nf int nhosts // number of hosts { int tid // of host string options // from hostfile \fIso=\fR field string login // in form ``[username@]hostname.domain'' string command // to run on remote host } [nhosts] .fi The hoster should attempt to run each command on each host and record the result. A command usually looks like: .br $PVM_ROOT/lib/pvmd -s -d8 -nhonk 1 80a9ca95:0f5a 4096 3 80a95c43:0000 and a reply from a slave pvmd like: .br ddpro<2312> arch ip<80a95c43:0b3f> mtu<4096> When finished, the hoster should send a \fISM_STHOSTACK\fR message back to the address of the sender (the master pvmd). The format of the reply message is: .nf { int tid // of host, must match request string status // result line from slave or error code } [] // implied count .fi The TIDs in the reply must match those in the request. They may be in a different order, however. The result string should contain the entire reply (a single line) from each new slave pvmd, or an error code if something went wrong. Legal error codes are the literal names of the \fIpvm_errno\fR codes, for example ``PvmCantStart''. The default PVM hoster can return PvmDSysErr or PvmCantStart, and the slave pvmd itself can return PvmDupHost. The hoster must use \fIpvm_setmwid()\fR to set the wait ID in the reply message to the same value as in the request. The wait ID in the request is obtained by calling \fIpvm_getmwid()\fR. The hoster task must use pvm_setopt(PvmResvTids, 1) to allow sending reserved messages. Messages should be packed using encoding \fIPvmDataDefault\fR to ensure they can be unpacked anywhere in the system. pvm_reg_hoster() returns PvmOk when successful. .SH SEE ALSO pvm_addhosts(3PVM), pvm_config(3PVM), pvm_setmwid(3PVM) ./pvm3/man/man3/pvm_reg_rm.30100644007401100000360000000505406221604714014740 0ustar kohlgopher.\" $Id: pvm_reg_rm.3,v 1.1 1996/09/23 22:06:04 pvmsrc Exp $ .TH REG_RM 3PVM "4 March, 1994" "" "PVM Version 3.4" .SH NAME pvm_reg_rm \- Register task as PVM resource manager. .SH SYNOPSIS .nf .ft B C #include int cc = pvm_reg_rm( struct pvmhostinfo **hip ) .br struct pvmhostinfo { .br int hi_tid; .br char *hi_name; .br char *hi_arch; .br int hi_speed; .br }; .br Fortran Not Available .fi .SH PARAMETERS .IP hostp Returns pointer to a pvmhostinfo structure which contains information about the master host. .SH DESCRIPTION Registers the calling task as a PVM task and slave host manager. This means it intercepts certain libpvm calls from other tasks in order to have a say in scheduling policy. The resource manager will asynchronously receive messages from tasks containing requests for service, as well as messages from pvmds notifying it of system failures. Before you start using this function, be warned that it's not a trivial thing, i.e. you can't just call it to turn off the default round-robin task assignment. Rather, it allows you to write your own resource manager and hook it to PVM. To understand what the following messages mean, you should refer to the PVM source code and/or user guide section on implementation; There's just too much to say about them. When one of the following libpvm functions is called in a task with resource manager set, the given message tag is sent to to resource manager. .ta 4 26 44 .nf \fILibpvm call RM message Normal message\fR pvm_addhosts() SM_ADDHOST TM_ADDHOST pvm_config() SM_CONFIG TM_CONFIG pvm_delhosts() SM_DELHOST TM_DELHOST pvm_notify() SM_NOTIFY TM_NOTIFY pvm_spawn() SM_SPAWN TM_SPAWN pvm_tasks() SM_TASK TM_TASK pvm_reg_rm() SM_SCHED TM_SCHED .fi The resource manager must in turn compose the following messages and send them to the pvmds: .ta 4 22 .nf \fIRM message Normal message\fR SM_EXEC DM_EXEC SM_EXECACK DM_EXECACK SM_ADD DM_ADD SM_ADDACK DM_ADDACK SM_HANDOFF (none - change of resource manager) .fi The following messages are sent asynchronously to the resource manager by the system: .nf \fIRM message Meaning\fR SM_TASKX notify of task exit/fail SM_HOSTX notify of host delete/fail .fi The resource manager task must use pvm_setopt(PvmResvTids, 1) to allow sending reserved messages. Messages should be packed using encoding \fIPvmDataDefault\fR to ensure they can be unpacked anywhere in the system. pvm_reg_rm() returns PvmOk when successful. .SH SEE ALSO pvm_addhosts(3PVM), pvm_config(3PVM), pvm_delhosts(3PVM), pvm_notify(3PVM), pvm_spawn(3PVM), pvm_tasks(3PVM) ./pvm3/man/man3/pvm_reg_tasker.30100644007401100000360000000500306221604716015607 0ustar kohlgopher.\" $Id: pvm_reg_tasker.3,v 1.1 1996/09/23 22:06:06 pvmsrc Exp $ .TH REG_TASKER 3PVM "16 March, 1994" "" "PVM Version 3.4" .SH NAME pvm_reg_tasker \- Register task as PVM task starter. .SH SYNOPSIS .nf .ft B C #include int cc = pvm_reg_tasker() .br Fortran Not Available .fi .SH DESCRIPTION Registers the calling task as a PVM task starter. When a tasker is registered with a pvmd, and the pvmd receives a DM_EXEC message, instead of fork()ing and exec()ing the task itself, it passes a message to the tasker, which does the dirty work and sends a message back to the pvmd. Note: If this doesn't make sense, don't worry about it. This function is for folks who are writing stuff like debugger servers and so on. For a more complete explanation of what's going on here, you should refer to the PVM source code and/or user guide section on implementation; this is only a man page. That said... When the pvmd receives a \fIDM_EXEC\fR message (request to exec new tasks), it searches \fIepath\fR (the PVM executable search path) for the file name. If it finds the file, it then either attempts to start the processes (using \fIfork()\fR and \fIexec()\fR) or, if a tasker has registered, sends it a \fISM_STTASK\fR message. The format of the SM_STTASK message is: .ta 4 26 .nf int tid // of task int flags // as passed to spawn() string path // absolute path of the executable int argc // number of args to process string argv[argc] // args int nenv // number of envars to pass to task string env[nenv] // environment strings .fi The tasker must attempt to start the process when it gets one of these messages. The tasker doesn't reply to the pvmd if the task is successfully started; the task will reconnect to the pvmd on its own, using the cookie in envar \fIPVMEPID\fR to identify itself to the pvmd. The tasker must send a \fISM_TASKX\fR message to the pvmd when any task that it owns (has started) exits, or if it can't start a particular task. The format of the SM_TASKX message is: .nf int tid // of task int status // the Unix exit status (from \fIwait()\fR) int u_sec // user time used by the task, seconds int u_usec // microseconds int s_sec // system time used by the task, seconds int s_usec // microseconds .fi The tasker task must use pvm_setopt(PvmResvTids, 1) to allow sending reserved messages. Messages should be packed using encoding \fIPvmDataDefault\fR to ensure they can be unpacked anywhere in the system. pvm_reg_tasker() returns PvmOk when successful. .SH SEE ALSO pvm_spawn(3PVM), pvm_tasks(3PVM), ./pvm3/man/man3/pvm_scatter.30100644007401100000360000000733406221604721015133 0ustar kohlgopher.\" $Id: pvm_scatter.3,v 1.1 1996/09/23 22:06:09 pvmsrc Exp $ .TH SCATTER 3PVM "21 April, 1994" "" "PVM Version 3.4" .SH NAME pvm_scatter \- Sends to each member of a group a section of an array from a specified member of the group. .SH SYNOPSIS .nf .ft B C int info = pvm_scatter( void *result, void *data, .br int count, int datatype, int msgtag, .br char *group, int rootginst) .br Fortran call pvmfscatter(result, data, count, datatype, .br msgtag, group, rootginst, info) .fi .SH PARAMETERS .IP result 0.8i Pointer to the starting address of an array of length .I count of .I datatype which will be overwritten by the message from the specified root member of the group. .br .IP data On the root this is a pointer to the starting address of an array .I datatype of local values which are to be distributed to the members of the group. If n is the number of members in the group, then this array of .I datatype should be of length at least n*\fIcount\fR. This argument is meaningful only on the root. .br .IP count Integer specifying the number of elements of .I datatype to be sent to each member of the group from the root. .br .IP datatype Integer specifying the type of the entries in the result and data arrays. (See below for defined types.) .IP msgtag Integer message tag supplied by the user. msgtag should be >= 0. It allows the user's program to distinguish between different kinds of messages. .br .IP group Character string group name of an existing group. .br .IP rootginst Integer instance number of group member who performs the scatter of its array to the members of the group. .br .IP info Integer status code returned by the routine. Values less than zero indicate an error. .SH DESCRIPTION .I pvm_scatter() performs a scatter of data from the specified root member of the group to each of the members of the group, including itself. All group members must call pvm_scatter(), each receives a portion of the .I data array from the root in their local .I result array. It is as if the root node sends to the ith member of the group .I count elements from its array .I data starting at offset i*\fIcount\fR from the beginning of the .I data array. And, it is as if, each member of the group performs a corresponding receive of .I count values of .I datatype into its .I result array. The root task is identified by its instance number in the group. .PP C and Fortran defined .I datatypes are: .nf C datatypes FORTRAN datatypes ----------------------------------- PVM_BYTE BYTE1 PVM_SHORT INTEGER2 PVM_INT INTEGER4 PVM_FLOAT REAL4 PVM_CPLX COMPLEX8 PVM_DOUBLE REAL8 PVM_DCPLX COMPLEX16 PVM_LONG .fi .PP In using the scatter and gather routines, keep in mind that C stores multidimensional arrays in row order, typically starting with an initial index of 0; whereas, Fortran stores arrays in column order, typically starting with an offset of 1. .PP The current algorithm is very simple and robust. A future implementation may make more efficient use of the architecture to allow greater parallelism. .SH EXAMPLES .nf C: info = pvm_scatter(&getmyrow, &matrix, 10, PVM_INT, msgtag, "workers", rootginst); .sp Fortran: CALL PVMFSCATTER(GETMYCOLUMN, MATRIX, COUNT, INTEGER4, & MTAG, 'workers', ROOT, INFO) .fi .SH ERRORS These error conditions can be returned by .I pvm_scatter .IP PvmNoInst Calling task is not in the group .IP PvmBadParam The datatype specified is not appropriate .IP PvmSysErr Pvm system error .PP .SH SEE ALSO pvm_bcast(3PVM), pvm_barrier(3PVM), pvm_psend(3PVM) ./pvm3/man/man3/pvm_send.30100644007401100000360000000424406221604722014415 0ustar kohlgopher.\" $Id: pvm_send.3,v 1.1 1996/09/23 22:06:10 pvmsrc Exp $ .TH SEND 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_send \- Immediately sends the data in the active message buffer. .SH SYNOPSIS .nf .ft B C int info = pvm_send( int tid, int msgtag ) .br Fortran call pvmfsend( tid, msgtag, info ) .fi .SH PARAMETERS .IP tid 0.8i Integer task identifier of destination process. .br .IP msgtag Integer message tag supplied by the user. msgtag should be >= 0. .br .IP info Integer status code returned by the routine. .SH DESCRIPTION The routine .I pvm_send sends a message stored in the active send buffer to the PVM process identified by .I tid. .I msgtag is used to label the content of the message. If pvm_send is successful, .I info will be 0. If some error occurs then .I info will be < 0. .PP The pvm_send routine is asynchronous. Computation on the sending processor resumes as soon as the message is safely on its way to the receiving processor. This is in contrast to synchronous communication, during which computation on the sending processor halts until the matching receive is executed by the receiving processor. .PP The PVM model guarantees the following about message order. If task 1 sends message A to task 2, then task 1 sends message B to task 2, message A will arrive at task 2 before message B. Moreover, if both messages arrive before task 2 does a receive, then a wildcard receive will always return message A. .PP Terminating a PVM task immediately after sending a message or messages from it may result in those messages being lost. To be sure, always call pvm_exit() before stopping. .SH EXAMPLES .nf C: info = pvm_initsend( PvmDataDefault ); info = pvm_pkint( array, 10, 1 ); msgtag = 3 ; info = pvm_send( tid, msgtag ); .sp Fortran: CALL PVMFINITSEND(PVMRAW, INFO) CALL PVMFPACK( REAL8, DATA, 100, 1, INFO ) CALL PVMFSEND( TID, 3, INFO ) .fi .SH ERRORS These error conditions can be returned by .I pvm_send .IP PvmBadParam giving an invalid tid or a msgtag. .IP PvmSysErr pvmd not responding. .IP PvmNoBuf no active send buffer. Try pvm_initsend() before send. .PP .SH SEE ALSO pvm_initsend(3PVM), pvm_mcast(3PVM), pvm_pack(3PVM), pvm_psend(3PVM), pvm_recv(3PVM) ./pvm3/man/man3/pvm_sendsig.30100644007401100000360000000267406221604724015127 0ustar kohlgopher.\" $Id: pvm_sendsig.3,v 1.1 1996/09/23 22:06:12 pvmsrc Exp $ .TH SENDSIG 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_sendsig \- Sends a signal to another PVM process. .SH SYNOPSIS .nf .ft B C int info = pvm_sendsig( int tid, int signum ) .br Fortran call pvmfsendsig( tid, signum, info ) .fi .SH PARAMETERS .IP tid 0.8i Integer task identifier of PVM process to receive the signal. .br .IP signum Integer signal number. .br .IP info Integer status code returned by the routine. .SH DESCRIPTION The routine .I pvm_sendsig sends the signal number .I signum to the PVM process identified by .I tid. If pvm_sendsig is successful, .I info will be 0. If some error occurs then .I info will be < 0. .PP pvm_sendsig should only be used by programmers with Unix signal handling experience. Many library functions (and in fact the PVM library functions) cannot be called in a signal handler context because they do not mask signals or lock internal data structures. Further caveat: the signal numbers passed between systems are not mapped - PVM assumes that signal 9 on one system is the same as on another. .SH EXAMPLES .nf C: tid = pvm_parent(); info = pvm_sendsig( tid, SIGKILL); .sp Fortran: CALL PVMFBUFINFO( BUFID, BYTES, TYPE, TID, INFO ); CALL PVMFSENDSIG( TID, SIGNUM, INFO ) .SH ERRORS These error conditions can be returned by .I pvm_sendsig .IP PvmSysErr pvmd not responding. .IP PvmBadParam giving an invalid tid value. .PP .SH SEE ALSO ./pvm3/man/man3/pvm_serror.30100644007401100000360000000247006221604725015002 0ustar kohlgopher.\" $Id: pvm_serror.3,v 1.1 1996/09/23 22:06:13 pvmsrc Exp $ .TH SERROR 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_serror \- Sets automatic error message printing on or off. .br [In Version 3.2: Replaced by pvm_setopt] .SH SYNOPSIS .nf .ft B C int oldset = pvm_serror( int set ) .br Fortran call pvmfserror( set, oldset ) .fi .SH PARAMETERS .IP set 0.8i Integer defining whether detection is to be turned on (1) or off (0). .br .IP oldset Integer defining the previous setting of pvm_serror. .SH DESCRIPTION The routine .I pvm_serror sets automatic error message printing for all subsequent PVM calls by this process. Any PVM routines that return an error condition will automatically print the associated error message. The argument .I set defines whether this detection is to be turned on (1) or turned off (0) for subsequent calls. In the future a value of (2) will cause the program to exit after printing the error message. pvm_serror returns the previous value of set in .I oldset. .PP All stdout and stderr messages are placed in the file /tmp/pvml. on the master pvmd's host. .SH EXAMPLES .nf C: info = pvm_serror( 1 ); Fortran: CALL PVMFSERROR( 0, INFO ) .SH ERRORS This error condition can be returned by .I pvm_serror .IP PvmBadParam giving an invalid set value. .PP .SH SEE ALSO pvm_setopt(3PVM) ./pvm3/man/man3/pvm_setcontext.30100644007401100000360000000013306322753061015660 0ustar kohlgopher.\" $Id: pvm_setcontext.3,v 1.1 1997/04/09 17:47:29 pvmsrc Exp $ .so man3/pvm_newcontext.3 ./pvm3/man/man3/pvm_setmwid.30100644007401100000360000000251006221604730015131 0ustar kohlgopher.\" $Id: pvm_setmwid.3,v 1.1 1996/09/23 22:06:16 pvmsrc Exp $ .TH SETMWID 3PVM "18 May, 1994" "" "PVM Version 3.4" .SH NAME pvm_getmwid, pvm_setmwid \- Get or set wait ID of a message. .br [In Version 3.4: Relaced by pvm_getminfo and pvm_setminfo] .SH SYNOPSIS .nf .ft B C int info = pvm_getmwid( int bufid ) .br int info = pvm_setmwid( int bufid, int waitid ) .br Fortran Not Available .fi .SH PARAMETERS .IP bufid 0.8i Message buffer identifier. .IP waitid Wait identifier number. .SH DESCRIPTION A wait identifier is part of a message (like the source, destination, tag and body). It is used to match a reply to the corresponding request. The default wait ID for a message is zero (none). pvm_getmwid returns the wait ID associated with a message buffer, or a negative error code. pvm_setmwid assigns a new wait ID to a message buffer. It returns PvmOk unless an error occurs. .SH EXAMPLES .nf int src, tag; pvm_recv(-1, -1); /* ... process, compose reply message */ pvm_setmwid(pvm_getsbuf(), pvm_getmwid(pvm_getrbuf())); pvm_bufinfo(pvm_getrbuf(), (int *)0, &tag, &src); pvm_send(src, tag); .SH ERRORS The following error conditions can be returned by pvm_getmwid or pvm_setmwid: .IP PvmBadParam Invalid value for \fIbufid\fR argument. .IP PvmNoSuchBuf Message buffer \fIbufid\fR doesn't exist. .PP .SH SEE ALSO pvm_bufinfo(3PVM) ./pvm3/man/man3/pvm_setopt.30100644007401100000360000002267507051106367015016 0ustar kohlgopher.\" $Id: pvm_setopt.3,v 1.2 2000/02/11 22:28:07 pvmsrc Exp $ .TH SETOPT 3PVM "4 April, 1994" "" "PVM Version 3.4" .SH NAME pvm_setopt \- Sets libpvm options. .SH SYNOPSIS .nf .ft B C int oldval = pvm_setopt( int what, int val ) .br Fortran call pvmfsetopt( what, val, oldval ) .fi .SH PARAMETERS .IP what 0.8i Integer defining what to set. One of: .nf PvmRoute 1 Message routing policy PvmDebugMask 2 Libpvm debug mask PvmAutoErr 3 Auto error reporting PvmOutputTid 4 Stdout destination for children PvmOutputCode 5 Output message tag for children PvmTraceTid 6 Trace data destination for children PvmTraceCode 7 Trace message tag for children PvmTraceBuffer 8 Trace buffer size for children PvmTraceOptions 9 Trace collection options for children PvmFragSize 10 Message fragment size PvmResvTids 11 Allow messages to reserved tags and TIDs PvmSelfOutputTid 12 Stdout destination PvmSelfOutputCode 13 Output message tag PvmSelfTraceTid 14 Trace data destination PvmSelfTraceCode 15 Trace message tag PvmSelfTraceBuffer 16 Trace buffer size PvmSelfTraceOptions 17 Trace collection options PvmShowTids 18 pvm_catchout prints task ids with output PvmPollType 19 Message wait policy (shared memory) PvmPollTime 20 Message spinwait duration PvmOutputContext 21 Output message context for children PvmTraceContext 22 Trace message context for children PvmSelfOutputContext 23 Output message context PvmSelfTraceContext 24 Trace message context PvmNoReset 25 Do not kill task on reset .fi .br .IP val Integer specifying new setting of option. .sp Predefined values for \fIPvmRoute\fR are: .nf PvmDontRoute 1 Don't request or grant connections PvmAllowDirect 2 (Default) Don't request but allow PvmRouteDirect 3 Request and allow connections .fi .sp Predefined values for \fIPvmTraceOptions\fR are: .nf PvmTraceFull 1 (Default) Do full trace events PvmTraceTime 2 Only do PVM routine timings PvmTraceCount 3 Only do PVM routine profiling (call counts) .fi .sp Predefined values for \fIPvmPollType\fR are: .nf PvmPollConstant 1 Spin on its message queue PvmPollSleep 2 Poll the message queue PvmPollTime times .fi .sp .IP oldval Integer returning the previous setting of the option. .SH DESCRIPTION The routine .I pvm_setopt is a general purpose function used to set miscellaneous options in the PVM library. \fIWhat\fR is one of: .sp .IP PvmRoute Advises PVM on whether to set up direct task-to-task links .I PvmRouteDirect (using TCP) for all subsequent communication. Once a link is established it persists until the application finishes. If a direct link can not be established because one of the two tasks has requested .I PvmDontRoute or because adequate resources aren't available, then the default route through the PVM daemons is used. On multiprocessors such as Intel Paragon this option is ignored because the communication between tasks on these machines always uses the native protocol for direct communication. pvm_setopt can be called multiple times to selectively establish direct links, but is typically set only once near the beginning of each task. .I PvmAllowDirect is the default route setting. This setting on task A allows other tasks to set up direct links to A. Once a direct link is established between tasks both tasks will use it for sending messages. .sp .IP PvmDebugMask When debugging is turned on, PVM will log detailed information about its operations and progress on its \fIstderr\fR stream. \fIval\fR is the debugging level. Default is not to print any debug information. .PP .IP PvmAutoErr When an error results from a libpvm function call and \fIPvmAutoErr\fR is set to 1 (the default), an error message is automatically printed on \fIstderr\fR. A setting of 0 disables this. A setting of 2 causes the library to terminate the task by calling exit() after printing the error message. A setting of 3 causes the library to abort after printing the error message. .sp .IP PvmOutputTid Sets the \fIstdout\fR destination for children tasks (spawned after the call to pvm_setopt). Everything printed on the standard output of tasks spawned by the calling task is packed into messages and sent to the destination. \fIval\fR is the TID of a PVM task. Setting PvmOutputTid to 0 redirects stdout to the master pvmd, which writes to the log file /tmp/pvml. The default setting is inherited from the parent task, else is 0. .sp .IP PvmOutputCode Sets the message tag for standard output messages. Should only be set when a task has \fIPvmOutputTid\fR set to itself. .sp .IP PvmTraceTid Sets the trace data message destination for children tasks (spawned after the call to pvm_setopt). Libpvm trace data is sent as messages to the destination. \fIval\fR is the TID of a PVM task. Setting PvmTraceTid to 0 discards trace data. The default setting is inherited from the parent task, else is 0. .sp .IP PvmTraceCode Sets the message tag for trace data messages. Should only be set when a task has \fIPvmTraceTid\fR set to itself. .sp .IP PvmTraceBuffer Sets the trace buffer size for trace event collection (in bytes). Rather than send a separate message for each trace event, the events are written to a message buffer until the buffer reaches PvmTraceBuffer bytes. Then a single large trace message is sent. This can greatly reduce tracing intrusion. Make sure you call pvm_exit() in your tasks to flush the trace buffer! .sp .IP PvmTraceOptions Sets the PVM built-in tracing options. This is useful for custom trace collection tools to allow analysis of library routine execution times and invocation counts. By default, tracing with \fIPvmTraceFull\fR produces full trace events with calling arguments and return values. Using \fIPvmTraceTime\fR produces total time spent executing each library routine. The \fIPvmTraceCount\fR option keep only a count of the number of times each routine was called. .sp .IP PvmFragSize \fIVal\fR specifies the message fragment size in bytes. Default value varies with host architecture. .sp .IP PvmResvTids A \fIval\fR of 1 enables the task to send messages with reserved tags and to non-task destinations. The default (0) causes libpvm to generate a \fIPvmBadParam\fR error when a reserved identifier is specified. .sp .IP PvmSelfOutputTid Sets the \fIstdout\fR destination for the calling task. Everything printed on \fIstdout\fR is packed into messages and sent to the destination. Note: this only works for spawned tasks, because the pvmd doesn't get the output from tasks started by other means. \fIval\fR is the TID of a PVM task. Setting PvmSelfOutputTid to 0 redirects stdout to the master pvmd, which writes to the log file /tmp/pvml.. The default setting is inherited from the parent task, else is 0. Setting either PvmSelfOutputTid or PvmSelfOutputCode also causes both \fIPvmOutputTid\fR and \fIPvmOutputCode\fR to take on the values of PvmSelfOutputTid and PvmSelfOutputCode, respectively. .sp .IP PvmSelfOutputCode Sets the message tag for standard output messages. .sp .IP PvmSelfTraceTid Sets the trace data message destination for the calling task. Libpvm trace data is sent as messages to the destination. \fIval\fR is the TID of a PVM task. Setting PvmSelfTraceTid to 0 discards trace data. The default setting is inherited from the parent task, else is 0. Setting either PvmSelfTraceTid or PvmSelfTraceCode also causes both \fIPvmTraceTid\fR and \fIPvmTraceCode\fR to take on the values of PvmSelfTraceTid and PvmSelfTraceCode, respectively. .sp .IP PvmSelfTraceCode Sets the message tag for trace data messages. .sp .IP PvmSelfTraceBuffer Sets the trace buffer size for trace event collection (in bytes). .sp .IP PvmSelfTraceOptions Sets the PVM built-in tracing options for the calling task (see PvmTraceOptions). .sp .IP PvmShowTids If true (nonzero), \fIpvm_catchout\fR tags each line of output printed by a child task with the task id. Otherwise, output is exactly as printed. .sp .IP PvmPollType Sets the message wait policy when using shared-memory message transport. Setting PvmPollType to PvmPollConstant causes the application to spin on its message queue waiting for a message. Setting PvmPollType to PvmPollSleep causes the application to poll the message queue for messages PvmPollTime times before pending on the semaphore. .sp .IP PvmPollTime Sets the poll count for applications checking their message queue before they pend on the semaphore. This option is ignored if PvmPollType is set to PvmPollConstant. .sp .IP PvmOutputContext Sets the message context for output collection messages from children. .sp .IP PvmTraceContext Sets the message context for trace data messages from children. .sp .IP PvmSelfOutputContext Sets the message context for output collection from the calling task. .sp .IP PvmSelfTraceContext Sets the message context for trace data messages from the calling task. .sp .IP PvmNoReset When set true (non-zero integer value) informs PVM *not* to kill off the calling task when performing a "reset" command, such as issued by the "pvm" console. .sp .PP pvm_setopt returns the previous value of the option. If an error occurs, the PVM error code is returned in place of the option value. .SH EXAMPLES .nf C: oldval = pvm_setopt( PvmRoute, PvmRouteDirect ); Fortran: CALL PVMFSETOPT( PVMAUTOERR, 1, OLDVAL ) .SH ERRORS This error condition can be returned .IP PvmBadParam giving an invalid value. .PP .SH SEE ALSO pvm_getopt(3PVM) ./pvm3/man/man3/pvm_setrbuf.30100644007401100000360000000312706221604733015137 0ustar kohlgopher.\" $Id: pvm_setrbuf.3,v 1.1 1996/09/23 22:06:19 pvmsrc Exp $ .TH SETRBUF 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_setrbuf \- Switches the active receive buffer and saves the previous buffer. .SH SYNOPSIS .nf .ft B C int oldbuf = pvm_setrbuf( int bufid ) .br Fortran call pvmfsetrbuf( bufid, oldbuf ) .fi .SH PARAMETERS .IP bufid 0.8i Integer specifying the message buffer identifier for the new active receive buffer. .br .IP oldbuf Integer returning the message buffer identifier for the previous active receive buffer. .SH DESCRIPTION The routine .I pvm_setrbuf switches the active receive buffer to .I bufid and saves the previous active receive buffer .I oldbuf. If .I bufid is set to 0 then the present active receive buffer is saved and no active receive buffer exists. .PP A successful receive automatically creates a new active receive buffer. If a previous receive has not been unpacked and needs to be saved for later, then the previous bufid can be saved and reset later to the active buffer for unpacking. .PP The routine is required when managing multiple message buffers. For example switching back and forth between two buffers. One buffer could be used to send information to a graphical interface while a second buffer could be used send data to other tasks in the application. .SH EXAMPLES .nf C: rbuf1 = pvm_setrbuf( rbuf2 ); .sp Fortran: CALL PVMFSETRBUF( NEWBUF, OLDBUF ) .SH ERRORS These error conditions can be returned by .I pvm_setrbuf .IP PvmBadParam giving an invalid bufid. .IP PvmNoSuchBuf switching to a non-existent message buffer. .PP .SH SEE ALSO pvm_setsbuf(3PVM) ./pvm3/man/man3/pvm_setsbuf.30100644007401100000360000000253206221604734015140 0ustar kohlgopher.\" $Id: pvm_setsbuf.3,v 1.1 1996/09/23 22:06:20 pvmsrc Exp $ .TH SETSBUF 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_setsbuf \- Switches the active send buffer. .SH SYNOPSIS .nf .ft B C int oldbuf = pvm_setsbuf( int bufid ) .br Fortran call pvmfsetsbuf( bufid, oldbuf ) .fi .SH PARAMETERS .IP bufid 0.8i Integer the message buffer identifier for the new active send buffer. A value of 0 indicates the default receive buffer. .br .IP oldbuf Integer returning the message buffer identifier for the previous active send buffer. .SH DESCRIPTION The routine .I pvm_setsbuf switches the active send buffer to .I bufid and saves the previous active send buffer .I oldbuf. If .I bufid is set to 0 then the present active send buffer is saved and no active send buffer exists. .PP The routine is required when managing multiple message buffers. For example switching back and forth between two buffers. One buffer could be used to send information to a graphical interface while a second buffer could be used send data to other tasks in the application. .SH EXAMPLES .nf C: sbuf1 = pvm_setsbuf( sbuf2 ); Fortran: CALL PVMFSETSBUF( NEWBUF, OLDBUF ) .fi .SH ERRORS These error conditions can be returned by .I pvm_setsbuf .IP PvmBadParam giving an invalid bufid. .IP PvmNoSuchBuf switching to a non-existent message buffer. .PP .SH SEE ALSO pvm_setrbuf(3PVM) ./pvm3/man/man3/pvm_settmask.30100644007401100000360000000672206221606511015320 0ustar kohlgopher.\" $Id: pvm_settmask.3,v 1.1 1996/09/23 22:20:57 pvmsrc Exp $ .TH SETTMASK 3PVM "16 March, 1994" "" "PVM Version 3.4" .SH NAME pvm_gettmask, pvm_settmask \- Get or set trace mask of a task or its children. .SH SYNOPSIS .nf .ft B C #include #include int info = pvm_gettmask( int who, Pvmtmask mask ) .br int info = pvm_settmask( int who, Pvmtmask mask ) .br Fortran Not Available .fi .SH PARAMETERS .IP who 0.8i Specifies which trace mask to get or set: .ta 4 20 .nf PvmTaskSelf The current task PvmTaskChild Children tasks to be spawned .fi .IP mask Trace mask (owned by caller), which is filled in with the current trace vector on calling pvm_gettmask or used to set the current trace vector on calling pvm_settmask. .br .IP info Status code returned. Values less than zero indicate an error. .SH DESCRIPTION Each task has a trace mask, which can be used to individually enable tracing of each \fIlibpvm\fR function. The mask is inherited from its parent task (or initially all cleared if the task has no parent). When calls are made to functions in libpvm, the parameters and results are sent in messages to the \fItrace sink\fR of the task (variable \fIPvmTraceTid\fR set by calling \fIpvm_setopt\fR - see man page). The PVM console and XPVM use this system to get trace data from application programs. A task can get or set either its own trace mask, or the mask passed to children it spawns. Note the mask must be set before the spawn call; setting the child trace mask has no effect on already-running children. The trace mask can be kept in a temporary variable, declared as: Pvmtmask mymask; Right now, this is a character array with approximately 80 bits. There are four macros defined to manipulate trace masks. Along with the functions, these allow a program to get the current trace mask, modify or save it, and put it back: .nf TEV_INIT_MASK(mask) TEV_SET_MASK(mask, kind) TEV_UNSET_MASK(mask, kind) TEV_CHECK_MASK(mask, kind) .fi TEV_INIT_MASK initializes a mask to all bits cleared and must be used to initialize a trace mask (unless that is done by setting it from pvm_gettmask). TEV_SET_MASK sets a bit in a mask. Bit values are defined in . Likewise, TEV_UNSET_MASK clears a single bit and TEV_CHECK_MASK checks to see if a bit is set, returning nonzero if true. Note: Most events in the trace mask come in pairs, the first (ending in ...0) is generated on entry to a function and the second (...1) on exit. The trace mask has only half as many bits as there are events; events are enabled in pairs. In other words, if you select TEV_SEND0, you'll also get TEV_SEND1. The trace mask is deliberately kept as a printable (and null-terminated) string, for two reasons. First, it is passed through the environment between tasks, in the form: PVMTMASK=@@AAOG@@NO@L@@@@@@@@ so the pvmd doesn't have to explicitly manage it. Second, the mask variables can be passed between tasks using pvm_pkstr() or otherwise manipulated as strings. pvm_gettmask and pvm_settmask return PvmOk on success, else a negative value. .SH EXAMPLES .nf C: #include #include Pvmtmask m; pvm_gettmask( PvmTaskChild, m ); TEV_SET_MASK(m, TEV_ADDHOSTS0 ); pvm_settmask( PvmTaskChild, m ); pvm_spawn( "worker", (char **)0, PvmTaskDefault, "", 1, (int *)0); .SH ERRORS The following error condition can be returned by pvm_gettmask or pvm_settmask: .IP PvmBadParam invalid value for \fIwho\fR argument. .PP .SH SEE ALSO pvm(1PVM), pvm_getopt(3PVM), pvm_setopt(3PVM) ./pvm3/man/man3/pvm_siblings.30100644007401100000360000000470406354544441015307 0ustar kohlgopher.\" $Id: pvm_siblings.3,v 1.1 1997/06/26 19:55:13 pvmsrc Exp $ .TH SIBLINGS 3PVM "26 June, 1997" "" "PVM Version 3.4" .SH NAME pvm_siblings \- return the number and associated task ids of processes that were started together in a single spawn call. .SH SYNOPSIS .nf .ft B C int ntids = pvm_siblings( int **tids ) .br Fortran call pvmfsiblings( ntids, index, sibling ) .fi .SH PARAMETERS .IP ntids 0.8i Returns the number of tids that were spawned together. Value less than 0 indicates an error. .br .IP tids 0.8i Pointer to the array of tids that contains the siblings. Indexed from 0 to (ntids - 1) .br .IP index Integer index of tid to be returned in sibling. If index is set to -1, then sibling is unchanged. Otherwise, must be in the range [0, ntids - 1] .br .IP sibling When index is in the range [0, ntids -1], this contains the tid of the desired index. .SH DESCRIPTION The routine .I pvm_siblings returns the number of tasks and a list of task ids of processes that were spawned together in a single spawn call. The spawning task multicasts the list of successful to the spawned tasks so that each task has an identical copy of the sibling list. .I pvm_siblings uses local storage to keep the list of tids and does not update this list when sibling tasks exit the virtual machine. The FORTRAN version allows calling programs read a particular index in the internal sibling array. If pvm_siblings is successful, .I ntids will be > 0. If some error occurs then .I ntids will be < 0. .PP pvm_siblings is designed to simplify the logic in static spmd-style programs. By giving tasks an identical list of tids and its size, programs may self size and treat the sibling as static map between instances and tasks. The internal list is not updated when sibling tasks exit the virtual machine and should be treated as a snapshot of the parallel program when it was first started. .PP If a task was started by .I pvm_spawn, then .I pvm_siblings will return .I ntids = 1 and .I ntids = 1 and .I tids will contain a single entry identical to the task id returned by .I pvm_mytid() .SH EXAMPLES .nf C: int *tids; ntids = pvm_siblings(&tids); .sp Fortran: INTEGER TIDS(0:MAXNPROC) CALL PVMFSIBLINGS(NTIDS, -1, IDUM) DO I = 0, NTIDS-1 CALL PVMFSIBLINGS(NTIDS, I, TIDS(I)) .fi .SH ERRORS .I pvm_siblings can return the following error codes .IP PvmNoTask No task at that index, or index is invalid. .SH SEE ALSO pvm_spawn(3PVM), pvm_mytid(3PVM), pvm_parent(3PVM) ./pvm3/man/man3/pvm_spawn.30100644007401100000360000001576707271037467014644 0ustar kohlgopher.\" $Id: pvm_spawn.3,v 1.3 2001/04/23 14:41:59 pvmsrc Exp $ .TH SPAWN 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_spawn \- Starts new PVM processes. .SH SYNOPSIS .nf .ft B C int numt = pvm_spawn( char *task, char **argv, int flag, char *where, int ntask, int *tids ) .br Fortran call pvmfspawn( task, flag, where, ntask, tids, numt ) .fi .SH PARAMETERS .IP task 0.8i Character string which is the executable file name of the PVM process to be started. The executable must already reside on the host on which it is to be started. The name may be a file in the PVM search path or an absolute path. The default PVM search path is $HOME/pvm3/bin/$PVM_ARCH/ . .br .IP argv Pointer to an array of arguments to the executable (if supported on the target machine), not including the executable name, with the end of the array specified by NULL. argv[0] of the spawned task is set to the executable path relative to the PVM working directory (or absolute if an absolute filename was specified). If the executable needs no arguments, then the second argument to pvm_spawn is NULL. .br .IP flag Integer specifying spawn options. .ta 0.5i 2.0i 2.5i .nf In C, \fIflag\fR should be the \fIsum\fR of: Option value MEANING PvmTaskDefault 0 PVM can choose any machine to start task PvmTaskHost 1 \fIwhere\fR specifies a particular host PvmTaskArch 2 \fIwhere\fR specifies a type of architecture PvmTaskDebug 4 Start up processes under debugger PvmTaskTrace 8 Processes will generate PVM trace data. * PvmMppFront 16 Start process on MPP front-end. PvmHostCompl 32 Use complement host set In Fortran, \fIflag\fR should be the \fIsum\fR of: Option value MEANING PVMDEFAULT 0 PVM can choose any machine to start task PVMHOST 1 \fIwhere\fR specifies a particular host PVMARCH 2 \fIwhere\fR specifies a type of architecture PVMDEBUG 4 Start up processes under debugger PVMTRACE 8 Processes will generate PVM trace data. * * future extension .fi .IP where Character string specifying where to start the PVM process. Depending on the value of .I flag, .I where can be a host name such as "ibm1.epm.ornl.gov" or a PVM architecture class such as "SUN4". Also, the host name "." is taken as the localhost. If .I flag is 0, then .I where is ignored when determining the target host or architecture, and PVM will select the most appropriate host. .sp The .I where argument can also be used to specify a custom working directory for each given spawn command. This is done by appending a ':' and the desired working directory path to the .I where string, i.e.: .sp "ibm1.epm.ornl.gov:/home/user/project/foo" .sp PVM will temporarily change the working directory to spawn the given task(s), and will then reset to the default working directory after the spawn is executed. This option need not be used in conjunction with either the .I PvmTaskHost or .I PvmTaskArch flags, as the working directory path is stripped off prior to parsing any host or architecture name. A valid specification for .I where is therefore: .sp ":/home/user/project/foo" .sp The working directory can be either an absolute path name or can be relative to the current default working directory. .br .IP ntask Integer specifying the number of copies of the executable to start. .br .IP tids Integer array of length .I ntask returning the tids of the PVM processes started by this pvm_spawn call. .br .IP numt Integer returning the actual number of tasks started. Values less than zero indicate a system error. A positive value less than .I ntask indicates a partial failure. In this case the user should check the .I tids array for the error code(s). .SH DESCRIPTION The routine .I pvm_spawn starts .I ntask copies of the executable named .I task. On systems that support environment, spawn passes selected variables from parent environment to children tasks. If set, the envar \fIPVM_EXPORT\fR is passed. If PVM_EXPORT contains other names (separated by ':') they will be passed too. This is useful for e.g.: .nf setenv DISPLAY myworkstation:0.0 setenv MYSTERYVAR 13 setenv PVM_EXPORT DISPLAY:MYSTERYVAR .fi .PP The hosts on which the PVM processes are started are determined by the .I flag and .I where arguments. On return the array .I tids contains the PVM task identifiers for each process started. .PP If pvm_spawn starts one or more tasks, .I numt will be the actual number of tasks started. If a system error occurs then .I numt will be < 0. If .I numt is less than .I ntask then some executables have failed to start and the user should check the last .I ntask - .I numt locations in the .I tids array which will contain error codes (see below for meaning). The first .I numt tids in the array are always valid. .PP When .I flag is set to 0 and .I where is set to NULL (or "*" in Fortran) a heuristic (round-robin assignment) is used to distribute the .I ntask processes across the virtual machine. .PP If the PvmHostCompl flag is set, the resulting host set gets complemented. Given that the TaskHost host name "." is taken as localhost, these can be used together, for example, to request n - 1 tasks on host "." but with flags TaskHost|HostCompl to spawn n - 1 tasks on hosts other than the localhost. .PP In the special case where a multiprocessor is specified by .I where, pvm_spawn will start all .I ntask copies on this single machine using the vendor's underlying routines. .PP The spawned task will have .I argv[0] set to the the executable path relative to its inherited working directory (or possibly an absolute path), so the base filename can be got by using: .br char *p; .br p = (p = rindex(argv[0], '/')) ? p + 1 : argv[0]; .PP If PvmTaskDebug is set, then the pvmd will start the task(s) under debugger(s). In this case, instead of executing \fIpvm3/bin/ARCH/task args\fR it executes \fIpvm3/lib/debugger pvm3/bin/ARCH/task args\fR. debugger is a shell script that the users can modify to their individual tastes. Presently the script starts an xterm with dbx or comparable debugger in it. .SH EXAMPLES .nf C: numt = pvm_spawn( "host", 0, PvmTaskHost, "sparky", 1, &tid[0] ); numt = pvm_spawn( "host", 0, (PvmTaskHost+PvmTaskDebug), "sparky", 1, &tid[0] ); numt = pvm_spawn( "node", 0, PvmTaskArch, "RIOS", 1, &tid[i] ); char *args[] = { "12", "60" , (char*)0 }; numt = pvm_spawn( "FEM1", args, 0, 0, 16, tids ); numt = pvm_spawn( "pde", 0, PvmTaskHost, "paragon.ornl", 512, tids ); .sp Fortran: FLAG = PVMARCH + PVMDEBUG CALL PVMFSPAWN( 'node', FLAG, 'SUN4', 1, TID(3), NUMT ) CALL PVMFSPAWN( 'FEM1', PVMDEFAULT, '*', 16, TIDS, NUMT ) CALL PVMFSPAWN( 'TBMD', PVMHOST, 'cm5.utk.edu', 32, TIDS, NUMT ) .SH ERRORS These error conditions can be returned by .I pvm_spawn either in .I numt or in the .I tids array. .IP PvmBadParam giving an invalid argument value. .IP PvmNoHost Specified host is not in the virtual machine. .IP PvmNoFile Specified executable cannot be found. The default location PVM looks in is ~/pvm3/bin/ARCH, where ARCH is a PVM architecture name. .IP PvmNoMem Malloc failed. Not enough memory on host. .IP PvmSysErr pvmd not responding. .IP PvmOutOfRes out of resources. .PP .SH SEE ALSO pvm_export(3PVM) ./pvm3/man/man3/pvm_start_pvmd.30100644007401100000360000000377306313337500015654 0ustar kohlgopher.\" $Id: pvm_start_pvmd.3,v 1.2 1997/03/17 22:01:36 pvmsrc Exp $ .TH START_PVMD 3PVM "11 December, 1995" "" "PVM Version 3.4" .SH NAME pvm_start_pvmd \- Starts new PVM daemon. .SH SYNOPSIS .nf .ft B C int info = pvm_start_pvmd( int argc, char **argv, int block ) .br Fortran call pvmfstartpvmd( args, block, info ) .fi .SH PARAMETERS .IP argc 0.8i Number of arguments in argv. .br .IP argv An array of arguments to the executable. .br .IP args A character string containing the arguments to the executable. .br .IP args A character string containing the arguments to the executable. .br .IP block Integer specifying whether to block until startup of all hosts complete or return immediately. .br .IP info Integer returning the error code. .SH DESCRIPTION The routine .I pvm_start_pvmd starts up a pvmd3 process, the master of a new virtual machine. It returns as soon as the pvmd is started and ready for work. If the block parameter is nonzero and a hostfile is passed to the pvmd as a parameter, it returns when all hosts marked to start have been added. pvm_start_pvmd returns zero on success. If PVM is compiled to allow running more than one pvmd per host, a task calling pvm_start_pvmd before any other pvm functions will connect to the pvmd that it starts. pvm_start_pvmd sets environment variable \fIPVMSOCK\fR to the address printed by the pvmd as it starts up. .SH EXAMPLES .nf C: static char *argv[] = { "-d41", "/u/jones/pvmd_hosts", }; argc = 2 info = pvm_start_pvmd( argc, argv, block ); .sp Fortran: CALL PVMFSTART_PVMD( '-d41 /u/jones/pvmd_hosts', BLOCK, INFO ) .fi .SH EXAMPLES .nf C: static char *argv[] = { "-d41", "/u/jones/pvmd_hosts", }; argc = 2 info = pvm_start_pvmd( argc, argv, block ); .sp Fortran: CALL PVMFSTART_PVMD( '-d41 /u/jones/pvmd_hosts', BLOCK, INFO ) .fi .SH ERRORS The following error conditions can be returned .IP PvmDupHost A pvmd is already running. .IP PvmSysErr The local pvmd is not responding. .PP .SH SEE ALSO pvm_addhosts(3PVM), pvmd3(1PVM) pvmd3(1PVM) ./pvm3/man/man3/pvm_tasks.30100644007401100000360000000547206221606515014617 0ustar kohlgopher.\" $Id: pvm_tasks.3,v 1.1 1996/09/23 22:21:01 pvmsrc Exp $ .TH TASKS 3PVM "31 August, 1994" "" "PVM Version 3.4" .SH NAME pvm_tasks \- Returns information about the tasks running on the virtual machine. .SH SYNOPSIS .nf .ft B C int info = pvm_tasks( int where, int *ntask, struct pvmtaskinfo **taskp ) struct pvmtaskinfo { int ti_tid; int ti_ptid; int ti_host; int ti_flag; char *ti_a_out; } taskp; .br Fortran call pvmftasks( where, ntask, tid, ptid, dtid, flag, aout, info ) .fi .SH PARAMETERS .IP where 0.8i Integer specifying what tasks to return information about. The options are: .ta 0.5i 1.5i .nf 0 for all the tasks on the virtual machine pvmd tid for all tasks on a given host tid for a specific task .fi .IP ntask Integer returning the number of tasks being reported on. .br .IP taskp Returns pointer to an array of structures which contain information about each task including its task ID, parent tid, pvmd task ID, status flag, and the name of this task's executable file. The status flag values are: waiting for a message, waiting for the pvmd, and running. .br .IP tid Integer returning task ID of one task .br .IP ptid Integer returning parent task ID .br .IP dtid Integer returning pvmd task ID of host task is on. .br .IP flag Integer returning status of task .br .IP aout Character string returning the name of spawned task. Manually started tasks return blank. .br .IP info Integer status code returned by the routine. Values less than zero indicate an error. .SH DESCRIPTION The routine .I pvm_tasks returns information about tasks presently running on the virtual machine. The information returned is the same as that available from the console command .I ps. The C function returns information about the entire virtual machine in one call. The Fortran function returns information about one task per call and cycles through all the tasks. Thus, if where = 0, and .I pvmftasks is called ntask times, all tasks will be represented. Note that in Fortran the reported value of ntask and the set of tasks do not change until the function resets at the end of a complete cycle. The user can reset pvmftasks() at any time by calling it with .I ntask = -1. If pvm_tasks is successful, .I info will be 0. If some error occurs then .I info will be < 0. .SH EXAMPLES .nf C: struct pvmtaskinfo *taskp; int i, ntask; info = pvm_tasks( 0, &ntask, &taskp ); for (i = 0; i < ntask; i++) printf("t%x\\n", taskp[i].ti_tid); Fortran: Do i=1, NTASK CALL PVMFTASKS( DTID, NTASK, TID(i), PTID(i), DTID(i), & FLAG(i), AOUT(i), INFO ) EndDo .SH ERRORS The following error condition can be returned by .I pvm_tasks .IP PvmBadParam invalid value for \fIwhere\fR argument. .IP PvmSysErr pvmd not responding. .IP PvmNoHost specified host not in virtual machine. .PP .SH SEE ALSO pvm_config(3PVM), pvm_tidtohost(3PVM) ./pvm3/man/man3/pvm_tidtohost.30100644007401100000360000000142706221606517015511 0ustar kohlgopher.\" $Id: pvm_tidtohost.3,v 1.1 1996/09/23 22:21:03 pvmsrc Exp $ .TH TIDTOHOST 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_tidtohost \- Returns the host of the specified PVM process. .SH SYNOPSIS .nf .ft B C int dtid = pvm_tidtohost( tid ) .br Fortran call pvmftidtoh( tid, dtid ) .fi .SH PARAMETERS .IP tid 0.8i Integer task identifier of the PVM process in question. .br .IP dtid Integer returns the tid of the host's pvmd3 or a negative value if an error. .SH DESCRIPTION The routine .I pvm_tidtohost returns the host id on which the process identified by .I tid is located. .SH ERRORS The following error conditions can be returned .IP PvmBadParam An invalid tid value was specified. .IP PvmSysErr pvmd not responding. .PP .SH SEE ALSO pvm_config(3PVM), pvm_tasks(3PVM) ./pvm3/man/man3/pvm_trecv.30100644007401100000360000000652706221606520014613 0ustar kohlgopher.\" $Id: pvm_trecv.3,v 1.1 1996/09/23 22:21:04 pvmsrc Exp $ .TH TRECV 3PVM "8 February, 1994" "" "PVM Version 3.4" .SH NAME pvm_trecv \- Receive with timeout. .SH SYNOPSIS .nf .ft B .nf C #include .br int bufid = pvm_trecv( int tid, int msgtag, struct timeval *tmout ) .br Fortran call pvmftrecv( tid, msgtag, sec, usec, bufid ) .fi .SH PARAMETERS .IP tid 0.8i Integer to match task identifier of sending process. .br .IP msgtag Integer to match message tag; should be >= 0. .br .IP tmout (or \fIsec\fR and \fIusec\fR) Time to wait before returning without a message. .br .IP bufid Integer returns the value of the new active receive buffer identifier. Values less than zero indicate an error. .SH DESCRIPTION The routine \fIpvm_trecv\fR blocks the process until a message with label \fImsgtag\fR has arrived from \fItid\fR. pvm_trecv then places the message in a new \fIactive\fR receive buffer, also clearing the current receive buffer. If no matching message arrives within the specified waiting time, pvm_trecv returns without a message. .PP A -1 in \fImsgtag\fR or \fItid\fR matches anything. This allows the user the following options. If \fItid\fR = -1 then pvm_trecv will accept a message from any process which has a matching \fImsgtag\fR. If \fImsgtag\fR = -1 then pvm_trecv will accept any message that is sent from process \fItid\fR. If \fItid\fR and \fImsgtag\fR are both -1, then pvm_trecv will accept any message from any process. .PP In C, the \fItmout\fR fields tv_sec and tv_usec specify how long pvm_trecv will wait without returning a matching message. In Fortran, two separate parameters, \fIsec\fR and \fIusec\fR are passed. With both set to zero, pvm_trecv behaves the same as \fIpvm_nrecv\fR, which is to probe for messages and return immediately even if none are matched. In C, passing a null pointer in \fItmout\fR makes pvm_trecv act like \fIpvm_recv\fR, that is, it will wait indefinitely. In Fortran, setting \fIsec\fR to -1 has the same effect. .PP The PVM model guarantees the following about message order. If task 1 sends message A to task 2, then task 1 sends message B to task 2, message A will arrive at task 2 before message B. Moreover, if both messages arrive before task 2 does a receive, then a wildcard receive will always return message A. .PP If pvm_trecv is successful, \fIbufid\fR will be the new active receive buffer identifier. If no message is received, pvm_trecv returns 0. If some error occurs then \fIbufid\fR will be < 0. .PP Once pvm_trecv returns, the data in the message can be unpacked into the user's memory using the unpack routines. .SH EXAMPLES .nf C: struct timeval tmout; tid = pvm_parent(); msgtag = 4 ; tmout.tv_sec = 60; tmout.tv_usec = 0; if ((bufid = pvm_trecv( tid, msgtag, &tmout )) > 0) { pvm_upkint( tid_array, 10, 1 ); pvm_upkint( problem_size, 1, 1 ); pvm_upkfloat( input_array, 100, 1 ); } .sp Fortran: CALL PVMFTRECV( -1, 4, 60, 0, BUFID ) IF (BUFID .EQ. 0) GO TO 666 CALL PVMFUNPACK( INTEGER4, TIDS, 25, 1, INFO ) CALL PVMFUNPACK( REAL8, MATRIX, 100, 100, INFO ) 666 CONTINUE .fi .SH ERRORS These error conditions can be returned by .I pvm_trecv .IP PvmBadParam giving an invalid tid value, or msgtag < -1. .IP PvmSysErr pvmd not responding. .PP .SH SEE ALSO pvm_bufinfo(3PVM), pvm_getminfo(3PVM), pvm_nrecv(3PVM), pvm_recv(3PVM), pvm_unpack(3PVM), pvm_probe(3PVM), pvm_send(3PVM), pvm_mcast(3PVM) ./pvm3/man/man3/pvm_unexport.30100644007401100000360000000012506221606521015341 0ustar kohlgopher.\" $Id: pvm_unexport.3,v 1.1 1996/09/23 22:21:05 pvmsrc Exp $ .so man3/pvm_export.3 ./pvm3/man/man3/pvm_unpack.30100644007401100000360000001364206221606523014750 0ustar kohlgopher.\" $Id: pvm_unpack.3,v 1.1 1996/09/23 22:21:07 pvmsrc Exp $ .TH UNPACK 3PVM "30 August, 1993" "" "PVM Version 3.4" .SH NAME pvm_unpack \- Unpack the active message buffer into arrays of prescribed data type. .SH SYNOPSIS .ft B .nf C .br int info = pvm_unpackf( const char *fmt, ... ) .br int info = pvm_upkbyte( char *xp, int nitem, int stride) .br int info = pvm_upkcplx( float *cp, int nitem, int stride) .br int info = pvm_upkdcplx( double *zp, int nitem, int stride) .br int info = pvm_upkdouble( double *dp, int nitem, int stride) .br int info = pvm_upkfloat( float *fp, int nitem, int stride) .br int info = pvm_upkint( int *ip, int nitem, int stride) .br int info = pvm_upkuint( unsigned int *ip, int nitem, int stride ) .br int info = pvm_upkushort( unsigned short *ip, int nitem, int stride ) .br int info = pvm_upkulong( unsigned long *ip, int nitem, int stride ) .br int info = pvm_upklong( long *ip, int nitem, int stride) .br int info = pvm_upkshort( short *jp, int nitem, int stride) .br int info = pvm_upkstr( char *sp ) Fortran .br call pvmfunpack( what, xp, nitem, stride, info ) .fi .SH PARAMETERS .IP fmt 0.8i Printf-like format expression specifying what to pack. (See discussion) .br .IP nitem The total number of \fIitems\fR to be unpacked (not the number of bytes). .\" For example, if nitem = 5 in pvm_upkdouble, then 5 double precision .\" floating point values will be unpacked. .br .IP stride The stride to be used when packing the items. For example, if stride = 2 in pvm_upkcplx, then every other complex number will be unpacked. .br .IP xp Pointer to the beginning of a block of bytes. Can be any data type, but must match the corresponding pack data type. .br .IP cp Complex array at least nitem*stride items long. .br .IP zp Double precision complex array at least nitem*stride items long. .br .IP dp Double precision real array at least nitem*stride items long. .br .IP fp Real array at least nitem*stride items long. .br .IP ip Integer array at least nitem*stride items long. .br .IP jp Integer*2 array at least nitem*stride items long. .br .IP sp Pointer to a null terminated character string. .br .IP what Integer specifying the type of data being unpacked. .sp .ce \fIwhat\fR options .ta 0.5i 2.0i 2.5i 4.0i .nf STRING 0 REAL4 4 BYTE1 1 COMPLEX8 5 INTEGER2 2 REAL8 6 INTEGER4 3 COMPLEX16 7 .fi .IP info Integer status code returned by the routine. Values less than zero indicate an error. .SH DESCRIPTION Each of the pvm_upk* routines unpacks an array of the given data type from the active receive buffer. The arguments for each of the routines are a pointer to the array to be unpacked into, .I nitem which is the total number of items to unpack, and .I stride which is the stride to use when unpacking. .PP An exception is pvm_upkstr() which by definition unpacks a NULL terminated character string and thus does not need .I nitem or .I stride arguments. The Fortran routine pvmfunpack( STRING, ... ) expects .I nitem to be the number of characters in the string and .I stride to be 1. .PP If the unpacking is successful, .I info will be 0. If some error occurs then .I info will be < 0. .PP A single variable (not an array) can be unpacked by setting .I nitem = 1 and .I stride = 1. .PP The routine pvm_unpackf() uses a printf-like format expression to specify what and how to unpack data from the receive buffer. All variables are passed as addresses. A BNF-like description of the format syntax is: .br format : null | init | format fmt .br init : null | '%' '+' .br fmt : '%' count stride modifiers fchar .br fchar : 'c' | 'd' | 'f' | 'x' | 's' .br count : null | [0-9]+ | '*' .br stride : null | '.' ( [0-9]+ | '*' ) .br modifiers : null | modifiers mchar .br mchar : 'h' | 'l' | 'u' Formats: .nf + means initsend - must match an int (how) in the param list. c pack/unpack bytes d integer f float x complex float s string Modifiers: h short (int) l long (int, float, complex float) u unsigned (int) '*' count or stride must match an int in the param list. .fi .PP Future extensions to the .I what argument in pvmfunpack will include 64 bit types when XDR encoding of these types is available. Meanwhile users should be aware that precision can be lost when passing data from a 64 bit machine like a Cray to a 32 bit machine like a SPARCstation. As a mnemonic the .I what argument name includes the number of bytes of precision to expect. By setting encoding to PVMRAW (see pvmfinitsend) data can be transferred between two 64 bit machines with full precision even if the PVM configuration is heterogeneous. .PP Messages should be unpacked exactly like they were packed to insure data integrity. Packing integers and unpacking them as floats will often fail because a type encoding will have occurred transferring the data between heterogeneous hosts. Packing 10 integers and 100 floats then trying to unpack only 3 integers and the 100 floats will also fail. .SH EXAMPLES .nf C: info = pvm_recv( tid, msgtag ); info = pvm_upkstr( string ); info = pvm_upkint( &size, 1, 1 ); info = pvm_upkint( array, size, 1 ); info = pvm_upkdouble( matrix, size*size, 1 ); .sp int count, *iarry; double darry[4]; pvm_unpackf("%d", &count); pvm_unpackf("%*d %4lf", count, iarry, darry); .sp Fortran: CALL PVMFRECV( TID, MSGTAG, INFO ); CALL PVMFUNPACK( INTEGER4, NSIZE, 1, 1, INFO ) CALL PVMFUNPACK( STRING, STEPNAME, 8, 1, INFO ) CALL PVMFUNPACK( REAL4, A(5,1), NSIZE, NSIZE , INFO ) .fi .SH ERRORS .IP PvmNoData Reading beyond the end of the receive buffer. Most likely cause is trying to unpack more items than were originally packed into the buffer. .IP PvmBadMsg The received message can not be decoded. Most likely because the hosts are heterogeneous and the user specified an incompatible encoding. Try setting the encoding to PvmDataDefault (see pvm_mkbuf). .IP PvmNoBuf There is no active receive buffer to unpack. .PP .SH SEE ALSO pvm_pack(3PVM) pvm_send(3PVM), pvm_recv(3PVM), pvm_pkmesg(3PVM) ./pvm3/man/man3/pvm_unpackf.30100644007401100000360000000012406221606524015106 0ustar kohlgopher.\" $Id: pvm_unpackf.3,v 1.1 1996/09/23 22:21:08 pvmsrc Exp $ .so man3/pvm_unpack.3 ./pvm3/man/man3/pvm_upkbyte.30100644007401100000360000000012406221606525015143 0ustar kohlgopher.\" $Id: pvm_upkbyte.3,v 1.1 1996/09/23 22:21:09 pvmsrc Exp $ .so man3/pvm_unpack.3 ./pvm3/man/man3/pvm_upkcplx.30100644007401100000360000000012406221606527015150 0ustar kohlgopher.\" $Id: pvm_upkcplx.3,v 1.1 1996/09/23 22:21:11 pvmsrc Exp $ .so man3/pvm_unpack.3 ./pvm3/man/man3/pvm_upkdcplx.30100644007401100000360000000012506221606530015307 0ustar kohlgopher.\" $Id: pvm_upkdcplx.3,v 1.1 1996/09/23 22:21:12 pvmsrc Exp $ .so man3/pvm_unpack.3 ./pvm3/man/man3/pvm_upkdouble.30100644007401100000360000000012606221606531015451 0ustar kohlgopher.\" $Id: pvm_upkdouble.3,v 1.1 1996/09/23 22:21:13 pvmsrc Exp $ .so man3/pvm_unpack.3 ./pvm3/man/man3/pvm_upkfloat.30100644007401100000360000000012506221606532015304 0ustar kohlgopher.\" $Id: pvm_upkfloat.3,v 1.1 1996/09/23 22:21:14 pvmsrc Exp $ .so man3/pvm_unpack.3 ./pvm3/man/man3/pvm_upkint.30100644007401100000360000000012306221606534014771 0ustar kohlgopher.\" $Id: pvm_upkint.3,v 1.1 1996/09/23 22:21:16 pvmsrc Exp $ .so man3/pvm_unpack.3 ./pvm3/man/man3/pvm_upklong.30100644007401100000360000000012406221606535015140 0ustar kohlgopher.\" $Id: pvm_upklong.3,v 1.1 1996/09/23 22:21:17 pvmsrc Exp $ .so man3/pvm_unpack.3 ./pvm3/man/man3/pvm_upkmesg.30100644007401100000360000000012406221606536015135 0ustar kohlgopher.\" $Id: pvm_upkmesg.3,v 1.1 1996/09/23 22:21:18 pvmsrc Exp $ .so man3/pvm_pkmesg.3 ./pvm3/man/man3/pvm_upkshort.30100644007401100000360000000012506221606540015335 0ustar kohlgopher.\" $Id: pvm_upkshort.3,v 1.1 1996/09/23 22:21:20 pvmsrc Exp $ .so man3/pvm_unpack.3 ./pvm3/man/man3/pvm_upkstr.30100644007401100000360000000012306221606541015005 0ustar kohlgopher.\" $Id: pvm_upkstr.3,v 1.1 1996/09/23 22:21:21 pvmsrc Exp $ .so man3/pvm_unpack.3 ./pvm3/man/man3/pvm_upkuint.30100644007401100000360000000012406221606542015156 0ustar kohlgopher.\" $Id: pvm_upkuint.3,v 1.1 1996/09/23 22:21:22 pvmsrc Exp $ .so man3/pvm_unpack.3 ./pvm3/man/man3/pvm_upkulong.30100644007401100000360000000012506221606544015326 0ustar kohlgopher.\" $Id: pvm_upkulong.3,v 1.1 1996/09/23 22:21:24 pvmsrc Exp $ .so man3/pvm_unpack.3 ./pvm3/man/man3/pvm_upkushort.30100644007401100000360000000012606221606545015530 0ustar kohlgopher.\" $Id: pvm_upkushort.3,v 1.1 1996/09/23 22:21:25 pvmsrc Exp $ .so man3/pvm_unpack.3 ./pvm3/man/WIN32/0042755007401100000360000000000010117676455012476 5ustar kohlgopher./pvm3/man/WIN32/Pvmhelp.GID0100644007401100000360000002066406670053503014431 0ustar kohlgopher?_!ÿÿÿÿ´!/&;)z4ÿÿÀÿÿÿÿ|FILES|Flags®|KWBTREEP|KWMAP|Pete«/&;)F!ÿÿÿÿÿÿFAQsInstallationU„Introductionlibpvm3, libfpvm3 libraryz‰pvm consoleæPVM Fortran Interface€€PVM Message Passing Functions€pvmd3 daemon€/&;)L4zÿÿ—ÿÿÿÿN=C:\Program Files\pvm3.4\man\Pvmhelp.hlp'C:\Program Files\pvm3.4\man\Pvmhelp.CNTýô‡,ÿÿÿÿ  ËÊ4./pvm3/man/WIN32/Pvmhelp.hlp0100644007401100000360000121050406654443021014604 0ustar kohlgopher?_éÿÿÿÿDÙÐl!ËÊ4(Parallel Virtual Machine (PVM) 3.4 HELPBrowseButtons()ZmainmainParallel Virtual Machine (PVM) 3.4 HELP  /&;)z4ÿÿ \ ÿÿÿÿDOUGHBOY.WMF®PVM.WMF‘+|CONTEXTÔ|CTXOMAPl·|FONT‚µ|KWBTREE±·|KWDATAw·|KWMAP ·|SYSTEM|TOPIC|TTLBTREEà»|bm0>Ü|bm1+æj°a°ÿÿÿÿ = ÿÿÿÿI1ÿÿÿÿ€I{PIntroduction2 {# €€€‚ÿIntroduction&I¡# €€€‚ÿD {å8 @€€€‚‚‚€†"€€‚‚‚‚ÿ(¡ $ €€€‚‚ÿæåóI `€;€€€€‚‚€‚ãñnõ‰ã}$á‰ã›®tö‰ã Ùµ-‰‚‚ÿParallel Virtual Machine (PVM) Version 3.4Check out PVM Intro or pvm console or pvmd3 daemon or libpvm3, libfpvm3 library for an overview.ýÔ ð) €©€dCP È:‚H€‚‚ÿAny comments on our project, bug reports and hints are welcome. You can contact us at pvm@msr.epm.ornl.gov or you can find us on the internet by browsing for latest information to http://www.epm.ornl.gov/pvm.(ó$ €€€‚‚ÿ8ðP& €$€€€‚ÿYour PVM Team.: Š1Ê ÿÿÿÿ抹j„PVM Intro/ P¹# €€€‚ÿPVM IntroB Šû7 >€€€‚‚‚‚€†"€€‚‚ÿ‰H¹„A P€‘€€‚‚‚€€€‚‚€€‚‚‚ã Ùµ-‰‚ÿParallel Virtual Machine (PVM) Version 3.4DESCRIPTIONPVM is a software system that enables a collection of heterogeneous computers to be used as a coherent and flexible concurrent computational resource. The individual computers may be shared- or local-memory multiprocessors, vector supercomputers, specialized graphics engines, or scalar workstations, that may be interconnected by a variety of networks, such as ethernet, FDDI.User programs written in C, C++ or Fortran access PVM through library routines (libpvm3.a and libfpvm3.a libpvm3, libfpvm3 library ). Ïû: B€Ÿ€€‚ã›®tö‰‚‚€€‚‚ƒ‚ƒ‚ƒ‚ÿDaemon programs (pvmd3 daemon) provide communication and process control between computers.MACHINE ARCHITECTUREIn the PVM system, machines are assigned a short string to identify their architectures (this includes operating system type as well as CPU type). The types currently predefined in the distribution are: AFX8 Alliant FX/8 ALPHA DEC Alpha/OSF-1 ALPHAMP DEC Alpha/OSF-1 / using shared memoryå„¥ 3 4€Ë€€ƒ‚ƒ‚ƒ‚‚ƒ‚ƒ‚ƒ‚‚ƒ‚ÿ AIX46K IBM/RS6000 / AIX 4.x AIX4MP IBM SMP / shared memory transport / AIX 4.x AIX4SP2 IBM SP-2 / using MPI / AIX 4.x APOLLO HP 300 running Domain/OS ATT AT&T/NCR 3600 running SysVR4 BAL Sequent Balance BFLY BBN Butterfly TC2000 BSD386 80[345]86 running BSDI or BSD386 CM2 Thinking Machines CM-2 Sun front-end Ó° 8 >€§€€ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ÿ CM5 Thinking Machines CM-5 CNVX Convex using IEEE floating-point CNVXN Convex using native f.p. CRAY Cray CRAY2 Cray-2 CRAYSMP Cray S-MP CSPP Convex Exemplar DGAV Data General Aviion E88K Encore 88000 FREEBSD 80[345]86 running FreeBSD HP300 HP 9000 68000 cpu-ô¥ Ý9 @€é€€ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ÿ HPPA HP 9000 PA-Risc HPPAMP HP 9000 PA-Risc / shared memory transport KSR1 Kendall Square I860 Intel RX Hypercube IPSC2 Intel IPSC/2 LINUX 80[3456]86 running Linux M88K Motorola M88100 running Real/IX M88K Motorola M88100 running Real/IX MASPAR Maspar MIPS Mips NETBSDAMIGA Amiga running NetBSDϰ ï@7 <€Ÿ€€ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ÿ NETBSDHP300 HP 300 running NetBSD NETBSDI386 80[345]86 running NetBSD NETBSDMAC68K Macintosh running NetBSD NETBSDPMAX DEC Pmax running NetBSD NETBSDSPARC Sparc running Ýï@PNetBSD NETBSDSUN3 SUN 3 running NetBSD NEXT NeXT PGON Intel Paragon PMAX DEC/Mips arch (3100, 5000, etc.) RS6K IBM/RS6000 / AIX 3.x#ðÝC3 4€á€€ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ÿ RS6KMP IBM SMP / shared memory transport / AIX 3.x RT IBM/RT SCO 80[345]86 running SCO Unix SGI Silicon Graphics IRIS SGI5 Silicon Graphics IRIS running OS >= 5.0 SGI64 Silicon Graphics IRIS running OS >= 6.0 SGIMP Silicon Graphics IRIS / OS 5.x / using shared memory SGIMP64 Silicon Graphics IRIS / OS 6.x / using shared memory&îï@8E8 >€Ý€€ƒ‚ƒ‚ƒ‚ƒ‚‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ÿ SP2MPI IBM SP-2 / using MPI / AIX 3.x SUN3 Sun 3 SUN4 Sun 4, 4c, sparc, etc. SUN4SOL2 Sun 4 running Solaris 2.x SUNMP Sun 4 / using shared memory / Solaris 2.x SX3 NEC SX-3 SYMM Sequent Symmetry TITN Stardent Titan U370 IBM 3090 running AIX UTS2 Amdahl running UTS UVAX DEC/Microvax*ùCbG1 0€ó€€ƒ‚ƒ‚ƒ‚ƒƒ‚‚‚‚‚‚ÿ UXPM Fujitsu running UXP/M VCM2 Thinking Machines CM-2 Vax front-end X86SOL2 80[345]86 running Solaris 2.x WIN32PC's running Windows95 or NT (Intel, Alpha)ENVIRONMENT VARIABLES PVM_ROOT The path where PVM libraries and system programs are installed, for example /usr/local/pvm3 or $HOME/pvm3. This variable must be set on each host where PVM is used in order for PVM to function. There is no default value.Õ8EcK, &€«€€‚‚‚‚‚‚‚‚‚ÿ PVM_EXPORT Names of environment variables to export from a parent task to children tasks through (). Multiple names must be separated by ':'. If PVM_EXPORT is not set, no environment is exported. PVM_DEBUGGER The debugger script to use when pvm_spawn is called with PvmTaskDebug set. The default is $PVM_ROOT/lib/debugger. PVM_DPATH [v3.3.2 and later] The path of the pvmd startup script (default is $PVM_ROOT/lib/pvmd). It is overridden by host file option dx=. This variable is useful if you use a shell that doesn't automatically execute a startup script (such as .cshrc) to allow setting PVM_ROOT on slave (added) hosts. If you set it to the absolute or relative path of the pvmd startup script (for example /usr/local/pvm3/lib/pvmd or pvm3/lib/pvmd), the script will automatically set PVM_ROOT. Note that for this to work, you must set it to run the pvmd script, not the pvmd3 executable itself.ôÈbGWN, &€‘€€‚‚‚‚‚‚‚‚‚ÿ PVMDLOGMAX [v3.3.8 and later] Sets the maximum length of the pvmd error log file. Default value is the PVMDLOGMAX parameter in the source, 1 Mbyte. PVMDDEBUG [v3.3.8 and later] Sets the default pvmd debugging mask (as does the pvmd -d option). Value can be in hexadecimal (0x...), octal (0...) or decimal. Used to debug the pvmd (not intended to be used to debug application programs). PVMTASKDEBUG [v3.3.8 and later] Sets the default libpvm debugging mask (as does pvm_setopt(PvmDebugMask, x)). Value can be in hexadecimal (0x...), octal (0...) or decimal. Used to debug libpvm (not intended to be used to debug application programs).ϦcK2) €M€€‚‚‚‚‚‚ÿ PVMBUFSIZE Sets the size of the shared memory buffers used by libpvm and the pvmd. The default value is 1048576. If your program composes messages longer than this size, you must increase it. PVMKEY PVM uses this value, combined with the process id, to generate shared-memory segment keys. The default value is your numeric uid. PVM automWN2Patically detects collisions when generating a key and picks a new key, so it should almost never need to be set explicitly. The following environment variables are used by PVM internally. With the exception of PVM_ARCH, their values should not be modified. This is for information only.¤yWNÖƒ+ $€ó€€‚‚‚‚‚‚‚‚ÿ PVM_ARCH The PVM architecture name of the host on which it is set, used to distinguish between machines with different executable (a.out) formats. Copies of a program for different architectures are installed in parallel directories named for PVM architectures. PVMSOCK Is passed from pvmd to spawned task, and gives the address of the pvmd local socket. PVMEPID Holds the expected process id of a spawned task exec'd by the pvmd. This is a magic cookie used by the task to identify itself when reconnecting to the pvmd, in order to get the correct task slot.”m2j„' €Ú€€‚‚‚‚‚ÿ PVMTMASK [v3.3 and later] The libpvm trace mask, passed from the pvmd to spawned tasks.< Öƒ¦„1M ª€¦„ׄÿÀpvm console1j„ׄ# €€€‚ÿpvm console—b¦„n‡5 8€Å€€€‚‚‚‚‚‚€€‚‚‚ÿpvm PVM version 3 consoleSYNOPSISpvm [ -options ] [ hostfile ]DESCRIPTIONPvm is a stand alone PVM task which allows the user to interactively query and modify the virtual machine. The console can be started and stopped multiple times on any of the hosts in the virtual machine without affecting PVM or any applications that may be running. When started pvm determines if PVM is already running and if not automatically executes pvmd3 on this host, passing pvmd3 the command line options and host file. Thus PVM need not be running to start the console. Once started the console prints the prompt:4öׄ¢‰> J€í€€‚ƒ‚‚‚‚ƒ‚ƒƒ‚ƒƒ‚ƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒ‚ÿpvm>The following console commands are available: add hostname(s) Add hosts to virtual machine alias Define/list command aliases conf List virtual machine configuration delete hostname(s) Delete hosts from virtual machine echo Echo arguments export Add environment variables to spawn export list halt Stop pvmds help [command] Print helpful information about a command Ën‡¬‹? L€—€€ƒƒ‚ƒƒ‚ƒƒ‚ƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒ‚ÿ id Print console task id jobs List running jobs kill task-tid Terminate tasks mstat host, tid Show status of hosts ps -a List all PVM tasks pstat task-tid Show status of tasks quit Exit console reset Kill all tasks setenv Display/set environment variables sig signum task Send signal to taskߢ‰Ä9 @€¿€€ƒ‚ƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒ‚ƒ‚ƒ‚ƒƒ‚ÿ spawn [opt] a.out Spawn task opts are: -(count) number of tasks, default is 1 -(host) spawn on host, default is any -(ARCH) spawn on hosts of ARCH -? enable debugging -> redirect task output to console -> file redirect task output to file ->>file redirect task output append to file trace Set/display trace event maskѬ‹Õ@ N€£€€ƒƒ‚ƒƒ‚ƒƒ‚‚‚‚‚‚‚‚‚‚€€‚ƒ‚‚‚ÿ unexport Remove environment variables from spawn export list unalias Undefine command alias version Show libpvm versionpvm reads $HOME/.pvmrc before reading commands from the tty, so it can be used to customize the console environment, for example: alias ? help alias j jobs setenv PVM_EXPORT DISPLAY # print my id echo new pvm shell idEXAMPLESpvmStarts up pvmd3 on the local host or connects to running pvmd3.åÄÿÀ9 @€Ë€€‚ƒ‚‚‚‚‚ãÕÿÀj„ñnõ‰‚ã›®tö‰‚‚ÿpvm d:\users\fischer\pvmhostfile.txtStarts up console and pvmd3, which inturn reads the host file and adds the listed computers to the virtual machine. ( full path required on WIN32 )see alsoPVM Intropvmd3 daemon= Õ<Á1³)æz‰<ÁnÁ´Jpvmd3 daemon2ÿÀnÁ# €€€‚ÿpvmd3 daemon$ï<Á’Ã5 8€ß€€€‚‚‚‚‚‚€€‚‚‚ÿpvmd, pvmd3 PVM daemonSYNOPSISpvmd [ -options] [ hostfile ] &DESCRIPTIONPvmd3 is a daemon process which coordinates unix hosts in a virtual machine. One pvmd3 must run on each host in the group. They provide the communication and process control functions needed by the user's PVM processes. The daemon can be started manually with a host file argument that will automatically start the remote pvmds. The local and remote pvmds can also be started from the PVM console program pvm.v>nÁÆ8 >€}€€‚‚‚‚€€‚‚‚€€‚‚ÿThe name of the daemon executable is pvmd3. It is usually started by a shell script, %PVM_ROOT%/lib/pvmd.[v3.4 and later] Before running pvmd3, pvmd sources any commands in $HOME/.pvmprofile if this file exists.OPTIONSThe following options may be specified on the command line when starting the master pvmd or PVM console:-dmask Set pvmd debug mask. Used to debug the pvmd or libpvm (not intended to be used to debug application programs). Mask is the sum of the following bits and can be specified in hexadecimal (0x...), octal (0...) or decimal:Î’à È7 <€€€ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ÿ Bit Information 0x1 Packet routing 0x2 Message routing and entry points 0x4 Task state 0x8 Slave pvmd startup 0x10 Host table updates 0x20 Select loop (below packet layer) 0x40 IP network 0x80 Multiprocessor nodes 0x100 Resource manager interface—^ƤÊ9 @€½€€ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚‚‚€€‚‚ÿ 0x200 Application (messages with no destination, etc.) 0x400 Wait contexts 0x800 Shared memory operations 0x1000 Semaphores 0x2000 Locks 0x4000 Message route control -nname Specify an alternate hostname for the master pvmd to use. Useful when gethostname() returns a name not assigned to any network interface. The following options are used by the master pvmd when starting slaves and are only of interest to someone writing a hoster. Don't just go using them, now.È ȪÌ> J€‘€€‚€€‚‚‚€€‚‚‚€€‚‚ÿ-s Start pvmd in slave mode. Hostfile cannot be used, five additional parameters must be supplied: master pvmd index, master IP, master MTU, slave pvmd index, and slave IP.-S Same as -s, but slave pvmd doesn't wait for its stdin to be closed after printing its parameters. Used for manual startup. -f Slave doesn't fork after configuration (useful if the slave is to be controlled or monitored by some process).Ú¤¤Ê6 :€I€€‚€€‚‚‚‚‚‚‚‚‚‚‚‚ÿHOST FILE FORMATEach host in the virtual machine must have an entry in the host file. Lines beginning with a splat ( # ), optionally preceded by whitespace, are ignored. A simple host file might look like: # my first host file thud fred wilma barney bettyThis specifies the names of five hosts to be configured in the virtual machine. The master pvmd for a group is started by hand on the localhost, and it starts slaves on each of the remaining hosts using the rsh or rexec command. The master host may appear on any line of the host file. Host names cannot be numeric (IP) addresses, because they are passed to rsh and rexec(), which usually don't accept addresses. The simple format above works fine iªÌÿÀf you have the same login name on all five machines and the name of the master host in your .rhosts files on the other four.LªÌÜ: B€%€€‚‚‚€€‚‚‚€€‚‚‚‚‚ÿThere are several host file options available:lo=NAME Specifies an alternate login name (NAME) to use. so=pw This is necessary when the remote host cannot trust the master. Causes the master pvmd to prompt for a password for the remote host in the tty of the pvmd (note you can't start the master using the console or background it when using this option) you will see:Password (honk.cs.utk.edu:manchek):you should type your password for the remote host. The startup will then continue as normal. Óå6 :€§€€‚‚€€‚‚‚€€‚‚ÿdx=FILE Specifies the path of the pvmd executable. FILE may be a simple filename, an absolute pathname, or a path relative to the user's home directory on the remote host. This is mainly useful to aid in debugging new versions of PVM, but may have other uses.ep=PATH Specifies a path for the pvmd to search for executable program components when spawning a new process. The path may have multiple elements, separated by colons ( : ).’?ÜwS t€€€‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚€€€€‚ÿwd=PATH Specifies a working directory in which all spawned tasks on this host will execute.sp=VALUE Specifies the relative computational speed of this host compared to other hosts in the configuration. VALUE is an integer in the range [1 - 1000000] bx=PATH Specifies the debugger program path. Note: the environment variable PVM_DEBUGGER can also be set.ip=NAME Specifies an alternate IP address to use for the host. As with host names (when ip= is not used), the address must be a host name, not a numeric address, because it is passed to rsh and rexec(). This option allows one to pick a specific network interface for a machine without using the interface's name. It can also be used to create a virtual machine using symbolic (instead of actual) host names. ðå— 0 .€á€€‚€€‚‚‚‚‚‚ÿso=ms Rarely used. Causes the master pvmd to request user to manually perform the startup of a pvmd on a slave host when rsh and rexec network services are disabled but IP connectivity exists. See section "MANUAL STARTUP".A dollar sign ( $ ) in an option introduces a variable name, for example $PVM_ARCH Names are expanded from environment variables by each pvmd.Each of the flags above has a default value. These are: lo The loginname on the master host.d5wû / ,€k€€‚‚‚‚‚‚‚‚‚‚‚‚ÿ so Nothing dx $PVM_ROOT/lib/pvmd (or environment variable PVM_DPATH) ep $HOME/pvm3/bin/$PVM_ARCH:$PVM_ROOT/bin/$PVM_ARCH wd $HOME sp 1000 bx $PVM_ROOT/lib/debuggerYou can change these by adding a line with a star ( * ) in the first field followed by the options, for example: * lo=afriend so=pwThis sets new default values for 'lo' and 'so' for the remainder of the host file, or until the next '*' line. Options set on the last '*' line also apply to hosts added dynamically using pvm_addhosts(). Host options can be set without starting the hosts automatically. Information on host file lines beginning with '&' is stored, but the hosts are not started until added using pvm_addhosts().4— ;@0 .€ €€‚‚‚‚‚‚‚‚‚‚‚‚‚ÿExample host file: # host file for testing on various platforms fonebone refuge # installed in /usr/local here sigi.cs dx=/usr/local/pvm3/lib/pvmd # borrowed accts, "guest", don't trust fonebone * lo=guest so=pw sn666.jrandom.com cubie.misc.edu # really painful one, must start it by hand and share a homedir & igor.firewall.comû ;@ÿÀ lo=guest2 so=ms ep=bob/pvm3/bin/$PVM_ARCHáû OB3 4€Ã€€‚€‚‚‚‚‚‚‚‚‚‚‚‚ÿMANUAL STARTUPWhen adding a host with this option set you will see on the tty of the pvmd: *** Manual startup *** Login to "honk" and type: $PVM_ROOT/lib/pvmd -S -d0 -nhonk 1 80a9ca95:0cb6 4096 2 80a95c43:0000 Type response:after typing the given command on host honk, you should see a line like: ddpro<2312> arch ip<80a95c43:0a8e> mtu<4096>type this line on the tty of the master pvmd. You should then see:ï;@nD0 .€ß€€‚‚‚‚€‚€‚‚ÿ Thanksand the two pvmds should be able to communicate. Note you can't start the master using the console or background it when using this option.OVERLOADING HOSTSYou can force PVM to overload a host (start more than one pvmd on it) by putting a '$' before the host name in the host file. This is not recommended unless you know what you're doing and have a good reason for it. You must build the PVM source with option OVERLOADHOST defined for it to work.i;OB×G. *€w€€‚‚€‚€‚‚ÿYou may also need to use the ip= hostfile option to define several names with the same IP address. If two or more hosts in a PVM have the same name, they cannot be identified uniquely.STOPPING PVMD3The preferred method of stopping all the pvmds is to give halt command in the PVM console. This kills all PVM tasks, all the remote daemons, the local daemon, and finally the console itself. If the master pvmd is killed manually it should be sent a SIGTERM signal to allow it to kill the remote pvmds and clean up various files. The pvmd can be killed in a manner that leaves the file /tmp/pvmd.uid behind on one or more hosts. Uid is the numeric user ID (from /etc/passwd) of the user. This will prevent PVM from restarting on that host. Deletion of this file will fix this problem: 4ónD JA P€ç€€‚‚‚€€‚ƒƒƒ‚ƒ‚ƒƒƒ‚ƒƒ‚ƒ‚ƒƒƒƒ‚ÿ rm `( grep $user /etc/passwd || ypmatch $user passwd ) | awk -F: '{print "/tmp/pvmd."$3; exit}'`FILES $PVM_ROOT/lib/pvmd PVM daemon startup script $PVM_ROOT/lib/$PVM_ARCH/pvmd3PVM daemon executable $HOME/.pvmprofile Shell commands read by pvmd before running pvmd3 $HOME/pvm3/bin/$PVM_ARCH Private PVM executable directory $PVM_ROOT/pvm3/bin/$PVM_ARCH System PVM executable directory /tmp/pvmd.uid Pvmd local socket address©|×G´J- *€ø€€ƒƒƒƒ‚ƒƒƒ‚‚‚ÿ /tmp/pvml.uid Pvmd runtime error log $HOME/.rhosts File allowing access to a host from other hostsJ JþJ1±€ÿÿÿÿþJ=KTÁlibpvm3, libfpvm3 library?´J=K# €8€€‚ÿlibpvm3, libfpvm3 library> þJ{N1 0€€€€‚‚€€‚‚‚ÿlibpvm3.a, libfpvm3.a PVM C and Fortran programming librariesDESCRIPTIONAll PVM applications must be linked with the libpvm library to allow them to communicate with other entities in the PVM system. The base library (libpvm3.a) is written in C and directly supports C and C++ applications. The Fortran library (libfpvm3.a) consists of wrapper functions to convert Fortran calling sequences to C. Applications written in C must be linked with at least the base PVM library, libpvm3.a. Fortran applications must be linked with both libfpvm3.a and libpvm3.a. On some operating systems, PVM programs must be linked with other vendor-provided libraries (containing for example, socket or XDR functions). Programs that use group functions must also be linked with libgpvm3.a.Ö=K¥€H ^€­€€‚€€‚‚‚€€‚‚‚‚€€‚‚‚‚€€‚ÿSUBROUTINESThe libpvm subroutines can be divided into roughly five classes:Message Passingpvm_bufinfo, pvm_freebuf, pvm_getrbuf, pvm_getsbuf, pvm_initsend, pvm_mcast, pvm_mkbuf, pvm_nrecv, pvm_pack, pvm_precv, pvm_probe, pvm_psend, pvm_recv, pvm_recvf, pvm_send, pvm_sendsig, pvm_setmwid, pvm_setrbuf, pvm_{N¥€´Jsetsbuf, pvm_trecv, pvm_unpackTask Controlpvm_exit, pvm_kill, pvm_mytid, pvm_parent, pvm_pstat, pvm_spawn, pvm_tasks Group Library Functionsi'{NƒB R€O€€‚‚‚€€‚‚‚‚€€‚‚‚‚€€‚‚ÿpvm_barrier, pvm_bcast, pvm_gather, pvm_getinst, pvm_gettid, pvm_gsize, pvm_joingroup, pvm_lvgroup, pvm_reduce, pvm_scatterVirtual Machine Controlpvm_addhosts, pvm_config, pvm_delhosts, pvm_halt, pvm_mstat, pvm_reg_hoster, pvm_reg_rm, pvm_reg_tasker, pvm_start_pvmd Miscellaneouspvm_archcode, pvm_catchout, pvm_getopt, pvm_hostsync, pvm_notify, pvm_perror, pvm_setopt, pvm_settmask, pvm_tidtohostERRORSOn success, most libpvm functions return the constant PvmOk. The following error conditions can be returned by libpvm functions:À¥€…O l€€€‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚ÿPvmAlreadyThe requested operation requires exclusive access, and another was already in progress.PvmBadMsgThe received messages has a data format native to another machine, which cannot be decoded by libpvm.PvmBadParamA bad parameter was passed to the function.PvmBadVersionTwo PVM components (pvmd and task, two pvmds or two tasks) have incompatible protocol versions and cannot interoperate. Version mismatchPvmCantStart„<ƒ¡‡H ^€y€€‚‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚ÿA pvmd could not be started on the local host, or a slave pvmd could not be started on a remote host.PvmDSysErrSome internal mechanism in the pvmd failed during the requested operation. PvmDupEntryThe class server already has an entry matching the insert request. [In Version 3.4: Relaced by PvmExists]PvmDupGroupThe task has already a member of the group it attempted to join.PvmDupHostAn attempt was made to add the same host to a virtual machine more than once, or to add a host already a member of another virtual machine owned by the same user.º…´‰Y €€u€€‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚ÿPvmDeniedOperation is refused due to locking, permissions, etc.PvmExistsThere is already an entry matching the insert request.PvmHostFailA foreign host in the virtual machine failed during the requested operation. PvmMismatchA parameter does not match a corresponding one.PvmNoBufThere is no current message buffer to pack or unpack.PvmNoDataThe end of a message buffer was reached while trying to unpack data.¡‡Ï‹Y €€…€€‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚ÿPvmNoEntryThe class server has no entry matching the lookup request. [In Version 3.4: Relaced by PvmNotFound]PvmNoFileThe named executable does not exist.PvmNoGroupThe named group does not exist.PvmNoHostThere is no host in the virtual machine with the given name, or the name could not be resolved to an address.PvmNoInstThe named group has no member with this instance.PvmNoMemMalloc failed to get memory for libpvm.Ÿ´‰Ñc ”€?€€‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚‚ÿPvmNoParentThis task has no parent task.PvmNoSuchBufThere is no message buffer with the given buffer handle.PvmNoTaskNo task exists with the given tid.PvmNotFoundNo entry matching the lookup request was found.PvmNotImplThis libpvm function or option is not implemented.PvmNotInGroupThe named group has no such member task.PvmNullGroupA null group name was passed to a function.»Ï‹ØL f€w€€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚ƒƒ‚ƒƒ‚ƒƒ‚ÿPvmOutOfResThe requested operation could not be completed due to lack of resources.PvmOverflowA value is too large to be packed or unpacked.PvmSysErrLibpvm could not contact a pvmd on the local host, or the pvmd failed during an operation.FILES$PVM_ROOT/include/fpvm3.h Fortran header file$PVM_ROOT/include/pvm3.h C header file$PVM_ROOT/include/pvmsdpro.h Header file for tasker, hoster and resource manager tasksp-ÑTÁC T€[€€ƒƒ‚ƒ‚ƒØTÁ´J‚ƒ‚‚‚ãñnõ‰‚ã}$ቂ㛮tö‰‚ÿ$PVM_ROOT/include/pvmtev.h Header file for tasks manipulating trace events$PVM_ROOT/lib/$PVM_ARCH/libpvm3.a C (base) library$PVM_ROOT/lib/$PVM_ARCH/libfpvm3.a Fortran wrapper library$PVM_ROOT/lib/$PVM_ARCH/libgpvm3.a Group function librarysee alsoPVM Intropvm consolepvmd3 daemonNØ¢Á1 €€¢ÁåÁÀÅPVM Message Passing FunctionsC TÁåÁ# €@€€‚ÿPVM Message Passing FunctionsâÁéÃA P€‡€€‚‚‚€€‚‚‚‚€€‚‚‚‚€€‚ÿIn the following pages you will retrieve information about:Message Passingpvm_bufinfo, pvm_freebuf, pvm_getrbuf, pvm_getsbuf, pvm_initsend, pvm_mcast, pvm_mkbuf, pvm_nrecv, pvm_pack, pvm_precv, pvm_probe, pvm_psend, pvm_recv, pvm_recvf, pvm_send, pvm_sendsig, pvm_setmwid, pvm_setrbuf, pvm_setsbuf, pvm_trecv, pvm_unpackTask Controlpvm_exit, pvm_kill, pvm_mytid, pvm_parent, pvm_pstat, pvm_spawn, pvm_tasks Group Library Functions×åÁÀÅ: B€;€€‚‚‚€€‚‚‚‚€€‚‚‚‚ÿpvm_barrier, pvm_bcast, pvm_gather, pvm_getinst, pvm_gettid, pvm_gsize, pvm_joingroup, pvm_lvgroup, pvm_reduce, pvm_scatterVirtual Machine Controlpvm_addhosts, pvm_config, pvm_delhosts, pvm_halt, pvm_mstat, pvm_reg_hoster, pvm_reg_rm, pvm_reg_tasker, pvm_start_pvmd Miscellaneouspvm_archcode, pvm_catchout, pvm_getopt, pvm_hostsync, pvm_notify, pvm_perror, pvm_setopt, pvm_settmask, pvm_tidtohost= éÃýÅ1ó ÿÿÿÿhýÅ/Æ pvm_addhosts2ÀÅ/Æ# €€€‚ÿpvm_addhostsQýÅ€È8 >€3€€€‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚ÿpvm_addhosts - Add hosts to the virtual machine.Cint info = pvm_addhosts( char **hosts, int nhost, int *infos )Fortrancall pvmfaddhost( host, info )PARAMETERShostsAn array of strings naming the hosts to be added. Pvmd must already be installed and the user must have an account on the specified hosts. nhost Integer specifying the length of array hosts. infos Integer array of length nhost which returns the status for each host. Values less than zero indicate an error, while positive values are TIDs of the new hosts.æ/Æ™Ê3 4€Í€€‚‚‚‚‚‚‚€€‚‚‚ÿhostCharacter string naming the host to be added.infoInteger status code returned by the routine. Values less than \fInhost\fR indicate partial failure, and values less than 1 indicate total failure.DESCRIPTIONThe routine pvm_addhosts adds the computers named in hosts to the configuration of computers making up the virtual machine.The names should have the same syntax as lines of a pvmd hostfile (see man page for pvmd3):A hostname followed by options of the form xx=y.ò€ÈµÌ* "€å€€‚‚‚‚‚‚‚ÿIf pvm_addhosts is successful, info will be equal to nhost. Partial success is indicated by 0 < info < nhost,and total failure by info < 1.The array infos can be checked to determine which host caused the error.The Fortran routine pvmfaddhost adds a single host to the configuration with each call. info will be 1 if successful or < 0 if error.If a host fails, the PVM system will continue to function. The user can use this routine to increase the fault tolerance of his PVM application.?™ÊôÎ% €5€€‚‚ÿThe status of hosts can be requested by the application using pvm_mstat and pvm_config. If a host fails it will be automatically deleted from the configuration. Using pvm_addhosts a replacement host can be added by the application, however it is the responsibility of the application developer to make his application tolerant of host failure. Another use of this feature would be to add more hosts as they become available, for example on a weekend, or if the application dynamically determines it could use more computational power.,еÌ,\ †€¡€€‚‚‚€€‚‚‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚‚‚ƒ‚‚€€‚‚‚€€‚€€‚€€‚ÿpvm_addhosts requires the synchronization of the entire virtual machine.EXAMPLESC:static char *hosts[] = { "sparky", "thud.cs.utk.edu",};info = pvm_addhôÎ,ÀÅosts( hosts, 2, infos );Fortran:CALL PVMFADDHOST( 'azure', INFO )ERRORSThe following error conditions can be returned by pvm_addhostsPvmBadParam giving an invalid argument value.PvmAlready another task is currently adding hosts.PvmSysErr local pvmd is not responding.áhôÎ y À€Ñ€€‚‚€€‚€€‚€€‚€€‚€€‚€€‚‚‚ã›®tö‰‚ã®×0O‰‚ã®c¤©‰‚ãL<‰‚ãß©Eö‰‚‚€‚ÿand in the infos vector:PvmBadParam bad hostname syntax.PvmNoHost no such host.PvmCantStart failed to start pvmd on host.PvmDupHost host already configured.PvmBadVersion pvmd protocol versions don't match.PvmOutOfRes PVM has run out of system resources.see alsopvmd3 daemonpvm_delhostspvm_start_pvmdpvm_configpvm_mstat; ,H1‘ €ƒ€Hx @pvm_addmhf0 x# €€€‚ÿpvm_addmhf:øH²B R€ñ€€€‚‚‚‚‚ƒ‚ƒ‚‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚ÿpvm_addmhf Install message-handler functions.pvm_delmhf Remove message-handler functions.SYNOPSISCint mhid = pvm_addmhf( int src, int tag, int ctx, int (*func)(int mid) )int info = pvm_delmhf( int mhid )FortranNot availablePARAMETERSsrc The tid of the sender.tag The tag sent with the message.ctx The context sent with the message.func Function to call when message received.mhid Message handler id.info Result code.mid Message buffer identifier for new active receive buffer.¼‡xn5 8€€€‚€€‚‚‚‚‚‚ƒ‚‚‚‚ÿDESCRIPTIONpvm_addmhf specifies a function that will be called whenever libpvm copies in a message whose header fields of src, tag, and ctx match those provided to pvm_addmhf().The src and tag fields may be left unspecified (wildcard) by setting to -1.The calling sequence of the message handler function is:int handler( int mid )Where mid is the bufid of the received message. The handler function is completely responsible for the receivedmessage buffer. It must use pvm_setrbuf to unpack the contents of the message (and to restore the current buffer afterward), and it must call pvm_freebuf to deallocate the message when done.Í–²; 7 <€-€€‚‚‚‚‚ƒ‚‚ƒ‚ƒ‚ƒ‚ƒ‚‚‚‚‚ÿNote:Operation in the message handler context is somewhat restricted.The function may call some PVM functions, but not others.For example, it may compose and send a reply message as shown:int sbf;sbf = pvm_setsbuf(0);pvm_packf("%+ %s", PvmDataDefault, "got your message");pvm_send(tid, tag);pvm_freebuf(pvm_setsbuf(sbf));but is not allowed to call certain other PVM communication functions, such as multicast or receive.pvm_addmhf returns the id number of the newly created message handler if successful; this number may be passed to pvm_delmhf to remove the entry. There is no guarantee to the ordering of id values returned by pvm_addmhf. Én[ W |€“€€‚‚‚‚€€‚€€‚€€‚‚‚ƒ‚‚ƒ‚ƒ‚ƒ‚ƒƒ‚‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ÿPvmExists is returned if the handler already exists.pvm_delmhf returns PvmOk if successful.PvmBadParam if pvm_delmhf is passed a negative id value.PvmNotFound if the id value is not found.EXAMPLES/* Print a message when hosts are added to virtual machine */inthostAdded( int mid ){int rbf, n;rbf = pvm_setrbuf(mid);pvm_unpackf("%d", &n);printf("*** %d new hosts just added ***\\n", n);pvm_freebuf(pvm_setrbuf(rbf));!Ø; |I `€±€€ƒ‚‚ƒ‚‚ƒ‚‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚‚€€‚‚‚‚‚€€‚ÿ}/* ... later ... */int src, tag, ctx;src = -1;tag = 99;ctx = -1;pvm_addmhf(src, tag, ctx, hostAdded);pvm_notify(PvmHostAdd, 99, -1, (int *)0);ERRORSThe following error conditions can be returned by pvm_addmhf():PvmExists: Can't insert as handler already exists with same (tag, ctx, src) including "wild-cards" (those set to -1)The following error conditions can be returned by pvm_delmhf():PvmBadParam: Invalid (negative) mhid passed in.\5[  @' €j€€€‚‚ÿPvmNotFound: Message handler mhiddoes not exist.| @ ; |G@1õhë†G@w@;Hpvm_advise0 @w@# €€€‚ÿpvm_advise»G@}BK d€w€€€‚‚‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚ƒƒƒ‚ƒƒƒ‚ƒƒƒ‚‚‚ÿpvm_advise() Controls use of direct task-to-task routing.[In Version 3.2: Replaced by pvm_setopt]SYNOPSISCint info = pvm_advise( int route )Fortrancall pvmfadvise( route, info )PARAMETERSroute Integer advising PVM to set up direct task-to-task links.route optionsPvmDontRoute1Don't allow direct links to this task PvmAllowDirect2Allow but don't request direct links PvmRouteDirect3Request direct linksinfoyKw@öE. *€—€€‚‚€€‚‚‚ÿInteger returning error status.DESCRIPTIONThe routine pvm_advise advises PVM on whether or not to set up direct task-to-task links (using TCP) forall subsequent communication. Once a link is established it remains until the application finishes. If a direct link can not be established because one of the two tasks has requested PvmDontRoute or because no resources are available, then the default route through the PVM daemons is used. pvm_advise can be called multiple times to selectively establish direct links, but is typically set only once near the beginning of each task. PvmAllowDirect is the default advise setting. This setting on task A allows other tasks to set up direct links to A. Once a direct link is established between tasks both tasks will use it for sending messages. pvm_advise returns the error status in info.¿}BùGD V€€€‚‚€€‚‚ƒ‚‚ƒ‚‚‚€€‚‚€€‚‚ÿThe performance of direct task-to-task links can be up to a factor of two better than the default route. The draw back is a lack of scalability of the direct links. Some versions of UNIX limit the number of links to no more than 30.EXAMPLESC:info = pvm_advise( PvmRouteDirect );Fortran:CALL PVMFADVISE( PVMROUTEDIRECT, INFO )ERRORSThis error condition can be returned by pvm_advisePvmBadParam: giving an invalid route value.BöE;H) "€2€€ã¿l‰‚ÿsee also pvm_setopt= ùGxH1å€Û‹ xHªH^Npvm_archcode2;HªH# €€€‚ÿpvm_archcodeÅxHoKF Z€ÿ€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚€€‚‚ÿpvm_archcode Returns the data representation code for a PVM architecture name.SYNOPSISCint cod = pvm_archcode( char *arch )Fortrancall pvmfarchcode( arch, cod )PARAMETERSarch Character string containing the architecture name.cod Integer returning architecture code.DESCRIPTIONThe routine pvm_archcode returns an integer given an architecture name.The code returned identifies machines with compatible binary data formats. For example, SUN4 and RS6K have the same code, while ALPHA has a different one (because a few datatypes have different sizes). This lets you know when you can get away with using PvmDataRawÒªH~M= H€¥€€‚‚‚‚€€‚‚‚ƒ‚ƒ‚‚ƒ‚ƒ‚‚‚ƒ‚ÿinstead of PvmDataDefault encoding to pass messages between tasks on two machines.Naturally, you shouldn't assume the values returned by pvm_archcode are etched in stone; the numbers have no intrinsic meaning except thatif two different arch names map to the same value then they're compatible.EXAMPLESC:struct pvmhostinfo *hip;int i;pvm_config((int *)0, (int *)0, &hip);i = pvm_archcode(hip[0].hi_arch);Fortran:CALL PVMFARCHCODE( 'RS6K', k )àoK^NP n€!€€‚€€‚‚‚ãL<‰‚ãÆ$«æ‰‚ãA¦e‰‚ãÔøœ÷‰‚ãT‰‚ÿERRORSNo error conditions are be returned by pvm_archcodesee also pvm_config pvm_initsendpvm_notifypvm_taskspvm_tidtohost< ~MšN1¡ 놖 šNËN‚‡pvm_barrier1^NËN# €€€‚ÿpvm_barrierRšN)< F€-€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚ÿpvm_barrier Blocks the calling process until all processes in a group have called it.SYNOPSISCint info = pvm_barrier( char *group, int count )Fortrancall pvmfbarrier( group, count, info )PARAMETERSgroup Character string group name. TËN)^Nhe group must exist and the calling process must be a member of the group.count Integer specifying the number of group members that must call pvm_barrier before they are all released. Though not required, count is expected to be the total number of members of the specified group.ÊšËNóƒ0 .€5€€‚‚‚‚€€‚‚‚ÿinfo Integer status code returned by the routine. Values less than zero indicate an error.DESCRIPTIONThe routine pvm_barrier blocks the calling process until count members of the group have called pvm_barrier.The count argument is required because processes could be joining the given group after other processes have called pvm_barrier. Thus PVM doesn't know how many group members to wait for at any given instant. Although count can be set less, it is typically the total number of members of the group. So the logical function of the pvm_barrier call is to provide a group synchronization. During any given barrier call all participating group members!à)†A P€Á€€‚‚‚‚‚€€‚‚‚ƒ‚ƒ‚ƒ‚ƒ‚‚‚ƒ‚ƒ‚ƒ‚ÿmust call barrier with the same count value. Once a given barrier has been successfully passed,pvm_barrier can be called again by the same group using the same group name.If pvm_barrier is successful, info will be 0. If some error occurs then info will be < 0.EXAMPLESC:inum = pvm_joingroup( "worker" ); . .info = pvm_barrier( "worker", 5 );Fortran:CALL PVMFJOINGROUP( "shakers", INUM )COUNT = 10CALL PVMFBARRIER( "shakers", COUNT, INFO )n󃂇R r€9€€‚‚€€‚‚€€‚€€‚€€‚€€‚‚ãC^w0‰‚‚ÿERRORSThese error conditions can be returned by pvm_barrierPvmSysErr: pvmd was not started or has crashed.PvmBadParam giving a count < 1.PvmNoGroup giving a non-existent group name.PvmNotInGroup calling process is not in specified group.see also pvm_joingroup: †¼‡1 Û‹€ ¼‡ë‡´Ápvm_bcast/ ‚‡ë‡# €€€‚ÿpvm_bcastD¼‡/Š@ N€ €€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚‚‚ÿpvm_bcast Broadcasts the data in the active message buffer to a group of processes.SYNOPSISCint info = pvm_bcast( char *group, int msgtag )Fortrancall pvmfbcast( group, msgtag, info )PARAMETERSgroup Character string group name of an existing group.msgtag Integer message tag supplied by the user.msgtag should be >= 0. It allows the user's program to distinguish between different kinds of messages .info integer status code returned by the routine. Values less than zero indicate an error.äë‡B/ ,€É€€‚€€‚‚‚‚‚ÿDESCRIPTIONThe routine pvm_bcast broadcasts a message stored in the active send buffer to all the members of group. In PVM 3.2 and later the broadcast message is not sent back to the sender. Any PVM task can call pvm_bcast(), it need not be a member of the group. The content of the message can be distinguished by msgtag.If pvm_bcast is successful, info will be 0. If some error occurs then info will be < 0.pvm_bcast is asynchronous. Computation on the sending processor resumes as soon as the message is safely on its way to the receiving processors. This is in contrast to synchronous communication, during which computation on the sending processor halts until a matching receive is executed by all the receiving processors.ð/ŠX& €á€€‚‚‚ÿpvm_bcast first determines the tids of the group members by checking a group data base. A multicast is performed to these tids. If the group is changed during a broadcast the change will not be reflected in the broadcast.Multicasting is not supported by most multiprocessor vendors.Typically their native calls only support broadcasting to all the user's processes on a multiprocessor. Because of this omission, pvm_bcast may not be an efficient communication method on some multiprocessors.*ÏBŽÁ[ „€Ÿ€€‚€€‚‚‚ƒ‚ƒ‚ƒ‚ƒ‚‚‚ƒ‚ƒ‚ƒ‚‚€€‚‚€€‚€€‚€€‚ÿEXAMPLESC:info = pvm_initsend( PvmDataRaw );info = pvm_pkint( arrayXŽÁ‚‡, 10, 1 );msgtag = 5 ;info = pvm_bcast( "worker", msgtag );Fortran:CALL PVMFINITSEND( PVMDEFAULT )CALL PVMFPKFLOAT( DATA, 100, 1, INFO )CALL PVMFBCAST( 'worker', 5, INFO )ERRORSThese error conditions can be returned by pvm_bcastPvmSysErr: pvmd was not started or has crashed.PvmBadParam: giving a negative msgtag.PvmNoGroup: giving a non-existent group name.&X´Á# €€€‚ÿ< ŽÁðÁ1‰–{† ðÁ!ÂyÉpvm_bufinfo1´Á!Â# €€€‚ÿpvm_bufinfoÜðÁ4Ä7 <€¹€€€‚‚‚‚ƒ‚‚ƒ‚‚‚‚‚‚‚‚‚ÿpvm_bufinfo() Returns information about a message buffer.SYNOPSISCint info = pvm_bufinfo( int bufid, int *bytes, int *msgtag, int *tid )Fortrancall pvmfbufinfo( bufid, bytes, msgtag, tid, info )PARAMETERSbufid Integer specifying a particular message buffer identifier.bytesInteger returning the length in bytes of the body of the message. This will be equal to the actual size of the data packed, if PvmDataRawis used, otherwise it may include pad bytes.Æ!Â6Ç< F€€€‚‚‚‚‚‚‚‚‚‚€€‚€€‚‚ÿmsgtagInteger returning the message label. Useful when the message was received with a wildcard msgtag.tidInteger returning the source of the message. Useful when the message was received with a wildcard tid.infoInteger status code returned by the routine. Values less than zero indicate an error.DESCRIPTIONThe routine pvm_bufinfo returns information about the requested message buffer. Typically it is used to determinefacts about the last received message such as its size or source. pvm_bufinfo is especially useful when an application is able to receive any incoming message, and the action taken depends on the source tid and the msgtag associated with the message that comes in first.Ä4ÄQÉW |€‰€€‚‚‚‚‚ƒ‚ƒ‚‚‚ƒ‚ƒ‚‚€€‚€€‚€€‚€€‚‚ã¬M„#‰‚ÿIf pvm_bufinfo is successful, info will be 0. If some error occurs then info will be < 0.EXAMPLESC:bufid = pvm_recv( -1, -1 );info = pvm_bufinfo( bufid, &bytes, &type, &source );Fortran:CALL PVMFRECV( -1, -1, BUFID )CALL PVMFBUFINFO( BUFID, BYTES, TYPE, SOURCE, INFO )ERRORSThis error condition can be returned by pvm_bufinfo.PvmNoSuchBuf: specified buffer does not exist.PvmBadParam: invalid argumentsee also pvm_recv(6ÇyÉ$ €€€‚‚ÿ= QɶÉ1ˆ €Ð ¶ÉèÉhpvm_catchout2yÉèÉ# €€€‚ÿpvm_catchoutÄr¶É¬ÌR r€å€€€‚‚‚‚ƒ‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚‚‚‚€€‚€€‚ÿpvm_catchout Catch output from child tasks.SYNOPSISC#include int info = pvm_catchout( FILE *ff )Fortrancall pvmfcatchout( onoff, info )PARAMETERSffFile descriptor on which to write collected output.onoffInteger parameter. Turns output collection on or off.infoInteger status code returned by the routine. Values less than zero indicate an error.DESCRIPTIONThe routine pvm_catchout causes the calling task (the parent) to catch output from tasks spawned after the call to pvm_catchout. Characters printed on \fIstdout\fR or \fIstderr\fR in children tasks are collected by the pvmdsY)èÉÏ0 .€S€€‚‚‚‚‚ƒ‚ƒ‚ƒ‚‚‚ÿand sent in control messages to the parent task, which tags each line and appends it to the specified file.Output from grandchildren (spawned by children) tasks is also collected, provided the children don't reset PvmOutputTid.If option PvmShowTids (see pvm_setopt) is true (nonzero), output is printed as shown below, tagged with the task id where the output originated: [txxxxx] BEGIN[txxxxx] (text from child task)[txxxxx] ENDThe output from each task includes one BEGIN line and one END line, with whatever the task prints in between.6 ¬ÌG* "€€€‚‚‚‚‚‚‚ÿIf PvmShowTids is false, raw output is printed with no additional information.In C, the output file descriptor may be specified. Giving a null pointer turns output collection off.In Fortran, output collectÏGyÉion can only be turned on or off, and is logged to stdout of the parent task.If pvm_exit is called while output collection is in effect, it will block until all tasks sending it output have exited,in order to print all their output. To avoid this, output collection can be turned off by calling pvm_catchout(0)!ÐÏhQ p€¡€€‚‚‚‚€€‚‚‚ƒ‚‚ƒ‚‚‚ƒ‚‚‚ãpu#‰‚ã¿l‰‚ã½€z÷‰‚‚ÿbefore calling pvm_exit.pvm_catchout() always returns 0.EXAMPLESC:#include pvm_catchout(stdout);Fortran:CALL PVMFCATCHOUT( 1, INFO )see alsopvm_exitpvm_setoptpvm_spawn; G£1^ {†× £Ó pvm_config0 hÓ# €€€‚ÿpvm_config¸£ØM h€q€€€‚‚‚‚ƒ‚ƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒ‚‚ƒ‚‚‚€€‚‚‚‚‚‚ÿpvm_config Returns information about the present virtual machine configuration.SYNOPSISCint info = pvm_config( int *nhost, int *narch, struct pvmhostinfo **hostp ) .brstruct pvmhostinfo {int hi_tid;char *hi_name;char *hi_arch;int hi_speed;};Fortrancall pvmfconfig( nhost, narch, dtid, name, arch, speed, info )PARAMETERSnhostInteger returning the number of hosts (pvmds) in the virtual machine.narchUÓ-6 :€?€€‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚ÿInteger returning the number of different data formats being used.hostpReturns pointer to an array of structures which contain information about each host including its pvmd task ID, name, architecture, and relative speed.dtidInteger returning pvmd task ID for hostnameCharacter string returning name of hostarchCharacter string returning architecture name of hostspeedInteger returning relative speed of host. Default value is 1000.infoInteger status code returned by the routine. Values less than zero indicate an error.LØ® 5 8€™€€‚€€‚€€‚‚‚‚ÿDESCRIPTIONThe routine pvm_config returns information about the present virtual machine. The information returned issimilar to that available from the console command conf.The C function returns information about the entire virtual machine in one call. The Fortran function returns information about one host per call and cycles through all the hosts. Thus, if pvmfconfig is called nhost times, the entire virtual machine will be represented. Note that in C the hostp array is allocated and owned by libpvm. It is automatically freed or reused on the next call to pvm_config.Ë-³ : B€—€€‚‚‚‚‚€€‚‚‚ƒ‚ƒ‚‚ƒ‚ƒ‚ÿNote that in Fortran the reported value of nhost and the host configuration do not change until the function resets at the end of a complete cycle. The user can reset pvmfconfig() at any time by calling it with nhost = -1.If pvm_config is successful, info will be 0. If some error occurs then info will be < 0.EXAMPLESC:struct pvmhostinfo *hostp;int i, nhost, narch;info = pvm_config( &nhost, &narch, &hostp );for (i = 0; i < nhost; i++)M ®  A P€€€ƒƒ‚‚‚ƒ‚ƒ‚ƒ‚‚€€‚‚‚‚‚ãÔøœ÷‰‚ÿprintf("%s\\n", hostp[i].hi_name);Fortran:Do i=1, NHOST CALL PVMFCONFIG( NHOST,NARCH,DTID(i),HOST(i),ARCH(i),SPEED(i),INFO )EnddoERRORSThe following error condition can be returned by pvm_configPvmSysErr: pvmd not responding.see also pvm_tasks; ³ ; 1|Ðð ; k ¶pvm_delete0 k # €€€‚ÿpvm_deleteK ; ¶? L€€€€‚‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚ÿpvm_delete delete data from pvmd database .br[In Version 3.4: Relaced by pvm_delinfo]SYNOPSISCint cc = pvm_delete( char *name, int index ) .brFortranNot availablePARAMETERSnameThe class name, a null-terminated string.indexThe class index, >= 0.= k ó1 × š…ó%ÌGpvm_delhosts2¶%# €€€‚ÿpvm_delhosts@üóqAD V€ù€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚‚‚‚‚‚‚ÿpvm_delhosts Deletes hosts from the virtual machine.SYNOPSISCint info = pvm_delhosts( char **hosts, int nhost, int *infos )Fortrancall pvmfde%qA¶lhost( host, info )PARAMETERShostsAn array of pointers to character stringscontaining the names of the machines to be deleted.nhostInteger specifying the number of hosts to be deleted.infosInteger array of lengthnhostwhich contains the status code returned by the routine for the individual hosts. Values less than zero indicate an error.x@%éC8 >€€€‚‚‚‚‚‚‚€€‚€€‚ÿhostCharacter string containing the name of the machine to be deleted.infoInteger status code returned by the routine. Values less than nhost indicate partial failure, values less than 1 indicate total failure.DESCRIPTIONThe routine pvm_delhosts deletes the computers pointed to in hosts from the existing configuration of computers making up the virtual machine. All PVM processes and the pvmd running on these computers are killed as the computer is deleted. If pvm_delhosts is successful, info will be nhost. Partial success is indicated by 1<= info < nhost,$ûqA F) €÷€€‚‚‚‚‚‚ÿand total failure by info < 1.The array infos can be checked to determine which host caused the error.The Fortran routine pvmfdelhost deletes a single host from the configuration with each call.If a host fails, the PVM system will continue to function and will automatically delete this host from the virtual machine.An application can be notified of a host failure by calling pvm_notify. It is still the responsibility of the application developer to make his application tolerant of host failure. ¿_éCÌG` Ž€¿€€‚€€‚‚‚ƒ‚ƒƒ‚ƒƒ‚ƒ‚ƒ‚‚‚ƒ‚‚€€‚€€‚‚‚‚‚ã„”Z³‰‚ãA¦e‰‚‚‚ÿEXAMPLESC:static char *hosts[] = {"sparky","thud.cs.utk.edu",};info = pvm_delhosts( hosts, 2 );Fortran:CALL PVMFDELHOST( 'azure', INFO )ERRORSThese error conditions can be returned by pvm_delhostsPvmBadParam giving an invalid argument value.PvmSysErr local pvmd not responding.see also pvm_addhostspvm_notify< FH1¹ ð w„H9HËÅpvm_delinfo1ÌG9H# €€€‚ÿpvm_delinfoÆHJJK d€€€€‚€€‚€€‚€€‚‚‚‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚‚‚ÿpvm_putinfo,pvm_recvinfo,pvm_getmboxinfo,pvm_delinfo Store and retrieve messages in global mailbox.SYNOPSISCint index = pvm_putinfo( char *name, int bufid, int flags )int bufid = pvm_recvinfo( char *name, int index, int flags )int info = pvm_delinfo( char *name, int index, int flags )int info = pvm_getmboxinfo( char *pattern, int *nclasses, struct pvmmboxinfo **classes ) struct pvmmboxinfo {Ý9HXL1 0€»€€‚‚‚‚‚‚‚‚ƒ‚ƒ‚ƒ‚ÿ char *mi_name; /* class name */ int mi_nentries; /* # of entries for this class */ int *mi_indices; /* mbox entry indices */ int *mi_owners; /* mbox entry owner tids */ int *mi_flags; /* mbox entry flags */ };Fortrancall pvmfputinfo( name, bufid, flags, index )call pvmfrecvinfo( name, index, flags, bufid )call pvmfdelinfo( name, index, flags, info )t9JJÌN; D€s€€ƒ‚ƒ‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚ÿcall pvmfgetmboxinfo( pattern, name, nclasses, nentries, index, owner, flags, info )PARAMETERSnameDatabase key (class name), any null-terminated string.indexDatabase key (class index), >= 0. Default index = 0.flagsUser specified options. (see below)bufidHandle of message buffer to put in database, or message returned. A returned bufid < 0 indicates an error.infoResulting status code.patternGNU regular expression (pattern) to match on names in mailbox database. Additionally, the singular "*" will match on all names.4ûXL ƒ9 @€÷€€‚‚‚‚‚‚‚‚‚‚‚‚‚€€‚‚‚ÿnclassesNumber of classes matching pattern.classesArray of pvmmboxinfo mailbox entries matching pattern.nentriesNumber of entries for a given class.ownerTask id that inserted entry into mailbox database.DESCRIPTIONThese functions impÌN ƒÌGlement a "message mailbox" database that can be used by PVM tasks to advertise information to other PVM tasks. An example would be to advertise names or locations of services. Another example would be to advertise a common "context" on which two tasks may communicate. The database entries are PVM messages keyed by a user specified name and an optional index value. The name may be any null-terminated string and the index a non-negative integer. The index value is assigned by PVM and is used to uniquely identify one of multiple named instances within the database. Entries are "owned" by the task that created them. An entry is automatically removed from the database when the owner task exits unless the database entry was created with flag PvmMboxPersistent..ÌN:…) € €€‚‚‚‚‚‚ÿWhen a task exits and leaves an entry in the mailbox, the owner tid of that entry is marked as zero (0) to indicate that there is no longer an active owner task.pvm_putinfoinserts a record in the database, given a key and data (message). It returns mailbox index number if the record is successfully stored, PvmExists if a record with the given key already exists, or PvmDenied if an attempt is made to overwrite a locked record. The following options are added together as the flags parameter to pvm_putinfo. Ý ƒC‡, &€»€€‚‚‚‚‚‚‚‚‚ÿPvmMboxDefaultInserts entry as the only named instance for a given name. This entry may only be modified and deleted by its owner. It is automatically deleted when its owner exits.PvmMboxPersistentEntry remains in the database when the owner task exits. Entries are removed from the database when PVM is halted or a reset is issued from the console.PvmMboxMultiInstancePermits multiple entry instances of the same name. PVM will assign an index key to each instance.î:…\‰+ $€Ý€€‚‚‚‚‚‚‚‚ÿPvmMboxOverWritablePermits other tasks to overwrite and delete this database entry.pvm_recvinfooperates just like a pvm_recv() except the message is coming from the database. The message should be unpacked after pvm_recvinfo(). Like pvm_recv, pvm_recvinfo returns a pointer to a message buffer containing the record matching the key from the database. Returned value < 0 indicates an error.The following options are added together as the flags parameter to pvm_recvinfo.vJC‡Ò‹, &€•€€‚‚‚‚‚‚‚‚‚ÿPvmMboxDefaultexact match on key is returned. Returns PvmNotFound if exact match not found.PvmMboxFirstAvailThe first entry in with index greater than or equal to the specified index parameter is retuned. PvmMboxFirstAvail with index = 0 will produce the same results as using PvmMboxDefault. PvmMboxReadAndDeleteReturn entry and delete from database. Task must be permitted to do both read and delete otherwise an error will occur. bufid returns PvmNotFound if entry does not exist and will return PvmDenied if the record exists but may not be deleted.tK\‰FŽ) €—€€‚‚‚‚‚‚ÿpvm_delinfodeletes database entry specified by the key . Returns PvmOK if the record was deleted, PvmNotFound if the record does not exist, or PvmDenied if an attempt is made to remove a "locked" record. There are no flags presently specified for pvm_delinfo.pvm_getmboxinforeturns an array of pvmmboxinfo for all class names in the database. This is used, for example, by programs that clean up the database or for applications to find out what is available. classes returns a pointer to the array allocated by libpvm and freed on the next call to pvm_getmboxinfo.(ïÒ‹zÀ9 @€ß€€‚‚‚€€‚‚‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ÿThe Fortran function returns information on one entry per call. Thus, if called repeatedly until an info value of PvmNotFound is returned, all entries matching the given pattern will have been returned. If a new pattern is desired, calling pvmfgetnames() with info = -1 will reset the entry name list and obtain a new list for the given pattern.EXAMPLESC:/** create and inFŽzÀÌGsert mailbox entry*/sprintf( service, "Task_A_service" );sprintf( message, "Greetings from task A." );ÍFŽ‹ÂD V€›€€ƒ‚ƒ‚ƒ‚ƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒ‚‚‚ƒ‚ƒ‚ƒ‚ƒ‚ƒƒƒ‚ÿpvm_initsend( PvmDataDefault );pvm_pkint( &mytid, 1, 1 );pvm_pkint( &context, 1, 1 );pvm_pkstr( message );if (( pvm_putinfo( service, pvm_getsbuf(), PvmMboxDefault )) == PvmExists ){ printf( "can't register - service already running\n" );exit( -1 );}/** look for and retrieve specified mailbox*/sprintf( service, "Task_A_service" );if (( msg_buf = pvm_recvinfo(service, 0, PvmMboxFirstAvail )) >= 0 ){ pvm_setrbuf( msg_buf );9âzÀÄÄW |€Å€€ƒƒ‚ƒƒ‚ƒƒ‚ƒ‚‚‚ƒ‚‚€€‚‚€€‚€€‚€€‚€€‚ÿpvm_upkint( &their_tid, 1, 1 );pvm_upkint( &their_context, 1, 1 );pvm_upkstr( message );}Fortran:we need the fortran examples...ERRORSThe following error conditions can be returned by one or more of these functions: PPvmBadParam An invalid value was specified for bufid argument.PvmNoSuchBuf: Message buffer bufid doesn't exist.PvmNoMem: Libpvm is unable to allocate memory to pack data.PvmExists: The requested key is already in use (pvm_putinfo).È‹ÂËÅ? L€‘€€€‚€€‚‚‚ãÆ$«æ‰‚ã˜ÏÞm‰‚‚ÿPvmNotFound: The requested key does not exist (pvm_recvinfo, pvm_delinfo).PvmDenied: The key is locked by another task and cannot be replaced or deleted.see alsopvm_initsendpvm_getsbuf; ÄÄÆ1mš…—„Æ6ÆrÆpvm_delmhf0 ËÅ6Æ# €€€‚ÿpvm_delmhf<ÆrÆ) "€&€€ãàækñ‰‚ÿsee pvm_addmhf96Æ«Æ1¬w„‰‡«ÆÙÆTÊpvm_exit. rÆÙÆ# €€€‚ÿpvm_exit «ÆäÈI `€…€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚€€‚€€‚ÿpvm_exit Tells the local pvmd that this process is leaving PVM.SYNOPSISCint info = pvm_exit( void )Fortrancall pvmfexit( info )PARAMETERSinfoInteger status code returned by the routine. Values less than zero indicate an error.DESCRIPTIONThe routine pvm_exit tells the local pvmd that this process is leaving PVM. This routine does not kill the process, which can continue to perform tasks just like any other serial process.p%ÙÆTÊK d€K€€‚‚‚€€‚‚‚ƒ‚ƒ‚ƒ‚‚‚ƒ‚ƒ‚‚€€‚€€‚‚ÿpvm_exit should be called by all PVM processes before they stop or exit for good. It must be called by processes that were not started with pvm_spawn.EXAMPLESC:/* Program done */pvm_exit();exit();Fortran:CALL PVMFEXIT(INFO)STOPERRORSPvmSysErr: pvmd not responding; äÈÊ1 —„ċʿʮÏpvm_export0 TÊ¿Ê# €€€‚ÿpvm_export€5Ê?ÍK d€k€€€‚‚‚‚ƒ‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚€€‚€€‚ÿpvm_export, pvm_unexport Mark environment variables to export through spawnSYNOPSISCint cc = pvm_export( char *name )int cc = pvm_unexport( char *name )FortranNot availablePARAMETERSnameName of an environment variable to add to or delete from export list.DESCRIPTIONThe routines pvm_export and pvm_unexport are provided for convenience in editing environment variable PVM_EXPORT, while maintaining the colon-separated list syntax it requires. The variable can be modified by other means, and at the same time by the pvm_export functions.Ñ¿ÊRÏB R€£€€‚‚‚€€‚‚‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚‚€€‚‚ÿpvm_export checks to see if a name is already in PVM_EXPORT before including it, and exporting a name more than once is not considered an error. Likewise, pvm_unexport will not complain if you specify a name not in PVM_EXPORT.EXAMPLESC:/* PVM_EXPORT=SHELL:HOME */pvm_export("DISPLAY");pvm_export("TERM");pvm_unexport("HOME");/* PVM_EXPORT=SHELL:DISPLAY:TERM */ERRORSNo error conditions are currently returned by pvm_export and pvm_unexport.\(?Í®Ï4 8€P€€‚‚ã}$ቂ㽀z÷‰‚‚‚ÿsee alsopvm consolepvm_spawn< RÏ 1ä‰‡Ä =ìpvm_freebuf®Ï ®Ï1®Ï=# €€€‚ÿpvm_freebuf{/ ¸L f€_€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚€€‚€€‚ÿpvm_freebuf Disposes of a message buffer.SYNOPSISCint info = pvm_freebuf( int bufid )Fortrancall pvmffreebuf( bufid, info )PARAMETERSbufidInteger message buffer identifier.infoInteger status code returned by the routine. Values less than zero indicate an error.DESCRIPTIONThe routine pvm_freebuf frees the memory associated with the message buffer identified by bufid. Message buffers are created by pvm_mkbuf, pvm_initsend, and pvm_recv. If pvm_freebuf is successful, info will be 0. If some error occurs then info will be < 0.S.= % €]€€‚‚ÿpvm_freebuf can be called for a send buffer created by pvm_mkbuf after the message has been sent and is no longer needed. Receive buffers typically do not have to be freed unless they have been saved in the course of using multiple buffers. But pvm_freebuf can be used to destroy receive buffers as well. So messages that arrive but are no longer needed can be destroyed so they will not consume buffer space. Typically multiple send and receive buffers are not needed and the user can simply use the pvm_initsend routine toreset the default send buffer. ã¸' €Ç€€‚‚‚‚ÿThere are several cases where multiple buffers are useful. One example where multiple message buffers are needed involves libraries or graphical interfaces that use PVM and interact with a running PVM application but do not want to interfere with the application's own communication.When multiple buffers are used they generally are made and freed for each message that is packed. In fact, pvm_initsend simply does a pvm_freebuf followed by a pvm_mkbuf for the default buffer. ×v ìa €í€€‚€€‚‚‚ƒ‚ƒ‚‚‚ƒ‚ƒ‚‚‚‚‚€€‚€€‚‚‚ã“v;ö‰‚ãÆ$«æ‰‚ã¬M„#‰‚‚ÿEXAMPLESC:bufid = pvm_mkbuf( PvmDataDefault );info = pvm_freebuf( bufid );Fortran:CALL PVMFMKBUF( PVMDEFAULT, BUFID )CALL PVMFFREEBUF( BUFID, INFO )ERRORSThese error conditions can be returned by pvm_freebufPvmBadParam: giving an invalid argument value.PvmNoSuchBuf: giving an invalid bufid value.see alsopvm_mkbufpvm_initsendpvm_recv@, 1qÄ‹í, a ¡ pvm_freecontext5ìa # €$€€‚ÿpvm_freecontext@, ¡ ) "€.€€ãéZb‰‚ÿsee pvm_newcontext@a á 1Ö Ä‚á  3Epvm_freezegroup5¡  # €$€€‚ÿpvm_freezegroupJá ` I `€€€€‚‚‚‚ƒ‚‚ƒ‚‚‚‚‚‚‚‚‚‚‚‚‚€€‚€€‚ÿpvm_freezegroup Freezes dynamic group membership and caches info locally SYNOPSISCint info = pvm_freezegroup( char *group , int size)Fortrancall pvmffreezegroup( group, size, info )PARAMETERSgroupCharacter string group name of an existing group.sizeSize of the group when it is frozen infosize of group on success. Values less than 0 indicate and error. DESCRIPTIONThe routine pvm_freezegroup makes a dynamic group named group static. The group information is then "cached" by all group members. pvm_freezegroup is a synchronizing routine and must be called by all group members to complete. size indicates the size the dynamic group should be when made static. A value of -1 indicates that the current size of the group should be used.zP æA* "€¡€€‚‚‚‚‚‚‚ÿinforeturns error information.Once a dynamic group has been frozen with pvm_freezegroup, all subsequent operations that can be satisfied with local data use the locally held information. For processes that are outside of the group, the first group call, e.g., pvm_bcast(), will cause the static group information to be copied to the calling process. Subsequent operations then use the local information. Barriers are still arbitrated by the group server.Group members should call pvm_lvgroup to leave the group and free any allocated structures that hold the group information. Processes not in the group may call pvm_lvgro` æA¡ up to free any locally allocated structures. In this case, an error code of PvmNotInGroup or PvmNoGroup will be returned to the caller. Barrier are always arbitrated by the group server, even if the group has been made static with pvm_freezegroup. If a process leaves a static group while other process are waiting at a barrier, then PvmNoGroup is returned to all processes waiting at the barrier. Future barrier calls with the defunct static group, return the same error.&Û`  DK d€·€€‚€€‚‚‚ƒ‚ƒ‚‚‚ƒ‚ƒ‚‚‚€€‚€€‚‚‚‚‚ÿEXAMPLESC: inum = pvm_joingroup("worker");info = pvm_freezegroup( "worker", size );Fortran: CALL PVMFJOINGROUP('group2', inum)CALL PVMFFREEZEGROUP( 'group2', size, info )ERRORSThese error conditions can be returned by pvm_freezegroupPvmSysErr: pvmd was not started or has crashed.PvmBadParam: giving a NULL group name.PvmDupGroup: trying to freeze a group that is already frozen.PvmNotInGroup: trying to freeze a group that you are not in.'çæA3E@ N€Ï€€‚€€‚‚‚‚‚‚‚‚ã• ãom\‰‚ÿBUGSThere is no way to unfreeze a group.Processes are not notified if a frozen group becomes invalid.Having a non-member process call pvm_lvgroup to free structures is a bit strange.see alsopvm_barrierpvm_lvgroup; DnE1ríæ nEžEÛ„pvm_gather0 3EžE# €€€‚ÿpvm_gather2÷nEÐH; D€ï€€€‚‚‚‚‚‚‚‚‚‚‚€€‚‚‚‚ÿpvm_gather A specified member of the group receives messages from each member of the group and gathers these messages into a single array.SYNOPSISC int info = pvm_gather( void *result, void *data, int count, int datatype, int msgtag, char *group, int rootginst)Fortran call pvmfgather(result, data, count, datatype, msgtag, group, rootginst, info)PARAMETERSresultOn the root this is a pointer to the starting address of an array datatype of local values which are to be accumulated from the members of the group. If n is the number of members in the group, then this array of datatype should be of length at least n* count. This argument is meaningful only on the root.b3žE2K/ ,€g€€‚‚‚‚‚‚‚‚‚‚‚‚ÿdata For each group member this is a pointer to the starting address of an array of length count of datatype which will be sent to the specified root member of the group.countInteger specifying the number of elements of datatype to be sent by each member of the group to the root.datatype Integer specifying the type of the entries in the result and data arrays. (See below for defined types.)msgtag Integer message tag supplied by the user. msgtag should be >= 0. It allows the user's program to distinguish between different kinds of messages.}NÐH¯N/ ,€€€‚‚‚‚‚‚‚‚‚‚‚‚ÿgroup Character string group name of an existing group.rootginstInteger instance number of group member who performs the gather of the messages from the members of the group.info Integer status code returned by the routine. Values less than zero indicate an error.DESCRIPTIONpvm_gather() performs a send of messages from each member of the group to the specified root member of the group. All group members must call pvm_gather(), each sends its array data of length count of datatype to the root which accumulates these messages into its result array. It is as if the root receives count elements of datatype from the ith member of the group and places these values in its result array starting with offset i* count from the beginning of the result array. The root task is identified by its instance number in the group. §u2Kb2 2€ë€€‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚ÿC and Fortran defined datatypes are: C datatypes FORTRAN datatypes ----------------------------------- PVM_BYTE BYTE1 PVM_SHORT INTEGER2 PVM_INT INTEGER4 PVM_FLOAT REAL4 PVM_CPLX ¯Nb3E COMPLEX8 PVM_DOUBLE REAL8 PVM_DCPLX COMPLEX16 PVM_LONGIn using the scatter and gather routines, keep in mind that C stores multidimensional arrays in row order, typically starting with an initial index of 0; whereas, Fortran stores arrays in column order, typically starting with an offset of 1.)õ¯N‹ƒ4 6€ë€€‚‚‚‚€€‚‚‚‚‚‚‚ÿNote: pvm_gather() does not block. If a task calls pvm_gather and then leaves the group before the root has called pvm_gather an error may occur.The current algorithm is very simple and robust. A future implementation may make more efficient use of the architecture to allow greater parallelism.EXAMPLESC: info = pvm_gather(&getmatrix, &myrow, 10, PVM_INT, msgtag, "workers", rootginst);Fortran: CALL PVMFGATHER(GETMATRIX, MYCOLUMN, COUNT, INTEGER4, MTAG, 'workers', ROOT, INFO)PñbÛ„_ Œ€ã€€‚€€‚€€‚€€‚€€‚€€‚‚ãßäóó‰‚ã• 㺿áö‰‚‚‚ÿERRORSThese error conditions can be returned by pvm_gatherPvmNoInst: Calling task is not in the groupPvmBadParam: The datatype specified is not appropriatePvmSysErr: Pvm system errorpvm_bcastpvm_barrierpvm_psend?‹ƒ…1q‚ …N…Ž…pvm_getcontext4Û„N…# €"€€‚ÿpvm_getcontext@…Ž…) "€.€€ãéZb‰‚ÿsee pvm_newcontext; N…É…1¹ æ – É…ù…pvm_getfds0 Ž…ù…# €€€‚ÿpvm_getfdsò¯É…ëˆC T€_€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚€€‚‚ÿpvm_getfds Get file descriptors in use by PVM.SYNOPSISCint nfds = pvm_getfds( int **fds )FortranNot AvailablePARAMETERSfdsReturns integer array of file descriptors.DESCRIPTIONA PVM task uses sockets to communicate between libpvm and other tasks or the pvmd. It is sometimes useful to know the file descriptor numbers of the sockets in order to wait from input from either PVM messages or an external source. For example, the PVM console waits on both keyboard input and notify messages. Input can be multiplexed by polling all sources, but this wastes cpu cycles. Instead, the select() system call can be used to wait until one or more sources of input are ready. çù…ø‹& €Ï€€‚‚‚ÿIf it completes successfully, pvm_getfds returns the number of sockets in use, and the file descriptor numbers in an array (allocated and freed by libpvm). At least one socket always exists (from task to pvmd), and its descriptor is always fds[0]. The number of sockets varies as direct routes are established to other tasks. It can be difficult to track the set of file descriptors if direct routing is enabled, because routes are created as messages are either sent or received. The simplest approach is to disable direct routing. When select returns with a PVM file descriptor ready, a complete message may be ready to be received, or instead only a fragment may be waiting. pvm_nrecv or pvm_probe should be used test without blocking. ½ëˆŽO l€{€€‚€€‚‚‚€€‚‚‚‚ƒ‚ƒ‚‚ƒ‚ƒ‚‚ƒ‚ƒ‚ƒ‚ƒ‚ƒƒ‚ƒƒ‚ÿRESTRICTIONSpvm_getfds is only available when running PVM on a Unix or similar system.EXAMPLESThe following program fragment waits until either keyboard input is available, or a PVM message has arrived.int *d;fd_set r;pvm_setopt(PvmRoute, PvmDontRoute);pvm_getfds(&d);FD_ZERO(&r);FD_SET(0, &r);FD_SET(d[0], &r);while (1) {if (select(d[0] + 1, &r, (fd_set*)0, (fd_set*)0, (struct timeval*)0) > 0) {}(ø‹U x€Q€€ƒƒƒ‚ƒƒƒƒ‚ƒƒƒ‚ƒƒƒƒ‚ƒƒ‚ƒ‚‚€€‚‚‚‚‚ãA¦e‰‚ã$2±÷‰‚‚ÿif (FD_ISSET(0, &r))... /* read keyboard input */if (FD_ISSET(d[0], &r) && pvm_nrecv(-1, -1) > 0)... /* got a PVM message */}}ERRORSThe following error condition can be returned by pvm_getfds:PvmSysErr: pvmd not responding.see alsopvm_notifypvm_trecv< ޽1o É„ ½ À›Åpvm_getinst1 À# €€€‚ÿpvm_getinst½ ÀÀ½ÂG \€€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚‚‚€€‚ÿpvm_getinst Returns the instance number in a group of a PVM process.SYNOPSISCint inum = pvm_getinst( char *group, int tid )Fortrancall pvmfgetinst( group, tid, inum )PARAMETERSgroupCharacter string group name of an existing group.tidInteger task identifier of a PVM process.inumInteger instance number returned by the routine. Instance numbers start at 0 and count up. Values less than zero indicate an error.DESCRIPTION Ò ÀÄ8 >€¥€€‚‚€€‚‚‚ƒ‚ƒ‚ƒ‚‚‚ƒ‚ÿThe routine pvm_getinst takes a group name group and a PVM task identifier tid and returns the unique instance number that corresponds to the input. It can be called by any task whether in the group or not. If pvm_getinst is successful, inum will be >= 0. If some error occurs then inum will be < 0.EXAMPLESC:inum = pvm_getinst( "worker", pvm_mytid() );--------inum = pvm_getinst( "worker", tid[i] );Fortran:CALL PVMFGETINST( 'GROUP3', TID, INUM )~7›ÅG \€o€€‚€€‚€€‚‚‚‚‚‚‚ãC^w0‰‚ãÛ³F&‰‚‚ÿERRORSThese error conditions can be returned by pvm_getinstPvmSysErr: pvmd was not started or has crashed.PvmBadParam: giving an invalid tid value.PvmNoGroup: giving a non-existent group name.PvmNotInGroup:specifying a group in which the tid is not a member.see alsopvm_joingrouppvm_gettid@ÄÛÅ1n– ï„ ÛÅÆMÆpvm_getmboxinfo5›ÅÆ# €$€€‚ÿpvm_getmboxinfo=ÛÅMÆ) "€(€€ãkÙ9‰‚ÿsee pvm_putinfo< ƉÆ1nÉ„ … ‰ÆºÆ÷Æpvm_getmwid1MƺÆ# €€€‚ÿpvm_getmwid=‰Æ÷Æ) "€(€€ã¹B<‰‚ÿsee pvm_setmwid; ºÆ2Ç1þï„ ìŠ 2ÇbÇ/Îpvm_getopt0 ÷ÆbÇ# €€€‚ÿpvm_getopt$×2džÉM h€¯€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒ‚ƒƒ‚ÿpvm_getopt Returns the value of libpvm options.SYNOPSISCint val = pvm_getopt( int what )Fortrancall pvmfgetopt( what, val )PARAMETERSwhatInteger defining option to get.One of:PvmRoute1 Message routing policyPvmDebugMask 2 Libpvm debug maskPvmAutoErr3 Auto error reportingPvmOutputTid 4 Stdout destination for children PvmOutputCode 5 Output message tagPvmTraceTid 6 Trace data destination for children ábÇ¡Ë: B€Ã€€ƒ‚ƒƒ‚ƒƒ‚ƒ‚ƒ‚ƒƒ‚ƒ‚ƒƒ‚ƒƒ‚ÿPvmTraceCode 7 Trace message tagPvmFragSize 8 Message fragment sizePvmResvTids 9 Allow messages to reserved tags and TIDs PvmSelfOutputTid 10 Stdout destinationPvmSelfOutputCode 11 Output message tagPvmSelfTraceTid 12 Trace data destinationPvmSelfTraceCode 13 Trace message tagPvmShowTids 14 pvm_catchout prints task ids with output PvmPollType 15 Message wait policy (shared memory) #׆ÉÄÍL f€¯€€ƒƒ‚‚‚‚‚€€‚‚‚‚‚€€‚‚‚ƒ‚‚ƒ‚‚€€‚‚ÿPvmPollTime 16 Message spinwait durationvalInteger returning the value of the option.DESCRIPTIONThe routine pvm_getopt returns the value of the specified option in PVM. For a discussion of options and values, see pvm_setopt.If an error occurs, the PVM error code is returned in place of the option value.EXAMPLESC:val = pvm_getopt( PvmFragSize );Fortran:CALL PVMFGETOPT( PVMAUTOERR, VAL )ERRORSThis error condition can be returnedk?¡Ë/Î, (€~€€‚‚‚ã¿l‰‚ÿPvmBadParam: giving an invalid value.see alsopvm_setopt< ÄÍkÎ1\… y kΜÎipvm_getrbuf1/ΜÎ# €€€‚ÿpvm_getrbufÁkθO l€ƒ€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚€€‚‚‚€€‚‚‚ƒ‚ÿpvm_getrbuf Returns the message buffer identifier for the active receive buffer.SYNOPSISCint bufid = pvm_getrbuf( void )Fortrancall pvmfgetrbuf( bufid )PARAMETERSbufidInteger returning message buffer identifier for the active receive buffer.DESCRIPTIONTheœÎ¸/Î routine pvm_getrbuf returns the message buffer identifier bufid for the active receive buffer or 0 if there is no current buffer.EXAMPLESC:bufid = pvm_getrbuf();±yœÎi8 @€ò€€‚‚ƒ‚‚€€‚‚‚‚ã˜ÏÞm‰‚ÿFortran:CALL PVMFGETRBUF( BUFID )ERRORSNo error conditions are returned by pvm_getrbufsee alsopvm_getsbuf< ¸¥1êìŠ ¹ ¥Öpvm_getsbuf1iÖ# €€€‚ÿpvm_getsbuf¹¥ÞO l€s€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚€€‚‚‚€€‚‚‚ƒ‚ÿpvm_getsbuf Returns the message buffer identifier for the active send buffer.SYNOPSISCint bufid = pvm_getsbuf( void )Fortrancall pvmfgetsbuf( bufid )PARAMETERSbufidInteger returning message buffer identifier for the active send buffer.DESCRIPTIONThe routine pvm_getsbuf returns the message buffer identifier bufid for the active send buffer or 0 if there is no current buffer.EXAMPLESC:bufid = pvm_getsbuf();±yÖ8 @€ò€€‚‚ƒ‚‚€€‚‚‚‚ã™Ým‰‚ÿFortran:CALL PVMFGETSBUF( BUFID )ERRORSNo error conditions are returned by pvm_getsbufsee alsopvm_getrbuf; ÞÊ1Èy É !Êú‘ pvm_gettid0 ú# €€€‚ÿpvm_gettid¦]Ê I `€»€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚‚‚‚€€‚‚ÿpvm_gettid Returns the tid of the process identified by a group name and instance number.SYNOPSISCint tid = pvm_gettid( char *group, int inum )Fortrancall pvmfgettid( group, inum, tid )PARAMETERSgroupCharacter string that contains the name of an existing group.inumInteger instance number of the process in the group.tidInteger task identifier returned.DESCRIPTIONThe routine pvm_gettid returns the tid of the PVM process identified by the group name group and the instance number inum. If pvm_gettid is successful, tid will be > 0. If some error occurs then tid will be < 0.ñ¦ú‘ K d€M€€‚€€‚‚‚ƒ‚‚‚ƒ‚‚‚‚‚‚‚‚‚‚ãC^w0‰‚ã>Óm‰‚‚ÿEXAMPLESC: tid = pvm_gettid("worker",0);Fortran: CALL PVMFGETTID('worker',5,TID)ERRORSThese error conditions can be returned by pvm_gettid.PvmSysErr: Can not contact the local pvmd; most likely it is not running.PvmBadParam: Bad Parameter most likely a NULL character string.PvmNoGroup: No group exists by that name.PvmNoInst: No such instance in the group.see alsopvm_joingrouppvm_getinst=  Î 1o¹ í "Î  > pvm_gettmask2‘  # €€€‚ÿpvm_gettmask>Î > ) "€*€€ã€è‰‚ÿsee pvm_settmask: x 1¿É Ü #x § 5pvm_gsize/ > § # €€€‚ÿpvm_gsizeÓx À F Z€§€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚€€‚‚ÿpvm_gsize Returns the number of members presently in the named group.SYNOPSISCint size = pvm_gsize( char *group )Fortrancall pvmfgsize( group, size )PARAMETERSgroupCharacter string group name of an existing group.sizeInteger returning the number of members presently in the group. Values less than zero indicate an error.DESCRIPTIONThe routine pvm_gsize returns the size of the group named group. If there is an error size will be negative.-ó§ í: B€ç€€‚‚‚€€‚‚‚ƒ‚‚‚ƒ‚‚‚‚‚‚ÿSince groups can change dynamically in PVM 3.0, this routine can only guarantee to return the instantaneous size of a given group. It is the user's responsibility to make sure the group members are not changing dynamically during the call to pvm_gsize. EXAMPLESC:size = pvm_gsize( "worker" );Fortran:CALL PVMFGSIZE( 'group2', SIZE )ERRORSThese error conditions can be returned by pvm_gsizePvmSysErr: pvmd was not started or has crashed.PvmBadParam: giving an invalid group name.HÀ 5+ &€:€€‚‚ãC^w0‰‚ÿsee also pvm_joingroup9ín1í ”€ $nœžBpvm_halt. 5œ# €€€‚ÿpvm_haltÑnÄAK d€£€€€‚‚‚‚ƒ‚‚ƒ‚‚€‚‚€‚‚‚€€‚€€‚‚‚ÿpvm_halt Shuts down theœÄA5 entire PVM system.SYNOPSISCint info = pvm_halt( void )Fortrancall pvmfhalt( info )PARAMETERSinfoInteger returns the error status.DESCRIPTIONThe routine pvm_halt shuts down the entire PVM system including remote tasks, remote pvmds, the local tasks (including the calling task) and the local pvmd.The task calling pvm_halt() must ignore or catch signal \fISIGTERM\fR or it will be killed along with all the others.Ú”œžBF Z€)€€‚€€‚‚‚‚‚ã®×0O‰‚ãî{#‰‚ãpu#‰‚‚‚ÿERRORSThe following error conditions can be returnedPvmSysErr: ocal pvmd is not responding.see alsopvm_delhostspvm_killpvm_exit= ÄAÛB1ìÜ q† %ÛB CÈIpvm_hostsync2žB C# €€€‚ÿpvm_hostsyncÅÛBEC T€‹€€€‚‚‚‚ƒ‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚‚‚ÿpvm_hostsync Get time-of-day clock from PVM host.SYNOPSISC#include int info = pvm_hostsync( int host, struct timeval *clk, struct timeval *delta )Fortrancall pvmfhostsync( host, clksec, clkusec, deltasec, deltausec, info ) PARAMETERShostTID of host.clk(or clksec and clkusec) Returns time-of-day clock sample from host.delta(or deltasec and deltausec) Returns difference between local clock and remote host clock.X# CmG5 8€G€€‚€€‚€€‚‚‚‚ÿDESCRIPTIONpvm_hostsync samples the time-of day clock of a host in the virtual machine and returns both the clock value and the difference between local and remote clocks. To reduce the delta error due to message transit time, local clock samples are taken before and after reading the remote clock. Delta is the difference between the mean local clocks and remote clock.Note that the delta time can be negative. The microseconds field is always normalized to 0..999999, while the sign of the seconds field gives the sign of the delta.ÊEIH ^€•€€‚‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚‚‚‚‚‚€€‚€€‚‚ÿFor example:3.25 Sec = 3,2500000 = 0,0-1 uSec = -1,999999-1 Sec = -1,000000-1.1 Sec = -2,999000In C, if clk or delta is a null pointer, that parameter is not returned.ERRORSIf pvm_hostsync is successful, it returns PvmOk. These error conditions can be returned by pvm_hostsyncPvmSysErr: pvmd not responding.PvmNoHost: specified host not in virtual machine.PvmHostFail: host is unreachable (and thus possibly failed)ImGÈI- *€8€€‚‚ãL<‰‚‚‚ÿsee also pvm_config= IJ1? ”€ p &J7JB„pvm_initsend2ÈI7J# €€€‚ÿpvm_initsend ÁJDLL f€ƒ€€€‚‚ƒ‚‚ƒ‚‚‚‚‚‚ƒƒƒ‚ƒƒƒ‚ƒƒƒ‚ƒƒƒ‚‚‚ƒƒƒ‚ƒƒƒ‚ÿpvm_initsend Clear default send buffer and specify message encoding.Cint bufid = pvm_initsend( int encoding )Fortrancall pvmfinitsend( encoding, bufid )variables:encoding - Integer specifying the next message's encoding scheme.Options in C are:Encoding valueMEANINGPvmDataDefault0XDRPvmDataRaw1no encodingPvmDataInPlace2data left in placeOption names are in Fortran are:Encoding valueMEANINGPVMDEFAULT0XDRµw7JùN> J€ï€€ƒƒƒƒ‚ƒƒƒ‚‚‚‚‚€€‚€€‚ÿPVMRAW1no encodingPVMINPLACE2data left in placebufid:Integer returned containing the message buffer identifier.Values less than zero indicate an error.The routine pvm_initsend clears the send buffer and prepares it for packing a new message. The encoding scheme used for the packing is set by encoding. XDR encoding is used by default because PVM can not know if the user is going to add a heterogeneous machine before this message is sent.If the user knows that the next message will only be sent to a machine that understands the native format, then he can use PvmDataRaw encoding and save on encoding costs.X-DL]+ $€[€€‚€€‚ÿPvmDataInPlace encoding specifies that data be left in place during packing. The message buffer only contains the sizes and pointers to the items to be sent. When pvm_send is called the items are copied directly out of ùN]ÈIthe user's memory. This option decreases the number of times a message is copied at the expense of requiring the user to not modify the items between the time they are packed and the time they are sent.If pvm_initsend is successful, then bufid will contain the message buffer identifier. If some error occurs then bufid will be < 0.šUùN÷ƒE X€«€€‚‚‚‚ƒ‚ƒ‚ƒ‚ƒ‚‚‚ƒ‚ƒ‚ƒ‚‚€€€€‚ÿPvmDataInPlace allows only dense (stride = 1) data in version 3.3. It cannot be used on shared memory (*MP) architectures; a PvmNotImpl error will occur at send time.C:bufid = pvm_initsend( PvmDataDefault );info = pvm_pkint( array, 10, 1 );msgtag = 3 ;info = pvm_send( tid, msgtag );Fortran:CALL PVMFINITSEND(PVMRAW, BUFID)CALL PVMFPACK( REAL4, DATA, 100, 1, INFO )CALL PVMFSEND( TID, 3, INFO )These error conditions can be returned by pvm_initsend PvmBadParam giving an invalid encoding value PvmNoMem Malloc has failed. There is not enough memory to create the bufferK]B„0 0€6€€‚‚‚ã“v;ö‰‚€‚ÿsee alsopvm_mkbuf; ÷ƒ}„1öq† { '}„­„r‹pvm_insert0 B„­„# €€€‚ÿpvm_insertá–}„އK d€-€€€‚‚‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚‚‚‚€€‚‚ÿpvm_insert store data in pvmd database[In Version 3.4: Relaced by pvm_putinfo]SYNOPSISCint cc = pvm_insert( char *name, int index, int data )FortranNot availablePARAMETERSnameThe class name, a null-terminated string.indexThe class index, >= 0 or -1 for first available.dataData to store in the entry.DESCRIPTIONThe master pvmd maintains a simple database, which can be used to store values such as tids and make them accessible anywhere within a virtual machine. This is useful when building an application such as the group server, which must advertise its task id so clients can register send messages to register.J­„؉+ $€?€€‚€€‚ÿThe database stores integer data, indexed by pairs. The name may be any null-terminated string and the index any non-negative integer. Database entries are grouped by name into classes; index may be specified as -1 to store or retrieve the first available instance in a class. These functions are not part of the group library, but are the underlying mechanism used to implement it.pvm_insert stores data at the given index. If index is -1, the data is stored at the first available index in the named class, starting at 0.šIއr‹Q p€“€€‚€€‚€€‚€€‚€€‚‚‚ã•ó ‰‚ãœéT‰‚‚ÿERRORSIf successful, pvm_insert returns the index at which the data was stored, otherwise it returns a negative result. The following error conditions can be returned:PvmBadParam: giving an invalid argument value.PvmDupEntry: the requested pair is already in use.see alsopvm_deletepvm_lookup> ؉°‹1­p P (°‹ã‹ Âpvm_joingroup3r‹ã‹# € €€‚ÿpvm_joingroup…:°‹hŽK d€u€€€‚‚‚‚ƒ‚ƒ‚‚€€‚‚‚‚‚‚‚‚€€‚€€‚ÿpvm_joingroup Enrolls the calling process in a named group.SYNOPSISCint inum = pvm_joingroup( char *group )Fortrancall pvmfjoingroup( group, inum )PARAMETERSgroupCharacter string group name of an existing group.inumInteger instance number returned by the routine. Instance numbers start at 0 and count up. Values less than zero indicate an error.DESCRIPTIONThe routine pvm_joingroup enrolls the calling task in the group named group and returns the instance number, inum of this task in this group. If there is an error inum will be negative.î㋇À% €Ý€€‚‚ÿInstance numbers start at 0 and count up. When using groups a (group, inum) pair uniquely identifies a PVM process. This is consistent with the PVM 2.4 naming schemes. If a task leaves a group by calling pvm_lvgroup and later rejoins the same group, the task is not guaranteed to get the same instance number. PVM attempts to reuse old instance numbers, so when a task hއÀr‹joins a group it will get the lowest available instance number. A task can be a member of multiple groups simultaneously.™PhŽ ÂI `€¡€€‚€€‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚ãom\‰‚‚‚ÿEXAMPLESC:inum = pvm_joingroup( "worker" );Fortran:CALL PVMFJOINGROUP( 'group2', INUM )ERRORSThese error conditions can be returned by pvm_joingroupPvmSysErr: pvmd was not started or has crashed.PvmBadParam: giving a NULL group name.PvmDupGroup: trying to join a group you are already in.see also pvm_lvgroup9‡ÀYÂ1â{ q… )Y‡Â8Çpvm_kill. ‡Â# €€€‚ÿpvm_kill»pYÂBÅK d€á€€€‚‚‚‚ƒ‚ƒ‚‚€€‚‚‚‚‚‚‚‚€€‚€€‚ÿpvm_kill Terminates a specified PVM process.SYNOPSISCint info = pvm_kill( int tid )Fortrancall pvmfkill( tid, info )PARAMETERStidInteger task identifier of the PVM process to be killed (not yourself).infoInteger status code returned by the routine. Values less than zero indicate an error.DESCRIPTIONThe routine pvm_kill sends a terminate (SIGTERM) signal to the PVM process identified by tid. In the case of multiprocessors the terminate signal is replaced with a host dependent method for killing a process. If pvm_kill is successful, info will be 0. If some error occurs then info will be < 0.ö¦‡Â8ÇP n€M€€‚‚‚€€‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚ãpu#‰‚ã‹x#‰‚‚ÿpvm_kill is not designed to kill the calling process. To kill yourself in C call pvm_exit() followed by exit(). To kill yourself in Fortran call pvmfexit followed by stop.EXAMPLESC:info = pvm_kill( tid );Fortran:CALL PVMFKILL( TID, INFO )ERRORSThese error conditions can be returned by pvm_kill PvmBadParam: giving an invalid tid value.PvmSysErr: pvmd not responding.see alsopvm_exitpvm_halt; BÅsÇ1;P óˆ *sǣǭËpvm_lookup0 8Ç£Ç# €€€‚ÿpvm_lookup¢OsÇEÊS t€Ÿ€€€‚‚‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚‚‚‚€€‚ã3ê 9‰‚‚‚ÿpvm_lookup retrieve data from pvmd database[In Version 3.4: Relaced by pvm_getinfo]SYNOPSISCint cc = pvm_lookup( char *name, int index, int *data )FortranNot availablePARAMETERSnameThe class name, a null-terminated string.indexThe class index, >= 0 or -1 for first available.dataReturns the data stored in the entry.DESCRIPTIONSee pvm_insert for a description of this database.pvm_lookup retrieves data stored in the location given by . If index is -1, the data stored at the first existing index in the named class is returned.h&£Ç­ËB R€M€€‚€€‚‚‚‚‚‚‚‚ã•ó ‰‚ã3ê 9‰‚‚‚ÿEXAMPLESERRORSIf successful, pvm_lookup returns the index at which the data was stored (>= 0), otherwise it returns a negative error code:PvmBadParam: giving an invalid argument value.PvmNoEntry: the requested pair does not exist.see alsopvm_delete,pvm_insert< EÊéË1%q… ^ +éËÌñpvm_lvgroup1­ËÌ# €€€‚ÿpvm_lvgroupÌéË+ÎE X€™€€€‚‚‚‚ƒ‚ƒ‚‚€€‚‚‚‚‚‚‚‚€€‚‚ÿpvm_lvgroup Unenrolls the calling process from a named group.SYNOPSISCint info = pvm_lvgroup( char *group )Fortrancall pvmflvgroup( group, info )PARAMETERSgroupCharacter string group name of an existing group.infoInteger status code returned by the routine. Values less than zero indicate an error.DESCRIPTIONThe routine pvm_lvgroup unenrolls the calling process from the group named group. If there is an error info will be negative..ùÌe5 8€ó€€‚‚‚‚‚‚ƒ‚‚‚ƒ‚‚‚‚‚‚‚ÿIf a process leaves a group by calling either pvm_lvgroup or pvm_exit, and later rejoins the same group, the process may be assigned a new instance number. Old instance numbers are reassigned to processes calling pvm_joingroup. EXAMPLESC:info = pvm_lvgroup( "worker" );Fortran:CALL PVMFLVGROUP( 'group2', INFO )ERRORSThese error conditions can be returned by pvm_lvgroup PvmSysErr: pvmd not respondin+Îe­Ëg.PvmBadParam: giving a NULL group name.PvmNoGroup: giving a non-existent group name.Œ^+Îñ. ,€¼€€‚‚‚ãC^w0‰‚‚‚ÿPvmNotInGroup: asking to leave a group you are not a member of.see alsopvm_joingroup: e+1â óˆ  ,+Z pvm_mcast/ ñZ# €€€‚ÿpvm_mcastF + = H€€€€‚‚‚‚ƒ‚‚ƒ‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚ÿpvm_mcast Multicasts the data in the active message buffer to a set of tasks.SYNOPSISCint info = pvm_mcast( int *tids, int ntask, int msgtag )Fortrancall pvmfmcast( ntask, tids, msgtag, info )PARAMETERSntaskInteger specifying the number of tasks to be sent to.tidsInteger array of lengthntaskcontaining the task IDs of the tasks to be sent to.msgtagInteger message tag supplied by the user. msgtag should be >= 0. It allows the user's program to distinguish between different kinds of messages .Ô©Zt+ $€S€€‚‚‚‚‚‚‚‚ÿinfoInteger status code returned by the routine. Values less than zero indicate an error.DESCRIPTIONThe routine pvm_mcast multicasts a message stored in the active send buffer to ntask tasks specified in the tids array. The message is not sent to the caller even if listed in the array of tids. The content of the message can be distinguished by msgtag. If pvm_mcast is successful, info will be 0. If some error occurs then info will be < 0.The receiving processes can call either pvm_recv or pvm_nrecv to receive their copy of the multicast. pvm_mcast is asynchronous and based on a minimum spanning tree algorithm between the pvmds. Computation on the sending processor resumes as soon as the message is safely on its way to the receiving processors. This is in contrast to synchronous communication, during which computation on the sending processor halts until the matching receive is executed by the receiving processor. E  ¹ % €A€€‚‚ÿpvm_mcast first determines which other pvmds contain the specified tasks. Then passes the message to these pvmds which in turn distribute the message to their local tasks without further network traffic. Multicasting is not supported by most multiprocessor vendors. Typically their native calls only support broadcasting to all the user's processes on a multiprocessor. Because of this omission, pvm_mcast may not be an efficient communication method on some multiprocessors except in the special case of broadcasting to all PVM processes. ¼tÁ L f€y€€‚€€‚‚‚ƒ‚ƒ‚ƒ‚ƒ‚‚‚ƒ‚ƒ‚ƒ‚‚‚‚‚‚‚‚‚㺿áö‰‚ÿEXAMPLESC:info = pvm_initsend( PvmDataRaw );info = pvm_pkint( array, 10, 1 );msgtag = 5 ;info = pvm_mcast( tids, ntask, msgtag );Fortran:CALL PVMFINITSEND(PVMDEFAULT)CALL PVMFPACK( REAL4, DATA, 100, 1, INFO )CALL PVMFMCAST( NPROC, TIDS, 5, INFO )ERRORSThese error conditions can be returned by pvm_mcastPvmBadParam: giving a msgtag < 0.PvmSysErr: pvmd not responding.PvmNoBuf: no send buffer.see alsopvm_psendJ¹  0 0€4€ã`‡àö€‰‚ㆅ#‰‚ÿpvm_precv,pvm_send: Á E 1}^ °‡ -E t ËJpvm_mkbuf/ t # €€€‚ÿpvm_mkbufªE z\ †€U€€€‚‚ƒ‚‚ƒ‚‚€€‚€€‚‚‚ƒƒƒ‚ƒƒƒ‚ƒƒƒ‚ƒƒƒ‚‚‚ƒƒƒ‚ƒƒƒ‚ƒƒƒ‚ÿpvm_mkbuf Creates a new message buffer.Cint bufid = pvm_mkbuf( int encoding )Fortrancall pvmfmkbuf( encoding, bufid )PARAMETERSencoding: Integer specifying the buffer's encoding scheme.Options in C are:Encoding valueMEANINGPvmDataDefault0XDRPvmDataRaw1no encodingPvmDataInPlace2data left in placeOption names in Fortran are:Encoding valueMEANINGPVMDEFAULT0XDRPVMRAW1no encoding·|t =B; D€ù€€ƒƒƒ‚‚€€‚‚‚€€‚‚‚‚ÿPVMINPLACE2data left in placebufid:Integer message buffer identifier returned. Values less than zero indicate an error.Description:The routine pvm_mkbuf creates a new message buffer and sets its encoding status to encoding. If pvm_mkbuf is successful, bufid will be the identifier for the new buffer, which can be usez=B d as a send buffer. If some error occurs then bufid will be < 0.With the default setting XDR encoding is used when packing the message because PVM can not know if the user is going to add a heterogeneous machine before this message is sent. The other options to encoding allow the user to take advantage of knowledge about his virtual machine even when it is heterogeneous. For example, if the user knows that the next message will only be sent to a machine that understands the native format, then he can use PvmDataRaw encoding and save on encoding costs.·zôD' €!€€‚‚‚‚ÿPvmDataInPlace encoding specifies that data be left in place during packing. The message buffer only contains the sizes and pointers to the items to be sent. When pvm_send is called the items are copied directly out of the user's memory. This option decreases the number of times a message is copied at the expense of requiring the user to not modify the items between the time they are packed and the time they are sent.pvm_mkbuf is required if the user wishes to manage multiple message buffers and should be used in conjunction with pvm_freebuf. pvm_freebuf should be called for a send buffer after a message has been sent and is no longer needed.‚Y=BvG) €³€€‚‚‚‚‚‚ÿReceive buffers are created automatically by the pvm_recv and pvm_nrecv routines and do not have to be freed unless they have been explicitly saved with pvm_setrbuf.Typically multiple send and receive buffers are not needed and the user can simply use the pvm_initsend routine to reset the default send buffer.There are several cases where multiple buffers are useful. One example where multiple message buffers are needed involves libraries or graphical interfaces that use PVM and interact with a running PVM application but do not want to interfere with the application's own communication.ÁôD|IE X€ƒ€€‚‚‚€€‚‚‚‚€€‚‚‚ƒ‚ƒ‚ƒ‚‚‚ƒ‚ƒ‚ÿWhen multiple buffers are used they generally are made and freed for each message that is packed.RESTRICTIONS:PvmDataInPlace allows only dense (stride = 1) data in version 3.3.It cannot be used on shared memory (*MP) architectures; a PvmNotImpl error will occur at send time.EXAMPLESC:bufid = pvm_mkbuf( PvmDataRaw );/* send message */info = pvm_freebuf( bufid );Fortran:CALL PVMFMKBUF(PVMDEFAULT, MBUF)*SEND MESSAGE HEREOvGËJI `€ €€ƒ‚‚€€‚‚‚ƒƒ‚ƒƒ‚‚‚ãÆ$«æ‰ƒ‚ãE3àc‰€‚ÿCALL PVMFFREEBUF( MBUF, INFO )ERRORSThese error conditions can be returned by pvm_mkbufPvmBadParamgiving an invalid encoding value.PvmNoMemMalloc has failed. There is not enough memory to create the buffersee alsopvm_initsendpvm_freebuf: |IK1 .K4K*€pvm_mstat/ ËJ4K# €€€‚ÿpvm_mstat5àKiNU x€Á€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚ƒƒƒ‚ƒƒƒ‚ƒƒ‚ƒƒ‚‚€€‚‚ÿpvm_mstat Returns the status of a host in the virtual machine.SYNOPSISCint mstat = pvm_mstat( char *host )Fortrancall pvmfmstat( host, mstat )PARAMETERShostCharacter string containing the host name.mstatInteger returning machine status:valueMEANINGPvmOkhost is OKPvmNoHosthost is not in virtual machinePvmHostFailhost is unreachable (and thus possibly failed)DESCRIPTIONThe routine pvm_mstat returns the status mstat of the computer named host with respect to running PVM processes. This routine can be used to determine if a particular host has failed and if the virtual machine needs to be reconfigured. The function pvm_notify() can also be used to notify the caller that a host has failed. µf4K*€O l€Í€€‚€€‚‚‚ƒ‚‚‚ƒ‚‚€€‚‚‚‚‚‚‚ãA¦e‰‚ãL<‰‚ÿEXAMPLESC:mstat = pvm_mstat( "msr.ornl.gov" );Fortran:CALL PVMFMSTAT( 'msr.ornl.gov', MSTAT )ERRORSThese error conditions can be returned by pvm_mstat PvmSysErr: pvmd not responding.PvmNoHost: giving a host name not in the virtual machine.PvmHostFail: host is unreachable (and thus possibly failed).see alsiN*€ËJo pvm_notifypvm_config: iNd€1а‡ « /d€“€ì†pvm_mytid/ *€“€# €€€‚ÿpvm_mytidL d€ß‚C T€€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚€€‚‚ÿpvm_mytid Returns the \fItid\fR of the calling process.SYNOPSISCint tid = pvm_mytid( void )Fortrancall pvmfmytid( tid )PARAMETERStidInteger returning the task identifier of the calling PVM process. Values less than zero indicate an error.DESCRIPTIONThe routine pvm_mytid enrolls this process into PVM on its first call. It also generates a unique tid if this process was not created by pvm_spawn. pvm_mytid returns the tid of the calling process and can be called multiple times in an application.i“€o…' €Ó€€‚‚‚‚ÿAny PVM system call (not just pvm_mytid) will enroll a task in PVM if the task is not enrolled before the call.The tid is a 32 bit positive integer created by the local pvmd. The 32 bits are divided into fields that encode various information about this process such as its location in the virtual machine (i.e. local pvmd address), the CPU number in the case where the process is on a multiprocessor, and a process ID field. This information is used by PVM and is not expected to be used by applications. Applications should not attempt to predict or interpret the tid with the exception of calling tidtohost()}-ß‚ì†P n€[€€‚‚‚€€‚‚‚ƒ‚‚‚ƒ‚‚€€‚‚‚‚‚ãT‰‚ãºOt‰‚‚ÿIf PVM has not been started before an application calls pvm_mytid the returned tid will be < 0.EXAMPLESC:tid = pvm_mytid( );Fortran:CALL PVMFMYTID( TID )ERRORSThis error condition can be returned by pvm_mytidPvmSysErr: pvmd not responding.see alsopvm_tidtohostpvm_parent?o…+‡1 n 0+‡_‡•Ãpvm_newcontext4ì†_‡# €"€€‚ÿpvm_newcontextÅ+‡v‰R r€‹€€€‚‚€€‚€€‚€€‚‚‚‚ƒ‚ƒ‚ƒ‚ƒ‚‚‚ƒ‚ƒ‚ƒ‚ƒ‚ÿpvm_newcontext Request new context.pvm_setcontext Change context.pvm_freecontext Free existing context.pvm_getcontext Get current context.SYNOPSISCint ctx = pvm_newcontext( void )int old_ctx = pvm_setcontext( int new_ctx )int info = pvm_freecontext( ctx )int ctx = pvm_getcontext( void )Fortrancall pvmfnewcontext( ctx )call pvmfsetcontext( new_ctx, old_ctx )call pvmffreecontext( ctx, info )call pvmfgetcontext( ctx )þÄ_‡t: B€‰€€‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚€€‚‚ÿPARAMETERSctxContext value.new_ctxNew context value.old_ctxPrior context value.infoResult code.DESCRIPTIONThe context functions provide a system-wide unique context and the means to manipulate this context. Contexts provide the ability for communicating tasks to automatically differentiate messages by the context in which they were sent. Thus a message sent in context A by the sender must be received in context A by the recipient. A sender may send in any context. However, a recipient will not accept a message sent in a context that differs from its own. One such use of contexts is with library routines. Using contexts, library routine inter-communication may be logically seperated from the user's application inter-communication. This will prevent the inadvertent receipt of one another's messages. Spawned tasks inherit the spawn-time context of their parent. Existing PVM applications work unchanged using the default context.3üv‰§7 <€ù€€‚‚‚‚‚‚‚‚‚‚‚ƒ‚ƒ‚‚ƒƒƒ‚ÿpvm_newcontext returns a newly allocated context. However, this new context is not yet active. pvm_setcontext changes the current context from old_ctx to new_ctx.pvm_freecontext frees ctx so that it may be reused. Contexts are a system resource that will be exhausted if not recycled.pvm_getcontext returns the current context of the requesting task.EXAMPLES/* parent task with context */int cc, context0, context1;char buf[25];context0 = pvm_getcontext();/* get my current context */3ötæÁ= H€í€€ƒƒƒƒƒ‚ƒ‚ƒ‚ƒƒƒ‚ƒ‚ƒ‚ƒƒƒ‚‚‚ƒ‚ÿcontext1 = pvm_newcontext(§æÁì†);/* get a new context */ pvm_setcontext(context1);/* set my context to new context */printf("My context is: %d", context1);pvm_spawn("child", (char**)0, PvmTaskDefault, "", 1, &tid);cc = pvm_recv(-1, -1);/* receive message from child - in context1 */ pvm_upkstr(buf);printf("%s", buf);pvm_setcontext(context0);/* reset my context to my original context0 *//* child task with context - child inherits parent's context as default */ int context;¯n§•ÃA P€Ý€€ƒ‚ƒ‚‚ƒ‚ƒƒƒ‚ƒƒ‚ƒ‚ƒ‚ƒ‚‚€€‚‚‚ÿint ptid;char buf[25];ptid = pvm_parent();context = pvm_getcontext();/* get my current context */sprintf(buf, "Greetings from child who's context is: %d.", context); pvm_initsend(PvmDataDefault);pvm_pkstr(buf);pvm_send(ptid, 1);ERRORSOnly system resource errors will be returned as the context programs themselves do not generate errors.; æÁÐÃ1( « XŠ 1ÐÃÄ÷Ípvm_notify0 •ÃÄ# €€€‚ÿpvm_notifyÐÐÃÆE X€¡€€€‚‚‚‚ƒ‚‚ƒ‚‚‚‚‚‚‚ƒƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚‚‚‚ÿpvm_notify Request notification of PVM event such as host failure.SYNOPSISCint info = pvm_notify( int what, int msgtag, int cnt, int *tids ) .brFortrancall pvmfnotify( what, msgtag, cnt, tids, info )PARAMETERSwhatType of event to trigger the notification. Presently one of:ValueMeaningPvmTaskExitTask exits or is killedPvmHostDeleteHost is deleted or crashesPvmHostAddNew host is addedmsgtagMessage tag to be used in notification.›kİÈ0 .€×€€‚‚‚‚‚‚‚‚‚‚‚‚‚ÿcntFor PvmTaskExit and PvmHostDelete, specifies the length of the tids array.For PvmHostAdd, specifies the number of times to notify.tidsFor PvmTaskExit and PvmHostDelete, an array of length cnt of task or pvmd TIDs to be notified about. The array is not used with the PvmHostAdd option.infoInteger status code returned by the routine. Values less than zero indicate an error.DESCRIPTIONThe routine pvm_notify requests PVM to notify the caller on detecting certain events. One or more notify messages (see below) are sent by PVM back to the calling task. The messages have tag msgtag supplied to notify.: ÆêÊ. *€€€‚‚‚‚‚‚‚‚‚‚‚ÿThe notification messages have the following format:PvmTaskExitOne notify message for each TID requested. The message body contains a single TID of exited task.PvmHostDeleteOne notify message for each TID requested. The message body contains a single pvmd-TID of exited pvmd.PvmHostAddcnt notify messages are sent, one each time the local pvmd's host table is updated. The message body contains an integer length followed by a list of pvmd-TIDs of new pvmds. The counter of PvmHostAdd messages yet to be sent isͰÈìÌ5 8€›€€‚‚‚‚‚‚‚€€‚‚‚ƒ‚ÿreplaced by successive calls to pvm_notify.Specifying a cnt of -1 turns on PvmHostAdd messages until a future notify; a count of zero disables them.TIDs in the notify messages are packed as integers. The calling task is responsible for receiving messages with the specified tag and taking appropriate action.Future versions of PVM may expand the list of available notification events.EXAMPLESC:info = pvm_notify( PvmTaskExit, 9999, ntask, tids ) ÉêÊ÷ÍB R€“€€‚‚ƒ‚‚€€‚‚‚‚‚ãÔøœ÷‰‚ãL<‰‚‚ÿFortran:CALL PVMFNOTIFY( PVMHOSTDELETE, 1111, NUMHOSTS, DTIDS, INFO )ERRORSPvmSysErr: pvmd not responding.PvmBadParam: giving an invalid argument value.see alsopvm_tasks,pvm_config: ìÌ1Î1v n þ21Î`Îl pvm_nrecv/ ÷Í`Î# €€€‚ÿpvm_nrecvÒ1ÎC T€¥€€€‚‚‚‚ƒ‚‚ƒ‚‚‚‚‚‚‚‚‚‚‚‚‚€€‚‚ÿpvm_nrecv Non-blocking receive.SYNOPSISCint bufid = pvm_nrecv( int tid, int msgtag )Fortrancall pvmfnrecv( tid, msgtag, bufid )PARAMETERStidInteger task identifier of sending process supplied by the user.msgtagInteger message tag supplied by the user. msgtag should be >= 0.bufidInteger returning the value of the new active rec`Î÷Íeive buffer identifier. Values less than zero indicate an error.DESCRIPTIONThe routine pvm_nrecv checks to see if a message with label msgtag has arrived from tid. and also clears the current receive buffer if any, If a matching message has arrived pvm_nrecv immediately places the message in a new active receive buffer, and returns the buffer identifier in bufid.V/`Î×' €_€€‚‚‚‚ÿIf the requested message has not arrived, then pvm_nrecv immediately returns with a 0 in bufid. If some error occurs bufid will be < 0.A -1 in msgtag or tid matches anything. This allows the user the following options. If tid = -1 and msgtag is defined by the user, then pvm_nrecv will accept a message from any process which has a matching msgtag. If msgtag = -1 and tid is defined by the user, then pvm_nrecv will accept any message that is sent from process tid. If tid = -1 and msgtag = -1, then pvm_nrecv will accept any message from any process. ýØÔ% €±€€‚‚ÿThe PVM model guarantees the following about message order. If task 1 sends message A to task 2, then task 1 sends message B to task 2, message A will arrive at task 2 before message B. Moreover, if both messages arrive before task 2 does a receive, then a wildcard receive will always return message A. pvm_nrecv is non-blocking in the sense that the routine always returns immediately either with the message or with the information that the message has not arrived at the local pvmd yet. pvm_nrecv can be called multiple times to check if a given message has arrived yet. In addition the blocking receive pvm_recv can be called for the same message if the application runs out of work it could do before the data arrives.'æ×ûA P€Í€€‚‚‚‚ƒ‚ƒ‚ƒ‚ƒ‚ƒƒ‚ƒ‚ƒƒ‚‚‚ƒ‚ƒ‚ƒ‚ƒ‚ÿIf pvm_nrecv returns with the message, then the data in the message can be unpacked into the user's memory using the unpack routines. C:tid = pvm_parent();msgtag = 4 ;arrived = pvm_nrecv( tid, msgtag );if ( arrived > 0)info = pvm_upkint( tid_array, 10, 1 );else/* go do other computing */Fortran:CALL PVMFNRECV( -1, 4, ARRIVED )IF ( ARRIVED .gt. 0 ) THEN CALL PVMFUNPACK( INTEGER4, TIDS, 25, 1, INFO ) CALL PVMFUNPACK( REAL8, MATRIX, 100, 100, INFO )qÔl ` Ž€#€€ƒ‚ƒ‚ƒ‚‚€€‚‚‚‚‚‚ãÿ­A›‰‚ã0‰Jʼn‚ã¬M„#‰‚ã;Óà÷‰‚ãzº1ö‰‚ㆅ#‰‚ÿELSE* GO DO USEFUL WORKENDIFERRORSThese error conditions can be returned by pvm_nrecv.PvmBadParam: giving an invalid tid value or msgtag.PvmSysErr: pvmd not responding.see alsopvm_bufinfopvm_getmboxinfopvm_recvpvm_unpk*pvm_mcastpvm_send8û¤ 10XŠ “3¤ Ñ F‡pvm_pk*- l Ñ # €€€‚ÿpvm_pk*&ö¤ ÷ 0 .€í€€€‚‚‚‚‚‚‚‚‚‚ÿpvm_pack Pack the active message buffer with arrays of prescribed data type.SYNOPSIS C int info = pvm_packf( const char *fmt, ... ) int info = pvm_pkbyte( char *xp, int nitem, int stride ) int info = pvm_pkcplx( float *cp, int nitem, int stride ) int info = pvm_pkdcplx( double *zp, int nitem, int stride ) int info = pvm_pkdouble( double *dp, int nitem, int stride ) int info = pvm_pkfloat( float *fp, int nitem, int stride )ÝÑ þ* "€»€€‚‚‚‚‚‚‚ÿ int info = pvm_pkint( int *ip, int nitem, int stride ) int info = pvm_pkuint( unsigned int *ip, int nitem, int stride ) int info = pvm_pkushort( unsigned short *ip, int nitem, int stride ) int info = pvm_pkulong( unsigned long *ip, int nitem, int stride ) int info = pvm_pklong( long *ip, int nitem, int stride ) int info = pvm_pkshort( short *jp, int nitem, int stride ) int info = pvm_pkstr( char *sp )Y÷ cA; D€=€€‚‚‚‚‚€€‚‚‚‚‚‚‚‚‚‚‚‚‚ÿ Fortran call pvmfpack( what, xp, nitem, stride, info )PARAMETERS fmt Printf-like format expression specifying what to pack. (See discussion).nitem The total numþcAl ber of items to be packed (not the number of bytes).stride The stride to be used when packing the items. For example, if stride = 2 in pvm_pkcplx, then every other complex number will be packed.xp Pointer to the beginning of a block of bytes. Can be any data type, but must match the corresponding unpack data type..óþ‘C; D€ç€€‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚ÿcp Complex array at least nitem*stride items long.zp Double precision complex array at least nitem*stride items long.dp Double precision real array at least nitem*stride items long.fp Real array at least nitem*stride items long.ip Integer array at least nitem*stride items long.jp Integer*2 array at least nitem*stride items long.sp Pointer to a null terminated character string.what Integer specifying the type of data being packed.í¯cA~F> J€_€€ƒƒ‚ƒƒ‚ƒ‚ƒƒ‚ƒ‚‚‚‚‚‚€€‚‚‚ÿ what options STRING 0 REAL4 4 BYTE1 1 COMPLEX8 5 INTEGER2 2 REAL8 6 INTEGER4 3 COMPLEX16 7info Integer status code returned by the routine. Values less than zero indicate an error.DESCRIPTIONEach of the pvm_pk* routines packs an array of the given data type into the active send buffer. The arguments for each of the routines are a pointer to the first item to be packed, nitem which is the total number of items to pack from this array, and stride which is the stride to use when packing.6‘C´H% €#€€‚‚ÿAn exception is pvm_pkstr() which by definition packs a NULL terminated character string and thus does not need nitem or stride arguments. The Fortran routine pvmfpack( STRING, ... ) expects nitem to be the number of characters in the string and stride to be 1.A null string ("") can be packed; this is just a string with no characters before the terminating '\0'. However, packing a null string pointer, (char *)0, is not allowed. If the packing is successful, info will be 0. If some error occurs then info will be < 0.!ù~FÕJ( €ó€€‚‚‚‚‚ÿA single variable (not an array) can be packed by setting nitem = 1 and stride = 1.The routine pvm_packf() uses a printf-like format expression to specify what and how to pack data into the send buffer. All variables are passed as addresses if count and stride are specified otherwise, variables are assumed to be values. A BNF-like description of the format syntax is: format : null | init | format fmt init : null | '%' '+' fmt : '%' count stride modifiers fchar Õ´HÞL4 6€«€€‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚ÿ fchar : 'c' | 'd' | 'f' | 'x' | 's' count : null | [0-9]+ | '*' stride : null | '.' ( [0-9]+ | '*' ) modifiers : null | modifiers mchar mchar : 'h' | 'l' | 'u'Formats: + means initsend - must match an int (how) in the param list. c pack/unpack bytes d integers f float x complex float s stringModifiers: h short (int) l long (int, float, complex float)ͧÕJ·€& €O€€‚‚‚ÿ u unsigned (int)Future extensions to the what argument in pvmfpack will include 64 bit types when XDR encoding of these types is available. Meanwhile users should be aware that precision can be lost when passing data from a 64 bit machine like a Cray to a 32 bit machine like a SPARCstation. As a mnemonic the what argument name includes the number of bytes of precision to expect. By setting encoding to PVMRAW (see pvmfinitsend) data can be transferred between two 64 bit machines with full precision even if the PVM configuration is heterogeneous. Messages should be unpacked exactly like they were packed to insure data integrity. Packing integers and unpacking them as floats will often fail because a type encoding will have occÞL·€l urred transferring the data between heterogeneous hosts. Packing 10 integers and 100 floats then trying to unpack only 3 integers and the 100 floats will also fail. ËÞL¹‚7 <€—€€‚€€‚‚‚‚‚‚‚‚‚‚‚‚‚ÿEXAMPLES C: info = pvm_initsend( PvmDataDefault ); info = pvm_pkstr( "initial data" ); info = pvm_pkint( &size, 1, 1 ); info = pvm_pkint( array, size, 1 ); info = pvm_pkdouble( matrix, size*size, 1 ); msgtag = 3 ; info = pvm_send( tid, msgtag ); int count, *iarry; double darry[4]; pvm_packf("%+ %d %*d %4lf", PvmDataRaw, count, count, iarry, darry);L·€…4 6€1€€‚‚‚‚‚‚‚‚‚€€‚‚ÿ Fortran: CALL PVMFINITSEND(PVMRAW, INFO) CALL PVMFPACK( INTEGER4, NSIZE, 1, 1, INFO ) CALL PVMFPACK( STRING, 'row 5 of NXN matrix', 19, 1, INFO ) CALL PVMFPACK( REAL8, A(5,1), NSIZE, NSIZE , INFO ) CALL PVMFSEND( TID, MSGTAG, INFO )WARNINGSStrings cannot be packed when using the PvmDataInPlace encoding, due to limitations in the implementation. Attempting to pack a string using pvm_pkstr or pvm_packf will cause error code PvmNotImpl to be returned.¡¹‚‡b ’€C€€‚€€‚‚€€‚‚€€‚‚€€‚‚‚ãÆ$«æ‰‚ã;Óà÷‰‚ã¬M„#‰‚ㆅ#‰‚‚ÿERRORSPvmNoMem: Malloc has failed. Message buffer size has exceeded the available memory on this host.PvmNoBuf: There is no active send buffer to pack into. Try calling pvm_initsend before packing message.PvmOverflow: Attempt to pack a value too large. E.g. packing an 8-byte long with XDR encoding if the value won't fit into 4 bytes.see alsopvm_initsendpvm_unpk*pvm_recvpvm_send>…F‡/ .€€€‚‚‚‚‚‚‚‚‚‚‚‚‚ÿ; ‡‡1¤þ‘4‡±‡$‹pvm_parent0 F‡±‡# €€€‚ÿpvm_parentF‡÷‰C T€€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚€€‚‚ÿpvm_parent Returns the tid of the process that spawned the calling process.SYNOPSISCint tid = pvm_parent( void )Fortrancall pvmfparent( tid )PARAMETERStidInteger returns the task identifier of the parent of the calling process. If the calling process was not created with pvm_spawn, then tid = PvmNoParent.DESCRIPTIONThe routine pvm_parent returns the tid of the process that spawned the calling process. If the calling process was not created with pvm_spawn, then tid is set to PvmNoParent.-$‹? L€Ý€€‚€€‚‚‚ƒ‚‚‚ƒ‚‚€€‚‚‚‚‚ÿEXAMPLESC:tid = pvm_parent();Fortran:CALL PVMFPARENT( TID )ERRORSThis error condition can be returned by pvm_parent.PvmNoParent: The calling process was not created with pvm_spawn.PvmSysErr: Can't contact local pvmd.; ÷‰_‹1_“B 5_‹‹½pvm_perror0 $‹‹# €€€‚ÿpvm_perror}7_‹ ŽF Z€o€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚€€‚‚ÿpvm_perror Prints message describing the last error returned by a PVM call.SYNOPSISCint info = pvm_perror( char *msg )Fortrancall pvmfperror( msg, info )PARAMETERSmsgCharacter string supplied by the user which will be prepended to the error message of the last PVM call.infoInteger status code returned by the routine. Values less than zero indicate an error.DESCRIPTIONThe routine pvm_perror returns the error message of the last PVM call. The user can use msg to add additional information to the error message, for example, its location.±m‹½D V€Û€€‚‚‚€€‚‚‚ƒ‚ƒƒ‚‚‚ƒ‚ƒ‚‚€€‚‚‚ÿUnless redirected, all stdout and stderr messages are placed in the file /tmp/pvml. (or /%PVM_TMP%/username file on WIN32) on the master host.EXAMPLESC:if ( pvm_send( tid, msgtag ) )pvm_perror();Fortran:CALL PVMFSEND( TID, MSGTAG )IF( INFO .LT. 0 ) CALL PVMFPERROR( 'Step 6', INFO )ERRORSNo error condition is returned by pvm_perror.: Ž À1-‘W6 À;À„pvm_precv½ À½/ ½;À# €€€‚ÿpvm_precv+î ÀfÂ= H€Ý€€€‚‚‚‚ƒ‚‚ƒ‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚ÿpvm_precv Receive a message directly into a buffer.SYNOPSISCint info = pvm_precv( int tid, int msgtag, char *buf, int len, int datatype, int *atid, int *atag, int *alen )Fortrancall pvmfprecv( tid, msgtag, buf, len, datatype, atid, atag, alen, info )PARAMETERStidInteger task identifier of sending process (to match).msgtagInteger message tag (to match). msgtag should be >= 0.bufPointer to a buffer to receive into.lenLength of buffer (in multiple of data type size).à;À{Ä5 8€Á€€‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚ÿdatatypeType of data to which buf points (see below).atidReturns actual TID of sender.atagReturns actual message tag.alenReturns actual message length.infoReturns PvmOk on success. Values less than zero indicate an error.DESCRIPTIONThe routine pvm_precv blocks the process until a message with label msgtag has arrived from tid. pvm_precv then places the contents of the message in the supplied buffer, buf up to a maximum length of len * (size of data type). úfšÆ% €õ€€‚‚ÿpvm_precv can receive messages sent by pvm_psend, pvm_send, pvm_mcast, or pvm_bcast. A -1 in msgtag or tid matches anything. This allows the user the following options. If tid = -1 and msgtag is defined by the user, then pvm_precv will accept a message from any process which has a matching msgtag. If msgtag = -1 and tid is defined by the user, then pvm_precv will accept any message that is sent from process tid. If tid = -1 and msgtag = -1, then pvm_precv will accept any message from any process. ¼{Ä¢ÈL f€y€€‚‚ƒ€ƒ€‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ÿIn C the \fIdatatype\fR parameter must be one of the following, depending on the type of data to be unpacked: [Version 3.3.0 - This parameter only determines message length, not data conversion. It only unpacks raw bytes] .datatypeData TypePVM_STRstringPVM_BYTEbytePVM_SHORTshortPVM_INTintPVM_FLOATrealPVM_CPLXcomplexPVM_DOUBLEdoublePVM_DCPLXdouble complexPVM_LONGlong integerPVM_USHORTunsigned short int ۚƬÊ/ ,€·€€ƒƒ‚ƒƒ‚‚‚‚‚‚‚ÿPVM_UINTunsigned intPVM_ULONGunsigned long intIn Fortran the same data types specified for unpack should be used.The PVM model guarantees the following about message order. If task 1 sends message A to task 2, then task 1 sends message B to task 2, message A will arrive at task 2 before message B. Moreover, if both messages arrive before task 2 does a receive, then a wildcard receive will always return message A.If pvm_precv is successful, infowill be = 0.8 ¢ÈäÌ/ ,€€€‚‚‚‚‚‚‚‚‚‚‚‚ÿIf some error occurs then info will be < 0..PPpvm_precv is blocking which means the routine waits until a messagematching the user specified tid and msgtag arrives at thelocal pvmd.If the message has already arrived then pvm_precvreturns immediately with the message..PPpvm_precv does not affect the state of the current receive message buffer (created by the other receive functions)..SH WARNINGSIn some versions of PVM (CM5, I860 and PGON),messages sent using pvm_psend must be received only by pvm_precv, Ù¬ÊíÎ0 .€³€€‚‚‚‚‚‚‚‚‚‚‚‚‚ÿlikewise those sent with pvm_sendmust be received by pvm_recv, pvm_nrecv or pvm_trecv.pvm_psend is not compatible with pvm_recv(nor pvm_send with pvm_precv).In addition, pvm_probe is not interoperable with pvm_psend..PPThis problem occursbecause nonstandard message headers are used for efficiencyin the pvm_psend function.In the generic Unix version of PVM,the calls are fully interoperable..PPThe message tag space is shared between pvm_send and pvm_psend, ÓäÌ8 >€§€€‚‚‚‚‚ƒ‚‚‚‚ƒ‚‚‚‚‚‚‚‚‚‚ÿso you must be careful to avoid selecting the wrong message(for example by using a wildcard to match the message)..SH EXAMPLES.nfC:info = pvm_precv( tid, msgtag, array, cnt, PVM_FLOAT, &src,íν &rtag, &rlen );.spFortran:CALL PVMFPRECV( -1, 4, BUF, CNT, REAL4, > SRC, RTAG, RCNT, INFO ).fi.SH ERRORSThese error conditions can be returned by.I pvm_precv.IP PvmBadParamgiving an invalid tid, msgtag, or datatype.€Wí΄) "€®€€‚‚‚‚‚‚‚ÿ.IP PvmSysErrpvmd not responding..PP.SH SEE ALSOpvm_psend(3PVM),pvm_recv(3PVM): ¾1j B ˆ7¾í& pvm_probe/ „í# €€€‚ÿpvm_probe ¾÷H ^€…€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚‚‚‚€€‚ÿpvm_probe Non blocking check of message arrivalSYNOPSISCint bufid = pvm_probe( int tid, int msgtag )Fortrancall pvmfprobe( tid, msgtag, bufid )PARAMETERStidInteger task identifier of sending process supplied by the user. msgtagInteger message tag supplied by the user. msgtag should be >= 0.bufidInteger returning the value of the new active receive buffer identifier. Values less than zero indicate an error.DESCRIPTIONg?í^( €€€‚‚‚‚‚ÿThe routine pvm_probe checks to see if a message with label msgtag has arrived from tid. If a matching message has arrived pvm_probe returns a buffer identifier in bufid. This bufid can be used with pvm_bufinfo to determine information about the message such as its source and length.If the requested message has not arrived, then pvm_probe returns with a 0 in bufid. If some error occurs bufid will be < 0.A -1 in msgtag or tid matches anything. This allows the user the following options. If tid = -1 and msgtag is defined by the user, then pvm_probe will accept a message from any process which has a matching msgtag. If msgtag = -1 and tid is defined by the user, then pvm_probe will accept any message that is sent from process tid. If tid = -1 and msgtag = -1, then pvm_probe will accept any message from any process. Î÷n B R€€€‚‚€€‚‚‚ƒ‚ƒ‚ƒ‚ƒ‚ƒƒ‚ƒ‚ƒƒ‚‚‚ƒ‚ÿpvm_probe can be called multiple times to check if a given message has arrived yet. After the message has arrived, pvm_recv must be called before the message can be unpacked into the user's memory using the unpack routines. EXAMPLESC:tid = pvm_parent();msgtag = 4 ;arrived = pvm_probe( tid, msgtag );if ( arrived )info = pvm_bufinfo( arrived, &len, &tag, &tid );else/* go do other computing */Fortran:CALL PVMFPROBE( -1, 4, ARRIVED )¸V^& b ’€­€€ƒ‚ƒƒ‚ƒ‚ƒƒ‚ƒ‚‚‚€€‚‚‚‚‚‚ãÿ­A›‰‚ã0‰Jʼn‚ãþ1xö‰‚ã¬M„#‰‚ã;Óà÷‰‚‚‚ÿIF ( ARRIVED .GT. 0 ) THENCALL PVMFBUFINFO( ARRIVED, LEN, TAG, TID, INFO )ELSE*GO DO USEFUL WORKENDIFERRORSThese error conditions can be returned by pvm_probe.PvmBadParam: giving an invalid tid value or msgtag.PvmSysErr: pvmd not responding.see alsopvm_bufinfopvm_getmboxinfopvm_nrecvpvm_recvpvm_unpk*: n ` 1W݇8`  ÓIpvm_psend/ &  # €€€‚ÿpvm_psend%å` ´ @ N€Ë€€€‚‚‚‚ƒ‚‚ƒ‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚ÿpvm_psend Pack and send data in one call.SYNOPSISCint info = pvm_psend( int tid, int msgtag, char *buf, int len, int datatype )Fortrancall pvmfpsend( tid, msgtag, buf, len, datatype, info )PARAMETERStidInteger task identifier of destination process.msgtagInteger message tag supplied by the user. msgtag should be >= 0.bufPointer to a buffer to send.lenLength of buffer (in multiple of data type size).datatypeType of data to which buf points (see below).ì Þ@2 2€Ù€€‚‚‚‚€€‚‚‚‚‚ÿinfoInteger status code returned by the routine.DESCRIPTIONThe routine pvm_psend takes a pointer to a buffer buf its length len and its data type datatype and sends this data directly to the PVM task identified by tid. msgtag is used to label the content of the message. If pvm_psend is successful, info will be 0. If some error occurs then info will be < 0.pvm_psend data can be received by pvm_precv, pvm_recv, pvm_trecv, or pvm_nrecv.The pvm_psend routine is asynchronous. Computation on the sending processor resumes as soo´ Þ@& n as the buffer is safe for reuse. This is in contrast to synchronous communication, during which computation on the sending processor halts until the matching receive is executed by the receiving processor.Å´ ïBL f€‹€€‚‚‚‚ƒƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ÿIn C the datatype parameter must be one of the following, depending on the type of data to be sent:[Version 3.3.0 - This parameter only determines message length, not data conversion. It only sends raw bytes]datatypeData TypePVM_STRstringPVM_BYTEbytePVM_SHORTshortPVM_INTintPVM_FLOATrealPVM_CPLXcomplexPVM_DOUBLEdoublePVM_DCPLXdouble complexPVM_LONGlong integerPVM_USHORTunsigned short intPVM_UINTunsigned int9Þ@(E+ $€€€ƒƒ‚‚‚‚‚‚ÿPVM_ULONGunsigned long intIn Fortran the same data types specified for pack should be used.The PVM model guarantees the following about message order. If task 1 sends message A to task 2, then task 1 sends message B to task 2, message A will arrive at task 2 before message B. Moreover, if both messages arrive before task 2 does a receive, then a wildcard receive will always return message A.pvm_psend does not affect the state of the current outgoing message buffer (created by pvm_initsend and used by pvm_send).<ïBdG. *€€€‚€€‚‚‚‚ÿWARNINGSIn some versions of PVM (CM5, I860 and PGON), messages sent using pvm_psend must be received only by pvm_precv, likewise those sent with pvm_send must be received by pvm_recv, pvm_nrecv or pvm_trecv. pvm_psend is not compatible with pvm_recv (nor pvm_send with pvm_precv). In addition, pvm_probe is not interoperable with pvm_psend.This problem occurs because nonstandard message headers are used for efficiency in the pvm_psend function. In the generic Unix version of PVM, the calls are fully interoperable.×(EzI? L€¯€€‚‚€€‚‚‚ƒ‚‚‚ƒ‚‚€€‚‚‚‚ÿThe message tag space is shared between pvm_send and pvm_psend, so you must be careful to avoid selecting the wrong message (for example by using a wildcard to match the message).EXAMPLESC:info = pvm_psend( tid, msgtag, array, 1000, PVM_FLOAT );Fortran:CALL PVMFPSEND( TID, MSGTAG, BUF, CNT, REAL4, INFO )ERRORSThese error conditions can be returned by pvm_psendPvmBadParam: giving an invalid tid, msgtag, or datatype.PvmSysErr: pvmd not responding.Y%dGÓI4 8€J€€‚‚ã`‡àö‰‚ㆅ#‰‚‚‚ÿsee alsopvm_precvpvm_send: zI J1fˆŸŠ9 J€³€€‚‚‚€‚‚‚‚ƒ‚ƒ‚ƒ‚ƒ‚‚‚‚ÿpvm_putinfo,pvm_recvinfo,pvm_getmboxinfo,pvm_delinfo Store and retrieve messages in global mailbox.SYNOPSISCint index = pvm_putinfo( char *name, int bufid, int flags )int bufid = pvm_recvinfo( char *name, int index, int flags )int info = pvm_delinfo( char *name, int index, int flags )int info = pvm_getmboxinfo( char *pattern, int *nclasses, struct pvmmboxinfo **classes ) struct pvmmboxinfo { char *mi_name; /* class name */ÞM €qM.üÞM:‚2 2€ù€€‚‚‚‚‚‚‚ƒ‚ƒ‚ƒ‚ƒ‚ÿ int mi_nentries; /* # of entries for this class */ int *mi_indices; /* mbox entry indices */ int *mi_owners; /* mbox entry owner tids */ int *mi_flags; /* mbox entry flags */ };Fortrancall pvmfputinfo( name, bufid, flags, index )call pvmfrecvinfo( name, index, flags, bufid )call pvmfdelinfo( name, index, flags, info )call pvmfgetmboxinfo( pattern, name, nclasses, nentries, index, owner, flags, info )Í €>„7 <€›€€‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚ÿPARAMETERSnameDatabase key (class name), any null-terminated string. index Database key (class index), >= 0. Default index = 0.flagsUser specified options. (see below)bufidHandle of message buffer to put in database, or message returned. A returned bufid < 0 indicates an error.infoResulting status code.patternGNU regular expression (pattern) to match on names in mailbox database. Additionally, the singular "*" will match on all names.ØŸ:‚‰9 @€? €€‚‚‚‚‚‚‚‚‚‚‚‚‚€€‚‚‚ÿnclassesNumber of classes matching pattern.classesArray of pvmmboxinfo mailbox entries matching pattern.nentriesNumber of entries for a given class.ownerTask id that inserted entry into mailbox database. DESCRIPTIONThese functions implement a "message mailbox" database that can be used by PVM tasks to advertise information to other PVM tasks. An example would be to advertise names or locations of services. Another example would be to advertise a common "context" on which two tasks may communicate. The database entries are PVM messages keyed by a user specified name and an optional index value. The name may be any null-terminated string and the index a non-negative integer. The index value is assigned by PVM and is used to uniquely identify one of multiple named instances within the database. Entries are "owned" by the task that created them. An entry is automatically removed from the database when the owner task exits unless the database entry was created with flag PvmMboxPersistent. When a task exits and leaves an entry in the mailbox, the owner tid of that entry is marked as zero (0) to indicate that there is no longer an active owner task. H>„^‹. *€5€€‚€€‚‚‚‚ÿpvm_putinfo inserts a record in the database, given a key and data (message). It returns mailbox index number if the record is successfully stored, PvmExists if a record with the given key already exists, or PvmDenied if an attempt is made to overwrite a locked record. The following options are added together as the flags parameter to pvm_putinfo.PvmMboxDefaultInserts entry as the only named instance for a given name. This entry may only be modified and deleted by its owner. It is automatically deleted when its owner exits.G‰¥Ž4 6€'€€‚‚‚‚‚‚‚‚‚‚€€‚ÿPvmMboxPersistentEntry remains in the database when the owner task exits. Entries are removed from the database when PVM is halted or a reset is issued from the console.PvmMboxMultiInstancePermits multiple entry instances of the same name. PVM will assign an index key to each instance.PvmMboxOverWritablePermits other tasks to overwrite and delete this database entry.pvm_recvinfo operates just like a pvm_recv() except the message is coming from the database. The message should be unpacked after pvm_recvinfo(). Like pvm_recv, pvm_recvinfo returns a pointer to a message buffer containing the record matching the key from the database. Returned value < 0 indicates an error. The following options are added together as the flags parameter to pvm_recvinfo.uI^‹&Á, &€“€€‚‚‚‚‚‚‚‚‚ÿPvmMboxDefaultExact match on key is returned. Returns PvmNotFound if exact match not found.PvmMboxFirstAvailThe first entry in with index greater than or equal to the specified index parameter is retuned. PvmMboxFirstAvail with index = 0 will produce the same results as using¥Ž&ÁqM PvmMboxDefault.PvmMboxReadAndDeleteReturn entry and delete from database. Task must be permitted to do both read and delete otherwise an error will occur. bufid returns PvmNotFound if entry does not exist and will return PvmDenied if the record exists but may not be deleted. ݪ¥ŽÅ3 4€U€€‚€€‚‚€€‚ÿpvm_delinfo deletes database entry specified by the key . Returns PvmOK if the record was deleted, PvmNotFound if the record does not exist, or PvmDenied if an attempt is made to remove a "locked" record. There are no flags presently specified for pvm_delinfo.pvm_getmboxinfo returns an array of pvmmboxinfo for all class names in the database. This is used, for example, by programs that clean up the database or for applications to find out what is available. classes returns a pointer to the array allocated by libpvm and freed on the next call to pvm_getmboxinfo. The Fortran function returns information on one entry per call. Thus, if called repeatedly until an info value of PvmNotFound is returned, all entries matching the given pattern will have been returned. If a new pattern is desired, calling pvmfgetnames() with info = -1 will reset the entry name list and obtain a new list for the given pattern.!Ò&Á$ÇO l€¥€€‚€€‚‚‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒƒ‚ƒƒ‚ƒ‚‚‚ƒ‚ƒ‚ÿEXAMPLESC:/** create and insert mailbox entry*/sprintf( service, "Task_A_service" );sprintf( message, "Greetings from task A." );pvm_initsend( PvmDataDefault );pvm_pkint( &mytid, 1, 1 );pvm_pkint( &context, 1, 1 );pvm_pkstr( message );if (( pvm_putinfo( service, pvm_getsbuf(), PvmMboxDefault )) == PvmExists ){ printf( "can't register - service already running\n" );exit( -1 );}/** look for and retrieve specified mailbox ÃÅ.ÉG \€‡€€ƒ‚ƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒ‚‚‚ƒ‚‚€€‚‚‚‚ÿ*/sprintf( service, "Task_A_service" );if (( msg_buf = pvm_recvinfo(service, 0, PvmMboxFirstAvail )) >= 0 ){ pvm_setrbuf( msg_buf );pvm_upkint( &their_tid, 1, 1 );pvm_upkint( &their_context, 1, 1 );pvm_upkstr( message );}Fortran:we need the fortran examples...ERRORSThe following error conditions can be returned by one or more of these functions: PvmBadParam: An invalid value was specified for \fIbufid\fR argument.Â$ÇñÊA P€€€‚‚‚‚‚‚‚ãÆ$«æ‰‚ã˜ÏÞm‰‚ãýk‰‚‚‚ÿPvmNoSuchBuf: Message buffer \fIbufid\fR doesn't exist.PvmNoMem: Libpvm is unable to allocate memory to pack data.PvmExists: The requested key is already in use (pvm_putinfo).PvmNotFound: The requested key does not exist (pvm_recvinfo, pvm_delinfo).PvmDenied: The key is locked by another task and cannot be replaced or deleted.see alsopvm_initsendpvm_getsbufpvm_pk*9.É*Ë1Ò ŸŠL;*ËXË5 pvm_recv. ñÊXË# €€€‚ÿpvm_recvÀw*ËÎI `€ï€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚‚‚‚€€‚‚ÿpvm_recv Receive a message.SYNOPSISCint bufid = pvm_recv( int tid, int msgtag )Fortrancall pvmfrecv( tid, msgtag, bufid )PARAMETERStidInteger task identifier of sending process supplied by the user.msgtagInteger message tag supplied by the user. msgtag should be >= 0.bufidInteger returns the value of the new active receive buffer identifier. Values less than zero indicate an error.DESCRIPTIONThe routine pvm_recv blocks the process until a message with label msgtag has arrived from tid. pvm_recv then places the message in a new active receive buffer, which also clears the current receive buffer.ùÒXË ' €¥€€‚‚‚‚ÿA -1 in msgtag or tid matches anything. This allows the user the following options. If tid = -1 and msgtag is defined by the user, then pvm_recv will accept a message from any process which has a matching msgtag. If msgtag = -1 and tid is defined by the user, then pvm_recv will accept any message that is sent from process tid. If tid = -1 and msgtag = -1, then pvm_recv will accept any message from any process.The PVM model guarantees the folÎ ñÊlowing about message order. If task 1 sends message A to task 2, then task 1 sends message B to task 2, message A will arrive at task 2 before message B. Moreover, if both messages arrive before task 2 does a receive, then a wildcard receive will always return message A.ëÎ0 ( €×€€‚‚‚‚‚ÿIf pvm_recv is successful, bufid will be the value of the new active receive buffer identifier. If some error occurs then bufid will be < 0.pvm_recv is blocking which means the routine waits until a message matching the user specified tid and msgtag values arrives at the local pvmd. If the message has already arrived then pvm_recv returns immediately with the message. Once pvm_recv returns, the data in the message can be unpacked into the user's memory using the unpack routines. #Ø S K d€±€€‚€‚€‚‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚‚‚ƒ‚ƒ‚ƒ‚‚€€‚‚‚ÿEXAMPLESC:tid = pvm_parent();msgtag = 4 ;bufid = pvm_recv( tid, msgtag );info = pvm_upkint( tid_array, 10, 1 );info = pvm_upkint( problem_size, 1, 1 );info = pvm_upkfloat( input_array, 100, 1 );Fortran:CALL PVMFRECV( -1, 4, BUFID )CALL PVMFUNPACK( INTEGER4, TIDS, 25, 1, INFO )CALL PVMFUNPACK( REAL8, MATRIX, 100, 100, INFO )ERRORSThese error conditions can be returned by pvm_recvPvmBadParam: giving an invalid tid value, or msgtag < -1.â‰0 5 Y €€€€‚‚‚ãÿ­A›‰‚ã0‰Jʼn‚ãþ1xö‰‚ã;Óà÷‰‚ã^Ïàö‰‚ㆅ#‰‚ãzº1ö‰‚‚‚ÿPvmSysErr: pvmd not responding.see alsopvm_bufinfopvm_getmboxinfopvm_nrecvpvm_unpk*pvm_probepvm_sendpvm_mcast: S o 1Ç Áˆ€<o ž @@ pvm_recvf/ 5 ž # €€€‚ÿpvm_recvfÊo   8 >€•€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚ÿpvm_recvf Redefines the comparison function used to accept messages.SYNOPSISCint (*old)() = pvm_recvf( int (*new)( int bufid, int tid, int tag ))FortranNOT AVAILABLEDESCRIPTIONThe routine pvm_recvf defines the comparison function to be used by the pvm_recv, pvm_nrecv, and pvm_probe functions. It is available as a means to customize PVM message passing. pvm_recvf sets a user supplied comparison function to evaluate messages for receiving.Öž § 1 0€­€€‚‚‚‚‚‚‚€€‚ÿrecvf returns the old value of the matching function, or 0 if the old function was the default matcher pvm_recvf is intended for sophisticated C programmers who understand the function of such routines (like signal) and who require a receive routine that can match on more complex message contexts than the default provides.MATCHING FUNCTIONThe default comparison function evaluates the source and message tag associated with all incoming messages.PARAMETERS`   J b€-€€‚‚‚‚‚‚‚‚‚‚‚‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚‚€€‚‚ÿtidInteger task identifier of sending process supplied by the user.tagInteger message tag supplied by the user.bufidInteger message buffer identifier.The matching function should return:ValueAction taken< 0Return immediately with this error code. 0Do not pick this message. 1Pick this message and do not scan the rest.> 1Pick this highest ranked message afterscanning them all.EXAMPLESImplementing message probe with recvf, using our matching function to return information in a global variable.¶§  X ~€m€€‚‚‚‚‚‚‚ƒ‚ƒ‚ƒ‚‚ƒ‚ƒ‚‚ƒ‚‚ƒƒƒ‚ƒƒ‚‚ƒ‚‚‚‚‚‚ƒ‚ƒ‚‚ƒ‚‚ƒ‚‚ƒ‚ƒƒ‚ÿ#include static int foundit = 0;static intfoo_match(mid, tid, tag)int mid;int tid;int tag;{int t, c;struct pvmminfo header;pvm_getminfo(mid, &header);if ((tid == -1 || tid == header.src) && (tag == -1 || tag == header.tag)) foundit = 1;return 0;}intprobe(src, tag){int (*omatch)();int cc;omatch = pvm_recvf(foo_match);foundit = 0;if ((cc = pvm_nrecv(src, tag)) < 0)return cc;¾ @@ a €}€€‚ƒ‚‚ƒ‚‚‚€€‚‚‚‚ãÿ­A›‰‚ã0‰Jʼn‚ã¬M„#‰‚ãþ1xö‰‚ã^Ïàö‰‚ã$2±÷‰‚‚‚ÿpvm_recvf(omatch);return foundit;}ERRORSNo error conditions are returned by pvm_recvfsee alsopvm_bufinfopvm_getmboxinfo @@ 5 pvm_recvpvm_nrecvpvm_probepvm_trecv=  }@ 1nL#€=}@ ¯@ ì@ pvm_recvinfo2@@ ¯@ # €€€‚ÿpvm_recvinfo=}@ ì@ ) "€(€€ãkÙ9‰‚ÿsee pvm_putinfo; ¯@ 'A 1`€‰>'A WA ­Š pvm_reduce0 ì@ WA # €€€‚ÿpvm_reduce_$'A ¶C ; D€I€€€‚‚‚‚‚‚‚‚‚‚‚€€‚‚‚‚ÿpvm_reduce Performs a reduction operation over members of the specified group. SYNOPSISC int info = pvm_reduce( void (*func)(), void *data, int count, int datatype, int msgtag, char *group, int rootginst)Fortran call pvmfreduce(func, data, count, datatype, msgtag, group, rootginst, info)PARAMETERSfuncFunction which defines the operation performed on the global data. Predefined are PvmMax, PvmMin, PvmSum, and PvmProduct. Users can define their own function.<WA òE , &€!€€‚‚‚‚‚‚‚‚‚ÿSYNOPSIS for func C void func(int *datatype, void *x, void *y, int *num, int *info) Fortran call func(datatype, x, y, num, info)data Pointer to the starting address of an array of local values. On return, the data array on the root will be overwritten with the result of the reduce operation over the group. For the other (non-root) members of the group the values of the data array upon return from the reduce operation are not defined; the values may be different than those originally passed to pvm_reduce. Ú¶C ûG / ,€µ€€‚‚‚‚‚‚‚‚‚‚‚‚ÿcountInteger specifying the number of elements of datatype in the data array. The value of count should agree between all members of the group. datatype Integer specifying the type of the entries in the data array. (See below for defined types.)msgtag Integer message tag supplied by the user. msgtag should be >= 0. It allows the user's program to distinguish between different kinds of messages.group Character string group name of an existing group.&ùòE !J - (€ó€€‚‚‚‚‚‚‚‚‚‚ÿrootginst Integer instance number of group member who gets the result.info Integer status code returned by the routine. Values less than zero indicate an error.DESCRIPTIONpvm_reduce() performs global operations such as max, min, sum, or a user provided operation on the data provided by the members of a group. All group members call pvm_reduce with the same size local data array which may contain one or more entries. The root task is identified by its instance number in the group. áûG /L - (€Ã€€‚‚‚‚‚‚‚‚‚‚ÿThe inner workings of the pvm_reduce call are implementation dependent; however, when the pvm_reduce call completes, the root's data array will be equal to the specified operation applied element-wise to the data arrays of all the group members.A broadcast by the root can be used if the other members of the group need the resultant value(s).PVM supplies the following predefined functions that can be specified in func. PvmMin PvmMax PvmSum á!J =N - (€Ã€€‚‚‚‚‚‚‚‚ƒ‚ÿ PvmProduct PvmMax and PvmMin are implemented for all the datatypes listed below. For complex values the minimum [maximum] is that complex pair with the minimum [maximum] modulus. PvmSum and PvmProduct are implemented for all the datatypes listed below with the exception of PVM_BYTE and BYTE1.C and Fortran defined datatypes are: C datatypes FORTRAN datatypes ----------------------------------- PVM_BYTE BYTE1 ئ/L ! 2 2€M€€ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚‚‚‚ÿ PVM_SHORT INTEGER2 PVM_INT INTEGER4 PVM_FLOAT REAL4 PVM_CPLX COMPLEX8 PVM_DOUBLE REAL8 PVM_DCPLX COMPLEX16 PVM_LONG A user defined function may be used in func. The argument func is a function with four arguments. It is the base=N ! ì@ function used for the reduction operation. Both x and y are arrays of type specified by datatype with num entries. The arguments datatype and info are as specified above. The arguments x and num correspond to data and count above. The argument y contains received values. ìÇ=N „ % €€€‚‚ÿCaveat: pvm_reduce() does not block, a call to pvm_barrier may be necessary.For example, an error may occur if a task calls pvm_reduce and then leaves the group before the root has completed its call to pvm_reduce. Similarly, an error may occur if a task joins the group after the root has issued its call to pvm_reduce. Synchronization of the tasks (such as a call to pvm_barrier) was not included within the pvm_reduce implementation since this overhead is unnecessary in many user codes (which may already synchronize the tasks for other purposes). The current algorithm is very simple and robust. A future implementation may make more efficient use of the architecture to allow greater parallelism.A! N† 3 4€€€‚€€‚‚‚‚‚‚‚‚‚ÿILLUSTRATIONThe following example illustrates a call to pvm_reduce. Suppose you have three group members (instance numbers 0, 1, 2) with an array called Idata with 5 values as specified: instance the 5 values in the integer array 0 1, 2, 3, 4, 5 1 10, 20, 30, 40, 50 2 100, 200, 300, 400, 500And, suppose that a call to reduce (such as the ones following) are issued where the root is the group member with instance value of 1: Û „ Zˆ 1 0€·€€‚‚‚‚‚‚‚‚‚‚‚‚‚‚ÿ C: root = 1; info = pvm_reduce(PvmSum, &Idata, 5, PVM_INT, msgtag, "worker", root); Fortran: root = 1 call pvmfreduce(PvmSum, Idata, 5, INTEGER4, msgtag, "worker", root, info)Then, upon completion of the reduce call, the following will result: instance the 5 values in the integer array 0 .... not defined....... 1 111, 222, 333, 444, 555 2 .... not defined ......»N† ]Š H ^€w€€‚€€‚‚‚‚‚‚‚‚‚€€‚‚‚‚‚‚‚‚ãßäóó‰‚ÿEXAMPLESC: info = pvm_reduce(PvmMax, &myvals, 10, PVM_FLOAT, msgtag, "worker", rootginst);Fortran: CALL PVMFREDUCE(PvmMax, MYVALS, COUNT, REAL4, MTAG, 'worker', ROOT, INFO)ERRORSThese error conditions can be returned by pvm_reducePvmNoInst: Calling task is not in the groupPvmBadParam: The datatype specified is not appropriate for the specified reduction function.PvmSysErr: Pvm system errorsee alsopvm_bcastPZˆ ­Š 2 4€<€ã• ‚㺿áö‰‚‚‚ÿpvm_barrierpvm_psend?]Š ìŠ 1‘ #€[†?ìŠ ‹ uÇ pvm_reg_hoster4­Š ‹ # €"€€‚ÿpvm_reg_hosterù»ìŠ Ž > J€w€€€‚‚‚‚ƒ‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚ÿpvm_reg_hoster Register task as PVM slave starter.SYNOPSISC#include int cc = pvm_reg_hoster()FortranNot AvailableDESCRIPTIONRegisters the calling task as a PVM slave pvmd starter. When the master pvmd receives a DM_ADD message, instead of starting the new slave pvmd processes itself, it passes a message to the hoster, which does the dirty work and sends a message back to the pvmd.Note: This function isn't for beginners. If you don't grok what it does, you probably don't need it. For a more complete explanation of what's going on here, you should refer to the PVM source code and/or user guide section on implementation; this is just a man page. That said....ú ‹ SÀ 4 6€õ€€‚‚‚‚ƒƒ‚ƒ‚ƒƒƒ‚ƒƒƒ‚ÿWhen the master pvmd receives a DM_ADD message (request to add hosts to the virtual machine), it looks up the new host IP addresses, gets parameters from the host file if it was started with one, and sets default parameters. It then either attempts to start the processes (using rsh or rexec()) or, if a hoster has registered, sends it a SM_STHOST message.The format of the SM_STHOST message is:int nhosts// number of hosts{Ž SÀ ­Š int tid// of hoststring options// from hostfile \fIso=\fR fieldOŽ ¢Â 6 :€3€€ƒƒƒ‚ƒƒƒ‚ƒ‚‚‚ƒ‚‚ƒ‚‚‚ÿstring login// in form ``[username@]hostname.domain''string command// to run on remote host} [nhosts]The hoster should attempt to run each command on each host and record the result. A command usually looks like:$PVM_ROOT/lib/pvmd -s -d8 -nhonk 1 80a9ca95:0f5a 4096 3 80a95c43:0000and a reply from a slave pvmd like:ddpro<2312> arch ip<80a95c43:0b3f> mtu<4096>When finished, the hoster should send a SM_STHOSTACK message back to the address of the sender (the master pvmd). The format of the reply message is:ÌSÀ ¨Ä : B€™€€‚ƒ‚ƒƒƒ‚ƒƒƒ‚ƒƒ‚‚‚‚‚‚‚‚‚‚ÿ{int tid// of host, must match requeststring status// result line from slave or error code} []// implied countThe TIDs in the reply must match those in the request. They may be in a different order, however.The result string should contain the entire reply (a single line)from each new slave pvmd,or an error code if something went wrong.Legalerror codes are the literal names of the \fIpvm_errno\fR codes,for example ``PvmCantStart''.(ü¢Â ÐÆ , &€ù€€‚‚‚‚‚‚‚‚‚ÿThe default PVM hoster can return PvmDSysErr or PvmCantStart,and the slave pvmd itself can return PvmDupHost.The hoster must use \fIpvm_setmwid()\fR to set the wait ID in the reply message to the same value as in the request.The wait ID in the request is obtained by calling \fIpvm_getmwid()\fR.The hoster taskmust use pvm_setopt(PvmResvTids, 1) to allow sending reserved messages. Messages should be packed using encoding \fIPvmDataDefault\fR toensure they can be unpacked anywhere in the system.¥z¨Ä uÇ + &€ô€€‚‚‚‚‚‚‚‚‚ÿpvm_reg_hoster()returns PvmOk when successful..SH SEE ALSOpvm_addhosts(3PVM),pvm_config(3PVM),pvm_setmwid(3PVM); ÐÆ °Ç 1§ ‰Š@°Ç àÇ = pvm_reg_rm0 uÇ àÇ # €€€‚ÿpvm_reg_rmWÿ°Ç 7Í X ~€ÿ €€€‚‚‚‚ƒ‚‚ƒ‚‚ƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚€€‚‚‚ÿpvm_reg_rm Register task as PVM resource manager.SYNOPSISC#include int cc = pvm_reg_rm( struct pvmhostinfo **hip )struct pvmhostinfo {int hi_tid;char *hi_name;char *hi_arch;int hi_speed;};FortranNot AvailablePARAMETERShostpReturns pointer to a pvmhostinfo structure which contains information about the master host.DESCRIPTIONRegisters the calling task as a PVM task and slave host manager. This means it intercepts certain libpvm calls from other tasks in order to have a say in scheduling policy. The resource manager will asynchronously receive messages from tasks containing requests for service, as well as messages from pvmds notifying it of system failures. Before you start using this function, be warned that it's not a trivial thing, i.e. you can't just call it to turn off the default round-robin task assignment. Rather, it allows you to write your own resource manager and hook it to PVM. To understand what the following messages mean, you should refer to the PVM source code and/or user guide section on implementation; There's just too much to say about them. When one of the following libpvm functions is called in a task with resource manager set, the given message tag is sent to to resource manager. ¸àÇ >Ï O l€q€€‚ƒƒƒƒƒƒ‚ƒƒƒ‚ƒƒƒ‚ƒƒƒ‚ƒƒƒ‚ƒƒƒ‚ƒƒƒ‚‚‚‚ƒƒ‚ƒƒ‚ƒƒ‚ÿLibpvm callRM messageNormal message pvm_addhosts()SM_ADDHOSTTM_ADDHOSTpvm_config()SM_CONFIGTM_CONFIGpvm_delhosts()SM_DELHOSTTM_DELHOSTpvm_notify()SM_NOTIFYTM_NOTIFYpvm_spawn()SM_SPAWNTM_SPAWNpvm_tasks()SM_TASKTM_TASKpvm_reg_rm()SM_SCHEDTM_SCHEDThe resource manager must in turn compose the following messages and send them to the pvmds:RM messageNormal messageSM_EXECDM_EXECSM_EXECACKDM_EXECACKÝ7Í a : B€»€€ƒƒ‚ƒƒ‚ƒƒ‚‚‚‚ƒƒ‚ƒƒ‚ƒƒ‚‚‚ÿSM_ADDDM_ADDSM_ADDACKDM_ADDACKSM_HANDOFF(none - change of resource manager)The following messages are sent asynchronously to >Ï a uÇ the resource manager by the system:RM messageMeaningSM_TASKXnotify of task exit/failSM_HOSTXnotify of host delete/failThe resource manager task must use pvm_setopt(PvmResvTids, 1) to allow sending reserved messages. Messages should be packed using encoding PvmDataDefault to ensure they can be unpacked anywhere in the system. ÜŠ>Ï = R r€€€‚‚‚ã„”Z³‰‚ãL<‰‚ã®×0O‰‚ãA¦e‰‚ã½€z÷‰‚ãÔøœ÷‰‚‚‚ÿpvm_reg_rm() returns PvmOk when successful.see alsopvm_addhostspvm_configpvm_delhostspvm_notifypvm_spawnpvm_tasks?a | 1r [†Ä A| ° ñ pvm_reg_tasker4= ° # €"€€‚ÿpvm_reg_tasker8ú| è > J€õ€€€‚‚‚‚ƒ‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚ÿpvm_reg_tasker Register task as PVM task starter.SYNOPSISC#include int cc = pvm_reg_tasker()FortranNot Available.SH DESCRIPTIONRegisters the calling task as a PVM task starter. When a tasker is registered with a pvmd, and the pvmd receives a DM_EXEC message, instead of fork()ing and exec()ing the task itself, it passes a message to the tasker, which does the dirty work and sends a message back to the pvmd.Note: If this doesn't make sense, don't worry about it. This function is for folks who are writing stuff like debugger servers and so on. For a more complete explanation of what's going on here, you should refer to the PVM source code and/or user guide section on implementation; this is only a man page. That said...ç°  7 <€Ï€€‚‚‚‚‚ƒƒƒ‚ƒƒƒ‚ƒƒ‚ƒƒƒ‚ÿWhen the pvmd receives a DM_EXEC message (request to exec new tasks), it searches epath (the PVM executable search path) for the file name. If it finds the file, it then either attempts to start the processes (using fork() and exec()) or, if a tasker has registered, sends it a SM_STTASK message.The format of the SM_STTASK message is:int tid// of taskint flags// as passed to spawn()string path// absolute path of the executableint argc// number of args to process>è D / ,€€€ƒƒ‚ƒƒƒ‚ƒƒ‚‚‚ÿstring argv[argc]// argsint nenv// number of envars to pass to taskstring env[nenv]// environment stringsThe tasker must attempt to start the process when it gets one of these messages. The tasker doesn't reply to the pvmd if the task is successfully started; the task will reconnect to the pvmd on its own, using the cookie in envar PVMEPID to identify itself to the pvmd. The tasker must send a SM_TASKX message to the pvmd when any task that it owns (has started) exits, or if it can't start a particular task. â d > J€Å€€‚‚‚ƒƒƒ‚ƒƒƒ‚ƒƒƒ‚ƒƒ‚ƒƒƒ‚ƒƒ‚‚‚ÿThe format of the SM_TASKX message is:int tid// of taskint status// the Unix exit status (from \fIwait()\fR)int u_sec// user time used by the task, secondsint u_usec// microsecondsint s_sec// system time used by the task, secondsint s_usec// microsecondsThe tasker task must use pvm_setopt(PvmResvTids, 1) to allow sending reserved messages. Messages should be packed using encoding PvmDataDefault to ensure they can be unpacked anywhere in the system. WD ñ 6 <€®€€‚‚‚‚ã½€z÷‰‚ãÔøœ÷‰‚‚‚ÿpvm_reg_tasker() returns PvmOk when successful.see alsopvm_spawnpvm_tasks< d - 1|ЉB- ^ L pvm_scatter1ñ ^ # €€€‚ÿpvm_scatter6þ- ” 8 >€ý€€€‚‚‚‚‚‚‚‚€€‚‚‚‚ÿpvm_scatter Sends to each member of a group a section of an array from a specified member of the group.SYNOPSISC int info = pvm_scatter( void *result, void *data, int count, int datatype, int msgtag, char *group, int rootginst)Fortran call pvmfscatter(result, data, count, datatype, msgtag, group, rootginst, info)PARAMETERSresultPointer to the starting address of an array of length count of datatype which will be overwritten by the message from the specified root member of the group.N"^ îA , &€E€€‚‚‚‚‚‚‚‚‚ÿdata On the root this is a pointer to the starting address of” îA ñ an array datatype of local values which are to be distributed to the members of the group. If n is the number of members in the group, then this array of datatype should be of length at least n* count. This argument is meaningful only on the root.countInteger specifying the number of elements of datatype to be sent to each member of the group from the root.datatype Integer specifying the type of the entries in the result and data arrays. (See below for defined types.)Ô” üC : B€©€€‚‚‚‚‚‚‚‚‚‚‚‚‚‚€€‚‚‚ÿmsgtag Integer message tag supplied by the user. msgtag should be >= 0. It allows the user's program to distinguish between different kinds of messages.group Character string group name of an existing group.rootginstInteger instance number of group member who performs the scatter of its array to the members of the group.info Integer status code returned by the routine. Values less than zero indicate an error.DESCRIPTIONpvm_scatter() ŠfîA †F $ €Í€€‚ÿperforms a scatter of data from the specified root member of the group to each of the members of the group, including itself. All group members must call pvm_scatter(), each receives a portion of the data array from the root in their local result array. It is as if the root node sends to the ith member of the group count elements from its array data starting at offset i* count from the beginning of the data array. And, it is as if, each member of the group performs a corresponding receive of count values of datatype into its result array. The root task is identified by its instance number in the group.³züC 9I 9 @€õ€€‚‚‚‚‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚‚‚‚ÿC and Fortran defined datatypes are: C datatypes FORTRAN datatypes ----------------------------------- PVM_BYTE BYTE1 PVM_SHORT INTEGER2 PVM_INT INTEGER4 PVM_FLOAT REAL4 PVM_CPLX COMPLEX8 PVM_DOUBLE REAL8 PVM_DCPLX COMPLEX16 PVM_LONGIn using the scatter and gather routines, keep in mind that C stores multidimensional arrays in row order, typically starting with an initial index of 0; whereas, Fortran stores arrays in column order, typically starting with an offset of 1. Ó†F IK = H€§€€‚‚€€‚‚‚‚‚‚‚‚‚€€‚‚‚ÿThe current algorithm is very simple and robust. A future implementation may make more efficient use of the architecture to allow greater parallelism.EXAMPLESC: info = pvm_scatter(&getmyrow, &matrix, 10, PVM_INT, msgtag, "workers", rootginst);Fortran: CALL PVMFSCATTER(GETMYCOLUMN, MATRIX, COUNT, INTEGER4, MTAG, 'workers', ROOT, INFO)ERRORSThese error conditions can be returned by pvm_scatter PvmNoInst: Calling task is not in the groupº~9I L < H€ü€€‚‚‚ãßäóó‰‚ã• 㺿áö‰‚‚‚ÿPvmBadParam: The datatype specified is not appropriatePvmSysErr: Pvm system errorpvm_bcastpvm_barrierpvm_psend9IK = 0.infoInteger status code returned by the routine.DESCRIPTIONThe routine pvm_send sends a message stored in the active send buffer to the PVM process identified by tid. msgtag is used to label the content of the message. If pvm_send is successful, info will be 0. If some error occurs then info will be < 0.¤~jL Ñ & €ý€€‚‚‚ÿThe pvm_send routine is asynchronous. Computation on the sending processor resumes as soon as the message is safely on its way to the receiving processor. This is in contrast to sync!O Ñ L hronous communication, during which computation on the sending processor halts until the matching receive is executed by the receiving processor. The PVM model guarantees the following about message order. If task 1 sends message A to task 2, then task 1 sends message B to task 2, message A will arrive at task 2 before message B. Moreover, if both messages arrive before task 2 does a receive, then a wildcard receive will always return message A. 3ì!O „ G \€Ù€€‚‚€€‚‚‚ƒ‚ƒ‚ƒ‚ƒ‚‚‚ƒ‚ƒ‚ƒ‚‚€€‚‚ÿTerminating a PVM task immediately after sending a message or messages from it may result in those messages being lost. To be sure, always call pvm_exit() before stopping. EXAMPLESC:info = pvm_initsend( PvmDataDefault );info = pvm_pkint( array, 10, 1 );msgtag = 3 ;info = pvm_send( tid, msgtag );Fortran:CALL PVMFINITSEND(PVMRAW, INFO)CALL PVMFPACK( REAL8, DATA, 100, 1, INFO )CALL PVMFSEND( TID, 3, INFO )ERRORSThese error conditions can be returned by pvm_send(ÛÑ ,… M h€·€€‚‚‚‚‚ãÆ$«æ‰‚ãzº1ö‰‚ãýk‰‚㺿áö‰‚ã¬M„#‰‚‚‚ÿPvmBadParam: giving an invalid tid or a msgtag.PvmSysErr: pvmd not responding.PvmNoBuf: no active send buffer. Try pvm_initsend() before send.see alsopvm_initsendpvm_mcastpvm_pk*pvm_psendpvm_recv< „ h… 1Á‰±Dh… ™… )‹ pvm_sendsig1,… ™… # €€€‚ÿpvm_sendsigR h… ë‡ I `€€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚‚‚‚€€‚‚ÿpvm_sendsig Sends a signal to another PVM process.SYNOPSISCint info = pvm_sendsig( int tid, int signum )Fortrancall pvmfsendsig( tid, signum, info )PARAMETERStidInteger task identifier of PVM process to receive the signal.signumInteger signal number.infoInteger status code returned by the routine.DESCRIPTIONThe routine pvm_sendsig sends the signal number signum to the PVM process identified by tid. If pvm_sendsig is successful, info will be 0. If some error occurs then info will be < 0.à™… Š 5 8€Á€€‚‚‚‚‚€€‚‚‚ƒ‚ƒ‚ÿpvm_sendsig should only be used by programmers with Unix signal handling experience. Many library functions (and in fact the PVM library functions) cannot be called in a signal handler context because they do not mask signals or lock internal data structures. Further caveat: the signal numbers passed between systems are notmapped - PVM assumes that signal 9 on one system is the same as on another.EXAMPLESC:tid = pvm_parent();info = pvm_sendsig( tid, SIGKILL);)óë‡ )‹ 6 :€ç€€‚‚ƒ‚ƒ‚‚€€‚‚‚‚‚‚ÿFortran:CALL PVMFBUFINFO( BUFID, BYTES, TYPE, TID, INFO );CALL PVMFSENDSIG( TID, SIGNUM, INFO )ERRORSThese error conditions can be returned by pvm_sendsigPvmSysErr: pvmd not responding.PvmBadParam: giving an invalid tid value.; Š d‹ 1»Ç€Ed‹ ”‹ ³À pvm_serror0 )‹ ”‹ # €€€‚ÿpvm_serror‚<d‹  F Z€y€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚€€‚‚ÿpvm_serror Sets automatic error message printing on or off. [In Version 3.2: Replaced by pvm_setopt]SYNOPSISCint oldset = pvm_serror( int set )Fortrancall pvmfserror( set, oldset )PARAMETERSsetInteger defining whether detection is to be turned on (1) or off (0).oldsetInteger defining the previous setting of pvm_serror.DESCRIPTIONThe routine pvm_serror sets automatic error message printing for all subsequent PVM calls by this process. Any PVM routines that return an error condition will automatically print the associated error message. The argument set defines whether this detection is to be turned on (1) or turned off (0) for subsequent calls. In the future a value of (2) will cause the program to exit after printing the error message. pvm_serror returns the previous value of set in oldset.‘J”‹ ³À G \€•€€‚‚€€‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚ã¿l‰‚‚ÿAll stdout and stderr messages are placed in the file /tmp/pvml. (%PVM_TMP%/pvml.username) on the master pvmd's host.EXAMPLESC:info = pvm_serror( 1 ) ³À )‹ ;Fortran:CALL PVMFSERROR( 0, INFO )ERRORSThis error condition can be returned by pvm_serrorPvmBadParam: giving an invalid set value.see alsopvm_setopt? òÀ 1q±(€FòÀ &Á fÁ pvm_setcontext4³À &Á # €"€€‚ÿpvm_setcontext@òÀ fÁ ) "€.€€ãéZb‰‚ÿsee pvm_newcontext< &Á ¢Á 1€Á„G¢Á ÓÁ !Ç pvm_setmwid1fÁ ÓÁ # €€€‚ÿpvm_setmwide¢Á 8Ä Q p€)€€€‚€€‚‚‚‚‚‚ƒ‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚€€‚‚ÿpvm_getmwid,pvm_setmwid Get or set wait ID of a message.[In Version 3.4: Relaced by pvm_getminfo and pvm_setminfo]SYNOPSISCint info = pvm_getmwid( int bufid )int info = pvm_setmwid( int bufid, int waitid )FortranNot AvailablePARAMETERSbufidMessage buffer identifier.waitidWait identifier number.DESCRIPTIONA wait identifier is part of a message (like the source, destination, tag and body). It is used to match a reply to the corresponding request. The default wait ID for a message is zero (none).8õÓÁ pÆ C T€ë€€‚‚‚‚‚‚‚€€‚‚ƒ‚‚ƒ‚ƒ‚ƒƒ‚ƒ‚ƒ‚‚‚‚ÿpvm_getmwid returns the wait ID associated with a message buffer, or a negative error code.pvm_setmwid assigns a new wait ID to a message buffer.It returns PvmOk unless an error occurs.EXAMPLESint src, tag;pvm_recv(-1, -1);/* ... process, compose reply message */ pvm_setmwid(pvm_getsbuf(), pvm_getmwid(pvm_getrbuf())); pvm_bufinfo(pvm_getrbuf(), (int *)0, &tag, &src);pvm_send(src, tag);ERRORSThe following error conditions can be returned by pvm_getmwid or pvm_setmwid:±‚8Ä !Ç / ,€€€‚‚‚‚‚ãÿ­A›‰‚ÿPvmBadParam: Invalid value for bufid argument.PvmNoSuchBuf: Message buffer \fIbufid\fR doesn't exist.see alsopvm_bufinfo; pÆ \Ç 1Ÿ(€ ‚H\Ç ŒÇ éC pvm_setopt0 !Ç ŒÇ # €€€‚ÿpvm_setoptBñ\Ç ÎÉ Q p€ã€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚ƒƒƒ‚ƒƒ‚ƒƒƒ‚ƒƒƒ‚ƒƒ‚ƒƒƒ‚ÿpvm_setopt Sets libpvm options.SYNOPSISCint oldval = pvm_setopt( int what, int val )Fortrancall pvmfsetopt( what, val, oldval )PARAMETERSwhatInteger defining what to set. One of:PvmRoute1Message routing policyPvmDebugMask 2 Libpvm debug maskPvmAutoErr 3 Auto error reportingPvmOutputTid 4 Stdout destination for childrenPvmOutputCode 5 Output message tagPvmTraceTid 6 Trace data destination for children+íŒÇ ùË > J€Û€€ƒƒ‚ƒƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒƒƒ‚ƒƒƒ‚ÿPvmTraceCode 7 Trace message tagPvmFragSize 8 Message fragment sizePvmResvTids 9 Allow messages to reserved tags and TIDs PvmSelfOutputTid 10 Stdout destinationPvmSelfOutputCode 11 Output message tagPvmSelfTraceTid 12 Trace data destinationPvmSelfTraceCode 13 Trace message tagPvmShowTids 14 pvm_catchout prints task ids with outputPvmPollType 15 Message wait policy (shared memory)BÎÉ ;Î ; D€€€ƒƒƒ‚‚‚‚‚ƒƒ‚ƒƒƒ‚ƒƒ‚‚‚‚‚‚‚ÿPvmPollTime 16 Message spinwait durationvalInteger specifying new setting of option. Predefined values for PvmRoute are:PvmDontRoute 1 Don't request or grant connectionsPvmAllowDirect 2 (Default) Don't request but allowPvmRouteDirect 3 Request and allow connectionsoldvalInteger returning the previous setting of the option.DESCRIPTIONThe routine pvm_setopt is a general purpose function used to set miscellaneous options in the PVM library. What is one of:ý×ùË D & €¯€€‚‚‚ÿPvmRouteAdvises PVM on whether to set up direct task-to-task links. PvmRouteDirect (using TCP) for all subsequent communication. Once a link is established it persists until the application finishes. If a direct link can not be established because one of the two tasks has requested PvmDontRoute or because adequate resources aren't available, then the default route through the PVM daemons is used. On multiproc;Î D !Ç essors such as Intel Paragon this option is ignored because the communication between tasks on these machines always uses the native protocol for direct communication. pvm_setopt can be called multiple times to selectively establish direct links, but is typically set only once near the beginning of each task.E;Î ‰ , &€3€€‚‚‚‚‚‚‚‚‚ÿPvmAllowDirectis the default route setting. This setting on task A allows other tasks to set up direct links to A. Once a direct link is established between tasks both tasks will use it for sending messages.PvmDebugMaskWhen debugging is turned on, PVM will log detailed information about its operations and progress on its stderr stream. val is the debugging level. Default is not to print any debug information.PvmAutoErrWhen an error results from a libpvm function call and PvmAutoErr is set to 1 (the default), an error message is automatically printed on stderr. A setting of 0 disables this. A setting of 2 causes the library to terminate the task by calling exit() after printing the error message. A setting of 3 causes the library to abort after printing the error message. a8D ê ) €q€€‚‚‚‚‚‚ÿPvmOutputTidSets the stdout destination for children tasks (spawned after the call to pvm_setopt). Everything printed on the standard output of tasks spawned by the calling task is packed into messages and sent to the destination. val is the TID of a PVM task. Setting PvmOutputTid to 0 redirects stdout to the master pvmd, which writes to the log file /tmp/pvml. The default setting is inherited from the parent task, else is 0.PvmOutputCodeSets the message tag for standard output messages. Should only be set when a task has PvmOutputTid set to itself.L ‰ 6 , &€A€€‚‚‚‚‚‚‚‚‚ÿPvmTraceTidSets the trace data message destination for children tasks (spawned after the call to pvm_setopt). Libpvm trace data is sent as messages to the destination. val is the TID of a PVM task. Setting PvmTraceTid to 0 discards trace data. The default setting is inherited from the parent task, else is 0.PvmTraceCodeSets the message tag for trace data messages. Should only be set when a task has PvmTraceTid set to itself.PvmFragSizeVal specifies the message fragment size in bytes. Default value varies with host architecture.…[ê » * "€·€€‚‚‚‚‚‚‚ÿPvmResvTidsA val of 1 enables the task to send messages with reserved tags and to non-task destinations. The default (0) causes libpvm to generate a PvmBadParam error when a reserved identifier is specified.PvmSelfOutputTidSets the stdout destination for the task. Everything printed on stdout is packed into messages and sent to the destination.Note: this only works for spawned tasks, because the pvmd doesn't get the output from tasks started by other means. val is the TID of a PVM task. Setting PvmSelfOutputTid to 0 redirects stdout to the master pvmd, which writes to the log file /tmp/pvml.. The default setting is inherited from the parent task, else is 0. Setting either PvmSelfOutputTid or PvmSelfOutputCode also causes both PvmOutputTid and PvmOutputCode to take on the values of PvmSelfOutputTid and PvmSelfOutputCode, respectively.16 ì ) €€€‚‚‚‚‚‚ÿPvmSelfOutputCodeSets the message tag for standard output messages.PvmSelfTraceTidSets the trace data message destination for the task.Libpvm trace data is sent as messages to the destination. val is the TID of a PVM task. Setting PvmSelfTraceTid to 0 discards trace data. The default setting is inherited from the parent task, else is 0. Setting either PvmSelfTraceTid or PvmSelfTraceCode also causes both PvmTraceTid and PvmTraceCode to take on the values of PvmSelfTraceTid and PvmSelfTraceCode, respectively.e9» ]A , &€s€€‚‚‚‚‚‚‚‚‚ÿPvmSelfTraceCodeSets the message tag for trace data messages.PvmShowTidsIf true (nonzero), pvm_catchout tags each line of output printed by a child task with the task id. Otherwise, output is exactly as printed.PvmPollTypeSì ]A !Ç ets the message wait policy when using shared-memory message transport. Setting PvmPollType to PvmPollConstant causes the application to spin on its message queue waiting for a message. Setting PvmPollType to PvmPollSleep causes the application to poll the message queue for messages PvmPollTime times before pending on the semaphore. !áì ~C @ N€Ã€€‚‚‚‚‚‚€€‚‚‚ƒ‚‚ƒ‚‚€€‚‚ÿPvmPollTimeSets the poll count for applications checking their message queue before they pend on the semaphore. This option is ignored if PvmPollType is set to PvmPollConstant.pvm_setopt returns the previous value of the option. If an error occurs, the PVM error code is returned in place of the option value.EXAMPLESC:oldval = pvm_setopt( PvmRoute, PvmRouteDirect );Fortran:CALL PVMFSETOPT( PVMAUTOERR, 1, OLDVAL )ERRORSThis error condition can be returnedk?]A éC , (€~€€‚‚‚ãûF&‰‚ÿPvmBadParam: giving an invalid value.see alsopvm_getopt< ~C %D 1cÁ„°‡I%D VD ˆJ pvm_setrbuf1éC VD # €€€‚ÿpvm_setrbuf±k%D G F Z€×€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚€€‚‚ÿpvm_setrbuf Switches the active receive buffer and saves the previous buffer.SYNOPSISCint oldbuf = pvm_setrbuf( int bufid )Fortrancall pvmfsetrbuf( bufid, oldbuf )PARAMETERSbufidInteger specifying the message buffer identifier for the new active receive buffer.oldbufInteger returning the message buffer identifier for the previous active receive buffer.DESCRIPTIONThe routine pvm_setrbuf switches the active receive buffer to bufid and saves the previous active receive buffer oldbuf. If bufid is set to 0 then the present active receive buffer is saved and no active receive buffer exists. %VD ,I $ €€€‚ÿA successful receive automatically creates a new active receive buffer. If a previous receive has not been unpacked and needs to be saved for later, then the previous bufid can be saved and reset later to the active buffer for unpacking. The routine is required when managing multiple message buffers. For example switching back and forth between two buffers. One buffer could be used to send information to a graphical interface while a second buffer could be used send data to other tasks in the application.\G ˆJ F Z€-€€‚€€‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚ã™Ým‰‚ÿEXAMPLESC:rbuf1 = pvm_setrbuf( rbuf2 );Fortran:CALL PVMFSETRBUF( NEWBUF, OLDBUF )ERRORSThese error conditions can be returned by pvm_setrbufPvmBadParam: giving an invalid bufid.PvmNoSuchBuf: switching to a non-existent message buffer.see alsopvm_getrbuf< ,I ÄJ 1l ‚JÄJ õJ <€ pvm_setsbuf1ˆJ õJ # €€€‚ÿpvm_setsbuf¥_ÄJ šM F Z€¿€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚€€‚‚ÿpvm_setsbuf Switches the active send buffer.SYNOPSISCint oldbuf = pvm_setsbuf( int bufid )Fortrancall pvmfsetsbuf( bufid, oldbuf )PARAMETERSbufidInteger the message buffer identifier for the new active send buffer. A value of 0 indicates the default receive buffer.oldbufInteger returning the message buffer identifier for the previous active send buffer.DESCRIPTIONThe routine pvm_setsbuf switches the active send buffer to bufid and saves the previous active send buffer oldbuf. If bufid is set to 0 then the present active send buffer is saved and no active send buffer exists.ÕõJ ¬O = H€«€€‚‚€€‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚ÿThe routine is required when managing multiple message buffers. For example switching back and forth between two buffers. One buffer could be used to send information to a graphical interface while a second buffer could be used send data to other tasks in the application.EXAMPLESC:sbuf1 = pvm_setsbuf( sbuf2 );Fortran:CALL PVMFSETSBUF( NEWBUF, OLDBUF )ERRORSThese error conditions can be returned by pvm_setsbufPvmBadParam: giving an invalid bufid.„VšM <€ . ,€¬€€‚‚‚ãñ½A‰‚‚‚ÿPvmNoSuchBuf: switching to a non-exis¬O <€ ˆJ tent message buffer.see alsopvm_setrbuf= ¬O y€ 1o°‡ê Ky€ «€ éŽ pvm_settmask2<€ «€ # €€€‚ÿpvm_settmask†:y€ 1ƒ L f€u€€‚€‚‚‚‚ƒ‚ƒ‚‚ƒ‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚ƒƒ‚ƒƒ‚‚‚‚ÿpvm_gettmask,pvm_settmask Get or set trace mask of a task or its children..SH SYNOPSISC#include #include int info = pvm_gettmask( int who, Pvmtmask mask )int info = pvm_settmask( int who, Pvmtmask mask )FortranNot AvailablePARAMETERSwhoSpecifies which trace mask to get or set:PvmTaskSelfThe current taskPvmTaskChildChildren tasks to be spawnedmaskTrace mask (owned by caller), which is filled in with the current trace vector on calling pvm_gettmask or used to set the current trace vector on calling pvm_settmask.Ì«€ 3… 6 :€™€€‚‚‚‚€€‚ã¿l‰‚‚ÿinfoStatus code returned. Values less than zero indicate an error.DESCRIPTIONEach task has a trace mask, which can be used to individually enable tracing of each libpvm function. The mask is inherited from its parent task (or initially all cleared if the task has no parent). When calls are made to functions in libpvm, the parameters and results are sent in messages to the trace sink of the task (variable PvmTraceTid set by calling pvm_setopt).—o1ƒ ʇ ( €ß€€‚ƒ‚‚‚ÿThe PVM console and XPVM use this system to get trace data from application programs. A task can get or set either its own trace mask, or the mask passed to children it spawns. Note the mask must be set before the spawn call; setting the child trace mask has no effect on already-running children. The trace mask can be kept in a temporary variable, declared as: Pvmtmask mymask;Right now, this is a character array with approximately 80 bits. There are four macros defined to manipulate trace masks. Along with the functions, these allow a program to get the current trace mask, modify or save it, and put it back:(ø3… òŠ 0 .€ñ€€‚ƒ‚ƒ‚ƒ‚ƒ‚‚‚‚‚ÿTEV_INIT_MASK(mask)TEV_SET_MASK(mask, kind)TEV_UNSET_MASK(mask, kind)TEV_CHECK_MASK(mask, kind)TEV_INIT_MASK initializes a mask to all bits cleared and must be used to initialize a trace mask (unless that is done by setting it from pvm_gettmask). TEV_SET_MASK sets a bit in a mask. Bit values are defined in . Likewise, TEV_UNSET_MASK clears a single bit and TEV_CHECK_MASK checks to see if a bit is set, returning nonzero if true. Note:Most events in the trace mask come in pairs, the first (ending in ...0) is generated on entry to a function and the second (...1) on exit. The trace mask has only half as many bits as there are events; events are enabled in pairs. In other words, if you select TEV_SEND0, you'll also get TEV_SEND1.ßʇ  6 :€¿€€‚‚‚ƒ‚‚‚‚€€‚‚‚ƒ‚ÿThe trace mask is deliberately kept as a printable (and null-terminated) string, for two reasons. First, it is passed through the environment between tasks, in the form:PVMTMASK=@@AAOG@@NO@L@@@@@@@@so the pvmd doesn't have to explicitly manage it. Second, the mask variables can be passed between tasks using pvm_pkstr() or otherwise manipulated as strings. pvm_gettmask and pvm_settmask return PvmOk on success, else a negative value.EXAMPLESC:#include âòŠ éŽ S t€€€ƒ‚‚ƒ‚‚ƒ‚ƒ‚ƒ‚ƒ‚‚€€‚‚‚‚‚ã}$ቂã¿l‰‚ãûF&‰‚‚ÿ#include Pvmtmask m;pvm_gettmask( PvmTaskChild, m );TEV_SET_MASK(m, TEV_ADDHOSTS0 );pvm_settmask( PvmTaskChild, m );pvm_spawn( "worker", (char **)0, PvmTaskDefault, "", 1, (int *)0);ERRORSThe following error condition can be returned by pvm_gettmask or pvm_settmask:PvmBadParam: invalid value for \fIwho\fR argument.see alsopvm consolepvm_setoptpvm_getopt=  & 1™ o†L& X É pvm_siblings2éŽ X # €€€‚ÿpvm_siblingsŽN& òÁ @ N€€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚‚‚ÿpvm_siblings return the number and associated task ids of processes that were started together in a sX òÁ éŽ ingle spawn call. SYNOPSISCint ntids = pvm_siblings( int **tids )Fortrancall pvmfsiblings( ntids, index, sibling )PARAMETERSntidsReturns the number of tids that were spawned together. Value less than 0 indicates an error. tidsPointer to the array of tids that contains the siblings. Indexed from 0 to (ntids - 1)index Integer index of tid to be returned in sibling. If index is set to -1, then sibling is unchanged. Otherwise, must be in the range [0, ntids - 1] ûÌX íÄ / ,€™€€‚‚‚‚€€‚‚ÿsibling When index is in the range [0, ntids -1], this contains the tid of the desired index.DESCRIPTIONThe routine pvm_siblings returns the number of tasks and a list of task ids of processes that were spawned together in a single spawn call. The spawning task multicasts the list of successful to the spawned tasks so that each task has an identical copy of the sibling list. pvm_siblings uses local storage to keep the list of tids and does not update this list when sibling tasks exit the virtual machine. The FORTRAN version allows calling programs read a particular index in the internal sibling array. If pvm_siblings is successful, ntids will be > 0. If some error occurs then ntids will be < 0.`9òÁ MÇ ' €s€€‚‚‚‚ÿpvm_siblings is designed to simplify the logic in static spmd-style programs. By giving tasks an identical list of tids and its size, programs may self size and treat the sibling as static map between instances and tasks. The internal list is not updated when sibling tasks exit the virtual machine and should be treated as a snapshot of the parallel program when it was first started. If a task was started by pvm_spawn, then pvm_siblings will return ntids = 1 and ntids = 1 and tids will contain a single entry identical to the task id returned by pvm_mytid() ÉjíÄ É _ Œ€Õ€€‚‚€€‚‚‚ƒ‚ƒ‚‚ƒ‚ƒ‚ƒ‚ƒ‚‚€€‚‚‚‚‚ã½€z÷‰‚ã™òLö‰‚ãºOt‰‚‚‚‚ÿEXAMPLESC:int *tids;ntids = pvm_siblings(&tids);Fortran:INTEGER TIDS(0:MAXNPROC)CALL PVMFSIBLINGS(NTIDS, -1, IDUM)DO I = 0, NTIDS-1 CALL PVMFSIBLINGS(NTIDS, I, TIDS(I))ERRORSpvm_siblings can return the following error codesPvmNoTask: No task at that index, or index is invalid.see alsopvm_spawnpvm_mytidpvm_parent: MÇ PÉ 1…ê €MPÉ É fB pvm_spawn/ É É # €€€‚ÿpvm_spawn7PÉ ¶Ë 4 6€€€€‚‚‚‚ƒ‚‚ƒ‚‚‚‚‚‚ÿpvm_spawn Starts new PVM processes.SYNOPSISCint numt = pvm_spawn( char *task, char **argv, int flag, char *where, int ntask, int *tids )Fortrancall pvmfspawn( task, flag, where, ntask, tids, numt )PARAMETERStaskCharacter string which is the executable file name of the PVM process to be started. The executable must already reside on the host on which it is to be started. The name may be a file in the PVM search path or an absolute path. The default PVM search path is $HOME/pvm3/bin/$PVM_ARCH/ .çÉ ÈÍ + $€Ï€€‚‚‚‚‚‚‚‚ÿargvPointer to an array of arguments to the executable (if supported on the target machine), not including the executable name, with the end of the array specified by NULL. argv[0] of the spawned task is set to the executable path relative to the PVM working directory (or absolute if an absolute filename was specified). If the executable needs no arguments, then the second argument to pvm_spawn is NULL.flagInteger specifying spawn options.In C, flag should be the sum of:Ì¶Ë ÚÏ F Z€™€€‚ƒƒƒ‚ƒƒƒƒƒƒƒƒƒƒƒƒ‚ƒƒƒƒƒƒ‚ƒƒƒ‚‚‚ƒƒƒ‚ÿOption valueMEANINGPvmTaskDefault0PVM can choose any machine to start task PvmTaskHost1\fIwhere\fR specifies a particular host PvmTaskArch2\fIwhere\fR specifies a type of architecture PvmTaskDebug4Start up processes under debuggerPvmTaskTrace8Processes will generate PVM trace data. * PvmMppFront16Start process on MPP front-end.PvmHostCompl32Use complement host setIn Fortran, flag should be the sum of:Option valueMEANINGr7ÈÍ X ; D€o€€ƒƒƒƒÚÏ X É ƒƒ‚ƒƒƒ‚ƒƒƒ‚ƒƒƒ‚‚‚‚‚‚ÿPVMDEFAULT0PVM can choose any machine to start task PVMHOST1\fIwhere\fR specifies a particular hostPVMARCH2\fIwhere\fR specifies a type of architecturePVMDEBUG4Start up processes under debuggerPVMTRACE8Processes will generate PVM trace data. ** future extensionwhereCharacter string specifying where to start the PVM process. Depending on the value of flag, where can be a host name such as ``ibm1.epm.ornl.gov'' or a PVM architecture class such as ``SUN4''. If flag is 0, then where is ignored and PVM will select the most appropriate host.:ÚÏ ’ 5 8€ €€‚‚‚‚‚‚‚‚‚‚€€‚‚ÿntaskInteger specifying the number of copies of the executable to start.tidsInteger array of length ntask returning the tids of the PVM processes started by this pvm_spawn call. numtInteger returning the actual number of tasks started. Values less than zero indicate a system error. A positive value less than ntask indicates a partial failure. In this case the user should check the tids array for the error code(s).DESCRIPTIONThe routine pvm_spawn starts ntask copies of the executable named task. On systems that support environment, spawn passes selected variables from parent environment to children tasks. If set, the envar PVM_EXPORT is passed. If PVM_EXPORT contains other names (separated by ':') they will be passed too. This is useful for e.g.: ÌŸX ^ - (€?€€‚‚ƒ‚ƒ‚ƒ‚‚‚ÿsetenv DISPLAY myworkstation:0.0setenv MYSTERYVAR 13setenv PVM_EXPORT DISPLAY:MYSTERYVARThe hosts on which the PVM processes are started are determined by the flag and where arguments. On return the array tids contains the PVM task identifiers for each process started. If pvm_spawn starts one or more tasks, numt will be the actual number of tasks started. If a system error occurs then numt will be < 0. If numt is less than ntask then some executables have failed to start and the user should check the last ntask - numt locations in the tids array which will contain error codes (see below for meaning). The first numt tids in the array are always valid. €Z’ Þ & €µ€€‚‚‚ÿWhen flag is set to 0 and where is set to NULL (or ``*'' in Fortran) a heuristic (round-robin assignment) is used to distribute the ntask processes across the virtual machine. If the PvmHostCompl flag is set, the resulting host set gets complemented. Also, the TaskHost hostname "." is taken as localhost. These can be used, for example, to spawn n - 1 tasks on host "." with flags TaskHost|HostCompl to get all but the localhost.In the special case where a multiprocessor is specified by where, pvm_spawn will start all ntask copies on this single machine using the vendor's underlying routines. „Z^ b * "€µ€€‚ƒ‚ƒ‚‚‚ÿThe spawned task will have argv[0] set to the the executable path relative to its inherited working directory (or possibly an absolute path), so the base filename can be got by using: char *p;p = (p = rindex(argv[0], '/')) ? p + 1 : argv[0];If PvmTaskDebug is set, then the pvmd will start the task(s) under debugger(s). In this case, instead of executing pvm3/bin/ARCH/task args it executes pvm3/lib/debugger pvm3/bin/ARCH/task args. debugger is a shell script that the users can modify to their individual tastes. Presently the script starts an xterm with dbx or comparable debugger in it. +ëÞ  @ N€×€€‚€€‚‚‚ƒ‚ƒ‚ƒ‚‚ƒ‚ƒ‚ƒ‚‚‚ƒ‚ƒ‚ÿEXAMPLESC:numt = pvm_spawn( "host", 0, PvmTaskHost, "sparky", 1, &tid[0] );numt = pvm_spawn( "host", 0, (PvmTaskHost+PvmTaskDebug), sparky", 1, &tid[0] );numt = pvm_spawn( "node", 0, PvmTaskArch, "RIOS", 1, &tid[i] );char *args[] = { "12", "60" , (char*)0 };numt = pvm_spawn( "FEM1", args, 0, 0, 16, tids );numt = pvm_spawn( "pde", 0, PvmTaskHost, "paragon.ornl", 512, tids );Fortran:FLAG = PVMARCH + PVMDEBUGCALL PVMFSPAWN( 'node', FLAG, 'SUN4', 1, TID(3), NUMT ) Ùb ¥A 3 4€³€€ƒ‚ƒ‚‚€€‚‚‚‚‚ÿCALL PVMFSPAWN( 'FEM1', PVMDEFAULT, '*', 16, TIDS, NUMT )CAL ¥A É L PVMFSPAWN( 'TBMD', PVMHOST, 'cm5.utk.edu', 32, TIDS, NUMT )ERRORSThese error conditions can be returned by pvm_spawn either in numt or in the tids array.PvmBadParam: giving an invalid argument value.PvmNoHost: Specified host is not in the virtual machine.PvmNoFile: Specified executable cannot be found. The default location PVM looks in is ~/pvm3/bin/ARCH, where ARCH is a PVM architecture name. Á fB 2 2€€€‚‚‚‚‚㲊š‰‚‚‚‚ÿPvmNoMem: Malloc failed. Not enough memory on host.PvmSysErr: pvmd not responding.PvmOutOfRes: out of resources.see alsopvm_export?¥A ¥B 1Èo†n†N¥B ÙB pI pvm_start_pvmd4fB ÙB # €"€€‚ÿpvm_start_pvmdØ¥B ÷D F Z€±€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚ÿpvm_start_pvmd Starts new PVM daemon.SYNOPSISCint info = pvm_start_pvmd( int argc, char **argv, int block )Fortrancall pvmfstartpvmd( args, block, info )PARAMETERSargcNumber of arguments in argv.argvAn array of arguments to the executable.argsA character string containing the arguments to the executable.blockInteger specifying whether to block until startup of all hosts complete or return immediately.infoInteger returning the error code.˜lÙB G , &€Ù€€‚€€‚‚ÿDESCRIPTIONThe routine pvm_start_pvmd starts up a pvmd3 process, the master of a new virtual machine. It returns as soon as the pvmd is started and ready for work. If the block parameter is nonzero and a hostfile is passed to the pvmd as a parameter, it returns when all hosts marked to start have been added. pvm_start_pvmd returns zero on success. If PVM is compiled to allow running more than one pvmd per host, calling pvm_start_pvmd before any other pvm functions will connect to the pvmd that it starts. pvm_start_pvmd sets environment variable PVMSOCK to the address printed by the pvmd as it starts up.áŠ÷D pI W |€€€‚€€‚‚‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚‚‚ƒ‚‚‚‚‚‚‚‚ã„”Z³‰‚ã›®tö‰‚‚ƒƒƒ‚ÿEXAMPLESC:static char *argv[] = { "-d41", "/u/jones/pvmd_hosts",};argc = 2info = pvm_start_pvmd( argc, argv, block );Fortran:CALL PVMFSTART_PVMD( '-d41 /u/jones/pvmd_hosts', BLOCK, INFO )The following error conditions can be returnedPvmDupHost: pvmd is already running.PvmSysErr: The local pvmd is not responding.see alsopvm_addhostspvmd3 daemon : G ªI 1Ë € OªI ÙI "… pvm_tasks/ pI ÙI # €€€‚ÿpvm_tasks½ªI ÛK E X€{€€€‚‚‚‚ƒ‚‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚‚ƒ‚‚‚‚‚‚‚‚ÿpvm_tasks Returns information about the tasks running on the virtual machine.SYNOPSISCint info = pvm_tasks( int where, int *ntask, struct pvmtaskinfo **taskp )struct pvmtaskinfo {int ti_tid;int ti_ptid;int ti_host;int ti_flag;char *ti_a_out;} taskp;Fortrancall pvmftasks( where, ntask, tid, ptid, dtid, flag, aout, info ) PARAMETERSwhereInteger specifying what tasks to return information about.The options are:ÑÙI ÞM 2 2€£€€ƒƒ‚ƒƒ‚ƒƒ‚‚‚‚‚‚‚ÿ 0for all the tasks on the virtual machinepvmd tidfor all tasks on a given host tidfor a specific taskntaskInteger returning the number of tasks being reported on.taskpReturns pointer to an array of structures which contain information about each task including its task ID, parent tid, pvmd task ID, status flag, and the name of this task's executable file. The status flag values are: waiting for a message, waiting for the pvmd, and running. ¯qÛK ™‚ > J€ã€€‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚€€‚‚ÿtidInteger returning task ID of one taskptidInteger returning parent task IDdtidInteger returning pvmd task ID of host task is on.flagInteger returning status of taskaoutCharacter string returning the name of spawned task. Manually started tasks return blank.infoInteger status code returned by the routine. Values less than zero indicate an error.DESCRIPTIONThe routine pvm_tasks returns information about tasks presently running on the virtual machine. The inÞM ™‚ pI formation returned is the same as that available from the console command ps. The C function returns information about the entire virtual machine in one call. The Fortran function returns information about one task per call and cycles through all the tasks. Thus, if where = 0, and pvmftasks is called ntask times, all tasks will be represented. Note that in Fortran the reported value of ntask and the set of tasks do not change until the function resets at the end of a complete cycle. The user can reset pvmftasks() at any time by calling it with ntask = -1. If pvm_tasks is successful, info will be 0. If some error occurs then info will be < 0. .âÞM Ç„ L f€Å€€‚€€‚‚‚ƒ‚ƒ‚‚ƒ‚ƒ‚ƒƒ‚‚ƒ‚ƒ‚ƒ‚‚€€‚‚‚‚‚ÿEXAMPLESC:struct pvmtaskinfo *taskp;int i, ntask;info = pvm_tasks( 0, &ntask, &taskp );for (i = 0; i < ntask; i++)printf("t%x\\n", taskp[i].ti_tid);Fortran:Do i=1, NTASK CALL PVMFTASKS( DTID, NTASK, TID(i), PTID(i), DTID(i), FLAG(i), AOUT(i), INFO )EndDoERRORSThe following error condition can be returned by pvm_tasksPvmBadParam: invalid value for where argument.PvmSysErr: pvmd not responding.PvmNoHost: specified host not in virtual machine.[)™‚ "… 2 4€R€€‚‚ãL<‰‚ãT‰‚ÿsee alsopvm_configpvm_tidtohost> Ç„ `… 1n†kP`… “… fˆ pvm_tidtohost3"… “… # € €€‚ÿpvm_tidtohost)Ú`… ¼‡ O l€µ€€€‚‚‚‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚€€‚‚‚€€‚‚ÿpvm_tidtohost Returns the host of the specified PVM process.SYNOPSISCint dtid = pvm_tidtohost( tid )Fortrancall pvmftidtoh( tid, dtid )PARAMETERStidInteger task identifier of the PVM process in question.dtidInteger returns the tid of the host's pvmd3 or a negative value if an error.DESCRIPTIONThe routine pvm_tidtohost returns the host id on which the process identified by tid is located.ERRORSThe following error conditions can be returnedªv“… fˆ 4 8€ì€€‚‚‚‚ãÔøœ÷‰‚ãL<‰‚ÿPvmBadParam: An invalid tid value was specified.PvmSysErr: pvmd not responding.see alsopvm_taskspvm_config: ¼‡  ˆ 1/ -…Q ˆ ψ Æ pvm_trecv/ fˆ ψ # €€€‚ÿpvm_trecvH ˆ ‹ E X€€€€‚‚‚‚ƒ‚ƒ‚‚ƒ‚‚€€‚‚‚‚‚‚‚‚‚‚‚‚‚ÿpvm_trecv Receive with timeout.SYNOPSISC#include int bufid = pvm_trecv( int tid, int msgtag, struct timeval *tmout )Fortrancall pvmftrecv( tid, msgtag, sec, usec, bufid )PARAMETERStidInteger to match task identifier of sending process.msgtagInteger to match message tag; should be >= 0.tmout (or sec and usec)Time to wait before returning without a message.bufidInteger returns the value of the new active receive buffer identifier. Values less than zero indicate an error.Ô§ψ ë - (€O€€‚€€‚‚‚ÿDESCRIPTIONThe routine pvm_trecv blocks the process until a message with label msgtag has arrived from tid. pvm_trecv then places the message in a new active receive buffer, also clearing the current receive buffer. If no matching message arrives within the specified waiting time, pvm_trecv returns without a message. A -1 in msgtag or tid matches anything. This allows the user the following options. If tid = -1 then pvm_trecv will accept a message from any process which has a matching msgtag. If msgtag = -1 then pvm_trecv will accept any message that is sent from process tid. If tid and msgtag are both -1, then pvm_trecv will accept any message from any process. å‹ À $ €Ë€€‚ÿIn C, the tmout fields tv_sec and tv_usec specify how long pvm_trecv will wait without returning a matching message. In Fortran, two separate parameters, sec and usec are passed. With both set to zero, pvm_trecv behaves the same as pvm_nrecv, which is to probe for messages and return immediately even if none are matched. In C, passing a null pointer in tmout makes pvm_trecv act like pvm_recv, that is, it will wait indefinitely. In Fortran, setting sec to -1 has the same effect.ë À fˆ æë  & €Í€€‚‚‚ÿThe PVM model guarantees the following about message order. If task 1 sends message A to task 2, then task 1 sends message B to task 2, message A will arrive at task 2 before message B. Moreover, if both messages arrive before task 2 does a receive, then a wildcard receive will always return message A. If pvm_trecv is successful, bufid will be the new active receive buffer identifier. If no message is received, pvm_trecv returns 0. If some error occurs then bufid will be < 0. ¾ À Ä I `€}€€‚‚€€‚‚‚ƒ‚‚ƒ‚ƒ‚ƒ‚ƒ‚ƒ‚ƒƒ‚ƒƒ‚ƒƒ‚ƒ‚‚ƒ‚ÿOnce pvm_trecv returns, the data in the message can be unpacked into the user's memory using the unpack routines.EXAMPLESC:struct timeval tmout;tid = pvm_parent();msgtag = 4 ;tmout.tv_sec = 60;tmout.tv_usec = 0;if ((bufid = pvm_trecv( tid, msgtag, &tmout )) > 0) {pvm_upkint( tid_array, 10, 1 );pvm_upkint( problem_size, 1, 1 );pvm_upkfloat( input_array, 100, 1 );}Fortran:CALL PVMFTRECV( -1, 4, 60, 0, BUFID )ö‰ Æ m ¨€€€ƒ‚ƒ‚ƒ‚ƒ‚‚‚‚€€‚‚‚‚‚‚ãÿ­A›‰‚ãþ1xö‰‚ã¬M„#‰‚ã;Óà÷‰‚ã^Ïàö‰‚ㆅ#‰‚ãzº1ö‰‚‚‚ÿIF (BUFID .EQ. 0) GO TO 666CALL PVMFUNPACK( INTEGER4, TIDS, 25, 1, INFO )CALL PVMFUNPACK( REAL8, MATRIX, 100, 100, INFO )666CONTINUEERRORSThese error conditions can be returned by pvm_trecv PvmBadParam: giving an invalid tid value, or msgtag < -1.PvmSysErr: pvmd not responding.see alsopvm_bufinfopvm_nrecvpvm_recvpvm_unpk*pvm_probepvm_sendpvm_mcast= Ä RÆ 1mkO…RRÆ „Æ ÀÆ pvm_unexport2Æ „Æ # €€€‚ÿpvm_unexport<RÆ ÀÆ ) "€&€€㲊š‰‚ÿsee pvm_export: „Æ úÆ 1A-…ÿÿÿÿSúÆ )Ç A pvm_unpk*/ ÀÆ )Ç # €€€‚ÿpvm_unpk**ùúÆ SÉ 1 0€ó€€€‚‚‚‚‚‚‚‚‚‚‚ÿpvm_unpack Unpack the active message buffer into arrays of prescribed data type.SYNOPSIS C int info = pvm_unpackf( const char *fmt, ... ) int info = pvm_upkbyte( char *xp, int nitem, int stride) int info = pvm_upkcplx( float *cp, int nitem, int stride) int info = pvm_upkdcplx( double *zp, int nitem, int stride) int info = pvm_upkdouble( double *dp, int nitem, int stride) int info = pvm_upkfloat( float *fp, int nitem, int stride) á)Ç ^Ë * "€Ã€€‚‚‚‚‚‚‚ÿ int info = pvm_upkint( int *ip, int nitem, int stride) int info = pvm_upkuint( unsigned int *ip, int nitem, int stride ) int info = pvm_upkushort( unsigned short *ip, int nitem, int stride ) int info = pvm_upkulong( unsigned long *ip, int nitem, int stride ) int info = pvm_upklong( long *ip, int nitem, int stride) int info = pvm_upkshort( short *jp, int nitem, int stride) int info = pvm_upkstr( char *sp )WSÉ µÍ ; D€9€€‚‚‚‚‚€€‚‚‚‚‚‚‚‚‚‚‚‚‚ÿ Fortran call pvmfunpack( what, xp, nitem, stride, info )PARAMETERS fmt Printf-like format expression specifying what to pack. (See discussion)nitem The total number of items to be unpacked (not the number of bytes).stride The stride to be used when packing the items. For example, if stride = 2 in pvm_upkcplx, then every other complex number will be unpacked.xp Pointer to the beginning of a block of bytes. Can be any data type, but must match the corresponding pack data type.1ö^Ë ; D€í€€‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚ÿcp Complex array at least nitem*stride items long.zp Double precision complex array at least nitem*stride items long.dp Double precision real array at least nitem*stride items long.fp Real array at least nitem*stride items long.ip Integer array at least nitem*stride items long.jp Integer*2 array at least nitem*stride items long.sp Pointer to a null terminated character string.what Integer specifying the type of data being unpacked.µÍ ÀÆ á¢µÍ í ? L€E€€‚‚ƒƒ‚ƒƒ‚ƒƒ‚ƒ‚‚‚‚‚‚‚€€‚‚‚ÿ what options STRING 0 REAL4 4 BYTE11 COMPLEX8 5 INTEGER2 2 REAL8 6 INTEGER4 3 COMPLEX16 7info Integer status code returned by the routine. Values less than zero indicate an error.DESCRIPTIONEach of the pvm_upk* routines unpacks an array of the given data type from the active receive buffer. The arguments for each of the routines are a pointer to the array to be unpacked into, nitem which is the total number of items to unpack, and stride which is the stride to use when unpacking.Ó« À ( €W€€‚‚‚‚‚ÿAn exception is pvm_upkstr() which by definition unpacks a NULL terminated character string and thus does not need nitem or stride arguments. The Fortran routine pvmfunpack( STRING, ... ) expects nitme to be the number of characters in the string and stride to be 1.If the unpacking is successful, info will be 0. If some error occurs then info will be < 0.A single variable (not an array) can be unpacked by setting nitem = 1 and stride = 1.The routine pvm_unpackf() uses a printf-like format expression to specify what and how to unpack data from the receive buffer. All variables are passed as addresses. A BNF-like description of the format syntax is: Øí Ê 2 2€±€€‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚ÿ format : null | init | format fmt init : null | '%' '+' fmt : '%' count stride modifiers fchar fchar : 'c' | 'd' | 'f' | 'x' | 's' count : null | [0-9]+ | '*' stride : null | '.' ( [0-9]+ | '*' ) modifiers : null | modifiers mchar mchar : 'h' | 'l' | 'u'Formats: + means initsend - must match an int (how) in the param list. c pack/unpack bytes d integer f floatN!À  - (€C€€‚‚‚‚‚‚‚‚‚‚ÿ x complex float s stringModifiers: h short (int) l long (int, float, complex float) u unsigned (int)Future extensions to the what argument in pvmfunpack will include 64 bit types when XDR encoding of these types is available. Meanwhile users should be aware that precision can be lost when passing data from a 64 bit machine like a Cray to a 32 bit machine like a SPARCstation. As a mnemonic the what argument name includes the number of bytes of precision to expect. By setting encoding to PVMRAW (see pvmfinitsend) data can be transferred between two 64 bit machines with full precision even if the PVM configuration is heterogeneous. Messages should be unpacked exactly like they were packed to insure data integrity. Packing integers and unpacking them as floats will often fail because a type encoding will have occurred transferring the data between heterogeneous hosts. Packing 10 integers and 100 floats then trying to unpack only 3 integers and the 100 floats will also fail. ÔÊ & : B€©€€‚‚€€‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚ÿEXAMPLES C: info = pvm_recv( tid, msgtag ); info = pvm_upkstr( string ); info = pvm_upkint( &size, 1, 1 ); info = pvm_upkint( array, size, 1 ); info = pvm_upkdouble( matrix, size*size, 1 ); int count, *iarry; double darry[4]; pvm_unpackf("%d", &count); pvm_unpackf("%*d %4lf", count, iarry, darry); Fortran: CALL PVMFRECV( TID, MSGTAG, INFO );ƒ? µ@ D V€€€‚‚‚‚€€‚‚€€‚‚€€ã“v;ö‰‚ÿ CALL PVMFUNPACK( INTEGER4, NSIZE, 1, 1, INFO ) CALL PVMFUNPACK( STRING, STEPNAME, 8, 1, INFO ) CALL PVMFUNPACK( REAL4, A(5,1), NSIZE, NSIZE , INFO )ERRORS PvmNoData: Reading beyond the end of the receive buffer. Most likely cause is trying to unpack more items than were originally packed into the buffer.PvmBadMsg: The received message can not be decode& µ@ ÀÆ d. Most likely because the hosts are heterogeneous and the user specified an incompatible encoding. Try setting the encoding to PvmDataDefault (see pvm_mkbuf ).Ø€& A X ~€€€‚€€‚‚‚ãýk‰‚ㆅ#‰‚ã¬M„#‰‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚ÿPvmNoBuf: There is no active receive buffer to unpack.see alsopvm_pk*pvm_send pvm_recvFµ@ ÓA 1€TÓA B ùB PVM Fortran Interface;A B # €0€€‚ÿPVM Fortran InterfaceëÄÓA ùB ' €‰€€‚‚‚‚ÿThe Fortran Interface maps the PVM calls placed in a Fortran program with the lipvm3 library written in C.Fortran is more restrictive than C and a few functionalities are missing in Fortran.= B 6C 1oÿÿÿÿ€U6C hC ¦C pvmfaddhosts2ùB hC # €€€‚ÿpvmfaddhosts>6C ¦C ) "€*€€ã„”Z³‰‚ÿsee pvm_addhosts; hC áC 1m\ VáC D MD pvmfaddmhf0 ¦C D # €€€‚ÿpvmfaddmhf<áC MD ) "€&€€ãàækñ‰‚ÿsee pvm_addmhf; D ˆD 1m€ÀWˆD ¸D ôD pvmfadvise0 MD ¸D # €€€‚ÿpvmfadvise<ˆD ôD ) "€&€€ã*¢ñ‰‚ÿsee pvm_advise= ¸D 1E 1o äX1E cE ¡E pvmfarchcode2ôD cE # €€€‚ÿpvmfarchcode>1E ¡E ) "€*€€ã}E‰‚ÿsee pvm_archcode< cE ÝE 1nÀ‚YÝE F KF pvmfbarrier1¡E F # €€€‚ÿpvmfbarrier=ÝE KF ) "€(€€ã• ÿsee pvm_barrier: F …F 1lä$‚Z…F ´F ïF pvmfbcast/ KF ´F # €€€‚ÿpvmfbcast;…F ïF ) "€$€€ãßäóó‰‚ÿsee pvm_bcast< ´F +G 1n‚F‚[+G \G ™G pvmfbufinfo1ïF \G # €€€‚ÿpvmfbufinfo=+G ™G ) "€(€€ãÿ­A›‰‚ÿsee pvm_bufinfo= \G ÖG 1o$‚j‚\ÖG H FH pvmfcatchout2™G H # €€€‚ÿpvmfcatchout>ÖG FH ) "€*€€ã Štg‰‚ÿsee pvm_catchout; H H 1mF‚Š‚]H ±H íH pvmfconfig0 FH ±H # €€€‚ÿpvmfconfig<H íH ) "€&€€ãL<‰‚ÿsee pvm_config; ±H (I 1mj‚ª‚^(I XI ”I pvmfdelete0 íH XI # €€€‚ÿpvmfdelete<(I ”I ) "€&€€ã•ó ‰‚ÿsee pvm_delete= XI ÑI 1oŠ‚΂_ÑI J AJ pvmfdelhosts2”I J # €€€‚ÿpvmfdelhosts>ÑI AJ ) "€*€€ã®×0O‰‚ÿsee pvm_delhosts< J }J 1nª‚ð‚`}J ®J ëJ pvmfdelinfo1AJ ®J # €€€‚ÿpvmfdelinfo=}J ëJ ) "€(€€ãG£Ø‰‚ÿsee pvm_delinfo; ®J &K 1m΂ƒa&K VK ’K pvmfdelmhf0 ëJ VK # €€€‚ÿpvmfdelmhf<&K ’K ) "€&€€ãZIó ‰‚ÿsee pvm_delmhf9VK ËK 1kð‚,ƒbËK ùK 3L pvmfexit. ’K ùK # €€€‚ÿpvmfexit:ËK 3L ) "€"€€ãpu#‰‚ÿsee pvm_exit; ùK nL 1mƒLƒcnL žL ÚL pvmfexport0 3L žL # €€€‚ÿpvmfexport<nL ÚL ) "€&€€㲊š‰‚ÿsee pvm_export< žL M 1n,ƒnƒdM GM „M pvmffreebuf1ÚL GM # €€€‚ÿpvmffreebuf=M „M ) "€(€€ãE3àc‰‚ÿsee pvm_freebuf@GM ÄM 1rLƒ˜ƒeÄM ùM :N pvmffreecontext5„M ùM # €$€€‚ÿpvmffreecontextAÄM :N ) "€0€€ãy·s†‰‚ÿsee pvm_freecontext@ùM zN 1rnƒƒfzN ¯N ðN pvmffreezegroup5:N ¯N # €$€€‚ÿpvmffreezegroupAzN ðN ) "€0€€ãR£d‰‚ÿsee pvm_freezegroup; ¯N +O 1m˜ƒâƒg+O [O —O pvmfgather0 ðN [O # €€€‚ÿpvmfgather<+O —O ) "€&€€ãͱu%‰‚ÿsee pvm_gather?[O ÖO 1qƒhÖO € V€ pvmfgetcontext4—O € # €"€€‚ÿpvmfgeÖO € —O tcontext@ÖO V€ ) "€.€€ãóe[ʉ‚ÿsee pvm_getcontext; € ‘€ 1mâƒ7i‘€ Á€ ý€ pvmfgetfds0 V€ Á€ # €€€‚ÿpvmfgetfds<‘€ ý€ ) "€&€€ãõMF&‰‚ÿsee pvm_getfds< Á€ 9 1oZj9 j ¨ pvmfgetinst1ý€ j # €€€‚ÿpvmfgetinst>9 ¨ ) "€*€€ã>Óm‰‚ÿsee pvm_getinst@j è 1r7„kè ‚ ^‚ pvmfgetmboxinfo5¨ ‚ # €$€€‚ÿpvmfgetmboxinfoAè ^‚ ) "€0€€ã0‰Jʼn‚ÿsee pvm_getmboxinfo< ‚ š‚ 1nZ¦lš‚ Ë‚ ƒ pvmfgetmwid1^‚ Ë‚ # €€€‚ÿpvmfgetmwid=š‚ ƒ ) "€(€€ãÍØm‰‚ÿsee pvm_getmwid; Ë‚ Cƒ 1m„ÆmCƒ sƒ ¯ƒ pvmfgetopt0 ƒ sƒ # €€€‚ÿpvmfgetopt<Cƒ ¯ƒ ) "€&€€ãûF&‰‚ÿsee pvm_getopt< sƒ ëƒ 1n¦ènëƒ „ Y„ pvmfgetrbuf1¯ƒ „ # €€€‚ÿpvmfgetrbuf=ëƒ Y„ ) "€(€€ã™Ým‰‚ÿsee pvm_getrbuf< „ •„ 1nÆ o•„ Æ„ … pvmfgetsbuf1Y„ Æ„ # €€€‚ÿpvmfgetsbuf=•„ … ) "€(€€ã˜ÏÞm‰‚ÿsee pvm_getsbuf; Æ„ >… 1mè*p>… n… ª… pvmfgettid0 … n… # €€€‚ÿpvmfgettid<>… ª… ) "€&€€ãÛ³F&‰‚ÿsee pvm_gettid= n… ç… 1o Nqç… † W† pvmfgettmask2ª… † # €€€‚ÿpvmfgettmask>ç… W† ) "€*€€ã`Ó­t‰‚ÿsee pvm_gettmask: † ‘† 1l*lr‘† À† û† pvmfgsize/ W† À† # €€€‚ÿpvmfgsize;‘† û† ) "€$€€ãj^ õ‰‚ÿsee pvm_gsize9À† 4‡ 1kNˆs4‡ b‡ œ‡ pvmfhalt. û† b‡ # €€€‚ÿpvmfhalt:4‡ œ‡ ) "€"€€ã‹x#‰‚ÿsee pvm_halt= b‡ Ù‡ 1ol¬tÙ‡ ˆ Iˆ pvmfhostsync2œ‡ ˆ # €€€‚ÿpvmfhostsync>Ù‡ Iˆ ) "€*€€ãMélm‰‚ÿsee pvm_hostsync= ˆ †ˆ 1oˆÐu†ˆ ¸ˆ öˆ pvmfinitsend2Iˆ ¸ˆ # €€€‚ÿpvmfinitsend>†ˆ öˆ ) "€*€€ãÆ$«æ‰‚ÿsee pvm_initsend; ¸ˆ 1‰ 1m¬ðv1‰ a‰ ‰ pvmfinsert0 öˆ a‰ # €€€‚ÿpvmfinsert<1‰ ‰ ) "€&€€ã3ê 9‰‚ÿsee pvm_insert> a‰ Û‰ 1pÐwÛ‰ Š QŠ pvmfjoingroup7‰ Š & €"€€€‚ÿpvmfjoingroup?Û‰ QŠ ) "€,€€ãC^w0‰‚ÿsee pvm_joingroup9Š ŠŠ 1kð3xŠŠ ¸Š òŠ pvmfkill. QŠ ¸Š # €€€‚ÿpvmfkill:ŠŠ òŠ ) "€"€€ãî{#‰‚ÿsee pvm_kill; ¸Š -‹ 1mSy-‹ ]‹ ™‹ pvmflookup0 òŠ ]‹ # €€€‚ÿpvmflookup<-‹ ™‹ ) "€&€€ãœéT‰‚ÿsee pvm_lookup< ]‹ Õ‹ 1n3uzÕ‹ Œ CŒ pvmflvgroup1™‹ Œ # €€€‚ÿpvmflvgroup=Õ‹ CŒ ) "€(€€ãom\‰‚ÿsee pvm_lvgroup: Œ }Œ 1lS“{}Œ ¬Œ çŒ pvmfmcast/ CŒ ¬Œ # €€€‚ÿpvmfmcast;}Œ çŒ ) "€$€€ãzº1ö‰‚ÿsee pvm_mcast: ¬Œ ! 1lu±|! P ‹ pvmfmkbuf/ çŒ P # €€€‚ÿpvmfmkbuf;! ‹ ) "€$€€ã“v;ö‰‚ÿsee pvm_mkbuf: P Å 1l“Ï}Å ô /Ž pvmfmstat/ ‹ ô # €€€‚ÿpvmfmstat;Å /Ž ) "€$€€ãß©Eö‰‚ÿsee pvm_mstat: ô iŽ 1l±í~iŽ ˜Ž ÓŽ pvmfmytid/ /Ž ˜Ž # €€€‚ÿpvmfmytid;iŽ ÓŽ ) "€$€€ã™òLö‰‚ÿsee pvm_mytid?˜Ž  1qÏ F † pvmfnewcontext4ÓŽ F # €"€€‚ÿpvmfnewcontext@ † ) "€.€€ãéZb‰‚ÿsee pvm_newcontext; F Á 1m퀀Á À HÀ pvmfnotify0 † À # €€€‚ÿpvmfnotifyÁ À † <Á HÀ ) "€&€€ãA¦e‰‚ÿsee pvm_notify: À ‚À 1l1€‚À ±À ìÀ pvmfnrecv/ HÀ ±À # €€€‚ÿpvmfnrecv;‚À ìÀ ) "€$€€ãþ1xö‰‚ÿsee pvm_nrecv; ±À 'Á 1m€Q€‚'Á WÁ “Á pvmfparent0 ìÀ WÁ # €€€‚ÿpvmfparent<'Á “Á ) "€&€€ãºOt‰‚ÿsee pvm_parent; WÁ ÎÁ 1m1€q€ƒÎÁ þÁ : pvmfperror0 “Á þÁ # €€€‚ÿpvmfperror<ÎÁ : ) "€&€€ãæÂ u‰‚ÿsee pvm_perror: þÁ t 1lQ€€„t £Â Þ pvmfprecv/ : £Â # €€€‚ÿpvmfprecv;t Þ ) "€$€€ã`‡àö‰‚ÿsee pvm_precv: £Â à 1lq€­€…à Gà ‚à pvmfprobe/ Þ Gà # €€€‚ÿpvmfprobe;à ‚à ) "€$€€ã^Ïàö‰‚ÿsee pvm_probe: Gà ¼Ã 1l€Ë€†¼Ã ëà &Ä pvmfpsend/ ‚à ëà # €€€‚ÿpvmfpsend;¼Ã &Ä ) "€$€€㺿áö‰‚ÿsee pvm_psend: ëà `Ä 1l­€é€‡`Ä Ä ÊÄ pvmfpstat/ &Ä Ä # €€€‚ÿpvmfpstat;`Ä ÊÄ ) "€$€€ãò)âö‰‚ÿsee pvm_pstat< Ä Å 1nË€ ˆÅ 7Å tÅ pvmfputinfo1ÊÄ 7Å # €€€‚ÿpvmfputinfo=Å tÅ ) "€(€€ãkÙ9‰‚ÿsee pvm_putinfo97Å ­Å 1ké€'‰­Å ÛÅ Æ pvmfrecv. tÅ ÛÅ # €€€‚ÿpvmfrecv:­Å Æ ) "€"€€ã¬M„#‰‚ÿsee pvm_recv: ÛÅ OÆ 1l EŠOÆ ~Æ ¹Æ pvmfrecvf/ Æ ~Æ # €€€‚ÿpvmfrecvf;OÆ ¹Æ ) "€$€€ãú 9÷‰‚ÿsee pvm_recvf= ~Æ öÆ 1o'i‹öÆ (Ç fÇ pvmfrecvinfo2¹Æ (Ç # €€€‚ÿpvmfrecvinfo>öÆ fÇ ) "€*€€ãÆG ‰‚ÿsee pvm_recvinfo; (Ç ¡Ç 1mE‰Œ¡Ç ÑÇ È pvmfreduce0 fÇ ÑÇ # €€€‚ÿpvmfreduce<¡Ç È ) "€&€€ãì1–†‰‚ÿsee pvm_reduce> ÑÇ KÈ 1qi°KÈ ~È ¾È pvmfreghoster3 È ~È # € €€‚ÿpvmfreghoster@KÈ ¾È ) "€.€€㔂*މ‚ÿsee pvm_reg_hoster: ~È øÈ 1m‰ÏŽøÈ 'É cÉ pvmfregrm/ ¾È 'É # €€€‚ÿpvmfregrm<øÈ cÉ ) "€&€€ãÚ*™†‰‚ÿsee pvm_reg_rm> 'É ¡É 1q°ö¡É ÔÉ Ê pvmfregtasker3cÉ ÔÉ # € €€‚ÿpvmfregtasker@¡É Ê ) "€.€€ã©øuô‰‚ÿsee pvm_reg_tasker< ÔÉ PÊ 1nÏ‚PÊ Ê ¾Ê pvmfscatter1Ê Ê # €€€‚ÿpvmfscatter=PÊ ¾Ê ) "€(€€ãÜ'߉‚ÿsee pvm_scatter9Ê ÷Ê 1kö4‚‘÷Ê %Ë _Ë pvmfsend. ¾Ê %Ë # €€€‚ÿpvmfsend:÷Ê _Ë ) "€"€€ã†…#‰‚ÿsee pvm_send< %Ë ›Ë 1n‚V‚’›Ë ÌË Ì pvmfsendsig1_Ë ÌË # €€€‚ÿpvmfsendsig=›Ë Ì ) "€(€€ã‡:ø‰‚ÿsee pvm_sendsig; ÌË DÌ 1m4‚v‚“DÌ tÌ °Ì pvmfserror0 Ì tÌ # €€€‚ÿpvmfserror<DÌ °Ì ) "€&€€ãFj‰‚ÿsee pvm_serror?tÌ ïÌ 1qV‚ž‚”ïÌ #Í cÍ pvmfsetcontext4°Ì #Í # €"€€‚ÿpvmfsetcontext@ïÌ cÍ ) "€.€€ãwa’S‰‚ÿsee pvm_setcontext< #Í ŸÍ 1nv‚À‚•ŸÍ ÐÍ Î pvmfsetmwid1cÍ ÐÍ # €€€‚ÿpvmfsetmwid=ŸÍ Î ) "€(€€ã¹B<‰‚ÿsee pvm_setmwid; ÐÍ HÎ 1mž‚à‚–HÎ xÎ ´Î pvmfsetopt0 Î xÎ # €€€‚ÿpvmfsetopt<HÎ ´Î ) "€&€€ã¿l‰‚ÿsee pvm_setopt< xÎ ðÎ 1nÀ‚ƒ—ðÎ !Ï ^Ï pvmfsetrbuf1´Î !Ï # €€€‚ÿpvmfsetrbuf=ðÎ ^Ï ) "€(€€ãñ½A‰‚ÿsee pvm_setrbuf< !Ï šÏ 1nà‚˜šÏ ËÏ pvmfsetsbuf1^Ï ËÏ # €€€‚ÿpvmfsetsbuf=šÏ ) "€(€€ã„ôB‰‚ÿsee pvm_seËÏ ^Ï tsbuf= ËÏ Q1oƒ$™QƒÁpvmfsettmask2ƒ# €€€‚ÿpvmfsettmask>QÁ) "€*€€ã€è‰‚ÿsee pvm_settmask= ƒþ1oHšþ0npvmfsiblings2Á0# €€€‚ÿpvmfsiblings>þn) "€*€€ã—B,‰‚ÿsee pvm_siblings: 0¨1l$f›¨×pvmfspawn/ n×# €€€‚ÿpvmfspawn;¨) "€$€€ã½€z÷‰‚ÿsee pvm_spawn> ×P1qHœPƒÃpvmfstartpvmd3ƒ# € €€‚ÿpvmfstartpvmd@PÃ) "€.€€ã®c¤©‰‚ÿsee pvm_start_pvmd: ƒý1lf«ý,gpvmftasks/ Ã,# €€€‚ÿpvmftasks;ýg) "€$€€ãÔøœ÷‰‚ÿsee pvm_tasks> ,¥1pÑž¥Øpvmftidtohost3gØ# € €€‚ÿpvmftidtohost?¥) "€,€€ãT‰‚ÿsee pvm_tidtohost: ØQ1l«ïŸQ€»pvmftrecv/ €# €€€‚ÿpvmftrecv;Q») "€$€€ã$2±÷‰‚ÿsee pvm_trecv= €ø1oÑ ø*hpvmfunexport2»*# €€€‚ÿpvmfunexport>øh) "€*€€ãù=8‰‚ÿsee pvm_unexport: *¢1iïÿÿÿÿ¡¢ÿÿÿÿÑpvmfunpk*/ hÑ# €€€‚ÿpvmfunpk*9¢ 1g€€5„¢ ÿÿÿÿ8Glossary. Ñ8# €€€‚ÿGlossary@ x1e ÿÿÿÿ£x­ºBPVM Error Codes58­# €$€€‚ÿPVM Error CodesÁx¾P n€ƒ€€‚‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚ÿPvmAlreadyThe requested operation requires exclusive access, and another was already in progress.PvmBadMsgThe received messages has a data format native to another machine, which cannot be decoded by libpvm.PvmBadParamA bad parameter was passed to the function.PvmBadVersionTwo PVM components (pvmd and task, two pvmds or two tasks) have incompatible protocol versions and cannot interoperate. Version mismatchPvmCantStart„<­B H ^€y€€‚‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚ÿA pvmd could not be started on the local host, or a slave pvmd could not be started on a remote host.PvmDSysErrSome internal mechanism in the pvmd failed during the requested operation. PvmDupEntryThe class server already has an entry matching the insert request. [In Version 3.4: Relaced by PvmExists]PvmDupGroupThe task has already a member of the group it attempted to join.PvmDupHostAn attempt was made to add the same host to a virtual machine more than once, or to add a host already a member of another virtual machine owned by the same user.º¾U Y €€u€€‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚ÿPvmDeniedOperation is refused due to locking, permissions, etc.PvmExistsThere is already an entry matching the insert request.PvmHostFailA foreign host in the virtual machine failed during the requested operation. PvmMismatchA parameter does not match a corresponding one.PvmNoBufThere is no current message buffer to pack or unpack.PvmNoDataThe end of a message buffer was reached while trying to unpack data.ÂB pY €€…€€‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚ÿPvmNoEntryThe class server has no entry matching the lookup request. [In Version 3.4: Relaced by PvmNotFound]PvmNoFileThe named executable does not exist.PvmNoGroupThe named group does not exist.PvmNoHostThere is no host in the virtual machine with the given name, or the name could not be resolved to an address.PvmNoInstThe named group has no member with this instance.PvmNoMemMalloc failed to get memory for libpvm.ŸU ~Ac ”€?€€‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚‚€€‚‚‚ÿPvmNoParentThis task has no parent task.p~A8PvmNoSuchBufThere is no message buffer with the given buffer handle.PvmNoTaskNo task exists with the given tid.PvmNotFoundNo entry matching the lookup request was found.PvmNotImplThis libpvm function or option is not implemented.PvmNotInGroupThe named group has no such member task.PvmNullGroupA null group name was passed to a function.<pºB< F€€€€‚‚‚€€‚‚‚€€‚‚‚‚ÿPvmOutOfResThe requested operation could not be completed due to lack of resources.PvmOverflowA value is too large to be packed or unpacked.PvmSysErrLibpvm could not contact a pvmd on the local host, or the pvmd failed during an operation.B~AüB1Ç*ÿÿÿÿ¤üB3CÉFList of PVM Calls7ºB3C# €(€€‚ÿList of PVM Calls>üBqE= H€€€€‚‚‚‚€€‚‚‚‚€€‚‚‚ÿMessage Passingpvm_bufinfo, pvm_freebuf, pvm_getrbuf, pvm_getsbuf, pvm_initsend, pvm_mcast, pvm_mkbuf, pvm_nrecv, pvm_pack, pvm_precv, pvm_probe, pvm_psend, pvm_recv, pvm_recvf, pvm_send, pvm_sendsig, pvm_setmwid, pvm_setrbuf, pvm_setsbuf, pvm_trecv, pvm_unpackTask Controlpvm_exit, pvm_kill, pvm_mytid, pvm_parent, pvm_pstat, pvm_spawn, pvm_tasks Group Library Functionspvm_barrier, pvm_bcast, pvm_gather, pvm_getinst, pvm_gettid, pvm_gsize, pvm_joingroup, pvm_lvgroup, pvm_reduce, pvm_scatterX 3CÉF8 >€A€€‚€€‚‚‚‚€€‚‚‚‚ÿVirtual Machine Controlpvm_addhosts, pvm_config, pvm_delhosts, pvm_halt, pvm_mstat, pvm_reg_hoster, pvm_reg_rm, pvm_reg_tasker, pvm_start_pvmd Miscellaneouspvm_archcode, pvm_catchout, pvm_getopt, pvm_hostsync, pvm_notify, pvm_perror, pvm_setopt, pvm_settmask, pvm_tidtohostMqEG1ÿÿÿÿ¥GÿÿÿÿYGPVM in the WIN32 environmentC ÉFYG# €@€€‚ÿPVM in the WIN32 environment = G–G1‰ÿÿÿÿp‡¦–GÈG KInstallation2YGÈG# €€€‚ÿInstallation¬…–GtJ' € €€‚‚‚‚ÿPVM now comes with a self extracting executable which guides you through the installation. The wizzard asks for destination paths and directories for temporary data. Furthermore you can distinguish between a typical, a custom or administrative installation. The latter one is meant for configuring the daemon which is required for startup of other WIN32 hosts to your machine.Unlike earlier versions PVM uses the registry to store relevant information. Based on the installation and chosen compiler, a generic Makefile lets you recompile PVM on a dos-prompt bases. It is also possible to use the script for compiling your own applications.¬‡ÈG K% €€€‚‚ÿAn uninstall is simply done by choosing SYSTEM CONTROL, SOFTWARE and clicking on add/remove after highlighting the PVM 3.4 package.HtJhK1ØU„s§hK¥K ƒDifferences to UNIX PVM= K¥K# €4€€‚ÿDifferences to UNIX PVMçhKµM) €Ï€€‚‚‚‚‚‚ÿThere are differences in the implementation to the UNIX version, as well as differences between 9x and NT. PVM is switching during runtime to the correct WIN32 mode.The user on a WIN32 sees the difference in the pvm{l,d}. file instead of pvmd. used on UNIX hosts. This requires a WIN32 user to be logged onto the system ! If you see a pvm{l,d}.SYSTEM file your properties are not set up correctly.The more important changes are when starting up another WIN32 host.&¥KÛM# €€€‚ÿãµM €3 4€Ç€€ €ƒ€€‚‚‚‚‚‚ÿ·Before adding any WIN32 host make sure you installed a rshd or rexecd. In the pvm-shell (pvm.exe) you have to use the add command. Adding WIN32 hosts requires you to specify the location of the pvm daemon (including executable). A proper add command for a WIN32 box (using the same account, rsh-ing in) looks like: add "hostname dx=c:\pvm\pvm3\lib\win32\pvmd3.exe" for adding a NT box with a different login (using rexecd) you have to type: ÛM € K¬„ÛM¸€( € €€‚‚‚‚‚ÿ add "hostname dx=c:\pvm\pvm3\lib\win32\pvmd3.exe lo=yourlogin so=pw" so=pw is a fixed expression !Y. €+ &€\€dCPÈ:‚H€ €ƒ‚ÿ·Adding Unix machines is simply done by: øÁ¸€ ƒ7 <€ƒ€€‚‚‚‚‚ƒ‚ƒ‚‚‚‚‚‚ƒ‚‚‚‚‚ÿ add hostname Before you try to add other hosts you should check whether your rshd settings are correct. This is simply done by getting the content of the remote directory. Tryrsh remotehost -l yourlogin dir | moreIf this works you are ready to run PVM on your machines.If you like to fire up PVM with a hostfile, you have to provide the full path to the file:eg. pvm c:\users\markus\hostfile.txtN-Joy.4=ƒ1„ p‡ÿÿÿÿ¨=ƒfƒ¹FAQ) ƒfƒ# € €€‚ÿFAQ4=ƒš…- (€€€‚‚‚‚‚‚‚‚‚‚ÿ Frequently Asked Questions for Setting up PVM for WIN32 Installation For PC based systems running '95 or NT we now created an InstallShield which leads you through the installation. Environment variables are no longer used and PVM Keys are stored in the registry. Additional Software You are still required to install a rshd on WIN95-boxes, if you like to add them to your Virtual Machine. On WIN NT you can choose between rexecd or rshd. For simpleDfƒÞ‡* "€5€€‚‚‚‚‚‚‚ÿ testing you can try your permissions and proper installations in the MS-DOS prompt by getting the directory of the remote machine, rsh remotehost dir , for example. If this does not work you do not have a PVM problem and should contact your SysAdmin. However we are also working on distributing a rshd. This is currently working under "laboratory conditions". What Filesystems do I need ? When running NT you are required to use NTFS (security), with WIN95 you can use-š… Š, &€€€‚‚‚‚‚‚‚‚‚ÿ FAT32 or FAT. How do I add hosts to my machine ? Before adding any WIN32 host make sure you installed the additional software . In the pvm-shell (pvm.exe) you have to use the add command. Then, adding WIN32 hosts requires you to specify the location of the daemon (including executable) A proper add command for a WIN32 box (using the same account, rsh-ing in) looks like: add "hostname dx=c:\pvm\pvm3\lib\win32\pvmd3.exe" S Þ‡^Œ3 4€A€€‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚ÿ for adding a NT box with a different login (using rexecd) you have to type: add "hostname dx=c:\pvm\pvm3\lib\win32\pvmd3.exe lo=login so=pw" Adding Unix machines is simply done by: add hostname I can't establish rexec or rsh on my WIN machines ! On WIN NT you are required to be allowed to log on as a service. You'll find this in the user rights entries. You need to have administrative rights to perform the changes,T' вŽ- (€O€€‚‚‚‚‚‚‚‚‚‚ÿ though. You do not need any administrative rights to run PVM ! Where do I get proper rsh or rexec daemons for WIN32 ? There are several rexecd or rshd out there. But some or most of them do not follow the BSD specifications. We have good experiences with http://www.ataman.com. How do I set the environments properly ? Environment variables are no longer needed :-) What is a service pack ? Service packs are provided by MS ... for NT 3.51 you'll need service pack 5 or laterà^Œ¹' €Á€€‚‚‚‚ÿ for WIN95 service pack 1 ! What is a rshd or rexecd ... ? These daemons (rshd XOR rexecd) are required to fire up PVM. You need to install them on each machine you like to run PVM on. 1²Ž À1Uÿÿÿÿÿÿÿÿ©ÿÿÿÿ À0À¹ À¹$¹0À" €€€ ÿ1 Àÿÿÿÿ1ÿÿÿÿÿÿÿÿªÿÿÿÿÿÿÿÿÿÿÿÿêá hMS Sans SerifSystemFixedsysTerminalMS SerifCourierSymbolSmall FontsModernMarlettArial ) sU„z‰æ€€€€/&;)F24ÿÿCÿÿÿÿFAQInstallationIntroductionlibpvm3, libfpvm3 library pvm consolePVM Fortran InterfacePVM Message Passing Functionspvmd3 daemon/&;)Lzÿÿ«ÿÿIntroductionªPVM Introæpvm console€pvmd3 daemonz‰libpvm3, libfpvm3 library€PVM Message Passing Functions€ƒpvm_addhostshpvm_addmhf€pvm_adviseë†pvm_archcodeÛ‹pvm_barrier–pvm_bcast€pvm_bufinfo{†pvm_catchoutÐpvm_config× pvm_deleteð pvm_delhostsš…pvm_delinfow„pvm_delmhf—„pvm_exit‰‡pvm_exportÄ‹pvm_freebufÄpvm_freecontextípvm_freezegroup‚pvm_gatheræ pvm_getcontext pvm_getfds– pvm_getinstÉ„ pvm_getmboxinfoï„ pvm_getmwid… pvm_getoptìŠ pvm_getrbufy pvm_getsbuf¹ pvm_gettidÉ pvm_gettmaskí pvm_gsizeÜ pvm_halt”€ pvm_hostsyncq† pvm_initsendp pvm_insert{ pvm_joingroupP pvm_killq… pvm_lookupóˆ pvm_lvgroup^ pvm_mcast pvm_mkbuf°‡ pvm_mstat pvm_mytid« pvm_newcontextn pvm_notifyXŠ pvm_nrecvþpvm_pk*“pvm_parent‘pvm_perrorB pvm_precvWpvm_probeˆpvm_psend݇pvm_pstatŸŠpvm_putinfoÁˆpvm_recvLpvm_recvf€pvm_recvinfo#€pvm_reduce‰pvm_reg_hoster[†pvm_reg_rmŠpvm_reg_taskerÄ pvm_scatter‰pvm_sendÇpvm_sendsig±pvm_serror€pvm_setcontext(€pvm_setmwidÁ„pvm_setopt ‚pvm_setrbuf°‡pvm_setsbufpvm_settmaskê pvm_siblingso†pvm_spawn€pvm_start_pvmdn†pvm_tasks pvm_tidtohostkpvm_trecv-…pvm_unexportO…pvm_unpk*€€PVM Fortran Interface\pvmfaddhosts€pvmfaddmhf pvmfadviseÀpvmfarchcodeäpvmfbarrier‚pvmfbcast$‚pvmfbufinfoF‚pvmfcatchoutj‚pvmfconfigŠ‚pvmfdeleteª‚pvmfdelhosts΂pvmfdelinfoð‚pvmfdelmhfƒpvmfexit,ƒpvmfexportLƒpvmffreebufnƒpvmffreecontext˜ƒpvmffreezegroupƒpvmfgatherâƒpvmfgetcontextpvmfgetfds7pvmfgetinstZpvmfgetmboxinfo„pvmfgetmwid¦pvmfgetoptÆpvmfgetrbufèpvmfgetsbuf pvmfgettid*pvmfgettmaskNpvmfgsizelpvmfhaltˆpvmfhostsync¬pvmfinitsendÐpvmfinsertðpvmfjoingrouppvmfkill3pvmflookupSpvmflvgroupupvmfmcast“pvmfmkbuf±pvmfmstatÏpvmfmytidA,ÿÿípvmfnewcontextpvmfnotify€pvmfnrecv1€pvmfparentQ€pvmfperrorq€pvmfprecv€pvmfprobe­€pvmfpsendË€pvmfpstaté€pvmfputinfo pvmfrecv'pvmfrecvfEpvmfrecvinfoipvmfreduce‰pvmfreghoster°pvmfregrmÏpvmfregtaskeröpvmfscatter‚pvmfsend4‚pvmfsendsigV‚pvmfserrorv‚pvmfsetcontextž‚pvmfsetmwidÀ‚pvmfsetoptà‚pvmfsetrbufƒpvmfsetsbufpvmfsettmask$pvmfsiblingsHpvmfspawnfpvmfstartpvmdpvmftasks«pvmftidtohostÑpvmftrecvïpvmfunexportpvmfunpk*Glossary*PVM Error CodesList of PVM Calls5„PVM in the WIN32 environmentU„Installationp‡Differences to UNIX PVMsFAQ €pvm_killq… pvm_lookupóˆ pvm_lvgroup^ pvm_mcast pvm_mkbuf°‡ pvm_mstat pvm_mytid« pvm_newcontextn pvm_notifyXŠ pvm_nrecvþpvm_pk*“pvm_parent‘pvm_perrorB pvm_precvWpvm_probeˆpvm_psend݇pvm_pstatŸŠpvm_putinfoÁˆpvm_recvLpvm_recvf€pvm_recvinfo#€pvm_reduce‰pvm_reg_hoster[†pvm_reg_rmŠpvm_reg_taskerÄ pvm_scatter‰pvm_sendÇpvm_sendsig±pvm_serror€pvm_setcontext(€pvm_setmwidÁ„pvm_setopt ‚pvm_setrbuf°‡pvm_setsbufpvm_settmaskê pvm_siblingso†pvm_spawn€pvm_start_pvmdn†pvm_tasks pvm_tidtohostkpvm_trecv-…pvm_unexportO…pvm_unpk*€€PVM Fortran Interface\pvmfaddhosts€pvmfaddmhf pvmfadviseÀpvmfarchcodeäpvmfbarrier‚pvmfbcast$‚pvmfbufinfoF‚pvmfcatchoutj‚pvmfconfigŠ‚pvmfdeleteª‚pvmfdelhosts΂pvmfdelinfoð‚pvmfdelmhfƒpvmfexit,ƒpvmfexportLƒpvmffreebufnƒpvmffreecontext˜ƒpvmffreezegroupƒpvmfgatherâƒpvmfgetcontextpvmfgetfds7pvmfgetinstZpvmfgetmboxinfo„pvmfgetmwid¦pvmfgetoptÆpvmfgetrbufèpvmfgetsbuf pvmfgettid*pvmfgettmaskNpvmfgsizelpvmfhaltˆpvmfhostsync¬pvmfinitsendÐpvmfinsertðpvmfjoingrouppvmfkill3pvmflookupSpvmflvgroupupvmfmcast“pvmfmkbuf±pvmfmstatÏpvmfmytidôí/&;)L4ÿÿ©°©ÿÿÿÿƒ}ƒ$P±\…äy·s†Äì1–†#€Ú*™†[†”‚*މFj±¿lÁ„èúxïвđ€€˜û‘˜ƒM%“3œ£½•J¶˜Î‚—μ˜ö‚¡™ÿ­A›€j‘¸œÀ´\±¤Ùk¦ª‚®c¤©€BáÕ¬4‚«÷­«t鮞‚¬d®à‚?› ®ƒ„”Z³€ƒÅÕZ³1€—Þ+´Q€v‹¯¾F‚¶ê§Äˆ0‰JÅÉ„ M¡Åióe[Êæ æƒÊ‰ÉÔèË*ÈauÎV‚p¹wÎÀ‚&€îÏé€b@rÑU„T•ˆÓâƒæš`×ð}$áæÆ$«æq† €è¹é€ºQÖê• îÛ‹àækñh*¢ñ€*õòSßäóó–©øuôŠj^ õí ñnõªzº1ö^ “v;ö ß©Eö°‡ ™òLö ›®tö€þ1xöXŠ `‡àö€^ÏàöWº¿áöˆò)âö݇ú 9÷L½€z÷o†Ôøœ÷n†$2±÷k;Óà÷O…Ú½úLƒ$·Kþfâ¡sG£Øš…Ü'ßÄ ‘5áp‡ùª°7ˆÄµ„À?»ÆSv¼èL<ÐT R£díÆG €í•• \•ó × ZIó w„Ĭ nƒ‡:øÇ¹B<(€ñ½A ‚„ôB°‡²Šš‰‡pu#—„‹x#Ü î{#P ¬M„#Áˆ†…#‰©’J%ƒÄM%l=nQ%åÍY% ?[%‚ͱu%‚õMF& ûF&… Û³F&¹ —B,ê  Ùµ-z‰‘w0€C^w0{ Û½Œ0 ûùÚ0ϺT2$‚ù=8-…kÙ9ŸŠ3ê 9p /&æ=¬m»?rnÐB‚ýçèCNýGDj‚ DEu&E“r3"E±,|)EÏ‘»TE€}Eë†ó½Eq€ñX½E€MI¾E­€…³¾EË€•F'̱F°P WFHg‚yF·»FÑÎ\½FF-þJŠ‚ eþJð‚f¹ÿN5„®×0Oð {~áOZwa’S€œéTq… c¦¥W,ƒGB³W*om\óˆ Ø¿\v‚/‚aEéZb« E3àc~Í€dƒ¦iQe¬¬Qe¦ŒÏQe A¦en Štg{†JŠ2kíýkþMélm”€ >Óm– ÍØmï„ ™ÝmìŠ ˜ÏÞmy ºOt“`Ó­tÉ æÂ u‘ä¬xÐí ä lpp ˆ3ŽŽ â œ …‚ ‡ Ù Ä %…÷€ÿ„ÿ€1…4‹5œ C ̃]‚„Ù Ä (‚]ƒ‚´ €ÿƒ€ÿ2AAAAAAAA&‚Š &… &‚… &‚… & & & & & …ƒ "‚ ‹‚ " '"$""#"‚ ""…""  "!ƒ „"  " ƒ33„" "‚ 3…" "‚  3… ""‚ ƒ 3"ƒ"‚ ‚  30" "‚ ‡" "  3"3ƒ0" ˆ""   3…"" 3ƒ0"‚"„  3†" 30„330"Œ"" "   3‚0 … 3"…330""" "" "  30ƒ 0"3‚" """""  30ƒ" "3‚0"Œ "" 3""  30ƒ""" 3‚" " " 30""  30„"" "3‘0" " " "00""  30„" "‚ 3" ""00""  3‚0 „"" "‚" 3" " 300""  3‚0 ‹"" 30"3‘0"" " 3030""  3‚0"‚""3‚0"‚ 3’0" " "330"" "  3Š0" "" 3‚0" 3’0" ""330"" ""  30"‚ 30"30" " 3330"" " 3"‚  3"† 33" Š" 30330"" " 30 3–"" 33" "30330"" "3‰0"" 3"Š"3330"" " 3‚03•0"" "" 33330"" "3†"3Œ0"" " 303„0"" "3" 3‰0" "303„0"" "30"3‚0"ƒ33„0"" "3" 3† 333„0"" "30 "3ƒ303„0"" "3 "303„0"" "3ƒ0"ƒ 303…" "3‚ "ƒ"303‚""30‚ "3030"" 30"3030"" 3"303„"" "ƒ30"„ "303„"" "„330"„ "3„0330"" ‚0"„"3‡0330"" " ‚0 †"3‡033"" "‚ ƒ33‚ ‚3‡033"""‚ ‚3 …" 3ƒ030"…"" ‚0 „" 3Š30"" "" „330 ƒ"3‰3"""" ‚0 ƒ" 3ˆ3""" ‚3 ‚ 3‡0"" " ƒ33 ‚3‡00"" 3 3†0"" „330 3†" „3303†"" 33„3‚333 3#30&3„0) 3„0, 3„0/3„023„05†308ƒ;AAAAAAAƒ+z+lpÚ2ã )˶VŽ Êr¤p…‚  - 4÷á …ááÁœ›œœ••á—E*L#7à.à:ááp\…4‹5¤pC Ì„sì„- 4(…ìsƒ‚Ý ƒá …ááÁœœœ›á••*E—#L.à7:àpááMnnƒj…j…j…j…j…j…j…j…j…j‡    ‚                 ‚   !…  ‚      … „„‚„ƒ‚„ ‚„„‚„…  ‚ ƒ‚‚‚‚  …‚ ‚‚‚‚ …‚„‚ ƒ‚‚‚‚…ƒ ƒ ‚‚ ƒ‚ƒ„‚ ƒ ‚‚%…‚ ‚‚‚‚ ‚‚„‚ ‚ ‚‚‚&…  ‚ ‚ ‚  †…  ‚‚… † †‚‚ ‚  ‚††… † ‚‚‚… …‚„ …‚…† ‚‚‚…„„‚„ ‚„…† „ƒ„…‚ƒ‚… ‚ƒ‚ ‚ƒ…‚‚‚‚† ‚‚ ‚ƒ‚ ‚‚‚…‚‚‚„‚ ƒ„  ‚…‚ ‚‚‚ƒ ‚‚ ‚‚‚ ‚‚  …   ‚ ƒ  ‚  ƒ …‚A‚„ 4 2K…@‚‚‚31J…?‚ 1 ‚/H‡E   ‚6    4H…D   S  1H…   k  KI…j…j…j…j…j…j…j…j…j…* 8…# 2…   0…  -…C ) "  ,…<    +…:     "‚ *…8     %‚ )…6    ‚ (‚ (…5   . († &‚ # " 6‚  ˆ $    Š ‚#‚ ‚ ‚ Œ ‚"‚  ‚ Œj‚  ‚ ‚jŒj‚ ‚  ‚ ‚jŒj‚ ‚‚ ‚ ‚ ‚jŒj‚‚‚  ‚‚jŒ D‚‚‚ ‚ ‚‚D Œ ?‚‚ ‚ ‚‚? Œ ; †‚ ‚ † ; Œ‚ ‚9„‚  „9‚ ‚‚ƒ‚0„‚  ‚ „0‚ƒ …‚.„ %‚ ‚ „.‚„   ‚ ‚ ‚,„‚  '‚   „,‚ ‚ …  †† ‚*„‚   ƒ‚   ‚*‚ …†  ‚‚‚ ƒ ‚(„‚ !ƒ ‚(‚ ‚‚‚  ‚  ƒ ‰‚  "ƒ‚ „‰ ƒ  ‚‚  ‚„ „ ‚ ‰„ ‚ #‚+„‰ ‚„ ‚ ‚  ƒ ‚Œ‚‰… # +„‰‚‰‚ ‚†   ‚… ‚ ‡ ‚‰„ # +„‰‚‡   ƒ‚  ‚‚ ‚ ‡ ‚‰„(!  +„‰‚ †  †‚  ‚ ‹ „(! ‚ +„‹  ƒ‚  ‰‚ † ƒ‚Œ„(  „‚+„Œ ƒƒ … ‚‰ƒ  ƒ‚ ‚ Œ  …„(  ‚+„… ‚Œ  ‚ ‚ƒ   ‚„ ‰  ‚ “„( ƒƒ ‚‚+„“ ‚ˆ „ ‚    ‰ …  ‚”„(   ‚ ‚+„”‚ …‰     ‰  ”„(  ‚‚+„”ˆ    ‚ ƒ…  ”„(‚ „+„” … ‚    …  ˆ‰„(   ‚ ƒ+„‰ˆˆ  ‚    …  ”„(‚  ƒ ƒ+„” …        “„(  ƒ …+„“      ƒ‚'  Œ„( …ƒ +„Œ ' ‚ƒ  ‚ƒ' Œ„(  ‚ƒ+„Œ& ‚   '  ‹ „(   ‚ƒ +„ ‹&    ƒ'  Œ  „(     +„   & „  '  ‹  „(      +„  ‹ & ‚   '  ‚  „(   ‚   +„ ‘ ‚ & ‚  ‚(  ˆ‚ „'    ‚    ‚+„ ‚ ˆ ' ‚   ' ˆ ‚ „$   *„ ‚ ˆ'   ' „‚‰ ‚ …#    )… ‚ ‰‚„' „  ƒ' „‚ ‚ ƒ(   &ƒ ‚ ‚„( ƒ  ) „ ‚ ƒ'   &‚ ‚ „)   + ƒ‚ ‚ ‚M‚ ‚ ‚ƒ*   , ‚ ‚ ‚M‚ ‚ ‚,   ‚* ƒ‚ ‚ ‚‚M‚‚ ‚ ‚‚+ ‚ , +‚ ‚ ‚M‚ ‚ ‚* ,  9‚ ‚M‚ ‚9   H‚ ‚ ‚M‚ ‚ ‚G   W‚  ‚M‚  ‚V  e ‚M‚ e ‚M‚ Œ ‚M‚ Œ ‚M‚ Œ ‚M‚ Œ ‚M‚ Œ ‚M‚ Š M ˆ M …nnãÚ×ÍÆš‚]`®W â œ   Ù Ä %÷€€€ÿÿÿÿ€45œ C Ì]‚Ù Ä (‚]´€€€ÿÿÿ€ÿ""""""""""" """"""""""""""""""" """"""""" """""""""" """""""""""33" """""""""""" 3333333"""""""""""""" 33333333333 """"""""""""" 333333333333""""""""""""  333333333330"""" """"""" " " 33333333333""""3330"""""" ""  33333333333"" 333330"""""""" 33333333333" 30330""""""" " 33333333330  3"""330""""""" "" " 33333333330 0""""""333"""""" """"" 33333333330" """""""3330"""""" "" 3"" 33333333330"""""""""" 33333""" " " 30"" 33333333330"""""""""""333330" " " "00"" 33333333330" """"""""" 333333" ""00"" 33333333330 "" """""""" 3333333" " 300"" 33333333330 "" 30""""333330"" " 3030"" 33333333330"""33330""" 33330" " "330"" " 33333333330" "" 33333330""" 33330" ""330"" "" 33333333330""""""3333333330""""3330" " 3330"" """33333333333"""" 33333333333""" 33" " 30330"" """"3333333333303333333333333"" 33" "30330"" """""3333333333333333333333333333330"" 3""3330"" """""3333333330333333333333333333330"" "" 33330"" """""33333333"33333333333333333330"" " 303330"" """""3333333""""" 33333333333333333333330" "303330"" """""3333330"""""""33333333333333333333330"""33330"" """""333333""""""" 333333333333333333333333 333330"" """""333330"""""""""33333333333333333333333333033330"" """""33333"""""""""333333333333333333333333333033330"" """""33330"""""" 33333333333333333333333333303333" "3333 """""33333333333333333333333333303333"""""3330 """"""33333333333333333333333333303330""""""" 3330"""""""33333333333333333333333333303330""""""" 333"""""""3333333333333333333333333330333"" """""30"""" "3333333333333333333333333330333"" """""330"""" "3333333333333333333333333330330""""""" 0""""3333333333333333333333333330330"" """"" 0"333333333333333333333333333033"" """" 33 333333333333333333333333333033""""" 3" 3333333333333333333333333333030""""" 0" 333333333333333333333333333330"" "" 330"33333333333333333333333333333""""0" 33333333333333333333333333333"""3 333333333333333333333333333330"" "33333333333333333333333333333300""333333333333333333333333333333330""33033333333333333333333333333333" 33033333333333333333333333333"" 333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333330333333333333333303333333333333033333333330333333303333030³åªå×ÍÆšìs`îV Êr¤p  - 4÷ááá ááÁÁÁ›œœ••á—E*L#7à.à:ááp45¤pC Ìsì- 4(ìsÝááá ááÁÁÁœœ›á••*E—#L.à7:àpáá                                                                                                                                                                                                                                                        ./pvm3/misc/0042755007401100000360000000000010117676455012054 5ustar kohlgopher./pvm3/misc/group-hack-3370100644007401100000360000001151406221607256014340 0ustar kohlgopher*** ../../netlib/pvm3.3.7/src/lpvm.c Tue Feb 07 15:16:11 1995 --- lpvm.c Mon May 15 14:17:06 1995 *************** *** 1971,1976 **** --- 1971,1977 ---- char buf[16]; /* for converting sockaddr */ char *p; int x; + int gid; /* pvm_setopt(PvmDebugMask, -1); *************** *** 2033,2038 **** --- 2034,2045 ---- pvmlogerror("pvmbeatask() can't creat t-auth file\n"); cc = PvmSysErr; goto bail2; + } + if ((gid = pvmgetugid()) != -1) { + if (fchown(authfd, -1, gid) == -1) + pvmlogperror("pvmbeatask() can't chown t-auth file"); + if (fchmod(authfd, 0660) == -1) + pvmlogperror("pvmbeatask() can't chmod t-auth file"); } sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); *** ../../netlib/pvm3.3.7/src/pvmcruft.c Wed Nov 09 10:58:42 1994 --- pvmcruft.c Mon May 15 14:37:16 1995 *************** *** 66,71 **** --- 66,72 ---- #include #define CINDEX(s,c) index(s,c) #endif + #include #include "global.h" #include "protoglarp.h" #include "pvmalloc.h" *************** *** 458,463 **** --- 459,465 ---- char hna[128]; char *p; + int gid; #ifdef SHAREDTMP if (gethostname(hna, sizeof(hna)-1) == -1) { *************** *** 466,477 **** } if (p = CINDEX(hna, '.')) *p = 0; ! (void)sprintf(buf, TDSOCKNAME, pvm_useruid, hna); #else ! (void)sprintf(buf, TDSOCKNAME, pvm_useruid); #endif return buf; } --- 468,515 ---- } if (p = CINDEX(hna, '.')) *p = 0; ! if ((gid = pvmgetugid()) != -1) { ! (void)sprintf(buf, TDSOCKGNAME, gid, hna); ! else ! (void)sprintf(buf, TDSOCKNAME, pvm_useruid, hna); #else ! if ((gid = pvmgetugid()) != -1) ! (void)sprintf(buf, TDSOCKGNAME, gid); ! else ! (void)sprintf(buf, TDSOCKNAME, pvm_useruid); #endif return buf; } + + + int + pvmgetugid() + { + static int gid = -2; + + char *p; + struct group *ge; + char buf[128]; + + if (gid == -2) { + gid = -1; + if (p = getenv("PVM_GID")) { + if (isdigit(*p)) + return (int)atoi(p); + + if (ge = getgrnam(p)) + gid = ge->gr_gid; + else { + sprintf(buf, "pvmgetugid() can't lookup group \"%s\"\n", p); + pvmlogerror(buf); + } + endgrent(); + } + } + + return gid; + } + *** ../../netlib/pvm3.3.7/src/startup.c Tue Feb 07 15:16:13 1995 --- startup.c Mon May 15 14:20:43 1995 *************** *** 242,247 **** --- 242,248 ---- char spath[LEN_OF_TMP_NAM]; /* local socket path */ struct sockaddr_un uns; #endif + int gid; /* * make pvmd-pvmd socket *************** *** 395,400 **** --- 396,407 ---- } } else { + if ((gid = pvmgetugid()) != -1) { + if (fchown(d, -1, gid) == -1) + pvmlogperror("mksocs() can't chown address file"); + if (fchmod(d, 0640) == -1) + pvmlogperror("mksocs() can't chmod address file"); + } cc = write(d, p, strlen(p)); if (cc != strlen(p)) { if (cc == -1) { *** ../../netlib/pvm3.3.7/src/tdpro.c Wed Nov 09 10:58:44 1994 --- tdpro.c Mon May 15 14:20:54 1995 *************** *** 106,111 **** --- 106,113 ---- ** ** ***************/ + char *getenv(); + extern void task_dump(); char *debug_flags(); char *inadport_hex(); *************** *** 298,303 **** --- 300,306 ---- char authfn[LEN_OF_TMP_NAM]; /* t-auth file name */ int d; int cc; + int gid; if (upkint(mp, &ver) || upkstr(mp, authfn, sizeof(authfn))) { pvmlogerror("tm_connect() bad msg format\n"); *************** *** 345,356 **** tp->t_authnam = TALLOC(LEN_OF_TMP_NAM, char, "auth"); (void)TMPNAMFUN(tp->t_authnam); ! if ((tp->t_authfd = open(tp->t_authnam, O_RDONLY|O_CREAT|O_TRUNC, 0600)) ! == -1) { pvmlogperror("tm_connect() can't create d-auth file"); PVM_FREE(tp->t_authnam); tp->t_authnam = 0; goto bail; } /* --- 348,364 ---- tp->t_authnam = TALLOC(LEN_OF_TMP_NAM, char, "auth"); (void)TMPNAMFUN(tp->t_authnam); ! if ((tp->t_authfd = open(tp->t_authnam, O_RDONLY|O_CREAT|O_TRUNC, 0600)) == -1) { pvmlogperror("tm_connect() can't create d-auth file"); PVM_FREE(tp->t_authnam); tp->t_authnam = 0; goto bail; + } + if ((gid = pvmgetugid()) != -1) { + if (fchown(tp->t_authfd, -1, gid) == -1) + pvmlogperror("tm_connect() can't chown d-auth file"); + if (fchmod(tp->t_authfd, 0660) == -1) + pvmlogperror("tm_connect() can't chmod d-auth file"); } /* *** ../../netlib/pvm3.3.7/src/tdpro.h Fri Jun 03 16:38:32 1994 --- tdpro.h Mon May 15 14:32:25 1995 *************** *** 59,66 **** --- 59,68 ---- #ifdef SHAREDTMP #define TDSOCKNAME "/tmp/pvmd.%d.%s" /* file with task->pvmd sockaddr */ + #define TDSOCKGNAME "/tmp/pvmd.g%d.%s" /* file with task->pvmd sockaddr */ #else #define TDSOCKNAME "/tmp/pvmd.%d" /* file with task->pvmd sockaddr */ + #define TDSOCKGNAME "/tmp/pvmd.g%d" /* file with task->pvmd sockaddr */ #endif #define TM_FIRST 0x80010001 /* first TM_ message */ ./pvm3/misc/pvm_fork.c0100644007401100000360000000430706360711202014023 0ustar kohlgopher /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * pvm_fork.c * * In the spirit of fork(), fork a process and enroll it as a new PVM task. * If parent, returns task id (>0) of child, or error (<0). * If child, returns 0. */ #ifdef IMA_TITN #include #endif #include int pvm_fork(cpid) int *cpid; /* cpid returns child pid if nonnull */ { int tid; /* tid to return (child tid or 0) */ int pid; int pfd[2]; if ((tid = pvm_mytid()) > 0) { if ( #ifdef IMA_TITN socketpair(AF_UNIX, SOCK_STREAM, 0, pfd) #else pipe(pfd) #endif == -1) tid = PvmOutOfRes; else if (pid = fork()) { /* parent */ close(pfd[1]); if (cpid) *cpid = pid; if (pid == -1) tid = PvmOutOfRes; else if (read(pfd[0], (char *)&tid, sizeof(tid)) != sizeof(tid)) tid = PvmOutOfRes; close(pfd[0]); } else { /* child */ close(pfd[0]); pvmendtask(); tid = pvm_mytid(); write(pfd[1], (char *)&tid, sizeof(tid)); close(pfd[1]); tid = 0; } } return tid; } ./pvm3/misc/Readme0100644007401100000360000000220006221607254013151 0ustar kohlgopher misc directory 09 October 1995 ________________________________________________________________________ This directory contains a bunch of random PVM-related programs and utilities. They're here because they might be generally useful, but I don't want to kill myself supporting them. Like the "examples", even less official. pvm_fork.c This is an implementation of pvm_fork(), a function to fork a new PVM task from an existing PVM task. xhoster/ This is a little X-Windows program that enrolls as the hoster task, giving the user a convenient place to type passwords when starting hosts that require them. group-hack-337 This is a patch to PVM version 3.3.7 to allow access to the virtual machine to anyone in a unix group. If environment variable PVM_GID is set to the name or number of a group, sockets and files are chown'd to that group and mode 0660 is used instead of 0600. Note that all spawned processes have the same user id as the pvmd, so this isn't a true multi-user virtual machine. This is seen as being useful mainly for allowing e.g. a group of people access to a database, or display or instrument server. ./pvm3/misc/xhoster/0042755007401100000360000000000010117676455013550 5ustar kohlgopher./pvm3/misc/xhoster/Imakefile0100644007401100000360000000042006313340252015332 0ustar kohlgopher SRCS = xhoster.c hostc.c OBJS = xhoster.o hostc.o CCOPTIONS = -I$(PVM_ROOT)/include -I$(PVM_ROOT)/src -DIMA_$(PVM_ARCH) $(ARCHCFLAGS) EXTRA_LOAD_FLAGS = -L$(PVM_ROOT)/lib/$(PVM_ARCH) EXTRA_LIBRARIES = -lXaw -lXt -lXmu -lXext -lX11 -lpvm3 ComplexProgramTarget(xhoster) ./pvm3/misc/xhoster/Makefile0100644007401100000360000003364306313340253015177 0ustar kohlgopher# Makefile generated by imake - do not edit! # $XConsortium: imake.c,v 1.65 91/07/25 17:50:17 rws Exp $ # ------------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and # $XConsortium: Imake.tmpl,v 1.139 91/09/16 08:52:48 rws Exp $ # # From the Alpha Imakefile # Platform-specific parameters may be set in the appropriate .cf # configuration files. Site-specific parameters should be set in the file # site.def. Full rebuilds are recommended if any parameters are changed. # # If your C preprocessor does not define any unique symbols, you will need # to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing # "make World" the first time). # # ------------------------------------------------------------------------- # site-specific configuration parameters that need to come before # the platform-specific parameters - edit site.def to change # site: $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $ # ------------------------------------------------------------------------- # platform-specific configuration parameters - edit osf1.cf to change # platform: osf1.cf # Operating system: 1/1 3.2 SHAREDSWITCH = # Using 1 shared library rules # ------------------------------------------------------------------------- # site-specific configuration parameters that go after # the platform-specific parameters - edit site.def to change # site: $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $ SHELL = /bin/sh TOP = . CURRENT_DIR = . AR = ar cqls LOCAR = ar clq BOOTSTRAPCFLAGS = CC = cc $(SHAREDSWITCH) LOCCC = cc LOCSHARCC = LocShareCcCmd AS = as COMPRESS = compress CPP = /lib/cpp $(STD_CPP_DEFINES) PREPROCESSCMD = cc $(SHAREDSWITCH) -E $(STD_CPP_DEFINES) INSTALL = /usr/bin/X11/install.sh LD = ld LINT = lint LINTLIBFLAG = -o LINTOPTS = -ax LN = ln -s MAKE = make MV = mv CP = cp RM = rm -f TROFF = psroff MSMACROS = -ms TBL = tbl EQN = eqn STD_INCLUDES = LOCSTD_INCLUDES = STD_CPP_DEFINES = -DDEC -DR5_XLIB -DSMT STD_DEFINES = -DDEC -DR5_XLIB -DSMT EXTRA_LOAD_FLAGS = EXTRA_LIBRARIES = LOCEXTRA_LIBRARIES = TAGS = ctags SHAREDCODEDEF = -DSHAREDCODE SHLIBDEF = PROTO_DEFINES = -DFUNCPROTO=3 INSTPGMFLAGS = -s INSTBINFLAGS = -m 0755 INSTUIDFLAGS = -m 4755 INSTLIBFLAGS = -m 0644 INSTINCFLAGS = -m 0444 INSTMANFLAGS = -m 0444 INSTDATFLAGS = -m 0444 INSTKMEMFLAGS = -m 4755 CDEBUGFLAGS = -O2 -Olimit 2000 CCOPTIONS = LOCCCOPTIONS = ALLINCLUDES = $(INCLUDES) $(EXTRA_INCLUDES) $(TOP_INCLUDES) $(STD_INCLUDES) LOCALLINCLUDES = $(INCLUDES) $(EXTRA_INCLUDES) $(TOP_INCLUDES) $(LOCSTD_INCLUDES) ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(EXTRA_DEFINES) $(PROTO_DEFINES) $(DEFINES) LOCALLDEFINES = $(LOCALLINCLUDES) $(STD_DEFINES) $(EXTRA_DEFINES) $(PROTO_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES) LOCCFLAGS = $(CDEBUGFLAGS) $(LOCCCOPTIONS) $(LOCALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES) LDLIBS = $(SYS_LIBRARIES) $(EXTRA_LIBRARIES) LOCLDLIBS = $(SYS_LIBRARIES) $(LOCEXTRA_LIBRARIES) LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS) $(LOCAL_LDFLAGS) LOCLDOPTIONS = $(CDEBUGFLAGS) $(LOCCCOPTIONS) $(LOCAL_LDFLAGS) LDCOMBINEFLAGS = -X -r DEPENDFLAGS = -D__alpha -D__osf__ -I -I$(CROSSBASE)/usr/include MACROFILE = osf1.cf RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut IMAKE_DEFINES = IRULESRC = $(CONFIGDIR) IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES) ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules \ $(IRULESRC)/Project.tmpl $(IRULESRC)/site.def \ $(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES) # ------------------------------------------------------------------------- # X Window System Build Parameters # $XConsortium: Project.tmpl,v 1.142 92/01/25 16:44:02 rws Exp $ # ------------------------------------------------------------------------- # X Window System make variables; this need to be coordinated with rules PATHSEP = / USRLIBDIR = /usr/lib BINDIR = /usr/bin/X11 INCROOT = /usr/include BUILDINCROOT = $(TOP) BUILDINCDIR = $(BUILDINCROOT)/X11 BUILDINCTOP = .. INCDIR = $(INCROOT)/X11 ADMDIR = /usr/adm LIBDIR = $(USRLIBDIR)/X11 VARDIR = /usr/var/X11 CONFIGDIR = $(LIBDIR)/config LINTLIBDIR = $(USRLIBDIR)/lint FONTDIR = $(LIBDIR)/fonts USERFONTDIR = $(VARDIR)/fonts/user FSDIR = $(VARDIR)/fs XINITDIR = $(LIBDIR)/xinit XDMDIR = $(VARDIR)/xdm TWMDIR = $(LIBDIR)/twm MANPATH = /usr/man MANSOURCEPATH = $(MANPATH)/man MANSUFFIX = n LIBMANSUFFIX = 3 MANDIR = $(MANSOURCEPATH)$(MANSUFFIX) LIBMANDIR = $(MANSOURCEPATH)$(LIBMANSUFFIX) NLSDIR = $(LIBDIR)/nls PEXAPIDIR = $(LIBDIR)/PEX XAPPLOADDIR = $(LIBDIR)/app-defaults FONTCFLAGS = -t INSTAPPFLAGS = $(INSTDATFLAGS) IMAKE = imake DEPEND = makedepend RGB = rgb FONTC = bdftopcf MKFONTDIR = mkfontdir MKDIRHIER = /bin/sh $(BINDIR)/mkdirhier CONFIGSRC = $(TOP)/config DOCUTILSRC = $(TOP)/doc/util CLIENTSRC = $(TOP)/clients DEMOSRC = $(TOP)/demos LIBSRC = $(TOP)/lib FONTSRC = $(TOP)/fonts INCLUDESRC = $(TOP)/X11 SERVERSRC = $(TOP)/server UTILSRC = $(TOP)/util SCRIPTSRC = $(UTILSRC)/scripts EXAMPLESRC = $(TOP)/examples CONTRIBSRC = $(TOP)/../contrib DOCSRC = $(TOP)/doc RGBSRC = $(TOP)/rgb DEPENDSRC = $(UTILSRC)/makedepend IMAKESRC = $(CONFIGSRC) XAUTHSRC = $(LIBSRC)/Xau XLIBSRC = $(LIBSRC)/X XMUSRC = $(LIBSRC)/Xmu TOOLKITSRC = $(LIBSRC)/Xt AWIDGETSRC = $(LIBSRC)/Xaw OLDXLIBSRC = $(LIBSRC)/oldX XDMCPLIBSRC = $(LIBSRC)/Xdmcp BDFTOPCFSRC = $(FONTSRC)/clients/bdftopcf MKFONTDIRSRC = $(FONTSRC)/clients/mkfontdir FSLIBSRC = $(FONTSRC)/lib/fs FONTSERVERSRC = $(FONTSRC)/server EXTENSIONSRC = $(TOP)/extensions XILIBSRC = $(EXTENSIONSRC)/lib/xinput XTESTLIBSRC = $(EXTENSIONSRC)/lib/xtest XTRAPLIBSRC = $(EXTENSIONSRC)/lib/xtrap PHIGSLIBSRC = $(EXTENSIONSRC)/lib/PEX XIELIBSRC = $(EXTENSIONSRC)/lib/XIE EXTINCSRC = $(TOP)/X11/extensions USRSHLIBDIR = /usr/shlib XSHLIBDIR = /usr/shlib/X11 SHLIBFLAGS = -check_registry $(CROSSBASE)/usr/shlib/so_locations -L$(CROSSBASE)/usr/shlib -L$(CROSSBASE)/usr/ccs/lib DEPEXTENSIONLIB = $(USRSHLIBDIR)/libXext.so EXTENSIONLIB = -lXext DEPXLIB = $(DEPEXTENSIONLIB) $(USRSHLIBDIR)/libX11.so XLIB = -lXext -lX11 DEPXMULIB = $(USRSHLIBDIR)/libXmu.so XMULIB = -lXmu DEPOLDXLIB = $(USRSHLIBDIR)/liboldX.so OLDXLIB = -loldX DEPXTOOLLIB = $(USRSHLIBDIR)/libXt.so XTOOLLIB = -lXt DEPXAWLIB = $(USRSHLIBDIR)/libXaw.so XAWLIB = -lXaw DEPXXIELIB = $(USRSHLIBDIR)/libXIE.so XXIELIB = -lXIE DEPXILIB = $(USRSHLIBDIR)/libXi.a XILIB = -lXi DNETLIB = -ldnet_stub SOXLIBREV = SharedXlibRev SOXTREV = SharedXtRev SOXAWREV = SharedXawRev SOXIEREV = SharedXIERev SOOLDXREV = SharedOldXRev SOXMUREV = SharedXmuRev SOXEXTREV = SharedXextRev SOXINPUTREV = SharedXinputRev SOXTESTREV = SharedXTestRev SOXTRAPREV = SharedXTrapRev DEPXAUTHLIB = $(USRLIBDIR)/libXau.a XAUTHLIB = -lXau DEPXDMCPLIB = $(USRLIBDIR)/libXdmcp.a XDMCPLIB = -lXdmcp DEPXTESTLIB = $(USRLIBDIR)/libXtst.a XTESTLIB = -lXtst DEPXTRAPLIB = $(USRLIBDIR)/libXTrap.a XTRAPLIB = -lXTrap DEPPHIGSLIB = $(USRLIBDIR)/libphigs.a PHIGSLIB = -lphigs DEPACCESSXLIB = $(USRLIBDIR)/libAccessX.a ACCESSXLIB = -lAccessx DEPACCESSXLIB = $(USRLIBDIR)/libAccessX.a ACCESSXLIB = -lAccessx DEPXBSDLIB = $(USRLIBDIR)/libXbsd.a XBSDLIB = -lXbsd LINTEXTENSIONLIB = $(LINTLIBDIR)/llib-lXext.ln LINTXLIB = $(LINTLIBDIR)/llib-lX11.ln LINTXMU = $(LINTLIBDIR)/llib-lXmu.ln LINTXTOOL = $(LINTLIBDIR)/llib-lXt.ln LINTXAW = $(LINTLIBDIR)/llib-lXaw.ln LINTXXIE = $(LINTLIBDIR)/llib-lXIE.ln LINTXI = $(LINTLIBDIR)/llib-lXi.ln LINTPHIGS = $(LINTLIBDIR)/llib-lphigs.ln DEPXBSDLIB = $(USRLIBDIR)/libXbsd.a XBSDLIB = -lXbsd DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB) DEPLIBS1 = $(DEPLIBS) DEPLIBS2 = $(DEPLIBS) DEPLIBS3 = $(DEPLIBS) UILFLAGS = MLIBSRC = $(TOP)/motif/lib XMSRC = $(MLIBSRC)/Xm LINTXM = $(USRLIBDIR)/llib-lXm.ln USRINCDIR = $(INCDIR) TESTSRC = $(TOP)/tests MTOOLKITSRC = $(LIBSRC)/Xt MWIDGETSRC = $(MLIBSRC)/Xm MRESOURCESRC = $(MLIBSRC)/Mrm MCLIENTSRC = $(TOP)/motif/clients UILSRC = $(MCLIENTSRC)/uil MINCLUDESRC = $(INCLUDESRC) UIL = uil INSTALLLIB = $(DESTDIR)/usr/lib INSTALLSHLIB = $(DESTDIR)/usr/shlib DEPXMLIB = $(USRSHLIBDIR)/libXm.so XMLIB = -lXm DEPMRESOURCELIB = $(USRSHLIBDIR)/libMrm.so MRESOURCELIB = -lMrm UILINCLUDES = UILLIB = $(UILSRC)/libUil.a LINTXMWIDGETLIB = $(MWIDGETSRC)/llib-l/Xm.ln LINTXMTOOL = $(MTOOLKITSRC)/llib-lXt.ln LINTUILLIB = $(UILSRC)/llib-lUil.ln # ------------------------------------------------------------------------- # DEC-Specific System Build Parameters HELPDIR = $(LIBDIR)/help UIDDIR = $(LIBDIR)/uid CDADIR = $(USRLIBDIR)/cda DXMSRC = $(MLIBSRC)/DXm DPSSRC = $(EXTENSIONSRC)/DPSII/lib/dps DPSTKSRC = $(EXTENSIONSRC)/DPSII/lib/dpstk PSRESSRC = $(EXTENSIONSRC)/DPSII/lib/psres XIESRC = $(EXTENSIONSRC)/lib/xie IDSSRC = $(MLIBSRC)/ids BKRSRC = $(MLIBSRC)/bkr DWI18NSRC = $(MLIBSRC)/dwi18n LWKSRC = $(MLIBSRC)/lwk DVRSRC = $(MLIBSRC)/dvr DEPDXMLIB = $(USRSHLIBDIR)/libDXm.so DXMLIB = -lDXm MDXMLIB = $(DXMLIB) DEPDPSLIB = $(USRSHLIBDIR)/libdps.so DPSLIB = -ldps DEPDPSTKLIB = $(USRSHLIBDIR)/libdpstk.so DPSTKLIB = -ldpstk DEPPSRESLIB = $(USRSHLIBDIR)/libpsres.so PSRESLIB = -lpsres DEPXIELIB = $(USRLIBDIR)/libXie.a XIELIB = -lXie DEPIDSLIB = $(USRSHLIBDIR)/libids.so IDSLIB = -lids DEPBKRLIB = $(USRSHLIBDIR)/libbkr.so BKRLIB = -lbkr DEPDWI18NLIB = $(USRLIBDIR)/libdwi18n.a DWI18NLIB = -ldwi18n DEPLWKLIB = $(USRSHLIBDIR)/liblwkdxm.so LWKLIB = -llwkdxm DEPDVRLIB = $(USRSHLIBDIR)/libdvr.so DVRLIB = -ldvr DEPIMGLIB = DEPIPSLIB = DEPCHFLIB = DEPCDALIB = DEPDVSLIB = DEPIDS_NOXLIB = IMGLIB = -limg IPSLIB = -lips CHFLIB = -lchf CDALIB = -lcda IDS_NOXLIB = -lids_nox DVSLIB = -ldvs DEBUGUSRLIBDIR=/usr/debugshlib # ------------------------------------------------------------------------- # Imake rules for building libraries, programs, scripts, and data files # rules: $XConsortium: Imake.rules,v 1.123 91/09/16 20:12:16 rws Exp $ # ------------------------------------------------------------------------- # DEC-Specific System Build Rules # $Id: Makefile,v 1.2 1997/03/17 22:07:39 pvmsrc Exp $ # ------------------------------------------------------------------------- # start of Imakefile SRCS = xhoster.c hostc.c OBJS = xhoster.o hostc.o CCOPTIONS = -I$(PVM_ROOT)/include -I$(PVM_ROOT)/src -DIMA_$(PVM_ARCH) $(ARCHCFLAGS) EXTRA_LOAD_FLAGS = -L$(PVM_ROOT)/lib/$(PVM_ARCH) EXTRA_LIBRARIES = -lXaw -lXt -lXmu -lXext -lX11 -lpvm3 PROGRAM = xhoster all:: xhoster xhoster: $(OBJS) $(DEPLIBS) $(RM) $@ $(CC) -o $@ $(OBJS) $(LDOPTIONS) $(LOCAL_LIBRARIES) $(LDLIBS) $(EXTRA_LOAD_FLAGS) install:: xhoster @if [ -d $(DESTDIR)$(BINDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(DESTDIR)$(BINDIR)); fi $(INSTALL) -c $(INSTPGMFLAGS) xhoster $(DESTDIR)$(BINDIR) install.man:: xhoster.man @if [ -d $(DESTDIR)$(MANDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(DESTDIR)$(MANDIR)); fi $(INSTALL) -c $(INSTMANFLAGS) xhoster.man $(DESTDIR)$(MANDIR)/xhoster.$(MANSUFFIX) depend:: $(DEPEND) $(DEPENDFLAGS) -s "# DO NOT DELETE" -- $(ALLDEFINES) -- $(SRCS) lint: $(LINT) $(LINTFLAGS) $(SRCS) $(LINTLIBS) lint1: $(LINT) $(LINTFLAGS) $(FILE) $(LINTLIBS) clean:: $(RM) $(PROGRAM) # ------------------------------------------------------------------------- # common rules for all Makefiles - do not edit emptyrule:: clean:: $(RM_CMD) "#"* Makefile:: -@if [ -f Makefile ]; then set -x; \ $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \ else exit 0; fi $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR) tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS # ------------------------------------------------------------------------- # empty rules for directories that do not have SUBDIRS - do not edit install:: @echo "install in $(CURRENT_DIR) done" install.man:: @echo "install.man in $(CURRENT_DIR) done" Makefiles:: includes:: # ------------------------------------------------------------------------- # dependencies generated by makedepend ./pvm3/misc/xhoster/README0100644007401100000360000000223606757022415014422 0ustar kohlgopher Xhoster 09 Oct 1995 ________________________________________________________________________ This is a little X-Windows program that enrolls as the hoster task, giving the user a convenient place to type passwords when starting hosts that require them. It also logs problems related to startup, for help in debugging. To build it, type "xmkmf" then "aimk" in this directory, and install it wherever you want, f.e. $PVM_ROOT/lib/$PVM_ARCH/xhoster. Suggested X defaults to make it look less ugly would be: xhoster*background: antiquewhite3 xhoster*font: -*-helvetica-medium-r-normal--14-100-*-*-p-*-*-* xhoster.geometry: 700x300 The xhoster can be attached and detached without shutting down the pvmds. -b ------------------------------------------------------------------------ August 19, 1999 The hoster protocols have changed enough in PVM 3.4.2 that this xhoster no longer works. Consider this source code a template for constructing a X-Windows hoster program, and refer to the text-based hoster in pvm3/hoster for assiatance in constructing your own hoster. All the Best, Jimbo ------------------------------------------------------------------------ ./pvm3/misc/xhoster/hostc.c0100644007401100000360000001433106741172445015027 0ustar kohlgopher /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * hostc.c * * Host cache functions. * * $Log: hostc.c,v $ * Revision 1.4 1999/07/08 18:59:49 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.3 1998/01/28 19:12:56 pvmsrc * Commented out ancient #include ... * (Spanker=kohl) * * Revision 1.2 1997/07/09 13:31:24 pvmsrc * Fixed Author Header. * * Revision 1.1 1996/09/23 22:29:56 pvmsrc * Initial revision * */ #include #ifdef SYSVSTR #include #else #include #endif #include #include /* #ifdef IMA_LINUX */ /* #include */ /* #endif */ #include #include <../src/bfunc.h> #include <../src/listmac.h> #include "myalloc.h" #include "hostc.h" static char rcsid[] = "$Id: hostc.c,v 1.4 1999/07/08 18:59:49 kohl Exp $"; static struct hostc *curhosts = 0; static int addtag = -1; static int deltag = -1; static int (*addcallback)() = 0; static int (*delcallback)() = 0; static struct hostc * hc_new() { struct hostc *hp; if (hp = TALLOC(1, struct hostc, "hd")) BZERO(hp, sizeof(struct hostc)); return hp; } static int hc_init() { if (curhosts = hc_new()) curhosts->link = curhosts->rlink = curhosts; else fprintf(stderr, "hc_init() out of memory\n"); return 0; } static struct hostc * hc_add(hip) struct pvmhostinfo *hip; { struct hostc *hp, *hp2; /* * if we have a delete message tag and it's not this host, notify */ if (deltag != -1 && hip->hi_tid != pvm_tidtohost(pvm_mytid())) pvm_notify(PvmHostDelete, deltag, 1, &hip->hi_tid); if (hp = hc_new()) { hp->pvmd_tid = hip->hi_tid; hp->name = STRALLOC(hip->hi_name); hp->alias = STRALLOC(hip->hi_name); hp->arch = STRALLOC(hip->hi_arch); hp->speed = hip->hi_speed; pvm_hostsync(hp->pvmd_tid, (struct timeval *)0, &(hp->delta)); } for (hp2 = curhosts->link; hp2 != curhosts; hp2 = hp2->link) if (hp->pvmd_tid < hp2->pvmd_tid) break; LISTPUTBEFORE(hp2, hp, link, rlink); return hp; } static int hc_delete(hp) struct hostc *hp; { LISTDELETE(hp, link, rlink); if (hp->name) MY_FREE(hp->name); if (hp->arch) MY_FREE(hp->arch); if (hp->alias) MY_FREE(hp->alias); MY_FREE(hp); return 0; } static struct hostc * hc_find(tid) { struct hostc *hp; for (hp = curhosts->link; hp != curhosts; hp = hp->link) if (tid <= hp->pvmd_tid) break; return (tid == hp->pvmd_tid) ? hp : (struct hostc *)0; } /* host_init() * * Initialize host cache. Called once at beginning of time. * Synchronize to current configuration. * Specify message tags to be used for HostAdd and HostDelete notify. */ host_init(atag, dtag, acb, dcb) int atag; /* message tag to use for HostAdd notify or -1 */ int dtag; /* tag to use for HostDelete notify or -1 */ int (*acb)(); /* callback for each host added */ int (*dcb)(); /* callback for each host deleted */ { struct pvmhostinfo *hip; int nh; addtag = atag; deltag = dtag; addcallback = acb; delcallback = dcb; hc_init(); if (addtag != -1) pvm_notify(PvmHostAdd, addtag, -1, (int *)0); if (!pvm_config(&nh, (int *)0, &hip)) { while (nh > 0) { nh--; hc_add(&hip[nh]); } } return 0; } /* host_add() * * Called when a HostAdd notify message has been received. * The message is in the current receive buffer. */ host_add() { int d = 0; int n; int *dtids; int i, j; struct pvmhostinfo *hip; int nh; pvm_upkint(&n, 1, 1); if (n < 1 || n > 4096) return 0; dtids = TALLOC(n, int, "dtid"); pvm_upkint(dtids, n, 1); pvm_freebuf(pvm_getrbuf()); if (!pvm_config(&nh, (int *)0, &hip)) { for (j = n; j-- > 0; ) for (i = nh; i-- > 0; ) { if (dtids[j] == hip[i].hi_tid) { hc_add(&hip[i]); if (addcallback) addcallback(dtids[j]); d++; break; } } } MY_FREE(dtids); return d; } /* host_delete() * * Called when a HostDelete notify message has been received. * The message is in the current receive buffer. */ host_delete() { int tid; struct hostc *hp; int d = 0; pvm_upkint(&tid, 1, 1); if (tid == pvm_tidtohost(tid) && (hp = hc_find(tid))) { if (delcallback) delcallback(tid); hc_delete(hp); d++; } return d; } struct hostc * host_findtid(tid) int tid; { return hc_find(tid); } struct hostc * host_findname(name) char *name; { struct hostc *hp; for (hp = curhosts->link; hp != curhosts; hp = hp->link) if (!strcmp(name, hp->name)) return hp; return (struct hostc *)0; } struct hostc * host_next(hp) struct hostc *hp; { hp = hp ? hp->link : curhosts->link; return (hp == curhosts) ? 0 : hp; } host_show() { struct hostc *hp; int nh = 0; int na = 0; int a; long mask = 0; for (hp = 0; hp = host_next(hp); ) { nh++; a = pvm_archcode(hp->arch); if (!(mask & (1 << a))) { na++; mask |= (1 << a); } } printf("Configuration: %d host%s, %d data format%s\n", nh, (nh == 1 ? "" : "s"), na, (na == 1 ? "" : "s")); printf(" TID ARCH SPEED HOSTNAME\n"); for (hp = 0; hp = host_next(hp); ) { printf("%8x %10s %7d %-24s\n", hp->pvmd_tid, hp->arch, hp->speed, hp->name); } } ./pvm3/misc/xhoster/hostc.h0100644007401100000360000000407606741172445015041 0ustar kohlgopher /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * hostc.h * * Host cache definitions. * * $Log: hostc.h,v $ * Revision 1.3 1999/07/08 18:59:49 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.2 1997/07/09 13:31:26 pvmsrc * Fixed Author Header. * * Revision 1.1 1996/09/23 22:30:00 pvmsrc * Initial revision * */ struct hostc { struct hostc *link, *rlink; int pvmd_tid; char *name; char *alias; char *arch; int speed; struct timeval delta; }; int host_init __ProtoGlarp__(( int atag, int dtag, int (*acb)(), int (*dcb)() )); int host_add __ProtoGlarp__(( void )); int host_delete __ProtoGlarp__(( void )); struct hostc *host_findtid __ProtoGlarp__(( int tid )); struct hostc *host_findname __ProtoGlarp__(( char *name )); struct hostc *host_next __ProtoGlarp__(( struct hostc *hp )); int host_show __ProtoGlarp__(( void )); ./pvm3/misc/xhoster/myalloc.h0100644007401100000360000000412606741172446015356 0ustar kohlgopher /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * myalloc.h * * Malloc defines. * * $Log: myalloc.h,v $ * Revision 1.3 1999/07/08 18:59:50 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.2 1997/07/09 13:31:27 pvmsrc * Fixed Author Header. * * Revision 1.1 1996/09/23 22:30:01 pvmsrc * Initial revision * */ #ifdef HASSTDLIB #include #endif #ifdef USE_PVM_ALLOC #define MY_ALLOC(n,g) pvm_alloc((unsigned)(n),(g)) #define MY_REALLOC(p,n) pvm_realloc((char*)(p),(unsigned)(n)) #define MY_FREE(p) pvm_free((char*)(p)) #else #define MY_ALLOC(n,g) malloc((unsigned)(n)) #define MY_REALLOC(p,n) realloc((char*)(p),(unsigned)(n)) #define MY_FREE(p) free((char*)(p)) #endif #define TALLOC(n,t,g) (t*)MY_ALLOC((n)*sizeof(t),(g)) #define TREALLOC(p,n,t) (t*)MY_REALLOC(p,(n)*sizeof(t)) #define STRALLOC(s) strcpy(TALLOC(strlen(s)+1,char,"str"),s) ./pvm3/misc/xhoster/xhoster.c0100644007401100000360000006102207052063045015371 0ustar kohlgopher /* * xhoster.c * * Example X-Window hoster. Lets user type passwords without having * master pvmd running in foreground. * From hoster.c example. * * 21 Sep 1994 Manchek */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef NEEDSSELECTH #include #endif #ifdef SYSVSTR #include #define CINDEX(s,c) strchr(s,c) #else #include #define CINDEX(s,c) index(s,c) #endif #include #include #include "hostc.h" #include "bfunc.h" #ifndef RSHTIMEOUT #define RSHTIMEOUT 60 #endif #ifndef RSHNPLL #define RSHNPLL 5 #endif #ifndef max #define max(a,b) ((a)>(b)?(a):(b)) #endif #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif #define TALLOC(n,t,g) (t*)malloc((n)*sizeof(t)) #define FREE(p) free((char *)p) #define STRALLOC(s) strcpy(TALLOC(strlen(s)+1,char,"str"),s) #define LISTPUTAFTER(o,n,f,r) \ { (n)->f=(o)->f; (n)->r=(o); (o)->f->r=(n); (o)->f=(n); } #define LISTPUTBEFORE(o,n,f,r) \ { (n)->r=(o)->r; (n)->f=(o); (o)->r->f=(n); (o)->r=(n); } #define LISTDELETE(e,f,r) \ { (e)->f->r=(e)->r; (e)->r->f=(e)->f; (e)->r=(e)->f=0; } #define TVCLEAR(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0) #define TVISSET(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) #define TVXLTY(xtv, ytv) \ ((xtv)->tv_sec < (ytv)->tv_sec || \ ((xtv)->tv_sec == (ytv)->tv_sec && (xtv)->tv_usec < (ytv)->tv_usec)) #define TVXADDY(ztv, xtv, ytv) \ if (((ztv)->tv_usec = (xtv)->tv_usec + (ytv)->tv_usec) < 1000000) { \ (ztv)->tv_sec = (xtv)->tv_sec + (ytv)->tv_sec; \ } else { \ (ztv)->tv_usec -= 1000000; \ (ztv)->tv_sec = (xtv)->tv_sec + (ytv)->tv_sec + 1; \ } #define TVXSUBY(ztv, xtv, ytv) \ if ((xtv)->tv_usec >= (ytv)->tv_usec) { \ (ztv)->tv_sec = (xtv)->tv_sec - (ytv)->tv_sec; \ (ztv)->tv_usec = (xtv)->tv_usec - (ytv)->tv_usec; \ } else { \ (ztv)->tv_sec = (xtv)->tv_sec - (ytv)->tv_sec - 1; \ (ztv)->tv_usec = (xtv)->tv_usec + 1000000 - (ytv)->tv_usec; \ } /* * for keeping state assoc. with a host */ struct hst { int h_tid; char *h_name; char *h_login; char *h_sopts; int h_flag; #define HST_PASSWORD 1 /* ask for a password */ #define HST_MANUAL 2 /* do manual startup */ char *h_pwd; char *h_cmd; char *h_result; }; #define STA_IDLE 0 #define STA_NEEDPW 1 #define STA_START 2 #define HostAdded 1 /* for notify */ #define HostDeleted 2 struct slot { struct slot *s_link, *s_rlink; /* free/active list */ struct hst *s_hst; /* host table entry */ struct timeval s_bail; /* timeout time */ int s_rfd, s_wfd, s_efd; /* slave stdin/out/err */ char s_buf[256]; /* config reply line */ char s_ebuf[256]; /* stderr from host */ int s_len; /* length of s_buf */ int s_elen; /* length of s_ebuf */ }; int debugmask = 0; char *username = 0; Display *xDisp = 0; XtAppContext context = 0; Widget topLevel = 0; /* main widget */ int xScrn = 0; Window xRootW = 0; char pwbuffer[30]; Widget pwdWindow = 0; Widget logWindow = 0; Widget okButton = 0; Widget okallButton = 0; Widget hostsLabel = 0; int mystate = STA_IDLE; /* state of widgy */ struct hst **hostlist = 0; /* hosts being added */ int numhost = 0; /* number of hosts */ int fromtid = 0; /* source tid of add request */ int fromwid = 0; /* wait id in request */ int curhost = 0; /* waiting for password for this host */ char scribble[1024]; static struct slot slots[RSHNPLL+2]; /* state var/context for each slot */ static struct slot *slfree = 0; /* free list of slots */ static Arg args[16]; static XtCallbackRec callback[2] = { { 0, 0 }, { 0, 0 } }; static char *fallbacks[] = { "*titleLabel.label: PVM Xhoster", "*titleLabel.borderWidth: 0", "*hostsLabel.borderWidth: 0", "*pwdLabel.label: Password:", "*pwdLabel.borderWidth: 0", "*quitButton.label: Exit", "*hbox.borderWidth: 0", "*okButton.label: Ok", "*okallButton.label: Ok-for-all", "*logWindow.width: 400", "*logWindow.height: 90", "*logWindow.scrollHorizontal: Always", "*logWindow.scrollVertical: Always", 0 }; typedef struct { Bool mono; /* force monochrome display */ } app_res_t, *app_resp_t; static app_res_t app_res; static XtResource res_list[] = { { "monochrome", "Monochrome", XtRBool, sizeof(Bool), XtOffset(app_resp_t, mono), XtRString, "off" }, }; static XrmOptionDescRec knownargs[] = { { "-mono", ".monochrome", XrmoptionNoArg, "on" }, { "+mono", ".monochrome", XrmoptionNoArg, "off" }, }; char *pvmgetrsh(); void pvm_cb(); void quit_cb(); hostcount() { int nh = 0; struct hostc *hp = 0; while (hp = host_next(hp)) nh++; sprintf(scribble, "Hosts:%3d", nh); XtSetArg(args[0], XtNlabel, scribble); XtSetValues(hostsLabel, args, 1); } host_was_added(tid) int tid; { return 0; } host_was_deleted(tid) int tid; { struct hostc *hp; if (hp = host_findtid(tid)) { sprintf(scribble, "Host %s deleted\n", hp->name); log_this(scribble); } return 0; } main(argc, argv) int argc; char **argv; { struct passwd *pe; int uid; int n; int *fds; int didstart = 0; n = 0; topLevel = XtAppInitialize(&context, "xhoster", knownargs, XtNumber(knownargs), &argc, argv, fallbacks, args, n); /* XtGetApplicationResources(topLevel, (caddr_t)&app_res, res_list, XtNumber(res_list), 0, 0); */ pvm_setopt(PvmRoute, PvmDontRoute); if (pvm_mytid() < 0) { if (pvm_start_pvmd(0, (char **)0, 1) < 0) exit(1); didstart = 1; } /* XtAppAddActions(context, actbl, XtNumber(actbl)); */ xDisp = XtDisplay(topLevel); xScrn = DefaultScreen(xDisp); xRootW = RootWindow(xDisp, xScrn); create_widget(); if ((uid = getuid()) == -1) { fprintf(stderr, "main() can't getuid()\n"); exit(1); } if (pe = getpwuid(uid)) username = STRALLOC(pe->pw_name); else fprintf(stderr, "main() can't getpwuid\n"); endpwent(); pvm_setopt(PvmResvTids, 1); if (pvm_reg_hoster()) { pvm_exit(); exit(1); } host_init(HostAdded, HostDeleted, host_was_added, host_was_deleted); pvm_getfds(&fds); XtAppAddInput(context, fds[0], (XtPointer)XtInputReadMask, pvm_cb, (XtPointer)0); if (didstart) log_this("No pvmd found, started one"); log_this("PVM Xhoster ready"); XtAppMainLoop(context); pvm_exit(); /* not reached */ exit(0); } void pvm_cb(cli, src, id) XtPointer cli; int *src; XtInputId *id; { int tag; while (pvm_nrecv(-1, -1) > 0) { pvm_bufinfo(pvm_getrbuf(), (int *)0, (int *)&tag, (int *)0); if (tag == SM_STHOST) hoster(); if (tag == HostAdded) { host_add(); hostcount(); } if (tag == HostDeleted) { host_delete(); hostcount(); } } } void ok_cb(wgt, cli, cd) Widget wgt; caddr_t cli; caddr_t cd; { int n; if (mystate == STA_NEEDPW) hostlist[curhost]->h_pwd = STRALLOC(pwbuffer); /* else TextAppend(logWindow, "what?\n", 6); */ BZERO(pwbuffer, sizeof(pwbuffer)); n = 0; XtSetArg(args[n], XtNstring, pwbuffer); n++; XtSetValues(pwdWindow, args, n); if (mystate == STA_NEEDPW) next_pwd(); } void okall_cb(wgt, cli, cd) Widget wgt; caddr_t cli; caddr_t cd; { int n; if (mystate == STA_NEEDPW) { while (curhost < numhost) { if (hostlist[curhost]->h_flag & HST_PASSWORD) hostlist[curhost]->h_pwd = STRALLOC(pwbuffer); curhost++; } log_this("Using password for all hosts\n"); } BZERO(pwbuffer, sizeof(pwbuffer)); n = 0; XtSetArg(args[n], XtNstring, pwbuffer); n++; XtSetValues(pwdWindow, args, n); if (mystate == STA_NEEDPW) hoster2(); } void quit_cb(wgt, cli, cd) Widget wgt; caddr_t cli; caddr_t cd; { pvm_exit(); exit(0); } log_this(s) char *s; { /* int n; n = 0; XtSetArg(args[n], XtNlabel, s); n++; XtSetValues(stateLabel, args, n); */ TextAppend(logWindow, s, strlen(s)); if (s[strlen(s) - 1] != '\n') TextAppend(logWindow, "\n", 1); } long TextLength(w) Widget w; { return XawTextSourceScan(XawTextGetSource(w), (XawTextPosition)0, XawstAll, XawsdRight, 1, TRUE); } TextReplace(w, start, end, block) Widget w; XawTextBlock *block; { Arg arg; Widget source; XawTextEditType edit_mode; source = XawTextGetSource(w); XtSetArg(arg, XtNeditType, &edit_mode); XtGetValues(source, &arg, 1); XtSetArg(arg, XtNeditType, XawtextEdit); XtSetValues(source, &arg, 1); XawTextReplace(w, start, end, block); XtSetArg(arg, XtNeditType, edit_mode); XtSetValues(source, &arg, 1); } TextAppend(w, s, len) Widget w; char *s; { long last, current; XawTextBlock block; current = XawTextGetInsertionPoint(w); last = TextLength(w); block.ptr = s; block.firstPos = 0; block.length = len; block.format = FMT8BIT; TextReplace(w, last, last, &block); if (current == last) XawTextSetInsertionPoint(w, last + block.length); } create_widget() { Widget box, hbox; Widget w, w2; int n; /* Pixmap pm; */ XtAccelerators atbl; int nh; atbl = XtParseAcceleratorTable("#override\nReturn:set()notify()reset()\n"); n = 0; box = XtCreateManagedWidget("", formWidgetClass, topLevel, args, n); n = 0; XtSetArg(args[n], XtNtop, XawChainTop); n++; XtSetArg(args[n], XtNbottom, XawChainTop); n++; XtSetArg(args[n], XtNleft, XawChainLeft); n++; XtSetArg(args[n], XtNright, XawChainLeft); n++; hbox = XtCreateManagedWidget("hbox", formWidgetClass, box, args, n); n = 0; sprintf(scribble, "PVM Xhoster (task id =t%x)", pvm_mytid()); XtSetArg(args[n], XtNlabel, scribble); n++; w = XtCreateManagedWidget("titleLabel", labelWidgetClass, hbox, args, n); n = 0; XtSetArg(args[n], XtNfromHoriz, w); n++; pvm_config(&nh, (int *)0, (struct pvmhostinfo **)0); sprintf(scribble, "Hosts:%3d", nh); XtSetArg(args[n], XtNlabel, scribble); n++; w = hostsLabel = XtCreateManagedWidget("hostsLabel", labelWidgetClass, hbox, args, n); n = 0; XtSetArg(args[n], XtNfromHoriz, w); n++; callback[0].callback = (XtCallbackProc)quit_cb; callback[0].closure = (caddr_t)0; XtSetArg(args[n], XtNcallback, callback); n++; /* pm = XCreatePixmapFromBitmapData(xDisp, xRootW, quit_bits, quit_width, quit_height, 1, 0, 1); XtSetArg(args[n], XtNbitmap, (XtArgVal)pm); n++; */ w = XtCreateManagedWidget("quitButton", commandWidgetClass, hbox, args, n); n = 0; XtSetArg(args[n], XtNfromVert, hbox); n++; XtSetArg(args[n], XtNtop, XawChainTop); n++; XtSetArg(args[n], XtNbottom, XawChainBottom); n++; XtSetArg(args[n], XtNleft, XawChainLeft); n++; XtSetArg(args[n], XtNright, XawChainRight); n++; hbox = logWindow = XtCreateManagedWidget("logWindow", asciiTextWidgetClass, box, args, n); n = 0; XtSetArg(args[n], XtNfromVert, hbox); n++; XtSetArg(args[n], XtNtop, XawChainBottom); n++; XtSetArg(args[n], XtNbottom, XawChainBottom); n++; XtSetArg(args[n], XtNleft, XawChainLeft); n++; XtSetArg(args[n], XtNright, XawChainLeft); n++; hbox = XtCreateManagedWidget("hbox", formWidgetClass, box, args, n); n = 0; XtSetArg(args[n], XtNeditType, XawtextEdit); n++; w = XtCreateManagedWidget("pwdLabel", labelWidgetClass, hbox, args, n); n = 0; XtSetArg(args[n], XtNfromHoriz, w); n++; XtSetArg(args[n], XtNeditType, XawtextEdit); n++; XtSetArg(args[n], XtNstring, pwbuffer); n++; XtSetArg(args[n], XtNlength, sizeof(pwbuffer)-1); n++; XtSetArg(args[n], XtNuseStringInPlace, True); n++; XtSetArg(args[n], XtNecho, False); n++; w = pwdWindow = XtCreateManagedWidget("pwdWindow", asciiTextWidgetClass, hbox, args, n); n = 0; XtSetArg(args[n], XtNfromHoriz, w); n++; callback[0].callback = (XtCallbackProc)ok_cb; callback[0].closure = (caddr_t)0; XtSetArg(args[n], XtNcallback, callback); n++; XtSetArg(args[n], XtNaccelerators, atbl); n++; w = okButton = XtCreateManagedWidget("okButton", commandWidgetClass, hbox, args, n); n = 0; XtSetArg(args[n], XtNfromHoriz, w); n++; callback[0].callback = (XtCallbackProc)okall_cb; callback[0].closure = (caddr_t)0; XtSetArg(args[n], XtNcallback, callback); n++; XtSetArg(args[n], XtNaccelerators, atbl); n++; w = okallButton = XtCreateManagedWidget("okallButton", commandWidgetClass, hbox, args, n); XtRealizeWidget(topLevel); XtInstallAccelerators(pwdWindow, okButton); } /* hoster() * * Unpack host table from message, attempt to start 'em up, * send reply message. */ hoster() { int i; struct hst *hp; char *p; struct pvmminfo minfo; char sopts[64]; char lognam[256]; char cmd[512]; /* * unpack the startup message */ pvm_bufinfo(pvm_getrbuf(), (int *)0, (int *)0, &fromtid); pvm_unpackf("%d", &numhost); pvm_getminfo(pvm_getrbuf(), &minfo); fromwid = minfo.wid; if (numhost > 0) { log_this("Ready to add hosts:\n"); hostlist = TALLOC(numhost, struct hst *, "xxx"); for (i = 0; i < numhost; i++) { hp = TALLOC(1, struct hst, "xxx"); BZERO((char *)hp, sizeof(struct hst)); hostlist[i] = hp; if (pvm_unpackf("%d %s %s %s", &hp->h_tid, sopts, lognam, cmd)) { log_this("received message with bad format\n"); return 1; } hp->h_sopts = STRALLOC(sopts); hp->h_login = STRALLOC(lognam); hp->h_cmd = STRALLOC(cmd); sprintf(scribble, "%2d. %s\n", i + 1, hp->h_login); log_this(scribble); if (debugmask) fprintf(stderr, "%d. t%x %s so=\"%s\"\n", i, hp->h_tid, hp->h_login, hp->h_sopts); if (p = CINDEX(hp->h_login, '@')) { hp->h_name = STRALLOC(p + 1); *p = 0; p = STRALLOC(hp->h_login); FREE(hp->h_login); hp->h_login = p; } else { hp->h_name = hp->h_login; hp->h_login = 0; } if (!strcmp(hp->h_sopts, "pw")) hp->h_flag |= HST_PASSWORD; if (!strcmp(hp->h_sopts, "ms")) hp->h_flag |= HST_MANUAL; } } curhost = -1; next_pwd(); return 0; } next_pwd() { char buf[256]; while (1) { curhost++; if (curhost >= numhost) { hoster2(); break; } else if (hostlist[curhost]->h_flag & HST_PASSWORD) { mystate = STA_NEEDPW; sprintf(buf, "Enter password for %s:\n", hostlist[curhost]->h_name); log_this(buf); break; } } } hoster2() { int i; char *p; struct hst *hp; struct pvmminfo minfo; /* * do it */ mystate = STA_START; log_this("Starting..."); XFlush(xDisp); pl_startup(numhost, hostlist); /* * send results back to pvmd */ pvm_packf("%+ %d", PvmDataFoo, numhost); for (i = 0; i < numhost; i++) { pvm_packf("%d", hostlist[i]->h_tid); pvm_packf("%s", hostlist[i]->h_result ? hostlist[i]->h_result : "PvmDSysErr"); } pvm_getminfo(pvm_getsbuf(), &minfo); minfo.wid = fromwid; pvm_setminfo(pvm_getsbuf(), &minfo); pvm_send(fromtid, SM_STHOSTACK); mystate = STA_IDLE; log_this("...Done"); for (i = 0; i < numhost; i++) { hp = hostlist[i]; if (hp->h_name) FREE(hp->h_name); if (hp->h_login) FREE(hp->h_login); if (hp->h_sopts) FREE(hp->h_sopts); if (hp->h_pwd) { for (p = hp->h_pwd; *p; p++) *p = 0; FREE(hp->h_pwd); } if (hp->h_cmd) FREE(hp->h_cmd); if (hp->h_result) FREE(hp->h_result); FREE(hp); } FREE(hostlist); hostlist = 0; numhost = 0; return 0; } close_slot(sp) struct slot *sp; { if (sp->s_wfd != -1) (void)close(sp->s_wfd); if (sp->s_rfd != -1) (void)close(sp->s_rfd); if (sp->s_efd != -1) (void)close(sp->s_efd); LISTDELETE(sp, s_link, s_rlink); LISTPUTBEFORE(slfree, sp, s_link, s_rlink); return 0; } pl_startup(num, hostlist) int num; struct hst **hostlist; { int nxth = 0; /* next host in list to start */ struct slot *slact = 0; /* active list of slots */ struct hst *hp; struct slot *sp, *sp2; struct timeval tnow; struct timeval tout; #ifdef FDSETNOTSTRUCT fd_set rfds; #else struct fd_set rfds; #endif int nfds; int i; int n; char *p; /* init slot free list */ slfree = &slots[RSHNPLL+1]; slfree->s_link = slfree->s_rlink = slfree; slact = &slots[RSHNPLL]; slact->s_link = slact->s_rlink = slact; for (i = RSHNPLL; i-- > 0; ) { LISTPUTAFTER(slfree, &slots[i], s_link, s_rlink); } /* * keep at this until all hosts in table are completed */ for (; ; ) { /* * if empty slots, start on new hosts */ for (; ; ) { /* find a host for slot */ if (slfree->s_link != slfree && nxth < num) hp = hostlist[nxth++]; else break; sp = slfree->s_link; LISTDELETE(sp, s_link, s_rlink); sp->s_hst = hp; sp->s_len = 0; sp->s_elen = 0; if (debugmask) { fprintf(stderr, "pl_startup() trying %s\n", hp->h_name); } phase1(sp); if (hp->h_result) { /* error or fully started (manual startup) */ LISTPUTBEFORE(slfree, sp, s_link, s_rlink); } else { /* partially started */ LISTPUTBEFORE(slact, sp, s_link, s_rlink); gettimeofday(&sp->s_bail, (struct timezone*)0); tout.tv_sec = RSHTIMEOUT; tout.tv_usec = 0; TVXADDY(&sp->s_bail, &sp->s_bail, &tout); } } /* if no hosts in progress, we are finished */ if (slact->s_link == slact) break; /* * until next timeout, get output from any slot */ FD_ZERO(&rfds); nfds = 0; TVCLEAR(&tout); gettimeofday(&tnow, (struct timezone*)0); for (sp = slact->s_link; sp != slact; sp = sp->s_link) { if (TVXLTY(&sp->s_bail, &tnow)) { sprintf(scribble, "Giving up on host %s after %d secs\n", sp->s_hst->h_name, RSHTIMEOUT); log_this(scribble); sp->s_hst->h_result = STRALLOC("PvmCantStart"); sp2 = sp->s_rlink; close_slot(sp); sp = sp2; continue; } if (!TVISSET(&tout) || TVXLTY(&sp->s_bail, &tout)) tout = sp->s_bail; if (sp->s_rfd >= 0) FD_SET(sp->s_rfd, &rfds); if (sp->s_rfd > nfds) nfds = sp->s_rfd; if (sp->s_efd >= 0) FD_SET(sp->s_efd, &rfds); if (sp->s_efd > nfds) nfds = sp->s_efd; } if (slact->s_link == slact) break; nfds++; if (TVXLTY(&tnow, &tout)) { TVXSUBY(&tout, &tout, &tnow); } else { TVCLEAR(&tout); } if (debugmask) { fprintf(stderr, "pl_startup() select timeout is %d.%06d\n", tout.tv_sec, tout.tv_usec); } if ((n = select(nfds, #ifdef FDSETISINT (int *)&rfds, (int *)0, (int *)0, #else (fd_set *)&rfds, (fd_set *)0, (fd_set *)0, #endif &tout)) == -1) { if (errno != EINTR) { pvmlogperror("work() select"); pvmbailout(0); } } if (debugmask) { (void)fprintf(stderr, "pl_startup() select returns %d\n", n); } if (n < 1) { if (n == -1 && errno != EINTR) { pvmlogperror("pl_startup() select"); pvmbailout(0); /* XXX this is too harsh */ } continue; } /* * check for response on stdout or stderr of any slave. */ for (sp = slact->s_link; sp != slact; sp = sp->s_link) { /* * stderr ready. log output with remote's host name. */ if (sp->s_efd >= 0 && FD_ISSET(sp->s_efd, &rfds)) { n = read(sp->s_efd, sp->s_ebuf + sp->s_elen, sizeof(sp->s_ebuf) - sp->s_elen - 1); if (n > 0) { sp->s_elen += n; sp->s_ebuf[sp->s_elen] = 0; while (p = CINDEX(sp->s_ebuf, '\n')) { *p = 0; sprintf(scribble, "stderr@%s: %s\n", sp->s_hst->h_name, sp->s_ebuf); log_this(scribble); p++; sp->s_elen -= p - sp->s_ebuf; if (sp->s_elen > 0) { BCOPY(p, sp->s_ebuf, sp->s_elen); sp->s_ebuf[sp->s_elen] = 0; } } if (sp->s_elen == sizeof(sp->s_ebuf) - 1) { sprintf(scribble, "stderr@%s: %s\n", sp->s_hst->h_name, sp->s_ebuf); log_this(scribble); sp->s_elen = 0; } } else { if (sp->s_elen > 0) { sprintf(scribble, "stderr@%s: %s\n", sp->s_hst->h_name, sp->s_ebuf); log_this(scribble); sp->s_elen = 0; } (void)close(sp->s_efd); sp->s_efd = -1; } } /* * stdout ready. * look for a complete line starting with "ddpro". */ if (sp->s_rfd >= 0 && FD_ISSET(sp->s_rfd, &rfds)) { n = read(sp->s_rfd, sp->s_buf + sp->s_len, sizeof(sp->s_buf) - sp->s_len - 1); if (n > 0) { sp->s_len += n; sp->s_buf[sp->s_len] = 0; while (p = CINDEX(sp->s_buf, '\n')) { *p = 0; if (!strncmp(sp->s_buf, "ddpro", 5)) { if (debugmask) { sprintf(scribble, "stdout@%s: %s\n", sp->s_hst->h_name, sp->s_buf); log_this(scribble); } sp->s_hst->h_result = STRALLOC(sp->s_buf); break; } else { sprintf(scribble, "stdout@%s: %s\n", sp->s_hst->h_name, sp->s_buf); log_this(scribble); p++; sp->s_len -= p - sp->s_buf; if (sp->s_len > 0) { BCOPY(p, sp->s_buf, sp->s_len); sp->s_buf[sp->s_len] = 0; } } } if (sp->s_len == sizeof(sp->s_buf) - 1) { sprintf(scribble, "stdout@%s: %s\n", sp->s_hst->h_name, sp->s_buf); log_this(scribble); sp->s_len = 0; } } else { if (sp->s_len > 0) { sprintf(scribble, "stdout@%s: %s\n", sp->s_hst->h_name, sp->s_buf); log_this(scribble); sp->s_len = 0; } if (n) { sprintf(scribble, "stdout@%s", sp->s_hst->h_name); pvmlogperror(scribble); } else { sprintf(scribble, "stdout@%s: EOF\n", sp->s_hst->h_name); log_this(scribble); } sp->s_hst->h_result = STRALLOC("PvmCantStart"); if (sp->s_elen > 0) { sprintf(scribble, "stderr@%s: %s\n", sp->s_hst->h_name, sp->s_ebuf); log_this(scribble); sp->s_elen = 0; } } if (sp->s_hst->h_result) { sp2 = sp->s_rlink; close_slot(sp); sp = sp2; continue; } } } } return 0; } phase1(sp) struct slot *sp; { struct hst *hp; char *hn; char *av[16]; /* for rsh args */ int ac; char buf[512]; int pid = -1; /* pid of rsh */ char *p; #ifndef NOREXEC struct servent *se; static u_short execport = 0; if (!execport) { if (!(se = getservbyname("exec", "tcp"))) { fprintf(stderr, "phase1() can't getservbyname(): %s\n", "exec"); pvmbailout(0); } execport = se->s_port; endservent(); } #endif hp = sp->s_hst; hn = hp->h_name; sp->s_rfd = sp->s_wfd = sp->s_efd = -1; /* * XXX manual startup hack... this is if we can't use rexec or rsh */ if (hp->h_flag & HST_MANUAL) { sprintf(scribble, "Can't start %s, manual startup specified\n", hp->h_name); log_this(scribble); hp->h_result = STRALLOC("PvmNotImpl"); #if 0 fprintf(stderr, "*** Manual startup ***\n"); fprintf(stderr, "Login to \"%s\" and type:\n", hn); fprintf(stderr, "%s\n", hp->h_cmd); /* get version */ fprintf(stderr, "Type response: "); fflush(stderr); if (!(fgets(buf, sizeof(buf), stdin))) { fprintf(stderr, "host %s read error\n", hn); goto oops; } p = buf + strlen(buf) - 1; if (*p == '\n') *p = 0; hp->h_result = STRALLOC(buf); fprintf(stderr, "Thanks\n"); fflush(stderr); #endif return 0; } /* * XXX end manual startup hack */ if (!(hp->h_flag & HST_PASSWORD)) { /* use rsh to start */ int wpfd[2], rpfd[2], epfd[2]; int i; if (debugmask) { fprintf(stderr, "phase1() trying rsh to %s\n", hn); } /* fork an rsh to startup the slave pvmd */ #ifdef IMA_TITN if (socketpair(AF_UNIX, SOCK_STREAM, 0, wpfd) == -1 || socketpair(AF_UNIX, SOCK_STREAM, 0, rpfd) == -1 || socketpair(AF_UNIX, SOCK_STREAM, 0, epfd) == -1) { pvmlogperror("phase1() socketpair"); goto oops; } #else if (pipe(wpfd) == -1 || pipe(rpfd) == -1 || pipe(epfd) == -1) { pvmlogperror("phase1() pipe"); goto oops; } #endif if (debugmask) { fprintf(stderr, "phase1() pipes: %d %d %d %d %d %d\n", wpfd[0], wpfd[1], rpfd[0], rpfd[1], epfd[0], epfd[1]); } if ((pid = fork()) == -1) { pvmlogperror("phase1() fork"); pvmbailout(0); } if (!pid) { (void)dup2(wpfd[0], 0); (void)dup2(rpfd[1], 1); (void)dup2(epfd[1], 2); for (i = getdtablesize(); --i > 2; ) (void)close(i); ac = 0; av[ac++] = pvmgetrsh(); av[ac++] = hn; if (hp->h_login) { av[ac++] = "-l"; av[ac++] = hp->h_login; } av[ac++] = hp->h_cmd; av[ac++] = 0; if (debugmask) { for (ac = 0; av[ac]; ac++) fprintf(stderr, "av[%d]=\"%s\" ", ac, av[ac]); fputc('\n', stderr); } execvp(av[0], av); fputs("phase1() execvp failed\n", stderr); fflush(stderr); _exit(1); } (void)close(wpfd[0]); (void)close(rpfd[1]); (void)close(epfd[1]); sp->s_wfd = wpfd[1]; sp->s_rfd = rpfd[0]; sp->s_efd = epfd[0]; } else { /* use rexec to start */ #ifdef NOREXEC log_this("Sorry, xhoster has been compiled without rexec()\n"); log_this("and can't take passwords\n"); goto oops; #else if (debugmask) { fprintf(stderr, "phase1() rexec \"%s\"\n", hp->h_cmd); } if ((sp->s_wfd = sp->s_rfd = rexec(&hn, execport, (hp->h_login ? hp->h_login : username), (hp->h_flag & HST_PASSWORD ? hp->h_pwd : (char *)0), hp->h_cmd, &sp->s_efd)) == -1) { sprintf(scribble, "Permission denied for %s\n", hn); log_this(scribble); goto oops; } #endif } return 0; oops: hp->h_result = STRALLOC("PvmCantStart"); if (sp->s_wfd != -1) close(sp->s_wfd); if (sp->s_rfd != -1) close(sp->s_rfd); if (sp->s_efd != -1) close(sp->s_efd); sp->s_wfd = sp->s_rfd = sp->s_efd = -1; return 1; } ./pvm3/rm/0042755007401100000360000000000010117676455011537 5ustar kohlgopher./pvm3/rm/Makefile0100644007401100000360000000074406364722447013201 0ustar kohlgopher# # $Id: Makefile,v 1.2 1997/07/21 18:06:31 pvmsrc Exp $ # PVMDIR = $(PVM_ROOT) #CC = cc #CFLOPTS = -g PVMOPTS = CC=$(CC) CFLOPTS=$(CFLOPTS) PVMDIR=$(PVMDIR) default: local install: $(PVMDIR)/lib/aimk $(PVMOPTS) install @ ctags -w *.c *.h & local: $(PVMDIR)/lib/aimk $(PVMOPTS) local @ ctags -w *.c *.h & objs: $(PVMDIR)/lib/aimk $(PVMOPTS) objs again: $(PVMDIR)/lib/aimk $(PVMOPTS) again clean: $(PVMDIR)/lib/aimk clean veryclean: $(PVMDIR)/lib/aimk veryclean ./pvm3/rm/Makefile.aimk0100644007401100000360000000264306401365613014107 0ustar kohlgopher# # $Id: Makefile.aimk,v 1.4 1997/08/28 21:20:11 pvmsrc Exp $ # # Generic Makefile body to be concatenated to config header. # # Imports: # PVM_ARCH = the official pvm-name of your processor # ARCHCFLAGS = special cc flags # ARCHLIB = special libs needed for daemon # DEBUG = #DEBUG = -DDEBUG_RM #DEBUG = -DDEBUG_RM_MORE #MESSAGE = MESSAGE = -DMESSAGE_ON DEBUG_FLAGS = $(DEBUG) $(MESSAGE) SHELL = /bin/sh PVMDIR = ../.. PVMIDIR = $(PVMDIR)/include PVMLDIR = $(PVMDIR)/lib/$(PVM_ARCH) PVMLIB = pvm3 LIBPREFIX = lib PVMLIBDEP = $(PVMLDIR)/$(LIBPREFIX)$(PVMLIB).a SDIR = $(PVMDIR)/rm BDIR = $(PVMDIR)/bin XDIR = $(BDIR)/$(PVM_ARCH) CFLOPTS = -g CFLAGS = $(CFLOPTS) -I$(PVMIDIR) $(ARCHCFLAGS) \ -DIMA_$(PVM_ARCH) $(ARCHCFLAGS) \ $(DEBUG_FLAGS) LIBS = -L$(PVMLDIR) -l$(PVMLIB) $(ARCHLIB) HEADERS = $(PVMIDIR)/pvm3.h $(PVMIDIR)/pvmproto.h $(SDIR)/srm.h default: all all: $(XDIR) $(XDIR)/srm$(EXESFX) $(XDIR): - mkdir $(BDIR) - mkdir $(XDIR) $(XDIR)/srm$(EXESFX): srm$(EXESFX) cp srm$(EXESFX) $(XDIR) default: local install: $(XDIR) $(XDIR)/srm$(EXESFX) local: srm$(EXESFX) srm$(EXESFX): srm.o $(XDIR) $(CC) $(CFLAGS) -o $@ srm.o $(LIBS) srm.o: $(SDIR)/srm.c $(HEADERS) $(PVMLIBDEP) $(XDIR) $(CC) $(CFLAGS) -c $(SDIR)/srm.c again: cd $(SDIR) ; touch *.c *.h ; make clean: - rm -f srm$(EXESFX) *.o veryclean: - rm -f srm$(EXESFX) *.o core $(XDIR)/srm$(EXESFX) ./pvm3/rm/OS2/0042755007401100000360000000000010117676455012142 5ustar kohlgopher./pvm3/rm/OS2/Makefile0100644007401100000360000000061706401365556013577 0ustar kohlgopher# # $Id: Makefile,v 1.1 1997/08/28 21:19:42 pvmsrc Exp $ # PVMDIR = ../.. SDIR = $(PVMDIR)/rm PVM_ARCH = OS2 CONFFILE = $(PVMDIR)/conf/$(PVM_ARCH).def LIBDIR = $(PVMDIR)/lib/$(PVM_ARCH) all: make LIBPREFIX="" -f $(CONFFILE) -f $(SDIR)/Makefile.aimk all install: make LIBPREFIX="" -f $(CONFFILE) -f $(SDIR)/Makefile.aimk install clean: make -f $(CONFFILE) -f $(SDIR)/Makefile.aimk clean ./pvm3/rm/srm.c0100644007401100000360000006421007240574605012477 0ustar kohlgopher static char rcsid[] = "$Id: srm.c,v 1.5 2001/02/08 19:54:45 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, K. S. London, R. J. Manchek, * P. Mucci, P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ #include #include #include #include #include "pvm3.h" #include "pvmproto.h" #include "pvmtev.h" #include "../src/global.h" #include "srm.h" #ifdef DEBUG_RM_MORE #ifndef DEBUG_MORE #define DEBUG_MORE #endif #endif static void my_handler(); char *pvmnametag(); int main(argc, argv) int argc; char *argv[]; { HOST_HEAD.next = NULL; HOST_HEAD.prev = NULL; TASK_HEAD.next = NULL; TASK_HEAD.prev = NULL; no_signal = TRUE; loop_init(); return 0; } void start_pvm() { int cc, i, narch, nhost, ntask, se; struct pvmhostinfo *hosts; struct pvmtaskinfo *tasks; pvm_setopt( PvmResvTids, 1 ); pvm_setopt( PvmRoute, PvmDontRoute ); se = pvm_setopt( PvmAutoErr, 0 ); cc = pvm_start_pvmd( 0, (char **) "", FALSE ); if ( cc < 0 ) { if ( cc == PvmDupHost ) { printf( "Connecting to PVMD already running... \n" ); fflush( stdout ); } else { pvm_perror( "Can't Start PVM" ); exit( -1 ); } } else { printf( "New PVMD started...\n" ); fflush( stdout ); } pvm_setopt( PvmResvTids, 1 ); /* Get My TID */ MYTID = pvm_mytid(); if ( MYTID < 0 ) { pvm_perror( "Error Joining PVM" ); exit( -1 ); } else printf( "SRM connected as TID=0x%x.\n", MYTID ); if (pvm_reg_rm(&our_host) != PvmOk) { pvm_perror( "Error registering as Resource Manager" ); exit( -1 ); } else printf( "SRM registered as Resource Manager.\n"); /* signal(SIGTERM, SIG_IGN); */ signal(SIGINT, SIG_IGN); /* if (signal(SIGINT, my_handler) == SIG_ERR) */ /* printf ("Oops problem\n"); */ /* Need to do a config otherwise the first host gets messed up if we start the daemon */ pvm_config ( &nhost, &narch, &hosts ); for ( i = 0; i < nhost; i++ ) add_host ( &(hosts[i]) ); pvm_tasks(0, &ntask, &tasks); for ( i = 0; i < ntask; i++ ) add_task( &(tasks[i])); } int loop_init() { int buf, id, found, handled, i, msgtag, msgtid; struct pvmminfo info; start_pvm ( ); while ( no_signal ) { handled = 0; buf = pvm_recv(-1, -1); pvm_bufinfo(buf, 0, &msgtag, &msgtid); pvm_getminfo(buf, &info); for ( i=0; i < MAX_MESSAGE; i++ ) if (msgtag == Messages[i].msg_tag) { #ifdef MESSAGE_ON printf ("PVMd message is %s from t%x\n", pvmnametag(msgtag,&found), msgtid ); #endif Messages[i].code(msgtid, &info); handled = 1; break; } #ifdef DEBUG_RM if ( !handled ) printf ("Unexpected message with tag %d from t%x\n", msgtag, msgtid ); #endif } return 1; } int sm_spawn(who, info) int who; struct pvmminfo *info; { char arch[100], buf[1000], new_buf[1000], where[100]; int arg_count, count, dest, env_count, flag, i, j, new_tid; int ret_count, sbuf, trc_ctx, trc_tag, trc_tid, out_ctx, out_tag; int out_tid, one = 1; char **argv, **env; struct pvmtaskinfo tinfo; pvm_upkstr ( buf ); pvm_upkint ( &flag, 1, 0 ); pvm_upkstr ( where ); pvm_upkint ( &count, 1, 0 ); arg_count = unpack_list (&argv); pvm_upkint ( &out_tid, 1, 1 ); pvm_upkint ( &out_ctx, 1, 1 ); pvm_upkint ( &out_tag, 1, 1 ); pvm_upkint ( &trc_tid, 1, 1 ); pvm_upkint ( &trc_ctx, 1, 1 ); pvm_upkint ( &trc_tag, 1, 1 ); env_count = unpack_list (&env); #ifdef DEBUG_RM_MORE printf ("Buf %s, Flag %d, Where %s, Out_Tid t%x, Out_ctx %x\n", buf, flag, where, out_tid, out_ctx); printf ("Out_tag %x, Trc_tid %x, Trc_ctx %x, Trc_tag %x\n", out_tag, trc_tid, trc_ctx, trc_tag ); #endif pvm_initsend(PvmDataDefault); pvm_pkint ( &count, 1, 1); pvm_setminfo ( pvm_getsbuf(), info ); for ( i = 0; i < count; i++ ) { if ( flag & PvmTaskArch ) dest = select_host ( flag, arch ); else dest = select_host ( flag, where ); if ( dest ) { sbuf = pvm_setsbuf (pvm_mkbuf(PvmDataDefault)); pvm_pkint(&who, 1, 1); pvm_pkstr(buf); pvm_pkint(&flag, 1, 1); pvm_pkint(&one, 1, 1); pvm_pkint (&arg_count, 1, 1); for (j = 0; j < arg_count; j++) pvm_pkstr ( argv[j] ); pvm_pkint(&out_tid, 1, 1); pvm_pkint(&out_ctx, 1, 1); pvm_pkint(&out_tag, 1, 1); pvm_pkint(&trc_tid, 1, 1); pvm_pkint(&trc_ctx, 1, 1); pvm_pkint(&trc_tag, 1, 1); pvm_pkint(&env_count, 1, 1); sprintf(new_buf, "PVMTMASK=%s", pvmctrc.tmask); pvm_pkstr(new_buf); sprintf(new_buf, "PVMTRCBUF=%d", pvmctrc.trcbuf); pvm_pkstr(new_buf); sprintf(new_buf, "PVMTRCOPT=%d", pvmctrc.trcopt); pvm_pkstr(new_buf); sprintf(new_buf, "PVMCTX=0x%x", pvmmyctx); pvm_pkstr(new_buf); for (j = 0; j < env_count; j++) pvm_pkstr( env[j] ); pvm_setminfo ( pvm_getsbuf(), info ); pvm_send(dest | TIDPVMD, SM_EXEC); pvm_freebuf(pvm_setsbuf(sbuf)); pvm_recv(-1, SM_EXECACK); pvm_upkint(&ret_count, 1, 1); if (ret_count != 1) { printf("sm_spawn: unexpected return count: %d\n" , ret_count); } pvm_upkint(&new_tid, 1, 1); pvm_pkint(&new_tid, 1, 1); tinfo.ti_tid = new_tid; tinfo.ti_ptid = who; tinfo.ti_host = dest; /* tinfo.ti_flag = 0x00000000; */ tinfo.ti_flag = flag; tinfo.ti_a_out = buf; tinfo.ti_pid = 0; add_task(&tinfo); } else { new_tid = PvmNoHost; pvm_pkint(&new_tid, 1, 1); } } pvm_send(who, SM_SPAWN); free_list(argv, arg_count - 2); free_list(env, env_count); return 0; } int sm_exec(who, info) int who; struct pvmminfo *info; { #ifdef DEBUG_RM printf("sm_exec: Should mot be called!\n"); #endif return 0; } int sm_execack(who, info) int who; struct pvmminfo *info; { int count, i; struct pvmtaskinfo task; pvm_upkint ( &count, 1, 1 ); pvm_upkint(&(task.ti_tid), 1, 1); task.ti_ptid = 0; task.ti_host = pvm_tidtohost( task.ti_tid ); task.ti_flag = 0x00000000; task.ti_a_out = "\0"; task.ti_pid = 0; add_task( &task ); return 0; } int sm_task(who, info) int who; struct pvmminfo *info; { int error = 0; int where; task_type *task; host_type *host; pvm_upkint(&where, 1, 1); pvm_initsend(PvmDataDefault); pvm_setminfo ( pvm_getsbuf(), info ); pvm_pkint(&error, 1, 1 ); if ( where == 0 ) { task = find_task ( who ); if ( task ) { #ifdef DEBUG_RM_MORE printf("Sm_task calling find_host\n"); fflush(stdout); #endif host = find_host ( task->entry.ti_host ); where = host->entry.hi_tid; } } pack_task_list(where); pvm_send(who, SM_TASK); return 0; } int sm_config(who, info) int who; struct pvmminfo *info; { pvm_initsend(PvmDataDefault); pvm_setminfo ( pvm_getsbuf(), info ); pack_host_list(); pvm_send(who, SM_CONFIG); return 0; } int sm_addhost(who, info) int who; struct pvmminfo *info; { int count, i, narches; char new_host_arch[100], new_host_name[100]; char **host_names; struct pvmhostinfo newhost; count = unpack_list(&host_names); pvm_initsend(PvmDataDefault); pvm_setminfo ( pvm_getsbuf(), info ); pvm_pkint(&count, 1, 1); for (i = 0; i < count; i++) pvm_pkstr( host_names[i] ); pvm_send(our_host->hi_tid | TIDPVMD, SM_ADD); pvm_recv(-1, SM_ADDACK); pvm_upkint(&count, 1, 1); pvm_upkint(&narches, 1, 1); pvm_initsend(PvmDataDefault); pvm_setminfo ( pvm_getsbuf(), info ); pvm_pkint(&count, 1, 1); pvm_pkint(&narches, 1, 1); #ifdef DEBUG_RM_MORE printf ("Count %d: Arch: %d Tid %d\n", count, narches, newhost.hi_tid); #endif if ( count > 0 ) { newhost.hi_name = new_host_name; newhost.hi_arch = new_host_arch; for (i = 0; i < count; i++) { pvm_upkint(&newhost.hi_tid, 1, 1); #ifdef DEBUG_RM printf ("Newhost hi_tid t%x\n", newhost.hi_tid); #endif if ( newhost.hi_tid > 0 ) /* Error */ { pvm_upkstr( new_host_name ); pvm_upkstr( new_host_arch ); pvm_upkint(&newhost.hi_speed, 1, 1); pvm_upkint(&newhost.hi_dsig, 1, 1); #ifdef DEBUG_RM_MORE printf ("%s %s %d sig%x\n", new_host_name,new_host_arch,newhost.hi_speed, newhost.hi_dsig); #endif add_host( &newhost ); } pvm_pkint(&newhost.hi_tid, 1, 1); pvm_pkstr( new_host_name ); pvm_pkstr( new_host_arch ); pvm_pkint(&newhost.hi_speed, 1, 1); pvm_pkint(&newhost.hi_dsig, 1, 1); } } pvm_send(who, SM_ADDHOST); free_list(host_names, count); return 0; } int sm_delhost(who, info) int who; struct pvmminfo *info; { char **host_names; int count, i, rc; int *status; struct pvmminfo temp_info; temp_info = *info; count = unpack_list(&host_names); status = (int *) malloc( count * sizeof(int) ); /* Can't just use rc since we recursively call pvm_delhosts KSL */ rc = pvm_delhosts( host_names, count, status ); pvm_initsend(PvmDataDefault); pvm_setminfo ( pvm_getsbuf(), &temp_info ); if ( rc == 0 ) /* XXX Look just don't ask KSL */ pvm_pkint(&count, 1, 1); else pvm_pkint(&rc, 1, 1); pvm_pkint(status, 1, 1); pvm_send ( who, SM_DELHOST); free(status); free_list(host_names, count); return 0; } int sm_add(who, info) int who; struct pvmminfo *info; { #ifdef DEBUG_RM printf("sm_add: Should not be called!\n"); #endif return 0; } int sm_addack(who, info) int who; struct pvmminfo *info; { #ifdef DEBUG_RM printf("sm_addack: Should not be called!\n"); #endif return 0; } int sm_notify(who, info) int who; struct pvmminfo *info; { int count, ctx, flags, code, i, notify_tid, vals[200]; pvm_upkint(&flags, 1, 1); pvm_upkint(&ctx, 1, 1); pvm_upkint(&code, 1, 1); pvm_upkint(&count, 1, 1); #ifdef DEBUG_RM_MORE printf ("Flags %x, Who t%x, Code %d, Vals %x, Ctx %d, Count %d\n", flags, who, code, vals[0], ctx, count); #endif if ( flags & PvmNotifyCancel ) { for ( i = 0; i < num_notifys; i++ ) if ( notifylist[i].for_who == who ) del_notification(notifylist[i].for_who, notifylist[i].on_tid); } else if ( flags == PvmHostAdd ) { new_notification(flags, who, code, count, ctx); } else { for (; count > 0; count--) { pvm_upkint(¬ify_tid, 1, 1); #ifdef DEBUG_RM_MORE printf("Setting up notification with flags %d, who t%x, code %d, notify_tid %d, ctx %d", flags, who, code,count, ctx); #endif new_notification(flags, who, code, notify_tid, ctx); } } return 0; } int sm_taskx(who, info) int who; struct pvmminfo *info; { int i, status, tid, error; pvm_upkint (&tid, 1, 1); error = delete_task ( tid ); send_notification( PvmTaskExit, tid ); pvm_upkint (&status, 1, 1); #ifdef DEBUG_RM printf ("sm_taskx: Task t%x, exit with status 0x%x\n", tid, status); #endif return 0; } int sm_hostx(who, info) int who; struct pvmminfo *info; { int error, i, tid; pvm_upkint (&tid, 1, 1); tid &= ~TIDPVMD; /*Quick and Dirty fix */ #ifdef DEBUG_RM_MORE printf ("Attepmpting to delete host t%x\n", tid ); #endif send_notification(PvmHostDelete, tid); error = delete_host ( tid ); #ifdef DEBUG_RM if ( error != -1 ) printf ("sm_hostx: Host t%x deleted.\n", tid); #endif return 0; } int sm_handoff(who, info) int who; struct pvmminfo *info; { #ifdef DEBUG_RM printf ("sm_handoff: This should not be called!\n"); #endif return 0; } int sm_sched(who, info) int who; struct pvmminfo *info; { int error; pvm_initsend ( PvmDataDefault ); pvm_setminfo ( pvm_getsbuf(), info ); pvm_pkint ( &error, 1, 1 ); pvm_send (who, SM_SCHED); return 0; } int sm_sthost(who, info) int who; struct pvmminfo *info; { #ifdef DEBUG_RM printf ("sm_sthost: This should not be called!\n"); #endif return 0; } int sm_sthostack(who, info) int who; struct pvmminfo *info; { #ifdef DEBUG_RM printf ("sm_sthostack: This should not be called!\n"); #endif return 0; } int add_host (host) struct pvmhostinfo *host; { host_type *next_host, *new_host, *temp_host; bool found_arch = FALSE; bool found_host = FALSE; temp_host = &(HOST_HEAD); for (next_host=HOST_HEAD.next;next_host;next_host=next_host->next) { if(!found_arch&&!strcmp( next_host->entry.hi_arch,host->hi_arch)) found_arch = TRUE; temp_host = next_host; if ( next_host->entry.hi_tid == host->hi_tid ) { found_host = TRUE; break; } } if ( found_host ) { #ifdef DEBUG_RM printf ("Host t%x already in the list.\n", host->hi_tid); #endif return -1; } if ( !found_arch ) num_arches++; new_host = (host_type *) malloc (sizeof (host_type) ); temp_host->next = new_host; new_host->prev = temp_host; new_host->next = NULL; new_host->load = 0; new_host->entry.hi_tid = host->hi_tid; new_host->entry.hi_name = (char *) strdup(host->hi_name); new_host->entry.hi_arch = (char *) strdup(host->hi_arch); new_host->entry.hi_speed= host->hi_speed; new_host->entry.hi_dsig = host->hi_dsig; send_notification(PvmHostAdd, host->hi_tid); num_hosts++; #ifdef DEBUG_RM printf ( "Adding host t%x\n", host->hi_tid ); #endif #ifdef DEBUG_RM_HOSTS print_host_contents(); #endif return 0; } int add_task (task) struct pvmtaskinfo *task; { task_type *next_task, *new_task, *temp_task; host_type *host; temp_task = &TASK_HEAD; for(next_task=TASK_HEAD.next;next_task;next_task=next_task->next) { if (next_task->entry.ti_tid == task->ti_tid) { #ifdef DEBUG_RM printf ("Task already added\n"); #endif return -1; } temp_task = next_task; } new_task = (task_type *) malloc (sizeof (task_type) ); temp_task->next = new_task; new_task->prev = temp_task; new_task->next = NULL; new_task->entry.ti_tid = task->ti_tid; new_task->entry.ti_ptid = task->ti_ptid; new_task->entry.ti_host = task->ti_host; new_task->entry.ti_flag = task->ti_flag; new_task->entry.ti_a_out= (char *) strdup( task->ti_a_out ); new_task->entry.ti_pid = task->ti_pid; #ifdef DEBUG_RM_MORE printf("add_task calling find_host\n"); fflush(stdout); #endif host = find_host( task->ti_host ); if ( host ) host->load++; #ifdef DEBUG_RM else printf ("Hmmmm no host found for t%x", task->ti_host ); printf ("Adding task t%x\n", task->ti_tid ); #endif #ifdef DEBUG_RM_TASKS print_task_contents(); #endif return 0; } int select_host (flag, where) int flag; char * where; { host_type *best_host, *next_host; /* Put load balancing code here */ next_host = HOST_HEAD.next; best_host = HOST_HEAD.next; for ( ; next_host ; next_host = next_host->next ) { if ( (flag & PvmTaskArch) && strcmp(where, next_host->entry.hi_name) ) continue; if ( (flag & PvmTaskHost) && strcmp(where, next_host->entry.hi_name) ) continue; if ( next_host->load < best_host->load ) best_host = next_host; } #ifdef MESSAGE_ON printf ("Host selected: %s\n", best_host->entry.hi_name ); #endif #ifdef DEBUG_RM_MORE printf ("Host tid: t%x\n", best_host->entry.hi_tid); fflush(stdout); #endif return best_host->entry.hi_tid; } int delete_host ( tid ) int tid; { host_type *next, *next_host; bool found = FALSE; for ( next = HOST_HEAD.next; next; next = next->next ) if ( next->entry.hi_tid == tid ) { found = TRUE; break; } if ( !found ) { #ifdef DEBUG_RM printf ( "delete_host: Host t%x not found.\n\r", tid ); #endif return -1; } found = FALSE; for (next_host=HOST_HEAD.next;next_host;next_host=next_host->next) if (!strcmp (next_host->entry.hi_arch, next->entry.hi_arch) ) { found = TRUE; break; } if ( !found ) num_arches--; next->prev->next = next->next; if ( next->next ) next->next->prev = next->prev; free ( next ); num_hosts--; return 0; } int delete_task ( tid ) int tid; { host_type *host; task_type *next; bool found = FALSE; for ( next = TASK_HEAD.next; next; next = next->next) if ( next->entry.ti_tid == tid ) { found = TRUE; break; } if ( !found ) { #ifdef DEBUG_RM printf ("delete_task: Task t%x not found.\n", tid ); #endif return -1; } #ifdef DEBUG_RM_MORE printf("delete_task calling find_host\n"); fflush(stdout); #endif host = find_host ( next->entry.ti_host ); if ( host ) host->load--; #ifdef DEBUG_RM else printf ("Hmmm host t%x not found\n", next->entry.ti_host ); #endif next->prev->next = next->next; if ( next->next ) next->next->prev = next->prev; free ( next ); return 0; } int unpack_list(str_list) char ***str_list; { int i, count = 0; char temp_str[1000]; pvm_upkint( &count, 1, 1 ); *str_list = (char **) malloc( (count + 1) * sizeof(char *)); for (i = 0 ; i < count; i++ ) { pvm_upkstr( temp_str ); (*str_list)[i] = (char *) strdup( temp_str ); } (*str_list)[i] = 0; return count; } int free_list(str_list, count) char **str_list; int count; { int i; for (i = 0; i < count; i++) { free(str_list[i]); } free(str_list); return 0; } int pack_host(host) struct pvmhostinfo *host; { pvm_pkint(&(host->hi_tid), 1, 1); pvm_pkstr(host->hi_name); pvm_pkstr(host->hi_arch ? host->hi_arch : "" ); pvm_pkint(&(host->hi_speed), 1, 1); pvm_pkint(&(host->hi_dsig), 1, 1); return 0; } int pack_host_list() { host_type *next_host; pvm_pkint(&num_hosts, 1, 1); pvm_pkint(&num_arches, 1, 1); for ( next_host = HOST_HEAD.next;next_host;next_host=next_host->next) pack_host(&(next_host->entry)); return 0; } int pack_task(task) task_type *task; { pvm_pkint(&(task->entry.ti_tid), 1, 1); pvm_pkint(&(task->entry.ti_ptid), 1, 1); pvm_pkint(&(task->entry.ti_host), 1, 1); pvm_pkint(&(task->entry.ti_flag), 1, 1); pvm_pkstr(task->entry.ti_a_out); pvm_pkint(&(task->entry.ti_pid), 1, 1); return 0; } int pack_task_list(where) int where; { task_type *next_task; host_type *host; #ifdef DEBUG_RM_MORE printf("pack_task_list calling find host\n"); fflush(stdout); #endif host = find_host(where); for (next_task=TASK_HEAD.next; next_task; next_task = next_task->next) { if ( where == 0 || (host != NULL && next_task->entry.ti_host == host->entry.hi_tid ) || ( next_task->entry.ti_tid == where ) ) pack_task(next_task); } return 0; } host_type * find_host(tid) int tid; { host_type *next_host; for ( next_host = HOST_HEAD.next;next_host;next_host=next_host->next ) { if ( next_host->entry.hi_tid == tid ) return next_host; } return HOST_HEAD.next; /* XXX Needs to be fixed */ } task_type * find_task(tid) int tid; { task_type *next_task; for ( next_task = TASK_HEAD.next;next_task;next_task=next_task->next) { if ( next_task->entry.ti_tid == tid ) return next_task; } return NULL; /* XXX Needs to be fixed */ } int send_notification(kind, on_tid) int kind, on_tid; { int i, sbuf; struct pvmhostinfo *notify_host; host_type *host; for (i = 0; i < num_notifys; i++) { if (notifylist[i].kind == kind && ((kind == PvmHostAdd) || (notifylist[i].on_tid == on_tid))) { sbuf = pvm_setsbuf(pvm_mkbuf(PvmDataDefault)); if (kind == PvmTaskExit) { pvm_pkint(&on_tid, 1, 1); } else { #ifdef DEBUG_RM_MORE printf ("Send_notification calling find host.\n"); fflush(stdout); #endif host = find_host(on_tid); notify_host = &(host->entry); pack_host(notify_host); } pvm_send(notifylist[i].for_who, notifylist[i].msg_tag); if ( kind == PvmHostAdd && notifylist[i].on_tid == 1 ) { del_notification(notifylist[i].for_who, notifylist[i].on_tid ); i--; } else if ( kind == PvmHostAdd ) notifylist[i].on_tid --; else if ( kind == PvmHostDelete || kind == PvmTaskExit) { del_notification(notifylist[i].for_who, notifylist[i].on_tid ); i--; } pvm_freebuf(pvm_setsbuf(sbuf)); } } return 0; } int del_notification(for_who, on_tid) int for_who, on_tid; { int i, j; for (i = 0; i < num_notifys; i++) if (notifylist[i].for_who == for_who && notifylist[i].on_tid == on_tid) { break; } if (i >= num_notifys) { #ifdef DEBUG_RM fprintf(stderr, "del_notification: Unable to find notify struct\n"); #endif return -1; } for ( j = (i+1); j < num_notifys; j++,i++ ) notifylist[i] = notifylist[j]; #ifdef DEBUG_RM printf ("Deleteing notify\n"); #endif #ifdef DEBUG_RM_NOTIFY print_notify_contents(); #endif num_notifys--; return 0; } int new_notification(kind, for_who, msg_tag, on_tid, ctx) int kind, for_who, msg_tag, on_tid, ctx; { int i; #ifdef DEBUG_RM_MORE printf ("For_whom t%x, On_tid t%x\n", for_who, on_tid); #endif if (notify_list_size == 0) { notify_list_size = 10; notifylist = (struct notification *) malloc(notify_list_size * sizeof(struct notification)); } if (num_notifys + 1 >= notify_list_size) { notify_list_size *= 2; notifylist = (struct notification *) realloc(notifylist, notify_list_size * sizeof(struct notification)); } notifylist[num_notifys].kind = kind; notifylist[num_notifys].for_who = for_who; notifylist[num_notifys].msg_tag = msg_tag; notifylist[num_notifys].on_tid = on_tid; notifylist[num_notifys].m_ctx = ctx; num_notifys++; #ifdef DEBUG_RM printf ("Setting up notify with kind %d\n", kind); #endif #ifdef DEBUG_RM_NOTIFY print_notify_contents(); #endif return 0; } int print_task_contents() { task_type *task; int i = 0; for ( task= TASK_HEAD.next; task; task = task->next) { printf("\n"); printf("Entry %d\n", i); printf("Task Tid t%x\n",task->entry.ti_tid); printf("Task PTid t%x\n",task->entry.ti_ptid); printf("Task Host t%x\n",task->entry.ti_host); printf("Task Flag %d\n",task->entry.ti_flag); printf("Task A_Out %s\n",task->entry.ti_a_out); printf("Task Pid t%x\n",task->entry.ti_pid); i++; } return 1; } int print_notify_contents() { int i = 0; printf("Here\n"); for ( i = 0; i < num_notifys; i++ ) { printf("\n"); printf("Kind %d\n", notifylist[i].kind ); printf("For who t%x\n", notifylist[i].for_who ); printf("Msg tag %d\n", notifylist[i].msg_tag ); printf("On_tid t%x\n", notifylist[i].on_tid ); printf("Context %d\n", notifylist[i].m_ctx ); } fflush(stdout); return 1; } int print_host_contents() { host_type *host; int i = 0; for ( host= HOST_HEAD.next; host; host = host->next) { printf("\n"); printf("Entry %d\n", i); printf("Load %d\n",host->load); printf("Host Tid t%x\n",host->entry.hi_tid); printf("Host name %s\n",host->entry.hi_name); printf("Host arch %s\n",host->entry.hi_arch); printf("Host speed %d\n",host->entry.hi_speed); printf("Host signature %x\n",host->entry.hi_dsig); i++; } return 1; } static void my_handler( signo ) int signo; { int cc,sbf, rbf; sbf = pvm_setsbuf(pvm_mkbuf(PvmDataDefault)); rbf = pvm_setrbuf(0); cc = (msendrecv(TIDPVMD, TM_HALT, SYSCTX_TM) < 0) ? 0 : PvmSysErr; pvm_freebuf(pvm_setsbuf(sbf)); pvm_setrbuf(rbf); no_signal = FALSE; printf ("Pvm halted....\n"); fflush(stdout); return; } ./pvm3/rm/srm.h0100644007401100000360000001267406367432657012524 0ustar kohlgopher /* $Id: srm.h,v 1.2 1997/07/29 18:25:51 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, K. S. London, R. J. Manchek, * P. Mucci, P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* Dynamic resource code for PVM has been developed by many different * groups and people over the last 3 years. * Thanks goes to the following: * Technische Universitat Munchen, University of Wisconsin Madison and * the University of Reading UK. * * Special thanks to the CoCheck team for being the first to attempt a * real RM (we found almost all the bugs now, thanks) * * */ #if !defined(FALSE) #define FALSE 0 #endif #if !defined(TRUE) #define TRUE 1 #endif #define MAX_MESSAGE 16 /* Make sure this number stays right :) */ /* Structure definitions */ typedef int bool; typedef struct HOST_TYPE host_type; typedef struct MESSAGE_TYPE message_type; typedef struct TASK_TYPE task_type; struct HOST_TYPE { struct pvmhostinfo entry; host_type *next; host_type *prev; int load; }; struct MESSAGE_TYPE { int msg_tag; int (*code)(); }; struct TASK_TYPE { struct pvmtaskinfo entry; task_type *next; task_type *prev; }; struct notification { int kind; int for_who; int msg_tag; int on_tid; int m_ctx; } *notifylist; int MYTID; int notify_list_size = 0; int num_arches = 0; int num_hosts = 0; int num_notifys = 0; int num_tasks = 0; int task_list_size = 0; host_type HOST_HEAD; task_type TASK_HEAD; struct pvmhostinfo *host; struct pvmhostinfo *our_host; struct pvmhostinfo *LOCAL_HOST; extern struct Pvmtracer pvmctrc; extern int pvmmyctx; extern struct Pvmtracer pvmtrc; /* Function Prototypes */ int add_host ( ); int add_task ( ); int delete_host ( ); int del_notification ( ); int delete_task ( ); task_type * find_task ( ); host_type * find_host ( ); int free_list ( ); int new_notification ( ); int pack_host_list ( ); int pack_task_list ( ); int select_host ( ); int send_notification ( ); int sm_spawn ( ); int sm_exec ( ); int sm_execack ( ); int sm_task ( ); int sm_config ( ); int sm_addhost ( ); int sm_delhost ( ); int sm_add ( ); int sm_addack ( ); int sm_notify ( ); int sm_taskx ( ); int sm_hostx ( ); int sm_handoff ( ); int sm_sched ( ); int sm_sthost ( ); int sm_sthostack ( ); int loop_init ( ); int unpack_string ( ); message_type Messages[MAX_MESSAGE] = { /* Message Tag Message Code */ { SM_TASK, sm_task }, /* 0 */ { SM_TASKX, sm_taskx }, { SM_SPAWN, sm_spawn }, { SM_EXEC, sm_exec }, { SM_EXECACK, sm_execack }, { SM_CONFIG, sm_config }, /* 5 */ { SM_ADDHOST, sm_addhost }, { SM_DELHOST, sm_delhost }, { SM_ADD, sm_add }, { SM_ADDACK, sm_addack }, { SM_NOTIFY, sm_notify }, /* 10 */ { SM_HOSTX, sm_hostx }, { SM_HANDOFF, sm_handoff }, { SM_SCHED, sm_sched }, { SM_STHOST, sm_sthost }, { SM_STHOSTACK, sm_sthostack } /* 15 */ }; #ifdef DEBUG_RM_MORE #ifndef DEBUG_MORE #define DEBUG_MORE #endif #endif bool no_signal; ./pvm3/shmd/0042755007401100000360000000000010117676455012054 5ustar kohlgopher./pvm3/shmd/Makefile.aimk0100644007401100000360000000774006672022525014431 0ustar kohlgopher# # $Id: Makefile.aimk,v 1.4 1999/03/11 20:19:33 pvmsrc Exp $ # # Generic Makefile body to be concatenated to config header. # # Imports: # PVM_ARCH = the official pvm-name of your processor # ARCHCFLAGS = special cc flags # ARCHLIB = special libs needed for daemon # HASRANLIB = 't' or 'f' # # Define: # NOSTRCASE if libc doesn't have strcasecmp, strncasecmp # SYSVSIGNAL for system5 signal handling # SYSVSTR for strchr() instead of index() # SHELL = /bin/sh PVMDIR = ../.. SDIR = $(PVMDIR)/shmd DOBJ = pvm_shmd.o block.o sem.o tidinfo.o LOBJ = sendrecv.o block.o sem.o tidinfo.o lpvm.o PVMIDIR = $(PVMDIR)/include PVMSDIR = $(PVMDIR)/src PVMSLDIR = $(PVM_ROOT)/src PVMBDIR = $(PVMDIR)/bin PVMXDIR = $(PVMBDIR)/$(PVM_ARCH) PVMLDIR = $(PVMDIR)/lib/$(PVM_ARCH) PVMLODIR = $(PVM_ROOT)/src/$(PVM_ARCH) LPOBJ = \ $(PVMLODIR)/imalloc.o $(PVMLODIR)/tev.o $(PVMLODIR)/lpvmcat.o $(PVMLODIR)/lpvmgen.o \ $(PVMLODIR)/lpvmpack.o $(PVMLODIR)/lpvmglob.o $(PVMLODIR)/pmsg.o $(PVMLODIR)/pvmalloc.o \ $(PVMLODIR)/pvmcruft.o $(PVMLODIR)/pvmerr.o $(PVMLODIR)/pvmfrag.o $(PVMLODIR)/waitc.o \ $(PVMLODIR)/pvmregex.o $(PVMLODIR)/regex.o $(PVMLODIR)/global.o $(PVMLODIR)/pvmdabuf.o PVMLIB = pvm3 LIBPREFIX = lib PVMLIBDEP = $(PVMLDIR)/$(LIBPREFIX)$(PVMLIB).a CFLAGS = $(CFLOPTS) -I$(PVMIDIR) -I$(PVMSDIR) -DIMA_$(PVM_ARCH) \ $(ARCHCFLAGS) -DSEM LIBS = $(LOPT) -L$(PVMLDIR) -l$(PVMLIB) $(ARCHLIB) DIRS = $(PVMXDIR) $(PVMLDIR) PROGS = $(PVMXDIR)/pvm_shmd_stat$(EXESFX) \ $(PVMXDIR)/pvm_shmd$(EXESFX) LPROGS = $(PVMLDIR)/pvm_shmd$(EXESFX) LIBSHMDPVM = $(LIBPREFIX)pvm3shmd.a install: all install-mpp: all-mpp all: $(DIRS) $(PROGS) $(PVMLDIR)/$(LIBSHMDPVM) $(LPROGS) all-mpp: $(DIRS) $(PROGS) $(PVMLDIR)/$(LIBSHMDPVM)-mpp $(LPROGS) $(PVMXDIR): - mkdir $(PVMBDIR) - mkdir $(PVMXDIR) $(PVMLDIR): - mkdir $(PVMLDIR) $(PVMXDIR)/pvm_shmd_stat$(EXESFX): pvm_shmd_stat$(EXESFX) cp pvm_shmd_stat$(EXESFX) $(PVMXDIR) $(PVMXDIR)/pvm_shmd$(EXESFX): pvm_shmd$(EXESFX) cp pvm_shmd$(EXESFX) $(PVMXDIR) $(PVMLDIR)/$(LIBSHMDPVM): $(LIBSHMDPVM) cp $(LIBSHMDPVM) $(PVMLDIR) case x$(HASRANLIB) in xt ) echo ranlib; ranlib $(PVMLDIR)/$(LIBSHMDPVM) ;; esac $(PVMLDIR)/$(LIBSHMDPVM)-mpp: $(LIBSHMDPVM)-mpp cp $(LIBSHMDPVM) $(PVMLDIR) case x$(HASRANLIB) in xt ) echo ranlib; ranlib $(PVMLDIR)/$(LIBSHMDPVM) ;; esac touch $(PVMLDIR)/$(LIBSHMDPVM)-mpp $(PVMLDIR)/pvm_shmd$(EXESFX): pvm_shmd$(EXESFX) cp pvm_shmd $(PVMLDIR) pvm_shmd$(EXESFX): $(DOBJ) $(PVMLIBDEP) $(CC) $(CFLAGS) -o $@ $(DOBJ) $(LIBS) pbwtest.shmd: ../../examples/bwtest.c $(XDIR) $(CC) $(CFLAGS) -o $@ ../../examples/bwtest.c -L$(PVMLDIR) \ -lpvm3shmd -lgpvm3 mv $@ $(PVMXDIR) $(LIBSHMDPVM): $(LOBJ) $(LPOBJ) rm -f $(LIBSHMDPVM) $(AR) cr $(LIBSHMDPVM) $(LOBJ) $(LPOBJ) case x$(HASRANLIB) in xt ) echo ranlib; ranlib $(LIBSHMDPVM) ;; esac $(LIBSHMDPVM)-mpp: $(LOBJ) rm -f $(LIBSHMDPVM) $(AR_FRONT) cr $(LIBSHMDPVM) $(LOBJ) case x$(HASRANLIB) in xt ) echo ranlib; ranlib $(LIBSHMDPVM) ;; esac touch $(LIBSHMDPVM)-mpp pvm_shmd_stat$(EXESFX): pvm_shmd_stat.o $(LIBSHMDPVM) $(PVMLIBDEP) $(CC) $(CFLAGS) -o $@ pvm_shmd_stat.o $(LIBSHMDPVM) $(LIBS) clean: rm -f $(DOBJ) $(LOBJ) pvm_shmd$(EXESFX) $(LIBSHMDPVM) \ pvm_shmd_stat.o pvm_shmd_stat$(EXESFX) tidy: rm -f $(DOBJ) $(LOBJ) lint: lint -DARCHCLASS=\"$(PVM_ARCH)\" pvm_shmd.c > Ld lint -DARCHCLASS=\"$(PVM_ARCH)\" sendrecv.c > Ll # block.o: $(SDIR)/block.c $(CC) $(CFLAGS) -c $(SDIR)/block.c sem.o: $(SDIR)/sem.c $(CC) $(CFLAGS) -c $(SDIR)/sem.c tidinfo.o: $(SDIR)/tidinfo.c $(CC) $(CFLAGS) -c $(SDIR)/tidinfo.c pvm_shmd.o: $(SDIR)/pvm_shmd.c $(CC) $(CFLAGS) -c $(SDIR)/pvm_shmd.c pvm_shmd_stat.o: $(SDIR)/pvm_shmd_stat.c $(CC) $(CFLAGS) -c $(SDIR)/pvm_shmd_stat.c sendrecv.o: $(SDIR)/sendrecv.c $(CC) $(CFLAGS) -c $(SDIR)/sendrecv.c # # OK to build a complete user lib we need to recompile the lpvm file # lpvm.o: $(PVMSLDIR)/lpvm.c $(CC) $(CFLAGS) -DPVM_SHMD -c $(PVMSLDIR)/lpvm.c # # Source File Dependencies # include $(PVMDEPPATH)$(SDIR)/pvmdep ./pvm3/shmd/pvmdep0100644007401100000360000000062206667576747013307 0ustar kohlgopher# # *** DO NOT MODIFY *** AUTOMATICALLY GENERATED *** # # $Id: pvmdep,v 1.1 1999/03/04 21:40:55 pvmsrc Exp $ # # PVM Source Header Dependencies # block.o: $(SDIR)/shmd.h pvm_shmd.o: $(PVMDIR)/include/pvm3.h pvm_shmd.o: $(SDIR)/shmd.h pvm_shmd_stat.o: $(PVMDIR)/include/pvm3.h pvm_shmd_stat.o: $(SDIR)/shmd.h sendrecv.o: $(PVMDIR)/include/pvm3.h sendrecv.o: $(SDIR)/shmd.h tidinfo.o: $(SDIR)/shmd.h ./pvm3/shmd/block.c0100644007401100000360000001775306667575611013331 0ustar kohlgopher static char rcsid[] = "$Id: block.c,v 1.1 1999/03/04 21:30:49 pvmsrc Exp $"; #include #include #include "shmd.h" /* int get(); */ /* int back(); */ /* void map(); */ int initblocks (blkptr, psize, npages, semkey, segkey, semid, segid) blockinfo_t* blkptr; int psize, npages; key_t semkey; key_t segkey; /* used for info only */ int semid, segid; { int i,j; int r,s; blkptr->semkey = semkey; blkptr->segkey = segkey; blkptr->semid = semid; blkptr->segid = segid; blkptr->psize = psize; if (npagesnpages = npages; else blkptr->npages = MAXPAGESALLOWED; /* should log a warning here */ blkptr->pagesfree = blkptr->npages; blkptr->largestblockfree = blkptr->npages; blkptr->largeststart = 0; /* i.e. at the very very start */ /* stats setup */ blkptr->totalallocated = 0; blkptr->totalfreed = 0; blkptr->jumpsaved = 0; blkptr->firstfound = 0; blkptr->highestutilised = 0; blkptr->largestused = 0; /* now we can setup the block/pagemap */ for(i=0;ipagemap[i] = npages-i; return (blkptr->npages); /* return the number of pages provided */ } int getblocks(blkptr, id, size) blockinfo_t* blkptr; int id, size; { /* here we find first place where the section will fit */ int i,j,k; #if SEM lock_sem (blkptr->semid, 0); #endif /* SEM */ for (i=0;inpages;i++) { if (blkptr->pagemap[i] >= size) { /* found a block! */ /* first mark it as ours */ /* could use a copy operation here todo[] */ for(j=i;j<(i+size);j++) blkptr->pagemap[j] = -id; blkptr->pagesfree -= size; /* STATS */ /* these will be ifdef'd later */ blkptr->totalallocated+= size; if (blkptr->highestutilised < (blkptr->npages - blkptr->pagesfree)) blkptr->highestutilised = (blkptr->npages - blkptr->pagesfree); if (blkptr->largestused < size) blkptr->largestused = size; /* to set largest block free and largest start will take a search */ /* so we will worry about them later. */ /* todo[] */ /* unless we can make an assumption.. */ /* which does fail BTW! */ /* have just put it here to see how usefull it is.. */ blkptr->largestblockfree -= size; /* bad */ blkptr->largeststart = i+size; /* possibly worse */ #if SEM unlock_sem (blkptr->semid, 0); #endif /* SEM */ return (i); /* i.e. where we started the allocation */ } /* end we found one */ if (blkptr->pagemap[i]>0) /* i.e. we are in a block that is too small */ /* jump ahead by the size of the block that is too small */ { blkptr->jumpsaved += (blkptr->pagemap[i]) -1; i += (blkptr->pagemap[i]) -1; } } /* else just do a linear search (yuck) */ #if SEM unlock_sem (blkptr->semid, 0); #endif /* SEM */ return (-1); /* no single block big enough! */ } int freeblock_by_id(blkptr, id) blockinfo_t* blkptr; int id; { int i, j; int freed=0; /* NOTE */ /* can only be called by owner of segments */ /* i.e. pvm_shmd or sniped/snipe_shmd */ /* Does not lock segment as it calls a routine which does and therefore */ /* would lock itself out... */ /* Is safe in that freeblock() calls lock and */ /* this routine only changes pages that belond to a DEAD task */ /* Weak assumptions, but true */ /* short cuts */ /* if none allocated in this segment, then just return */ if (blkptr->npages == blkptr->pagesfree) return (freed); /* do a linear search of blocks and when you find one that matches */ /* nuke it (i.e. call freeblock() on it */ for(i=0;inpages;i++) { if ((blkptr->pagemap[i])==(-id)) { /* we have the start of a matching block */ #ifdef BLOCKDEBUG printf("Block started at [%d]\n", i); #endif /* BLOCKDEBUG */ for (j=0;j<((blkptr->npages)-i);j++) if ((blkptr->pagemap[i+j])!=(-id)) break; /* j = size of section owned by id in blocks */ #ifdef BLOCKDEBUG printf("block owned by [%d] found at [%d] of length [%d]\n", id, i, j); #endif /* BLOCKDEBUG */ freed += freeblock (blkptr, id, j, i); /* free it */ /* this does all the stats for us as well... */ } else if(blkptr->pagemap[i]>0) { blkptr->jumpsaved += (blkptr->pagemap[i])-1; i += (blkptr->pagemap[i])-1; } } /* for linear search with hops(tm) */ #ifdef BLOCKDEBUG if(freed) { printf("Total pages previously owned by [%d] freed [%d]\n", id, freed); printf("Total pages free in segment [0x%x] is now [%d]\n", blkptr->segkey, blkptr->pagesfree); } else printf("No pages owned by [%d] found in this segment [0x%x]\n", id, blkptr->segkey); #endif /* BLOCKDEBUG */ return (freed); } int freeblock(blkptr, id, size, where) blockinfo_t* blkptr; int id, size, where; /* where is in blocks from 0..npages-1 */ /* not an abs addr yet */ { int i,j,k,last; int after=0; /* number free after last in our block... */ #if SEM lock_sem (blkptr->semid, 0); #endif /* SEM */ /* first 3 checks paranoid but safer */ /* first check, right address ? */ if (blkptr->pagemap[where]!=(-id)) { fprintf(stderr,"Help, block belongs to wrong task!\n"); #if SEM unlock_sem (blkptr->semid, 0); #endif /* SEM */ return(-1); } /* is block too big ? */ if ((where+size)>blkptr->npages) { fprintf(stderr,"Help, block is too big to fit in segment?!\n"); #if SEM unlock_sem (blkptr->semid, 0); #endif /* SEM */ return(-1); } last = where+size -1; /* last block in this set of pages */ /* check last block? */ /* instead of checking them all... */ /* note, this check my introduce page faults, except we use it as */ /* the start of our readdressing of pages loop 8) */ /* so, we use that page again straight away.... */ if ((blkptr->pagemap[last]) != -id) { fprintf(stderr,"Help, block is not all ours?!\n"); #if SEM unlock_sem (blkptr->semid, 0); #endif /* SEM */ return(-1); } /* ok, get after value... */ if (last==(blkptr->npages-1)) /* i.e. on the edge */ after = 0; /* boundary */ else after = blkptr->pagemap[last+1]; /* not on the edge so get the count! */ if (after<0) after = 1; /* as after maybe an identifer value */ /* instead of a count */ /* note =1 instead of 1 so that we don't have */ /* to increment later */ else /* increment after as we are one space to the left... */ after++; for (i=last;i>=where;i--) /* fill 'em back in */ blkptr->pagemap[i] = after++; /* incrementing as we go... */ /* well now we need to check to see if we have run into any other */ /* free blocks and if so, we can keep on adding them bad boys together */ #ifdef BLOCKDEBUG printf("where[%d], i[%d], after[%d]\n", where, i, after); #endif /* BLOCKDEBUG */ for(j=where-1;j>=0; j--) if (blkptr->pagemap[j] > 0) blkptr->pagemap[j] = after++; else break; /* found a reserved block, so stop! */ #ifdef BLOCKDEBUG printf("later j+1[%d] new large block of [%d]\n", j, blkptr->pagemap[j+1]); #endif /* BLOCKDEBUG */ /* and yes.. we now have a few more pages free.. */ blkptr->pagesfree += size; /* optional STATS */ if (blkptr->largestblockfree < blkptr->pagemap[j+1]) { blkptr->largestblockfree = blkptr->pagemap[j+1]; blkptr->largeststart = j+1; #ifdef BLOCKDEBUG printf("New largest block at [%d] of size [%d]\n", blkptr->largeststart, blkptr->largestblockfree); #endif /* BLOCKDEBUG */ } blkptr->totalfreed += size; #if SEM unlock_sem (blkptr->semid, 0); #endif /* SEM */ return (size); /* how many did we free */ } void blockmap(blkptr) blockinfo_t* blkptr; { int i,j; #if SEM lock_sem (blkptr->semid, 0); #endif /* SEM */ printf("Info and Block map for segment [0x%x]\n", blkptr->segkey); for(i=0;inpages;i++) printf("%3d\t", blkptr->pagemap[i]); printf("\n\n"); printf("Pages free left=[%d]\n", blkptr->pagesfree); printf("Total pages asked for [%d]\n", blkptr->totalallocated); printf("Total pages freed [%d]\n", blkptr->totalfreed); printf("Jumps saved [%d] steps\n", blkptr->jumpsaved); printf("Found first time [%d]\n", blkptr->firstfound); printf("Highest utilisation [%d]\n", blkptr->highestutilised); printf("Largest block used [%d]\n", blkptr->largestused); #if SEM unlock_sem (blkptr->semid, 0); #endif /* SEM */ } ./pvm3/shmd/pvm_shmd.c0100644007401100000360000003310606672273617014037 0ustar kohlgopher static char rcsid[] = "$Id: pvm_shmd.c,v 1.2 1999/03/12 20:22:39 pvmsrc Exp $"; #include #include #include #include #include #include #include #include #include #include #include #include /* GEF libs */ #include "shmd.h" /* Prototypes */ unsigned int get_max_seg_size(); unsigned int create_segments(); void clean_segs(); int make_mqueue(); int del_mqueue(); void bambismother(); void huphuphup(); /* Consts */ /* #define MAXSEGS 255 */ /* in the header files now */ /* well its a limit and we do need one */ /* can be controlled by ifdef or ENV vars */ /* at run-time */ #ifndef SHM_FAILED #define SHM_FAILED (void*)-1 #endif #define FAILEDCOUNT (10) /* Globals */ unsigned segsize; unsigned numsegs; key_t keys[MAXSEGS]; int shmids[MAXSEGS]; void* segptrs[MAXSEGS]; unsigned totalmem; main(argc, argv) int argc; char *argv[]; { int i,id; key_t key; int semid; struct shmid_ds shmsbuf; unsigned size; int pagesize; size_t bsize, bsizepb, o1, o2, o3; /* for working out mem offsets */ int pages[MAXSEGS]; char* addr; unsigned firstpagehdr; int tid; int bufid, from, bytes, msgtag; int died; int tidslots; /* not an array, but number of tids I can handle at once */ int slot, left, join; key_t mqkey; int mqid; int j, cc; int finished=0; /* first things first */ /* The PVM stuff */ tid = pvm_mytid(); if (tid<=0) { fprintf(stderr,"Cannot join the virtual machine.\n"); exit (-3); } if (register_shmd (tid)) { fprintf(stderr,"Cannot setup system mailbox entry.\n"); exit (-4); } o1 = (size_t) (16*1024); /* first offset is a 16K block */ /* calculate offsets into shmpages */ pagesize = getpagesize(); bsize = sizeof (blockinfo_t); /* calculate blockinfo size in whole pages (on page boundary) */ if (bsize%pagesize) bsizepb = ((bsize/pagesize)+1) * pagesize; else bsizepb = (bsize); key = (key_t) (0x2d000000+((int)getuid()*0x1000)); /* inital key */ /* segsize = get_max_seg_size(); */ segsize = get_max_seg_size(pagesize); /* printf("seg size %d %x\n", segsize, segsize); exit (-1); */ /* numsegs = create_segments(key, keys, shmids, segptrs, MAXSEGS); */ numsegs = create_segments(key, MAXSEGS); if (numsegs<2) { fprintf(stderr,"WARNING:\nCan not create 2 or more segments.\nExiting.\n"); fflush(stderr); clean_segs(); exit (-2); } for(i=0;isegoffset = firstpagehdr; /* first page starts after header */ /* First page offsets */ ((blockinfo_t*)addr)->nextoffset = bsizepb; /* and the previous is wrapped around... */ ((blockinfo_t*)addr)->previousoffset = (numsegs-1) * bsizepb; /* all other segments are just for message info */ for(i=1;isegoffset = 0; /* i.e. first page is at the head of the seg */ /* offsets to previous / next blockinfo structs */ if (i<(numsegs-1)) ((blockinfo_t*)addr)->nextoffset = bsizepb; else /* wrap around */ ((blockinfo_t*)addr)->nextoffset = -((numsegs-1) * bsizepb); ((blockinfo_t*)addr)->previousoffset = -bsizepb; } /* previous/next wrap around tests */ /* first forwards */ printf("Forwards loop\n"); addr = o1 + (char*)segptrs[0]; for(i=0;i<=numsegs;i++) { printf("segkey [0x%x]\t", ((blockinfo_t*)addr)->segkey ); addr += ((blockinfo_t*)addr)->nextoffset; } printf("\n\n"); /* backwards */ printf("Backwards loop\n"); addr = o1 + (char*)segptrs[0]; for(i=0;i<=numsegs;i++) { printf("segkey [0x%x]\t", ((blockinfo_t*)addr)->segkey ); addr += ((blockinfo_t*)addr)->previousoffset; } printf("\n\n"); for(i=0;inumsegs = numsegs; /* should check tidslots here TODO */ /* Safe to register myself now */ if (register_shmd (tid, shmids[0])) { fprintf(stderr,"Cannot setup system mailbox entry.\n"); exit (-4); } /* now the pvm daemon knows we are here */ /* when it exits it sends up a TERM so that we can exit neatly */ /* we also catch a HUP for completeness */ (void) signal (SIGTERM, bambismother); #ifndef LINUX (void) sigset (SIGTERM, bambismother); /* yes I mean it, ok ? */ #endif (void) signal (SIGHUP, huphuphup); while (!finished) { /* ok, we really would do some work in here... honest */ bufid = pvm_recv(-1,-1); pvm_bufinfo( bufid, &bytes, &msgtag, &from ); switch (msgtag) { case 1: /* join */ join = from; make_mqueue (join, &mqkey, &mqid); if (mqid<0) { pvm_initsend(PvmDataDefault); pvm_pkint (&mqid, 1, 1); /* failed */ pvm_send (join, join); fprintf(stderr,"TID [0x%x] failed on make_mqueue\n", join); break; } slot = add_tidinfo (join, mqkey, mqid); if (slot<0) { pvm_initsend(PvmDataDefault); pvm_pkint (&slot, 1, 1); /* failed */ pvm_send (join, join); fprintf(stderr,"TID [0x%x] failed on add_tidinfo\n", join); break; } /* else ok, so we setup notify and then signal task */ printf("TID [0x%x] added into tidinfo slot [%d]\n", join, slot); pvm_notify (PvmTaskExit, 9, 1, &join); fprintf(stderr,"Adding [0x%x] to notify list\n", join); fflush(stderr); j = 0; /* i.e. isitok is yes */ pvm_initsend(PvmDataDefault); pvm_pkint (&j, 1, 1); /* passed */ fprintf(stderr,"Sending message [%d] to [0x%x] tag [0x%x]\n", j, join, join); cc = pvm_send (join, join); fprintf(stderr,"Sent message [%d] to [0x%x] tag [0x%x] = [%d]\n", j, join, join, cc); fflush(stderr); break; case 2: /* exit (polite) */ left = from; /* just adds to readability, maybe */ del_mqueue (left); slot = remove_tidinfo (left); printf("TID [0x%x] removed from tidinfo slot [%d]\n", left, slot); /* freeing space by this task */ left = left & 0xFFFF; /* task part of address */ for(i=0;itidsexited++; break; case 3: /* blockmap */ for(i=0;itidsmurdered++; break; default: /* ? */ fprintf(stderr,"Unknown message from [0x%x] of tag [0x%x]\n", from, msgtag); pvm_freebuf (bufid); break; } /* end switch */ } clean_segs(); pvm_exit(); /* which takes the PVM reg with it! */ exit (0); /* Normally I hope */ } /* unsigned int get_max_seg_size() */ unsigned int get_max_seg_size(psize) unsigned psize; { key_t key; unsigned int size; int id; key = (key_t) 0x2d000000; /* size = 1024 * 1024 * 1024; */ /* size = 1024 * 1024 * 32; */ /* start looking from 32MBytes */ size = MAXPAGESALLOWED * psize; /* start from our limit */ for(;;) { id = shmget (key, size, IPC_CREAT | 0600); if (id>0) { /* printf("id\t%d\n",id); */ /* printf("key\t%x\n",key); */ /* printf("size\t[0x%x or %u bytes] [%u KBytes]\n", size, size, size/1024); */ break; } /* key += 0x10; */ if (id<0) { if (errno==EINVAL) perror("shmget:EINVAL"); if (errno==ENOSPC) perror("shmget:ENOSPC"); size /= 0x2; /* break; */ } } shmctl (id, IPC_RMID, 0); /* I know its a waste.. but.. */ return (size); } unsigned int create_segments(basekey, maxsegs) key_t basekey; unsigned int maxsegs; { int c=0; /* number of segments that we get a valid id for */ int v=0; /* number of segments that we get a valid ptr for */ void *ptr; key_t key; struct shmid_ds shmsbuf; int suc, attached; int i; int f; /* f is for failed */ int num; /* number of segments that we have a valid id and valid ptr for */ key = (key_t) basekey; /* make sure we are all reset fully */ for(i=0;i0) printf("%s storing syshdr as shmid [0x%x]\n", fullname, shmid); else { printf("%s marking shmem as disabled\n", fullname, shmid); shmid = -1; } ssbuf = pvm_setsbuf(0); sbuf = pvm_initsend(PvmDataDefault); pvm_pkint(&tid,1,1); pvm_pkint(&shmid,1,1); if ( (cc = pvm_putinfo(fullname, sbuf, PvmMboxDefault)) != 0 ) { pvm_perror("pvm_shmd already running?"); } pvm_setsbuf(ssbuf); pvm_freebuf(sbuf); return(cc); /* Will be PvmOK if register succeeded, < 0 otherwise */ } int make_mqueue (tid, mqkey, mqid) int tid; key_t* mqkey; int* mqid; { key_t key; int id; int i,j,k; key = (key_t) (0x2c000000+((int)getuid()*0x1000)+(0xFFFF&tid)); /* inital key */ for(i=0;i<1000;i++) { id = msgget(key, IPC_CREAT|0666); if (id>0) break; else key++; } if (id<0) return (-1); /* can't get one ! */ /* else we can and we did! */ printf("TID [0x%x] has a new message queue of key [0x%x] and id [%d]\n", tid, key, id); *mqkey = key; *mqid = id; return (0); } int del_mqueue (tid) int tid; { key_t key; int id; int i,j,k; /* first get the id from the tidinfo structure using the processes tid */ id = find_tidinfo_id (((char *)segptrs[0]), tid); if (id<0) { fprintf (stderr, "No TID [0x%x] found when removing mqueue ??\n", tid); fflush(stderr); return (-1); /* i.e. no tid record... ? */ } i = msgctl (id, IPC_RMID, (struct msqid_ds *) 0 ); if (!i) { printf("TID [0x%x] had a message queue of id [%d] deleted.\n", tid, id); return (0); } else { printf("Failed to remove TID [0x%x] message queue [%d]\n", tid, id); return (-1); } } void huphuphup () { fprintf(stderr,"pvm_shmd: Received a sig HUP.\nExiting.\n"); fflush(stderr); clean_segs(); pvmendtask(); exit (SIGHUP); } void bambismother () { fprintf(stderr,"pvm_shmd: Received a sig TERM.\nExiting.\n"); fflush(stderr); clean_segs(); pvmendtask(); /* pvm_exit(); */ /* this causes a PVM not implemented error to appear */ exit (SIGTERM); } ./pvm3/shmd/pvm_shmd_stat.c0100644007401100000360000000224706667575614015102 0ustar kohlgopher static char rcsid[] = "$Id: pvm_shmd_stat.c,v 1.1 1999/03/04 21:30:52 pvmsrc Exp $"; #include "pvm3.h" #include "shmd.h" #include #include #include #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 256 #endif main () { int numsegs=0; char hname[MAXHOSTNAMELEN]; char shmdname[1024]; int isitok=0; /* ok or not ? */ int mytid, i, j, k, srbuf, localid, shmdtid; int id; mytid = pvm_mytid(); if (mytid<0) /* ops no pvm... */ exit (-1); bzero (shmdname, 1024); gethostname(hname, MAXHOSTNAMELEN); strcat (shmdname, "pvm_shmd:"); strcat (shmdname, hname); srbuf = pvm_setrbuf(0); if ( pvm_recvinfo(shmdname, 0, PvmMboxDefault) == PvmNotFound ) { fprintf(stderr,"No pvm_shmd\n"); exit (-1); } pvm_upkint(&shmdtid,1,1); pvm_upkint(&id,1,1); pvm_setrbuf(srbuf); pvm_initsend(PvmDataDefault); pvm_pkint(&mytid,1,1); /* get block map is message tag 3 */ pvm_send (shmdtid, 3); pvm_exit(); } ./pvm3/shmd/sem.c0100644007401100000360000000544707354134725013007 0ustar kohlgopher static char rcsid[] = "$Id: sem.c,v 1.3 2001/09/25 17:07:33 pvmsrc Exp $"; /* Semaphore control code for Binary Semaphores only GEF UTK/ORNL 20 Jan 1997 */ #include #include #include #include /* needed for usleep */ #include #ifdef XXX_IMA_LINUX /* Seems to be O.K. on latest Linux systems now. JAK - 9/25/01 */ union semun forth_arg; /* XXXX optional under all OSs except Linux ! */ #endif void unlock_sem_forced (); int get_sem (key_t k, int n) { int semid; for(;(semid=semget(k, n, 0)) == -1;) usleep (1000); return semid; } void lock_sem (int sem, int n) { struct sembuf sop; /* 1 element array */ sop.sem_num = n; /* which sem are we operating on */ sop.sem_op = -1; /* -1 locks */ sop.sem_flg = SEM_UNDO; /* if I crash reset the semaphore */ /* this is a very important flag to set! */ semop (sem, &sop, 1); /* block until resource is free, then lock it */ } int sem_is (int sem, int n) { #ifdef XXX_IMA_LINUX /* Seems to be O.K. on latest Linux systems now. JAK - 9/25/01 */ return (semctl( sem, n, GETVAL, forth_arg)); #else return (semctl( sem, n, GETVAL)); #endif } void unlock_sem (int sem, int n) { struct sembuf sop; /* 1 element array */ sop.sem_num = n; /* which sem are we operating on */ sop.sem_op = 1; /* +1 locks */ sop.sem_flg = SEM_UNDO; semop (sem, &sop, 1); /* unblock resource */ } void unlock_sem_forced (int sem, int n) { struct sembuf sop; /* 1 element array */ sop.sem_num = n; /* which sem are we operating on */ sop.sem_op = 1; /* +1 locks */ sop.sem_flg = 0; /* flag =0 NOT SEM_UNDO */ semop (sem, &sop, 1); /* unblock resource */ } int init_sem (key_t k, int n) { int semid, i; if((semid=semget (k, n, 0)) !=-1) { printf("[init_sem] sem key %lx exists with id of %d\n", (long) k, semid); #ifdef XXX_IMA_LINUX /* Seems to be O.K. on latest Linux systems now. JAK - 9/25/01 */ semctl (semid, 0, IPC_RMID, forth_arg); /* existing sem destroy */ #else semctl (semid, 0, IPC_RMID); /* existing sem destroy */ #endif } if((semid=semget (k, n, IPC_CREAT | 0600)) !=-1) { /* semaphore are init to zero, i.e. locked so we unlock them */ /* for(i=0;i #include #include #include #include #include #include /* #include */ /* #include */ #include #include #include #include #include #include "shmd.h" #include #ifndef SHM_FAILED #define SHM_FAILED (void*)-1 #endif /* Globals */ /* used to make this library easier and faster to code as always */ int shm_enabled=0; /* if 0 not attempted yet */ /* if 1 ok */ /* if -1 not ready or unavailable as of yet */ int mytid=0; /* so we don't get our own tid every single call */ int localid=0; /* a shorten version used by the block routines */ int mymqueue=0;/* my own message queue */ /* this lot is filled in by shm-attach() call. */ /* its mostly read-only info that is only changed by the pvm_shmd. */ shm_header_info_t* syshdr; /* pointer to the start of all this mess */ int psize; /* page/block size */ int nsegs; /* number of segments to choose from */ int maxpages; /* maximum number of pages in a segment.. */ blockinfo_t* blocks[MAXSEGS]; /* pointers to the block info stuff... yeah */ char* segs[MAXSEGS]; /* pointers to actual segments */ char* msgblocks[MAXSEGS]; /* pointers to the actual shm blocks */ /* fully qualified addresses used */ /* so you can access directly */ int shmd_pvm_psend(tid, tag, cp, len, dt) int tid; int tag; void *cp; int len; int dt; { unsigned pages; int i, j, k; int remoteid=0; int olen; msg_info_t msg_info; int cc=0; int mqid; /* message queue of the destination */ int seg; int block, c; /* printf("shmd_pvm_psend()\n"); */ #ifdef NAMES printf("shmd_pvm_psend(0x%x,%d,%x,%d,%d)\n", tid, tag, cp, len, dt); #endif #ifdef DEBUG printf("shm enabled = %d\n", shm_enabled); #endif /* DEBUG */ /* if no shared memory allowed then use pvm_psend() */ if (shm_enabled<0) return (pvm_psend(tid, tag, cp, len, dt)); #ifdef DEBUG printf("shm enabled = %d\n", shm_enabled); #endif /* DEBUG */ /* Else check to see if we have ever used shared memory */ /* if not can we ? */ if (!shm_enabled) { shm_attach(); /* get it while its hot or not */ if (shm_enabled<0) return (pvm_psend(tid, tag, cp, len, dt)); } /* remote or local */ if ((mytid&0xFFFF0000)!=(tid&0xFFFF0000)) /* remote then... */ return (pvm_psend(tid, tag, cp, len, dt)); /* ok, we are here because we might be able to... */ /* ok, is the destination a valid target yet? */ /* i.e. does it have a valid message queue? */ mqid = find_tidinfo_id (syshdr, tid); if (mqid<0) { fprintf(stderr,"TID [0x%x] cannot send to TID [0x%x] as have not found its mqueue yet.\n", mytid, tid); fflush(stderr); return (pvm_psend(tid, tag, cp, len, dt)); /* nope */ } /* ok, we think we can.. you, me, we both shared memory enabled */ /* from out of the woods into the wood burner (tm) */ olen = len; /* backup of length just in case ;) */ switch (dt) { case PVM_BYTE: len *= sizeof(char); break; case PVM_SHORT: case PVM_USHORT: len *= sizeof(short); break; case PVM_INT: case PVM_UINT: len *= sizeof(int); break; case PVM_LONG: case PVM_ULONG: len *= sizeof(long); break; case PVM_FLOAT: len *= sizeof(float); break; case PVM_CPLX: len *= sizeof(float) * 2; break; case PVM_DOUBLE: len *= sizeof(double); break; case PVM_DCPLX: len *= sizeof(double) * 2; break; case PVM_STR: cc = PvmNotImpl; break; default: cc = PvmBadParam; break; } if (cc<0) return (cc); /* data type error */ /* ok len is now the length of the message in bytes */ /* short cut here for zero length messages... */ if (len) { /* we now need to know how many pages that is */ pages = (len / psize); if (len % psize) pages++; #ifdef DEBUG fprintf(stderr,"send: len [%d] bytes or [%d] whole pages\n", len, pages); fflush(stderr); fprintf(stderr,"send: pages requested [%d] max in any segment [%d]\n", pages, maxpages); fflush(stderr); #endif /* DEBUG */ /* now find a block with that kind of memory available */ if (pages>maxpages) return (pvm_psend(tid, tag, cp, olen, dt)); /* nope */ /* ok now really look! */ remoteid = (tid & 0x0000FFFF); /* shorten TIDs */ seg = (remoteid*5) % nsegs; /* hash into a set segment */ block = -1; #ifdef DEBUG fprintf(stderr,"Hash localid&[0x%x]*5 %% nsegs [%d] -> [%d]\n", remoteid, nsegs, seg); fflush(stderr); #endif /* DEBUG */ /* loop round until we find one! */ for(c=0;clargestblockfree, pages); fflush(stderr); #endif /* DEBUG */ if (blocks[seg]->largestblockfree >= pages) { /* maybe in luck */ /* block = getblocks (blocks[seg], localid, pages); */ /* try remote id for speed see writen notes */ block = getblocks (blocks[seg], remoteid, pages); #ifdef DEBUG fprintf(stderr,"Blocks found at [0x%x] [%d] when looking for [%d]\n", blocks[seg], block, pages); fflush(stderr); #endif /* DEBUG */ if (block>=0) break; /* happy we have the memory */ } /* there might be space */ seg = (seg+1) % nsegs; /* wrap round if required */ } if (block<0) /* no space in at the Inn... */ { fprintf(stderr, "psend() from [0x%x] to [0x%x] of len [%d] bytes out of message buffers?\n", mytid, tid, olen); for(j=0;jpagesfree); fprintf(stderr, "\nUsing pvm_psend() sockets instead.\n"); return (pvm_psend(tid, tag, cp, olen, dt)); /* glad we copied len into olen.... */ } /* ok, we have a reserved block big enought in seg 'seg' at the */ /* start of block 'block' */ /* so lets copy data into it and then mqueue it out of here */ #ifdef DEBUG printf("Copy into [%x] from [%x] [%d] bytes\n", (char*)msgblocks[seg]+(psize*block), (char *)cp, len); #endif memcpy ((char*)msgblocks[seg]+(psize*block), (char *)cp, len); } /* if ( len != 0 ) */ else { seg = -1; block = -1; pages = 0; } /* dirty dead has been done, now to kick the receiver */ /* First make the message */ msg_info.mtype = (long) tag; msg_info.from = mytid; msg_info.seg = seg; msg_info.block = block; msg_info.pages = pages; msg_info.bytes = len; /* now to shift the data out of here! */ cc = msgsnd (mqid, (void *)&msg_info, (sizeof(msg_info)), 0); #ifdef DEBUG printf("TID [0x%x] sent message via shared memory seg [%d] block [%d] that was [%d]bytes or [%d] pages long to tid [0x%x] signalling on mqueue [%d]=[%d]\n", mytid, seg, block, len, pages, tid, mqid, cc); fflush(stdout); #endif /* DEBUG */ /* if (cc<0) { */ /* i.e. the message was not sent! */ /* to be done, and its messy... */ return (cc); } int shmd_pvm_precv(tid, tag, cp, len, dt, rtid, rtag, rlen) int tid; int tag; void *cp; int len; int dt; int *rtid; int *rtag; int *rlen; { unsigned pages; int i, j, k; int remoteid=0; int olen; msg_info_t msg_info; int cc=0; unsigned int stime = 1; /* initial usleep time */ int found=0; int alen; int c; /* printf("shmd_pvm_precv()\n"); */ #ifdef NAMES printf("shmd_pvm_precv(%x, %d, %x, %d, %d, %x, %x, %x)\n", tid, tag, cp, len, dt, rtid, rtag, rlen); #endif /* if no shared memory allowed then use pvm_precv() */ if (shm_enabled<0) return (pvm_precv(tid, tag, cp, len, dt, rtid, rtag, rlen)); /* Else check to see if we have ever used shared memory */ /* if not can we ? */ if (!shm_enabled) { shm_attach(); /* get it while its hot or not */ if (shm_enabled<0) return (pvm_precv(tid, tag, cp, len, dt, rtid, rtag, rlen)); } /* remote or local */ if ((mytid&0xFFFF0000)!=(tid&0xFFFF0000)) { /* remote then... */ fprintf(stderr,"Me [0x%x] and src [0x%x] not on same machine\n", mytid, tid); fflush(stderr); return (pvm_precv(tid, tag, cp, len, dt, rtid, rtag, rlen)); } /* ok, we are here because we might be able to... */ /* does the sender have shared memory? */ /* actually it might have sent and then died why we were busy */ /* so we do not check whether it has a message queue (left) itself */ /* mqid = find_tidinfo_id (seg0, tid); */ /* ok, we think we can.. you, me, we both shared memory enabled */ /* from out of the woods into the wood burner (tm) */ olen = len; /* backup of length just in case ;) */ switch (dt) { case PVM_BYTE: len *= sizeof(char); break; case PVM_SHORT: case PVM_USHORT: len *= sizeof(short); break; case PVM_INT: case PVM_UINT: len *= sizeof(int); break; case PVM_LONG: case PVM_ULONG: len *= sizeof(long); break; case PVM_FLOAT: len *= sizeof(float); break; case PVM_CPLX: len *= sizeof(float) * 2; break; case PVM_DOUBLE: len *= sizeof(double); break; case PVM_DCPLX: len *= sizeof(double) * 2; break; case PVM_STR: cc = PvmNotImpl; break; default: cc = PvmBadParam; break; } if (cc<0) return (cc); /* i.e. invalid data type param */ /* ok len is now the length of the message in bytes */ /* we now need to know how many pages that is */ pages = (len / psize); if (len % psize) pages++; #ifdef DEBUG fprintf(stderr,"recv: len [%d] bytes or [%d] whole pages\n", len, pages); fflush(stderr); fprintf(stderr,"recv: pages requested [%d] max in any segment [%d]\n", pages, maxpages); fflush(stderr); #endif /* DEBUG */ /* paranoid and safe */ if (pages>maxpages) { return (pvm_precv(tid, tag, cp, olen, dt, rtid, rtag, rlen)); } /* ok, only now can we change the tag as mqueue and pvm use different */ /* ones for a wildcard */ if (tag==-1) tag = 0; found = 0; stime =1; c = 0; /* tight loop counter */ while (!found) { cc = msgrcv (mymqueue, (void *) &msg_info, sizeof(msg_info), (long) tag, 0); /* IPC_NOWAIT); */ if (cc>0) { /* success */ #ifdef DEBUG printf("got one from the message cue. Sleep was [%d] on count[%d].\nAsked for src[0x%x] tag[%d] size[%d]bytes\nGot from [0x%x] of tag[%d] size[%d]bytes, pages[%d]\n", stime, c, tid, tag, len, msg_info.from, msg_info.mtype, msg_info.bytes, msg_info.pages); #endif /* DEBUG */ break; /* out to main routine */ } if (cc==-1) { /* failure */ if (errno == EIDRM) { /* id is now invalid */ shm_enabled = -1; mymqueue = -1; return (pvm_precv(tid, tag, cp, olen, dt, rtid, rtag, rlen)); } /* if (errno == ENOMSG) */ } /* tight loop counter c is checked */ if (c>100) { /* ok, we now probe for a real pvm message and the iterate */ cc = pvm_probe (tid, tag); if (cc>0) return (pvm_precv(tid, tag, cp, olen, dt, rtid, rtag, rlen)); } /* ok, neither message avaliable under either */ /* so, sleep and increase the sleep amount each time */ if (c>200) { usleep (stime); if (stime<500) stime *= 2; /* exp increase... */ } c++; /* tight loop counter */ } /* end while not found */ /* so lets get a copy of the data out of here */ /* first agree on the data size */ /* i.e. the smallest of the two.. */ alen = len; if (msg_info.bytes < len) alen = msg_info.bytes; if (alen) { #ifdef DEBUG printf("Copy into [%x] from [%x] [%d] bytes\n", (char *)cp, (char*)(msgblocks[msg_info.seg]+(psize*msg_info.block)), alen); #endif memcpy ((char *)cp, (char*)(msgblocks[msg_info.seg]+(psize*msg_info.block)), alen); /* dirty dead has been done, now to clean the block info up. */ #ifdef DEBUG printf("recv: [0x%x] cleaning up message block from [0x%x] in Seg[%d] start block [%d] of [%d] pages\n", mytid, msg_info.from, msg_info.seg, msg_info.block, msg_info.pages); #endif /* DEBUG */ freeblock (blocks[msg_info.seg], localid, msg_info.pages, msg_info.block); } /* if (rlen) *rlen = (int) alen; */ /* if (rtid) *rtid = (int) msg_info.from; */ /* if (rtag) *rtag = (int) msg_info.mtype; */ /* must cast or else long will over write other args */ return (PvmOk); } int shm_attach() { int i,id; key_t key, k1, k2; int id1, id2; struct shmid_ds shmsbuf; unsigned size; void* ptr; int* iptr; int toview; int last; int shmdtid; int srbuf, bufid; blockinfo_t* baseptr; char* cptr; shm_header_info_t* hptr; int numsegs=0; char hname[MAXHOSTNAMELEN]; char shmdname[1024]; int isitok=0; /* ok or not ? */ /* make sure we have our tid so we can decide if this local or remote */ if (!mytid) { mytid = pvm_mytid(); localid = (mytid & 0x0000FFFF); /* shorten TIDs */ if (mytid<0) /* ops no pvm... */ return (-1); } bzero (shmdname, 1024); gethostname(hname, MAXHOSTNAMELEN); strcat (shmdname, "pvm_shmd:"); strcat (shmdname, hname); srbuf = pvm_setrbuf(0); if ( pvm_recvinfo(shmdname, 0, PvmMboxDefault) == PvmNotFound ) { fprintf(stderr,"No pvm_shmd\n"); exit (-1); } pvm_upkint(&shmdtid,1,1); pvm_upkint(&id,1,1); pvm_setrbuf(srbuf); pvm_initsend(PvmDataDefault); pvm_pkint(&mytid,1,1); pvm_send (shmdtid, 1); /* join the shared memory system */ #ifdef DEBUGSTART fprintf(stderr,"Joining the system\n"); fflush(stderr); fprintf(stderr,"Recv on [0x%x] and tag [0x%x]\n", shmdtid, mytid); fflush(stderr); #endif /* DEBUGSTART */ bufid = pvm_recv (shmdtid, mytid); /* i.e. my message no questions */ #ifdef DEBUGSTART fprintf(stderr,"Got message back?\n"); fflush(stderr); #endif /* DEBUGSTART */ pvm_upkint (&isitok, 1, 1); /* shm says yeah or nay ? */ #ifdef DEBUGSTART fprintf(stderr,"Value [%d]\n", isitok); fflush(stderr); #endif /* DEBUGSTART */ /* we do this handshake so that we don't have to spin */ /* on our own info mqueue appearing in the shm header segment */ /* once we get this message we know its there ok! */ if (isitok<0) { fprintf(stderr,"pvm_shmd said no shm for [0x%x] ?", mytid); shm_enabled = -1; return (-1); } ptr = shmat (id, 0, 0); /* inital shmat attempt */ /* if (ptr>0) { */ if (ptr != SHM_FAILED) { #ifdef DEBUGSTART printf("attached at offset of 0x%lx\n", (long) ptr ); #endif /* DEBUGSTART */ } else { perror("shmat:"); shm_enabled = -1; return (-1); } segs[0] = (char *) ptr; /* first segment pointer */ syshdr = (shm_header_info_t *) ptr; /* system header pointer */ psize = getpagesize(); /* ok a system call really */ nsegs = syshdr->numsegs; /* number of segments */ #ifdef DEBUGSTART printf("Got syshdr [0x%lx] pagesize [%d] nsegs [%d]\n", (long) syshdr, psize, nsegs); #endif /* DEBUGSTART */ cptr = (char *) ptr; /* cptr += sizeof (shm_header_info_t); */ /* gets us to the blockinfo */ /* actually this was a mistake, and a bug of my own making!!! */ /* the sysheader only tasks around 200 bytes.. the rest is */ /* the tidlist proper! */ /* real start of blockinfo is 16KBytes lower.... */ cptr += (16384); baseptr = (blockinfo_t*)cptr; /* cast and assign */ for(i=0;isegkey, blocks[i]->segid, (long) blocks[i]); #endif /* DEBUGSTART */ if (i) { /* we have already attached the first segment just the rest to go */ segs[i] = shmat (baseptr->segid, 0, 0); /* if (segs[i]<0) { */ if (segs[i]==SHM_FAILED) { perror("shmat:"); shm_enabled = -1; return (-1); } #ifdef DEBUGSTART printf("Seg[%d] attached at [0x%lx]\n", i, (long) segs[i]); #endif /* DEBUGSTART */ } msgblocks[i] = segs[i]+(baseptr->segoffset); cptr = (char *)blocks[i] + blocks[i]->nextoffset; baseptr = (blockinfo_t *) cptr; /* point to the next blockinfo_t struct */ } #ifdef DEBUGSTART printf("Number of segments is [%d]\n", i); fflush(stdout); #endif /* DEBUGSTART */ /* Now to find the maximum pages allowed for any single message.. */ /* this should change when I allow messages across segments. */ #ifdef DEBUGSTART for(i=0;inpages, (long) msgblocks[i], (long) segs[i]); #endif /* DEBUGSTART */ maxpages = blocks[0]->npages; for(i=1;inpages > maxpages) maxpages = blocks[i]->npages; /* now to find my own message queue and we are away */ mymqueue = find_tidinfo_id (syshdr, mytid); if (mymqueue < 0) { shm_enabled = -1; return (-1); } #ifdef DEBUGSTART printf("mqueue: TID [0x%x] queue id [%d]\n", mytid, mymqueue); #endif /* DEBUGSTART */ /* if (processor_bind(P_PID, P_MYID, 0, NULL) == -1) perror("processor_bind"); */ /* no further objections my honour */ shm_enabled = 1; /* i.e. all is ok and ready for SHM action */ return (0); } ./pvm3/shmd/tidinfo.c0100644007401100000360000001417506667601504013655 0ustar kohlgopher static char rcsid[] = "$Id: tidinfo.c,v 1.2 1999/03/04 22:03:48 pvmsrc Exp $"; #include "shmd.h" #include /* global */ /* this is used so we don't have to recheck the head ptr every time */ shm_header_info_t* headptr=(shm_header_info_t *)0; tidinfo_t* tidinfoptr=(tidinfo_t *)0; int init_tidinfo (ptr, headersize) char* ptr; /* where we start to put the info */ unsigned int headersize; /* how much space we have to play with */ { int s, t, n, i, m; shm_header_info_t* hdrptr; tidinfo_t* tptr; tidinfo_t* tptr0; char * tmpptr; unsigned totalsize; hdrptr = (shm_header_info_t*) ptr; s = sizeof(shm_header_info_t); m = headersize; t = sizeof(tidinfo_t); n = (m - s - 4) / t; /* -4 is used to force 32bit boundary */ /* as this is the most a structure can be moved by to make aligment */ printf("Sizeof shm_header_info_t [%d]\n", s); printf("Sizeof tidinfo_t [%d]\n", t); printf("Number of tidinfo blocks allowed [%d]\n", n); hdrptr->maxtids = n; hdrptr->tidsinuse = 0; hdrptr->freeslots = n; hdrptr->firstfree = 0; hdrptr->maxtidsused = 0; hdrptr->totalstids = 0; hdrptr->tidsexited = 0; hdrptr->tidsmurdered = 0; printf("Wrote header info at [0x%lx]\n", (long) hdrptr); fflush(stdout); /* now to find start of tidinfo table */ tmpptr = ptr + s; tptr = (tidinfo_t *) tmpptr; tptr0 = tptr; printf("Start of tidinfo at [0x%lx]\n", (long) tptr); fflush(stdout); for(i=0;itid = -1; tptr->mqkey = -1; tptr->mqid = -1; tptr++; } /* paranoid check */ printf("End of tidinfo at [0x%lx]\n", (long) tptr); printf("End of tidinfo[0] at [0x%lx]\n", (long) &tptr0[0]); printf("End of tidinfo[%d] at [0x%lx]\n", n-1, (long) &tptr0[n-1]); fflush(stdout); if (n>0) { /* i.e. we are ok, then set the global pointers */ headptr = hdrptr; tidinfoptr = tptr0; } return (n); } int add_tidinfo (tid, key, id) int tid; key_t key; int id; { int slot, c, i, j; int max; if (!headptr) { fprintf(stderr,"Panic, headerinfo address not set???\n"); fflush(stderr); exit(-9); } if (!tidinfoptr) { fprintf(stderr,"Panic, tidinfo address not set???\n"); fflush(stderr); exit(-9); } if (!(headptr->freeslots)) { fprintf(stderr,"Warning: TID [0x%x] cannot be put in shm tid info table as there is no space left\n", tid); fflush(stderr); return (-1); } /* get basic info first */ max = headptr->maxtids; /* ok, lets find one */ slot = (tid * 5) % max; /* a simple hash lookup */ for(c=0;ctidsinuse++; headptr->freeslots--; /* Stats info */ headptr->totalstids++; if (headptr->maxtidsused < headptr->tidsinuse) headptr->maxtidsused = headptr->tidsinuse; return (slot); /* from 0 to maxtids-1 */ } /* paranoid check */ if (tidinfoptr[slot].tid == tid) { /* already in table... */ fprintf(stderr,"TID [0x%x] is already in the shm tidinfo table at slot [%d]\n", tid, slot); fflush(stderr); /* do we exit or continue? */ /* continue and return -1 which means no shm usage! */ return (-1); } /* no space so inc counters with wrap around */ slot++; if (slot==max) slot=0; } /* for linear search */ /* default case is no space */ fprintf(stderr,"TID [0x%x] cannot be put in tidinfo table for unknown reason...????", tid); fflush(stderr); return (-1); } int remove_tidinfo (tid) /* returns slot or -1 if error */ int tid; { int slot, c, i, j; int max; if (!headptr) { fprintf(stderr,"Panic, headerinfo address not set???\n"); fflush(stderr); exit(-9); } if (!tidinfoptr) { fprintf(stderr,"Panic, tidinfo address not set???\n"); fflush(stderr); exit(-9); } if (!(headptr->tidsinuse)) { fprintf(stderr,"Warning: TID [0x%x] cannot be in shm tid info table as there are no entries!\n", tid); fflush(stderr); return (-1); } /* get basic info first */ max = headptr->maxtids; /* ok, lets find one */ slot = (tid * 5) % max; /* a simple hash lookup */ for(c=0;ctidsinuse--; headptr->freeslots++; /* Stats info */ /* have to be updated by main caller as we don't know */ /* if it exited or was killed */ return (slot); /* from 0 to maxtids-1 */ } /* not found so inc counters with wrap around */ slot++; if (slot==max) slot=0; } /* for linear search */ /* whatthe case is */ fprintf(stderr,"TID [0x%x] was not found in tidinfo table for unknown reason...????", tid); fflush(stderr); return (-1); } int find_tidinfo_id (ptr, tid) /* returns id or -1 if error */ /* this is used by the clients (once only, I hope ) */ int tid; char* ptr; /* start of first mem segment i.e. system header location */ { int slot, c, i, j; int max; char* tmpptr; shm_header_info_t* sptr; tidinfo_t* tptr; if (!ptr) { fprintf(stderr,"Panic, SYSTEM header address not set???\n"); fflush(stderr); exit(-9); } sptr = (shm_header_info_t *) ptr; /* system pointer */ tmpptr = ptr + (sizeof(shm_header_info_t)); tptr = (tidinfo_t *) tmpptr; /* tidinfo pointer */ /* get basic info first */ max = sptr->maxtids; /* ok, lets find one */ slot = (tid * 5) % max; /* a simple hash lookup */ #ifdef TIDINFODEBUG printf("Searching for TID [0x%x] starting at mem location [0x%x] for [%d] tidinfo entries using hash of [%d] \n", tid, tptr, max, slot); #endif for(c=0;c=max) slot=0; } /* for linear search */ /* default case not found */ /* fprintf(stderr,"TID [0x%x] cannot be found in tidinfo table for unknown reason...????", tid); */ /* fflush(stderr); */ return (-1); } ./pvm3/shmd/shmd.h0100644007401100000360000001235307331302447013146 0ustar kohlgopher /* $Id: shmd.h,v 1.3 2001/07/30 16:02:47 pvmsrc Exp $ */ /* header file needed for silly stuff like fixed contexts blah */ /* (c) Graham E. Fagg, University of Tennessee, Knoxville, TN, USA */ /* Contact address fagg@cs.utk.edu or pvm@msr.csm.ornl.gov */ #include /* needed for key_t */ /* Globals */ /* These may be changed by knowledgable users */ /* MAXPAGESALLOWED sets the maximum number of pages allowed per segment */ /* This is important as some machines allow very large segments and others */ /* i.e. Suns under Solaris default to 1Megabyte segments */ /* The daemon will attempt to get segments upto but not exceeding this size */ #define MAXPAGESALLOWED (4096) /* This controls the maximum number of segments the daemon is allowed to */ /* allocate. Again this is important as some machines may allow all VM to */ /* be allocated to shared memory while other have small limits i.e. Solaris */ /* The larger the number the better the interlacing of memory between procs */ /* and thus less sharing of memory (less contension). Too high a number and */ /* you will have no memory left for what yoru program is actually doing! */ #define MAXSEGS 8 /* This is the data structure stored in the head shm segment */ typedef struct blockinfo { /* now for the block map itself */ /* not that we statically allocate this upto the maximum */ int pagemap [MAXPAGESALLOWED]; /* we put the block map first as it is most used and will */ /* hopefully be put on a page boundary by the nice block init routines */ /* now for the useful stuff */ key_t semkey; /* semaphore for this infomation */ key_t segkey; /* key for this segment (infomation only) */ int semid; /* id of actual semaphore */ int segid; /* segment id */ int psize; /* page size, should be obvious */ int npages; /* total number of pages in this segment */ /* ptr to start of first page in segment */ unsigned segoffset; /* not an absolute value as each process may map a shared memory segment */ /* into a different part of its memory map */ /* expect this to be 0 or after HEADER in first segment only */ int pagesfree; /* total number of pages free */ int largestblockfree; /* largest continuous block of pages free */ int largeststart; /* where this block starts */ /* used to optimse certain allocation schemes */ /* some book keeping stuff */ /* not enabled all the time */ /* also, watch out for roll overs */ unsigned int totalallocated; /* how many have been used */ unsigned int totalfreed; /* how many have been recycled */ unsigned int jumpsaved; /* search shortcut effectiviness */ unsigned int firstfound; /* how often the first free saved us */ unsigned int highestutilised; /* how many were in use */ unsigned int largestused; /* largest set of blocks used */ /* links */ /* Although this isn't a link'd list we have a relative offset */ /* to the start of the next blockinfo struct from the start of this one */ /* esp important as I force the blocks onto page boundaries... */ /* so you cannot just inc by blockinfo_t size to get to the next one */ int nextoffset; /* relative address in bytes */ int previousoffset; /* relative address in bytes */ } blockinfo_t; typedef struct { int tid; /* attached TID */ key_t mqkey; /* message queue key */ int mqid; /* message queue id */ } tidinfo_t; typedef struct { /* First segment info */ key_t seg0key; int seg0id; int numsegs; int maxsegsize; int maxsegsizeallowed; /* note any other info is in the blockinfo structures */ /* which are stored in their own headers to avoid contension */ /* lock problems if they were all stored here */ /* tid contact info */ unsigned maxtids; /* maximum of tids allowed */ unsigned tidsinuse; /* number of tids in table */ unsigned freeslots; /* should be obvious */ unsigned firstfree; /* for when we are not using hashing */ /* and doing a linear search */ /* tid table stats */ unsigned maxtidsused; /* the most we had at once */ unsigned totalstids; /* how many are/have been through here */ unsigned tidsexited; /* how many have said good bye */ unsigned tidsmurdered; /* how many have been 'murdered' */ /* First TIDINFO entry would follow here! */ } shm_header_info_t; typedef struct { long mtype; int from; int seg; int block; int pages; int bytes; } msg_info_t; /* Semaphore control header for Binary Semaphores only GEF UTK/ORNL 20 Jan 1997 */ /* This operation creates the semaphore set */ /* Should only be called by one process as it destroys any pre-existing ones */ int init_sem (key_t k, int n); /* This operation waits untill the above semaphore exits */ /* Yes it can be done by nesting semaphores, but hey its late */ int get_sem (key_t k, int n); /* Finially, he who creates can bloody well destroy! */ void del_sem (int semid); int sem_is (key_t k, int n); /* gets the actual semaphore value */ /* set and reset or P,Q or lock unlock operations! */ void lock_sem (int sem, int n); void unlock_sem (int sem, int n); /* Prototypes of functions that are provided */ /* block functions */ int initblockstruct(); int get(); int back(); void map(); /* tidinfo functions */ int init_tidinfo (); int add_tidinfo (); int find_tidinfo_id (); int remove_tidinfo (); ./pvm3/shmd/shmdproto.h0100644007401100000360000000325306667602201014233 0ustar kohlgopher /* $Id: shmdproto.h,v 1.1 1999/03/04 22:09:05 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ #ifdef __ProtoGlarp__ #undef __ProtoGlarp__ #endif #if defined(__STDC__) || defined(__cplusplus) #define __ProtoGlarp__(x) x #else #define __ProtoGlarp__(x) () #endif #ifdef __cplusplus extern "C" { #endif int shmd_pvm_precv __ProtoGlarp__(( int, int, void *, int, int, int *, int *, int * )); int shmd_pvm_psend __ProtoGlarp__(( int, int, void *, int, int )); ./pvm3/tasker/0042755007401100000360000000000010117676455012412 5ustar kohlgopher./pvm3/tasker/Makefile.aimk0100644007401100000360000000171006351574062014760 0ustar kohlgopher# # $Id: Makefile.aimk,v 1.5 1997/06/17 20:48:50 pvmsrc Exp $ # # Generic Makefile body to be concatenated to config header. # # Imports: # PVM_ARCH = the official pvm-name of your processor # ARCHCFLAGS = special cc flags # ARCHLIB = special libs needed for daemon # SHELL = /bin/sh PVMDIR = ../.. PVMIDIR = $(PVMDIR)/include PVMLDIR = $(PVMDIR)/lib/$(PVM_ARCH) PVMLIB = pvm3 PVMLIBDEP = $(PVMLDIR)/lib$(PVMLIB).a SDIR = $(PVMDIR)/tasker BDIR = $(PVMDIR)/bin XDIR = $(BDIR)/$(PVM_ARCH) CFLOPTS = -g CFLAGS = $(CFLOPTS) -I$(PVMIDIR) $(ARCHCFLAGS) \ -DIMA_$(PVM_ARCH) $(ARCHCFLAGS) LIBS = -L$(PVMLDIR) -l$(PVMLIB) $(ARCHLIB) HEADERS = $(PVMIDIR)/pvm3.h $(PVMIDIR)/pvmproto.h default: all all: $(XDIR) $(XDIR)/tasker $(XDIR): - mkdir $(BDIR) - mkdir $(XDIR) $(XDIR)/tasker: tasker cp tasker $(XDIR) tasker: $(SDIR)/tasker.c $(HEADERS) $(XDIR) $(PVMLIBDEP) $(CC) $(CFLAGS) -o tasker $(SDIR)/tasker.c $(LIBS) clean: rm -f tasker *.o ./pvm3/tasker/tasker.c0100644007401100000360000002147006463701625014043 0ustar kohlgopher static char rcsid[] = "$Id: tasker.c,v 1.7 1998/01/28 19:14:29 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * tasker.c * * Example tasker task to demonstrate and verify the protocol. * * 06 Mar 1994 Robert Manchek */ #ifdef HASSTDLIB #include #endif #include #include #include /* #ifdef IMA_LINUX */ /* #include */ /* #endif */ #include #include #include #ifdef IMA_RS6K #include #endif #ifdef SYSVSTR #include #else #include #endif #include #if defined(SYSVBFUNC) #include #define BZERO(d,n) memset(d,0,n) #define BCMP(s,d,n) memcmp(d,s,n) #define BCOPY(s,d,n) memcpy(d,s,n) #else #define BZERO(d,n) bzero(d,n) #define BCMP(s,d,n) bcmp(s,d,n) #define BCOPY(s,d,n) bcopy(s,d,n) #endif #define LISTPUTAFTER(o,n,f,r) \ { (n)->f=(o)->f; (n)->r=o; (o)->f->r=n; (o)->f=n; } #define LISTPUTBEFORE(o,n,f,r) \ { (n)->r=(o)->r; (n)->f=o; (o)->r->f=n; (o)->r=n; } #define LISTDELETE(e,f,r) \ { (e)->f->r=(e)->r; (e)->r->f=(e)->f; (e)->r=(e)->f=0; } #define TALLOC(n,t,g) (t*)malloc((n)*sizeof(t)) #define FREE(p) free((char *)p) #define STRALLOC(s) strcpy(TALLOC(strlen(s)+1,char,"str"),s) #ifndef DEBUG #define DEBUG 0 #endif /* * to collect stats from exited tasks */ struct deaddata { int dd_pid; /* process id */ int dd_es; /* unix exit status */ struct timeval dd_ut; /* user time used */ struct timeval dd_st; /* system time used */ }; /* * to track live tasks */ struct task { struct task *t_link, *t_rlink; int t_tid; int t_pid; }; int debug = DEBUG; struct deaddata *deads = 0; /* circ queue of dead task data */ int ndead = 1000; /* len of deads */ int rdead = 0; /* read ptr for deads */ int wdead = 0; /* write ptr for deads */ struct task *mytasks = 0; /************************** * task management stuff * * * **************************/ void task_init() { mytasks = TALLOC(1, struct task, 0); mytasks->t_link = mytasks->t_rlink = mytasks; mytasks->t_tid = 0; mytasks->t_pid = 0; } /* task_new() * * Make a new task descriptor, add to list. */ struct task * task_new(tid, pid) int tid, pid; { struct task *tp; if (!(tp = TALLOC(1, struct task, 0))) { fprintf(stderr, "task_new() can't get memory\n"); exit(1); } tp->t_tid = tid; tp->t_pid = pid; LISTPUTBEFORE(mytasks, tp, t_link, t_rlink); return tp; } void task_free(tp) struct task *tp; { LISTDELETE(tp, t_link, t_rlink); FREE(tp); } /* task_find() * * Find a task by its tid. */ struct task * task_find(tid) int tid; { struct task *tp; for (tp = mytasks->t_link; tp != mytasks; tp = tp->t_link) if (tp->t_tid == tid) return tp; return (struct task*)0; } /* task_findpid() * * Find a task by its pid. */ struct task * task_findpid(pid) int pid; { struct task *tp; for (tp = mytasks->t_link; tp != mytasks; tp = tp->t_link) if (tp->t_pid == pid) return tp; return (struct task*)0; } void task_dump() { struct task *tp; for (tp = mytasks->t_link; tp != mytasks; tp = tp->t_link) printf("t%x pid %d\n", tp->t_tid, tp->t_pid); } /****************** * general stuff * * * ******************/ /* reap() * * Child task has exited; get its stats and put in the fifo. */ void reap(sig) int sig; { int pid; int es = 0; #ifndef NOWAIT3 struct rusage rus; #endif sig = sig; #ifdef NOWAIT3 #ifdef NOWAITPID if ((pid = wait(&es)) > 0) #else while ((pid = waitpid(-1, &es, WNOHANG)) > 0) #endif #else /*NOWAIT3*/ while ((pid = wait3(&es, WNOHANG, &rus)) > 0) #endif /*NOWAIT3*/ { /* deads[wdead] = pid; */ #ifdef NOWAIT3 deads[wdead].dd_ut.tv_sec = 0; deads[wdead].dd_ut.tv_usec = 0; deads[wdead].dd_st.tv_sec = 0; deads[wdead].dd_st.tv_usec = 0; #else deads[wdead].dd_ut = rus.ru_utime; deads[wdead].dd_st = rus.ru_stime; #endif deads[wdead].dd_pid = pid; deads[wdead].dd_es = es; if (++wdead >= ndead) wdead = 0; } #ifdef SYSVSIGNAL (void)signal(SIGCLD, reap); #endif } main(argc, argv) int argc; char **argv; { int otid; /* tid of request */ int tag; /* message tag */ int *fdlist; /* to get libpvm fd list */ #ifdef FDSETNOTSTRUCT fd_set rfds, fds; #else struct fd_set rfds, fds; #endif int nfds; int mid; struct task *tp; pvm_mytid(); /* become a task */ pvm_setopt(PvmResvTids, 1); /* allow reserved messages */ pvm_reg_tasker(); /* register as tasker */ pvm_setopt(PvmRoute, PvmDontRoute); /* no freaks talking to me */ /* get the pvmd socket fd so we can wait with select() */ pvm_getfds(&fdlist); FD_ZERO(&rfds); FD_SET(fdlist[0], &rfds); nfds = fdlist[0] + 1; /* install child signal handler */ deads = TALLOC(ndead, struct deaddata, 0); BZERO((char*)deads, ndead * sizeof(struct deaddata)); #ifndef SYSVSIGNAL (void)signal(SIGCHLD, reap); #else (void)signal(SIGCLD, reap); #endif task_init(); while (1) { /* task_dump(); */ fds = rfds; select(nfds, #ifdef FDSETISINT (int *)&fds, (int *)0, (int *)0, #else (fd_set *)&fds, (fd_set *)0, (fd_set *)0, #endif (struct timeval *)0); /* clean up after any croaked processes */ while (rdead != wdead) { if (tp = task_findpid(deads[rdead].dd_pid)) { if (debug) printf("Exit t%x pid %d\n", tp->t_tid, tp->t_pid); pvm_packf("%+ %d %d %d %d %d %d", PvmDataFoo, tp->t_tid, deads[rdead].dd_es, (int)deads[rdead].dd_ut.tv_sec, (int)deads[rdead].dd_ut.tv_usec, (int)deads[rdead].dd_st.tv_sec, (int)deads[rdead].dd_st.tv_usec); pvm_send(0x80000000, SM_TASKX); task_free(tp); } if (++rdead >= ndead) rdead = 0; } /* check for task-start messages */ while ((mid = pvm_nrecv(-1, -1)) > 0) { pvm_bufinfo(pvm_getrbuf(), (int *)0, &tag, &otid); if (tag == SM_STTASK) { startem(); } else { printf("tasker: unknown message tag %d\n", tag); } } /* while nrecv >0 */ /* we need a test here to catch nrecv sys errors */ if (mid<0) break; } /* while the select/nrecv loop */ pvm_reg_tasker(); pvm_exit(); exit(0); } /* startem() * * Unpack task info from message and start it up. * * SM_STTASK() { * uint tid * int flags * string path * int argc * string argv[argc] * int nenv * string env[nenv] * } */ int startem() { int tid; int flags; char path[1024]; char buf[1024]; int ac; char **av; int nenv; char **envp; int i; int pid; pvm_unpackf("%ud %d %s %d", &tid, &flags, path, &ac); av = TALLOC(ac + 1, char *, 0); av[ac] = 0; for (i = 0; i < ac; i++) { pvm_unpackf("%s", buf); av[i] = STRALLOC(buf); } pvm_unpackf("%d", &nenv); envp = TALLOC(nenv + 1, char *, 0); envp[nenv] = 0; for (i = 0; i < nenv; i++) { pvm_unpackf("%s", buf); envp[i] = STRALLOC(buf); } if (debug) { printf("tid t%x flags %x path \"%s\"\n", tid, flags, path); printf("argc %d\n", ac); for (i = 0; i < ac; i++) printf(" %d \"%s\"\n", i, av[i]); printf("nenv %d\n", nenv); for (i = 0; i < nenv; i++) printf(" %d \"%s\"\n", i, envp[i]); } if ((pid = dofork(path, ac, av, nenv, envp)) != -1) { task_new(tid, pid); if (debug) printf("Forked %d\n", pid); } else { pvm_packf("%+ %d %d %d %d %d %d", PvmDataFoo, tid, 0, 0, 0, 0, 0); pvm_send(0x80000000, SM_TASKX); } return pid; } /* dofork() * * Fork and exec task, add changes to environment first. */ int dofork(path, argc, argv, nenv, envp) char *path; int argc; char **argv; int nenv; char **envp; { int pid; if (pid = fork()) { } else { pvmendtask(); while (nenv-- > 0) pvmputenv(envp[nenv]); execv(path, argv); /* execve(path, argv, envp); */ fprintf(stderr, "dofork() aaugh, bit it\n"); _exit(1); } return pid; } ./pvm3/xdr/0042755007401100000360000000000010117676455011716 5ustar kohlgopher./pvm3/xdr/xdr.c0100644007401100000360000002570106355032360012645 0ustar kohlgopher/* @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ #if !defined(lint) && defined(SCCSIDS) static char sccsid[] = "@(#)xdr.c 1.35 87/08/12"; #endif /* * xdr.c, Generic XDR routines implementation. * * Copyright (C) 1986, Sun Microsystems, Inc. * * These are the "generic" xdr routines used to serialize and de-serialize * most common data items. See xdr.h for more info on the interface to * xdr. */ #include char *malloc(); #include "..\xdr\types.h" #include "..\xdr\xdr.h" /* * constants specific to the xdr "protocol" */ #define XDR_FALSE ((long) 0) #define XDR_TRUE ((long) 1) #define LASTUNSIGNED ((u_int) 0-1) /* * for unit alignment */ static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 }; /* * Free a data structure using XDR * Not a filter, but a convenient utility nonetheless */ void xdr_free(proc, objp) xdrproc_t proc; char *objp; { XDR x; x.x_op = XDR_FREE; (*proc)(&x, objp); } /* * XDR nothing */ bool_t xdr_void(/* xdrs, addr */) /* XDR *xdrs; */ /* caddr_t addr; */ { return (TRUE); } /* * XDR integers */ bool_t xdr_int(xdrs, ip) XDR *xdrs; int *ip; { #ifdef lint (void) (xdr_short(xdrs, (short *)ip)); return (xdr_long(xdrs, (long *)ip)); #else if (sizeof (int) == sizeof (long)) { return (xdr_long(xdrs, (long *)ip)); } else { return (xdr_short(xdrs, (short *)ip)); } #endif } /* * XDR unsigned integers */ bool_t xdr_u_int(xdrs, up) XDR *xdrs; u_int *up; { #ifdef lint (void) (xdr_short(xdrs, (short *)up)); return (xdr_u_long(xdrs, (u_long *)up)); #else if (sizeof (u_int) == sizeof (u_long)) { return (xdr_u_long(xdrs, (u_long *)up)); } else { return (xdr_short(xdrs, (short *)up)); } #endif } /* * XDR long integers * same as xdr_u_long - open coded to save a proc call! */ bool_t xdr_long(xdrs, lp) register XDR *xdrs; long *lp; { if (xdrs->x_op == XDR_ENCODE) return (XDR_PUTLONG(xdrs, lp)); if (xdrs->x_op == XDR_DECODE) return (XDR_GETLONG(xdrs, lp)); if (xdrs->x_op == XDR_FREE) return (TRUE); return (FALSE); } /* * XDR unsigned long integers * same as xdr_long - open coded to save a proc call! */ bool_t xdr_u_long(xdrs, ulp) register XDR *xdrs; u_long *ulp; { if (xdrs->x_op == XDR_DECODE) return (XDR_GETLONG(xdrs, (long *)ulp)); if (xdrs->x_op == XDR_ENCODE) return (XDR_PUTLONG(xdrs, (long *)ulp)); if (xdrs->x_op == XDR_FREE) return (TRUE); return (FALSE); } /* * XDR short integers */ bool_t xdr_short(xdrs, sp) register XDR *xdrs; short *sp; { long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (long) *sp; return (XDR_PUTLONG(xdrs, &l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &l)) { return (FALSE); } *sp = (short) l; return (TRUE); case XDR_FREE: return (TRUE); } return (FALSE); } /* * XDR unsigned short integers */ bool_t xdr_u_short(xdrs, usp) register XDR *xdrs; u_short *usp; { u_long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (u_long) *usp; return (XDR_PUTLONG(xdrs, &l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &l)) { return (FALSE); } *usp = (u_short) l; return (TRUE); case XDR_FREE: return (TRUE); } return (FALSE); } /* * XDR a char */ bool_t xdr_char(xdrs, cp) XDR *xdrs; char *cp; { int i; i = (*cp); if (!xdr_int(xdrs, &i)) { return (FALSE); } *cp = i; return (TRUE); } /* * XDR an unsigned char */ bool_t xdr_u_char(xdrs, cp) XDR *xdrs; char *cp; { u_int u; u = (*cp); if (!xdr_u_int(xdrs, &u)) { return (FALSE); } *cp = u; return (TRUE); } /* * XDR booleans */ bool_t xdr_bool(xdrs, bp) register XDR *xdrs; bool_t *bp; { long lb; switch (xdrs->x_op) { case XDR_ENCODE: lb = *bp ? XDR_TRUE : XDR_FALSE; return (XDR_PUTLONG(xdrs, &lb)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &lb)) { return (FALSE); } *bp = (lb == XDR_FALSE) ? FALSE : TRUE; return (TRUE); case XDR_FREE: return (TRUE); } return (FALSE); } /* * XDR enumerations */ bool_t xdr_enum(xdrs, ep) XDR *xdrs; enum_t *ep; { #ifndef lint enum sizecheck { SIZEVAL }; /* used to find the size of an enum */ /* * enums are treated as ints */ if (sizeof (enum sizecheck) == sizeof (long)) { return (xdr_long(xdrs, (long *)ep)); } else if (sizeof (enum sizecheck) == sizeof (short)) { return (xdr_short(xdrs, (short *)ep)); } else { return (FALSE); } #else (void) (xdr_short(xdrs, (short *)ep)); return (xdr_long(xdrs, (long *)ep)); #endif } /* * XDR opaque data * Allows the specification of a fixed size sequence of opaque bytes. * cp points to the opaque object and cnt gives the byte length. */ bool_t xdr_opaque(xdrs, cp, cnt) register XDR *xdrs; caddr_t cp; register u_int cnt; { register u_int rndup; static crud[BYTES_PER_XDR_UNIT]; /* * if no data we are done */ if (cnt == 0) return (TRUE); /* * round byte count to full xdr units */ rndup = cnt % BYTES_PER_XDR_UNIT; if (rndup > 0) rndup = BYTES_PER_XDR_UNIT - rndup; if (xdrs->x_op == XDR_DECODE) { if (!XDR_GETBYTES(xdrs, cp, cnt)) { return (FALSE); } if (rndup == 0) return (TRUE); return (XDR_GETBYTES(xdrs, crud, rndup)); } if (xdrs->x_op == XDR_ENCODE) { if (!XDR_PUTBYTES(xdrs, cp, cnt)) { return (FALSE); } if (rndup == 0) return (TRUE); return (XDR_PUTBYTES(xdrs, xdr_zero, rndup)); } if (xdrs->x_op == XDR_FREE) { return (TRUE); } return (FALSE); } /* * XDR counted bytes * *cpp is a pointer to the bytes, *sizep is the count. * If *cpp is NULL maxsize bytes are allocated */ bool_t xdr_bytes(xdrs, cpp, sizep, maxsize) register XDR *xdrs; char **cpp; register u_int *sizep; u_int maxsize; { register char *sp = *cpp; /* sp is the actual string pointer */ register u_int nodesize; /* * first deal with the length since xdr bytes are counted */ if (! xdr_u_int(xdrs, sizep)) { return (FALSE); } nodesize = *sizep; if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) { return (FALSE); } /* * now deal with the actual bytes */ switch (xdrs->x_op) { case XDR_DECODE: if (nodesize == 0) { return (TRUE); } if (sp == NULL) { *cpp = sp = (char *)mem_alloc(nodesize); } if (sp == NULL) { #ifdef WIN32 nt_rpc_report("xdr_bytes: out of memory\n"); #else (void) fprintf(stderr, "xdr_bytes: out of memory\n"); #endif return (FALSE); } /* fall into ... */ case XDR_ENCODE: return (xdr_opaque(xdrs, sp, nodesize)); case XDR_FREE: if (sp != NULL) { mem_free(sp, nodesize); *cpp = NULL; } return (TRUE); } return (FALSE); } /* * Implemented here due to commonality of the object. */ bool_t xdr_netobj(xdrs, np) XDR *xdrs; struct netobj *np; { return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ)); } /* * XDR a descriminated union * Support routine for discriminated unions. * You create an array of xdrdiscrim structures, terminated with * an entry with a null procedure pointer. The routine gets * the discriminant value and then searches the array of xdrdiscrims * looking for that value. It calls the procedure given in the xdrdiscrim * to handle the discriminant. If there is no specific routine a default * routine may be called. * If there is no specific or default routine an error is returned. */ bool_t xdr_union(xdrs, dscmp, unp, choices, dfault) register XDR *xdrs; enum_t *dscmp; /* enum to decide which arm to work on */ char *unp; /* the union itself */ struct xdr_discrim *choices; /* [value, xdr proc] for each arm */ xdrproc_t dfault; /* default xdr routine */ { register enum_t dscm; /* * we deal with the discriminator; it's an enum */ if (! xdr_enum(xdrs, dscmp)) { return (FALSE); } dscm = *dscmp; /* * search choices for a value that matches the discriminator. * if we find one, execute the xdr routine for that value. */ for (; choices->proc != NULL_xdrproc_t; choices++) { if (choices->value == dscm) return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED)); } /* * no match - execute the default xdr routine if there is one */ return ((dfault == NULL_xdrproc_t) ? FALSE : (*dfault)(xdrs, unp, LASTUNSIGNED)); } /* * Non-portable xdr primitives. * Care should be taken when moving these routines to new architectures. */ /* * XDR null terminated ASCII strings * xdr_string deals with "C strings" - arrays of bytes that are * terminated by a NULL character. The parameter cpp references a * pointer to storage; If the pointer is null, then the necessary * storage is allocated. The last parameter is the max allowed length * of the string as specified by a protocol. */ bool_t xdr_string(xdrs, cpp, maxsize) register XDR *xdrs; char **cpp; u_int maxsize; { register char *sp = *cpp; /* sp is the actual string pointer */ u_int size; u_int nodesize; /* * first deal with the length since xdr strings are counted-strings */ switch (xdrs->x_op) { case XDR_FREE: if (sp == NULL) { return(TRUE); /* already free */ } /* fall through... */ case XDR_ENCODE: size = strlen(sp); break; } if (! xdr_u_int(xdrs, &size)) { return (FALSE); } if (size > maxsize) { return (FALSE); } nodesize = size + 1; /* * now deal with the actual bytes */ switch (xdrs->x_op) { case XDR_DECODE: if (nodesize == 0) { return (TRUE); } if (sp == NULL) *cpp = sp = (char *)mem_alloc(nodesize); if (sp == NULL) { #ifdef WIN32 nt_rpc_report("xdr_string: out of memory\n"); #else (void) fprintf(stderr, "xdr_string: out of memory\n"); #endif return (FALSE); } sp[size] = 0; /* fall into ... */ case XDR_ENCODE: return (xdr_opaque(xdrs, sp, size)); case XDR_FREE: mem_free(sp, nodesize); *cpp = NULL; return (TRUE); } return (FALSE); } /* * Wrapper for xdr_string that can be called directly from * routines like clnt_call */ bool_t xdr_wrapstring(xdrs, cpp) XDR *xdrs; char **cpp; { if (xdr_string(xdrs, cpp, LASTUNSIGNED)) { return (TRUE); } return (FALSE); } ./pvm3/xdr/xdr_floa.c0100644007401100000360000001664106355032363013654 0ustar kohlgopher/* @(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ #if !defined(lint) && defined(SCCSIDS) static char sccsid[] = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro"; #endif /* * xdr_float.c, Generic XDR routines impelmentation. * * Copyright (C) 1984, Sun Microsystems, Inc. * * These are the "floating point" xdr routines used to (de)serialize * most common data items. See xdr.h for more info on the interface to * xdr. */ #include #include "..\xdr\types.h" #include "..\xdr\xdr.h" /* * NB: Not portable. * This routine works on Suns (Sky / 68000's) and Vaxen. */ #if defined(vax) || defined(WIN32) /* What IEEE single precision floating point looks like on a Vax */ struct ieee_single { unsigned int mantissa: 23; unsigned int exp : 8; unsigned int sign : 1; }; /* Vax single precision floating point */ struct vax_single { unsigned int mantissa1 : 7; unsigned int exp : 8; unsigned int sign : 1; unsigned int mantissa2 : 16; }; #define VAX_SNG_BIAS 0x81 #define IEEE_SNG_BIAS 0x7f static struct sgl_limits { struct vax_single s; struct ieee_single ieee; } sgl_limits[2] = { {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */ { 0x0, 0xff, 0x0 }}, /* Max IEEE */ {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */ { 0x0, 0x0, 0x0 }} /* Min IEEE */ }; #endif /* vax */ bool_t xdr_float(xdrs, fp) register XDR *xdrs; register float *fp; { #if !defined(mc68000) && !defined(sparc) && !defined(mips) && !defined(mmax) && !defined(_X86_) struct ieee_single is; struct vax_single vs, *vsp; struct sgl_limits *lim; int i; #endif switch (xdrs->x_op) { case XDR_ENCODE: #if defined(WIN32) || defined(mc68000) || defined(sparc) || defined(mips) || defined(mmax) || defined(_X86_) return (XDR_PUTLONG(xdrs, (long *)fp)); #else vs = *((struct vax_single *)fp); for (i = 0, lim = sgl_limits; i < sizeof(sgl_limits)/sizeof(struct sgl_limits); i++, lim++) { if ((vs.mantissa2 == lim->s.mantissa2) && (vs.exp == lim->s.exp) && (vs.mantissa1 == lim->s.mantissa1)) { is = lim->ieee; goto shipit; } } is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS; is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2; shipit: is.sign = vs.sign; return (XDR_PUTLONG(xdrs, (long *)&is)); #endif case XDR_DECODE: #if defined(WIN32) || defined(mc68000) || defined(sparc) || defined(mips) || defined(mmax) || defined(_X86_) return (XDR_GETLONG(xdrs, (long *)fp)); #else vsp = (struct vax_single *)fp; if (!XDR_GETLONG(xdrs, (long *)&is)) return (FALSE); for (i = 0, lim = sgl_limits; i < sizeof(sgl_limits)/sizeof(struct sgl_limits); i++, lim++) { if ((is.exp == lim->ieee.exp) && (is.mantissa == lim->ieee.mantissa)) { *vsp = lim->s; goto doneit; } } vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS; vsp->mantissa2 = is.mantissa; vsp->mantissa1 = (is.mantissa >> 16); doneit: vsp->sign = is.sign; return (TRUE); #endif case XDR_FREE: return (TRUE); } return (FALSE); } /* * This routine works on Suns (Sky / 68000's) and Vaxen. */ #ifdef vax /* What IEEE double precision floating point looks like on a Vax */ struct ieee_double { unsigned int mantissa1 : 20; unsigned int exp : 11; unsigned int sign : 1; unsigned int mantissa2 : 32; }; /* Vax double precision floating point */ struct vax_double { unsigned int mantissa1 : 7; unsigned int exp : 8; unsigned int sign : 1; unsigned int mantissa2 : 16; unsigned int mantissa3 : 16; unsigned int mantissa4 : 16; }; #define VAX_DBL_BIAS 0x81 #define IEEE_DBL_BIAS 0x3ff #define MASK(nbits) ((1 << nbits) - 1) static struct dbl_limits { struct vax_double d; struct ieee_double ieee; } dbl_limits[2] = { {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */ { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */ {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */ { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */ }; #endif /* vax */ bool_t xdr_double(xdrs, dp) register XDR *xdrs; double *dp; { register long *lp; #if !defined(WIN32) && !defined(mc68000) && !defined(sparc) && !defined(mips) && !defined(mmax) && !defined(_X86_) struct ieee_double id; struct vax_double vd; register struct dbl_limits *lim; int i; #endif switch (xdrs->x_op) { case XDR_ENCODE: #if defined(WIN32) || defined(mc68000) || defined(sparc) || defined(mips) || defined(mmax) || defined(_X86_) lp = (long *)dp; #else vd = *((struct vax_double *)dp); for (i = 0, lim = dbl_limits; i < sizeof(dbl_limits)/sizeof(struct dbl_limits); i++, lim++) { if ((vd.mantissa4 == lim->d.mantissa4) && (vd.mantissa3 == lim->d.mantissa3) && (vd.mantissa2 == lim->d.mantissa2) && (vd.mantissa1 == lim->d.mantissa1) && (vd.exp == lim->d.exp)) { id = lim->ieee; goto shipit; } } id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS; id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3); id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) | (vd.mantissa3 << 13) | ((vd.mantissa4 >> 3) & MASK(13)); shipit: id.sign = vd.sign; lp = (long *)&id; #endif #if defined(WIN32) || defined(_X86_) return (XDR_PUTLONG(xdrs, lp+1) && XDR_PUTLONG(xdrs, lp)); #else return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp)); #endif case XDR_DECODE: #if defined(WIN32) || defined(mc68000) || defined(sparc) || defined(mips) || defined(mmax) || defined(_X86_) lp = (long *)dp; #if defined(WIN32) || defined(_X86_) return (XDR_GETLONG(xdrs, lp+1) && XDR_GETLONG(xdrs, lp)); #else return (XDR_GETLONG(xdrs, lp++) && XDR_GETLONG(xdrs, lp)); #endif #else lp = (long *)&id; if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp)) return (FALSE); for (i = 0, lim = dbl_limits; i < sizeof(dbl_limits)/sizeof(struct dbl_limits); i++, lim++) { if ((id.mantissa2 == lim->ieee.mantissa2) && (id.mantissa1 == lim->ieee.mantissa1) && (id.exp == lim->ieee.exp)) { vd = lim->d; goto doneit; } } vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS; vd.mantissa1 = (id.mantissa1 >> 13); vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) | (id.mantissa2 >> 29); vd.mantissa3 = (id.mantissa2 >> 13); vd.mantissa4 = (id.mantissa2 << 3); doneit: vd.sign = id.sign; *dp = *((double *)&vd); return (TRUE); #endif case XDR_FREE: return (TRUE); } return (FALSE); } ./pvm3/xdr/xdr_mem.c0100644007401100000360000001052307240353134013476 0ustar kohlgopher/* @(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ #if !defined(lint) && defined(SCCSIDS) static char sccsid[] = "@(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro"; #endif /* * xdr_mem.h, XDR implementation using memory buffers. * * Copyright (C) 1984, Sun Microsystems, Inc. * * If you have some data to be interpreted as external data representation * or to be converted to external data representation in a memory buffer, * then this is the package for you. * */ #if defined(WIN32) || defined(CYGWIN) #include "..\xdr\types.h" #include "..\xdr\xdr.h" #else #include #include #endif #ifdef WIN32 #define bcopy(a,b,c) memcpy(a,b,c) #include #else #include #endif static bool_t xdrmem_getlong(); static bool_t xdrmem_putlong(); static bool_t xdrmem_getbytes(); static bool_t xdrmem_putbytes(); static u_int xdrmem_getpos(); static bool_t xdrmem_setpos(); static long * xdrmem_inline(); static void xdrmem_destroy(); static struct xdr_ops xdrmem_ops = { xdrmem_getlong, xdrmem_putlong, xdrmem_getbytes, xdrmem_putbytes, xdrmem_getpos, xdrmem_setpos, xdrmem_inline, xdrmem_destroy }; /* * The procedure xdrmem_create initializes a stream descriptor for a * memory buffer. */ void xdrmem_create(xdrs, addr, size, op) register XDR *xdrs; caddr_t addr; u_int size; enum xdr_op op; { xdrs->x_op = op; xdrs->x_ops = &xdrmem_ops; xdrs->x_private = xdrs->x_base = addr; xdrs->x_handy = size; } static void xdrmem_destroy(/*xdrs*/) /*XDR *xdrs;*/ { } static bool_t xdrmem_getlong(xdrs, lp) register XDR *xdrs; long *lp; { if ((xdrs->x_handy -= sizeof(long)) < 0) return (FALSE); *lp = (long)ntohl((u_long)(*((long *)(xdrs->x_private)))); xdrs->x_private += sizeof(long); return (TRUE); } static bool_t xdrmem_putlong(xdrs, lp) register XDR *xdrs; long *lp; { if ((xdrs->x_handy -= sizeof(long)) < 0) return (FALSE); *(long *)xdrs->x_private = (long)htonl((u_long)(*lp)); xdrs->x_private += sizeof(long); return (TRUE); } static bool_t xdrmem_getbytes(xdrs, addr, len) register XDR *xdrs; caddr_t addr; register u_int len; { if ((xdrs->x_handy -= len) < 0) return (FALSE); bcopy(xdrs->x_private, addr, len); xdrs->x_private += len; return (TRUE); } static bool_t xdrmem_putbytes(xdrs, addr, len) register XDR *xdrs; caddr_t addr; register u_int len; { if ((xdrs->x_handy -= len) < 0) return (FALSE); bcopy(addr, xdrs->x_private, len); xdrs->x_private += len; return (TRUE); } static u_int xdrmem_getpos(xdrs) register XDR *xdrs; { return ((u_int)xdrs->x_private - (u_int)xdrs->x_base); } static bool_t xdrmem_setpos(xdrs, pos) register XDR *xdrs; u_int pos; { register caddr_t newaddr = xdrs->x_base + pos; register caddr_t lastaddr = xdrs->x_private + xdrs->x_handy; if ((long)newaddr > (long)lastaddr) return (FALSE); xdrs->x_private = newaddr; xdrs->x_handy = (int)lastaddr - (int)newaddr; return (TRUE); } static long * xdrmem_inline(xdrs, len) register XDR *xdrs; int len; { long *buf = 0; if (xdrs->x_handy >= len) { xdrs->x_handy -= len; buf = (long *) xdrs->x_private; xdrs->x_private += len; } return (buf); } ./pvm3/xdr/types.h0100644007401100000360000000431307620015670013216 0ustar kohlgopher/* @(#)types.h 2.3 88/08/15 4.0 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ /* @(#)types.h 1.18 87/07/24 SMI */ /* * Rpc additions to */ #ifndef __TYPES_RPC_HEADER__ #define __TYPES_RPC_HEADER__ #define bool_t int #define enum_t int #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE (1) #endif #define __dontcare__ -1 #ifndef NULL # define NULL 0 #endif #ifndef WIN32 extern char *malloc(); #endif #define mem_alloc malloc #define mem_free(ptr, bsize) free(ptr) #ifndef makedev /* ie, we haven't already included it */ #include #endif #ifndef WIN32 #include #endif #ifndef CYGWIN #ifndef WIN32 #ifndef INADDR_LOOPBACK #define INADDR_LOOPBACK (u_long)0x7F000001 #endif #endif #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 64 #endif typedef char *caddr_t; typedef unsigned int u_int; typedef unsigned long u_long; typedef unsigned short u_short; #endif /* Conflict (CYGWIN) */ #endif /* ndef __TYPES_RPC_HEADER__ */ ./pvm3/xdr/xdr.h0100644007401100000360000002240206355032362012647 0ustar kohlgopher/* @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ /* @(#)xdr.h 1.19 87/04/22 SMI */ /* * xdr.h, External Data Representation Serialization Routines. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #ifndef __XDR_HEADER__ #define __XDR_HEADER__ /* * XDR provides a conventional way for converting between C data * types and an external bit-string representation. Library supplied * routines provide for the conversion on built-in C data types. These * routines and utility routines defined here are used to help implement * a type encode/decode routine for each user-defined type. * * Each data type provides a single procedure which takes two arguments: * * bool_t * xdrproc(xdrs, argresp) * XDR *xdrs; * *argresp; * * xdrs is an instance of a XDR handle, to which or from which the data * type is to be converted. argresp is a pointer to the structure to be * converted. The XDR handle contains an operation field which indicates * which of the operations (ENCODE, DECODE * or FREE) is to be performed. * * XDR_DECODE may allocate space if the pointer argresp is null. This * data can be freed with the XDR_FREE operation. * * We write only one procedure per data type to make it easy * to keep the encode and decode procedures for a data type consistent. * In many cases the same code performs all operations on a user defined type, * because all the hard work is done in the component type routines. * decode as a series of calls on the nested data types. */ /* * Xdr operations. XDR_ENCODE causes the type to be encoded into the * stream. XDR_DECODE causes the type to be extracted from the stream. * XDR_FREE can be used to release the space allocated by an XDR_DECODE * request. */ enum xdr_op { XDR_ENCODE=0, XDR_DECODE=1, XDR_FREE=2 }; /* * This is the number of bytes per unit of external data. */ #define BYTES_PER_XDR_UNIT (4) #define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \ * BYTES_PER_XDR_UNIT) /* * A xdrproc_t exists for each data type which is to be encoded or decoded. * * The second argument to the xdrproc_t is a pointer to an opaque pointer. * The opaque pointer generally points to a structure of the data type * to be decoded. If this pointer is 0, then the type routines should * allocate dynamic storage of the appropriate size and return it. * bool_t (*xdrproc_t)(XDR *, caddr_t *); */ typedef bool_t (*xdrproc_t)(); /* * The XDR handle. * Contains operation which is being applied to the stream, * an operations vector for the paticular implementation (e.g. see xdr_mem.c), * and two private fields for the use of the particular impelementation. */ typedef struct { enum xdr_op x_op; /* operation; fast additional param */ struct xdr_ops { bool_t (*x_getlong)(); /* get a long from underlying stream */ bool_t (*x_putlong)(); /* put a long to " */ bool_t (*x_getbytes)();/* get some bytes from " */ bool_t (*x_putbytes)();/* put some bytes to " */ u_int (*x_getpostn)();/* returns bytes off from beginning */ bool_t (*x_setpostn)();/* lets you reposition the stream */ long * (*x_inline)(); /* buf quick ptr to buffered data */ void (*x_destroy)(); /* free privates of this xdr_stream */ } *x_ops; caddr_t x_public; /* users' data */ caddr_t x_private; /* pointer to private data */ caddr_t x_base; /* private used for position info */ int x_handy; /* extra private word */ } XDR; /* * Operations defined on a XDR handle * * XDR *xdrs; * long *longp; * caddr_t addr; * u_int len; * u_int pos; */ #define XDR_GETLONG(xdrs, longp) \ (*(xdrs)->x_ops->x_getlong)(xdrs, longp) #define xdr_getlong(xdrs, longp) \ (*(xdrs)->x_ops->x_getlong)(xdrs, longp) #define XDR_PUTLONG(xdrs, longp) \ (*(xdrs)->x_ops->x_putlong)(xdrs, longp) #define xdr_putlong(xdrs, longp) \ (*(xdrs)->x_ops->x_putlong)(xdrs, longp) #define XDR_GETBYTES(xdrs, addr, len) \ (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) #define xdr_getbytes(xdrs, addr, len) \ (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) #define XDR_PUTBYTES(xdrs, addr, len) \ (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) #define xdr_putbytes(xdrs, addr, len) \ (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) #define XDR_GETPOS(xdrs) \ (*(xdrs)->x_ops->x_getpostn)(xdrs) #define xdr_getpos(xdrs) \ (*(xdrs)->x_ops->x_getpostn)(xdrs) #define XDR_SETPOS(xdrs, pos) \ (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) #define xdr_setpos(xdrs, pos) \ (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) #define XDR_INLINE(xdrs, len) \ (*(xdrs)->x_ops->x_inline)(xdrs, len) #define xdr_inline(xdrs, len) \ (*(xdrs)->x_ops->x_inline)(xdrs, len) #define XDR_DESTROY(xdrs) \ if ((xdrs)->x_ops->x_destroy) \ (*(xdrs)->x_ops->x_destroy)(xdrs) #define xdr_destroy(xdrs) \ if ((xdrs)->x_ops->x_destroy) \ (*(xdrs)->x_ops->x_destroy)(xdrs) /* * Support struct for discriminated unions. * You create an array of xdrdiscrim structures, terminated with * a entry with a null procedure pointer. The xdr_union routine gets * the discriminant value and then searches the array of structures * for a matching value. If a match is found the associated xdr routine * is called to handle that part of the union. If there is * no match, then a default routine may be called. * If there is no match and no default routine it is an error. */ #define NULL_xdrproc_t ((xdrproc_t)0) struct xdr_discrim { int value; xdrproc_t proc; }; /* * In-line routines for fast encode/decode of primitve data types. * Caveat emptor: these use single memory cycles to get the * data from the underlying buffer, and will fail to operate * properly if the data is not aligned. The standard way to use these * is to say: * if ((buf = XDR_INLINE(xdrs, count)) == NULL) * return (FALSE); * <<< macro calls >>> * where ``count'' is the number of bytes of data occupied * by the primitive data types. * * N.B. and frozen for all time: each data type here uses 4 bytes * of external representation. */ #define IXDR_GET_LONG(buf) ((long)ntohl((u_long)*(buf)++)) #define IXDR_PUT_LONG(buf, v) (*(buf)++ = (long)htonl((u_long)v)) #define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf)) #define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf)) #define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_LONG(buf)) #define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf)) #define IXDR_GET_U_SHORT(buf) ((u_short)IXDR_GET_LONG(buf)) #define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) #define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) #define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) #define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) #define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) /* * These are the "generic" xdr routines. */ extern bool_t xdr_void(); extern bool_t xdr_int(); extern bool_t xdr_u_int(); extern bool_t xdr_long(); extern bool_t xdr_u_long(); extern bool_t xdr_short(); extern bool_t xdr_u_short(); extern bool_t xdr_bool(); extern bool_t xdr_enum(); extern bool_t xdr_array(); extern bool_t xdr_bytes(); extern bool_t xdr_opaque(); extern bool_t xdr_string(); extern bool_t xdr_union(); extern bool_t xdr_char(); extern bool_t xdr_u_char(); extern bool_t xdr_vector(); extern bool_t xdr_float(); extern bool_t xdr_double(); extern bool_t xdr_reference(); extern bool_t xdr_pointer(); extern bool_t xdr_wrapstring(); /* * Common opaque bytes objects used by many rpc protocols; * declared here due to commonality. */ #define MAX_NETOBJ_SZ 1024 struct netobj { u_int n_len; char *n_bytes; }; typedef struct netobj netobj; extern bool_t xdr_netobj(); /* * These are the public routines for the various implementations of * xdr streams. */ extern void xdrmem_create(); /* XDR using memory buffers */ extern void xdrstdio_create(); /* XDR using stdio library */ extern void xdrrec_create(); /* XDR pseudo records for tcp */ extern bool_t xdrrec_endofrecord(); /* make end of xdr record */ extern bool_t xdrrec_skiprecord(); /* move to beginning of next record */ extern bool_t xdrrec_eof(); /* true if no more input */ #endif /* __XDR_HEADER__ */ ./pvm3/xep/0042755007401100000360000000000010117676455011715 5ustar kohlgopher./pvm3/xep/Makefile.aimk0100644007401100000360000000345106401555014014257 0ustar kohlgopher# # $Id: Makefile.aimk,v 1.6 1997/08/29 14:17:48 pvmsrc Exp $ # # Generic Makefile body to be concatenated to config header. # # Imports: # PVM_ARCH = the official pvm-name of your processor # ARCHCFLAGS = special cc flags # ARCHLIB = special libs needed for daemon # SHELL = /bin/sh PVMDIR = ../.. PVMIDIR = $(PVMDIR)/include PVMLDIR = $(PVMDIR)/lib/$(PVM_ARCH) PVMLIB = pvm3 LIBPREFIX = lib PVMLIBDEP = $(PVMLDIR)/$(LIBPREFIX)$(PVMLIB).a SDIR = $(PVMDIR)/xep BDIR = $(PVMDIR)/bin XDIR = $(BDIR)/$(PVM_ARCH) #CFLOPTS = -O CFLOPTS = -g CFLAGS = $(CFLOPTS) -I$(PVMIDIR) -L$(PVMLDIR) $(ARCHCFLAGS) LIBS = -l$(PVMLIB) $(ARCHLIB) $(OS2XEPLIBS) XLIBS = -lXaw -lXmu -lXext -lXt -lX11 XCFLAGS = -I/usr/local/X11R5/include -I/usr/local/X11/include \ -L/usr/local/X11R5/lib -L/usr/local/X11/lib HEADERS = $(SDIR)/hostc.h $(SDIR)/imp.h $(SDIR)/myalloc.h \ $(PVMIDIR)/pvm3.h $(PVMDIR)/src/bfunc.h default: mtile$(EXESFX) xep$(EXESFX) all: mmain$(EXESFX) mtile$(EXESFX) xep$(EXESFX) $(XDIR): - mkdir $(BDIR) - mkdir $(XDIR) mmain$(EXESFX): $(SDIR)/mmain.c $(XDIR) $(PVMLIBDEP) $(CC) $(CFLAGS) -o $@ $(SDIR)/mmain.c $(LIBS) mv $@ $(XDIR) mtile$(EXESFX): $(SDIR)/mtile.c $(XDIR) $(PVMLIBDEP) $(CC) $(CFLAGS) -o $@ $(SDIR)/mtile.c $(LIBS) -lm mv $@ $(XDIR) xep$(EXESFX): xep.o hostc.o calc.o imp.o $(XDIR) $(PVMLIBDEP) $(CC) $(XCFLAGS) $(CFLAGS) -o $@ xep.o calc.o imp.o hostc.o \ $(XLIBS) $(LIBS) -lm mv $@ $(XDIR) clean: rm -f mmain$(EXESFX) mtile$(EXESFX) xep$(EXESFX) *.o xep.o: $(SDIR)/xep.c $(HEADERS) $(CC) $(XCFLAGS) $(CFLAGS) -c $(SDIR)/xep.c imp.o: $(SDIR)/imp.c $(HEADERS) $(CC) $(XCFLAGS) $(CFLAGS) -c $(SDIR)/imp.c calc.o: $(SDIR)/calc.c $(HEADERS) $(CC) $(XCFLAGS) $(CFLAGS) -c $(SDIR)/calc.c hostc.o: $(SDIR)/hostc.c $(HEADERS) $(CC) $(XCFLAGS) $(CFLAGS) -c $(SDIR)/hostc.c ./pvm3/xep/calc.c0100644007401100000360000002676006673500147012765 0ustar kohlgopher static char rcsid[] = "$Id: calc.c,v 1.3 1999/03/16 16:01:43 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * calc.c * * Bag of tasks driver for tiled workers. * Manages idle, busy, failed workers and message routing sockets. * * Oct 95 Manchek */ #ifdef HASSTDLIB #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "../src/bfunc.h" #include "../src/listmac.h" #include "myalloc.h" #include "hostc.h" #include "imp.h" #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif #ifndef max #define max(a,b) ((a)>(b)?(a):(b)) #endif #define JobSend 1 /* send tile to worker */ #define JobReturn 2 /* get image back from worker */ #define AddMessage 3 /* hosts were added */ #define DelMessage 4 /* hosts were deleted */ #define ExitMessage 5 /* worker exited */ #define RouteAddTag 6 /* new route socket opened */ #define RouteDeleteTag 7 /* route socket closed */ #define TILEHEIGHT 10 struct worker { struct worker *link, *rlink; /* dll of active or idle */ int tid; /* worker tid */ struct job *job; /* number */ XtInputId route; /* X id for route socket */ }; struct job { struct job *link, *rlink; int tile; /* tile number */ }; int gotmorehosts(); /*************** ** Globals ** ** ** ***************/ extern struct canvas imCan; /* from xep.c */ extern int dobars; /* from xep.c */ extern char *workerfile; /* from xep.c */ extern int nworkers; /* from xep.c */ int mytid; /* pvm tid */ struct worker *active = 0; /* active workers */ struct worker *idle = 0; /* idle workers */ struct job *todo = 0; /* jobs to be started */ int ntiles = 0; /* number of tiles in frame */ pvminit() { if ((mytid = pvm_mytid()) < 0) exit(1); pvm_notify(PvmRouteAdd, RouteAddTag, -1, (int *)0); pvm_setopt(PvmRoute, PvmRouteDirect); host_init(AddMessage, DelMessage, gotmorehosts, (int (*)())0); idle = TALLOC(1, struct worker, "worker"); idle->link = idle->rlink = idle; idle->tid = 0; idle->job = 0; active = TALLOC(1, struct worker, "worker"); active->link = active->rlink = active; active->tid = 0; active->job = 0; todo = TALLOC(1, struct job, "job"); todo->link = todo->rlink = todo; return 0; } more_workers() { int nh; int i; struct hostc *hp; struct worker *wp; int tid; hp = 0; nh = 0; while (hp = host_next(hp)) nh++; nh -= nworkers; if (nh <= 0) return 0; hp = 0; while (hp = host_next(hp)) { i = 0; for (wp = idle->link; wp != idle; wp = wp->link) if (pvm_tidtohost(wp->tid) == hp->pvmd_tid) { i = 1; break; } if (i) continue; for (wp = active->link; wp != active; wp = wp->link) if (pvm_tidtohost(wp->tid) == hp->pvmd_tid) { i = 1; break; } if (i) continue; if (pvm_spawn(workerfile, (char**)0, PvmTaskHost, hp->name, 1, &tid) < 0) { pvm_exit(); exit(1); } if (tid > 0) { wp = TALLOC(1, struct worker, "worker"); wp->tid = tid; wp->job = 0; wp->route = 0; LISTPUTBEFORE(idle, wp, link, rlink); pvm_notify(PvmTaskExit, ExitMessage, 1, &tid); #ifdef DEBUG fprintf(stderr, "more_workers() new worker 0x%x\n", tid); #endif nworkers++; } } setlabel(); return 0; } stop_workers() { struct worker *wp; while ((wp = idle->link) != idle) { #ifdef DEBUG fprintf(stderr, "stop_workers() killing 0x%x\n", wp->tid); #endif pvm_kill(wp->tid); LISTDELETE(wp, link, rlink); if (wp->route) { /* fprintf(stderr, "removeaninput() xii %ld\n", wp->route); */ XtRemoveInput(wp->route); wp->route = 0; } MY_FREE(wp); } while ((wp = active->link) != active) { #ifdef DEBUG fprintf(stderr, "stop_workers() killing 0x%x\n", wp->tid); #endif pvm_kill(wp->tid); LISTDELETE(wp, link, rlink); if (wp->route) { /* fprintf(stderr, "removeaninput() xii %ld\n", wp->route); */ XtRemoveInput(wp->route); wp->route = 0; } MY_FREE(wp); } nworkers = 0; setlabel(); return 0; } do_recalc() { struct worker *wp; struct job *jp; int ht = imCan.cn_ht; int i; /* toss anything that's already on the todo list */ while ((jp = todo->link) != todo) { LISTDELETE(jp, link, rlink); MY_FREE(jp); } /* scrub in-progress jobs */ for (wp = active; (wp = wp->link) != active; ) wp->job->tile = -1; /* fill it with new tiles */ ntiles = ht / TILEHEIGHT + 1; for (i = 0; i < ntiles; i += 8) { jp = TALLOC(1, struct job, "job"); jp->tile = i; LISTPUTBEFORE(todo, jp, link, rlink); } for (i = 4; i < ntiles; i += 8) { jp = TALLOC(1, struct job, "job"); jp->tile = i; LISTPUTBEFORE(todo, jp, link, rlink); } for (i = 2; i < ntiles; i += 4) { jp = TALLOC(1, struct job, "job"); jp->tile = i; LISTPUTBEFORE(todo, jp, link, rlink); } for (i = 1; i < ntiles; i += 2) { jp = TALLOC(1, struct job, "job"); jp->tile = i; LISTPUTBEFORE(todo, jp, link, rlink); } assign_work(); return 0; } /* assign_work() * * Send off tiles to idle workers. */ assign_work() { struct job *jp; struct worker *wp; double im1 = imCan.cn_im1; double im2 = imCan.cn_im2 - im1; int ht = imCan.cn_ht; int wd = imCan.cn_wd; double reim[4]; /* tile corner coords */ int wdht[2]; /* tile wd, ht */ int y1, y2; reim[0] = imCan.cn_re1; reim[2] = imCan.cn_re2; wdht[0] = wd; while (idle->link != idle && todo->link != todo) { jp = todo->link; LISTDELETE(jp, link, rlink); y2 = ((jp->tile + 1) * ht) / ntiles; y1 = (jp->tile * ht) / ntiles; reim[1] = im1 + (y1 * im2) / ht; reim[3] = im1 + (y2 * im2) / ht; wdht[1] = y2 - y1; wp = idle->link; LISTDELETE(wp, link, rlink); LISTPUTBEFORE(active, wp, link, rlink); wp->job = jp; #ifdef DEBUG fprintf(stderr, "sent job %d to 0x%x: %dx%d %f,%f/%f,%f\n", jp->tile, wp->tid, wdht[0], wdht[1], reim[0], reim[1], reim[2], reim[3]); #endif pvm_packf("%+ %2lx %2d", PvmDataDefault, reim, wdht); if (pvm_send(wp->tid, JobSend)) { pvm_exit(); exit(1); } if (dobars) label_row(y1, y2, wp->tid); } /* * we must check receive here because messages may have arrived * while we were sending, so the socket will not be ready to * read to wake us up. a bit sick. */ while (pvm_nrecv(-1, -1) > 0) claim_message(); return 0; } claim_message() { struct job *jp; struct worker *wp; int tag; int tid; /* id of sender */ int wd = imCan.cn_wd; int ht = imCan.cn_ht; double im1 = imCan.cn_im1; double im2 = imCan.cn_im2 - im1; double reim[4]; /* tile corner coords */ int wdht[2]; /* tile wd, ht */ int y1, y2; /* tile start, end rows */ int h; /* height of tile */ pvm_bufinfo(pvm_getrbuf(), (int*)0, &tag, &tid); #ifdef DEBUG fprintf(stderr, "message %d from 0x%x\n", tag, tid); #endif if (tag == AddMessage) { host_add(); } else if (tag == DelMessage) { host_delete(); } else if (tag == ExitMessage) { pvm_upkint(&tid, 1, 1); for (wp = idle->link; wp != idle; wp = wp->link) { if (wp->tid == tid) { LISTDELETE(wp, link, rlink); if (wp->route) { /* fprintf(stderr, "removeaninput() xii %ld\n", wp->route); */ XtRemoveInput(wp->route); wp->route = 0; } MY_FREE(wp); nworkers--; setlabel(); goto tryagain; } } for (wp = active->link; wp != active; wp = wp->link) { if (wp->tid == tid) { int i; LISTDELETE(wp, link, rlink); jp = wp->job; if (jp->tile >= 0) { LISTPUTAFTER(todo, jp, link, rlink); y1 = (jp->tile * ht) / ntiles; y2 = ((jp->tile + 1) * ht) / ntiles; h = y2 - y1; for (i = wd * h; i-- > 0; ) *((char*)imCan.cn_dat + y1 * wd + i) = 32; /* BZERO((char*)imCan.cn_dat + y1 * wd, wd * h); */ repaint_region(&imCan, 0, y1, wd - 1, y2 - 1); refresh_region(&imCan, 0, y1, wd - 1, y2 - 1); } else { MY_FREE(jp); } if (wp->route) { /* fprintf(stderr, "removeaninput() xii %ld\n", wp->route); */ XtRemoveInput(wp->route); wp->route = 0; } MY_FREE(wp); nworkers--; setlabel(); /* assign_work(); */ goto tryagain; } } tryagain: gotmorehosts(); /* hope we can start another */ } else if (tag == JobReturn) { for (wp = active->link; wp != active; wp = wp->link) if (wp->tid == tid) break; if (wp == active) { fprintf(stderr, "bogus message?\n"); return 0; } LISTDELETE(wp, link, rlink); jp = wp->job; if (jp->tile >= 0) { #ifdef DEBUG fprintf(stderr, "got job %d from 0x%x\n", jp->tile, wp->tid); #endif y1 = (jp->tile * ht) / ntiles; y2 = ((jp->tile + 1) * ht) / ntiles; h = y2 - y1; pvm_unpackf("%*c", wd * h, (char*)imCan.cn_dat + y1 * wd); if (dobars) label_row(y1, y2, wp->tid); repaint_region(&imCan, 0, y1, wd - 1, y2 - 1); refresh_region(&imCan, 0, y1, wd - 1, y2 - 1); } MY_FREE(jp); /* put work server back on free list */ LISTPUTBEFORE(idle, wp, link, rlink); /* assign more work if available */ assign_work(); } else if (tag == RouteAddTag) { int tid, fd; XtInputId xii; pvm_unpackf("%d %d", &tid, &fd); fprintf(stderr, "got route add notify tid 0x%x fd %d\n", tid, fd); for (wp = idle->link; wp != idle; wp = wp->link) if (wp->tid == tid) break; if (wp == idle) for (wp = active->link; wp != active; wp = wp->link) if (wp->tid == tid) break; if (wp == active) { fprintf(stderr, "route add notify for worker not mine tid 0x%x\n", tid); } else { addaninputfile(fd, &wp->route); pvm_notify(PvmRouteDelete, RouteDeleteTag, 1, &tid); } } else if (tag == RouteDeleteTag) { int tid, fd; XtInputId xii; pvm_unpackf("%d %d", &tid, &fd); fprintf(stderr, "got route delete notify tid 0x%x fd %d\n", tid, fd); for (wp = idle->link; wp != idle; wp = wp->link) if (wp->tid == tid) break; if (wp == idle) for (wp = active->link; wp != active; wp = wp->link) if (wp->tid == tid) break; if (wp == active) { fprintf(stderr, "route delete notify for worker not mine tid 0x%x\n", tid); } else if (wp->route) { /* removeaninputfile(wp->route); */ /* fprintf(stderr, "removeaninput() xii %ld\n", wp->route); */ XtRemoveInput(wp->route); wp->route = 0; } } return 0; } int gotmorehosts() { #ifdef DEBUG fprintf(stderr, "host added\n"); #endif more_workers(); assign_work(); return 0; } ./pvm3/xep/hostc.c0100644007401100000360000001447706741172515013205 0ustar kohlgopher static char rcsid[] = "$Id: hostc.c,v 1.5 1999/07/08 19:00:29 kohl Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * hostc.c * * Local host table cache functions. * * $Log: hostc.c,v $ * Revision 1.5 1999/07/08 19:00:29 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.4 1998/01/28 19:15:14 pvmsrc * Commented out ancient #include ... * (Spanker=kohl) * * Revision 1.3 1997/08/07 21:58:09 pvmsrc * Fixed stupid bugs... * * Revision 1.2 1997/07/09 13:56:50 pvmsrc * Fixed Author Header. * * Revision 1.1 1996/09/23 22:52:48 pvmsrc * Initial revision * */ #include #ifdef SYSVSTR #include #else #include #endif #include #include /* #ifdef IMA_LINUX */ /* #include */ /* #endif */ #include #include <../src/bfunc.h> #include <../src/listmac.h> #include "myalloc.h" #include "hostc.h" static struct hostc *curhosts = 0; static int addtag = -1; static int deltag = -1; static int (*addcallback)() = 0; static int (*delcallback)() = 0; static struct hostc * hc_new() { struct hostc *hp; if (hp = TALLOC(1, struct hostc, "hd")) BZERO(hp, sizeof(struct hostc)); return hp; } static int hc_init() { if (curhosts = hc_new()) curhosts->link = curhosts->rlink = curhosts; else fprintf(stderr, "hc_init() out of memory\n"); return 0; } static struct hostc * hc_add(hip) struct pvmhostinfo *hip; { struct hostc *hp, *hp2; /* * if we have a delete message tag and it's not this host, notify */ if (deltag != -1 && hip->hi_tid != pvm_tidtohost(pvm_mytid())) pvm_notify(PvmHostDelete, deltag, 1, &hip->hi_tid); if (hp = hc_new()) { hp->pvmd_tid = hip->hi_tid; hp->name = STRALLOC(hip->hi_name); hp->alias = STRALLOC(hip->hi_name); hp->arch = STRALLOC(hip->hi_arch); hp->speed = hip->hi_speed; pvm_hostsync(hp->pvmd_tid, (struct timeval *)0, &(hp->delta)); } for (hp2 = curhosts->link; hp2 != curhosts; hp2 = hp2->link) if (hp->pvmd_tid < hp2->pvmd_tid) break; LISTPUTBEFORE(hp2, hp, link, rlink); return hp; } static int hc_delete(hp) struct hostc *hp; { LISTDELETE(hp, link, rlink); if (hp->name) MY_FREE(hp->name); if (hp->arch) MY_FREE(hp->arch); if (hp->alias) MY_FREE(hp->alias); MY_FREE(hp); return 0; } static struct hostc * hc_find(tid) { struct hostc *hp; for (hp = curhosts->link; hp != curhosts; hp = hp->link) if (tid <= hp->pvmd_tid) break; return (tid == hp->pvmd_tid) ? hp : (struct hostc *)0; } /* host_init() * * Initialize host cache. Called once at beginning of time. * Synchronize to current configuration. * Specify message tags to be used for HostAdd and HostDelete notify. */ host_init(atag, dtag, acb, dcb) int atag; /* message tag to use for HostAdd notify or -1 */ int dtag; /* tag to use for HostDelete notify or -1 */ int (*acb)(); /* callback for each host added */ int (*dcb)(); /* callback for each host deleted */ { struct pvmhostinfo *hip; int nh; addtag = atag; deltag = dtag; addcallback = acb; delcallback = dcb; hc_init(); if (addtag != -1) pvm_notify(PvmHostAdd, addtag, -1, (int *)0); if (!pvm_config(&nh, (int *)0, &hip)) { while (nh > 0) { nh--; hc_add(&hip[nh]); } } return 0; } /* host_add() * * Called when a HostAdd notify message has been received. * The message is in the current receive buffer. */ host_add() { int d = 0; int n; int *dtids; int i, j; struct pvmhostinfo *hip; int nh; pvm_upkint(&n, 1, 1); if (n < 1 || n > 4096) return 0; dtids = TALLOC(n, int, "dtid"); pvm_upkint(dtids, n, 1); pvm_freebuf(pvm_getrbuf()); if (!pvm_config(&nh, (int *)0, &hip)) { for (j = n; j-- > 0; ) for (i = nh; i-- > 0; ) { if (dtids[j] == hip[i].hi_tid) { hc_add(&hip[i]); if (addcallback) addcallback(dtids[j]); d++; break; } } } MY_FREE(dtids); return d; } /* host_delete() * * Called when a HostDelete notify message has been received. * The message is in the current receive buffer. */ host_delete() { int tid; struct hostc *hp; int d = 0; pvm_upkint(&tid, 1, 1); if (tid == pvm_tidtohost(tid) && (hp = hc_find(tid))) { if (delcallback) delcallback(tid); hc_delete(hp); d++; } return d; } struct hostc * host_findtid(tid) int tid; { return hc_find(tid); } struct hostc * host_findname(name) char *name; { struct hostc *hp; for (hp = curhosts->link; hp != curhosts; hp = hp->link) if (!strcmp(name, hp->name)) return hp; return (struct hostc *)0; } struct hostc * host_next(hp) struct hostc *hp; { hp = hp ? hp->link : curhosts->link; return (hp == curhosts) ? 0 : hp; } int host_show() { struct hostc *hp; int nh = 0; int na = 0; int a; long mask = 0; for (hp = 0; hp = host_next(hp); ) { nh++; a = pvm_archcode(hp->arch); if (!(mask & (1 << a))) { na++; mask |= (1 << a); } } printf("Configuration: %d host%s, %d data format%s\n", nh, (nh == 1 ? "" : "s"), na, (na == 1 ? "" : "s")); printf(" TID ARCH SPEED HOSTNAME\n"); for (hp = 0; hp = host_next(hp); ) { printf("%8x %10s %7d %-24s\n", hp->pvmd_tid, hp->arch, hp->speed, hp->name); } return 0; } ./pvm3/xep/imp.c0100644007401100000360000003602607052601544012637 0ustar kohlgopher static char rcsid[] = "$Id: imp.c,v 1.4 2000/02/16 20:07:00 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * imp.c * * X device-independent image display * * Oct 95 Manchek */ #ifdef HASSTDLIB #include #endif #include #include #include #include #include #include #include #include #include #include #include #include "../src/bfunc.h" #include "myalloc.h" #include "imp.h" #define MTALLOC(n,t,g) (t*)malloc((n)*sizeof(t)) #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif #ifndef max #define max(a,b) ((a)>(b)?(a):(b)) #endif #ifndef NCMV #define NCMV 128 #endif #define byteswide(w) (((w)+7)/8) #ifdef __ProtoGlarp__ #undef __ProtoGlarp__ #endif #if defined(__STDC__) || defined(__cplusplus) #define __ProtoGlarp__(x) x #else #define __ProtoGlarp__(x) () #endif static int mkrbow __ProtoGlarp__ (( unsigned int *, unsigned int *, unsigned int *, int, int )); /*************** ** Globals ** ** ** ***************/ extern Display *xDisp; /* from xep.c */ static Colormap myCmap = 0; static Visual *myVisual = 0; static GC myGC = 0; /* canvas painting gc */ static unsigned long *cmapColors = 0; static unsigned int *lutr = 0; /* lut for non-colormapped displays */ static unsigned int *lutg = 0; static unsigned int *lutb = 0; static int ncmv = 0; static int isMono = 0; static int nPlanes = 0; /* display depth */ static int revByte = 0; /* X server byte order is opposite ours */ static int bimbo = 0; /* bitmap bit order */ static int xBpp = 0; /* ximage bits per pixel */ static int xBypp = 0; /* ximage bytes per pixel */ static int redMask = 0; static int redShift = 0; static int greenMask = 0; static int greenShift = 0; static int blueMask = 0; static int blueShift = 0; /*************** ** Xt Gorp ** ** ** ***************/ /* * Ordered dither for worst case / binary displays */ u_char ditclass[8][8] = { 2, 130, 34, 162, 10, 138, 42, 170, 194, 66, 226, 98, 202, 74, 234, 106, 50, 178, 18, 146, 58, 186, 26, 154, 242, 114, 210, 82, 250, 122, 218, 90, 14, 142, 46, 174, 6, 134, 38, 166, 206, 78, 238, 110, 198, 70, 230, 102, 62, 190, 30, 158, 54, 182, 22, 150, 254, 126, 222, 94, 246, 118, 214, 86 }; setup_color(cnp, forcemono, falsecolor) struct canvas *cnp; int forcemono; int falsecolor; { int i, j; XColor colr; unsigned int rbor[NCMV], rbog[NCMV], rbob[NCMV]; unsigned int mbo = 0x04030201; /* to test machine byte order */ int xScrn = DefaultScreen(xDisp); XGCValues xgcv; XWindowAttributes wat; XGetWindowAttributes(xDisp, cnp->cn_win, &wat); nPlanes = wat.depth; myVisual = wat.visual; myCmap = wat.colormap; if (cmapColors && ncmv > 0) { XFreeColors(xDisp, myCmap, cmapColors, ncmv, (long)0); MY_FREE(cmapColors); } cmapColors = 0; ncmv = 0; if (lutr) MY_FREE(lutr); if (lutg) MY_FREE(lutg); if (lutb) MY_FREE(lutb); lutr = lutg = lutb = 0; if (myGC) XFreeGC(xDisp, myGC); xgcv.function = GXcopy; xgcv.background = BlackPixel(xDisp, xScrn); xgcv.foreground = WhitePixel(xDisp, xScrn); myGC = XCreateGC(xDisp, cnp->cn_win, GCBackground|GCForeground|GCFunction, &xgcv); revByte = (ImageByteOrder(xDisp) == MSBFirst) ? 1 : 0; if (*(char *)&mbo == 4) revByte = !revByte; bimbo = BitmapBitOrder(xDisp); if (!forcemono && nPlanes > 1) { isMono = 0; if (myVisual->class == TrueColor || myVisual->class == DirectColor) { XPixmapFormatValues *pfv; int i; if (!(pfv = XListPixmapFormats(xDisp, &i))) { fprintf(stderr, "can't get pixmap format list for screen\n"); exit(1); } while (--i >= 0) if (pfv[i].depth == nPlanes) break; if (i < 0) { fprintf(stderr, "no pixmap format matches screen depth?\n"); exit(1); } xBpp = pfv[i].bits_per_pixel; xBypp = xBpp / 8; redMask = myVisual->red_mask; redShift = ffs(redMask & ~(redMask >> 1)) - 8; greenMask = myVisual->green_mask; greenShift = ffs(greenMask & ~(greenMask >> 1)) - 8; blueMask = myVisual->blue_mask; blueShift = ffs(blueMask & ~(blueMask >> 1)) - 8; #ifdef DEBUG fprintf(stderr, "np %d r 0x%x %d g 0x%x %d b 0x%x %d bpp %d bypp %d\n", nPlanes, redMask, redShift, greenMask, greenShift, blueMask, blueShift, xBpp, xBypp); #endif lutr = TALLOC(256, unsigned int, "lut"); lutg = TALLOC(256, unsigned int, "lut"); lutb = TALLOC(256, unsigned int, "lut"); if (falsecolor) mkrbow(lutr, lutg, lutb, 256, 256); else for (i = 0; i < 256; i++) lutr[i] = lutg[i] = lutb[i] = i; return 0; } else { cmapColors = TALLOC(NCMV, unsigned long, "cmap"); ncmv = NCMV; while (ncmv > 3) { #ifdef DEBUG fprintf(stderr, "setup_color() trying %d cells\n", ncmv); #endif j = 17 - ffs(ncmv); if (falsecolor) mkrbow(rbor, rbog, rbob, 65536, ncmv); for (i = 0; i < ncmv; i++) { if (falsecolor) { colr.red = rbor[i]; colr.green = rbog[i]; colr.blue = rbob[i]; } else colr.red = colr.green = colr.blue = (i * 65536) / ncmv; if (!XAllocColor(xDisp, myCmap, &colr)) { if (i > 0) { #ifdef DEBUG fprintf(stderr, "recycling %d color cells\n", i); #endif XFreeColors(xDisp, myCmap, cmapColors, i, (long)0); } break; } cmapColors[i] = colr.pixel; } if (i == ncmv) return 0; /* ncmv = i; */ ncmv /= 2; } fputs("couldn't alloc enough color cells\n", stderr); MY_FREE(cmapColors); cmapColors = 0; } } isMono = 1; fputs("display is binary, it's not gonna look great...\n", stderr); return 0; } /* mkrbow() * * Generate a rainbow lookup table. 0 is black, len-1 is white, and entries * between those two go through the spectrum from red to violet. * Output values are from 0 to mxval-1. */ static int mkrbow(r, g, b, mxval, len) unsigned int *r, *g, *b; /* red, grn, blu lut return */ int mxval; /* max value */ int len; /* number of entries (length of r, g, b) */ { int i, j; double d, e; for (i = 1; i < len - 1; i++) { j = len - 1 - i; d = (d = cos((double)((j - len * 0.16) * (3.1415926535 / len)))) < 0.0 ? 0.0 : d; b[i] = d * mxval; d = (d = cos((double)((j - len * 0.52) * (3.1415926535 / len)))) < 0.0 ? 0.0 : d; g[i] = d * mxval; d = (d = cos((double)((j - len * .83) * (3.1415926535 / len)))) < 0.0 ? 0.0 : d; e = (e = cos((double)(j * (3.1415926535 / len)))) < 0.0 ? 0.0 : e; r[i] = d * mxval + e * (mxval / 2); } r[i] = g[i] = b[i] = mxval - 1; r[0] = g[0] = b[0] = 0; return 0; } /* bsw() * * Byteswap an integer. */ bsw(p, n) char *p; int n; { char c; char *q; switch (n) { case 4: c = p[0]; p[0] = p[3]; p[3] = c; c = p[1]; p[1] = p[2]; p[2] = c; break; case 8: c = p[0]; p[0] = p[7]; p[7] = c; c = p[1]; p[1] = p[6]; p[6] = c; c = p[2]; p[2] = p[5]; p[5] = c; c = p[3]; p[3] = p[4]; p[4] = c; break; case 2: c = p[0]; p[0] = p[1]; p[1] = c; break; default: q = p + n - 1; while (p < q) { c = *p; *p++ = *q; *q-- = c; } break; } return 0; } /* repaint_region() * * Replot XImage from its underlying image. */ repaint_region(cnp, x1, y1, x2, y2) struct canvas *cnp; int x1, y1, x2, y2; /* image coordinates */ { char *ximbuf; /* ximage data */ u_char *ribuf; /* src image data */ if (x1 < cnp->cn_ox) x1 = cnp->cn_ox; if (y1 < cnp->cn_oy) y1 = cnp->cn_oy; if (++x2 > cnp->cn_wd) x2 = cnp->cn_wd; if (++y2 > cnp->cn_ht) y2 = cnp->cn_ht; ximbuf = cnp->cn_xim->data; ribuf = cnp->cn_dat; if (isMono) { /* * binary display - XXX region not done yet */ int sx, sy; /* source x, y counter */ int dx, dy; /* dest x, y counter */ int xa, ya; unsigned char *sa; char *da; u_char pxa; u_char msks[8]; int lbs; for (lbs = 0; lbs < 8; lbs++) if (bimbo == LSBFirst) msks[lbs] = 1 << lbs; else msks[7 - lbs] = 1 << lbs; sy = cnp->cn_oy; dy = 0; ya = 0; while (sy < cnp->cn_ht && dy < cnp->cn_ht) { sx = cnp->cn_ox; dx = 0; xa = 0; sa = ribuf + sy * cnp->cn_wd + sx; da = ximbuf + dy * cnp->cn_xim->bytes_per_line; pxa = 0; while (sx < cnp->cn_wd && dx < cnp->cn_wd) { if (*sa > ditclass[dx & 7][dy & 7]) pxa |= msks[dx & 7]; if (!(++dx & 7)) { *da++ = pxa; pxa = 0; } if (++xa >= cnp->cn_zoom) { xa = 0; sx++; sa++; } } if (dx & 7) *da++ = pxa; dy++; if (++ya >= cnp->cn_zoom) { ya = 0; sy++; } } } else if (cmapColors) { /* * colormapped display */ int sx, sy; /* source x, y counter */ int dx, dy; /* dest x, y counter */ int xa, ya; unsigned char *sa; char *da; sy = y1; dy = (y1 - cnp->cn_oy) * cnp->cn_zoom; ya = 0; while (sy < y2 && dy < cnp->cn_ht) { sx = x1; dx = (x1 - cnp->cn_ox) * cnp->cn_zoom; xa = 0; sa = ribuf + sy * cnp->cn_wd + sx; da = ximbuf + dy * cnp->cn_xim->bytes_per_line + dx; while (sx < x2 && dx < cnp->cn_wd) { *da = cmapColors[(*sa * ncmv) / 256]; da++; dx++; if (++xa >= cnp->cn_zoom) { xa = 0; sx++; sa++; } } dy++; if (++ya >= cnp->cn_zoom) { ya = 0; sy++; } } } else { /* * non-colormapped display */ int sx, sy; /* source x, y counter */ int dx, dy; /* dest x, y counter */ int xa, ya; unsigned char *sa; char *da; if (xBypp == sizeof(unsigned int)) { unsigned int pixv; unsigned int ps, pixr, pixg, pixb; sy = y1; dy = (y1 - cnp->cn_oy) * cnp->cn_zoom; ya = 0; while (sy < y2 && dy < cnp->cn_ht) { sx = x1; dx = (x1 - cnp->cn_ox) * cnp->cn_zoom; xa = 0; sa = ribuf + sy * cnp->cn_wd + sx; da = ximbuf + dy * cnp->cn_xim->bytes_per_line + dx * xBypp; while (sx < x2 && dx < cnp->cn_wd) { ps = 0xff & *sa; pixr = lutr[ps]; pixg = lutg[ps]; pixb = lutb[ps]; if (redShift >= 0) pixv = redMask & (pixr << redShift); else pixv = redMask & (pixr >> -redShift); if (greenShift >= 0) pixv |= greenMask & (pixg << greenShift); else pixv |= greenMask & (pixg >> -greenShift); if (blueShift >= 0) pixv |= blueMask & (pixb << blueShift); else pixv |= blueMask & (pixb >> -blueShift); if (revByte) bsw((char *)&pixv, (int) sizeof(pixv)); *((unsigned int *)da) = pixv; da += xBypp; dx++; if (++xa >= cnp->cn_zoom) { xa = 0; sx++; sa++; } } dy++; if (++ya >= cnp->cn_zoom) { ya = 0; sy++; } } } else if (xBypp == sizeof(unsigned short)) { unsigned short pixv; unsigned int ps, pixr, pixg, pixb; sy = y1; dy = (y1 - cnp->cn_oy) * cnp->cn_zoom; ya = 0; while (sy < y2 && dy < cnp->cn_ht) { sx = x1; dx = (x1 - cnp->cn_ox) * cnp->cn_zoom; xa = 0; sa = ribuf + sy * cnp->cn_wd + sx; da = ximbuf + dy * cnp->cn_xim->bytes_per_line + dx * xBypp; while (sx < x2 && dx < cnp->cn_wd) { ps = 0xff & *sa; pixr = lutr[ps]; pixg = lutg[ps]; pixb = lutb[ps]; if (redShift >= 0) pixv = redMask & (pixr << redShift); else pixv = redMask & (pixr >> -redShift); if (greenShift >= 0) pixv |= greenMask & (pixg << greenShift); else pixv |= greenMask & (pixg >> -greenShift); if (blueShift >= 0) pixv |= blueMask & (pixb << blueShift); else pixv |= blueMask & (pixb >> -blueShift); if (revByte) bsw((char *)&pixv, (int) sizeof(pixv)); *((unsigned short *)da) = pixv; da += xBypp; dx++; if (++xa >= cnp->cn_zoom) { xa = 0; sx++; sa++; } } dy++; if (++ya >= cnp->cn_zoom) { ya = 0; sy++; } } } else if (xBypp == sizeof(unsigned char)) { unsigned char pixv; unsigned int ps, pixr, pixg, pixb; sy = y1; dy = (y1 - cnp->cn_oy) * cnp->cn_zoom; ya = 0; while (sy < y2 && dy < cnp->cn_ht) { sx = x1; dx = (x1 - cnp->cn_ox) * cnp->cn_zoom; xa = 0; sa = ribuf + sy * cnp->cn_wd + sx; da = ximbuf + dy * cnp->cn_xim->bytes_per_line + dx * xBypp; while (sx < x2 && dx < cnp->cn_wd) { ps = 0xff & *sa; pixr = lutr[ps]; pixg = lutg[ps]; pixb = lutb[ps]; if (redShift >= 0) pixv = redMask & (pixr << redShift); else pixv = redMask & (pixr >> -redShift); if (greenShift >= 0) pixv |= greenMask & (pixg << greenShift); else pixv |= greenMask & (pixg >> -greenShift); if (blueShift >= 0) pixv |= blueMask & (pixb << blueShift); else pixv |= blueMask & (pixb >> -blueShift); *((unsigned char *)da) = pixv; da += xBypp; dx++; if (++xa >= cnp->cn_zoom) { xa = 0; sx++; sa++; } } dy++; if (++ya >= cnp->cn_zoom) { ya = 0; sy++; } } } else { fprintf(stderr, "aaugh, i can't do %d byte true color pixels\n", xBypp); exit(1); } } return 0; } /* cre_xim() * * Create (or change) XImage for a canvas. */ cre_xim(cnp) struct canvas *cnp; { char *ximbuf; int wd = cnp->cn_wd; int ht = cnp->cn_ht; if (cnp->cn_xim) XDestroyImage(cnp->cn_xim); if (isMono) { ximbuf = MTALLOC(byteswide(wd) * ht, char, "imb"); cnp->cn_xim = XCreateImage(xDisp, myVisual, 1, XYBitmap, 0, ximbuf, wd, ht, 8, byteswide(wd)); } else if (cmapColors) { ximbuf = MTALLOC(wd * ht, char, "imb"); cnp->cn_xim = XCreateImage(xDisp, myVisual, nPlanes, ZPixmap, 0, ximbuf, wd, ht, 8, wd); } else { ximbuf = MTALLOC(wd * ht * xBypp, char, "imb"); cnp->cn_xim = XCreateImage(xDisp, myVisual, nPlanes, ZPixmap, 0, ximbuf, wd, ht, xBpp, wd * xBypp); } return 0; } /* refresh_region() * * Refresh a canvas window. */ refresh_region(cnp, x1, y1, x2, y2) struct canvas *cnp; int x1, y1, x2, y2; { XPutImage(xDisp, cnp->cn_win, myGC, cnp->cn_xim, x1, y1, x1, y1, x2 - x1 + 1, y2 - y1 + 1); return 0; } ./pvm3/xep/mmain.c0100644007401100000360000001347406360714247013163 0ustar kohlgopher static char rcsid[] = "$Id: mmain.c,v 1.2 1997/07/09 13:56:55 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * main.c * * Mandelbrot calculator. * Uses tile processes to calculate strips from the requested * region, cats the strips together. * * Usage: * main width height x1 y1 x2 y2 filename * ( main 256 256 -2.0 -2.0 2.0 2.0 whole_mandelbrot ) * * 3 Jun 1991 Robert Manchek manchek@CS.UTK.EDU. * 22 Sep 91 - took out ncpus command arg because we can find out from pvm * 02 Sep 92 - ported to v3 */ #ifdef HASSTDLIB #include #endif #include #include #include #include #include "pvm3.h" #include "../src/bfunc.h" char *mandelbrot(); int nprocessors = 1; /* number of processors to use */ int *prtids = 0; /* processor task ids */ main(argc, argv) int argc; char **argv; { int mytid; /* my task id */ int wd = 16, ht = 16; /* size of image to calculate */ double x1, y1, x2, y2; /* image corner coordinates */ char *pix; /* image data */ int d; /* output file */ int i; /* gp */ char *dfn; /* file to write to */ if (argc != 8) goto usage; wd = atoi(argv[1]); ht = atoi(argv[2]); x1 = atof(argv[3]); y1 = atof(argv[4]); x2 = atof(argv[5]); y2 = atof(argv[6]); dfn = argv[7]; if (wd < 1 || wd > 2048 || ht < 1 || ht > 2048) { fputs("width and heigh must be between 1 and 2048\n", stderr); goto usage; } /* enroll in pvm */ if ((mytid = pvm_mytid()) < 0) { exit(1); } /* printf("i'm t%x\n", mytid); */ pvm_config(&nprocessors, (int*)0, (struct pvmhostinfo**)0); if (nprocessors > wd) nprocessors = wd; fprintf(stderr, "using %d tile servers in calculation\n", nprocessors); /* create n instances of tile */ prtids = (int*)malloc(nprocessors * sizeof(int)); /* if (pvm_spawn("mtile", (char**)0, 0, "", nprocessors, prtids) < 0) { fputs("can't initiate calculators\n", stderr); pvm_exit(); exit(1); } */ for (i = 0; i < nprocessors; i++) { if (pvm_spawn("mtile", (char**)0, 0, "", 1, &prtids[i]) < 0) { fputs("can't initiate calculator\n", stderr); pvm_exit(); exit(1); } /* printf("task t%x\n", prtids[i]); */ } pix = mandelbrot(x1, y1, x2, y2, wd, ht); fputs("writing\n", stderr); if ((d = open(dfn, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1) { perror(dfn); } else { (void)write(d, pix, wd * ht); (void)close(d); fprintf(stderr, "%s: written\n", dfn); } /* kill processors we created */ for (i = 0; i < nprocessors; i++) pvm_kill(prtids[i]); /* un-enroll from pvm */ pvm_exit(); exit(0); usage: fputs("usage: mmain width height x1 y1 x2 y2 filename\n", stderr); exit(1); } char* mandelbrot(x1, y1, x2, y2, wd, ht) double x1, y1, x2, y2; int wd, ht; { char *pix = 0; /* calculated image */ char *tile = 0; /* data from a single strip */ int *tpos; /* tile positions */ int maxwd = 0; /* maximum width of strip */ int slavetid; /* processor id responding */ int twd; /* width of a tile */ double xyxy[4]; /* gp */ int wdht[2]; /* gp */ int i, j; /* gp */ int y; /* gp */ char *ba1, *ba2; /* gp */ pix = (char*)malloc(wd * ht); /* divide up area into strips and assign them to processors */ tpos = (int*)malloc((nprocessors + 1) * sizeof(int)); x2 -= x1; xyxy[0] = x1; xyxy[1] = y1; xyxy[3] = y2; wdht[1] = ht; tpos[0] = 0; fputs("sending work to processors\n", stderr); for (i = 0; i < nprocessors; i++) { pvm_initsend(PvmDataDefault); tpos[i + 1] = ((i + 1) * wd) / nprocessors; wdht[0] = tpos[i + 1] - tpos[i]; if (wdht[0] > maxwd) maxwd = wdht[0]; xyxy[2] = (tpos[i + 1] * x2) / wd + x1; pvm_pkdouble(xyxy, 4, 1); pvm_pkint(wdht, 2, 1); if (pvm_send(prtids[i], 1)) { fprintf(stderr, "error sending to <%x>\n", prtids[i]); pvm_exit(); exit(1); } xyxy[0] = xyxy[2]; } /* collect results and patch together */ tile = (char*)malloc(maxwd * ht); fputs("processors responding:", stderr); fflush(stderr); for (i = 0; i < nprocessors; i++) { if (pvm_recv(-1, 2) < 1) { fprintf(stderr, "error receiving message type 2\n"); pvm_exit(); exit(1); } pvm_bufinfo(pvm_getrbuf(), &j, (int*)0, &slavetid); /* fprintf(stderr, "len %d\n", j); */ for (j = 0; j < nprocessors; j++) if (prtids[j] == slavetid) break; if (j < nprocessors) { fprintf(stderr, " %d", j); fflush(stderr); twd = tpos[j + 1] - tpos[j]; pvm_upkbyte(tile, twd * ht, 1); ba1 = tile; ba2 = pix + tpos[j]; for (y = ht; y-- > 0; ) { BCOPY(ba1, ba2, twd); ba1 += twd; ba2 += wd; } } else { fprintf(stderr, "got response from unknown processor %x?\n", slavetid); } } fputs("\n", stderr); free(tpos); free(tile); return pix; } ./pvm3/xep/mtile.c0100644007401100000360000000704106360714250013157 0ustar kohlgopher static char rcsid[] = "$Id: mtile.c,v 1.2 1997/07/09 13:56:56 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * mtile.c * * Mandelbrot tile calculation server. * Receives a request to calculate a tile, generates the tile, and * sends it back. * * 3 Jun 1991 Robert Manchek manchek@CS.UTK.EDU. * 2 Dec 91 check for null argv[0] * 02 Sep 92 - ported to v3 */ #ifdef HASSTDLIB #include #endif #include #include #include #include "pvm3.h" char* calc_tile(); main(argc, argv) int argc; char **argv; { int mytid; /* my task id */ int mastertid; /* who sent us this tile */ double x1, y1, x2, y2; /* tile corner coordinates */ int wd, ht; /* size of tile */ char *pix; /* calculated image */ int mid; mytid = pvm_mytid(); /* loop forever reading sizes and coords of tiles we should calculate */ while ((mid = pvm_recv(-1, 1)) > 0) { pvm_bufinfo(mid, (int*)0, (int*)0, &mastertid); pvm_unpackf("%lf %lf %lf %lf %d %d", &x1, &y1, &x2, &y2, &wd, &ht); /* fprintf(stderr, "%dx%d tile between %f,%f and %f,%f\n", wd, ht, x1, y1, x2, y2); */ pix = calc_tile(x1, y1, x2, y2, wd, ht); pvm_packf("%+ %*c", PvmDataDefault, wd * ht, pix); /* umbuf_dump(pvm_getsbuf(), 1); */ /* pvm_packf("%+ %*c", PvmDataInPlace, wd * ht, pix); */ if (pvm_send(mastertid, 2)) { fprintf(stderr, "error sending image back\n"); } free(pix); } fprintf(stderr, "error receiving work to do\n"); pvm_exit(); exit(1); } char* calc_tile(x1, y1, x2, y2, wd, ht) double x1, y1, x2, y2; /* tile corner coords */ int wd, ht; /* size of tile */ { char *pix; /* calculated image */ int ix, iy; /* pixel coords */ double x, y; /* re, im coords */ register double ar, ai; /* accumulator */ register double a1, a2; register int ite; /* number of iter until divergence */ if (wd < 1 || wd > 2048 || ht < 1 || ht > 2048) { fputs("insane wd/ht\n", stderr); pvm_exit(); exit(1); } pix = (char*)malloc(wd * ht); x2 -= x1; y2 -= y1; for (iy = ht; iy-- > 0; ) { y = (iy * y2) / ht + y1; for (ix = wd; ix-- > 0; ) { x = (ix * x2) / wd + x1; ar = x; ai = y; for (ite = 0; ite < 255; ite++) { a1 = (ar * ar); a2 = (ai * ai); if (a1 + a2 > 4.0) break; ai = 2 * ai * ar + y; ar = a1 - a2 + x; } pix[iy * wd + ix] = ~ite; } } return pix; } ./pvm3/xep/xep.c0100644007401100000360000005333306673500152012647 0ustar kohlgopher static char rcsid[] = "$Id: xep.c,v 1.5 1999/03/16 16:01:46 pvmsrc Exp $"; /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * xep.c * * Display pixmap calculated by tiled workers in an X window. * * Nov 92 Manchek * Oct 95 Manchek */ #ifdef HASSTDLIB #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "../src/bfunc.h" #include "myalloc.h" #include "hostc.h" #include "imp.h" #include "bars.xbm" #include "color.xbm" #include "reset.xbm" #include "quit.xbm" #include "into.xbm" #include "outof.xbm" #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif #ifndef max #define max(a,b) ((a)>(b)?(a):(b)) #endif static void pick(); static void zoom(); static void redraw(); static void configure(); static void pvm_cb(); static void zin_cb(); static void zout_cb(); static void reset_cb(); /*************** ** Globals ** ** ** ***************/ Display *xDisp; XtAppContext context; Widget topLevel = 0; /* main widget */ Widget thelabel1 = 0; Widget thelabel2 = 0; int xScrn; Window xRootW; GC rubGc; /* rubberbox gc */ Cursor crossCr; struct canvas imCan; /* just one image for now */ char *workerfile = 0; int nworkers = 0; /* number of active+idle work servers */ int dobars = 0; /* label tiles with worker number */ /*************** ** Xt Gorp ** ** ** ***************/ char canvasTl[] = "*canvas.translations:\ :pick(start)\\n\ :pick(adjust)\\n\ :pick(end)\\n\ :zoom()\\n\ :pick(modify)\\n\ :pick(adjust)\\n\ :pick(end)\\n\ :redraw()\\n\ :configure()\\n\ "; /* Widget default values */ static char *fallbacks[] = { "*allowShellResize:true", "*quitButton.label:Quit", "*recalcButton.label:Redo", "*workersButton.label:NewWorkers", canvasTl, 0 }; /* To get custom resources */ typedef struct { Bool mono; /* force monochrome display */ Bool fc; /* use false-color graymap */ String worker; /* worker a.out name */ Bool bars; /* display processor id bars */ int n; /* number of workers */ } app_res_t, *app_resp_t; static app_res_t app_res; static XtResource res_list[] = { { "worker", "Worker", XtRString, sizeof(String), XtOffset(app_resp_t, worker), XtRString, "mtile" }, { "monochrome", "Monochrome", XtRBool, sizeof(Bool), XtOffset(app_resp_t, mono), XtRString, "off" }, { "falsecolor", "Falsecolor", XtRBool, sizeof(Bool), XtOffset(app_resp_t, fc), XtRString, "on" }, { "bars", "Bars", XtRBool, sizeof(Bool), XtOffset(app_resp_t, bars), XtRString, "off" }, { "nWorkers", "NWorkers", XtRInt, sizeof(int), XtOffset(app_resp_t, n), XtRString, "-1" }, }; static XrmOptionDescRec knownargs[] = { { "-mono", ".monochrome", XrmoptionNoArg, "on" }, { "+mono", ".monochrome", XrmoptionNoArg, "off" }, { "-fc", ".falsecolor", XrmoptionNoArg, "on" }, { "+fc", ".falsecolor", XrmoptionNoArg, "off" }, { "-worker", ".worker", XrmoptionSepArg, 0 }, { "-bars", ".bars", XrmoptionNoArg, "on" }, { "+bars", ".bars", XrmoptionNoArg, "off" }, { "-n", ".nWorkers", XrmoptionSepArg, 0 }, }; static XtCallbackRec callback[2] = { { 0, 0 }, { 0, 0 } }; static Arg args[16]; static XtActionsRec actbl[] = { { "pick", pick }, { "zoom", zoom }, { "redraw", redraw }, { "configure", configure }, }; main(argc, argv) int argc; char **argv; { int n; XGCValues xgcv; int *fds; srandom(getpid()); n = 0; topLevel = XtAppInitialize(&context, "xep", knownargs, XtNumber(knownargs), &argc, argv, fallbacks, args, n); if (argc > 1) { for (n = 1; n < argc; n++) fprintf(stderr, "unknown option <%s>\n", argv[n]); fputs("options:\n", stderr); fputs(" -worker filename set calculation task name\n", stderr); fputs(" -/+mono force mono mode\n", stderr); fputs(" -/+fc use false-color graymap\n", stderr); fputs(" -/+bars display/don't display processor bars\n", stderr); /* fputs(" -n count set number of workers\n", stderr); */ exit(1); } XtGetApplicationResources(topLevel, (caddr_t)&app_res, res_list, XtNumber(res_list), 0, 0); workerfile = app_res.worker; dobars = app_res.bars; pvminit(); XtAppAddActions(context, actbl, XtNumber(actbl)); xDisp = XtDisplay(topLevel); xScrn = DefaultScreen(xDisp); xRootW = RootWindow(xDisp, xScrn); crossCr = XCreateFontCursor(xDisp, XC_tcross); xgcv.function = GXxor; xgcv.background = BlackPixel(xDisp, xScrn); /* xgcv.foreground = WhitePixel(xDisp, xScrn) ^ BlackPixel(xDisp, xScrn); */ xgcv.foreground = ~0; rubGc = XCreateGC(xDisp, xRootW, GCBackground|GCForeground|GCFunction, &xgcv); create_xep_widget(); more_workers(); do_recalc(); n = pvm_getfds(&fds); #if 0 while (n-- > 0) { #ifdef DEBUG fprintf(stderr, "adding fd %d as input\n", fds[n]); #endif XtAppAddInput(context, fds[n], (XtPointer)XtInputReadMask, pvm_cb, (XtPointer)0); } #endif addaninputfile(fds[0], (XtInputId *)0); XtAppMainLoop(context); } int addaninputfile(fd, xiip) int fd; XtInputId *xiip; { XtInputId xii; xii = XtAppAddInput(context, fd, (XtPointer)XtInputReadMask, pvm_cb, (XtPointer)0); fprintf(stderr, "addaninputfile() fd %d xii %ld\n", fd, xii); if (xiip) *xiip = xii; return 0; } int removeaninputfile(xii) XtInputId xii; { XtRemoveInput(xii); return 0; } static void pvm_cb(cli, src, id) XtPointer cli; int *src; XtInputId *id; { while (pvm_nrecv(-1, -1) > 0) claim_message(); } static void quit_cb(wgt, cli, cd) Widget wgt; caddr_t cli; caddr_t cd; { stop_workers(); pvm_exit(); exit(0); } static void reset_cb(wgt, cli, cd) Widget wgt; caddr_t cli; caddr_t cd; { if (imCan.cn_wd < imCan.cn_ht) { imCan.cn_re1 = -2.0; imCan.cn_im1 = (-2.0 * imCan.cn_ht) / imCan.cn_wd; imCan.cn_re2 = 2.0; imCan.cn_im2 = (2.0 * imCan.cn_ht) / imCan.cn_wd; } else { imCan.cn_re1 = (-2.0 * imCan.cn_wd) / imCan.cn_ht; imCan.cn_im1 = -2.0; imCan.cn_re2 = (2.0 * imCan.cn_wd) / imCan.cn_ht; imCan.cn_im2 = 2.0; } splat_out(imCan.cn_dat, imCan.cn_wd, imCan.cn_ht, 1); repaint_region(&imCan, 0, 0, imCan.cn_wd - 1, imCan.cn_ht - 1); refresh_region(&imCan, 0, 0, imCan.cn_wd - 1, imCan.cn_ht - 1); imCan.cn_x1 = 0; imCan.cn_y1 = 0; imCan.cn_x2 = 0; imCan.cn_y2 = 0; do_recalc(); } static void zout_cb(wgt, cli, cd) Widget wgt; caddr_t cli; caddr_t cd; { double d; d = (imCan.cn_re2 - imCan.cn_re1) / 2; imCan.cn_re1 -= d; imCan.cn_re2 += d; d = (imCan.cn_im2 - imCan.cn_im1) / 2; imCan.cn_im1 -= d; imCan.cn_im2 += d; splat_out(imCan.cn_dat, imCan.cn_wd, imCan.cn_ht, 1); repaint_region(&imCan, 0, 0, imCan.cn_wd - 1, imCan.cn_ht - 1); refresh_region(&imCan, 0, 0, imCan.cn_wd - 1, imCan.cn_ht - 1); imCan.cn_x1 = 0; imCan.cn_y1 = 0; imCan.cn_x2 = 0; imCan.cn_y2 = 0; do_recalc(); } static void zin_cb(wgt, cli, cd) Widget wgt; caddr_t cli; caddr_t cd; { double re1, im1, re2, im2; int wd = imCan.cn_wd; int ht = imCan.cn_ht; int x1 = imCan.cn_x1; int y1 = imCan.cn_y1; int x2 = imCan.cn_x2; int y2 = imCan.cn_y2; int t; if (x1 != x2 && y1 != y2) { if (x1 > x2) { t = x1; x1 = x2; x2 = t; } if (y1 > y2) { t = y1; y1 = y2; y2 = t; } re1 = imCan.cn_re1 + x1 * (imCan.cn_re2 - imCan.cn_re1) / wd; im1 = imCan.cn_im1 + y1 * (imCan.cn_im2 - imCan.cn_im1) / ht; re2 = re1 + (x2 - x1) * (imCan.cn_re2 - imCan.cn_re1) / wd; im2 = im1 + (x2 - x1) * (imCan.cn_im2 - imCan.cn_im1) / wd; imCan.cn_re1 = re1; imCan.cn_im1 = im1; imCan.cn_re2 = re2; imCan.cn_im2 = im2; splat_out(imCan.cn_dat, imCan.cn_wd, imCan.cn_ht, 1); repaint_region(&imCan, 0, 0, imCan.cn_wd - 1, imCan.cn_ht - 1); refresh_region(&imCan, 0, 0, imCan.cn_wd - 1, imCan.cn_ht - 1); imCan.cn_x1 = 0; imCan.cn_y1 = 0; imCan.cn_x2 = 0; imCan.cn_y2 = 0; do_recalc(); } } static void bars_cb(wgt, cli, cd) Widget wgt; caddr_t cli; caddr_t cd; { dobars = !dobars; } static void color_cb(wgt, cli, cd) Widget wgt; caddr_t cli; caddr_t cd; { app_res.fc = !app_res.fc; setup_color(&imCan, app_res.mono, app_res.fc); repaint_region(&imCan, 0, 0, imCan.cn_wd - 1, imCan.cn_ht - 1); refresh_region(&imCan, 0, 0, imCan.cn_wd - 1, imCan.cn_ht - 1); } create_xep_widget() { Widget box, box2; Widget w; int n; char buf[128]; Pixmap pm; n = 0; box = XtCreateManagedWidget("box", formWidgetClass, topLevel, args, n); imCan.cn_re1 = -2.0; imCan.cn_im1 = -2.0; imCan.cn_re2 = 2.0; imCan.cn_im2 = 2.0; n = 0; XtSetArg(args[n], XtNdefaultDistance, 2); n++; XtSetArg(args[n], XtNborderWidth, 0); n++; XtSetArg(args[n], XtNleft, XtChainLeft); n++; XtSetArg(args[n], XtNright, XtChainLeft); n++; XtSetArg(args[n], XtNtop, XtChainTop); n++; XtSetArg(args[n], XtNbottom, XtChainTop); n++; box2 = XtCreateManagedWidget("box3", formWidgetClass, box, args, n); n = 0; XtSetArg(args[n], XtNborderWidth, 0); n++; w = XtCreateManagedWidget("hosts", labelWidgetClass, box2, args, n); n = 0; XtSetArg(args[n], XtNfromHoriz, w); n++; XtSetArg(args[n], XtNborderWidth, 0); n++; XtSetArg(args[n], XtNlabel, "0"); n++; /* sprintf(buf, "(%.2e,%.2e) (%.2e,%.2e)", imCan.cn_re1, imCan.cn_im1, imCan.cn_re2, imCan.cn_im2); XtSetArg(args[n], XtNlabel, buf); n++; */ thelabel1 = w = XtCreateManagedWidget("thelabel1", labelWidgetClass, box2, args, n); n = 0; XtSetArg(args[n], XtNfromHoriz, w); n++; XtSetArg(args[n], XtNborderWidth, 0); n++; w = XtCreateManagedWidget("workers", labelWidgetClass, box2, args, n); n = 0; XtSetArg(args[n], XtNfromHoriz, w); n++; XtSetArg(args[n], XtNborderWidth, 0); n++; XtSetArg(args[n], XtNlabel, "0"); n++; thelabel2 = w = XtCreateManagedWidget("thelabel2", labelWidgetClass, box2, args, n); n = 0; XtSetArg(args[n], XtNfromVert, box2); n++; XtSetArg(args[n], XtNdefaultDistance, 2); n++; XtSetArg(args[n], XtNborderWidth, 0); n++; XtSetArg(args[n], XtNleft, XtChainLeft); n++; XtSetArg(args[n], XtNright, XtChainLeft); n++; XtSetArg(args[n], XtNtop, XtChainTop); n++; XtSetArg(args[n], XtNbottom, XtChainTop); n++; box2 = XtCreateManagedWidget("box2", formWidgetClass, box, args, n); n = 0; /* XtSetArg(args[n], XtNhorizDistance, 0); n++; XtSetArg(args[n], XtNvertDistance, 0); n++; */ callback[0].callback = (XtCallbackProc)quit_cb; callback[0].closure = (caddr_t)0; XtSetArg(args[n], XtNcallback, callback); n++; pm = XCreatePixmapFromBitmapData(xDisp, xRootW, quit_bits, quit_width, quit_height, 1, 0, 1); XtSetArg(args[n], XtNbitmap, (XtArgVal)pm); n++; w = XtCreateManagedWidget("quitButton", commandWidgetClass, box2, args, n); n = 0; /* XtSetArg(args[n], XtNhorizDistance, 0); n++; XtSetArg(args[n], XtNvertDistance, 0); n++; */ callback[0].callback = (XtCallbackProc)reset_cb; callback[0].closure = (caddr_t)0; XtSetArg(args[n], XtNcallback, callback); n++; XtSetArg(args[n], XtNfromHoriz, w); n++; pm = XCreatePixmapFromBitmapData(xDisp, xRootW, reset_bits, reset_width, reset_height, 1, 0, 1); XtSetArg(args[n], XtNbitmap, (XtArgVal)pm); n++; w = XtCreateManagedWidget("resetButton", commandWidgetClass, box2, args, n); n = 0; callback[0].callback = (XtCallbackProc)zin_cb; callback[0].closure = (caddr_t)0; XtSetArg(args[n], XtNcallback, callback); n++; XtSetArg(args[n], XtNfromHoriz, w); n++; pm = XCreatePixmapFromBitmapData(xDisp, xRootW, into_bits, into_width, into_height, 1, 0, 1); XtSetArg(args[n], XtNbitmap, (XtArgVal)pm); n++; w = XtCreateManagedWidget("recalcButton", commandWidgetClass, box2, args, n); n = 0; callback[0].callback = (XtCallbackProc)zout_cb; callback[0].closure = (caddr_t)0; XtSetArg(args[n], XtNcallback, callback); n++; XtSetArg(args[n], XtNfromHoriz, w); n++; pm = XCreatePixmapFromBitmapData(xDisp, xRootW, outof_bits, outof_width, outof_height, 1, 0, 1); XtSetArg(args[n], XtNbitmap, (XtArgVal)pm); n++; w = XtCreateManagedWidget("zoomoutButton", commandWidgetClass, box2, args, n); n = 0; callback[0].callback = (XtCallbackProc)color_cb; callback[0].closure = (caddr_t)0; XtSetArg(args[n], XtNcallback, callback); n++; XtSetArg(args[n], XtNfromHoriz, w); n++; XtSetArg(args[n], XtNstate, (app_res.fc ? 1 : 0)); n++; pm = XCreatePixmapFromBitmapData(xDisp, xRootW, color_bits, color_width, color_height, 1, 0, 1); XtSetArg(args[n], XtNbitmap, (XtArgVal)pm); n++; w = XtCreateManagedWidget("colorButton", toggleWidgetClass, box2, args, n); n = 0; callback[0].callback = (XtCallbackProc)bars_cb; callback[0].closure = (caddr_t)0; XtSetArg(args[n], XtNcallback, callback); n++; XtSetArg(args[n], XtNfromHoriz, w); n++; XtSetArg(args[n], XtNstate, dobars); n++; pm = XCreatePixmapFromBitmapData(xDisp, xRootW, bars_bits, bars_width, bars_height, 1, 0, 1); XtSetArg(args[n], XtNbitmap, (XtArgVal)pm); n++; w = XtCreateManagedWidget("barsButton", toggleWidgetClass, box2, args, n); imCan.cn_wd = 200; imCan.cn_ht = 200; n = 0; XtSetArg(args[n], XtNleft, XtChainLeft); n++; XtSetArg(args[n], XtNright, XtChainRight); n++; XtSetArg(args[n], XtNtop, XtChainTop); n++; XtSetArg(args[n], XtNbottom, XtChainBottom); n++; XtSetArg(args[n], XtNwidth, imCan.cn_wd); n++; XtSetArg(args[n], XtNheight, imCan.cn_ht); n++; XtSetArg(args[n], XtNfromVert, box2); n++; imCan.cn_wgt = XtCreateManagedWidget("canvas", widgetClass, box, args, n); XtRealizeWidget(topLevel); imCan.cn_win = XtWindow(imCan.cn_wgt); /* testothervisual(TrueColor); */ setup_color(&imCan, app_res.mono, app_res.fc); imCan.cn_x1 = 0; imCan.cn_y1 = 0; imCan.cn_x2 = 0; imCan.cn_y2 = 0; imCan.cn_zoom = 1; imCan.cn_ox = 0; imCan.cn_oy = 0; imCan.cn_dat = TALLOC(imCan.cn_wd * imCan.cn_ht, u_char, "data"); splat_out(imCan.cn_dat, imCan.cn_wd, imCan.cn_ht, 1); cre_xim(&imCan); repaint_region(&imCan, 0, 0, imCan.cn_wd - 1, imCan.cn_ht - 1); XDefineCursor(xDisp, imCan.cn_win, crossCr); return 0; } testothervisual(clas) int clas; { XVisualInfo *vinf; int nv; int i; XSetWindowAttributes xswat; vinf = XGetVisualInfo(xDisp, VisualNoMask, (XVisualInfo*)0, &nv); for (i = 0; i < nv; i++) if (vinf[i].class == clas) break; if (i == nv) { fprintf(stderr, "couldn't find the right visual\n"); exit(1); } fprintf(stderr, "found visual %d: np %d cs %d r 0x%lx g 0x%lx b 0x%lx\n", i, vinf[i].depth, vinf[i].colormap_size, (long) vinf[i].red_mask, (long) vinf[i].blue_mask, (long) vinf[i].green_mask); xswat.colormap = XCreateColormap(xDisp, xRootW, vinf[i].visual, AllocNone); xswat.border_pixmap = XCreatePixmap(xDisp, xRootW, 16, 16, 8); imCan.cn_win = XCreateWindow(xDisp, xRootW, 0, 0, 300, 300, 1, 8, InputOutput, vinf[i].visual, CWColormap|CWBorderPixmap, &xswat); XMapWindow(xDisp, imCan.cn_win); return 0; } setlabel() { int nh; struct hostc *hp; char buf[64]; hp = 0; nh = 0; while (hp = host_next(hp)) nh++; sprintf(buf, "%d", nh); XtSetArg(args[0], XtNlabel, buf); XtSetValues(thelabel1, args, 1); sprintf(buf, "%d", nworkers); XtSetArg(args[0], XtNlabel, buf); XtSetValues(thelabel2, args, 1); return 0; } static void configure(wgt, xev, par, nump) Widget wgt; XEvent *xev; String *par; int *nump; { int wd, ht; /* size of new canvas */ double re1, im1, re2, im2; int ox, oy; /* offset of new image in old */ u_char *dat; /* new canvas image */ u_char *b1, *b2; /* for copying image data */ int w, h; if (xev->type == ConfigureNotify) { wd = xev->xconfigure.width; ht = xev->xconfigure.height; ox = (imCan.cn_wd - wd) / 2; re1 = imCan.cn_re1 + ((imCan.cn_re2 - imCan.cn_re1) * ox) / imCan.cn_wd; re2 = imCan.cn_re1 + ((imCan.cn_re2 - imCan.cn_re1) * (ox + wd)) / imCan.cn_wd; oy = (imCan.cn_ht - ht) / 2; im1 = imCan.cn_im1 + ((imCan.cn_re2 - imCan.cn_re1) * oy) / imCan.cn_wd; im2 = imCan.cn_im1 + ((imCan.cn_re2 - imCan.cn_re1) * (oy + ht)) / imCan.cn_wd; imCan.cn_re1 = re1; imCan.cn_re2 = re2; imCan.cn_im1 = im1; imCan.cn_im2 = im2; /* fprintf(stderr, "%dx%d %e,%e %e,%e\n", wd, ht, re1, im1, re2, im2); fprintf(stderr, "%e : %e\n", (re2 - re1) / wd, (im2 - im1) / ht); */ dat = TALLOC(wd * ht, u_char, "data"); splat_out(dat, wd, ht, 1); w = min(imCan.cn_wd, wd); h = min(imCan.cn_ht, ht); b1 = imCan.cn_dat + max(0, ox) + max(0, oy) * imCan.cn_wd; b2 = dat + max(0, -ox) + max(0, -oy) * wd; while (h-- > 0) { BCOPY(b1, b2, w); b1 += imCan.cn_wd; b2 += wd; } MY_FREE(imCan.cn_dat); imCan.cn_dat = dat; imCan.cn_wd = wd; imCan.cn_ht = ht; imCan.cn_x1 = 0; imCan.cn_y1 = 0; imCan.cn_x2 = 0; imCan.cn_y2 = 0; cre_xim(&imCan); repaint_region(&imCan, 0, 0, imCan.cn_wd - 1, imCan.cn_ht - 1); refresh_region(&imCan, 0, 0, imCan.cn_wd - 1, imCan.cn_ht - 1); do_recalc(); } } static void redraw(wgt, xev, par, nump) Widget wgt; XEvent *xev; String *par; int *nump; { if (xev->type == Expose) { rubbox(imCan.cn_win, imCan.cn_x1, imCan.cn_y1, imCan.cn_x2, imCan.cn_y2); refresh_region(&imCan, xev->xexpose.x, xev->xexpose.y, xev->xexpose.x + xev->xexpose.width - 1, xev->xexpose.y + xev->xexpose.height - 1); rubbox(imCan.cn_win, imCan.cn_x1, imCan.cn_y1, imCan.cn_x2, imCan.cn_y2); } } static void zoom(wgt, xev, par, nump) Widget wgt; XEvent *xev; String *par; int *nump; { zin_cb(wgt, (char *)0, (char *)0); } /* pick() * * s - start * a - adjust * e - end * m - modify */ static void pick(wgt, xev, par, nump) Widget wgt; XEvent *xev; String *par; int *nump; { Window w = XtWindow(wgt); int wd = imCan.cn_wd; int ht = imCan.cn_ht; int x1 = imCan.cn_x1; int y1 = imCan.cn_y1; int x2 = imCan.cn_x2; int y2 = imCan.cn_y2; int x, y; if (*nump == 1 && get_event_xy(xev, &x, &y)) { switch (par[0][0]) { case 's': if (x1 != -1) rubbox(w, x1, y1, x2, y2); x2 = x1 = x; y2 = y1 = y; rubbox(w, x1, y1, x2, y2); break; case 'a': if (x1 != -1) { rubbox(w, x1, y1, x2, y2); x2 = (abs(y - y1) * wd) / ht; x2 = x - x1 > 0 ? x1 + x2 : x1 - x2; y2 = (abs(x - x1) * ht) / wd; y2 = y - y1 > 0 ? y1 + y2 : y1 - y2; if (abs(x2 - x1) > abs(x - x1)) y2 = y; else x2 = x; rubbox(w, x1, y1, x2, y2); } break; case 'e': if (x1 != -1) { x2 = (abs(y - y1) * wd) / ht; x2 = x - x1 > 0 ? x1 + x2 : x1 - x2; y2 = (abs(x - x1) * ht) / wd; y2 = y - y1 > 0 ? y1 + y2 : y1 - y2; if (abs(x2 - x1) > abs(x - x1)) y2 = y; else x2 = x; /* fprintf(stderr, "%d, %d -> %d, %d\n", x1, y1, x2, y2); */ } break; case 'm': if (x1 != -1) { rubbox(w, x1, y1, x2, y2); if (abs(x - x1) < abs(x - x2)) x1 = x2; if (abs(y - y1) < abs(y - y2)) y1 = y2; x2 = (abs(y - y1) * wd) / ht; x2 = x - x1 > 0 ? x1 + x2 : x1 - x2; y2 = (abs(x - x1) * ht) / wd; y2 = y - y1 > 0 ? y1 + y2 : y1 - y2; if (abs(x2 - x1) > abs(x - x1)) y2 = y; else x2 = x; rubbox(w, x1, y1, x2, y2); } break; default: break; } imCan.cn_x1 = x1; imCan.cn_y1 = y1; imCan.cn_x2 = x2; imCan.cn_y2 = y2; } } int get_event_xy(xev, xp, yp) XEvent *xev; int *xp, *yp; { switch (xev->type) { case KeyPress: case KeyRelease: *xp = xev->xkey.x; *yp = xev->xkey.y; return 1; /* break; */ case ButtonPress: case ButtonRelease: *xp = xev->xbutton.x; *yp = xev->xbutton.y; return 1; /* break; */ case MotionNotify: *xp = xev->xmotion.x; *yp = xev->xmotion.y; return 1; /* break; */ case EnterNotify: case LeaveNotify: *xp = xev->xcrossing.x; *yp = xev->xcrossing.y; return 1; /* break; */ default: return 0; } } /* rubbox() * * Draw a rubberband box XOR in a window. Call again to undraw. */ rubbox(w, x1, y1, x2, y2) Window w; int x1, x2, y1, y2; { register int x, y, h, v; if (x1 < x2) { x = x1; h = x2 - x1; } else { x = x2; h = x1 - x2; } if (y1 < y2) { y = y1; v = y2 - y1; } else { y = y2; v = y1 - y2; } XDrawRectangle(xDisp, w, rubGc, x, y, h, v); return 0; } splat_out(ba, wd, ht, dir) u_char *ba; int wd, ht; int dir; { int x = wd; int o = 0; int n = wd * ht; dir = dir ? 7 : 1; while (--n >= 0) { *ba++ = x & 7 ? 0 : 255; if (--x <= o) { o = (o + dir) & 7; x = wd + o; } } return 0; } label_row(y1, y2, n) int y1, y2; int n; { int wd = imCan.cn_wd; int h = y2 - y1; int y, x; u_char *ba; int c = 240; ba = imCan.cn_dat + y1 * wd; for (y = h; y-- > 0; ) { BZERO(ba, 21); ba += wd; } ba = imCan.cn_dat + y1 * wd; for (y = h - 2; y-- > 0; ) { ba += wd; for (x = 0; x < 20; x++) if (x & 3) ba[x] = (n & (1 << x / 4)) ? 255 : c; } repaint_region(&imCan, 0, y1, 20, y2 - 1); refresh_region(&imCan, 0, y1, 20, y2 - 1); return 0; } ./pvm3/xep/hostc.h0100644007401100000360000000416706741172516013206 0ustar kohlgopher /* $Id: hostc.h,v 1.3 1999/07/08 19:00:30 kohl Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * hostc.h * * Host cache definitions. * * $Log: hostc.h,v $ * Revision 1.3 1999/07/08 19:00:30 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.2 1997/07/09 13:56:51 pvmsrc * Fixed Author Header. * * Revision 1.1 1996/09/23 22:52:54 pvmsrc * Initial revision * */ struct hostc { struct hostc *link, *rlink; int pvmd_tid; char *name; char *alias; char *arch; int speed; struct timeval delta; }; int host_init __ProtoGlarp__(( int atag, int dtag, int (*acb)(), int (*dcb)() )); int host_add __ProtoGlarp__(( void )); int host_delete __ProtoGlarp__(( void )); struct hostc *host_findtid __ProtoGlarp__(( int tid )); struct hostc *host_findname __ProtoGlarp__(( char *name )); struct hostc *host_next __ProtoGlarp__(( struct hostc *hp )); int host_show __ProtoGlarp__(( void )); ./pvm3/xep/imp.h0100644007401100000360000000336306360714246012647 0ustar kohlgopher /* $Id: imp.h,v 1.2 1997/07/09 13:56:54 pvmsrc Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* describes an image canvas */ struct canvas { Widget cn_wgt; /* widget */ Window cn_win; /* window */ int cn_wd; /* image size */ int cn_ht; u_char *cn_dat; /* image data */ XImage *cn_xim; /* ximage struct */ int cn_zoom; /* display mag */ int cn_ox; /* offset for zoom */ int cn_oy; double cn_re1; /* corner coords */ double cn_im1; double cn_re2; double cn_im2; int cn_x1; /* pick coords */ int cn_y1; int cn_x2; int cn_y2; }; ./pvm3/xep/myalloc.h0100644007401100000360000000422106741172516013515 0ustar kohlgopher /* $Id: myalloc.h,v 1.3 1999/07/08 19:00:30 kohl Exp $ */ /* * PVM version 3.4: Parallel Virtual Machine System * University of Tennessee, Knoxville TN. * Oak Ridge National Laboratory, Oak Ridge TN. * Emory University, Atlanta GA. * Authors: J. J. Dongarra, G. E. Fagg, M. Fischer * G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci, * P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam * (C) 1997 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * Neither the Institutions (Emory University, Oak Ridge National * Laboratory, and University of Tennessee) nor the Authors make any * representations about the suitability of this software for any * purpose. This software is provided ``as is'' without express or * implied warranty. * * PVM version 3 was funded in part by the U.S. Department of Energy, * the National Science Foundation and the State of Tennessee. */ /* * myalloc.h * * Malloc defines. * * $Log: myalloc.h,v $ * Revision 1.3 1999/07/08 19:00:30 kohl * Fixed "Log" keyword placement. * - indent with " * " for new CVS. * * Revision 1.2 1997/07/09 13:56:57 pvmsrc * Fixed Author Header. * * Revision 1.1 1996/09/23 22:52:57 pvmsrc * Initial revision * */ #ifdef HASSTDLIB #include #endif #ifdef USE_PVM_ALLOC #define MY_ALLOC(n,g) pvm_alloc((unsigned)(n),(g)) #define MY_REALLOC(p,n) pvm_realloc((char*)(p),(unsigned)(n)) #define MY_FREE(p) pvm_free((char*)(p)) #else #define MY_ALLOC(n,g) malloc((unsigned)(n)) #define MY_REALLOC(p,n) realloc((char*)(p),(unsigned)(n)) #define MY_FREE(p) free((char*)(p)) #endif #define TALLOC(n,t,g) (t*)MY_ALLOC((n)*sizeof(t),(g)) #define TREALLOC(p,n,t) (t*)MY_REALLOC(p,(n)*sizeof(t)) #define STRALLOC(s) strcpy(TALLOC(strlen(s)+1,char,"str"),s) ./pvm3/xep/bars.xbm0100644007401100000360000000056606221611556013346 0ustar kohlgopher#define bars_width 16 #define bars_height 24 static char bars_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x19, 0x98, 0x19, 0x98, 0x19, 0x98, 0x19, 0x98, 0x19, 0x98, 0x19, 0x98, 0x19, 0x98, 0x19, 0x98, 0x19, 0x98, 0x19, 0x98, 0x19, 0x98, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; ./pvm3/xep/color.xbm0100644007401100000360000000101706221611557013526 0ustar kohlgopher#define color_width 24 #define color_height 24 static char color_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x41, 0x00, 0x80, 0x80, 0x00, 0x40, 0x00, 0x01, 0x40, 0x00, 0x01, 0x40, 0x00, 0x01, 0x40, 0x00, 0x01, 0x40, 0x00, 0x01, 0x80, 0x80, 0x00, 0xf0, 0xc1, 0x07, 0xf8, 0xbf, 0x0c, 0xfc, 0x57, 0x12, 0xfe, 0x2f, 0x29, 0xfe, 0x9f, 0x24, 0xfe, 0x4f, 0x32, 0xfe, 0x2f, 0x29, 0xfe, 0x9f, 0x24, 0xfc, 0x57, 0x12, 0xf8, 0x23, 0x09, 0xf0, 0xc1, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; ./pvm3/xep/into.xbm0100644007401100000360000000056606221611560013363 0ustar kohlgopher#define into_width 16 #define into_height 24 static char into_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x07, 0x00, 0x08, 0x00, 0x10, 0x20, 0x10, 0x40, 0x20, 0x80, 0x20, 0xe0, 0x21, 0x98, 0x20, 0x44, 0x20, 0x24, 0x10, 0x04, 0x10, 0x04, 0x08, 0x08, 0x04, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; ./pvm3/xep/neww.xbm0100644007401100000360000000101406221611562013361 0ustar kohlgopher#define neww_width 24 #define neww_height 24 static char neww_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x49, 0x00, 0x80, 0x88, 0x00, 0x40, 0x08, 0x01, 0xe0, 0x9c, 0x03, 0xe0, 0x9c, 0x03, 0xe0, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; ./pvm3/xep/outof.xbm0100644007401100000360000000057106221611563013545 0ustar kohlgopher#define outof_width 16 #define outof_height 24 static char outof_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x43, 0x10, 0x4c, 0x08, 0x50, 0x04, 0x60, 0x04, 0x7c, 0x02, 0x00, 0x02, 0x00, 0x82, 0x01, 0x02, 0x02, 0x04, 0x02, 0x04, 0x02, 0x18, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; ./pvm3/xep/quit.xbm0100644007401100000360000000056606221611565013401 0ustar kohlgopher#define quit_width 16 #define quit_height 24 static char quit_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07, 0xf8, 0x0f, 0xfc, 0x1f, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x1f, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; ./pvm3/xep/redo.xbm0100644007401100000360000000101406221611566013336 0ustar kohlgopher#define redo_width 24 #define redo_height 24 static char redo_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x07, 0x20, 0x00, 0x04, 0x20, 0xf8, 0x05, 0x20, 0x08, 0x05, 0x20, 0x08, 0x05, 0x20, 0x08, 0x05, 0x20, 0xf8, 0x05, 0x20, 0x00, 0x04, 0x20, 0x00, 0x04, 0x20, 0x00, 0x04, 0xe0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; ./pvm3/xep/reset.xbm0100644007401100000360000000057106221611567013537 0ustar kohlgopher#define reset_width 16 #define reset_height 24 static char reset_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x70, 0x38, 0x78, 0x3c, 0x7c, 0x3e, 0x7e, 0x3f, 0x7c, 0x3e, 0x78, 0x3c, 0x70, 0x38, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; ./pvm3/xep/TrueColorFix0100644007401100000360000002457706221612357014227 0ustar kohlgopherReceived: from msr.epm.ornl.gov by CS.UTK.EDU with SMTP (cf v2.9s-UTK) id EAA23496; Mon, 11 Jul 1994 04:48:33 -0400 Received: from appana.ap.titech.ac.jp by msr.epm.ornl.gov (4.1/1.34) id AA28611; Mon, 11 Jul 94 04:46:41 EDT Received: by appana.ap.titech.ac.jp (5.65+1.6W/tit-mx1.1); Mon, 11 Jul 94 17:45:55 +0900 Received: by wisdom.ap.titech.ac.jp (NX5.67c/NX3.0S) id AA12748; Mon, 11 Jul 94 17:46:04 +0900 Date: Mon, 11 Jul 94 17:46:04 +0900 From: Satoshi Adachi Message-Id: <9407110846.AA12748@wisdom.ap.titech.ac.jp> To: pvm@msr.epm.ornl.gov Subject: Modifications of xep necessary for NeXTstation Color. Cc: adachi@wisdom.ap.titech.ac.jp Dear Scientists and Engineers who have been developing PVM: (1) Recently, I was informed by my friend that there is a very nice software system, called PVM, that enable us to look a cluster of many workstations as a single virtual machine and to write parallel programs for the virtual machine. So, I installed PVM3.2.4 for our workstation cluster of NeXTstation's and IBM RS6000's. Now, PVM works very well on our workstation cluster. I have just begun writing several programs for physics by using PVM. Thank you very much for developing such a nice software system and for making it a free software. In the installation of PVM3.2.4, the body part of PVM did not need any change of source code and the installcation was completely automatic. However, the installtion of the demo program "xep" for NeXTstation color needed some change of source code. In this email, I will explain the modification of the source code of "xep" which is necessary to run "xep" on NeXTstation Color and NeXTstation Color Turbo. I hope that the modification or its equivalent will be incorpolated in the future releases of "xep". (2) Our NeXTstaion Color's and NeXTstation Color Turbo's are running under NeXTSTEP 3.0J and the commercial X Window software "Co-Xist" is installed on these machines. For NeXTstaion Color and NeXTstation Color Turbo, the true color model is used rather than the pseudo color model. On the screen, each pixel directly corresponds to a binary number of 12 bit length. Namely, Red, Green and Blue intensities are expressed by 4 bit integers. In C programs, a pixel is prepresented by a short integer with 16 bit which consists of 12 bit RGB fields and 4 bit pad. The source code of "xep" supports the not only the pseudo colode model but also the true color model. However, when the true color model is used, it is assumed that each pixel is expressed by the RGB value of 24 bit length (8 bit each) and is represented by 32 bit integer in C programs (including 8 bit pad). This assumption supposed by "xep" does not hold for NeXTstation Color and NeXTstation Color Turbo. Consequently, "xep" abends on these machines with Co-Xist. In order to support the true color model with RGB value represented by not only 3*8 bit but also 3*4 bit, I changed the source code of "xep" in the file "xep/xep.c" in the following way: ------------------------------------------------------------------------------- *** xep.c Mon Jul 11 17:19:01 1994 --- xep.c.org Sat Jul 9 20:16:37 1994 *************** *** 70,78 **** typedef unsigned int IBIT32; - /* ***** Added by S.Adachi (94/07/09) ***** */ - typedef unsigned short int IBIT16; - /* describes an image canvas (currently only one) */ struct canvas { --- 70,75 ---- *************** *** 410,437 **** } xBpp = pfv[i].bits_per_pixel; xBypp = xBpp / 8; - /* ***** Modified by S.Adachi (94/07/10) ***** */ - #if 0 redMask = defVis->red_mask; redShift = ffs(redMask & ~(redMask >> 1)) - 8; greenMask = defVis->green_mask; greenShift = ffs(greenMask & ~(greenMask >> 1)) - 8; blueMask = defVis->blue_mask; blueShift = ffs(blueMask & ~(blueMask >> 1)) - 8; - #else - if ((xBypp != 2) && (xBypp != 4)) { - fprintf(stderr, "unsupported bytes per pixel: %d\n", - xBypp); - exit(1); - } - redMask = defVis->red_mask; - redShift = ffs(redMask) - 1; - greenMask = defVis->green_mask; - greenShift = ffs(greenMask) - 1; - blueMask = defVis->blue_mask; - blueShift = ffs(blueMask) - 1; - #endif /* Modification by S.Adachi (94/07/10) */ mkrbow(fclutr, fclutg, fclutb, 256); } else { isCmap = 1; xCmap = DefaultColormap(xDisp, xScrn); --- 407,420 ---- } xBpp = pfv[i].bits_per_pixel; xBypp = xBpp / 8; redMask = defVis->red_mask; redShift = ffs(redMask & ~(redMask >> 1)) - 8; greenMask = defVis->green_mask; greenShift = ffs(greenMask & ~(greenMask >> 1)) - 8; blueMask = defVis->blue_mask; blueShift = ffs(blueMask & ~(blueMask >> 1)) - 8; mkrbow(fclutr, fclutg, fclutb, 256); + } else { isCmap = 1; xCmap = DefaultColormap(xDisp, xScrn); *************** *** 1044,1068 **** return x; } - /* ***** Added by S.Adachi (94/07/09) ***** */ - /* sw2() - * - * Byteswap a 16-bit integer. - */ - - IBIT16 - sw2(x) - IBIT16 x; - { - u_char *cp = (u_char*)&x; - u_char c; - - c = cp[0]; - cp[0] = cp[1]; - cp[1] = c; - return x; - } - /* repaint_region() * --- 1027,1032 ---- *************** *** 1133,1212 **** dy = (y1 - cnp->cn_oy) * cnp->cn_zoom; ya = 0; while (sy < y2 && dy < cnp->cn_ht) { ! sx = x1; ! dx = (x1 - cnp->cn_ox) * cnp->cn_zoom; ! xa = 0; ! sa = ribuf + sy * cnp->cn_wd + sx; ! /* ***** Modified by S.Adachi (94/07/09) ***** */ ! #if 0 ! da = (ximbuf + dy * cnp->cn_xim->bytes_per_line ! + dx * sizeof(IBIT32)); ! while (sx < x2 && dx < cnp->cn_wd) { ! pixv = lbm & *sa; ! pixr = fclutr[pixv]; ! pixg = fclutg[pixv]; ! pixb = fclutb[pixv]; ! pixv = (redMask & (pixr << redShift)) ! | (greenMask & (pixg << greenShift)) ! | (blueMask & (pixb << blueShift)); ! if (revByte) ! *((IBIT32*)da) = sw4(pixv); ! else ! *((IBIT32*)da) = pixv; ! da += sizeof(IBIT32); ! dx++; ! if (++xa >= cnp->cn_zoom) { ! xa = 0; ! sx++; ! sa++; ! } ! } ! #else ! da = (ximbuf + dy * cnp->cn_xim->bytes_per_line ! + dx * xBypp); ! while (sx < x2 && dx < cnp->cn_wd) { ! pixv = lbm & *sa; ! pixr = fclutr[pixv]; ! pixg = fclutg[pixv]; ! pixb = fclutb[pixv]; ! if (xBypp == 4) { ! pixv = ((redMask & (pixr << redShift)) ! |(greenMask & (pixg << greenShift)) ! |(blueMask & (pixb << blueShift))); ! if (revByte) ! *((IBIT32*)da) = sw4(pixv); ! else ! *((IBIT32*)da) = pixv; ! da += sizeof(IBIT32); ! } ! else { ! /* xBypp == 2 */ ! IBIT16 pixvs; ! pixr = pixr >> 4; ! pixg = pixg >> 4; ! pixb = pixb >> 4; ! pixvs = ((redMask & (pixr << redShift)) ! |(greenMask & (pixg << greenShift)) ! |(blueMask & (pixb << blueShift))); ! if (revByte) ! *((IBIT16*)da) = sw2(pixvs); ! else ! *((IBIT16*)da) = pixvs; ! da += sizeof(IBIT16); ! } ! dx++; ! if (++xa >= cnp->cn_zoom) { ! xa = 0; ! sx++; ! sa++; ! } ! } ! #endif /* ***** End of Modification by S.Adachi (94/07/10) ***** */ ! dy++; ! if (++ya >= cnp->cn_zoom) { ! ya = 0; ! sy++; ! } } } --- 1097,1133 ---- dy = (y1 - cnp->cn_oy) * cnp->cn_zoom; ya = 0; while (sy < y2 && dy < cnp->cn_ht) { ! sx = x1; ! dx = (x1 - cnp->cn_ox) * cnp->cn_zoom; ! xa = 0; ! sa = ribuf + sy * cnp->cn_wd + sx; ! da = ximbuf + dy * cnp->cn_xim->bytes_per_line + dx * sizeof(IBIT32); ! while (sx < x2 && dx < cnp->cn_wd) { ! pixv = lbm & *sa; ! pixr = fclutr[pixv]; ! pixg = fclutg[pixv]; ! pixb = fclutb[pixv]; ! pixv = (redMask & (pixr << redShift)) ! | (greenMask & (pixg << greenShift)) ! | (blueMask & (pixb << blueShift)); ! if (revByte) ! *((IBIT32*)da) = sw4(pixv); ! else ! *((IBIT32*)da) = pixv; ! ! da += sizeof(IBIT32); ! dx++; ! if (++xa >= cnp->cn_zoom) { ! xa = 0; ! sx++; ! sa++; ! } ! } ! dy++; ! if (++ya >= cnp->cn_zoom) { ! ya = 0; ! sy++; ! } } } ------------------------------------------------------------------------------- I would like to make several remarks on the above modifications: (i) In contrast to IBIT32 for the RGB value represented in 32 bit, a new type IBIT 16 is introduced for the RGB value represented in 16 bit as: typedef unsigned short int IBIT16; (ii) In order to confirm that when the true color model is used, the RGB value is represented in either 16 bit or 32 bit, the following code is added: if ((xBypp != 2) && (xBypp != 4)) { fprintf(stderr, "unsupported bytes per pixel: %d\n", xBypp); exit(1); } (iii) The original code to calculate the shift for the red field in the RGB value was redShift = ffs(redMask & ~(redMask >> 1)) - 8; This assumes that the field has 8 bit length. This is changed to redShift = ffs(redMask) - 1; Same is true for the fields of Green and Blue. This new code may have some problem on the respect to byte order mismatch between X server and X client. I am not sure. I did not inspect it. (iv) A new function "sw2()" is added. This is the 16 bit version of sw4(). (v) The following code assumes that each pixel is represented by 32 bit integer: da = (ximbuf + dy * cnp->cn_xim->bytes_per_line + dx * sizeof(IBIT32)); In the new code, "sizeof(IBIT32)" is replaced by "xBypp". (vi) When a pixel value is written in memory, the following "if" statement is introduced to respect the bit length of the pixel: if (xBypp == 4) { /* Same as the original code */ } else { /* xBypp == 2 */ IBIT16 pixvs; pixr = pixr >> 4; pixg = pixg >> 4; pixb = pixb >> 4; pixvs = ((redMask & (pixr << redShift)) |(greenMask & (pixg << greenShift)) |(blueMask & (pixb << blueShift))); if (revByte) *((IBIT16*)da) = sw2(pixvs); else *((IBIT16*)da) = pixvs; da += sizeof(IBIT16); } We should be careful that the original pixr, pixg, pixb values are in the range 0-255. Thank you very much. Satoshi Adachi (adachi@wisdom.ap.titech.ac.jp) Research Associate Department of Applied Physics Tokyo Institute of Technology Meguro, Tokyo 152, JAPAN ./pvm3/xep/PGON/0042755007401100000360000000000010117676455012460 5ustar kohlgopher./pvm3/xep/PGON/Makefile0100644007401100000360000000315706406052661014112 0ustar kohlgopher# # $Id: Makefile,v 1.4 1997/09/11 20:33:53 pvmsrc Exp $ # ARCH = PGON # # Generic Makefile body. # To update, edit Makefile.body and run lib/UpdateMk. # # Imports: # ARCH = the official pvm-name of your processor # ARCHCFLAGS = special cc flags # ARCHLIB = special libs needed for daemon # PVMDIR = ../.. PVMIDIR = $(PVMDIR)/include PVMLDIR = $(PVMDIR)/lib/$(ARCH) PVMLIB = -lpvm3 ARCHLIB = -lrpc -lnx SDIR = $(PVMDIR)/xep BDIR = $(PVMDIR)/bin # on cross compiler host # XIDIR = /usr/local/paragon/include/X11 # XLDIR = /usr/local/paragon/lib-coff # on paragon set XIDIR = /usr/include/X11 XLDIR = /usr/lib XDIR = $(BDIR)/$(ARCH) CC = icc CFLOPTS = -O CFLAGS = $(CFLOPTS) -I$(PVMIDIR) -L$(PVMLDIR) $(ARCHCFLAGS) LIBS = $(PVMLIB) $(ARCHLIB) XLIBS = -lXaw -lXmu -lXt -lXext -lX11 XCFLAGS = -I$(XIDIR) -I$(XLDIR) default: mtile xep all: mmain mtile xep $(XDIR): $(BDIR) - mkdir $(XDIR) $(BDIR): - mkdir $(BDIR) mmain: $(SDIR)/mmain.c $(XDIR) $(CC) $(CFLAGS) -o mmain $(SDIR)/mmain.c $(LIBS) mv mmain $(XDIR) mtile: $(SDIR)/mtile.c $(XDIR) $(CC) $(CFLAGS) -o mtile $(SDIR)/mtile.c -lpvm3pe $(ARCHLIB) -lm mv mtile $(XDIR) xep: xep.o calc.o imp.o hostc.o $(XDIR) $(CC) $(XCFLAGS) $(CFLAGS) -o xep xep.o calc.o imp.o hostc.o \ $(XLIBS) $(LIBS) -lm mv xep $(XDIR) xep.o: $(SDIR)/xep.c $(HEADERS) $(CC) $(XCFLAGS) $(CFLAGS) -c $(SDIR)/xep.c imp.o: $(SDIR)/imp.c $(HEADERS) $(CC) $(XCFLAGS) $(CFLAGS) -c $(SDIR)/imp.c calc.o: $(SDIR)/calc.c $(HEADERS) $(CC) $(XCFLAGS) $(CFLAGS) -c $(SDIR)/calc.c hostc.o: $(SDIR)/hostc.c $(HEADERS) $(CC) $(XCFLAGS) $(CFLAGS) -c $(SDIR)/hostc.c clean: rm -f mmain mtile xep *.o ./pvm3/xep/PMAX/0042755007401100000360000000000010117676455012462 5ustar kohlgopher./pvm3/xep/PMAX/Makefile0100644007401100000360000000204706334376062014115 0ustar kohlgopher# # $Id: Makefile,v 1.3 1997/05/08 16:15:46 pvmsrc Exp $ # # # Generic Makefile body to be concatenated to config header. # # Imports: # PVM_ARCH = the official pvm-name of your processor # ARCHCFLAGS = special cc flags # ARCHLIB = special libs needed for daemon # PVMDIR = ../.. PVMIDIR = $(PVMDIR)/include PVMLDIR = $(PVMDIR)/lib/$(PVM_ARCH) PVMLIB = -lpvm3 SDIR = $(PVMDIR)/xep BDIR = $(PVMDIR)/bin XDIR = $(BDIR)/$(PVM_ARCH) CFLOPTS = -O CFLAGS = $(CFLOPTS) -I$(PVMIDIR) -L$(PVMLDIR) $(ARCHCFLAGS) LIBS = $(PVMLIB) $(ARCHLIB) XLIBS = -lXaw -lXmu-mit -lXext-mit -lXt-mit -lX11-mit XCFLAGS = -I/usr/include/mit default: mtile xep all: mmain mtile xep $(XDIR): - mkdir $(BDIR) - mkdir $(XDIR) mmain: $(SDIR)/mmain.c $(XDIR) $(CC) $(CFLAGS) -o mmain $(SDIR)/mmain.c $(LIBS) mv mmain $(XDIR) mtile: $(SDIR)/mtile.c $(XDIR) $(CC) $(CFLAGS) -o mtile $(SDIR)/mtile.c $(LIBS) -lm mv mtile $(XDIR) xep: $(SDIR)/xep.c $(XDIR) $(CC) $(XCFLAGS) $(CFLAGS) -o xep $(SDIR)/xep.c $(XLIBS) $(LIBS) -lm mv xep $(XDIR) clean: rm -f mmain mtile xep *.o