mut_pthread.c

Go to the documentation of this file.
00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1999, 2000
00005  *      Sleepycat Software.  All rights reserved.
00006  */
00007 
00008 #include "config.h"
00009 
00010 #ifdef HAVE_MUTEX_PTHREAD
00011 
00012 #ifndef lint
00013 static const char revid[] = "$Id: mut__pthread_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 <string.h>
00021 #include <unistd.h>
00022 #endif
00023 
00024 #include "db_int.h"
00025 
00026 #ifdef DIAGNOSTIC
00027 #undef  MSG1
00028 #define MSG1            "mutex_lock: ERROR: lock currently in use: pid: %lu.\n"
00029 #undef  MSG2
00030 #define MSG2            "mutex_unlock: ERROR: lock already unlocked\n"
00031 #ifndef STDERR_FILENO
00032 #define STDERR_FILENO   2
00033 #endif
00034 #endif
00035 
00036 #ifdef HAVE_MUTEX_SOLARIS_LWP
00037 #define pthread_cond_signal     _lwp_cond_signal
00038 #define pthread_cond_wait       _lwp_cond_wait
00039 #define pthread_mutex_lock      _lwp_mutex_lock
00040 #define pthread_mutex_trylock   _lwp_mutex_trylock
00041 #define pthread_mutex_unlock    _lwp_mutex_unlock
00042 #define pthread_self            _lwp_self
00043 #endif
00044 #ifdef HAVE_MUTEX_UI_THREADS
00045 #define pthread_cond_signal     cond_signal
00046 #define pthread_cond_wait       cond_wait
00047 #define pthread_mutex_lock      mutex_lock
00048 #define pthread_mutex_trylock   mutex_trylock
00049 #define pthread_mutex_unlock    mutex_unlock
00050 #define pthread_self            thr_self
00051 #endif
00052 
00053 /*
00054  * __db_pthread_mutex_init --
00055  *      Initialize a MUTEX.
00056  *
00057  * PUBLIC: int __db_pthread_mutex_init __P((DB_ENV *, MUTEX *, u_int32_t));
00058  */
00059 int
00060 __db_pthread_mutex_init(dbenv, mutexp, flags)
00061         DB_ENV *dbenv;
00062         MUTEX *mutexp;
00063         u_int32_t flags;
00064 {
00065         int ret;
00066 
00067         ret = 0;
00068         memset(mutexp, 0, sizeof(*mutexp));
00069 
00070         /*
00071          * If this is a thread lock or the process has told us that there are
00072          * no other processes in the environment, use thread-only locks, they
00073          * are faster in some cases.
00074          *
00075          * This is where we decide to ignore locks we don't need to set -- if
00076          * the application isn't threaded, there aren't any threads to block.
00077          */
00078         if (LF_ISSET(MUTEX_THREAD) || F_ISSET(dbenv, DB_ENV_PRIVATE)) {
00079                 if (!F_ISSET(dbenv, DB_ENV_THREAD)) {
00080                         F_SET(mutexp, MUTEX_IGNORE);
00081                         return (0);
00082                 }
00083                 F_SET(mutexp, MUTEX_THREAD);
00084         }
00085 
00086 #ifdef HAVE_MUTEX_PTHREADS
00087         {
00088         pthread_condattr_t condattr, *condattrp = NULL;
00089         pthread_mutexattr_t mutexattr, *mutexattrp = NULL;
00090 
00091         if (!F_ISSET(mutexp, MUTEX_THREAD)) {
00092                 ret = pthread_condattr_init(&condattr);
00093                 if (ret == 0)
00094                         ret = pthread_condattr_setpshared(
00095                             &condattr, PTHREAD_PROCESS_SHARED);
00096                 condattrp = &condattr;
00097 
00098                 if (ret == 0)
00099                         ret = pthread_mutexattr_init(&mutexattr);
00100                 if (ret == 0)
00101                         ret = pthread_mutexattr_setpshared(
00102                             &mutexattr, PTHREAD_PROCESS_SHARED);
00103                 mutexattrp = &mutexattr;
00104         }
00105 
00106         if (ret == 0)
00107                 ret = pthread_mutex_init(&mutexp->mutex, mutexattrp);
00108         if (mutexattrp != NULL)
00109                 pthread_mutexattr_destroy(mutexattrp);
00110         if (LF_ISSET(MUTEX_SELF_BLOCK)) {
00111                 if (ret == 0)
00112                         ret = pthread_cond_init(&mutexp->cond, condattrp);
00113 
00114                 F_SET(mutexp, MUTEX_SELF_BLOCK);
00115                 if (condattrp != NULL)
00116                         pthread_condattr_destroy(condattrp);
00117         }}
00118 #endif
00119 #ifdef HAVE_MUTEX_SOLARIS_LWP
00120         /*
00121          * XXX
00122          * Gcc complains about missing braces in the static initializations of
00123          * lwp_cond_t and lwp_mutex_t structures because the structures contain
00124          * sub-structures/unions and the Solaris include file that defines the
00125          * initialization values doesn't have surrounding braces.  There's not
00126          * much we can do.
00127          */
00128         if (F_ISSET(mutexp, MUTEX_THREAD)) {
00129                 static lwp_mutex_t mi = DEFAULTMUTEX;
00130 
00131                 mutexp->mutex = mi;
00132         } else {
00133                 static lwp_mutex_t mi = SHAREDMUTEX;
00134 
00135                 mutexp->mutex = mi;
00136         }
00137         if (LF_ISSET(MUTEX_SELF_BLOCK)) {
00138                 if (F_ISSET(mutexp, MUTEX_THREAD)) {
00139                         static lwp_cond_t ci = DEFAULTCV;
00140 
00141                         mutexp->cond = ci;
00142                 } else {
00143                         static lwp_cond_t ci = SHAREDCV;
00144 
00145                         mutexp->cond = ci;
00146                 }
00147                 F_SET(mutexp, MUTEX_SELF_BLOCK);
00148         }
00149 #endif
00150 #ifdef HAVE_MUTEX_UI_THREADS
00151         {
00152         int type;
00153 
00154         type = F_ISSET(mutexp, MUTEX_THREAD) ? USYNC_THREAD : USYNC_PROCESS;
00155 
00156         ret = mutex_init(&mutexp->mutex, type, NULL);
00157         if (ret == 0 && LF_ISSET(MUTEX_SELF_BLOCK)) {
00158                 ret = cond_init(&mutexp->cond, type, NULL);
00159 
00160                 F_SET(mutexp, MUTEX_SELF_BLOCK);
00161         }}
00162 #endif
00163 
00164         mutexp->spins = CDB___os_spin();
00165 
00166         return (ret);
00167 }
00168 
00169 /*
00170  * __db_pthread_mutex_lock
00171  *      Lock on a mutex, logically blocking if necessary.
00172  *
00173  * PUBLIC: int __db_pthread_mutex_lock __P((MUTEX *));
00174  */
00175 int
00176 __db_pthread_mutex_lock(mutexp)
00177         MUTEX *mutexp;
00178 {
00179         u_int32_t nspins;
00180         int ret, waited;
00181 
00182         if (!DB_GLOBAL(db_mutexlocks) || F_ISSET(mutexp, MUTEX_IGNORE))
00183                 return (0);
00184 
00185         /* Attempt to acquire the resource for N spins. */
00186         for (nspins = mutexp->spins; nspins > 0; --nspins)
00187                 if (pthread_mutex_trylock(&mutexp->mutex) == 0)
00188                         break;
00189 
00190         if (nspins == 0 && (ret = pthread_mutex_lock(&mutexp->mutex)) != 0)
00191                 return (ret);
00192 
00193         if (F_ISSET(mutexp, MUTEX_SELF_BLOCK)) {
00194                 for (waited = 0; mutexp->locked != 0; waited = 1) {
00195                         ret = pthread_cond_wait(&mutexp->cond, &mutexp->mutex);
00196                         /*
00197                          * !!!
00198                          * Solaris bug workaround:
00199                          * pthread_cond_wait() sometimes returns ETIME -- out
00200                          * of sheer paranoia, check both ETIME and ETIMEDOUT.
00201                          * We believe this happens when the application uses
00202                          * SIGALRM for some purpose, e.g., the C library sleep
00203                          * call, and Solaris delivers the signal to the wrong
00204                          * LWP.
00205                          */
00206                         if (ret != 0 && ret != ETIME && ret != ETIMEDOUT)
00207                                 return (ret);
00208                 }
00209 
00210                 if (waited)
00211                         ++mutexp->mutex_set_wait;
00212                 else
00213                         ++mutexp->mutex_set_nowait;
00214 
00215 #ifdef DIAGNOSTIC
00216                 mutexp->locked = (u_int32_t)pthread_self();
00217 #else
00218                 mutexp->locked = 1;
00219 #endif
00220                 if ((ret = pthread_mutex_unlock(&mutexp->mutex)) != 0)
00221                         return (ret);
00222         } else {
00223                 if (nspins == mutexp->spins)
00224                         ++mutexp->mutex_set_nowait;
00225                 else
00226                         ++mutexp->mutex_set_wait;
00227 #ifdef DIAGNOSTIC
00228                 if (mutexp->locked) {
00229                         char msgbuf[128];
00230                         (void)snprintf(msgbuf,
00231                             sizeof(msgbuf), MSG1, (u_long)mutexp->locked);
00232                         (void)write(STDERR_FILENO, msgbuf, strlen(msgbuf));
00233                 }
00234                 mutexp->locked = (u_int32_t)pthread_self();
00235 #else
00236                 mutexp->locked = 1;
00237 #endif
00238         }
00239         return (0);
00240 }
00241 
00242 /*
00243  * __db_pthread_mutex_unlock --
00244  *      Release a lock.
00245  *
00246  * PUBLIC: int __db_pthread_mutex_unlock __P((MUTEX *));
00247  */
00248 int
00249 __db_pthread_mutex_unlock(mutexp)
00250         MUTEX *mutexp;
00251 {
00252         int ret;
00253 
00254         if (!DB_GLOBAL(db_mutexlocks) || F_ISSET(mutexp, MUTEX_IGNORE))
00255                 return (0);
00256 
00257 #ifdef DIAGNOSTIC
00258         if (!mutexp->locked)
00259                 (void)write(STDERR_FILENO, MSG2, sizeof(MSG2) - 1);
00260 #endif
00261 
00262         if (F_ISSET(mutexp, MUTEX_SELF_BLOCK)) {
00263                 if ((ret = pthread_mutex_lock(&mutexp->mutex)) != 0)
00264                         return (ret);
00265 
00266                 mutexp->locked = 0;
00267 
00268                 if ((ret = pthread_mutex_unlock(&mutexp->mutex)) != 0)
00269                         return (ret);
00270 
00271                 if ((ret = pthread_cond_signal(&mutexp->cond)) != 0)
00272                         return (ret);
00273         } else {
00274                 mutexp->locked = 0;
00275 
00276                 if ((ret = pthread_mutex_unlock(&mutexp->mutex)) != 0)
00277                         return (ret);
00278         }
00279 
00280         return (0);
00281 }
00282 
00283 #endif /* HAVE_MUTEX_PTHREAD */

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