VirtualBox

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

Last change on this file since 85546 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

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