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
5 Accessor functions for rw lock. */
9 +rw_lock_get_s_waiters(
10 +/*==================*/
14 +rw_lock_get_x_waiters(
15 +/*==================*/
19 +rw_lock_get_wx_waiters(
24 rw_lock_debug_t* info); /* in: debug struct */
25 #endif /* UNIV_SYNC_DEBUG */
27 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
28 +/* This value means NOT_LOCKED */
29 +#define RW_LOCK_BIAS 0x00100000
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
36 field. Then no new readers are allowed in. */
38 struct rw_lock_struct {
39 - os_event_t event; /* Used by sync0arr.c for thread queueing */
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
49 thread will be the next one to proceed
50 once the current the event gets
51 signalled. See LEMMA 2 in sync0sync.c */
53 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
54 + volatile lint lock_word; /* Used by using atomic builtin */
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
73 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
74 mutex_t mutex; /* The mutex protecting rw_lock_struct */
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
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.
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
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
104 Accessor functions for rw lock. */
107 -rw_lock_get_waiters(
108 +rw_lock_get_s_waiters(
112 - return(lock->waiters);
113 + return(lock->s_waiters);
117 -rw_lock_set_waiters(
119 +rw_lock_get_x_waiters(
120 +/*================*/
123 + return(lock->x_waiters);
127 +rw_lock_get_wx_waiters(
131 + return(lock->wait_ex_waiters);
135 +rw_lock_set_s_waiters(
139 + lock->s_waiters = flag;
143 +rw_lock_set_x_waiters(
147 - lock->waiters = flag;
148 + lock->x_waiters = flag;
152 +rw_lock_set_wx_waiters(
153 +/*================*/
157 + lock->wait_ex_waiters = flag;
165 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
166 + if (lock->writer == RW_LOCK_NOT_LOCKED) {
167 + return(RW_LOCK_NOT_LOCKED);
170 + if (lock->writer_is_wait_ex) {
171 + return(RW_LOCK_WAIT_EX);
173 + return(RW_LOCK_EX);
176 return(lock->writer);
183 lock->reader_count = count;
185 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
191 return(&(lock->mutex));
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 */
201 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
202 ut_ad(mutex_own(rw_lock_get_mutex(lock)));
205 /* Check if the writer field is free */
207 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
208 + if (UNIV_LIKELY(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED)) {
210 + if(__sync_sub_and_fetch(&(lock->lock_word),1) <= 0) {
212 + __sync_fetch_and_add(&(lock->lock_word),1);
213 + return(FALSE); /* locking did not succeed */
216 + __sync_fetch_and_add(&(lock->reader_count),1);
218 if (UNIV_LIKELY(lock->writer == RW_LOCK_NOT_LOCKED)) {
219 /* Set the shared lock by incrementing the reader count */
220 lock->reader_count++;
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 */
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);
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);
237 lock->reader_count++;
240 lock->last_s_file_name = file_name;
241 lock->last_s_line = line;
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);
249 lock->writer_count++;
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 */
258 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
259 mutex_enter(rw_lock_get_mutex(lock));
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));
267 return; /* Success */
269 /* Did not succeed, try spin wait */
270 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
271 mutex_exit(rw_lock_get_mutex(lock));
274 rw_lock_s_lock_spin(lock, pass, file_name, line);
276 @@ -271,11 +345,23 @@
278 ibool success = FALSE;
280 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
281 + if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {
283 + if(__sync_sub_and_fetch(&(lock->lock_word),1) <= 0) {
285 + __sync_fetch_and_add(&(lock->lock_word),1);
286 + return(FALSE); /* locking did not succeed */
289 + __sync_fetch_and_add(&(lock->reader_count),1);
291 mutex_enter(rw_lock_get_mutex(lock));
293 if (lock->writer == RW_LOCK_NOT_LOCKED) {
294 /* Set the shared lock by incrementing the reader count */
295 lock->reader_count++;
298 #ifdef UNIV_SYNC_DEBUG
299 rw_lock_add_debug_info(lock, 0, RW_LOCK_SHARED, file_name,
304 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
305 mutex_exit(rw_lock_get_mutex(lock));
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) {
318 + if(__sync_sub_and_fetch(&(lock->lock_word),
319 + RW_LOCK_BIAS) == 0) {
321 + /* try to lock writer */
322 + if(__sync_lock_test_and_set(&(lock->writer),RW_LOCK_EX)
323 + == RW_LOCK_NOT_LOCKED) {
325 + lock->writer_thread = curr_thread;
327 + lock->writer_is_wait_ex = FALSE;
328 + /* next function may work as memory barrier */
330 + __sync_fetch_and_add(&(lock->writer_count),1);
332 +#ifdef UNIV_SYNC_DEBUG
333 + rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line);
336 + lock->last_x_file_name = file_name;
337 + lock->last_x_line = line;
339 + ut_ad(rw_lock_validate(lock));
344 + __sync_fetch_and_add(&(lock->lock_word),
348 + /* fail (x-lock) */
349 + __sync_fetch_and_add(&(lock->lock_word),RW_LOCK_BIAS);
353 + if (lock->pass == 0
354 + && os_thread_eq(lock->writer_thread, curr_thread)
355 + && rw_lock_get_writer(lock) == RW_LOCK_EX) {
359 + ut_ad(rw_lock_validate(lock));
363 mutex_enter(rw_lock_get_mutex(lock));
365 if (UNIV_UNLIKELY(rw_lock_get_reader_count(lock) != 0)) {
367 ut_ad(rw_lock_validate(lock));
373 /**********************************************************************
374 @@ -353,16 +491,33 @@
378 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
379 mutex_t* mutex = &(lock->mutex);
382 + ibool x_sg = FALSE;
383 + ibool wx_sg = FALSE;
384 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
385 + ibool last = FALSE;
388 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
389 /* Acquire the mutex protecting the rw-lock fields */
393 /* Reset the shared lock by decrementing the reader count */
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);
400 + if(__sync_sub_and_fetch(&(lock->reader_count),1) == 0) {
404 lock->reader_count--;
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,
413 - if (UNIV_UNLIKELY(lock->waiters)
414 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
415 + if (UNIV_UNLIKELY(last && lock->wait_ex_waiters)) {
417 + if (UNIV_UNLIKELY(lock->wait_ex_waiters)
418 && lock->reader_count == 0) {
423 - rw_lock_set_waiters(lock, 0);
424 + rw_lock_set_wx_waiters(lock, 0);
426 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
427 + else if (UNIV_UNLIKELY(last && lock->x_waiters)) {
429 + else if (UNIV_UNLIKELY(lock->x_waiters)
430 + && lock->reader_count == 0) {
434 + rw_lock_set_x_waiters(lock, 0);
437 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
441 - if (UNIV_UNLIKELY(sg)) {
443 + if (UNIV_UNLIKELY(wx_sg)) {
444 os_event_set(lock->wait_ex_event);
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);
453 @@ -408,13 +579,19 @@
455 ut_ad(lock->reader_count > 0);
457 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
458 + __sync_sub_and_fetch(&(lock->reader_count),1);
460 lock->reader_count--;
463 #ifdef UNIV_SYNC_DEBUG
464 rw_lock_remove_debug_info(lock, 0, RW_LOCK_SHARED);
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
474 @@ -434,41 +611,81 @@
479 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
480 + ibool last = FALSE;
482 + ibool s_sg = FALSE;
483 + ibool x_sg = FALSE;
485 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
486 /* Acquire the mutex protecting the rw-lock fields */
487 mutex_enter(&(lock->mutex));
490 /* Reset the exclusive lock if this thread no longer has an x-mode
493 ut_ad(lock->writer_count > 0);
495 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
496 + if(__sync_sub_and_fetch(&(lock->writer_count),1) == 0) {
501 + /* unlock lock_word */
502 + __sync_fetch_and_add(&(lock->lock_word),RW_LOCK_BIAS);
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;
508 + /* atomic operation may be safer about memory order. */
509 + rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
510 + __sync_synchronize();
513 lock->writer_count--;
515 if (lock->writer_count == 0) {
516 rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
520 #ifdef UNIV_SYNC_DEBUG
521 rw_lock_remove_debug_info(lock, pass, RW_LOCK_EX);
524 /* If there may be waiters, signal the lock */
525 - if (UNIV_UNLIKELY(lock->waiters)
526 - && lock->writer_count == 0) {
529 - rw_lock_set_waiters(lock, 0);
530 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
533 + if (lock->writer_count == 0) {
535 + if(lock->s_waiters){
537 + rw_lock_set_s_waiters(lock, 0);
539 + if(lock->x_waiters){
541 + rw_lock_set_x_waiters(lock, 0);
545 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
546 mutex_exit(&(lock->mutex));
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);
554 + if (UNIV_UNLIKELY(x_sg)) {
556 + /* I doubt the necessity of it. */
557 os_event_set(lock->wait_ex_event);
559 - os_event_set(lock->event);
560 + os_event_set(lock->x_event);
561 sync_array_object_signalled(sync_primary_wait_array);
566 ut_ad(lock->writer_count > 0);
568 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
569 + if(__sync_sub_and_fetch(&(lock->writer_count),1) == 0) {
571 lock->writer_count--;
573 if (lock->writer_count == 0) {
575 rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
579 rw_lock_remove_debug_info(lock, 0, RW_LOCK_EX);
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));
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 @@
594 if (type == SYNC_MUTEX) {
595 return(os_event_reset(((mutex_t *) object)->event));
597 } else if (type == RW_LOCK_WAIT_EX) {
598 return(os_event_reset(
599 ((rw_lock_t *) object)->wait_ex_event));
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));
610 @@ -413,15 +413,12 @@
612 if (cell->request_type == SYNC_MUTEX) {
613 event = ((mutex_t*) cell->wait_object)->event;
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;
621 + } else if (cell->request_type == RW_LOCK_SHARED) {
622 + event = ((rw_lock_t*) cell->wait_object)->s_event;
624 - event = ((rw_lock_t*) cell->wait_object)->event;
625 + event = ((rw_lock_t*) cell->wait_object)->x_event;
628 cell->waiting = TRUE;
635 type = cell->request_type;
637 @@ -491,12 +489,10 @@
638 (ulong) mutex->waiters);
640 } else if (type == RW_LOCK_EX
642 || type == RW_LOCK_WAIT_EX
644 || type == RW_LOCK_SHARED) {
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);
649 rwlock = cell->old_wait_rw_lock;
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) {
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
665 : " wait exclusive\n");
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 */
684 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
685 + __sync_fetch_and_add(&(arr->sg_count),1);
687 sync_array_enter(arr);
691 sync_array_exit(arr);
695 /**************************************************************************
696 @@ -889,19 +891,23 @@
698 mutex = cell->wait_object;
699 os_event_set(mutex->event);
701 } else if (cell->request_type
702 == RW_LOCK_WAIT_EX) {
705 lock = cell->wait_object;
706 os_event_set(lock->wait_ex_event);
709 + } else if (cell->request_type
710 + == RW_LOCK_SHARED) {
713 lock = cell->wait_object;
714 - os_event_set(lock->event);
715 + os_event_set(lock->s_event);
719 + lock = cell->wait_object;
720 + os_event_set(lock->x_event);
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
728 /* If this is the very first time a synchronization object is
729 created, then the following call initializes the sync system. */
731 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
732 mutex_create(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK);
734 lock->mutex.cfile_name = cfile_name;
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 */
741 - rw_lock_set_waiters(lock, 0);
742 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
743 + lock->lock_word = RW_LOCK_BIAS;
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);
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);
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);
763 mutex_enter(&rw_lock_list_mutex);
765 @@ -181,19 +186,21 @@
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);
777 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
778 mutex_free(rw_lock_get_mutex(lock));
781 mutex_enter(&rw_lock_list_mutex);
782 - os_event_free(lock->event);
785 + os_event_free(lock->s_event);
786 + os_event_free(lock->x_event);
787 os_event_free(lock->wait_ex_event);
790 if (UT_LIST_GET_PREV(list, lock)) {
791 ut_a(UT_LIST_GET_PREV(list, lock)->magic_n == RW_LOCK_MAGIC_N);
793 Checks that the rw-lock has been initialized and that there are no
794 simultaneous shared and exclusive locks. */
796 +/* MEMO: If HAVE_GCC_ATOMIC_BUILTINS, we should use this function statically. */
805 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
806 mutex_enter(rw_lock_get_mutex(lock));
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));
825 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
826 mutex_exit(rw_lock_get_mutex(lock));
831 @@ -258,13 +275,14 @@
832 ut_ad(rw_lock_validate(lock));
837 rw_s_spin_wait_count++;
839 /* Spin waiting for the writer field to become free */
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));
849 @@ -285,15 +303,27 @@
850 lock->cfile_name, (ulong) lock->cline, (ulong) i);
853 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
854 mutex_enter(rw_lock_get_mutex(lock));
857 /* We try once again to obtain the lock */
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));
864 return; /* Success */
866 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
867 + /* like sync0sync.c doing */
870 + if (i < SYNC_SPIN_ROUNDS) {
874 /* If we get here, locking did not succeed, we may
875 suspend the thread to wait in the wait array */
881 - rw_lock_set_waiters(lock, 1);
882 + rw_lock_set_s_waiters(lock, 1);
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 */
893 mutex_exit(rw_lock_get_mutex(lock));
896 if (srv_print_latch_waits) {
898 @@ -343,13 +383,19 @@
900 ut_ad(rw_lock_is_locked(lock, RW_LOCK_EX));
902 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
903 mutex_enter(&(lock->mutex));
906 lock->writer_thread = os_thread_get_curr_id();
910 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
911 mutex_exit(&(lock->mutex));
913 + __sync_synchronize();
917 /**********************************************************************
919 const char* file_name,/* in: file name where lock requested */
920 ulint line) /* in: line where requested */
922 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
923 + os_thread_id_t curr_thread = os_thread_get_curr_id();
925 + /* try to lock writer */
926 + if(__sync_lock_test_and_set(&(lock->writer),RW_LOCK_EX)
927 + == RW_LOCK_NOT_LOCKED) {
929 + /* obtain RW_LOCK_WAIT_EX right */
930 + lock->writer_thread = curr_thread;
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,
941 + if (!os_thread_eq(lock->writer_thread, curr_thread)) {
942 + return(RW_LOCK_NOT_LOCKED);
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) {
950 + if(__sync_sub_and_fetch(&(lock->lock_word),
951 + RW_LOCK_BIAS) == 0) {
954 + lock->writer_is_wait_ex = FALSE;
955 + __sync_fetch_and_add(&(lock->writer_count),1);
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,
963 + lock->last_x_file_name = file_name;
964 + lock->last_x_line = line;
966 + /* Locking succeeded, we may return */
967 + return(RW_LOCK_EX);
970 + __sync_fetch_and_add(&(lock->lock_word),
974 + /* There are readers, we have to wait */
975 + return(RW_LOCK_WAIT_EX);
980 + /* already have x-lock */
981 + if ((lock->pass == 0)&&(pass == 0)) {
982 + __sync_fetch_and_add(&(lock->writer_count),1);
984 +#ifdef UNIV_SYNC_DEBUG
985 + rw_lock_add_debug_info(lock, pass, RW_LOCK_EX, file_name,
989 + lock->last_x_file_name = file_name;
990 + lock->last_x_line = line;
992 + /* Locking succeeded, we may return */
993 + return(RW_LOCK_EX);
996 + return(RW_LOCK_NOT_LOCKED);
1000 + default: /* ??? */
1001 + return(RW_LOCK_NOT_LOCKED);
1003 +#else /* HAVE_GCC_ATOMIC_BUILTINS */
1005 ut_ad(mutex_own(rw_lock_get_mutex(lock)));
1007 if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {
1009 /* Locking succeeded, we may return */
1012 +#endif /* HAVE_GCC_ATOMIC_BUILTINS */
1014 /* Locking did not succeed */
1015 return(RW_LOCK_NOT_LOCKED);
1016 @@ -472,19 +602,33 @@
1017 ulint line) /* in: line where requested */
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;
1025 ulint i; /* spin round count */
1027 ut_ad(rw_lock_validate(lock));
1032 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
1033 + prev_state = state;
1035 /* Acquire the mutex protecting the rw-lock fields */
1036 mutex_enter_fast(&(lock->mutex));
1039 state = rw_lock_x_lock_low(lock, pass, file_name, line);
1041 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
1042 + if (state != prev_state) i=0; /* if progress, reset counter. */
1044 mutex_exit(&(lock->mutex));
1048 if (state == RW_LOCK_EX) {
1050 return; /* Locking succeeded */
1051 @@ -492,10 +636,9 @@
1052 } else if (state == RW_LOCK_NOT_LOCKED) {
1054 /* Spin waiting for the writer field to become free */
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) {
1067 /* Spin waiting for the reader count field to become zero */
1070 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
1071 + while (lock->lock_word != RW_LOCK_BIAS
1073 while (rw_lock_get_reader_count(lock) != 0
1075 && i < SYNC_SPIN_ROUNDS) {
1076 if (srv_spin_wait_delay) {
1077 ut_delay(ut_rnd_interval(0,
1082 - i = 0; /* Eliminate a compiler warning */
1086 @@ -541,34 +686,69 @@
1087 /* We try once again to obtain the lock. Acquire the mutex protecting
1088 the rw-lock fields */
1090 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
1091 + prev_state = state;
1093 mutex_enter(rw_lock_get_mutex(lock));
1096 state = rw_lock_x_lock_low(lock, pass, file_name, line);
1098 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
1099 + if (state != prev_state) i=0; /* if progress, reset counter. */
1102 if (state == RW_LOCK_EX) {
1103 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
1104 mutex_exit(rw_lock_get_mutex(lock));
1107 return; /* Locking succeeded */
1110 +#ifdef HAVE_GCC_ATOMIC_BUILTINS
1111 + /* like sync0sync.c doing */
1114 + if (i < SYNC_SPIN_ROUNDS) {
1119 rw_x_system_call_count++;
1121 sync_array_reserve_cell(sync_primary_wait_array,
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)
1134 - rw_lock_set_waiters(lock, 1);
1135 + if (state == RW_LOCK_WAIT_EX) {
1136 + rw_lock_set_wx_waiters(lock, 1);
1138 + rw_lock_set_x_waiters(lock, 1);
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 */
1150 + if (state != prev_state) {
1152 + sync_array_free_cell(sync_primary_wait_array, index);
1157 mutex_exit(rw_lock_get_mutex(lock));
1160 if (srv_print_latch_waits) {
1164 ut_ad(rw_lock_validate(lock));
1166 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
1167 mutex_enter(&(lock->mutex));
1170 info = UT_LIST_GET_FIRST(lock->debug_list);
1173 && (info->pass == 0)
1174 && (info->lock_type == lock_type)) {
1176 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
1177 mutex_exit(&(lock->mutex));
1184 info = UT_LIST_GET_NEXT(list, info);
1186 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
1187 mutex_exit(&(lock->mutex));
1192 @@ -770,21 +956,25 @@
1194 ut_ad(rw_lock_validate(lock));
1196 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
1197 mutex_enter(&(lock->mutex));
1200 if (lock_type == RW_LOCK_SHARED) {
1201 if (lock->reader_count > 0) {
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) {
1213 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
1214 mutex_exit(&(lock->mutex));
1219 @@ -814,16 +1004,26 @@
1223 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
1224 mutex_enter(&(lock->mutex));
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)) {
1234 fprintf(file, "RW-LOCK: %p ", (void*) lock);
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);
1241 + if (rw_lock_get_x_waiters(lock)) {
1242 + fputs(" x_waiters for the lock exist\n", file);
1244 + if (rw_lock_get_wx_waiters(lock)) {
1245 + fputs(" wait_ex_waiters for the lock exist\n", file);
1249 @@ -835,7 +1035,9 @@
1253 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
1254 mutex_exit(&(lock->mutex));
1256 lock = UT_LIST_GET_NEXT(list, lock);
1259 @@ -860,10 +1062,18 @@
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)) {
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);
1273 + if (rw_lock_get_x_waiters(lock)) {
1274 + fputs(" x_waiters for the lock exist\n", stderr);
1276 + if (rw_lock_get_wx_waiters(lock)) {
1277 + fputs(" wait_ex_waiters for the lock exist\n", stderr);
1281 @@ -922,14 +1132,18 @@
1282 lock = UT_LIST_GET_FIRST(rw_lock_list);
1284 while (lock != NULL) {
1285 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
1286 mutex_enter(rw_lock_get_mutex(lock));
1289 if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
1290 || (rw_lock_get_reader_count(lock) != 0)) {
1294 +#ifndef HAVE_GCC_ATOMIC_BUILTINS
1295 mutex_exit(rw_lock_get_mutex(lock));
1297 lock = UT_LIST_GET_NEXT(list, lock);
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
1304 +File=innodb_rw_lock.patch
1305 +Name=Fix of InnoDB rw_locks
1307 +Author=Yasufumi Kinoshita