Update from db-2.3.12.
[kopensolaris-gnu/glibc.git] / db2 / include / lock.h
1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 1996, 1997
5  *      Sleepycat Software.  All rights reserved.
6  *
7  *      @(#)lock.h      10.9 (Sleepycat) 10/25/97
8  */
9
10 typedef struct __db_lockobj     DB_LOCKOBJ;
11
12 #define DB_DEFAULT_LOCK_FILE    "__db_lock.share"
13 #define DB_LOCK_DEFAULT_N       5000
14
15 /*
16  * The locker id space is divided between the transaction manager and the lock
17  * manager.  Lockid's start at 0 and go to DB_LOCK_MAXID.  Txn Id's start at
18  * DB_LOCK_MAXID + 1 and go up to TXN_INVALID.
19  */
20 #define DB_LOCK_MAXID           0x7fffffff
21
22 /*
23  * The lock region consists of:
24  *      The DB_LOCKREGION structure (sizeof(DB_LOCKREGION)).
25  *      The conflict matrix of nmodes * nmodes bytes (nmodes * nmodes).
26  *      The hash table for object lookup (hashsize * sizeof(DB_OBJ *)).
27  *      The locks themselves (maxlocks * sizeof(struct __db_lock).
28  *      The objects being locked (maxlocks * sizeof(DB_OBJ)).
29  *      String space to represent the DBTs that are the objects being locked.
30  */
31 struct __db_lockregion {
32         RLAYOUT         hdr;            /* Shared region header. */
33         u_int32_t       magic;          /* lock magic number */
34         u_int32_t       version;        /* version number */
35         u_int32_t       id;             /* unique id generator */
36         u_int32_t       need_dd;        /* flag for deadlock detector */
37         u_int32_t       detect;         /* run dd on every conflict */
38         SH_TAILQ_HEAD(lock_header) free_locks;  /* free lock header */
39         SH_TAILQ_HEAD(obj_header) free_objs;    /* free obj header */
40         u_int32_t       maxlocks;       /* maximum number of locks in table */
41         u_int32_t       table_size;     /* size of hash table */
42         u_int32_t       nmodes;         /* number of lock modes */
43         u_int32_t       numobjs;        /* number of objects */
44         u_int32_t       nlockers;       /* number of lockers */
45         size_t          increment;      /* how much to grow region */
46         size_t          hash_off;       /* offset of hash table */
47         size_t          mem_off;        /* offset of memory region */
48         size_t          mem_bytes;      /* number of bytes in memory region */
49         u_int32_t       nconflicts;     /* number of lock conflicts */
50         u_int32_t       nrequests;      /* number of lock gets */
51         u_int32_t       nreleases;      /* number of lock puts */
52         u_int32_t       ndeadlocks;     /* number of deadlocks */
53 };
54
55 /* Macros to lock/unlock the region. */
56 #define LOCK_LOCKREGION(lt)                                             \
57         (void)__db_mutex_lock(&(lt)->region->hdr.lock, (lt)->fd)
58 #define UNLOCK_LOCKREGION(lt)                                           \
59         (void)__db_mutex_unlock(&(lt)->region->hdr.lock, (lt)->fd)
60
61 /*
62  * Since we will be keeping DBTs in shared memory, we need the equivalent
63  * of a DBT that will work in shared memory.
64  */
65 typedef struct __sh_dbt {
66         u_int32_t size;
67         ssize_t off;
68 } SH_DBT;
69
70 #define SH_DBT_PTR(p)   ((void *)(((u_int8_t *)(p)) + (p)->off))
71
72 /*
73  * The lock table is the per-process cookie returned from a lock_open call.
74  */
75 struct __db_lockobj {
76         SH_DBT  lockobj;                /* Identifies object locked. */
77         SH_TAILQ_ENTRY links;           /* Links for free list. */
78         union {
79                 SH_TAILQ_HEAD(_wait) _waiters;  /* List of waiting locks. */
80                 u_int32_t       _dd_id;         /* Deadlock detector id. */
81         } wlinks;
82         union {
83                 SH_LIST_HEAD(_held) _heldby;    /* Locks held by this locker. */
84                 SH_TAILQ_HEAD(_hold) _holders;  /* List of held locks. */
85         } dlinks;
86 #define DB_LOCK_OBJTYPE         1
87 #define DB_LOCK_LOCKER          2
88         u_int8_t type;                  /* Real object or locker id. */
89 };
90
91
92 #define dd_id   wlinks._dd_id
93 #define waiters wlinks._waiters
94 #define holders dlinks._holders
95 #define heldby  dlinks._heldby
96
97 struct __db_locktab {
98         DB_ENV          *dbenv;         /* Environment. */
99         int              fd;            /* mapped file descriptor */
100         DB_LOCKREGION   *region;        /* address of shared memory region */
101         DB_HASHTAB      *hashtab;       /* Beginning of hash table. */
102         size_t          reg_size;       /* last known size of lock region */
103         void            *mem;           /* Beginning of string space. */
104         u_int8_t        *conflicts;     /* Pointer to conflict matrix. */
105 };
106
107 /* Test for conflicts. */
108 #define CONFLICTS(T, HELD, WANTED) \
109         T->conflicts[HELD * T->region->nmodes + WANTED]
110
111 /*
112  * Status of a lock.
113  */
114 typedef enum {
115         DB_LSTAT_ABORTED,               /* Lock belongs to an aborted txn. */
116         DB_LSTAT_ERR,                   /* Lock is bad. */
117         DB_LSTAT_FREE,                  /* Lock is unallocated. */
118         DB_LSTAT_HELD,                  /* Lock is currently held. */
119         DB_LSTAT_NOGRANT,               /* Lock was not granted. */
120         DB_LSTAT_PENDING,               /* Lock was waiting and has been
121                                          * promoted; waiting for the owner
122                                          * to run and upgrade it to held. */
123         DB_LSTAT_WAITING                /* Lock is on the wait queue. */
124 } db_status_t;
125
126 /*
127  * Resources in the lock region.  Used to indicate which resource
128  * is running low when we need to grow the region.
129  */
130 typedef enum {
131         DB_LOCK_MEM, DB_LOCK_OBJ, DB_LOCK_LOCK
132 } db_resource_t;
133
134 struct __db_lock {
135         /*
136          * Wait on mutex to wait on lock.  You reference your own mutex with
137          * ID 0 and others reference your mutex with ID 1.
138          */
139         db_mutex_t      mutex;
140
141         u_int32_t       holder;         /* Who holds this lock. */
142         SH_TAILQ_ENTRY  links;          /* Free or holder/waiter list. */
143         SH_LIST_ENTRY   locker_links;   /* List of locks held by a locker. */
144         u_int32_t       refcount;       /* Reference count the lock. */
145         db_lockmode_t   mode;           /* What sort of lock. */
146         ssize_t         obj;            /* Relative offset of object struct. */
147         db_status_t     status;         /* Status of this lock. */
148 };
149
150 /*
151  * We cannot return pointers to the user (else we cannot easily grow regions),
152  * so we return offsets in the region.  These must be converted to and from
153  * regular pointers.  Always use the macros below.
154  */
155 #define OFFSET_TO_LOCK(lt, off) \
156         ((struct __db_lock *)((u_int8_t *)((lt)->region) + (off)))
157 #define LOCK_TO_OFFSET(lt, lock) \
158         ((size_t)((u_int8_t *)(lock) - (u_int8_t *)lt->region))
159 #define OFFSET_TO_OBJ(lt, off)  \
160         ((DB_LOCKOBJ *)((u_int8_t *)((lt)->region) + (off)))
161 #define OBJ_TO_OFFSET(lt, obj) \
162         ((size_t)((u_int8_t *)(obj) - (u_int8_t *)lt->region))
163
164 /*
165  * The lock header contains the region structure and the conflict matrix.
166  * Aligned to a large boundary because we don't know what the underlying
167  * type of the hash table elements are.
168  */
169 #define LOCK_HASH_ALIGN 8
170 #define LOCK_HEADER_SIZE(M)     \
171         ((size_t)(sizeof(DB_LOCKREGION) + ALIGN((M * M), LOCK_HASH_ALIGN)))
172
173 /*
174  * For the full region, we need to add the locks, the objects, the hash table
175  * and the string space (which is 16 bytes per lock).
176  */
177 #define STRING_SIZE(N) (16 * N)
178
179 #define LOCK_REGION_SIZE(M, N, H)                                       \
180         (ALIGN(LOCK_HEADER_SIZE(M) +                                    \
181         (H) * sizeof(DB_HASHTAB), MUTEX_ALIGNMENT) +                    \
182         (N) * ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT) +        \
183         ALIGN((N) * sizeof(DB_LOCKOBJ), sizeof(size_t)) +               \
184         ALIGN(STRING_SIZE(N), sizeof(size_t)))
185
186 #ifdef DEBUG
187 #define LOCK_DEBUG_LOCKERS      0x0001
188 #define LOCK_DEBUG_LOCK         0x0002
189 #define LOCK_DEBUG_OBJ          0x0004
190 #define LOCK_DEBUG_CONF         0x0008
191 #define LOCK_DEBUG_MEM          0x0010
192 #define LOCK_DEBUG_BUCKET       0x0020
193 #define LOCK_DEBUG_OBJECTS      0x0040
194 #define LOCK_DEBUG_ALL          0xFFFF
195
196 #define LOCK_DEBUG_NOMUTEX      0x0100
197 #endif
198
199 #include "lock_ext.h"