forked from 0ad/0ad
enable use of ACPI without the mahaf driver (required for NUMA SRAT access at work). also use new DLL import macros.
This was SVN commit r7718.
This commit is contained in:
parent
8c1bd05ab9
commit
b2c4a8597e
@ -23,15 +23,39 @@
|
||||
#include "precompiled.h"
|
||||
#include "lib/sysdep/acpi.h"
|
||||
|
||||
#include "lib/sysdep/os/win/mahaf.h"
|
||||
#include "lib/sysdep/cpu.h"
|
||||
#include "lib/module_init.h"
|
||||
|
||||
#define ENABLE_MAHAF 0
|
||||
#if ENABLE_MAHAF
|
||||
# include "lib/sysdep/os/win/mahaf.h"
|
||||
#else
|
||||
# include "lib/sysdep/os/win/wacpi.h"
|
||||
#endif
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
typedef const volatile u8* PCV_u8;
|
||||
typedef const volatile AcpiTable* PCV_AcpiTable;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// table
|
||||
|
||||
static AcpiTable* AllocateTable(size_t size)
|
||||
{
|
||||
debug_assert(size >= sizeof(AcpiTable));
|
||||
return (AcpiTable*)malloc(size);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
static void DeallocateTable(const T* table)
|
||||
{
|
||||
free((void*)table);
|
||||
}
|
||||
|
||||
|
||||
// return 8-bit checksum of a buffer (should be 0)
|
||||
static u8 ComputeChecksum(PCV_u8 buf, size_t numBytes)
|
||||
{
|
||||
@ -43,9 +67,49 @@ static u8 ComputeChecksum(PCV_u8 buf, size_t numBytes)
|
||||
}
|
||||
|
||||
|
||||
static bool ValidateTable(const AcpiTable* table, const char* signature = 0)
|
||||
{
|
||||
if(!table)
|
||||
return false;
|
||||
|
||||
// caller knowns the signature; make sure it matches
|
||||
if(signature)
|
||||
{
|
||||
if(memcmp(table->signature, signature, 4) != 0)
|
||||
return false;
|
||||
}
|
||||
// no specific signature is called for; just make sure it's 4 letters
|
||||
else
|
||||
{
|
||||
for(size_t i = 0; i < 4; i++)
|
||||
{
|
||||
if(!isalpha(table->signature[i]))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// must be at least as large as the common header
|
||||
if(table->size < sizeof(AcpiTable))
|
||||
return false;
|
||||
|
||||
// checksum of table must be 0
|
||||
// .. AMIBIOS OEMB table has an incorrect checksum (off-by-one),
|
||||
// so don't complain about any OEM tables (ignored anyway).
|
||||
const bool isOemTable = (memcmp(table->signature, "OEM", 3) == 0);
|
||||
if(!isOemTable)
|
||||
{
|
||||
if(ComputeChecksum((PCV_u8)table, table->size) != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if ENABLE_MAHAF
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// exception-safe transactional map/use/unmap
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// note: if the OS happens to unmap our physical memory, the Unsafe*
|
||||
// functions may crash. we catch this via SEH; on Unix, we'd need handlers
|
||||
@ -57,7 +121,7 @@ static void* FAILED = (void*)(intptr_t)-1;
|
||||
|
||||
typedef void* (*UnsafeFunction)(PCV_u8 mem, size_t numBytes, void* arg);
|
||||
|
||||
static inline void* CallWithSafetyBlanket(UnsafeFunction func, PCV_u8 mem, size_t numBytes, void* arg)
|
||||
static void* CallWithSafetyBlanket(UnsafeFunction func, PCV_u8 mem, size_t numBytes, void* arg)
|
||||
{
|
||||
#if MSC_VERSION
|
||||
__try
|
||||
@ -86,7 +150,6 @@ static void* TransactPhysicalMemory(uintptr_t physicalAddress, size_t numBytes,
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Root System Descriptor Pointer
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
struct BiosDataArea
|
||||
{
|
||||
@ -162,10 +225,9 @@ static bool RetrieveRsdp(RSDP& rsdp)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// table retrieval
|
||||
//-----------------------------------------------------------------------------
|
||||
// copy tables from physical memory
|
||||
|
||||
static inline void* UnsafeAllocateCopyOfTable(PCV_u8 mem, size_t numBytes, void* arg)
|
||||
static void* UnsafeAllocateAndCopyTable(PCV_u8 mem, size_t numBytes, void* arg)
|
||||
{
|
||||
debug_assert(numBytes >= sizeof(AcpiTable));
|
||||
|
||||
@ -180,7 +242,7 @@ static inline void* UnsafeAllocateCopyOfTable(PCV_u8 mem, size_t numBytes, void*
|
||||
return 0;
|
||||
}
|
||||
|
||||
PCV_u8 copy = (PCV_u8)malloc(tableSize);
|
||||
PCV_u8 copy = (PCV_u8)AllocateTable(tableSize);
|
||||
if(!copy)
|
||||
return FAILED;
|
||||
|
||||
@ -188,130 +250,116 @@ static inline void* UnsafeAllocateCopyOfTable(PCV_u8 mem, size_t numBytes, void*
|
||||
return (void*)copy;
|
||||
}
|
||||
|
||||
// caller is responsible for verifying the table is valid and using
|
||||
// DeallocateTable to free it.
|
||||
static const AcpiTable* AllocateCopyOfTable(uintptr_t physicalAddress)
|
||||
|
||||
static const AcpiTable* AllocateAndCopyTable(uintptr_t physicalAddress)
|
||||
{
|
||||
// ACPI table sizes are not known until they've been mapped. since that
|
||||
// is slow, we don't always want to do it twice. the solution is to map
|
||||
// enough for a typical table; if that is too small, realloc and map again.
|
||||
static const size_t initialSize = 4*KiB;
|
||||
size_t actualSize = 0;
|
||||
void* ret = TransactPhysicalMemory(physicalAddress, initialSize, UnsafeAllocateCopyOfTable, &actualSize);
|
||||
void* ret = TransactPhysicalMemory(physicalAddress, initialSize, UnsafeAllocateAndCopyTable, &actualSize);
|
||||
// initialSize was too small; actualSize has been set
|
||||
if(ret == 0)
|
||||
ret = TransactPhysicalMemory(physicalAddress, actualSize, UnsafeAllocateCopyOfTable);
|
||||
ret = TransactPhysicalMemory(physicalAddress, actualSize, UnsafeAllocateAndCopyTable);
|
||||
// *either* of the above calls failed to allocate memory
|
||||
if(ret == FAILED)
|
||||
return 0;
|
||||
return (const AcpiTable*)ret;
|
||||
}
|
||||
|
||||
#endif // ENABLE_MAHAF
|
||||
|
||||
template<typename T>
|
||||
static void DeallocateTable(const T* table)
|
||||
|
||||
static void AllocateAndCopyTables(const AcpiTable**& tables, size_t& numTables)
|
||||
{
|
||||
free((void*)table);
|
||||
}
|
||||
#if ENABLE_MAHAF
|
||||
if(mahaf_IsPhysicalMappingDangerous())
|
||||
return;
|
||||
if(!mahaf_Init())
|
||||
return;
|
||||
|
||||
|
||||
static bool VerifyTable(const AcpiTable* table, const char* signature = 0)
|
||||
{
|
||||
if(!table)
|
||||
return false;
|
||||
|
||||
// caller knowns the signature; make sure it matches
|
||||
if(signature)
|
||||
{
|
||||
if(memcmp(table->signature, signature, 4) != 0)
|
||||
return false;
|
||||
}
|
||||
// no specific signature is called for; just make sure it's 4 letters
|
||||
else
|
||||
{
|
||||
for(size_t i = 0; i < 4; i++)
|
||||
{
|
||||
if(!isalpha(table->signature[i]))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// must be at least as large as the common header
|
||||
if(table->size < sizeof(AcpiTable))
|
||||
return false;
|
||||
|
||||
// checksum of table must be 0
|
||||
// .. AMIBIOS OEMB table has an incorrect checksum (off-by-one),
|
||||
// so don't complain about any OEM tables (ignored anyway).
|
||||
const bool isOemTable = (memcmp(table->signature, "OEM", 3) == 0);
|
||||
if(ComputeChecksum((PCV_u8)table, table->size) != 0 && !isOemTable)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static const AcpiTable* GetTable(uintptr_t physicalAddress, const char* signature = 0)
|
||||
{
|
||||
const AcpiTable* table = AllocateCopyOfTable(physicalAddress);
|
||||
if(VerifyTable(table, signature))
|
||||
return table;
|
||||
else
|
||||
{
|
||||
DeallocateTable(table);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// table storage
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Root System Descriptor Table
|
||||
struct RSDT
|
||||
{
|
||||
AcpiTable header;
|
||||
u32 tables[1];
|
||||
};
|
||||
|
||||
// avoid std::map et al. because we may be called before _cinit
|
||||
static const AcpiTable** tables;
|
||||
static size_t numTables;
|
||||
|
||||
static bool LatchAllTables()
|
||||
{
|
||||
RSDP rsdp;
|
||||
if(!RetrieveRsdp(rsdp))
|
||||
return false;
|
||||
const RSDT* rsdt = (const RSDT*)GetTable(rsdp.rsdtPhysicalAddress, "RSDT");
|
||||
if(!rsdt)
|
||||
return false;
|
||||
return;
|
||||
|
||||
// Root System Descriptor Table
|
||||
struct RSDT
|
||||
{
|
||||
AcpiTable header;
|
||||
u32 tableAddresses[1];
|
||||
};
|
||||
const RSDT* rsdt = (const RSDT*)AllocateAndCopyTable(rsdp.rsdtPhysicalAddress);
|
||||
if(!ValidateTable(&rsdt->header, "RSDT"))
|
||||
{
|
||||
DeallocateTable(rsdt);
|
||||
return;
|
||||
}
|
||||
|
||||
numTables = (rsdt->header.size - sizeof(AcpiTable)) / sizeof(rsdt->tableAddresses[0]);
|
||||
debug_assert(numTables != 0);
|
||||
|
||||
numTables = (rsdt->header.size - sizeof(AcpiTable)) / sizeof(rsdt->tables[0]);
|
||||
debug_assert(numTables > 0);
|
||||
tables = new const AcpiTable*[numTables];
|
||||
for(size_t i = 0; i < numTables; i++)
|
||||
tables[i] = GetTable(rsdt->tables[i]);
|
||||
tables[i] = AllocateAndCopyTable(rsdt->tableAddresses[i]);
|
||||
|
||||
DeallocateTable(rsdt);
|
||||
return true;
|
||||
#else
|
||||
const std::vector<u32> tableIDs = wacpi_TableIDs();
|
||||
debug_assert(!tableIDs.empty());
|
||||
|
||||
numTables = tableIDs.size();
|
||||
tables = new const AcpiTable*[numTables];
|
||||
|
||||
for(size_t i = 0; i < numTables; i++)
|
||||
{
|
||||
std::vector<u8> table = wacpi_GetTable(tableIDs[i]);
|
||||
tables[i] = AllocateTable(table.size());
|
||||
memcpy((void*)tables[i], &table[0], table.size());
|
||||
}
|
||||
#endif
|
||||
|
||||
// to prevent callers from choking on invalid tables, we
|
||||
// zero out the corresponding tables[] entries.
|
||||
for(size_t i = 0; i < numTables; i++)
|
||||
{
|
||||
if(!ValidateTable(tables[i]))
|
||||
{
|
||||
DeallocateTable(tables[i]);
|
||||
tables[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void FreeAllTables()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// note: avoid global std::map etc. because we may be called before _cinit
|
||||
static const AcpiTable** tables; // tables == 0 <=> not initialized
|
||||
static const AcpiTable* invalidTables; // tables == &invalidTables => init failed
|
||||
static size_t numTables;
|
||||
|
||||
void acpi_Shutdown()
|
||||
{
|
||||
if(tables)
|
||||
{
|
||||
for(size_t i = 0; i < numTables; i++)
|
||||
DeallocateTable(tables[i]);
|
||||
delete[] tables;
|
||||
SAFE_ARRAY_DELETE(tables);
|
||||
numTables = 0;
|
||||
}
|
||||
|
||||
#if ENABLE_MAHAF
|
||||
mahaf_Shutdown();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
const AcpiTable* acpi_GetTable(const char* signature)
|
||||
{
|
||||
if(cpu_CAS(&tables, (const AcpiTable**)0, &invalidTables))
|
||||
AllocateAndCopyTables(tables, numTables);
|
||||
|
||||
// (typically only a few tables, linear search is OK)
|
||||
for(size_t i = 0; i < numTables; i++)
|
||||
{
|
||||
@ -322,44 +370,5 @@ const AcpiTable* acpi_GetTable(const char* signature)
|
||||
return table;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0; // no matching AND valid table found
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define initState acpiInitState
|
||||
static ModuleInitState initState;
|
||||
|
||||
bool acpi_Init()
|
||||
{
|
||||
if(ModuleIsError(&initState))
|
||||
return false;
|
||||
if(!ModuleShouldInitialize(&initState))
|
||||
return true;
|
||||
|
||||
if(mahaf_IsPhysicalMappingDangerous())
|
||||
goto fail;
|
||||
if(!mahaf_Init())
|
||||
goto fail;
|
||||
|
||||
if(!LatchAllTables())
|
||||
goto fail;
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
ModuleSetError(&initState);
|
||||
return false;
|
||||
}
|
||||
|
||||
void acpi_Shutdown()
|
||||
{
|
||||
if(!ModuleShouldShutdown(&initState))
|
||||
return;
|
||||
|
||||
FreeAllTables();
|
||||
|
||||
mahaf_Shutdown();
|
||||
}
|
||||
#undef initState
|
||||
|
@ -64,9 +64,18 @@ struct AcpiGenericAddress
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
extern bool acpi_Init();
|
||||
extern void acpi_Shutdown();
|
||||
/**
|
||||
* @param signature e.g. "RSDT"
|
||||
* @return pointer to internal storage (valid until acpi_Shutdown())
|
||||
*
|
||||
* note: the first call may be slow, e.g. if a kernel-mode driver is
|
||||
* loaded. subsequent requests will be faster since tables are cached.
|
||||
**/
|
||||
LIB_API const AcpiTable* acpi_GetTable(const char* signature);
|
||||
|
||||
extern const AcpiTable* acpi_GetTable(const char* signature);
|
||||
/**
|
||||
* invalidates all pointers returned by acpi_GetTable.
|
||||
**/
|
||||
LIB_API void acpi_Shutdown();
|
||||
|
||||
#endif // #ifndef INCLUDED_ACPI
|
||||
|
42
source/lib/sysdep/os/win/wacpi.cpp
Normal file
42
source/lib/sysdep/os/win/wacpi.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
#include "precompiled.h"
|
||||
#include "lib/sysdep/os/win/wacpi.h"
|
||||
|
||||
#include "lib/byte_order.h"
|
||||
#include "lib/sysdep/os/win/wutil.h"
|
||||
|
||||
|
||||
static const DWORD provider = FOURCC_BE('A','C','P','I');
|
||||
|
||||
std::vector<u32> wacpi_TableIDs()
|
||||
{
|
||||
WUTIL_FUNC(pEnumSystemFirmwareTables, UINT, (DWORD, PVOID, DWORD));
|
||||
WUTIL_IMPORT_KERNEL32(EnumSystemFirmwareTables, pEnumSystemFirmwareTables);
|
||||
|
||||
const UINT bufSize = pEnumSystemFirmwareTables(provider, 0, 0);
|
||||
debug_assert(bufSize != 0);
|
||||
debug_assert(bufSize % sizeof(DWORD) == 0);
|
||||
|
||||
std::vector<u32> tableIDs(DivideRoundUp((size_t)bufSize, sizeof(DWORD)));
|
||||
|
||||
const UINT ret = pEnumSystemFirmwareTables(provider, &tableIDs[0], bufSize);
|
||||
debug_assert(ret == bufSize);
|
||||
|
||||
return tableIDs;
|
||||
}
|
||||
|
||||
|
||||
std::vector<u8> wacpi_GetTable(u32 id)
|
||||
{
|
||||
WUTIL_FUNC(pGetSystemFirmwareTable, UINT, (DWORD, DWORD, PVOID, DWORD));
|
||||
WUTIL_IMPORT_KERNEL32(GetSystemFirmwareTable, pGetSystemFirmwareTable);
|
||||
|
||||
const UINT bufSize = pGetSystemFirmwareTable(provider, id, 0, 0);
|
||||
debug_assert(bufSize != 0);
|
||||
|
||||
std::vector<u8> table(bufSize);
|
||||
|
||||
const UINT ret = pGetSystemFirmwareTable(provider, id, &table[0], bufSize);
|
||||
debug_assert(ret == bufSize);
|
||||
|
||||
return table;
|
||||
}
|
8
source/lib/sysdep/os/win/wacpi.h
Normal file
8
source/lib/sysdep/os/win/wacpi.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef INCLUDED_WACPI
|
||||
#define INCLUDED_WACPI
|
||||
|
||||
extern std::vector<u32> wacpi_TableIDs();
|
||||
|
||||
extern std::vector<u8> wacpi_GetTable(u32 id);
|
||||
|
||||
#endif // #ifndef INCLUDED_WACPI
|
@ -25,11 +25,12 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.h"
|
||||
#include "lib/sysdep/os/win/wcpu.h"
|
||||
#include "lib/sysdep/os_cpu.h"
|
||||
|
||||
#include "lib/sysdep/os/win/win.h"
|
||||
#include "lib/bits.h"
|
||||
#include "lib/module_init.h"
|
||||
#include "lib/sysdep/os/win/wutil.h"
|
||||
|
||||
#ifdef _OPENMP
|
||||
# include <omp.h>
|
||||
@ -130,9 +131,8 @@ size_t os_cpu_LargePageSize()
|
||||
|
||||
if(largePageSize == ~(size_t)0)
|
||||
{
|
||||
typedef SIZE_T (WINAPI *PGetLargePageMinimum)();
|
||||
const HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll");
|
||||
const PGetLargePageMinimum pGetLargePageMinimum = (PGetLargePageMinimum)GetProcAddress(hKernel32, "GetLargePageMinimum");
|
||||
WUTIL_FUNC(pGetLargePageMinimum, SIZE_T, (void));
|
||||
WUTIL_IMPORT_KERNEL32(GetLargePageMinimum, pGetLargePageMinimum);
|
||||
if(pGetLargePageMinimum)
|
||||
{
|
||||
largePageSize = pGetLargePageMinimum();
|
||||
@ -148,11 +148,11 @@ size_t os_cpu_LargePageSize()
|
||||
}
|
||||
|
||||
|
||||
static void GetMemoryStatusEx(MEMORYSTATUSEX& mse)
|
||||
static void GetMemoryStatus(MEMORYSTATUSEX& mse)
|
||||
{
|
||||
// note: we no longer bother dynamically importing GlobalMemoryStatusEx -
|
||||
// it's available starting with Win2k and avoids overflow/wraparound
|
||||
// on systems with >= 4 GB of memory.
|
||||
// it's available on Win2k and above. this function safely handles
|
||||
// systems with > 4 GB of memory.
|
||||
mse.dwLength = sizeof(mse);
|
||||
const BOOL ok = GlobalMemoryStatusEx(&mse);
|
||||
WARN_IF_FALSE(ok);
|
||||
@ -165,7 +165,7 @@ size_t os_cpu_MemorySize()
|
||||
if(memorySizeMiB == 0)
|
||||
{
|
||||
MEMORYSTATUSEX mse;
|
||||
GetMemoryStatusEx(mse);
|
||||
GetMemoryStatus(mse);
|
||||
DWORDLONG memorySize = mse.ullTotalPhys;
|
||||
|
||||
// Richter, "Programming Applications for Windows": the reported
|
||||
@ -184,7 +184,7 @@ size_t os_cpu_MemorySize()
|
||||
size_t os_cpu_MemoryAvailable()
|
||||
{
|
||||
MEMORYSTATUSEX mse;
|
||||
GetMemoryStatusEx(mse);
|
||||
GetMemoryStatus(mse);
|
||||
const size_t memoryAvailableMiB = size_t(mse.ullAvailPhys / MiB);
|
||||
return memoryAvailableMiB;
|
||||
}
|
||||
@ -233,21 +233,14 @@ uintptr_t wcpu_ProcessorMaskFromAffinity(DWORD_PTR processAffinity, DWORD_PTR af
|
||||
|
||||
static const DWORD invalidProcessorNumber = (DWORD)-1;
|
||||
|
||||
|
||||
|
||||
static DWORD CurrentProcessorNumber()
|
||||
{
|
||||
typedef DWORD (WINAPI *PGetCurrentProcessorNumber)();
|
||||
static PGetCurrentProcessorNumber pGetCurrentProcessorNumber;
|
||||
|
||||
static bool initialized;
|
||||
if(!initialized)
|
||||
{
|
||||
initialized = true;
|
||||
const HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll");
|
||||
// note: NtGetCurrentProcessorNumber and RtlGetCurrentProcessorNumber aren't
|
||||
// implemented on WinXP SP2, so we can't use those either.
|
||||
pGetCurrentProcessorNumber = (PGetCurrentProcessorNumber)GetProcAddress(hKernel32, "GetCurrentProcessorNumber");
|
||||
}
|
||||
|
||||
// note: NtGetCurrentProcessorNumber and RtlGetCurrentProcessorNumber aren't
|
||||
// implemented on WinXP SP2.
|
||||
WUTIL_FUNC(pGetCurrentProcessorNumber, DWORD, (void));
|
||||
WUTIL_IMPORT_KERNEL32(GetCurrentProcessorNumber, pGetCurrentProcessorNumber);
|
||||
if(pGetCurrentProcessorNumber)
|
||||
return pGetCurrentProcessorNumber();
|
||||
else
|
||||
|
@ -42,14 +42,10 @@
|
||||
# include "lib/sysdep/arch/ia32/ia32_asm.h"
|
||||
#endif
|
||||
#include "lib/external_libraries/dbghelp.h"
|
||||
#include "lib/sysdep/os/win/winit.h"
|
||||
#include "lib/sysdep/os/win/wdbg.h"
|
||||
#include "lib/sysdep/os/win/wutil.h"
|
||||
|
||||
|
||||
WINIT_REGISTER_CRITICAL_INIT(wdbg_sym_Init);
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// dbghelp
|
||||
//----------------------------------------------------------------------------
|
||||
@ -64,6 +60,13 @@ static uintptr_t mod_base;
|
||||
// for StackWalk64; taken from PE header by wdbg_init.
|
||||
static WORD machine;
|
||||
|
||||
// note: RtlCaptureStackBackTrace (http://msinilo.pl/blog/?p=40)
|
||||
// is likely to be much faster than StackWalk64 (especially relevant
|
||||
// for debug_GetCaller), but wasn't known during development and
|
||||
// remains undocumented.
|
||||
static WUTIL_FUNC(pRtlCaptureContext, VOID, (PCONTEXT));
|
||||
|
||||
|
||||
// call on-demand (allows handling exceptions raised before winit.cpp
|
||||
// init functions are called); no effect if already initialized.
|
||||
static LibError sym_init()
|
||||
@ -77,6 +80,7 @@ static LibError sym_init()
|
||||
hProcess = GetCurrentProcess();
|
||||
|
||||
dbghelp_ImportFunctions();
|
||||
WUTIL_IMPORT_KERNEL32(RtlCaptureContext, pRtlCaptureContext);
|
||||
|
||||
// set options
|
||||
// notes:
|
||||
@ -299,14 +303,6 @@ static LibError ia32_walk_stack(_tagSTACKFRAME64* sf)
|
||||
|
||||
#endif
|
||||
|
||||
// note: RtlCaptureStackBackTrace (http://msinilo.pl/blog/?p=40)
|
||||
// is likely to be much faster than StackWalk64 (especially relevant
|
||||
// for debug_GetCaller), but wasn't known during development and
|
||||
// remains undocumented.
|
||||
|
||||
typedef VOID (WINAPI *PRtlCaptureContext)(PCONTEXT);
|
||||
static PRtlCaptureContext s_RtlCaptureContext;
|
||||
|
||||
|
||||
LibError wdbg_sym_WalkStack(StackFrameCallback cb, uintptr_t cbData, const CONTEXT* pcontext, const wchar_t* lastFuncToSkip)
|
||||
{
|
||||
@ -338,11 +334,11 @@ LibError wdbg_sym_WalkStack(StackFrameCallback cb, uintptr_t cbData, const CONTE
|
||||
#if ARCH_IA32
|
||||
ia32_asm_GetCurrentContext(&context);
|
||||
#else
|
||||
if(!s_RtlCaptureContext)
|
||||
if(!pRtlCaptureContext)
|
||||
return ERR::NOT_SUPPORTED; // NOWARN
|
||||
memset(&context, 0, sizeof(context));
|
||||
context.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER;
|
||||
s_RtlCaptureContext(&context);
|
||||
pRtlCaptureContext(&context);
|
||||
#endif
|
||||
}
|
||||
pcontext = &context;
|
||||
@ -1884,14 +1880,3 @@ void wdbg_sym_WriteMinidump(EXCEPTION_POINTERS* exception_pointers)
|
||||
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static LibError wdbg_sym_Init()
|
||||
{
|
||||
HMODULE hKernel32Dll = GetModuleHandleW(L"kernel32.dll");
|
||||
s_RtlCaptureContext = (PRtlCaptureContext)GetProcAddress(hKernel32Dll, "RtlCaptureContext");
|
||||
|
||||
return INFO::OK;
|
||||
}
|
||||
|
@ -154,8 +154,6 @@ private:
|
||||
return ERR::FAIL; // NOWARN (happens on Win2k)
|
||||
if(!mahaf_Init())
|
||||
return ERR::FAIL; // NOWARN (no Administrator privileges)
|
||||
if(!acpi_Init())
|
||||
WARN_RETURN(ERR::FAIL); // shouldn't fail, since we've checked mahaf_IsPhysicalMappingDangerous
|
||||
|
||||
const HpetDescriptionTable* hpet = (const HpetDescriptionTable*)acpi_GetTable("HPET");
|
||||
if(!hpet)
|
||||
|
@ -68,8 +68,6 @@ public:
|
||||
// mahaf is needed for port I/O.
|
||||
if(!mahaf_Init())
|
||||
return ERR::FAIL; // NOWARN (no Administrator privileges)
|
||||
if(!acpi_Init())
|
||||
return ERR::FAIL; // NOWARN (happens on Win2k; see mahaf_IsPhysicalMappingDangerous)
|
||||
// (note: it's called FADT, but the signature is "FACP")
|
||||
const FADT* fadt = (const FADT*)acpi_GetTable("FACP");
|
||||
if(!fadt)
|
||||
@ -81,7 +79,6 @@ public:
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
acpi_Shutdown();
|
||||
mahaf_Shutdown();
|
||||
}
|
||||
|
||||
|
@ -293,12 +293,6 @@ static inline void ShutdownUpdateThread()
|
||||
|
||||
static LibError whrt_Init()
|
||||
{
|
||||
// note: several counter implementations use acpi.cpp. if a counter is
|
||||
// deemed unsafe, it is shut down, which releases the (possibly only)
|
||||
// reference to the ACPI module. unloading and reloading it after trying
|
||||
// each counter would be a waste of time, so we grab a reference here.
|
||||
(void)acpi_Init();
|
||||
|
||||
InitCounter();
|
||||
|
||||
// latch initial counter value so that timer starts at 0
|
||||
|
@ -43,9 +43,8 @@ WINIT_REGISTER_EARLY_INIT(wnuma_Init);
|
||||
|
||||
static size_t NumNodes()
|
||||
{
|
||||
typedef BOOL (WINAPI *PGetNumaHighestNodeNumber)(PULONG highestNode);
|
||||
const HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll");
|
||||
const PGetNumaHighestNodeNumber pGetNumaHighestNodeNumber = (PGetNumaHighestNodeNumber)GetProcAddress(hKernel32, "GetNumaHighestNodeNumber");
|
||||
WUTIL_FUNC(pGetNumaHighestNodeNumber, BOOL, (PULONG));
|
||||
WUTIL_IMPORT_KERNEL32(GetNumaHighestNodeNumber, pGetNumaHighestNodeNumber);
|
||||
if(pGetNumaHighestNodeNumber)
|
||||
{
|
||||
ULONG highestNode;
|
||||
@ -62,9 +61,8 @@ static size_t NumNodes()
|
||||
|
||||
static void FillNodesProcessorMask(uintptr_t* nodesProcessorMask)
|
||||
{
|
||||
typedef BOOL (WINAPI *PGetNumaNodeProcessorMask)(UCHAR node, PULONGLONG affinity);
|
||||
const HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll");
|
||||
const PGetNumaNodeProcessorMask pGetNumaNodeProcessorMask = (PGetNumaNodeProcessorMask)GetProcAddress(hKernel32, "GetNumaNodeProcessorMask");
|
||||
WUTIL_FUNC(pGetNumaNodeProcessorMask, BOOL, (UCHAR, PULONGLONG));
|
||||
WUTIL_IMPORT_KERNEL32(GetNumaNodeProcessorMask, pGetNumaNodeProcessorMask);
|
||||
if(pGetNumaNodeProcessorMask)
|
||||
{
|
||||
DWORD_PTR processAffinity, systemAffinity;
|
||||
@ -155,14 +153,8 @@ 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.
|
||||
typedef BOOL (WINAPI *PGetNumaAvailableMemoryNode)(UCHAR node, PULONGLONG availableBytes);
|
||||
static PGetNumaAvailableMemoryNode pGetNumaAvailableMemoryNode;
|
||||
if(!pGetNumaAvailableMemoryNode)
|
||||
{
|
||||
const HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll");
|
||||
pGetNumaAvailableMemoryNode = (PGetNumaAvailableMemoryNode)GetProcAddress(hKernel32, "GetNumaAvailableMemoryNode");
|
||||
}
|
||||
|
||||
WUTIL_FUNC(pGetNumaAvailableMemoryNode, BOOL, (UCHAR, PULONGLONG));
|
||||
WUTIL_IMPORT_KERNEL32(GetNumaAvailableMemoryNode, pGetNumaAvailableMemoryNode);
|
||||
if(pGetNumaAvailableMemoryNode)
|
||||
{
|
||||
ULONGLONG availableBytes;
|
||||
@ -228,15 +220,9 @@ bool numa_IsMemoryInterleaved()
|
||||
static int isInterleaved = -1;
|
||||
if(isInterleaved == -1)
|
||||
{
|
||||
if(acpi_Init())
|
||||
{
|
||||
// the BIOS only generates an SRAT (System Resource Affinity Table)
|
||||
// if node interleaving is disabled.
|
||||
isInterleaved = acpi_GetTable("SRAT") == 0;
|
||||
acpi_Shutdown();
|
||||
}
|
||||
else
|
||||
isInterleaved = 0; // can't tell
|
||||
// the BIOS only generates an SRAT (System Resource Affinity Table)
|
||||
// if node interleaving is disabled.
|
||||
isInterleaved = acpi_GetTable("SRAT") == 0;
|
||||
}
|
||||
|
||||
return isInterleaved != 0;
|
||||
@ -329,15 +315,10 @@ void* numa_Allocate(size_t size, LargePageDisposition largePageDisposition, size
|
||||
|
||||
static bool VerifyPages(void* mem, size_t size, size_t pageSize, size_t node)
|
||||
{
|
||||
typedef BOOL (WINAPI *PQueryWorkingSetEx)(HANDLE hProcess, PVOID buffer, DWORD bufferSize);
|
||||
static PQueryWorkingSetEx pQueryWorkingSetEx;
|
||||
WUTIL_FUNC(pQueryWorkingSetEx, BOOL, (HANDLE, PVOID, DWORD));
|
||||
WUTIL_IMPORT_KERNEL32(QueryWorkingSetEx, pQueryWorkingSetEx);
|
||||
if(!pQueryWorkingSetEx)
|
||||
{
|
||||
const HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll");
|
||||
pQueryWorkingSetEx = (PQueryWorkingSetEx)GetProcAddress(hKernel32, "QueryWorkingSetEx");
|
||||
if(!pQueryWorkingSetEx)
|
||||
return true; // can't do anything
|
||||
}
|
||||
return true; // can't do anything
|
||||
|
||||
#if WINVER >= 0x600
|
||||
size_t largePageSize = os_cpu_LargePageSize();
|
||||
|
@ -111,9 +111,9 @@ static const fs::wpath& GetDirectSoundDriverPath()
|
||||
{
|
||||
#define DS_OK 0
|
||||
typedef BOOL (CALLBACK* LPDSENUMCALLBACKW)(void*, const wchar_t*, const wchar_t*, void*);
|
||||
typedef HRESULT (WINAPI *PDirectSoundEnumerateW)(LPDSENUMCALLBACKW, void*);
|
||||
HMODULE hDsoundDll = LoadLibraryW(L"dsound.dll");
|
||||
PDirectSoundEnumerateW pDirectSoundEnumerateW = (PDirectSoundEnumerateW)GetProcAddress(hDsoundDll, "DirectSoundEnumerateW");
|
||||
WUTIL_FUNC(pDirectSoundEnumerateW, HRESULT, (LPDSENUMCALLBACKW, void*));
|
||||
WUTIL_IMPORT(hDsoundDll, DirectSoundEnumerateW, pDirectSoundEnumerateW);
|
||||
if(pDirectSoundEnumerateW)
|
||||
{
|
||||
HRESULT ret = pDirectSoundEnumerateW(DirectSoundCallback, (void*)0);
|
||||
|
Loading…
Reference in New Issue
Block a user