1*7c478bd9Sstevel@tonic-gate /*- 2*7c478bd9Sstevel@tonic-gate * See the file LICENSE for redistribution information. 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * Copyright (c) 1996, 1997, 1998 5*7c478bd9Sstevel@tonic-gate * Sleepycat Software. All rights reserved. 6*7c478bd9Sstevel@tonic-gate */ 7*7c478bd9Sstevel@tonic-gate 8*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 9*7c478bd9Sstevel@tonic-gate 10*7c478bd9Sstevel@tonic-gate #include "config.h" 11*7c478bd9Sstevel@tonic-gate 12*7c478bd9Sstevel@tonic-gate #ifndef lint 13*7c478bd9Sstevel@tonic-gate static const char sccsid[] = "@(#)lock_region.c 10.21 (Sleepycat) 10/19/98"; 14*7c478bd9Sstevel@tonic-gate #endif /* not lint */ 15*7c478bd9Sstevel@tonic-gate 16*7c478bd9Sstevel@tonic-gate #ifndef NO_SYSTEM_INCLUDES 17*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 18*7c478bd9Sstevel@tonic-gate 19*7c478bd9Sstevel@tonic-gate #include <ctype.h> 20*7c478bd9Sstevel@tonic-gate #include <errno.h> 21*7c478bd9Sstevel@tonic-gate #include <string.h> 22*7c478bd9Sstevel@tonic-gate #endif 23*7c478bd9Sstevel@tonic-gate 24*7c478bd9Sstevel@tonic-gate #include "db_int.h" 25*7c478bd9Sstevel@tonic-gate #include "shqueue.h" 26*7c478bd9Sstevel@tonic-gate #include "db_shash.h" 27*7c478bd9Sstevel@tonic-gate #include "lock.h" 28*7c478bd9Sstevel@tonic-gate #include "common_ext.h" 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate static u_int32_t __lock_count_locks __P((DB_LOCKREGION *)); 31*7c478bd9Sstevel@tonic-gate static u_int32_t __lock_count_objs __P((DB_LOCKREGION *)); 32*7c478bd9Sstevel@tonic-gate static void __lock_dump_locker __P((DB_LOCKTAB *, DB_LOCKOBJ *, FILE *)); 33*7c478bd9Sstevel@tonic-gate static void __lock_dump_object __P((DB_LOCKTAB *, DB_LOCKOBJ *, FILE *)); 34*7c478bd9Sstevel@tonic-gate static const char * 35*7c478bd9Sstevel@tonic-gate __lock_dump_status __P((db_status_t)); 36*7c478bd9Sstevel@tonic-gate static void __lock_reset_region __P((DB_LOCKTAB *)); 37*7c478bd9Sstevel@tonic-gate static int __lock_tabinit __P((DB_ENV *, DB_LOCKREGION *)); 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate int 40*7c478bd9Sstevel@tonic-gate lock_open(path, flags, mode, dbenv, ltp) 41*7c478bd9Sstevel@tonic-gate const char *path; 42*7c478bd9Sstevel@tonic-gate u_int32_t flags; 43*7c478bd9Sstevel@tonic-gate int mode; 44*7c478bd9Sstevel@tonic-gate DB_ENV *dbenv; 45*7c478bd9Sstevel@tonic-gate DB_LOCKTAB **ltp; 46*7c478bd9Sstevel@tonic-gate { 47*7c478bd9Sstevel@tonic-gate DB_LOCKTAB *lt; 48*7c478bd9Sstevel@tonic-gate u_int32_t lock_modes, maxlocks, regflags; 49*7c478bd9Sstevel@tonic-gate int ret; 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate /* Validate arguments. */ 52*7c478bd9Sstevel@tonic-gate #ifdef HAVE_SPINLOCKS 53*7c478bd9Sstevel@tonic-gate #define OKFLAGS (DB_CREATE | DB_THREAD) 54*7c478bd9Sstevel@tonic-gate #else 55*7c478bd9Sstevel@tonic-gate #define OKFLAGS (DB_CREATE) 56*7c478bd9Sstevel@tonic-gate #endif 57*7c478bd9Sstevel@tonic-gate if ((ret = __db_fchk(dbenv, "lock_open", flags, OKFLAGS)) != 0) 58*7c478bd9Sstevel@tonic-gate return (ret); 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate /* Create the lock table structure. */ 61*7c478bd9Sstevel@tonic-gate if ((ret = __os_calloc(1, sizeof(DB_LOCKTAB), <)) != 0) 62*7c478bd9Sstevel@tonic-gate return (ret); 63*7c478bd9Sstevel@tonic-gate lt->dbenv = dbenv; 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate /* Grab the values that we need to compute the region size. */ 66*7c478bd9Sstevel@tonic-gate lock_modes = DB_LOCK_RW_N; 67*7c478bd9Sstevel@tonic-gate maxlocks = DB_LOCK_DEFAULT_N; 68*7c478bd9Sstevel@tonic-gate regflags = REGION_SIZEDEF; 69*7c478bd9Sstevel@tonic-gate if (dbenv != NULL) { 70*7c478bd9Sstevel@tonic-gate if (dbenv->lk_modes != 0) { 71*7c478bd9Sstevel@tonic-gate lock_modes = dbenv->lk_modes; 72*7c478bd9Sstevel@tonic-gate regflags = 0; 73*7c478bd9Sstevel@tonic-gate } 74*7c478bd9Sstevel@tonic-gate if (dbenv->lk_max != 0) { 75*7c478bd9Sstevel@tonic-gate maxlocks = dbenv->lk_max; 76*7c478bd9Sstevel@tonic-gate regflags = 0; 77*7c478bd9Sstevel@tonic-gate } 78*7c478bd9Sstevel@tonic-gate } 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate /* Join/create the lock region. */ 81*7c478bd9Sstevel@tonic-gate lt->reginfo.dbenv = dbenv; 82*7c478bd9Sstevel@tonic-gate lt->reginfo.appname = DB_APP_NONE; 83*7c478bd9Sstevel@tonic-gate if (path == NULL) 84*7c478bd9Sstevel@tonic-gate lt->reginfo.path = NULL; 85*7c478bd9Sstevel@tonic-gate else 86*7c478bd9Sstevel@tonic-gate if ((ret = __os_strdup(path, <->reginfo.path)) != 0) 87*7c478bd9Sstevel@tonic-gate goto err; 88*7c478bd9Sstevel@tonic-gate lt->reginfo.file = DB_DEFAULT_LOCK_FILE; 89*7c478bd9Sstevel@tonic-gate lt->reginfo.mode = mode; 90*7c478bd9Sstevel@tonic-gate lt->reginfo.size = 91*7c478bd9Sstevel@tonic-gate LOCK_REGION_SIZE(lock_modes, maxlocks, __db_tablesize(maxlocks)); 92*7c478bd9Sstevel@tonic-gate lt->reginfo.dbflags = flags; 93*7c478bd9Sstevel@tonic-gate lt->reginfo.addr = NULL; 94*7c478bd9Sstevel@tonic-gate lt->reginfo.fd = -1; 95*7c478bd9Sstevel@tonic-gate lt->reginfo.flags = regflags; 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate if ((ret = __db_rattach(<->reginfo)) != 0) 98*7c478bd9Sstevel@tonic-gate goto err; 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate /* Now set up the pointer to the region. */ 101*7c478bd9Sstevel@tonic-gate lt->region = lt->reginfo.addr; 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate /* Initialize the region if we created it. */ 104*7c478bd9Sstevel@tonic-gate if (F_ISSET(<->reginfo, REGION_CREATED)) { 105*7c478bd9Sstevel@tonic-gate lt->region->maxlocks = maxlocks; 106*7c478bd9Sstevel@tonic-gate lt->region->nmodes = lock_modes; 107*7c478bd9Sstevel@tonic-gate if ((ret = __lock_tabinit(dbenv, lt->region)) != 0) 108*7c478bd9Sstevel@tonic-gate goto err; 109*7c478bd9Sstevel@tonic-gate } else { 110*7c478bd9Sstevel@tonic-gate /* Check for an unexpected region. */ 111*7c478bd9Sstevel@tonic-gate if (lt->region->magic != DB_LOCKMAGIC) { 112*7c478bd9Sstevel@tonic-gate __db_err(dbenv, 113*7c478bd9Sstevel@tonic-gate "lock_open: %s: bad magic number", path); 114*7c478bd9Sstevel@tonic-gate ret = EINVAL; 115*7c478bd9Sstevel@tonic-gate goto err; 116*7c478bd9Sstevel@tonic-gate } 117*7c478bd9Sstevel@tonic-gate } 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate /* Check for automatic deadlock detection. */ 120*7c478bd9Sstevel@tonic-gate if (dbenv != NULL && dbenv->lk_detect != DB_LOCK_NORUN) { 121*7c478bd9Sstevel@tonic-gate if (lt->region->detect != DB_LOCK_NORUN && 122*7c478bd9Sstevel@tonic-gate dbenv->lk_detect != DB_LOCK_DEFAULT && 123*7c478bd9Sstevel@tonic-gate lt->region->detect != dbenv->lk_detect) { 124*7c478bd9Sstevel@tonic-gate __db_err(dbenv, 125*7c478bd9Sstevel@tonic-gate "lock_open: incompatible deadlock detector mode"); 126*7c478bd9Sstevel@tonic-gate ret = EINVAL; 127*7c478bd9Sstevel@tonic-gate goto err; 128*7c478bd9Sstevel@tonic-gate } 129*7c478bd9Sstevel@tonic-gate if (lt->region->detect == DB_LOCK_NORUN) 130*7c478bd9Sstevel@tonic-gate lt->region->detect = dbenv->lk_detect; 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate /* Set up remaining pointers into region. */ 134*7c478bd9Sstevel@tonic-gate lt->conflicts = (u_int8_t *)lt->region + sizeof(DB_LOCKREGION); 135*7c478bd9Sstevel@tonic-gate lt->hashtab = 136*7c478bd9Sstevel@tonic-gate (DB_HASHTAB *)((u_int8_t *)lt->region + lt->region->hash_off); 137*7c478bd9Sstevel@tonic-gate lt->mem = (void *)((u_int8_t *)lt->region + lt->region->mem_off); 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate UNLOCK_LOCKREGION(lt); 140*7c478bd9Sstevel@tonic-gate *ltp = lt; 141*7c478bd9Sstevel@tonic-gate return (0); 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate err: if (lt->reginfo.addr != NULL) { 144*7c478bd9Sstevel@tonic-gate UNLOCK_LOCKREGION(lt); 145*7c478bd9Sstevel@tonic-gate (void)__db_rdetach(<->reginfo); 146*7c478bd9Sstevel@tonic-gate if (F_ISSET(<->reginfo, REGION_CREATED)) 147*7c478bd9Sstevel@tonic-gate (void)lock_unlink(path, 1, dbenv); 148*7c478bd9Sstevel@tonic-gate } 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate if (lt->reginfo.path != NULL) 151*7c478bd9Sstevel@tonic-gate __os_freestr(lt->reginfo.path); 152*7c478bd9Sstevel@tonic-gate __os_free(lt, sizeof(*lt)); 153*7c478bd9Sstevel@tonic-gate return (ret); 154*7c478bd9Sstevel@tonic-gate } 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate /* 157*7c478bd9Sstevel@tonic-gate * __lock_panic -- 158*7c478bd9Sstevel@tonic-gate * Panic a lock region. 159*7c478bd9Sstevel@tonic-gate * 160*7c478bd9Sstevel@tonic-gate * PUBLIC: void __lock_panic __P((DB_ENV *)); 161*7c478bd9Sstevel@tonic-gate */ 162*7c478bd9Sstevel@tonic-gate void 163*7c478bd9Sstevel@tonic-gate __lock_panic(dbenv) 164*7c478bd9Sstevel@tonic-gate DB_ENV *dbenv; 165*7c478bd9Sstevel@tonic-gate { 166*7c478bd9Sstevel@tonic-gate if (dbenv->lk_info != NULL) 167*7c478bd9Sstevel@tonic-gate dbenv->lk_info->region->hdr.panic = 1; 168*7c478bd9Sstevel@tonic-gate } 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate /* 172*7c478bd9Sstevel@tonic-gate * __lock_tabinit -- 173*7c478bd9Sstevel@tonic-gate * Initialize the lock region. 174*7c478bd9Sstevel@tonic-gate */ 175*7c478bd9Sstevel@tonic-gate static int 176*7c478bd9Sstevel@tonic-gate __lock_tabinit(dbenv, lrp) 177*7c478bd9Sstevel@tonic-gate DB_ENV *dbenv; 178*7c478bd9Sstevel@tonic-gate DB_LOCKREGION *lrp; 179*7c478bd9Sstevel@tonic-gate { 180*7c478bd9Sstevel@tonic-gate struct __db_lock *lp; 181*7c478bd9Sstevel@tonic-gate struct lock_header *tq_head; 182*7c478bd9Sstevel@tonic-gate struct obj_header *obj_head; 183*7c478bd9Sstevel@tonic-gate DB_LOCKOBJ *op; 184*7c478bd9Sstevel@tonic-gate u_int32_t i, nelements; 185*7c478bd9Sstevel@tonic-gate const u_int8_t *conflicts; 186*7c478bd9Sstevel@tonic-gate u_int8_t *curaddr; 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate conflicts = dbenv == NULL || dbenv->lk_conflicts == NULL ? 189*7c478bd9Sstevel@tonic-gate db_rw_conflicts : dbenv->lk_conflicts; 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate lrp->table_size = __db_tablesize(lrp->maxlocks); 192*7c478bd9Sstevel@tonic-gate lrp->magic = DB_LOCKMAGIC; 193*7c478bd9Sstevel@tonic-gate lrp->version = DB_LOCKVERSION; 194*7c478bd9Sstevel@tonic-gate lrp->id = 0; 195*7c478bd9Sstevel@tonic-gate /* 196*7c478bd9Sstevel@tonic-gate * These fields (lrp->maxlocks, lrp->nmodes) are initialized 197*7c478bd9Sstevel@tonic-gate * in the caller, since we had to grab those values to size 198*7c478bd9Sstevel@tonic-gate * the region. 199*7c478bd9Sstevel@tonic-gate */ 200*7c478bd9Sstevel@tonic-gate lrp->need_dd = 0; 201*7c478bd9Sstevel@tonic-gate lrp->detect = DB_LOCK_NORUN; 202*7c478bd9Sstevel@tonic-gate lrp->numobjs = lrp->maxlocks; 203*7c478bd9Sstevel@tonic-gate lrp->nlockers = 0; 204*7c478bd9Sstevel@tonic-gate lrp->mem_bytes = ALIGN(STRING_SIZE(lrp->maxlocks), sizeof(size_t)); 205*7c478bd9Sstevel@tonic-gate lrp->increment = lrp->hdr.size / 2; 206*7c478bd9Sstevel@tonic-gate lrp->nconflicts = 0; 207*7c478bd9Sstevel@tonic-gate lrp->nrequests = 0; 208*7c478bd9Sstevel@tonic-gate lrp->nreleases = 0; 209*7c478bd9Sstevel@tonic-gate lrp->ndeadlocks = 0; 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate /* 212*7c478bd9Sstevel@tonic-gate * As we write the region, we've got to maintain the alignment 213*7c478bd9Sstevel@tonic-gate * for the structures that follow each chunk. This information 214*7c478bd9Sstevel@tonic-gate * ends up being encapsulated both in here as well as in the 215*7c478bd9Sstevel@tonic-gate * lock.h file for the XXX_SIZE macros. 216*7c478bd9Sstevel@tonic-gate */ 217*7c478bd9Sstevel@tonic-gate /* Initialize conflict matrix. */ 218*7c478bd9Sstevel@tonic-gate curaddr = (u_int8_t *)lrp + sizeof(DB_LOCKREGION); 219*7c478bd9Sstevel@tonic-gate memcpy(curaddr, conflicts, lrp->nmodes * lrp->nmodes); 220*7c478bd9Sstevel@tonic-gate curaddr += lrp->nmodes * lrp->nmodes; 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate /* 223*7c478bd9Sstevel@tonic-gate * Initialize hash table. 224*7c478bd9Sstevel@tonic-gate */ 225*7c478bd9Sstevel@tonic-gate curaddr = (u_int8_t *)ALIGNP(curaddr, LOCK_HASH_ALIGN); 226*7c478bd9Sstevel@tonic-gate lrp->hash_off = curaddr - (u_int8_t *)lrp; 227*7c478bd9Sstevel@tonic-gate nelements = lrp->table_size; 228*7c478bd9Sstevel@tonic-gate __db_hashinit(curaddr, nelements); 229*7c478bd9Sstevel@tonic-gate curaddr += nelements * sizeof(DB_HASHTAB); 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate /* 232*7c478bd9Sstevel@tonic-gate * Initialize locks onto a free list. Since locks contains mutexes, 233*7c478bd9Sstevel@tonic-gate * we need to make sure that each lock is aligned on a MUTEX_ALIGNMENT 234*7c478bd9Sstevel@tonic-gate * boundary. 235*7c478bd9Sstevel@tonic-gate */ 236*7c478bd9Sstevel@tonic-gate curaddr = (u_int8_t *)ALIGNP(curaddr, MUTEX_ALIGNMENT); 237*7c478bd9Sstevel@tonic-gate tq_head = &lrp->free_locks; 238*7c478bd9Sstevel@tonic-gate SH_TAILQ_INIT(tq_head); 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate for (i = 0; i++ < lrp->maxlocks; 241*7c478bd9Sstevel@tonic-gate curaddr += ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT)) { 242*7c478bd9Sstevel@tonic-gate lp = (struct __db_lock *)curaddr; 243*7c478bd9Sstevel@tonic-gate lp->status = DB_LSTAT_FREE; 244*7c478bd9Sstevel@tonic-gate SH_TAILQ_INSERT_HEAD(tq_head, lp, links, __db_lock); 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate /* Initialize objects onto a free list. */ 248*7c478bd9Sstevel@tonic-gate obj_head = &lrp->free_objs; 249*7c478bd9Sstevel@tonic-gate SH_TAILQ_INIT(obj_head); 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate for (i = 0; i++ < lrp->maxlocks; curaddr += sizeof(DB_LOCKOBJ)) { 252*7c478bd9Sstevel@tonic-gate op = (DB_LOCKOBJ *)curaddr; 253*7c478bd9Sstevel@tonic-gate SH_TAILQ_INSERT_HEAD(obj_head, op, links, __db_lockobj); 254*7c478bd9Sstevel@tonic-gate } 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate /* 257*7c478bd9Sstevel@tonic-gate * Initialize the string space; as for all shared memory allocation 258*7c478bd9Sstevel@tonic-gate * regions, this requires size_t alignment, since we store the 259*7c478bd9Sstevel@tonic-gate * lengths of malloc'd areas in the area. 260*7c478bd9Sstevel@tonic-gate */ 261*7c478bd9Sstevel@tonic-gate curaddr = (u_int8_t *)ALIGNP(curaddr, sizeof(size_t)); 262*7c478bd9Sstevel@tonic-gate lrp->mem_off = curaddr - (u_int8_t *)lrp; 263*7c478bd9Sstevel@tonic-gate __db_shalloc_init(curaddr, lrp->mem_bytes); 264*7c478bd9Sstevel@tonic-gate return (0); 265*7c478bd9Sstevel@tonic-gate } 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate int 268*7c478bd9Sstevel@tonic-gate lock_close(lt) 269*7c478bd9Sstevel@tonic-gate DB_LOCKTAB *lt; 270*7c478bd9Sstevel@tonic-gate { 271*7c478bd9Sstevel@tonic-gate int ret; 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate LOCK_PANIC_CHECK(lt); 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate if ((ret = __db_rdetach(<->reginfo)) != 0) 276*7c478bd9Sstevel@tonic-gate return (ret); 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate if (lt->reginfo.path != NULL) 279*7c478bd9Sstevel@tonic-gate __os_freestr(lt->reginfo.path); 280*7c478bd9Sstevel@tonic-gate __os_free(lt, sizeof(*lt)); 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate return (0); 283*7c478bd9Sstevel@tonic-gate } 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate int 286*7c478bd9Sstevel@tonic-gate lock_unlink(path, force, dbenv) 287*7c478bd9Sstevel@tonic-gate const char *path; 288*7c478bd9Sstevel@tonic-gate int force; 289*7c478bd9Sstevel@tonic-gate DB_ENV *dbenv; 290*7c478bd9Sstevel@tonic-gate { 291*7c478bd9Sstevel@tonic-gate REGINFO reginfo; 292*7c478bd9Sstevel@tonic-gate int ret; 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate memset(®info, 0, sizeof(reginfo)); 295*7c478bd9Sstevel@tonic-gate reginfo.dbenv = dbenv; 296*7c478bd9Sstevel@tonic-gate reginfo.appname = DB_APP_NONE; 297*7c478bd9Sstevel@tonic-gate if (path != NULL && (ret = __os_strdup(path, ®info.path)) != 0) 298*7c478bd9Sstevel@tonic-gate return (ret); 299*7c478bd9Sstevel@tonic-gate reginfo.file = DB_DEFAULT_LOCK_FILE; 300*7c478bd9Sstevel@tonic-gate ret = __db_runlink(®info, force); 301*7c478bd9Sstevel@tonic-gate if (reginfo.path != NULL) 302*7c478bd9Sstevel@tonic-gate __os_freestr(reginfo.path); 303*7c478bd9Sstevel@tonic-gate return (ret); 304*7c478bd9Sstevel@tonic-gate } 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate /* 307*7c478bd9Sstevel@tonic-gate * __lock_validate_region -- 308*7c478bd9Sstevel@tonic-gate * Called at every interface to verify if the region has changed size, 309*7c478bd9Sstevel@tonic-gate * and if so, to remap the region in and reset the process' pointers. 310*7c478bd9Sstevel@tonic-gate * 311*7c478bd9Sstevel@tonic-gate * PUBLIC: int __lock_validate_region __P((DB_LOCKTAB *)); 312*7c478bd9Sstevel@tonic-gate */ 313*7c478bd9Sstevel@tonic-gate int 314*7c478bd9Sstevel@tonic-gate __lock_validate_region(lt) 315*7c478bd9Sstevel@tonic-gate DB_LOCKTAB *lt; 316*7c478bd9Sstevel@tonic-gate { 317*7c478bd9Sstevel@tonic-gate int ret; 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate if (lt->reginfo.size == lt->region->hdr.size) 320*7c478bd9Sstevel@tonic-gate return (0); 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate /* Detach/reattach the region. */ 323*7c478bd9Sstevel@tonic-gate if ((ret = __db_rreattach(<->reginfo, lt->region->hdr.size)) != 0) 324*7c478bd9Sstevel@tonic-gate return (ret); 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate /* Reset region information. */ 327*7c478bd9Sstevel@tonic-gate lt->region = lt->reginfo.addr; 328*7c478bd9Sstevel@tonic-gate __lock_reset_region(lt); 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate return (0); 331*7c478bd9Sstevel@tonic-gate } 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate /* 334*7c478bd9Sstevel@tonic-gate * __lock_grow_region -- 335*7c478bd9Sstevel@tonic-gate * We have run out of space; time to grow the region. 336*7c478bd9Sstevel@tonic-gate * 337*7c478bd9Sstevel@tonic-gate * PUBLIC: int __lock_grow_region __P((DB_LOCKTAB *, int, size_t)); 338*7c478bd9Sstevel@tonic-gate */ 339*7c478bd9Sstevel@tonic-gate int 340*7c478bd9Sstevel@tonic-gate __lock_grow_region(lt, which, howmuch) 341*7c478bd9Sstevel@tonic-gate DB_LOCKTAB *lt; 342*7c478bd9Sstevel@tonic-gate int which; 343*7c478bd9Sstevel@tonic-gate size_t howmuch; 344*7c478bd9Sstevel@tonic-gate { 345*7c478bd9Sstevel@tonic-gate struct __db_lock *newl; 346*7c478bd9Sstevel@tonic-gate struct lock_header *lock_head; 347*7c478bd9Sstevel@tonic-gate struct obj_header *obj_head; 348*7c478bd9Sstevel@tonic-gate DB_LOCKOBJ *op; 349*7c478bd9Sstevel@tonic-gate DB_LOCKREGION *lrp; 350*7c478bd9Sstevel@tonic-gate float lock_ratio, obj_ratio; 351*7c478bd9Sstevel@tonic-gate size_t incr, oldsize, used, usedmem; 352*7c478bd9Sstevel@tonic-gate u_int32_t i, newlocks, newmem, newobjs, usedlocks, usedobjs; 353*7c478bd9Sstevel@tonic-gate u_int8_t *curaddr; 354*7c478bd9Sstevel@tonic-gate int ret; 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate lrp = lt->region; 357*7c478bd9Sstevel@tonic-gate oldsize = lrp->hdr.size; 358*7c478bd9Sstevel@tonic-gate incr = lrp->increment; 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate /* Figure out how much of each sort of space we have. */ 361*7c478bd9Sstevel@tonic-gate usedmem = lrp->mem_bytes - __db_shalloc_count(lt->mem); 362*7c478bd9Sstevel@tonic-gate usedobjs = lrp->numobjs - __lock_count_objs(lrp); 363*7c478bd9Sstevel@tonic-gate usedlocks = lrp->maxlocks - __lock_count_locks(lrp); 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate /* 366*7c478bd9Sstevel@tonic-gate * Figure out what fraction of the used space belongs to each 367*7c478bd9Sstevel@tonic-gate * different type of "thing" in the region. Then partition the 368*7c478bd9Sstevel@tonic-gate * new space up according to this ratio. 369*7c478bd9Sstevel@tonic-gate */ 370*7c478bd9Sstevel@tonic-gate used = usedmem + 371*7c478bd9Sstevel@tonic-gate usedlocks * ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT) + 372*7c478bd9Sstevel@tonic-gate usedobjs * sizeof(DB_LOCKOBJ); 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate lock_ratio = usedlocks * 375*7c478bd9Sstevel@tonic-gate ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT) / (float)used; 376*7c478bd9Sstevel@tonic-gate obj_ratio = usedobjs * sizeof(DB_LOCKOBJ) / (float)used; 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate newlocks = (u_int32_t)(lock_ratio * 379*7c478bd9Sstevel@tonic-gate incr / ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT)); 380*7c478bd9Sstevel@tonic-gate newobjs = (u_int32_t)(obj_ratio * incr / sizeof(DB_LOCKOBJ)); 381*7c478bd9Sstevel@tonic-gate newmem = incr - 382*7c478bd9Sstevel@tonic-gate (newobjs * sizeof(DB_LOCKOBJ) + 383*7c478bd9Sstevel@tonic-gate newlocks * ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT)); 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate /* 386*7c478bd9Sstevel@tonic-gate * Make sure we allocate enough memory for the object being 387*7c478bd9Sstevel@tonic-gate * requested. 388*7c478bd9Sstevel@tonic-gate */ 389*7c478bd9Sstevel@tonic-gate switch (which) { 390*7c478bd9Sstevel@tonic-gate case DB_LOCK_LOCK: 391*7c478bd9Sstevel@tonic-gate if (newlocks == 0) { 392*7c478bd9Sstevel@tonic-gate newlocks = 10; 393*7c478bd9Sstevel@tonic-gate incr += newlocks * sizeof(struct __db_lock); 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate break; 396*7c478bd9Sstevel@tonic-gate case DB_LOCK_OBJ: 397*7c478bd9Sstevel@tonic-gate if (newobjs == 0) { 398*7c478bd9Sstevel@tonic-gate newobjs = 10; 399*7c478bd9Sstevel@tonic-gate incr += newobjs * sizeof(DB_LOCKOBJ); 400*7c478bd9Sstevel@tonic-gate } 401*7c478bd9Sstevel@tonic-gate break; 402*7c478bd9Sstevel@tonic-gate case DB_LOCK_MEM: 403*7c478bd9Sstevel@tonic-gate if (newmem < howmuch * 2) { 404*7c478bd9Sstevel@tonic-gate incr += howmuch * 2 - newmem; 405*7c478bd9Sstevel@tonic-gate newmem = howmuch * 2; 406*7c478bd9Sstevel@tonic-gate } 407*7c478bd9Sstevel@tonic-gate break; 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate newmem += ALIGN(incr, sizeof(size_t)) - incr; 411*7c478bd9Sstevel@tonic-gate incr = ALIGN(incr, sizeof(size_t)); 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate /* 414*7c478bd9Sstevel@tonic-gate * Since we are going to be allocating locks at the beginning of the 415*7c478bd9Sstevel@tonic-gate * new chunk, we need to make sure that the chunk is MUTEX_ALIGNMENT 416*7c478bd9Sstevel@tonic-gate * aligned. We did not guarantee this when we created the region, so 417*7c478bd9Sstevel@tonic-gate * we may need to pad the old region by extra bytes to ensure this 418*7c478bd9Sstevel@tonic-gate * alignment. 419*7c478bd9Sstevel@tonic-gate */ 420*7c478bd9Sstevel@tonic-gate incr += ALIGN(oldsize, MUTEX_ALIGNMENT) - oldsize; 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate __db_err(lt->dbenv, 423*7c478bd9Sstevel@tonic-gate "Growing lock region: %lu locks %lu objs %lu bytes", 424*7c478bd9Sstevel@tonic-gate (u_long)newlocks, (u_long)newobjs, (u_long)newmem); 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate if ((ret = __db_rgrow(<->reginfo, oldsize + incr)) != 0) 427*7c478bd9Sstevel@tonic-gate return (ret); 428*7c478bd9Sstevel@tonic-gate lt->region = lt->reginfo.addr; 429*7c478bd9Sstevel@tonic-gate __lock_reset_region(lt); 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate /* Update region parameters. */ 432*7c478bd9Sstevel@tonic-gate lrp = lt->region; 433*7c478bd9Sstevel@tonic-gate lrp->increment = incr << 1; 434*7c478bd9Sstevel@tonic-gate lrp->maxlocks += newlocks; 435*7c478bd9Sstevel@tonic-gate lrp->numobjs += newobjs; 436*7c478bd9Sstevel@tonic-gate lrp->mem_bytes += newmem; 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate curaddr = (u_int8_t *)lrp + oldsize; 439*7c478bd9Sstevel@tonic-gate curaddr = (u_int8_t *)ALIGNP(curaddr, MUTEX_ALIGNMENT); 440*7c478bd9Sstevel@tonic-gate 441*7c478bd9Sstevel@tonic-gate /* Put new locks onto the free list. */ 442*7c478bd9Sstevel@tonic-gate lock_head = &lrp->free_locks; 443*7c478bd9Sstevel@tonic-gate for (i = 0; i++ < newlocks; 444*7c478bd9Sstevel@tonic-gate curaddr += ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT)) { 445*7c478bd9Sstevel@tonic-gate newl = (struct __db_lock *)curaddr; 446*7c478bd9Sstevel@tonic-gate SH_TAILQ_INSERT_HEAD(lock_head, newl, links, __db_lock); 447*7c478bd9Sstevel@tonic-gate } 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate /* Put new objects onto the free list. */ 450*7c478bd9Sstevel@tonic-gate obj_head = &lrp->free_objs; 451*7c478bd9Sstevel@tonic-gate for (i = 0; i++ < newobjs; curaddr += sizeof(DB_LOCKOBJ)) { 452*7c478bd9Sstevel@tonic-gate op = (DB_LOCKOBJ *)curaddr; 453*7c478bd9Sstevel@tonic-gate SH_TAILQ_INSERT_HEAD(obj_head, op, links, __db_lockobj); 454*7c478bd9Sstevel@tonic-gate } 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate *((size_t *)curaddr) = newmem - sizeof(size_t); 457*7c478bd9Sstevel@tonic-gate curaddr += sizeof(size_t); 458*7c478bd9Sstevel@tonic-gate __db_shalloc_free(lt->mem, curaddr); 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate return (0); 461*7c478bd9Sstevel@tonic-gate } 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate static void 464*7c478bd9Sstevel@tonic-gate __lock_reset_region(lt) 465*7c478bd9Sstevel@tonic-gate DB_LOCKTAB *lt; 466*7c478bd9Sstevel@tonic-gate { 467*7c478bd9Sstevel@tonic-gate lt->conflicts = (u_int8_t *)lt->region + sizeof(DB_LOCKREGION); 468*7c478bd9Sstevel@tonic-gate lt->hashtab = 469*7c478bd9Sstevel@tonic-gate (DB_HASHTAB *)((u_int8_t *)lt->region + lt->region->hash_off); 470*7c478bd9Sstevel@tonic-gate lt->mem = (void *)((u_int8_t *)lt->region + lt->region->mem_off); 471*7c478bd9Sstevel@tonic-gate } 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate /* 474*7c478bd9Sstevel@tonic-gate * lock_stat -- 475*7c478bd9Sstevel@tonic-gate * Return LOCK statistics. 476*7c478bd9Sstevel@tonic-gate */ 477*7c478bd9Sstevel@tonic-gate int 478*7c478bd9Sstevel@tonic-gate lock_stat(lt, gspp, db_malloc) 479*7c478bd9Sstevel@tonic-gate DB_LOCKTAB *lt; 480*7c478bd9Sstevel@tonic-gate DB_LOCK_STAT **gspp; 481*7c478bd9Sstevel@tonic-gate void *(*db_malloc) __P((size_t)); 482*7c478bd9Sstevel@tonic-gate { 483*7c478bd9Sstevel@tonic-gate DB_LOCKREGION *rp; 484*7c478bd9Sstevel@tonic-gate int ret; 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate *gspp = NULL; 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate LOCK_PANIC_CHECK(lt); 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate if ((ret = __os_malloc(sizeof(**gspp), db_malloc, gspp)) != 0) 491*7c478bd9Sstevel@tonic-gate return (ret); 492*7c478bd9Sstevel@tonic-gate 493*7c478bd9Sstevel@tonic-gate /* Copy out the global statistics. */ 494*7c478bd9Sstevel@tonic-gate LOCK_LOCKREGION(lt); 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate rp = lt->region; 497*7c478bd9Sstevel@tonic-gate (*gspp)->st_magic = rp->magic; 498*7c478bd9Sstevel@tonic-gate (*gspp)->st_version = rp->version; 499*7c478bd9Sstevel@tonic-gate (*gspp)->st_maxlocks = rp->maxlocks; 500*7c478bd9Sstevel@tonic-gate (*gspp)->st_nmodes = rp->nmodes; 501*7c478bd9Sstevel@tonic-gate (*gspp)->st_numobjs = rp->numobjs; 502*7c478bd9Sstevel@tonic-gate (*gspp)->st_nlockers = rp->nlockers; 503*7c478bd9Sstevel@tonic-gate (*gspp)->st_nconflicts = rp->nconflicts; 504*7c478bd9Sstevel@tonic-gate (*gspp)->st_nrequests = rp->nrequests; 505*7c478bd9Sstevel@tonic-gate (*gspp)->st_nreleases = rp->nreleases; 506*7c478bd9Sstevel@tonic-gate (*gspp)->st_ndeadlocks = rp->ndeadlocks; 507*7c478bd9Sstevel@tonic-gate (*gspp)->st_region_nowait = rp->hdr.lock.mutex_set_nowait; 508*7c478bd9Sstevel@tonic-gate (*gspp)->st_region_wait = rp->hdr.lock.mutex_set_wait; 509*7c478bd9Sstevel@tonic-gate (*gspp)->st_refcnt = rp->hdr.refcnt; 510*7c478bd9Sstevel@tonic-gate (*gspp)->st_regsize = rp->hdr.size; 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate UNLOCK_LOCKREGION(lt); 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate return (0); 515*7c478bd9Sstevel@tonic-gate } 516*7c478bd9Sstevel@tonic-gate 517*7c478bd9Sstevel@tonic-gate static u_int32_t 518*7c478bd9Sstevel@tonic-gate __lock_count_locks(lrp) 519*7c478bd9Sstevel@tonic-gate DB_LOCKREGION *lrp; 520*7c478bd9Sstevel@tonic-gate { 521*7c478bd9Sstevel@tonic-gate struct __db_lock *newl; 522*7c478bd9Sstevel@tonic-gate u_int32_t count; 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate count = 0; 525*7c478bd9Sstevel@tonic-gate for (newl = SH_TAILQ_FIRST(&lrp->free_locks, __db_lock); 526*7c478bd9Sstevel@tonic-gate newl != NULL; 527*7c478bd9Sstevel@tonic-gate newl = SH_TAILQ_NEXT(newl, links, __db_lock)) 528*7c478bd9Sstevel@tonic-gate count++; 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate return (count); 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate 533*7c478bd9Sstevel@tonic-gate static u_int32_t 534*7c478bd9Sstevel@tonic-gate __lock_count_objs(lrp) 535*7c478bd9Sstevel@tonic-gate DB_LOCKREGION *lrp; 536*7c478bd9Sstevel@tonic-gate { 537*7c478bd9Sstevel@tonic-gate DB_LOCKOBJ *obj; 538*7c478bd9Sstevel@tonic-gate u_int32_t count; 539*7c478bd9Sstevel@tonic-gate 540*7c478bd9Sstevel@tonic-gate count = 0; 541*7c478bd9Sstevel@tonic-gate for (obj = SH_TAILQ_FIRST(&lrp->free_objs, __db_lockobj); 542*7c478bd9Sstevel@tonic-gate obj != NULL; 543*7c478bd9Sstevel@tonic-gate obj = SH_TAILQ_NEXT(obj, links, __db_lockobj)) 544*7c478bd9Sstevel@tonic-gate count++; 545*7c478bd9Sstevel@tonic-gate 546*7c478bd9Sstevel@tonic-gate return (count); 547*7c478bd9Sstevel@tonic-gate } 548*7c478bd9Sstevel@tonic-gate 549*7c478bd9Sstevel@tonic-gate #define LOCK_DUMP_CONF 0x001 /* Conflict matrix. */ 550*7c478bd9Sstevel@tonic-gate #define LOCK_DUMP_FREE 0x002 /* Display lock free list. */ 551*7c478bd9Sstevel@tonic-gate #define LOCK_DUMP_LOCKERS 0x004 /* Display lockers. */ 552*7c478bd9Sstevel@tonic-gate #define LOCK_DUMP_MEM 0x008 /* Display region memory. */ 553*7c478bd9Sstevel@tonic-gate #define LOCK_DUMP_OBJECTS 0x010 /* Display objects. */ 554*7c478bd9Sstevel@tonic-gate #define LOCK_DUMP_ALL 0x01f /* Display all. */ 555*7c478bd9Sstevel@tonic-gate 556*7c478bd9Sstevel@tonic-gate /* 557*7c478bd9Sstevel@tonic-gate * __lock_dump_region -- 558*7c478bd9Sstevel@tonic-gate * 559*7c478bd9Sstevel@tonic-gate * PUBLIC: void __lock_dump_region __P((DB_LOCKTAB *, char *, FILE *)); 560*7c478bd9Sstevel@tonic-gate */ 561*7c478bd9Sstevel@tonic-gate void 562*7c478bd9Sstevel@tonic-gate __lock_dump_region(lt, area, fp) 563*7c478bd9Sstevel@tonic-gate DB_LOCKTAB *lt; 564*7c478bd9Sstevel@tonic-gate char *area; 565*7c478bd9Sstevel@tonic-gate FILE *fp; 566*7c478bd9Sstevel@tonic-gate { 567*7c478bd9Sstevel@tonic-gate struct __db_lock *lp; 568*7c478bd9Sstevel@tonic-gate DB_LOCKOBJ *op; 569*7c478bd9Sstevel@tonic-gate DB_LOCKREGION *lrp; 570*7c478bd9Sstevel@tonic-gate u_int32_t flags, i, j; 571*7c478bd9Sstevel@tonic-gate int label; 572*7c478bd9Sstevel@tonic-gate 573*7c478bd9Sstevel@tonic-gate /* Make it easy to call from the debugger. */ 574*7c478bd9Sstevel@tonic-gate if (fp == NULL) 575*7c478bd9Sstevel@tonic-gate fp = stderr; 576*7c478bd9Sstevel@tonic-gate 577*7c478bd9Sstevel@tonic-gate for (flags = 0; *area != '\0'; ++area) 578*7c478bd9Sstevel@tonic-gate switch (*area) { 579*7c478bd9Sstevel@tonic-gate case 'A': 580*7c478bd9Sstevel@tonic-gate LF_SET(LOCK_DUMP_ALL); 581*7c478bd9Sstevel@tonic-gate break; 582*7c478bd9Sstevel@tonic-gate case 'c': 583*7c478bd9Sstevel@tonic-gate LF_SET(LOCK_DUMP_CONF); 584*7c478bd9Sstevel@tonic-gate break; 585*7c478bd9Sstevel@tonic-gate case 'f': 586*7c478bd9Sstevel@tonic-gate LF_SET(LOCK_DUMP_FREE); 587*7c478bd9Sstevel@tonic-gate break; 588*7c478bd9Sstevel@tonic-gate case 'l': 589*7c478bd9Sstevel@tonic-gate LF_SET(LOCK_DUMP_LOCKERS); 590*7c478bd9Sstevel@tonic-gate break; 591*7c478bd9Sstevel@tonic-gate case 'm': 592*7c478bd9Sstevel@tonic-gate LF_SET(LOCK_DUMP_MEM); 593*7c478bd9Sstevel@tonic-gate break; 594*7c478bd9Sstevel@tonic-gate case 'o': 595*7c478bd9Sstevel@tonic-gate LF_SET(LOCK_DUMP_OBJECTS); 596*7c478bd9Sstevel@tonic-gate break; 597*7c478bd9Sstevel@tonic-gate } 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate lrp = lt->region; 600*7c478bd9Sstevel@tonic-gate 601*7c478bd9Sstevel@tonic-gate fprintf(fp, "%s\nLock region parameters\n", DB_LINE); 602*7c478bd9Sstevel@tonic-gate fprintf(fp, "%s: %lu, %s: %lu, %s: %lu, %s: %lu\n%s: %lu, %s: %lu\n", 603*7c478bd9Sstevel@tonic-gate "table size", (u_long)lrp->table_size, 604*7c478bd9Sstevel@tonic-gate "hash_off", (u_long)lrp->hash_off, 605*7c478bd9Sstevel@tonic-gate "increment", (u_long)lrp->increment, 606*7c478bd9Sstevel@tonic-gate "mem_off", (u_long)lrp->mem_off, 607*7c478bd9Sstevel@tonic-gate "mem_bytes", (u_long)lrp->mem_bytes, 608*7c478bd9Sstevel@tonic-gate "need_dd", (u_long)lrp->need_dd); 609*7c478bd9Sstevel@tonic-gate 610*7c478bd9Sstevel@tonic-gate if (LF_ISSET(LOCK_DUMP_CONF)) { 611*7c478bd9Sstevel@tonic-gate fprintf(fp, "\n%s\nConflict matrix\n", DB_LINE); 612*7c478bd9Sstevel@tonic-gate for (i = 0; i < lrp->nmodes; i++) { 613*7c478bd9Sstevel@tonic-gate for (j = 0; j < lrp->nmodes; j++) 614*7c478bd9Sstevel@tonic-gate fprintf(fp, "%lu\t", 615*7c478bd9Sstevel@tonic-gate (u_long)lt->conflicts[i * lrp->nmodes + j]); 616*7c478bd9Sstevel@tonic-gate fprintf(fp, "\n"); 617*7c478bd9Sstevel@tonic-gate } 618*7c478bd9Sstevel@tonic-gate } 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate if (LF_ISSET(LOCK_DUMP_LOCKERS | LOCK_DUMP_OBJECTS)) { 621*7c478bd9Sstevel@tonic-gate fprintf(fp, "%s\nLock hash buckets\n", DB_LINE); 622*7c478bd9Sstevel@tonic-gate for (i = 0; i < lrp->table_size; i++) { 623*7c478bd9Sstevel@tonic-gate label = 1; 624*7c478bd9Sstevel@tonic-gate for (op = SH_TAILQ_FIRST(<->hashtab[i], __db_lockobj); 625*7c478bd9Sstevel@tonic-gate op != NULL; 626*7c478bd9Sstevel@tonic-gate op = SH_TAILQ_NEXT(op, links, __db_lockobj)) { 627*7c478bd9Sstevel@tonic-gate if (LF_ISSET(LOCK_DUMP_LOCKERS) && 628*7c478bd9Sstevel@tonic-gate op->type == DB_LOCK_LOCKER) { 629*7c478bd9Sstevel@tonic-gate if (label) { 630*7c478bd9Sstevel@tonic-gate fprintf(fp, 631*7c478bd9Sstevel@tonic-gate "Bucket %lu:\n", (u_long)i); 632*7c478bd9Sstevel@tonic-gate label = 0; 633*7c478bd9Sstevel@tonic-gate } 634*7c478bd9Sstevel@tonic-gate __lock_dump_locker(lt, op, fp); 635*7c478bd9Sstevel@tonic-gate } 636*7c478bd9Sstevel@tonic-gate if (LF_ISSET(LOCK_DUMP_OBJECTS) && 637*7c478bd9Sstevel@tonic-gate op->type == DB_LOCK_OBJTYPE) { 638*7c478bd9Sstevel@tonic-gate if (label) { 639*7c478bd9Sstevel@tonic-gate fprintf(fp, 640*7c478bd9Sstevel@tonic-gate "Bucket %lu:\n", (u_long)i); 641*7c478bd9Sstevel@tonic-gate label = 0; 642*7c478bd9Sstevel@tonic-gate } 643*7c478bd9Sstevel@tonic-gate __lock_dump_object(lt, op, fp); 644*7c478bd9Sstevel@tonic-gate } 645*7c478bd9Sstevel@tonic-gate } 646*7c478bd9Sstevel@tonic-gate } 647*7c478bd9Sstevel@tonic-gate } 648*7c478bd9Sstevel@tonic-gate 649*7c478bd9Sstevel@tonic-gate if (LF_ISSET(LOCK_DUMP_FREE)) { 650*7c478bd9Sstevel@tonic-gate fprintf(fp, "%s\nLock free list\n", DB_LINE); 651*7c478bd9Sstevel@tonic-gate for (lp = SH_TAILQ_FIRST(&lrp->free_locks, __db_lock); 652*7c478bd9Sstevel@tonic-gate lp != NULL; 653*7c478bd9Sstevel@tonic-gate lp = SH_TAILQ_NEXT(lp, links, __db_lock)) 654*7c478bd9Sstevel@tonic-gate fprintf(fp, "0x%lx: %lu\t%lu\t%s\t0x%lx\n", (u_long)lp, 655*7c478bd9Sstevel@tonic-gate (u_long)lp->holder, (u_long)lp->mode, 656*7c478bd9Sstevel@tonic-gate __lock_dump_status(lp->status), (u_long)lp->obj); 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate fprintf(fp, "%s\nObject free list\n", DB_LINE); 659*7c478bd9Sstevel@tonic-gate for (op = SH_TAILQ_FIRST(&lrp->free_objs, __db_lockobj); 660*7c478bd9Sstevel@tonic-gate op != NULL; 661*7c478bd9Sstevel@tonic-gate op = SH_TAILQ_NEXT(op, links, __db_lockobj)) 662*7c478bd9Sstevel@tonic-gate fprintf(fp, "0x%lx\n", (u_long)op); 663*7c478bd9Sstevel@tonic-gate } 664*7c478bd9Sstevel@tonic-gate 665*7c478bd9Sstevel@tonic-gate if (LF_ISSET(LOCK_DUMP_MEM)) 666*7c478bd9Sstevel@tonic-gate __db_shalloc_dump(lt->mem, fp); 667*7c478bd9Sstevel@tonic-gate } 668*7c478bd9Sstevel@tonic-gate 669*7c478bd9Sstevel@tonic-gate static void 670*7c478bd9Sstevel@tonic-gate __lock_dump_locker(lt, op, fp) 671*7c478bd9Sstevel@tonic-gate DB_LOCKTAB *lt; 672*7c478bd9Sstevel@tonic-gate DB_LOCKOBJ *op; 673*7c478bd9Sstevel@tonic-gate FILE *fp; 674*7c478bd9Sstevel@tonic-gate { 675*7c478bd9Sstevel@tonic-gate struct __db_lock *lp; 676*7c478bd9Sstevel@tonic-gate u_int32_t locker; 677*7c478bd9Sstevel@tonic-gate void *ptr; 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate ptr = SH_DBT_PTR(&op->lockobj); 680*7c478bd9Sstevel@tonic-gate memcpy(&locker, ptr, sizeof(u_int32_t)); 681*7c478bd9Sstevel@tonic-gate fprintf(fp, "L %lx", (u_long)locker); 682*7c478bd9Sstevel@tonic-gate 683*7c478bd9Sstevel@tonic-gate lp = SH_LIST_FIRST(&op->heldby, __db_lock); 684*7c478bd9Sstevel@tonic-gate if (lp == NULL) { 685*7c478bd9Sstevel@tonic-gate fprintf(fp, "\n"); 686*7c478bd9Sstevel@tonic-gate return; 687*7c478bd9Sstevel@tonic-gate } 688*7c478bd9Sstevel@tonic-gate for (; lp != NULL; lp = SH_LIST_NEXT(lp, locker_links, __db_lock)) 689*7c478bd9Sstevel@tonic-gate __lock_printlock(lt, lp, 0); 690*7c478bd9Sstevel@tonic-gate } 691*7c478bd9Sstevel@tonic-gate 692*7c478bd9Sstevel@tonic-gate static void 693*7c478bd9Sstevel@tonic-gate __lock_dump_object(lt, op, fp) 694*7c478bd9Sstevel@tonic-gate DB_LOCKTAB *lt; 695*7c478bd9Sstevel@tonic-gate DB_LOCKOBJ *op; 696*7c478bd9Sstevel@tonic-gate FILE *fp; 697*7c478bd9Sstevel@tonic-gate { 698*7c478bd9Sstevel@tonic-gate struct __db_lock *lp; 699*7c478bd9Sstevel@tonic-gate u_int32_t j; 700*7c478bd9Sstevel@tonic-gate u_int8_t *ptr; 701*7c478bd9Sstevel@tonic-gate u_int ch; 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate ptr = SH_DBT_PTR(&op->lockobj); 704*7c478bd9Sstevel@tonic-gate for (j = 0; j < op->lockobj.size; ptr++, j++) { 705*7c478bd9Sstevel@tonic-gate ch = *ptr; 706*7c478bd9Sstevel@tonic-gate fprintf(fp, isprint(ch) ? "%c" : "\\%o", ch); 707*7c478bd9Sstevel@tonic-gate } 708*7c478bd9Sstevel@tonic-gate fprintf(fp, "\n"); 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate fprintf(fp, "H:"); 711*7c478bd9Sstevel@tonic-gate for (lp = 712*7c478bd9Sstevel@tonic-gate SH_TAILQ_FIRST(&op->holders, __db_lock); 713*7c478bd9Sstevel@tonic-gate lp != NULL; 714*7c478bd9Sstevel@tonic-gate lp = SH_TAILQ_NEXT(lp, links, __db_lock)) 715*7c478bd9Sstevel@tonic-gate __lock_printlock(lt, lp, 0); 716*7c478bd9Sstevel@tonic-gate lp = SH_TAILQ_FIRST(&op->waiters, __db_lock); 717*7c478bd9Sstevel@tonic-gate if (lp != NULL) { 718*7c478bd9Sstevel@tonic-gate fprintf(fp, "\nW:"); 719*7c478bd9Sstevel@tonic-gate for (; lp != NULL; lp = SH_TAILQ_NEXT(lp, links, __db_lock)) 720*7c478bd9Sstevel@tonic-gate __lock_printlock(lt, lp, 0); 721*7c478bd9Sstevel@tonic-gate } 722*7c478bd9Sstevel@tonic-gate } 723*7c478bd9Sstevel@tonic-gate 724*7c478bd9Sstevel@tonic-gate static const char * 725*7c478bd9Sstevel@tonic-gate __lock_dump_status(status) 726*7c478bd9Sstevel@tonic-gate db_status_t status; 727*7c478bd9Sstevel@tonic-gate { 728*7c478bd9Sstevel@tonic-gate switch (status) { 729*7c478bd9Sstevel@tonic-gate case DB_LSTAT_ABORTED: 730*7c478bd9Sstevel@tonic-gate return ("aborted"); 731*7c478bd9Sstevel@tonic-gate case DB_LSTAT_ERR: 732*7c478bd9Sstevel@tonic-gate return ("err"); 733*7c478bd9Sstevel@tonic-gate case DB_LSTAT_FREE: 734*7c478bd9Sstevel@tonic-gate return ("free"); 735*7c478bd9Sstevel@tonic-gate case DB_LSTAT_HELD: 736*7c478bd9Sstevel@tonic-gate return ("held"); 737*7c478bd9Sstevel@tonic-gate case DB_LSTAT_NOGRANT: 738*7c478bd9Sstevel@tonic-gate return ("nogrant"); 739*7c478bd9Sstevel@tonic-gate case DB_LSTAT_PENDING: 740*7c478bd9Sstevel@tonic-gate return ("pending"); 741*7c478bd9Sstevel@tonic-gate case DB_LSTAT_WAITING: 742*7c478bd9Sstevel@tonic-gate return ("waiting"); 743*7c478bd9Sstevel@tonic-gate } 744*7c478bd9Sstevel@tonic-gate return ("unknown status"); 745*7c478bd9Sstevel@tonic-gate } 746