[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