|
@@ -0,0 +1,212 @@
|
|
1
|
+diff -urN db-4.7.25.NC/lock/lock_deadlock.c db-4.7.25.NC.new/lock/lock_deadlock.c
|
|
2
|
+--- db-4.7.25.NC/lock/lock_deadlock.c 2008-03-10 14:31:33.000000000 +0100
|
|
3
|
++++ db-4.7.25.NC.new/lock/lock_deadlock.c 2009-11-08 12:53:25.000000000 +0100
|
|
4
|
+@@ -121,7 +121,7 @@
|
|
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 *bitmap, *copymap, **deadp, **deadlist, *tmpmap;
|
|
10
|
+ u_int32_t i, cid, keeper, killid, limit, nalloc, nlockers;
|
|
11
|
+ u_int32_t lock_max, txn_max;
|
|
12
|
+ int ret, status;
|
|
13
|
+@@ -133,7 +133,8 @@
|
|
14
|
+ if (IS_REP_CLIENT(env))
|
|
15
|
+ atype = DB_LOCK_MINWRITE;
|
|
16
|
+
|
|
17
|
+- free_me = NULL;
|
|
18
|
++ copymap = tmpmap = NULL;
|
|
19
|
++ deadlist = NULL;
|
|
20
|
+
|
|
21
|
+ lt = env->lk_handle;
|
|
22
|
+ if (rejectp != NULL)
|
|
23
|
+@@ -179,11 +180,11 @@
|
|
24
|
+ memcpy(copymap, bitmap, nlockers * sizeof(u_int32_t) * nalloc);
|
|
25
|
+
|
|
26
|
+ if ((ret = __os_calloc(env, sizeof(u_int32_t), nalloc, &tmpmap)) != 0)
|
|
27
|
+- goto err1;
|
|
28
|
++ goto err;
|
|
29
|
+
|
|
30
|
+ /* Find a deadlock. */
|
|
31
|
+ if ((ret =
|
|
32
|
+- __dd_find(env, bitmap, idmap, nlockers, nalloc, &deadp)) != 0)
|
|
33
|
++ __dd_find(env, bitmap, idmap, nlockers, nalloc, &deadlist)) != 0)
|
|
34
|
+ return (ret);
|
|
35
|
+
|
|
36
|
+ /*
|
|
37
|
+@@ -204,8 +205,7 @@
|
|
38
|
+ txn_max = TXN_MAXIMUM;
|
|
39
|
+
|
|
40
|
+ killid = BAD_KILLID;
|
|
41
|
+- free_me = deadp;
|
|
42
|
+- for (; *deadp != NULL; deadp++) {
|
|
43
|
++ for (deadp = deadlist; *deadp != NULL; deadp++) {
|
|
44
|
+ if (rejectp != NULL)
|
|
45
|
+ ++*rejectp;
|
|
46
|
+ killid = (u_int32_t)(*deadp - bitmap) / nalloc;
|
|
47
|
+@@ -342,11 +342,12 @@
|
|
48
|
+ __db_msg(env,
|
|
49
|
+ "Aborting locker %lx", (u_long)idmap[killid].id);
|
|
50
|
+ }
|
|
51
|
+- __os_free(env, tmpmap);
|
|
52
|
+-err1: __os_free(env, copymap);
|
|
53
|
+-
|
|
54
|
+-err: if (free_me != NULL)
|
|
55
|
+- __os_free(env, free_me);
|
|
56
|
++err: if(copymap != NULL)
|
|
57
|
++ __os_free(env, copymap);
|
|
58
|
++ if (deadlist != NULL)
|
|
59
|
++ __os_free(env, deadlist);
|
|
60
|
++ if(tmpmap != NULL)
|
|
61
|
++ __os_free(env, tmpmap);
|
|
62
|
+ __os_free(env, bitmap);
|
|
63
|
+ __os_free(env, idmap);
|
|
64
|
+
|
|
65
|
+@@ -360,6 +361,17 @@
|
|
66
|
+
|
|
67
|
+ #define DD_INVALID_ID ((u_int32_t) -1)
|
|
68
|
+
|
|
69
|
++/*
|
|
70
|
++ * __dd_build --
|
|
71
|
++ * Build the lock dependency bit maps.
|
|
72
|
++ * Notes on syncronization:
|
|
73
|
++ * LOCK_SYSTEM_LOCK is used to hold objects locked when we have
|
|
74
|
++ * a single partition.
|
|
75
|
++ * LOCK_LOCKERS is held while we are walking the lockers list and
|
|
76
|
++ * to single thread the use of lockerp->dd_id.
|
|
77
|
++ * LOCK_DD protects the DD list of objects.
|
|
78
|
++ */
|
|
79
|
++
|
|
80
|
+ static int
|
|
81
|
+ __dd_build(env, atype, bmp, nlockers, allocp, idmap, rejectp)
|
|
82
|
+ ENV *env;
|
|
83
|
+@@ -393,6 +405,7 @@
|
|
84
|
+ * In particular we do not build the conflict array and our caller
|
|
85
|
+ * needs to expect this.
|
|
86
|
+ */
|
|
87
|
++ LOCK_SYSTEM_LOCK(lt, region);
|
|
88
|
+ if (atype == DB_LOCK_EXPIRE) {
|
|
89
|
+ skip: LOCK_DD(env, region);
|
|
90
|
+ op = SH_TAILQ_FIRST(®ion->dd_objs, __db_lockobj);
|
|
91
|
+@@ -430,17 +443,18 @@
|
|
92
|
+ OBJECT_UNLOCK(lt, region, indx);
|
|
93
|
+ }
|
|
94
|
+ UNLOCK_DD(env, region);
|
|
95
|
++ LOCK_SYSTEM_UNLOCK(lt, region);
|
|
96
|
+ goto done;
|
|
97
|
+ }
|
|
98
|
+
|
|
99
|
+ /*
|
|
100
|
+- * We'll check how many lockers there are, add a few more in for
|
|
101
|
+- * good measure and then allocate all the structures. Then we'll
|
|
102
|
+- * verify that we have enough room when we go back in and get the
|
|
103
|
+- * mutex the second time.
|
|
104
|
++ * Allocate after locking the region
|
|
105
|
++ * to make sure the structures are large enough.
|
|
106
|
+ */
|
|
107
|
+-retry: count = region->stat.st_nlockers;
|
|
108
|
++ LOCK_LOCKERS(env, region);
|
|
109
|
++ count = region->stat.st_nlockers;
|
|
110
|
+ if (count == 0) {
|
|
111
|
++ UNLOCK_LOCKERS(env, region);
|
|
112
|
+ *nlockers = 0;
|
|
113
|
+ return (0);
|
|
114
|
+ }
|
|
115
|
+@@ -448,50 +462,37 @@
|
|
116
|
+ if (FLD_ISSET(env->dbenv->verbose, DB_VERB_DEADLOCK))
|
|
117
|
+ __db_msg(env, "%lu lockers", (u_long)count);
|
|
118
|
+
|
|
119
|
+- count += 20;
|
|
120
|
+ nentries = (u_int32_t)DB_ALIGN(count, 32) / 32;
|
|
121
|
+
|
|
122
|
+- /*
|
|
123
|
+- * Allocate enough space for a count by count bitmap matrix.
|
|
124
|
+- *
|
|
125
|
+- * XXX
|
|
126
|
+- * We can probably save the malloc's between iterations just
|
|
127
|
+- * reallocing if necessary because count grew by too much.
|
|
128
|
+- */
|
|
129
|
++ /* Allocate enough space for a count by count bitmap matrix. */
|
|
130
|
+ if ((ret = __os_calloc(env, (size_t)count,
|
|
131
|
+- sizeof(u_int32_t) * nentries, &bitmap)) != 0)
|
|
132
|
++ sizeof(u_int32_t) * nentries, &bitmap)) != 0) {
|
|
133
|
++ UNLOCK_LOCKERS(env, region);
|
|
134
|
+ return (ret);
|
|
135
|
++ }
|
|
136
|
+
|
|
137
|
+ if ((ret = __os_calloc(env,
|
|
138
|
+ sizeof(u_int32_t), nentries, &tmpmap)) != 0) {
|
|
139
|
++ UNLOCK_LOCKERS(env, region);
|
|
140
|
+ __os_free(env, bitmap);
|
|
141
|
+ return (ret);
|
|
142
|
+ }
|
|
143
|
+
|
|
144
|
+ if ((ret = __os_calloc(env,
|
|
145
|
+ (size_t)count, sizeof(locker_info), &id_array)) != 0) {
|
|
146
|
++ UNLOCK_LOCKERS(env, region);
|
|
147
|
+ __os_free(env, bitmap);
|
|
148
|
+ __os_free(env, tmpmap);
|
|
149
|
+ return (ret);
|
|
150
|
+ }
|
|
151
|
+
|
|
152
|
+ /*
|
|
153
|
+- * Now go back in and actually fill in the matrix.
|
|
154
|
+- */
|
|
155
|
+- if (region->stat.st_nlockers > count) {
|
|
156
|
+- __os_free(env, bitmap);
|
|
157
|
+- __os_free(env, tmpmap);
|
|
158
|
+- __os_free(env, id_array);
|
|
159
|
+- goto retry;
|
|
160
|
+- }
|
|
161
|
+-
|
|
162
|
+- /*
|
|
163
|
+ * First we go through and assign each locker a deadlock detector id.
|
|
164
|
+ */
|
|
165
|
+ id = 0;
|
|
166
|
+- LOCK_LOCKERS(env, region);
|
|
167
|
+ SH_TAILQ_FOREACH(lip, ®ion->lockers, ulinks, __db_locker) {
|
|
168
|
+ if (lip->master_locker == INVALID_ROFF) {
|
|
169
|
++ DB_ASSERT(env, id < count);
|
|
170
|
+ lip->dd_id = id++;
|
|
171
|
+ id_array[lip->dd_id].id = lip->id;
|
|
172
|
+ switch (atype) {
|
|
173
|
+@@ -510,7 +511,6 @@
|
|
174
|
+ lip->dd_id = DD_INVALID_ID;
|
|
175
|
+
|
|
176
|
+ }
|
|
177
|
+- UNLOCK_LOCKERS(env, region);
|
|
178
|
+
|
|
179
|
+ /*
|
|
180
|
+ * We only need consider objects that have waiters, so we use
|
|
181
|
+@@ -669,7 +669,6 @@
|
|
182
|
+ * status after building the bit maps so that we will not detect
|
|
183
|
+ * a blocked transaction without noting that it is already aborting.
|
|
184
|
+ */
|
|
185
|
+- LOCK_LOCKERS(env, region);
|
|
186
|
+ for (id = 0; id < count; id++) {
|
|
187
|
+ if (!id_array[id].valid)
|
|
188
|
+ continue;
|
|
189
|
+@@ -738,6 +737,7 @@
|
|
190
|
+ id_array[id].in_abort = 1;
|
|
191
|
+ }
|
|
192
|
+ UNLOCK_LOCKERS(env, region);
|
|
193
|
++ LOCK_SYSTEM_UNLOCK(lt, region);
|
|
194
|
+
|
|
195
|
+ /*
|
|
196
|
+ * Now we can release everything except the bitmap matrix that we
|
|
197
|
+@@ -839,6 +839,7 @@
|
|
198
|
+ ret = 0;
|
|
199
|
+
|
|
200
|
+ /* We must lock so this locker cannot go away while we abort it. */
|
|
201
|
++ LOCK_SYSTEM_LOCK(lt, region);
|
|
202
|
+ LOCK_LOCKERS(env, region);
|
|
203
|
+
|
|
204
|
+ /*
|
|
205
|
+@@ -895,6 +896,7 @@
|
|
206
|
+ done: OBJECT_UNLOCK(lt, region, info->last_ndx);
|
|
207
|
+ err:
|
|
208
|
+ out: UNLOCK_LOCKERS(env, region);
|
|
209
|
++ LOCK_SYSTEM_UNLOCK(lt, region);
|
|
210
|
+ return (ret);
|
|
211
|
+ }
|
|
212
|
+
|