00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00075 #ifndef DISABLE_IPC
00076
00077 #include <stdio.h>
00078 #include <stdlib.h>
00079 #include <stdbool.h>
00080 #include <unistd.h>
00081 #include <sys/sem.h>
00082 #include "qDecoder.h"
00083 #include "qInternal.h"
00084
00095 int qSemInit(const char *keyfile, int keyid, int nsems, bool ifexistdestroy) {
00096 key_t semkey;
00097 int semid;
00098
00099
00100 if(keyfile != NULL) {
00101 semkey = ftok(keyfile, keyid);
00102 if (semkey == -1) return -1;
00103 } else {
00104 semkey = IPC_PRIVATE;
00105 }
00106
00107
00108 if ((semid = semget(semkey, nsems, IPC_CREAT | IPC_EXCL | 0666)) == -1) {
00109 if(ifexistdestroy == false) return -1;
00110
00111
00112 if((semid = qSemGetId(keyfile, keyid)) >= 0) qSemFree(semid);
00113 if ((semid = semget(semkey, nsems, IPC_CREAT | IPC_EXCL | 0666)) == -1) return -1;
00114 }
00115
00116
00117 int i;
00118 for (i = 0; i < nsems; i++) {
00119 struct sembuf sbuf;
00120
00121
00122 sbuf.sem_num = i;
00123 sbuf.sem_op = 1;
00124 sbuf.sem_flg = 0;
00125
00126
00127 if (semop(semid, &sbuf, 1) != 0) {
00128 qSemFree(semid);
00129 return -1;
00130 }
00131 }
00132
00133 return semid;
00134 }
00135
00136
00145 int qSemGetId(const char *keyfile, int keyid) {
00146 int semid;
00147
00148
00149 key_t semkey = ftok(keyfile, keyid);
00150 if (semkey == -1) return -1;
00151
00152
00153 if ((semid = semget(semkey, 0, 0)) == -1) return -1;
00154
00155 return semid;
00156 }
00157
00168 bool qSemEnter(int semid, int semno) {
00169 struct sembuf sbuf;
00170
00171
00172 sbuf.sem_num = semno;
00173 sbuf.sem_op = -1;
00174 sbuf.sem_flg = SEM_UNDO;
00175
00176
00177 if (semop(semid, &sbuf, 1) != 0) return false;
00178 return true;
00179 }
00180
00189 bool qSemEnterNowait(int semid, int semno) {
00190 struct sembuf sbuf;
00191
00192
00193 sbuf.sem_num = semno;
00194 sbuf.sem_op = -1;
00195 sbuf.sem_flg = SEM_UNDO | IPC_NOWAIT;
00196
00197
00198 if (semop(semid, &sbuf, 1) != 0) return false;
00199 return true;
00200 }
00201
00218 bool qSemEnterForce(int semid, int semno, int maxwaitms, bool *forceflag) {
00219 int wait;
00220 for(wait = 0; wait < maxwaitms; wait += 10) {
00221 if(qSemEnterNowait(semid, semno) == true) {
00222 if(forceflag != NULL) *forceflag = false;
00223 return true;
00224 }
00225 usleep(10*1000);
00226 }
00227
00228 DEBUG("force to unlock semaphore %d-%d", semid, semno);
00229 while(true) {
00230 qSemLeave(semid, semno);
00231 if(qSemEnterNowait(semid, semno) == true) break;
00232 }
00233
00234 if(forceflag != NULL) *forceflag = true;
00235 return true;
00236 }
00237
00246 bool qSemLeave(int semid, int semno) {
00247 struct sembuf sbuf;
00248
00249
00250 sbuf.sem_num = semno;
00251 sbuf.sem_op = 1;
00252 sbuf.sem_flg = SEM_UNDO;
00253
00254
00255 if (semop(semid, &sbuf, 1) != 0) return false;
00256 return true;
00257 }
00258
00267 bool qSemCheck(int semid, int semno) {
00268 if(semctl(semid, semno, GETVAL, 0) == 0) return true;
00269 return false;
00270 }
00271
00279 bool qSemFree(int semid) {
00280 if (semid < 0) return false;
00281 if (semctl(semid, 0, IPC_RMID, 0) != 0) return false;
00282 return true;
00283 }
00284
00285 #endif