1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#include "common.h"
#include "CommonTypes.h"
#include "CommonMacros.h"
#include "daccess.h"
#include "PalRedhawkCommon.h"
#include "PalRedhawk.h"
#include "rhassert.h"
#include "slist.h"
#include "holder.h"
#include "Crst.h"
#include "rhbinder.h"
#include "RWLock.h"
#include "RuntimeInstance.h"
#include "gcrhinterface.h"
#include "shash.h"
#include "module.h"
// Macro nonsense to get around limitations of the C++ preprocessor.
#define MAKE_WIDE_STRING(_str) L ## _str
#define WIDE_STRING(_str) MAKE_WIDE_STRING(_str)
#define MAIN_RH_MODULE_NAME_W WIDE_STRING(RH_BASE_NAME)
#ifdef FEATURE_PROFILING
#ifndef APP_LOCAL_RUNTIME //need to sort out how to get this thread started, where to log, etc., without violating the WACK
UInt32 __stdcall ProfileThread(void *pv)
{
RuntimeInstance *runtimeInstance = (RuntimeInstance *)pv;
for (;;)
{
PalSleep(10*1000);
runtimeInstance->WriteProfileInfo();
}
}
#endif
void RuntimeInstance::InitProfiling(ModuleHeader *pModuleHeader)
{
#ifdef APP_LOCAL_RUNTIME //need to sort out how to get this thread started, where to log, etc., without violating the WACK
UNREFERENCED_PARAMETER(pModuleHeader);
#else
if (!m_fProfileThreadCreated && pModuleHeader->GetProfilingEntries() != NULL)
{
// this module has profile data, and we don't have a profile-writing thread yet
// so let's create one
UInt32 threadId;
PalCreateThread(NULL, 4096, ProfileThread, this, 0, &threadId);
m_fProfileThreadCreated = true;
}
#endif
}
void RuntimeInstance::WriteProfileInfo()
{
#ifndef APP_LOCAL_RUNTIME //need to sort out how to get this thread started, where to log, etc., without violating the WACK
FOREACH_MODULE(pModule)
{
PTR_ModuleHeader pModuleHeader = pModule->GetModuleHeader();
if (pModuleHeader->GetProfilingEntries() != NULL)
{
// our general error handling strategy is just to give up writing the profile
// if we encounter any errors or the names get insanely long
WCHAR *wzModuleFileName;
const size_t MAX_PATH = 260;
size_t moduleFileNameLength = PalGetModuleFileName(&wzModuleFileName, pModule->GetOsModuleHandle());
if (moduleFileNameLength >= MAX_PATH)
continue;
const UInt32 BUFFER_SIZE = 512;
WCHAR profileName[BUFFER_SIZE];
WCHAR *basicName = wcsrchr(wzModuleFileName, L'\\');
if (basicName == NULL)
basicName = wzModuleFileName;
else
basicName += 1; // skip past the '\'
size_t basicNameLength = wcslen(basicName);
size_t dirNameLength = PalGetEnvironmentVariable(L"LOCALAPPDATA", profileName, MAX_PATH);
// make sure the names are not so long as to cause trouble
const size_t MAX_SAFE_LENGTH = MAX_PATH - 50;
if ( basicNameLength >= MAX_SAFE_LENGTH
|| dirNameLength >= MAX_SAFE_LENGTH
|| basicNameLength + dirNameLength >= MAX_SAFE_LENGTH)
{
continue;
}
// make sure %LOCALAPPDATA%\Microsoft\mrt100\ProfileData exists
wcscat_s(profileName, L"\\Microsoft");
if (!PalCreateDirectoryW(profileName, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
continue;
wcscat_s(profileName, L"\\");
wcscat_s(profileName, MAIN_RH_MODULE_NAME_W);
if (!PalCreateDirectoryW(profileName, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
continue;
wcscat_s(profileName, L"\\ProfileData");
if (!PalCreateDirectoryW(profileName, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
continue;
// final filename is %LOCALAPPDATA%\Microsoft\mrt100\ProfileData\<basicName>.profile
wcscat_s(profileName, L"\\");
wcscat_s(profileName, basicName);
wcscat_s(profileName, L".profile");
HANDLE fileHandle = PalCreateFileW(profileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if (fileHandle == INVALID_HANDLE_VALUE)
{
continue;
}
else
{
ProfilingEntry *profilingEntry = (ProfilingEntry *)pModuleHeader->GetProfilingEntries();
ProfilingEntry *profilingEntryLast = profilingEntry + pModuleHeader->CountOfProfilingEntries;
for( ; profilingEntry < profilingEntryLast; profilingEntry++)
{
if (profilingEntry->m_count != 0)
{
UInt32 bytesWritten = 0;
if (!PalWriteFile(fileHandle, profilingEntry, sizeof(ProfilingEntry), &bytesWritten, NULL))
break;
}
}
PalCloseHandle(fileHandle);
}
}
}
END_FOREACH_MODULE;
#endif //!APP_LOCAL_RUNTIME
}
#endif // FEATURE_PROFILING
|