semlib.cc

00001 /* 
00002    EyeDB Object Database Management System
00003    Copyright (C) 1994-2008 SYSRA
00004    
00005    EyeDB is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009    
00010    EyeDB is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014    
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with this library; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
00018 */
00019 
00020 /*
00021    Author: Eric Viara <viara@sysra.com>
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 /* WARNING!!!!!!!!!!!!!!!! */
00040 /*#define SEM_UNDO 0*/
00041 
00042 //#define SECURE_LOCK
00043 
00044 /*#define TRACE*/
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     /* mind: permission! */
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     /* mind: permission! */
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 }

Generated on Mon Dec 22 18:16:07 2008 for eyedb by  doxygen 1.5.3