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
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 #ifndef _lock_ops_h
00082 #define _lock_ops_h
00083
00084 #ifdef USE_FUTEX
00085 #include "futexlock.h"
00086
00087 #endif
00088
00089
00090 #ifdef USE_FUTEX
00091
00092 typedef futex_lock_t gen_lock_t;
00093
00094 #define lock_destroy(lock)
00095 #define lock_init(lock) futex_init(lock)
00096 #define lock_try(lock) futex_try(lock)
00097 #define lock_get(lock) futex_get(lock)
00098 #define lock_release(lock) futex_release(lock)
00099
00100
00101 #elif defined FAST_LOCK
00102 #include "fastlock.h"
00103
00104 typedef fl_lock_t gen_lock_t;
00105
00106
00107 #define lock_destroy(lock)
00108
00109 inline static gen_lock_t* lock_init(gen_lock_t* lock)
00110 {
00111 init_lock(*lock);
00112 return lock;
00113 }
00114
00115 #define lock_try(lock) try_lock(lock)
00116 #define lock_get(lock) get_lock(lock)
00117 #define lock_release(lock) release_lock(lock)
00118
00119
00120 #elif defined USE_PTHREAD_MUTEX
00121 #include <pthread.h>
00122
00123 typedef pthread_mutex_t gen_lock_t;
00124
00125 #define lock_destroy(lock)
00126
00127 inline static gen_lock_t* lock_init(gen_lock_t* lock)
00128 {
00129 if (pthread_mutex_init(lock, 0)==0) return lock;
00130 else return 0;
00131 }
00132
00133 #define lock_try(lock) pthread_mutex_trylock(lock)
00134 #define lock_get(lock) pthread_mutex_lock(lock)
00135 #define lock_release(lock) pthread_mutex_unlock(lock)
00136
00137
00138
00139 #elif defined USE_POSIX_SEM
00140 #include <semaphore.h>
00141
00142 typedef sem_t gen_lock_t;
00143
00144 #define lock_destroy(lock)
00145
00146 inline static gen_lock_t* lock_init(gen_lock_t* lock)
00147 {
00148 if (sem_init(lock, 1, 1)<0) return 0;
00149 return lock;
00150 }
00151
00152 #define lock_try(lock) sem_trywait(lock)
00153 #define lock_get(lock) sem_wait(lock)
00154 #define lock_release(lock) sem_post(lock)
00155
00156
00157 #elif defined USE_SYSV_SEM
00158 #include <sys/ipc.h>
00159 #include <sys/sem.h>
00160
00161 #include <errno.h>
00162 #include <string.h>
00163 #include <sys/types.h>
00164 #include <unistd.h>
00165 #include "dprint.h"
00166 #include "globals.h"
00167
00168 #if ((defined(HAVE_UNION_SEMUN) || defined(__GNU_LIBRARY__) )&& !defined(_SEM_SEMUN_UNDEFINED))
00169
00170
00171 #else
00172
00173 union semun {
00174 int val;
00175 struct semid_ds *buf;
00176 unsigned short int *array;
00177 struct seminfo *__buf;
00178 };
00179 #endif
00180
00181 typedef int gen_lock_t;
00182
00183
00184
00185
00186 inline static gen_lock_t* lock_init(gen_lock_t* lock)
00187 {
00188 union semun su;
00189 int euid;
00190
00191 euid=geteuid();
00192 if (uid && uid!=euid)
00193 seteuid(uid);
00194 *lock=semget(IPC_PRIVATE, 1, 0700);
00195 if (uid && uid!=euid)
00196 seteuid(euid);
00197 if (*lock==-1) return 0;
00198 su.val=1;
00199 if (semctl(*lock, 0, SETVAL, su)==-1){
00200
00201 return 0;
00202 }
00203 return lock;
00204 }
00205
00206 inline static void lock_destroy(gen_lock_t* lock)
00207 {
00208 semctl(*lock, 0, IPC_RMID, (union semun)(int)0);
00209 }
00210
00211
00212
00213 inline static int lock_try(gen_lock_t* lock)
00214 {
00215 struct sembuf sop;
00216
00217 sop.sem_num=0;
00218 sop.sem_op=-1;
00219 sop.sem_flg=IPC_NOWAIT;
00220 tryagain:
00221 if (semop(*lock, &sop, 1)==-1){
00222 if (errno==EAGAIN){
00223 return -1;
00224 }else if (errno==EINTR){
00225 DBG("lock_get: signal received while waiting for on a mutex\n");
00226 goto tryagain;
00227 }else{
00228 LOG(L_CRIT, "ERROR: lock_get sysv: %s (%d)\n", strerror(errno),
00229 errno);
00230 return -1;
00231 }
00232 }
00233 return 0;
00234 }
00235
00236 inline static void lock_get(gen_lock_t* lock)
00237 {
00238 struct sembuf sop;
00239
00240 sop.sem_num=0;
00241 sop.sem_op=-1;
00242 sop.sem_flg=0;
00243 tryagain:
00244 if (semop(*lock, &sop, 1)==-1){
00245 if (errno==EINTR){
00246 DBG("lock_get: signal received while waiting for on a mutex\n");
00247 goto tryagain;
00248 }else{
00249 LOG(L_CRIT, "ERROR: lock_get sysv: %s (%d)\n", strerror(errno),
00250 errno);
00251 }
00252 }
00253 }
00254
00255 inline static void lock_release(gen_lock_t* lock)
00256 {
00257 struct sembuf sop;
00258
00259 sop.sem_num=0;
00260 sop.sem_op=1;
00261 sop.sem_flg=0;
00262 tryagain:
00263 if (semop(*lock, &sop, 1)==-1){
00264 if (errno==EINTR){
00265
00266 DBG("lock_release: signal received while releasing a mutex\n");
00267 goto tryagain;
00268 }else{
00269 LOG(L_CRIT, "ERROR: lock_release sysv: %s (%d)\n",
00270 strerror(errno), errno);
00271 }
00272 }
00273 }
00274
00275
00276 #else
00277 #error "no locking method selected"
00278 #endif
00279
00280
00281
00282
00283 #if defined(FAST_LOCK) || defined(USE_PTHREAD_MUTEX) || \
00284 defined(USE_POSIX_SEM) || defined(USE_FUTEX)
00285 #define GEN_LOCK_T_PREFERRED
00286 #define GEN_LOCK_T_PREFERED
00287 #define GEN_LOCK_T_UNLIMITED
00288 #define GEN_LOCK_SET_T_UNLIMITED
00289
00290 struct gen_lock_set_t_ {
00291 long size;
00292 gen_lock_t* locks;
00293 };
00294 typedef struct gen_lock_set_t_ gen_lock_set_t;
00295
00296
00297 #define lock_set_destroy(lock_set)
00298
00299 inline static gen_lock_set_t* lock_set_init(gen_lock_set_t* s)
00300 {
00301 int r;
00302 for (r=0; r<s->size; r++) if (lock_init(&s->locks[r])==0) return 0;
00303 return s;
00304 }
00305
00306
00307 #define lock_set_try(set, i) lock_try(&set->locks[i])
00308 #define lock_set_get(set, i) lock_get(&set->locks[i])
00309 #define lock_set_release(set, i) lock_release(&set->locks[i])
00310
00311 #elif defined(USE_SYSV_SEM)
00312 #undef GEN_LOCK_T_PREFERRED
00313 #undef GEN_LOCK_T_PREFERED
00314 #undef GEN_LOCK_T_UNLIMITED
00315 #undef GEN_LOCK_SET_T_UNLIMITED
00316 #define GEN_LOCK_T_LIMITED
00317 #define GEN_LOCK_SET_T_LIMITED
00318
00319 struct gen_lock_set_t_ {
00320 int size;
00321 int semid;
00322 };
00323
00324
00325 typedef struct gen_lock_set_t_ gen_lock_set_t;
00326 inline static gen_lock_set_t* lock_set_init(gen_lock_set_t* s)
00327 {
00328 union semun su;
00329 int r;
00330 int euid;
00331
00332 euid=geteuid();
00333 if (uid && uid!=euid)
00334 seteuid(uid);
00335 s->semid=semget(IPC_PRIVATE, s->size, 0700);
00336 if (uid && uid!=euid)
00337 seteuid(euid);
00338 if (s->semid==-1){
00339 LOG(L_CRIT, "ERROR: lock_set_init (SYSV): semget (..., %d, 0700)"
00340 " failed: %s\n",
00341 s->size, strerror(errno));
00342 return 0;
00343 }
00344 su.val=1;
00345 for (r=0; r<s->size; r++){
00346 if (semctl(s->semid, r, SETVAL, su)==-1){
00347 LOG(L_CRIT, "ERROR: lock_set_init (SYSV): semctl failed on sem %d"
00348 ": %s\n", r, strerror(errno));
00349 semctl(s->semid, 0, IPC_RMID, (union semun)(int)0);
00350 return 0;
00351 }
00352 }
00353 return s;
00354 }
00355
00356 inline static void lock_set_destroy(gen_lock_set_t* s)
00357 {
00358 semctl(s->semid, 0, IPC_RMID, (union semun)(int)0);
00359 }
00360
00361
00362
00363 inline static int lock_set_try(gen_lock_set_t* s, int n)
00364 {
00365 struct sembuf sop;
00366
00367 sop.sem_num=n;
00368 sop.sem_op=-1;
00369 sop.sem_flg=IPC_NOWAIT;
00370 tryagain:
00371 if (semop(s->semid, &sop, 1)==-1){
00372 if (errno==EAGAIN){
00373 return -1;
00374 }else if (errno==EINTR){
00375 DBG("lock_get: signal received while waiting for on a mutex\n");
00376 goto tryagain;
00377 }else{
00378 LOG(L_CRIT, "ERROR: lock_get sysv: %s (%d)\n", strerror(errno),
00379 errno);
00380 return -1;
00381 }
00382 }
00383 return 0;
00384 }
00385
00386
00387 inline static void lock_set_get(gen_lock_set_t* s, int n)
00388 {
00389 struct sembuf sop;
00390 sop.sem_num=n;
00391 sop.sem_op=-1;
00392 sop.sem_flg=0;
00393 tryagain:
00394 if (semop(s->semid, &sop, 1)==-1){
00395 if (errno==EINTR){
00396 DBG("lock_set_get: signal received while waiting on a mutex\n");
00397 goto tryagain;
00398 }else{
00399 LOG(L_CRIT, "ERROR: lock_set_get sysv: %s (%d)\n",
00400 strerror(errno), errno);
00401 }
00402 }
00403 }
00404
00405 inline static void lock_set_release(gen_lock_set_t* s, int n)
00406 {
00407 struct sembuf sop;
00408 sop.sem_num=n;
00409 sop.sem_op=1;
00410 sop.sem_flg=0;
00411 tryagain:
00412 if (semop(s->semid, &sop, 1)==-1){
00413 if (errno==EINTR){
00414
00415 DBG("lock_set_release: signal received while releasing mutex\n");
00416 goto tryagain;
00417 }else{
00418 LOG(L_CRIT, "ERROR: lock_set_release sysv: %s (%d)\n",
00419 strerror(errno), errno);
00420 }
00421 }
00422 }
00423 #else
00424 #error "no lock set method selected"
00425 #endif
00426
00427
00428 #endif