Aggiunta funzione MurexRead, riscritti Mutex con il file locking
[gapil.git] / sources / Mutex.c
1 /* Mutex.c
2  * 
3  * Copyright (C) 2002 Simone Piccardi
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or (at
8  * your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /*****************************************************************************
20  *
21  * File Mutex.c: define a set of functions for mutex manipulation 
22  *
23  * Author: S. Piccardi Dec. 2002
24  *
25  * $Id: Mutex.c,v 1.5 2003/01/06 21:24:41 piccardi Exp $
26  *
27  *****************************************************************************/
28 #include <sys/sem.h>     /* IPC semaphore declarations */
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <signal.h>      /* signal handling declarations */
33
34 #include "Gapil.h"
35 /*
36  * Function MutexCreate: create a mutex/semaphore
37  *
38  * First call create a semaphore, using the given key. 
39  * We want only one semaphore so we set second argument to 1; third 
40  * parameter is the flag argument, and is set to create a semaphore 
41  * with R/W privilege for the user.
42  * Second call initialize the semaphore to 1 (unlocked)
43  *
44  * Input: an IPC key value (to create an unique semaphore)
45  * Return: the semaphore id# or -1 on error
46  */
47 int MutexCreate(key_t ipc_key) 
48 {
49     const union semun semunion={1};             /* semaphore union structure */
50     int sem_id, ret;
51     sem_id = semget(ipc_key, 1, IPC_CREAT|0666);         /* get semaphore ID */
52     if (sem_id == -1) {                              /* if error return code */
53         return sem_id;
54     }
55     ret = semctl(sem_id, 0, SETVAL, semunion);             /* init semaphore */
56     if (ret == -1) {
57         return ret;
58     }
59     return sem_id;
60 }
61 /*
62  * Function MutexFind: get the semaphore/mutex Id given the IPC key value
63  *
64  * Input: an IPC key value
65  */
66 int MutexFind(key_t ipc_key) 
67 {
68     return semget(ipc_key, 1, 0);
69 }
70 /*
71  * Function MutexRead: read the current value of the mutex/semaphore
72  *
73  * Input:  a semaphore id #
74  * Return: the semaphore value
75  */
76 int MutexRead(int sem_id) 
77 {
78     return semctl(sem_id, 0, GETVAL);
79 }
80 /*
81  * Define sembuf structures to lock and unlock the semaphore 
82  * (used to implement a mutex)
83  */
84 struct sembuf sem_lock={                                /* to lock semaphore */
85     0,                                   /* semaphore number (only one so 0) */
86     -1,                                    /* operation (-1 to use resource) */
87     SEM_UNDO};                                /* flag (set for undo at exit) */
88 struct sembuf sem_ulock={                             /* to unlock semaphore */
89     0,                                   /* semaphore number (only one so 0) */
90     1,                                  /* operation (1 to release resource) */
91     SEM_UNDO};                                      /* flag (in this case 0) */
92 /*
93  * Function MutexLock: to lock a mutex/semaphore
94  *
95  * Input:  a semaphore id #
96  * Output: semop return code  (0 OK, -1 KO)
97  */
98 int MutexLock(int sem_id) 
99 {
100     return semop(sem_id, &sem_lock, 1);
101 }
102 /*
103  * Function MutexUnlock: to unlock a mutex/semaphore
104  *
105  * Input:  a semaphore id #
106  * Return: semop return code (0 OK, -1 KO)
107  */
108 int MutexUnlock(int sem_id) 
109 {
110     return semop(sem_id, &sem_ulock, 1);
111 }
112 /*
113  * Function MutexRemove: remove a mutex/semaphore
114  *
115  * Input:  a semaphore id #
116  * Return: return code of semctl
117  */
118 int MutexRemove(int sem_id) 
119 {
120     return semctl(sem_id, 0, IPC_RMID);
121 }
122 /***************************************************************************** 
123  *
124  * File locking mutex 
125  *
126  * Create a mutex usinf file locking. Use file locking to lock a file
127  * as a mutex request, and unlock it as a mutex release.
128  *
129  * Author: S. Piccardi Dec. 2002
130  *
131  *****************************************************************************/
132 /*
133  * Function CreateMutex: Create a mutex using file locking.  
134  *
135  * Open a new lock file (creating it if not existent, and giving error
136  * otherwise). Is a simple wrapper for open.
137  *
138  * Input:  a filename
139  * Output: a file descriptor  (>0 OK, -1 KO)
140  */
141 int CreateMutex(const char *path_name)
142 {
143     return open(path_name, O_EXCL|O_CREAT);
144 }
145 /*
146  * Function UnlockMutex: unlock a file.  
147  * 
148  * Open a lock file (failing if not existent). Is a simple wrapper for
149  * open.
150  *
151  * Input:  a filename
152  * Output: a return code  (>0 OK, -1 KO)
153  */
154 int FindMutex(const char *path_name)
155 {
156     return open(path_name, O_RDWR);
157 }
158 /*
159  * Function LockMutex: lock mutex using file locking.
160  *
161  * Input:  a mutex (i.e. a file descriptor)
162  * Output: a return code  (0 OK, -1 KO)
163  */
164 int LockMutex(int fd)
165 {
166     struct flock lock;                                /* file lock structure */
167     /* first open the file (creating it if not existent) */
168     /* set flock structure */
169     lock.l_type = F_WRLCK;                        /* set type: read or write */
170     lock.l_whence = SEEK_SET;        /* start from the beginning of the file */
171     lock.l_start = 0;                  /* set the start of the locked region */
172     lock.l_len = 0;                   /* set the length of the locked region */
173     /* do locking */
174     return fcntl(fd, F_SETLKW, &lock);
175 }
176 /*
177  * Function UnlockMutex: unlock a file.  
178  *
179  * Input:  a mutex (i.e. a file descriptor)
180  * Output: a return code  (0 OK, -1 KO)
181  */
182 int UnlockMutex(int fd)
183 {
184     struct flock lock;                                /* file lock structure */
185     /* set flock structure */
186     lock.l_type = F_UNLCK;                               /* set type: unlock */
187     lock.l_whence = SEEK_SET;        /* start from the beginning of the file */
188     lock.l_start = 0;                  /* set the start of the locked region */
189     lock.l_len = 0;                   /* set the length of the locked region */
190     /* do locking */
191     return fcntl(fd, F_SETLK, &lock);
192 }
193 /*
194  * Function RemoveMutex: remove a mutex (unlinking the lock file).
195  * 
196  * Just remove the lock file.
197  *
198  * Input:  a filename
199  * Output: a return code (0 OK, -1 KO)
200  */
201 int RemoveMutex(const char *path_name)
202 {
203     return unlink(path_name);
204 }
205 /*
206  * Function ReadMutex: read a mutex status.
207  * 
208  * Read the status for a mutex.
209  *
210  * Input:  a mutex (i.e. a file descriptor)
211  * Output: the lock type (F_UNLCK,  F_RDLCK or  F_WRLCK, or -1 if KO)
212  */
213 int ReadMutex(int fd)
214 {
215     int res;
216     struct flock lock;                                /* file lock structure */
217     /* set flock structure */
218     lock.l_type = F_WRLCK;                               /* set type: unlock */
219     lock.l_whence = SEEK_SET;        /* start from the beginning of the file */
220     lock.l_start = 0;                  /* set the start of the locked region */
221     lock.l_len = 0;                   /* set the length of the locked region */
222     /* do locking */
223     if ( (res = fcntl(fd, F_GETLK, &lock)) ) {
224         return res;
225     }
226     return lock.l_type;
227 }