00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <eyedbconfig.h>
00025
00026 #include <sys/types.h>
00027 #include <sys/ipc.h>
00028 #include <sys/sem.h>
00029 #include <sys/stat.h>
00030 #include <fcntl.h>
00031 #include <unistd.h>
00032 #include <sys/time.h>
00033 #include <signal.h>
00034 #include <errno.h>
00035 #include <stdio.h>
00036 #include <pthread.h>
00037 #include <eyedblib/semlib.h>
00038
00039
00040
00041
00042
00043
00044
00045
00046 #ifdef TRACE
00047 int semlib_trace;
00048
00049 #define RETURN(R) \
00050 if (semlib_trace) \
00051 printf("%d: semlib: returning %d\n", pthread_self(), R); \
00052 return r
00053
00054 #define PTRACE(X) if (semlib_trace) printf X
00055 #else
00056 #define RETURN(R) \
00057 return r
00058 #define PTRACE(X)
00059 #endif
00060
00061 int ut_sem_create(int key)
00062 {
00063 int r;
00064 PTRACE(("%d: ut_sem_create(%d)\n", pthread_self(), key));
00065
00066 if (ut_sem_open(key) >= 0)
00067 r = -1;
00068 else {
00069
00070 r = semget(key, 1, 0666|IPC_CREAT);
00071 }
00072 RETURN(r);
00073 }
00074
00075 int ut_sem_open(int key)
00076 {
00077 int r;
00078 PTRACE(("%d: ut_sem_open(%d)\n", pthread_self(), key));
00079 if (!key)
00080 r = -1;
00081 else
00082 r = semget(key, 1, 0);
00083 RETURN(r);
00084 }
00085
00086 int ut_sem_rm(int id)
00087 {
00088 int r;
00089 PTRACE(("%d: ut_sem_rm(%d)\n", pthread_self(), id));
00090 r = semctl(id, 0, IPC_RMID, 0);
00091 RETURN(r);
00092 }
00093
00094 int ut_sem_close(int id)
00095 {
00096 return 0;
00097 }
00098
00099 int ut_sem_wait(int id)
00100 {
00101 static struct sembuf op = {0, -1, SEM_UNDO};
00102 int r;
00103 PTRACE(("%d: ut_sem_wait(%d)\n", pthread_self(), id));
00104 r = semop(id, &op, 1);
00105 RETURN(r);
00106 }
00107
00108 int ut_sem_condwait(int id1, int id2)
00109 {
00110 int r;
00111 PTRACE(("%d: ut_sem_condwait(%d, %d)\n", pthread_self(), id1, id2));
00112 r = ut_sem_unlock(id1);
00113 if (r < 0) return r;
00114 r = ut_sem_wait(id2);
00115 if (r < 0) return r;
00116 return ut_sem_lock(id1);
00117 }
00118
00119 static void alarm_handler(int sig)
00120 {
00121 }
00122
00123 static int
00124 ut_setitimer(int msecs)
00125 {
00126 struct itimerval timer_value;
00127
00128 timer_value.it_value.tv_sec = msecs/1000;
00129 timer_value.it_value.tv_usec = (msecs - (msecs/1000)*1000)*1000;
00130 timer_value.it_interval.tv_sec = 0;
00131 timer_value.it_interval.tv_usec = 0;
00132
00133 signal(SIGALRM, alarm_handler);
00134
00135 if (setitimer(ITIMER_REAL, &timer_value, 0) < 0)
00136 return -1;
00137
00138 return 0;
00139 }
00140
00141 static int
00142 ut_unsetitimer(void)
00143 {
00144 struct itimerval timer_value;
00145
00146 signal(SIGALRM, SIG_DFL);
00147
00148 timer_value.it_value.tv_sec = 0;
00149 timer_value.it_value.tv_usec = 0;
00150 timer_value.it_interval.tv_sec = 0;
00151 timer_value.it_interval.tv_usec = 0;
00152
00153 if (setitimer(ITIMER_REAL, &timer_value, 0) < 0)
00154 return -1;
00155
00156 return 0;
00157 }
00158
00159 int ut_sem_timedwait(int id, int msecs)
00160 {
00161 static struct sembuf op = {0, -1, SEM_UNDO};
00162 int r;
00163
00164 PTRACE(("%d: ut_sem_timedwait(%d, msecs=%d)\n", pthread_self(), id, msecs));
00165 if (ut_setitimer(msecs))
00166 return -1;
00167
00168 r = semop(id, &op, 1);
00169
00170 if (r < 0 && errno == EINTR)
00171 r = ETIMEDOUT;
00172
00173 if (ut_unsetitimer())
00174 return -1;
00175
00176 RETURN(r);
00177 }
00178
00179 int ut_sem_timedcondwait(int id1, int id2, int msecs)
00180 {
00181 int tr = 0;
00182 int r;
00183 PTRACE(("%d: ut_sem_timedcondwait(%d, %d, msecs=%d)\n", pthread_self(), id1, id2, msecs));
00184 r = ut_sem_unlock(id1);
00185 if (r < 0) return r;
00186 r = ut_sem_timedwait(id2, msecs);
00187 if (r < 0) return r;
00188
00189 if (r == ETIMEDOUT)
00190 {
00191 (void)ut_sem_lock(id1);
00192 return ETIMEDOUT;
00193 }
00194
00195 return ut_sem_lock(id1);
00196 }
00197
00198 int ut_sem_signal(int id)
00199 {
00200 static struct sembuf op = {0, 1, SEM_UNDO};
00201 int r;
00202 PTRACE(("%d: ut_sem_condsignal(%d)\n", pthread_self(), id));
00203 r = semop(id, &op, 1);
00204 RETURN(r);
00205 }
00206
00207 int ut_sem_lock(int id)
00208 {
00209 #ifdef SECURE_LOCK
00210 return ut_sem_timedlock(id, 4000);
00211 #else
00212 static struct sembuf op[2] = {
00213 0, 0, 0,
00214 0, 1, SEM_UNDO
00215 };
00216 int r;
00217 PTRACE(("%d: ut_sem_lock(%d)\n", pthread_self(), id));
00218 r = semop(id, op, 2);
00219 RETURN(r);
00220 #endif
00221 }
00222
00223 int ut_sem_timedlock(int id, int msecs)
00224 {
00225 int r;
00226 static struct sembuf op[2] = {
00227 0, 0, 0,
00228 0, 1, SEM_UNDO
00229 };
00230
00231 PTRACE(("%d: ut_sem_timedlock(%d, msecs=%d)\n", pthread_self(), id, msecs));
00232
00233 if (ut_setitimer(msecs))
00234 return -1;
00235
00236 r = semop(id, op, 2);
00237
00238 if (r < 0 && errno == EINTR) {
00239 #ifdef SECURE_LOCK
00240 printf("%d: timeout on sem %d\n", id);
00241 #endif
00242 r = ETIMEDOUT;
00243 }
00244
00245 if (ut_unsetitimer())
00246 return -1;
00247
00248 RETURN(r);
00249 }
00250
00251 int ut_sem_unlock(int id)
00252 {
00253 static struct sembuf op = {0, -1, SEM_UNDO};
00254 int r;
00255 PTRACE(("%d: ut_sem_unlock(%d)\n", pthread_self(), id));
00256 r = semop(id, &op, 1);
00257 RETURN(r);
00258 }
00259
00260 int ut_sem_createSX(int key)
00261 {
00262 int r;
00263 PTRACE(("%d: ut_sem_createSX(%d)\n", pthread_self(), key));
00264 if (ut_sem_open(key) >= 0)
00265 r = -1;
00266 else
00267
00268 r = semget(key, 2, 0666|IPC_CREAT);
00269 RETURN(r);
00270 }
00271
00272 int ut_sem_openSX(int key)
00273 {
00274 int r;
00275 PTRACE(("%d: ut_sem_openSX(%d)\n", pthread_self(), key));
00276 if (!key)
00277 r = -1;
00278 else
00279 r = semget(key, 2, 0);
00280 RETURN(r);
00281 }
00282
00283 int ut_sem_lockX(int id)
00284 {
00285 static struct sembuf op[3] = {
00286 0, 0, 0,
00287 1, 0, 0,
00288 0, 1, SEM_UNDO
00289 };
00290 int r;
00291 PTRACE(("%d: ut_sem_lockX(%d)\n", pthread_self(), id));
00292 r = semop(id, op, 3);
00293 RETURN(r);
00294 }
00295
00296 int ut_sem_lockS(int id)
00297 {
00298 static struct sembuf op[2] = {
00299 0, 0, 0,
00300 1, 1, SEM_UNDO
00301 };
00302 int r;
00303 PTRACE(("%d: ut_sem_lockS(%d)\n", pthread_self(), id));
00304 r = semop(id, op, 2);
00305 RETURN(r);
00306 }
00307
00308 int ut_sem_unlockX(int id)
00309 {
00310 static struct sembuf op = {0, -1, SEM_UNDO};
00311 int r;
00312 PTRACE(("%d: ut_sem_unlockX(%d)\n", pthread_self(), id));
00313 r = semop(id, &op, 1);
00314 RETURN(r);
00315 }
00316
00317 int ut_sem_unlockS(int id)
00318 {
00319 static struct sembuf op = {1, -1, SEM_UNDO};
00320 int r;
00321 PTRACE(("%d: ut_sem_unlockS(%d)\n", pthread_self(), id));
00322 r = semop(id, &op, 1);
00323 RETURN(r);
00324 }
00325
00326 int ut_sem_get(int id)
00327 {
00328 return semctl(id, 0, GETVAL, 0);
00329 }
00330
00331 int ut_sem_set(int id, int val)
00332 {
00333 #ifdef HAVE_UNION_SEMUN_VAL
00334 union semun s;
00335 #else
00336 union semun {
00337 int val;
00338 struct semid_ds *buf;
00339 ushort *array;
00340 } s;
00341 #endif
00342
00343 s.val = val;
00344 return semctl(id, 0, SETVAL, s);
00345 }
00346
00347 #define FIRST_SEM_KEY 100
00348 #define LAST_SEM_KEY 20000
00349
00350 int ut_sem_find(int *pkey, int sx)
00351 {
00352 int key, id;
00353
00354 for (key = FIRST_SEM_KEY; key < LAST_SEM_KEY; key++)
00355 if ((id = ((*(sx ? ut_sem_createSX : ut_sem_create))(key))) >= 0) {
00356 *pkey = key;
00357 return id;
00358 }
00359
00360 *pkey = 0;
00361 return -1;
00362 }