TEST(TraceLifecycleTest, moduleUnloadAfterThreadDetach) { /* OMR VM data structures */ OMRTestVM testVM; OMR_VMThread *vmthread = NULL; omrthread_t childThread = NULL; ChildThreadData *childData = NULL; OMRPORT_ACCESS_FROM_OMRPORT(rasTestEnv->getPortLibrary()); char *datDir = getTraceDatDir(rasTestEnv->_argc, (const char **)rasTestEnv->_argv); OMRTEST_ASSERT_ERROR_NONE(omrTestVMInit(&testVM, OMRPORTLIB)); /* use small buffers to exercise buffer wrapping */ OMRTEST_ASSERT_ERROR_NONE(omr_ras_initTraceEngine(&testVM.omrVM, "buffers=1k:maximal=all:print=omr_test", datDir)); OMRTEST_ASSERT_ERROR_NONE(OMR_Thread_Init(&testVM.omrVM, NULL, &vmthread, "moduleLoadBeforeThreadAttach")); ASSERT_NO_FATAL_FAILURE(startChildThread(&testVM, &childThread, moduleUnloadAfterThreadDetachHelper, &childData)); ASSERT_EQ(1, omrthread_resume(childThread)); OMRTEST_ASSERT_ERROR_NONE(waitForChildThread(&testVM, childThread, childData)); /* Unload the module that was left loaded by the child thread */ UT_OMR_TEST_MODULE_UNLOADED(testVM.omrVM._trcEngine->utIntf); /* Now clear up the VM we started for this test case. */ OMRTEST_ASSERT_ERROR_NONE(omr_ras_cleanupTraceEngine(vmthread)); OMRTEST_ASSERT_ERROR_NONE(OMR_Thread_Free(vmthread)); OMRTEST_ASSERT_ERROR_NONE(omrTestVMFini(&testVM)); ASSERT_TRUE(NULL == (void *)omr_test_UtModuleInfo.intf); }
TEST(TraceLifecycleTest, threadAttachDetachStress) { /* OMR VM data structures */ OMRTestVM testVM; OMR_VMThread *vmthread = NULL; const int attachDetachHelpersCount = 10; omrthread_t attachDetachHelpers[attachDetachHelpersCount]; ChildThreadData *attachDetachData[attachDetachHelpersCount]; omrthread_t shutdownHelper = NULL; ChildThreadData *shutdownData = NULL; OMRPORT_ACCESS_FROM_OMRPORT(rasTestEnv->getPortLibrary()); char *datDir = getTraceDatDir(rasTestEnv->_argc, (const char **)rasTestEnv->_argv); OMRTEST_ASSERT_ERROR_NONE(omrTestVMInit(&testVM, OMRPORTLIB)); /* use small buffers to exercise buffer wrapping */ OMRTEST_ASSERT_ERROR_NONE(omr_ras_initTraceEngine(&testVM.omrVM, "buffers=1k:maximal=all", datDir)); /* Attach the thread to the trace engine */ OMRTEST_ASSERT_ERROR_NONE(OMR_Thread_Init(&testVM.omrVM, NULL, &vmthread, "registerSubscriberAfterShutdown")); UT_OMR_TEST_MODULE_LOADED(testVM.omrVM._trcEngine->utIntf); /* module is not unloaded before trace engine shutdown */ for (int i = 0; i < attachDetachHelpersCount; i++) { ASSERT_NO_FATAL_FAILURE(startChildThread(&testVM, &attachDetachHelpers[i], attachDetachHelper, &attachDetachData[i])); } ASSERT_NO_FATAL_FAILURE(startChildThread(&testVM, &shutdownHelper, shutdownTraceHelper, &shutdownData)); for (int i = 0; i < attachDetachHelpersCount; i++) { ASSERT_EQ(1, omrthread_resume(attachDetachHelpers[i])); } ASSERT_EQ(1, omrthread_resume(shutdownHelper)); for (int i = 0; i < attachDetachHelpersCount; i++) { OMRTEST_ASSERT_ERROR_NONE(waitForChildThread(&testVM, attachDetachHelpers[i], attachDetachData[i])); } OMRTEST_ASSERT_ERROR_NONE(waitForChildThread(&testVM, shutdownHelper, shutdownData)); /* Now clear up the VM we started for this test case. */ UT_OMR_TEST_MODULE_UNLOADED(testVM.omrVM._trcEngine->utIntf); OMRTEST_ASSERT_ERROR_NONE(OMR_Thread_Free(vmthread)); OMRTEST_ASSERT_ERROR_NONE(omrTestVMFini(&testVM)); ASSERT_TRUE(NULL == (void *)omr_test_UtModuleInfo.intf); }
static uintptr_t canCreateThread(const create_attr_t *expected, const omrthread_attr_t attr) { uintptr_t status = 0; uintptr_t rc; omrthread_t handle; threaddata_t data; data.expected = expected; data.status = 0; getCurrentOsSched(&data.curPriority, &data.curPolicy); rc = J9THREAD_VERBOSE(omrthread_create_ex(&handle, (attr? &attr : J9THREAD_ATTR_DEFAULT), 1, threadmain, &data)); if (J9THREAD_SUCCESS == rc) { OSTHREAD tid = handle->handle; omrthread_resume(handle); #if defined(SPEC_PTHREAD_API) #if defined(LINUX) /* bug? Linux can return a success code, but still fail to create the thread. * NOTE: It is not guaranteed that tid 0 is invalid in all pthread implementations. */ if (0 == tid) { omrTestEnv->log(LEVEL_ERROR, " LINUX: tid 0 returned\n"); status |= CREATE_FAILED; return status; } #endif /* defined(LINUX) */ /* this may fail because omrthreads detach themselves upon exiting */ #if defined(OSX) /* OSX TODO: Why do the tests segfault in child thread when accessing &data on OSX without a 1ms sleep? */ omrthread_sleep(10); #endif /* defined(OSX) */ PTHREAD_VERBOSE(pthread_join(tid, NULL)); status |= data.status; #elif defined(SPEC_WIN_API) WaitForSingleObject(tid, INFINITE); status |= data.status; #else /* In this case, * threadmain() doesn't access the expected data, so it's ok to continue without * waiting for the child thread to complete. */ #endif /* defined(SPEC_PTHREAD_API) */ } else { status |= CREATE_FAILED; } return status; }
TEST(JoinTest, joinLiveThread) { omrthread_t suspendedThr = NULL; omrthread_t joinHelperThr = NULL; JoinThreadHelperData helperData; /* suspend the child thread when it starts */ ASSERT_NO_FATAL_FAILURE(createThread(&suspendedThr, TRUE, J9THREAD_CREATE_JOINABLE, doNothingHelper, NULL)); /* create a thread to join on the suspended thread */ helperData.threadToJoin = suspendedThr; helperData.expectedRc = J9THREAD_SUCCESS; ASSERT_NO_FATAL_FAILURE(createThread(&joinHelperThr, FALSE, J9THREAD_CREATE_JOINABLE, joinThreadHelper, &helperData)); /* hopefully wait long enough for the join helper thread to start joining */ ASSERT_EQ(J9THREAD_SUCCESS, omrthread_sleep(3000)); /* resume the child thread */ printf("resuming suspendedThr\n"); fflush(stdout); ASSERT_EQ(1, omrthread_resume(suspendedThr)); VERBOSE_JOIN(joinHelperThr, J9THREAD_SUCCESS); }
/* * Tests: * - Attempt to log a tracepoint after trace engine shutdown started. * - Attempt to unload a module after trace engine shutdown started. * * If module unloading fails, this test case tends to cause later tests * to crash because the static omr_test_UtModuleInfo and omr_test_UtActive * structures are left in a polluted state. */ TEST(TraceLifecycleTest, traceAndModuleUnloadAfterTraceShutdown) { const OMR_TI *ti = omr_agent_getTI(); UtSubscription *subscriptionID = NULL; /* OMR VM data structures */ OMRTestVM testVM; OMR_VMThread *vmthread = NULL; /* child thread data */ omrthread_t shutdownTrcThr = NULL; ChildThreadData *shutdownTrcData = NULL; TracePointCountsMT tpCountsMT; TracePointCounts tpCounts[2]; tpCountsMT.numThreads = 2; tpCountsMT.tpCounts = tpCounts; memset(tpCounts, 0, sizeof(TracePointCounts) * 2); initWrapBuffer(&tpCounts[0].wrapBuffer); initWrapBuffer(&tpCounts[1].wrapBuffer); tpCounts[0].osThread = omrthread_self(); ASSERT_EQ(0, omrthread_monitor_init_with_name(&tpCountsMT.lock, 0, "&tpCountsMT.lock")); OMRPORT_ACCESS_FROM_OMRPORT(rasTestEnv->getPortLibrary()); char *datDir = getTraceDatDir(rasTestEnv->_argc, (const char **)rasTestEnv->_argv); OMRTEST_ASSERT_ERROR_NONE(omrTestVMInit(&testVM, OMRPORTLIB)); /* use small buffers to exercise buffer wrapping */ OMRTEST_ASSERT_ERROR_NONE(omr_ras_initTraceEngine(&testVM.omrVM, "buffers=1k:maximal=all:print=omr_test", datDir)); OMRTEST_ASSERT_ERROR_NONE(OMR_Thread_Init(&testVM.omrVM, NULL, &vmthread, "traceTest")); /* start counting tracepoints */ OMRTEST_ASSERT_ERROR_NONE( ti->RegisterRecordSubscriber(vmthread, "traceAndModuleUnloadAfterTraceShutdown", countTracepointsMT, NULL, (void *)&tpCountsMT, &subscriptionID)); /* Initialise the omr_test module for tracing */ UT_OMR_TEST_MODULE_LOADED(testVM.omrVM._trcEngine->utIntf); /* Shut down the trace engine */ ASSERT_NO_FATAL_FAILURE(startChildThread(&testVM, &shutdownTrcThr, shutdownTraceHelper, &shutdownTrcData)); ASSERT_EQ(1, omrthread_resume(shutdownTrcThr)); OMRTEST_ASSERT_ERROR_NONE(waitForChildThread(&testVM, shutdownTrcThr, shutdownTrcData)); /* Attempt to log a tracepoint. It will not be logged. */ Trc_OMR_Test_UnloggedTracepoint(vmthread, "Tracepoint initiated after trace engine shutdown is started."); UT_OMR_TEST_MODULE_UNLOADED(testVM.omrVM._trcEngine->utIntf); /* Now clear up the VM we started for this test case. */ /* Stop counting tracepoints */ omr_trc_stopThreadTrace(vmthread); /* flush the thread's trace buffer and delete all subscribers */ OMRTEST_ASSERT_ERROR_NONE(ti->DeregisterRecordSubscriber(vmthread, subscriptionID)); /* do nothing */ OMRTEST_ASSERT_ERROR_NONE(OMR_Thread_Free(vmthread)); OMRTEST_ASSERT_ERROR_NONE(omrTestVMFini(&testVM)); ASSERT_EQ(0, tpCounts[0].unloggedCount); ASSERT_EQ(0, tpCounts[0].loggedCount); freeWrapBuffer(&tpCounts[0].wrapBuffer); ASSERT_EQ(0, tpCounts[1].unloggedCount); ASSERT_EQ(0, tpCounts[1].loggedCount); freeWrapBuffer(&tpCounts[1].wrapBuffer); ASSERT_EQ(0, omrthread_monitor_destroy(tpCountsMT.lock)); ASSERT_TRUE(NULL == (void *)omr_test_UtModuleInfo.intf); }
TEST_F(ThreadCreateTest, NumaSetAffinitySuspended) { omrthread_t thread; omrthread_monitor_t monitor; numadata_t data; intptr_t result = 0; uintptr_t status = 0; uintptr_t numaMaxNode = omrthread_numa_get_max_node(); uintptr_t numaNode = 0; uintptr_t expectedAffinityBeforeStart = 0; omrthread_monitor_init(&monitor, 0); if (numaMaxNode > 0) { uintptr_t nodeCount = 1; /* first, see if we can even run this test */ intptr_t affinityResultCode = omrthread_numa_get_node_affinity(omrthread_self(), &data.expectedAffinity, &nodeCount); data.monitor = monitor; data.status = 0; if (J9THREAD_NUMA_ERR_AFFINITY_NOT_SUPPORTED == affinityResultCode) { /* this platform can't meaningfully run this test so just end */ omrTestEnv->log(LEVEL_ERROR, "NUMA-level thread affinity not supported on this platform\n"); goto endtest; } /* Create the thread suspended */ if (J9THREAD_SUCCESS != J9THREAD_VERBOSE(omrthread_create_ex(&thread, J9THREAD_ATTR_DEFAULT, 1, numaSetAffinitySuspendedThreadMain, &data))) { status |= CREATE_FAILED; goto endtest; } /* Set the affinity to the highest node which has CPUs associated to it */ numaNode = numaMaxNode; while (numaNode > 0) { omrTestEnv->log(LEVEL_ERROR, "Setting thread numa affinity to %zu\n", numaNode); result = omrthread_numa_set_node_affinity(thread, &numaNode, 1, 0); if (result == J9THREAD_NUMA_ERR_NO_CPUS_FOR_NODE) { omrTestEnv->log(LEVEL_ERROR, "Tried to set thread numa affinity to node %zu, but no CPUs associated with node\n", numaNode); numaNode--; continue; } else if (result != 0) { omrTestEnv->log(LEVEL_ERROR, "Failed to set affinity to %zu\n", numaNode); status |= EXPECTED_VALID; goto endtest; } else { data.expectedAffinity = numaNode; break; } } /* Check that the affinity on the suspended thread is indeed what we set it to */ if (0 != J9THREAD_VERBOSE(omrthread_numa_get_node_affinity(thread, &expectedAffinityBeforeStart, &nodeCount))) { omrTestEnv->log(LEVEL_ERROR, "Failed to get affinity on the thread while it's still suspended\n"); status |= EXPECTED_VALID; goto endtest; } if (expectedAffinityBeforeStart != data.expectedAffinity) { omrTestEnv->log(LEVEL_ERROR, "Suspended thread's deferred affinity is not what it should be. Expected:%zu Actual:%zu\n", data.expectedAffinity, expectedAffinityBeforeStart); status |= EXPECTED_VALID; goto endtest; } J9THREAD_VERBOSE(omrthread_monitor_enter(monitor)); if (1 != omrthread_resume(thread)) { omrTestEnv->log(LEVEL_ERROR, "Failed to resume the thread\n"); goto endtest; } if (0 != J9THREAD_VERBOSE(omrthread_monitor_wait(monitor))) { status |= NULL_ATTR; goto endtest; } status |= data.status; } else { omrTestEnv->log("Doesn't look like NUMA is available on this system\n"); } endtest: omrthread_monitor_exit(monitor); omrthread_monitor_destroy(monitor); ASSERT_EQ((uintptr_t)0, status) << "Failed with Code: " << std::hex << status; }