1/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
3#ident "$Id$"
4/*======
5This file is part of PerconaFT.
6
7
8Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
9
10 PerconaFT is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License, version 2,
12 as published by the Free Software Foundation.
13
14 PerconaFT is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
21
22----------------------------------------
23
24 PerconaFT is free software: you can redistribute it and/or modify
25 it under the terms of the GNU Affero General Public License, version 3,
26 as published by the Free Software Foundation.
27
28 PerconaFT is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU Affero General Public License for more details.
32
33 You should have received a copy of the GNU Affero General Public License
34 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
35======= */
36
37#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
38
39#pragma once
40
41#include "rwlock.h"
42
43//Use case:
44// General purpose non blocking mutex with properties:
45// 1. one writer at a time
46
47// An external mutex must be locked when using these functions. An alternate
48// design would bury a mutex into the nb_mutex itself. While this may
49// increase parallelism at the expense of single thread performance, we
50// are experimenting with a single higher level lock.
51
52extern toku_instr_key *nb_mutex_key;
53
54typedef struct nb_mutex *NB_MUTEX;
55struct nb_mutex {
56 struct st_rwlock lock;
57#if defined(TOKU_MYSQL_WITH_PFS)
58 toku_mutex_t toku_mutex;
59#endif
60};
61
62#if defined(TOKU_MYSQL_WITH_PFS)
63#define nb_mutex_init(MK, RK, M) \
64 inline_nb_mutex_init(MK, RK, M)
65#else
66#define nb_mutex_init(MK, RK, M) inline_nb_mutex_init(M)
67#endif
68
69// initialize an nb mutex
70inline void inline_nb_mutex_init(
71#if defined(TOKU_MYSQL_WITH_PFS)
72 const toku_instr_key &mutex_instr_key,
73 const toku_instr_key &rwlock_instr_key,
74#endif
75 NB_MUTEX nb_mutex) {
76#if defined(TOKU_MYSQL_WITH_PFS)
77 toku_mutex_init(mutex_instr_key, &nb_mutex->toku_mutex, nullptr);
78#endif
79 rwlock_init(rwlock_instr_key, &nb_mutex->lock);
80}
81
82// destroy a read write lock
83inline void nb_mutex_destroy(NB_MUTEX nb_mutex) {
84#if defined(TOKU_MYSQL_WITH_PFS)
85 toku_instr_mutex_destroy(nb_mutex->toku_mutex.psi_mutex);
86#endif
87 rwlock_destroy(&nb_mutex->lock);
88}
89
90// obtain a write lock
91// expects: mutex is locked
92inline void nb_mutex_lock(NB_MUTEX nb_mutex, toku_mutex_t *mutex) {
93#ifdef TOKU_MYSQL_WITH_PFS
94 toku_mutex_instrumentation mutex_instr;
95 toku_instr_mutex_lock_start(mutex_instr,
96 *mutex,
97 __FILE__,
98 __LINE__); // TODO: pull these to caller?
99#endif
100 rwlock_write_lock(&nb_mutex->lock, mutex);
101#if defined(TOKU_MYSQL_WITH_PFS)
102 toku_instr_mutex_lock_end(mutex_instr, 0);
103#endif
104}
105
106// release a write lock
107// expects: mutex is locked
108
109inline void nb_mutex_unlock(NB_MUTEX nb_mutex) {
110#if defined(TOKU_MYSQL_WITH_PFS)
111 toku_instr_mutex_unlock(nb_mutex->toku_mutex.psi_mutex);
112#endif
113 rwlock_write_unlock(&nb_mutex->lock);
114}
115
116static inline void nb_mutex_wait_for_users(NB_MUTEX nb_mutex, toku_mutex_t *mutex) {
117 rwlock_wait_for_users(&nb_mutex->lock, mutex);
118}
119
120// returns: the number of writers who are waiting for the lock
121
122static inline int nb_mutex_blocked_writers(NB_MUTEX nb_mutex) {
123 return rwlock_blocked_writers(&nb_mutex->lock);
124}
125
126// returns: the number of writers
127
128static inline int nb_mutex_writers(NB_MUTEX nb_mutex) {
129 return rwlock_writers(&nb_mutex->lock);
130}
131
132// returns: the sum of the number of readers, pending readers,
133// writers, and pending writers
134static inline int nb_mutex_users(NB_MUTEX nb_mutex) {
135 return rwlock_users(&nb_mutex->lock);
136}
137