~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Stewart Smith
  • Author(s): Marko Mäkelä
  • Date: 2010-12-20 03:21:44 UTC
  • mto: (2021.1.2 build)
  • mto: This revision was merged to the branch mainline in revision 2022.
  • Revision ID: stewart@flamingspork.com-20101220032144-7aqh2z403u7d7bdp
Merge Revision revid:marko.makela@oracle.com-20101104131215-pfxnpidlrzd4krg0 from MySQL InnoDB

Original revid:marko.makela@oracle.com-20101104131215-pfxnpidlrzd4krg0

Original Authors: Marko Mäkelä <marko.makela@oracle.com>
Original commit message:
row_ins_index_entry(): Note that only CREATE INDEX sets foreign=FALSE.

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