00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "db_config.h"
00011
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014
00015 #include <string.h>
00016 #endif
00017
00018 #include "db_int.h"
00019 #include "dbinc/mutex_int.h"
00020
00021 #ifdef HAVE_MUTEX_SOLARIS_LWP
00022 #define pthread_cond_destroy(x) 0
00023 #define pthread_cond_signal _lwp_cond_signal
00024 #define pthread_cond_wait _lwp_cond_wait
00025 #define pthread_mutex_destroy(x) 0
00026 #define pthread_mutex_lock _lwp_mutex_lock
00027 #define pthread_mutex_trylock _lwp_mutex_trylock
00028 #define pthread_mutex_unlock _lwp_mutex_unlock
00029 #endif
00030 #ifdef HAVE_MUTEX_UI_THREADS
00031 #define pthread_cond_destroy(x) cond_destroy
00032 #define pthread_cond_signal cond_signal
00033 #define pthread_cond_wait cond_wait
00034 #define pthread_mutex_destroy mutex_destroy
00035 #define pthread_mutex_lock mutex_lock
00036 #define pthread_mutex_trylock mutex_trylock
00037 #define pthread_mutex_unlock mutex_unlock
00038 #endif
00039
00040 #define PTHREAD_UNLOCK_ATTEMPTS 5
00041
00042
00043
00044
00045
00046
00047 #define RET_SET(f, ret) do { \
00048 if (((ret) = (f)) == -1 && ((ret) = errno) == 0) \
00049 (ret) = EAGAIN; \
00050 } while (0)
00051
00052
00053
00054
00055
00056
00057
00058 int
00059 __db_pthread_mutex_init(dbenv, mutex, flags)
00060 DB_ENV *dbenv;
00061 db_mutex_t mutex;
00062 u_int32_t flags;
00063 {
00064 DB_MUTEX *mutexp;
00065 DB_MUTEXMGR *mtxmgr;
00066 DB_MUTEXREGION *mtxregion;
00067 int ret;
00068
00069 mtxmgr = dbenv->mutex_handle;
00070 mtxregion = mtxmgr->reginfo.primary;
00071 mutexp = MUTEXP_SET(mutex);
00072 ret = 0;
00073
00074 #ifdef HAVE_MUTEX_PTHREADS
00075 {
00076 pthread_condattr_t condattr, *condattrp = NULL;
00077 pthread_mutexattr_t mutexattr, *mutexattrp = NULL;
00078
00079 if (!LF_ISSET(DB_MUTEX_THREAD)) {
00080 RET_SET((pthread_mutexattr_init(&mutexattr)), ret);
00081 #ifndef HAVE_MUTEX_THREAD_ONLY
00082 if (ret == 0)
00083 RET_SET((pthread_mutexattr_setpshared(
00084 &mutexattr, PTHREAD_PROCESS_SHARED)), ret);
00085 #endif
00086 mutexattrp = &mutexattr;
00087 }
00088
00089 if (ret == 0)
00090 RET_SET((pthread_mutex_init(&mutexp->mutex, mutexattrp)), ret);
00091 if (mutexattrp != NULL)
00092 (void)pthread_mutexattr_destroy(mutexattrp);
00093 if (ret == 0 && LF_ISSET(DB_MUTEX_SELF_BLOCK)) {
00094 if (!LF_ISSET(DB_MUTEX_THREAD)) {
00095 RET_SET((pthread_condattr_init(&condattr)), ret);
00096 if (ret == 0) {
00097 condattrp = &condattr;
00098 #ifndef HAVE_MUTEX_THREAD_ONLY
00099 RET_SET((pthread_condattr_setpshared(
00100 &condattr, PTHREAD_PROCESS_SHARED)), ret);
00101 #endif
00102 }
00103 }
00104
00105 if (ret == 0)
00106 RET_SET(
00107 (pthread_cond_init(&mutexp->cond, condattrp)), ret);
00108
00109 F_SET(mutexp, DB_MUTEX_SELF_BLOCK);
00110 if (condattrp != NULL)
00111 (void)pthread_condattr_destroy(condattrp);
00112 }
00113
00114 }
00115 #endif
00116 #ifdef HAVE_MUTEX_SOLARIS_LWP
00117
00118
00119
00120
00121
00122
00123
00124
00125 if (LF_ISSET(DB_MUTEX_THREAD)) {
00126 static lwp_mutex_t mi = DEFAULTMUTEX;
00127
00128 mutexp->mutex = mi;
00129 } else {
00130 static lwp_mutex_t mi = SHAREDMUTEX;
00131
00132 mutexp->mutex = mi;
00133 }
00134 if (LF_ISSET(DB_MUTEX_SELF_BLOCK)) {
00135 if (LF_ISSET(DB_MUTEX_THREAD)) {
00136 static lwp_cond_t ci = DEFAULTCV;
00137
00138 mutexp->cond = ci;
00139 } else {
00140 static lwp_cond_t ci = SHAREDCV;
00141
00142 mutexp->cond = ci;
00143 }
00144 F_SET(mutexp, DB_MUTEX_SELF_BLOCK);
00145 }
00146 #endif
00147 #ifdef HAVE_MUTEX_UI_THREADS
00148 {
00149 int type;
00150
00151 type = LF_ISSET(DB_MUTEX_THREAD) ? USYNC_THREAD : USYNC_PROCESS;
00152
00153 ret = mutex_init(&mutexp->mutex, type, NULL);
00154 if (ret == 0 && LF_ISSET(DB_MUTEX_SELF_BLOCK)) {
00155 ret = cond_init(&mutexp->cond, type, NULL);
00156
00157 F_SET(mutexp, DB_MUTEX_SELF_BLOCK);
00158 }}
00159 #endif
00160
00161 if (ret != 0) {
00162 __db_err(dbenv,
00163 "unable to initialize mutex: %s", strerror(ret));
00164 }
00165 return (ret);
00166 }
00167
00168
00169
00170
00171
00172
00173
00174 int
00175 __db_pthread_mutex_lock(dbenv, mutex)
00176 DB_ENV *dbenv;
00177 db_mutex_t mutex;
00178 {
00179 DB_MUTEX *mutexp;
00180 DB_MUTEXMGR *mtxmgr;
00181 DB_MUTEXREGION *mtxregion;
00182 int i, ret;
00183
00184 if (!MUTEX_ON(dbenv) || F_ISSET(dbenv, DB_ENV_NOLOCKING))
00185 return (0);
00186
00187 mtxmgr = dbenv->mutex_handle;
00188 mtxregion = mtxmgr->reginfo.primary;
00189 mutexp = MUTEXP_SET(mutex);
00190
00191 #ifdef HAVE_STATISTICS
00192
00193
00194
00195
00196
00197
00198
00199 if (F_ISSET(mutexp, DB_MUTEX_LOCKED))
00200 ++mutexp->mutex_set_wait;
00201 else
00202 ++mutexp->mutex_set_nowait;
00203 #endif
00204
00205 RET_SET((pthread_mutex_lock(&mutexp->mutex)), ret);
00206 if (ret != 0)
00207 goto err;
00208
00209 if (F_ISSET(mutexp, DB_MUTEX_SELF_BLOCK)) {
00210 while (F_ISSET(mutexp, DB_MUTEX_LOCKED)) {
00211 RET_SET((pthread_cond_wait(
00212 &mutexp->cond, &mutexp->mutex)), ret);
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 if (ret != 0 && ret != EINTR &&
00224 #ifdef ETIME
00225 ret != ETIME &&
00226 #endif
00227 ret != ETIMEDOUT) {
00228 (void)pthread_mutex_unlock(&mutexp->mutex);
00229 goto err;
00230 }
00231 }
00232
00233 F_SET(mutexp, DB_MUTEX_LOCKED);
00234 dbenv->thread_id(dbenv, &mutexp->pid, &mutexp->tid);
00235 CHECK_MTX_THREAD(dbenv, mutexp);
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 i = PTHREAD_UNLOCK_ATTEMPTS;
00247 do {
00248 RET_SET((pthread_mutex_unlock(&mutexp->mutex)), ret);
00249 } while (ret == EFAULT && --i > 0);
00250 if (ret != 0)
00251 goto err;
00252 } else {
00253 #ifdef DIAGNOSTIC
00254 if (F_ISSET(mutexp, DB_MUTEX_LOCKED)) {
00255 char buf[DB_THREADID_STRLEN];
00256 (void)dbenv->thread_id_string(dbenv,
00257 mutexp->pid, mutexp->tid, buf);
00258 __db_err(dbenv,
00259 "pthread lock failed: lock currently in use: pid/tid: %s",
00260 buf);
00261 ret = EINVAL;
00262 goto err;
00263 }
00264 #endif
00265 F_SET(mutexp, DB_MUTEX_LOCKED);
00266 dbenv->thread_id(dbenv, &mutexp->pid, &mutexp->tid);
00267 CHECK_MTX_THREAD(dbenv, mutexp);
00268 }
00269
00270 #ifdef DIAGNOSTIC
00271
00272
00273
00274
00275 if (F_ISSET(dbenv, DB_ENV_YIELDCPU))
00276 __os_yield(NULL, 1);
00277 #endif
00278 return (0);
00279
00280 err: __db_err(dbenv, "pthread lock failed: %s", db_strerror(ret));
00281 return (__db_panic(dbenv, ret));
00282 }
00283
00284
00285
00286
00287
00288
00289
00290 int
00291 __db_pthread_mutex_unlock(dbenv, mutex)
00292 DB_ENV *dbenv;
00293 db_mutex_t mutex;
00294 {
00295 DB_MUTEX *mutexp;
00296 DB_MUTEXMGR *mtxmgr;
00297 DB_MUTEXREGION *mtxregion;
00298 int i, ret;
00299
00300 if (!MUTEX_ON(dbenv) || F_ISSET(dbenv, DB_ENV_NOLOCKING))
00301 return (0);
00302
00303 mtxmgr = dbenv->mutex_handle;
00304 mtxregion = mtxmgr->reginfo.primary;
00305 mutexp = MUTEXP_SET(mutex);
00306
00307 #ifdef DIAGNOSTIC
00308 if (!F_ISSET(mutexp, DB_MUTEX_LOCKED)) {
00309 __db_err(dbenv, "pthread unlock failed: lock already unlocked");
00310 return (__db_panic(dbenv, EACCES));
00311 }
00312 #endif
00313 if (F_ISSET(mutexp, DB_MUTEX_SELF_BLOCK)) {
00314 RET_SET((pthread_mutex_lock(&mutexp->mutex)), ret);
00315 if (ret != 0)
00316 goto err;
00317
00318 F_CLR(mutexp, DB_MUTEX_LOCKED);
00319
00320 RET_SET((pthread_cond_signal(&mutexp->cond)), ret);
00321 if (ret != 0)
00322 goto err;
00323 } else
00324 F_CLR(mutexp, DB_MUTEX_LOCKED);
00325
00326
00327 i = PTHREAD_UNLOCK_ATTEMPTS;
00328 do {
00329 RET_SET((pthread_mutex_unlock(&mutexp->mutex)), ret);
00330 } while (ret == EFAULT && --i > 0);
00331
00332 err: if (ret != 0) {
00333 __db_err(dbenv, "pthread unlock failed: %s", db_strerror(ret));
00334 return (__db_panic(dbenv, ret));
00335 }
00336 return (ret);
00337 }
00338
00339
00340
00341
00342
00343
00344
00345 int
00346 __db_pthread_mutex_destroy(dbenv, mutex)
00347 DB_ENV *dbenv;
00348 db_mutex_t mutex;
00349 {
00350 DB_MUTEX *mutexp;
00351 DB_MUTEXMGR *mtxmgr;
00352 DB_MUTEXREGION *mtxregion;
00353 int ret, t_ret;
00354
00355 if (!MUTEX_ON(dbenv))
00356 return (0);
00357
00358 mtxmgr = dbenv->mutex_handle;
00359 mtxregion = mtxmgr->reginfo.primary;
00360 mutexp = MUTEXP_SET(mutex);
00361
00362 ret = 0;
00363 if (F_ISSET(mutexp, DB_MUTEX_SELF_BLOCK)) {
00364 RET_SET((pthread_cond_destroy(&mutexp->cond)), ret);
00365 if (ret != 0)
00366 __db_err(NULL,
00367 "unable to destroy cond: %s", strerror(ret));
00368 }
00369 RET_SET((pthread_mutex_destroy(&mutexp->mutex)), t_ret);
00370 if (t_ret != 0) {
00371 __db_err(NULL, "unable to destroy mutex: %s", strerror(t_ret));
00372 if (ret == 0)
00373 ret = t_ret;
00374 }
00375 return (ret);
00376 }