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


/* Carles Pina i Estany - carles@pinux.info
 * Febrer 2004 */

/*http://66.102.11.104/search?q=cache:UpdbPwN-OM0J:www.infor.uva.es/~benja/semaforos-memoria.html+ejemplo+sem%C3%A1foros+unix&hl=en&ie=UTF-8*/

int inicia (int valor);
void P (int semaforo);
void V (int semaforo);
int semcall (int semaforo, int operacion);

int inicia (int valor) {
	int id;

	union semun {
		int val;
		struct semid_ds *buf;
		ushort *array;
	} arg;

	if ((id=semget(IPC_PRIVATE, 1, (IPC_CREAT|0666))) == -1) {
		perror("Error al crear el semáforo.");
		return(-1);
	} 

	arg.val = valor;
	if (semctl(id, 0, SETVAL, arg) == -1) {
		perror("Error al inicializar el semáforo.");
		return (-1); /*error en inicializacion*/
	}
	return (id);
}

void P (int semaforo) {
	if ( semcall(semaforo, -1) == -1 ) {
		perror("Error en operación P.");
	}
	 
}

void V (int semaforo) {
	if ( semcall(semaforo, 1) == -1 ) {
		perror("Error en operación V."); 
	}
}

int semcall (int semaforo, int operacion) {
	struct sembuf sb;
	sb.sem_num = 0;
	sb.sem_op = operacion;
	sb.sem_flg = 0;

	return ( semop(semaforo, &sb, 1) ); /*devuelve -1 si error */ 
}

int main () {
	pid_t pid;
	int mutex;

	mutex=inicia(1);

	pid=fork();

	if (pid>0) {
		//Sóc el pare
		sleep(1);
		P(mutex); //bloqueja
		printf("Ara espero 1 segon\n");
		sleep(1);
		V(mutex); //desbloqueja

		sleep(2);
		kill(pid,15);
	}
	else {
		//Sóc el fill
		for (;;) {
			P(mutex);
			fprintf(stderr,".");
			V(mutex);
		}
	}
	
	return (0);
}
