Correzioni di impaginazione e indicizzazione
[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  *****************************************************************************/
26 #include <sys/sem.h>     /* SysV semaphores */
27 #include <sys/types.h>   /* primitive system data types */
28 #include <sys/stat.h>    /* file characteristics constants and functions */
29 #include <fcntl.h>       /* file control functions */
30 #include <signal.h>      /* signal constants, types and functions */
31
32 #include "Gapil.h"
33 /*
34  * Function MutexCreate: create a mutex/semaphore
35  *
36  * First call create a semaphore, using the given key. 
37  * We want only one semaphore so we set second argument to 1; third 
38  * parameter is the flag argument, and is set to create a semaphore 
39  * with R/W privilege for the user.
40  * Second call initialize the semaphore to 1 (unlocked)
41  *
42  * Input: an IPC key value (to create an unique semaphore)
43  * Return: the semaphore id# or -1 on error
44  */
45 int MutexCreate(key_t ipc_key) 
46 {
47     const union semun semunion={1};             /* semaphore union structure */
48     int sem_id, ret;
49     sem_id = semget(ipc_key, 1, IPC_CREAT|0666);         /* get semaphore ID */
50     if (sem_id == -1) {                              /* if error return code */
51         return sem_id;
52     }
53     ret = semctl(sem_id, 0, SETVAL, semunion);             /* init semaphore */
54     if (ret == -1) {
55         return ret;
56     }
57     return sem_id;
58 }
59 /*
60  * Function MutexFind: get the semaphore/mutex Id given the IPC key value
61  *
62  * Input: an IPC key value
63  */
64 int MutexFind(key_t ipc_key) 
65 {
66     return semget(ipc_key, 1, 0);
67 }
68 /*
69  * Function MutexRead: read the current value of the mutex/semaphore
70  *
71  * Input:  a semaphore id #
72  * Return: the semaphore value
73  */
74 int MutexRead(int sem_id) 
75 {
76     return semctl(sem_id, 0, GETVAL);
77 }
78 /*
79  * Define sembuf structures to lock and unlock the semaphore 
80  * (used to implement a mutex)
81  */
82 struct sembuf sem_lock={                                /* to lock semaphore */
83     0,                                   /* semaphore number (only one so 0) */
84     -1,                                    /* operation (-1 to use resource) */
85     SEM_UNDO};                                /* flag (set for undo at exit) */
86 struct sembuf sem_ulock={                             /* to unlock semaphore */
87     0,                                   /* semaphore number (only one so 0) */
88     1,                                  /* operation (1 to release resource) */
89     SEM_UNDO};                                      /* flag (in this case 0) */
90 /*
91  * Function MutexLock: to lock a mutex/semaphore
92  *
93  * Input:  a semaphore id #
94  * Output: semop return code  (0 OK, -1 KO)
95  */
96 int MutexLock(int sem_id) 
97 {
98     return semop(sem_id, &sem_lock, 1);
99 }
100 /*
101  * Function MutexUnlock: to unlock a mutex/semaphore
102  *
103  * Input:  a semaphore id #
104  * Return: semop return code (0 OK, -1 KO)
105  */
106 int MutexUnlock(int sem_id) 
107 {
108     return semop(sem_id, &sem_ulock, 1);
109 }
110 /*
111  * Function MutexRemove: remove a mutex/semaphore
112  *
113  * Input:  a semaphore id #
114  * Return: return code of semctl
115  */
116 int MutexRemove(int sem_id) 
117 {
118     return semctl(sem_id, 0, IPC_RMID);
119 }
120 /***************************************************************************** 
121  *
122  * File locking mutex 
123  *
124  * Create a mutex usinf file locking. Use file locking to lock a file
125  * as a mutex request, and unlock it as a mutex release.
126  *
127  * Author: S. Piccardi Dec. 2002
128  *
129  *****************************************************************************/
130 /*
131  * Function CreateMutex: Create a mutex using file locking.  
132  *
133  * Open a new lock file (creating it if not existent, and giving error
134  * otherwise). Is a simple wrapper for open.
135  *
136  * Input:  a filename
137  * Output: a file descriptor  (>0 OK, -1 KO)
138  */
139 int CreateMutex(const char *path_name)
140 {
141     return open(path_name, O_EXCL|O_CREAT);
142 }
143 /*
144  * Function UnlockMutex: unlock a file.  
145  * 
146  * Open a lock file (failing if not existent). Is a simple wrapper for
147  * open.
148  *
149  * Input:  a filename
150  * Output: a return code  (>0 OK, -1 KO)
151  */
152 int FindMutex(const char *path_name)
153 {
154     return open(path_name, O_RDWR);
155 }
156 /*
157  * Function LockMutex: lock mutex using file locking.
158  *
159  * Input:  a mutex (i.e. a file descriptor)
160  * Output: a return code  (0 OK, -1 KO)
161  */
162 int LockMutex(int fd)
163 {
164     struct flock lock;                                /* file lock structure */
165     /* first open the file (creating it if not existent) */
166     /* set flock structure */
167     lock.l_type = F_WRLCK;                        /* set type: read or write */
168     lock.l_whence = SEEK_SET;        /* start from the beginning of the file */
169     lock.l_start = 0;                  /* set the start of the locked region */
170     lock.l_len = 0;                   /* set the length of the locked region */
171     /* do locking */
172     return fcntl(fd, F_SETLKW, &lock);
173 }
174 /*
175  * Function UnlockMutex: unlock a file.  
176  *
177  * Input:  a mutex (i.e. a file descriptor)
178  * Output: a return code  (0 OK, -1 KO)
179  */
180 int UnlockMutex(int fd)
181 {
182     struct flock lock;                                /* file lock structure */
183     /* set flock structure */
184     lock.l_type = F_UNLCK;                               /* set type: unlock */
185     lock.l_whence = SEEK_SET;        /* start from the beginning of the file */
186     lock.l_start = 0;                  /* set the start of the locked region */
187     lock.l_len = 0;                   /* set the length of the locked region */
188     /* do locking */
189     return fcntl(fd, F_SETLK, &lock);
190 }
191 /*
192  * Function RemoveMutex: remove a mutex (unlinking the lock file).
193  * 
194  * Just remove the lock file.
195  *
196  * Input:  a filename
197  * Output: a return code (0 OK, -1 KO)
198  */
199 int RemoveMutex(const char *path_name)
200 {
201     return unlink(path_name);
202 }
203 /*
204  * Function ReadMutex: read a mutex status.
205  * 
206  * Read the status for a mutex.
207  *
208  * Input:  a mutex (i.e. a file descriptor)
209  * Output: the lock type (F_UNLCK,  F_RDLCK or  F_WRLCK, or -1 if KO)
210  */
211 int ReadMutex(int fd)
212 {
213     int res;
214     struct flock lock;                                /* file lock structure */
215     /* set flock structure */
216     lock.l_type = F_WRLCK;                               /* set type: unlock */
217     lock.l_whence = SEEK_SET;        /* start from the beginning of the file */
218     lock.l_start = 0;                  /* set the start of the locked region */
219     lock.l_len = 0;                   /* set the length of the locked region */
220     /* do locking */
221     if ( (res = fcntl(fd, F_GETLK, &lock)) ) {
222         return res;
223     }
224     return lock.l_type;
225 }