Author: Richard Plangger <planri...@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 _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit