Exemplo n.º 1
0
/*
 * Provides signal protection for the libc backtrace call. If the stack walk causes a segfault then we check the output
 * array to see if we got any frames as we may be able to provide a partial backtrace. We also record that the stack walk
 * was incomplete so that information is available after the fuction returns.
 */
uintptr_t
backtrace_sigprotect(struct OMRPortLibrary *portLibrary,
	J9PlatformThread *threadInfo, void **address_array, int capacity)
{
	uintptr_t ret;
	struct frameData args;
	args.address_array = address_array;
	args.capacity = capacity;

	memset(address_array, 0, sizeof(void*) * capacity);

	if (omrthread_self()) {
		if (portLibrary->sig_protect(portLibrary, protectedBacktrace, &args,
			handler, NULL,
			OMRPORT_SIG_FLAG_SIGALLSYNC | OMRPORT_SIG_FLAG_MAY_RETURN, &ret)
			!= 0) {
			/* check to see if there were any addresses populated */
			for (ret = 0; ret < args.capacity && address_array[ret] != NULL;
				ret++)
				;

			threadInfo->error = FAULT_DURING_BACKTRACE;
		}

		return ret;
	}
	else {
		return backtrace(address_array, capacity);
	}
}
Exemplo n.º 2
0
static int
numaSetAffinitySuspendedThreadMain(void *arg)
{
	numadata_t *data = (numadata_t *)arg;
	omrthread_monitor_t monitor = data->monitor;

	uintptr_t status = 0;
	uintptr_t currentAffinity = 0;
	uintptr_t nodeCount = 1;

	J9THREAD_VERBOSE(omrthread_monitor_enter(monitor));
	if (0 != J9THREAD_VERBOSE(omrthread_numa_get_node_affinity(omrthread_self(), &currentAffinity, &nodeCount))) {
		status |= EXPECTED_VALID;
		goto endthread;
	}

	if (currentAffinity != data->expectedAffinity) {
		omrTestEnv->log(LEVEL_ERROR, "Affinity different from expected. Expected:%zu Actual:%zu\n", data->expectedAffinity, currentAffinity);
		status |= EXPECTED_VALID;
		goto endthread;
	}

endthread:
	data->status = status;
	J9THREAD_VERBOSE(omrthread_monitor_notify_all(monitor));
	J9THREAD_VERBOSE(omrthread_monitor_exit(monitor));
	return 0;
}
Exemplo n.º 3
0
void
MM_MasterGCThread::masterThreadEntryPoint()
{
	OMR_VMThread *omrVMThread = NULL;
	Assert_MM_true(NULL != _collectorControlMutex);
	Assert_MM_true(NULL == _masterGCThread);

	/* Attach the thread as a system daemon thread */	
	/* You need a VM thread so that the stack walker can work */
	omrVMThread = MM_EnvironmentBase::attachVMThread(_extensions->getOmrVM(), "Dedicated GC Master", MM_EnvironmentBase::ATTACH_GC_MASTER_THREAD);
	if (NULL == omrVMThread) {
		/* we failed to attach so notify the creating thread that we should fail to start up */
		omrthread_monitor_enter(_collectorControlMutex);
		_masterThreadState = STATE_ERROR;
		omrthread_monitor_notify(_collectorControlMutex);
		omrthread_exit(_collectorControlMutex);
	} else {
		/* thread attached successfully */
		MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(omrVMThread);

		/* attachVMThread could allocate an execute a barrier (since it that point, this thread acted as a mutator thread.
		 * Flush GC chaches (like barrier buffers) before turning into the master thread */
		env->flushGCCaches();

		env->setThreadType(GC_MASTER_THREAD);

		/* Begin running the thread */
		omrthread_monitor_enter(_collectorControlMutex);
		
		_collector->preMasterGCThreadInitialize(env);
		
		_masterThreadState = STATE_WAITING;
		_masterGCThread = omrthread_self();
		omrthread_monitor_notify(_collectorControlMutex);
		do {
			if (STATE_GC_REQUESTED == _masterThreadState) {
				if (_runAsImplicit) {
					handleConcurrent(env);
				} else {
					handleSTW(env);
				}
			}

			if (STATE_WAITING == _masterThreadState) {
				if (_runAsImplicit || !handleConcurrent(env)) {
					omrthread_monitor_wait(_collectorControlMutex);
				}
			}
		} while (STATE_TERMINATION_REQUESTED != _masterThreadState);
		/* notify the other side that we are active so that they can continue running */
		_masterThreadState = STATE_TERMINATED;
		_masterGCThread = NULL;
		omrthread_monitor_notify(_collectorControlMutex);
		MM_EnvironmentBase::detachVMThread(_extensions->getOmrVM(), omrVMThread, MM_EnvironmentBase::ATTACH_GC_MASTER_THREAD);
		omrthread_exit(_collectorControlMutex);
	}
}
Exemplo n.º 4
0
/* Since we can't read affinity on Win32, at least make sure that we can call the setAffinity API without crashing.
 * Note that this should be safe on all platforms (either succeeds or fails but we ignore the return code since
 * any answer is correct, so long as we don't crash - without reading the affinity, we don't know of any more
 * interesting tests).
 */
TEST_F(ThreadCreateTest, NumaSetAffinityBlindly)
{
#define NODE_LIST_SIZE 4
	uintptr_t nodeList[NODE_LIST_SIZE];
	uintptr_t i = 0;

	for (i = 0; i < NODE_LIST_SIZE; i++) {
		nodeList[i] = i + 1;
	}
	omrthread_numa_set_node_affinity(omrthread_self(), nodeList, NODE_LIST_SIZE, 0);
}
Exemplo n.º 5
0
TEST_F(ThreadCreateTest, NumaSetAffinity)
{
	uintptr_t status = 0;
	omrthread_t thread;
	omrthread_monitor_t monitor;
	numadata_t data;
	uintptr_t nodeCount = 0;
	intptr_t affinityResultCode = 0;

	if (0 != J9THREAD_VERBOSE(omrthread_monitor_init(&monitor, 0))) {
		omrTestEnv->log(LEVEL_ERROR, "Failed to initialize monitor\n");
		status |= NULL_ATTR;
		goto endtest;
	}

	data.monitor = monitor;
	data.status = 0;
	data.expectedAffinity = 0;

	omrthread_monitor_enter(monitor);

	nodeCount = 1;
	affinityResultCode = omrthread_numa_get_node_affinity(omrthread_self(), &data.expectedAffinity, &nodeCount);
	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;
	}
	if (J9THREAD_NUMA_OK != affinityResultCode) {
		omrTestEnv->log(LEVEL_ERROR, "Failed to get parent thread's affinity\n");
		status |= CREATE_FAILED;
		goto endtest;
	}

	if (J9THREAD_SUCCESS != J9THREAD_VERBOSE(omrthread_create_ex(&thread, J9THREAD_ATTR_DEFAULT, 0, numaSetAffinityThreadMain, &data))) {
		omrTestEnv->log(LEVEL_ERROR, "Failed to create the thread\n");
		status |= CREATE_FAILED;
		goto endtest;
	}

	if (0 != omrthread_monitor_wait(monitor)) {
		omrTestEnv->log(LEVEL_ERROR, "Failed to wait on monitor\n");
		status |= NULL_ATTR;
		goto endtest;
	}

	status |= data.status;
endtest:
	omrthread_monitor_exit(monitor);
	omrthread_monitor_destroy(monitor);
	ASSERT_EQ((uintptr_t)0, status) << "Failed with Code: " << std::hex << status;
}
Exemplo n.º 6
0
TEST(JoinTest, joinDetachedThread)
{
	JoinThreadHelperData helperData;

	/* we can guarantee this thread is live, so we won't crash in omrthread_join() */
	helperData.threadToJoin = omrthread_self();
	helperData.expectedRc = J9THREAD_INVALID_ARGUMENT;

	omrthread_t helperThr = NULL;
	ASSERT_NO_FATAL_FAILURE(createThread(&helperThr, FALSE, J9THREAD_CREATE_JOINABLE, joinThreadHelper, (void *)&helperData));

	VERBOSE_JOIN(helperThr, J9THREAD_SUCCESS);
}
Exemplo n.º 7
0
	MMINLINE void payAllocationTax(MM_EnvironmentBase *env)
	{
		if (0 != _allocationTaxSize) {
			/* alloctor should have set this to point to subspace that spine came from */
			Assert_MM_true(NULL != _memorySubSpace);

			omrthread_t mutator = omrthread_self();
			uintptr_t category = omrthread_get_category(mutator);
			MM_GCExtensionsBase *extensions = env->getExtensions();

			if (extensions->trackMutatorThreadCategory) {
				/* this thread is doing concurrent GC work, charge time spent against the GC category */
				omrthread_set_category(mutator, J9THREAD_CATEGORY_SYSTEM_GC_THREAD, J9THREAD_TYPE_SET_GC);
			}

			_memorySubSpace->payAllocationTax(env, this);

			if (extensions->trackMutatorThreadCategory) {
				/* done doing concurrent GC work, restore the thread category */
				omrthread_set_category(mutator, category, J9THREAD_TYPE_SET_GC);
			}
		}
	}
Exemplo n.º 8
0
TEST(TraceLifecycleTest, moduleLoadBeforeThreadAttach)
{
	/* OMR VM data structures */
	OMRTestVM testVM;
	OMR_VMThread *vmthread = NULL;
	const OMR_TI *ti = omr_agent_getTI();
	UtSubscription *subscriptionID = NULL;

	TracePointCounts tpCounts;
	memset(&tpCounts, 0, sizeof(tpCounts));
	tpCounts.osThread = omrthread_self();
	initWrapBuffer(&tpCounts.wrapBuffer);

	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));

	/* Attempt to load a module before attaching the thread. This should fail silently without crashing */
	UT_OMR_TEST_MODULE_LOADED(testVM.omrVM._trcEngine->utIntf);

	/* Attach the thread to the trace engine */
	OMRTEST_ASSERT_ERROR_NONE(OMR_Thread_Init(&testVM.omrVM, NULL, &vmthread, "moduleLoadBeforeThreadAttach"));

	OMRTEST_ASSERT_ERROR_NONE(
		ti->RegisterRecordSubscriber(vmthread, "moduleLoadBeforeThreadAttach", countTracepoints, NULL, (void *)&tpCounts, &subscriptionID));

	/* Attempt to log a tracepoint. Nothing should happen. */
	Trc_OMR_Test_UnloggedTracepoint(vmthread, "The trace module was loaded before the current thread was attached.");

#if ENABLE_BUGS
	/* This can't be done because there is no check for whether the module was actually loaded. */
	UT_OMR_TEST_MODULE_UNLOADED(testVM.omrVM._trcEngine->utIntf);
#endif /* ENABLE_BUGS */

	/* This should succeed. */
	UT_OMR_TEST_MODULE_LOADED(testVM.omrVM._trcEngine->utIntf);
	Trc_OMR_Test_String(vmthread, "This tracepoint should appear.");
	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));

	/*
	 * Must not deregister before omr_ras_cleanupTraceEngine() because cleanup flushes the trace buffers.
	 * This succeeds for a weird reason: omr_ras_cleanupTraceEngine() actually deregistered all
	 * subscribers when it detached the current thread. This Deregister call does nothing.
	 */
	OMRTEST_ASSERT_ERROR_NONE(ti->DeregisterRecordSubscriber(vmthread, subscriptionID));

	OMRTEST_ASSERT_ERROR_NONE(OMR_Thread_Free(vmthread));
	OMRTEST_ASSERT_ERROR_NONE(omrTestVMFini(&testVM));

	/* Validate the number of tracepoints */
	ASSERT_EQ(0, tpCounts.unloggedCount);
	ASSERT_EQ(1, tpCounts.loggedCount);
	freeWrapBuffer(&tpCounts.wrapBuffer);

	ASSERT_TRUE(NULL == (void *)omr_test_UtModuleInfo.intf);
}
Exemplo n.º 9
0
/*
 * 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);
}
Exemplo n.º 10
0
static int numaSetAffinityThreadMain(void *arg)
{
	uintptr_t status = 0;
	intptr_t result = 0;
	uintptr_t maxNumaNode = omrthread_numa_get_max_node();
	uintptr_t numaNode = 0;
	uintptr_t expectedNodeForNoAffinity = 0;
	numadata_t *data = (numadata_t *)arg;
	omrthread_monitor_t monitor = data->monitor;
	omrthread_monitor_enter(monitor);
	if (maxNumaNode > 0) {
		/* Check that our current affinity is 0 */
		uintptr_t currentAffinity = 0;
		uintptr_t nodeCount = 1;
		if (0 != J9THREAD_VERBOSE(omrthread_numa_get_node_affinity(omrthread_self(), &currentAffinity, &nodeCount))) {
			omrTestEnv->log(LEVEL_ERROR, "Failed to get thread affinity\n");
			status |= EXPECTED_VALID;
			goto endthread;
		}

		/* We used to check that a child thread inherits its parent's affinity. This is Linux behaviour, but not
		 * AIX or Windows behaviour. We don't rely on, specify or document this behaviour, so don't test it.
		 */
#if 0
		if (currentAffinity != data->expectedAffinity) {
			omrTestEnv->log(LEVEL_ERROR, "Thread's initial affinity is different from parent's. Expected:%zu Actual:%zu\n", data->expectedAffinity, currentAffinity);
			status |= EXPECTED_VALID;
			goto endthread;
		}
#endif

		expectedNodeForNoAffinity = currentAffinity;

		/* Set the affinity to the highest node which has CPUs associated to it */
		numaNode = maxNumaNode;
		while (numaNode > 0) {
			omrTestEnv->log(LEVEL_ERROR, "Setting thread numa affinity to %zu\n", numaNode);
			result = omrthread_numa_set_node_affinity(omrthread_self(), &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 endthread;
			} else {
				break;
			}
		}

		/* Verify that it was correctly set */
		nodeCount = 1;
		if (0 != J9THREAD_VERBOSE(omrthread_numa_get_node_affinity(omrthread_self(), &currentAffinity, &nodeCount))) {
			omrTestEnv->log(LEVEL_ERROR, "Failed to get thread affinity\n");
			status |= EXPECTED_VALID;
			goto endthread;
		}

		if (numaNode != currentAffinity) {
			omrTestEnv->log(LEVEL_ERROR, "Affinity is incorrectly set. Expected:%zu Actual:%zu\n", numaNode, currentAffinity);
			status |= EXPECTED_VALID;
			goto endthread;
		}

		/* Now unset the affinity */
		currentAffinity = 0;
		if (0 != J9THREAD_VERBOSE(omrthread_numa_set_node_affinity(omrthread_self(), &currentAffinity, 1, 0))) {
			omrTestEnv->log(LEVEL_ERROR, "Failed to clear affinity\n");
			status |= EXPECTED_VALID;
			goto endthread;
		}

		/* Verify that it was correctly cleared */
		nodeCount = 1;
		if (0 != J9THREAD_VERBOSE(omrthread_numa_get_node_affinity(omrthread_self(), &currentAffinity, &nodeCount))) {
			omrTestEnv->log(LEVEL_ERROR, "Failed to get thread affinity\n");
			status |= EXPECTED_VALID;
			goto endthread;
		}

		if (expectedNodeForNoAffinity != currentAffinity) {
			omrTestEnv->log(LEVEL_ERROR, "Affinity is incorrectly set. Expected:%zu Actual:%zu\n", expectedNodeForNoAffinity, currentAffinity);
			status |= EXPECTED_VALID;
			goto endthread;
		}

	} else {
		omrTestEnv->log("Doesn't look like NUMA is available on this system\n");
	}
endthread:
	data->status = status;
	omrthread_monitor_notify_all(monitor);
	omrthread_monitor_exit(monitor);
	return 0;
}
Exemplo n.º 11
0
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;
}
Exemplo n.º 12
0
/**
 * PortLibrary startup.
 *
 * Start the port library, allocate resources required by the components of the portlibrary.
 * All resources created here should be destroyed in @ref omrport_shutdown_library.
 *
 * @param[in] portLibrary The portlibrary.
 *
 * @return 0 on success, negative error code on failure.  Error code values returned are
 * \arg OMRPORT_ERROR_STARTUP_THREAD
 * \arg OMRPORT_ERROR_STARTUP_MEM
 * \arg OMRPORT_ERROR_STARTUP_TLS
 * \arg OMRPORT_ERROR_STARTUP_TLS_ALLOC
 * \arg OMRPORT_ERROR_STARTUP_TLS_MUTEX
 * \arg OMRPORT_ERROR_STARTUP_ERROR
 * \arg OMRPORT_ERROR_STARTUP_CPU
 * \arg OMRPORT_ERROR_STARTUP_VMEM
 * \arg OMRPORT_ERROR_STARTUP_FILE
 * \arg OMRPORT_ERROR_STARTUP_TTY
 * \arg OMRPORT_ERROR_STARTUP_TTY_HANDLE
 * \arg OMRPORT_ERROR_STARTUP_TTY_CONSOLE
 * \arg OMRPORT_ERROR_STARTUP_MMAP
 * \arg OMRPORT_ERROR_STARTUP_IPCMUTEX
 * \arg OMRPORT_ERROR_STARTUP_NLS
 * \arg OMRPORT_ERROR_STARTUP_SOCK
 * \arg OMRPORT_ERROR_STARTUP_TIME
 * \arg OMRPORT_ERROR_STARTUP_GP
 * \arg OMRPORT_ERROR_STARTUP_EXIT
 * \arg OMRPORT_ERROR_STARTUP_SYSINFO
 * \arg OMRPORT_ERROR_STARTUP_SL
 * \arg OMRPORT_ERROR_STARTUP_STR
 * \arg OMRPORT_ERROR_STARTUP_SHSEM
 * \arg OMRPORT_ERROR_STARTUP_SHMEM
 * \arg OMRPORT_ERROR_STARTUP_SIGNAL
 *
 * @note The port library memory is deallocated if it was created by @ref omrport_allocate_library
 */
int32_t
omrport_startup_library(struct OMRPortLibrary *portLibrary)
{
	int32_t rc = 0;

	Assert_PRT_true(omrthread_self() != NULL);

	/* Must not access anything in portGlobals, as this allocates them */
	rc = portLibrary->mem_startup(portLibrary, sizeof(OMRPortLibraryGlobalData));
	if (0 != rc) {
		goto cleanup;
	}

	/* Create the tls buffers as early as possible */
	rc = omrport_tls_startup(portLibrary);
	if (0 != rc) {
		goto cleanup;
	}

	/* Start error handling as early as possible, require TLS buffers */
	rc = portLibrary->error_startup(portLibrary);
	if (0 != rc) {
		goto cleanup;
	}

	rc = portLibrary->cpu_startup(portLibrary);
	if (0 != rc) {
		goto cleanup;
	}

	rc = portLibrary->file_startup(portLibrary);
	if (0 != rc) {
		goto cleanup;
	}

	rc = portLibrary->file_blockingasync_startup(portLibrary);
	if (0 != rc) {
		goto cleanup;
	}

	rc = portLibrary->tty_startup(portLibrary);
	if (0 != rc) {
		goto cleanup;
	}

	rc = portLibrary->mmap_startup(portLibrary);
	if (0 != rc) {
		goto cleanup;
	}

	rc = portLibrary->nls_startup(portLibrary);
	if (0 != rc) {
		goto cleanup;
	}


	rc = portLibrary->time_startup(portLibrary);
	if (0 != rc) {
		goto cleanup;
	}

	rc = portLibrary->exit_startup(portLibrary);
	if (0 != rc) {
		goto cleanup;
	}

	rc = portLibrary->sysinfo_startup(portLibrary);
	if (0 != rc) {
		goto cleanup;
	}

	rc = portLibrary->sl_startup(portLibrary);
	if (0 != rc) {
		goto cleanup;
	}

	rc = portLibrary->dump_startup(portLibrary);
	if (0 != rc) {
		goto cleanup;
	}

	/* vmem startup now requires sl support.*/
	rc = portLibrary->vmem_startup(portLibrary);
	if (0 != rc) {
		goto cleanup;
	}

	rc = portLibrary->str_startup(portLibrary);
	if (0 != rc) {
		goto cleanup;
	}

	rc = portLibrary->sig_startup(portLibrary);
	if (0 != rc) {
		goto cleanup;
	}

	rc = portLibrary->introspect_startup(portLibrary);
	if (0 != rc) {
		goto cleanup;
	}

#if defined(OMR_OPT_CUDA)
	rc = portLibrary->cuda_startup(portLibrary);
	if (0 != rc) {
		goto cleanup;
	}
#endif /* OMR_OPT_CUDA */

	return rc;

cleanup:
	/* TODO: should call shutdown, but need to make all shutdown functions
	 *  safe if the corresponding startup was not called.  No worse than the existing
	 * code
	 */

	/* If this port library was self allocated free this memory */
	if (NULL != portLibrary->self_handle) {
		omrmem_deallocate_portLibrary(portLibrary);
	}
	return rc;
}
Exemplo n.º 13
0
bool
MM_MasterGCThread::garbageCollect(MM_EnvironmentBase *env, MM_AllocateDescription *allocDescription)
{
	Assert_MM_mustHaveExclusiveVMAccess(env->getOmrVMThread());
	bool didAttemptCollect = false;
	
	if (NULL != _collector) {
		/* the collector has started up so try to run */
		/* once the master thread has stored itself in the _masterGCThread, it should never need to collect - this would hang */
		Assert_MM_true(omrthread_self() != _masterGCThread);
		if (_runAsImplicit || (NULL == _masterGCThread)) {
			/* We might not have _masterGCThread in the startup phase or late in the shutdown phase.
			 * For example, there may be a native out-of-memory during startup or RAS may 
			 * trigger a GC after we've shutdown the master thread.
			 */
			Assert_MM_true(0 == env->getSlaveID());
			_collector->preMasterGCThreadInitialize(env);
			_collector->masterThreadGarbageCollect(env, allocDescription);

			if (_runAsImplicit && _collector->isConcurrentWorkAvailable(env)) {
				omrthread_monitor_enter(_collectorControlMutex);

				if (STATE_WAITING == _masterThreadState) {
					_masterThreadState = STATE_GC_REQUESTED;
					omrthread_monitor_notify(_collectorControlMutex);
				}

				omrthread_monitor_exit(_collectorControlMutex);
			}
		} else {
			/* this is the general case, when the master thread is running internally */
			omrthread_monitor_enter(_collectorControlMutex);
			/* The variable assignments below are safe because we hold Xaccess.  Otherwise, it is possible (based on the wait/notify mechanism here)
			 * that another thread could come in under this mutex and stomp on the "parameters" while another thread is waiting.
			 */
			_allocDesc = allocDescription;
			_incomingCycleState = env->_cycleState;
			MasterGCThreadState previousState = _masterThreadState;
			_masterThreadState = STATE_GC_REQUESTED;
			if (STATE_WAITING == previousState) {
				omrthread_monitor_notify(_collectorControlMutex);
			} else if (STATE_RUNNING_CONCURRENT == previousState) {
				_collector->forceConcurrentFinish();
			} else {
				Assert_MM_unreachable();
			}
			
			/* The master thread will claim exclusive VM access. Artificially give it up in this thread so that tools like -Xcheck:vm continue to work. */
			uintptr_t savedExclusiveCount = env->relinquishExclusiveVMAccess();
			while (STATE_GC_REQUESTED == _masterThreadState) {
				omrthread_monitor_wait(_collectorControlMutex);
			}
			env->assumeExclusiveVMAccess(savedExclusiveCount);

			Assert_MM_true(NULL == _incomingCycleState);
			omrthread_monitor_exit(_collectorControlMutex);
		}
		
		didAttemptCollect = true;
	}
	return didAttemptCollect;
}
Exemplo n.º 14
0
/*
 * Test pthread_sigmask() with cross fire signaling.
 *  - create 2 threads
 *  - one thread calls pthread_sigmask() and verifies that the specified mask is set
 *  - other thread verifies that the specified mask is not set
 *  - send some signals to each thread, e.g. by pthread_kill and verify that it is blocked or not.
 *
 *  Note: under heavy load test environment, the signal may not be delivered in timely fashion
 *
 * mask   thread:----s(READY)-w(SIGMASK)-----------m---s(READY)-w(PTHREADKILL)----------j----s(READY)------w(EXIT)-------s(FINISHED)---------->>
 * main   thread:-w(READY)---------s(SIGMASK)-w(READY)------------c----s(PTHREADKILL)-w(READY)----------k----s(EXIT)--w(FINISHED)--------->>
 *
 * main   thread:-w(READY)---------s(SIGMASK)-w(READY)------------c----s(PTHREADKILL)----w(FINISHED)---------->>
 * unmask thread:---s(READY)-w(SIGMASK)-------m--s(READY)-w(PTHREADKILL)----------j----i----s(FINISHED)-------------->>
 *
 * where:
 * 	m: run pthread_sigmask
 * 	c: check result of pthread_sigmask
 * 	j: run sigprotected function
 * 	k: run pthread_kill
 * 	i: signal handler (OMRPORT_SIG_EXCEPTION_RETURN)
 *
 */
TEST(PortSignalExtendedTests, sig_ext_test1)
{
	OMRPORT_ACCESS_FROM_OMRPORT(portTestEnv->getPortLibrary());
	const char *testName = "omrsig_ext_test1";
	omrthread_monitor_t maskMonitor = NULL;
	omrthread_monitor_t unmaskMonitor = NULL;
	omrthread_t mainThread = NULL;
	omrthread_t maskThread = NULL;
	omrthread_t unmaskThread = NULL;
	pthread_t osMaskThread = 0;
	pthread_t osUnmaskThread = 0;
	uint32_t flags = 0;
	SigMaskTestInfo maskThreadInfo;
	SigMaskTestInfo unmaskThreadInfo;
	intptr_t monitorRC = 0;
	int memcmp_ret = 0;
	sigset_t mask;
	sigset_t oldMask;
	sigset_t currentMask;
	sigset_t maskThread_mask;
	sigset_t unmaskThread_mask;
	portTestEnv->changeIndent(1);

	reportTestEntry(OMRPORTLIB, testName);

	/* initialize local variables */
	memset(&maskThreadInfo, 0, sizeof(maskThreadInfo));
	memset(&unmaskThreadInfo, 0, sizeof(unmaskThreadInfo));
	sigemptyset(&mask);
	sigemptyset(&oldMask);
	sigemptyset(&currentMask);
	sigemptyset(&maskThread_mask);
	sigemptyset(&unmaskThread_mask);

	/*
	 * OSX will redirect the SIGILL from the masked thread to other threads unless they are also masked.
	 * This thread's mask will be inherited. Mask SIGILL for all threads for mask testing.
	 */
	sigaddset(&mask, SIGILL);
	if (0 != pthread_sigmask(SIG_SETMASK, &mask, &oldMask)) {
		outputErrorMessage(PORTTEST_ERROR_ARGS, "pthread_sigmask failed: %s(%d).\n", strerror(errno), errno);
		FAIL();
	}

	monitorRC = omrthread_monitor_init_with_name(&maskMonitor, 0, "omrsig_ext_sigmask_monitor");
	if (0 != monitorRC) {
		outputErrorMessage(PORTTEST_ERROR_ARGS, "omrthread_monitor_init_with_name failed with %i\n", monitorRC);
		FAIL();
	}
	setSigMaskTestInfo(&maskThreadInfo, OMRPORTLIB, "Masked Thread", maskMonitor, maskProtectedFunction, INVALID);

	monitorRC = omrthread_monitor_init_with_name(&unmaskMonitor, 0, "omrsig_ext_sigunmask_monitor");
	if (0 != monitorRC) {
		outputErrorMessage(PORTTEST_ERROR_ARGS, "omrthread_monitor_init_with_name failed with %i\n", monitorRC);
		FAIL();
	}
	setSigMaskTestInfo(&unmaskThreadInfo, OMRPORTLIB, "Unmasked Thread", unmaskMonitor, unmaskProtectedFunction, INVALID);

	mainThread = omrthread_self();
	maskThread = create_thread(OMRPORTLIB, (omrthread_entrypoint_t)sigMaskThread, &maskThreadInfo);
	unmaskThread = create_thread(OMRPORTLIB, (omrthread_entrypoint_t)sigMaskThread, &unmaskThreadInfo);

	if ((NULL != mainThread) && (NULL != maskThread) && (NULL != unmaskThread)) {
		portTestEnv->log("%s\t:created test threads.\n", testName);
		/* wait for maskThread and unmaskThread ready */
		if (!waitForEvent(testName, &maskThreadInfo, READY, &osMaskThread, sizeof(pthread_t))) {
			goto exit;
		}
		if (!waitForEvent(testName, &unmaskThreadInfo, READY, &osUnmaskThread, sizeof(pthread_t))) {
			goto exit;
		}
		portTestEnv->log("%s\t:test threads are READY.\n", testName);

		/* test pthread_sigmask */
		/* ask maskThread to mask SIGBUS signal */
		flags = SIGBUS;
		portTestEnv->log("%s\t:configure mask thread to mask SIGBUS signal.\n", testName);
		sendEvent(&maskThreadInfo, SIGMASK, &flags, sizeof(flags));
		/* ask unMaskThread to not mask any signal */
		flags = 0;
		portTestEnv->log("%s\t:configure unmask thread to not mask any tested signal.\n", testName);
		sendEvent(&unmaskThreadInfo, SIGMASK, &flags, sizeof(flags));

		portTestEnv->log("%s\t:testing pthread_sigmask...\n", testName);

		/* check pthread_sigmask result */
		if (!waitForEvent(testName, &maskThreadInfo, READY, &maskThread_mask, sizeof(maskThread_mask))) {
			goto exit;
		}
		if (!waitForEvent(testName, &unmaskThreadInfo, READY, &unmaskThread_mask, sizeof(unmaskThread_mask))) {
			goto exit;
		}
		portTestEnv->log("%s\t:operation pthread_sigmask has been done. checking pthread_sigmask result...\n", testName);

		/*
		 * Expected behavior:
		 * 1. main thread's signal mask shall be untouched
		 * 2. child threads shall inherit main thread's signal mask
		 * 3. child threads' pthread_sigmask operation shall not interfere each other
		 */
		if (0 != pthread_sigmask(SIG_SETMASK, NULL, &currentMask)) {
			outputErrorMessage(PORTTEST_ERROR_ARGS, "pthread_sigmask failed: %s(%d).\n", strerror(errno), errno);
			goto exit;
		}
		/* check whether main thread signal mask was affected by child thread pthread_sigmask operation */
		if (0 != (memcmp_ret = memcmp(&currentMask, &mask, sizeof(currentMask)))) {
			outputErrorMessage(PORTTEST_ERROR_ARGS, "main thread mask was modified (old=0x%X, new=0x%X), %X\n", *((uint32_t *)&mask), *((uint32_t *)&currentMask), memcmp_ret);
			goto exit;
		} else {
			portTestEnv->log("%s\t:main thread signal mask was not affected.\n", testName);
		}

		/* UNIX opengroup example says that newly created thread shall inherit the mask */
		if (!sigismember(&maskThread_mask, SIGILL) || !sigismember(&unmaskThread_mask, SIGILL)) {
			outputErrorMessage(PORTTEST_ERROR_ARGS, "created threads did not inherit mask.(maskThreadInfo=0x%X, unmaskThreadInfo=0x%X)\n", *((uint32_t *)&maskThread_mask), *((uint32_t *)&unmaskThread_mask));
			goto exit;
		} else {
			portTestEnv->log("%s\t:child thread inherited main thread's signal mask.\n", testName);
		}

		/* Check whether two child threads' pthread_sigmask operation can interfere each other. */
		if (!sigismember(&maskThread_mask, SIGBUS) || sigismember(&unmaskThread_mask, SIGBUS)) {
			outputErrorMessage(PORTTEST_ERROR_ARGS, "pthread_sigmask did not work.(maskThreadInfo=0x%X, unmaskThreadInfo=0x%X)\n", *((uint32_t *)&maskThread_mask), *((uint32_t *)&unmaskThread_mask));
			goto exit;
		} else {
			portTestEnv->log("%s\t:pthread_sigmask operation in each child thread did not interfere each other.\n", testName);
		}

		/*
		 * test unmask thread signal handling behavior
		 * unmask thread will install SIGSEGV handler and launch a protected function unmaskProtectedFunction().
		 * unmaskProtectedFunction() shall be terminated by SIGSEGV generated in its body, and the unmask thread
		 * will send report to this main thread.
		 */
		flags = OMRPORT_SIG_FLAG_MAY_RETURN | OMRPORT_SIG_FLAG_SIGSEGV; /* SIGSEGV shall be received */
		portTestEnv->log("%s\t:configure unmask thread to prepare for unmasked signal SIGSEGV test.\n", testName);
		sendEvent(&unmaskThreadInfo, PTHREADKILL, &flags, sizeof(flags));

		if (!waitForEvent(testName, &unmaskThreadInfo, FINISHED, NULL, 0)) {
			goto exit;
		} else {
			portTestEnv->log("%s\t:unmasked thread finished. checking unmask thread's signal status...\n", testName);

			if (unmaskThreadInfo.bulletinBoard.status ==  SIGNALED) {
				portTestEnv->log("%s\t:unmasked thread received signal as expected.\n", testName);
			} else {
				outputErrorMessage(PORTTEST_ERROR_ARGS, "unmasked thread did not received signal as expected.(SignalStatus=%d)\n", unmaskThreadInfo.bulletinBoard.status);
				goto exit;
			}
		}


		/*
		 * test mask thread signal handling behavior
		 * mask thread will install SIGILL handler and launch a protected function maskProtectedFunction().
		 */
		portTestEnv->log("%s\t:testing pthread_kill...\n", testName);
		flags = OMRPORT_SIG_FLAG_MAY_RETURN | OMRPORT_SIG_FLAG_SIGILL; /* SIGILL shall not be received */
		sendEvent(&maskThreadInfo, PTHREADKILL, &flags, sizeof(flags));
		portTestEnv->log("%s\t:configure mask thread to prepare for pthread_kill test.\n", testName);

		if (!waitForEvent(testName, &maskThreadInfo, READY, NULL, 0)) {
			goto exit;
		}
		portTestEnv->log("%s\t:mask thread is ready to receive signal. sending pthread_kill...\n", testName);
		/* send SIGILL to maskThread which will never receive this signal */
		pthread_kill(osMaskThread, SIGILL);

		/* check pthread_kill result */
		/*
		 * Expected behavior:
		 * 1. child thread with signal mask on SIGILL shall not receive this signal and therefore NOTSIGNALED.
		 */

		portTestEnv->log("%s\t:notify mask thread to exit.\n", testName);
		sendEvent(&maskThreadInfo, EXIT, NULL, 0);
		if (!waitForEvent(testName, &maskThreadInfo, FINISHED, NULL, 0)) {
			goto exit;
		} else {
			portTestEnv->log("%s\t:masked thread finished. checking mask thread's signal status...\n", testName);
			if (maskThreadInfo.bulletinBoard.status ==  NOTSIGNALED) {
				portTestEnv->log("%s\t:masked thread did not receive signal as expected.\n", testName);
			} else {
				outputErrorMessage(PORTTEST_ERROR_ARGS, "masked thread received signal as not expected.(SignalStatus=%d)\n", maskThreadInfo.bulletinBoard.status);
				goto exit;
			}
		}

		portTestEnv->log("%s\t:pthread_sigmask works on each individual thread.\n", testName);

	}

	portTestEnv->log("%s\t:destroying unmaskMonitor...\n", testName);
	omrthread_monitor_destroy(unmaskMonitor);

	portTestEnv->log("%s\t:destroying maskMonitor...\n", testName);
	omrthread_monitor_destroy(maskMonitor);

	goto cleanup;

exit:
	portTestEnv->log(LEVEL_ERROR, "%s\t:test stopped with errors\n", testName);
	FAIL();

cleanup:
	/* restore signal mask */
	pthread_sigmask(SIG_SETMASK, &oldMask, NULL);
	portTestEnv->changeIndent(-1);
	reportTestExit(OMRPORTLIB, testName);
}
Exemplo n.º 15
0
TEST(JoinTest, joinSelf)
{
	ASSERT_EQ(J9THREAD_INVALID_ARGUMENT, omrthread_join(omrthread_self()));
}