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 #include <string.h>
00015 #endif
00016
00017 #include "db_int.h"
00018 #include "dbinc/db_shash.h"
00019 #include "dbinc/mutex_int.h"
00020 #include "dbinc/db_page.h"
00021 #include "dbinc/db_am.h"
00022 #include "dbinc/hash.h"
00023 #include "dbinc/lock.h"
00024 #include "dbinc/txn.h"
00025
00026 static int __env_in_api __P((DB_ENV *));
00027
00028
00029
00030
00031
00032
00033
00034 int
00035 __env_failchk_pp(dbenv, flags)
00036 DB_ENV *dbenv;
00037 u_int32_t flags;
00038 {
00039 DB_THREAD_INFO *ip;
00040 int ret;
00041
00042 PANIC_CHECK(dbenv);
00043 ENV_ILLEGAL_BEFORE_OPEN(dbenv, "DB_ENV->failchk");
00044
00045
00046
00047
00048
00049 if (!ALIVE_ON(dbenv)) {
00050 __db_err(dbenv,
00051 "DB_ENV->failchk requires DB_ENV->is_alive be configured");
00052 return (EINVAL);
00053 }
00054
00055 if (flags != 0)
00056 return (__db_ferr(dbenv, "DB_ENV->failchk", 0));
00057
00058 ENV_ENTER(dbenv, ip);
00059
00060
00061
00062
00063
00064 if ((ret = __env_in_api(dbenv)) != 0)
00065 goto err;
00066
00067 if (LOCKING_ON(dbenv) && (ret = __lock_failchk(dbenv)) != 0)
00068 goto err;
00069
00070 if (TXN_ON(dbenv) && (ret = __txn_failchk(dbenv)) != 0)
00071 goto err;
00072
00073 err: ENV_LEAVE(dbenv, ip);
00074 return (ret);
00075 }
00076
00077
00078
00079
00080
00081
00082
00083 int
00084 __env_thread_init(dbenv, created)
00085 DB_ENV *dbenv;
00086 int created;
00087 {
00088 DB_HASHTAB *htab;
00089 DB_MUTEXMGR *mtxmgr;
00090 DB_MUTEXREGION *mtxregion;
00091 REGINFO *infop;
00092 THREAD_INFO *thread;
00093 int ret;
00094
00095 mtxmgr = dbenv->mutex_handle;
00096 mtxregion = mtxmgr->reginfo.primary;
00097 infop = &mtxmgr->reginfo;
00098
00099 if (mtxregion->thread_off == INVALID_ROFF) {
00100 if (dbenv->thr_nbucket == 0) {
00101 dbenv->thr_hashtab = NULL;
00102 if (ALIVE_ON(dbenv)) {
00103 __db_err(dbenv,
00104 "is_alive method specified but no thread region allocated");
00105 return (EINVAL);
00106 }
00107 return (0);
00108 }
00109
00110 if (!created) {
00111 __db_err(dbenv,
00112 "thread table must be allocated at environment create time");
00113 return (EINVAL);
00114 }
00115
00116 if ((ret = __db_shalloc(infop,
00117 sizeof(THREAD_INFO), 0, &thread)) != 0) {
00118 __db_err(dbenv,
00119 "cannot allocate a thread status block");
00120 return (ret);
00121 }
00122 memset(thread, 0, sizeof(*thread));
00123 mtxregion->thread_off = R_OFFSET(infop, thread);
00124 thread->thr_nbucket = __db_tablesize(dbenv->thr_nbucket);
00125 if ((ret = __db_shalloc(infop,
00126 thread->thr_nbucket * sizeof(DB_HASHTAB), 0, &htab)) != 0)
00127 return (ret);
00128 thread->thr_hashoff = R_OFFSET(infop, htab);
00129 __db_hashinit(htab, thread->thr_nbucket);
00130 thread->thr_max = dbenv->thr_max;
00131 } else {
00132 thread = R_ADDR(infop, mtxregion->thread_off);
00133 htab = R_ADDR(infop, thread->thr_hashoff);
00134 }
00135
00136 dbenv->thr_hashtab = htab;
00137 dbenv->thr_nbucket = thread->thr_nbucket;
00138 dbenv->thr_max = thread->thr_max;
00139 return (0);
00140 }
00141
00142
00143
00144
00145
00146 static int
00147 __env_in_api(dbenv)
00148 DB_ENV *dbenv;
00149 {
00150 DB_HASHTAB *htab;
00151 DB_MUTEXMGR *mtxmgr;
00152 DB_MUTEXREGION *mtxregion;
00153 DB_THREAD_INFO *ip;
00154 REGINFO *infop;
00155 THREAD_INFO *thread;
00156 u_int32_t i;
00157
00158 if ((htab = dbenv->thr_hashtab) == NULL)
00159 return (EINVAL);
00160
00161 mtxmgr = dbenv->mutex_handle;
00162 mtxregion = mtxmgr->reginfo.primary;
00163 infop = &mtxmgr->reginfo;
00164 thread = R_ADDR(infop, mtxregion->thread_off);
00165
00166 for (i = 0; i < dbenv->thr_nbucket; i++)
00167 SH_TAILQ_FOREACH(ip, &htab[i], dbth_links, __db_thread_info) {
00168 if (ip->dbth_state == THREAD_SLOT_NOT_IN_USE ||
00169 (ip->dbth_state == THREAD_OUT &&
00170 thread->thr_count < thread->thr_max))
00171 continue;
00172 if (dbenv->is_alive(dbenv, ip->dbth_pid, ip->dbth_tid))
00173 continue;
00174 if (ip->dbth_state == THREAD_OUT) {
00175 ip->dbth_state = THREAD_SLOT_NOT_IN_USE;
00176 continue;
00177 }
00178 return (__db_failed(dbenv,
00179 "Thread died in Berkeley DB library",
00180 ip->dbth_pid, ip->dbth_tid));
00181 }
00182
00183 return (0);
00184 }
00185
00186 struct __db_threadid {
00187 pid_t pid;
00188 db_threadid_t tid;
00189 };
00190
00191 static int __thread_id_cmp __P((struct __db_threadid *, DB_THREAD_INFO *));
00192 static int __thread_state_cmp __P((DB_THREAD_STATE, DB_THREAD_INFO *));
00193
00194 static
00195 int __thread_id_cmp(id, ip)
00196 struct __db_threadid *id;
00197 DB_THREAD_INFO *ip;
00198 {
00199 #ifdef HAVE_INTEGRAL_THREAD_TYPE
00200 return (id->pid == ip->dbth_pid && id->tid == ip->dbth_tid);
00201 #else
00202 if (memcmp(&id->pid, &ip->dbth_pid, sizeof(id->pid)) != 0)
00203 return (0);
00204 if (memcmp(&id->tid, &ip->dbth_tid, sizeof(id->tid)) != 0)
00205 return (0);
00206 return (1);
00207 #endif
00208 }
00209
00210 static
00211 int __thread_state_cmp(state, ip)
00212 DB_THREAD_STATE state;
00213 DB_THREAD_INFO *ip;
00214 {
00215 return (ip->dbth_state == state);
00216 }
00217
00218
00219
00220
00221
00222 int
00223 __env_set_state(dbenv, ipp, state)
00224 DB_ENV *dbenv;
00225 DB_THREAD_INFO **ipp;
00226 DB_THREAD_STATE state;
00227 {
00228 DB_HASHTAB *htab;
00229 DB_MUTEXMGR *mtxmgr;
00230 DB_MUTEXREGION *mtxregion;
00231 DB_THREAD_INFO *ip;
00232 struct __db_threadid id;
00233 REGINFO *infop;
00234 THREAD_INFO *thread;
00235 int ret;
00236 u_int32_t indx;
00237
00238 htab = (DB_HASHTAB *)dbenv->thr_hashtab;
00239
00240 dbenv->thread_id(dbenv, &id.pid, &id.tid);
00241
00242
00243
00244
00245
00246 #ifdef HAVE_INTEGRAL_THREAD_TYPE
00247
00248
00249
00250
00251 indx = (u_int32_t)((uintptr_t)id.pid ^ (uintptr_t)id.tid);
00252 #else
00253 indx = __ham_func5(NULL, &id.tid, sizeof(id.tid));
00254 #endif
00255 indx %= dbenv->thr_nbucket;
00256 HASHLOOKUP(htab, indx,
00257 __db_thread_info, dbth_links, &id, ip, __thread_id_cmp);
00258 #ifdef DIAGNOSTIC
00259 if (state == THREAD_DIAGNOSTIC) {
00260 *ipp = ip;
00261 return (0);
00262 }
00263 #endif
00264
00265 ret = 0;
00266 if (ip == NULL) {
00267 mtxmgr = dbenv->mutex_handle;
00268 mtxregion = mtxmgr->reginfo.primary;
00269 infop = &mtxmgr->reginfo;
00270 thread = R_ADDR(infop, mtxregion->thread_off);
00271 MUTEX_SYSTEM_LOCK(dbenv);
00272
00273
00274
00275
00276
00277
00278
00279 if (thread->thr_count >= thread->thr_max) {
00280 HASHLOOKUP(htab, indx, __db_thread_info,
00281 dbth_links, THREAD_OUT, ip, __thread_state_cmp);
00282 while (ip != NULL &&
00283 ip->dbth_state != THREAD_SLOT_NOT_IN_USE &&
00284 (ip->dbth_state != THREAD_OUT || !ALIVE_ON(dbenv) ||
00285 dbenv->is_alive(dbenv,
00286 ip->dbth_pid, ip->dbth_tid))) {
00287 ip = SH_TAILQ_NEXT(ip,
00288 dbth_links, __db_thread_info);
00289 }
00290 if (ip != NULL)
00291 goto init;
00292 }
00293
00294 thread->thr_count++;
00295 if ((ret = __db_shalloc(infop,
00296 sizeof(DB_THREAD_INFO), 0, &ip)) == 0) {
00297 memset(ip, 0, sizeof(*ip));
00298
00299
00300
00301
00302
00303
00304 HASHINSERT(htab,
00305 indx, __db_thread_info, dbth_links, ip);
00306 init: ip->dbth_pid = id.pid;
00307 ip->dbth_tid = id.tid;
00308 ip->dbth_state = state;
00309 }
00310 MUTEX_SYSTEM_UNLOCK(dbenv);
00311 } else
00312 ip->dbth_state = state;
00313 *ipp = ip;
00314
00315 return (ret);
00316 }
00317
00318
00319
00320
00321
00322
00323
00324
00325 char *
00326 __env_thread_id_string(dbenv, pid, tid, buf)
00327 DB_ENV *dbenv;
00328 pid_t pid;
00329 db_threadid_t tid;
00330 char *buf;
00331 {
00332 #ifdef HAVE_INTEGRAL_THREAD_TYPE
00333 #ifdef UINT64_FMT
00334 char fmt[10];
00335
00336 snprintf(fmt, sizeof(fmt), "%s/%s", UINT64_FMT, UINT64_FMT);
00337 snprintf(buf,
00338 DB_THREADID_STRLEN, fmt, (u_int64_t)pid, (u_int64_t)(uintptr_t)tid);
00339 #else
00340 snprintf(buf, DB_THREADID_STRLEN, "%lu/%lu", (u_long)pid, (u_long)tid);
00341 #endif
00342 #else
00343 #ifdef UINT64_FMT
00344 char fmt[10];
00345
00346 snprintf(fmt, sizeof(fmt), "%s/TID", UINT64_FMT);
00347 snprintf(buf, DB_THREADID_STRLEN, fmt, (u_int64_t)pid);
00348 #else
00349 snprintf(buf, DB_THREADID_STRLEN, "%lu/TID", (u_long)pid);
00350 #endif
00351 #endif
00352 COMPQUIET(dbenv, NULL);
00353 COMPQUIET(*(u_int8_t *)&tid, 0);
00354
00355 return (buf);
00356 }