/***************************************************************************/
/**  Tema    : Implementacion do 1eiro problema de Lectores Escritores    **/
/**            empregando Semaforos.                                      **/
/**                                                                       **/
/**  Data    : 4-Xunho-1997                                               **/
/***************************************************************************/

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

typedef struct
         {
          char *Mutex;
          char *Delay;
          char *Valor;
          char *Despertar;
         }Semaforo;




Semaforo Smut;
Semaforo Swrt;
char *FichInfo,*DatosPila,*CimaPila;
char *Sbinario;



int Ler_Disco(NomFich,Posicion)
char *NomFich;
int Posicion;
{

int df,Valor;
df=open(NomFich,O_CREAT|O_RDONLY,0600);
lseek(df,Posicion*sizeof(int),SEEK_SET);
read(df,&Valor,sizeof(int));
close(df);
/*printf("\n Lin o valor: %d  da Posicion %d ",Valor,Posicion);
printf("do ficheiro %s ",NomFich);*/
return Valor;

}

void Grabar_Disco(NomFich,Posicion,Dato)
char *NomFich;
int Posicion;
int Dato;
{
int df,Tino;

 df=open(NomFich,O_CREAT|O_WRONLY,0600);
 lseek(df,Posicion*sizeof(int),SEEK_SET);
 write(df,&Dato,sizeof(int));
/* printf("\n Grabei o valor %d na Posicion %d ",Dato,Posicion);
 printf(" do ficheiro %s ",NomFich);*/
 close(df);

}

/* Implementacion de operacions para Semaforos binarios */

void Pb(Nome)
char *Nome;
{

   int df;
   while ((df=open(Nome,O_CREAT|O_EXCL,0600))==-1);
   close(df);

}

void Vb(Nome)
char *Nome;
{
 unlink(Nome);
}


/* Funcion para Insertar Dato na Pila */
void InsPila(Dato)
int Dato;
{
int Cima;
Cima=Ler_Disco(CimaPila,0);
Cima=Cima+1;
Grabar_Disco(DatosPila,Cima,Dato);
Grabar_Disco(CimaPila,0,Cima);
/*printf("\n Inserto na Pila o valor %d na posicion %d",Dato,Cima);*/
}


/* Ler e Suprimir un dato da Pila */
int SuprPila(void)
{
int Cima,Dato;

Pb(Sbinario);
Cima=Ler_Disco(CimaPila,0);
Dato=Ler_Disco(DatosPila,Cima);
if (Cima==-1) printf("\n Pila Vacia ");
 else
   {
    Grabar_Disco(CimaPila,0,Cima-1);
   }
Vb(Sbinario);
return Dato;

}


/* Implementacion de Kearns de semaforos Xerales a partir de Sem. binarios */
void P(s)  Semaforo s;  {
 int df,Valor;
 int Despertar;
 Pb(s.Mutex);
 Valor=Ler_Disco(s.Valor,0);
 Valor=Valor+1;
 Grabar_Disco(s.Valor,0,Valor);
 if (Valor<0)
    {
      Vb(s.Mutex);
      Pb(s.Delay);
      Pb(s.Mutex);
      Despertar=Ler_Disco(s.Despertar,0);
      Despertar=Despertar-1;
      Grabar_Disco(s.Despertar,0,Despertar);
      if (Despertar>0) Vb(s.Delay);

     }
  Vb(s.Mutex);
}



void V(s)  Semaforo s;  {
  int df,Valor,Despertar;
  Pb(s.Mutex);
  Valor=Ler_Disco(s.Valor,0);
  Valor=Valor+1;
  Grabar_Disco(s.Valor,0,Valor);
  if (Valor<=0)
      {
        Despertar=Ler_Disco(s.Despertar,0);
         Despertar=Despertar+1;
        Grabar_Disco(s.Despertar,0,Despertar);

      Vb(s.Delay);
      }
  Vb(s.Mutex);
}

/* Primeiro Problema dos Lectores Escritores */

void Lector(Sem,Swrt,Num)
Semaforo Sem;Semaforo Swrt;
int Num;
{
 int ReadCounter,df,DatoPila;
 printf("\n O lector %d quere ler un libro ... \n",Num);
 fflush(stdout);
 P(Sem);
 ReadCounter=Ler_Disco(FichInfo,0);
 ReadCounter=ReadCounter+1;
 Grabar_Disco(FichInfo,0,ReadCounter);
 if (ReadCounter==1)  P(Swrt);
 V(Sem);
    printf("\n O Lector %d Consigue Ler o libro da Sabiduria\n",Num);
    fflush(stdout);
    DatoPila=SuprPila();

 P(Sem);
 ReadCounter=Ler_Disco(FichInfo,0);
 ReadCounter=ReadCounter-1;
 Grabar_Disco(FichInfo,0,ReadCounter);
 if (ReadCounter==0) V(Swrt);
 V(Sem);

}


void Escritor(Swrt,Num)
Semaforo Swrt;
int Num;
{
sleep(2);
printf("\n O Escritor %d intenta que lle publiquen un libro ",Num);
P(Swrt);

  printf("\n O Escritor %d consigue publicar un libro ",Num);
  InsPila(Num);

V(Swrt);

}


main ()

{


/* Inicializo Datos */
 int ReadCounter,df;
 int Valor,Despertar,i;
 Sbinario="SemPila";
 CimaPila="CimaPila";
 DatosPila="DatosPila";
 FichInfo="FichInfo";
 Smut.Mutex="SmutMutex";
 Smut.Delay="SmutDelay";
 Smut.Valor="SmutValor";
 Smut.Despertar="SmutDespertar";
 Valor=1;
 Despertar=0;
 Swrt.Mutex="SwrtMutex";
 Swrt.Delay="SwrtDelay";
 Swrt.Valor="SwrtValor";
 Swrt.Despertar="SwrtDespertar";
 ReadCounter=0;
 Grabar_Disco(Smut.Valor,0,Valor);
 Grabar_Disco(Smut.Despertar,0,Despertar);
 Grabar_Disco(FichInfo,0,ReadCounter);
 Grabar_Disco(Swrt.Valor,0,Valor);
 Grabar_Disco(Swrt.Despertar,0,Despertar);
 unlink(Smut.Mutex);
 unlink(Swrt.Mutex);
 unlink(DatosPila);
 unlink(CimaPila);
 unlink(Sbinario);
 df=open(Smut.Delay,O_CREAT|O_WRONLY,0600);
 close(df);
 df=open(Swrt.Delay,O_CREAT|O_WRONLY,0600);
 close(df);
 Grabar_Disco(CimaPila,0,-1);
 for (i=1;i<12;i++) InsPila(i);
/* Fin Inicializacion de Datos */
/* Creo 20 procesos concurrentes : 10 Lectores e 10 Escritores */
 if (fork()==0)
  Lector(Smut,Swrt,1);
 else
  if (fork()==0)
   Lector(Smut,Swrt,2);
  else
   if (fork()==0)
    Escritor(Swrt,1);
   else
    if (fork()==0)
     Lector(Smut,Swrt,3);
    else
     if (fork()==0)
      Escritor(Swrt,2);
     else
      if (fork()==0)
       Escritor(Swrt,3);
      else
       if (fork()==0)
        Lector(Smut,Swrt,4);
       else
        if (fork()==0)
         Lector(Smut,Swrt,5);
        else
         if (fork()==0)
          Lector(Smut,Swrt,6);
         else
          if (fork()==0)
           Escritor(Swrt,4);
          else
           if (fork()==0)
            Lector(Smut,Swrt,7);
           else
            if (fork()==0)
             Lector(Smut,Swrt,8);
            else
             if (fork()==0)
              Escritor(Swrt,5);
             else
              if (fork()==0)
               Escritor(Swrt,6);
              else
               if (fork()==0)
                Escritor(Swrt,7);
               else
                if (fork()==0)
                 Escritor(Swrt,8);
                else
                 if (fork()==0)
                  Escritor(Swrt,9);
                 else
                  if (fork()==0)
                   Escritor(Swrt,10);
                  else
                   if (fork()==0)
                    Lector(Smut,Swrt,9);
                   else
                    Lector(Smut,Swrt,10);


}







