VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTCritSectRw.cpp@ 100762

Last change on this file since 100762 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 21.9 KB
Line 
1/* $Id: tstRTCritSectRw.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT Testcase - Reader/Writer Critical Sections.
4 */
5
6/*
7 * Copyright (C) 2009-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/critsect.h>
42
43#include <iprt/asm.h>
44#include <iprt/assert.h>
45#include <iprt/err.h>
46#include <iprt/initterm.h>
47#include <iprt/lockvalidator.h>
48#include <iprt/mp.h>
49#include <iprt/rand.h>
50#include <iprt/semaphore.h>
51#include <iprt/string.h>
52#include <iprt/stream.h>
53#include <iprt/test.h>
54#include <iprt/time.h>
55#include <iprt/thread.h>
56
57
58/*********************************************************************************************************************************
59* Global Variables *
60*********************************************************************************************************************************/
61static RTTEST g_hTest;
62static RTCRITSECTRW g_CritSectRw;
63static bool volatile g_fTerminate;
64static bool g_fYield;
65static bool g_fQuiet;
66static unsigned g_uWritePercent;
67static uint32_t volatile g_cConcurrentWriters;
68static uint32_t volatile g_cConcurrentReaders;
69
70
71static DECLCALLBACK(int) Test4Thread(RTTHREAD ThreadSelf, void *pvUser)
72{
73 /* Use randomization to get a little more variation of the sync pattern.
74 We use a pseudo random generator here so that we don't end up testing
75 the speed of the /dev/urandom implementation, but rather the read-write
76 semaphores. */
77 int rc;
78 RTRAND hRand;
79 RTTEST_CHECK_RC_OK_RET(g_hTest, rc = RTRandAdvCreateParkMiller(&hRand), rc);
80 RTTEST_CHECK_RC_OK_RET(g_hTest, rc = RTRandAdvSeed(hRand, (uintptr_t)ThreadSelf), rc);
81 unsigned c100 = RTRandAdvU32Ex(hRand, 0, 99);
82
83 uint64_t *pcItr = (uint64_t *)pvUser;
84 bool fWrite;
85 for (;;)
86 {
87 unsigned readrec = RTRandAdvU32Ex(hRand, 0, 3);
88 unsigned writerec = RTRandAdvU32Ex(hRand, 0, 3);
89 /* Don't overdo recursion testing. */
90 if (readrec > 1)
91 readrec--;
92 if (writerec > 1)
93 writerec--;
94
95 fWrite = (c100 < g_uWritePercent);
96 if (fWrite)
97 {
98 for (unsigned i = 0; i <= writerec; i++)
99 {
100 rc = RTCritSectRwEnterExcl(&g_CritSectRw);
101 if (RT_FAILURE(rc))
102 {
103 RTTestFailed(g_hTest, "Write recursion %u on %s failed with rc=%Rrc", i, RTThreadSelfName(), rc);
104 break;
105 }
106 }
107 if (RT_FAILURE(rc))
108 break;
109 if (ASMAtomicIncU32(&g_cConcurrentWriters) != 1)
110 {
111 RTTestFailed(g_hTest, "g_cConcurrentWriters=%u on %s after write locking it",
112 g_cConcurrentWriters, RTThreadSelfName());
113 break;
114 }
115 if (g_cConcurrentReaders != 0)
116 {
117 RTTestFailed(g_hTest, "g_cConcurrentReaders=%u on %s after write locking it",
118 g_cConcurrentReaders, RTThreadSelfName());
119 break;
120 }
121 }
122 else
123 {
124 rc = RTCritSectRwEnterShared(&g_CritSectRw);
125 if (RT_FAILURE(rc))
126 {
127 RTTestFailed(g_hTest, "Read locking on %s failed with rc=%Rrc", RTThreadSelfName(), rc);
128 break;
129 }
130 ASMAtomicIncU32(&g_cConcurrentReaders);
131 if (g_cConcurrentWriters != 0)
132 {
133 RTTestFailed(g_hTest, "g_cConcurrentWriters=%u on %s after read locking it",
134 g_cConcurrentWriters, RTThreadSelfName());
135 break;
136 }
137 }
138 for (unsigned i = 0; i < readrec; i++)
139 {
140 rc = RTCritSectRwEnterShared(&g_CritSectRw);
141 if (RT_FAILURE(rc))
142 {
143 RTTestFailed(g_hTest, "Read recursion %u on %s failed with rc=%Rrc", i, RTThreadSelfName(), rc);
144 break;
145 }
146 }
147 if (RT_FAILURE(rc))
148 break;
149
150 /*
151 * Check for fairness: The values of the threads should not differ too much
152 */
153 (*pcItr)++;
154
155 /*
156 * Check for correctness: Give other threads a chance. If the implementation is
157 * correct, no other thread will be able to enter this lock now.
158 */
159 if (g_fYield)
160 RTThreadYield();
161
162 for (unsigned i = 0; i < readrec; i++)
163 {
164 rc = RTCritSectRwLeaveShared(&g_CritSectRw);
165 if (RT_FAILURE(rc))
166 {
167 RTTestFailed(g_hTest, "Read release %u on %s failed with rc=%Rrc", i, RTThreadSelfName(), rc);
168 break;
169 }
170 }
171 if (RT_FAILURE(rc))
172 break;
173
174 if (fWrite)
175 {
176 if (ASMAtomicDecU32(&g_cConcurrentWriters) != 0)
177 {
178 RTTestFailed(g_hTest, "g_cConcurrentWriters=%u on %s before write release",
179 g_cConcurrentWriters, RTThreadSelfName());
180 break;
181 }
182 if (g_cConcurrentReaders != 0)
183 {
184 RTTestFailed(g_hTest, "g_cConcurrentReaders=%u on %s before write release",
185 g_cConcurrentReaders, RTThreadSelfName());
186 break;
187 }
188 for (unsigned i = 0; i <= writerec; i++)
189 {
190 rc = RTCritSectRwLeaveExcl(&g_CritSectRw);
191 if (RT_FAILURE(rc))
192 {
193 RTTestFailed(g_hTest, "Write release %u on %s failed with rc=%Rrc", i, RTThreadSelfName(), rc);
194 break;
195 }
196 }
197 }
198 else
199 {
200 if (g_cConcurrentWriters != 0)
201 {
202 RTTestFailed(g_hTest, "g_cConcurrentWriters=%u on %s before read release",
203 g_cConcurrentWriters, RTThreadSelfName());
204 break;
205 }
206 ASMAtomicDecU32(&g_cConcurrentReaders);
207 rc = RTCritSectRwLeaveShared(&g_CritSectRw);
208 if (RT_FAILURE(rc))
209 {
210 RTTestFailed(g_hTest, "Read release on %s failed with rc=%Rrc", RTThreadSelfName(), rc);
211 break;
212 }
213 }
214
215 if (g_fTerminate)
216 break;
217
218 c100++;
219 c100 %= 100;
220 }
221 if (!g_fQuiet)
222 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Thread %s exited with %lld\n", RTThreadSelfName(), *pcItr);
223 RTRandAdvDestroy(hRand);
224 return VINF_SUCCESS;
225}
226
227
228static void Test4(unsigned cThreads, unsigned cSeconds, unsigned uWritePercent, bool fYield, bool fQuiet)
229{
230 unsigned i;
231 uint64_t acIterations[32];
232 RTTHREAD aThreads[RT_ELEMENTS(acIterations)];
233 AssertRelease(cThreads <= RT_ELEMENTS(acIterations));
234
235 RTTestSubF(g_hTest, "Test4 - %u threads, %u sec, %u%% writes, %syielding",
236 cThreads, cSeconds, uWritePercent, fYield ? "" : "non-");
237
238 /*
239 * Init globals.
240 */
241 g_fYield = fYield;
242 g_fQuiet = fQuiet;
243 g_fTerminate = false;
244 g_uWritePercent = uWritePercent;
245 g_cConcurrentWriters = 0;
246 g_cConcurrentReaders = 0;
247
248 RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectRwInit(&g_CritSectRw), VINF_SUCCESS);
249
250 /*
251 * Create the threads and let them block on the semrw.
252 */
253 RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectRwEnterExcl(&g_CritSectRw), VINF_SUCCESS);
254
255 for (i = 0; i < cThreads; i++)
256 {
257 acIterations[i] = 0;
258 RTTEST_CHECK_RC_RETV(g_hTest, RTThreadCreateF(&aThreads[i], Test4Thread, &acIterations[i], 0,
259 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE,
260 "test-%u", i), VINF_SUCCESS);
261 }
262
263 /*
264 * Do the test run.
265 */
266 uint32_t cErrorsBefore = RTTestErrorCount(g_hTest);
267 uint64_t u64StartTS = RTTimeNanoTS();
268 RTTEST_CHECK_RC(g_hTest, RTCritSectRwLeaveExcl(&g_CritSectRw), VINF_SUCCESS);
269 RTThreadSleep(cSeconds * 1000);
270 ASMAtomicWriteBool(&g_fTerminate, true);
271 uint64_t ElapsedNS = RTTimeNanoTS() - u64StartTS;
272
273 /*
274 * Clean up the threads and semaphore.
275 */
276 for (i = 0; i < cThreads; i++)
277 RTTEST_CHECK_RC(g_hTest, RTThreadWait(aThreads[i], 5000, NULL), VINF_SUCCESS);
278
279 RTTEST_CHECK_MSG(g_hTest, g_cConcurrentWriters == 0, (g_hTest, "g_cConcurrentWriters=%u at end of test\n", g_cConcurrentWriters));
280 RTTEST_CHECK_MSG(g_hTest, g_cConcurrentReaders == 0, (g_hTest, "g_cConcurrentReaders=%u at end of test\n", g_cConcurrentReaders));
281
282 RTTEST_CHECK_RC(g_hTest, RTCritSectRwDelete(&g_CritSectRw), VINF_SUCCESS);
283
284 if (RTTestErrorCount(g_hTest) != cErrorsBefore)
285 RTThreadSleep(100);
286
287 /*
288 * Collect and display the results.
289 */
290 uint64_t cItrTotal = acIterations[0];
291 for (i = 1; i < cThreads; i++)
292 cItrTotal += acIterations[i];
293
294 uint64_t cItrNormal = cItrTotal / cThreads;
295 uint64_t cItrMinOK = cItrNormal / 20; /* 5% */
296 uint64_t cItrMaxDeviation = 0;
297 for (i = 0; i < cThreads; i++)
298 {
299 uint64_t cItrDelta = RT_ABS((int64_t)(acIterations[i] - cItrNormal));
300 if (acIterations[i] < cItrMinOK)
301 RTTestFailed(g_hTest, "Thread %u did less than 5%% of the iterations - %llu (it) vs. %llu (5%%) - %llu%%\n",
302 i, acIterations[i], cItrMinOK, cItrDelta * 100 / cItrNormal);
303 else if (cItrDelta > cItrNormal / 2)
304 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS,
305 "Warning! Thread %u deviates by more than 50%% - %llu (it) vs. %llu (avg) - %llu%%\n",
306 i, acIterations[i], cItrNormal, cItrDelta * 100 / cItrNormal);
307 if (cItrDelta > cItrMaxDeviation)
308 cItrMaxDeviation = cItrDelta;
309
310 }
311
312 //RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS,
313 // "Threads: %u Total: %llu Per Sec: %llu Avg: %llu ns Max dev: %llu%%\n",
314 // cThreads,
315 // cItrTotal,
316 // cItrTotal / cSeconds,
317 // ElapsedNS / cItrTotal,
318 // cItrMaxDeviation * 100 / cItrNormal
319 // );
320 //
321 RTTestValue(g_hTest, "Thruput", cItrTotal * UINT32_C(1000000000) / ElapsedNS, RTTESTUNIT_CALLS_PER_SEC);
322 RTTestValue(g_hTest, "Max diviation", cItrMaxDeviation * 100 / cItrNormal, RTTESTUNIT_PCT);
323}
324
325
326static void TestNegative(void)
327{
328 RTTestSub(g_hTest, "Negative");
329 bool fSavedAssertQuiet = RTAssertSetQuiet(true);
330 bool fSavedAssertMayPanic = RTAssertSetMayPanic(false);
331 bool fSavedLckValEnabled = RTLockValidatorSetEnabled(false);
332
333 RTCRITSECTRW CritSectRw;
334 RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectRwInit(&CritSectRw), VINF_SUCCESS);
335
336 RTTEST_CHECK_RC(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VERR_NOT_OWNER);
337 RTTEST_CHECK_RC(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VERR_NOT_OWNER);
338
339 RTTEST_CHECK_RC(g_hTest, RTCritSectRwEnterExcl(&CritSectRw), VINF_SUCCESS);
340 RTTEST_CHECK_RC(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VERR_NOT_OWNER);
341
342 RTTEST_CHECK_RC(g_hTest, RTCritSectRwEnterShared(&CritSectRw), VINF_SUCCESS);
343 RTTEST_CHECK_RC(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VERR_WRONG_ORDER); /* cannot release the final write before the reads. */
344 RTTEST_CHECK_RC(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VINF_SUCCESS);
345 RTTEST_CHECK_RC(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS);
346
347 RTTEST_CHECK_RC(g_hTest, RTCritSectRwDelete(&CritSectRw), VINF_SUCCESS);
348
349 RTLockValidatorSetEnabled(fSavedLckValEnabled);
350 RTAssertSetMayPanic(fSavedAssertMayPanic);
351 RTAssertSetQuiet(fSavedAssertQuiet);
352}
353
354
355static bool Test1(void)
356{
357 RTTestSub(g_hTest, "Basics");
358
359 RTCRITSECTRW CritSectRw;
360 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwInit(&CritSectRw), VINF_SUCCESS, false);
361 RTTEST_CHECK_RET(g_hTest, RTCritSectRwIsInitialized(&CritSectRw), false);
362
363 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterShared(&CritSectRw), VINF_SUCCESS, false);
364 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VINF_SUCCESS, false);
365
366 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterShared(&CritSectRw), VINF_SUCCESS, false);
367 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterShared(&CritSectRw), VINF_SUCCESS, false);
368 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VINF_SUCCESS, false);
369 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VINF_SUCCESS, false);
370
371 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterExcl(&CritSectRw), VINF_SUCCESS, false);
372 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false);
373
374 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterExcl(&CritSectRw), VINF_SUCCESS, false);
375 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterExcl(&CritSectRw), VINF_SUCCESS, false);
376 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false);
377 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false);
378
379 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterExcl(&CritSectRw), VINF_SUCCESS, false);
380 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterShared(&CritSectRw), VINF_SUCCESS, false);
381 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VINF_SUCCESS, false);
382 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false);
383
384 for (int iRun = 0; iRun < 3; iRun++)
385 {
386 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterExcl(&CritSectRw), VINF_SUCCESS, false);
387 RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriteRecursion(&CritSectRw) == 1, false);
388 RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriterReadRecursion(&CritSectRw) == 0, false);
389 RTTEST_CHECK_RET(g_hTest, RTCritSectRwIsWriteOwner(&CritSectRw) == true, false);
390
391 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterExcl(&CritSectRw), VINF_SUCCESS, false);
392 RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriteRecursion(&CritSectRw) == 2, false);
393 RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriterReadRecursion(&CritSectRw) == 0, false);
394 RTTEST_CHECK_RET(g_hTest, RTCritSectRwIsWriteOwner(&CritSectRw) == true, false);
395
396 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterShared(&CritSectRw), VINF_SUCCESS, false);
397 RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriteRecursion(&CritSectRw) == 2, false);
398 RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriterReadRecursion(&CritSectRw) == 1, false);
399 RTTEST_CHECK_RET(g_hTest, RTCritSectRwIsWriteOwner(&CritSectRw) == true, false);
400
401 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwEnterExcl(&CritSectRw), VINF_SUCCESS, false);
402 RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriteRecursion(&CritSectRw) == 3, false);
403 RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriterReadRecursion(&CritSectRw) == 1, false);
404 RTTEST_CHECK_RET(g_hTest, RTCritSectRwIsWriteOwner(&CritSectRw) == true, false);
405
406 /* midway */
407
408 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false);
409 RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriteRecursion(&CritSectRw) == 2, false);
410 RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriterReadRecursion(&CritSectRw) == 1, false);
411 RTTEST_CHECK_RET(g_hTest, RTCritSectRwIsWriteOwner(&CritSectRw) == true, false);
412
413 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VINF_SUCCESS, false);
414 RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriteRecursion(&CritSectRw) == 2, false);
415 RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriterReadRecursion(&CritSectRw) == 0, false);
416 RTTEST_CHECK_RET(g_hTest, RTCritSectRwIsWriteOwner(&CritSectRw) == true, false);
417
418 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false);
419 RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriteRecursion(&CritSectRw) == 1, false);
420 RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriterReadRecursion(&CritSectRw) == 0, false);
421 RTTEST_CHECK_RET(g_hTest, RTCritSectRwIsWriteOwner(&CritSectRw) == true, false);
422
423 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false);
424 RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriteRecursion(&CritSectRw) == 0, false);
425 RTTEST_CHECK_RET(g_hTest, RTCritSectRwGetWriterReadRecursion(&CritSectRw) == 0, false);
426 RTTEST_CHECK_RET(g_hTest, RTCritSectRwIsWriteOwner(&CritSectRw) == false, false);
427 }
428
429 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwTryEnterShared(&CritSectRw), VINF_SUCCESS, false);
430 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VINF_SUCCESS, false);
431
432 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwTryEnterShared(&CritSectRw), VINF_SUCCESS, false);
433 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwTryEnterShared(&CritSectRw), VINF_SUCCESS, false);
434 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VINF_SUCCESS, false);
435 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VINF_SUCCESS, false);
436
437 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwTryEnterExcl(&CritSectRw), VINF_SUCCESS, false);
438 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false);
439
440 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwTryEnterExcl(&CritSectRw), VINF_SUCCESS, false);
441 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwTryEnterExcl(&CritSectRw), VINF_SUCCESS, false);
442 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false);
443 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false);
444
445 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwTryEnterExcl(&CritSectRw), VINF_SUCCESS, false);
446 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwTryEnterShared(&CritSectRw), VINF_SUCCESS, false);
447 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveShared(&CritSectRw), VINF_SUCCESS, false);
448 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwLeaveExcl(&CritSectRw), VINF_SUCCESS, false);
449
450
451 RTTEST_CHECK_RET(g_hTest, RTCritSectRwIsInitialized(&CritSectRw), false);
452 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectRwDelete(&CritSectRw), VINF_SUCCESS, false);
453 RTTEST_CHECK_RET(g_hTest, !RTCritSectRwIsInitialized(&CritSectRw), false);
454
455 return true;
456}
457
458int main(int argc, char **argv)
459{
460 RT_NOREF_PV(argv);
461 int rc = RTTestInitAndCreate("tstRTCritSectRw", &g_hTest);
462 if (rc)
463 return 1;
464 RTTestBanner(g_hTest);
465
466 if (Test1())
467 {
468 RTCPUID cCores = RTMpGetOnlineCoreCount();
469 if (argc == 1)
470 {
471 TestNegative();
472
473 /* threads, seconds, writePercent, yield, quiet */
474 Test4( 1, 1, 0, true, false);
475 Test4( 1, 1, 1, true, false);
476 Test4( 1, 1, 5, true, false);
477 Test4( 2, 1, 3, true, false);
478 Test4( 10, 1, 5, true, false);
479 Test4( 10, 10, 10, false, false);
480
481 if (cCores > 1)
482 {
483 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "benchmarking (%u CPU cores)...\n", cCores);
484 for (unsigned cThreads = 1; cThreads < 32; cThreads++)
485 Test4(cThreads, 2, 1, false, true);
486 }
487 else
488 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "skipping benchmarking (only %u core available)\n", cCores);
489
490 /** @todo add a testcase where some stuff times out. */
491 }
492 else
493 {
494 if (cCores > 1)
495 {
496 /* threads, seconds, writePercent, yield, quiet */
497 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "benchmarking (%u CPU cores)...\n", cCores);
498 Test4( 1, 3, 1, false, true);
499 Test4( 1, 3, 1, false, true);
500 Test4( 1, 3, 1, false, true);
501 Test4( 2, 3, 1, false, true);
502 Test4( 2, 3, 1, false, true);
503 Test4( 2, 3, 1, false, true);
504 Test4( 3, 3, 1, false, true);
505 Test4( 3, 3, 1, false, true);
506 Test4( 3, 3, 1, false, true);
507 }
508 else
509 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "skipping benchmarking (only %u core available)\n", cCores);
510 }
511 }
512
513 return RTTestSummaryAndDestroy(g_hTest);
514}
515
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette