Motr  M0
rwlock.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2011-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #include "ut/ut.h"
24 #include "lib/thread.h"
25 #include "lib/rwlock.h"
26 #include "lib/assert.h"
27 #include "lib/semaphore.h"
28 
33 enum {
34  NR = 255,
35 
36  /*
37  * Starvation tests.
38  */
39 
40  /* A number of "starvers" acquiring and releasing the lock (in the
41  required mode) in an infinite loop. */
42  S = 8,
43  /* A number of "checkers" which try to squeeze between starvers and
44  acquire the lock in a different mode at least once. */
45  C = 3
46 };
47 
48 M0_BASSERT(S + C <= NR);
49 
50 static int counter;
51 static struct m0_thread t[NR];
52 static struct m0_rwlock m;
53 static int sum;
54 static struct m0_semaphore p;
55 static struct m0_semaphore q;
56 static int stop;
57 static int i;
58 
59 static void writer(int n)
60 {
61  int i;
62 
63  for (i = 0; i < NR; ++i) {
65  counter += n;
67  }
68 }
69 
70 static void reader(int n)
71 {
75  M0_UT_ASSERT(counter == 0);
77 }
78 
79 static void wstarver(int x)
80 {
82  while (!stop) {
85  }
87 }
88 
89 static void rstarver(int x)
90 {
92  while (!stop) {
95  }
97 }
98 
99 
100 static void rcheck(int x)
101 {
104 }
105 
106 static void wcheck(int x)
107 {
110 }
111 
115 static void test_rw_writers(void)
116 {
117  int result;
118 
119  counter = 0;
120 
121  for (sum = 0, i = 0; i < NR; ++i) {
122  result = M0_THREAD_INIT(&t[i], int, NULL, &writer, i,
123  "writer[%i]", i);
124  M0_UT_ASSERT(result == 0);
125  sum += i * NR;
126  }
127 
128  for (i = 0; i < NR; ++i) {
129  m0_thread_join(&t[i]);
130  m0_thread_fini(&t[i]);
131  }
132 
134 }
135 
139 static void test_rw_readers(void)
140 {
141  int result;
142 
143  counter = 0;
144 
145  for (i = 0; i < NR; ++i) {
146  result = M0_THREAD_INIT(&t[i], int, NULL, &reader, i,
147  "reader[%i]", i);
148  M0_UT_ASSERT(result == 0);
150  }
151 
152  for (i = 0; i < NR; ++i)
153  m0_semaphore_up(&q);
154 
155  for (i = 0; i < NR; ++i) {
156  m0_thread_join(&t[i]);
157  m0_thread_fini(&t[i]);
158  }
159 }
160 
164 static void test_rw_excl(void)
165 {
166  int result;
167 
168  for (i = 0; i < NR / 2; ++i) {
169  result = M0_THREAD_INIT(&t[i], int, NULL, &reader, i,
170  "reader[%i]", i);
171  M0_UT_ASSERT(result == 0);
173  }
174 
175  for (sum = 0; i < NR; ++i) {
176  result = M0_THREAD_INIT(&t[i], int, NULL, &writer, i,
177  "writer[%i]", i);
178  M0_UT_ASSERT(result == 0);
179  sum += i * NR;
180  }
181 
182  for (i = 0; i < NR / 2; ++i) {
183  M0_UT_ASSERT(counter == 0);
184  m0_semaphore_up(&q);
185  }
186 
187  for (i = 0; i < NR; ++i) {
188  m0_thread_join(&t[i]);
189  m0_thread_fini(&t[i]);
190  }
192 }
193 
200 static void test_rw_rstarve(void)
201 {
202  int result;
203 
204  stop = false;
205 
206  for (i = 0; i < S; ++i) {
207  result = M0_THREAD_INIT(&t[i], int, NULL, &wstarver, 0,
208  "wstarver[%i]", i);
209  M0_UT_ASSERT(result == 0);
210  }
211 
212  for (i = S; i < S + C; ++i) {
213  result = M0_THREAD_INIT(&t[i], int, NULL, &rcheck, 0,
214  "rcheck[%i]", i);
215  M0_UT_ASSERT(result == 0);
216  }
217 
218  for (i = S; i < S + C; ++i) {
219  m0_thread_join(&t[i]);
220  m0_thread_fini(&t[i]);
221  }
222 
223  stop = true;
224 
225  for (i = 0; i < S; ++i) {
226  m0_thread_join(&t[i]);
227  m0_thread_fini(&t[i]);
228  }
229 }
230 
234 static void test_rw_wstarve(void)
235 {
236  int result;
237 
238  for (i = 0; i < S; ++i) {
239  result = M0_THREAD_INIT(&t[i], int, NULL, &rstarver, 0,
240  "rstarver[%i]", i);
241  M0_UT_ASSERT(result == 0);
242  }
243 
244  for (i = S; i < S + C; ++i) {
245  result = M0_THREAD_INIT(&t[i], int, NULL, &wcheck, 0,
246  "wcheck[%i]", i);
247  M0_UT_ASSERT(result == 0);
248  }
249 
250  for (i = S; i < S + C; ++i) {
251  m0_thread_join(&t[i]);
252  m0_thread_fini(&t[i]);
253  }
254 
255  stop = true;
256 
257  for (i = 0; i < S; ++i) {
258  m0_thread_join(&t[i]);
259  m0_thread_fini(&t[i]);
260  }
261 }
262 
263 void test_rw(void)
264 {
265  m0_rwlock_init(&m);
266  m0_semaphore_init(&p, 0);
267  m0_semaphore_init(&q, 0);
268 
269  test_rw_writers();
270  test_rw_readers();
271  test_rw_excl();
272  test_rw_rstarve();
273  test_rw_wstarve();
274 
277  m0_rwlock_fini(&m);
278 }
279 
280 
281 /*
282  * Local variables:
283  * c-indentation-style: "K&R"
284  * c-basic-offset: 8
285  * tab-width: 8
286  * fill-column: 80
287  * scroll-step: 1
288  * End:
289  */
static void test_rw_writers(void)
Definition: rwlock.c:115
static struct m0_semaphore q
Definition: rwlock.c:55
#define NULL
Definition: misc.h:38
static int i
Definition: rwlock.c:57
int m0_thread_join(struct m0_thread *q)
Definition: kthread.c:169
static bool x
Definition: sm.c:168
static void wstarver(int x)
Definition: rwlock.c:79
static void test_rw_rstarve(void)
Definition: rwlock.c:200
M0_INTERNAL void m0_rwlock_write_lock(struct m0_rwlock *lock)
Definition: rwlock.c:42
static struct m0_thread t[NR]
Definition: rwlock.c:51
static struct m0_semaphore p
Definition: rwlock.c:54
static int sum
Definition: rwlock.c:53
static void test_rw_excl(void)
Definition: rwlock.c:164
#define M0_THREAD_INIT(thread, TYPE, init, func, arg, namefmt,...)
Definition: thread.h:139
static struct m0_rwlock m
Definition: rwlock.c:52
static void rstarver(int x)
Definition: rwlock.c:89
M0_INTERNAL void m0_rwlock_init(struct m0_rwlock *lock)
Definition: rwlock.c:32
static void reader(int n)
Definition: rwlock.c:70
static void rcheck(int x)
Definition: rwlock.c:100
void m0_thread_fini(struct m0_thread *q)
Definition: thread.c:92
M0_INTERNAL int m0_semaphore_init(struct m0_semaphore *semaphore, unsigned value)
Definition: semaphore.c:38
static int stop
Definition: rwlock.c:56
M0_INTERNAL void m0_rwlock_write_unlock(struct m0_rwlock *lock)
Definition: rwlock.c:47
M0_BASSERT(S+C<=NR)
uint64_t n
Definition: fops.h:107
static int counter
Definition: rwlock.c:50
M0_INTERNAL void m0_semaphore_fini(struct m0_semaphore *semaphore)
Definition: semaphore.c:45
void test_rw(void)
Definition: rwlock.c:263
M0_INTERNAL void m0_rwlock_read_lock(struct m0_rwlock *lock)
Definition: rwlock.c:52
static void writer(int n)
Definition: rwlock.c:59
static void test_rw_readers(void)
Definition: rwlock.c:139
M0_INTERNAL void m0_rwlock_fini(struct m0_rwlock *lock)
Definition: rwlock.c:37
Definition: rwlock.c:42
M0_INTERNAL void m0_rwlock_read_unlock(struct m0_rwlock *lock)
Definition: rwlock.c:57
M0_INTERNAL void m0_semaphore_down(struct m0_semaphore *semaphore)
Definition: semaphore.c:49
Definition: rwlock.c:45
M0_INTERNAL void m0_semaphore_up(struct m0_semaphore *semaphore)
Definition: semaphore.c:65
#define M0_UT_ASSERT(a)
Definition: ut.h:46
Definition: rwlock.c:34
static void wcheck(int x)
Definition: rwlock.c:106
static void test_rw_wstarve(void)
Definition: rwlock.c:234