Changeset 24352 in vbox for trunk/src/VBox
- Timestamp:
- Nov 4, 2009 6:49:05 PM (15 years ago)
- Location:
- trunk/src/VBox/Runtime/testcase
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/testcase/Makefile.kmk
r23960 r24352 90 90 tstRTS3 \ 91 91 tstSems \ 92 tstSemEvent \ 92 93 tstSemPingPong \ 93 94 tstRTStrCache \ … … 356 357 tstSemMutex_SOURCES = tstSemMutex.cpp 357 358 359 tstSemEvent_SOURCES = tstSemEvent.cpp 360 358 361 tstSemRW_SOURCES = tstSemRW.cpp 359 362 -
trunk/src/VBox/Runtime/testcase/tstSemEvent.cpp
r24286 r24352 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT Testcase - Reader/WriterSemaphore Test.3 * IPRT Testcase - Event Semaphore Test. 4 4 */ 5 5 … … 46 46 * Global Variables * 47 47 *******************************************************************************/ 48 static RTSEMRW g_hSemRW = NIL_RTSEMRW; 49 static bool volatile g_fTerminate; 50 static bool g_fYield; 51 static bool g_fQuiet; 52 static unsigned g_uWritePercent; 53 static uint32_t volatile g_cbConcurrentWrite; 54 static uint32_t volatile g_cbConcurrentRead; 48 static RTSEMEVENTMULTI g_hSemEM = NIL_RTSEMEVENTMULTI; 55 49 static uint32_t volatile g_cErrors; 56 50 … … 60 54 ASMAtomicIncU32(&g_cErrors); 61 55 62 RTPrintf("tstSem RW: FAILURE - ");56 RTPrintf("tstSemEvent: FAILURE - "); 63 57 va_list va; 64 58 va_start(va, pszFormat); … … 72 66 int ThreadTest1(RTTHREAD ThreadSelf, void *pvUser) 73 67 { 74 // Use randomization to get a little more variation of the sync pattern 75 unsigned c100 = RTRandU32Ex(0, 99); 76 uint64_t *pu64 = (uint64_t *)pvUser; 77 bool fWrite; 78 for (;;) 68 int rc; 69 rc = RTSemEventMultiWait(g_hSemEM, 1000); 70 if (rc != VERR_TIMEOUT) 79 71 { 80 int rc; 81 unsigned readrec = RTRandU32Ex(0, 3); 82 unsigned writerec = RTRandU32Ex(0, 3); 83 /* Don't overdo recursion testing. */ 84 if (readrec > 1) 85 readrec--; 86 if (writerec > 1) 87 writerec--; 72 PrintError("Thread 1: unexpected result of first RTSemEventMultiWait %Rrc\n", rc); 73 return VINF_SUCCESS; 74 } 88 75 89 fWrite = (c100 < g_uWritePercent); 90 if (fWrite) 91 { 92 for (unsigned i = 0; i <= writerec; i++) 93 { 94 rc = RTSemRWRequestWriteNoResume(g_hSemRW, RT_INDEFINITE_WAIT); 95 if (RT_FAILURE(rc)) 96 { 97 PrintError("%x: RTSemRWRequestWriteNoResume failed with %Rrc\n", rc); 98 break; 99 } 100 } 101 if (RT_FAILURE(rc)) 102 break; 103 if (ASMAtomicIncU32(&g_cbConcurrentWrite) != 1) 104 { 105 PrintError("g_cbConcurrentWrite=%d after request!\n", g_cbConcurrentWrite); 106 break; 107 } 108 if (g_cbConcurrentRead != 0) 109 { 110 PrintError("g_cbConcurrentRead=%d after request!\n", g_cbConcurrentRead); 111 break; 112 } 113 } 114 else 115 { 116 rc = RTSemRWRequestReadNoResume(g_hSemRW, RT_INDEFINITE_WAIT); 117 if (RT_FAILURE(rc)) 118 { 119 PrintError("%x: RTSemRWRequestReadNoResume failed with %Rrc\n", rc); 120 break; 121 } 122 ASMAtomicIncU32(&g_cbConcurrentRead); 123 if (g_cbConcurrentWrite != 0) 124 { 125 PrintError("g_cbConcurrentWrite=%d after request!\n", g_cbConcurrentWrite); 126 break; 127 } 128 } 129 for (unsigned i = 0; i < readrec; i++) 130 { 131 rc = RTSemRWRequestReadNoResume(g_hSemRW, RT_INDEFINITE_WAIT); 132 if (RT_FAILURE(rc)) 133 { 134 PrintError("%x: RTSemRWRequestReadNoResume failed with %Rrc\n", rc); 135 break; 136 } 137 } 138 if (RT_FAILURE(rc)) 139 break; 76 rc = RTSemEventMultiWait(g_hSemEM, 1000); 77 if (RT_FAILURE(rc)) 78 { 79 PrintError("Thread 1: unexpected result of second RTSemEventMultiWait %Rrc\n", rc); 80 return VINF_SUCCESS; 81 } 140 82 141 /* 142 * Check for fairness: The values of the threads should not differ too much 143 */ 144 (*pu64)++; 145 146 /* 147 * Check for correctness: Give other threads a chance. If the implementation is 148 * correct, no other thread will be able to enter this lock now. 149 */ 150 if (g_fYield) 151 RTThreadYield(); 152 153 for (unsigned i = 0; i < readrec; i++) 154 { 155 rc = RTSemRWReleaseRead(g_hSemRW); 156 if (RT_FAILURE(rc)) 157 { 158 PrintError("%x: RTSemRWReleaseRead failed with %Rrc\n", rc); 159 break; 160 } 161 } 162 if (RT_FAILURE(rc)) 163 break; 164 165 if (fWrite) 166 { 167 if (ASMAtomicDecU32(&g_cbConcurrentWrite) != 0) 168 { 169 PrintError("g_cbConcurrentWrite=%d before release!\n", g_cbConcurrentWrite); 170 break; 171 } 172 if (g_cbConcurrentRead != 0) 173 { 174 PrintError("g_cbConcurrentRead=%d before release!\n", g_cbConcurrentRead); 175 break; 176 } 177 for (unsigned i = 0; i <= writerec; i++) 178 { 179 rc = RTSemRWReleaseWrite(g_hSemRW); 180 if (RT_FAILURE(rc)) 181 { 182 PrintError("%x: RTSemRWReleaseWrite failed with %Rrc\n", rc); 183 break; 184 } 185 } 186 } 187 else 188 { 189 if (g_cbConcurrentWrite != 0) 190 { 191 PrintError("g_cbConcurrentWrite=%d before release!\n", g_cbConcurrentWrite); 192 break; 193 } 194 ASMAtomicDecU32(&g_cbConcurrentRead); 195 rc = RTSemRWReleaseRead(g_hSemRW); 196 if (RT_FAILURE(rc)) 197 { 198 PrintError("%x: RTSemRWReleaseRead failed with %Rrc\n", rc); 199 break; 200 } 201 } 202 203 if (g_fTerminate) 204 break; 205 206 c100++; 207 c100 %= 100; 208 } 209 if (!g_fQuiet) 210 RTPrintf("tstSemRW: Thread %08x exited with %lld\n", ThreadSelf, *pu64); 83 RTPrintf("tstSemEvent: Thread 1 normal exit...\n"); 211 84 return VINF_SUCCESS; 212 85 } 213 86 214 87 215 static int Test1(unsigned cThreads, unsigned cSeconds, unsigned uWritePercent, bool fYield, bool fQuiet)88 int ThreadTest2(RTTHREAD ThreadSelf, void *pvUser) 216 89 { 217 90 int rc; 218 unsigned i; 219 uint64_t g_au64[32]; 220 RTTHREAD aThreads[RT_ELEMENTS(g_au64)]; 221 AssertRelease(cThreads <= RT_ELEMENTS(g_au64)); 91 rc = RTSemEventMultiWait(g_hSemEM, RT_INDEFINITE_WAIT); 92 if (RT_FAILURE(rc)) 93 { 94 PrintError("Thread 2: unexpected result of RTSemEventMultiWait %Rrc\n", rc); 95 return VINF_SUCCESS; 96 } 97 98 RTPrintf("tstSemEvent: Thread 2 normal exit...\n"); 99 return VINF_SUCCESS; 100 } 101 102 103 static int Test1() 104 { 105 int rc; 106 RTTHREAD Thread1, Thread2; 107 108 rc = RTSemEventMultiCreate(&g_hSemEM); 109 if (RT_FAILURE(rc)) 110 return PrintError("RTSemEventMultiCreate failed (rc=%Rrc)\n", rc); 222 111 223 112 /* 224 * Init globals.113 * Create the threads and let them block on the event multi semaphore. 225 114 */ 226 g_fYield = fYield; 227 g_fQuiet = fQuiet; 228 g_fTerminate = false; 229 g_uWritePercent = uWritePercent; 230 g_cbConcurrentWrite = 0; 231 g_cbConcurrentRead = 0; 115 rc = RTSemEventMultiReset(g_hSemEM); 116 if (RT_FAILURE(rc)) 117 return PrintError("RTSemEventMultiReset failed (rc=%Rrc)\n", rc); 232 118 233 rc = RT SemRWCreate(&g_hSemRW);119 rc = RTThreadCreate(&Thread2, ThreadTest2, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test2"); 234 120 if (RT_FAILURE(rc)) 235 return PrintError("RTSemRWCreate failed (rc=%Rrc)\n", rc); 121 return PrintError("RTThreadCreate failed for thread 2 (rc=%Rrc)\n", rc); 122 RTThreadSleep(100); 236 123 237 /* 238 * Create the threads and let them block on the semrw. 239 */ 240 rc = RTSemRWRequestWrite(g_hSemRW, RT_INDEFINITE_WAIT); 124 rc = RTThreadCreate(&Thread1, ThreadTest1, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test1"); 241 125 if (RT_FAILURE(rc)) 242 return PrintError("RT SemRWRequestWrite failed(rc=%Rrc)\n", rc);126 return PrintError("RTThreadCreate failed for thread 1 (rc=%Rrc)\n", rc); 243 127 244 for (i = 0; i < cThreads; i++) 245 { 246 g_au64[i] = 0; 247 rc = RTThreadCreate(&aThreads[i], ThreadTest1, &g_au64[i], 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test"); 248 if (RT_FAILURE(rc)) 249 return PrintError("RTThreadCreate failed for thread %u (rc=%Rrc)\n", i, rc); 250 } 128 /* Force first thread (which has a timeout of 1 second) to timeout in the 129 * first wait, and the second wait will succeed. */ 130 RTThreadSleep(1500); 131 rc = RTSemEventMultiSignal(g_hSemEM); 132 if (RT_FAILURE(rc)) 133 PrintError("RTSemEventMultiSignal failed (rc=%Rrc)\n", rc); 251 134 252 if (!fQuiet)253 RTPrintf("tstSemRW: %zu Threads created. Racing them for %u seconds (%s) ...\n",254 cThreads, cSeconds, g_fYield ? "yielding" : "no yielding");135 rc = RTThreadWait(Thread1, 1000, NULL); 136 if (RT_FAILURE(rc)) 137 PrintError("RTThreadWait failed for thread 1 (rc=%Rrc)\n", rc); 255 138 256 uint64_t u64StartTS = RTTimeNanoTS(); 257 rc = RTSemRWReleaseWrite(g_hSemRW); 139 rc = RTThreadWait(Thread2, 1000, NULL); 258 140 if (RT_FAILURE(rc)) 259 PrintError("RTSemRWReleaseWrite failed (rc=%Rrc)\n", rc); 260 RTThreadSleep(cSeconds * 1000); 261 ASMAtomicXchgBool(&g_fTerminate, true); 262 uint64_t ElapsedNS = RTTimeNanoTS() - u64StartTS; 141 PrintError("RTThreadWait failed for thread 2 (rc=%Rrc)\n", rc); 263 142 264 for (i = 0; i < cThreads; i++) 265 { 266 rc = RTThreadWait(aThreads[i], 5000, NULL); 267 if (RT_FAILURE(rc)) 268 PrintError("RTThreadWait failed for thread %u (rc=%Rrc)\n", i, rc); 269 } 270 271 if (g_cbConcurrentWrite != 0) 272 PrintError("g_cbConcurrentWrite=%d at end of test!\n", g_cbConcurrentWrite); 273 if (g_cbConcurrentRead != 0) 274 PrintError("g_cbConcurrentRead=%d at end of test!\n", g_cbConcurrentRead); 275 276 rc = RTSemRWDestroy(g_hSemRW); 143 rc = RTSemEventMultiDestroy(g_hSemEM); 277 144 if (RT_FAILURE(rc)) 278 PrintError("RTSem RWDestroy failed - %Rrc\n", rc);279 g_hSem RW = NIL_RTSEMRW;145 PrintError("RTSemEventMultiDestroy failed - %Rrc\n", rc); 146 g_hSemEM = NIL_RTSEMEVENTMULTI; 280 147 if (g_cErrors) 281 148 RTThreadSleep(100); 282 283 /*284 * Collect and display the results.285 */286 uint64_t Total = g_au64[0];287 for (i = 1; i < cThreads; i++)288 Total += g_au64[i];289 290 uint64_t Normal = Total / cThreads;291 uint64_t MaxDeviation = 0;292 for (i = 0; i < cThreads; i++)293 {294 uint64_t Delta = RT_ABS((int64_t)(g_au64[i] - Normal));295 if (Delta > Normal / 2)296 RTPrintf("tstSemRW: Warning! Thread %d deviates by more than 50%% - %llu (it) vs. %llu (avg)\n",297 i, g_au64[i], Normal);298 if (Delta > MaxDeviation)299 MaxDeviation = Delta;300 301 }302 303 RTPrintf("tstSemRW: Threads: %u Total: %llu Per Sec: %llu Avg: %llu ns Max dev: %llu%%\n",304 cThreads,305 Total,306 Total / cSeconds,307 ElapsedNS / Total,308 MaxDeviation * 100 / Normal309 );310 149 return 0; 311 150 } … … 317 156 if (RT_FAILURE(rc)) 318 157 { 319 RTPrintf("tstSem RW: RTR3Init failed (rc=%Rrc)\n", rc);158 RTPrintf("tstSemEvent: RTR3Init failed (rc=%Rrc)\n", rc); 320 159 return 1; 321 160 } 322 RTPrintf("tstSemRW: TESTING...\n"); 323 324 if (argc == 1) 325 { 326 /* threads, seconds, writePercent, yield, quiet */ 327 Test1( 1, 1, 0, true, false); 328 Test1( 1, 1, 1, true, false); 329 Test1( 1, 1, 5, true, false); 330 Test1( 2, 1, 3, true, false); 331 Test1( 10, 1, 5, true, false); 332 Test1( 10, 10, 10, false, false); 333 334 RTPrintf("tstSemRW: benchmarking...\n"); 335 for (unsigned cThreads = 1; cThreads < 32; cThreads++) 336 Test1(cThreads, 2, 1, false, true); 337 338 /** @todo add a testcase where some stuff times out. */ 339 } 340 else 341 { 342 /* threads, seconds, writePercent, yield, quiet */ 343 RTPrintf("tstSemRW: benchmarking...\n"); 344 Test1( 1, 3, 1, false, true); 345 Test1( 1, 3, 1, false, true); 346 Test1( 1, 3, 1, false, true); 347 Test1( 2, 3, 1, false, true); 348 Test1( 2, 3, 1, false, true); 349 Test1( 2, 3, 1, false, true); 350 Test1( 3, 3, 1, false, true); 351 Test1( 3, 3, 1, false, true); 352 Test1( 3, 3, 1, false, true); 353 } 161 RTPrintf("tstSemEvent: TESTING...\n"); 162 Test1(); 354 163 355 164 if (!g_cErrors) 356 RTPrintf("tstSem RW: SUCCESS\n");165 RTPrintf("tstSemEvent: SUCCESS\n"); 357 166 else 358 RTPrintf("tstSem RW: FAILURE - %u errors\n", g_cErrors);167 RTPrintf("tstSemEvent: FAILURE - %u errors\n", g_cErrors); 359 168 return g_cErrors != 0; 360 169 }
Note:
See TracChangeset
for help on using the changeset viewer.