Merge lp:~laurynas-biveinis/percona-server/xtradb-thread-priority-flag into lp:percona-server/5.6
- xtradb-thread-priority-flag
- Merge into 5.6
Status: | Merged |
---|---|
Approved by: | Alexey Kopytov |
Approved revision: | no longer in the source branch. |
Merged at revision: | 435 |
Proposed branch: | lp:~laurynas-biveinis/percona-server/xtradb-thread-priority-flag |
Merge into: | lp:percona-server/5.6 |
Diff against target: |
4053 lines (+2141/-303) 48 files modified
Percona-Server/mysql-test/suite/sys_vars/r/innodb_priority_cleaner_basic.result (+31/-0) Percona-Server/mysql-test/suite/sys_vars/r/innodb_priority_io_basic.result (+31/-0) Percona-Server/mysql-test/suite/sys_vars/r/innodb_priority_master_basic.result (+31/-0) Percona-Server/mysql-test/suite/sys_vars/r/innodb_priority_purge_basic.result (+31/-0) Percona-Server/mysql-test/suite/sys_vars/t/innodb_priority_cleaner_basic.test (+40/-0) Percona-Server/mysql-test/suite/sys_vars/t/innodb_priority_io_basic.test (+40/-0) Percona-Server/mysql-test/suite/sys_vars/t/innodb_priority_master_basic.test (+40/-0) Percona-Server/mysql-test/suite/sys_vars/t/innodb_priority_purge_basic.test (+40/-0) Percona-Server/storage/innobase/btr/btr0sea.cc (+3/-3) Percona-Server/storage/innobase/buf/buf0buddy.cc (+1/-1) Percona-Server/storage/innobase/buf/buf0buf.cc (+12/-12) Percona-Server/storage/innobase/buf/buf0flu.cc (+4/-2) Percona-Server/storage/innobase/buf/buf0lru.cc (+6/-6) Percona-Server/storage/innobase/buf/buf0rea.cc (+3/-3) Percona-Server/storage/innobase/fil/fil0fil.cc (+2/-2) Percona-Server/storage/innobase/fsp/fsp0fsp.cc (+11/-11) Percona-Server/storage/innobase/ha/hash0hash.cc (+15/-15) Percona-Server/storage/innobase/handler/ha_innodb.cc (+31/-0) Percona-Server/storage/innobase/include/btr0sea.h (+1/-1) Percona-Server/storage/innobase/include/btr0sea.ic (+1/-1) Percona-Server/storage/innobase/include/btr0types.h (+1/-1) Percona-Server/storage/innobase/include/buf0buf.h (+4/-4) Percona-Server/storage/innobase/include/buf0buf.ic (+4/-4) Percona-Server/storage/innobase/include/dict0dict.h (+2/-2) Percona-Server/storage/innobase/include/dict0dict.ic (+1/-1) Percona-Server/storage/innobase/include/dict0mem.h (+2/-2) Percona-Server/storage/innobase/include/fil0fil.h (+1/-1) Percona-Server/storage/innobase/include/ha0ha.ic (+2/-2) Percona-Server/storage/innobase/include/hash0hash.h (+10/-9) Percona-Server/storage/innobase/include/hash0hash.ic (+4/-4) Percona-Server/storage/innobase/include/log0log.h (+1/-1) Percona-Server/storage/innobase/include/mtr0mtr.h (+3/-3) Percona-Server/storage/innobase/include/mtr0mtr.ic (+3/-3) Percona-Server/storage/innobase/include/srv0srv.h (+12/-0) Percona-Server/storage/innobase/include/sync0rw.h (+350/-70) Percona-Server/storage/innobase/include/sync0rw.ic (+527/-61) Percona-Server/storage/innobase/include/sync0sync.h (+187/-0) Percona-Server/storage/innobase/include/sync0sync.ic (+235/-6) Percona-Server/storage/innobase/include/sync0types.h (+13/-0) Percona-Server/storage/innobase/include/trx0purge.h (+1/-1) Percona-Server/storage/innobase/include/trx0trx.h (+1/-1) Percona-Server/storage/innobase/include/univ.i (+7/-0) Percona-Server/storage/innobase/mtr/mtr0mtr.cc (+2/-2) Percona-Server/storage/innobase/srv/srv0srv.cc (+22/-0) Percona-Server/storage/innobase/srv/srv0start.cc (+1/-0) Percona-Server/storage/innobase/sync/sync0arr.cc (+92/-21) Percona-Server/storage/innobase/sync/sync0rw.cc (+197/-41) Percona-Server/storage/innobase/sync/sync0sync.cc (+82/-6) |
To merge this branch: | bzr merge lp:~laurynas-biveinis/percona-server/xtradb-thread-priority-flag |
Related bugs: | |
Related blueprints: |
XtraDB Thread Priority Flag
(High)
XtraDB Priority Mutex
(High)
XtraDB Priority RW Lock
(High)
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alexey Kopytov (community) | Approve | ||
Review via email: mp+187773@code.launchpad.net |
This proposal supersedes a proposal from 2013-09-20.
Commit message
Description of the change
2nd MP:
Thread priority flag, priority mutex, priority free list refill, priority rw latch.
Jenkins http://
Additionally tested by making sync_arr_
Thread priority flag changes from the original MP:
- UNIV_THREAD_LOCAL defined to __thread under UNIV_LINUX instead
of __GNUC__, and as no-op elsewhere. The original suggestion to define it as
0 on other platforms was not used because lvalue is needed.
- The thread-priority setting system variables are exposed only
under UNIV_LINUX too.
1st MP:
Implement thread priority flag
(https:/
that would be available for InnoDB threads to check whether they
should acquire some shared resource with priority or no. The actual
uses of this flag will be in follow-up.
This flag srv_current_
thread-local storage. There were two other alternatives considered
for its implementation.
1. Passing the flag value from the DECLARE_THREAD functions to its use
sites through the callstacks. But such callstacks would be very
deep and would require patching dozens of InnoDB functions to
include this new arg.
2. pthread_
advantage of being slightly more portable than TLS, but it's more
complicated to use: 1) the flag would have to be allocated in
heap. 2) pthread_
be necessary, moreover they'd have to be placed in mysys instead of
InnoDB and any affected non-mysys-
would have to be converted to initialize mysys. 3)
pthread_
paths, such as mutex locking/unlocking code.
Thus TLS appears to be the best option.
Means to change the flag value for individual InnoDB utility threads
are provided for UNIV_PERF_DEBUG or UNIV_DEBUG builds through the new
global dynamic variables innodb_
innodb_
for them.
http://
Alexey Kopytov (akopytov) wrote : Posted in a previous version of this proposal | # |
Laurynas Biveinis (laurynas-biveinis) wrote : Posted in a previous version of this proposal | # |
Yes, UNIV_LINUX makes more sense than __GNUC__.
Re. isolation. The whole set of changes would be as follows, in the smallest parts:
- This MP.
- Priority mutex implementation.
- Specific buffer pool free list mutex conversion to priority.
- Non-specific mutex conversion to priority: dict_sys, LRU list, rseg, log.
- Priority rwlatch implementation.
- Non-specific rwlatch conversion to priority: fsp, page_hash, AHI, index, purge.
How this should be distributed among MPs? One big one with everything? Are separate commits OK or one big commit too?
Thanks.
Alexey Kopytov (akopytov) wrote : Posted in a previous version of this proposal | # |
1 MP, multiple commits should be fine.
Laurynas Biveinis (laurynas-biveinis) wrote : | # |
Repushed. Removed fprintf, and fixed a typo in the last rw_lock_
Laurynas Biveinis (laurynas-biveinis) wrote : | # |
Jenkins of the repush http://
Alexey Kopytov (akopytov) : | # |
Preview Diff
1 | === added file 'Percona-Server/mysql-test/suite/sys_vars/r/innodb_priority_cleaner_basic.result' |
2 | --- Percona-Server/mysql-test/suite/sys_vars/r/innodb_priority_cleaner_basic.result 1970-01-01 00:00:00 +0000 |
3 | +++ Percona-Server/mysql-test/suite/sys_vars/r/innodb_priority_cleaner_basic.result 2013-09-26 14:59:13 +0000 |
4 | @@ -0,0 +1,31 @@ |
5 | +SET @start_value = @@GLOBAL.innodb_priority_cleaner; |
6 | +SELECT @@GLOBAL.innodb_priority_cleaner; |
7 | +@@GLOBAL.innodb_priority_cleaner |
8 | +0 |
9 | +SELECT @@SESSION.innodb_priority_cleaner; |
10 | +ERROR HY000: Variable 'innodb_priority_cleaner' is a GLOBAL variable |
11 | +SET GLOBAL innodb_priority_cleaner='OFF'; |
12 | +SELECT @@GLOBAL.innodb_priority_cleaner; |
13 | +@@GLOBAL.innodb_priority_cleaner |
14 | +0 |
15 | +SET GLOBAL innodb_priority_cleaner='ON'; |
16 | +SELECT @@GLOBAL.innodb_priority_cleaner; |
17 | +@@GLOBAL.innodb_priority_cleaner |
18 | +1 |
19 | +SET GLOBAL innodb_priority_cleaner=0; |
20 | +SELECT @@GLOBAL.innodb_priority_cleaner; |
21 | +@@GLOBAL.innodb_priority_cleaner |
22 | +0 |
23 | +SET GLOBAL innodb_priority_cleaner=1; |
24 | +SELECT @@GLOBAL.innodb_priority_cleaner; |
25 | +@@GLOBAL.innodb_priority_cleaner |
26 | +1 |
27 | +SET GLOBAL innodb_priority_cleaner=1.1; |
28 | +ERROR 42000: Incorrect argument type to variable 'innodb_priority_cleaner' |
29 | +SET GLOBAL innodb_priority_cleaner=1e1; |
30 | +ERROR 42000: Incorrect argument type to variable 'innodb_priority_cleaner' |
31 | +SET GLOBAL innodb_priority_cleaner=2; |
32 | +ERROR 42000: Variable 'innodb_priority_cleaner' can't be set to the value of '2' |
33 | +SET GLOBAL innodb_priority_cleaner='foo'; |
34 | +ERROR 42000: Variable 'innodb_priority_cleaner' can't be set to the value of 'foo' |
35 | +SET GLOBAL innodb_priority_cleaner = @start_value; |
36 | |
37 | === added file 'Percona-Server/mysql-test/suite/sys_vars/r/innodb_priority_io_basic.result' |
38 | --- Percona-Server/mysql-test/suite/sys_vars/r/innodb_priority_io_basic.result 1970-01-01 00:00:00 +0000 |
39 | +++ Percona-Server/mysql-test/suite/sys_vars/r/innodb_priority_io_basic.result 2013-09-26 14:59:13 +0000 |
40 | @@ -0,0 +1,31 @@ |
41 | +SET @start_value = @@GLOBAL.innodb_priority_io; |
42 | +SELECT @@GLOBAL.innodb_priority_io; |
43 | +@@GLOBAL.innodb_priority_io |
44 | +0 |
45 | +SELECT @@SESSION.innodb_priority_io; |
46 | +ERROR HY000: Variable 'innodb_priority_io' is a GLOBAL variable |
47 | +SET GLOBAL innodb_priority_io='OFF'; |
48 | +SELECT @@GLOBAL.innodb_priority_io; |
49 | +@@GLOBAL.innodb_priority_io |
50 | +0 |
51 | +SET GLOBAL innodb_priority_io='ON'; |
52 | +SELECT @@GLOBAL.innodb_priority_io; |
53 | +@@GLOBAL.innodb_priority_io |
54 | +1 |
55 | +SET GLOBAL innodb_priority_io=0; |
56 | +SELECT @@GLOBAL.innodb_priority_io; |
57 | +@@GLOBAL.innodb_priority_io |
58 | +0 |
59 | +SET GLOBAL innodb_priority_io=1; |
60 | +SELECT @@GLOBAL.innodb_priority_io; |
61 | +@@GLOBAL.innodb_priority_io |
62 | +1 |
63 | +SET GLOBAL innodb_priority_io=1.1; |
64 | +ERROR 42000: Incorrect argument type to variable 'innodb_priority_io' |
65 | +SET GLOBAL innodb_priority_io=1e1; |
66 | +ERROR 42000: Incorrect argument type to variable 'innodb_priority_io' |
67 | +SET GLOBAL innodb_priority_io=2; |
68 | +ERROR 42000: Variable 'innodb_priority_io' can't be set to the value of '2' |
69 | +SET GLOBAL innodb_priority_io='foo'; |
70 | +ERROR 42000: Variable 'innodb_priority_io' can't be set to the value of 'foo' |
71 | +SET GLOBAL innodb_priority_io = @start_value; |
72 | |
73 | === added file 'Percona-Server/mysql-test/suite/sys_vars/r/innodb_priority_master_basic.result' |
74 | --- Percona-Server/mysql-test/suite/sys_vars/r/innodb_priority_master_basic.result 1970-01-01 00:00:00 +0000 |
75 | +++ Percona-Server/mysql-test/suite/sys_vars/r/innodb_priority_master_basic.result 2013-09-26 14:59:13 +0000 |
76 | @@ -0,0 +1,31 @@ |
77 | +SET @start_value = @@GLOBAL.innodb_priority_master; |
78 | +SELECT @@GLOBAL.innodb_priority_master; |
79 | +@@GLOBAL.innodb_priority_master |
80 | +0 |
81 | +SELECT @@SESSION.innodb_priority_master; |
82 | +ERROR HY000: Variable 'innodb_priority_master' is a GLOBAL variable |
83 | +SET GLOBAL innodb_priority_master='OFF'; |
84 | +SELECT @@GLOBAL.innodb_priority_master; |
85 | +@@GLOBAL.innodb_priority_master |
86 | +0 |
87 | +SET GLOBAL innodb_priority_master='ON'; |
88 | +SELECT @@GLOBAL.innodb_priority_master; |
89 | +@@GLOBAL.innodb_priority_master |
90 | +1 |
91 | +SET GLOBAL innodb_priority_master=0; |
92 | +SELECT @@GLOBAL.innodb_priority_master; |
93 | +@@GLOBAL.innodb_priority_master |
94 | +0 |
95 | +SET GLOBAL innodb_priority_master=1; |
96 | +SELECT @@GLOBAL.innodb_priority_master; |
97 | +@@GLOBAL.innodb_priority_master |
98 | +1 |
99 | +SET GLOBAL innodb_priority_master=1.1; |
100 | +ERROR 42000: Incorrect argument type to variable 'innodb_priority_master' |
101 | +SET GLOBAL innodb_priority_master=1e1; |
102 | +ERROR 42000: Incorrect argument type to variable 'innodb_priority_master' |
103 | +SET GLOBAL innodb_priority_master=2; |
104 | +ERROR 42000: Variable 'innodb_priority_master' can't be set to the value of '2' |
105 | +SET GLOBAL innodb_priority_master='foo'; |
106 | +ERROR 42000: Variable 'innodb_priority_master' can't be set to the value of 'foo' |
107 | +SET GLOBAL innodb_priority_master = @start_value; |
108 | |
109 | === added file 'Percona-Server/mysql-test/suite/sys_vars/r/innodb_priority_purge_basic.result' |
110 | --- Percona-Server/mysql-test/suite/sys_vars/r/innodb_priority_purge_basic.result 1970-01-01 00:00:00 +0000 |
111 | +++ Percona-Server/mysql-test/suite/sys_vars/r/innodb_priority_purge_basic.result 2013-09-26 14:59:13 +0000 |
112 | @@ -0,0 +1,31 @@ |
113 | +SET @start_value = @@GLOBAL.innodb_priority_purge; |
114 | +SELECT @@GLOBAL.innodb_priority_purge; |
115 | +@@GLOBAL.innodb_priority_purge |
116 | +0 |
117 | +SELECT @@SESSION.innodb_priority_purge; |
118 | +ERROR HY000: Variable 'innodb_priority_purge' is a GLOBAL variable |
119 | +SET GLOBAL innodb_priority_purge='OFF'; |
120 | +SELECT @@GLOBAL.innodb_priority_purge; |
121 | +@@GLOBAL.innodb_priority_purge |
122 | +0 |
123 | +SET GLOBAL innodb_priority_purge='ON'; |
124 | +SELECT @@GLOBAL.innodb_priority_purge; |
125 | +@@GLOBAL.innodb_priority_purge |
126 | +1 |
127 | +SET GLOBAL innodb_priority_purge=0; |
128 | +SELECT @@GLOBAL.innodb_priority_purge; |
129 | +@@GLOBAL.innodb_priority_purge |
130 | +0 |
131 | +SET GLOBAL innodb_priority_purge=1; |
132 | +SELECT @@GLOBAL.innodb_priority_purge; |
133 | +@@GLOBAL.innodb_priority_purge |
134 | +1 |
135 | +SET GLOBAL innodb_priority_purge=1.1; |
136 | +ERROR 42000: Incorrect argument type to variable 'innodb_priority_purge' |
137 | +SET GLOBAL innodb_priority_purge=1e1; |
138 | +ERROR 42000: Incorrect argument type to variable 'innodb_priority_purge' |
139 | +SET GLOBAL innodb_priority_purge=2; |
140 | +ERROR 42000: Variable 'innodb_priority_purge' can't be set to the value of '2' |
141 | +SET GLOBAL innodb_priority_purge='foo'; |
142 | +ERROR 42000: Variable 'innodb_priority_purge' can't be set to the value of 'foo' |
143 | +SET GLOBAL innodb_priority_purge = @start_value; |
144 | |
145 | === added file 'Percona-Server/mysql-test/suite/sys_vars/t/innodb_priority_cleaner_basic.test' |
146 | --- Percona-Server/mysql-test/suite/sys_vars/t/innodb_priority_cleaner_basic.test 1970-01-01 00:00:00 +0000 |
147 | +++ Percona-Server/mysql-test/suite/sys_vars/t/innodb_priority_cleaner_basic.test 2013-09-26 14:59:13 +0000 |
148 | @@ -0,0 +1,40 @@ |
149 | +--source include/have_debug.inc |
150 | +--source include/have_innodb.inc |
151 | + |
152 | +if (`SELECT @@version_compile_os LIKE "Linux" = 0`) |
153 | +{ |
154 | + skip Needs Linux; |
155 | +} |
156 | + |
157 | +# A dynamic, global variable |
158 | + |
159 | +SET @start_value = @@GLOBAL.innodb_priority_cleaner; |
160 | + |
161 | +# Default value |
162 | +SELECT @@GLOBAL.innodb_priority_cleaner; |
163 | + |
164 | +# Global only |
165 | +--error ER_INCORRECT_GLOBAL_LOCAL_VAR |
166 | +SELECT @@SESSION.innodb_priority_cleaner; |
167 | + |
168 | +# Correct values |
169 | +SET GLOBAL innodb_priority_cleaner='OFF'; |
170 | +SELECT @@GLOBAL.innodb_priority_cleaner; |
171 | +SET GLOBAL innodb_priority_cleaner='ON'; |
172 | +SELECT @@GLOBAL.innodb_priority_cleaner; |
173 | +SET GLOBAL innodb_priority_cleaner=0; |
174 | +SELECT @@GLOBAL.innodb_priority_cleaner; |
175 | +SET GLOBAL innodb_priority_cleaner=1; |
176 | +SELECT @@GLOBAL.innodb_priority_cleaner; |
177 | + |
178 | +# Incorrect values |
179 | +--error ER_WRONG_TYPE_FOR_VAR |
180 | +SET GLOBAL innodb_priority_cleaner=1.1; |
181 | +--error ER_WRONG_TYPE_FOR_VAR |
182 | +SET GLOBAL innodb_priority_cleaner=1e1; |
183 | +--error ER_WRONG_VALUE_FOR_VAR |
184 | +SET GLOBAL innodb_priority_cleaner=2; |
185 | +--error ER_WRONG_VALUE_FOR_VAR |
186 | +SET GLOBAL innodb_priority_cleaner='foo'; |
187 | + |
188 | +SET GLOBAL innodb_priority_cleaner = @start_value; |
189 | |
190 | === added file 'Percona-Server/mysql-test/suite/sys_vars/t/innodb_priority_io_basic.test' |
191 | --- Percona-Server/mysql-test/suite/sys_vars/t/innodb_priority_io_basic.test 1970-01-01 00:00:00 +0000 |
192 | +++ Percona-Server/mysql-test/suite/sys_vars/t/innodb_priority_io_basic.test 2013-09-26 14:59:13 +0000 |
193 | @@ -0,0 +1,40 @@ |
194 | +--source include/have_debug.inc |
195 | +--source include/have_innodb.inc |
196 | + |
197 | +if (`SELECT @@version_compile_os LIKE "Linux" = 0`) |
198 | +{ |
199 | + skip Needs Linux; |
200 | +} |
201 | + |
202 | +# A dynamic, global variable |
203 | + |
204 | +SET @start_value = @@GLOBAL.innodb_priority_io; |
205 | + |
206 | +# Default value |
207 | +SELECT @@GLOBAL.innodb_priority_io; |
208 | + |
209 | +# Global only |
210 | +--error ER_INCORRECT_GLOBAL_LOCAL_VAR |
211 | +SELECT @@SESSION.innodb_priority_io; |
212 | + |
213 | +# Correct values |
214 | +SET GLOBAL innodb_priority_io='OFF'; |
215 | +SELECT @@GLOBAL.innodb_priority_io; |
216 | +SET GLOBAL innodb_priority_io='ON'; |
217 | +SELECT @@GLOBAL.innodb_priority_io; |
218 | +SET GLOBAL innodb_priority_io=0; |
219 | +SELECT @@GLOBAL.innodb_priority_io; |
220 | +SET GLOBAL innodb_priority_io=1; |
221 | +SELECT @@GLOBAL.innodb_priority_io; |
222 | + |
223 | +# Incorrect values |
224 | +--error ER_WRONG_TYPE_FOR_VAR |
225 | +SET GLOBAL innodb_priority_io=1.1; |
226 | +--error ER_WRONG_TYPE_FOR_VAR |
227 | +SET GLOBAL innodb_priority_io=1e1; |
228 | +--error ER_WRONG_VALUE_FOR_VAR |
229 | +SET GLOBAL innodb_priority_io=2; |
230 | +--error ER_WRONG_VALUE_FOR_VAR |
231 | +SET GLOBAL innodb_priority_io='foo'; |
232 | + |
233 | +SET GLOBAL innodb_priority_io = @start_value; |
234 | |
235 | === added file 'Percona-Server/mysql-test/suite/sys_vars/t/innodb_priority_master_basic.test' |
236 | --- Percona-Server/mysql-test/suite/sys_vars/t/innodb_priority_master_basic.test 1970-01-01 00:00:00 +0000 |
237 | +++ Percona-Server/mysql-test/suite/sys_vars/t/innodb_priority_master_basic.test 2013-09-26 14:59:13 +0000 |
238 | @@ -0,0 +1,40 @@ |
239 | +--source include/have_debug.inc |
240 | +--source include/have_innodb.inc |
241 | + |
242 | +if (`SELECT @@version_compile_os LIKE "Linux" = 0`) |
243 | +{ |
244 | + skip Needs Linux; |
245 | +} |
246 | + |
247 | +# A dynamic, global variable |
248 | + |
249 | +SET @start_value = @@GLOBAL.innodb_priority_master; |
250 | + |
251 | +# Default value |
252 | +SELECT @@GLOBAL.innodb_priority_master; |
253 | + |
254 | +# Global only |
255 | +--error ER_INCORRECT_GLOBAL_LOCAL_VAR |
256 | +SELECT @@SESSION.innodb_priority_master; |
257 | + |
258 | +# Correct values |
259 | +SET GLOBAL innodb_priority_master='OFF'; |
260 | +SELECT @@GLOBAL.innodb_priority_master; |
261 | +SET GLOBAL innodb_priority_master='ON'; |
262 | +SELECT @@GLOBAL.innodb_priority_master; |
263 | +SET GLOBAL innodb_priority_master=0; |
264 | +SELECT @@GLOBAL.innodb_priority_master; |
265 | +SET GLOBAL innodb_priority_master=1; |
266 | +SELECT @@GLOBAL.innodb_priority_master; |
267 | + |
268 | +# Incorrect values |
269 | +--error ER_WRONG_TYPE_FOR_VAR |
270 | +SET GLOBAL innodb_priority_master=1.1; |
271 | +--error ER_WRONG_TYPE_FOR_VAR |
272 | +SET GLOBAL innodb_priority_master=1e1; |
273 | +--error ER_WRONG_VALUE_FOR_VAR |
274 | +SET GLOBAL innodb_priority_master=2; |
275 | +--error ER_WRONG_VALUE_FOR_VAR |
276 | +SET GLOBAL innodb_priority_master='foo'; |
277 | + |
278 | +SET GLOBAL innodb_priority_master = @start_value; |
279 | |
280 | === added file 'Percona-Server/mysql-test/suite/sys_vars/t/innodb_priority_purge_basic.test' |
281 | --- Percona-Server/mysql-test/suite/sys_vars/t/innodb_priority_purge_basic.test 1970-01-01 00:00:00 +0000 |
282 | +++ Percona-Server/mysql-test/suite/sys_vars/t/innodb_priority_purge_basic.test 2013-09-26 14:59:13 +0000 |
283 | @@ -0,0 +1,40 @@ |
284 | +--source include/have_debug.inc |
285 | +--source include/have_innodb.inc |
286 | + |
287 | +if (`SELECT @@version_compile_os LIKE "Linux" = 0`) |
288 | +{ |
289 | + skip Needs Linux; |
290 | +} |
291 | + |
292 | +# A dynamic, global variable |
293 | + |
294 | +SET @start_value = @@GLOBAL.innodb_priority_purge; |
295 | + |
296 | +# Default value |
297 | +SELECT @@GLOBAL.innodb_priority_purge; |
298 | + |
299 | +# Global only |
300 | +--error ER_INCORRECT_GLOBAL_LOCAL_VAR |
301 | +SELECT @@SESSION.innodb_priority_purge; |
302 | + |
303 | +# Correct values |
304 | +SET GLOBAL innodb_priority_purge='OFF'; |
305 | +SELECT @@GLOBAL.innodb_priority_purge; |
306 | +SET GLOBAL innodb_priority_purge='ON'; |
307 | +SELECT @@GLOBAL.innodb_priority_purge; |
308 | +SET GLOBAL innodb_priority_purge=0; |
309 | +SELECT @@GLOBAL.innodb_priority_purge; |
310 | +SET GLOBAL innodb_priority_purge=1; |
311 | +SELECT @@GLOBAL.innodb_priority_purge; |
312 | + |
313 | +# Incorrect values |
314 | +--error ER_WRONG_TYPE_FOR_VAR |
315 | +SET GLOBAL innodb_priority_purge=1.1; |
316 | +--error ER_WRONG_TYPE_FOR_VAR |
317 | +SET GLOBAL innodb_priority_purge=1e1; |
318 | +--error ER_WRONG_VALUE_FOR_VAR |
319 | +SET GLOBAL innodb_priority_purge=2; |
320 | +--error ER_WRONG_VALUE_FOR_VAR |
321 | +SET GLOBAL innodb_priority_purge='foo'; |
322 | + |
323 | +SET GLOBAL innodb_priority_purge = @start_value; |
324 | |
325 | === modified file 'Percona-Server/storage/innobase/btr/btr0sea.cc' |
326 | --- Percona-Server/storage/innobase/btr/btr0sea.cc 2013-09-20 05:27:28 +0000 |
327 | +++ Percona-Server/storage/innobase/btr/btr0sea.cc 2013-09-26 14:59:13 +0000 |
328 | @@ -72,7 +72,7 @@ |
329 | being updated in-place! We can use fact (1) to perform unique searches to |
330 | indexes. */ |
331 | |
332 | -UNIV_INTERN rw_lock_t* btr_search_latch_arr; |
333 | +UNIV_INTERN prio_rw_lock_t* btr_search_latch_arr; |
334 | |
335 | /** padding to prevent other memory update hotspots from residing on |
336 | the same memory cache line */ |
337 | @@ -184,8 +184,8 @@ |
338 | /* btr_search_index_num is constrained to machine word size for |
339 | historical reasons. This limitation can be easily removed later. */ |
340 | |
341 | - btr_search_latch_arr = (rw_lock_t *) |
342 | - mem_alloc(sizeof(rw_lock_t) * btr_search_index_num); |
343 | + btr_search_latch_arr = (prio_rw_lock_t *) |
344 | + mem_alloc(sizeof(prio_rw_lock_t) * btr_search_index_num); |
345 | |
346 | btr_search_sys = (btr_search_sys_t*) |
347 | mem_alloc(sizeof(btr_search_sys_t)); |
348 | |
349 | === modified file 'Percona-Server/storage/innobase/buf/buf0buddy.cc' |
350 | --- Percona-Server/storage/innobase/buf/buf0buddy.cc 2013-09-20 05:27:28 +0000 |
351 | +++ Percona-Server/storage/innobase/buf/buf0buddy.cc 2013-09-26 14:59:13 +0000 |
352 | @@ -548,7 +548,7 @@ |
353 | ib_mutex_t* mutex; |
354 | ulint space; |
355 | ulint offset; |
356 | - rw_lock_t* hash_lock; |
357 | + prio_rw_lock_t* hash_lock; |
358 | |
359 | ut_ad(mutex_own(&buf_pool->zip_free_mutex)); |
360 | ut_ad(!mutex_own(&buf_pool->zip_mutex)); |
361 | |
362 | === modified file 'Percona-Server/storage/innobase/buf/buf0buf.cc' |
363 | --- Percona-Server/storage/innobase/buf/buf0buf.cc 2013-09-25 05:20:37 +0000 |
364 | +++ Percona-Server/storage/innobase/buf/buf0buf.cc 2013-09-26 14:59:13 +0000 |
365 | @@ -1640,7 +1640,7 @@ |
366 | buf_page_t* bpage; |
367 | ulint i; |
368 | buf_pool_t* buf_pool = buf_pool_get(space, offset); |
369 | - rw_lock_t* hash_lock; |
370 | + prio_rw_lock_t* hash_lock; |
371 | |
372 | hash_lock = buf_page_hash_lock_get(buf_pool, fold); |
373 | |
374 | @@ -1756,7 +1756,7 @@ |
375 | { |
376 | #ifdef UNIV_SYNC_DEBUG |
377 | /* We must also own the appropriate hash_bucket mutex. */ |
378 | - rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, fold); |
379 | + prio_rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, fold); |
380 | ut_ad(rw_lock_own(hash_lock, RW_LOCK_EX)); |
381 | #endif /* UNIV_SYNC_DEBUG */ |
382 | |
383 | @@ -1782,7 +1782,7 @@ |
384 | buf_page_t* bpage; |
385 | buf_pool_t* buf_pool = buf_pool_get(space, offset); |
386 | ulint fold = buf_page_address_fold(space, offset); |
387 | - rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, |
388 | + prio_rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, |
389 | fold); |
390 | |
391 | rw_lock_x_lock(hash_lock); |
392 | @@ -1828,7 +1828,7 @@ |
393 | buf_page_t* bpage; |
394 | buf_pool_t* buf_pool = buf_pool_get(space, offset); |
395 | ulint fold = buf_page_address_fold(space, offset); |
396 | - rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, |
397 | + prio_rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, |
398 | fold); |
399 | |
400 | rw_lock_s_lock(hash_lock); |
401 | @@ -1919,7 +1919,7 @@ |
402 | { |
403 | buf_page_t* bpage; |
404 | buf_pool_t* buf_pool = buf_pool_get(space, offset); |
405 | - rw_lock_t* hash_lock; |
406 | + prio_rw_lock_t* hash_lock; |
407 | |
408 | bpage = buf_page_hash_get_s_locked(buf_pool, space, offset, |
409 | &hash_lock); |
410 | @@ -1953,7 +1953,7 @@ |
411 | { |
412 | buf_page_t* bpage; |
413 | buf_pool_t* buf_pool = buf_pool_get(space, offset); |
414 | - rw_lock_t* hash_lock; |
415 | + prio_rw_lock_t* hash_lock; |
416 | |
417 | bpage = buf_page_hash_get_s_locked(buf_pool, space, offset, |
418 | &hash_lock); |
419 | @@ -2031,7 +2031,7 @@ |
420 | { |
421 | buf_page_t* bpage; |
422 | ib_mutex_t* block_mutex; |
423 | - rw_lock_t* hash_lock; |
424 | + prio_rw_lock_t* hash_lock; |
425 | ibool discard_attempted = FALSE; |
426 | ibool must_read; |
427 | trx_t* trx = NULL; |
428 | @@ -2505,7 +2505,7 @@ |
429 | unsigned access_time; |
430 | ulint fix_type; |
431 | ibool must_read; |
432 | - rw_lock_t* hash_lock; |
433 | + prio_rw_lock_t* hash_lock; |
434 | ib_mutex_t* block_mutex; |
435 | buf_page_t* hash_bpage; |
436 | ulint retries = 0; |
437 | @@ -3286,7 +3286,7 @@ |
438 | ibool success; |
439 | ulint fix_type; |
440 | buf_pool_t* buf_pool = buf_pool_get(space_id, page_no); |
441 | - rw_lock_t* hash_lock; |
442 | + prio_rw_lock_t* hash_lock; |
443 | |
444 | ut_ad(mtr); |
445 | ut_ad(mtr->state == MTR_ACTIVE); |
446 | @@ -3498,7 +3498,7 @@ |
447 | buf_block_t* block; |
448 | buf_page_t* bpage = NULL; |
449 | buf_page_t* watch_page; |
450 | - rw_lock_t* hash_lock; |
451 | + prio_rw_lock_t* hash_lock; |
452 | mtr_t mtr; |
453 | ulint fold; |
454 | ibool lru = FALSE; |
455 | @@ -3751,7 +3751,7 @@ |
456 | ulint fold; |
457 | buf_block_t* free_block = NULL; |
458 | buf_pool_t* buf_pool = buf_pool_get(space, offset); |
459 | - rw_lock_t* hash_lock; |
460 | + prio_rw_lock_t* hash_lock; |
461 | |
462 | ut_ad(mtr); |
463 | ut_ad(mtr->state == MTR_ACTIVE); |
464 | @@ -4007,7 +4007,7 @@ |
465 | ibool ret = TRUE; |
466 | const ulint fold = buf_page_address_fold(bpage->space, |
467 | bpage->offset); |
468 | - rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, fold); |
469 | + prio_rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, fold); |
470 | |
471 | /* First unfix and release lock on the bpage */ |
472 | mutex_enter(&buf_pool->LRU_list_mutex); |
473 | |
474 | === modified file 'Percona-Server/storage/innobase/buf/buf0flu.cc' |
475 | --- Percona-Server/storage/innobase/buf/buf0flu.cc 2013-09-25 05:20:37 +0000 |
476 | +++ Percona-Server/storage/innobase/buf/buf0flu.cc 2013-09-26 14:59:13 +0000 |
477 | @@ -1141,7 +1141,7 @@ |
478 | buf_page_t* bpage; |
479 | buf_pool_t* buf_pool = buf_pool_get(space, offset); |
480 | bool ret; |
481 | - rw_lock_t* hash_lock; |
482 | + prio_rw_lock_t* hash_lock; |
483 | ib_mutex_t* block_mutex; |
484 | |
485 | ut_ad(flush_type == BUF_FLUSH_LRU |
486 | @@ -1260,7 +1260,7 @@ |
487 | for (i = low; i < high; i++) { |
488 | |
489 | buf_page_t* bpage; |
490 | - rw_lock_t* hash_lock; |
491 | + prio_rw_lock_t* hash_lock; |
492 | ib_mutex_t* block_mutex; |
493 | |
494 | if ((count + n_flushed) >= n_to_flush) { |
495 | @@ -2452,6 +2452,8 @@ |
496 | |
497 | while (srv_shutdown_state == SRV_SHUTDOWN_NONE) { |
498 | |
499 | + srv_current_thread_priority = srv_cleaner_thread_priority; |
500 | + |
501 | /* The page_cleaner skips sleep if the server is |
502 | idle and there are no pending IOs in the buffer pool |
503 | and there is work to do. */ |
504 | |
505 | === modified file 'Percona-Server/storage/innobase/buf/buf0lru.cc' |
506 | --- Percona-Server/storage/innobase/buf/buf0lru.cc 2013-09-20 05:27:28 +0000 |
507 | +++ Percona-Server/storage/innobase/buf/buf0lru.cc 2013-09-26 14:59:13 +0000 |
508 | @@ -751,7 +751,7 @@ |
509 | bpage != NULL; |
510 | /* No op */) { |
511 | |
512 | - rw_lock_t* hash_lock; |
513 | + prio_rw_lock_t* hash_lock; |
514 | buf_page_t* prev_bpage; |
515 | ib_mutex_t* block_mutex = NULL; |
516 | |
517 | @@ -1187,7 +1187,7 @@ |
518 | { |
519 | buf_block_t* block; |
520 | |
521 | - mutex_enter(&buf_pool->free_list_mutex); |
522 | + mutex_enter_last(&buf_pool->free_list_mutex); |
523 | |
524 | block = (buf_block_t*) UT_LIST_GET_LAST(buf_pool->free); |
525 | |
526 | @@ -1900,7 +1900,7 @@ |
527 | buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); |
528 | const ulint fold = buf_page_address_fold(bpage->space, |
529 | bpage->offset); |
530 | - rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, fold); |
531 | + prio_rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, fold); |
532 | |
533 | ib_mutex_t* block_mutex = buf_page_get_mutex(bpage); |
534 | |
535 | @@ -2228,7 +2228,7 @@ |
536 | page_zip_set_size(&block->page.zip, 0); |
537 | } |
538 | |
539 | - mutex_enter(&buf_pool->free_list_mutex); |
540 | + mutex_enter_first(&buf_pool->free_list_mutex); |
541 | buf_block_set_state(block, BUF_BLOCK_NOT_USED); |
542 | UT_LIST_ADD_FIRST(list, buf_pool->free, (&block->page)); |
543 | ut_d(block->page.in_free_list = TRUE); |
544 | @@ -2264,7 +2264,7 @@ |
545 | ulint fold; |
546 | const buf_page_t* hashed_bpage; |
547 | buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); |
548 | - rw_lock_t* hash_lock; |
549 | + prio_rw_lock_t* hash_lock; |
550 | |
551 | ut_ad(bpage); |
552 | ut_ad(mutex_own(&buf_pool->LRU_list_mutex)); |
553 | @@ -2513,7 +2513,7 @@ |
554 | #ifdef UNIV_SYNC_DEBUG |
555 | const ulint fold = buf_page_address_fold(bpage->space, |
556 | bpage->offset); |
557 | - rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, fold); |
558 | + prio_rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, fold); |
559 | #endif |
560 | ib_mutex_t* block_mutex = buf_page_get_mutex(bpage); |
561 | |
562 | |
563 | === modified file 'Percona-Server/storage/innobase/buf/buf0rea.cc' |
564 | --- Percona-Server/storage/innobase/buf/buf0rea.cc 2013-09-20 05:27:28 +0000 |
565 | +++ Percona-Server/storage/innobase/buf/buf0rea.cc 2013-09-26 14:59:13 +0000 |
566 | @@ -65,7 +65,7 @@ |
567 | == BUF_BLOCK_FILE_PAGE); |
568 | const ulint fold = buf_page_address_fold(bpage->space, |
569 | bpage->offset); |
570 | - rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, fold); |
571 | + prio_rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, fold); |
572 | |
573 | mutex_enter(&buf_pool->LRU_list_mutex); |
574 | rw_lock_x_lock(hash_lock); |
575 | @@ -347,7 +347,7 @@ |
576 | |
577 | for (i = low; i < high; i++) { |
578 | |
579 | - rw_lock_t* hash_lock; |
580 | + prio_rw_lock_t* hash_lock; |
581 | |
582 | const buf_page_t* bpage = |
583 | buf_page_hash_get_s_locked(buf_pool, space, i, |
584 | @@ -642,7 +642,7 @@ |
585 | |
586 | for (i = low; i < high; i++) { |
587 | |
588 | - rw_lock_t* hash_lock; |
589 | + prio_rw_lock_t* hash_lock; |
590 | |
591 | bpage = buf_page_hash_get_s_locked(buf_pool, space, i, |
592 | &hash_lock); |
593 | |
594 | === modified file 'Percona-Server/storage/innobase/fil/fil0fil.cc' |
595 | --- Percona-Server/storage/innobase/fil/fil0fil.cc 2013-09-09 14:20:25 +0000 |
596 | +++ Percona-Server/storage/innobase/fil/fil0fil.cc 2013-09-26 14:59:13 +0000 |
597 | @@ -238,7 +238,7 @@ |
598 | hash_node_t hash; /*!< hash chain node */ |
599 | hash_node_t name_hash;/*!< hash chain the name_hash table */ |
600 | #ifndef UNIV_HOTBACKUP |
601 | - rw_lock_t latch; /*!< latch protecting the file space storage |
602 | + prio_rw_lock_t latch; /*!< latch protecting the file space storage |
603 | allocation */ |
604 | #endif /* !UNIV_HOTBACKUP */ |
605 | UT_LIST_NODE_T(fil_space_t) unflushed_spaces; |
606 | @@ -545,7 +545,7 @@ |
607 | Returns the latch of a file space. |
608 | @return latch protecting storage allocation */ |
609 | UNIV_INTERN |
610 | -rw_lock_t* |
611 | +prio_rw_lock_t* |
612 | fil_space_get_latch( |
613 | /*================*/ |
614 | ulint id, /*!< in: space id */ |
615 | |
616 | === modified file 'Percona-Server/storage/innobase/fsp/fsp0fsp.cc' |
617 | --- Percona-Server/storage/innobase/fsp/fsp0fsp.cc 2013-09-20 05:27:28 +0000 |
618 | +++ Percona-Server/storage/innobase/fsp/fsp0fsp.cc 2013-09-26 14:59:13 +0000 |
619 | @@ -2044,7 +2044,7 @@ |
620 | ib_id_t seg_id; |
621 | buf_block_t* block = 0; /* remove warning */ |
622 | fseg_header_t* header = 0; /* remove warning */ |
623 | - rw_lock_t* latch; |
624 | + prio_rw_lock_t* latch; |
625 | ibool success; |
626 | ulint n_reserved; |
627 | ulint i; |
628 | @@ -2212,7 +2212,7 @@ |
629 | ulint space; |
630 | ulint flags; |
631 | ulint zip_size; |
632 | - rw_lock_t* latch; |
633 | + prio_rw_lock_t* latch; |
634 | |
635 | space = page_get_space_id(page_align(header)); |
636 | latch = fil_space_get_latch(space, &flags); |
637 | @@ -2632,7 +2632,7 @@ |
638 | ulint space; |
639 | ulint flags; |
640 | ulint zip_size; |
641 | - rw_lock_t* latch; |
642 | + prio_rw_lock_t* latch; |
643 | buf_block_t* block; |
644 | ulint n_reserved; |
645 | |
646 | @@ -2749,7 +2749,7 @@ |
647 | mtr_t* mtr) /*!< in/out: mini-transaction */ |
648 | { |
649 | fsp_header_t* space_header; |
650 | - rw_lock_t* latch; |
651 | + prio_rw_lock_t* latch; |
652 | ulint n_free_list_ext; |
653 | ulint free_limit; |
654 | ulint size; |
655 | @@ -2865,7 +2865,7 @@ |
656 | ulint n_free; |
657 | ulint n_free_up; |
658 | ulint reserve; |
659 | - rw_lock_t* latch; |
660 | + prio_rw_lock_t* latch; |
661 | mtr_t mtr; |
662 | |
663 | /* The convoluted mutex acquire is to overcome latching order |
664 | @@ -3195,7 +3195,7 @@ |
665 | ulint flags; |
666 | ulint zip_size; |
667 | fseg_inode_t* seg_inode; |
668 | - rw_lock_t* latch; |
669 | + prio_rw_lock_t* latch; |
670 | |
671 | latch = fil_space_get_latch(space, &flags); |
672 | zip_size = fsp_flags_get_zip_size(flags); |
673 | @@ -3225,7 +3225,7 @@ |
674 | mtr_t mtr; |
675 | ibool is_free; |
676 | ulint flags; |
677 | - rw_lock_t* latch; |
678 | + prio_rw_lock_t* latch; |
679 | xdes_t* descr; |
680 | ulint zip_size; |
681 | fseg_inode_t* seg_inode; |
682 | @@ -3350,7 +3350,7 @@ |
683 | ulint flags; |
684 | ulint zip_size; |
685 | ulint header_page; |
686 | - rw_lock_t* latch; |
687 | + prio_rw_lock_t* latch; |
688 | |
689 | space = page_get_space_id(page_align(header)); |
690 | header_page = page_get_page_no(page_align(header)); |
691 | @@ -3438,7 +3438,7 @@ |
692 | ulint flags; |
693 | ulint zip_size; |
694 | ulint page_no; |
695 | - rw_lock_t* latch; |
696 | + prio_rw_lock_t* latch; |
697 | |
698 | space = page_get_space_id(page_align(header)); |
699 | |
700 | @@ -3755,7 +3755,7 @@ |
701 | fsp_header_t* header; |
702 | fseg_inode_t* seg_inode; |
703 | page_t* seg_inode_page; |
704 | - rw_lock_t* latch; |
705 | + prio_rw_lock_t* latch; |
706 | ulint size; |
707 | ulint flags; |
708 | ulint zip_size; |
709 | @@ -4007,7 +4007,7 @@ |
710 | fsp_header_t* header; |
711 | fseg_inode_t* seg_inode; |
712 | page_t* seg_inode_page; |
713 | - rw_lock_t* latch; |
714 | + prio_rw_lock_t* latch; |
715 | ulint flags; |
716 | ulint zip_size; |
717 | ulint size; |
718 | |
719 | === modified file 'Percona-Server/storage/innobase/ha/hash0hash.cc' |
720 | --- Percona-Server/storage/innobase/ha/hash0hash.cc 2013-08-06 15:16:34 +0000 |
721 | +++ Percona-Server/storage/innobase/ha/hash0hash.cc 2013-09-26 14:59:13 +0000 |
722 | @@ -105,15 +105,15 @@ |
723 | void |
724 | hash_mutex_exit_all_but( |
725 | /*====================*/ |
726 | - hash_table_t* table, /*!< in: hash table */ |
727 | - ib_mutex_t* keep_mutex) /*!< in: mutex to keep */ |
728 | + hash_table_t* table, /*!< in: hash table */ |
729 | + ib_prio_mutex_t* keep_mutex) /*!< in: mutex to keep */ |
730 | { |
731 | ulint i; |
732 | |
733 | ut_ad(table->type == HASH_TABLE_SYNC_MUTEX); |
734 | for (i = 0; i < table->n_sync_obj; i++) { |
735 | |
736 | - ib_mutex_t* mutex = table->sync_obj.mutexes + i; |
737 | + ib_prio_mutex_t* mutex = table->sync_obj.mutexes + i; |
738 | if (UNIV_LIKELY(keep_mutex != mutex)) { |
739 | mutex_exit(mutex); |
740 | } |
741 | @@ -132,7 +132,7 @@ |
742 | ulint fold) /*!< in: fold */ |
743 | { |
744 | |
745 | - rw_lock_t* lock = hash_get_lock(table, fold); |
746 | + prio_rw_lock_t* lock = hash_get_lock(table, fold); |
747 | |
748 | ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); |
749 | ut_ad(lock); |
750 | @@ -155,7 +155,7 @@ |
751 | ulint fold) /*!< in: fold */ |
752 | { |
753 | |
754 | - rw_lock_t* lock = hash_get_lock(table, fold); |
755 | + prio_rw_lock_t* lock = hash_get_lock(table, fold); |
756 | |
757 | ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); |
758 | ut_ad(lock); |
759 | @@ -179,7 +179,7 @@ |
760 | ulint fold) /*!< in: fold */ |
761 | { |
762 | |
763 | - rw_lock_t* lock = hash_get_lock(table, fold); |
764 | + prio_rw_lock_t* lock = hash_get_lock(table, fold); |
765 | |
766 | ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); |
767 | ut_ad(lock); |
768 | @@ -200,7 +200,7 @@ |
769 | hash_table_t* table, /*!< in: hash table */ |
770 | ulint fold) /*!< in: fold */ |
771 | { |
772 | - rw_lock_t* lock = hash_get_lock(table, fold); |
773 | + prio_rw_lock_t* lock = hash_get_lock(table, fold); |
774 | |
775 | ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); |
776 | ut_ad(lock); |
777 | @@ -225,7 +225,7 @@ |
778 | ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); |
779 | for (i = 0; i < table->n_sync_obj; i++) { |
780 | |
781 | - rw_lock_t* lock = table->sync_obj.rw_locks + i; |
782 | + prio_rw_lock_t* lock = table->sync_obj.rw_locks + i; |
783 | #ifdef UNIV_SYNC_DEBUG |
784 | ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); |
785 | ut_ad(!rw_lock_own(lock, RW_LOCK_EX)); |
786 | @@ -248,7 +248,7 @@ |
787 | ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); |
788 | for (i = 0; i < table->n_sync_obj; i++) { |
789 | |
790 | - rw_lock_t* lock = table->sync_obj.rw_locks + i; |
791 | + prio_rw_lock_t* lock = table->sync_obj.rw_locks + i; |
792 | #ifdef UNIV_SYNC_DEBUG |
793 | ut_ad(rw_lock_own(lock, RW_LOCK_EX)); |
794 | #endif /* UNIV_SYNC_DEBUG */ |
795 | @@ -264,14 +264,14 @@ |
796 | hash_unlock_x_all_but( |
797 | /*==================*/ |
798 | hash_table_t* table, /*!< in: hash table */ |
799 | - rw_lock_t* keep_lock) /*!< in: lock to keep */ |
800 | + prio_rw_lock_t* keep_lock) /*!< in: lock to keep */ |
801 | { |
802 | ulint i; |
803 | |
804 | ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); |
805 | for (i = 0; i < table->n_sync_obj; i++) { |
806 | |
807 | - rw_lock_t* lock = table->sync_obj.rw_locks + i; |
808 | + prio_rw_lock_t* lock = table->sync_obj.rw_locks + i; |
809 | #ifdef UNIV_SYNC_DEBUG |
810 | ut_ad(rw_lock_own(lock, RW_LOCK_EX)); |
811 | #endif /* UNIV_SYNC_DEBUG */ |
812 | @@ -373,8 +373,8 @@ |
813 | |
814 | switch (type) { |
815 | case HASH_TABLE_SYNC_MUTEX: |
816 | - table->sync_obj.mutexes = static_cast<ib_mutex_t*>( |
817 | - mem_alloc(n_sync_obj * sizeof(ib_mutex_t))); |
818 | + table->sync_obj.mutexes = static_cast<ib_prio_mutex_t*>( |
819 | + mem_alloc(n_sync_obj * sizeof(ib_prio_mutex_t))); |
820 | |
821 | for (i = 0; i < n_sync_obj; i++) { |
822 | mutex_create(hash_table_mutex_key, |
823 | @@ -384,8 +384,8 @@ |
824 | break; |
825 | |
826 | case HASH_TABLE_SYNC_RW_LOCK: |
827 | - table->sync_obj.rw_locks = static_cast<rw_lock_t*>( |
828 | - mem_alloc(n_sync_obj * sizeof(rw_lock_t))); |
829 | + table->sync_obj.rw_locks = static_cast<prio_rw_lock_t*>( |
830 | + mem_alloc(n_sync_obj * sizeof(prio_rw_lock_t))); |
831 | |
832 | for (i = 0; i < n_sync_obj; i++) { |
833 | rw_lock_create(hash_table_rw_lock_key, |
834 | |
835 | === modified file 'Percona-Server/storage/innobase/handler/ha_innodb.cc' |
836 | --- Percona-Server/storage/innobase/handler/ha_innodb.cc 2013-09-24 13:11:08 +0000 |
837 | +++ Percona-Server/storage/innobase/handler/ha_innodb.cc 2013-09-26 14:59:13 +0000 |
838 | @@ -16549,6 +16549,31 @@ |
839 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, |
840 | "Number of pages reserved in doublewrite buffer for batch flushing", |
841 | NULL, NULL, 120, 1, 127, 0); |
842 | + |
843 | +#ifdef UNIV_LINUX |
844 | + |
845 | +static MYSQL_SYSVAR_BOOL(priority_purge, srv_purge_thread_priority, |
846 | + PLUGIN_VAR_OPCMDARG, |
847 | + "Make purge coordinator and worker threads acquire shared resources with " |
848 | + "priority", NULL, NULL, FALSE); |
849 | + |
850 | +static MYSQL_SYSVAR_BOOL(priority_io, srv_io_thread_priority, |
851 | + PLUGIN_VAR_OPCMDARG, |
852 | + "Make I/O threads acquire shared resources with priority", |
853 | + NULL, NULL, FALSE); |
854 | + |
855 | +static MYSQL_SYSVAR_BOOL(priority_cleaner, srv_cleaner_thread_priority, |
856 | + PLUGIN_VAR_OPCMDARG, |
857 | + "Make buffer pool cleaner thread acquire shared resources with priority", |
858 | + NULL, NULL, FALSE); |
859 | + |
860 | +static MYSQL_SYSVAR_BOOL(priority_master, srv_master_thread_priority, |
861 | + PLUGIN_VAR_OPCMDARG, |
862 | + "Make buffer pool cleaner thread acquire shared resources with priority", |
863 | + NULL, NULL, FALSE); |
864 | + |
865 | +#endif /* UNIV_LINUX */ |
866 | + |
867 | #endif /* defined UNIV_DEBUG || defined UNIV_PERF_DEBUG */ |
868 | |
869 | static MYSQL_SYSVAR_LONG(buffer_pool_instances, innobase_buffer_pool_instances, |
870 | @@ -17210,6 +17235,12 @@ |
871 | #if defined UNIV_DEBUG || defined UNIV_PERF_DEBUG |
872 | MYSQL_SYSVAR(page_hash_locks), |
873 | MYSQL_SYSVAR(doublewrite_batch_size), |
874 | +#ifdef UNIV_LINUX |
875 | + MYSQL_SYSVAR(priority_purge), |
876 | + MYSQL_SYSVAR(priority_io), |
877 | + MYSQL_SYSVAR(priority_cleaner), |
878 | + MYSQL_SYSVAR(priority_master), |
879 | +#endif /* UNIV_LINUX */ |
880 | #endif /* defined UNIV_DEBUG || defined UNIV_PERF_DEBUG */ |
881 | MYSQL_SYSVAR(print_all_deadlocks), |
882 | MYSQL_SYSVAR(cmp_per_index_enabled), |
883 | |
884 | === modified file 'Percona-Server/storage/innobase/include/btr0sea.h' |
885 | --- Percona-Server/storage/innobase/include/btr0sea.h 2013-09-06 13:40:39 +0000 |
886 | +++ Percona-Server/storage/innobase/include/btr0sea.h 2013-09-26 14:59:13 +0000 |
887 | @@ -208,7 +208,7 @@ |
888 | Returns the adaptive hash index latch for a given index key. |
889 | @return the adaptive hash index latch for a given index key */ |
890 | UNIV_INLINE |
891 | -rw_lock_t* |
892 | +prio_rw_lock_t* |
893 | btr_search_get_latch( |
894 | /*=================*/ |
895 | const dict_index_t* index) /*!< in: index */ |
896 | |
897 | === modified file 'Percona-Server/storage/innobase/include/btr0sea.ic' |
898 | --- Percona-Server/storage/innobase/include/btr0sea.ic 2013-09-06 13:40:39 +0000 |
899 | +++ Percona-Server/storage/innobase/include/btr0sea.ic 2013-09-26 14:59:13 +0000 |
900 | @@ -100,7 +100,7 @@ |
901 | Returns the adaptive hash index latch for a given index key. |
902 | @return the adaptive hash index latch for a given index key */ |
903 | UNIV_INLINE |
904 | -rw_lock_t* |
905 | +prio_rw_lock_t* |
906 | btr_search_get_latch( |
907 | /*=================*/ |
908 | const dict_index_t* index) /*!< in: index */ |
909 | |
910 | === modified file 'Percona-Server/storage/innobase/include/btr0types.h' |
911 | --- Percona-Server/storage/innobase/include/btr0types.h 2013-09-06 13:40:39 +0000 |
912 | +++ Percona-Server/storage/innobase/include/btr0types.h 2013-09-26 14:59:13 +0000 |
913 | @@ -55,7 +55,7 @@ |
914 | Bear in mind (3) and (4) when using the hash indexes. |
915 | */ |
916 | |
917 | -extern rw_lock_t* btr_search_latch_arr; |
918 | +extern prio_rw_lock_t* btr_search_latch_arr; |
919 | |
920 | #endif /* UNIV_HOTBACKUP */ |
921 | |
922 | |
923 | === modified file 'Percona-Server/storage/innobase/include/buf0buf.h' |
924 | --- Percona-Server/storage/innobase/include/buf0buf.h 2013-09-20 05:27:28 +0000 |
925 | +++ Percona-Server/storage/innobase/include/buf0buf.h 2013-09-26 14:59:13 +0000 |
926 | @@ -1256,7 +1256,7 @@ |
927 | buf_pool_t* buf_pool, /*!< buffer pool instance */ |
928 | ulint space, /*!< in: space id */ |
929 | ulint offset, /*!< in: page number */ |
930 | - rw_lock_t** lock, /*!< in/out: lock of the page |
931 | + prio_rw_lock_t** lock, /*!< in/out: lock of the page |
932 | hash acquired if bpage is |
933 | found. NULL otherwise. If NULL |
934 | is passed then the hash_lock |
935 | @@ -1282,7 +1282,7 @@ |
936 | buf_pool_t* buf_pool, /*!< buffer pool instance */ |
937 | ulint space, /*!< in: space id */ |
938 | ulint offset, /*!< in: page number */ |
939 | - rw_lock_t** lock, /*!< in/out: lock of the page |
940 | + prio_rw_lock_t** lock, /*!< in/out: lock of the page |
941 | hash acquired if bpage is |
942 | found. NULL otherwise. If NULL |
943 | is passed then the hash_lock |
944 | @@ -1818,8 +1818,8 @@ |
945 | pool instance, protects compressed |
946 | only pages (of type buf_page_t, not |
947 | buf_block_t */ |
948 | - ib_mutex_t LRU_list_mutex; |
949 | - ib_mutex_t free_list_mutex; |
950 | + ib_prio_mutex_t LRU_list_mutex; |
951 | + ib_prio_mutex_t free_list_mutex; |
952 | ib_mutex_t zip_free_mutex; |
953 | ib_mutex_t zip_hash_mutex; |
954 | ib_mutex_t flush_state_mutex; /*!< Flush state protection |
955 | |
956 | === modified file 'Percona-Server/storage/innobase/include/buf0buf.ic' |
957 | --- Percona-Server/storage/innobase/include/buf0buf.ic 2013-09-20 05:27:28 +0000 |
958 | +++ Percona-Server/storage/innobase/include/buf0buf.ic 2013-09-26 14:59:13 +0000 |
959 | @@ -1100,7 +1100,7 @@ |
960 | |
961 | #ifdef UNIV_SYNC_DEBUG |
962 | ulint hash_fold; |
963 | - rw_lock_t* hash_lock; |
964 | + prio_rw_lock_t* hash_lock; |
965 | |
966 | hash_fold = buf_page_address_fold(space, offset); |
967 | ut_ad(hash_fold == fold); |
968 | @@ -1149,7 +1149,7 @@ |
969 | buf_pool_t* buf_pool, /*!< buffer pool instance */ |
970 | ulint space, /*!< in: space id */ |
971 | ulint offset, /*!< in: page number */ |
972 | - rw_lock_t** lock, /*!< in/out: lock of the page |
973 | + prio_rw_lock_t** lock, /*!< in/out: lock of the page |
974 | hash acquired if bpage is |
975 | found. NULL otherwise. If NULL |
976 | is passed then the hash_lock |
977 | @@ -1160,7 +1160,7 @@ |
978 | { |
979 | buf_page_t* bpage = NULL; |
980 | ulint fold; |
981 | - rw_lock_t* hash_lock; |
982 | + prio_rw_lock_t* hash_lock; |
983 | ulint mode = RW_LOCK_SHARED; |
984 | |
985 | if (lock != NULL) { |
986 | @@ -1232,7 +1232,7 @@ |
987 | buf_pool_t* buf_pool, /*!< buffer pool instance */ |
988 | ulint space, /*!< in: space id */ |
989 | ulint offset, /*!< in: page number */ |
990 | - rw_lock_t** lock, /*!< in/out: lock of the page |
991 | + prio_rw_lock_t** lock, /*!< in/out: lock of the page |
992 | hash acquired if bpage is |
993 | found. NULL otherwise. If NULL |
994 | is passed then the hash_lock |
995 | |
996 | === modified file 'Percona-Server/storage/innobase/include/dict0dict.h' |
997 | --- Percona-Server/storage/innobase/include/dict0dict.h 2013-08-14 03:57:21 +0000 |
998 | +++ Percona-Server/storage/innobase/include/dict0dict.h 2013-09-26 14:59:13 +0000 |
999 | @@ -1367,7 +1367,7 @@ |
1000 | Gets the read-write lock of the index tree. |
1001 | @return read-write lock */ |
1002 | UNIV_INLINE |
1003 | -rw_lock_t* |
1004 | +prio_rw_lock_t* |
1005 | dict_index_get_lock( |
1006 | /*================*/ |
1007 | dict_index_t* index) /*!< in: index */ |
1008 | @@ -1552,7 +1552,7 @@ |
1009 | |
1010 | /* Dictionary system struct */ |
1011 | struct dict_sys_t{ |
1012 | - ib_mutex_t mutex; /*!< mutex protecting the data |
1013 | + ib_prio_mutex_t mutex; /*!< mutex protecting the data |
1014 | dictionary; protects also the |
1015 | disk-based dictionary system tables; |
1016 | this mutex serializes CREATE TABLE |
1017 | |
1018 | === modified file 'Percona-Server/storage/innobase/include/dict0dict.ic' |
1019 | --- Percona-Server/storage/innobase/include/dict0dict.ic 2013-08-06 15:16:34 +0000 |
1020 | +++ Percona-Server/storage/innobase/include/dict0dict.ic 2013-09-26 14:59:13 +0000 |
1021 | @@ -1175,7 +1175,7 @@ |
1022 | Gets the read-write lock of the index tree. |
1023 | @return read-write lock */ |
1024 | UNIV_INLINE |
1025 | -rw_lock_t* |
1026 | +prio_rw_lock_t* |
1027 | dict_index_get_lock( |
1028 | /*================*/ |
1029 | dict_index_t* index) /*!< in: index */ |
1030 | |
1031 | === modified file 'Percona-Server/storage/innobase/include/dict0mem.h' |
1032 | --- Percona-Server/storage/innobase/include/dict0mem.h 2013-09-02 10:01:38 +0000 |
1033 | +++ Percona-Server/storage/innobase/include/dict0mem.h 2013-09-26 14:59:13 +0000 |
1034 | @@ -544,7 +544,7 @@ |
1035 | initialized to 0, NULL or FALSE in dict_mem_index_create(). */ |
1036 | struct dict_index_t{ |
1037 | index_id_t id; /*!< id of the index */ |
1038 | - rw_lock_t* search_latch; /*!< latch protecting the AHI partition |
1039 | + prio_rw_lock_t* search_latch; /*!< latch protecting the AHI partition |
1040 | corresponding to this index */ |
1041 | hash_table_t* search_table; /*!< hash table protected by |
1042 | search_latch */ |
1043 | @@ -632,7 +632,7 @@ |
1044 | /*!< approximate number of leaf pages in the |
1045 | index tree */ |
1046 | /* @} */ |
1047 | - rw_lock_t lock; /*!< read-write lock protecting the |
1048 | + prio_rw_lock_t lock; /*!< read-write lock protecting the |
1049 | upper levels of the index tree */ |
1050 | trx_id_t trx_id; /*!< id of the transaction that created this |
1051 | index, or 0 if the index existed |
1052 | |
1053 | === modified file 'Percona-Server/storage/innobase/include/fil0fil.h' |
1054 | --- Percona-Server/storage/innobase/include/fil0fil.h 2013-08-14 03:57:21 +0000 |
1055 | +++ Percona-Server/storage/innobase/include/fil0fil.h 2013-09-26 14:59:13 +0000 |
1056 | @@ -189,7 +189,7 @@ |
1057 | Returns the latch of a file space. |
1058 | @return latch protecting storage allocation */ |
1059 | UNIV_INTERN |
1060 | -rw_lock_t* |
1061 | +prio_rw_lock_t* |
1062 | fil_space_get_latch( |
1063 | /*================*/ |
1064 | ulint id, /*!< in: space id */ |
1065 | |
1066 | === modified file 'Percona-Server/storage/innobase/include/ha0ha.ic' |
1067 | --- Percona-Server/storage/innobase/include/ha0ha.ic 2013-08-06 15:16:34 +0000 |
1068 | +++ Percona-Server/storage/innobase/include/ha0ha.ic 2013-09-26 14:59:13 +0000 |
1069 | @@ -123,7 +123,7 @@ |
1070 | ut_ad(mutex_own(hash_get_mutex(table, fold))); |
1071 | } else if (table->type == HASH_TABLE_SYNC_RW_LOCK) { |
1072 | # ifdef UNIV_SYNC_DEBUG |
1073 | - rw_lock_t* lock = hash_get_lock(table, fold); |
1074 | + prio_rw_lock_t* lock = hash_get_lock(table, fold); |
1075 | ut_ad(rw_lock_own(lock, RW_LOCK_EX)); |
1076 | # endif |
1077 | } else { |
1078 | @@ -146,7 +146,7 @@ |
1079 | ut_ad(mutex_own(hash_get_mutex(table, fold))); |
1080 | } else if (table->type == HASH_TABLE_SYNC_RW_LOCK) { |
1081 | # ifdef UNIV_SYNC_DEBUG |
1082 | - rw_lock_t* lock = hash_get_lock(table, fold); |
1083 | + prio_rw_lock_t* lock = hash_get_lock(table, fold); |
1084 | ut_ad(rw_lock_own(lock, RW_LOCK_EX) |
1085 | || rw_lock_own(lock, RW_LOCK_SHARED)); |
1086 | # endif |
1087 | |
1088 | === modified file 'Percona-Server/storage/innobase/include/hash0hash.h' |
1089 | --- Percona-Server/storage/innobase/include/hash0hash.h 2013-08-06 15:16:34 +0000 |
1090 | +++ Percona-Server/storage/innobase/include/hash0hash.h 2013-09-26 14:59:13 +0000 |
1091 | @@ -382,7 +382,7 @@ |
1092 | Gets the nth mutex in a hash table. |
1093 | @return mutex */ |
1094 | UNIV_INLINE |
1095 | -ib_mutex_t* |
1096 | +ib_prio_mutex_t* |
1097 | hash_get_nth_mutex( |
1098 | /*===============*/ |
1099 | hash_table_t* table, /*!< in: hash table */ |
1100 | @@ -391,7 +391,7 @@ |
1101 | Gets the nth rw_lock in a hash table. |
1102 | @return rw_lock */ |
1103 | UNIV_INLINE |
1104 | -rw_lock_t* |
1105 | +prio_rw_lock_t* |
1106 | hash_get_nth_lock( |
1107 | /*==============*/ |
1108 | hash_table_t* table, /*!< in: hash table */ |
1109 | @@ -400,7 +400,7 @@ |
1110 | Gets the mutex for a fold value in a hash table. |
1111 | @return mutex */ |
1112 | UNIV_INLINE |
1113 | -ib_mutex_t* |
1114 | +ib_prio_mutex_t* |
1115 | hash_get_mutex( |
1116 | /*===========*/ |
1117 | hash_table_t* table, /*!< in: hash table */ |
1118 | @@ -409,7 +409,7 @@ |
1119 | Gets the rw_lock for a fold value in a hash table. |
1120 | @return rw_lock */ |
1121 | UNIV_INLINE |
1122 | -rw_lock_t* |
1123 | +prio_rw_lock_t* |
1124 | hash_get_lock( |
1125 | /*==========*/ |
1126 | hash_table_t* table, /*!< in: hash table */ |
1127 | @@ -450,8 +450,8 @@ |
1128 | void |
1129 | hash_mutex_exit_all_but( |
1130 | /*====================*/ |
1131 | - hash_table_t* table, /*!< in: hash table */ |
1132 | - ib_mutex_t* keep_mutex); /*!< in: mutex to keep */ |
1133 | + hash_table_t* table, /*!< in: hash table */ |
1134 | + ib_prio_mutex_t* keep_mutex); /*!< in: mutex to keep */ |
1135 | /************************************************************//** |
1136 | s-lock a lock for a fold value in a hash table. */ |
1137 | UNIV_INTERN |
1138 | @@ -506,7 +506,7 @@ |
1139 | hash_unlock_x_all_but( |
1140 | /*==================*/ |
1141 | hash_table_t* table, /*!< in: hash table */ |
1142 | - rw_lock_t* keep_lock); /*!< in: lock to keep */ |
1143 | + prio_rw_lock_t* keep_lock); /*!< in: lock to keep */ |
1144 | |
1145 | #else /* !UNIV_HOTBACKUP */ |
1146 | # define hash_get_heap(table, fold) ((table)->heap) |
1147 | @@ -547,10 +547,11 @@ |
1148 | rw_locks depending on the type. |
1149 | Must be a power of 2 */ |
1150 | union { |
1151 | - ib_mutex_t* mutexes;/* NULL, or an array of mutexes |
1152 | + ib_prio_mutex_t* mutexes; |
1153 | + /* NULL, or an array of mutexes |
1154 | used to protect segments of the |
1155 | hash table */ |
1156 | - rw_lock_t* rw_locks;/* NULL, or an array of rw_lcoks |
1157 | + prio_rw_lock_t* rw_locks;/* NULL, or an array of rw_lcoks |
1158 | used to protect segments of the |
1159 | hash table */ |
1160 | } sync_obj; |
1161 | |
1162 | === modified file 'Percona-Server/storage/innobase/include/hash0hash.ic' |
1163 | --- Percona-Server/storage/innobase/include/hash0hash.ic 2013-08-06 15:16:34 +0000 |
1164 | +++ Percona-Server/storage/innobase/include/hash0hash.ic 2013-09-26 14:59:13 +0000 |
1165 | @@ -150,7 +150,7 @@ |
1166 | Gets the nth mutex in a hash table. |
1167 | @return mutex */ |
1168 | UNIV_INLINE |
1169 | -ib_mutex_t* |
1170 | +ib_prio_mutex_t* |
1171 | hash_get_nth_mutex( |
1172 | /*===============*/ |
1173 | hash_table_t* table, /*!< in: hash table */ |
1174 | @@ -168,7 +168,7 @@ |
1175 | Gets the mutex for a fold value in a hash table. |
1176 | @return mutex */ |
1177 | UNIV_INLINE |
1178 | -ib_mutex_t* |
1179 | +ib_prio_mutex_t* |
1180 | hash_get_mutex( |
1181 | /*===========*/ |
1182 | hash_table_t* table, /*!< in: hash table */ |
1183 | @@ -188,7 +188,7 @@ |
1184 | Gets the nth rw_lock in a hash table. |
1185 | @return rw_lock */ |
1186 | UNIV_INLINE |
1187 | -rw_lock_t* |
1188 | +prio_rw_lock_t* |
1189 | hash_get_nth_lock( |
1190 | /*==============*/ |
1191 | hash_table_t* table, /*!< in: hash table */ |
1192 | @@ -206,7 +206,7 @@ |
1193 | Gets the rw_lock for a fold value in a hash table. |
1194 | @return rw_lock */ |
1195 | UNIV_INLINE |
1196 | -rw_lock_t* |
1197 | +prio_rw_lock_t* |
1198 | hash_get_lock( |
1199 | /*==========*/ |
1200 | hash_table_t* table, /*!< in: hash table */ |
1201 | |
1202 | === modified file 'Percona-Server/storage/innobase/include/log0log.h' |
1203 | --- Percona-Server/storage/innobase/include/log0log.h 2013-06-25 13:13:06 +0000 |
1204 | +++ Percona-Server/storage/innobase/include/log0log.h 2013-09-26 14:59:13 +0000 |
1205 | @@ -796,7 +796,7 @@ |
1206 | ulint buf_free; /*!< first free offset within the log |
1207 | buffer */ |
1208 | #ifndef UNIV_HOTBACKUP |
1209 | - ib_mutex_t mutex; /*!< mutex protecting the log */ |
1210 | + ib_prio_mutex_t mutex; /*!< mutex protecting the log */ |
1211 | |
1212 | ib_mutex_t log_flush_order_mutex;/*!< mutex to serialize access to |
1213 | the flush list when we are putting |
1214 | |
1215 | === modified file 'Percona-Server/storage/innobase/include/mtr0mtr.h' |
1216 | --- Percona-Server/storage/innobase/include/mtr0mtr.h 2013-06-25 13:13:06 +0000 |
1217 | +++ Percona-Server/storage/innobase/include/mtr0mtr.h 2013-09-26 14:59:13 +0000 |
1218 | @@ -234,7 +234,7 @@ |
1219 | /*=============================*/ |
1220 | mtr_t* mtr, /*!< in: mtr */ |
1221 | ulint savepoint, /*!< in: savepoint */ |
1222 | - rw_lock_t* lock); /*!< in: latch to release */ |
1223 | + prio_rw_lock_t* lock); /*!< in: latch to release */ |
1224 | #else /* !UNIV_HOTBACKUP */ |
1225 | # define mtr_release_s_latch_at_savepoint(mtr,savepoint,lock) ((void) 0) |
1226 | #endif /* !UNIV_HOTBACKUP */ |
1227 | @@ -281,7 +281,7 @@ |
1228 | void |
1229 | mtr_s_lock_func( |
1230 | /*============*/ |
1231 | - rw_lock_t* lock, /*!< in: rw-lock */ |
1232 | + prio_rw_lock_t* lock, /*!< in: rw-lock */ |
1233 | const char* file, /*!< in: file name */ |
1234 | ulint line, /*!< in: line number */ |
1235 | mtr_t* mtr); /*!< in: mtr */ |
1236 | @@ -292,7 +292,7 @@ |
1237 | void |
1238 | mtr_x_lock_func( |
1239 | /*============*/ |
1240 | - rw_lock_t* lock, /*!< in: rw-lock */ |
1241 | + prio_rw_lock_t* lock, /*!< in: rw-lock */ |
1242 | const char* file, /*!< in: file name */ |
1243 | ulint line, /*!< in: line number */ |
1244 | mtr_t* mtr); /*!< in: mtr */ |
1245 | |
1246 | === modified file 'Percona-Server/storage/innobase/include/mtr0mtr.ic' |
1247 | --- Percona-Server/storage/innobase/include/mtr0mtr.ic 2013-05-26 14:20:00 +0000 |
1248 | +++ Percona-Server/storage/innobase/include/mtr0mtr.ic 2013-09-26 14:59:13 +0000 |
1249 | @@ -130,7 +130,7 @@ |
1250 | /*=============================*/ |
1251 | mtr_t* mtr, /*!< in: mtr */ |
1252 | ulint savepoint, /*!< in: savepoint */ |
1253 | - rw_lock_t* lock) /*!< in: latch to release */ |
1254 | + prio_rw_lock_t* lock) /*!< in: latch to release */ |
1255 | { |
1256 | mtr_memo_slot_t* slot; |
1257 | dyn_array_t* memo; |
1258 | @@ -261,7 +261,7 @@ |
1259 | void |
1260 | mtr_s_lock_func( |
1261 | /*============*/ |
1262 | - rw_lock_t* lock, /*!< in: rw-lock */ |
1263 | + prio_rw_lock_t* lock, /*!< in: rw-lock */ |
1264 | const char* file, /*!< in: file name */ |
1265 | ulint line, /*!< in: line number */ |
1266 | mtr_t* mtr) /*!< in: mtr */ |
1267 | @@ -280,7 +280,7 @@ |
1268 | void |
1269 | mtr_x_lock_func( |
1270 | /*============*/ |
1271 | - rw_lock_t* lock, /*!< in: rw-lock */ |
1272 | + prio_rw_lock_t* lock, /*!< in: rw-lock */ |
1273 | const char* file, /*!< in: file name */ |
1274 | ulint line, /*!< in: line number */ |
1275 | mtr_t* mtr) /*!< in: mtr */ |
1276 | |
1277 | === modified file 'Percona-Server/storage/innobase/include/srv0srv.h' |
1278 | --- Percona-Server/storage/innobase/include/srv0srv.h 2013-08-06 15:16:34 +0000 |
1279 | +++ Percona-Server/storage/innobase/include/srv0srv.h 2013-09-26 14:59:13 +0000 |
1280 | @@ -479,6 +479,18 @@ |
1281 | extern const char* srv_io_thread_op_info[]; |
1282 | extern const char* srv_io_thread_function[]; |
1283 | |
1284 | +/* The relative priority of the purge coordinator and worker threads. */ |
1285 | +extern my_bool srv_purge_thread_priority; |
1286 | + |
1287 | +/* The relative priority of the I/O threads. */ |
1288 | +extern my_bool srv_io_thread_priority; |
1289 | + |
1290 | +/* The relative priority of the cleaner thread. */ |
1291 | +extern my_bool srv_cleaner_thread_priority; |
1292 | + |
1293 | +/* The relative priority of the master thread. */ |
1294 | +extern my_bool srv_master_thread_priority; |
1295 | + |
1296 | /* the number of purge threads to use from the worker pool (currently 0 or 1) */ |
1297 | extern ulong srv_n_purge_threads; |
1298 | |
1299 | |
1300 | === modified file 'Percona-Server/storage/innobase/include/sync0rw.h' |
1301 | --- Percona-Server/storage/innobase/include/sync0rw.h 2013-08-06 15:16:34 +0000 |
1302 | +++ Percona-Server/storage/innobase/include/sync0rw.h 2013-09-26 14:59:13 +0000 |
1303 | @@ -96,6 +96,7 @@ |
1304 | #define X_LOCK_DECR 0x00100000 |
1305 | |
1306 | struct rw_lock_t; |
1307 | +struct prio_rw_lock_t; |
1308 | #ifdef UNIV_SYNC_DEBUG |
1309 | struct rw_lock_debug_t; |
1310 | #endif /* UNIV_SYNC_DEBUG */ |
1311 | @@ -299,6 +300,24 @@ |
1312 | #endif /* UNIV_DEBUG */ |
1313 | const char* cmutex_name); /*!< in: mutex name */ |
1314 | /******************************************************************//** |
1315 | +Creates, or rather, initializes a priority rw-lock object in a specified memory |
1316 | +location (which must be appropriately aligned). The rw-lock is initialized |
1317 | +to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free |
1318 | +is necessary only if the memory block containing it is freed. */ |
1319 | +UNIV_INTERN |
1320 | +void |
1321 | +rw_lock_create_func( |
1322 | +/*================*/ |
1323 | + prio_rw_lock_t* lock, /*!< in: pointer to memory */ |
1324 | +#ifdef UNIV_DEBUG |
1325 | +# ifdef UNIV_SYNC_DEBUG |
1326 | + ulint level, /*!< in: level */ |
1327 | +# endif /* UNIV_SYNC_DEBUG */ |
1328 | + const char* cfile_name, /*!< in: file name where created */ |
1329 | + ulint cline, /*!< in: file line where created */ |
1330 | +#endif /* UNIV_DEBUG */ |
1331 | + const char* cmutex_name); /*!< in: mutex name */ |
1332 | +/******************************************************************//** |
1333 | Calling this function is obligatory only if the memory buffer containing |
1334 | the rw-lock is freed. Removes an rw-lock object from the global list. The |
1335 | rw-lock is checked to be in the non-locked state. */ |
1336 | @@ -307,6 +326,15 @@ |
1337 | rw_lock_free_func( |
1338 | /*==============*/ |
1339 | rw_lock_t* lock); /*!< in: rw-lock */ |
1340 | +/******************************************************************//** |
1341 | +Calling this function is obligatory only if the memory buffer containing |
1342 | +the priority rw-lock is freed. Removes an rw-lock object from the global list. |
1343 | +The rw-lock is checked to be in the non-locked state. */ |
1344 | +UNIV_INTERN |
1345 | +void |
1346 | +rw_lock_free_func( |
1347 | +/*==============*/ |
1348 | + prio_rw_lock_t* lock); /*!< in: rw-lock */ |
1349 | #ifdef UNIV_DEBUG |
1350 | /******************************************************************//** |
1351 | Checks that the rw-lock has been initialized and that there are no |
1352 | @@ -317,6 +345,15 @@ |
1353 | rw_lock_validate( |
1354 | /*=============*/ |
1355 | rw_lock_t* lock); /*!< in: rw-lock */ |
1356 | +/******************************************************************//** |
1357 | +Checks that the priority rw-lock has been initialized and that there are no |
1358 | +simultaneous shared and exclusive locks. |
1359 | +@return TRUE */ |
1360 | +UNIV_INTERN |
1361 | +ibool |
1362 | +rw_lock_validate( |
1363 | +/*=============*/ |
1364 | + prio_rw_lock_t* lock); /*!< in: rw-lock */ |
1365 | #endif /* UNIV_DEBUG */ |
1366 | /******************************************************************//** |
1367 | Low-level function which tries to lock an rw-lock in s-mode. Performs no |
1368 | @@ -349,6 +386,22 @@ |
1369 | const char* file_name,/*!< in: file name where lock requested */ |
1370 | ulint line); /*!< in: line where requested */ |
1371 | /******************************************************************//** |
1372 | +NOTE! Use the corresponding macro, not directly this function, except if |
1373 | +you supply the file name and line number. Lock a priority rw-lock in shared |
1374 | +mode for the current thread, using the relative thread priority. If the |
1375 | +rw-lock is locked in exclusive mode, or there is an exclusive lock request |
1376 | +waiting, the function spins a preset time (controlled by SYNC_SPIN_ROUNDS), |
1377 | +waiting for the lock, before suspending the thread. */ |
1378 | +UNIV_INLINE |
1379 | +void |
1380 | +rw_lock_s_lock_func( |
1381 | +/*================*/ |
1382 | + prio_rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
1383 | + ulint pass, /*!< in: pass value; != 0, if the lock will |
1384 | + be passed to another thread to unlock */ |
1385 | + const char* file_name,/*!< in: file name where lock requested */ |
1386 | + ulint line); /*!< in: line where requested */ |
1387 | +/******************************************************************//** |
1388 | NOTE! Use the corresponding macro, not directly this function! Lock an |
1389 | rw-lock in exclusive mode for the current thread if the lock can be |
1390 | obtained immediately. |
1391 | @@ -373,6 +426,17 @@ |
1392 | rw_lock_t* lock); /*!< in/out: rw-lock */ |
1393 | |
1394 | /******************************************************************//** |
1395 | +Releases a shared mode priority lock. */ |
1396 | +UNIV_INLINE |
1397 | +void |
1398 | +rw_lock_s_unlock_func( |
1399 | +/*==================*/ |
1400 | +#ifdef UNIV_SYNC_DEBUG |
1401 | + ulint pass, /*!< in: pass value; != 0, if the lock may have |
1402 | + been passed to another thread to unlock */ |
1403 | +#endif |
1404 | + prio_rw_lock_t* lock); /*!< in/out: rw-lock */ |
1405 | +/******************************************************************//** |
1406 | NOTE! Use the corresponding macro, not directly this function! Lock an |
1407 | rw-lock in exclusive mode for the current thread. If the rw-lock is locked |
1408 | in shared or exclusive mode, or there is an exclusive lock request waiting, |
1409 | @@ -385,7 +449,30 @@ |
1410 | void |
1411 | rw_lock_x_lock_func( |
1412 | /*================*/ |
1413 | - rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
1414 | + rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
1415 | + ulint pass, /*!< in: pass value; != 0, if the lock will |
1416 | + be passed to another thread to unlock */ |
1417 | + const char* file_name,/*!< in: file name where lock requested */ |
1418 | + ulint line, /*!< in: line where requested */ |
1419 | + bool priority_lock = false, |
1420 | + /*!< in: whether the lock is a priority lock */ |
1421 | + bool high_priority = false); |
1422 | + /*!< in: whether we are acquiring a priority |
1423 | + lock with high priority */ |
1424 | +/******************************************************************//** |
1425 | +NOTE! Use the corresponding macro, not directly this function! Lock a priority |
1426 | +rw-lock in exclusive mode for the current thread. If the rw-lock is locked |
1427 | +in shared or exclusive mode, or there is an exclusive lock request waiting, |
1428 | +the function spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting |
1429 | +for the lock, before suspending the thread. If the same thread has an x-lock |
1430 | +on the rw-lock, locking succeed, with the following exception: if pass != 0, |
1431 | +only a single x-lock may be taken on the lock. NOTE: If the same thread has |
1432 | +an s-lock, locking does not succeed! */ |
1433 | +UNIV_INTERN |
1434 | +void |
1435 | +rw_lock_x_lock_func( |
1436 | +/*================*/ |
1437 | + prio_rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
1438 | ulint pass, /*!< in: pass value; != 0, if the lock will |
1439 | be passed to another thread to unlock */ |
1440 | const char* file_name,/*!< in: file name where lock requested */ |
1441 | @@ -402,6 +489,17 @@ |
1442 | #endif |
1443 | rw_lock_t* lock); /*!< in/out: rw-lock */ |
1444 | /******************************************************************//** |
1445 | +Releases an exclusive mode priority lock. */ |
1446 | +UNIV_INLINE |
1447 | +void |
1448 | +rw_lock_x_unlock_func( |
1449 | +/*==================*/ |
1450 | +#ifdef UNIV_SYNC_DEBUG |
1451 | + ulint pass, /*!< in: pass value; != 0, if the lock may have |
1452 | + been passed to another thread to unlock */ |
1453 | +#endif |
1454 | + prio_rw_lock_t* lock); /*!< in/out: rw-lock */ |
1455 | +/******************************************************************//** |
1456 | This function is used in the insert buffer to move the ownership of an |
1457 | x-latch on a buffer frame to the current thread. The x-latch was set by |
1458 | the buffer read operation and it protected the buffer frame while the |
1459 | @@ -424,6 +522,15 @@ |
1460 | rw_lock_get_x_lock_count( |
1461 | /*=====================*/ |
1462 | const rw_lock_t* lock); /*!< in: rw-lock */ |
1463 | +/******************************************************************//** |
1464 | +Returns the value of writer_count for the priority lock. Does not reserve the |
1465 | +lock mutex, so the caller must be sure it is not changed during the call. |
1466 | +@return value of writer_count */ |
1467 | +UNIV_INLINE |
1468 | +ulint |
1469 | +rw_lock_get_x_lock_count( |
1470 | +/*=====================*/ |
1471 | + const prio_rw_lock_t* lock); /*!< in: rw-lock */ |
1472 | /********************************************************************//** |
1473 | Check if there are threads waiting for the rw-lock. |
1474 | @return 1 if waiters, 0 otherwise */ |
1475 | @@ -432,6 +539,14 @@ |
1476 | rw_lock_get_waiters( |
1477 | /*================*/ |
1478 | const rw_lock_t* lock); /*!< in: rw-lock */ |
1479 | +/********************************************************************//** |
1480 | +Check if there are threads waiting for the priority rw-lock. |
1481 | +@return 1 if waiters, 0 otherwise */ |
1482 | +UNIV_INLINE |
1483 | +ulint |
1484 | +rw_lock_get_waiters( |
1485 | +/*================*/ |
1486 | + const prio_rw_lock_t* lock); /*!< in: rw-lock */ |
1487 | /******************************************************************//** |
1488 | Returns the write-status of the lock - this function made more sense |
1489 | with the old rw_lock implementation. |
1490 | @@ -442,6 +557,15 @@ |
1491 | /*===============*/ |
1492 | const rw_lock_t* lock); /*!< in: rw-lock */ |
1493 | /******************************************************************//** |
1494 | +Returns the write-status of the priority lock - this function made more sense |
1495 | +with the old rw_lock implementation. |
1496 | +@return RW_LOCK_NOT_LOCKED, RW_LOCK_EX, RW_LOCK_WAIT_EX */ |
1497 | +UNIV_INLINE |
1498 | +ulint |
1499 | +rw_lock_get_writer( |
1500 | +/*===============*/ |
1501 | + const prio_rw_lock_t* lock); /*!< in: rw-lock */ |
1502 | +/******************************************************************//** |
1503 | Returns the number of readers. |
1504 | @return number of readers */ |
1505 | UNIV_INLINE |
1506 | @@ -450,6 +574,14 @@ |
1507 | /*=====================*/ |
1508 | const rw_lock_t* lock); /*!< in: rw-lock */ |
1509 | /******************************************************************//** |
1510 | +Returns the number of readers. |
1511 | +@return number of readers */ |
1512 | +UNIV_INLINE |
1513 | +ulint |
1514 | +rw_lock_get_reader_count( |
1515 | +/*=====================*/ |
1516 | + const prio_rw_lock_t* lock); /*!< in: rw-lock */ |
1517 | +/******************************************************************//** |
1518 | Decrements lock_word the specified amount if it is greater than 0. |
1519 | This is used by both s_lock and x_lock operations. |
1520 | @return TRUE if decr occurs */ |
1521 | @@ -496,6 +628,17 @@ |
1522 | ulint lock_type) /*!< in: lock type: RW_LOCK_SHARED, |
1523 | RW_LOCK_EX */ |
1524 | __attribute__((warn_unused_result)); |
1525 | +/******************************************************************//** |
1526 | +Checks if the thread has locked the priority rw-lock in the specified mode, |
1527 | +with the pass value == 0. */ |
1528 | +UNIV_INTERN |
1529 | +ibool |
1530 | +rw_lock_own( |
1531 | +/*========*/ |
1532 | + prio_rw_lock_t* lock, /*!< in: rw-lock */ |
1533 | + ulint lock_type) /*!< in: lock type: RW_LOCK_SHARED, |
1534 | + RW_LOCK_EX */ |
1535 | + __attribute__((warn_unused_result)); |
1536 | #endif /* UNIV_SYNC_DEBUG */ |
1537 | /******************************************************************//** |
1538 | Checks if somebody has locked the rw-lock in the specified mode. */ |
1539 | @@ -631,6 +774,27 @@ |
1540 | #endif /* UNIV_DEBUG */ |
1541 | }; |
1542 | |
1543 | +/** The structure implementing a priority rw lock. */ |
1544 | +struct prio_rw_lock_t { |
1545 | + struct rw_lock_t base_lock; /* The regular rw latch |
1546 | + provides the lock word etc. for |
1547 | + the priority rw lock */ |
1548 | + volatile ulint high_priority_s_waiters; |
1549 | + /* If 1, high priority S |
1550 | + waiters exist */ |
1551 | + os_event_t high_priority_s_event; /* High priority wait |
1552 | + array event for S waiters */ |
1553 | + volatile ulint high_priority_x_waiters; |
1554 | + /* If 1, high priority X |
1555 | + waiters exist */ |
1556 | + os_event_t high_priority_x_event; |
1557 | + /* High priority wait arraay |
1558 | + event for X waiters */ |
1559 | + volatile ulint high_priority_wait_ex_waiter; |
1560 | + /* If 1, a waiting next-writer |
1561 | + exists and is high-priority */ |
1562 | +}; |
1563 | + |
1564 | #ifdef UNIV_SYNC_DEBUG |
1565 | /** The structure for storing debug info of an rw-lock. All access to this |
1566 | structure must be protected by rw_lock_debug_mutex_enter(). */ |
1567 | @@ -695,6 +859,26 @@ |
1568 | const char* cmutex_name); /*!< in: mutex name */ |
1569 | |
1570 | /******************************************************************//** |
1571 | +Performance schema instrumented wrap function for rw_lock_create_func() |
1572 | +NOTE! Please use the corresponding macro rw_lock_create(), not |
1573 | +directly this function! */ |
1574 | +UNIV_INLINE |
1575 | +void |
1576 | +pfs_rw_lock_create_func( |
1577 | +/*====================*/ |
1578 | + PSI_rwlock_key key, /*!< in: key registered with |
1579 | + performance schema */ |
1580 | + prio_rw_lock_t* lock, /*!< in: rw lock */ |
1581 | +#ifdef UNIV_DEBUG |
1582 | +# ifdef UNIV_SYNC_DEBUG |
1583 | + ulint level, /*!< in: level */ |
1584 | +# endif /* UNIV_SYNC_DEBUG */ |
1585 | + const char* cfile_name, /*!< in: file name where created */ |
1586 | + ulint cline, /*!< in: file line where created */ |
1587 | +#endif /* UNIV_DEBUG */ |
1588 | + const char* cmutex_name); /*!< in: mutex name */ |
1589 | + |
1590 | +/******************************************************************//** |
1591 | Performance schema instrumented wrap function for rw_lock_x_lock_func() |
1592 | NOTE! Please use the corresponding macro rw_lock_x_lock(), not |
1593 | directly this function! */ |
1594 | @@ -707,6 +891,21 @@ |
1595 | be passed to another thread to unlock */ |
1596 | const char* file_name,/*!< in: file name where lock requested */ |
1597 | ulint line); /*!< in: line where requested */ |
1598 | + |
1599 | +/******************************************************************//** |
1600 | +Performance schema instrumented wrap function for rw_lock_x_lock_func() |
1601 | +NOTE! Please use the corresponding macro rw_lock_x_lock(), not |
1602 | +directly this function! */ |
1603 | +UNIV_INLINE |
1604 | +void |
1605 | +pfs_rw_lock_x_lock_func( |
1606 | +/*====================*/ |
1607 | + prio_rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
1608 | + ulint pass, /*!< in: pass value; != 0, if the lock will |
1609 | + be passed to another thread to unlock */ |
1610 | + const char* file_name,/*!< in: file name where lock requested */ |
1611 | + ulint line); /*!< in: line where requested */ |
1612 | + |
1613 | /******************************************************************//** |
1614 | Performance schema instrumented wrap function for |
1615 | rw_lock_x_lock_func_nowait() |
1616 | @@ -719,75 +918,147 @@ |
1617 | rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
1618 | const char* file_name,/*!< in: file name where lock requested */ |
1619 | ulint line); /*!< in: line where requested */ |
1620 | -/******************************************************************//** |
1621 | -Performance schema instrumented wrap function for rw_lock_s_lock_func() |
1622 | -NOTE! Please use the corresponding macro rw_lock_s_lock(), not directly |
1623 | -this function! */ |
1624 | -UNIV_INLINE |
1625 | -void |
1626 | -pfs_rw_lock_s_lock_func( |
1627 | -/*====================*/ |
1628 | - rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
1629 | - ulint pass, /*!< in: pass value; != 0, if the lock will |
1630 | - be passed to another thread to unlock */ |
1631 | - const char* file_name,/*!< in: file name where lock requested */ |
1632 | - ulint line); /*!< in: line where requested */ |
1633 | -/******************************************************************//** |
1634 | -Performance schema instrumented wrap function for rw_lock_s_lock_func() |
1635 | -NOTE! Please use the corresponding macro rw_lock_s_lock(), not directly |
1636 | -this function! |
1637 | -@return TRUE if success */ |
1638 | -UNIV_INLINE |
1639 | -ibool |
1640 | -pfs_rw_lock_s_lock_low( |
1641 | -/*===================*/ |
1642 | - rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
1643 | - ulint pass, /*!< in: pass value; != 0, if the |
1644 | - lock will be passed to another |
1645 | - thread to unlock */ |
1646 | - const char* file_name, /*!< in: file name where lock requested */ |
1647 | - ulint line); /*!< in: line where requested */ |
1648 | -/******************************************************************//** |
1649 | -Performance schema instrumented wrap function for rw_lock_x_lock_func() |
1650 | -NOTE! Please use the corresponding macro rw_lock_x_lock(), not directly |
1651 | -this function! */ |
1652 | -UNIV_INLINE |
1653 | -void |
1654 | -pfs_rw_lock_x_lock_func( |
1655 | -/*====================*/ |
1656 | - rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
1657 | - ulint pass, /*!< in: pass value; != 0, if the lock will |
1658 | - be passed to another thread to unlock */ |
1659 | - const char* file_name,/*!< in: file name where lock requested */ |
1660 | - ulint line); /*!< in: line where requested */ |
1661 | -/******************************************************************//** |
1662 | -Performance schema instrumented wrap function for rw_lock_s_unlock_func() |
1663 | -NOTE! Please use the corresponding macro rw_lock_s_unlock(), not directly |
1664 | -this function! */ |
1665 | -UNIV_INLINE |
1666 | -void |
1667 | -pfs_rw_lock_s_unlock_func( |
1668 | -/*======================*/ |
1669 | -#ifdef UNIV_SYNC_DEBUG |
1670 | - ulint pass, /*!< in: pass value; != 0, if the |
1671 | - lock may have been passed to another |
1672 | - thread to unlock */ |
1673 | -#endif |
1674 | - rw_lock_t* lock); /*!< in/out: rw-lock */ |
1675 | -/******************************************************************//** |
1676 | -Performance schema instrumented wrap function for rw_lock_s_unlock_func() |
1677 | -NOTE! Please use the corresponding macro rw_lock_x_unlock(), not directly |
1678 | -this function! */ |
1679 | -UNIV_INLINE |
1680 | -void |
1681 | -pfs_rw_lock_x_unlock_func( |
1682 | -/*======================*/ |
1683 | -#ifdef UNIV_SYNC_DEBUG |
1684 | - ulint pass, /*!< in: pass value; != 0, if the |
1685 | - lock may have been passed to another |
1686 | - thread to unlock */ |
1687 | -#endif |
1688 | - rw_lock_t* lock); /*!< in/out: rw-lock */ |
1689 | + |
1690 | +/******************************************************************//** |
1691 | +Performance schema instrumented wrap function for rw_lock_s_lock_func() |
1692 | +NOTE! Please use the corresponding macro rw_lock_s_lock(), not directly |
1693 | +this function! */ |
1694 | +UNIV_INLINE |
1695 | +void |
1696 | +pfs_rw_lock_s_lock_func( |
1697 | +/*====================*/ |
1698 | + rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
1699 | + ulint pass, /*!< in: pass value; != 0, if the lock will |
1700 | + be passed to another thread to unlock */ |
1701 | + const char* file_name,/*!< in: file name where lock requested */ |
1702 | + ulint line); /*!< in: line where requested */ |
1703 | + |
1704 | +/******************************************************************//** |
1705 | +Performance schema instrumented wrap function for rw_lock_s_lock_func() |
1706 | +NOTE! Please use the corresponding macro rw_lock_s_lock(), not directly |
1707 | +this function! */ |
1708 | +UNIV_INLINE |
1709 | +void |
1710 | +pfs_rw_lock_s_lock_func( |
1711 | +/*====================*/ |
1712 | + prio_rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
1713 | + ulint pass, /*!< in: pass value; != 0, if the lock will |
1714 | + be passed to another thread to unlock */ |
1715 | + const char* file_name,/*!< in: file name where lock requested */ |
1716 | + ulint line); /*!< in: line where requested */ |
1717 | + |
1718 | +/******************************************************************//** |
1719 | +Performance schema instrumented wrap function for rw_lock_s_lock_func() |
1720 | +NOTE! Please use the corresponding macro rw_lock_s_lock(), not directly |
1721 | +this function! |
1722 | +@return TRUE if success */ |
1723 | +UNIV_INLINE |
1724 | +ibool |
1725 | +pfs_rw_lock_s_lock_low( |
1726 | +/*===================*/ |
1727 | + rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
1728 | + ulint pass, /*!< in: pass value; != 0, if the |
1729 | + lock will be passed to another |
1730 | + thread to unlock */ |
1731 | + const char* file_name, /*!< in: file name where lock requested */ |
1732 | + ulint line); /*!< in: line where requested */ |
1733 | +/******************************************************************//** |
1734 | +Performance schema instrumented wrap function for rw_lock_s_lock_func() |
1735 | +NOTE! Please use the corresponding macro rw_lock_s_lock(), not directly |
1736 | +this function! |
1737 | +@return TRUE if success */ |
1738 | +UNIV_INLINE |
1739 | +ibool |
1740 | +pfs_rw_lock_s_lock_low( |
1741 | +/*===================*/ |
1742 | + prio_rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
1743 | + ulint pass, /*!< in: pass value; != 0, if the |
1744 | + lock will be passed to another |
1745 | + thread to unlock */ |
1746 | + const char* file_name, /*!< in: file name where lock requested */ |
1747 | + ulint line); /*!< in: line where requested */ |
1748 | +/******************************************************************//** |
1749 | +Performance schema instrumented wrap function for rw_lock_x_lock_func() |
1750 | +NOTE! Please use the corresponding macro rw_lock_x_lock(), not directly |
1751 | +this function! */ |
1752 | +UNIV_INLINE |
1753 | +void |
1754 | +pfs_rw_lock_x_lock_func( |
1755 | +/*====================*/ |
1756 | + rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
1757 | + ulint pass, /*!< in: pass value; != 0, if the lock will |
1758 | + be passed to another thread to unlock */ |
1759 | + const char* file_name,/*!< in: file name where lock requested */ |
1760 | + ulint line); /*!< in: line where requested */ |
1761 | +/******************************************************************//** |
1762 | +Performance schema instrumented wrap function for rw_lock_x_lock_func() |
1763 | +NOTE! Please use the corresponding macro rw_lock_x_lock(), not directly |
1764 | +this function! */ |
1765 | +UNIV_INLINE |
1766 | +void |
1767 | +pfs_rw_lock_x_lock_func( |
1768 | +/*====================*/ |
1769 | + prio_rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
1770 | + ulint pass, /*!< in: pass value; != 0, if the lock will |
1771 | + be passed to another thread to unlock */ |
1772 | + const char* file_name,/*!< in: file name where lock requested */ |
1773 | + ulint line); /*!< in: line where requested */ |
1774 | +/******************************************************************//** |
1775 | +Performance schema instrumented wrap function for rw_lock_s_unlock_func() |
1776 | +NOTE! Please use the corresponding macro rw_lock_s_unlock(), not directly |
1777 | +this function! */ |
1778 | +UNIV_INLINE |
1779 | +void |
1780 | +pfs_rw_lock_s_unlock_func( |
1781 | +/*======================*/ |
1782 | +#ifdef UNIV_SYNC_DEBUG |
1783 | + ulint pass, /*!< in: pass value; != 0, if the |
1784 | + lock may have been passed to another |
1785 | + thread to unlock */ |
1786 | +#endif |
1787 | + rw_lock_t* lock); /*!< in/out: rw-lock */ |
1788 | +/******************************************************************//** |
1789 | +Performance schema instrumented wrap function for rw_lock_s_unlock_func() |
1790 | +NOTE! Please use the corresponding macro rw_lock_s_unlock(), not directly |
1791 | +this function! */ |
1792 | +UNIV_INLINE |
1793 | +void |
1794 | +pfs_rw_lock_s_unlock_func( |
1795 | +/*======================*/ |
1796 | +#ifdef UNIV_SYNC_DEBUG |
1797 | + ulint pass, /*!< in: pass value; != 0, if the |
1798 | + lock may have been passed to another |
1799 | + thread to unlock */ |
1800 | +#endif |
1801 | + prio_rw_lock_t* lock); /*!< in/out: rw-lock */ |
1802 | +/******************************************************************//** |
1803 | +Performance schema instrumented wrap function for rw_lock_s_unlock_func() |
1804 | +NOTE! Please use the corresponding macro rw_lock_x_unlock(), not directly |
1805 | +this function! */ |
1806 | +UNIV_INLINE |
1807 | +void |
1808 | +pfs_rw_lock_x_unlock_func( |
1809 | +/*======================*/ |
1810 | +#ifdef UNIV_SYNC_DEBUG |
1811 | + ulint pass, /*!< in: pass value; != 0, if the |
1812 | + lock may have been passed to another |
1813 | + thread to unlock */ |
1814 | +#endif |
1815 | + rw_lock_t* lock); /*!< in/out: rw-lock */ |
1816 | +/******************************************************************//** |
1817 | +Performance schema instrumented wrap function for rw_lock_s_unlock_func() |
1818 | +NOTE! Please use the corresponding macro rw_lock_x_unlock(), not directly |
1819 | +this function! */ |
1820 | +UNIV_INLINE |
1821 | +void |
1822 | +pfs_rw_lock_x_unlock_func( |
1823 | +/*======================*/ |
1824 | +#ifdef UNIV_SYNC_DEBUG |
1825 | + ulint pass, /*!< in: pass value; != 0, if the |
1826 | + lock may have been passed to another |
1827 | + thread to unlock */ |
1828 | +#endif |
1829 | + prio_rw_lock_t* lock); /*!< in/out: rw-lock */ |
1830 | /******************************************************************//** |
1831 | Performance schema instrumented wrap function for rw_lock_free_func() |
1832 | NOTE! Please use the corresponding macro rw_lock_free(), not directly |
1833 | @@ -797,6 +1068,15 @@ |
1834 | pfs_rw_lock_free_func( |
1835 | /*==================*/ |
1836 | rw_lock_t* lock); /*!< in: rw-lock */ |
1837 | +/******************************************************************//** |
1838 | +Performance schema instrumented wrap function for rw_lock_free_func() |
1839 | +NOTE! Please use the corresponding macro rw_lock_free(), not directly |
1840 | +this function! */ |
1841 | +UNIV_INLINE |
1842 | +void |
1843 | +pfs_rw_lock_free_func( |
1844 | +/*==================*/ |
1845 | + prio_rw_lock_t* lock); /*!< in: rw-lock */ |
1846 | #endif /* UNIV_PFS_RWLOCK */ |
1847 | |
1848 | |
1849 | |
1850 | === modified file 'Percona-Server/storage/innobase/include/sync0rw.ic' |
1851 | --- Percona-Server/storage/innobase/include/sync0rw.ic 2013-08-06 15:16:34 +0000 |
1852 | +++ Percona-Server/storage/innobase/include/sync0rw.ic 2013-09-26 14:59:13 +0000 |
1853 | @@ -31,17 +31,22 @@ |
1854 | *******************************************************/ |
1855 | |
1856 | /******************************************************************//** |
1857 | -Lock an rw-lock in shared mode for the current thread. If the rw-lock is |
1858 | -locked in exclusive mode, or there is an exclusive lock request waiting, |
1859 | -the function spins a preset time (controlled by SYNC_SPIN_ROUNDS), |
1860 | +Lock a regular or priority rw-lock in shared mode for the current thread. If |
1861 | +the rw-lock is locked in exclusive mode, or there is an exclusive lock request |
1862 | +waiting, the function spins a preset time (controlled by SYNC_SPIN_ROUNDS), |
1863 | waiting for the lock before suspending the thread. */ |
1864 | UNIV_INTERN |
1865 | void |
1866 | rw_lock_s_lock_spin( |
1867 | /*================*/ |
1868 | - rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
1869 | + void* _lock, /*!< in: pointer to rw-lock */ |
1870 | ulint pass, /*!< in: pass value; != 0, if the lock will |
1871 | be passed to another thread to unlock */ |
1872 | + bool priority_lock, |
1873 | + /*!< in: whether the lock is a priority lock */ |
1874 | + bool high_priority, |
1875 | + /*!< in: whether we are acquiring a priority |
1876 | + lock with high priority */ |
1877 | const char* file_name,/*!< in: file name where lock requested */ |
1878 | ulint line); /*!< in: line where requested */ |
1879 | #ifdef UNIV_SYNC_DEBUG |
1880 | @@ -80,6 +85,20 @@ |
1881 | } |
1882 | |
1883 | /********************************************************************//** |
1884 | +Check if there are threads waiting for the priority rw-lock. |
1885 | +@return 1 if waiters, 0 otherwise */ |
1886 | +UNIV_INLINE |
1887 | +ulint |
1888 | +rw_lock_get_waiters( |
1889 | +/*================*/ |
1890 | + const prio_rw_lock_t* lock) /*!< in: rw-lock */ |
1891 | +{ |
1892 | + return rw_lock_get_waiters(&lock->base_lock) |
1893 | + | lock->high_priority_s_waiters |
1894 | + | lock->high_priority_x_waiters; |
1895 | +} |
1896 | + |
1897 | +/********************************************************************//** |
1898 | Sets lock->waiters to 1. It is not an error if lock->waiters is already |
1899 | 1. On platforms where ATOMIC builtins are used this function enforces a |
1900 | memory barrier. */ |
1901 | @@ -137,6 +156,19 @@ |
1902 | } |
1903 | |
1904 | /******************************************************************//** |
1905 | +Returns the write-status of the priority lock - this function made more sense |
1906 | +with the old rw_lock implementation. |
1907 | +@return RW_LOCK_NOT_LOCKED, RW_LOCK_EX, RW_LOCK_WAIT_EX */ |
1908 | +UNIV_INLINE |
1909 | +ulint |
1910 | +rw_lock_get_writer( |
1911 | +/*===============*/ |
1912 | + const prio_rw_lock_t* lock) /*!< in: rw-lock */ |
1913 | +{ |
1914 | + return(rw_lock_get_writer(&lock->base_lock)); |
1915 | +} |
1916 | + |
1917 | +/******************************************************************//** |
1918 | Returns the number of readers. |
1919 | @return number of readers */ |
1920 | UNIV_INLINE |
1921 | @@ -156,6 +188,18 @@ |
1922 | return(0); |
1923 | } |
1924 | |
1925 | +/******************************************************************//** |
1926 | +Returns the number of readers. |
1927 | +@return number of readers */ |
1928 | +UNIV_INLINE |
1929 | +ulint |
1930 | +rw_lock_get_reader_count( |
1931 | +/*=====================*/ |
1932 | + const prio_rw_lock_t* lock) /*!< in: rw-lock */ |
1933 | +{ |
1934 | + return(rw_lock_get_reader_count(&lock->base_lock)); |
1935 | +} |
1936 | + |
1937 | #ifndef INNODB_RW_LOCKS_USE_ATOMICS |
1938 | UNIV_INLINE |
1939 | ib_mutex_t* |
1940 | @@ -185,6 +229,19 @@ |
1941 | } |
1942 | |
1943 | /******************************************************************//** |
1944 | +Returns the value of writer_count for the priority lock. Does not reserve the |
1945 | +lock mutex, so the caller must be sure it is not changed during the call. |
1946 | +@return value of writer_count */ |
1947 | +UNIV_INLINE |
1948 | +ulint |
1949 | +rw_lock_get_x_lock_count( |
1950 | +/*=====================*/ |
1951 | + const prio_rw_lock_t* lock) /*!< in: rw-lock */ |
1952 | +{ |
1953 | + return(rw_lock_get_x_lock_count(&lock->base_lock)); |
1954 | +} |
1955 | + |
1956 | +/******************************************************************//** |
1957 | Two different implementations for decrementing the lock_word of a rw_lock: |
1958 | one for systems supporting atomic operations, one for others. This does |
1959 | does not support recusive x-locks: they should be handled by the caller and |
1960 | @@ -361,7 +418,75 @@ |
1961 | } else { |
1962 | /* Did not succeed, try spin wait */ |
1963 | |
1964 | - rw_lock_s_lock_spin(lock, pass, file_name, line); |
1965 | + rw_lock_s_lock_spin(lock, pass, false, false, file_name, line); |
1966 | + |
1967 | + return; |
1968 | + } |
1969 | +} |
1970 | + |
1971 | +/******************************************************************//** |
1972 | +Return true if waiters of higher priority than the current thread |
1973 | +exist. |
1974 | +@true if waiterss of higher priority exist */ |
1975 | +UNIV_INLINE |
1976 | +bool |
1977 | +rw_lock_higher_prio_waiters_exist( |
1978 | +/*==============================*/ |
1979 | + bool priority_lock, /*!< in: whether the lock is a priority lock */ |
1980 | + bool high_priority, /*!< in: whether we are acquiring a priority |
1981 | + lock with high priority */ |
1982 | + void* lock) /*!< in: rw lock */ |
1983 | +{ |
1984 | + if (high_priority || !priority_lock) { |
1985 | + ut_ad(!(!priority_lock && high_priority)); |
1986 | + return(false); |
1987 | + } |
1988 | + |
1989 | + ut_ad(priority_lock && !high_priority); |
1990 | + |
1991 | + prio_rw_lock_t *prio_rw_lock = (prio_rw_lock_t *) lock; |
1992 | + return prio_rw_lock->high_priority_wait_ex_waiter > 0 |
1993 | + || prio_rw_lock->high_priority_s_waiters > 0 |
1994 | + || prio_rw_lock->high_priority_x_waiters > 0; |
1995 | +} |
1996 | + |
1997 | +/******************************************************************//** |
1998 | +NOTE! Use the corresponding macro, not directly this function, except if |
1999 | +you supply the file name and line number. Lock a priority rw-lock in shared |
2000 | +mode for the current thread, using the relative thread priority. If the |
2001 | +rw-lock is locked in exclusive mode, or there is an exclusive lock request |
2002 | +waiting, the function spins a preset time (controlled by SYNC_SPIN_ROUNDS), |
2003 | +waiting for the lock, before suspending the thread. */ |
2004 | +UNIV_INLINE |
2005 | +void |
2006 | +rw_lock_s_lock_func( |
2007 | +/*================*/ |
2008 | + prio_rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
2009 | + ulint pass, /*!< in: pass value; != 0, if the lock will |
2010 | + be passed to another thread to unlock */ |
2011 | + const char* file_name,/*!< in: file name where lock requested */ |
2012 | + ulint line) /*!< in: line where requested */ |
2013 | +{ |
2014 | +#ifdef UNIV_SYNC_DEBUG |
2015 | + ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); /* see NOTE above */ |
2016 | + ut_ad(!rw_lock_own(lock, RW_LOCK_EX)); |
2017 | +#endif /* UNIV_SYNC_DEBUG */ |
2018 | + |
2019 | + bool high_priority = srv_current_thread_priority > 0; |
2020 | + |
2021 | + /* Do not attempt to acquire a low-priority S latch if there are |
2022 | + high-priority waiters even if such attempt would be successful. This |
2023 | + is to prevent a high priority X request from being starved by a |
2024 | + sequence of overlapping regular priority S requests. */ |
2025 | + |
2026 | + if (!rw_lock_higher_prio_waiters_exist(true, high_priority, lock) |
2027 | + && rw_lock_s_lock_low(&lock->base_lock, pass, file_name, line)) { |
2028 | + |
2029 | + return; /* Success */ |
2030 | + } else { |
2031 | + /* Did not succeed, try spin wait */ |
2032 | + rw_lock_s_lock_spin(lock, pass, true, high_priority, file_name, |
2033 | + line); |
2034 | |
2035 | return; |
2036 | } |
2037 | @@ -380,8 +505,6 @@ |
2038 | const char* file_name,/*!< in: file name where lock requested */ |
2039 | ulint line) /*!< in: line where requested */ |
2040 | { |
2041 | - os_thread_id_t curr_thread = os_thread_get_curr_id(); |
2042 | - |
2043 | ibool success; |
2044 | |
2045 | #ifdef INNODB_RW_LOCKS_USE_ATOMICS |
2046 | @@ -401,7 +524,8 @@ |
2047 | rw_lock_set_writer_id_and_recursion_flag(lock, TRUE); |
2048 | |
2049 | } else if (lock->recursive |
2050 | - && os_thread_eq(lock->writer_thread, curr_thread)) { |
2051 | + && os_thread_eq(lock->writer_thread, |
2052 | + os_thread_get_curr_id())) { |
2053 | /* Relock: this lock_word modification is safe since no other |
2054 | threads can modify (lock, unlock, or reserve) lock_word while |
2055 | there is an exclusive writer and this is the writer thread. */ |
2056 | @@ -469,13 +593,75 @@ |
2057 | } |
2058 | |
2059 | /******************************************************************//** |
2060 | -Releases an exclusive mode lock. */ |
2061 | +Releases a shared mode priority lock. */ |
2062 | UNIV_INLINE |
2063 | void |
2064 | -rw_lock_x_unlock_func( |
2065 | +rw_lock_s_unlock_func( |
2066 | /*==================*/ |
2067 | #ifdef UNIV_SYNC_DEBUG |
2068 | ulint pass, /*!< in: pass value; != 0, if the lock may have |
2069 | + been passed to another thread to unlock */ |
2070 | +#endif |
2071 | + prio_rw_lock_t* lock) /*!< in/out: rw-lock */ |
2072 | +{ |
2073 | + ut_ad(lock->base_lock.lock_word > -X_LOCK_DECR); |
2074 | + ut_ad(lock->base_lock.lock_word != 0); |
2075 | + ut_ad(lock->base_lock.lock_word < X_LOCK_DECR); |
2076 | + |
2077 | +#ifdef UNIV_SYNC_DEBUG |
2078 | + rw_lock_remove_debug_info(&lock->base_lock, pass, RW_LOCK_SHARED); |
2079 | +#endif |
2080 | + |
2081 | + /* Increment lock_word to indicate 1 less reader */ |
2082 | + if (rw_lock_lock_word_incr(&lock->base_lock, 1) == 0) { |
2083 | + |
2084 | + /* A waiting next-writer exists, either high priority or |
2085 | + regular. Wake up the first waiter in this order: 1) high |
2086 | + priority next-writer; 2) high priority X waiters; 3) high |
2087 | + priority S waiters; 4) regular priority next-waiter. This |
2088 | + allows high priority requests to overtake an already-waiting |
2089 | + regular priority next-waiter. */ |
2090 | + if (lock->high_priority_wait_ex_waiter) { |
2091 | + |
2092 | + lock->high_priority_wait_ex_waiter = 0; |
2093 | + /* Note that we do not have a separate high priority |
2094 | + next-waiter event. There can be only one such waiter, |
2095 | + here we already know it's high priority, no |
2096 | + regular-priority wakeup may happen. */ |
2097 | + os_event_set(lock->base_lock.wait_ex_event); |
2098 | + } else if (lock->high_priority_x_waiters) { |
2099 | + |
2100 | + lock->high_priority_x_waiters = 0; |
2101 | + os_event_set(lock->high_priority_x_event); |
2102 | + } else if (lock->high_priority_s_waiters) { |
2103 | + |
2104 | + lock->high_priority_s_waiters = 0; |
2105 | + os_event_set(lock->high_priority_s_event); |
2106 | + } else { |
2107 | + |
2108 | + os_event_set(lock->base_lock.wait_ex_event); |
2109 | + } |
2110 | + sync_array_object_signalled(); |
2111 | + } |
2112 | + |
2113 | + ut_ad(rw_lock_validate(lock)); |
2114 | + |
2115 | +#ifdef UNIV_SYNC_PERF_STAT |
2116 | + rw_s_exit_count++; |
2117 | +#endif |
2118 | +} |
2119 | + |
2120 | +/******************************************************************//** |
2121 | +Prepares an exclusive mode lock release: resets the recursion flag and removes |
2122 | +the debug information if needed and returns the required lock word increment |
2123 | +value. |
2124 | +@return lock word increment value to perform the unlock */ |
2125 | +UNIV_INLINE |
2126 | +ulint |
2127 | +rw_lock_x_prepare_unlock( |
2128 | +/*=====================*/ |
2129 | +#ifdef UNIV_SYNC_DEBUG |
2130 | + ulint pass, /*!< in: pass value; != 0, if the lock may have |
2131 | been passed to another thread to unlock */ |
2132 | #endif |
2133 | rw_lock_t* lock) /*!< in/out: rw-lock */ |
2134 | @@ -507,10 +693,32 @@ |
2135 | x_lock_incr = 1; |
2136 | } |
2137 | |
2138 | + return(x_lock_incr); |
2139 | +} |
2140 | + |
2141 | +/******************************************************************//** |
2142 | +Releases an exclusive mode lock. */ |
2143 | +UNIV_INLINE |
2144 | +void |
2145 | +rw_lock_x_unlock_func( |
2146 | +/*==================*/ |
2147 | +#ifdef UNIV_SYNC_DEBUG |
2148 | + ulint pass, /*!< in: pass value; != 0, if the lock may have |
2149 | + been passed to another thread to unlock */ |
2150 | +#endif |
2151 | + rw_lock_t* lock) /*!< in/out: rw-lock */ |
2152 | +{ |
2153 | + ulint x_lock_incr = rw_lock_x_prepare_unlock( |
2154 | +#ifdef UNIV_SYNC_DEBUG |
2155 | + pass, |
2156 | +#endif |
2157 | + lock); |
2158 | + |
2159 | if (rw_lock_lock_word_incr(lock, x_lock_incr) == X_LOCK_DECR) { |
2160 | /* Lock is now free. May have to signal read/write waiters. |
2161 | We do not need to signal wait_ex waiters, since they cannot |
2162 | exist when there is a writer. */ |
2163 | + |
2164 | if (lock->waiters) { |
2165 | rw_lock_reset_waiter_flag(lock); |
2166 | os_event_set(lock->event); |
2167 | @@ -525,6 +733,58 @@ |
2168 | #endif |
2169 | } |
2170 | |
2171 | +/******************************************************************//** |
2172 | +Releases an exclusive mode priority lock. */ |
2173 | +UNIV_INLINE |
2174 | +void |
2175 | +rw_lock_x_unlock_func( |
2176 | +/*==================*/ |
2177 | +#ifdef UNIV_SYNC_DEBUG |
2178 | + ulint pass, /*!< in: pass value; != 0, if the lock may have |
2179 | + been passed to another thread to unlock */ |
2180 | +#endif |
2181 | + prio_rw_lock_t* lock) /*!< in/out: rw-lock */ |
2182 | +{ |
2183 | + ulint x_lock_incr = rw_lock_x_prepare_unlock( |
2184 | +#ifdef UNIV_SYNC_DEBUG |
2185 | + pass, |
2186 | +#endif |
2187 | + &lock->base_lock); |
2188 | + |
2189 | + if (rw_lock_lock_word_incr(&lock->base_lock, x_lock_incr) |
2190 | + == X_LOCK_DECR) { |
2191 | + |
2192 | + /* Priority lock is now free. Signal any waiters in this |
2193 | + order: 1) high priority X waiters; 2) high priority S waiters; |
2194 | + 3) regular priority waiters. |
2195 | + We do not need to signal wait_ex waiters, since they cannot |
2196 | + exist when there is a writer. */ |
2197 | + |
2198 | + if (lock->high_priority_x_waiters) { |
2199 | + |
2200 | + lock->high_priority_x_waiters = 0; |
2201 | + os_event_set(lock->high_priority_x_event); |
2202 | + sync_array_object_signalled(); |
2203 | + } else if (lock->high_priority_s_waiters) { |
2204 | + |
2205 | + lock->high_priority_s_waiters = 0; |
2206 | + os_event_set(lock->high_priority_s_event); |
2207 | + sync_array_object_signalled(); |
2208 | + } else if (lock->base_lock.waiters) { |
2209 | + |
2210 | + rw_lock_reset_waiter_flag(&lock->base_lock); |
2211 | + os_event_set(lock->base_lock.event); |
2212 | + sync_array_object_signalled(); |
2213 | + } |
2214 | + } |
2215 | + |
2216 | + ut_ad(rw_lock_validate(lock)); |
2217 | + |
2218 | +#ifdef UNIV_SYNC_PERF_STAT |
2219 | + rw_x_exit_count++; |
2220 | +#endif |
2221 | +} |
2222 | + |
2223 | #ifdef UNIV_PFS_RWLOCK |
2224 | |
2225 | /******************************************************************//** |
2226 | @@ -561,6 +821,42 @@ |
2227 | # endif /* UNIV_DEBUG */ |
2228 | cmutex_name); |
2229 | } |
2230 | + |
2231 | +/******************************************************************//** |
2232 | +Performance schema instrumented wrap function for rw_lock_create_func(). |
2233 | +NOTE! Please use the corresponding macro rw_lock_create(), not directly |
2234 | +this function! */ |
2235 | +UNIV_INLINE |
2236 | +void |
2237 | +pfs_rw_lock_create_func( |
2238 | +/*====================*/ |
2239 | + mysql_pfs_key_t key, /*!< in: key registered with |
2240 | + performance schema */ |
2241 | + prio_rw_lock_t* lock, /*!< in: pointer to memory */ |
2242 | +# ifdef UNIV_DEBUG |
2243 | +# ifdef UNIV_SYNC_DEBUG |
2244 | + ulint level, /*!< in: level */ |
2245 | +# endif /* UNIV_SYNC_DEBUG */ |
2246 | + const char* cfile_name, /*!< in: file name where created */ |
2247 | + ulint cline, /*!< in: file line where created */ |
2248 | +# endif /* UNIV_DEBUG */ |
2249 | + const char* cmutex_name) /*!< in: mutex name */ |
2250 | +{ |
2251 | + /* Initialize the rwlock for performance schema */ |
2252 | + lock->base_lock.pfs_psi = PSI_RWLOCK_CALL(init_rwlock)(key, lock); |
2253 | + |
2254 | + /* The actual function to initialize an rwlock */ |
2255 | + rw_lock_create_func(lock, |
2256 | +# ifdef UNIV_DEBUG |
2257 | +# ifdef UNIV_SYNC_DEBUG |
2258 | + level, |
2259 | +# endif /* UNIV_SYNC_DEBUG */ |
2260 | + cfile_name, |
2261 | + cline, |
2262 | +# endif /* UNIV_DEBUG */ |
2263 | + cmutex_name); |
2264 | +} |
2265 | + |
2266 | /******************************************************************//** |
2267 | Performance schema instrumented wrap function for rw_lock_x_lock_func() |
2268 | NOTE! Please use the corresponding macro rw_lock_x_lock(), not directly |
2269 | @@ -594,6 +890,42 @@ |
2270 | rw_lock_x_lock_func(lock, pass, file_name, line); |
2271 | } |
2272 | } |
2273 | + |
2274 | +/******************************************************************//** |
2275 | +Performance schema instrumented wrap function for rw_lock_x_lock_func() |
2276 | +NOTE! Please use the corresponding macro rw_lock_x_lock(), not directly |
2277 | +this function! */ |
2278 | +UNIV_INLINE |
2279 | +void |
2280 | +pfs_rw_lock_x_lock_func( |
2281 | +/*====================*/ |
2282 | + prio_rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
2283 | + ulint pass, /*!< in: pass value; != 0, if the lock will |
2284 | + be passed to another thread to unlock */ |
2285 | + const char* file_name,/*!< in: file name where lock requested */ |
2286 | + ulint line) /*!< in: line where requested */ |
2287 | +{ |
2288 | + if (lock->base_lock.pfs_psi != NULL) |
2289 | + { |
2290 | + PSI_rwlock_locker* locker; |
2291 | + PSI_rwlock_locker_state state; |
2292 | + |
2293 | + /* Record the entry of rw x lock request in performance schema */ |
2294 | + locker = PSI_RWLOCK_CALL(start_rwlock_wrwait)( |
2295 | + &state, lock->base_lock.pfs_psi, PSI_RWLOCK_WRITELOCK, |
2296 | + file_name, line); |
2297 | + |
2298 | + rw_lock_x_lock_func(lock, pass, file_name, line); |
2299 | + |
2300 | + if (locker != NULL) |
2301 | + PSI_RWLOCK_CALL(end_rwlock_wrwait)(locker, 0); |
2302 | + } |
2303 | + else |
2304 | + { |
2305 | + rw_lock_x_lock_func(lock, pass, file_name, line); |
2306 | + } |
2307 | +} |
2308 | + |
2309 | /******************************************************************//** |
2310 | Performance schema instrumented wrap function for |
2311 | rw_lock_x_lock_func_nowait() |
2312 | @@ -650,6 +982,26 @@ |
2313 | |
2314 | rw_lock_free_func(lock); |
2315 | } |
2316 | + |
2317 | +/******************************************************************//** |
2318 | +Performance schema instrumented wrap function for rw_lock_free_func() |
2319 | +NOTE! Please use the corresponding macro rw_lock_free(), not directly |
2320 | +this function! */ |
2321 | +UNIV_INLINE |
2322 | +void |
2323 | +pfs_rw_lock_free_func( |
2324 | +/*==================*/ |
2325 | + prio_rw_lock_t* lock) /*!< in: pointer to rw-lock */ |
2326 | +{ |
2327 | + if (lock->base_lock.pfs_psi != NULL) |
2328 | + { |
2329 | + PSI_RWLOCK_CALL(destroy_rwlock)(lock->base_lock.pfs_psi); |
2330 | + lock->base_lock.pfs_psi = NULL; |
2331 | + } |
2332 | + |
2333 | + rw_lock_free_func(lock); |
2334 | +} |
2335 | + |
2336 | /******************************************************************//** |
2337 | Performance schema instrumented wrap function for rw_lock_s_lock_func() |
2338 | NOTE! Please use the corresponding macro rw_lock_s_lock(), not |
2339 | @@ -687,6 +1039,46 @@ |
2340 | |
2341 | return; |
2342 | } |
2343 | + |
2344 | +/******************************************************************//** |
2345 | +Performance schema instrumented wrap function for rw_lock_s_lock_func() |
2346 | +NOTE! Please use the corresponding macro rw_lock_s_lock(), not |
2347 | +directly this function! */ |
2348 | +UNIV_INLINE |
2349 | +void |
2350 | +pfs_rw_lock_s_lock_func( |
2351 | +/*====================*/ |
2352 | + prio_rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
2353 | + ulint pass, /*!< in: pass value; != 0, if the |
2354 | + lock will be passed to another |
2355 | + thread to unlock */ |
2356 | + const char* file_name,/*!< in: file name where lock |
2357 | + requested */ |
2358 | + ulint line) /*!< in: line where requested */ |
2359 | +{ |
2360 | + if (lock->base_lock.pfs_psi != NULL) |
2361 | + { |
2362 | + PSI_rwlock_locker* locker; |
2363 | + PSI_rwlock_locker_state state; |
2364 | + |
2365 | + /* Instrumented to inform we are aquiring a shared rwlock */ |
2366 | + locker = PSI_RWLOCK_CALL(start_rwlock_rdwait)( |
2367 | + &state, lock->base_lock.pfs_psi, PSI_RWLOCK_READLOCK, |
2368 | + file_name, line); |
2369 | + |
2370 | + rw_lock_s_lock_func(lock, pass, file_name, line); |
2371 | + |
2372 | + if (locker != NULL) |
2373 | + PSI_RWLOCK_CALL(end_rwlock_rdwait)(locker, 0); |
2374 | + } |
2375 | + else |
2376 | + { |
2377 | + rw_lock_s_lock_func(lock, pass, file_name, line); |
2378 | + } |
2379 | + |
2380 | + return; |
2381 | +} |
2382 | + |
2383 | /******************************************************************//** |
2384 | Performance schema instrumented wrap function for rw_lock_s_lock_func() |
2385 | NOTE! Please use the corresponding macro rw_lock_s_lock(), not |
2386 | @@ -728,55 +1120,129 @@ |
2387 | } |
2388 | |
2389 | /******************************************************************//** |
2390 | -Performance schema instrumented wrap function for rw_lock_x_unlock_func() |
2391 | -NOTE! Please use the corresponding macro rw_lock_x_unlock(), not directly |
2392 | -this function! */ |
2393 | -UNIV_INLINE |
2394 | -void |
2395 | -pfs_rw_lock_x_unlock_func( |
2396 | -/*======================*/ |
2397 | -#ifdef UNIV_SYNC_DEBUG |
2398 | - ulint pass, /*!< in: pass value; != 0, if the |
2399 | - lock may have been passed to another |
2400 | - thread to unlock */ |
2401 | -#endif |
2402 | - rw_lock_t* lock) /*!< in/out: rw-lock */ |
2403 | -{ |
2404 | - /* Inform performance schema we are unlocking the lock */ |
2405 | - if (lock->pfs_psi != NULL) |
2406 | - PSI_RWLOCK_CALL(unlock_rwlock)(lock->pfs_psi); |
2407 | - |
2408 | - rw_lock_x_unlock_func( |
2409 | -#ifdef UNIV_SYNC_DEBUG |
2410 | - pass, |
2411 | -#endif |
2412 | - lock); |
2413 | -} |
2414 | - |
2415 | -/******************************************************************//** |
2416 | -Performance schema instrumented wrap function for rw_lock_s_unlock_func() |
2417 | -NOTE! Please use the corresponding macro pfs_rw_lock_s_unlock(), not |
2418 | -directly this function! */ |
2419 | -UNIV_INLINE |
2420 | -void |
2421 | -pfs_rw_lock_s_unlock_func( |
2422 | -/*======================*/ |
2423 | -#ifdef UNIV_SYNC_DEBUG |
2424 | - ulint pass, /*!< in: pass value; != 0, if the |
2425 | - lock may have been passed to another |
2426 | - thread to unlock */ |
2427 | -#endif |
2428 | - rw_lock_t* lock) /*!< in/out: rw-lock */ |
2429 | -{ |
2430 | - /* Inform performance schema we are unlocking the lock */ |
2431 | - if (lock->pfs_psi != NULL) |
2432 | - PSI_RWLOCK_CALL(unlock_rwlock)(lock->pfs_psi); |
2433 | - |
2434 | - rw_lock_s_unlock_func( |
2435 | -#ifdef UNIV_SYNC_DEBUG |
2436 | - pass, |
2437 | -#endif |
2438 | - lock); |
2439 | - |
2440 | -} |
2441 | +Performance schema instrumented wrap function for rw_lock_s_lock_func() |
2442 | +NOTE! Please use the corresponding macro rw_lock_s_lock(), not |
2443 | +directly this function! |
2444 | +@return TRUE if success */ |
2445 | +UNIV_INLINE |
2446 | +ibool |
2447 | +pfs_rw_lock_s_lock_low( |
2448 | +/*===================*/ |
2449 | + prio_rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
2450 | + ulint pass, /*!< in: pass value; != 0, if the |
2451 | + lock will be passed to another |
2452 | + thread to unlock */ |
2453 | + const char* file_name, /*!< in: file name where lock requested */ |
2454 | + ulint line) /*!< in: line where requested */ |
2455 | +{ |
2456 | + return(pfs_rw_lock_s_lock_low(&lock->base_lock, pass, |
2457 | + file_name, line)); |
2458 | +} |
2459 | + |
2460 | +/******************************************************************//** |
2461 | +Performance schema instrumented wrap function for rw_lock_x_unlock_func() |
2462 | +NOTE! Please use the corresponding macro rw_lock_x_unlock(), not directly |
2463 | +this function! */ |
2464 | +UNIV_INLINE |
2465 | +void |
2466 | +pfs_rw_lock_x_unlock_func( |
2467 | +/*======================*/ |
2468 | +#ifdef UNIV_SYNC_DEBUG |
2469 | + ulint pass, /*!< in: pass value; != 0, if the |
2470 | + lock may have been passed to another |
2471 | + thread to unlock */ |
2472 | +#endif |
2473 | + rw_lock_t* lock) /*!< in/out: rw-lock */ |
2474 | +{ |
2475 | + /* Inform performance schema we are unlocking the lock */ |
2476 | + if (lock->pfs_psi != NULL) |
2477 | + PSI_RWLOCK_CALL(unlock_rwlock)(lock->pfs_psi); |
2478 | + |
2479 | + rw_lock_x_unlock_func( |
2480 | +#ifdef UNIV_SYNC_DEBUG |
2481 | + pass, |
2482 | +#endif |
2483 | + lock); |
2484 | +} |
2485 | + |
2486 | +/******************************************************************//** |
2487 | +Performance schema instrumented wrap function for rw_lock_x_unlock_func() |
2488 | +NOTE! Please use the corresponding macro rw_lock_x_unlock(), not directly |
2489 | +this function! */ |
2490 | +UNIV_INLINE |
2491 | +void |
2492 | +pfs_rw_lock_x_unlock_func( |
2493 | +/*======================*/ |
2494 | +#ifdef UNIV_SYNC_DEBUG |
2495 | + ulint pass, /*!< in: pass value; != 0, if the |
2496 | + lock may have been passed to another |
2497 | + thread to unlock */ |
2498 | +#endif |
2499 | + prio_rw_lock_t* lock) /*!< in/out: rw-lock */ |
2500 | +{ |
2501 | + /* Inform performance schema we are unlocking the lock */ |
2502 | + if (lock->base_lock.pfs_psi != NULL) |
2503 | + PSI_RWLOCK_CALL(unlock_rwlock)(lock->base_lock.pfs_psi); |
2504 | + |
2505 | + rw_lock_x_unlock_func( |
2506 | +#ifdef UNIV_SYNC_DEBUG |
2507 | + pass, |
2508 | +#endif |
2509 | + lock); |
2510 | +} |
2511 | + |
2512 | +/******************************************************************//** |
2513 | +Performance schema instrumented wrap function for rw_lock_s_unlock_func() |
2514 | +NOTE! Please use the corresponding macro pfs_rw_lock_s_unlock(), not |
2515 | +directly this function! */ |
2516 | +UNIV_INLINE |
2517 | +void |
2518 | +pfs_rw_lock_s_unlock_func( |
2519 | +/*======================*/ |
2520 | +#ifdef UNIV_SYNC_DEBUG |
2521 | + ulint pass, /*!< in: pass value; != 0, if the |
2522 | + lock may have been passed to another |
2523 | + thread to unlock */ |
2524 | +#endif |
2525 | + rw_lock_t* lock) /*!< in/out: rw-lock */ |
2526 | +{ |
2527 | + /* Inform performance schema we are unlocking the lock */ |
2528 | + if (lock->pfs_psi != NULL) |
2529 | + PSI_RWLOCK_CALL(unlock_rwlock)(lock->pfs_psi); |
2530 | + |
2531 | + rw_lock_s_unlock_func( |
2532 | +#ifdef UNIV_SYNC_DEBUG |
2533 | + pass, |
2534 | +#endif |
2535 | + lock); |
2536 | + |
2537 | +} |
2538 | + |
2539 | +/******************************************************************//** |
2540 | +Performance schema instrumented wrap function for rw_lock_s_unlock_func() |
2541 | +NOTE! Please use the corresponding macro pfs_rw_lock_s_unlock(), not |
2542 | +directly this function! */ |
2543 | +UNIV_INLINE |
2544 | +void |
2545 | +pfs_rw_lock_s_unlock_func( |
2546 | +/*======================*/ |
2547 | +#ifdef UNIV_SYNC_DEBUG |
2548 | + ulint pass, /*!< in: pass value; != 0, if the |
2549 | + lock may have been passed to another |
2550 | + thread to unlock */ |
2551 | +#endif |
2552 | + prio_rw_lock_t* lock) /*!< in/out: rw-lock */ |
2553 | +{ |
2554 | + /* Inform performance schema we are unlocking the lock */ |
2555 | + if (lock->base_lock.pfs_psi != NULL) |
2556 | + PSI_RWLOCK_CALL(unlock_rwlock)(lock->base_lock.pfs_psi); |
2557 | + |
2558 | + rw_lock_s_unlock_func( |
2559 | +#ifdef UNIV_SYNC_DEBUG |
2560 | + pass, |
2561 | +#endif |
2562 | + lock); |
2563 | + |
2564 | +} |
2565 | + |
2566 | #endif /* UNIV_PFS_RWLOCK */ |
2567 | |
2568 | === modified file 'Percona-Server/storage/innobase/include/sync0sync.h' |
2569 | --- Percona-Server/storage/innobase/include/sync0sync.h 2013-09-20 05:27:28 +0000 |
2570 | +++ Percona-Server/storage/innobase/include/sync0sync.h 2013-09-26 14:59:13 +0000 |
2571 | @@ -160,6 +160,8 @@ |
2572 | |
2573 | mutex_create |
2574 | mutex_enter |
2575 | +mutex_enter_first |
2576 | +mutex_enter_last |
2577 | mutex_exit |
2578 | mutex_enter_nowait |
2579 | mutex_free |
2580 | @@ -195,6 +197,12 @@ |
2581 | # define mutex_enter_nowait(M) \ |
2582 | pfs_mutex_enter_nowait_func((M), __FILE__, __LINE__) |
2583 | |
2584 | +# define mutex_enter_first(M) \ |
2585 | + pfs_mutex_enter_func((M), __FILE__, __LINE__, HIGH_PRIO) |
2586 | + |
2587 | +# define mutex_enter_last(M) \ |
2588 | + pfs_mutex_enter_func((M), __FILE__, __LINE__, LOW_PRIO) |
2589 | + |
2590 | # define mutex_exit(M) pfs_mutex_exit_func(M) |
2591 | |
2592 | # define mutex_free(M) pfs_mutex_free_func(M) |
2593 | @@ -221,6 +229,12 @@ |
2594 | # define mutex_enter_nowait(M) \ |
2595 | mutex_enter_nowait_func((M), __FILE__, __LINE__) |
2596 | |
2597 | +# define mutex_enter_first(M) \ |
2598 | + mutex_enter_func((M), __FILE__, __LINE__, HIGH_PRIO) |
2599 | + |
2600 | +# define mutex_enter_last(M) \ |
2601 | + mutex_enter_func((M), __FILE__, __LINE__, LOW_PRIO) |
2602 | + |
2603 | # define mutex_exit(M) mutex_exit_func(M) |
2604 | |
2605 | # define mutex_free(M) mutex_free_func(M) |
2606 | @@ -247,6 +261,26 @@ |
2607 | const char* cmutex_name); /*!< in: mutex name */ |
2608 | |
2609 | /******************************************************************//** |
2610 | +Creates, or rather, initializes a priority mutex object in a specified memory |
2611 | +location (which must be appropriately aligned). The mutex is initialized |
2612 | +in the reset state. Explicit freeing of the mutex with mutex_free is |
2613 | +necessary only if the memory block containing it is freed. */ |
2614 | +UNIV_INTERN |
2615 | +void |
2616 | +mutex_create_func( |
2617 | +/*==============*/ |
2618 | + ib_prio_mutex_t* mutex, /*!< in: pointer to memory */ |
2619 | +#ifdef UNIV_DEBUG |
2620 | +# ifdef UNIV_SYNC_DEBUG |
2621 | + ulint level, /*!< in: level */ |
2622 | +# endif /* UNIV_SYNC_DEBUG */ |
2623 | + const char* cfile_name, /*!< in: file name where |
2624 | + created */ |
2625 | + ulint cline, /*!< in: file line where |
2626 | + created */ |
2627 | +#endif /* UNIV_DEBUG */ |
2628 | + const char* cmutex_name); /*!< in: mutex name */ |
2629 | +/******************************************************************//** |
2630 | NOTE! Use the corresponding macro mutex_free(), not directly this function! |
2631 | Calling this function is obligatory only if the memory buffer containing |
2632 | the mutex is freed. Removes a mutex object from the mutex list. The mutex |
2633 | @@ -256,6 +290,16 @@ |
2634 | mutex_free_func( |
2635 | /*============*/ |
2636 | ib_mutex_t* mutex); /*!< in: mutex */ |
2637 | +/******************************************************************//** |
2638 | +NOTE! Use the corresponding macro mutex_free(), not directly this function! |
2639 | +Calling this function is obligatory only if the memory buffer containing |
2640 | +the mutex is freed. Removes a priority mutex object from the mutex list. The |
2641 | +mutex is checked to be in the reset state. */ |
2642 | +UNIV_INTERN |
2643 | +void |
2644 | +mutex_free_func( |
2645 | +/*============*/ |
2646 | + ib_prio_mutex_t* mutex); /*!< in: mutex */ |
2647 | /**************************************************************//** |
2648 | NOTE! The following macro should be used in mutex locking, not the |
2649 | corresponding function. */ |
2650 | @@ -275,6 +319,26 @@ |
2651 | ib_mutex_t* mutex, /*!< in: pointer to mutex */ |
2652 | const char* file_name, /*!< in: file name where locked */ |
2653 | ulint line); /*!< in: line where locked */ |
2654 | +/******************************************************************//** |
2655 | +NOTE! Use the corresponding macro in the header file, not this function |
2656 | +directly. Locks a priority mutex for the current thread. If the mutex is |
2657 | +reserved the function spins a preset time (controlled by SYNC_SPIN_ROUNDS) |
2658 | +waiting for the mutex before suspending the thread. If the thread is suspended, |
2659 | +the priority argument value determines the relative order for its wake up. Any |
2660 | +HIGH_PRIO waiters will be woken up before any LOW_PRIO waiters. In case of |
2661 | +DEFAULT_PRIO, the relative priority will be set according to |
2662 | +srv_current_thread_priority. */ |
2663 | +UNIV_INLINE |
2664 | +void |
2665 | +mutex_enter_func( |
2666 | +/*=============*/ |
2667 | + ib_prio_mutex_t* mutex, /*!< in: pointer to mutex */ |
2668 | + const char* file_name, /*!< in: file name where |
2669 | + locked */ |
2670 | + ulint line, /*!< in: line where locked */ |
2671 | + enum ib_sync_priority priority = DEFAULT_PRIO); |
2672 | + /*!<in: mutex acquisition |
2673 | + priority */ |
2674 | /********************************************************************//** |
2675 | NOTE! Use the corresponding macro in the header file, not this function |
2676 | directly. Tries to lock the mutex for the current thread. If the lock is not |
2677 | @@ -288,6 +352,20 @@ |
2678 | const char* file_name, /*!< in: file name where mutex |
2679 | requested */ |
2680 | ulint line); /*!< in: line where requested */ |
2681 | +/********************************************************************//** |
2682 | +NOTE! Use the corresponding macro in the header file, not this function |
2683 | +directly. Tries to lock the mutex for the current thread. If the lock is not |
2684 | +acquired immediately, returns with return value 1. |
2685 | +@return 0 if succeed, 1 if not */ |
2686 | +UNIV_INTERN |
2687 | +ulint |
2688 | +mutex_enter_nowait_func( |
2689 | +/*====================*/ |
2690 | + ib_prio_mutex_t* mutex, /*!< in: pointer to mutex */ |
2691 | + const char* file_name, /*!< in: file name where mutex |
2692 | + requested */ |
2693 | + ulint line); /*!< in: line where |
2694 | + requested */ |
2695 | /******************************************************************//** |
2696 | NOTE! Use the corresponding macro mutex_exit(), not directly this function! |
2697 | Unlocks a mutex owned by the current thread. */ |
2698 | @@ -296,6 +374,14 @@ |
2699 | mutex_exit_func( |
2700 | /*============*/ |
2701 | ib_mutex_t* mutex); /*!< in: pointer to mutex */ |
2702 | +/******************************************************************//** |
2703 | +NOTE! Use the corresponding macro mutex_exit(), not directly this function! |
2704 | +Unlocks a priority mutex owned by the current thread. */ |
2705 | +UNIV_INLINE |
2706 | +void |
2707 | +mutex_exit_func( |
2708 | +/*============*/ |
2709 | + ib_prio_mutex_t* mutex); /*!< in: pointer to mutex */ |
2710 | |
2711 | |
2712 | #ifdef UNIV_PFS_MUTEX |
2713 | @@ -320,6 +406,29 @@ |
2714 | # endif /* UNIV_DEBUG */ |
2715 | const char* cmutex_name); |
2716 | /******************************************************************//** |
2717 | +NOTE! Please use the corresponding macro mutex_create(), not directly |
2718 | +this function! |
2719 | +A wrapper function for mutex_create_func(), registers the mutex |
2720 | +with peformance schema if "UNIV_PFS_MUTEX" is defined when |
2721 | +creating the performance mutex */ |
2722 | +UNIV_INLINE |
2723 | +void |
2724 | +pfs_mutex_create_func( |
2725 | +/*==================*/ |
2726 | + PSI_mutex_key key, /*!< in: Performance Schema |
2727 | + key */ |
2728 | + ib_prio_mutex_t* mutex, /*!< in: pointer to memory */ |
2729 | +# ifdef UNIV_DEBUG |
2730 | +# ifdef UNIV_SYNC_DEBUG |
2731 | + ulint level, /*!< in: level */ |
2732 | +# endif /* UNIV_SYNC_DEBUG */ |
2733 | + const char* cfile_name, /*!< in: file name where |
2734 | + created */ |
2735 | + ulint cline, /*!< in: file line where |
2736 | + created */ |
2737 | +# endif /* UNIV_DEBUG */ |
2738 | + const char* cmutex_name); |
2739 | +/******************************************************************//** |
2740 | NOTE! Please use the corresponding macro mutex_enter(), not directly |
2741 | this function! |
2742 | This is a performance schema instrumented wrapper function for |
2743 | @@ -331,6 +440,22 @@ |
2744 | ib_mutex_t* mutex, /*!< in: pointer to mutex */ |
2745 | const char* file_name, /*!< in: file name where locked */ |
2746 | ulint line); /*!< in: line where locked */ |
2747 | +/******************************************************************//** |
2748 | +NOTE! Please use the corresponding macro mutex_enter(), not directly |
2749 | +this function! |
2750 | +This is a performance schema instrumented wrapper function for |
2751 | +mutex_enter_func(). */ |
2752 | +UNIV_INLINE |
2753 | +void |
2754 | +pfs_mutex_enter_func( |
2755 | +/*=================*/ |
2756 | + ib_prio_mutex_t* mutex, /*!< in: pointer to mutex */ |
2757 | + const char* file_name, /*!< in: file name where |
2758 | + locked */ |
2759 | + ulint line, /*!< in: line where locked */ |
2760 | + enum ib_sync_priority priority = DEFAULT_PRIO); |
2761 | + /*!<in: mutex acquisition |
2762 | + priority */ |
2763 | /********************************************************************//** |
2764 | NOTE! Please use the corresponding macro mutex_enter_nowait(), not directly |
2765 | this function! |
2766 | @@ -345,6 +470,21 @@ |
2767 | const char* file_name, /*!< in: file name where mutex |
2768 | requested */ |
2769 | ulint line); /*!< in: line where requested */ |
2770 | +/********************************************************************//** |
2771 | +NOTE! Please use the corresponding macro mutex_enter_nowait(), not directly |
2772 | +this function! |
2773 | +This is a performance schema instrumented wrapper function for |
2774 | +mutex_enter_nowait_func. |
2775 | +@return 0 if succeed, 1 if not */ |
2776 | +UNIV_INLINE |
2777 | +ulint |
2778 | +pfs_mutex_enter_nowait_func( |
2779 | +/*========================*/ |
2780 | + ib_prio_mutex_t* mutex, /*!< in: pointer to mutex */ |
2781 | + const char* file_name, /*!< in: file name where mutex |
2782 | + requested */ |
2783 | + ulint line); /*!< in: line where |
2784 | + requested */ |
2785 | /******************************************************************//** |
2786 | NOTE! Please use the corresponding macro mutex_exit(), not directly |
2787 | this function! |
2788 | @@ -355,6 +495,16 @@ |
2789 | pfs_mutex_exit_func( |
2790 | /*================*/ |
2791 | ib_mutex_t* mutex); /*!< in: pointer to mutex */ |
2792 | +/******************************************************************//** |
2793 | +NOTE! Please use the corresponding macro mutex_exit(), not directly |
2794 | +this function! |
2795 | +A wrap function of mutex_exit_func() with peformance schema instrumentation. |
2796 | +Unlocks a priority mutex owned by the current thread. */ |
2797 | +UNIV_INLINE |
2798 | +void |
2799 | +pfs_mutex_exit_func( |
2800 | +/*================*/ |
2801 | + ib_prio_mutex_t* mutex); /*!< in: pointer to mutex */ |
2802 | |
2803 | /******************************************************************//** |
2804 | NOTE! Please use the corresponding macro mutex_free(), not directly |
2805 | @@ -366,6 +516,16 @@ |
2806 | pfs_mutex_free_func( |
2807 | /*================*/ |
2808 | ib_mutex_t* mutex); /*!< in: mutex */ |
2809 | +/******************************************************************//** |
2810 | +NOTE! Please use the corresponding macro mutex_free(), not directly |
2811 | +this function! |
2812 | +Wrapper function for mutex_free_func(). Also destroys the performance |
2813 | +schema probes when freeing the priority mutex */ |
2814 | +UNIV_INLINE |
2815 | +void |
2816 | +pfs_mutex_free_func( |
2817 | +/*================*/ |
2818 | + ib_prio_mutex_t* mutex); /*!< in: mutex */ |
2819 | |
2820 | #endif /* UNIV_PFS_MUTEX */ |
2821 | |
2822 | @@ -414,6 +574,16 @@ |
2823 | /*======*/ |
2824 | const ib_mutex_t* mutex) /*!< in: mutex */ |
2825 | __attribute__((warn_unused_result)); |
2826 | +/******************************************************************//** |
2827 | +Checks that the current thread owns the priority mutex. Works only |
2828 | +in the debug version. |
2829 | +@return TRUE if owns */ |
2830 | +UNIV_INTERN |
2831 | +ibool |
2832 | +mutex_own( |
2833 | +/*======*/ |
2834 | + const ib_prio_mutex_t* mutex) /*!< in: priority mutex */ |
2835 | + __attribute__((warn_unused_result)); |
2836 | #endif /* UNIV_DEBUG */ |
2837 | #ifdef UNIV_SYNC_DEBUG |
2838 | /******************************************************************//** |
2839 | @@ -748,6 +918,9 @@ |
2840 | #define RW_LOCK_SHARED 352 |
2841 | #define RW_LOCK_WAIT_EX 353 |
2842 | #define SYNC_MUTEX 354 |
2843 | +#define SYNC_PRIO_MUTEX 355 |
2844 | +#define PRIO_RW_LOCK_EX 356 |
2845 | +#define PRIO_RW_LOCK_SHARED 357 |
2846 | |
2847 | /* NOTE! The structure appears here only for the compiler to know its size. |
2848 | Do not use its fields directly! The structure used in the spin lock |
2849 | @@ -798,6 +971,20 @@ |
2850 | #endif |
2851 | }; |
2852 | |
2853 | +/** XtraDB priority mutex */ |
2854 | +struct ib_prio_mutex_t { |
2855 | + ib_mutex_t base_mutex; /* The regular mutex provides the lock |
2856 | + word etc. for the priority mutex */ |
2857 | + os_event_t high_priority_event; /* High priority wait array |
2858 | + event */ |
2859 | + volatile ulint high_priority_waiters; /* Set to 1 if there are (or |
2860 | + may be) threads that asked for this |
2861 | + mutex to be acquired with high priority |
2862 | + in the global wait array for this mutex |
2863 | + to be released. Otherwise, this is |
2864 | + 0. */ |
2865 | +}; |
2866 | + |
2867 | /** Constant determining how long spin wait is continued before suspending |
2868 | the thread. A value 600 rounds on a 1995 100 MHz Pentium seems to correspond |
2869 | to 20 microseconds. */ |
2870 | |
2871 | === modified file 'Percona-Server/storage/innobase/include/sync0sync.ic' |
2872 | --- Percona-Server/storage/innobase/include/sync0sync.ic 2013-08-06 15:16:34 +0000 |
2873 | +++ Percona-Server/storage/innobase/include/sync0sync.ic 2013-09-26 14:59:13 +0000 |
2874 | @@ -39,14 +39,17 @@ |
2875 | ib_mutex_t* mutex, /*!< in: mutex */ |
2876 | ulint n); /*!< in: value to set */ |
2877 | /******************************************************************//** |
2878 | -Reserves a mutex for the current thread. If the mutex is reserved, the |
2879 | -function spins a preset time (controlled by SYNC_SPIN_ROUNDS) waiting |
2880 | -for the mutex before suspending the thread. */ |
2881 | +Reserves a mutex or a priority mutex for the current thread. If the mutex is |
2882 | +reserved, the function spins a preset time (controlled by SYNC_SPIN_ROUNDS) |
2883 | +waiting for the mutex before suspending the thread. */ |
2884 | UNIV_INTERN |
2885 | void |
2886 | mutex_spin_wait( |
2887 | /*============*/ |
2888 | - ib_mutex_t* mutex, /*!< in: pointer to mutex */ |
2889 | + void* _mutex, /*!< in: pointer to mutex */ |
2890 | + bool high_priority, /*!< in: whether the mutex is a |
2891 | + priority mutex with high priority |
2892 | + specified */ |
2893 | const char* file_name, /*!< in: file name where mutex |
2894 | requested */ |
2895 | ulint line); /*!< in: line where requested */ |
2896 | @@ -192,6 +195,55 @@ |
2897 | } |
2898 | |
2899 | /******************************************************************//** |
2900 | +NOTE! Use the corresponding macro mutex_exit(), not directly this function! |
2901 | +Unlocks a priority mutex owned by the current thread. */ |
2902 | +UNIV_INLINE |
2903 | +void |
2904 | +mutex_exit_func( |
2905 | +/*============*/ |
2906 | + ib_prio_mutex_t* mutex) /*!< in: pointer to mutex */ |
2907 | +{ |
2908 | + ut_ad(mutex_own(mutex)); |
2909 | + |
2910 | + ut_d(mutex->base_mutex.thread_id = (os_thread_id_t) ULINT_UNDEFINED); |
2911 | + |
2912 | +#ifdef UNIV_SYNC_DEBUG |
2913 | + sync_thread_reset_level(&mutex->base_mutex); |
2914 | +#endif |
2915 | + mutex_reset_lock_word(&mutex->base_mutex); |
2916 | + |
2917 | + /* A problem: we assume that mutex_reset_lock word |
2918 | + is a memory barrier, that is when we read the waiters |
2919 | + field next, the read must be serialized in memory |
2920 | + after the reset. A speculative processor might |
2921 | + perform the read first, which could leave a waiting |
2922 | + thread hanging indefinitely. |
2923 | + |
2924 | + Our current solution call every second |
2925 | + sync_arr_wake_threads_if_sema_free() |
2926 | + to wake up possible hanging threads if |
2927 | + they are missed in mutex_signal_object. */ |
2928 | + |
2929 | + /* Wake up any high priority waiters first. */ |
2930 | + if (mutex->high_priority_waiters != 0) { |
2931 | + |
2932 | + mutex->high_priority_waiters = 0; |
2933 | + os_event_set(mutex->high_priority_event); |
2934 | + sync_array_object_signalled(); |
2935 | + |
2936 | + } else if (mutex_get_waiters(&mutex->base_mutex) != 0) { |
2937 | + |
2938 | + mutex_signal_object(&mutex->base_mutex); |
2939 | + } |
2940 | + |
2941 | +#ifdef UNIV_SYNC_PERF_STAT |
2942 | + mutex_exit_count++; |
2943 | +#endif |
2944 | + |
2945 | +} |
2946 | + |
2947 | + |
2948 | +/******************************************************************//** |
2949 | Locks a mutex for the current thread. If the mutex is reserved, the function |
2950 | spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting for the mutex |
2951 | before suspending the thread. */ |
2952 | @@ -217,8 +269,54 @@ |
2953 | return; /* Succeeded! */ |
2954 | } |
2955 | |
2956 | - mutex_spin_wait(mutex, file_name, line); |
2957 | -} |
2958 | + mutex_spin_wait(mutex, false, file_name, line); |
2959 | +} |
2960 | + |
2961 | +/******************************************************************//** |
2962 | +NOTE! Use the corresponding macro in the header file, not this function |
2963 | +directly. Locks a priority mutex for the current thread. If the mutex is |
2964 | +reserved the function spins a preset time (controlled by SYNC_SPIN_ROUNDS) |
2965 | +waiting for the mutex before suspending the thread. If the thread is suspended, |
2966 | +the priority argument value determines the relative order for its wake up. Any |
2967 | +HIGH_PRIO waiters will be woken up before any LOW_PRIO waiters. In case of |
2968 | +DEFAULT_PRIO, the relative priority will be set according to |
2969 | +srv_current_thread_priority. */ |
2970 | +UNIV_INLINE |
2971 | +void |
2972 | +mutex_enter_func( |
2973 | +/*=============*/ |
2974 | + ib_prio_mutex_t* mutex, /*!< in: pointer to mutex */ |
2975 | + const char* file_name, /*!< in: file name where |
2976 | + locked */ |
2977 | + ulint line, /*!< in: line where locked */ |
2978 | + enum ib_sync_priority priority) |
2979 | + /*!<in: mutex acquisition |
2980 | + priority */ |
2981 | +{ |
2982 | + bool high_priority; |
2983 | + |
2984 | + ut_ad(mutex_validate(&mutex->base_mutex)); |
2985 | + ut_ad(!mutex_own(mutex)); |
2986 | + |
2987 | + /* Note that we do not peek at the value of lock_word before trying |
2988 | + the atomic test_and_set; we could peek, and possibly save time. */ |
2989 | + |
2990 | + if (!ib_mutex_test_and_set(&mutex->base_mutex)) { |
2991 | + ut_d(mutex->base_mutex.thread_id = os_thread_get_curr_id()); |
2992 | +#ifdef UNIV_SYNC_DEBUG |
2993 | + mutex_set_debug_info(&mutex->base_mutex, file_name, line); |
2994 | +#endif |
2995 | + return; /* Succeeded! */ |
2996 | + } |
2997 | + |
2998 | + if (UNIV_LIKELY(priority == DEFAULT_PRIO)) { |
2999 | + high_priority = srv_current_thread_priority; |
3000 | + } else { |
3001 | + high_priority = (priority == HIGH_PRIO); |
3002 | + } |
3003 | + mutex_spin_wait(mutex, high_priority, file_name, line); |
3004 | +} |
3005 | + |
3006 | |
3007 | #ifdef UNIV_PFS_MUTEX |
3008 | /******************************************************************//** |
3009 | @@ -252,6 +350,40 @@ |
3010 | } |
3011 | } |
3012 | |
3013 | +/******************************************************************//** |
3014 | +NOTE! Please use the corresponding macro mutex_enter(), not directly |
3015 | +this function! |
3016 | +This is a performance schema instrumented wrapper function for |
3017 | +mutex_enter_func(). */ |
3018 | +UNIV_INLINE |
3019 | +void |
3020 | +pfs_mutex_enter_func( |
3021 | +/*=================*/ |
3022 | + ib_prio_mutex_t* mutex, /*!< in: pointer to mutex */ |
3023 | + const char* file_name, /*!< in: file name where |
3024 | + locked */ |
3025 | + ulint line, /*!< in: line where locked */ |
3026 | + enum ib_sync_priority priority) /*!<in: mutex acquisition |
3027 | + priority */ |
3028 | +{ |
3029 | + if (mutex->base_mutex.pfs_psi != NULL) { |
3030 | + PSI_mutex_locker* locker; |
3031 | + PSI_mutex_locker_state state; |
3032 | + |
3033 | + locker = PSI_MUTEX_CALL(start_mutex_wait)( |
3034 | + &state, mutex->base_mutex.pfs_psi, |
3035 | + PSI_MUTEX_LOCK, file_name, line); |
3036 | + |
3037 | + mutex_enter_func(mutex, file_name, line, priority); |
3038 | + |
3039 | + if (locker != NULL) { |
3040 | + PSI_MUTEX_CALL(end_mutex_wait)(locker, 0); |
3041 | + } |
3042 | + } else { |
3043 | + mutex_enter_func(mutex, file_name, line, priority); |
3044 | + } |
3045 | +} |
3046 | + |
3047 | /********************************************************************//** |
3048 | NOTE! Please use the corresponding macro mutex_enter_nowait(), not directly |
3049 | this function! |
3050 | @@ -289,6 +421,26 @@ |
3051 | return(ret); |
3052 | } |
3053 | |
3054 | +/********************************************************************//** |
3055 | +NOTE! Please use the corresponding macro mutex_enter_nowait(), not directly |
3056 | +this function! |
3057 | +This is a performance schema instrumented wrapper function for |
3058 | +mutex_enter_nowait_func. |
3059 | +@return 0 if succeed, 1 if not */ |
3060 | +UNIV_INLINE |
3061 | +ulint |
3062 | +pfs_mutex_enter_nowait_func( |
3063 | +/*========================*/ |
3064 | + ib_prio_mutex_t* mutex, /*!< in: pointer to mutex */ |
3065 | + const char* file_name, /*!< in: file name where mutex |
3066 | + requested */ |
3067 | + ulint line) /*!< in: line where |
3068 | + requested */ |
3069 | +{ |
3070 | + return pfs_mutex_enter_nowait_func(&mutex->base_mutex, file_name, |
3071 | + line); |
3072 | +} |
3073 | + |
3074 | /******************************************************************//** |
3075 | NOTE! Please use the corresponding macro mutex_exit(), not directly |
3076 | this function! |
3077 | @@ -308,6 +460,25 @@ |
3078 | } |
3079 | |
3080 | /******************************************************************//** |
3081 | +NOTE! Please use the corresponding macro mutex_exit(), not directly |
3082 | +this function! |
3083 | +A wrap function of mutex_exit_func() with peformance schema instrumentation. |
3084 | +Unlocks a priority mutex owned by the current thread. */ |
3085 | +UNIV_INLINE |
3086 | +void |
3087 | +pfs_mutex_exit_func( |
3088 | +/*================*/ |
3089 | + ib_prio_mutex_t* mutex) /*!< in: pointer to mutex */ |
3090 | +{ |
3091 | + if (mutex->base_mutex.pfs_psi != NULL) { |
3092 | + PSI_MUTEX_CALL(unlock_mutex)(mutex->base_mutex.pfs_psi); |
3093 | + } |
3094 | + |
3095 | + mutex_exit_func(mutex); |
3096 | +} |
3097 | + |
3098 | + |
3099 | +/******************************************************************//** |
3100 | NOTE! Please use the corresponding macro mutex_create(), not directly |
3101 | this function! |
3102 | A wrapper function for mutex_create_func(), registers the mutex |
3103 | @@ -342,6 +513,44 @@ |
3104 | } |
3105 | |
3106 | /******************************************************************//** |
3107 | +NOTE! Please use the corresponding macro mutex_create(), not directly |
3108 | +this function! |
3109 | +A wrapper function for mutex_create_func(), registers the mutex |
3110 | +with peformance schema if "UNIV_PFS_MUTEX" is defined when |
3111 | +creating the performance mutex */ |
3112 | +UNIV_INLINE |
3113 | +void |
3114 | +pfs_mutex_create_func( |
3115 | +/*==================*/ |
3116 | + PSI_mutex_key key, /*!< in: Performance Schema |
3117 | + key */ |
3118 | + ib_prio_mutex_t* mutex, /*!< in: pointer to memory */ |
3119 | +# ifdef UNIV_DEBUG |
3120 | +# ifdef UNIV_SYNC_DEBUG |
3121 | + ulint level, /*!< in: level */ |
3122 | +# endif /* UNIV_SYNC_DEBUG */ |
3123 | + const char* cfile_name, /*!< in: file name where |
3124 | + created */ |
3125 | + ulint cline, /*!< in: file line where |
3126 | + created */ |
3127 | +# endif /* UNIV_DEBUG */ |
3128 | + const char* cmutex_name) |
3129 | +{ |
3130 | + mutex->base_mutex.pfs_psi = PSI_MUTEX_CALL(init_mutex)(key, mutex); |
3131 | + |
3132 | + mutex_create_func(mutex, |
3133 | +# ifdef UNIV_DEBUG |
3134 | +# ifdef UNIV_SYNC_DEBUG |
3135 | + level, |
3136 | +# endif /* UNIV_SYNC_DEBUG */ |
3137 | + cfile_name, |
3138 | + cline, |
3139 | +# endif /* UNIV_DEBUG */ |
3140 | + cmutex_name); |
3141 | +} |
3142 | + |
3143 | + |
3144 | +/******************************************************************//** |
3145 | NOTE! Please use the corresponding macro mutex_free(), not directly |
3146 | this function! |
3147 | Wrapper function for mutex_free_func(). Also destroys the performance |
3148 | @@ -360,6 +569,26 @@ |
3149 | mutex_free_func(mutex); |
3150 | } |
3151 | |
3152 | +/******************************************************************//** |
3153 | +NOTE! Please use the corresponding macro mutex_free(), not directly |
3154 | +this function! |
3155 | +Wrapper function for mutex_free_func(). Also destroys the performance |
3156 | +schema probes when freeing the priority mutex */ |
3157 | +UNIV_INLINE |
3158 | +void |
3159 | +pfs_mutex_free_func( |
3160 | +/*================*/ |
3161 | + ib_prio_mutex_t* mutex) /*!< in: mutex */ |
3162 | +{ |
3163 | + if (mutex->base_mutex.pfs_psi != NULL) { |
3164 | + PSI_MUTEX_CALL(destroy_mutex)(mutex->base_mutex.pfs_psi); |
3165 | + mutex->base_mutex.pfs_psi = NULL; |
3166 | + } |
3167 | + |
3168 | + mutex_free_func(mutex); |
3169 | +} |
3170 | + |
3171 | + |
3172 | #endif /* UNIV_PFS_MUTEX */ |
3173 | |
3174 | #ifndef HAVE_ATOMIC_BUILTINS |
3175 | |
3176 | === modified file 'Percona-Server/storage/innobase/include/sync0types.h' |
3177 | --- Percona-Server/storage/innobase/include/sync0types.h 2013-08-06 15:16:34 +0000 |
3178 | +++ Percona-Server/storage/innobase/include/sync0types.h 2013-09-26 14:59:13 +0000 |
3179 | @@ -28,4 +28,17 @@ |
3180 | |
3181 | struct ib_mutex_t; |
3182 | |
3183 | +/* The relative priority of the current thread. If 0, low priority; if 1, high |
3184 | +priority. */ |
3185 | +extern UNIV_THREAD_LOCAL ulint srv_current_thread_priority; |
3186 | + |
3187 | +struct ib_prio_mutex_t; |
3188 | + |
3189 | +/** Priority mutex and rwlatch acquisition priorities */ |
3190 | +enum ib_sync_priority { |
3191 | + DEFAULT_PRIO, |
3192 | + LOW_PRIO, |
3193 | + HIGH_PRIO |
3194 | +}; |
3195 | + |
3196 | #endif |
3197 | |
3198 | === modified file 'Percona-Server/storage/innobase/include/trx0purge.h' |
3199 | --- Percona-Server/storage/innobase/include/trx0purge.h 2013-08-06 15:16:34 +0000 |
3200 | +++ Percona-Server/storage/innobase/include/trx0purge.h 2013-09-26 14:59:13 +0000 |
3201 | @@ -138,7 +138,7 @@ |
3202 | purge query: this trx is not in the |
3203 | trx list of the trx system and it |
3204 | never ends */ |
3205 | - rw_lock_t latch; /*!< The latch protecting the purge |
3206 | + prio_rw_lock_t latch; /*!< The latch protecting the purge |
3207 | view. A purge operation must acquire an |
3208 | x-latch here for the instant at which |
3209 | it changes the purge view: an undo |
3210 | |
3211 | === modified file 'Percona-Server/storage/innobase/include/trx0trx.h' |
3212 | --- Percona-Server/storage/innobase/include/trx0trx.h 2013-09-02 10:01:38 +0000 |
3213 | +++ Percona-Server/storage/innobase/include/trx0trx.h 2013-09-26 14:59:13 +0000 |
3214 | @@ -1138,7 +1138,7 @@ |
3215 | |
3216 | Bear in mind (3) and (4) when using the hash index. |
3217 | */ |
3218 | -extern rw_lock_t* btr_search_latch_arr; |
3219 | +extern prio_rw_lock_t* btr_search_latch_arr; |
3220 | |
3221 | #ifndef UNIV_NONINL |
3222 | #include "trx0trx.ic" |
3223 | |
3224 | === modified file 'Percona-Server/storage/innobase/include/univ.i' |
3225 | --- Percona-Server/storage/innobase/include/univ.i 2013-08-29 17:05:40 +0000 |
3226 | +++ Percona-Server/storage/innobase/include/univ.i 2013-09-26 14:59:13 +0000 |
3227 | @@ -277,6 +277,13 @@ |
3228 | # define UNIV_COLD /* empty */ |
3229 | #endif |
3230 | |
3231 | +#ifdef UNIV_LINUX |
3232 | +# define UNIV_THREAD_LOCAL __thread |
3233 | +#else |
3234 | +/* FIXME: the TLS variables are silently broken on other platforms for now */ |
3235 | +# define UNIV_THREAD_LOCAL |
3236 | +#endif |
3237 | + |
3238 | #ifndef UNIV_MUST_NOT_INLINE |
3239 | /* Definition for inline version */ |
3240 | |
3241 | |
3242 | === modified file 'Percona-Server/storage/innobase/mtr/mtr0mtr.cc' |
3243 | --- Percona-Server/storage/innobase/mtr/mtr0mtr.cc 2013-06-25 13:13:06 +0000 |
3244 | +++ Percona-Server/storage/innobase/mtr/mtr0mtr.cc 2013-09-26 14:59:13 +0000 |
3245 | @@ -82,10 +82,10 @@ |
3246 | buf_page_release((buf_block_t*) object, slot->type); |
3247 | break; |
3248 | case MTR_MEMO_S_LOCK: |
3249 | - rw_lock_s_unlock((rw_lock_t*) object); |
3250 | + rw_lock_s_unlock((prio_rw_lock_t*) object); |
3251 | break; |
3252 | case MTR_MEMO_X_LOCK: |
3253 | - rw_lock_x_unlock((rw_lock_t*) object); |
3254 | + rw_lock_x_unlock((prio_rw_lock_t*) object); |
3255 | break; |
3256 | #ifdef UNIV_DEBUG |
3257 | default: |
3258 | |
3259 | === modified file 'Percona-Server/storage/innobase/srv/srv0srv.cc' |
3260 | --- Percona-Server/storage/innobase/srv/srv0srv.cc 2013-09-24 13:11:08 +0000 |
3261 | +++ Percona-Server/storage/innobase/srv/srv0srv.cc 2013-09-26 14:59:13 +0000 |
3262 | @@ -319,6 +319,22 @@ |
3263 | /* Number of iterations over which adaptive flushing is averaged. */ |
3264 | UNIV_INTERN ulong srv_flushing_avg_loops = 30; |
3265 | |
3266 | +/* The relative priority of the current thread. If 0, low priority; if 1, high |
3267 | +priority. */ |
3268 | +UNIV_INTERN UNIV_THREAD_LOCAL ulint srv_current_thread_priority = 0; |
3269 | + |
3270 | +/* The relative priority of the purge coordinator and worker threads. */ |
3271 | +UNIV_INTERN my_bool srv_purge_thread_priority = FALSE; |
3272 | + |
3273 | +/* The relative priority of the I/O threads. */ |
3274 | +UNIV_INTERN my_bool srv_io_thread_priority = FALSE; |
3275 | + |
3276 | +/* The relative priority of the cleaner thread. */ |
3277 | +UNIV_INTERN my_bool srv_cleaner_thread_priority = FALSE; |
3278 | + |
3279 | +/* The relative priority of the master thread. */ |
3280 | +UNIV_INTERN my_bool srv_master_thread_priority = FALSE; |
3281 | + |
3282 | /* The number of purge threads to use.*/ |
3283 | UNIV_INTERN ulong srv_n_purge_threads = 1; |
3284 | |
3285 | @@ -2863,6 +2879,8 @@ |
3286 | |
3287 | MONITOR_INC(MONITOR_MASTER_THREAD_SLEEP); |
3288 | |
3289 | + srv_current_thread_priority = srv_master_thread_priority; |
3290 | + |
3291 | if (srv_check_activity(old_activity_count)) { |
3292 | old_activity_count = srv_get_activity_count(); |
3293 | srv_master_do_active_tasks(); |
3294 | @@ -3003,6 +3021,8 @@ |
3295 | |
3296 | os_event_wait(slot->event); |
3297 | |
3298 | + srv_current_thread_priority = srv_purge_thread_priority; |
3299 | + |
3300 | if (srv_task_execute()) { |
3301 | |
3302 | /* If there are tasks in the queue, wakeup |
3303 | @@ -3279,6 +3299,8 @@ |
3304 | |
3305 | n_total_purged = 0; |
3306 | |
3307 | + srv_current_thread_priority = srv_purge_thread_priority; |
3308 | + |
3309 | rseg_history_len = srv_do_purge( |
3310 | srv_n_purge_threads, &n_total_purged); |
3311 | |
3312 | |
3313 | === modified file 'Percona-Server/storage/innobase/srv/srv0start.cc' |
3314 | --- Percona-Server/storage/innobase/srv/srv0start.cc 2013-08-14 03:57:21 +0000 |
3315 | +++ Percona-Server/storage/innobase/srv/srv0start.cc 2013-09-26 14:59:13 +0000 |
3316 | @@ -476,6 +476,7 @@ |
3317 | #endif /* UNIV_PFS_THREAD */ |
3318 | |
3319 | while (srv_shutdown_state != SRV_SHUTDOWN_EXIT_THREADS) { |
3320 | + srv_current_thread_priority = srv_io_thread_priority; |
3321 | fil_aio_wait(segment); |
3322 | } |
3323 | |
3324 | |
3325 | === modified file 'Percona-Server/storage/innobase/sync/sync0arr.cc' |
3326 | --- Percona-Server/storage/innobase/sync/sync0arr.cc 2013-08-14 03:57:21 +0000 |
3327 | +++ Percona-Server/storage/innobase/sync/sync0arr.cc 2013-09-26 14:59:13 +0000 |
3328 | @@ -83,10 +83,11 @@ |
3329 | void* wait_object; /*!< pointer to the object the |
3330 | thread is waiting for; if NULL |
3331 | the cell is free for use */ |
3332 | - ib_mutex_t* old_wait_mutex; /*!< the latest wait mutex in cell */ |
3333 | - rw_lock_t* old_wait_rw_lock; |
3334 | - /*!< the latest wait rw-lock |
3335 | - in cell */ |
3336 | + void* old_wait_mutex; /*!< the latest regular or priority |
3337 | + wait mutex in cell */ |
3338 | + void* old_wait_rw_lock; |
3339 | + /*!< the latest regular or priority |
3340 | + wait rw-lock in cell */ |
3341 | ulint request_type; /*!< lock type requested on the |
3342 | object */ |
3343 | const char* file; /*!< in debug version file where |
3344 | @@ -295,9 +296,19 @@ |
3345 | |
3346 | if (type == SYNC_MUTEX) { |
3347 | return(((ib_mutex_t*) cell->wait_object)->event); |
3348 | + } else if (type == SYNC_PRIO_MUTEX) { |
3349 | + return(((ib_prio_mutex_t*) cell->wait_object) |
3350 | + ->high_priority_event); |
3351 | } else if (type == RW_LOCK_WAIT_EX) { |
3352 | return(((rw_lock_t*) cell->wait_object)->wait_ex_event); |
3353 | + } else if (type == PRIO_RW_LOCK_SHARED) { |
3354 | + return(((prio_rw_lock_t *) cell->wait_object) |
3355 | + ->high_priority_s_event); |
3356 | + } else if (type == PRIO_RW_LOCK_EX) { |
3357 | + return(((prio_rw_lock_t *) cell->wait_object) |
3358 | + ->high_priority_x_event); |
3359 | } else { /* RW_LOCK_SHARED and RW_LOCK_EX wait on the same event */ |
3360 | + ut_ad(type == RW_LOCK_SHARED || type == RW_LOCK_EX); |
3361 | return(((rw_lock_t*) cell->wait_object)->event); |
3362 | } |
3363 | } |
3364 | @@ -336,12 +347,10 @@ |
3365 | cell->waiting = FALSE; |
3366 | cell->wait_object = object; |
3367 | |
3368 | - if (type == SYNC_MUTEX) { |
3369 | - cell->old_wait_mutex = |
3370 | - static_cast<ib_mutex_t*>(object); |
3371 | + if (type == SYNC_MUTEX || type == SYNC_PRIO_MUTEX) { |
3372 | + cell->old_wait_mutex = object; |
3373 | } else { |
3374 | - cell->old_wait_rw_lock = |
3375 | - static_cast<rw_lock_t*>(object); |
3376 | + cell->old_wait_rw_lock = object; |
3377 | } |
3378 | |
3379 | cell->request_type = type; |
3380 | @@ -436,7 +445,9 @@ |
3381 | sync_cell_t* cell) /*!< in: sync cell */ |
3382 | { |
3383 | ib_mutex_t* mutex; |
3384 | + ib_prio_mutex_t* prio_mutex; |
3385 | rw_lock_t* rwlock; |
3386 | + prio_rw_lock_t* prio_rwlock = NULL; |
3387 | ulint type; |
3388 | ulint writer; |
3389 | |
3390 | @@ -449,10 +460,19 @@ |
3391 | innobase_basename(cell->file), (ulong) cell->line, |
3392 | difftime(time(NULL), cell->reservation_time)); |
3393 | |
3394 | - if (type == SYNC_MUTEX) { |
3395 | + if (type == SYNC_MUTEX || type == SYNC_PRIO_MUTEX) { |
3396 | /* We use old_wait_mutex in case the cell has already |
3397 | been freed meanwhile */ |
3398 | - mutex = cell->old_wait_mutex; |
3399 | + if (type == SYNC_MUTEX) { |
3400 | + |
3401 | + mutex = static_cast<ib_mutex_t*>(cell->old_wait_mutex); |
3402 | + } else { |
3403 | + |
3404 | + prio_mutex = static_cast<ib_prio_mutex_t*> |
3405 | + (cell->old_wait_mutex); |
3406 | + mutex = &prio_mutex->base_mutex; |
3407 | + } |
3408 | + |
3409 | |
3410 | fprintf(file, |
3411 | "Mutex at %p '%s', lock var %lu\n" |
3412 | @@ -467,15 +487,38 @@ |
3413 | #endif /* UNIV_SYNC_DEBUG */ |
3414 | (ulong) mutex->waiters); |
3415 | |
3416 | + if (type == SYNC_PRIO_MUTEX) { |
3417 | + |
3418 | + fprintf(file, |
3419 | + "high-priority waiters flag %lu\n", |
3420 | + (ulong) prio_mutex->high_priority_waiters); |
3421 | + } |
3422 | + |
3423 | } else if (type == RW_LOCK_EX |
3424 | || type == RW_LOCK_WAIT_EX |
3425 | - || type == RW_LOCK_SHARED) { |
3426 | + || type == RW_LOCK_SHARED |
3427 | + || type == PRIO_RW_LOCK_SHARED |
3428 | + || type == PRIO_RW_LOCK_EX) { |
3429 | |
3430 | - fputs(type == RW_LOCK_EX ? "X-lock on" |
3431 | + fputs((type == RW_LOCK_EX || type == PRIO_RW_LOCK_EX) |
3432 | + ? "X-lock on" |
3433 | : type == RW_LOCK_WAIT_EX ? "X-lock (wait_ex) on" |
3434 | : "S-lock on", file); |
3435 | |
3436 | - rwlock = cell->old_wait_rw_lock; |
3437 | + /* Currently we are unable to tell high priority |
3438 | + RW_LOCK_WAIT_EX waiter from a regular priority one. Assume |
3439 | + it's a regular one. */ |
3440 | + if (type == RW_LOCK_EX || type == RW_LOCK_WAIT_EX |
3441 | + || type == RW_LOCK_SHARED) { |
3442 | + |
3443 | + rwlock = static_cast<rw_lock_t *> |
3444 | + (cell->old_wait_rw_lock); |
3445 | + } else { |
3446 | + |
3447 | + prio_rwlock = static_cast<prio_rw_lock_t *> |
3448 | + (cell->old_wait_rw_lock); |
3449 | + rwlock = &prio_rwlock->base_lock; |
3450 | + } |
3451 | |
3452 | fprintf(file, |
3453 | " RW-latch at %p '%s'\n", |
3454 | @@ -503,6 +546,15 @@ |
3455 | (ulong) rwlock->last_s_line, |
3456 | rwlock->last_x_file_name, |
3457 | (ulong) rwlock->last_x_line); |
3458 | + if (prio_rwlock) { |
3459 | + fprintf(stderr, "high priority S waiters flag %lu, " |
3460 | + "high priority X waiters flag %lu, " |
3461 | + "wait-exclusive waiter is " |
3462 | + "high priority if exists: %lu\n", |
3463 | + prio_rwlock->high_priority_s_waiters, |
3464 | + prio_rwlock->high_priority_x_waiters, |
3465 | + prio_rwlock->high_priority_wait_ex_waiter); |
3466 | + } |
3467 | } else { |
3468 | ut_error; |
3469 | } |
3470 | @@ -615,9 +667,15 @@ |
3471 | return(FALSE); /* No deadlock here */ |
3472 | } |
3473 | |
3474 | - if (cell->request_type == SYNC_MUTEX) { |
3475 | + if (cell->request_type == SYNC_MUTEX |
3476 | + || cell->request_type == SYNC_PRIO_MUTEX) { |
3477 | |
3478 | - mutex = static_cast<ib_mutex_t*>(cell->wait_object); |
3479 | + if (cell->request_type == SYNC_MUTEX) { |
3480 | + mutex = static_cast<ib_mutex_t*>(cell->wait_object); |
3481 | + } else { |
3482 | + mutex = &(static_cast<ib_prio_mutex_t*>( |
3483 | + cell->wait_object))->base_mutex; |
3484 | + } |
3485 | |
3486 | if (mutex_get_lock_word(mutex) != 0) { |
3487 | |
3488 | @@ -647,6 +705,7 @@ |
3489 | return(FALSE); /* No deadlock */ |
3490 | |
3491 | } else if (cell->request_type == RW_LOCK_EX |
3492 | + || cell->request_type == PRIO_RW_LOCK_EX |
3493 | || cell->request_type == RW_LOCK_WAIT_EX) { |
3494 | |
3495 | lock = static_cast<rw_lock_t*>(cell->wait_object); |
3496 | @@ -685,7 +744,8 @@ |
3497 | |
3498 | return(FALSE); |
3499 | |
3500 | - } else if (cell->request_type == RW_LOCK_SHARED) { |
3501 | + } else if (cell->request_type == RW_LOCK_SHARED |
3502 | + || cell->request_type == PRIO_RW_LOCK_SHARED) { |
3503 | |
3504 | lock = static_cast<rw_lock_t*>(cell->wait_object); |
3505 | |
3506 | @@ -734,16 +794,23 @@ |
3507 | ib_mutex_t* mutex; |
3508 | rw_lock_t* lock; |
3509 | |
3510 | - if (cell->request_type == SYNC_MUTEX) { |
3511 | + if (cell->request_type == SYNC_MUTEX |
3512 | + || cell->request_type == SYNC_PRIO_MUTEX) { |
3513 | |
3514 | - mutex = static_cast<ib_mutex_t*>(cell->wait_object); |
3515 | + if (cell->request_type == SYNC_MUTEX) { |
3516 | + mutex = static_cast<ib_mutex_t*>(cell->wait_object); |
3517 | + } else { |
3518 | + mutex = &(static_cast<ib_prio_mutex_t*>( |
3519 | + cell->wait_object))->base_mutex; |
3520 | + } |
3521 | |
3522 | if (mutex_get_lock_word(mutex) == 0) { |
3523 | |
3524 | return(TRUE); |
3525 | } |
3526 | |
3527 | - } else if (cell->request_type == RW_LOCK_EX) { |
3528 | + } else if (cell->request_type == RW_LOCK_EX |
3529 | + || cell->request_type == PRIO_RW_LOCK_EX) { |
3530 | |
3531 | lock = static_cast<rw_lock_t*>(cell->wait_object); |
3532 | |
3533 | @@ -762,7 +829,8 @@ |
3534 | |
3535 | return(TRUE); |
3536 | } |
3537 | - } else if (cell->request_type == RW_LOCK_SHARED) { |
3538 | + } else if (cell->request_type == RW_LOCK_SHARED |
3539 | + || cell->request_type == PRIO_RW_LOCK_SHARED) { |
3540 | lock = static_cast<rw_lock_t*>(cell->wait_object); |
3541 | |
3542 | /* lock_word > 0 means no writer or reserved writer */ |
3543 | @@ -770,6 +838,9 @@ |
3544 | |
3545 | return(TRUE); |
3546 | } |
3547 | + } else { |
3548 | + |
3549 | + ut_error; |
3550 | } |
3551 | |
3552 | return(FALSE); |
3553 | |
3554 | === modified file 'Percona-Server/storage/innobase/sync/sync0rw.cc' |
3555 | --- Percona-Server/storage/innobase/sync/sync0rw.cc 2013-08-06 15:16:34 +0000 |
3556 | +++ Percona-Server/storage/innobase/sync/sync0rw.cc 2013-09-26 14:59:13 +0000 |
3557 | @@ -277,6 +277,41 @@ |
3558 | } |
3559 | |
3560 | /******************************************************************//** |
3561 | +Creates, or rather, initializes a priority rw-lock object in a specified memory |
3562 | +location (which must be appropriately aligned). The rw-lock is initialized |
3563 | +to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free |
3564 | +is necessary only if the memory block containing it is freed. */ |
3565 | +UNIV_INTERN |
3566 | +void |
3567 | +rw_lock_create_func( |
3568 | +/*================*/ |
3569 | + prio_rw_lock_t* lock, /*!< in: pointer to memory */ |
3570 | +#ifdef UNIV_DEBUG |
3571 | +# ifdef UNIV_SYNC_DEBUG |
3572 | + ulint level, /*!< in: level */ |
3573 | +# endif /* UNIV_SYNC_DEBUG */ |
3574 | + const char* cfile_name, /*!< in: file name where created */ |
3575 | + ulint cline, /*!< in: file line where created */ |
3576 | +#endif /* UNIV_DEBUG */ |
3577 | + const char* cmutex_name) /*!< in: mutex name */ |
3578 | +{ |
3579 | + rw_lock_create_func(&lock->base_lock, |
3580 | +#ifdef UNIV_DEBUG |
3581 | +# ifdef UNIV_SYNC_DEBUG |
3582 | + level, |
3583 | +# endif |
3584 | + cfile_name, |
3585 | + cline, |
3586 | +#endif |
3587 | + cmutex_name); |
3588 | + lock->high_priority_s_waiters = 0; |
3589 | + lock->high_priority_s_event = os_event_create(); |
3590 | + lock->high_priority_x_waiters = 0; |
3591 | + lock->high_priority_x_event = os_event_create(); |
3592 | + lock->high_priority_wait_ex_waiter = 0; |
3593 | +} |
3594 | + |
3595 | +/******************************************************************//** |
3596 | Calling this function is obligatory only if the memory buffer containing |
3597 | the rw-lock is freed. Removes an rw-lock object from the global list. The |
3598 | rw-lock is checked to be in the non-locked state. */ |
3599 | @@ -321,6 +356,21 @@ |
3600 | #endif /* !INNODB_RW_LOCKS_USE_ATOMICS */ |
3601 | } |
3602 | |
3603 | +/******************************************************************//** |
3604 | +Calling this function is obligatory only if the memory buffer containing |
3605 | +the priority rw-lock is freed. Removes an rw-lock object from the global list. |
3606 | +The rw-lock is checked to be in the non-locked state. */ |
3607 | +UNIV_INTERN |
3608 | +void |
3609 | +rw_lock_free_func( |
3610 | +/*==============*/ |
3611 | + prio_rw_lock_t* lock) /*!< in: rw-lock */ |
3612 | +{ |
3613 | + os_event_free(lock->high_priority_s_event); |
3614 | + os_event_free(lock->high_priority_x_event); |
3615 | + rw_lock_free_func(&lock->base_lock); |
3616 | +} |
3617 | + |
3618 | #ifdef UNIV_DEBUG |
3619 | /******************************************************************//** |
3620 | Checks that the rw-lock has been initialized and that there are no |
3621 | @@ -347,20 +397,41 @@ |
3622 | |
3623 | return(TRUE); |
3624 | } |
3625 | + |
3626 | +/******************************************************************//** |
3627 | +Checks that the priority rw-lock has been initialized and that there are no |
3628 | +simultaneous shared and exclusive locks. |
3629 | +@return TRUE */ |
3630 | +UNIV_INTERN |
3631 | +ibool |
3632 | +rw_lock_validate( |
3633 | +/*=============*/ |
3634 | + prio_rw_lock_t* lock) /*!< in: rw-lock */ |
3635 | +{ |
3636 | + ut_ad(lock->high_priority_s_waiters < 2); |
3637 | + ut_ad(lock->high_priority_x_waiters < 2); |
3638 | + return(rw_lock_validate(&lock->base_lock)); |
3639 | +} |
3640 | + |
3641 | #endif /* UNIV_DEBUG */ |
3642 | |
3643 | /******************************************************************//** |
3644 | -Lock an rw-lock in shared mode for the current thread. If the rw-lock is |
3645 | -locked in exclusive mode, or there is an exclusive lock request waiting, |
3646 | -the function spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting |
3647 | -for the lock, before suspending the thread. */ |
3648 | +Lock a regular or priority rw-lock in shared mode for the current thread. If |
3649 | +the rw-lock is locked in exclusive mode, or there is an exclusive lock request |
3650 | +waiting, the function spins a preset time (controlled by SYNC_SPIN_ROUNDS), |
3651 | +waiting for the lock, before suspending the thread. */ |
3652 | UNIV_INTERN |
3653 | void |
3654 | rw_lock_s_lock_spin( |
3655 | /*================*/ |
3656 | - rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
3657 | + void* _lock, /*!< in: pointer to rw-lock */ |
3658 | ulint pass, /*!< in: pass value; != 0, if the lock |
3659 | will be passed to another thread to unlock */ |
3660 | + bool priority_lock, |
3661 | + /*!< in: whether the lock is a priority lock */ |
3662 | + bool high_priority, |
3663 | + /*!< in: whether we are acquiring a priority |
3664 | + lock with high priority */ |
3665 | const char* file_name, /*!< in: file name where lock requested */ |
3666 | ulint line) /*!< in: line where requested */ |
3667 | { |
3668 | @@ -368,6 +439,7 @@ |
3669 | ulint i = 0; /* spin round count */ |
3670 | sync_array_t* sync_arr; |
3671 | size_t counter_index; |
3672 | + rw_lock_t* lock = (rw_lock_t *) _lock; |
3673 | |
3674 | /* We reuse the thread id to index into the counter, cache |
3675 | it here for efficiency. */ |
3676 | @@ -379,35 +451,47 @@ |
3677 | rw_lock_stats.rw_s_spin_wait_count.add(counter_index, 1); |
3678 | lock_loop: |
3679 | |
3680 | - /* Spin waiting for the writer field to become free */ |
3681 | - while (i < SYNC_SPIN_ROUNDS && lock->lock_word <= 0) { |
3682 | - if (srv_spin_wait_delay) { |
3683 | - ut_delay(ut_rnd_interval(0, srv_spin_wait_delay)); |
3684 | - } |
3685 | - |
3686 | - i++; |
3687 | - } |
3688 | - |
3689 | - if (i == SYNC_SPIN_ROUNDS) { |
3690 | + if (!rw_lock_higher_prio_waiters_exist(priority_lock, high_priority, |
3691 | + lock)) { |
3692 | + |
3693 | + /* Spin waiting for the writer field to become free */ |
3694 | + while (i < SYNC_SPIN_ROUNDS && lock->lock_word <= 0) { |
3695 | + if (srv_spin_wait_delay) { |
3696 | + ut_delay(ut_rnd_interval(0, |
3697 | + srv_spin_wait_delay)); |
3698 | + } |
3699 | + |
3700 | + i++; |
3701 | + } |
3702 | + |
3703 | + if (i == SYNC_SPIN_ROUNDS) { |
3704 | + os_thread_yield(); |
3705 | + } |
3706 | + |
3707 | + if (srv_print_latch_waits) { |
3708 | + fprintf(stderr, |
3709 | + "Thread " ULINTPF " spin wait rw-s-lock at %p" |
3710 | + " '%s' rnds " ULINTPF "\n", |
3711 | + os_thread_pf(os_thread_get_curr_id()), |
3712 | + (void*) lock, lock->lock_name, i); |
3713 | + } |
3714 | + } else { |
3715 | + |
3716 | + /* In case of higher priority waiters already present, perform |
3717 | + only this part of the spinning code path. */ |
3718 | os_thread_yield(); |
3719 | } |
3720 | |
3721 | - if (srv_print_latch_waits) { |
3722 | - fprintf(stderr, |
3723 | - "Thread " ULINTPF " spin wait rw-s-lock at %p" |
3724 | - " '%s' rnds " ULINTPF "\n", |
3725 | - os_thread_pf(os_thread_get_curr_id()), |
3726 | - (void*) lock, lock->lock_name, i); |
3727 | - } |
3728 | - |
3729 | /* We try once again to obtain the lock */ |
3730 | - if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) { |
3731 | + if (!rw_lock_higher_prio_waiters_exist(priority_lock, high_priority, |
3732 | + lock) |
3733 | + && (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line))) { |
3734 | rw_lock_stats.rw_s_spin_round_count.add(counter_index, i); |
3735 | |
3736 | return; /* Success */ |
3737 | } else { |
3738 | |
3739 | - if (i < SYNC_SPIN_ROUNDS) { |
3740 | + if (i > 0 && i < SYNC_SPIN_ROUNDS) { |
3741 | goto lock_loop; |
3742 | } |
3743 | |
3744 | @@ -416,14 +500,24 @@ |
3745 | sync_arr = sync_array_get(); |
3746 | |
3747 | sync_array_reserve_cell( |
3748 | - sync_arr, lock, RW_LOCK_SHARED, |
3749 | + sync_arr, lock, |
3750 | + high_priority ? PRIO_RW_LOCK_SHARED : RW_LOCK_SHARED, |
3751 | file_name, line, &index); |
3752 | |
3753 | /* Set waiters before checking lock_word to ensure wake-up |
3754 | signal is sent. This may lead to some unnecessary signals. */ |
3755 | - rw_lock_set_waiter_flag(lock); |
3756 | + if (high_priority) { |
3757 | + prio_rw_lock_t* prio_rw_lock |
3758 | + = (prio_rw_lock_t *) _lock; |
3759 | + prio_rw_lock->high_priority_s_waiters = 1; |
3760 | + } else { |
3761 | + rw_lock_set_waiter_flag(lock); |
3762 | + } |
3763 | |
3764 | - if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) { |
3765 | + if (!rw_lock_higher_prio_waiters_exist(priority_lock, |
3766 | + high_priority, lock) |
3767 | + && (TRUE == rw_lock_s_lock_low(lock, pass, |
3768 | + file_name, line))) { |
3769 | sync_array_free_cell(sync_arr, index); |
3770 | return; /* Success */ |
3771 | } |
3772 | @@ -618,7 +712,12 @@ |
3773 | ulint pass, /*!< in: pass value; != 0, if the lock will |
3774 | be passed to another thread to unlock */ |
3775 | const char* file_name,/*!< in: file name where lock requested */ |
3776 | - ulint line) /*!< in: line where requested */ |
3777 | + ulint line, /*!< in: line where requested */ |
3778 | + bool priority_lock, |
3779 | + /*!< in: whether the lock is a priority lock */ |
3780 | + bool high_priority) |
3781 | + /*!< in: whether we are acquiring a priority |
3782 | + lock with high priority */ |
3783 | { |
3784 | ulint i; /*!< spin round count */ |
3785 | ulint index; /*!< index of the reserved wait cell */ |
3786 | @@ -640,12 +739,15 @@ |
3787 | |
3788 | lock_loop: |
3789 | |
3790 | - if (rw_lock_x_lock_low(lock, pass, file_name, line)) { |
3791 | + if (!rw_lock_higher_prio_waiters_exist(priority_lock, high_priority, |
3792 | + lock) |
3793 | + && rw_lock_x_lock_low(lock, pass, file_name, line)) { |
3794 | rw_lock_stats.rw_x_spin_round_count.add(counter_index, i); |
3795 | |
3796 | return; /* Locking succeeded */ |
3797 | |
3798 | - } else { |
3799 | + } else if (!rw_lock_higher_prio_waiters_exist(priority_lock, |
3800 | + high_priority, lock)) { |
3801 | |
3802 | if (!spinning) { |
3803 | spinning = TRUE; |
3804 | @@ -669,26 +771,42 @@ |
3805 | } else { |
3806 | goto lock_loop; |
3807 | } |
3808 | + } else { |
3809 | + |
3810 | + /* In case we skipped spinning because of higher-priority |
3811 | + waiters already waiting, perform only this bit of the spinning |
3812 | + code path. */ |
3813 | + os_thread_yield(); |
3814 | } |
3815 | |
3816 | - rw_lock_stats.rw_x_spin_round_count.add(counter_index, i); |
3817 | - |
3818 | - if (srv_print_latch_waits) { |
3819 | - fprintf(stderr, |
3820 | - "Thread " ULINTPF " spin wait rw-x-lock at %p" |
3821 | - " '%s' rnds " ULINTPF "\n", |
3822 | - os_thread_pf(os_thread_get_curr_id()), (void*) lock, |
3823 | - lock->lock_name, i); |
3824 | + if (spinning) { |
3825 | + |
3826 | + rw_lock_stats.rw_x_spin_round_count.add(counter_index, i); |
3827 | + |
3828 | + if (srv_print_latch_waits) { |
3829 | + fprintf(stderr, |
3830 | + "Thread " ULINTPF " spin wait rw-x-lock at %p" |
3831 | + " '%s' rnds " ULINTPF "\n", |
3832 | + os_thread_pf(os_thread_get_curr_id()), |
3833 | + (void*) lock,lock->lock_name, i); |
3834 | + } |
3835 | } |
3836 | |
3837 | sync_arr = sync_array_get(); |
3838 | |
3839 | sync_array_reserve_cell( |
3840 | - sync_arr, lock, RW_LOCK_EX, file_name, line, &index); |
3841 | + sync_arr, lock, |
3842 | + high_priority ? PRIO_RW_LOCK_EX : RW_LOCK_EX, |
3843 | + file_name, line, &index); |
3844 | |
3845 | /* Waiters must be set before checking lock_word, to ensure signal |
3846 | is sent. This could lead to a few unnecessary wake-up signals. */ |
3847 | - rw_lock_set_waiter_flag(lock); |
3848 | + if (high_priority) { |
3849 | + prio_rw_lock_t* prio_lock = (prio_rw_lock_t *)lock; |
3850 | + prio_lock->high_priority_x_waiters = 1; |
3851 | + } else { |
3852 | + rw_lock_set_waiter_flag(lock); |
3853 | + } |
3854 | |
3855 | if (rw_lock_x_lock_low(lock, pass, file_name, line)) { |
3856 | sync_array_free_cell(sync_arr, index); |
3857 | @@ -713,6 +831,29 @@ |
3858 | goto lock_loop; |
3859 | } |
3860 | |
3861 | +/******************************************************************//** |
3862 | +NOTE! Use the corresponding macro, not directly this function! Lock a priority |
3863 | +rw-lock in exclusive mode for the current thread. If the rw-lock is locked |
3864 | +in shared or exclusive mode, or there is an exclusive lock request waiting, |
3865 | +the function spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting |
3866 | +for the lock, before suspending the thread. If the same thread has an x-lock |
3867 | +on the rw-lock, locking succeed, with the following exception: if pass != 0, |
3868 | +only a single x-lock may be taken on the lock. NOTE: If the same thread has |
3869 | +an s-lock, locking does not succeed! */ |
3870 | +UNIV_INTERN |
3871 | +void |
3872 | +rw_lock_x_lock_func( |
3873 | +/*================*/ |
3874 | + prio_rw_lock_t* lock, /*!< in: pointer to rw-lock */ |
3875 | + ulint pass, /*!< in: pass value; != 0, if the lock will |
3876 | + be passed to another thread to unlock */ |
3877 | + const char* file_name,/*!< in: file name where lock requested */ |
3878 | + ulint line) /*!< in: line where requested */ |
3879 | +{ |
3880 | + rw_lock_x_lock_func(&lock->base_lock, pass, file_name, line, true, |
3881 | + srv_current_thread_priority > 0); |
3882 | +} |
3883 | + |
3884 | #ifdef UNIV_SYNC_DEBUG |
3885 | /******************************************************************//** |
3886 | Acquires the debug mutex. We cannot use the mutex defined in sync0sync, |
3887 | @@ -881,6 +1022,21 @@ |
3888 | |
3889 | return(FALSE); |
3890 | } |
3891 | + |
3892 | +/******************************************************************//** |
3893 | +Checks if the thread has locked the priority rw-lock in the specified mode, |
3894 | +with the pass value == 0. */ |
3895 | +UNIV_INTERN |
3896 | +ibool |
3897 | +rw_lock_own( |
3898 | +/*========*/ |
3899 | + prio_rw_lock_t* lock, /*!< in: rw-lock */ |
3900 | + ulint lock_type) /*!< in: lock type: RW_LOCK_SHARED, |
3901 | + RW_LOCK_EX */ |
3902 | +{ |
3903 | + return(rw_lock_own(&lock->base_lock, lock_type)); |
3904 | +} |
3905 | + |
3906 | #endif /* UNIV_SYNC_DEBUG */ |
3907 | |
3908 | /******************************************************************//** |
3909 | |
3910 | === modified file 'Percona-Server/storage/innobase/sync/sync0sync.cc' |
3911 | --- Percona-Server/storage/innobase/sync/sync0sync.cc 2013-09-20 05:27:28 +0000 |
3912 | +++ Percona-Server/storage/innobase/sync/sync0sync.cc 2013-09-26 14:59:13 +0000 |
3913 | @@ -321,6 +321,40 @@ |
3914 | } |
3915 | |
3916 | /******************************************************************//** |
3917 | +Creates, or rather, initializes a priority mutex object in a specified memory |
3918 | +location (which must be appropriately aligned). The mutex is initialized |
3919 | +in the reset state. Explicit freeing of the mutex with mutex_free is |
3920 | +necessary only if the memory block containing it is freed. */ |
3921 | +UNIV_INTERN |
3922 | +void |
3923 | +mutex_create_func( |
3924 | +/*==============*/ |
3925 | + ib_prio_mutex_t* mutex, /*!< in: pointer to memory */ |
3926 | +#ifdef UNIV_DEBUG |
3927 | +# ifdef UNIV_SYNC_DEBUG |
3928 | + ulint level, /*!< in: level */ |
3929 | +# endif /* UNIV_SYNC_DEBUG */ |
3930 | + const char* cfile_name, /*!< in: file name where |
3931 | + created */ |
3932 | + ulint cline, /*!< in: file line where |
3933 | + created */ |
3934 | +#endif /* UNIV_DEBUG */ |
3935 | + const char* cmutex_name) /*!< in: mutex name */ |
3936 | +{ |
3937 | + mutex_create_func(&mutex->base_mutex, |
3938 | +#ifdef UNIV_DEBUG |
3939 | +# ifdef UNIV_SYNC_DEBUG |
3940 | + level, |
3941 | +#endif /* UNIV_SYNC_DEBUG */ |
3942 | + cfile_name, |
3943 | + cline, |
3944 | +#endif /* UNIV_DEBUG */ |
3945 | + cmutex_name); |
3946 | + mutex->high_priority_waiters = 0; |
3947 | + mutex->high_priority_event = os_event_create(); |
3948 | +} |
3949 | + |
3950 | +/******************************************************************//** |
3951 | NOTE! Use the corresponding macro mutex_free(), not directly this function! |
3952 | Calling this function is obligatory only if the memory buffer containing |
3953 | the mutex is freed. Removes a mutex object from the mutex list. The mutex |
3954 | @@ -380,6 +414,22 @@ |
3955 | return; |
3956 | } |
3957 | |
3958 | +/******************************************************************//** |
3959 | +NOTE! Use the corresponding macro mutex_free(), not directly this function! |
3960 | +Calling this function is obligatory only if the memory buffer containing |
3961 | +the mutex is freed. Removes a priority mutex object from the mutex list. The |
3962 | +mutex is checked to be in the reset state. */ |
3963 | +UNIV_INTERN |
3964 | +void |
3965 | +mutex_free_func( |
3966 | +/*============*/ |
3967 | + ib_prio_mutex_t* mutex) /*!< in: mutex */ |
3968 | +{ |
3969 | + ut_a(mutex->high_priority_waiters == 0); |
3970 | + os_event_free(mutex->high_priority_event); |
3971 | + mutex_free_func(&mutex->base_mutex); |
3972 | +} |
3973 | + |
3974 | /********************************************************************//** |
3975 | NOTE! Use the corresponding macro in the header file, not this function |
3976 | directly. Tries to lock the mutex for the current thread. If the lock is not |
3977 | @@ -442,6 +492,20 @@ |
3978 | return(mutex_get_lock_word(mutex) == 1 |
3979 | && os_thread_eq(mutex->thread_id, os_thread_get_curr_id())); |
3980 | } |
3981 | + |
3982 | +/******************************************************************//** |
3983 | +Checks that the current thread owns the priority mutex. Works only |
3984 | +in the debug version. |
3985 | +@return TRUE if owns */ |
3986 | +UNIV_INTERN |
3987 | +ibool |
3988 | +mutex_own( |
3989 | +/*======*/ |
3990 | + const ib_prio_mutex_t* mutex) /*!< in: priority mutex */ |
3991 | +{ |
3992 | + return mutex_own(&mutex->base_mutex); |
3993 | +} |
3994 | + |
3995 | #endif /* UNIV_DEBUG */ |
3996 | |
3997 | /******************************************************************//** |
3998 | @@ -464,14 +528,17 @@ |
3999 | } |
4000 | |
4001 | /******************************************************************//** |
4002 | -Reserves a mutex for the current thread. If the mutex is reserved, the |
4003 | -function spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting |
4004 | -for the mutex before suspending the thread. */ |
4005 | +Reserves a mutex or a priority mutex for the current thread. If the mutex is |
4006 | +reserved, the function spins a preset time (controlled by SYNC_SPIN_ROUNDS), |
4007 | +waiting for the mutex before suspending the thread. */ |
4008 | UNIV_INTERN |
4009 | void |
4010 | mutex_spin_wait( |
4011 | /*============*/ |
4012 | - ib_mutex_t* mutex, /*!< in: pointer to mutex */ |
4013 | + void* _mutex, /*!< in: pointer to mutex */ |
4014 | + bool high_priority, /*!< in: whether the mutex is a |
4015 | + priority mutex with high priority |
4016 | + specified */ |
4017 | const char* file_name, /*!< in: file name where mutex |
4018 | requested */ |
4019 | ulint line) /*!< in: line where requested */ |
4020 | @@ -480,6 +547,10 @@ |
4021 | ulint index; /* index of the reserved wait cell */ |
4022 | sync_array_t* sync_arr; |
4023 | size_t counter_index; |
4024 | + /* The typecast below is performed for some of the priority mutexes |
4025 | + too, when !high_priority. This exploits the fact that regular mutex is |
4026 | + a prefix of the priority mutex in memory. */ |
4027 | + ib_mutex_t* mutex = (ib_mutex_t *) _mutex; |
4028 | |
4029 | counter_index = (size_t) os_thread_get_curr_id(); |
4030 | |
4031 | @@ -543,7 +614,8 @@ |
4032 | sync_arr = sync_array_get(); |
4033 | |
4034 | sync_array_reserve_cell( |
4035 | - sync_arr, mutex, SYNC_MUTEX, file_name, line, &index); |
4036 | + sync_arr, mutex, high_priority ? SYNC_PRIO_MUTEX : SYNC_MUTEX, |
4037 | + file_name, line, &index); |
4038 | |
4039 | /* The memory order of the array reservation and the change in the |
4040 | waiters field is important: when we suspend a thread, we first |
4041 | @@ -551,7 +623,11 @@ |
4042 | released in mutex_exit, the waiters field is first set to zero and |
4043 | then the event is set to the signaled state. */ |
4044 | |
4045 | - mutex_set_waiters(mutex, 1); |
4046 | + if (high_priority) { |
4047 | + ((ib_prio_mutex_t *)_mutex)->high_priority_waiters = 1; |
4048 | + } else { |
4049 | + mutex_set_waiters(mutex, 1); |
4050 | + } |
4051 | |
4052 | /* Try to reserve still a few times */ |
4053 | for (i = 0; i < 4; i++) { |
Just make it Linux-specific for now, i.e. so that the system variables only appear in UNIV_LINUX builds, and srv_current_ thread_ priority is #define'd to 0 otherwise.
Making it truly portable is more complex than just #ifdef __GNUC__, and I will address it later.
But I also don't like reviewing this change in isolation. Please resubmit with the code that actually makes use of srv_current_ thread_ priority.