]>
Commit | Line | Data |
---|---|---|
31696e2e AM |
1 | diff -ruN mysql-5.1.29-rc_orig/storage/innobase/include/sync0rw.h mysql-5.1.29-rc/storage/innobase/include/sync0rw.h |
2 | --- mysql-5.1.29-rc_orig/storage/innobase/include/sync0rw.h 2008-10-12 06:54:14.000000000 +0900 | |
3 | +++ mysql-5.1.29-rc/storage/innobase/include/sync0rw.h 2008-11-17 15:34:00.000000000 +0900 | |
4 | @@ -328,7 +328,17 @@ | |
5 | Accessor functions for rw lock. */ | |
6 | UNIV_INLINE | |
7 | ulint | |
8 | -rw_lock_get_waiters( | |
9 | +rw_lock_get_s_waiters( | |
10 | +/*==================*/ | |
11 | + rw_lock_t* lock); | |
12 | +UNIV_INLINE | |
13 | +ulint | |
14 | +rw_lock_get_x_waiters( | |
15 | +/*==================*/ | |
16 | + rw_lock_t* lock); | |
17 | +UNIV_INLINE | |
18 | +ulint | |
19 | +rw_lock_get_wx_waiters( | |
20 | /*================*/ | |
21 | rw_lock_t* lock); | |
22 | UNIV_INLINE | |
23 | @@ -412,6 +422,11 @@ | |
24 | rw_lock_debug_t* info); /* in: debug struct */ | |
25 | #endif /* UNIV_SYNC_DEBUG */ | |
26 | ||
27 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
28 | +/* This value means NOT_LOCKED */ | |
29 | +#define RW_LOCK_BIAS 0x00100000 | |
30 | +#endif | |
31 | + | |
32 | /* NOTE! The structure appears here only for the compiler to know its size. | |
33 | Do not use its fields directly! The structure used in the spin lock | |
34 | implementation of a read-write lock. Several threads may have a shared lock | |
35 | @@ -421,9 +436,9 @@ | |
36 | field. Then no new readers are allowed in. */ | |
37 | ||
38 | struct rw_lock_struct { | |
39 | - os_event_t event; /* Used by sync0arr.c for thread queueing */ | |
40 | - | |
41 | -#ifdef __WIN__ | |
42 | + /* Used by sync0arr.c for thread queueing */ | |
43 | + os_event_t s_event; /* Used for s_lock */ | |
44 | + os_event_t x_event; /* Used for x_lock */ | |
45 | os_event_t wait_ex_event; /* This windows specific event is | |
46 | used by the thread which has set the | |
47 | lock state to RW_LOCK_WAIT_EX. The | |
48 | @@ -431,30 +446,34 @@ | |
49 | thread will be the next one to proceed | |
50 | once the current the event gets | |
51 | signalled. See LEMMA 2 in sync0sync.c */ | |
52 | + | |
53 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
54 | + volatile lint lock_word; /* Used by using atomic builtin */ | |
55 | #endif | |
56 | ||
57 | - ulint reader_count; /* Number of readers who have locked this | |
58 | + volatile ulint reader_count; /* Number of readers who have locked this | |
59 | lock in the shared mode */ | |
60 | - ulint writer; /* This field is set to RW_LOCK_EX if there | |
61 | + volatile ulint writer; /* This field is set to RW_LOCK_EX if there | |
62 | is a writer owning the lock (in exclusive | |
63 | mode), RW_LOCK_WAIT_EX if a writer is | |
64 | queueing for the lock, and | |
65 | RW_LOCK_NOT_LOCKED, otherwise. */ | |
66 | - os_thread_id_t writer_thread; | |
67 | + volatile os_thread_id_t writer_thread; | |
68 | /* Thread id of a possible writer thread */ | |
69 | - ulint writer_count; /* Number of times the same thread has | |
70 | + volatile ulint writer_count; /* Number of times the same thread has | |
71 | recursively locked the lock in the exclusive | |
72 | mode */ | |
73 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
74 | mutex_t mutex; /* The mutex protecting rw_lock_struct */ | |
75 | +#endif | |
76 | ulint pass; /* Default value 0. This is set to some | |
77 | value != 0 given by the caller of an x-lock | |
78 | operation, if the x-lock is to be passed to | |
79 | another thread to unlock (which happens in | |
80 | asynchronous i/o). */ | |
81 | - ulint waiters; /* This ulint is set to 1 if there are | |
82 | - waiters (readers or writers) in the global | |
83 | - wait array, waiting for this rw_lock. | |
84 | - Otherwise, == 0. */ | |
85 | + volatile ulint s_waiters; /* 1: there are waiters (s_lock) */ | |
86 | + volatile ulint x_waiters; /* 1: there are waiters (x_lock) */ | |
87 | + volatile ulint wait_ex_waiters; /* 1: there are waiters (wait_ex) */ | |
88 | UT_LIST_NODE_T(rw_lock_t) list; | |
89 | /* All allocated rw locks are put into a | |
90 | list */ | |
91 | @@ -467,7 +486,7 @@ | |
92 | const char* cfile_name;/* File name where lock created */ | |
93 | const char* last_s_file_name;/* File name where last s-locked */ | |
94 | const char* last_x_file_name;/* File name where last x-locked */ | |
95 | - ibool writer_is_wait_ex; | |
96 | + volatile ibool writer_is_wait_ex; | |
97 | /* This is TRUE if the writer field is | |
98 | RW_LOCK_WAIT_EX; this field is located far | |
99 | from the memory update hotspot fields which | |
100 | diff -ruN mysql-5.1.29-rc_orig/storage/innobase/include/sync0rw.ic mysql-5.1.29-rc/storage/innobase/include/sync0rw.ic | |
101 | --- mysql-5.1.29-rc_orig/storage/innobase/include/sync0rw.ic 2008-10-12 06:54:14.000000000 +0900 | |
102 | +++ mysql-5.1.29-rc/storage/innobase/include/sync0rw.ic 2008-11-17 16:07:32.000000000 +0900 | |
103 | @@ -47,20 +47,52 @@ | |
104 | Accessor functions for rw lock. */ | |
105 | UNIV_INLINE | |
106 | ulint | |
107 | -rw_lock_get_waiters( | |
108 | +rw_lock_get_s_waiters( | |
109 | /*================*/ | |
110 | rw_lock_t* lock) | |
111 | { | |
112 | - return(lock->waiters); | |
113 | + return(lock->s_waiters); | |
114 | } | |
115 | UNIV_INLINE | |
116 | -void | |
117 | -rw_lock_set_waiters( | |
118 | +ulint | |
119 | +rw_lock_get_x_waiters( | |
120 | +/*================*/ | |
121 | + rw_lock_t* lock) | |
122 | +{ | |
123 | + return(lock->x_waiters); | |
124 | +} | |
125 | +UNIV_INLINE | |
126 | +ulint | |
127 | +rw_lock_get_wx_waiters( | |
128 | /*================*/ | |
129 | + rw_lock_t* lock) | |
130 | +{ | |
131 | + return(lock->wait_ex_waiters); | |
132 | +} | |
133 | +UNIV_INLINE | |
134 | +void | |
135 | +rw_lock_set_s_waiters( | |
136 | + rw_lock_t* lock, | |
137 | + ulint flag) | |
138 | +{ | |
139 | + lock->s_waiters = flag; | |
140 | +} | |
141 | +UNIV_INLINE | |
142 | +void | |
143 | +rw_lock_set_x_waiters( | |
144 | rw_lock_t* lock, | |
145 | ulint flag) | |
146 | { | |
147 | - lock->waiters = flag; | |
148 | + lock->x_waiters = flag; | |
149 | +} | |
150 | +UNIV_INLINE | |
151 | +void | |
152 | +rw_lock_set_wx_waiters( | |
153 | +/*================*/ | |
154 | + rw_lock_t* lock, | |
155 | + ulint flag) | |
156 | +{ | |
157 | + lock->wait_ex_waiters = flag; | |
158 | } | |
159 | UNIV_INLINE | |
160 | ulint | |
161 | @@ -68,7 +100,19 @@ | |
162 | /*===============*/ | |
163 | rw_lock_t* lock) | |
164 | { | |
165 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
166 | + if (lock->writer == RW_LOCK_NOT_LOCKED) { | |
167 | + return(RW_LOCK_NOT_LOCKED); | |
168 | + } | |
169 | + | |
170 | + if (lock->writer_is_wait_ex) { | |
171 | + return(RW_LOCK_WAIT_EX); | |
172 | + } else { | |
173 | + return(RW_LOCK_EX); | |
174 | + } | |
175 | +#else | |
176 | return(lock->writer); | |
177 | +#endif | |
178 | } | |
179 | UNIV_INLINE | |
180 | void | |
181 | @@ -96,6 +140,7 @@ | |
182 | { | |
183 | lock->reader_count = count; | |
184 | } | |
185 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
186 | UNIV_INLINE | |
187 | mutex_t* | |
188 | rw_lock_get_mutex( | |
189 | @@ -104,6 +149,7 @@ | |
190 | { | |
191 | return(&(lock->mutex)); | |
192 | } | |
193 | +#endif | |
194 | ||
195 | /********************************************************************** | |
196 | Returns the value of writer_count for the lock. Does not reserve the lock | |
197 | @@ -133,13 +179,27 @@ | |
198 | const char* file_name, /* in: file name where lock requested */ | |
199 | ulint line) /* in: line where requested */ | |
200 | { | |
201 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
202 | ut_ad(mutex_own(rw_lock_get_mutex(lock))); | |
203 | +#endif | |
204 | ||
205 | /* Check if the writer field is free */ | |
206 | ||
207 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
208 | + if (UNIV_LIKELY(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED)) { | |
209 | + /* try s-lock */ | |
210 | + if(__sync_sub_and_fetch(&(lock->lock_word),1) <= 0) { | |
211 | + /* fail */ | |
212 | + __sync_fetch_and_add(&(lock->lock_word),1); | |
213 | + return(FALSE); /* locking did not succeed */ | |
214 | + } | |
215 | + /* success */ | |
216 | + __sync_fetch_and_add(&(lock->reader_count),1); | |
217 | +#else | |
218 | if (UNIV_LIKELY(lock->writer == RW_LOCK_NOT_LOCKED)) { | |
219 | /* Set the shared lock by incrementing the reader count */ | |
220 | lock->reader_count++; | |
221 | +#endif | |
222 | ||
223 | #ifdef UNIV_SYNC_DEBUG | |
224 | rw_lock_add_debug_info(lock, pass, RW_LOCK_SHARED, file_name, | |
225 | @@ -166,11 +226,15 @@ | |
226 | const char* file_name, /* in: file name where requested */ | |
227 | ulint line) /* in: line where lock requested */ | |
228 | { | |
229 | - ut_ad(lock->writer == RW_LOCK_NOT_LOCKED); | |
230 | + ut_ad(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED); | |
231 | ut_ad(rw_lock_get_reader_count(lock) == 0); | |
232 | ||
233 | /* Set the shared lock by incrementing the reader count */ | |
234 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
235 | + __sync_fetch_and_add(&(lock->reader_count),1); | |
236 | +#else | |
237 | lock->reader_count++; | |
238 | +#endif | |
239 | ||
240 | lock->last_s_file_name = file_name; | |
241 | lock->last_s_line = line; | |
242 | @@ -198,7 +262,11 @@ | |
243 | ||
244 | rw_lock_set_writer(lock, RW_LOCK_EX); | |
245 | lock->writer_thread = os_thread_get_curr_id(); | |
246 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
247 | + __sync_fetch_and_add(&(lock->writer_count),1); | |
248 | +#else | |
249 | lock->writer_count++; | |
250 | +#endif | |
251 | lock->pass = 0; | |
252 | ||
253 | lock->last_x_file_name = file_name; | |
254 | @@ -240,15 +308,21 @@ | |
255 | ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); /* see NOTE above */ | |
256 | #endif /* UNIV_SYNC_DEBUG */ | |
257 | ||
258 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
259 | mutex_enter(rw_lock_get_mutex(lock)); | |
260 | +#endif | |
261 | ||
262 | if (UNIV_LIKELY(rw_lock_s_lock_low(lock, pass, file_name, line))) { | |
263 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
264 | mutex_exit(rw_lock_get_mutex(lock)); | |
265 | +#endif | |
266 | ||
267 | return; /* Success */ | |
268 | } else { | |
269 | /* Did not succeed, try spin wait */ | |
270 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
271 | mutex_exit(rw_lock_get_mutex(lock)); | |
272 | +#endif | |
273 | ||
274 | rw_lock_s_lock_spin(lock, pass, file_name, line); | |
275 | ||
276 | @@ -271,11 +345,23 @@ | |
277 | { | |
278 | ibool success = FALSE; | |
279 | ||
280 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
281 | + if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) { | |
282 | + /* try s-lock */ | |
283 | + if(__sync_sub_and_fetch(&(lock->lock_word),1) <= 0) { | |
284 | + /* fail */ | |
285 | + __sync_fetch_and_add(&(lock->lock_word),1); | |
286 | + return(FALSE); /* locking did not succeed */ | |
287 | + } | |
288 | + /* success */ | |
289 | + __sync_fetch_and_add(&(lock->reader_count),1); | |
290 | +#else | |
291 | mutex_enter(rw_lock_get_mutex(lock)); | |
292 | ||
293 | if (lock->writer == RW_LOCK_NOT_LOCKED) { | |
294 | /* Set the shared lock by incrementing the reader count */ | |
295 | lock->reader_count++; | |
296 | +#endif | |
297 | ||
298 | #ifdef UNIV_SYNC_DEBUG | |
299 | rw_lock_add_debug_info(lock, 0, RW_LOCK_SHARED, file_name, | |
300 | @@ -288,7 +374,9 @@ | |
301 | success = TRUE; | |
302 | } | |
303 | ||
304 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
305 | mutex_exit(rw_lock_get_mutex(lock)); | |
306 | +#endif | |
307 | ||
308 | return(success); | |
309 | } | |
310 | @@ -308,6 +396,55 @@ | |
311 | { | |
312 | ibool success = FALSE; | |
313 | os_thread_id_t curr_thread = os_thread_get_curr_id(); | |
314 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
315 | + if ((lock->lock_word == RW_LOCK_BIAS) | |
316 | + && rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) { | |
317 | + /* try x-lock */ | |
318 | + if(__sync_sub_and_fetch(&(lock->lock_word), | |
319 | + RW_LOCK_BIAS) == 0) { | |
320 | + /* success */ | |
321 | + /* try to lock writer */ | |
322 | + if(__sync_lock_test_and_set(&(lock->writer),RW_LOCK_EX) | |
323 | + == RW_LOCK_NOT_LOCKED) { | |
324 | + /* success */ | |
325 | + lock->writer_thread = curr_thread; | |
326 | + lock->pass = 0; | |
327 | + lock->writer_is_wait_ex = FALSE; | |
328 | + /* next function may work as memory barrier */ | |
329 | + relock: | |
330 | + __sync_fetch_and_add(&(lock->writer_count),1); | |
331 | + | |
332 | +#ifdef UNIV_SYNC_DEBUG | |
333 | + rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line); | |
334 | +#endif | |
335 | + | |
336 | + lock->last_x_file_name = file_name; | |
337 | + lock->last_x_line = line; | |
338 | + | |
339 | + ut_ad(rw_lock_validate(lock)); | |
340 | + | |
341 | + return(TRUE); | |
342 | + } else { | |
343 | + /* x-unlock */ | |
344 | + __sync_fetch_and_add(&(lock->lock_word), | |
345 | + RW_LOCK_BIAS); | |
346 | + } | |
347 | + } else { | |
348 | + /* fail (x-lock) */ | |
349 | + __sync_fetch_and_add(&(lock->lock_word),RW_LOCK_BIAS); | |
350 | + } | |
351 | + } | |
352 | + | |
353 | + if (lock->pass == 0 | |
354 | + && os_thread_eq(lock->writer_thread, curr_thread) | |
355 | + && rw_lock_get_writer(lock) == RW_LOCK_EX) { | |
356 | + goto relock; | |
357 | + } | |
358 | + | |
359 | + ut_ad(rw_lock_validate(lock)); | |
360 | + | |
361 | + return(FALSE); | |
362 | +#else | |
363 | mutex_enter(rw_lock_get_mutex(lock)); | |
364 | ||
365 | if (UNIV_UNLIKELY(rw_lock_get_reader_count(lock) != 0)) { | |
366 | @@ -338,6 +475,7 @@ | |
367 | ut_ad(rw_lock_validate(lock)); | |
368 | ||
369 | return(success); | |
370 | +#endif | |
371 | } | |
372 | ||
373 | /********************************************************************** | |
374 | @@ -353,16 +491,33 @@ | |
375 | #endif | |
376 | ) | |
377 | { | |
378 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
379 | mutex_t* mutex = &(lock->mutex); | |
380 | - ibool sg = FALSE; | |
381 | +#endif | |
382 | + ibool x_sg = FALSE; | |
383 | + ibool wx_sg = FALSE; | |
384 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
385 | + ibool last = FALSE; | |
386 | +#endif | |
387 | ||
388 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
389 | /* Acquire the mutex protecting the rw-lock fields */ | |
390 | mutex_enter(mutex); | |
391 | +#endif | |
392 | ||
393 | /* Reset the shared lock by decrementing the reader count */ | |
394 | ||
395 | ut_a(lock->reader_count > 0); | |
396 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
397 | + /* unlock lock_word */ | |
398 | + __sync_fetch_and_add(&(lock->lock_word),1); | |
399 | + | |
400 | + if(__sync_sub_and_fetch(&(lock->reader_count),1) == 0) { | |
401 | + last = TRUE; | |
402 | + } | |
403 | +#else | |
404 | lock->reader_count--; | |
405 | +#endif | |
406 | ||
407 | #ifdef UNIV_SYNC_DEBUG | |
408 | rw_lock_remove_debug_info(lock, pass, RW_LOCK_SHARED); | |
409 | @@ -371,20 +526,36 @@ | |
410 | /* If there may be waiters and this was the last s-lock, | |
411 | signal the object */ | |
412 | ||
413 | - if (UNIV_UNLIKELY(lock->waiters) | |
414 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
415 | + if (UNIV_UNLIKELY(last && lock->wait_ex_waiters)) { | |
416 | +#else | |
417 | + if (UNIV_UNLIKELY(lock->wait_ex_waiters) | |
418 | && lock->reader_count == 0) { | |
419 | - sg = TRUE; | |
420 | +#endif | |
421 | + wx_sg = TRUE; | |
422 | ||
423 | - rw_lock_set_waiters(lock, 0); | |
424 | + rw_lock_set_wx_waiters(lock, 0); | |
425 | } | |
426 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
427 | + else if (UNIV_UNLIKELY(last && lock->x_waiters)) { | |
428 | +#else | |
429 | + else if (UNIV_UNLIKELY(lock->x_waiters) | |
430 | + && lock->reader_count == 0) { | |
431 | +#endif | |
432 | + x_sg = TRUE; | |
433 | ||
434 | + rw_lock_set_x_waiters(lock, 0); | |
435 | + } | |
436 | + | |
437 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
438 | mutex_exit(mutex); | |
439 | +#endif | |
440 | ||
441 | - if (UNIV_UNLIKELY(sg)) { | |
442 | -#ifdef __WIN__ | |
443 | + if (UNIV_UNLIKELY(wx_sg)) { | |
444 | os_event_set(lock->wait_ex_event); | |
445 | -#endif | |
446 | - os_event_set(lock->event); | |
447 | + sync_array_object_signalled(sync_primary_wait_array); | |
448 | + } else if (UNIV_UNLIKELY(x_sg)) { | |
449 | + os_event_set(lock->x_event); | |
450 | sync_array_object_signalled(sync_primary_wait_array); | |
451 | } | |
452 | ||
453 | @@ -408,13 +579,19 @@ | |
454 | ||
455 | ut_ad(lock->reader_count > 0); | |
456 | ||
457 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
458 | + __sync_sub_and_fetch(&(lock->reader_count),1); | |
459 | +#else | |
460 | lock->reader_count--; | |
461 | +#endif | |
462 | ||
463 | #ifdef UNIV_SYNC_DEBUG | |
464 | rw_lock_remove_debug_info(lock, 0, RW_LOCK_SHARED); | |
465 | #endif | |
466 | ||
467 | - ut_ad(!lock->waiters); | |
468 | + ut_ad(!lock->s_waiters); | |
469 | + ut_ad(!lock->x_waiters); | |
470 | + ut_ad(!lock->wait_ex_waiters); | |
471 | ut_ad(rw_lock_validate(lock)); | |
472 | #ifdef UNIV_SYNC_PERF_STAT | |
473 | rw_s_exit_count++; | |
474 | @@ -434,41 +611,81 @@ | |
475 | #endif | |
476 | ) | |
477 | { | |
478 | - ibool sg = FALSE; | |
479 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
480 | + ibool last = FALSE; | |
481 | +#endif | |
482 | + ibool s_sg = FALSE; | |
483 | + ibool x_sg = FALSE; | |
484 | ||
485 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
486 | /* Acquire the mutex protecting the rw-lock fields */ | |
487 | mutex_enter(&(lock->mutex)); | |
488 | +#endif | |
489 | ||
490 | /* Reset the exclusive lock if this thread no longer has an x-mode | |
491 | lock */ | |
492 | ||
493 | ut_ad(lock->writer_count > 0); | |
494 | ||
495 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
496 | + if(__sync_sub_and_fetch(&(lock->writer_count),1) == 0) { | |
497 | + last = TRUE; | |
498 | + } | |
499 | + | |
500 | + if (last) { | |
501 | + /* unlock lock_word */ | |
502 | + __sync_fetch_and_add(&(lock->lock_word),RW_LOCK_BIAS); | |
503 | + | |
504 | + /* FIXME: It is a value of bad manners for pthread. | |
505 | + But we shouldn't keep an ID of not-owner. */ | |
506 | + lock->writer_thread = -1; | |
507 | + | |
508 | + /* atomic operation may be safer about memory order. */ | |
509 | + rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED); | |
510 | + __sync_synchronize(); | |
511 | + } | |
512 | +#else | |
513 | lock->writer_count--; | |
514 | ||
515 | if (lock->writer_count == 0) { | |
516 | rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED); | |
517 | } | |
518 | +#endif | |
519 | ||
520 | #ifdef UNIV_SYNC_DEBUG | |
521 | rw_lock_remove_debug_info(lock, pass, RW_LOCK_EX); | |
522 | #endif | |
523 | ||
524 | /* If there may be waiters, signal the lock */ | |
525 | - if (UNIV_UNLIKELY(lock->waiters) | |
526 | - && lock->writer_count == 0) { | |
527 | - | |
528 | - sg = TRUE; | |
529 | - rw_lock_set_waiters(lock, 0); | |
530 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
531 | + if (last) { | |
532 | +#else | |
533 | + if (lock->writer_count == 0) { | |
534 | +#endif | |
535 | + if(lock->s_waiters){ | |
536 | + s_sg = TRUE; | |
537 | + rw_lock_set_s_waiters(lock, 0); | |
538 | + } | |
539 | + if(lock->x_waiters){ | |
540 | + x_sg = TRUE; | |
541 | + rw_lock_set_x_waiters(lock, 0); | |
542 | + } | |
543 | } | |
544 | ||
545 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
546 | mutex_exit(&(lock->mutex)); | |
547 | +#endif | |
548 | ||
549 | - if (UNIV_UNLIKELY(sg)) { | |
550 | + if (UNIV_UNLIKELY(s_sg)) { | |
551 | + os_event_set(lock->s_event); | |
552 | + sync_array_object_signalled(sync_primary_wait_array); | |
553 | + } | |
554 | + if (UNIV_UNLIKELY(x_sg)) { | |
555 | #ifdef __WIN__ | |
556 | + /* I doubt the necessity of it. */ | |
557 | os_event_set(lock->wait_ex_event); | |
558 | #endif | |
559 | - os_event_set(lock->event); | |
560 | + os_event_set(lock->x_event); | |
561 | sync_array_object_signalled(sync_primary_wait_array); | |
562 | } | |
563 | ||
564 | @@ -493,9 +710,13 @@ | |
565 | ||
566 | ut_ad(lock->writer_count > 0); | |
567 | ||
568 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
569 | + if(__sync_sub_and_fetch(&(lock->writer_count),1) == 0) { | |
570 | +#else | |
571 | lock->writer_count--; | |
572 | ||
573 | if (lock->writer_count == 0) { | |
574 | +#endif | |
575 | rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED); | |
576 | } | |
577 | ||
578 | @@ -503,7 +724,9 @@ | |
579 | rw_lock_remove_debug_info(lock, 0, RW_LOCK_EX); | |
580 | #endif | |
581 | ||
582 | - ut_ad(!lock->waiters); | |
583 | + ut_ad(!lock->s_waiters); | |
584 | + ut_ad(!lock->x_waiters); | |
585 | + ut_ad(!lock->wait_ex_waiters); | |
586 | ut_ad(rw_lock_validate(lock)); | |
587 | ||
588 | #ifdef UNIV_SYNC_PERF_STAT | |
589 | diff -ruN mysql-5.1.29-rc_orig/storage/innobase/sync/sync0arr.c mysql-5.1.29-rc/storage/innobase/sync/sync0arr.c | |
590 | --- mysql-5.1.29-rc_orig/storage/innobase/sync/sync0arr.c 2008-10-12 06:54:15.000000000 +0900 | |
591 | +++ mysql-5.1.29-rc/storage/innobase/sync/sync0arr.c 2008-11-17 16:17:39.000000000 +0900 | |
592 | @@ -307,13 +307,13 @@ | |
593 | { | |
594 | if (type == SYNC_MUTEX) { | |
595 | return(os_event_reset(((mutex_t *) object)->event)); | |
596 | -#ifdef __WIN__ | |
597 | } else if (type == RW_LOCK_WAIT_EX) { | |
598 | return(os_event_reset( | |
599 | ((rw_lock_t *) object)->wait_ex_event)); | |
600 | -#endif | |
601 | - } else { | |
602 | - return(os_event_reset(((rw_lock_t *) object)->event)); | |
603 | + } else if (type == RW_LOCK_SHARED) { | |
604 | + return(os_event_reset(((rw_lock_t *) object)->s_event)); | |
605 | + } else { /* RW_LOCK_EX */ | |
606 | + return(os_event_reset(((rw_lock_t *) object)->x_event)); | |
607 | } | |
608 | } | |
609 | ||
610 | @@ -413,15 +413,12 @@ | |
611 | ||
612 | if (cell->request_type == SYNC_MUTEX) { | |
613 | event = ((mutex_t*) cell->wait_object)->event; | |
614 | -#ifdef __WIN__ | |
615 | - /* On windows if the thread about to wait is the one which | |
616 | - has set the state of the rw_lock to RW_LOCK_WAIT_EX, then | |
617 | - it waits on a special event i.e.: wait_ex_event. */ | |
618 | } else if (cell->request_type == RW_LOCK_WAIT_EX) { | |
619 | event = ((rw_lock_t*) cell->wait_object)->wait_ex_event; | |
620 | -#endif | |
621 | + } else if (cell->request_type == RW_LOCK_SHARED) { | |
622 | + event = ((rw_lock_t*) cell->wait_object)->s_event; | |
623 | } else { | |
624 | - event = ((rw_lock_t*) cell->wait_object)->event; | |
625 | + event = ((rw_lock_t*) cell->wait_object)->x_event; | |
626 | } | |
627 | ||
628 | cell->waiting = TRUE; | |
629 | @@ -462,6 +459,7 @@ | |
630 | mutex_t* mutex; | |
631 | rw_lock_t* rwlock; | |
632 | ulint type; | |
633 | + ulint writer; | |
634 | ||
635 | type = cell->request_type; | |
636 | ||
637 | @@ -491,12 +489,10 @@ | |
638 | (ulong) mutex->waiters); | |
639 | ||
640 | } else if (type == RW_LOCK_EX | |
641 | -#ifdef __WIN__ | |
642 | || type == RW_LOCK_WAIT_EX | |
643 | -#endif | |
644 | || type == RW_LOCK_SHARED) { | |
645 | ||
646 | - fputs(type == RW_LOCK_EX ? "X-lock on" : "S-lock on", file); | |
647 | + fputs(type == RW_LOCK_SHARED ? "S-lock on" : "X-lock on", file); | |
648 | ||
649 | rwlock = cell->old_wait_rw_lock; | |
650 | ||
651 | @@ -504,22 +500,24 @@ | |
652 | " RW-latch at %p created in file %s line %lu\n", | |
653 | (void*) rwlock, rwlock->cfile_name, | |
654 | (ulong) rwlock->cline); | |
655 | - if (rwlock->writer != RW_LOCK_NOT_LOCKED) { | |
656 | + writer = rw_lock_get_writer(rwlock); | |
657 | + if (writer != RW_LOCK_NOT_LOCKED) { | |
658 | fprintf(file, | |
659 | "a writer (thread id %lu) has" | |
660 | " reserved it in mode %s", | |
661 | (ulong) os_thread_pf(rwlock->writer_thread), | |
662 | - rwlock->writer == RW_LOCK_EX | |
663 | + writer == RW_LOCK_EX | |
664 | ? " exclusive\n" | |
665 | : " wait exclusive\n"); | |
666 | } | |
667 | ||
668 | fprintf(file, | |
669 | - "number of readers %lu, waiters flag %lu\n" | |
670 | + "number of readers %lu, s_waiters flag %lu, x_waiters flag %lu\n" | |
671 | "Last time read locked in file %s line %lu\n" | |
672 | "Last time write locked in file %s line %lu\n", | |
673 | (ulong) rwlock->reader_count, | |
674 | - (ulong) rwlock->waiters, | |
675 | + (ulong) rwlock->s_waiters, | |
676 | + (ulong) (rwlock->x_waiters || rwlock->wait_ex_waiters), | |
677 | rwlock->last_s_file_name, | |
678 | (ulong) rwlock->last_s_line, | |
679 | rwlock->last_x_file_name, | |
680 | @@ -844,11 +842,15 @@ | |
681 | /*========================*/ | |
682 | sync_array_t* arr) /* in: wait array */ | |
683 | { | |
684 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
685 | + __sync_fetch_and_add(&(arr->sg_count),1); | |
686 | +#else | |
687 | sync_array_enter(arr); | |
688 | ||
689 | arr->sg_count++; | |
690 | ||
691 | sync_array_exit(arr); | |
692 | +#endif | |
693 | } | |
694 | ||
695 | /************************************************************************** | |
696 | @@ -889,19 +891,23 @@ | |
697 | ||
698 | mutex = cell->wait_object; | |
699 | os_event_set(mutex->event); | |
700 | -#ifdef __WIN__ | |
701 | } else if (cell->request_type | |
702 | == RW_LOCK_WAIT_EX) { | |
703 | rw_lock_t* lock; | |
704 | ||
705 | lock = cell->wait_object; | |
706 | os_event_set(lock->wait_ex_event); | |
707 | -#endif | |
708 | - } else { | |
709 | + } else if (cell->request_type | |
710 | + == RW_LOCK_SHARED) { | |
711 | rw_lock_t* lock; | |
712 | ||
713 | lock = cell->wait_object; | |
714 | - os_event_set(lock->event); | |
715 | + os_event_set(lock->s_event); | |
716 | + } else { | |
717 | + rw_lock_t* lock; | |
718 | + | |
719 | + lock = cell->wait_object; | |
720 | + os_event_set(lock->x_event); | |
721 | } | |
722 | } | |
723 | } | |
724 | diff -ruN mysql-5.1.29-rc_orig/storage/innobase/sync/sync0rw.c mysql-5.1.29-rc/storage/innobase/sync/sync0rw.c | |
725 | --- mysql-5.1.29-rc_orig/storage/innobase/sync/sync0rw.c 2008-10-12 06:54:15.000000000 +0900 | |
726 | +++ mysql-5.1.29-rc/storage/innobase/sync/sync0rw.c 2008-11-17 17:43:45.000000000 +0900 | |
727 | @@ -119,6 +119,7 @@ | |
728 | /* If this is the very first time a synchronization object is | |
729 | created, then the following call initializes the sync system. */ | |
730 | ||
731 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
732 | mutex_create(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK); | |
733 | ||
734 | lock->mutex.cfile_name = cfile_name; | |
735 | @@ -128,8 +129,14 @@ | |
736 | lock->mutex.cmutex_name = cmutex_name; | |
737 | lock->mutex.mutex_type = 1; | |
738 | #endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ | |
739 | +#endif /* !HAVE_GCC_ATOMIC_BUILTINS */ | |
740 | ||
741 | - rw_lock_set_waiters(lock, 0); | |
742 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
743 | + lock->lock_word = RW_LOCK_BIAS; | |
744 | +#endif | |
745 | + rw_lock_set_s_waiters(lock, 0); | |
746 | + rw_lock_set_x_waiters(lock, 0); | |
747 | + rw_lock_set_wx_waiters(lock, 0); | |
748 | rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED); | |
749 | lock->writer_count = 0; | |
750 | rw_lock_set_reader_count(lock, 0); | |
751 | @@ -151,11 +158,9 @@ | |
752 | lock->last_x_file_name = "not yet reserved"; | |
753 | lock->last_s_line = 0; | |
754 | lock->last_x_line = 0; | |
755 | - lock->event = os_event_create(NULL); | |
756 | - | |
757 | -#ifdef __WIN__ | |
758 | + lock->s_event = os_event_create(NULL); | |
759 | + lock->x_event = os_event_create(NULL); | |
760 | lock->wait_ex_event = os_event_create(NULL); | |
761 | -#endif | |
762 | ||
763 | mutex_enter(&rw_lock_list_mutex); | |
764 | ||
765 | @@ -181,19 +186,21 @@ | |
766 | { | |
767 | ut_ad(rw_lock_validate(lock)); | |
768 | ut_a(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED); | |
769 | - ut_a(rw_lock_get_waiters(lock) == 0); | |
770 | + ut_a(rw_lock_get_s_waiters(lock) == 0); | |
771 | + ut_a(rw_lock_get_x_waiters(lock) == 0); | |
772 | + ut_a(rw_lock_get_wx_waiters(lock) == 0); | |
773 | ut_a(rw_lock_get_reader_count(lock) == 0); | |
774 | ||
775 | lock->magic_n = 0; | |
776 | ||
777 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
778 | mutex_free(rw_lock_get_mutex(lock)); | |
779 | +#endif | |
780 | ||
781 | mutex_enter(&rw_lock_list_mutex); | |
782 | - os_event_free(lock->event); | |
783 | - | |
784 | -#ifdef __WIN__ | |
785 | + os_event_free(lock->s_event); | |
786 | + os_event_free(lock->x_event); | |
787 | os_event_free(lock->wait_ex_event); | |
788 | -#endif | |
789 | ||
790 | if (UT_LIST_GET_PREV(list, lock)) { | |
791 | ut_a(UT_LIST_GET_PREV(list, lock)->magic_n == RW_LOCK_MAGIC_N); | |
792 | @@ -212,6 +219,8 @@ | |
793 | Checks that the rw-lock has been initialized and that there are no | |
794 | simultaneous shared and exclusive locks. */ | |
795 | ||
796 | +/* MEMO: If HAVE_GCC_ATOMIC_BUILTINS, we should use this function statically. */ | |
797 | + | |
798 | ibool | |
799 | rw_lock_validate( | |
800 | /*=============*/ | |
801 | @@ -219,7 +228,9 @@ | |
802 | { | |
803 | ut_a(lock); | |
804 | ||
805 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
806 | mutex_enter(rw_lock_get_mutex(lock)); | |
807 | +#endif | |
808 | ||
809 | ut_a(lock->magic_n == RW_LOCK_MAGIC_N); | |
810 | ut_a((rw_lock_get_reader_count(lock) == 0) | |
811 | @@ -227,11 +238,17 @@ | |
812 | ut_a((rw_lock_get_writer(lock) == RW_LOCK_EX) | |
813 | || (rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX) | |
814 | || (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED)); | |
815 | - ut_a((rw_lock_get_waiters(lock) == 0) | |
816 | - || (rw_lock_get_waiters(lock) == 1)); | |
817 | + ut_a((rw_lock_get_s_waiters(lock) == 0) | |
818 | + || (rw_lock_get_s_waiters(lock) == 1)); | |
819 | + ut_a((rw_lock_get_x_waiters(lock) == 0) | |
820 | + || (rw_lock_get_x_waiters(lock) == 1)); | |
821 | + ut_a((rw_lock_get_wx_waiters(lock) == 0) | |
822 | + || (rw_lock_get_wx_waiters(lock) == 1)); | |
823 | ut_a((lock->writer != RW_LOCK_EX) || (lock->writer_count > 0)); | |
824 | ||
825 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
826 | mutex_exit(rw_lock_get_mutex(lock)); | |
827 | +#endif | |
828 | ||
829 | return(TRUE); | |
830 | } | |
831 | @@ -258,13 +275,14 @@ | |
832 | ut_ad(rw_lock_validate(lock)); | |
833 | ||
834 | lock_loop: | |
835 | + i = 0; | |
836 | +spin_loop: | |
837 | rw_s_spin_wait_count++; | |
838 | ||
839 | /* Spin waiting for the writer field to become free */ | |
840 | - i = 0; | |
841 | ||
842 | - while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED | |
843 | - && i < SYNC_SPIN_ROUNDS) { | |
844 | + while (i < SYNC_SPIN_ROUNDS | |
845 | + && rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) { | |
846 | if (srv_spin_wait_delay) { | |
847 | ut_delay(ut_rnd_interval(0, srv_spin_wait_delay)); | |
848 | } | |
849 | @@ -285,15 +303,27 @@ | |
850 | lock->cfile_name, (ulong) lock->cline, (ulong) i); | |
851 | } | |
852 | ||
853 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
854 | mutex_enter(rw_lock_get_mutex(lock)); | |
855 | +#endif | |
856 | ||
857 | /* We try once again to obtain the lock */ | |
858 | ||
859 | if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) { | |
860 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
861 | mutex_exit(rw_lock_get_mutex(lock)); | |
862 | +#endif | |
863 | ||
864 | return; /* Success */ | |
865 | } else { | |
866 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
867 | + /* like sync0sync.c doing */ | |
868 | + i++; | |
869 | + | |
870 | + if (i < SYNC_SPIN_ROUNDS) { | |
871 | + goto spin_loop; | |
872 | + } | |
873 | +#endif | |
874 | /* If we get here, locking did not succeed, we may | |
875 | suspend the thread to wait in the wait array */ | |
876 | ||
877 | @@ -304,9 +334,19 @@ | |
878 | file_name, line, | |
879 | &index); | |
880 | ||
881 | - rw_lock_set_waiters(lock, 1); | |
882 | + rw_lock_set_s_waiters(lock, 1); | |
883 | ||
884 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
885 | + /* like sync0sync.c doing */ | |
886 | + for (i = 0; i < 4; i++) { | |
887 | + if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) { | |
888 | + sync_array_free_cell(sync_primary_wait_array, index); | |
889 | + return; /* Success */ | |
890 | + } | |
891 | + } | |
892 | +#else | |
893 | mutex_exit(rw_lock_get_mutex(lock)); | |
894 | +#endif | |
895 | ||
896 | if (srv_print_latch_waits) { | |
897 | fprintf(stderr, | |
898 | @@ -343,13 +383,19 @@ | |
899 | { | |
900 | ut_ad(rw_lock_is_locked(lock, RW_LOCK_EX)); | |
901 | ||
902 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
903 | mutex_enter(&(lock->mutex)); | |
904 | +#endif | |
905 | ||
906 | lock->writer_thread = os_thread_get_curr_id(); | |
907 | ||
908 | lock->pass = 0; | |
909 | ||
910 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
911 | mutex_exit(&(lock->mutex)); | |
912 | +#else | |
913 | + __sync_synchronize(); | |
914 | +#endif | |
915 | } | |
916 | ||
917 | /********************************************************************** | |
918 | @@ -367,6 +413,89 @@ | |
919 | const char* file_name,/* in: file name where lock requested */ | |
920 | ulint line) /* in: line where requested */ | |
921 | { | |
922 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
923 | + os_thread_id_t curr_thread = os_thread_get_curr_id(); | |
924 | + | |
925 | + /* try to lock writer */ | |
926 | + if(__sync_lock_test_and_set(&(lock->writer),RW_LOCK_EX) | |
927 | + == RW_LOCK_NOT_LOCKED) { | |
928 | + /* success */ | |
929 | + /* obtain RW_LOCK_WAIT_EX right */ | |
930 | + lock->writer_thread = curr_thread; | |
931 | + lock->pass = pass; | |
932 | + lock->writer_is_wait_ex = TRUE; | |
933 | + /* atomic operation may be safer about memory order. */ | |
934 | + __sync_synchronize(); | |
935 | +#ifdef UNIV_SYNC_DEBUG | |
936 | + rw_lock_add_debug_info(lock, pass, RW_LOCK_WAIT_EX, | |
937 | + file_name, line); | |
938 | +#endif | |
939 | + } | |
940 | + | |
941 | + if (!os_thread_eq(lock->writer_thread, curr_thread)) { | |
942 | + return(RW_LOCK_NOT_LOCKED); | |
943 | + } | |
944 | + | |
945 | + switch(rw_lock_get_writer(lock)) { | |
946 | + case RW_LOCK_WAIT_EX: | |
947 | + /* have right to try x-lock */ | |
948 | + if (lock->lock_word == RW_LOCK_BIAS) { | |
949 | + /* try x-lock */ | |
950 | + if(__sync_sub_and_fetch(&(lock->lock_word), | |
951 | + RW_LOCK_BIAS) == 0) { | |
952 | + /* success */ | |
953 | + lock->pass = pass; | |
954 | + lock->writer_is_wait_ex = FALSE; | |
955 | + __sync_fetch_and_add(&(lock->writer_count),1); | |
956 | + | |
957 | +#ifdef UNIV_SYNC_DEBUG | |
958 | + rw_lock_remove_debug_info(lock, pass, RW_LOCK_WAIT_EX); | |
959 | + rw_lock_add_debug_info(lock, pass, RW_LOCK_EX, | |
960 | + file_name, line); | |
961 | +#endif | |
962 | + | |
963 | + lock->last_x_file_name = file_name; | |
964 | + lock->last_x_line = line; | |
965 | + | |
966 | + /* Locking succeeded, we may return */ | |
967 | + return(RW_LOCK_EX); | |
968 | + } else { | |
969 | + /* fail */ | |
970 | + __sync_fetch_and_add(&(lock->lock_word), | |
971 | + RW_LOCK_BIAS); | |
972 | + } | |
973 | + } | |
974 | + /* There are readers, we have to wait */ | |
975 | + return(RW_LOCK_WAIT_EX); | |
976 | + | |
977 | + break; | |
978 | + | |
979 | + case RW_LOCK_EX: | |
980 | + /* already have x-lock */ | |
981 | + if ((lock->pass == 0)&&(pass == 0)) { | |
982 | + __sync_fetch_and_add(&(lock->writer_count),1); | |
983 | + | |
984 | +#ifdef UNIV_SYNC_DEBUG | |
985 | + rw_lock_add_debug_info(lock, pass, RW_LOCK_EX, file_name, | |
986 | + line); | |
987 | +#endif | |
988 | + | |
989 | + lock->last_x_file_name = file_name; | |
990 | + lock->last_x_line = line; | |
991 | + | |
992 | + /* Locking succeeded, we may return */ | |
993 | + return(RW_LOCK_EX); | |
994 | + } | |
995 | + | |
996 | + return(RW_LOCK_NOT_LOCKED); | |
997 | + | |
998 | + break; | |
999 | + | |
1000 | + default: /* ??? */ | |
1001 | + return(RW_LOCK_NOT_LOCKED); | |
1002 | + } | |
1003 | +#else /* HAVE_GCC_ATOMIC_BUILTINS */ | |
1004 | + | |
1005 | ut_ad(mutex_own(rw_lock_get_mutex(lock))); | |
1006 | ||
1007 | if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) { | |
1008 | @@ -447,6 +576,7 @@ | |
1009 | /* Locking succeeded, we may return */ | |
1010 | return(RW_LOCK_EX); | |
1011 | } | |
1012 | +#endif /* HAVE_GCC_ATOMIC_BUILTINS */ | |
1013 | ||
1014 | /* Locking did not succeed */ | |
1015 | return(RW_LOCK_NOT_LOCKED); | |
1016 | @@ -472,19 +602,33 @@ | |
1017 | ulint line) /* in: line where requested */ | |
1018 | { | |
1019 | ulint index; /* index of the reserved wait cell */ | |
1020 | - ulint state; /* lock state acquired */ | |
1021 | + ulint state = RW_LOCK_NOT_LOCKED; /* lock state acquired */ | |
1022 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
1023 | + ulint prev_state = RW_LOCK_NOT_LOCKED; | |
1024 | +#endif | |
1025 | ulint i; /* spin round count */ | |
1026 | ||
1027 | ut_ad(rw_lock_validate(lock)); | |
1028 | ||
1029 | lock_loop: | |
1030 | + i = 0; | |
1031 | + | |
1032 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
1033 | + prev_state = state; | |
1034 | +#else | |
1035 | /* Acquire the mutex protecting the rw-lock fields */ | |
1036 | mutex_enter_fast(&(lock->mutex)); | |
1037 | +#endif | |
1038 | ||
1039 | state = rw_lock_x_lock_low(lock, pass, file_name, line); | |
1040 | ||
1041 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
1042 | + if (state != prev_state) i=0; /* if progress, reset counter. */ | |
1043 | +#else | |
1044 | mutex_exit(&(lock->mutex)); | |
1045 | +#endif | |
1046 | ||
1047 | +spin_loop: | |
1048 | if (state == RW_LOCK_EX) { | |
1049 | ||
1050 | return; /* Locking succeeded */ | |
1051 | @@ -492,10 +636,9 @@ | |
1052 | } else if (state == RW_LOCK_NOT_LOCKED) { | |
1053 | ||
1054 | /* Spin waiting for the writer field to become free */ | |
1055 | - i = 0; | |
1056 | ||
1057 | - while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED | |
1058 | - && i < SYNC_SPIN_ROUNDS) { | |
1059 | + while (i < SYNC_SPIN_ROUNDS | |
1060 | + && rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) { | |
1061 | if (srv_spin_wait_delay) { | |
1062 | ut_delay(ut_rnd_interval(0, | |
1063 | srv_spin_wait_delay)); | |
1064 | @@ -509,9 +652,12 @@ | |
1065 | } else if (state == RW_LOCK_WAIT_EX) { | |
1066 | ||
1067 | /* Spin waiting for the reader count field to become zero */ | |
1068 | - i = 0; | |
1069 | ||
1070 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
1071 | + while (lock->lock_word != RW_LOCK_BIAS | |
1072 | +#else | |
1073 | while (rw_lock_get_reader_count(lock) != 0 | |
1074 | +#endif | |
1075 | && i < SYNC_SPIN_ROUNDS) { | |
1076 | if (srv_spin_wait_delay) { | |
1077 | ut_delay(ut_rnd_interval(0, | |
1078 | @@ -524,7 +670,6 @@ | |
1079 | os_thread_yield(); | |
1080 | } | |
1081 | } else { | |
1082 | - i = 0; /* Eliminate a compiler warning */ | |
1083 | ut_error; | |
1084 | } | |
1085 | ||
1086 | @@ -541,34 +686,69 @@ | |
1087 | /* We try once again to obtain the lock. Acquire the mutex protecting | |
1088 | the rw-lock fields */ | |
1089 | ||
1090 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
1091 | + prev_state = state; | |
1092 | +#else | |
1093 | mutex_enter(rw_lock_get_mutex(lock)); | |
1094 | +#endif | |
1095 | ||
1096 | state = rw_lock_x_lock_low(lock, pass, file_name, line); | |
1097 | ||
1098 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
1099 | + if (state != prev_state) i=0; /* if progress, reset counter. */ | |
1100 | +#endif | |
1101 | + | |
1102 | if (state == RW_LOCK_EX) { | |
1103 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
1104 | mutex_exit(rw_lock_get_mutex(lock)); | |
1105 | +#endif | |
1106 | ||
1107 | return; /* Locking succeeded */ | |
1108 | } | |
1109 | ||
1110 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
1111 | + /* like sync0sync.c doing */ | |
1112 | + i++; | |
1113 | + | |
1114 | + if (i < SYNC_SPIN_ROUNDS) { | |
1115 | + goto spin_loop; | |
1116 | + } | |
1117 | +#endif | |
1118 | + | |
1119 | rw_x_system_call_count++; | |
1120 | ||
1121 | sync_array_reserve_cell(sync_primary_wait_array, | |
1122 | lock, | |
1123 | -#ifdef __WIN__ | |
1124 | - /* On windows RW_LOCK_WAIT_EX signifies | |
1125 | - that this thread should wait on the | |
1126 | - special wait_ex_event. */ | |
1127 | (state == RW_LOCK_WAIT_EX) | |
1128 | ? RW_LOCK_WAIT_EX : | |
1129 | -#endif | |
1130 | RW_LOCK_EX, | |
1131 | file_name, line, | |
1132 | &index); | |
1133 | ||
1134 | - rw_lock_set_waiters(lock, 1); | |
1135 | + if (state == RW_LOCK_WAIT_EX) { | |
1136 | + rw_lock_set_wx_waiters(lock, 1); | |
1137 | + } else { | |
1138 | + rw_lock_set_x_waiters(lock, 1); | |
1139 | + } | |
1140 | ||
1141 | +#ifdef HAVE_GCC_ATOMIC_BUILTINS | |
1142 | + /* like sync0sync.c doing */ | |
1143 | + for (i = 0; i < 4; i++) { | |
1144 | + prev_state = state; | |
1145 | + state = rw_lock_x_lock_low(lock, pass, file_name, line); | |
1146 | + if (state == RW_LOCK_EX) { | |
1147 | + sync_array_free_cell(sync_primary_wait_array, index); | |
1148 | + return; /* Locking succeeded */ | |
1149 | + } | |
1150 | + if (state != prev_state) { | |
1151 | + /* retry! */ | |
1152 | + sync_array_free_cell(sync_primary_wait_array, index); | |
1153 | + goto lock_loop; | |
1154 | + } | |
1155 | + } | |
1156 | +#else | |
1157 | mutex_exit(rw_lock_get_mutex(lock)); | |
1158 | +#endif | |
1159 | ||
1160 | if (srv_print_latch_waits) { | |
1161 | fprintf(stderr, | |
1162 | @@ -730,7 +910,9 @@ | |
1163 | ut_ad(lock); | |
1164 | ut_ad(rw_lock_validate(lock)); | |
1165 | ||
1166 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
1167 | mutex_enter(&(lock->mutex)); | |
1168 | +#endif | |
1169 | ||
1170 | info = UT_LIST_GET_FIRST(lock->debug_list); | |
1171 | ||
1172 | @@ -740,7 +922,9 @@ | |
1173 | && (info->pass == 0) | |
1174 | && (info->lock_type == lock_type)) { | |
1175 | ||
1176 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
1177 | mutex_exit(&(lock->mutex)); | |
1178 | +#endif | |
1179 | /* Found! */ | |
1180 | ||
1181 | return(TRUE); | |
1182 | @@ -748,7 +932,9 @@ | |
1183 | ||
1184 | info = UT_LIST_GET_NEXT(list, info); | |
1185 | } | |
1186 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
1187 | mutex_exit(&(lock->mutex)); | |
1188 | +#endif | |
1189 | ||
1190 | return(FALSE); | |
1191 | } | |
1192 | @@ -770,21 +956,25 @@ | |
1193 | ut_ad(lock); | |
1194 | ut_ad(rw_lock_validate(lock)); | |
1195 | ||
1196 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
1197 | mutex_enter(&(lock->mutex)); | |
1198 | +#endif | |
1199 | ||
1200 | if (lock_type == RW_LOCK_SHARED) { | |
1201 | if (lock->reader_count > 0) { | |
1202 | ret = TRUE; | |
1203 | } | |
1204 | } else if (lock_type == RW_LOCK_EX) { | |
1205 | - if (lock->writer == RW_LOCK_EX) { | |
1206 | + if (rw_lock_get_writer(lock) == RW_LOCK_EX) { | |
1207 | ret = TRUE; | |
1208 | } | |
1209 | } else { | |
1210 | ut_error; | |
1211 | } | |
1212 | ||
1213 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
1214 | mutex_exit(&(lock->mutex)); | |
1215 | +#endif | |
1216 | ||
1217 | return(ret); | |
1218 | } | |
1219 | @@ -814,16 +1004,26 @@ | |
1220 | ||
1221 | count++; | |
1222 | ||
1223 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
1224 | mutex_enter(&(lock->mutex)); | |
1225 | +#endif | |
1226 | ||
1227 | if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) | |
1228 | || (rw_lock_get_reader_count(lock) != 0) | |
1229 | - || (rw_lock_get_waiters(lock) != 0)) { | |
1230 | + || (rw_lock_get_s_waiters(lock) != 0) | |
1231 | + || (rw_lock_get_x_waiters(lock) != 0) | |
1232 | + || (rw_lock_get_wx_waiters(lock) != 0)) { | |
1233 | ||
1234 | fprintf(file, "RW-LOCK: %p ", (void*) lock); | |
1235 | ||
1236 | - if (rw_lock_get_waiters(lock)) { | |
1237 | - fputs(" Waiters for the lock exist\n", file); | |
1238 | + if (rw_lock_get_s_waiters(lock)) { | |
1239 | + fputs(" s_waiters for the lock exist,", file); | |
1240 | + } | |
1241 | + if (rw_lock_get_x_waiters(lock)) { | |
1242 | + fputs(" x_waiters for the lock exist\n", file); | |
1243 | + } | |
1244 | + if (rw_lock_get_wx_waiters(lock)) { | |
1245 | + fputs(" wait_ex_waiters for the lock exist\n", file); | |
1246 | } else { | |
1247 | putc('\n', file); | |
1248 | } | |
1249 | @@ -835,7 +1035,9 @@ | |
1250 | } | |
1251 | } | |
1252 | ||
1253 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
1254 | mutex_exit(&(lock->mutex)); | |
1255 | +#endif | |
1256 | lock = UT_LIST_GET_NEXT(list, lock); | |
1257 | } | |
1258 | ||
1259 | @@ -860,10 +1062,18 @@ | |
1260 | ||
1261 | if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) | |
1262 | || (rw_lock_get_reader_count(lock) != 0) | |
1263 | - || (rw_lock_get_waiters(lock) != 0)) { | |
1264 | + || (rw_lock_get_s_waiters(lock) != 0) | |
1265 | + || (rw_lock_get_x_waiters(lock) != 0) | |
1266 | + || (rw_lock_get_wx_waiters(lock) != 0)) { | |
1267 | ||
1268 | - if (rw_lock_get_waiters(lock)) { | |
1269 | - fputs(" Waiters for the lock exist\n", stderr); | |
1270 | + if (rw_lock_get_s_waiters(lock)) { | |
1271 | + fputs(" s_waiters for the lock exist,", stderr); | |
1272 | + } | |
1273 | + if (rw_lock_get_x_waiters(lock)) { | |
1274 | + fputs(" x_waiters for the lock exist\n", stderr); | |
1275 | + } | |
1276 | + if (rw_lock_get_wx_waiters(lock)) { | |
1277 | + fputs(" wait_ex_waiters for the lock exist\n", stderr); | |
1278 | } else { | |
1279 | putc('\n', stderr); | |
1280 | } | |
1281 | @@ -922,14 +1132,18 @@ | |
1282 | lock = UT_LIST_GET_FIRST(rw_lock_list); | |
1283 | ||
1284 | while (lock != NULL) { | |
1285 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
1286 | mutex_enter(rw_lock_get_mutex(lock)); | |
1287 | +#endif | |
1288 | ||
1289 | if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) | |
1290 | || (rw_lock_get_reader_count(lock) != 0)) { | |
1291 | count++; | |
1292 | } | |
1293 | ||
1294 | +#ifndef HAVE_GCC_ATOMIC_BUILTINS | |
1295 | mutex_exit(rw_lock_get_mutex(lock)); | |
1296 | +#endif | |
1297 | lock = UT_LIST_GET_NEXT(list, lock); | |
1298 | } | |
1299 | ||
1300 | diff -ruN mysql-5.1.29-rc_orig/patch_info/innodb_rw_lock.info mysql-5.1.29-rc/patch_info/innodb_rw_lock.info | |
1301 | --- /dev/null 1970-01-01 09:00:00.000000000 +0900 | |
1302 | +++ mysql-5.1.29-rc/patch_info/innodb_rw_lock.info 2008-11-17 15:23:46.000000000 +0900 | |
1303 | @@ -0,0 +1,6 @@ | |
1304 | +File=innodb_rw_lock.patch | |
1305 | +Name=Fix of InnoDB rw_locks | |
1306 | +Version=1.0 | |
1307 | +Author=Yasufumi Kinoshita | |
1308 | +License=BSD | |
1309 | +Comment= |