Completata la descrizione dell'esempio dei mutex realizzati con i semafori.
[gapil.git] / sources / wrappers.h
1 /***************************************************************
2  *
3  * File wrappers.h: define a set of macro and inlined 
4  * functions for signal, shared memory and semaphore handling
5  *
6  * Author: S. Piccardi
7  *
8  * $Id: wrappers.h,v 1.4 2002/11/20 23:34:02 piccardi Exp $
9  *
10  ***************************************************************/
11 #include <sys/sem.h>     /* IPC semaphore declarations */
12 #include <sys/shm.h>     /* IPC shared memory declarations */
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <fcntl.h>
16 #include <signal.h>      /* signal handling declarations */
17 /**
18  ** Semaphore definition; used to implement a MutexXXXX API
19  ** To create a Mutex use an underlaying semaphore and init it;
20  ** we put here all the needed data structires
21  **/
22 /* put this definition, get from the man pages */
23 #if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
24 /* union semun is defined by including <sys/sem.h> */
25 #else
26 /* according to X/OPEN we have to define it ourselves */
27 union semun {
28   int val;                    /* value for SETVAL */
29   struct semid_ds *buf;       /* buffer for IPC_STAT, IPC_SET */
30   unsigned short int *array;  /* array for GETALL, SETALL */
31   struct seminfo *__buf;      /* buffer for IPC_INFO */
32 };
33 #endif
34 /*
35  * Function MutexCreate: create a mutex/semaphore
36  *
37  * First call create a semaphore, using the given key. 
38  * We want only one semaphore so we set second argument to 1; third 
39  * parameter is the flag argument, and is set to create a semaphore 
40  * with R/W privilege for the user.
41  * Second call initialize the semaphore to 1 (unlocked)
42  *
43  * Input: an IPC key value (to create an unique semaphore)
44  * Return: the semaphore id# or -1 on error
45  */
46 inline int MutexCreate(key_t ipc_key) 
47 {
48     const union semun semunion={1};             /* semaphore union structure */
49     int sem_id, ret;
50     sem_id = semget(ipc_key, 1, IPC_CREAT|0666);         /* get semaphore ID */
51     if (sem_id == -1) {                              /* if error return code */
52         return sem_id;
53     }
54     ret = semctl(sem_id, 0, SETVAL, semunion);             /* init semaphore */
55     if (ret == -1) {
56         return ret;
57     }
58     return sem_id;
59 }
60 /*
61  * Function MutexFind: get the semaphore/mutex Id given the IPC key value
62  *
63  * Input: an IPC key value
64  */
65 inline int MutexFind(key_t ipc_key) 
66 {
67     return semget(ipc_key,1,0);
68 }
69 /*
70  * Function MutexRead: read the current value of the mutex/semaphore
71  *
72  * Input:  a semaphore id #
73  * Return: the semaphore value
74  */
75 inline int MutexRead(int sem_id) 
76 {
77     return semctl(sem_id, 0, GETVAL);
78 }
79 /*
80  * Define sembuf structures to lock and unlock the semaphore 
81  * (used to implement a mutex)
82  */
83 struct sembuf sem_lock={                                /* to lock semaphore */
84     0,                                   /* semaphore number (only one so 0) */
85     -1,                                    /* operation (-1 to use resource) */
86     SEM_UNDO};                                /* flag (set for undo at exit) */
87 struct sembuf sem_ulock={                             /* to unlock semaphore */
88     0,                                   /* semaphore number (only one so 0) */
89     1,                                  /* operation (1 to release resource) */
90     SEM_UNO};                                       /* flag (in this case 0) */
91 /*
92  * Function MutexLock: to lock a mutex/semaphore
93  *
94  * Input:  a semaphore id #
95  * Output: semop return code  (0 OK, -1 KO)
96  */
97 inline int MutexLock(int sem_id) 
98 {
99     return semop(sem_id, &sem_lock, 1);
100 }
101 /*
102  * Function MutexUnlock: to unlock a mutex/semaphore
103  *
104  * Input:  a semaphore id #
105  * Return: semop return code (0 OK, -1 KO)
106  */
107 inline int MutexUnlock(int sem_id) 
108 {
109     return semop(sem_id, &sem_ulock, 1);
110 }
111 /*
112  * Function ShmCreate:
113  * Allocate a shared memory segment.
114  * First call get a shared memory segment with KEY key access and size SIZE,
115  * by creating it with R/W privilege for the user (this is the meaning of
116  * the ored flags). The function return an identifier shmid used for any 
117  * further reference to the shared memory segment. 
118  * Second call attach the shared memory segment to this process and return a
119  * pointer to it (of char * type). 
120  * Then initialize shared memory:
121  * Set all to 0x55 (means 0101 un binary notation
122  *
123  * Input:  an IPC key value
124  *         the shared memory segment size
125  * Return: the address of the segment
126  */
127 inline char * ShmCreate(key_t ipc_key, int shm_size) 
128 {
129     char * shptr;
130     int shmid;               /* ID of the IPC shared memory segment */
131     if ((shmid=shmget(ipc_key,shm_size,IPC_CREAT|0666))<0){ /* get shm ID */
132         perror("cannot find shared memory");
133         exit(1);
134     }
135     if ( (shptr=shmat(shmid,0,0)) < 0 ){    /* take the pointer to it */
136         perror("cannot attach shared memory");
137         exit(1);
138     }
139     memset((void *)shptr,0x55,shm_size);  /* second couter starts from "0" */
140     return shptr;
141 }
142 /*
143  * Function ShmFind:
144  * Find a shared memory segment 
145  * Input:  an IPC key value
146  *         the shared memory segment size
147  * Return: the address of the segment
148  */
149 inline char * ShmFind(key_t ipc_key, int shm_size) 
150 {
151     char * shptr;
152     int shmid;               /* ID of the IPC shared memory segment */
153     if ( (shmid=shmget(ipc_key,shm_size,0))<0 ){  /* find shared memory ID */
154         perror("cannot find shared memory");
155         exit(1);
156     }
157     if ( (shptr=shmat(shmid,0,0)) < 0 ){    /* take the pointer to it */
158         perror("cannot attach shared memory");
159         exit(1);
160     }
161     return shptr;
162 }
163 /*
164  * Function LockFile:
165  * Create a lockfile of the given pathname.
166  * Fail and exit in case of error or existence of the same lock 
167  * file, using unlink do not need to remove the file,
168  */
169 inline void LockFile(const char* path_name) 
170 {
171     if (open(path_name, O_EXCL|O_CREAT)<0) {
172         perror("Already active");
173         exit(1);
174     } 
175 }
176 inline void UnlockFile(const char* path_name) 
177 {
178     if (unlink(path_name)) {
179         perror("error, cannot unlink");
180         exit(1);
181     }   
182 }
183 /*
184  * Function Signal
185  * Initialize a signal handler.
186  * To enable the signal handling a process we need to tell it to
187  * kernel; this is done writing all needed info to a sigaction structure
188  * named sigact, and then callind sigaction() system call passing the
189  * information stored in the sigact structure variable.
190  *
191  * Input:  the signal to handle 
192  *         the signal handler function
193  * Return: the previous sigaction structure
194  */
195 typedef void SigFunc(int);
196 inline SigFunc * Signal(int signo, SigFunc *func) 
197 {
198     struct sigaction new_handl, old_handl;
199     new_handl.sa_handler=func;
200     /* clear signal mask: no signal blocked during execution of func */
201     if (sigemptyset(&new_handl.sa_mask)!=0){  /* initialize signal set */
202         perror("cannot initializes the signal set to empty"); /* see mess. */
203         exit(1);
204     }
205     new_handl.sa_flags=0;                  /* init to 0 all flags */
206     /* change action for signo signal */
207     if (sigaction(signo,&new_handl,&old_handl)){ 
208         perror("sigaction failed on signal action setting");
209         exit(1);
210     }
211     return (old_handl.sa_handler);
212 }
213
214 /**
215  ** Defining prototypes for the all other functions
216  **/ 
217 ssize_t SockRead(int fd, void *buf, size_t count);
218 ssize_t SockWrite(int fd, const void *buf, size_t count);
219
220 void HandSIGCHLD(int sig);