1/* 2 * This program is free software; you can redistribute it and/or 3 * modify it under the terms of the GNU General Public License as 4 * published by the Free Software Foundation; either version 2 of 5 * the License, or (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program; if not, write to the Free Software 14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 15 * MA 02111-1307 USA 16 */ 17#include <stdio.h> 18#include <stdarg.h> 19#include <string.h> 20#include <sys/stat.h> 21#include <errno.h> 22#include <fcntl.h> 23#include <unistd.h> 24#include <shared.h> 25#include "semaphore_mfp.h" 26 27semaphore_t Semaphore; 28semaphore_t spinlock[SPINLOCK_SPIN_MAX]; 29 30int semaphore_create() 31{ 32 int flag_sem = O_CREAT|O_RDWR; 33 int init_value = 1; 34 35 semaphore_unlink(SEM_NAME); 36 37 if (semaphore_open(SEM_NAME, flag_sem, FILE_MODE, init_value) == -1) 38 { 39 perror("semaphore_create fail"); 40 return -1; 41 } 42 43 return 0; 44} 45 46int semaphore_close() 47{ 48 if (Semaphore.sem_magic != SEM_MAGIC) 49 { 50 errno = EINVAL; 51 return -1; 52 } 53 54 Semaphore.sem_magic = 0; // in case caller tries to use it later 55 if (close(Semaphore.sem_fd[0]) == -1 || close(Semaphore.sem_fd[1]) == -1) 56 { 57 memset(&Semaphore, '\0', sizeof(semaphore_t)); 58 return -1; 59 } 60 61 memset(&Semaphore, '\0', sizeof(semaphore_t)); 62 return 0; 63} 64 65int semaphore_open(const char *pathname, int oflag, ... ) 66{ 67 int i, flags, save_errno; 68 char c; 69 mode_t mode; 70 va_list ap; 71 unsigned int value = 0; 72 73 if (oflag & O_CREAT) 74 { 75 va_start(ap, oflag); // init ap to final named argument 76 mode = va_arg(ap, mode_t); 77 value = va_arg(ap, unsigned int); 78 va_end(ap); 79 80 if (mkfifo(pathname, mode) < 0) 81 { 82 if (errno == EEXIST && (oflag & O_EXCL) == 0) 83 oflag &= ~O_CREAT; // already exists, OK 84 else 85 { 86 perror("Sen_open: mkfifo fail"); 87 return -1; 88 } 89 } 90 } 91 92 Semaphore.sem_fd[0] = Semaphore.sem_fd[1] = -1; 93 94 if ( (Semaphore.sem_fd[0] = open(pathname, O_RDONLY | O_NONBLOCK)) < 0) 95 goto error; 96 if ( (Semaphore.sem_fd[1] = open(pathname, O_WRONLY | O_NONBLOCK)) < 0) 97 goto error; 98 if ( (flags = fcntl(Semaphore.sem_fd[0], F_GETFL, 0)) < 0) 99 goto error; 100 flags &= ~O_NONBLOCK; 101 if (fcntl(Semaphore.sem_fd[0], F_SETFL, flags) < 0) 102 goto error; 103 if (oflag & O_CREAT) // initialize semaphore 104 { 105 for (i = 0; i < value; i++) 106 if (write(Semaphore.sem_fd[1], &c, 1) != 1) 107 goto error; 108 } 109 110 Semaphore.sem_magic = SEM_MAGIC; 111 return 0; 112 113error: 114 save_errno = errno; 115 if (oflag & O_CREAT) 116 unlink(pathname); // if we created FIFO 117 close(Semaphore.sem_fd[0]); // ignore error 118 close(Semaphore.sem_fd[1]); // ignore error 119 120 memset(&Semaphore, '\0',sizeof(semaphore_t)); 121 errno = save_errno; 122 perror("semaphore_open error"); 123 124 return -1; 125} 126 127int semaphore_unlink(const char *pathname) 128{ 129 return unlink(pathname); 130} 131 132int semaphore_post() 133{ 134 char c; 135 136 if (Semaphore.sem_magic != SEM_MAGIC) 137 { 138 errno = EINVAL; 139 return -1; 140 } 141 142 if (write(Semaphore.sem_fd[1], &c, 1) == 1) 143 return 0; 144 145 return -1; 146} 147 148int semaphore_wait() 149{ 150 char c; 151 152 if (Semaphore.sem_magic != SEM_MAGIC) 153 { 154 errno = EINVAL; 155 return -1; 156 } 157 158 if (read(Semaphore.sem_fd[0], &c, 1) == 1) 159 return 0; 160 161 return -1; 162} 163 164int spinlock_open(int idx, const char *pathname, int oflag, ... ) 165{ 166 int i, flags, save_errno; 167 char c; 168 mode_t mode; 169 va_list ap; 170 unsigned int value = 0; 171 172 if (oflag & O_CREAT) 173 { 174 va_start(ap, oflag); // init ap to final named argument 175 mode = va_arg(ap, mode_t); 176 value = va_arg(ap, unsigned int); 177 va_end(ap); 178 179 if (mkfifo(pathname, mode) < 0) 180 { 181 if (errno == EEXIST && (oflag & O_EXCL) == 0) 182 oflag &= ~O_CREAT; // already exists, OK 183 else 184 { 185 perror("Sen_open: mkfifo fail"); 186 return -1; 187 } 188 } 189 } 190 191 spinlock[idx].sem_fd[0] = spinlock[idx].sem_fd[1] = -1; 192 193 if ( (spinlock[idx].sem_fd[0] = open(pathname, O_RDONLY | O_NONBLOCK)) < 0) 194 goto error; 195 if ( (spinlock[idx].sem_fd[1] = open(pathname, O_WRONLY | O_NONBLOCK)) < 0) 196 goto error; 197 if ( (flags = fcntl(spinlock[idx].sem_fd[0], F_GETFL, 0)) < 0) 198 goto error; 199 flags &= ~O_NONBLOCK; 200 if (fcntl(spinlock[idx].sem_fd[0], F_SETFL, flags) < 0) 201 goto error; 202 203 if (oflag & O_CREAT) // initialize semaphore 204 { 205 for (i = 0; i < value; i++) 206 if (write(spinlock[idx].sem_fd[1], &c, 1) != 1) 207 goto error; 208 } 209 210 spinlock[idx].sem_magic = SEM_MAGIC; 211 return 0; 212 213error: 214 save_errno = errno; 215 if (oflag & O_CREAT) 216 unlink(pathname); // if we created FIFO 217 close(spinlock[idx].sem_fd[0]); // ignore error 218 close(spinlock[idx].sem_fd[1]); // ignore error 219 220 memset(&spinlock[idx], '\0',sizeof(semaphore_t)); 221 errno = save_errno; 222 perror("semaphore_open error"); 223 224 return -1; 225} 226 227int spinlock_init(int idx) 228{ 229 int flag_sem = O_CREAT|O_RDWR; 230 int init_value = 1; 231 char sem_name[32]; 232 233 if (idx < 0 || idx >= SPINLOCK_SPIN_MAX) 234 return -1; 235 236 sprintf(sem_name, "%s%d", SEM_NAME, idx); 237 semaphore_unlink(sem_name); 238 239 if (spinlock_open(idx, sem_name, flag_sem, FILE_MODE, init_value) == -1) 240 { 241 perror("semaphore_create fail"); 242 return -1; 243 } 244 245 return 0; 246} 247 248int spinlock_destroy(int idx) 249{ 250 if (idx < 0 || idx >= SPINLOCK_SPIN_MAX) 251 return -1; 252 253 if (spinlock[idx].sem_magic != SEM_MAGIC) 254 { 255 errno = EINVAL; 256 return -1; 257 } 258 259 spinlock[idx].sem_magic = 0; // in case caller tries to use it later 260 if (close(spinlock[idx].sem_fd[0]) == -1 || close(spinlock[idx].sem_fd[1]) == -1) 261 { 262 memset(&spinlock[idx], '\0', sizeof(semaphore_t)); 263 return -1; 264 } 265 266 memset(&spinlock[idx], '\0', sizeof(semaphore_t)); 267 return 0; 268} 269 270void init_spinlock(void) 271{ 272 int i; 273 274 for(i=0;i<SPINLOCK_SPIN_MAX;i++) 275 spinlock_init(i); 276} 277 278int spinlock_unlock(int idx) 279{ 280 char c; 281 282 if (idx < 0 || idx >= SPINLOCK_SPIN_MAX) 283 return -1; 284 285 if (spinlock[idx].sem_magic != SEM_MAGIC) 286 { 287 errno = EINVAL; 288 return -1; 289 } 290 291 if (write(spinlock[idx].sem_fd[1], &c, 1) == 1) 292 return 0; 293 294 return -1; 295} 296 297int spinlock_lock(int idx) 298{ 299 char c; 300 301 if (idx < 0 || idx >= SPINLOCK_SPIN_MAX) 302 return -1; 303 304 if (spinlock[idx].sem_magic != SEM_MAGIC) 305 { 306 errno = EINVAL; 307 return -1; 308 } 309 310 if (read(spinlock[idx].sem_fd[0], &c, 1) == 1) 311 return 0; 312 313 return -1; 314} 315