/* Fájlnév: term-fogy-inicializalas.c
   Az előadáson szereplő klasszikus termelő-fogyasztó problémára négy 
   fájlban adunk példát. 
   Elsőként kell futtatni jelen inicializáló programot, mely "elkészíti
   a raktárt": készít és inicializál szemaforkészletet a problémához.
   Ezután indíthatók tetszőleges sorrendben a termelők és a fogyasztók. 
   (A forrásprogramok a term-fogy-termelo.c és a term-fogy-fogyaszto.c).
   Célszerű ezeket a háttérben indítani és pid-jüket megjegyezni, ui. 
   SIGINT szignállal kell őket terminálni (a termelők és a fogyasztók 
   saját ütemükben végtelen ciklusban futnak). 
   Végül a term-fogy-takarito.c programot kell futtatni, hogy a 
   "takarítást" (szemafor megszüntetést) elvégezzük. (E helyett persze
   az ipcrm paranccsal is "takaríthatunk"). 
   
   Elékezve az előadás példájára, három klasszikus (Dijkstra féle)
   szemafor kellene probléma kezeléséhez: egy mutex szemafor a ki-berakó 
   gép védelméhez (amit 1-re kell inicializálni, egy teli szemafor a raktár 
   telítettség kezelésére (0-ra inicializálandó), és egy ures szemafor, 
   a raktár üresség kezeléshez (ezt N-re  kell inicializálni, ahol N
   a raktár rekeszeinek száma: induláskor mind az N rekesz ures). 
   Most mi a probléma megoldáshoz három elemi szemaforból álló készletet
   használuk, ahol a 0. indexű elemi szemafor lesz a mutex, az 1. indexű
   a teli, a 2. indexű az ures szemafor. 
   Az inicializáláshoz a semctl( ) rendszerhívás SETALL parancsát 
   használjuk. Figyeljék meg az union semunion arg deklarációt!
   Készítette: dr. Vadász Dénes
   2006. február
  
*/
#include "mysem.h"

#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
	/* union semun a sys/sem.h-ban már definiált */
#else
	union semun {
		int    val;	      /* A GETVAL és SETVAL-hoz */
		struct semid_ds *buf; /* Az IPC_STAT és IPC_GET-hez */	
		ushort *array;	      /* A GETALL és SETALL-hoz */
	}
#endif
	
main() {
ushort 	  inittabla[3] = {1, 0, N};   /* A mutex, a teli és az ures 
                                                               kezdeti értékei a táblában */
union 	    semun arg; 	     /* Az inicializálás változója */
int 	    id;		     /* A szemafor leírója */ 
int 	    mutex;		     /* A mutex szemafor értékéhez */

/* Megnézzük, létezik-e már a szemafor. Ha igen, és a mutex eleme 
   (a 0. indexű eleme) nem 0, akkor nem kell inicializálni, már 
   "kész a raktár". 
*/
	id = semget(TFKEY, 3, 0);
	if (id < 0) { /* Még nincs szemafor */
		id=semget(TFKEY, 3, PERM | IPC_CREAT);
		if (id < 0) {
			perror(" Baj van, nem készült szemafor. ");
			exit(-1);
		}
	}
	/* Lekérdezem a mutex-et */
	if ((mutex = semctl(id, 0, GETVAL, 0)) < 0) {
		perror(" Nem lehetet lekérdezni a szemafor értéket. "); 
		exit(-1); 
	}
	/* Ha a mutex 0, akkor inicilalizálni kell. */
	if (mutex == 0) {
		arg.array = &inittabla[0]; /* A táblában a kezdő értékek */
		
		if (semctl(id, 0, SETALL, arg) < 0) {
			perror(" Nem lehettt inicializálni. ");
			exit(-1);
		}
	}
	/* Kész vagyunk */
	exit(0);
}
