3 * Copyright (C) 2002 Simone Piccardi
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.
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.
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.
19 /*****************************************************************************
21 * File Mutex.c: define a set of functions for mutex manipulation
23 * Author: S. Piccardi Dec. 2002
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 */
34 * Function MutexCreate: create a mutex/semaphore
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)
42 * Input: an IPC key value (to create an unique semaphore)
43 * Return: the semaphore id# or -1 on error
45 int MutexCreate(key_t ipc_key)
47 const union semun semunion={1}; /* semaphore union structure */
49 sem_id = semget(ipc_key, 1, IPC_CREAT|0666); /* get semaphore ID */
50 if (sem_id == -1) { /* if error return code */
53 ret = semctl(sem_id, 0, SETVAL, semunion); /* init semaphore */
60 * Function MutexFind: get the semaphore/mutex Id given the IPC key value
62 * Input: an IPC key value
64 int MutexFind(key_t ipc_key)
66 return semget(ipc_key, 1, 0);
69 * Function MutexRead: read the current value of the mutex/semaphore
71 * Input: a semaphore id #
72 * Return: the semaphore value
74 int MutexRead(int sem_id)
76 return semctl(sem_id, 0, GETVAL);
79 * Define sembuf structures to lock and unlock the semaphore
80 * (used to implement a mutex)
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) */
91 * Function MutexLock: to lock a mutex/semaphore
93 * Input: a semaphore id #
94 * Output: semop return code (0 OK, -1 KO)
96 int MutexLock(int sem_id)
98 return semop(sem_id, &sem_lock, 1);
101 * Function MutexUnlock: to unlock a mutex/semaphore
103 * Input: a semaphore id #
104 * Return: semop return code (0 OK, -1 KO)
106 int MutexUnlock(int sem_id)
108 return semop(sem_id, &sem_ulock, 1);
111 * Function MutexRemove: remove a mutex/semaphore
113 * Input: a semaphore id #
114 * Return: return code of semctl
116 int MutexRemove(int sem_id)
118 return semctl(sem_id, 0, IPC_RMID);
120 /*****************************************************************************
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.
127 * Author: S. Piccardi Dec. 2002
129 *****************************************************************************/
131 * Function CreateMutex: Create a mutex using file locking.
133 * Open a new lock file (creating it if not existent, and giving error
134 * otherwise). Is a simple wrapper for open.
137 * Output: a file descriptor (>0 OK, -1 KO)
139 int CreateMutex(const char *path_name)
141 return open(path_name, O_EXCL|O_CREAT);
144 * Function UnlockMutex: unlock a file.
146 * Open a lock file (failing if not existent). Is a simple wrapper for
150 * Output: a return code (>0 OK, -1 KO)
152 int FindMutex(const char *path_name)
154 return open(path_name, O_RDWR);
157 * Function LockMutex: lock mutex using file locking.
159 * Input: a mutex (i.e. a file descriptor)
160 * Output: a return code (0 OK, -1 KO)
162 int LockMutex(int fd)
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 */
172 return fcntl(fd, F_SETLKW, &lock);
175 * Function UnlockMutex: unlock a file.
177 * Input: a mutex (i.e. a file descriptor)
178 * Output: a return code (0 OK, -1 KO)
180 int UnlockMutex(int fd)
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 */
189 return fcntl(fd, F_SETLK, &lock);
192 * Function RemoveMutex: remove a mutex (unlinking the lock file).
194 * Just remove the lock file.
197 * Output: a return code (0 OK, -1 KO)
199 int RemoveMutex(const char *path_name)
201 return unlink(path_name);
204 * Function ReadMutex: read a mutex status.
206 * Read the status for a mutex.
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)
211 int ReadMutex(int fd)
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 */
221 if ( (res = fcntl(fd, F_GETLK, &lock)) ) {