/*
 *  monitor.c :   A task monitor for Desqview API
 *  author:       Victor R. Volkman
 */


#include <stdio.h>
#include <malloc.h>
#include "dvapi.h"         /* These two files are found in */
#include "dvapi2.h"        /* the Desqview API C package.  */
#include "monitor.h"

#ifndef MAKEFD
#include "monitor.fd"
#endif


/* The monitor contains two mutually exclusive functions:
   recvl and sendv. The recvl function is used by
   subprocesses to wait for any signal. A signal can
   indicate either a synchronization wait or a communication
   wait.  The sendv function is used by suprocesses to send
   a synchronization signal or obtain exclusive write access
   to the global communication array.

   Semafore usage is decoded as follows:

   Semafore value    Usage
   --------------    -----
       MASTER        Signal indicating that the master node
                     is executing the critical section.

     1..NUMPRC       Communication signal indicates that
                     valid data is waiting for a given node.

    NUMPRC+node      Synchronization signal returned by the
                     master node to each individual node.

    2*NUMPRC+1       Termination signal returned when the
                     master node finds that no further
                     intervals will be used.
*/


open_monitor(sem_name, new_mon_pp)
char *sem_name;
MONITOR **new_mon_pp;
{
   DESQ_HAN semaphore_han;

   semaphore_han = mal_new();
   mal_name(semaphore_han, sem_name, strlen(sem_name));
   *new_mon_pp = (MONITOR *) calloc(sizeof(MONITOR),1);
   (*new_mon_pp)->sem_han = semaphore_han;
}


close_monitor(old_mon_pp)
MONITOR **old_mon_pp;
{
   mal_close((*old_mon_pp)->sem_han);
   free(*old_mon_pp);
   *old_mon_pp = NULL;
}


sendv(mon_p,val,to_node)
MONITOR *mon_p;
double val;
int to_node;
{
   DESQ_HAN semaphore_han = mon_p->sem_han;

   mal_lock(semaphore_han);      /* begin mutually exclusive
                                    access */
   mon_p->sent[to_node]++;
   mon_p->value[to_node] = val;
   mal_unlock(semaphore_han);    /* end mutually exclusive
                                    access   */
}


recvl(mon_p,val_p,from_node)
MONITOR *mon_p;
double *val_p;
int from_node;
{
   DESQ_HAN semaphore_han = mon_p->sem_han;
   int *from_ptr;

   from_ptr = &(mon_p->sent[from_node]);

   mal_lock(semaphore_han);      /* begin mutually exclusive
                                    access */
   while (! *from_ptr) {  /* message hasn't arrived yet */
      mal_unlock(semaphore_han);
      api_pause();
      mal_lock(semaphore_han);
      }
   *from_ptr = *from_ptr - 1;
   *val_p = mon_p->value[from_node];
   mal_unlock(semaphore_han);    /* end mutually exclusive
                                    access   */
}
