Пример #1
0
static Status wvm_Init()
{
	WUTIL_IMPORT_KERNEL32(GetCurrentProcessorNumber, pGetCurrentProcessorNumber);
	WUTIL_IMPORT_KERNEL32(GetNumaProcessorNode, pGetNumaProcessorNode);
	WUTIL_IMPORT_KERNEL32(VirtualAllocExNuma, pVirtualAllocExNuma);

	if(!pGetCurrentProcessorNumber)
		pGetCurrentProcessorNumber = &EmulateGetCurrentProcessorNumber;
	if(!pGetNumaProcessorNode)
		pGetNumaProcessorNode = &EmulateGetNumaProcessorNode;
	if(!pVirtualAllocExNuma)
		pVirtualAllocExNuma = &EmulateVirtualAllocExNuma;

	return INFO::OK;
}
Пример #2
0
static void PopulateNodes()
{
	WUTIL_FUNC(pGetNumaNodeProcessorMask, BOOL, (UCHAR, PULONGLONG));
	WUTIL_IMPORT_KERNEL32(GetNumaNodeProcessorMask, pGetNumaNodeProcessorMask);
	if(!pGetNumaNodeProcessorMask)
		return;

	DWORD_PTR processAffinity, systemAffinity;
	{
		const BOOL ok = GetProcessAffinityMask(GetCurrentProcess(), &processAffinity, &systemAffinity);
		WARN_IF_FALSE(ok);
	}
	ENSURE(PopulationCount(processAffinity) <= PopulationCount(systemAffinity));

	for(UCHAR nodeNumber = 0; nodeNumber <= HighestNodeNumber(); nodeNumber++)
	{
		ULONGLONG affinity;
		{
			const BOOL ok = pGetNumaNodeProcessorMask(nodeNumber, &affinity);
			WARN_IF_FALSE(ok);
		}
		if(!affinity)
			continue;	// empty node, skip

		Node* node = AddNode();
		node->nodeNumber = nodeNumber;
		node->processorMask = wcpu_ProcessorMaskFromAffinity(processAffinity, (DWORD_PTR)affinity);
	}
}
Пример #3
0
static UCHAR HighestNodeNumber()
{
	WUTIL_FUNC(pGetNumaHighestNodeNumber, BOOL, (PULONG));
	WUTIL_IMPORT_KERNEL32(GetNumaHighestNodeNumber, pGetNumaHighestNodeNumber);
	if(!pGetNumaHighestNodeNumber)
		return 0;	// NUMA not supported => only one node

	ULONG highestNodeNumber;
	const BOOL ok = pGetNumaHighestNodeNumber(&highestNodeNumber);
	WARN_IF_FALSE(ok);
	return (UCHAR)highestNodeNumber;
}
Пример #4
0
static bool VerifyPages(void* mem, size_t size, size_t pageSize, size_t node)
{
	WUTIL_FUNC(pQueryWorkingSetEx, BOOL, (HANDLE, PVOID, DWORD));
	WUTIL_IMPORT_KERNEL32(QueryWorkingSetEx, pQueryWorkingSetEx);
	if(!pQueryWorkingSetEx)
		return true;	// can't do anything

#if WINVER >= 0x600
	size_t largePageSize = os_cpu_LargePageSize();
	ENSURE(largePageSize != 0); // this value is needed for later

	// retrieve attributes of all pages constituting mem
	const size_t numPages = (size + pageSize-1) / pageSize;
	PSAPI_WORKING_SET_EX_INFORMATION* wsi = new PSAPI_WORKING_SET_EX_INFORMATION[numPages];
	for(size_t i = 0; i < numPages; i++)
		wsi[i].VirtualAddress = (u8*)mem + i*pageSize;
	pQueryWorkingSetEx(GetCurrentProcess(), wsi, DWORD(sizeof(PSAPI_WORKING_SET_EX_INFORMATION)*numPages));

	// ensure each is valid and allocated on the correct node
	for(size_t i = 0; i < numPages; i++)
	{
		const PSAPI_WORKING_SET_EX_BLOCK& attributes = wsi[i].VirtualAttributes;
		if(!attributes.Valid)
			return false;
		if((attributes.LargePage != 0) != (pageSize == largePageSize))
		{
			debug_printf("NUMA: is not a large page\n");
			return false;
		}
		if(attributes.Node != node)
		{
			debug_printf("NUMA: allocated from remote node\n");
			return false;
		}
	}

	delete[] wsi;
#else
	UNUSED2(mem);
	UNUSED2(size);
	UNUSED2(pageSize);
	UNUSED2(node);
#endif

	return true;
}
Пример #5
0
static void EnableLowFragmentationHeap()
{
	if(IsDebuggerPresent())
	{
		// and the debug heap isn't explicitly disabled,
		char* var = getenv("_NO_DEBUG_HEAP");
		if(!var || var[0] != '1')
			return;	// we can't enable the LFH
	}

#if WINVER >= 0x0501
	WUTIL_FUNC(pHeapSetInformation, BOOL, (HANDLE, HEAP_INFORMATION_CLASS, void*, size_t));
	WUTIL_IMPORT_KERNEL32(HeapSetInformation, pHeapSetInformation);
	if(pHeapSetInformation)
	{
		ULONG flags = 2;	// enable LFH
		pHeapSetInformation(GetProcessHeap(), HeapCompatibilityInformation, &flags, sizeof(flags));
	}
#endif	// #if WINVER >= 0x0501
}
Пример #6
0
size_t numa_AvailableMemory(size_t node)
{
	// note: it is said that GetNumaAvailableMemoryNode sometimes incorrectly
	// reports zero bytes. the actual cause may however be unexpected
	// RAM configuration, e.g. not all slots filled.
	WUTIL_FUNC(pGetNumaAvailableMemoryNode, BOOL, (UCHAR, PULONGLONG));
	WUTIL_IMPORT_KERNEL32(GetNumaAvailableMemoryNode, pGetNumaAvailableMemoryNode);
	if(pGetNumaAvailableMemoryNode)
	{
		const UCHAR nodeNumber = NodeNumberFromNode(node);
		ULONGLONG availableBytes;
		const BOOL ok = pGetNumaAvailableMemoryNode(nodeNumber, &availableBytes);
		WARN_IF_FALSE(ok);
		const size_t availableMiB = size_t(availableBytes / MiB);
		return availableMiB;
	}
	// NUMA not supported - return available system memory
	else
		return os_cpu_MemoryAvailable();
}
Пример #7
0
static void ImportWow64Functions()
{
	WUTIL_IMPORT_KERNEL32(IsWow64Process, pIsWow64Process);
	WUTIL_IMPORT_KERNEL32(Wow64DisableWow64FsRedirection, pWow64DisableWow64FsRedirection);
	WUTIL_IMPORT_KERNEL32(Wow64RevertWow64FsRedirection, pWow64RevertWow64FsRedirection);
}