/src/server/mysys/thr_rwlock.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. |
2 | | |
3 | | This program is free software; you can redistribute it and/or modify |
4 | | it under the terms of the GNU General Public License as published by |
5 | | the Free Software Foundation; version 2 of the License. |
6 | | |
7 | | This program is distributed in the hope that it will be useful, |
8 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | | GNU General Public License for more details. |
11 | | |
12 | | You should have received a copy of the GNU General Public License |
13 | | along with this program; if not, write to the Free Software |
14 | | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ |
15 | | |
16 | | /* Synchronization - readers / writer thread locks */ |
17 | | |
18 | | #include "mysys_priv.h" |
19 | | #if defined(NEED_MY_RW_LOCK) |
20 | | #include <errno.h> |
21 | | |
22 | | #ifdef _WIN32 |
23 | | |
24 | | int my_rw_init(my_rw_lock_t *rwp) |
25 | | { |
26 | | InitializeSRWLock(&rwp->srwlock); |
27 | | rwp->have_exclusive_srwlock = FALSE; |
28 | | return 0; |
29 | | } |
30 | | |
31 | | |
32 | | int my_rw_rdlock(my_rw_lock_t *rwp) |
33 | | { |
34 | | AcquireSRWLockShared(&rwp->srwlock); |
35 | | return 0; |
36 | | } |
37 | | |
38 | | |
39 | | int my_rw_tryrdlock(my_rw_lock_t *rwp) |
40 | | { |
41 | | if (!TryAcquireSRWLockShared(&rwp->srwlock)) |
42 | | return EBUSY; |
43 | | return 0; |
44 | | } |
45 | | |
46 | | |
47 | | int my_rw_wrlock(my_rw_lock_t *rwp) |
48 | | { |
49 | | AcquireSRWLockExclusive(&rwp->srwlock); |
50 | | rwp->have_exclusive_srwlock= TRUE; |
51 | | return 0; |
52 | | } |
53 | | |
54 | | int my_rw_trywrlock(my_rw_lock_t *rwp) |
55 | | { |
56 | | if (!TryAcquireSRWLockExclusive(&rwp->srwlock)) |
57 | | return EBUSY; |
58 | | rwp->have_exclusive_srwlock= TRUE; |
59 | | return 0; |
60 | | } |
61 | | |
62 | | |
63 | | int my_rw_unlock(my_rw_lock_t *rwp) |
64 | | { |
65 | | if (rwp->have_exclusive_srwlock) |
66 | | { |
67 | | rwp->have_exclusive_srwlock= FALSE; |
68 | | ReleaseSRWLockExclusive(&rwp->srwlock); |
69 | | } |
70 | | else |
71 | | { |
72 | | ReleaseSRWLockShared(&rwp->srwlock); |
73 | | } |
74 | | return 0; |
75 | | } |
76 | | |
77 | | int my_rw_destroy(my_rw_lock_t* rwp) |
78 | | { |
79 | | DBUG_ASSERT(!rwp->have_exclusive_srwlock); |
80 | | return 0; |
81 | | } |
82 | | |
83 | | #else |
84 | | #error no pthread_rwlock_init |
85 | | #endif /* !defined _WIN32 */ |
86 | | #endif /* NEED_MY_RW_LOCK*/ |
87 | | |
88 | | |
89 | | int rw_pr_init(rw_pr_lock_t *rwlock) |
90 | 0 | { |
91 | 0 | pthread_mutex_init(&rwlock->lock, NULL); |
92 | 0 | pthread_cond_init(&rwlock->no_active_readers, NULL); |
93 | 0 | rwlock->active_readers= 0; |
94 | 0 | rwlock->writers_waiting_readers= 0; |
95 | 0 | rwlock->active_writer= FALSE; |
96 | | #ifdef SAFE_MUTEX |
97 | | rwlock->writer_thread= 0; |
98 | | #endif |
99 | 0 | return 0; |
100 | 0 | } |
101 | | |
102 | | |
103 | | int rw_pr_destroy(rw_pr_lock_t *rwlock) |
104 | 0 | { |
105 | 0 | pthread_cond_destroy(&rwlock->no_active_readers); |
106 | 0 | pthread_mutex_destroy(&rwlock->lock); |
107 | 0 | return 0; |
108 | 0 | } |
109 | | |
110 | | |
111 | | int rw_pr_rdlock(rw_pr_lock_t *rwlock) |
112 | 0 | { |
113 | 0 | pthread_mutex_lock(&rwlock->lock); |
114 | | /* |
115 | | The fact that we were able to acquire 'lock' mutex means |
116 | | that there are no active writers and we can acquire rd-lock. |
117 | | Increment active readers counter to prevent requests for |
118 | | wr-lock from succeeding and unlock mutex. |
119 | | */ |
120 | 0 | rwlock->active_readers++; |
121 | 0 | pthread_mutex_unlock(&rwlock->lock); |
122 | 0 | return 0; |
123 | 0 | } |
124 | | |
125 | | |
126 | | int rw_pr_wrlock(rw_pr_lock_t *rwlock) |
127 | 0 | { |
128 | 0 | pthread_mutex_lock(&rwlock->lock); |
129 | |
|
130 | 0 | if (rwlock->active_readers != 0) |
131 | 0 | { |
132 | | /* There are active readers. We have to wait until they are gone. */ |
133 | 0 | rwlock->writers_waiting_readers++; |
134 | |
|
135 | 0 | while (rwlock->active_readers != 0) |
136 | 0 | pthread_cond_wait(&rwlock->no_active_readers, &rwlock->lock); |
137 | |
|
138 | 0 | rwlock->writers_waiting_readers--; |
139 | 0 | } |
140 | | |
141 | | /* |
142 | | We own 'lock' mutex so there is no active writers. |
143 | | Also there are no active readers. |
144 | | This means that we can grant wr-lock. |
145 | | Not releasing 'lock' mutex until unlock will block |
146 | | both requests for rd and wr-locks. |
147 | | Set 'active_writer' flag to simplify unlock. |
148 | | |
149 | | Thanks to the fact wr-lock/unlock in the absence of |
150 | | contention from readers is essentially mutex lock/unlock |
151 | | with a few simple checks make this rwlock implementation |
152 | | wr-lock optimized. |
153 | | */ |
154 | 0 | rwlock->active_writer= TRUE; |
155 | | #ifdef SAFE_MUTEX |
156 | | rwlock->writer_thread= pthread_self(); |
157 | | #endif |
158 | 0 | return 0; |
159 | 0 | } |
160 | | |
161 | | |
162 | | int rw_pr_unlock(rw_pr_lock_t *rwlock) |
163 | 0 | { |
164 | 0 | if (rwlock->active_writer) |
165 | 0 | { |
166 | | /* We are unlocking wr-lock. */ |
167 | | #ifdef SAFE_MUTEX |
168 | | rwlock->writer_thread= 0; |
169 | | #endif |
170 | 0 | rwlock->active_writer= FALSE; |
171 | 0 | if (rwlock->writers_waiting_readers) |
172 | 0 | { |
173 | | /* |
174 | | Avoid expensive cond signal in case when there is no contention |
175 | | or it is wr-only. |
176 | | |
177 | | Note that from view point of performance it would be better to |
178 | | signal on the condition variable after unlocking mutex (as it |
179 | | reduces number of contex switches). |
180 | | |
181 | | Unfortunately this would mean that such rwlock can't be safely |
182 | | used by MDL subsystem, which relies on the fact that it is OK |
183 | | to destroy rwlock once it is in unlocked state. |
184 | | */ |
185 | 0 | pthread_cond_signal(&rwlock->no_active_readers); |
186 | 0 | } |
187 | 0 | pthread_mutex_unlock(&rwlock->lock); |
188 | 0 | } |
189 | 0 | else |
190 | 0 | { |
191 | | /* We are unlocking rd-lock. */ |
192 | 0 | pthread_mutex_lock(&rwlock->lock); |
193 | 0 | rwlock->active_readers--; |
194 | 0 | if (rwlock->active_readers == 0 && |
195 | 0 | rwlock->writers_waiting_readers) |
196 | 0 | { |
197 | | /* |
198 | | If we are last reader and there are waiting |
199 | | writers wake them up. |
200 | | */ |
201 | 0 | pthread_cond_signal(&rwlock->no_active_readers); |
202 | 0 | } |
203 | 0 | pthread_mutex_unlock(&rwlock->lock); |
204 | 0 | } |
205 | 0 | return 0; |
206 | 0 | } |
207 | | |
208 | | |