locking_test.c

00001 /* $Id$ */
00002 /*
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  *
00006  * This file is part of ser, a free SIP server.
00007  *
00008  * ser is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * For a license to use the ser software under conditions
00014  * other than those described here, or to purchase support for this
00015  * software, please contact iptel.org by e-mail at the following addresses:
00016  *    info@iptel.org
00017  *
00018  * ser is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU General Public License 
00024  * along with this program; if not, write to the Free Software 
00025  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00026  */
00027 
00028 
00029 
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <errno.h>
00033 #include <string.h>
00034 #include <ctype.h>
00035 #include <unistd.h>
00036 #include <sys/types.h>
00037 #include <fcntl.h>
00038 
00039 #ifdef FLOCK
00040 #include <sys/file.h>
00041 
00042 static int lock_fd;
00043 #endif
00044 
00045 #ifdef POSIX_SEM
00046 #include <semaphore.h>
00047 
00048 static sem_t sem;
00049 #endif
00050 
00051 #ifdef PTHREAD_MUTEX
00052 #include <pthread.h>
00053 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
00054 #endif
00055 
00056 #ifdef FAST_LOCK
00057 #include "../../fastlock.h"
00058 fl_lock_t lock;
00059 #endif
00060 
00061 #ifdef FUTEX
00062 #define USE_FUTEX
00063 #include "../../futexlock.h"
00064 futex_lock_t lock;
00065 #endif
00066 
00067 #ifdef SYSV_SEM
00068 #include <sys/ipc.h>
00069 #include <sys/sem.h>
00070 
00071 
00072 #if (defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)) || \
00073         defined(__FreeBSD__)
00074         /* union semun is defined by including <sys/sem.h> */
00075 #else
00076         /* according to X/OPEN we have to define it ourselves */
00077         union semun {
00078                 int val;                    /* value for SETVAL */
00079                 struct semid_ds *buf;       /* buffer for IPC_STAT, IPC_SET */
00080                 unsigned short int *array;  /* array for GETALL, SETALL */
00081                 struct seminfo *__buf;      /* buffer for IPC_INFO */
00082         };
00083 #endif
00084 
00085 static int semid=-1;
00086 
00087 #endif
00088 
00089 
00090 #ifdef NO_LOCK
00091         #define LOCK()
00092         #define UNLOCK()
00093 #elif defined SYSV_SEM
00094         #define LOCK() \
00095         {\
00096                 struct sembuf sop; \
00097                 sop.sem_num=0; \
00098                 sop.sem_op=-1; /*down*/ \
00099                 sop.sem_flg=0 /*SEM_UNDO*/; \
00100                 semop(semid, &sop, 1); \
00101         }
00102 
00103         #define UNLOCK()        \
00104         {\
00105                 struct sembuf sop;\
00106                 sop.sem_num=0;\
00107                 sop.sem_op=1; /*up*/\
00108                 sop.sem_flg=0 /*SEM_UNDO*/;\
00109                 semop(semid, &sop, 1);\
00110         }
00111 #elif defined FLOCK
00112 
00113         #define LOCK() \
00114                 flock(lock_fd, LOCK_EX)
00115         #define  UNLOCK() \
00116                 flock(lock_fd, LOCK_UN)
00117 #elif defined POSIX_SEM
00118         #define LOCK() \
00119                 sem_wait(&sem)
00120         #define UNLOCK() \
00121                 sem_post(&sem);
00122 #elif defined PTHREAD_MUTEX
00123         #define LOCK() \
00124                 pthread_mutex_lock(&mutex)
00125         #define UNLOCK() \
00126                 pthread_mutex_unlock(&mutex)
00127 #elif defined FAST_LOCK
00128         #define LOCK() \
00129                 get_lock(&lock)
00130         #define UNLOCK() \
00131                 release_lock(&lock)
00132 #elif defined FUTEX
00133         #define LOCK() \
00134                 futex_get(&lock)
00135         #define UNLOCK() \
00136                 futex_release(&lock)
00137 #endif
00138 
00139 
00140 
00141 
00142 static char *id="$Id$";
00143 static char *version="locking_test 0.1-"
00144 #ifdef NO_LOCK
00145  "nolock"
00146 #elif defined SYSV_SEM
00147  "sysv_sem"
00148 #elif defined FLOCK
00149  "flock"
00150 #elif defined POSIX_SEM
00151  "posix_sem"
00152 #elif defined PTHREAD_MUTEX
00153  "pthread_mutex"
00154 #elif defined FAST_LOCK
00155  "fast_lock"
00156 #elif defined FUTEX
00157  "futex"
00158 #endif
00159 ;
00160 
00161 static char* help_msg="\
00162 Usage: locking_test -n address [-c count] [-v]\n\
00163 Options:\n\
00164     -c count      how many times to try lock/unlock \n\
00165     -v            increase verbosity level\n\
00166     -V            version number\n\
00167     -h            this help message\n\
00168 ";
00169 
00170 
00171 
00172 int main (int argc, char** argv)
00173 {
00174         int c;
00175         int r;
00176         char *tmp;
00177         
00178         int count;
00179         int verbose;
00180         char *address;
00181 #ifdef SYSV_SEM
00182         union semun su;
00183 #endif
00184         
00185         /* init */
00186         count=0;
00187         verbose=0;
00188         address=0;
00189 
00190 
00191 
00192         opterr=0;
00193         while ((c=getopt(argc,argv, "c:vhV"))!=-1){
00194                 switch(c){
00195                         case 'v':
00196                                 verbose++;
00197                                 break;
00198                         case 'c':
00199                                 count=strtol(optarg, &tmp, 10);
00200                                 if ((tmp==0)||(*tmp)){
00201                                         fprintf(stderr, "bad count: -c %s\n", optarg);
00202                                         goto error;
00203                                 }
00204                                 break;
00205                         case 'V':
00206                                 printf("version: %s\n", version);
00207                                 printf("%s\n",id);
00208                                 exit(0);
00209                                 break;
00210                         case 'h':
00211                                 printf("version: %s\n", version);
00212                                 printf("%s", help_msg);
00213                                 exit(0);
00214                                 break;
00215                         case '?':
00216                                 if (isprint(optopt))
00217                                         fprintf(stderr, "Unknown option `-%c´\n", optopt);
00218                                 else
00219                                         fprintf(stderr, "Unknown character `\\x%x´\n", optopt);
00220                                 goto error;
00221                         case ':':
00222                                 fprintf(stderr, "Option `-%c´ requires an argument.\n",
00223                                                 optopt);
00224                                 goto error;
00225                                 break;
00226                         default:
00227                                         abort();
00228                 }
00229         }
00230 
00231         
00232         /* check if all the required params are present */
00233         if(count==0){
00234                 fprintf(stderr, "Missing count (-c number)\n");
00235                 exit(-1);
00236         }else if(count<0){
00237                 fprintf(stderr, "Invalid count (-c %d)\n", count);
00238                 exit(-1);
00239         }
00240 
00241 
00242 #ifdef SYSV_SEM
00243         /*init*/
00244         puts("Initializing SYS V semaphores\n");
00245         semid=semget(IPC_PRIVATE,1,0700);
00246         if(semid==-1){
00247                 fprintf(stderr, "ERROR: could not init semaphore: %s\n",
00248                                 strerror(errno));
00249                 goto error;
00250         }
00251         /*set init value to 1 (mutex)*/
00252         su.val=1;
00253         if (semctl(semid, 0, SETVAL, su)==-1){
00254                 fprintf(stderr, "ERROR: could not set initial semaphore value: %s\n",
00255                                 strerror(errno));
00256                 semctl(semid, 0, IPC_RMID, (union semun)0);
00257                 goto error;
00258         }
00259 #elif defined FLOCK
00260         puts("Initializing flock\n");
00261         lock_fd=open("/dev/zero", O_RDONLY);
00262         if (lock_fd==-1){
00263                 fprintf(stderr, "ERROR: could not open file: %s\n", strerror(errno));
00264                 goto error;
00265         }
00266 #elif defined POSIX_SEM
00267         puts("Initializing semaphores\n");
00268         if (sem_init(&sem, 0, 1)<0){
00269                 fprintf(stderr, "ERROR: could not initialize semaphore: %s\n",
00270                                 strerror(errno));
00271                 goto error;
00272         }
00273 #elif defined PTHREAD_MUTEX
00274         puts("Initializing mutex -already initialized (statically)\n");
00275         /*pthread_mutext_init(&mutex, 0 );*/
00276 #elif defined FAST_LOCK
00277         puts("Initializing fast lock\n");
00278         init_lock(lock);
00279 #elif defined FUTEX
00280         puts("Initializing futex lock\n");
00281         futex_init(&lock);
00282 #endif
00283 
00284 
00285         /*  loop */
00286         for (r=0; r<count; r++){
00287                 LOCK();
00288                 if ((verbose>1)&&(r%1000))  putchar('.');
00289                 UNLOCK();
00290         }
00291 
00292         printf("%d loops\n", count);
00293 
00294 #ifdef SYSV_SEM
00295         semctl(semid, 0, IPC_RMID, (union semun)0);
00296 #elif defined LIN_SEM
00297         sem_destroy(&sem);
00298 #endif
00299 
00300         exit(0);
00301 
00302 error:
00303         exit(-1);
00304 }