/** * validates the following * * writer is excluded while another thread holds the rwmutex for read * once reader exits writer can enter */ TEST(RWMutex, WritersExcludedTest) { SupportThreadInfo *info; omrthread_entrypoint_t functionsToRun[2]; functionsToRun[0] = (omrthread_entrypoint_t) &enter_rwmutex_write; functionsToRun[1] = (omrthread_entrypoint_t) &exit_rwmutex_write; info = createSupportThreadInfo(functionsToRun, 2); /* first enter the mutex for read */ ASSERT_TRUE(0 == info->writeCounter); omrthread_rwmutex_enter_read(info->handle); /* start the concurrent thread that will try to enter for write and * check that it is blocked */ startConcurrentThread(info); ASSERT_TRUE(0 == info->writeCounter); /* now release the rwmutex and validate that the thread enters it */ omrthread_monitor_enter(info->synchronization); omrthread_rwmutex_exit_read(info->handle); omrthread_monitor_wait_interruptable(info->synchronization, MILLI_TIMEOUT, NANO_TIMEOUT); omrthread_monitor_exit(info->synchronization); ASSERT_TRUE(1 == info->writeCounter); /* done now so ask thread to release and clean up */ triggerNextStepDone(info); ASSERT_TRUE(0 == info->writeCounter); freeSupportThreadInfo(info); }
/** * This step exits the rwmutex in the SupporThreadInfo for read * @param info the SupporThreadInfo which can be used by the step */ static intptr_t J9THREAD_PROC exit_rwmutex_read(SupportThreadInfo *info) { omrthread_rwmutex_exit_read(info->handle); info->readCounter--; return 0; }
/** * Validate that we can enter/exit a RWMutex for read */ TEST(RWMutex, RWReadEnterExitTest) { intptr_t result; omrthread_rwmutex_t handle; uintptr_t flags = 0; const char *mutexName = "test_mutex"; result = omrthread_rwmutex_init(&handle, flags, mutexName); ASSERT_TRUE(0 == result); result = omrthread_rwmutex_enter_read(handle); ASSERT_TRUE(0 == result); result = omrthread_rwmutex_exit_read(handle); ASSERT_TRUE(0 == result); /* clean up */ result = omrthread_rwmutex_destroy(handle); ASSERT_TRUE(0 == result); }
TEST(RWMutex, MultipleReadersTest) { SupportThreadInfo *info; omrthread_entrypoint_t functionsToRun[2]; functionsToRun[0] = (omrthread_entrypoint_t) &enter_rwmutex_read; functionsToRun[1] = (omrthread_entrypoint_t) &exit_rwmutex_read; info = createSupportThreadInfo(functionsToRun, 2); startConcurrentThread(info); /* now the concurrent thread should have acquired the rwmutex * so validate that we can acquire it as well */ ASSERT_TRUE(1 == info->readCounter); omrthread_rwmutex_enter_read(info->handle); ASSERT_TRUE(1 == info->readCounter); omrthread_rwmutex_exit_read(info->handle); /* ok we were not blocked by the other thread holding the mutex for read * so ask it to release the mutex */ triggerNextStepDone(info); ASSERT_TRUE(0 == info->readCounter); freeSupportThreadInfo(info); }
/** * Validate that is_writelocked return true in writing state */ TEST(RWMutex, IsWriteLockedTest) { intptr_t result; omrthread_rwmutex_t handle; uintptr_t flags = 0; BOOLEAN ret; const char *mutexName = "test_mutex"; result = omrthread_rwmutex_init(&handle, flags, mutexName); ASSERT_TRUE(0 == result); ret = omrthread_rwmutex_is_writelocked(handle); ASSERT_TRUE(FALSE == ret); result = omrthread_rwmutex_enter_read(handle); ASSERT_TRUE(0 == result); ret = omrthread_rwmutex_is_writelocked(handle); ASSERT_TRUE(FALSE == ret); result = omrthread_rwmutex_exit_read(handle); ASSERT_TRUE(0 == result); result = omrthread_rwmutex_enter_write(handle); ASSERT_TRUE(0 == result); ret = omrthread_rwmutex_is_writelocked(handle); ASSERT_TRUE(TRUE == ret); result = omrthread_rwmutex_exit_write(handle); ASSERT_TRUE(0 == result); /* clean up */ result = omrthread_rwmutex_destroy(handle); ASSERT_TRUE(0 == result); }
/* validates the following * * reader can enter rwmutex even if write is pending (waiting on another reader) * 2nd reader to enter rwmutex continues to block write after first thread exits */ TEST(RWMutex, SecondReaderExcludesWrite) { omrthread_rwmutex_t saveHandle; SupportThreadInfo *info; SupportThreadInfo *infoReader; omrthread_entrypoint_t functionsToRun[2]; omrthread_entrypoint_t functionsToRunReader[2]; /* set up the steps for the 2 concurrent threads */ functionsToRun[0] = (omrthread_entrypoint_t) &enter_rwmutex_write; functionsToRun[1] = (omrthread_entrypoint_t) &exit_rwmutex_write; functionsToRunReader[0] = (omrthread_entrypoint_t) &enter_rwmutex_read; functionsToRunReader[1] = (omrthread_entrypoint_t) &exit_rwmutex_read; info = createSupportThreadInfo(functionsToRun, 2); infoReader = createSupportThreadInfo(functionsToRunReader, 2); /* set the two SupporThreadInfo structures so that they use the same rwmutex */ saveHandle = infoReader->handle; infoReader->handle = info->handle; /* first enter the mutex for read */ ASSERT_TRUE(0 == info->writeCounter); omrthread_rwmutex_enter_read(info->handle); /* start the concurrent thread that will try to enter for write and * check that it is blocked */ startConcurrentThread(info); ASSERT_TRUE(0 == info->writeCounter); /* start the concurrent thread that will try to enter for read and * check that it is not blocked */ startConcurrentThread(infoReader); ASSERT_TRUE(1 == infoReader->readCounter); /* now release the rwmutex and validate that the second readers still excludes the writer */ omrthread_monitor_enter(info->synchronization); omrthread_rwmutex_exit_read(infoReader->handle); ASSERT_TRUE(0 == info->writeCounter); ASSERT_TRUE(1 == infoReader->readCounter); /* now ask the reader to exit the mutex */ triggerNextStepDone(infoReader); ASSERT_TRUE(0 == infoReader->readCounter); /* now validate that the writer has now entered the mutex */ omrthread_monitor_wait_interruptable(info->synchronization, MILLI_TIMEOUT, NANO_TIMEOUT); omrthread_monitor_exit(info->synchronization); ASSERT_TRUE(1 == info->writeCounter); /* ok now let the writer exit */ triggerNextStepDone(info); ASSERT_TRUE(0 == info->writeCounter); /* now let the threads clean up. First fix up handle in infoReader so that we * can clean up properly */ infoReader->handle = saveHandle; freeSupportThreadInfo(info); freeSupportThreadInfo(infoReader); }
void CRWMutex::ExitRead(void) { omrthread_rwmutex_exit_read(m_monitor); }