Merge lp:~laurynas-biveinis/percona-server/bug1235285 into lp:percona-server/5.6

Proposed by Laurynas Biveinis
Status: Merged
Merged at revision: 460
Proposed branch: lp:~laurynas-biveinis/percona-server/bug1235285
Merge into: lp:percona-server/5.6
Diff against target: 114 lines (+36/-4)
2 files modified
Percona-Server/storage/innobase/include/sync0rw.ic (+15/-1)
Percona-Server/storage/innobase/sync/sync0rw.cc (+21/-3)
To merge this branch: bzr merge lp:~laurynas-biveinis/percona-server/bug1235285
Reviewer Review Type Date Requested Status
Sergei Glushchenko (community) g2 Approve
Review via email: mp+189394@code.launchpad.net

Description of the change

Fix bug 1235285 (Missed wakeup events in priority rw lock).

The following issues were found and addressed.
- high_priority_wait_ex_waiter was never set, meaning, that a sole
high-priority X waiter coming after any S waits will not receive its
wakeup event. Fixed by adding high_priority flag arg to
rw_lock_x_lock_wait() and setting high_priority_wait_ex_waiter there
as needed.

- Since low-priority S acquisitions were made to wait instead of
acquire when a high-priority S lockers exist, it is possible to have
waiters on S releases now. This was not done before, and fixed by
adjusting rw_lock_s_unlock_func() to set the regular RW lock event on
S unlocks too if needed.

http://jenkins.percona.com/job/percona-server-5.6-param/355/

To post a comment you must log in.
Revision history for this message
Sergei Glushchenko (sergei.glushchenko) wrote :

Approve

review: Approve (g2)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Percona-Server/storage/innobase/include/sync0rw.ic'
2--- Percona-Server/storage/innobase/include/sync0rw.ic 2013-09-26 14:58:37 +0000
3+++ Percona-Server/storage/innobase/include/sync0rw.ic 2013-10-04 17:55:53 +0000
4@@ -604,6 +604,8 @@
5 #endif
6 prio_rw_lock_t* lock) /*!< in/out: rw-lock */
7 {
8+ lint lock_word;
9+
10 ut_ad(lock->base_lock.lock_word > -X_LOCK_DECR);
11 ut_ad(lock->base_lock.lock_word != 0);
12 ut_ad(lock->base_lock.lock_word < X_LOCK_DECR);
13@@ -613,7 +615,8 @@
14 #endif
15
16 /* Increment lock_word to indicate 1 less reader */
17- if (rw_lock_lock_word_incr(&lock->base_lock, 1) == 0) {
18+ lock_word = rw_lock_lock_word_incr(&lock->base_lock, 1);
19+ if (lock_word == 0) {
20
21 /* A waiting next-writer exists, either high priority or
22 regular. Wake up the first waiter in this order: 1) high
23@@ -642,6 +645,17 @@
24 os_event_set(lock->base_lock.wait_ex_event);
25 }
26 sync_array_object_signalled();
27+ } else if (lock_word == X_LOCK_DECR) {
28+
29+ /* S-waiters may exist during an S unlock if a high-priority
30+ thread released it, because low-priority threads are prevented
31+ from acquiring S lock while high-priority thread holds it. */
32+ if (lock->base_lock.waiters) {
33+
34+ rw_lock_reset_waiter_flag(&lock->base_lock);
35+ os_event_set(lock->base_lock.event);
36+ sync_array_object_signalled();
37+ }
38 }
39
40 ut_ad(rw_lock_validate(lock));
41
42=== modified file 'Percona-Server/storage/innobase/sync/sync0rw.cc'
43--- Percona-Server/storage/innobase/sync/sync0rw.cc 2013-09-26 14:58:37 +0000
44+++ Percona-Server/storage/innobase/sync/sync0rw.cc 2013-10-04 17:55:53 +0000
45@@ -569,6 +569,10 @@
46 rw_lock_x_lock_wait(
47 /*================*/
48 rw_lock_t* lock, /*!< in: pointer to rw-lock */
49+ bool high_priority,
50+ /*!< in: if true, the rw lock is a priority
51+ lock and is being acquired with high
52+ priority */
53 #ifdef UNIV_SYNC_DEBUG
54 ulint pass, /*!< in: pass value; != 0, if the lock will
55 be passed to another thread to unlock */
56@@ -606,6 +610,13 @@
57 sync_arr, lock, RW_LOCK_WAIT_EX,
58 file_name, line, &index);
59
60+ if (high_priority) {
61+
62+ prio_rw_lock_t* prio_rw_lock
63+ = reinterpret_cast<prio_rw_lock_t *>(lock);
64+ prio_rw_lock->high_priority_wait_ex_waiter = 1;
65+ }
66+
67 i = 0;
68
69 /* Check lock_word to ensure wake-up isn't missed.*/
70@@ -645,6 +656,10 @@
71 rw_lock_x_lock_low(
72 /*===============*/
73 rw_lock_t* lock, /*!< in: pointer to rw-lock */
74+ bool high_priority,
75+ /*!< in: if true, the rw lock is a priority
76+ lock and is being acquired with high
77+ priority */
78 ulint pass, /*!< in: pass value; != 0, if the lock will
79 be passed to another thread to unlock */
80 const char* file_name,/*!< in: file name where lock requested */
81@@ -662,7 +677,7 @@
82 rw_lock_set_writer_id_and_recursion_flag(
83 lock, pass ? FALSE : TRUE);
84
85- rw_lock_x_lock_wait(lock,
86+ rw_lock_x_lock_wait(lock, high_priority,
87 #ifdef UNIV_SYNC_DEBUG
88 pass,
89 #endif
90@@ -737,11 +752,14 @@
91
92 i = 0;
93
94+ ut_ad(priority_lock || !high_priority);
95+
96 lock_loop:
97
98 if (!rw_lock_higher_prio_waiters_exist(priority_lock, high_priority,
99 lock)
100- && rw_lock_x_lock_low(lock, pass, file_name, line)) {
101+ && rw_lock_x_lock_low(lock, high_priority, pass,
102+ file_name, line)) {
103 rw_lock_stats.rw_x_spin_round_count.add(counter_index, i);
104
105 return; /* Locking succeeded */
106@@ -808,7 +826,7 @@
107 rw_lock_set_waiter_flag(lock);
108 }
109
110- if (rw_lock_x_lock_low(lock, pass, file_name, line)) {
111+ if (rw_lock_x_lock_low(lock, high_priority, pass, file_name, line)) {
112 sync_array_free_cell(sync_arr, index);
113 return; /* Locking succeeded */
114 }

Subscribers

People subscribed via source and target branches