00001 /*- 00002 * See the file LICENSE for redistribution information. 00003 * 00004 * Copyright (c) 1996, 1997, 1998, 1999, 2000 00005 * Sleepycat Software. All rights reserved. 00006 * 00007 * $Id: lock_8h-source.html,v 1.1 2008年06月08日 10:19:54 sebdiaz Exp $ 00008 */ 00009 00010 #ifndef DB_LOCK_DEFAULT_N 00011 #define DB_LOCK_DEFAULT_N 1000 /* Default # of locks in region. */ 00012 #endif 00013 00014 /* 00015 * Out of band value for a lock. Locks contain an offset into a lock region, 00016 * so we use an invalid region offset to indicate an invalid or unset lock. 00017 */ 00018 #define LOCK_INVALID INVALID_ROFF 00019 00020 /* 00021 * The locker id space is divided between the transaction manager and the lock 00022 * manager. Lock IDs start at 0 and go to DB_LOCK_MAXID. Txn IDs start at 00023 * DB_LOCK_MAXID + 1 and go up to TXN_INVALID. 00024 */ 00025 #define DB_LOCK_MAXID 0x7fffffff 00026 00027 /* 00028 * DB_LOCKREGION -- 00029 * The lock shared region. 00030 */ 00031 typedef struct __db_lockregion { 00032 u_int32_t id; /* unique id generator */ 00033 u_int32_t need_dd; /* flag for deadlock detector */ 00034 u_int32_t detect; /* run dd on every conflict */ 00035 /* free lock header */ 00036 SH_TAILQ_HEAD(__flock) free_locks; 00037 /* free obj header */ 00038 SH_TAILQ_HEAD(__fobj) free_objs; 00039 /* free locker header */ 00040 SH_TAILQ_HEAD(__flocker) free_lockers; 00041 SH_TAILQ_HEAD(__dobj) dd_objs; /* objects with waiters */ 00042 u_int32_t maxlocks; /* maximum number of locks in table */ 00043 u_int32_t table_size; /* size of hash table */ 00044 u_int32_t nmodes; /* number of lock modes */ 00045 u_int32_t nlockers; /* number of lockers */ 00046 u_int32_t maxnlockers; /* maximum number of lockers */ 00047 roff_t conf_off; /* offset of conflicts array */ 00048 roff_t obj_off; /* offset of object hash table */ 00049 roff_t osynch_off; /* offset of the object mutex table */ 00050 roff_t locker_off; /* offset of locker hash table */ 00051 roff_t lsynch_off; /* offset of the locker mutex table */ 00052 u_int32_t nconflicts; /* number of lock conflicts */ 00053 u_int32_t nrequests; /* number of lock gets */ 00054 u_int32_t nreleases; /* number of lock puts */ 00055 u_int32_t nnowaits; /* number of lock requests that would 00056 have waited without nowait */ 00057 u_int32_t ndeadlocks; /* number of deadlocks */ 00058 } DB_LOCKREGION; 00059 00060 /* 00061 * Since we will store DBTs in shared memory, we need the equivalent of a 00062 * DBT that will work in shared memory. 00063 */ 00064 typedef struct __sh_dbt { 00065 u_int32_t size; /* Byte length. */ 00066 ssize_t off; /* Region offset. */ 00067 } SH_DBT; 00068 00069 #define SH_DBT_PTR(p) ((void *)(((u_int8_t *)(p)) + (p)->off)) 00070 00071 /* 00072 * Object structures; these live in the object hash table. 00073 */ 00074 typedef struct __db_lockobj { 00075 SH_DBT lockobj; /* Identifies object locked. */ 00076 SH_TAILQ_ENTRY links; /* Links for free list or hash list. */ 00077 SH_TAILQ_ENTRY dd_links; /* Links for dd list. */ 00078 SH_TAILQ_HEAD(__wait) waiters; /* List of waiting locks. */ 00079 SH_TAILQ_HEAD(__hold) holders; /* List of held locks. */ 00080 /* Declare room in the object to hold 00081 * typical DB lock structures so that 00082 * we do not have to allocate them from 00083 * shalloc at run-time. */ 00084 u_int8_t objdata[sizeof(struct __db_ilock)]; 00085 } DB_LOCKOBJ; 00086 00087 /* 00088 * Locker structures; these live in the locker hash table. 00089 */ 00090 typedef struct __db_locker { 00091 u_int32_t id; /* Locker id. */ 00092 u_int32_t dd_id; /* Deadlock detector id. */ 00093 size_t master_locker; /* Locker of master transaction. */ 00094 size_t parent_locker; /* Parent of this child. */ 00095 SH_LIST_HEAD(_child) child_locker; /* List of descendant txns; 00096 only used in a "master" 00097 txn. */ 00098 SH_LIST_ENTRY child_link; /* Links transactions in the family; 00099 elements of the child_locker 00100 list. */ 00101 SH_TAILQ_ENTRY links; /* Links for free list. */ 00102 SH_LIST_HEAD(_held) heldby; /* Locks held by this locker. */ 00103 00104 #define DB_LOCKER_DELETED 0x0001 00105 u_int32_t flags; 00106 } DB_LOCKER; 00107 00108 /* 00109 * Lockers can be freed if they are not part of a transaction family. 00110 * Members of a family either point at the master transaction or are 00111 * the master transaction and have children lockers. 00112 */ 00113 #define LOCKER_FREEABLE(lp) \ 00114 ((lp)->master_locker == TXN_INVALID_ID && \ 00115 SH_LIST_FIRST(&(lp)->child_locker, __db_locker) == NULL) 00116 00117 /* 00118 * DB_LOCKTAB -- 00119 * The primary library lock data structure (i.e., the one referenced 00120 * by the environment, as opposed to the internal one laid out in the region.) 00121 */ 00122 typedef struct __db_locktab { 00123 DB_ENV *dbenv; /* Environment. */ 00124 REGINFO reginfo; /* Region information. */ 00125 u_int8_t *conflicts; /* Pointer to conflict matrix. */ 00126 DB_HASHTAB *obj_tab; /* Beginning of object hash table. */ 00127 DB_HASHTAB *locker_tab; /* Beginning of locker hash table. */ 00128 } DB_LOCKTAB; 00129 00130 /* Test for conflicts. */ 00131 #define CONFLICTS(T, R, HELD, WANTED) \ 00132 (T)->conflicts[(HELD) * (R)->nmodes + (WANTED)] 00133 00134 #define OBJ_LINKS_VALID(L) ((L)->links.stqe_prev != -1) 00135 00136 struct __db_lock { 00137 /* 00138 * Wait on mutex to wait on lock. You reference your own mutex with 00139 * ID 0 and others reference your mutex with ID 1. 00140 */ 00141 MUTEX mutex; 00142 00143 u_int32_t holder; /* Who holds this lock. */ 00144 u_int32_t gen; /* Generation count. */ 00145 SH_TAILQ_ENTRY links; /* Free or holder/waiter list. */ 00146 SH_LIST_ENTRY locker_links; /* List of locks held by a locker. */ 00147 u_int32_t refcount; /* Reference count the lock. */ 00148 db_lockmode_t mode; /* What sort of lock. */ 00149 ssize_t obj; /* Relative offset of object struct. */ 00150 db_status_t status; /* Status of this lock. */ 00151 }; 00152 00153 /* 00154 * Flag values for __lock_put_internal: 00155 * DB_LOCK_DOALL: Unlock all references in this lock (instead of only 1). 00156 * DB_LOCK_FREE: Free the lock (used in checklocker). 00157 * DB_LOCK_IGNOREDEL: Remove from the locker hash table even if already 00158 deleted (used in checklocker). 00159 * DB_LOCK_NOPROMOTE: Don't bother running promotion when releasing locks 00160 * (used by __lock_put_internal). 00161 * DB_LOCK_UNLINK: Remove from the locker links (used in checklocker). 00162 */ 00163 #define DB_LOCK_DOALL 0x001 00164 #define DB_LOCK_FREE 0x002 00165 #define DB_LOCK_IGNOREDEL 0x004 00166 #define DB_LOCK_NOPROMOTE 0x008 00167 #define DB_LOCK_UNLINK 0x010 00168 00169 /* 00170 * Macros to get/release different types of mutexes. 00171 */ 00172 #define OBJECT_LOOKUP(lt, ndx, dbt, sh_obj) \ 00173 HASHLOOKUP((lt)->objtab, \ 00174 ndx, __db_lockobj, links, dbt, sh_obj, CDB___lock_cmp); 00175 00176 #define OBJECT_LOCK(lt, reg, obj, ndx) \ 00177 ndx = CDB___lock_ohash(obj) % (reg)->table_size 00178 #define SHOBJECT_LOCK(lt, reg, shobj, ndx) \ 00179 ndx = CDB___lock_lhash(shobj) % (reg)->table_size 00180 #define OBJECT_UNLOCK(lt, ndx) 00181 00182 #define LOCKER_LOOKUP(lt, ndx, locker, sh_locker) \ 00183 HASHLOOKUP((lt)->lockertab, \ 00184 ndx, __db_locker, links, locker, sh_locker, CDB___lock_locker_cmp); 00185 00186 #define LOCKREGION(dbenv, lt) R_LOCK((dbenv), &(lt)->reginfo) 00187 #define UNLOCKREGION(dbenv, lt) R_UNLOCK((dbenv), &(lt)->reginfo) 00188 #include "lock_ext.h"