[pypy-commit] pypy default: copy over the implementation for pypy which was overwritten by the cpython version by merge
plan_rich
pypy.commits at gmail.com
Thu Mar 30 10:47:03 EDT 2017
Author: Richard Plangger <planrichi at gmail.com>
Branch:
Changeset: r90872:87791d83ead0
Date: 2017-03-30 10:44 -0400
http://bitbucket.org/pypy/pypy/changeset/87791d83ead0/
Log: copy over the implementation for pypy which was overwritten by the
cpython version by merge
diff --git a/rpython/rlib/rvmprof/src/shared/_vmprof.c b/rpython/rlib/rvmprof/src/shared/_vmprof.c
--- a/rpython/rlib/rvmprof/src/shared/_vmprof.c
+++ b/rpython/rlib/rvmprof/src/shared/_vmprof.c
@@ -150,23 +150,6 @@
Original_code_dealloc(co);
}
-
-void dump_native_symbols(int fileno)
-{
- PyObject * mod = NULL;
-
- mod = PyImport_ImportModuleNoBlock("vmprof");
- if (mod == NULL)
- goto error;
-
- PyObject_CallMethod(mod, "dump_native_symbols", "(l)", fileno);
-
-error:
- Py_XDECREF(mod);
-}
-
-
-
static PyObject *enable_vmprof(PyObject* self, PyObject *args)
{
int fd;
diff --git a/rpython/rlib/rvmprof/src/shared/_vmprof.h b/rpython/rlib/rvmprof/src/shared/_vmprof.h
--- a/rpython/rlib/rvmprof/src/shared/_vmprof.h
+++ b/rpython/rlib/rvmprof/src/shared/_vmprof.h
@@ -3,8 +3,15 @@
#include "vmprof.h"
#ifdef VMPROF_WINDOWS
+
+#include <Python.h>
+// CPython 3.6 defines all the inttypes for us, we do not need the msiinttypes
+// library for that version or any newer!
+#if (PY_VERSION_HEX < 0x3060000)
#include "msiinttypes/inttypes.h"
#include "msiinttypes/stdint.h"
+#endif
+
#else
#include <inttypes.h>
#include <stdint.h>
diff --git a/rpython/rlib/rvmprof/src/shared/symboltable.c b/rpython/rlib/rvmprof/src/shared/symboltable.c
--- a/rpython/rlib/rvmprof/src/shared/symboltable.c
+++ b/rpython/rlib/rvmprof/src/shared/symboltable.c
@@ -243,8 +243,6 @@
return 0;
}
-#ifdef RPYTHON_VMPROF
-
#define WORD_SIZE sizeof(long)
#define ADDR_SIZE sizeof(void*)
#define MAXLEN 1024
@@ -254,10 +252,12 @@
off_t pos_before;
struct str {
void * addr;
- // NOTE windows 64, not supported yet
+ // NOTE windows, not supported yet would be a problem for 64 bit
+ // hint: alignment
long size;
char str[1024];
} s;
+ fsync(fileno);
pos_before = lseek(fileno, 0, SEEK_CUR);
lseek(fileno, 0, SEEK_END);
@@ -286,7 +286,7 @@
{
long chars;
int count = read(fileno, &chars, sizeof(long));
- LOG("reading string of %d chars\n", chars);
+ //LOG("reading string of %d chars\n", chars);
if (count <= 0) {
return 1;
}
@@ -309,14 +309,14 @@
long _read_word(int fileno)
{
long w;
- read(fileno, &w, WORD_SIZE);
+ (void)read(fileno, &w, WORD_SIZE);
return w;
}
void * _read_addr(int fileno)
{
void * a;
- read(fileno, &a, ADDR_SIZE);
+ (void)read(fileno, &a, ADDR_SIZE);
return a;
}
@@ -341,21 +341,19 @@
void dump_native_symbols(int fileno)
{
- // only call this function
off_t orig_pos, cur_pos;
char marker;
ssize_t count;
int version;
int flags;
int memory = 0, lines = 0, native = 0;
+ fsync(fileno);
orig_pos = lseek(fileno, 0, SEEK_CUR);
lseek(fileno, 5*WORD_SIZE, SEEK_SET);
while (1) {
- LOG("pre read\n");
count = read(fileno, &marker, 1);
- LOG("post read\n");
if (count <= 0) {
break;
}
@@ -383,7 +381,7 @@
break;
} case MARKER_VIRTUAL_IP:
case MARKER_NATIVE_SYMBOLS: {
- LOG("virtip 0x%llx\n", cur_pos);
+ //LOG("virtip 0x%llx\n", cur_pos);
if (_skip_addr(fileno) != 0) { return; }
if (_skip_string(fileno) != 0) { return; }
break;
@@ -394,10 +392,16 @@
LOG("stack 0x%llx %d %d\n", cur_pos, trace_count, depth);
+#ifdef RPYTHON_VMPROF
for (i = depth/2-1; i >= 0; i--) {
long kind = (long)_read_addr(fileno);
void * addr = _read_addr(fileno);
if (kind == VMPROF_NATIVE_TAG) {
+#else
+ for (i = 0; i < depth; i++) {
+ void * addr = _read_addr(fileno);
+ if (((intptr_t)addr & 0x1) == 1) {
+#endif
LOG("found kind %p\n", addr);
char name[MAXLEN];
char srcfile[MAXLEN];
@@ -412,7 +416,9 @@
}
LOG("passed memory %d \n", memory);
- if (_skip_addr(fileno) != 0) { return; } // thread id
+ if (version >= VERSION_THREAD_ID) {
+ if (_skip_addr(fileno) != 0) { return; } // thread id
+ }
if (memory) {
if (_skip_addr(fileno) != 0) { return; } // profile memory
}
@@ -420,6 +426,7 @@
break;
} default: {
fprintf(stderr, "unknown marker 0x%x\n", marker);
+ lseek(fileno, 0, SEEK_END);
return;
}
}
@@ -432,4 +439,3 @@
lseek(fileno, 0, SEEK_END);
}
-#endif
diff --git a/rpython/rlib/rvmprof/src/shared/vmp_stack.c b/rpython/rlib/rvmprof/src/shared/vmp_stack.c
--- a/rpython/rlib/rvmprof/src/shared/vmp_stack.c
+++ b/rpython/rlib/rvmprof/src/shared/vmp_stack.c
@@ -126,7 +126,7 @@
}
int vmp_walk_and_record_python_stack_only(PY_STACK_FRAME_T *frame, void ** result,
- int max_depth, int depth, intptr_t pc)
+ int max_depth, int depth, intptr_t pc)
{
while (depth < max_depth && frame) {
frame = _write_python_stack_entry(frame, result, &depth, max_depth);
@@ -154,6 +154,25 @@
int max_depth, int signal, intptr_t pc) {
// called in signal handler
+ //
+ // This function records the stack trace for a python program. It also
+ // tracks native function calls if libunwind can be found on the system.
+ //
+ // The idea is the following (in the native case):
+ //
+ // 1) Remove frames until the signal frame is found (skipping it as well)
+ // 2) if the current frame corresponds to PyEval_EvalFrameEx (or the equivalent
+ // for each python version), the jump to 4)
+ // 3) jump to 2)
+ // 4) walk each python frame and record it
+ //
+ //
+ // There are several cases that need to be taken care of.
+ //
+ // CPython supports line profiling, PyPy does not. At the same time
+ // PyPy saves the information of an address in the same way as line information
+ // is saved in CPython. _write_python_stack_entry for details.
+ //
#ifdef VMP_SUPPORTS_NATIVE_PROFILING
intptr_t func_addr;
unw_cursor_t cursor;
diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_main.h b/rpython/rlib/rvmprof/src/shared/vmprof_main.h
--- a/rpython/rlib/rvmprof/src/shared/vmprof_main.h
+++ b/rpython/rlib/rvmprof/src/shared/vmprof_main.h
@@ -257,8 +257,15 @@
static int remove_sigprof_handler(void)
{
- if (signal(SIGPROF, SIG_DFL) == SIG_ERR)
+ struct sigaction ign_sigint, prev;
+ ign_sigint.sa_handler = SIG_IGN;
+ ign_sigint.sa_flags = 0;
+ sigemptyset(&ign_sigint.sa_mask);
+
+ if (sigaction(SIGPROF, &ign_sigint, NULL) < 0) {
+ fprintf(stderr, "Could not remove the signal handler (for profiling)\n");
return -1;
+ }
return 0;
}
@@ -275,12 +282,12 @@
static int remove_sigprof_timer(void) {
static struct itimerval timer;
- timer.it_interval.tv_sec = 0;
- timer.it_interval.tv_usec = 0;
- timer.it_value.tv_sec = 0;
- timer.it_value.tv_usec = 0;
- if (setitimer(ITIMER_PROF, &timer, NULL) != 0)
+ timerclear(&(timer.it_interval));
+ timerclear(&(timer.it_value));
+ if (setitimer(ITIMER_PROF, &timer, NULL) != 0) {
+ fprintf(stderr, "Could not disable the signal handler (for profiling)\n");
return -1;
+ }
return 0;
}
@@ -343,7 +350,6 @@
static void disable_cpyprof(void)
{
vmp_native_disable();
- dump_native_symbols(vmp_profile_fileno());
}
#endif
@@ -376,9 +382,15 @@
int close_profile(void)
{
+ int fileno = vmp_profile_fileno();
+ fsync(fileno);
+ dump_native_symbols(fileno);
+
(void)vmp_write_time_now(MARKER_TRAILER);
teardown_rss();
+
+
/* don't close() the file descriptor from here */
vmp_set_profile_fileno(-1);
return 0;
diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_main_win32.h b/rpython/rlib/rvmprof/src/shared/vmprof_main_win32.h
--- a/rpython/rlib/rvmprof/src/shared/vmprof_main_win32.h
+++ b/rpython/rlib/rvmprof/src/shared/vmprof_main_win32.h
@@ -19,6 +19,13 @@
int vmp_write_all(const char *buf, size_t bufsize);
+#ifdef VMPROF_RPYTHON
+typedef struct pypy_threadlocal_s PY_WIN_THREAD_STATE;
+#else
+typedef PyThreadState PY_WIN_THREAD_STATE;
+#endif
+
+
RPY_EXTERN
int vmprof_register_virtual_function(char *code_name, intptr_t code_uid,
int auto_retry)
@@ -35,11 +42,19 @@
return 0;
}
-int vmprof_snapshot_thread(DWORD thread_id, PyThreadState *tstate, prof_stacktrace_s *stack)
+int vmprof_snapshot_thread(DWORD thread_id, PY_WIN_THREAD_STATE *tstate, prof_stacktrace_s *stack)
{
HRESULT result;
- HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
+ HANDLE hThread;
int depth;
+ CONTEXT ctx;
+#ifdef RPYTHON_LL2CTYPES
+ return 0; // not much we can do
+#else
+#ifndef RPY_TLOFS_thread_ident
+ return 0; // we can't freeze threads, unsafe
+#else
+ hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
if (!hThread) {
return -1;
}
@@ -47,6 +62,19 @@
if(result == 0xffffffff)
return -1; // possible, e.g. attached debugger or thread alread suspended
// find the correct thread
+#ifdef RPYTHON_VMPROF
+ ctx.ContextFlags = CONTEXT_FULL;
+ if (!GetThreadContext(hThread, &ctx))
+ return -1;
+ depth = get_stack_trace(tstate->vmprof_tl_stack,
+ stack->stack, MAX_STACK_DEPTH-2, ctx.Eip);
+ stack->depth = depth;
+ stack->stack[depth++] = thread_id;
+ stack->count = 1;
+ stack->marker = MARKER_STACKTRACE;
+ ResumeThread(hThread);
+ return depth;
+#else
depth = vmp_walk_and_record_stack(tstate->frame, stack->stack,
MAX_STACK_DEPTH, 0, 0);
stack->depth = depth;
@@ -55,10 +83,15 @@
stack->marker = MARKER_STACKTRACE;
ResumeThread(hThread);
return depth;
+#endif
+
+#endif
+#endif
}
+#ifdef RPYTHON_VMPROF
static
-PyThreadState * get_current_thread_state(void)
+PY_WIN_THREAD_STATE * get_current_thread_state(void)
{
#if PY_MAJOR_VERSION < 3
return _PyThreadState_Current;
@@ -68,14 +101,21 @@
return _PyThreadState_UncheckedGet();
#endif
}
+#endif
long __stdcall vmprof_mainloop(void *arg)
-{
+{
+#ifdef RPYTHON_LL2CTYPES
+ // for tests only
+ return 0;
+#else
+ // it is not a test case!
+ PY_WIN_THREAD_STATE *tstate;
+ HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
prof_stacktrace_s *stack = (prof_stacktrace_s*)malloc(SINGLE_BUF_SIZE);
- HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
int depth;
- PyThreadState *tstate;
-
+#ifndef RPYTHON_VMPROF
+ // cpython version
while (1) {
Sleep(profile_interval_usec * 1000);
if (!enabled) {
@@ -90,6 +130,33 @@
SIZEOF_PROF_STACKTRACE + depth * sizeof(void*));
}
}
+#else
+ // pypy version
+ while (1) {
+ //Sleep(profile_interval_usec * 1000);
+ Sleep(10);
+ if (!enabled) {
+ continue;
+ }
+ _RPython_ThreadLocals_Acquire();
+ tstate = _RPython_ThreadLocals_Head(); // the first one is one behind head
+ tstate = _RPython_ThreadLocals_Enum(tstate);
+ while (tstate) {
+ if (p->ready == 42) {
+ depth = vmprof_snapshot_thread(tstate->thread_ident, tstate, stack);
+ if (depth > 0) {
+ _write_all((char*)stack + offsetof(prof_stacktrace_s, marker),
+ depth * sizeof(void *) +
+ sizeof(struct prof_stacktrace_s) -
+ offsetof(struct prof_stacktrace_s, marker));
+ }
+ }
+ tstate = _RPython_ThreadLocals_Enum(tstate);
+ }
+ _RPython_ThreadLocals_Release();
+ }
+#endif
+#endif
}
RPY_EXTERN
More information about the pypy-commit
mailing list