]>
Commit | Line | Data |
---|---|---|
77a24bd5 AM |
1 | *** lock/lock_deadlock.c 2008-03-11 00:31:33.000000000 +1100 |
2 | --- lock/lock_deadlock.c 2008-12-16 21:54:18.000000000 +1100 | |
3 | *************** | |
4 | *** 121,127 **** | |
5 | DB_LOCKTAB *lt; | |
6 | db_timespec now; | |
7 | locker_info *idmap; | |
8 | ! u_int32_t *bitmap, *copymap, **deadp, **free_me, *tmpmap; | |
9 | u_int32_t i, cid, keeper, killid, limit, nalloc, nlockers; | |
10 | u_int32_t lock_max, txn_max; | |
11 | int ret, status; | |
12 | --- 121,127 ---- | |
13 | DB_LOCKTAB *lt; | |
14 | db_timespec now; | |
15 | locker_info *idmap; | |
16 | ! u_int32_t *bitmap, *copymap, **deadp, **deadlist, *tmpmap; | |
17 | u_int32_t i, cid, keeper, killid, limit, nalloc, nlockers; | |
18 | u_int32_t lock_max, txn_max; | |
19 | int ret, status; | |
20 | *************** | |
21 | *** 133,139 **** | |
22 | if (IS_REP_CLIENT(env)) | |
23 | atype = DB_LOCK_MINWRITE; | |
24 | ||
25 | ! free_me = NULL; | |
26 | ||
27 | lt = env->lk_handle; | |
28 | if (rejectp != NULL) | |
29 | --- 133,140 ---- | |
30 | if (IS_REP_CLIENT(env)) | |
31 | atype = DB_LOCK_MINWRITE; | |
32 | ||
33 | ! copymap = tmpmap = NULL; | |
34 | ! deadlist = NULL; | |
35 | ||
36 | lt = env->lk_handle; | |
37 | if (rejectp != NULL) | |
38 | *************** | |
39 | *** 179,189 **** | |
40 | memcpy(copymap, bitmap, nlockers * sizeof(u_int32_t) * nalloc); | |
41 | ||
42 | if ((ret = __os_calloc(env, sizeof(u_int32_t), nalloc, &tmpmap)) != 0) | |
43 | ! goto err1; | |
44 | ||
45 | /* Find a deadlock. */ | |
46 | if ((ret = | |
47 | ! __dd_find(env, bitmap, idmap, nlockers, nalloc, &deadp)) != 0) | |
48 | return (ret); | |
49 | ||
50 | /* | |
51 | --- 180,190 ---- | |
52 | memcpy(copymap, bitmap, nlockers * sizeof(u_int32_t) * nalloc); | |
53 | ||
54 | if ((ret = __os_calloc(env, sizeof(u_int32_t), nalloc, &tmpmap)) != 0) | |
55 | ! goto err; | |
56 | ||
57 | /* Find a deadlock. */ | |
58 | if ((ret = | |
59 | ! __dd_find(env, bitmap, idmap, nlockers, nalloc, &deadlist)) != 0) | |
60 | return (ret); | |
61 | ||
62 | /* | |
63 | *************** | |
64 | *** 204,211 **** | |
65 | txn_max = TXN_MAXIMUM; | |
66 | ||
67 | killid = BAD_KILLID; | |
68 | ! free_me = deadp; | |
69 | ! for (; *deadp != NULL; deadp++) { | |
70 | if (rejectp != NULL) | |
71 | ++*rejectp; | |
72 | killid = (u_int32_t)(*deadp - bitmap) / nalloc; | |
73 | --- 205,211 ---- | |
74 | txn_max = TXN_MAXIMUM; | |
75 | ||
76 | killid = BAD_KILLID; | |
77 | ! for (deadp = deadlist; *deadp != NULL; deadp++) { | |
78 | if (rejectp != NULL) | |
79 | ++*rejectp; | |
80 | killid = (u_int32_t)(*deadp - bitmap) / nalloc; | |
81 | *************** | |
82 | *** 342,352 **** | |
83 | __db_msg(env, | |
84 | "Aborting locker %lx", (u_long)idmap[killid].id); | |
85 | } | |
86 | ! __os_free(env, tmpmap); | |
87 | ! err1: __os_free(env, copymap); | |
88 | ! | |
89 | ! err: if (free_me != NULL) | |
90 | ! __os_free(env, free_me); | |
91 | __os_free(env, bitmap); | |
92 | __os_free(env, idmap); | |
93 | ||
94 | --- 342,353 ---- | |
95 | __db_msg(env, | |
96 | "Aborting locker %lx", (u_long)idmap[killid].id); | |
97 | } | |
98 | ! err: if(copymap != NULL) | |
99 | ! __os_free(env, copymap); | |
100 | ! if (deadlist != NULL) | |
101 | ! __os_free(env, deadlist); | |
102 | ! if(tmpmap != NULL) | |
103 | ! __os_free(env, tmpmap); | |
104 | __os_free(env, bitmap); | |
105 | __os_free(env, idmap); | |
106 | ||
107 | *************** | |
108 | *** 360,365 **** | |
109 | --- 361,377 ---- | |
110 | ||
111 | #define DD_INVALID_ID ((u_int32_t) -1) | |
112 | ||
113 | + /* | |
114 | + * __dd_build -- | |
115 | + * Build the lock dependency bit maps. | |
116 | + * Notes on syncronization: | |
117 | + * LOCK_SYSTEM_LOCK is used to hold objects locked when we have | |
118 | + * a single partition. | |
119 | + * LOCK_LOCKERS is held while we are walking the lockers list and | |
120 | + * to single thread the use of lockerp->dd_id. | |
121 | + * LOCK_DD protects the DD list of objects. | |
122 | + */ | |
123 | + | |
124 | static int | |
125 | __dd_build(env, atype, bmp, nlockers, allocp, idmap, rejectp) | |
126 | ENV *env; | |
127 | *************** | |
128 | *** 393,398 **** | |
129 | --- 405,411 ---- | |
130 | * In particular we do not build the conflict array and our caller | |
131 | * needs to expect this. | |
132 | */ | |
133 | + LOCK_SYSTEM_LOCK(lt, region); | |
134 | if (atype == DB_LOCK_EXPIRE) { | |
135 | skip: LOCK_DD(env, region); | |
136 | op = SH_TAILQ_FIRST(®ion->dd_objs, __db_lockobj); | |
137 | *************** | |
138 | *** 430,446 **** | |
139 | OBJECT_UNLOCK(lt, region, indx); | |
140 | } | |
141 | UNLOCK_DD(env, region); | |
142 | goto done; | |
143 | } | |
144 | ||
145 | /* | |
146 | ! * We'll check how many lockers there are, add a few more in for | |
147 | ! * good measure and then allocate all the structures. Then we'll | |
148 | ! * verify that we have enough room when we go back in and get the | |
149 | ! * mutex the second time. | |
150 | */ | |
151 | ! retry: count = region->stat.st_nlockers; | |
152 | if (count == 0) { | |
153 | *nlockers = 0; | |
154 | return (0); | |
155 | } | |
156 | --- 443,460 ---- | |
157 | OBJECT_UNLOCK(lt, region, indx); | |
158 | } | |
159 | UNLOCK_DD(env, region); | |
160 | + LOCK_SYSTEM_UNLOCK(lt, region); | |
161 | goto done; | |
162 | } | |
163 | ||
164 | /* | |
165 | ! * Allocate after locking the region | |
166 | ! * to make sure the structures are large enough. | |
167 | */ | |
168 | ! LOCK_LOCKERS(env, region); | |
169 | ! count = region->stat.st_nlockers; | |
170 | if (count == 0) { | |
171 | + UNLOCK_LOCKERS(env, region); | |
172 | *nlockers = 0; | |
173 | return (0); | |
174 | } | |
175 | *************** | |
176 | *** 448,497 **** | |
177 | if (FLD_ISSET(env->dbenv->verbose, DB_VERB_DEADLOCK)) | |
178 | __db_msg(env, "%lu lockers", (u_long)count); | |
179 | ||
180 | - count += 20; | |
181 | nentries = (u_int32_t)DB_ALIGN(count, 32) / 32; | |
182 | ||
183 | ! /* | |
184 | ! * Allocate enough space for a count by count bitmap matrix. | |
185 | ! * | |
186 | ! * XXX | |
187 | ! * We can probably save the malloc's between iterations just | |
188 | ! * reallocing if necessary because count grew by too much. | |
189 | ! */ | |
190 | if ((ret = __os_calloc(env, (size_t)count, | |
191 | ! sizeof(u_int32_t) * nentries, &bitmap)) != 0) | |
192 | return (ret); | |
193 | ||
194 | if ((ret = __os_calloc(env, | |
195 | sizeof(u_int32_t), nentries, &tmpmap)) != 0) { | |
196 | __os_free(env, bitmap); | |
197 | return (ret); | |
198 | } | |
199 | ||
200 | if ((ret = __os_calloc(env, | |
201 | (size_t)count, sizeof(locker_info), &id_array)) != 0) { | |
202 | __os_free(env, bitmap); | |
203 | __os_free(env, tmpmap); | |
204 | return (ret); | |
205 | } | |
206 | ||
207 | /* | |
208 | - * Now go back in and actually fill in the matrix. | |
209 | - */ | |
210 | - if (region->stat.st_nlockers > count) { | |
211 | - __os_free(env, bitmap); | |
212 | - __os_free(env, tmpmap); | |
213 | - __os_free(env, id_array); | |
214 | - goto retry; | |
215 | - } | |
216 | - | |
217 | - /* | |
218 | * First we go through and assign each locker a deadlock detector id. | |
219 | */ | |
220 | id = 0; | |
221 | - LOCK_LOCKERS(env, region); | |
222 | SH_TAILQ_FOREACH(lip, ®ion->lockers, ulinks, __db_locker) { | |
223 | if (lip->master_locker == INVALID_ROFF) { | |
224 | lip->dd_id = id++; | |
225 | id_array[lip->dd_id].id = lip->id; | |
226 | switch (atype) { | |
227 | --- 462,498 ---- | |
228 | if (FLD_ISSET(env->dbenv->verbose, DB_VERB_DEADLOCK)) | |
229 | __db_msg(env, "%lu lockers", (u_long)count); | |
230 | ||
231 | nentries = (u_int32_t)DB_ALIGN(count, 32) / 32; | |
232 | ||
233 | ! /* Allocate enough space for a count by count bitmap matrix. */ | |
234 | if ((ret = __os_calloc(env, (size_t)count, | |
235 | ! sizeof(u_int32_t) * nentries, &bitmap)) != 0) { | |
236 | ! UNLOCK_LOCKERS(env, region); | |
237 | return (ret); | |
238 | + } | |
239 | ||
240 | if ((ret = __os_calloc(env, | |
241 | sizeof(u_int32_t), nentries, &tmpmap)) != 0) { | |
242 | + UNLOCK_LOCKERS(env, region); | |
243 | __os_free(env, bitmap); | |
244 | return (ret); | |
245 | } | |
246 | ||
247 | if ((ret = __os_calloc(env, | |
248 | (size_t)count, sizeof(locker_info), &id_array)) != 0) { | |
249 | + UNLOCK_LOCKERS(env, region); | |
250 | __os_free(env, bitmap); | |
251 | __os_free(env, tmpmap); | |
252 | return (ret); | |
253 | } | |
254 | ||
255 | /* | |
256 | * First we go through and assign each locker a deadlock detector id. | |
257 | */ | |
258 | id = 0; | |
259 | SH_TAILQ_FOREACH(lip, ®ion->lockers, ulinks, __db_locker) { | |
260 | if (lip->master_locker == INVALID_ROFF) { | |
261 | + DB_ASSERT(env, id < count); | |
262 | lip->dd_id = id++; | |
263 | id_array[lip->dd_id].id = lip->id; | |
264 | switch (atype) { | |
265 | *************** | |
266 | *** 510,516 **** | |
267 | lip->dd_id = DD_INVALID_ID; | |
268 | ||
269 | } | |
270 | - UNLOCK_LOCKERS(env, region); | |
271 | ||
272 | /* | |
273 | * We only need consider objects that have waiters, so we use | |
274 | --- 511,516 ---- | |
275 | *************** | |
276 | *** 669,675 **** | |
277 | * status after building the bit maps so that we will not detect | |
278 | * a blocked transaction without noting that it is already aborting. | |
279 | */ | |
280 | - LOCK_LOCKERS(env, region); | |
281 | for (id = 0; id < count; id++) { | |
282 | if (!id_array[id].valid) | |
283 | continue; | |
284 | --- 669,674 ---- | |
285 | *************** | |
286 | *** 738,743 **** | |
287 | --- 737,743 ---- | |
288 | id_array[id].in_abort = 1; | |
289 | } | |
290 | UNLOCK_LOCKERS(env, region); | |
291 | + LOCK_SYSTEM_UNLOCK(lt, region); | |
292 | ||
293 | /* | |
294 | * Now we can release everything except the bitmap matrix that we | |
295 | *************** | |
296 | *** 839,844 **** | |
297 | --- 839,845 ---- | |
298 | ret = 0; | |
299 | ||
300 | /* We must lock so this locker cannot go away while we abort it. */ | |
301 | + LOCK_SYSTEM_LOCK(lt, region); | |
302 | LOCK_LOCKERS(env, region); | |
303 | ||
304 | /* | |
305 | *************** | |
306 | *** 895,900 **** | |
307 | --- 896,902 ---- | |
308 | done: OBJECT_UNLOCK(lt, region, info->last_ndx); | |
309 | err: | |
310 | out: UNLOCK_LOCKERS(env, region); | |
311 | + LOCK_SYSTEM_UNLOCK(lt, region); | |
312 | return (ret); | |
313 | } | |
314 |