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/db_shash.h"
00020 #include "dbinc/log.h"
00021 #include "dbinc/lock.h"
00022 #include "dbinc/mp.h"
00023 #include "dbinc/mutex_int.h"
00024
00025 static int __mutex_region_init __P((DB_ENV *, DB_MUTEXMGR *));
00026 static size_t __mutex_region_size __P((DB_ENV *));
00027
00028
00029
00030
00031
00032
00033
00034 int
00035 __mutex_open(dbenv)
00036 DB_ENV *dbenv;
00037 {
00038 DB_MUTEXMGR *mtxmgr;
00039 DB_MUTEXREGION *mtxregion;
00040 db_mutex_t mutex;
00041 u_int i;
00042 int ret;
00043
00044
00045
00046
00047
00048
00049 if (dbenv->mutex_align == 0)
00050 dbenv->mutex_align = MUTEX_ALIGN;
00051 if (dbenv->mutex_tas_spins == 0)
00052 dbenv->mutex_tas_spins = __os_spin(dbenv);
00053
00054
00055
00056
00057
00058
00059
00060
00061 if (dbenv->mutex_cnt == 0)
00062 dbenv->mutex_cnt =
00063 __lock_region_mutex_count(dbenv) +
00064 __log_region_mutex_count(dbenv) +
00065 __memp_region_mutex_count(dbenv) +
00066 dbenv->mutex_inc + 500;
00067
00068
00069 if ((ret = __os_calloc(dbenv, 1, sizeof(DB_MUTEXMGR), &mtxmgr)) != 0)
00070 return (ret);
00071
00072
00073 mtxmgr->reginfo.dbenv = dbenv;
00074 mtxmgr->reginfo.type = REGION_TYPE_MUTEX;
00075 mtxmgr->reginfo.id = INVALID_REGION_ID;
00076 mtxmgr->reginfo.flags = REGION_JOIN_OK;
00077 if (F_ISSET(dbenv, DB_ENV_CREATE))
00078 F_SET(&mtxmgr->reginfo, REGION_CREATE_OK);
00079 if ((ret = __db_r_attach(dbenv,
00080 &mtxmgr->reginfo, __mutex_region_size(dbenv))) != 0)
00081 goto err;
00082
00083
00084 if (F_ISSET(&mtxmgr->reginfo, REGION_CREATE))
00085 if ((ret = __mutex_region_init(dbenv, mtxmgr)) != 0)
00086 goto err;
00087
00088
00089 mtxregion = mtxmgr->reginfo.primary =
00090 R_ADDR(&mtxmgr->reginfo, mtxmgr->reginfo.rp->primary);
00091 mtxmgr->mutex_array = R_ADDR(&mtxmgr->reginfo, mtxregion->mutex_offset);
00092
00093 dbenv->mutex_handle = mtxmgr;
00094
00095
00096 if (dbenv->mutex_iq != NULL) {
00097 DB_ASSERT(F_ISSET(&mtxmgr->reginfo, REGION_CREATE));
00098 for (i = 0; i < dbenv->mutex_iq_next; ++i) {
00099 if ((ret = __mutex_alloc_int(
00100 dbenv, 0, dbenv->mutex_iq[i].alloc_id,
00101 dbenv->mutex_iq[i].flags, &mutex)) != 0)
00102 goto err;
00103
00104
00105
00106
00107 DB_ASSERT(mutex == i + 1);
00108 }
00109 __os_free(dbenv, dbenv->mutex_iq);
00110 dbenv->mutex_iq = NULL;
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 mutex = MUTEX_INVALID;
00121 if ((ret =
00122 __mutex_alloc(dbenv, MTX_MUTEX_TEST, 0, &mutex) != 0) ||
00123 (ret = __mutex_lock(dbenv, mutex)) != 0 ||
00124 (ret = __mutex_unlock(dbenv, mutex)) != 0 ||
00125 (ret = __mutex_free(dbenv, &mutex)) != 0) {
00126 __db_err(dbenv,
00127 "Unable to acquire/release a mutex; check configuration");
00128 goto err;
00129 }
00130 }
00131
00132
00133
00134
00135
00136
00137 if ((ret = __env_thread_init(dbenv,
00138 F_ISSET(&mtxmgr->reginfo, REGION_CREATE))) != 0)
00139 goto err;
00140
00141 return (0);
00142
00143 err: dbenv->mutex_handle = NULL;
00144 if (mtxmgr->reginfo.addr != NULL)
00145 (void)__db_r_detach(dbenv, &mtxmgr->reginfo, 0);
00146
00147 __os_free(dbenv, mtxmgr);
00148 return (ret);
00149 }
00150
00151
00152
00153
00154
00155 static int
00156 __mutex_region_init(dbenv, mtxmgr)
00157 DB_ENV *dbenv;
00158 DB_MUTEXMGR *mtxmgr;
00159 {
00160 DB_MUTEXREGION *mtxregion;
00161 DB_MUTEX *mutexp;
00162 db_mutex_t i;
00163 int ret;
00164 void *mutex_array;
00165
00166 COMPQUIET(mutexp, NULL);
00167
00168 if ((ret = __db_shalloc(&mtxmgr->reginfo,
00169 sizeof(DB_MUTEXREGION), 0, &mtxmgr->reginfo.primary)) != 0) {
00170 __db_err(dbenv,
00171 "Unable to allocate memory for the mutex region");
00172 return (ret);
00173 }
00174 mtxmgr->reginfo.rp->primary =
00175 R_OFFSET(&mtxmgr->reginfo, mtxmgr->reginfo.primary);
00176 mtxregion = mtxmgr->reginfo.primary;
00177 memset(mtxregion, 0, sizeof(*mtxregion));
00178
00179 if ((ret = __mutex_alloc(
00180 dbenv, MTX_MUTEX_REGION, 0, &mtxregion->mtx_region)) != 0)
00181 return (ret);
00182
00183 mtxregion->mutex_size =
00184 (size_t)DB_ALIGN(sizeof(DB_MUTEX), dbenv->mutex_align);
00185
00186 mtxregion->stat.st_mutex_align = dbenv->mutex_align;
00187 mtxregion->stat.st_mutex_cnt = dbenv->mutex_cnt;
00188 mtxregion->stat.st_mutex_tas_spins = dbenv->mutex_tas_spins;
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 if ((ret = __db_shalloc(&mtxmgr->reginfo,
00200 (mtxregion->stat.st_mutex_cnt + 1) * mtxregion->mutex_size,
00201 mtxregion->stat.st_mutex_align, &mutex_array)) != 0) {
00202 __db_err(dbenv,
00203 "Unable to allocate memory for mutexes from the region");
00204 return (ret);
00205 }
00206
00207 mtxregion->mutex_offset = R_OFFSET(&mtxmgr->reginfo, mutex_array);
00208 mtxmgr->mutex_array = mutex_array;
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 for (i = 1; i < mtxregion->stat.st_mutex_cnt; ++i) {
00219 mutexp = MUTEXP_SET(i);
00220 mutexp->flags = 0;
00221 mutexp->mutex_next_link = i + 1;
00222 }
00223 mutexp = MUTEXP_SET(i);
00224 mutexp->flags = 0;
00225 mutexp->mutex_next_link = MUTEX_INVALID;
00226 mtxregion->mutex_next = 1;
00227 mtxregion->stat.st_mutex_free = mtxregion->stat.st_mutex_cnt;
00228 mtxregion->stat.st_mutex_inuse = mtxregion->stat.st_mutex_inuse_max = 0;
00229
00230 return (0);
00231 }
00232
00233
00234
00235
00236
00237
00238
00239 int
00240 __mutex_dbenv_refresh(dbenv)
00241 DB_ENV *dbenv;
00242 {
00243 DB_MUTEXMGR *mtxmgr;
00244 DB_MUTEXREGION *mtxregion;
00245 REGINFO *reginfo;
00246 int ret;
00247
00248 mtxmgr = dbenv->mutex_handle;
00249 reginfo = &mtxmgr->reginfo;
00250 mtxregion = mtxmgr->reginfo.primary;
00251
00252
00253
00254
00255
00256
00257 if (F_ISSET(dbenv, DB_ENV_PRIVATE)) {
00258 #ifdef HAVE_MUTEX_SYSTEM_RESOURCES
00259
00260
00261
00262
00263 __mutex_resource_return(dbenv, reginfo);
00264 #endif
00265
00266 __db_shalloc_free(
00267 reginfo, R_ADDR(reginfo, mtxregion->mutex_offset));
00268 }
00269
00270
00271 ret = __db_r_detach(dbenv, reginfo, 0);
00272
00273 __os_free(dbenv, mtxmgr);
00274
00275 dbenv->mutex_handle = NULL;
00276
00277 return (ret);
00278 }
00279
00280
00281
00282
00283
00284 static size_t
00285 __mutex_region_size(dbenv)
00286 DB_ENV *dbenv;
00287 {
00288 size_t s;
00289
00290 s = sizeof(DB_MUTEXMGR) + 1024;
00291 s += dbenv->mutex_cnt *
00292 __db_shalloc_size(sizeof(DB_MUTEX), dbenv->mutex_align);
00293
00294
00295
00296
00297 s += (dbenv->thr_max + dbenv->thr_max/4) *
00298 __db_shalloc_size(sizeof(DB_THREAD_INFO), sizeof(roff_t));
00299 s += dbenv->thr_nbucket *
00300 __db_shalloc_size(sizeof(DB_HASHTAB), sizeof(roff_t));
00301 return (s);
00302 }
00303
00304 #ifdef HAVE_MUTEX_SYSTEM_RESOURCES
00305
00306
00307
00308
00309
00310
00311 void
00312 __mutex_resource_return(dbenv, infop)
00313 DB_ENV *dbenv;
00314 REGINFO *infop;
00315 {
00316 DB_MUTEX *mutexp;
00317 DB_MUTEXMGR *mtxmgr, mtxmgr_st;
00318 DB_MUTEXREGION *mtxregion;
00319 db_mutex_t i;
00320 void *orig_handle;
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 memset(&mtxmgr_st, 0, sizeof(mtxmgr_st));
00339 mtxmgr = &mtxmgr_st;
00340 mtxmgr->reginfo = *infop;
00341 mtxregion = mtxmgr->reginfo.primary =
00342 R_ADDR(&mtxmgr->reginfo, mtxmgr->reginfo.rp->primary);
00343 mtxmgr->mutex_array = R_ADDR(&mtxmgr->reginfo, mtxregion->mutex_offset);
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 orig_handle = dbenv->mutex_handle;
00354 dbenv->mutex_handle = mtxmgr;
00355 for (i = 1; i <= mtxregion->stat.st_mutex_cnt; ++i, ++mutexp) {
00356 mutexp = MUTEXP_SET(i);
00357 if (F_ISSET(mutexp, DB_MUTEX_ALLOCATED))
00358 (void)__mutex_destroy(dbenv, i);
00359 }
00360 dbenv->mutex_handle = orig_handle;
00361 }
00362 #endif