00001 /* 00002 Simple Semaphore Interface - System V implementation 00003 AUP2, Sec. 7.09.2 00004 00005 Copyright 2003 by Marc J. Rochkind. All rights reserved. 00006 May be copied only for purposes and under conditions described 00007 on the Web page www.basepath.com/aup/copyright.htm. 00008 00009 The Example Files are provided "as is," without any warranty; 00010 without even the implied warranty of merchantability or fitness 00011 for a particular purpose. The author and his publisher are not 00012 responsible for any damages, direct or incidental, resulting 00013 from the use or non-use of these Example Files. 00014 00015 The Example Files may contain defects, and some contain deliberate 00016 coding mistakes that were included for educational reasons. 00017 You are responsible for determining if and how the Example Files 00018 are to be used. 00019 00020 */ 00021 #include "defs.h" 00022 #include "SimpleSem.h" 00023 #include <sys/sem.h> 00024 /*[SimpleSemOpen]*/ 00025 struct SimpleSem *SimpleSemOpen(const char *name) 00026 { 00027 struct SimpleSem *sem = NULL; 00028 key_t key; 00029 union semun { 00030 int val; 00031 struct semid_ds *buf; 00032 unsigned short *array; 00033 } arg; 00034 struct sembuf sop; 00035 00036 (void)close(open(name, O_WRONLY | O_CREAT, 0)); 00037 ec_neg1( key = ftok(name, 1) ) 00038 ec_null( sem = malloc(sizeof(struct SimpleSem)) ) 00039 if ((sem->sm.sm_semid = semget(key, 1, 00040 PERM_FILE | IPC_CREAT | IPC_EXCL)) != -1) { 00041 arg.val = 0; 00042 ec_neg1( semctl(sem->sm.sm_semid, 0, SETVAL, arg) ) 00043 sop.sem_num = 0; 00044 sop.sem_op = 0; 00045 sop.sem_flg = 0; 00046 ec_neg1( semop(sem->sm.sm_semid, &sop, 1) ) 00047 } 00048 else { 00049 if (errno == EEXIST) { 00050 while (true) 00051 if ((sem->sm.sm_semid = semget(key, 1, PERM_FILE)) == -1) { 00052 if (errno == ENOENT) { 00053 sleep(1); 00054 continue; 00055 } 00056 else 00057 EC_FAIL 00058 } 00059 else 00060 break; 00061 #ifndef FREEBSD // bug -- otime not set 00062 while (true) { 00063 struct semid_ds buf; 00064 00065 arg.buf = &buf; 00066 ec_neg1( semctl(sem->sm.sm_semid, 0, IPC_STAT, arg) ) 00067 if (buf.sem_otime == 0 && false) { 00068 sleep(1); 00069 continue; 00070 } 00071 else 00072 break; 00073 } 00074 #endif 00075 } 00076 else 00077 EC_FAIL 00078 } 00079 return sem; 00080 00081 EC_CLEANUP_BGN 00082 free(sem); 00083 return NULL; 00084 EC_CLEANUP_END 00085 } 00086 /*[SimpleSemPost]*/ 00087 bool SimpleSemPost(struct SimpleSem *sem) 00088 { 00089 struct sembuf sop; 00090 00091 sop.sem_num = 0; 00092 sop.sem_op = 1; 00093 sop.sem_flg = 0; 00094 ec_neg1( semop(sem->sm.sm_semid, &sop, 1) ) 00095 return true; 00096 00097 EC_CLEANUP_BGN 00098 return false; 00099 EC_CLEANUP_END 00100 } 00101 /*[SimpleSemWait]*/ 00102 bool SimpleSemWait(struct SimpleSem *sem) 00103 { 00104 struct sembuf sop; 00105 00106 sop.sem_num = 0; 00107 sop.sem_op = -1; 00108 sop.sem_flg = 0; 00109 ec_neg1( semop(sem->sm.sm_semid, &sop, 1) ) 00110 return true; 00111 00112 EC_CLEANUP_BGN 00113 return false; 00114 EC_CLEANUP_END 00115 } 00116 /*[SimpleSemClose]*/ 00117 bool SimpleSemClose(struct SimpleSem *sem) 00118 { 00119 free(sem); 00120 return true; 00121 } 00122 /*[SimpleSemRemove]*/ 00123 bool SimpleSemRemove(const char *name) 00124 { 00125 key_t key; 00126 int semid; 00127 00128 if ((key = ftok(name, 1)) == -1) { 00129 if (errno != ENOENT) 00130 EC_FAIL 00131 } 00132 else { 00133 if ((semid = semget(key, 1, PERM_FILE)) == -1) { 00134 if (errno != ENOENT) 00135 EC_FAIL 00136 } 00137 else 00138 ec_neg1( semctl(semid, 0, IPC_RMID) ) 00139 } 00140 return true; 00141 00142 EC_CLEANUP_BGN 00143 return false; 00144 EC_CLEANUP_END 00145 } 00146 /*[]*/