Skip to content

Commit 35a9234

Browse files
committed
fix windows compilation
1 parent af2deb6 commit 35a9234

File tree

6 files changed

+209
-194
lines changed

6 files changed

+209
-194
lines changed

setup.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ def run(self):
3333
# it might use the regiter rbx...
3434
extra_compile_args += ['-g']
3535
extra_compile_args += ['-O2']
36+
extra_source_files += ['src/vmprof_unix.c', 'src/vmprof_mt.c']
3637
elif sys.platform.startswith('linux'):
3738
libraries = ['dl','unwind']
3839
extra_compile_args = ['-Wno-unused']
@@ -43,6 +44,8 @@ def run(self):
4344
else:
4445
libraries.append('unwind-x86')
4546
extra_source_files += [
47+
'src/vmprof_mt.c',
48+
'src/vmprof_unix.c',
4649
'src/libbacktrace/backtrace.c',
4750
'src/libbacktrace/state.c',
4851
'src/libbacktrace/elf.c',
@@ -72,9 +75,7 @@ def run(self):
7275
'src/machine.c',
7376
'src/compat.c',
7477
'src/vmp_stack.c',
75-
'src/vmprof_unix.c',
7678
'src/vmprof_common.c',
77-
'src/vmprof_mt.c',
7879
'src/vmprof_memory.c',
7980
] + extra_source_files,
8081
depends=[

src/vmprof_common.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,21 @@ static pthread_t *threads = NULL;
3232
static size_t threads_size = 0;
3333
static size_t thread_count = 0;
3434
static size_t threads_size_step = 8;
35-
#endif
3635

3736
int vmprof_get_itimer_type(void) {
3837
return itimer_type;
3938
}
4039

40+
int vmprof_get_signal_type(void) {
41+
return signal_type;
42+
}
43+
#endif
44+
45+
#ifdef VMPROF_WINDOWS
46+
#include "vmprof_win.h"
47+
#endif
48+
49+
4150
int vmprof_is_enabled(void) {
4251
return is_enabled;
4352
}
@@ -62,10 +71,6 @@ void vmprof_set_profile_interval_usec(long value) {
6271
profile_interval_usec = value;
6372
}
6473

65-
int vmprof_get_signal_type(void) {
66-
return signal_type;
67-
}
68-
6974
char *vmprof_init(int fd, double interval, int memory,
7075
int proflines, const char *interp_name, int native, int real_time)
7176
{

src/vmprof_common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
#include <pthread.h>
1616
#endif
1717

18+
#ifdef VMPROF_UNIX
1819
#include "vmprof_getpc.h"
20+
#endif
1921

2022
#ifdef VMPROF_LINUX
2123
#include <syscall.h>

src/vmprof_memory.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include <mach/task_info.h>
99

1010
static mach_port_t mach_task;
11-
#else
11+
#elif defined(VMPROF_UNIX)
1212
#include <stdio.h>
1313
#include <stdlib.h>
1414
#include <sys/types.h>

src/vmprof_win.c

Lines changed: 183 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
// cannot include this header because it also has definitions
2-
#include "windows.h"
3-
#include "compat.h"
4-
#include "vmp_stack.h"
1+
#include "vmprof_win.h"
2+
3+
volatile int thread_started = 0;
4+
volatile int enabled = 0;
55

66
HANDLE write_mutex;
77

@@ -12,7 +12,20 @@ int prepare_concurrent_bufs(void)
1212
return 0;
1313
}
1414

15-
#include <tlhelp32.h>
15+
int vmprof_register_virtual_function(char *code_name, intptr_t code_uid,
16+
int auto_retry)
17+
{
18+
char buf[2048];
19+
long namelen;
20+
21+
namelen = (long)strnlen(code_name, 1023);
22+
buf[0] = MARKER_VIRTUAL_IP;
23+
*(intptr_t*)(buf + 1) = code_uid;
24+
*(long*)(buf + 1 + sizeof(intptr_t)) = namelen;
25+
memcpy(buf + 1 + sizeof(intptr_t) + sizeof(long), code_name, namelen);
26+
vmp_write_all(buf, 1 + sizeof(intptr_t) + sizeof(long) + namelen);
27+
return 0;
28+
}
1629

1730
int vmp_write_all(const char *buf, size_t bufsize)
1831
{
@@ -40,3 +53,168 @@ int vmp_write_all(const char *buf, size_t bufsize)
4053
return 0;
4154
}
4255

56+
HANDLE write_mutex;
57+
58+
#include "vmprof_common.h"
59+
60+
int vmprof_snapshot_thread(DWORD thread_id, PY_WIN_THREAD_STATE *tstate, prof_stacktrace_s *stack)
61+
{
62+
HRESULT result;
63+
HANDLE hThread;
64+
int depth;
65+
CONTEXT ctx;
66+
#ifdef RPYTHON_LL2CTYPES
67+
return 0; // not much we can do
68+
#else
69+
#if !defined(RPY_TLOFS_thread_ident) && defined(RPYTHON_VMPROF)
70+
return 0; // we can't freeze threads, unsafe
71+
#else
72+
hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
73+
if (!hThread) {
74+
return -1;
75+
}
76+
result = SuspendThread(hThread);
77+
if(result == 0xffffffff)
78+
return -1; // possible, e.g. attached debugger or thread alread suspended
79+
// find the correct thread
80+
#ifdef RPYTHON_VMPROF
81+
ctx.ContextFlags = CONTEXT_FULL;
82+
if (!GetThreadContext(hThread, &ctx))
83+
return -1;
84+
depth = get_stack_trace(tstate->vmprof_tl_stack,
85+
stack->stack, MAX_STACK_DEPTH-2, ctx.Eip);
86+
stack->depth = depth;
87+
stack->stack[depth++] = thread_id;
88+
stack->count = 1;
89+
stack->marker = MARKER_STACKTRACE;
90+
ResumeThread(hThread);
91+
return depth;
92+
#else
93+
depth = vmp_walk_and_record_stack(tstate->frame, stack->stack,
94+
MAX_STACK_DEPTH, 0, 0);
95+
stack->depth = depth;
96+
stack->stack[depth++] = (void*)((ULONG_PTR)thread_id);
97+
stack->count = 1;
98+
stack->marker = MARKER_STACKTRACE;
99+
ResumeThread(hThread);
100+
return depth;
101+
#endif
102+
103+
#endif
104+
#endif
105+
}
106+
107+
#ifndef RPYTHON_VMPROF
108+
static
109+
PY_WIN_THREAD_STATE * get_current_thread_state(void)
110+
{
111+
#if PY_MAJOR_VERSION < 3
112+
return _PyThreadState_Current;
113+
#elif PY_VERSION_HEX < 0x03050200
114+
return (PyThreadState*) _Py_atomic_load_relaxed(&_PyThreadState_Current);
115+
#else
116+
return _PyThreadState_UncheckedGet();
117+
#endif
118+
}
119+
#endif
120+
121+
long __stdcall vmprof_mainloop(void *arg)
122+
{
123+
#ifdef RPYTHON_LL2CTYPES
124+
// for tests only
125+
return 0;
126+
#else
127+
// it is not a test case!
128+
PY_WIN_THREAD_STATE *tstate;
129+
HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
130+
prof_stacktrace_s *stack = (prof_stacktrace_s*)malloc(SINGLE_BUF_SIZE);
131+
int depth;
132+
#ifndef RPYTHON_VMPROF
133+
// cpython version
134+
while (1) {
135+
Sleep(vmprof_get_profile_interval_usec() * 1000);
136+
if (!enabled) {
137+
continue;
138+
}
139+
tstate = get_current_thread_state();
140+
if (!tstate)
141+
continue;
142+
depth = vmprof_snapshot_thread(tstate->thread_id, tstate, stack);
143+
if (depth > 0) {
144+
vmp_write_all((char*)stack + offsetof(prof_stacktrace_s, marker),
145+
SIZEOF_PROF_STACKTRACE + depth * sizeof(void*));
146+
}
147+
}
148+
#else
149+
// pypy version
150+
while (1) {
151+
//Sleep(vmprof_get_profile_interval_usec() * 1000);
152+
Sleep(10);
153+
if (!enabled) {
154+
continue;
155+
}
156+
_RPython_ThreadLocals_Acquire();
157+
tstate = _RPython_ThreadLocals_Head(); // the first one is one behind head
158+
tstate = _RPython_ThreadLocals_Enum(tstate);
159+
while (tstate) {
160+
if (tstate->ready == 42) {
161+
depth = vmprof_snapshot_thread(tstate->thread_ident, tstate, stack);
162+
if (depth > 0) {
163+
vmp_write_all((char*)stack + offsetof(prof_stacktrace_s, marker),
164+
depth * sizeof(void *) +
165+
sizeof(struct prof_stacktrace_s) -
166+
offsetof(struct prof_stacktrace_s, marker));
167+
}
168+
}
169+
tstate = _RPython_ThreadLocals_Enum(tstate);
170+
}
171+
_RPython_ThreadLocals_Release();
172+
}
173+
#endif
174+
#endif
175+
}
176+
177+
RPY_EXTERN
178+
int vmprof_enable(int memory, int native, int real_time)
179+
{
180+
if (!thread_started) {
181+
if (!CreateThread(NULL, 0, vmprof_mainloop, NULL, 0, NULL)) {
182+
return -1;
183+
}
184+
thread_started = 1;
185+
}
186+
enabled = 1;
187+
return 0;
188+
}
189+
190+
RPY_EXTERN
191+
int vmprof_disable(void)
192+
{
193+
char marker = MARKER_TRAILER;
194+
(void)vmp_write_time_now(MARKER_TRAILER);
195+
196+
enabled = 0;
197+
vmp_set_profile_fileno(-1);
198+
return 0;
199+
}
200+
201+
RPY_EXTERN
202+
void vmprof_ignore_signals(int ignored)
203+
{
204+
enabled = !ignored;
205+
}
206+
207+
int vmp_native_enable(void)
208+
{
209+
return 0;
210+
}
211+
212+
void vmp_native_disable(void)
213+
{
214+
}
215+
216+
int get_stack_trace(PY_WIN_THREAD_STATE * current, void** result,
217+
int max_depth, intptr_t pc)
218+
{
219+
return 0;
220+
}

0 commit comments

Comments
 (0)