static char rcsid[] = "$Id: lpvmgen.c,v 1.101 2008/12/17 20:40: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. */ /* * lpvmgen.c * * Libpvm generic functions. * * $Log: lpvmgen.c,v $ * Revision 1.101 2008/12/17 20:40:49 pvmsrc * Added some extra debugging for diagnosing any future strerror() problems... * :-b * (Spanker=kohl) * * Revision 1.100 2007/07/09 19:59:54 pvmsrc * Added missing "char *pvmnametag();" function decl. * - submitted by David Mathog . * (Spanker=kohl) * * 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 *pvmnametag(); 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*/ if ( s == NULL ) { pvmlogprintf("NULL STRING PASSED TO pvmlogperror() errno=%d\n", errno); s = "(null string passed to pvmlogperror()...)"; } if ( em == NULL ) { pvmlogprintf("STRERROR IS BROKEN - %s errno=%d\n", s, errno); return -1; } 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; }