forked from adobe-flash/avmplus
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathSpyUtilsWinMo.cpp
143 lines (113 loc) · 3.7 KB
/
SpyUtilsWinMo.cpp
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
139
140
141
142
143
/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
/* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MMgc.h"
#ifdef MMGC_MEMORY_PROFILER
#include <Msgqueue.h>
/**
* compiled with the /W4 warning level
* which is quite picky. Disable warnings we don't care about.
*/
#ifdef _MSC_VER
#pragma warning(disable:4127) //conditional expression is constant
#endif
class SignalData : public MMgc::GCAllocObject
{
public:
SignalData(uint32_t *addr, HANDLE handle)
: profilerAddr(addr), eventHandle(handle) {}
uint32_t *profilerAddr;
HANDLE eventHandle;
};
void WriteOnNamedSignal(const char* name, uint32_t *addr);
static SignalData *sig_data=NULL;
static bool spyRunning=false;
static vmpi_spin_lock_t lock;
DWORD WINAPI WaitForMemorySignal(LPVOID)
{
SignalData *sd = sig_data;
while(spyRunning) {
WaitForSingleObject(sig_data->eventHandle, INFINITE);
// For some reason ReadMsgQueue does not clear the signal on the handle (even though it should), and we
// end up setting the profilerAddr constantly, which makes the VM hang, since all it is doing is writing out profile data.
// so we have to call CloseMsgQueue, and then open a new queue, and wait on that.
//char buff[256];
//DWORD bytesread;
//ReadMsgQueue(sig_data->eventHandle, buff, 256, &bytesread, INFINITE, 0);
CloseMsgQueue(sd->eventHandle);
if(spyRunning) {
VMPI_lockAcquire(&lock);
*(sig_data->profilerAddr) = true;
VMPI_lockRelease(&lock);
WriteOnNamedSignal("MMgc::MemoryProfiler::DumpFatties", sd->profilerAddr);
break;
}
}
delete sd;
return 0;
}
void WriteOnNamedSignal(const char *name, uint32_t *addr)
{
HANDLE m_namedSharedObject;
MSGQUEUEOPTIONS msgopts;
msgopts.dwFlags = MSGQUEUE_NOPRECOMMIT;
msgopts.dwMaxMessages = 1;
msgopts.cbMaxMessage = 256;
msgopts.bReadAccess = TRUE;
msgopts.dwSize = sizeof(MSGQUEUEOPTIONS);
WCHAR wName[256];
MultiByteToWideChar(CP_ACP, 0, name, -1, wName, 256);
m_namedSharedObject = CreateMsgQueue(wName, &msgopts);
sig_data = new SignalData(addr, m_namedSharedObject);
spyRunning = true;
CreateThread(NULL, 0, WaitForMemorySignal, NULL, 0, NULL);
}
#include "windows.h"
static uint32_t mmgc_spy_signal = 0;
FILE* spyStream = NULL;
void SpyLog(const char* message)
{
fprintf(spyStream, "%s", message);
}
typedef void (*LoggingFunction)(const char*);
extern LoggingFunction GetCurrentLogFunction();
extern void RedirectLogOutput(void (*)(const char*));
void VMPI_spyCallback()
{
if(mmgc_spy_signal)
{
VMPI_lockAcquire(&lock);
if(mmgc_spy_signal)
{
mmgc_spy_signal = 0;
spyStream = fopen("Temp\\gcstats.txt", "w");
GCAssert(spyStream != NULL);
LoggingFunction oldLogFunc = GetCurrentLogFunction();
RedirectLogOutput(SpyLog);
MMgc::GCHeap::GetGCHeap()->DumpMemoryInfo();
fflush(spyStream);
fclose(spyStream);
RedirectLogOutput(oldLogFunc);
spyStream = NULL;
}
VMPI_lockRelase(&lock);
}
}
bool VMPI_spySetup()
{
VMPI_lockInit(&lock);
WriteOnNamedSignal("MMgc::MemoryProfiler::DumpFatties", &mmgc_spy_signal);
return true;
}
void VMPI_spyTeardown()
{
VMPI_lockDestroy(&lock);
spyRunning = false;
}
bool VMPI_hasSymbols()
{
return false;
}
#endif //MMGC_MEMORY_PROFILER