
/***************************************************************
                        semlib.c

 Esta livraria de funções permite de forma fácil e limitada
 aceder aos mecanismos de semáforos utilizados em Linux.
 Foi desenvolvida no âmbito da cadeira de Sistemas Operativos I,
 com objectivo de permiter aos alunos do 1º Ano um primeiro
 contacto com a problemática da programação multitarefa.


 Versão:	1.0
 Data:		5 de Maio 2005

 Copyright:	Luis Lino Ferreira
 		llf@dei.isep.ipp.pt

***************************************************************/



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


union semun
{
	int val;			// value for SETVAL
	struct semid_ds *buf;		// buffer for IPC_STAT & IPC_SET
	unsigned short int *array;	// array for GETALL & SETALL
	struct seminfo *__buf;		// buffer for IPC_INFO
};

/***************************************************************

                         SemDef

 Permite definir um semáforo

 Parâmetros:
 	valor_inicial: valor a que deve ser inicializado o semaforo

 Saída
 	Descriptor do semaforo
	-1 em caso de erro

 Problemas e Limitações:
 	Apenas permite a utilização de semáforos comuns ao processo
	evovador e respectivos filhos.


***************************************************************/

int SemDef(int valor_inicial)
{
 int 	descr_sem;
 int 	erro;


  //Criação do Semáforo
 descr_sem = semget(IPC_PRIVATE, 1, IPC_CREAT|0777);
 if (descr_sem == -1)
 {
	perror("Erro ao criar o semáforo!");
	return(-1);
 }

 // Inicializa o valor do semáforo
 erro = semctl(descr_sem, 0, SETVAL, valor_inicial);
 if (erro == -1)
 {
	perror("Erro ao atribuir valor inicial ao semáforo!");
	return(-1);
 }
 return(descr_sem);
}

/***************************************************************

                         SemSignal

 Implementa a primitiva de Signal que permite incrementar o
 valor do semáforo.

 Parâmetros:
 	descr_sem: descritor do semafor

 Saída
 	0 em caso de sucesso
	-1 em caso de erro


***************************************************************/

int SemSignal(int descr_sem)
{
 struct sembuf 	aux;
 int 		erro;

 // Preenche a estrutura que permite operar sobre o semáforo
 aux.sem_num = 0;
 aux.sem_op = 1;
 aux.sem_flg = 0;

 // Excuta a operação
 erro = semop(descr_sem, &aux, 1);
 if (erro == -1)
 {
	perror("Erro em Signal!");
	return(-1);
 }

 // Em caso de sucesso da função
 return(0);

}


/***************************************************************

                         SemWait

 Implementa a primitiva de Wait que permite decrementar o
 valor do semáforo. Caso esta valor seja igual ou zero o
 processo evocados fica bloqueado

 Parâmetros:
 	descr_sem: descritor do semafor

 Saída
 	0 em caso de sucesso
	-1 em caso de erro

***************************************************************/

int SemWait(int descr_sem)
{
 struct sembuf 	aux;
 int 		erro;

 // Preenche a estrutura que permite operar sobre o semáforo
 aux.sem_num = 0;
 aux.sem_op = -1;
 aux.sem_flg = 0;

 // Excuta a operação
 erro = semop(descr_sem, &aux, 1);
 if (erro == -1)
 {
	perror("Erro em Wait!");
	return(-1);
 }

 // Em caso de sucesso da função
 return(0);
}


/***************************************************************

                         SemDel

 Remove um semáforo do Kernel.

 Parâmetros:
 	descr_sem: descritor do semafor

 Saída
 	0 em caso de sucesso
	-1 em caso de erro

***************************************************************/


int SemDel(int descr_sem)
{
 union semun aux;

 return(semctl(descr_sem, 0, IPC_RMID, aux));

}
