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 <stdlib.h>
00016 #include <string.h>
00017 #endif
00018
00019 #include "db_int.h"
00020
00021
00022
00023
00024 #define LOAD_ACTUAL_MUTEX_CODE
00025 #include "dbinc/mutex_int.h"
00026
00027
00028
00029
00030
00031
00032
00033 int
00034 __db_tas_mutex_init(dbenv, mutex, flags)
00035 DB_ENV *dbenv;
00036 db_mutex_t mutex;
00037 u_int32_t flags;
00038 {
00039 DB_MUTEX *mutexp;
00040 DB_MUTEXMGR *mtxmgr;
00041 DB_MUTEXREGION *mtxregion;
00042 int ret;
00043
00044 COMPQUIET(flags, 0);
00045
00046 mtxmgr = dbenv->mutex_handle;
00047 mtxregion = mtxmgr->reginfo.primary;
00048 mutexp = MUTEXP_SET(mutex);
00049
00050
00051 if (((uintptr_t)mutexp & (dbenv->mutex_align - 1)) != 0) {
00052 __db_err(dbenv, "TAS: mutex not appropriately aligned");
00053 return (EINVAL);
00054 }
00055
00056 if (MUTEX_INIT(&mutexp->tas)) {
00057 ret = __os_get_errno();
00058 __db_err(dbenv,
00059 "TAS: mutex initialize: %s", db_strerror(ret));
00060 return (ret);
00061 }
00062 return (0);
00063 }
00064
00065
00066
00067
00068
00069
00070
00071 int
00072 __db_tas_mutex_lock(dbenv, mutex)
00073 DB_ENV *dbenv;
00074 db_mutex_t mutex;
00075 {
00076 DB_MUTEX *mutexp;
00077 DB_MUTEXMGR *mtxmgr;
00078 DB_MUTEXREGION *mtxregion;
00079 u_int32_t nspins;
00080 u_long ms, max_ms;
00081
00082 if (!MUTEX_ON(dbenv) || F_ISSET(dbenv, DB_ENV_NOLOCKING))
00083 return (0);
00084
00085 mtxmgr = dbenv->mutex_handle;
00086 mtxregion = mtxmgr->reginfo.primary;
00087 mutexp = MUTEXP_SET(mutex);
00088
00089 #ifdef HAVE_STATISTICS
00090 if (F_ISSET(mutexp, DB_MUTEX_LOCKED))
00091 ++mutexp->mutex_set_wait;
00092 else
00093 ++mutexp->mutex_set_nowait;
00094 #endif
00095
00096
00097
00098
00099
00100
00101 ms = 1;
00102 max_ms = F_ISSET(mutexp, DB_MUTEX_LOGICAL_LOCK) ? 10 : 25;
00103
00104 loop:
00105 for (nspins =
00106 mtxregion->stat.st_mutex_tas_spins; nspins > 0; --nspins) {
00107 #ifdef HAVE_MUTEX_HPPA_MSEM_INIT
00108 relock:
00109 #endif
00110 #ifdef HAVE_MUTEX_S390_CC_ASSEMBLY
00111 tsl_t zero = 0;
00112 #endif
00113
00114
00115
00116
00117 if (F_ISSET(mutexp, DB_MUTEX_LOCKED) ||
00118 !MUTEX_SET(&mutexp->tas)) {
00119
00120
00121
00122
00123 #ifdef MUTEX_PAUSE
00124 MUTEX_PAUSE
00125 #endif
00126 continue;
00127 }
00128
00129 #ifdef HAVE_MUTEX_HPPA_MSEM_INIT
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 if (F_ISSET(mutexp, DB_MUTEX_LOCKED)) {
00141 F_SET(mutexp, DB_MUTEX_LOCKED);
00142 dbenv->thread_id(dbenv, &mutexp->pid, &mutexp->tid);
00143 CHECK_MTX_THREAD(dbenv, mutexp);
00144 goto relock;
00145 }
00146
00147
00148
00149
00150
00151 #endif
00152 #ifdef DIAGNOSTIC
00153 if (F_ISSET(mutexp, DB_MUTEX_LOCKED)) {
00154 char buf[DB_THREADID_STRLEN];
00155 __db_err(dbenv,
00156 "TAS lock failed: lock currently in use: ID: %s",
00157 dbenv->thread_id_string(dbenv,
00158 mutexp->pid, mutexp->tid, buf));
00159 return (__db_panic(dbenv, EACCES));
00160 }
00161 #endif
00162 F_SET(mutexp, DB_MUTEX_LOCKED);
00163 dbenv->thread_id(dbenv, &mutexp->pid, &mutexp->tid);
00164 CHECK_MTX_THREAD(dbenv, mutexp);
00165
00166 #ifdef DIAGNOSTIC
00167
00168
00169
00170
00171 if (F_ISSET(dbenv, DB_ENV_YIELDCPU))
00172 __os_yield(NULL, 1);
00173 #endif
00174 return (0);
00175 }
00176
00177
00178
00179
00180 __os_yield(NULL, ms * USEC_PER_MS);
00181 if ((ms <<= 1) > max_ms)
00182 ms = max_ms;
00183
00184
00185
00186
00187
00188
00189
00190 PANIC_CHECK(dbenv);
00191
00192 goto loop;
00193 }
00194
00195
00196
00197
00198
00199
00200
00201 int
00202 __db_tas_mutex_unlock(dbenv, mutex)
00203 DB_ENV *dbenv;
00204 db_mutex_t mutex;
00205 {
00206 DB_MUTEX *mutexp;
00207 DB_MUTEXMGR *mtxmgr;
00208 DB_MUTEXREGION *mtxregion;
00209
00210 if (!MUTEX_ON(dbenv) || F_ISSET(dbenv, DB_ENV_NOLOCKING))
00211 return (0);
00212
00213 mtxmgr = dbenv->mutex_handle;
00214 mtxregion = mtxmgr->reginfo.primary;
00215 mutexp = MUTEXP_SET(mutex);
00216
00217 #ifdef DIAGNOSTIC
00218 if (!F_ISSET(mutexp, DB_MUTEX_LOCKED)) {
00219 __db_err(dbenv, "TAS unlock failed: lock already unlocked");
00220 return (__db_panic(dbenv, EACCES));
00221 }
00222 #endif
00223 F_CLR(mutexp, DB_MUTEX_LOCKED);
00224
00225 MUTEX_UNSET(&mutexp->tas);
00226
00227 return (0);
00228 }
00229
00230
00231
00232
00233
00234
00235
00236 int
00237 __db_tas_mutex_destroy(dbenv, mutex)
00238 DB_ENV *dbenv;
00239 db_mutex_t mutex;
00240 {
00241 DB_MUTEX *mutexp;
00242 DB_MUTEXMGR *mtxmgr;
00243 DB_MUTEXREGION *mtxregion;
00244
00245 if (!MUTEX_ON(dbenv))
00246 return (0);
00247
00248 mtxmgr = dbenv->mutex_handle;
00249 mtxregion = mtxmgr->reginfo.primary;
00250 mutexp = MUTEXP_SET(mutex);
00251
00252 MUTEX_DESTROY(&mutexp->tas);
00253
00254 return (0);
00255 }