1
/*****************************************************************************
3
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
4
Copyright (c) 2008, Google Inc.
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.
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.
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.
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., 59 Temple
22
Place, Suite 330, Boston, MA 02111-1307 USA
24
*****************************************************************************/
26
1
/******************************************************
27
2
The read-write lock (for threads, not for database transactions)
29
6
Created 9/11/1995 Heikki Tuuri
30
7
*******************************************************/
76
47
there may be waiters for the event */
77
48
#endif /* UNIV_SYNC_DEBUG */
79
extern ib_int64_t rw_s_spin_wait_count;
80
extern ib_int64_t rw_s_spin_round_count;
81
extern ib_int64_t rw_s_exit_count;
82
extern ib_int64_t rw_s_os_wait_count;
83
extern ib_int64_t rw_x_spin_wait_count;
84
extern ib_int64_t rw_x_spin_round_count;
85
extern ib_int64_t rw_x_os_wait_count;
86
extern ib_int64_t rw_x_exit_count;
50
extern ulint rw_s_system_call_count;
51
extern ulint rw_s_spin_wait_count;
52
extern ulint rw_s_exit_count;
53
extern ulint rw_s_os_wait_count;
54
extern ulint rw_x_system_call_count;
55
extern ulint rw_x_spin_wait_count;
56
extern ulint rw_x_os_wait_count;
57
extern ulint rw_x_exit_count;
88
59
/**********************************************************************
89
60
Creates, or rather, initializes an rw-lock object in a specified memory
156
127
NOTE! The following macros should be used in rw s-locking, not the
157
128
corresponding function. */
159
#define rw_lock_s_lock_nowait(M, F, L) rw_lock_s_lock_low(\
161
/**********************************************************************
162
Low-level function which tries to lock an rw-lock in s-mode. Performs no
168
/* out: TRUE if success */
169
rw_lock_t* lock, /* in: pointer to rw-lock */
170
ulint pass __attribute__((unused)),
171
/* in: pass value; != 0, if the lock will be
172
passed to another thread to unlock */
173
const char* file_name, /* in: file name where lock requested */
174
ulint line); /* in: line where requested */
130
#define rw_lock_s_lock_nowait(M) rw_lock_s_lock_func_nowait(\
131
(M), __FILE__, __LINE__)
175
132
/**********************************************************************
176
133
NOTE! Use the corresponding macro, not directly this function, except if
177
134
you supply the file name and line number. Lock an rw-lock in shared mode
189
146
const char* file_name,/* in: file name where lock requested */
190
147
ulint line); /* in: line where requested */
191
148
/**********************************************************************
149
NOTE! Use the corresponding macro, not directly this function, except if
150
you supply the file name and line number. Lock an rw-lock in shared mode
151
for the current thread if the lock can be acquired immediately. */
154
rw_lock_s_lock_func_nowait(
155
/*=======================*/
156
/* out: TRUE if success */
157
rw_lock_t* lock, /* in: pointer to rw-lock */
158
const char* file_name,/* in: file name where lock requested */
159
ulint line); /* in: line where requested */
160
/**********************************************************************
192
161
NOTE! Use the corresponding macro, not directly this function! Lock an
193
162
rw-lock in exclusive mode for the current thread if the lock can be
194
163
obtained immediately. */
372
341
rw_lock_get_reader_count(
373
342
/*=====================*/
374
343
rw_lock_t* lock);
375
/**********************************************************************
376
Decrements lock_word the specified amount if it is greater than 0.
377
This is used by both s_lock and x_lock operations. */
380
rw_lock_lock_word_decr(
381
/*===================*/
382
/* out: TRUE if decr occurs */
383
rw_lock_t* lock, /* in: rw-lock */
384
ulint amount); /* in: amount to decrement */
385
/**********************************************************************
386
Increments lock_word the specified amount and returns new value. */
389
rw_lock_lock_word_incr(
390
/*===================*/
391
/* out: TRUE if decr occurs */
393
ulint amount); /* in: rw-lock */
394
/**********************************************************************
395
This function sets the lock->writer_thread and lock->recursive fields.
396
For platforms where we are using atomic builtins instead of lock->mutex
397
it sets the lock->writer_thread field using atomics to ensure memory
398
ordering. Note that it is assumed that the caller of this function
399
effectively owns the lock i.e.: nobody else is allowed to modify
400
lock->writer_thread at this point in time.
401
The protocol is that lock->writer_thread MUST be updated BEFORE the
402
lock->recursive flag is set. */
405
rw_lock_set_writer_id_and_recursion_flag(
406
/*=====================================*/
407
rw_lock_t* lock, /* in/out: lock to work on */
408
ibool recursive); /* in: TRUE if recursion
410
344
#ifdef UNIV_SYNC_DEBUG
411
345
/**********************************************************************
412
346
Checks if the thread has locked the rw-lock in the specified mode, with
483
417
implementation of a read-write lock. Several threads may have a shared lock
484
418
simultaneously in this lock, but only one writer may have an exclusive lock,
485
419
in which case no shared locks are allowed. To prevent starving of a writer
486
blocked by readers, a writer may queue for x-lock by decrementing lock_word:
487
no new readers will be let in while the thread waits for readers to exit. */
420
blocked by readers, a writer may queue for the lock by setting the writer
421
field. Then no new readers are allowed in. */
489
423
struct rw_lock_struct {
490
volatile lint lock_word;
491
/* Holds the state of the lock. */
492
volatile ulint waiters;/* 1: there are waiters */
493
volatile ibool recursive;/* Default value FALSE which means the lock
494
is non-recursive. The value is typically set
495
to TRUE making normal rw_locks recursive. In
496
case of asynchronous IO, when a non-zero
497
value of 'pass' is passed then we keep the
499
This flag also tells us about the state of
500
writer_thread field. If this flag is set
501
then writer_thread MUST contain the thread
502
id of the current x-holder or wait-x thread.
503
This flag must be reset in x_unlock
504
functions before incrementing the lock_word */
505
volatile os_thread_id_t writer_thread;
506
/* Thread id of writer thread. Is only
507
guaranteed to have sane and non-stale
508
value iff recursive flag is set. */
509
424
os_event_t event; /* Used by sync0arr.c for thread queueing */
510
os_event_t wait_ex_event;
511
/* Event for next-writer to wait on. A thread
512
must decrement lock_word before waiting. */
513
#ifndef INNODB_RW_LOCKS_USE_ATOMICS
427
os_event_t wait_ex_event; /* This windows specific event is
428
used by the thread which has set the
429
lock state to RW_LOCK_WAIT_EX. The
430
rw_lock design guarantees that this
431
thread will be the next one to proceed
432
once the current the event gets
433
signalled. See LEMMA 2 in sync0sync.c */
436
ulint reader_count; /* Number of readers who have locked this
437
lock in the shared mode */
438
ulint writer; /* This field is set to RW_LOCK_EX if there
439
is a writer owning the lock (in exclusive
440
mode), RW_LOCK_WAIT_EX if a writer is
441
queueing for the lock, and
442
RW_LOCK_NOT_LOCKED, otherwise. */
443
os_thread_id_t writer_thread;
444
/* Thread id of a possible writer thread */
445
ulint writer_count; /* Number of times the same thread has
446
recursively locked the lock in the exclusive
514
448
mutex_t mutex; /* The mutex protecting rw_lock_struct */
515
#endif /* INNODB_RW_LOCKS_USE_ATOMICS */
449
ulint pass; /* Default value 0. This is set to some
450
value != 0 given by the caller of an x-lock
451
operation, if the x-lock is to be passed to
452
another thread to unlock (which happens in
453
asynchronous i/o). */
454
ulint waiters; /* This ulint is set to 1 if there are
455
waiters (readers or writers) in the global
456
wait array, waiting for this rw_lock.
517
458
UT_LIST_NODE_T(rw_lock_t) list;
518
459
/* All allocated rw locks are put into a