~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/include/sync0rw.h

  • Committer: Brian Aker
  • Date: 2010-07-30 20:31:19 UTC
  • mto: This revision was merged to the branch mainline in revision 1679.
  • Revision ID: brian@gaz-20100730203119-89g2ye4zwnvcacxg
First pass in encapsulating row

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************************************************************************
2
 
 
3
 
Copyright (C) 1995, 2010, Innobase Oy. All Rights Reserved.
4
 
Copyright (C) 2008, Google Inc.
5
 
 
6
 
Portions of this file contain modifications contributed and copyrighted by
7
 
Google, Inc. Those modifications are gratefully acknowledged and are described
8
 
briefly in the InnoDB documentation. The contributions by Google are
9
 
incorporated with their permission, and subject to the conditions contained in
10
 
the file COPYING.Google.
11
 
 
12
 
This program is free software; you can redistribute it and/or modify it under
13
 
the terms of the GNU General Public License as published by the Free Software
14
 
Foundation; version 2 of the License.
15
 
 
16
 
This program is distributed in the hope that it will be useful, but WITHOUT
17
 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
 
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19
 
 
20
 
You should have received a copy of the GNU General Public License along with
21
 
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
22
 
St, Fifth Floor, Boston, MA 02110-1301 USA
23
 
 
24
 
*****************************************************************************/
25
 
 
26
 
/**************************************************//**
27
 
@file include/sync0rw.h
28
 
The read-write lock (for threads, not for database transactions)
29
 
 
30
 
Created 9/11/1995 Heikki Tuuri
31
 
*******************************************************/
32
 
 
33
 
#ifndef sync0rw_h
34
 
#define sync0rw_h
35
 
 
36
 
#include "univ.i"
37
 
#ifndef UNIV_HOTBACKUP
38
 
#include "ut0lst.h"
39
 
#include "sync0sync.h"
40
 
#include "os0sync.h"
41
 
 
42
 
/* The following undef is to prevent a name conflict with a macro
43
 
in MySQL: */
44
 
#undef rw_lock_t
45
 
#endif /* !UNIV_HOTBACKUP */
46
 
 
47
 
/* Latch types; these are used also in btr0btr.h: keep the numerical values
48
 
smaller than 30 and the order of the numerical values like below! */
49
 
#define RW_S_LATCH      1
50
 
#define RW_X_LATCH      2
51
 
#define RW_NO_LATCH     3
52
 
 
53
 
#ifndef UNIV_HOTBACKUP
54
 
/* We decrement lock_word by this amount for each x_lock. It is also the
55
 
start value for the lock_word, meaning that it limits the maximum number
56
 
of concurrent read locks before the rw_lock breaks. The current value of
57
 
0x00100000 allows 1,048,575 concurrent readers and 2047 recursive writers.*/
58
 
#define X_LOCK_DECR             0x00100000
59
 
 
60
 
typedef struct rw_lock_struct           rw_lock_t;
61
 
#ifdef UNIV_SYNC_DEBUG
62
 
typedef struct rw_lock_debug_struct     rw_lock_debug_t;
63
 
#endif /* UNIV_SYNC_DEBUG */
64
 
 
65
 
typedef UT_LIST_BASE_NODE_T(rw_lock_t)  rw_lock_list_t;
66
 
 
67
 
extern rw_lock_list_t   rw_lock_list;
68
 
extern mutex_t          rw_lock_list_mutex;
69
 
 
70
 
#ifdef UNIV_SYNC_DEBUG
71
 
/* The global mutex which protects debug info lists of all rw-locks.
72
 
To modify the debug info list of an rw-lock, this mutex has to be
73
 
 
74
 
acquired in addition to the mutex protecting the lock. */
75
 
extern mutex_t          rw_lock_debug_mutex;
76
 
extern os_event_t       rw_lock_debug_event;    /*!< If deadlock detection does
77
 
                                        not get immediately the mutex it
78
 
                                        may wait for this event */
79
 
extern ibool            rw_lock_debug_waiters;  /*!< This is set to TRUE, if
80
 
                                        there may be waiters for the event */
81
 
#endif /* UNIV_SYNC_DEBUG */
82
 
 
83
 
/** number of spin waits on rw-latches,
84
 
resulted during exclusive (write) locks */
85
 
extern  ib_int64_t      rw_s_spin_wait_count;
86
 
/** number of spin loop rounds on rw-latches,
87
 
resulted during exclusive (write) locks */
88
 
extern  ib_int64_t      rw_s_spin_round_count;
89
 
/** number of unlocks (that unlock shared locks),
90
 
set only when UNIV_SYNC_PERF_STAT is defined */
91
 
extern  ib_int64_t      rw_s_exit_count;
92
 
/** number of OS waits on rw-latches,
93
 
resulted during shared (read) locks */
94
 
extern  ib_int64_t      rw_s_os_wait_count;
95
 
/** number of spin waits on rw-latches,
96
 
resulted during shared (read) locks */
97
 
extern  ib_int64_t      rw_x_spin_wait_count;
98
 
/** number of spin loop rounds on rw-latches,
99
 
resulted during shared (read) locks */
100
 
extern  ib_int64_t      rw_x_spin_round_count;
101
 
/** number of OS waits on rw-latches,
102
 
resulted during exclusive (write) locks */
103
 
extern  ib_int64_t      rw_x_os_wait_count;
104
 
/** number of unlocks (that unlock exclusive locks),
105
 
set only when UNIV_SYNC_PERF_STAT is defined */
106
 
extern  ib_int64_t      rw_x_exit_count;
107
 
 
108
 
#ifdef UNIV_PFS_RWLOCK
109
 
/* Following are rwlock keys used to register with MySQL
110
 
performance schema */
111
 
# ifdef UNIV_LOG_ARCHIVE
112
 
extern  mysql_pfs_key_t archive_lock_key;
113
 
# endif /* UNIV_LOG_ARCHIVE */
114
 
extern  mysql_pfs_key_t btr_search_latch_key;
115
 
extern  mysql_pfs_key_t buf_block_lock_key;
116
 
# ifdef UNIV_SYNC_DEBUG
117
 
extern  mysql_pfs_key_t buf_block_debug_latch_key;
118
 
# endif /* UNIV_SYNC_DEBUG */
119
 
extern  mysql_pfs_key_t dict_operation_lock_key;
120
 
extern  mysql_pfs_key_t fil_space_latch_key;
121
 
extern  mysql_pfs_key_t checkpoint_lock_key;
122
 
extern  mysql_pfs_key_t trx_i_s_cache_lock_key;
123
 
extern  mysql_pfs_key_t trx_purge_latch_key;
124
 
extern  mysql_pfs_key_t index_tree_rw_lock_key;
125
 
#endif /* UNIV_PFS_RWLOCK */
126
 
 
127
 
 
128
 
#ifndef UNIV_PFS_RWLOCK
129
 
/******************************************************************//**
130
 
Creates, or rather, initializes an rw-lock object in a specified memory
131
 
location (which must be appropriately aligned). The rw-lock is initialized
132
 
to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free
133
 
is necessary only if the memory block containing it is freed.
134
 
if MySQL performance schema is enabled and "UNIV_PFS_RWLOCK" is
135
 
defined, the rwlock are instrumented with performance schema probes. */
136
 
# ifdef UNIV_DEBUG
137
 
#  ifdef UNIV_SYNC_DEBUG
138
 
#   define rw_lock_create(K, L, level)                          \
139
 
        rw_lock_create_func((L), (level), #L, __FILE__, __LINE__)
140
 
#  else /* UNIV_SYNC_DEBUG */
141
 
#   define rw_lock_create(K, L, level)                          \
142
 
        rw_lock_create_func((L), #L, __FILE__, __LINE__)
143
 
#  endif/* UNIV_SYNC_DEBUG */
144
 
# else /* UNIV_DEBUG */
145
 
#  define rw_lock_create(K, L, level)                           \
146
 
        rw_lock_create_func((L), __FILE__, __LINE__)
147
 
# endif /* UNIV_DEBUG */
148
 
 
149
 
/**************************************************************//**
150
 
NOTE! The following macros should be used in rw locking and
151
 
unlocking, not the corresponding function. */
152
 
 
153
 
# define rw_lock_s_lock(M)                                      \
154
 
        rw_lock_s_lock_func((M), 0, __FILE__, __LINE__)
155
 
 
156
 
# define rw_lock_s_lock_gen(M, P)                               \
157
 
        rw_lock_s_lock_func((M), (P), __FILE__, __LINE__)
158
 
 
159
 
# define rw_lock_s_lock_nowait(M, F, L)                         \
160
 
        rw_lock_s_lock_low((M), 0, (F), (L))
161
 
 
162
 
# ifdef UNIV_SYNC_DEBUG
163
 
#  define rw_lock_s_unlock_gen(L, P)    rw_lock_s_unlock_func(P, L)
164
 
# else
165
 
#  define rw_lock_s_unlock_gen(L, P)    rw_lock_s_unlock_func(L)
166
 
# endif
167
 
 
168
 
 
169
 
# define rw_lock_x_lock(M)                                      \
170
 
        rw_lock_x_lock_func((M), 0, __FILE__, __LINE__)
171
 
 
172
 
# define rw_lock_x_lock_gen(M, P)                               \
173
 
        rw_lock_x_lock_func((M), (P), __FILE__, __LINE__)
174
 
 
175
 
# define rw_lock_x_lock_nowait(M)                               \
176
 
        rw_lock_x_lock_func_nowait((M), __FILE__, __LINE__)
177
 
 
178
 
# ifdef UNIV_SYNC_DEBUG
179
 
#  define rw_lock_x_unlock_gen(L, P)    rw_lock_x_unlock_func(P, L)
180
 
# else
181
 
#  define rw_lock_x_unlock_gen(L, P)    rw_lock_x_unlock_func(L)
182
 
# endif
183
 
 
184
 
# define rw_lock_free(M)                rw_lock_free_func(M)
185
 
 
186
 
#else /* !UNIV_PFS_RWLOCK */
187
 
 
188
 
/* Following macros point to Performance Schema instrumented functions. */
189
 
# ifdef UNIV_DEBUG
190
 
#  ifdef UNIV_SYNC_DEBUG
191
 
#   define rw_lock_create(K, L, level)                          \
192
 
        pfs_rw_lock_create_func((K), (L), (level), #L, __FILE__, __LINE__)
193
 
#  else /* UNIV_SYNC_DEBUG */
194
 
#   define rw_lock_create(K, L, level)                          \
195
 
        pfs_rw_lock_create_func((K), (L), #L, __FILE__, __LINE__)
196
 
#  endif/* UNIV_SYNC_DEBUG */
197
 
# else  /* UNIV_DEBUG */
198
 
#  define rw_lock_create(K, L, level)                           \
199
 
        pfs_rw_lock_create_func((K), (L), __FILE__, __LINE__)
200
 
# endif /* UNIV_DEBUG */
201
 
 
202
 
/******************************************************************
203
 
NOTE! The following macros should be used in rw locking and
204
 
unlocking, not the corresponding function. */
205
 
 
206
 
# define rw_lock_s_lock(M)                                      \
207
 
        pfs_rw_lock_s_lock_func((M), 0, __FILE__, __LINE__)
208
 
 
209
 
# define rw_lock_s_lock_gen(M, P)                               \
210
 
        pfs_rw_lock_s_lock_func((M), (P), __FILE__, __LINE__)
211
 
 
212
 
# define rw_lock_s_lock_nowait(M, F, L)                         \
213
 
        pfs_rw_lock_s_lock_low((M), 0, (F), (L))
214
 
 
215
 
# ifdef UNIV_SYNC_DEBUG
216
 
#  define rw_lock_s_unlock_gen(L, P)    pfs_rw_lock_s_unlock_func(P, L)
217
 
# else
218
 
#  define rw_lock_s_unlock_gen(L, P)    pfs_rw_lock_s_unlock_func(L)
219
 
# endif
220
 
 
221
 
# define rw_lock_x_lock(M)                                      \
222
 
        pfs_rw_lock_x_lock_func((M), 0, __FILE__, __LINE__)
223
 
 
224
 
# define rw_lock_x_lock_gen(M, P)                               \
225
 
        pfs_rw_lock_x_lock_func((M), (P), __FILE__, __LINE__)
226
 
 
227
 
# define rw_lock_x_lock_nowait(M)                               \
228
 
        pfs_rw_lock_x_lock_func_nowait((M), __FILE__, __LINE__)
229
 
 
230
 
# ifdef UNIV_SYNC_DEBUG
231
 
#  define rw_lock_x_unlock_gen(L, P)    pfs_rw_lock_x_unlock_func(P, L)
232
 
# else
233
 
#  define rw_lock_x_unlock_gen(L, P)    pfs_rw_lock_x_unlock_func(L)
234
 
# endif
235
 
 
236
 
# define rw_lock_free(M)                pfs_rw_lock_free_func(M)
237
 
 
238
 
#endif /* UNIV_PFS_RWLOCK */
239
 
 
240
 
#define rw_lock_s_unlock(L)             rw_lock_s_unlock_gen(L, 0)
241
 
#define rw_lock_x_unlock(L)             rw_lock_x_unlock_gen(L, 0)
242
 
 
243
 
/******************************************************************//**
244
 
Creates, or rather, initializes an rw-lock object in a specified memory
245
 
location (which must be appropriately aligned). The rw-lock is initialized
246
 
to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free
247
 
is necessary only if the memory block containing it is freed. */
248
 
UNIV_INTERN
249
 
void
250
 
rw_lock_create_func(
251
 
/*================*/
252
 
        rw_lock_t*      lock,           /*!< in: pointer to memory */
253
 
#ifdef UNIV_DEBUG
254
 
# ifdef UNIV_SYNC_DEBUG
255
 
        ulint           level,          /*!< in: level */
256
 
# endif /* UNIV_SYNC_DEBUG */
257
 
        const char*     cmutex_name,    /*!< in: mutex name */
258
 
#endif /* UNIV_DEBUG */
259
 
        const char*     cfile_name,     /*!< in: file name where created */
260
 
        ulint           cline);         /*!< in: file line where created */
261
 
/******************************************************************//**
262
 
Calling this function is obligatory only if the memory buffer containing
263
 
the rw-lock is freed. Removes an rw-lock object from the global list. The
264
 
rw-lock is checked to be in the non-locked state. */
265
 
UNIV_INTERN
266
 
void
267
 
rw_lock_free_func(
268
 
/*==============*/
269
 
        rw_lock_t*      lock);  /*!< in: rw-lock */
270
 
#ifdef UNIV_DEBUG
271
 
/******************************************************************//**
272
 
Checks that the rw-lock has been initialized and that there are no
273
 
simultaneous shared and exclusive locks.
274
 
@return TRUE */
275
 
UNIV_INTERN
276
 
ibool
277
 
rw_lock_validate(
278
 
/*=============*/
279
 
        rw_lock_t*      lock);  /*!< in: rw-lock */
280
 
#endif /* UNIV_DEBUG */
281
 
/******************************************************************//**
282
 
Low-level function which tries to lock an rw-lock in s-mode. Performs no
283
 
spinning.
284
 
@return TRUE if success */
285
 
UNIV_INLINE
286
 
ibool
287
 
rw_lock_s_lock_low(
288
 
/*===============*/
289
 
        rw_lock_t*      lock,   /*!< in: pointer to rw-lock */
290
 
        ulint           /*pass __attribute__((unused))*/,
291
 
                                /*!< in: pass value; != 0, if the lock will be
292
 
                                passed to another thread to unlock */
293
 
        const char*     file_name, /*!< in: file name where lock requested */
294
 
        ulint           line);  /*!< in: line where requested */
295
 
/******************************************************************//**
296
 
NOTE! Use the corresponding macro, not directly this function, except if
297
 
you supply the file name and line number. Lock an rw-lock in shared mode
298
 
for the current thread. If the rw-lock is locked in exclusive mode, or
299
 
there is an exclusive lock request waiting, the function spins a preset
300
 
time (controlled by SYNC_SPIN_ROUNDS), waiting for the lock, before
301
 
suspending the thread. */
302
 
UNIV_INLINE
303
 
void
304
 
rw_lock_s_lock_func(
305
 
/*================*/
306
 
        rw_lock_t*      lock,   /*!< in: pointer to rw-lock */
307
 
        ulint           pass,   /*!< in: pass value; != 0, if the lock will
308
 
                                be passed to another thread to unlock */
309
 
        const char*     file_name,/*!< in: file name where lock requested */
310
 
        ulint           line);  /*!< in: line where requested */
311
 
/******************************************************************//**
312
 
NOTE! Use the corresponding macro, not directly this function! Lock an
313
 
rw-lock in exclusive mode for the current thread if the lock can be
314
 
obtained immediately.
315
 
@return TRUE if success */
316
 
UNIV_INLINE
317
 
ibool
318
 
rw_lock_x_lock_func_nowait(
319
 
/*=======================*/
320
 
        rw_lock_t*      lock,   /*!< in: pointer to rw-lock */
321
 
        const char*     file_name,/*!< in: file name where lock requested */
322
 
        ulint           line);  /*!< in: line where requested */
323
 
/******************************************************************//**
324
 
Releases a shared mode lock. */
325
 
UNIV_INLINE
326
 
void
327
 
rw_lock_s_unlock_func(
328
 
/*==================*/
329
 
#ifdef UNIV_SYNC_DEBUG
330
 
        ulint           pass,   /*!< in: pass value; != 0, if the lock may have
331
 
                                been passed to another thread to unlock */
332
 
#endif
333
 
        rw_lock_t*      lock);  /*!< in/out: rw-lock */
334
 
 
335
 
/******************************************************************//**
336
 
NOTE! Use the corresponding macro, not directly this function! Lock an
337
 
rw-lock in exclusive mode for the current thread. If the rw-lock is locked
338
 
in shared or exclusive mode, or there is an exclusive lock request waiting,
339
 
the function spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting
340
 
for the lock, before suspending the thread. If the same thread has an x-lock
341
 
on the rw-lock, locking succeed, with the following exception: if pass != 0,
342
 
only a single x-lock may be taken on the lock. NOTE: If the same thread has
343
 
an s-lock, locking does not succeed! */
344
 
UNIV_INTERN
345
 
void
346
 
rw_lock_x_lock_func(
347
 
/*================*/
348
 
        rw_lock_t*      lock,   /*!< in: pointer to rw-lock */
349
 
        ulint           pass,   /*!< in: pass value; != 0, if the lock will
350
 
                                be passed to another thread to unlock */
351
 
        const char*     file_name,/*!< in: file name where lock requested */
352
 
        ulint           line);  /*!< in: line where requested */
353
 
/******************************************************************//**
354
 
Releases an exclusive mode lock. */
355
 
UNIV_INLINE
356
 
void
357
 
rw_lock_x_unlock_func(
358
 
/*==================*/
359
 
#ifdef UNIV_SYNC_DEBUG
360
 
        ulint           pass,   /*!< in: pass value; != 0, if the lock may have
361
 
                                been passed to another thread to unlock */
362
 
#endif
363
 
        rw_lock_t*      lock);  /*!< in/out: rw-lock */
364
 
 
365
 
 
366
 
/******************************************************************//**
367
 
Low-level function which locks an rw-lock in s-mode when we know that it
368
 
is possible and none else is currently accessing the rw-lock structure.
369
 
Then we can do the locking without reserving the mutex. */
370
 
UNIV_INLINE
371
 
void
372
 
rw_lock_s_lock_direct(
373
 
/*==================*/
374
 
        rw_lock_t*      lock,           /*!< in/out: rw-lock */
375
 
        const char*     file_name,      /*!< in: file name where requested */
376
 
        ulint           line);          /*!< in: line where lock requested */
377
 
/******************************************************************//**
378
 
Low-level function which locks an rw-lock in x-mode when we know that it
379
 
is not locked and none else is currently accessing the rw-lock structure.
380
 
Then we can do the locking without reserving the mutex. */
381
 
UNIV_INLINE
382
 
void
383
 
rw_lock_x_lock_direct(
384
 
/*==================*/
385
 
        rw_lock_t*      lock,           /*!< in/out: rw-lock */
386
 
        const char*     file_name,      /*!< in: file name where requested */
387
 
        ulint           line);          /*!< in: line where lock requested */
388
 
/******************************************************************//**
389
 
This function is used in the insert buffer to move the ownership of an
390
 
x-latch on a buffer frame to the current thread. The x-latch was set by
391
 
the buffer read operation and it protected the buffer frame while the
392
 
read was done. The ownership is moved because we want that the current
393
 
thread is able to acquire a second x-latch which is stored in an mtr.
394
 
This, in turn, is needed to pass the debug checks of index page
395
 
operations. */
396
 
UNIV_INTERN
397
 
void
398
 
rw_lock_x_lock_move_ownership(
399
 
/*==========================*/
400
 
        rw_lock_t*      lock);  /*!< in: lock which was x-locked in the
401
 
                                buffer read */
402
 
/******************************************************************//**
403
 
Releases a shared mode lock when we know there are no waiters and none
404
 
else will access the lock during the time this function is executed. */
405
 
UNIV_INLINE
406
 
void
407
 
rw_lock_s_unlock_direct(
408
 
/*====================*/
409
 
        rw_lock_t*      lock);  /*!< in/out: rw-lock */
410
 
/******************************************************************//**
411
 
Releases an exclusive mode lock when we know there are no waiters, and
412
 
none else will access the lock durint the time this function is executed. */
413
 
UNIV_INLINE
414
 
void
415
 
rw_lock_x_unlock_direct(
416
 
/*====================*/
417
 
        rw_lock_t*      lock);  /*!< in/out: rw-lock */
418
 
/******************************************************************//**
419
 
Returns the value of writer_count for the lock. Does not reserve the lock
420
 
mutex, so the caller must be sure it is not changed during the call.
421
 
@return value of writer_count */
422
 
UNIV_INLINE
423
 
ulint
424
 
rw_lock_get_x_lock_count(
425
 
/*=====================*/
426
 
        const rw_lock_t*        lock);  /*!< in: rw-lock */
427
 
/********************************************************************//**
428
 
Check if there are threads waiting for the rw-lock.
429
 
@return 1 if waiters, 0 otherwise */
430
 
UNIV_INLINE
431
 
ulint
432
 
rw_lock_get_waiters(
433
 
/*================*/
434
 
        const rw_lock_t*        lock);  /*!< in: rw-lock */
435
 
/******************************************************************//**
436
 
Returns the write-status of the lock - this function made more sense
437
 
with the old rw_lock implementation.
438
 
@return RW_LOCK_NOT_LOCKED, RW_LOCK_EX, RW_LOCK_WAIT_EX */
439
 
UNIV_INLINE
440
 
ulint
441
 
rw_lock_get_writer(
442
 
/*===============*/
443
 
        const rw_lock_t*        lock);  /*!< in: rw-lock */
444
 
/******************************************************************//**
445
 
Returns the number of readers.
446
 
@return number of readers */
447
 
UNIV_INLINE
448
 
ulint
449
 
rw_lock_get_reader_count(
450
 
/*=====================*/
451
 
        const rw_lock_t*        lock);  /*!< in: rw-lock */
452
 
/******************************************************************//**
453
 
Decrements lock_word the specified amount if it is greater than 0.
454
 
This is used by both s_lock and x_lock operations.
455
 
@return TRUE if decr occurs */
456
 
UNIV_INLINE
457
 
ibool
458
 
rw_lock_lock_word_decr(
459
 
/*===================*/
460
 
        rw_lock_t*      lock,           /*!< in/out: rw-lock */
461
 
        ulint           amount);        /*!< in: amount to decrement */
462
 
/******************************************************************//**
463
 
Increments lock_word the specified amount and returns new value.
464
 
@return lock->lock_word after increment */
465
 
UNIV_INLINE
466
 
lint
467
 
rw_lock_lock_word_incr(
468
 
/*===================*/
469
 
        rw_lock_t*      lock,           /*!< in/out: rw-lock */
470
 
        ulint           amount);        /*!< in: amount to increment */
471
 
/******************************************************************//**
472
 
This function sets the lock->writer_thread and lock->recursive fields.
473
 
For platforms where we are using atomic builtins instead of lock->mutex
474
 
it sets the lock->writer_thread field using atomics to ensure memory
475
 
ordering. Note that it is assumed that the caller of this function
476
 
effectively owns the lock i.e.: nobody else is allowed to modify
477
 
lock->writer_thread at this point in time.
478
 
The protocol is that lock->writer_thread MUST be updated BEFORE the
479
 
lock->recursive flag is set. */
480
 
UNIV_INLINE
481
 
void
482
 
rw_lock_set_writer_id_and_recursion_flag(
483
 
/*=====================================*/
484
 
        rw_lock_t*      lock,           /*!< in/out: lock to work on */
485
 
        ibool           recursive);     /*!< in: TRUE if recursion
486
 
                                        allowed */
487
 
#ifdef UNIV_SYNC_DEBUG
488
 
/******************************************************************//**
489
 
Checks if the thread has locked the rw-lock in the specified mode, with
490
 
the pass value == 0. */
491
 
UNIV_INTERN
492
 
ibool
493
 
rw_lock_own(
494
 
/*========*/
495
 
        rw_lock_t*      lock,           /*!< in: rw-lock */
496
 
        ulint           lock_type)      /*!< in: lock type: RW_LOCK_SHARED,
497
 
                                        RW_LOCK_EX */
498
 
        __attribute__((warn_unused_result));
499
 
#endif /* UNIV_SYNC_DEBUG */
500
 
/******************************************************************//**
501
 
Checks if somebody has locked the rw-lock in the specified mode. */
502
 
UNIV_INTERN
503
 
ibool
504
 
rw_lock_is_locked(
505
 
/*==============*/
506
 
        rw_lock_t*      lock,           /*!< in: rw-lock */
507
 
        ulint           lock_type);     /*!< in: lock type: RW_LOCK_SHARED,
508
 
                                        RW_LOCK_EX */
509
 
#ifdef UNIV_SYNC_DEBUG
510
 
/***************************************************************//**
511
 
Prints debug info of an rw-lock. */
512
 
UNIV_INTERN
513
 
void
514
 
rw_lock_print(
515
 
/*==========*/
516
 
        rw_lock_t*      lock);  /*!< in: rw-lock */
517
 
/***************************************************************//**
518
 
Prints debug info of currently locked rw-locks. */
519
 
UNIV_INTERN
520
 
void
521
 
rw_lock_list_print_info(
522
 
/*====================*/
523
 
        FILE*   file);          /*!< in: file where to print */
524
 
/***************************************************************//**
525
 
Returns the number of currently locked rw-locks.
526
 
Works only in the debug version.
527
 
@return number of locked rw-locks */
528
 
UNIV_INTERN
529
 
ulint
530
 
rw_lock_n_locked(void);
531
 
/*==================*/
532
 
 
533
 
/*#####################################################################*/
534
 
 
535
 
/******************************************************************//**
536
 
Acquires the debug mutex. We cannot use the mutex defined in sync0sync,
537
 
because the debug mutex is also acquired in sync0arr while holding the OS
538
 
mutex protecting the sync array, and the ordinary mutex_enter might
539
 
recursively call routines in sync0arr, leading to a deadlock on the OS
540
 
mutex. */
541
 
UNIV_INTERN
542
 
void
543
 
rw_lock_debug_mutex_enter(void);
544
 
/*==========================*/
545
 
/******************************************************************//**
546
 
Releases the debug mutex. */
547
 
UNIV_INTERN
548
 
void
549
 
rw_lock_debug_mutex_exit(void);
550
 
/*==========================*/
551
 
/*********************************************************************//**
552
 
Prints info of a debug struct. */
553
 
UNIV_INTERN
554
 
void
555
 
rw_lock_debug_print(
556
 
/*================*/
557
 
        rw_lock_debug_t*        info);  /*!< in: debug struct */
558
 
#endif /* UNIV_SYNC_DEBUG */
559
 
 
560
 
/* NOTE! The structure appears here only for the compiler to know its size.
561
 
Do not use its fields directly! */
562
 
 
563
 
/** The structure used in the spin lock implementation of a read-write
564
 
lock. Several threads may have a shared lock simultaneously in this
565
 
lock, but only one writer may have an exclusive lock, in which case no
566
 
shared locks are allowed. To prevent starving of a writer blocked by
567
 
readers, a writer may queue for x-lock by decrementing lock_word: no
568
 
new readers will be let in while the thread waits for readers to
569
 
exit. */
570
 
struct rw_lock_struct {
571
 
        volatile lint   lock_word;
572
 
                                /*!< Holds the state of the lock. */
573
 
        volatile ulint  waiters;/*!< 1: there are waiters */
574
 
        volatile ibool  recursive;/*!< Default value FALSE which means the lock
575
 
                                is non-recursive. The value is typically set
576
 
                                to TRUE making normal rw_locks recursive. In
577
 
                                case of asynchronous IO, when a non-zero
578
 
                                value of 'pass' is passed then we keep the
579
 
                                lock non-recursive.
580
 
                                This flag also tells us about the state of
581
 
                                writer_thread field. If this flag is set
582
 
                                then writer_thread MUST contain the thread
583
 
                                id of the current x-holder or wait-x thread.
584
 
                                This flag must be reset in x_unlock
585
 
                                functions before incrementing the lock_word */
586
 
        volatile os_thread_id_t writer_thread;
587
 
                                /*!< Thread id of writer thread. Is only
588
 
                                guaranteed to have sane and non-stale
589
 
                                value iff recursive flag is set. */
590
 
        os_event_t      event;  /*!< Used by sync0arr.c for thread queueing */
591
 
        os_event_t      wait_ex_event;
592
 
                                /*!< Event for next-writer to wait on. A thread
593
 
                                must decrement lock_word before waiting. */
594
 
#ifndef INNODB_RW_LOCKS_USE_ATOMICS
595
 
        mutex_t mutex;          /*!< The mutex protecting rw_lock_struct */
596
 
#endif /* INNODB_RW_LOCKS_USE_ATOMICS */
597
 
 
598
 
        UT_LIST_NODE_T(rw_lock_t) list;
599
 
                                /*!< All allocated rw locks are put into a
600
 
                                list */
601
 
#ifdef UNIV_SYNC_DEBUG
602
 
        UT_LIST_BASE_NODE_T(rw_lock_debug_t) debug_list;
603
 
                                /*!< In the debug version: pointer to the debug
604
 
                                info list of the lock */
605
 
        ulint   level;          /*!< Level in the global latching order. */
606
 
#endif /* UNIV_SYNC_DEBUG */
607
 
#ifdef UNIV_PFS_RWLOCK
608
 
        struct PSI_rwlock *pfs_psi;/*!< The instrumentation hook */
609
 
#endif
610
 
        ulint count_os_wait;    /*!< Count of os_waits. May not be accurate */
611
 
        const char*     cfile_name;/*!< File name where lock created */
612
 
        /* last s-lock file/line is not guaranteed to be correct */
613
 
        const char*     last_s_file_name;/*!< File name where last s-locked */
614
 
        const char*     last_x_file_name;/*!< File name where last x-locked */
615
 
        ibool           writer_is_wait_ex;
616
 
                                /*!< This is TRUE if the writer field is
617
 
                                RW_LOCK_WAIT_EX; this field is located far
618
 
                                from the memory update hotspot fields which
619
 
                                are at the start of this struct, thus we can
620
 
                                peek this field without causing much memory
621
 
                                bus traffic */
622
 
        unsigned        cline:14;       /*!< Line where created */
623
 
        unsigned        last_s_line:14; /*!< Line number where last time s-locked */
624
 
        unsigned        last_x_line:14; /*!< Line number where last time x-locked */
625
 
#ifdef UNIV_DEBUG
626
 
        ulint   magic_n;        /*!< RW_LOCK_MAGIC_N */
627
 
/** Value of rw_lock_struct::magic_n */
628
 
#define RW_LOCK_MAGIC_N 22643
629
 
#endif /* UNIV_DEBUG */
630
 
};
631
 
 
632
 
#ifdef UNIV_SYNC_DEBUG
633
 
/** The structure for storing debug info of an rw-lock */
634
 
struct  rw_lock_debug_struct {
635
 
 
636
 
        os_thread_id_t thread_id;  /*!< The thread id of the thread which
637
 
                                locked the rw-lock */
638
 
        ulint   pass;           /*!< Pass value given in the lock operation */
639
 
        ulint   lock_type;      /*!< Type of the lock: RW_LOCK_EX,
640
 
                                RW_LOCK_SHARED, RW_LOCK_WAIT_EX */
641
 
        const char*     file_name;/*!< File name where the lock was obtained */
642
 
        ulint   line;           /*!< Line where the rw-lock was locked */
643
 
        UT_LIST_NODE_T(rw_lock_debug_t) list;
644
 
                                /*!< Debug structs are linked in a two-way
645
 
                                list */
646
 
};
647
 
#endif /* UNIV_SYNC_DEBUG */
648
 
 
649
 
/* For performance schema instrumentation, a new set of rwlock
650
 
wrap functions are created if "UNIV_PFS_RWLOCK" is defined.
651
 
The instrumentations are not planted directly into original
652
 
functions, so that we keep the underlying function as they
653
 
are. And in case, user wants to "take out" some rwlock from
654
 
instrumentation even if performance schema (UNIV_PFS_RWLOCK)
655
 
is defined, they can do so by reinstating APIs directly link to
656
 
original underlying functions.
657
 
The instrumented function names have prefix of "pfs_rw_lock_" vs.
658
 
original name prefix of "rw_lock_". Following are list of functions
659
 
that have been instrumented:
660
 
 
661
 
rw_lock_create()
662
 
rw_lock_x_lock()
663
 
rw_lock_x_lock_gen()
664
 
rw_lock_x_lock_nowait()
665
 
rw_lock_x_unlock_gen()
666
 
rw_lock_s_lock()
667
 
rw_lock_s_lock_gen()
668
 
rw_lock_s_lock_nowait()
669
 
rw_lock_s_unlock_gen()
670
 
rw_lock_free()
671
 
 
672
 
Two function APIs rw_lock_x_unlock_direct() and rw_lock_s_unlock_direct()
673
 
do not have any caller/user, they are not instrumented.
674
 
*/
675
 
 
676
 
#ifdef UNIV_PFS_RWLOCK
677
 
/******************************************************************//**
678
 
Performance schema instrumented wrap function for rw_lock_create_func()
679
 
NOTE! Please use the corresponding macro rw_lock_create(), not
680
 
directly this function! */
681
 
UNIV_INLINE
682
 
void
683
 
pfs_rw_lock_create_func(
684
 
/*====================*/
685
 
        PSI_rwlock_key  key,            /*!< in: key registered with
686
 
                                        performance schema */
687
 
        rw_lock_t*      lock,           /*!< in: rw lock */
688
 
#ifdef UNIV_DEBUG
689
 
# ifdef UNIV_SYNC_DEBUG
690
 
        ulint           level,          /*!< in: level */
691
 
# endif /* UNIV_SYNC_DEBUG */
692
 
        const char*     cmutex_name,    /*!< in: mutex name */
693
 
#endif /* UNIV_DEBUG */
694
 
        const char*     cfile_name,     /*!< in: file name where created */
695
 
        ulint           cline);         /*!< in: file line where created */
696
 
 
697
 
/******************************************************************//**
698
 
Performance schema instrumented wrap function for rw_lock_x_lock_func()
699
 
NOTE! Please use the corresponding macro rw_lock_x_lock(), not
700
 
directly this function! */
701
 
UNIV_INLINE
702
 
void
703
 
pfs_rw_lock_x_lock_func(
704
 
/*====================*/
705
 
        rw_lock_t*      lock,   /*!< in: pointer to rw-lock */
706
 
        ulint           pass,   /*!< in: pass value; != 0, if the lock will
707
 
                                be passed to another thread to unlock */
708
 
        const char*     file_name,/*!< in: file name where lock requested */
709
 
        ulint           line);  /*!< in: line where requested */
710
 
/******************************************************************//**
711
 
Performance schema instrumented wrap function for
712
 
rw_lock_x_lock_func_nowait()
713
 
NOTE! Please use the corresponding macro, not directly this function!
714
 
@return TRUE if success */
715
 
UNIV_INLINE
716
 
ibool
717
 
pfs_rw_lock_x_lock_func_nowait(
718
 
/*===========================*/
719
 
        rw_lock_t*      lock,   /*!< in: pointer to rw-lock */
720
 
        const char*     file_name,/*!< in: file name where lock requested */
721
 
        ulint           line);  /*!< in: line where requested */
722
 
/******************************************************************//**
723
 
Performance schema instrumented wrap function for rw_lock_s_lock_func()
724
 
NOTE! Please use the corresponding macro rw_lock_s_lock(), not directly
725
 
this function! */
726
 
UNIV_INLINE
727
 
void
728
 
pfs_rw_lock_s_lock_func(
729
 
/*====================*/
730
 
        rw_lock_t*      lock,   /*!< in: pointer to rw-lock */
731
 
        ulint           pass,   /*!< in: pass value; != 0, if the lock will
732
 
                                be passed to another thread to unlock */
733
 
        const char*     file_name,/*!< in: file name where lock requested */
734
 
        ulint           line);  /*!< in: line where requested */
735
 
/******************************************************************//**
736
 
Performance schema instrumented wrap function for rw_lock_s_lock_func()
737
 
NOTE! Please use the corresponding macro rw_lock_s_lock(), not directly
738
 
this function!
739
 
@return TRUE if success */
740
 
UNIV_INLINE
741
 
ibool
742
 
pfs_rw_lock_s_lock_low(
743
 
/*===================*/
744
 
        rw_lock_t*      lock,   /*!< in: pointer to rw-lock */
745
 
        ulint           pass,   /*!< in: pass value; != 0, if the
746
 
                                lock will be passed to another
747
 
                                thread to unlock */
748
 
        const char*     file_name, /*!< in: file name where lock requested */
749
 
        ulint           line);  /*!< in: line where requested */
750
 
/******************************************************************//**
751
 
Performance schema instrumented wrap function for rw_lock_x_lock_func()
752
 
NOTE! Please use the corresponding macro rw_lock_x_lock(), not directly
753
 
this function! */
754
 
UNIV_INLINE
755
 
void
756
 
pfs_rw_lock_x_lock_func(
757
 
/*====================*/
758
 
        rw_lock_t*      lock,   /*!< in: pointer to rw-lock */
759
 
        ulint           pass,   /*!< in: pass value; != 0, if the lock will
760
 
                                be passed to another thread to unlock */
761
 
        const char*     file_name,/*!< in: file name where lock requested */
762
 
        ulint           line);  /*!< in: line where requested */
763
 
/******************************************************************//**
764
 
Performance schema instrumented wrap function for rw_lock_s_unlock_func()
765
 
NOTE! Please use the corresponding macro rw_lock_s_unlock(), not directly
766
 
this function! */
767
 
UNIV_INLINE
768
 
void
769
 
pfs_rw_lock_s_unlock_func(
770
 
/*======================*/
771
 
#ifdef UNIV_SYNC_DEBUG
772
 
        ulint           pass,   /*!< in: pass value; != 0, if the
773
 
                                lock may have been passed to another
774
 
                                thread to unlock */
775
 
#endif
776
 
        rw_lock_t*      lock);  /*!< in/out: rw-lock */
777
 
/******************************************************************//**
778
 
Performance schema instrumented wrap function for rw_lock_s_unlock_func()
779
 
NOTE! Please use the corresponding macro rw_lock_x_unlock(), not directly
780
 
this function! */
781
 
UNIV_INLINE
782
 
void
783
 
pfs_rw_lock_x_unlock_func(
784
 
/*======================*/
785
 
#ifdef UNIV_SYNC_DEBUG
786
 
        ulint           pass,   /*!< in: pass value; != 0, if the
787
 
                                lock may have been passed to another
788
 
                                thread to unlock */
789
 
#endif
790
 
        rw_lock_t*      lock);  /*!< in/out: rw-lock */
791
 
/******************************************************************//**
792
 
Performance schema instrumented wrap function for rw_lock_free_func()
793
 
NOTE! Please use the corresponding macro rw_lock_free(), not directly
794
 
this function! */
795
 
UNIV_INLINE
796
 
void
797
 
pfs_rw_lock_free_func(
798
 
/*==================*/
799
 
        rw_lock_t*      lock);  /*!< in: rw-lock */
800
 
#endif  /* UNIV_PFS_RWLOCK */
801
 
 
802
 
 
803
 
#ifndef UNIV_NONINL
804
 
#include "sync0rw.ic"
805
 
#endif
806
 
#endif /* !UNIV_HOTBACKUP */
807
 
 
808
 
#endif