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