/*
 *              	   Exemple "SPMD.c" PVM versio 3.3
 *		 Susana Maria Bajo Sanchez (ei05646@salleURL.edu)
 *		 Josep Maria Garrell i Guiu (josepmg@salleURL.edu)
 *				Software Paral.lel
 *		           Departament d'Informatica (DI)
 *	               Enginyeria i Arquitectura La Salle
 *		           Universitat Ramon Llull (URL)
 * 	 	              	Curs 1999/2000
*/

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

#define NPROC 4

//-------------------------------------------------
// Funcion que pasa un token alrededor de un anillo
dowork(int me,int *tids,int nproc)
{
	int token, dest, count=1, stride=1, msgtag=4;
	if (me == 0)
		{
		token = tids[0];
		pvm_initsend(PvmDataDefault);
		pvm_pkint(&token,count,stride);
		pvm_send(tids[me+1],msgtag);
		pvm_recv(tids[nproc-1],msgtag);
		}
		else 	{
			pvm_recv(tids[me-1],msgtag);
			pvm_upkint(&token,count,stride);
			pvm_initsend(PvmDataDefault);
			pvm_pkint(&token,count,stride);
			dest = (me == nproc-1)? tids[0]:tids[me+1];
			pvm_send(dest,msgtag);
			}
}

//-------------------------------------------------
void main()
{
	int cc;
	int mytid, tids[NPROC], me, i;
	
	// salida estardar por pantalla
	pvm_catchout(stdout);

	mytid = pvm_mytid();
	printf("SPMD: Soy la tarea #%x\n",mytid);

	// miro si soy padre o hijo
	tids[0] = pvm_parent();

	if (tids[0] < 0) 
		{
		printf("SPMD: Soy el padre\n");
		tids[0] = mytid;
		me = 0;
		
		cc = pvm_spawn("SPMD",(char**)0,0,"",NPROC-1,&tids[1]);
		if (cc == NPROC-1)
			{
			printf("SPMD: He podido crear la tareas 'SPMD'\n");
			
			pvm_initsend(PvmDataDefault);
			printf("SPMD: Inicializo el SEND\n");
			
			pvm_pkint(tids,NPROC,1);
			printf("SPMD: Empaqueto el entero %d\n",tids);

			pvm_mcast(&tids[1],NPROC-1,0);
			printf("SPMD: Multicast a %d tareas SPMD\n",NPROC-1);
			}
			else printf("SPMD: NO he podido crear las tareas 'SPMD'\n");
		}
		else { 
			printf("SPMD: Soy un hijo\n");

			// recibo el array de tids
			pvm_recv(tids[0],0);
			printf("SPMD: Recibo de %d\n",tids[0]);

			pvm_upkint(tids,NPROC,1);
			printf("SPMD: Desempaqueto el entero %d\n",tids);

			for (i=1;i<NPROC;i++)
				if (mytid == tids[i])
					{
					me = i;
					break;
					}
			}

	// Todas las NPROC tareas son iguales ahora
	dowork(me,tids,NPROC);
	printf("SPMD: Salgo de PVM\n");
	pvm_exit();
}
