Ejemplo n.º 1
0
void kill_workers ()
{
	printf ("INFO: Killing the workers\n") ;
	/* kill all the worker */
	pvm_initsend(PvmDataDefault) ;
	pvm_mcast (Worker_tids,NUMBER_OF_WORKERS,KILL) ;

	/* close the window */
	auxCloseWindow() ;

	/* exit pvm */
	pvm_exit() ;

	/* free the pixel buffer */
	free (Pixel_buffer) ;

	/* free the pixel buffer */
	free (Image_buffer) ;

	/* free the worker tids */
	free (Worker_tids) ;

	/* exit the program */
	auxQuit() ;

}
Ejemplo n.º 2
0
void sendEof(FilterPlacement *pFilterP) {
    pvm_initsend(PvmDataRaw);
    int tipo_msg = MSGT_EOF;
    pvm_pkint(&tipo_msg, 1, 1);
    //sends the EOF message for all instances of the filter
    pvm_mcast(pFilterP->tids, pFilterP->numInstances, 0);
}
Ejemplo n.º 3
0
void mcast_accept_msg(struct state_info info) {
	char diag[200];
	GQueue *waiting_req_q = (*info.my_lift_number == LIFT_1) ? info.waiting_req_q1 : info.waiting_req_q2;
	int len = g_queue_get_length(waiting_req_q);
	// diag_msg(info.mstrtid, info.mytid, "*** 0");
	int *tids = malloc(len * sizeof(int));
	int i = 0;
	sprintf(diag, "*** %d processes awaiting accepts", g_queue_get_length(info.waiting_req_q));
	diag_msg(info.mstrtid, info.mytid, diag);
	while (!g_queue_is_empty(waiting_req_q)) {
		int *tid = g_queue_pop_head(waiting_req_q);
		int *sender_weight_ptr = g_hash_table_lookup(info.skiers_weights, tid);
		int *lift_free = (*info.my_lift_number == LIFT_1) ? info.lift1_free : info.lift2_free;
		*lift_free -= *sender_weight_ptr;
		tids[i] = *tid;
		i++;
		sprintf(diag, "*** mcast MSG_ACCEPT to %d [weight=%d]", *tid, *sender_weight_ptr);
		diag_msg(info.mstrtid, info.mytid, diag);
	}
	*info.local_clock += 1;

	int tag = MSG_ACCEPT;
	pvm_initsend(PvmDataDefault);
	pvm_pkint(&tag, 1, 1);
	pvm_pkint(&info.mytid, 1, 1);
	pvm_pkint(info.local_clock, 1, 1);
	pvm_mcast(tids, len, tag);

	sprintf(diag, "mcast MSG_ACCEPT to %d waiting processes [timestamp=%d]", len, *info.local_clock);
	diag_msg(info.mstrtid, info.mytid, diag);
}
Ejemplo n.º 4
0
int msend_msg(int *recipients, int number, int msgtag)
{
   int info;

   PVM_FUNC(info, pvm_mcast(recipients, number, msgtag));

   return(info);
}
Ejemplo n.º 5
0
value
Pvm_mcast(value tids, value msgtag)
{
  int *ctids, i, err;
  int n = Wosize_val(tids);

  ctids = (int*)malloc(sizeof(int)*(n+1));
  for(i = 0; i < n; i++) ctids[i] = Int_val(Field(tids, i));

  err = pvm_mcast(ctids, n, Int_val(msgtag));
  free(ctids);
  if (err < 0) TreatError(err);
  return;
}
Ejemplo n.º 6
0
void BroadStr(char *str, int tids[], int ntids, int MsgType)
{
  int info;

  info = pvm_initsend(PvmDataDefault);
  if (info) 
  {
     pvm_pkstr(str);
     pvm_mcast(tids,ntids, MsgType);
  }
  else
  {
     fprintf(stderr, "Problems with BroadStr : Message type %d\n", MsgType);
  }
}
Ejemplo n.º 7
0
void BroadInt(int IntBuf[], int n, int tid[], int ntid, int MsgType)
{
  int info;

  info = pvm_initsend(PvmDataDefault);
  if (info) 
  {
     pvm_pkint(IntBuf, n, 1);
     pvm_mcast(tid, ntid, MsgType);
  }
  else
  {
     fprintf(stderr, "Problems with BroadInt: Message type %d\n", MsgType);
  }
}
Ejemplo n.º 8
0
void BroadINFO(INFO *data, int n, int tid[], int ntid, int MsgType)
{
  int info;

  info = pvm_initsend(PvmDataDefault);

  if (info)
  {
     pvm_pkbyte((char *)data, n*sizeof(INFO), 1);
     pvm_mcast(tid, ntid, MsgType);
  }
  else
  {
     fprintf(stderr, "Problems with BroadINFO : Message type %d\n", MsgType);
  }
}
Ejemplo n.º 9
0
void BroadFloat(float *FloatBuf, int n, int tid[], int ntid, int MsgType)
{
  int info;

  info = pvm_initsend(PvmDataDefault);
  /*pvm_pkbyte((char *)FloatBuf, n*sizeof(float), 1);*/
  if (info)
  {
     pvm_pkfloat(FloatBuf, n, 1); /* wences */
     pvm_mcast(tid, ntid, MsgType);
  }
  else
  {
     fprintf(stderr, "Problems with BroadFloat : Message type %d\n", MsgType);
  }
}
Ejemplo n.º 10
0
void sendEowToAllInputs(FilterSpec * filterSpec) {
    int i, j;
    // for each input Port of this filter
    for(i = 0; i < filterSpec->numInputs; i++) {
        // i must send 1 Eow for each instace that writes to this filter
        for(j = 0; j < filterSpec->inputs[i]->fromFilter->filterPlacement.numInstances; j++) {
            //send our EOW to listeners on the other side
            int msgType = MSGT_EOW;
            int taskId = -1;

            pvm_initsend(PvmDataRaw);
            pvm_pkint(&msgType, 1, 1);
            pvm_pkint(&taskId, 1, 1);

            pvm_mcast(filterSpec->filterPlacement.tids, filterSpec->filterPlacement.numInstances, filterSpec->inputs[i]->tag);
        }
    }
}
Ejemplo n.º 11
0
static void
find_tree_manager(const int my_tid, int &tm_tid)
{
   struct pvmtaskinfo *taskp = 0;
   int ntask = 0;
   pvm_tasks(0, &ntask, &taskp);
   int * tids = new int[ntask];
   int i, k;
   
   for (i = 0, k = 0; i < ntask; ++i) {
      if (taskp[i].ti_ptid != 0)
	 continue; // has a parent, can't be the TM
      if (taskp[i].ti_tid == my_tid)
	 continue; // self
      // Otherwise it could be the TM (might be a console...)
      tids[k++] = taskp[i].ti_tid;
   }

   if (tm_tid != 0) {
      // Check that the given tid is among the candidates
      for (i = 0; i < k; ++i)
	 if (tids[i] == tm_tid)
	    break;
      if (i == k)
	 stop("No TM candidate has the given tid... Aborting.\n");
   } else {
      // Broadcast a query to the candidates
      pvm_initsend(PvmDataRaw);
      pvm_mcast(tids, k, BCP_ARE_YOU_TREEMANAGER);
      // Wait for an answer
      struct timeval tout = {15, 0};
      int bufid = pvm_trecv(-1, BCP_I_AM_TREEMANAGER, &tout);
      if (bufid == 0)
	 stop("No TM candidates replied within 30 seconds... Aborting.\n");
      int bytes = 0, msgtag = 0;
      pvm_bufinfo(bufid, &bytes, &msgtag, &tm_tid);
   }

   delete[] tids;
}
Ejemplo n.º 12
0
int main (int argc, char **argv)
  
{
	int nt;                 /* number of time samples */
	int nz;                 /* number of migrated depth samples */
	int nx,nxshot;      /* number of midpoints,shotgathers, the folds in a shot
				gather */

	int flag=1;		/*flag to use ft or meter as the unit*/
	int dip=65;		/*maximum dip angle to migrate*/
	int iz,iw,ix,it,oldsx;     /* loop counters*/
	int ntfft;        /* fft size*/
	int nw;              /* number of wave numbers */
	int mytid,tids[NNTASKS],msgtype,rc,i;/*variable for PVM function*/
	int nw1,task; 	
	int lpad=9999,rpad=9999;	/*zero-traces padded on left and right sides*/
	float f1,f2,f3,f4;	/*frequencies to build the Hamming window*/
	int nf1,nf2,nf3,nf4;	/*the index for above frequencies*/
	int NTASKS=0;		/*number of slave tasks to start*/
	char cpu_name[NNTASKS][80];	/*strings to store the computers' name*/
	int flag_cpu=0;			/*flag to control if using NTASKS variable*/

	float sx,gxmin,gxmax;	/*location of  geophone and receivers*/
	int isx,nxo,ifx=0;	/*index for geophone and receivers*/
	int ix1,ix2,ix3,il,ir;	/*dummy index*/

	float *wl,*wtmp;	/*pointers for the souce function*/
	float Fmax=25;		/*peak frequency to make the Ricker wavelet*/
	int ntw,truenw;		/*number of frequencies to be migrated*/


	float dt=0.004,dz;   	/*time, depth sampling interval*/
	float ft;            	/*first time sample*/
	float dw;         	/*frequency sampling interval*/
	float fw;         	/*first frequency*/
	float dx;            	/*spatial sampling interval*/
	float **p,**cresult,**result_tmp;    /* input, output data*/
	float **v;		/*double pointer direct to velocity structure*/ 
	complex *wlsp,**cp,**cq,**cq1; /*pointers for internal usage*/

	char *vfile="";         /* name of file containing velocities */
	char *cpufile="";	/* name of file containing CPU name */

	FILE *vfp,*cpu_fp;

                        
	/* hook up getpar to handle the parameters */
	initargs(argc,argv);
	requestdoc(1);

	/* get optional parameters */
	if (!getparfloat("ft",&ft)) ft = 0.0;
	if (!getparint("nz",&nz)) err("nz must be specified");
	if (!getparfloat("dz",&dz)) err("dz must be specified");
	if (!getparstring("vfile", &vfile)) err("vfile must be specified");
	if (!getparint("nxo",&nxo)) err("nxo must be specified");
	if (!getparint("nxshot",&nxshot)) err("nshot must be specified");
	if (!getparfloat("Fmax",&Fmax)) err("Fmax must be specified");
	if (!getparfloat("f1",&f1)) f1 = 10.0;
	if (!getparfloat("f2",&f2)) f2 = 20.0;
	if (!getparfloat("f3",&f3)) f3 = 40.0;
	if (!getparfloat("f4",&f4)) f4 = 50.0;
	if (!getparint("lpad",&lpad)) lpad=9999;
	if (!getparint("rpad",&rpad)) rpad=9999;
	if (!getparint("flag",&flag)) flag=1;
	if (!getparint("dip",&dip)) dip=65;

	if (getparstring("cpufile", &cpufile)){
	cpu_fp=fopen(cpufile,"r");
	NTASKS=0;
	while(!feof(cpu_fp)){
	fscanf(cpu_fp,"%s",cpu_name[NTASKS]);
	NTASKS++;
	}
	NTASKS-=1;
	flag_cpu=1;
	}
	else /*if cpufile not specified, the use NTASKS*/
	if (!getparint("NTASKS",&NTASKS)) err("No CPUfile specified, NTASKS must be specified");

	/*allocate space for the velocity profile*/
	tshot=nxshot;
	v=alloc2float(nxo,nz);
        
	/*load velicoty file*/
	vfp=efopen(vfile,"r");
	efread(v[0],FSIZE,nz*nxo,vfp);
	efclose(vfp);

	/*PVM communication starts here*/
	mytid=pvm_mytid();	/*get my pid*/
	task=NTASKS;
	warn("\n %d",task);
	rc=0;
	/*spawn slave processes here*/
	if(!flag_cpu){
	rc=pvm_spawn(child,NULL,PvmTaskDefault,"",task,tids);
	}
	else{
	for(i=0;i<NTASKS;i++){
	rc+=pvm_spawn(child,NULL,PvmTaskHost,cpu_name[i],1,&tids[i]);
	}
	}
        
	/*show the pid of slaves if*/
	for(i=0;i<NTASKS;i++){
	if(tids[i]<0)warn("\n %d",tids[i]);
	else warn("\nt%x\t",tids[i]);
        }

	/*if not all the slaves start, then quit*/
	if(rc<NTASKS){ warn("error");pvm_exit();exit(1);}
        
	/*broadcast the global parameters nxo,nz,dip to all slaves*/
	pvm_initsend(PvmDataDefault);
	rc=pvm_pkint(&nxo,1,1);
	rc=pvm_pkint(&nz,1,1);
	rc=pvm_pkint(&dip,1,1);
	msgtype=PARA_MSGTYPE;
	task=NTASKS;
	rc=pvm_mcast(tids,task,msgtype);

	/*broadcast the velocity profile to all slaves*/
        pvm_initsend(PvmDataDefault);
        rc=pvm_pkfloat(v[0],nxo*nz,1);
        msgtype=VEL_MSGTYPE; 
        rc=pvm_mcast(tids,task,msgtype);
	
	/*free the space for velocity profile*/
	free2float(v);


/*loop over shot gathers begin here*/
loop:

        /* get info from first trace */
        if (!gettr(&tr))  err("can't get first trace");
        nt = tr.ns;


        /* let user give dt and/or dx from command line */
        if (!getparfloat("dt", &dt)) {
                if (tr.dt) { /* is dt field set? */
                        dt = ((double) tr.dt)/1000000.0;
                } else { /* dt not set, assume 4 ms */   
                        dt = 0.004;
                        warn("tr.dt not set, assuming dt=0.004");
                }
        }
        if (!getparfloat("dx",&dx)) {
                if (tr.d2) { /* is d2 field set? */
                        dx = tr.d2;
                } else {
                        dx = 1.0;
                        warn("tr.d2 not set, assuming d2=1.0");
                }
        }


	sx=tr.sx;
	isx=sx/dx;
	gxmin=gxmax=tr.gx;
	oldsx=sx;

        /* determine frequency sampling interval*/
        ntfft = npfar(nt);
        nw = ntfft/2+1;
        dw = 2.0*PI/(ntfft*dt);

	/*compute the index of the frequency to be migrated*/
	fw=2.0*PI*f1;
	nf1=fw/dw+0.5;

	fw=2.0*PI*f2;
	nf2=fw/dw+0.5;
 
	fw=2.0*PI*f3;
	nf3=fw/dw+0.5;

	fw=2.0*PI*f4;
	nf4=fw/dw+0.5;

	/*the number of frequency to migrated*/
	truenw=nf4-nf1+1;
	fw=0.0+nf1*dw;
	warn("nf1=%d nf2=%d nf3=%d nf4=%d nw=%d",nf1,nf2,nf3,nf4,truenw);
	fw=0.0;

        /* allocate space */
        wl=alloc1float(ntfft);
        wlsp=alloc1complex(nw);

	/*generate the Ricker wavelet*/
        wtmp=ricker(Fmax,dt,&ntw);

        for(it=0;it<ntfft;it++)
        wl[it]=0.0;

        for(it=0;it<ntw-12;it++)
        wl[it]=wtmp[it+12];
	free1float( wtmp);

	/*Fourier transform the Ricker wavelet to frequency domain*/
        pfarc(-1,ntfft,wl,wlsp);
        
	/* allocate space */
        p = alloc2float(ntfft,nxo);
        cp = alloc2complex(nw,nxo);

        for (ix=0; ix<nxo; ix++)
                for (it=0; it<ntfft; it++)
                        p[ix][it] = 0.0;
       
	
	/*read in a single shot gather*/
	ix=tr.gx/dx;
	memcpy( (void *) p[ix], (const void *) tr.data,nt*FSIZE);

        nx = 0;

	while(gettr(&tr)){
			int igx;

			if(tr.sx!=oldsx){ fseek(stdin,(long)(-240-nt*4),SEEK_CUR); break;}
			igx=tr.gx/dx;
			memcpy( (void *) p[igx], (const void *) tr.data,nt*FSIZE);  
                
			if(gxmin>tr.gx)gxmin=tr.gx;
			if(gxmax<tr.gx)gxmax=tr.gx;
			nx++;
			oldsx=tr.sx;
			}

	warn("\nnx= %d",nx);
	warn("sx %f , gxmin %f  gxmax %f",sx,gxmin,gxmax);

	/*transform the shot gather from time to frequency domain*/
        pfa2rc(1,1,ntfft,nxo,p[0],cp[0]);

	/*compute the most left and right index for the migrated section*/ 
	ix1=sx/dx;
	ix2=gxmin/dx;
	ix3=gxmax/dx;
        
	if(ix1>=ix3)ix3=ix1;
	if(ix1<=ix2)ix2=ix1;

	il=ix2;
	ir=ix3;
	ix2-=lpad;
	ix3+=rpad;
	if(ix2<0)ix2=0;
	if(ix3>nxo-1)ix3=nxo-1;

	/*the total traces to be migrated*/
	nx=ix3-ix2+1;

	/*allocate space*/
        cq = alloc2complex(nx,nw);
	cq1 = alloc2complex(nx,nw);


	/*transpose the frequency domain data from data[ix][iw] to data[iw][ix] and
	apply a Hamming at the same time*/

	for (ix=0; ix<nx; ix++)
	for (iw=0; iw<nw; iw++){	

	float tmpp=0.0,tmppp=0.0;
	
	if(iw<nf1||iw>nf4)
	cq[iw][ix]=cmplx(0.0,0.0);
	else{
		if(iw>=nf1&&iw<=nf2){tmpp=PI/(nf2-nf1);tmppp=tmpp*(iw-nf1)-PI;tmpp=0.54+0.46*cos(tmppp);
		cq[iw][ix]=crmul(cp[ix+ix2][iw],tmpp);}
		else{
			if(iw>=nf3&&iw<=nf4){tmpp=PI/(nf4-nf3);tmppp=tmpp*(iw-nf3);tmpp=0.54+0.46*cos(tmppp);
			cq[iw][ix]=crmul(cp[ix+ix2][iw],tmpp);}
			else
			{cq[iw][ix]=cp[ix+ix2][iw];}
		}
	}
	cq[iw][ix]=cp[ix+ix2][iw];
	cq1[iw][ix]=cmplx(0.0,0.0);
	}


	ix=sx/dx-ifx;
	warn("ix %d",ix);

	for(iw=0;iw<nw;iw++){
	cq1[iw][ix-ix2]=wlsp[iw];
	}


	free2float(p);
	free2complex(cp);
	free1float(wl);
	free1complex(wlsp);

	/*if the horizontal spacing interval is in feet, convert it to meter*/ 
	if(!flag)
	dx*=0.3048;

	/*start of the timing function*/
	time(&t1);

	/* send local parameters to all slaves*/
	pvm_initsend(PvmDataDefault);

	ix=15;
	rc=pvm_pkint(&ix,1,1);

	rc=pvm_pkint(&ntfft,1,1);
        rc=pvm_pkint(&ix2,1,1);
        rc=pvm_pkint(&ix3,1,1);
	rc=pvm_pkint(&isx,1,1);
	rc=pvm_pkint(&il,1,1);
	rc=pvm_pkint(&ir,1,1);
        rc=pvm_pkfloat(&dx,1,1);
        rc=pvm_pkfloat(&dz,1,1);
        rc=pvm_pkfloat(&dw,1,1);
	rc=pvm_pkfloat(&dt,1,1);
	msgtype=PARA_MSGTYPE;

	task=NTASKS;
	rc=pvm_mcast(tids,task,msgtype);

	
	/* send all the frequency to slaves*/
	count=NTASKS*5; /*count is the number of frequency components in a shot
			gather*/ 
        
	nw=truenw;        
	nw1=nw/(count);
	if(nw1==0)nw1=1;
	total=count=ceil(nw*1.0/nw1);

	/* if it is the first shot gather, send equal data to all the slaves, then for
	the following shot gathers, only send data when slave requests*/

	if(nxshot==tshot){

	for(i=0;i<NTASKS;i++){ 
	float *tmpp;
	float fw1;
	int nww,byte,nwww;
			
        pvm_initsend(PvmDataDefault);
	nww=nf1+i*nw1;fw1=fw+nww*dw;
	nwww=nw1;
        byte=UnDone;

        rc=pvm_pkint(&byte,1,1);
        rc=pvm_pkfloat(&fw1,1,1);
        rc=pvm_pkint(&nwww,1,1);   
	rc=pvm_pkfloat((float *)cq[nww],nx*nwww*2,1);
        rc=pvm_pkfloat((float *)cq1[nww],nx*nwww*2,1);
	msgtype=DATA_MSGTYPE;
	pvm_send(tids[i],msgtype);
	}

	count-=NTASKS;

	}


	while(count){

	int tid0,bufid;
	float *tmpp;
	float fw1;
	int nww,byte,nwww;  
	int i;  
	i=total-count;

        
	msgtype=COM_MSGTYPE;
	bufid=pvm_recv(-1,msgtype);
	rc=pvm_upkint(&tid0,1,1);
	pvm_freebuf(bufid);
        
        pvm_initsend(PvmDataDefault);
        nww=nf1+i*nw1;fw1=fw+nww*dw;
        if(i==total-1)nwww=nw-nw1*i;
        else nwww=nw1;

	byte=UnDone;
        rc=pvm_pkint(&byte,1,1);
        rc=pvm_pkfloat(&fw1,1,1);
        rc=pvm_pkint(&nwww,1,1);
        rc=pvm_pkfloat((float *)cq[nww],nx*nwww*2,1);
        rc=pvm_pkfloat((float *)cq1[nww],nx*nwww*2,1);
        msgtype=DATA_MSGTYPE;
        pvm_send(tid0,msgtype);

        count--;
	}

	ix=Done;
        
        pvm_initsend(PvmDataDefault);
        rc=pvm_pkint(&ix,1,1);

        msgtype=DATA_MSGTYPE;
        pvm_mcast(tids,task,msgtype);


	free2complex(cq);
	free2complex(cq1);

	time(&t2);

	warn("\n %d shot been finished in %f seconds, Ntask=%d",nxshot,difftime(t2,t1),NTASKS);

	nxshot--;                       

	if(nxshot)goto loop;
	

	/*when all the shot gathers done, send signal to all slaves to request the
								partial imaging*/
	ix=FinalDone;
        pvm_initsend(PvmDataDefault);
        rc=pvm_pkint(&ix,1,1);
        msgtype=PARA_MSGTYPE;
        pvm_mcast(tids,task,msgtype);
        
	/*allocate space for the final image*/
        cresult = alloc2float(nz,nxo);
	for(ix=0;ix<nxo;ix++)
        for(iz=0;iz<nz;iz++)
        { cresult[ix][iz]=0.0;
	}

	result_tmp= alloc2float(nz,nxo);
	
	/*receive partial image from all the slaves*/
	msgtype=RESULT_MSGTYPE;
	i=0;

	while(i<NTASKS){
	int bufid;
	bufid=pvm_recv(-1,msgtype);
	rc=pvm_upkfloat(result_tmp[0],nxo*nz,1);
	pvm_freebuf(bufid);
	for(ix=0;ix<nxo;ix++)
	for(iz=0;iz<nz;iz++)
	{
	cresult[ix][iz]+=result_tmp[ix][iz];	
	}
	i=i+1;
	warn("\n i=%d been received",i);
	}

	/*send signal to all slaves to kill themselves*/
	pvm_initsend(PvmDataDefault);
	pvm_mcast(tids,task,COM_MSGTYPE);

	/*output the final image*/
        for(ix=0; ix<nxo; ix++){
                tr.ns = nz ;
                tr.dt = dz*1000000.0 ;
		tr.d2 = dx;
		tr.offset = 0;
		tr.cdp = tr.tracl = ix;
                memcpy( (void *) tr.data, (const void *) cresult[ix],nz*FSIZE);
                puttr(&tr);
        }



        pvm_exit();            
        return EXIT_SUCCESS;
                                
}                               
Ejemplo n.º 13
0
/// user function:add a new query to a pipeline of filters. Called by user manager runs this.
///	\param layout System Layout.
///	\param work Buffer with a Unit of Work (UoW)
///	\param workSize Unit of Work Size (UoW)
///	\return Zero on success, -1 on error.
int appendWork(Layout *layout, void *work, int workSize) {
#ifdef NO_BARRIER

    // sends work for each filter
    pvm_initsend(PvmDataRaw);
    // First tell that is a mensage of WORK
    int msgType = MSGT_WORK;
    pvm_pkint(&msgType, 1, 1);
    //then attach the work to it
    pvm_pkbyte((char *)work, workSize, 1);

    // for each filter, send his work
    for(i = 0; i < layout->numFilters; i++) {
        FilterPlacement *pFilterP = &(layout->filters[i]->filterPlacement);
        // sends work to all filters of this set
        pvm_mcast(pFilterP->tids, pFilterP->numInstances, 0);
    }

#else
    int i;
    int totalEows = 0, numEowsReceived;
#ifdef ATTACH
    int totalAttachedFilters = 0;
#endif
    int reconf = 0 /** should we reconfigure? */, remainingReconfs = 0; //how many times should we try?

#ifdef VOID_INST
#ifdef BMI_FT
    char instDir[MAX_IDIR_LENGTH];
    sprintf(instDir, "%s/", INST_DIR);
    for (i=0; i < layout->numFilters-1; i++) {
        if (strlen(instDir) >= (MAX_IDIR_LENGTH - 3)) {
            //dont want to overflow this array
            fprintf(stderr, "%s %d: warning, instrumentation directory name too big, truncating to %s\n", __FILE__, __LINE__, instDir);
            break;
        }
        sprintf(instDir, "%s%d-", instDir, layout->filters[i]->filterPlacement.numInstances);
    }
    sprintf(instDir, "%s%d", instDir, layout->filters[layout->numFilters-1]->filterPlacement.numInstances);
    char managerLogFile[MAX_IDIR_LENGTH+20];
    sprintf(managerLogFile, "%s/manager.time", instDir);
    FILE *fp = fopen(managerLogFile, "w");

    struct timeval tv;
    struct timezone tz; //not used
    //get the time
    gettimeofday(&tv, &tz);

    if(fp != NULL)
        fprintf(fp, "1 %ld %ld\n", tv.tv_sec, tv.tv_usec);
#endif
#endif

    //before sending, we check if we received any filter error
    int bufid = pvm_probe(-1, MSGT_FERROR);
    if (bufid != 0) {
        int bytes, tag, tid;
        char *msg;
        pvm_bufinfo(bufid, &bytes, &tag, &tid);
        msg = (char*)malloc(bytes+1);
        pvm_recv(tid, MSGT_FERROR);
        pvm_upkbyte(msg, bytes, 1);
        msg[bytes] = '\0';

        fprintf(stderr, "Manager.c: Error, received death notification\n");
        fprintf(stderr, "Manager.c: %s\n", msg);
        free(msg);
        killAllFilters(layout);
        exit(-1);
    }

    printf("Manager.c: starting work...\n");

    // number of EOWs we expect to receive
    for(i = 0; i < layout->numFilters; i++) {
        totalEows += layout->filters[i]->filterPlacement.numInstances;
#ifdef ATTACH
        if(layout->filters[i]->attached) {
            totalAttachedFilters += layout->filters[i]->filterPlacement.numInstances;
        }
        // TODO:TOSCO:::
        if(layout->filters[i]->attach) return 0;
#endif
    }

    //we stay in this loop while we have to reconfigure
    //usually, this will be only one time, unless a we get some reconf message
    do {

        // sends work for each filter
        pvm_initsend(PvmDataRaw);
        int msgType;
#ifdef VOID_FT
        if(!reconf) {
#endif
            // First tell that is a mensage of WORK
            msgType = MSGT_WORK;
#ifdef VOID_FT
        } else {
            // one fault has occurred
            msgType = MSGT_FT;
        }
#endif
        pvm_pkint(&msgType, 1, 1);
        //then attach the work to it
        pvm_pkbyte((char *)work, workSize, 1);

        reconf = 0; //we are optimistic, always expect to not reconfigure


        // for each filter, send his work
        for(i = 0; i < layout->numFilters; i++) {
            FilterPlacement *pFilterP = &(layout->filters[i]->filterPlacement);
            // sends work to all filters of this set
            pvm_mcast(pFilterP->tids, pFilterP->numInstances, 0);
        }
        /*

        		TaskIdList *finalTaskIdList = NULL, *currentTaskIdList;
        		int filtersThatUseTasks = 0;
        		// Manager receives filter's terminated tasks list
        		for(i = 0; i < layout->numFilters; i++) {
        			FilterPlacement *pFilterP = &(layout->filters[i]->filterPlacement);
#ifdef ATTACH
        			// if this filter is of the attached
        			// type i dont need worry about use Task
        //			if(layout->filters[i]->attached)continue;
#endif
        			for(j = 0; j < pFilterP->numInstances; j++) {
        				int instanceUseTasks = -1;

        				// Get is this filter use tasks
        				pvm_recv(pFilterP->tids[j], 0);
        				pvm_upkint(&instanceUseTasks, 1, 1);
        				layout->filters[i]->useTasks = instanceUseTasks;

#ifdef VOID_FT
        				if (instanceUseTasks) {
        					currentTaskIdList = (TaskIdList *)unpackTaskIdList();

        					//	Para fazer intersecao, gerente ordenar? as listas de tarefas recebidas e utilizar? a fun??o meet() do CrazyMiner/ID3.
        					qsort(currentTaskIdList->vetor, currentTaskIdList->size, sizeof(int), compareTaskId);
        					if(finalTaskIdList == NULL) {
        						finalTaskIdList = currentTaskIdList;
        					} else {
        						// 	Manager makes the intersection of all finished tasks lists
        						finalTaskIdList = taskIdListIntersection(finalTaskIdList, currentTaskIdList);
        						taskIdListDestroy(currentTaskIdList);
        					}
        				}
#endif

        			} // for

        			if (layout->filters[i]->useTasks) filtersThatUseTasks++;
        		}

        		//	Gerente devolve resultado das intersecoes para todas as instancias de todos os filtros.
        		for(i = 0; i < layout->numFilters; i++) {
         			FilterPlacement *pFilterP = &(layout->filters[i]->filterPlacement);
#ifdef ATTACH
        			// if this filter is of the attached
        			// type i dont need worry about use Task
        //TODO			if(layout->filters[i]->attached)continue;
#endif

        			int needForwardTaskMessages = 1;
        			if (filtersThatUseTasks < 2) needForwardTaskMessages = 0;

#ifdef VOID_FT
        			if (layout->filters[i]->useTasks) {
        				// Send if they should forward task messages
        				// and pigback :-) the final task id list
         				pvm_initsend(PvmDataDefault);
         				pvm_pkint(&needForwardTaskMessages, 1, 1);

        				packTaskIdList(finalTaskIdList);
        				pvm_mcast(pFilterP->tids, pFilterP->numInstances, 0);
        			} else {
#endif
        				// Only send if they should forward task messages
         				pvm_initsend(PvmDataDefault);
         				pvm_pkint(&needForwardTaskMessages, 1, 1);
        				pvm_mcast(pFilterP->tids, pFilterP->numInstances, 0);
#ifdef VOID_FT
        			}
#endif
        		}
        		taskIdListDestroy(finalTaskIdList);

        */

        //now we receive the EOWs
        numEowsReceived = 0;

        //now we expect to receive EOW or errors
        while(numEowsReceived < totalEows) {
            //we are open to receive anything from anyone here
            //all messages to the manager should be tagged, so we now their type
            int szMsg = -1;
            int inst_tid = -1;
            int msgTag = -1;
            int bufid = pvm_recv(-1, -1);
            pvm_bufinfo(bufid, &szMsg, &msgTag, &inst_tid);

            switch (msgTag) {
            case (MSGT_EOW): {
                //received EOW, expect this usually
                int instance = -1;
                FilterSpec *pFilter = NULL;

                getFilterByTid(layout, inst_tid, &pFilter, &instance);

                if ((pFilter != NULL) && (instance != -1)) {
                    printf("Manager.c: EOW received from %s, instance %d\n",
                           pFilter->name, instance);
                } else {
                    fprintf(stderr, "Manager.c: unknown EOW received! Shouldnt get here!\n");
                }
                numEowsReceived++;
                break;
            }
            case (MSGT_AEXIT):
            case (MSGT_FERROR): {
                //someone called dsExit or system error at the filter side
                //common cause for this are library not found, wrong initscritpt etc
                char *message = (char*)malloc(sizeof(char)*szMsg+1);
                pvm_upkbyte(message, szMsg, 1);
                message[szMsg] = '\0';

                //the filter and the instance
                FilterSpec *fp = NULL;
                int instance = -1;
                getFilterByTid(layout, inst_tid, &fp, &instance);

                if (msgTag == MSGT_AEXIT) {
                    printf("Manager.c: Filter %s, instance %d(tid %x) called dsExit: %s\n",
                           fp->name, instance, inst_tid, message);
                } else {
                    printf("Manager.c: Filter %s error, instance %d(tid %x) called exit: %s\n",
                           fp->name, instance, inst_tid, message);
                }
                free(message);
                // kill all instances
                killAllFilters(layout);
                exit(-1);
                break;
            }
            //task exited or host crashed
            case (MSGT_TEXIT):
            case (MSGT_HDEL): {
                //we only reconfigure a fixed number of times
                if (remainingReconfs <= 0) {
                    //max number of reconfigurations reached... aborting
                    fprintf(stderr, "Manager.c: max reconfigurations reached, aborting...\n");
                    fflush(stderr);
                    fprintf(stdout, "Manager.c: max reconfigurations reached, aborting...\n");
                    fflush(stdout);
                    reconf = 0;

                    // kill all instances which might be alive
                    killAllFilters(layout);
                    exit(-1);;

                }
#ifdef BMI_FT
                gettimeofday(&tv, &tz);
                fprintf(fp, "2 %ld %ld\n", tv.tv_sec, tv.tv_usec);
#endif

                remainingReconfs--;
                reconf = 1;
                // In case of pvm notification, inst_tid will be t80000000
                int notifiesRecv = 1; // We are receiving the first death notification
                int deadFilterTid = -1;
                FilterSpec *pFilter = NULL;
                int instanceDead = -1;

                // Get the tid and name of the dead filter
                int info = pvm_upkint(&deadFilterTid, 1, 1);
                if (info < 0) pvm_perror("Manager.c: error calling pvm_upkint");

                //discover which filter died
                getFilterByTid(layout, deadFilterTid, &pFilter, &instanceDead);

                if((pFilter != NULL) && (instanceDead != -1)) {
                    if (msgTag == MSGT_TEXIT) {
                        fprintf(stderr, "Manager.c: filter %s: instance %d (tid t%x) of %d is dead!!!\n",
                                pFilter->name, instanceDead, deadFilterTid, pFilter->filterPlacement.numInstances);
                    } else {
                        fprintf(stderr, "Manager.c: filter %s: instance %d (tid t%x) of %d machine's crashed!!!\n",
                                pFilter->name, instanceDead, deadFilterTid, pFilter->filterPlacement.numInstances);
                    }
                }
                printf("Manager.c: starting reconfiguration\n");

                // kill all filters in the pipeline
                killAllFilters(layout);

                if (msgTag == MSGT_HDEL) {
                    //int his case, host died, so we must change layout
                    replaceCrashedHost(layout, pFilter, instanceDead);
                }

#ifdef ATTACH
                if (pFilter->attached) {
                    // In this case, all filters that were killed have to notify
                    // their dead.
                    notifiesRecv = 0;
                }
#endif

                //Flush the streams
                //receive all messages which are about to arrive till we get the death notification
                //pvm order should garantee this
#ifdef ATTACH
                while (notifiesRecv < (totalEows - totalAttachedFilters)) {
#else
                while (notifiesRecv < totalEows) {
#endif
                    int newMsgTag = -1;
                    bufid = pvm_recv(-1, MSGT_TEXIT);
                    info = pvm_bufinfo(bufid, NULL, &newMsgTag, &inst_tid);
                    info = pvm_upkint(&deadFilterTid, 1, 1);
                    if (info < 0) pvm_perror("Manager.c: error calling pvm_upkint");

                    fprintf(stderr, "Manager.c: WARNING: received notification (tag %d) about pvm tid t%x death\n", newMsgTag, deadFilterTid);
                    notifiesRecv++;
                }

#ifdef ATTACH
                if(pFilter->attached) {
                    notifiesRecv = 1;
                } else {
                    notifiesRecv = 0;
                }
                // Receive all EOW messages from the attached filters.
                while(notifiesRecv < totalAttachedFilters) {
                    int newMsgTag = -1;
                    bufid = pvm_recv(-1, MSGT_EOW);
                    info = pvm_bufinfo(bufid, NULL, &newMsgTag, &inst_tid);
                    if (info < 0) pvm_perror("Manager.c: error calling pvm_upkint");

                    fprintf(stderr, "Manager.c: WARNING: received EOW (tag %d) from pvm tid t%x\n", newMsgTag, inst_tid);
                    notifiesRecv++;
                }
#endif
                // probes for remaining machine crash notifications
                while (pvm_probe(-1, MSGT_HDEL) > 0) {
                    int newMsgTag = -1;
                    bufid = pvm_recv(-1, MSGT_HDEL);
                    info = pvm_bufinfo(bufid, NULL, &newMsgTag, &inst_tid);
                    info = pvm_upkint(&deadFilterTid, 1, 1);
                    if (info < 0) pvm_perror("Manager.c: error calling pvm_upkint");

                    fprintf(stderr, "Manager.c: WARNING: received notification (tag %d) about pvm tid t%x machine's crash\n", newMsgTag, deadFilterTid);

                    // Replace the died host
                    FilterSpec *pCrashedFilter = NULL;
                    int crashedInstance = -1;
                    getFilterByTid(layout, deadFilterTid, &pCrashedFilter, &crashedInstance);
                    replaceCrashedHost(layout, pCrashedFilter, crashedInstance);
                }
#ifdef BMI_FT
                updateAllFiltersFaultStatus(layout, FAULT_OTHER_FILTER_INST);
                pFilter->faultStatus = instanceDead;
#endif

                //spawn all filters again
                spawnAllFilter(layout);
#ifdef ATTACH
                // Verifies if the dead filter is an attached. If yes, spawn it.
                if(pFilter->attached == 1) {
                    spawnOneAttachedInstance(layout, pFilter, instanceDead);
                }
#endif
                resetStreams(layout);
                //resend the data
                sendFiltersData(layout);
                //start all over again
                numEowsReceived = 0;

#ifdef BMI_FT
                gettimeofday(&tv, &tz);
                fprintf(fp, "3 %ld %ld\n", tv.tv_sec, tv.tv_usec);
#endif
                break;
            }
#ifdef VOID_TERM
        // One filter instance detected local termination
            case (MSGT_LOCALTERM): {
                int localTermTag; // filter instance local termination tag
                pvm_upkint(&localTermTag, 1, 1);
                verifyGlobalTermination(inst_tid, localTermTag);
                break;
            }
#endif
            default: {
                fprintf(stderr, "Manager.c: error receiving EOW, unknown tag!!!\n");
            }
        } //end switch message tag
        if((msgTag == MSGT_TEXIT) || (msgTag == MSGT_HDEL)) {
            // work should be sent again
            break;
        }
        } //end receiving eows
    }
    while(reconf == 1); //leave this loop if we will not reconfigure

#ifdef BMI_FT
    gettimeofday(&tv, &tz);

    fprintf(fp, "4 %ld %ld\n", tv.tv_sec, tv.tv_usec);
#endif

    printf("Manager.c: Work ended\n\n");
    return 0;
#endif
}


/// Finalize a Void pipeline. Only manager runs this.
int finalizeDs(Layout *layout) {
#ifdef NO_BARRIER

#else
    int i;

    // Envia eof para todos os filtros
    // Primeiro envia se eh work (WORK) ou EOF (END_OF_FILTER)
    pvm_initsend(PvmDataRaw);
    int tipo_msg = MSGT_EOF;
    pvm_pkint(&tipo_msg, 1, 1);
    //sends the EOF message for all instances of the filter
    for(i = 0; i < layout->numFilters; i++) {
        FilterPlacement *pFilterP = &(layout->filters[i]->filterPlacement);
#ifdef ATTACH
        if(layout->filters[i]->attach) continue;// this filter cant not receive a EOF because
        // it needs still runnig
#endif
        pvm_mcast(pFilterP->tids, pFilterP->numInstances, 0);
    }
    destroyLayout(layout);
    pvm_exit();
    return 0;
#endif
}
Ejemplo n.º 14
0
/* Function: main_loop_pvm()
 * Date:     SRE, Wed Aug 19 13:59:54 1998 [St. Louis]
 *
 * Purpose:  Given an HMM and parameters for synthesizing random
 *           sequences; return a histogram of scores.
 *           (PVM version)  
 *
 * Args:     hmm     - an HMM to calibrate.
 *           seed    - random number seed
 *           nsample - number of seqs to synthesize
 *           lumpsize- # of seqs per slave exchange; controls granularity
 *           lenmean - mean length of random sequence
 *           lensd   - std dev of random seq length
 *           fixedlen- if nonzero, override lenmean, always this len
 *           hist       - RETURN: the score histogram 
 *           ret_max    - RETURN: highest score seen in simulation
 *           extrawatch - RETURN: total CPU time spend in slaves.
 *           ret_nslaves- RETURN: number of PVM slaves run.
 *
 * Returns:  (void)
 *           hist is alloc'ed here, and must be free'd by caller.
 */
static void
main_loop_pvm(struct plan7_s *hmm, int seed, int nsample, int lumpsize,
	      float lenmean, float lensd, int fixedlen,
	      struct histogram_s **ret_hist, float *ret_max, 
	      Stopwatch_t *extrawatch, int *ret_nslaves)
{
  struct histogram_s *hist;
  int                 master_tid;
  int                *slave_tid;
  int                 nslaves;
  int                 nsent;	/* # of seqs we've asked for so far       */
  int                 ndone;	/* # of seqs we've got results for so far */
  int		      packet;	/* # of seqs to have a slave do           */
  float               max;
  int                 slaveidx;	/* id of a slave */
  float              *sc;        /* scores returned by a slave */
  Stopwatch_t         slavewatch;
  int                 i;
  
  StopwatchZero(extrawatch);
  hist = AllocHistogram(-200, 200, 100);
  max  = -FLT_MAX;

  /* Initialize PVM
   */
  if ((master_tid = pvm_mytid()) < 0)
    Die("pvmd not responding -- do you have PVM running?");
#if DEBUGLEVEL >= 1
  pvm_catchout(stderr);		/* catch output for debugging */
#endif
  PVMSpawnSlaves("hmmcalibrate-pvm", &slave_tid, &nslaves);

  /* Initialize the slaves
   */
  pvm_initsend(PvmDataDefault);
  pvm_pkfloat(&lenmean,       1, 1);
  pvm_pkfloat(&lensd,         1, 1);
  pvm_pkint(  &fixedlen,      1, 1);
  pvm_pkint(  &Alphabet_type, 1, 1);
  pvm_pkint(  &seed,          1, 1);
  if (! PVMPackHMM(hmm)) Die("Failed to pack the HMM");
  pvm_mcast(slave_tid, nslaves, HMMPVM_INIT);
  SQD_DPRINTF1(("Initialized %d slaves\n", nslaves));

  /* Confirm slaves' OK status.
   */
  PVMConfirmSlaves(slave_tid, nslaves);
  SQD_DPRINTF1(("Slaves confirm that they're ok...\n"));
 
  /* Load the slaves
   */
  nsent = ndone = 0;
  for (slaveidx = 0; slaveidx < nslaves; slaveidx++)
    {
      packet    = (nsample - nsent > lumpsize ? lumpsize : nsample - nsent);

      pvm_initsend(PvmDataDefault);
      pvm_pkint(&packet,    1, 1);
      pvm_pkint(&slaveidx,  1, 1);
      pvm_send(slave_tid[slaveidx], HMMPVM_WORK);
      nsent += packet;
    }
  SQD_DPRINTF1(("Loaded %d slaves\n", nslaves));

  /* Receive/send loop
   */
  sc = MallocOrDie(sizeof(float) * lumpsize);
  while (nsent < nsample)
    {
				/* integrity check of slaves */
      PVMCheckSlaves(slave_tid, nslaves);

				/* receive results */
      SQD_DPRINTF2(("Waiting for results...\n"));
      pvm_recv(-1, HMMPVM_RESULTS);
      pvm_upkint(&slaveidx,   1, 1);
      pvm_upkint(&packet,     1, 1);
      pvm_upkfloat(sc,   packet, 1);
      SQD_DPRINTF2(("Got results.\n"));
      ndone += packet;

				/* store results */
      for (i = 0; i < packet; i++) {
	AddToHistogram(hist, sc[i]);
	if (sc[i] > max) max = sc[i];
      }
				/* send new work */
      packet    = (nsample - nsent > lumpsize ? lumpsize : nsample - nsent);

      pvm_initsend(PvmDataDefault);
      pvm_pkint(&packet,    1, 1);
      pvm_pkint(&slaveidx,  1, 1);
      pvm_send(slave_tid[slaveidx], HMMPVM_WORK);
      SQD_DPRINTF2(("Told slave %d to do %d more seqs.\n", slaveidx, packet));
      nsent += packet;
    }
      
  /* Wait for the last output to come in.
   */
  while (ndone < nsample)
    {
				/* integrity check of slaves */
      PVMCheckSlaves(slave_tid, nslaves);

				/* receive results */
      SQD_DPRINTF1(("Waiting for final results...\n"));
      pvm_recv(-1, HMMPVM_RESULTS);
      pvm_upkint(&slaveidx, 1, 1);
      pvm_upkint(&packet,   1, 1);
      pvm_upkfloat(sc, packet, 1);
      SQD_DPRINTF2(("Got some final results.\n"));
      ndone += packet;
				/* store results */
      for (i = 0; i < packet; i++) {
	AddToHistogram(hist, sc[i]);
	if (sc[i] > max) max = sc[i];
      }
    }

  /* Shut down the slaves: send -1,-1,-1.
   */
  pvm_initsend(PvmDataDefault);
  packet = -1;
  pvm_pkint(&packet, 1, 1);
  pvm_pkint(&packet, 1, 1);
  pvm_pkint(&packet, 1, 1);
  pvm_mcast(slave_tid, nslaves, HMMPVM_WORK);

  /* Collect stopwatch results; quit the VM; return.
   */
  for (i = 0; i < nslaves; i++)
    {
      pvm_recv(-1, HMMPVM_RESULTS);
      pvm_upkint(&slaveidx, 1, 1);
      StopwatchPVMUnpack(&slavewatch);

      SQD_DPRINTF1(("Slave %d finished; says it used %.2f cpu, %.2f sys\n",
		    slaveidx, slavewatch.user, slavewatch.sys));

      StopwatchInclude(extrawatch, &slavewatch);
    }

  free(slave_tid);
  free(sc);
  pvm_exit();
  *ret_hist    = hist;
  *ret_max     = max;
  *ret_nslaves = nslaves;
  return;
}
Ejemplo n.º 15
0
void main (int argc, char** argv)
{
	int Message_counter ; /* counter for message packing */
	int My_tid ; /* my task id */

	/* show start up message */
	printf ("\n-=> Fractal Terrain Engine version 2.1 release 2 <=-\n\n") ;

	/* read the config files */
	read_config (argc,argv) ;

	/* set up the pixel buffer and it's variables */ 
	Pixel_buffer_width=User_view.X_size/Number_of_workers;
	Pixel_buffer_size=
		Pixel_buffer_width*User_view.Y_size*3*sizeof(unsigned char) ;
	Pixel_buffer=(unsigned char *) malloc(Pixel_buffer_size) ;

	/* set up worker tids array */
	Worker_tids=(int *)malloc(Number_of_workers*sizeof(int)) ;

	/* set up the image buffer */
	Image_buffer=(unsigned char *) malloc 
		((User_view.X_size*User_view.Y_size*3*sizeof(unsigned char))) ;

	/* start up pvm */
	if ((My_tid = pvm_mytid()) < 0) 
	{
		exit(1);
	}
	/* start up the workers */

	pvm_spawn(WORKER_NAME,(char**)0,PvmTaskDefault,"",
		Number_of_workers,Worker_tids) ;

	printf ("INFO:Spawned %i Workers\n",Number_of_workers) ;

	/* tell the worker what values to use for the terrain function */
	pvm_initsend(PvmDataDefault) ;

	pvm_pkdouble(&H,1,1) ;
	pvm_pkdouble(&Lacunarity,1,1);
	pvm_pkdouble(&Octaves,1,1);
	pvm_pkdouble(&Offset,1,1) ;

	pvm_pkfloat(&Ambient_light,1,1) ;

	pvm_pkfloat(&Fog.Red,1,1) ;
	pvm_pkfloat(&Fog.Green,1,1);
	pvm_pkfloat(&Fog.Blue,1,1) ;

	pvm_pkfloat(&Sky.Red,1,1) ;
	pvm_pkfloat(&Sky.Green,1,1) ;
	pvm_pkfloat(&Sky.Blue,1,1) ;

	pvm_pkfloat(&Horizon.Red,1,1) ;
	pvm_pkfloat(&Horizon.Green,1,1) ;
	pvm_pkfloat(&Horizon.Blue,1,1) ;

	pvm_pkdouble(Colour_boundaries,NUMBER_OF_TERRAIN_COLOURS,1) ;

	for ( Message_counter = 0 ;
		Message_counter<NUMBER_OF_TERRAIN_COLOURS ;
		Message_counter++ )
	{
		pvm_pkfloat(&Terrain_colours[Message_counter].Red,1,1) ;
		pvm_pkfloat(&Terrain_colours[Message_counter].Green,1,1) ;
		pvm_pkfloat(&Terrain_colours[Message_counter].Blue,1,1) ;
	}

	pvm_pkdouble(&Fog_start,1,1) ;
	pvm_pkdouble(&Fog_end,1,1) ;

	/* tell the worker what values to use for the display */
	pvm_pkdouble(&Ray_step,1,1) ;
	pvm_pkdouble(&X_view_angle,1,1) ; 
	pvm_pkdouble(&Y_view_angle,1,1) ;
	pvm_pkint(&Pixel_buffer_width,1,1) ;
	pvm_pkint(&User_view.Y_size,1,1) ;
	pvm_pkdouble(&X_ray_angle,1,1) ;
	pvm_pkdouble(&Y_ray_angle,1,1) ;

	/* send the message to all the workers */
	pvm_mcast (Worker_tids,Number_of_workers,INFO) ;

	/* set up light source */
	normalize_3d(Light_source) ;

	/* set the light source */
	Light_source[0]=0.1 ;
	Light_source[1]=0.4 ;
	Light_source[2]=0.3 ;

	/* tell the worker what values to use for the light source */
	pvm_initsend(PvmDataDefault) ;
	pvm_pkdouble(Light_source,3,1) ;
	pvm_mcast (Worker_tids,Number_of_workers,NEW_LIGHT_SOURCE) ;

	/* set up the users view point */
	Height=1.0 ;
	User.X=0 ;
	User.Y=0 ;
	User.Z=Height ;
	User.X_angle=0.0 ;
	User.Y_angle=0.0 ;
	User.Z_angle=0.0 ;

	/* set up window */
	open_window() ;
	print_keys() ;

	/*									*/
	/* set up the keyboard,Reshape and display routines			*/
	/*									*/
	auxKeyFunc(AUX_Q,kill_workers) ;
	auxKeyFunc(AUX_q,kill_workers) ;
	auxKeyFunc(AUX_ESCAPE,kill_workers) ;   

	auxKeyFunc(AUX_LEFT,left) ;
	auxKeyFunc(AUX_RIGHT,right) ;
	auxKeyFunc(AUX_UP,forwards) ;
	auxKeyFunc(AUX_DOWN,backwards) ;
	auxKeyFunc(AUX_a,up) ;
	auxKeyFunc(AUX_A,up) ;
	auxKeyFunc(AUX_Z,down) ;
	auxKeyFunc(AUX_z,down) ;

	auxKeyFunc(AUX_J,save_image) ;
	auxKeyFunc(AUX_j,save_image) ;

	auxMainLoop(display_loop) ;

}