mut_tas.c

Go to the documentation of this file.
00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996, 1997, 1998, 1999, 2000
00005  *      Sleepycat Software.  All rights reserved.
00006  */
00007 
00008 #include "config.h"
00009 
00010 #ifdef HAVE_MUTEX_TAS
00011 
00012 #ifndef lint
00013 static const char revid[] = "$Id: mut__tas_8c-source.html,v 1.1 2008/06/08 10:20:55 sebdiaz Exp $";
00014 #endif /* not lint */
00015 
00016 #ifndef NO_SYSTEM_INCLUDES
00017 #include <sys/types.h>
00018 
00019 #include <errno.h>
00020 #include <stdlib.h>
00021 #include <string.h>
00022 #include <unistd.h>
00023 #endif
00024 
00025 #include "db_int.h"
00026 
00027 #ifdef HAVE_MUTEX_68K_GCC_ASSEMBLY
00028 #include "68K.gcc"
00029 #endif
00030 #ifdef HAVE_MUTEX_ALPHA_GCC_ASSEMBLY
00031 #include "alpha.gcc"
00032 #endif
00033 #ifdef HAVE_MUTEX_HPPA_GCC_ASSEMBLY
00034 #include "parisc.gcc"
00035 #endif
00036 #ifdef HAVE_MUTEX_IA64_GCC_ASSEMBLY
00037 #include "ia64.gcc"
00038 #endif
00039 #ifdef HAVE_MUTEX_SCO_X86_CC_ASSEMBLY
00040 #include "sco.cc"
00041 #endif
00042 #ifdef HAVE_MUTEX_SPARC_GCC_ASSEMBLY
00043 #include "sparc.gcc"
00044 #endif
00045 #ifdef HAVE_MUTEX_X86_GCC_ASSEMBLY
00046 #include "x86.gcc"
00047 #endif
00048 
00049 #ifdef DIAGNOSTIC
00050 #undef  MSG1
00051 #define MSG1            "mutex_lock: ERROR: lock currently in use: pid: %lu.\n"
00052 #undef  MSG2
00053 #define MSG2            "mutex_unlock: ERROR: lock already unlocked\n"
00054 #ifndef STDERR_FILENO
00055 #define STDERR_FILENO   2
00056 #endif
00057 #endif
00058 
00059 /*
00060  * CDB___db_tas_mutex_init --
00061  *      Initialize a MUTEX.
00062  *
00063  * PUBLIC: int CDB___db_tas_mutex_init __P((DB_ENV *, MUTEX *, u_int32_t));
00064  */
00065 int
00066 CDB___db_tas_mutex_init(dbenv, mutexp, flags)
00067         DB_ENV *dbenv;
00068         MUTEX *mutexp;
00069         u_int32_t flags;
00070 {
00071         /* Check alignment. */
00072         DB_ASSERT(((db_alignp_t)mutexp & (MUTEX_ALIGN - 1)) == 0);
00073 
00074         memset(mutexp, 0, sizeof(*mutexp));
00075 
00076         /*
00077          * If this is a thread lock or the process has told us that there are
00078          * no other processes in the environment, use thread-only locks, they
00079          * are faster in some cases.
00080          *
00081          * This is where we decide to ignore locks we don't need to set -- if
00082          * the application isn't threaded, there aren't any threads to block.
00083          */
00084         if (LF_ISSET(MUTEX_THREAD) || F_ISSET(dbenv, DB_ENV_PRIVATE)) {
00085                 if (!F_ISSET(dbenv, DB_ENV_THREAD)) {
00086                         F_SET(mutexp, MUTEX_IGNORE);
00087                         return (0);
00088                 }
00089                 F_SET(mutexp, MUTEX_THREAD);
00090         }
00091 
00092         /* Initialize the lock. */
00093         if (MUTEX_INIT(&mutexp->tas))
00094                 return (CDB___os_get_errno());
00095 
00096         mutexp->spins = CDB___os_spin();
00097 
00098         return (0);
00099 }
00100 
00101 /*
00102  * CDB___db_tas_mutex_lock
00103  *      Lock on a mutex, logically blocking if necessary.
00104  *
00105  * PUBLIC: int CDB___db_tas_mutex_lock __P((MUTEX *));
00106  */
00107 int
00108 CDB___db_tas_mutex_lock(mutexp)
00109         MUTEX *mutexp;
00110 {
00111         u_long ms;
00112         int nspins;
00113 
00114         if (!DB_GLOBAL(db_mutexlocks) || F_ISSET(mutexp, MUTEX_IGNORE))
00115                 return (0);
00116 
00117         ms = 1;
00118 
00119 loop:   /* Attempt to acquire the resource for N spins. */
00120         for (nspins = mutexp->spins; nspins > 0; --nspins) {
00121 #ifdef HAVE_MUTEX_HPPA_MSEM_INIT
00122 relock:
00123 #endif
00124                 if (!MUTEX_SET(&mutexp->tas))
00125                         continue;
00126 #ifdef HAVE_MUTEX_HPPA_MSEM_INIT
00127                 /* 
00128                  * HP semaphores are unlocked automatically when a holding
00129                  * process exits.  If the mutex appears to be locked
00130                  * (mutexp->locked != 0) but we got here, assume this has
00131                  * happened.  Stick our own pid into mutexp->locked and
00132                  * lock again.  (The default state of the mutexes used to
00133                  * block in __lock_get_internal is locked, so exiting with
00134                  * a locked mutex is reasonable behavior for a process that
00135                  * happened to initialize or use one of them.)
00136                  */
00137                 if (mutexp->locked != 0) {
00138                         mutexp->locked = (u_int32_t)getpid();
00139                         goto relock;
00140                 }
00141                 /* 
00142                  * If we make it here, locked == 0, the diagnostic won't fire,
00143                  * and we were really unlocked by someone calling the
00144                  * DB mutex unlock function.
00145                  */
00146 #endif
00147 #ifdef DIAGNOSTIC
00148                 if (mutexp->locked != 0) {
00149                         char msgbuf[128];
00150                         (void)snprintf(msgbuf,
00151                             sizeof(msgbuf), MSG1, (u_long)mutexp->locked);
00152                         (void)write(STDERR_FILENO, msgbuf, strlen(msgbuf));
00153                 }
00154 #endif
00155 #if defined(DIAGNOSTIC) || defined(HAVE_MUTEX_HPPA_MSEM_INIT)
00156                 mutexp->locked = (u_int32_t)getpid();
00157 #endif
00158                 if (ms == 1)
00159                         ++mutexp->mutex_set_nowait;
00160                 else
00161                         ++mutexp->mutex_set_wait;
00162                 return (0);
00163         }
00164 
00165         /* Yield the processor; wait 1ms initially, up to 1 second. */
00166         CDB___os_yield(NULL, ms * USEC_PER_MS);
00167         if ((ms <<= 1) > MS_PER_SEC)
00168                 ms = MS_PER_SEC;
00169 
00170         goto loop;
00171 }
00172 
00173 /*
00174  * CDB___db_tas_mutex_unlock --
00175  *      Release a lock.
00176  *
00177  * PUBLIC: int CDB___db_tas_mutex_unlock __P((MUTEX *));
00178  */
00179 int
00180 CDB___db_tas_mutex_unlock(mutexp)
00181         MUTEX *mutexp;
00182 {
00183         if (!DB_GLOBAL(db_mutexlocks) || F_ISSET(mutexp, MUTEX_IGNORE))
00184                 return (0);
00185 
00186 #ifdef DIAGNOSTIC
00187         if (!mutexp->locked)
00188                 (void)write(STDERR_FILENO, MSG2, sizeof(MSG2) - 1);
00189 #endif
00190 #if defined(DIAGNOSTIC) || defined(HAVE_MUTEX_HPPA_MSEM_INIT)
00191         mutexp->locked = 0;
00192 #endif
00193 
00194         MUTEX_UNSET(&mutexp->tas);
00195 
00196         return (0);
00197 }
00198 #endif /* HAVE_MUTEX_TAS */

Generated on Sun Jun 8 10:56:38 2008 for GNUmifluz by  doxygen 1.5.5