Newsgroups: comp.parallel.pvm
From: Richard Kilgore <rkilgore@lore.ece.utexas.edu>
Subject: Re: Get a new tid for fork()'ed process?
Organization: The University of Texas at Austin
Date: Fri, 08 Mar 1996 15:44:35 -0600
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Message-ID: <3140AA43.5F6002DB@lore.ece.utexas.edu>

There were several responses indicating people were interested in how
to do this, so I decided to post results.  Basically, a few of the
answers to my original post were exactly correct.  You can use the
(undocumented) pvmendtask() function followed by a call to pvm_mytid()
to separate a newly forked task from the original.  pvmendtask() does
not appear in the header file, so you have to declare it yourself:

int pvmendtask();              /*  or  */
extern "C" int pvmendtask();   //for C++


Two caveats:
  (1) you can pretty much accomplish the same thing using pvm_exit()
      in place of pvmendtask(), but from a simple experiment I ran
      on a pentium 90, pvmendtask() appears to impose a LOT less
      overhead.  In my experiment, pvmendtask() required an average
      of about 0.65 ms to complete, and pvm_exit() usually required
      21 or 22 ms!

  (2) Expect problems doing this at all if you use pvm_catchout():
      another useful routine that is not in the header file.  This
      one used to be in the header file but is currently commented
      out, and possibly because of side effects like the one I
      experience when I do this fork(); pvmendtask(); pvm_mytid();
      trick.  The problem is that when the child task (from the
      fork()) calls pvm_exit(), it thinks that it was responsible
      for calling pvm_spawn() (because the original task WAS), and
      pvm_exit() never returns successfully: it waits forever to
      receive output messages from its non-existent children.  A
      kludge fix is to never call pvm_exit() in the child task, but
      this is definitely dangerous.  I think it can cause some of
      the messages this process sends to never be received under
      certain circumstances.  Also, if you use pvm_exit() instead
      of pvmendtask(), it's even worse.  In this case, neither the
      original Pvm task nor the child of the fork() will return
      from a pvm_exit() call!

And finally, Jon King sent me the source to a function that he claims
to have gotten from Bob Manchek with all this stuff built in.  I
figured that some of you might find useful.  I've included it below.
I'm not crazy about the use of goto, but you can be the judge. :@)

   Keep on,

   - rick


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

#include <pvm3.h>


int
pvm_fork(cpid)
   int *cpid;     /* returns child pid if nonnull */
{
   int ptid;         /* tid of parent */
   int tid;       /* tid to return */
   int pid;       /* pid of child */
   int sbf, rbf;

   sbf = pvm_setsbuf(0);
   rbf = pvm_setrbuf(0);

   if ((ptid = pvm_mytid()) < 0) {
      tid = ptid;
      goto done;
   }

   if (pid = fork()) {     /* parent */
      if (pid == -1) {
/*
         perror("fork");
*/
         tid = PvmOutOfRes;
         goto done;
      }

      tid = pvm_recv(-1, 1);
      if (tid < 0)
         goto done;
      tid = -1;
      pvm_upkint(&tid, 1, 1);

      if (cpid)
         *cpid = pid;

   } else {          /* child */
      pvmendtask();
      tid = pvm_mytid();
      pvm_initsend(PvmDataRaw);
      pvm_pkint(&tid, 1, 1);
      pvm_send(ptid, 1);
      tid = 0;
   }

done:
   if (sbf = pvm_setsbuf(sbf))
      pvm_freebuf(sbf);
   if (rbf = pvm_setrbuf(rbf))
      pvm_freebuf(rbf);
   return tid;
}


-- 
Richard B. Kilgore
Grad Student, University of Texas at Austin
WWW URL: http://lore.ece.utexas.edu/~rkilgore/
E-mail rkilgore@lore.ece.utexas.edu

