Coverage Report

Created: 2025-06-13 07:09

/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