2
// Copyright 2014 The ANGLE Project Authors. All rights reserved.
3
// Use of this source code is governed by a BSD-style license that can be
4
// found in the LICENSE file.
7
// test_utils_win32.cpp: Implementation of OS-specific functions for Win32 (Windows)
9
#include "util/test_utils.h"
14
#include "util/windows/third_party/StackWalker/src/StackWalker.h"
29
_(EXCEPTION_ACCESS_VIOLATION),
30
_(EXCEPTION_BREAKPOINT),
31
_(EXCEPTION_INT_DIVIDE_BY_ZERO),
32
_(EXCEPTION_STACK_OVERFLOW),
36
class CustomStackWalker : public StackWalker
39
CustomStackWalker() {}
40
~CustomStackWalker() override {}
42
void OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry) override
44
char buffer[STACKWALK_MAX_NAMELEN];
45
size_t maxLen = _TRUNCATE;
46
if ((eType != lastEntry) && (entry.offset != 0))
48
if (entry.name[0] == 0)
49
strncpy_s(entry.name, STACKWALK_MAX_NAMELEN, "(function-name not available)",
51
if (entry.undName[0] != 0)
52
strncpy_s(entry.name, STACKWALK_MAX_NAMELEN, entry.undName, _TRUNCATE);
53
if (entry.undFullName[0] != 0)
54
strncpy_s(entry.name, STACKWALK_MAX_NAMELEN, entry.undFullName, _TRUNCATE);
55
if (entry.lineFileName[0] == 0)
57
strncpy_s(entry.lineFileName, STACKWALK_MAX_NAMELEN, "(filename not available)",
59
if (entry.moduleName[0] == 0)
60
strncpy_s(entry.moduleName, STACKWALK_MAX_NAMELEN,
61
"(module-name not available)", _TRUNCATE);
62
_snprintf_s(buffer, maxLen, " %s - %p (%s): %s\n", entry.name,
63
reinterpret_cast<void *>(entry.offset), entry.moduleName,
67
_snprintf_s(buffer, maxLen, " %s (%s:%d)\n", entry.name, entry.lineFileName,
69
buffer[STACKWALK_MAX_NAMELEN - 1] = 0;
71
OutputDebugStringA(buffer);
76
void PrintBacktrace(CONTEXT *c)
78
printf("Backtrace:\n");
79
OutputDebugStringA("Backtrace:\n");
82
sw.ShowCallstack(GetCurrentThread(), c);
85
LONG WINAPI StackTraceCrashHandler(EXCEPTION_POINTERS *e)
87
const DWORD code = e->ExceptionRecord->ExceptionCode;
88
printf("\nCaught exception %lu", code);
89
for (size_t i = 0; i < ArraySize(kExceptions); i++)
91
if (kExceptions[i].code == code)
93
printf(" %s", kExceptions[i].name);
98
PrintBacktrace(e->ContextRecord);
100
// Exit NOW. Don't notify other threads, don't call anything registered with atexit().
103
// The compiler wants us to return something. This is what we'd do if we didn't _exit().
104
return EXCEPTION_EXECUTE_HANDLER;
107
CrashCallback *gCrashHandlerCallback;
109
LONG WINAPI CrashHandler(EXCEPTION_POINTERS *e)
111
if (gCrashHandlerCallback)
113
(*gCrashHandlerCallback)();
115
return StackTraceCrashHandler(e);
119
void SetLowPriorityProcess()
121
::SetPriorityClass(::GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);
124
bool StabilizeCPUForBenchmarking()
126
if (::SetThreadAffinityMask(::GetCurrentThread(), 1) == 0)
130
if (::SetPriorityClass(::GetCurrentProcess(), REALTIME_PRIORITY_CLASS) == FALSE)
134
if (::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL) == FALSE)
142
void PrintStackBacktrace()
145
ZeroMemory(&context, sizeof(CONTEXT));
146
RtlCaptureContext(&context);
147
PrintBacktrace(&context);
150
void InitCrashHandler(CrashCallback *callback)
154
gCrashHandlerCallback = callback;
156
SetUnhandledExceptionFilter(CrashHandler);
159
void TerminateCrashHandler()
161
gCrashHandlerCallback = nullptr;
162
SetUnhandledExceptionFilter(nullptr);
165
int NumberOfProcessors()
167
// A portable implementation could probably use GetLogicalProcessorInformation
168
return ::GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);