/* 
    PVM greetings based on forkjoin.c in the PVM book.
    Most error checking omitted for clarity.
*/

#include <stdio.h>
#include <pvm3.h>

#define MAXNCHILD   20
#define JOINTAG     11

int main(int argc, char* argv[])
{
    
    int ntask = 3;        /* number of tasks to spawn default = 3 */
    int info;             /* return code from pvm calls */
    int mytid;            /* my task id */
    int myparent;         /* my parents task id */
    int child[MAXNCHILD]; /* children task id array */
    int i, mydata, buf, len, tag, tid;

    /* find out my task id number */
    mytid = pvm_mytid();

    /* find my parent's task id number */
    myparent = pvm_parent();

    /* if i don't have a parent then i am the parent */
    if (myparent == PvmNoParent) {
        /* find out how many tasks to spawn */
        if (argc == 2) ntask = atoi(argv[1]);
        if ((ntask < 1) || (ntask > MAXNCHILD)) { pvm_exit(); return 0; }

        /* spawn the child tasks */
        info = pvm_spawn(argv[0], (char**)0, PvmTaskDefault, (char*)0,
			 ntask, child);

        /* make sure spawn succeeded */
        if (info == 0) { pvm_exit(); return -1; }

        /* only expect responses from those spawned correctly */
        ntask = info;
    
        for (i = 0; i < ntask; i++) {
            /* recv a message from any child process */
            buf = pvm_recv(-1, JOINTAG);
            pvm_bufinfo(buf, &len, &tag, &tid);
            pvm_upkint(&mydata, 1, 1);
            printf("Greetings from task %x!\n", tid);
	}
    }
    else { /* i'm a child */
	pvm_initsend(PvmDataDefault);
	pvm_pkint(&mytid, 1, 1);
	pvm_send(myparent, JOINTAG);
    }
    pvm_exit();
    return 0;
}

