#include <unistd.h>
#include <sys/ipc.h>
#include <sys/sem.h>

union semun{
  int val;
};


/* se chave == 0 */
/* criar semaforo privado */
/* definir valor */
/* devolver id */

/* se chave /= 0 */
/* se semaforo ja existe devolve id */
/* senao criar semaforo publico */
/* definir valor */
/* devolve id */

int cria_semaforo(int chave, int recursos){
  union semun su;
  int sem;

  if(chave == 0){

    if((sem = semget((key_t)0,1,0777|IPC_CREAT)) == -1){
      perror("semget");
      exit(1);
    }

    su.val = recursos;
    semctl(sem,0,SETVAL,su);

  }
  else{
    
    if((sem = semget((key_t)chave,1,0777)) == -1){

      printf("semaforo com a chave %d nao existe\n",chave);

      /* semaforo nao existe */
      if((sem = semget((key_t)chave,1,0777|IPC_CREAT)) == -1){
	perror("semget");
	exit(1);
      }

      su.val = recursos;
      semctl(sem,0,SETVAL,su);
    }

  } 

  return sem;
}


/* libertar (up) n recursos */

int libertar_recurso(int sem,int recursos){
  int res;
  struct sembuf up;

  up.sem_num = 0;
  up.sem_op = recursos;
  up.sem_flg = SEM_UNDO;

  res = semop(sem,&up,1);

  return res;
}
  

/* ocupar (down) n recursos  */

int ocupar_recurso(int sem,int recursos){
  int res;
  struct sembuf down;

  down.sem_num = 0;
  down.sem_op = -recursos;
  down.sem_flg = SEM_UNDO;

  res = semop(sem,&down,1);

  return res;
}


/* remover semaforo da tabela */

int remover_semaforo(int sem){
  int res;

  res = semctl(sem,0,IPC_RMID,NULL);

  return res;
}


/* obter valor do semaforo */

int valor_semaforo(int sem){
  int valor;

  valor = semctl(sem,0,GETVAL,NULL);

  return valor;
}
  
