[pypy-commit] pypy vmprof-native: copy dynamic loading for libunwind functions from pypy's history

plan_rich pypy.commits at gmail.com
Wed Mar 15 08:08:45 EDT 2017


Author: Richard Plangger <planrichi at gmail.com>
Branch: vmprof-native
Changeset: r90698:c6cdfd64054c
Date: 2017-03-14 15:12 +0100
http://bitbucket.org/pypy/pypy/changeset/c6cdfd64054c/

Log:	copy dynamic loading for libunwind functions from pypy's history

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
@@ -276,7 +276,7 @@
 
     for (i = 0; i < entry_count; i++) {
         routine_ip = m[i];
-        PyList_Append(list, PyLong_NEW((long)routine_ip));
+        PyList_Append(list, PyLong_NEW((ssize_t)routine_ip));
     }
 
     free(m);
diff --git a/rpython/rlib/rvmprof/src/shared/compat.h b/rpython/rlib/rvmprof/src/shared/compat.h
--- a/rpython/rlib/rvmprof/src/shared/compat.h
+++ b/rpython/rlib/rvmprof/src/shared/compat.h
@@ -7,12 +7,12 @@
       #define PyStr_AS_STRING PyBytes_AS_STRING
       #define PyStr_GET_SIZE PyBytes_GET_SIZE
       #define PyStr_NEW      PyUnicode_FromString
-      #define PyLong_NEW     PyLong_FromLong
+      #define PyLong_NEW     PyLong_FromSsize_t
 #  else
       #define PyStr_AS_STRING PyString_AS_STRING
       #define PyStr_GET_SIZE PyString_GET_SIZE
       #define PyStr_NEW      PyString_FromString
-      #define PyLong_NEW     PyInt_FromLong
+      #define PyLong_NEW     PyInt_FromSsize_t
 #  endif
 #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
@@ -16,12 +16,24 @@
 
 #ifdef VMP_SUPPORTS_NATIVE_PROFILING
 #define UNW_LOCAL_ONLY
-#include <libunwind.h>
+#include "unwind/libunwind.h"
 #  ifdef X86_64
 #    define REG_RBX UNW_X86_64_RBX
 #  elif defined(X86_32)
 #    define REG_RBX UNW_X86_EDI
 #  endif
+
+// functions copied from libunwind using dlopen
+
+#ifdef VMPROF_UNIX
+static int (*unw_get_reg)(unw_cursor_t*, int, unw_word_t*) = NULL;
+static int (*unw_step)(unw_cursor_t*) = NULL;
+static int (*unw_init_local)(unw_cursor_t *, unw_context_t *) = NULL;
+static int (*unw_get_proc_info)(unw_cursor_t *, unw_proc_info_t *) = NULL;
+static int (*unw_is_signal_frame)(unw_cursor_t *) = NULL;
+static int (*unw_getcontext)(unw_cursor_t *) = NULL;
+#endif
+
 #endif
 
 #ifdef __APPLE__
@@ -59,7 +71,7 @@
     int len;
     int addr;
     int j;
-    long line;
+    uint64_t line;
     char *lnotab;
 
 #ifndef RPYTHON_VMPROF // pypy does not support line profiling
@@ -76,7 +88,7 @@
         lnotab = PyStr_AS_STRING(frame->f_code->co_lnotab);
 
         if (lnotab != NULL) {
-            line = (long)frame->f_lineno;
+            line = (uint64_t)frame->f_lineno;
             addr = 0;
 
             len = (int)PyStr_GET_SIZE(frame->f_code->co_lnotab);
@@ -202,7 +214,6 @@
         //    printf("  %s %p\n", name, func_addr);
         //}
 
-
         //if (func_addr == 0) {
         //    unw_word_t rip = 0;
         //    if (unw_get_reg(&cursor, UNW_REG_IP, &rip) < 0) {
@@ -479,14 +490,47 @@
 }
 #endif
 
+static const char * vmprof_error = NULL;
+
 int vmp_native_enable(void) {
+    void * libhandle;
     vmp_native_traces_enabled = 1;
 
+    if (!unw_get_reg) {
+        if (!(libhandle = dlopen("libunwind.so", RTLD_LAZY | RTLD_LOCAL))) {
+            goto bail_out;
+        }
+        if (!(unw_getcontext = dlsym(libhandle, "_ULx86_64_getcontext"))) {
+            goto bail_out;
+        }
+        if (!(unw_get_reg = dlsym(libhandle, "_ULx86_64_get_reg"))) {
+            goto bail_out;
+        }
+        if (!(unw_get_proc_info = dlsym(libhandle, "_ULx86_64_get_proc_info"))){
+            goto bail_out;
+        }
+        if (!(unw_init_local = dlsym(libhandle, "_ULx86_64_init_local"))) {
+            goto bail_out;
+        }
+        if (!(unw_step = dlsym(libhandle, "_ULx86_64_step"))) {
+            goto bail_out;
+        }
+        if (!(unw_is_signal_frame = dlsym(libhandle, "_ULx86_64_is_signal_frame"))) {
+            goto bail_out;
+        }
+        if (dlclose(libhandle)) {
+            goto bail_out;
+        }
+    }
+
 #if defined(__unix__)
     return vmp_read_vmaps("/proc/self/maps");
 #elif defined(__APPLE__)
     return vmp_read_vmaps(NULL);
 #endif
+bail_out:
+    fprintf(stderr, "could not load libunwind at runtime. error: %s\n", vmprof_error);
+    return 0;
 }
 
 void vmp_native_disable(void) {
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
@@ -1,6 +1,8 @@
 #pragma once
 
+#ifdef VMPROF_UNIX
 #include <unistd.h>
+#endif
 
 // common defines
 #define MARKER_STACKTRACE '\x01'
@@ -52,6 +54,7 @@
 // for cpython
 #include "_vmprof.h"
 #include <Python.h>
+#include <pythread.h>
 #include <frameobject.h>
 #define PY_STACK_FRAME_T PyFrameObject
 #define PY_EVAL_RETURN_T PyObject
diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_common.h b/rpython/rlib/rvmprof/src/shared/vmprof_common.h
--- a/rpython/rlib/rvmprof/src/shared/vmprof_common.h
+++ b/rpython/rlib/rvmprof/src/shared/vmprof_common.h
@@ -48,7 +48,13 @@
  * is 4, but fails on win32
  */
 typedef struct prof_stacktrace_s {
+#ifdef VMPROF_WINDOWS
+    // if padding is 8 bytes, then on both 32bit and 64bit, the
+    // stack field is aligned
+    char padding[sizeof(void*) - 1];
+#else
     char padding[sizeof(long) - 1];
+#endif
     char marker;
     long count, depth;
     void *stack[];
@@ -96,16 +102,15 @@
     } header;
 
     const char * machine;
+    size_t namelen = strnlen(interp_name, 255);
 
     machine = vmp_machine_os_name();
 
-    size_t namelen = strnlen(interp_name, 255);
-
     header.hdr[0] = 0;
     header.hdr[1] = 3;
     header.hdr[2] = 0;
     header.hdr[3] = prepare_interval_usec;
-    if (strstr(machine, "win") != 0) {
+    if (strstr(machine, "win64") != 0) {
         header.hdr[4] = 1;
     } else {
         header.hdr[4] = 0;
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
@@ -12,10 +12,11 @@
  *
  * Tested only on gcc, linux, x86_64.
  *
- * Copyright (C) 2014-2015
+ * Copyright (C) 2014-2017
  *   Antonio Cuni - anto.cuni at gmail.com
  *   Maciej Fijalkowski - fijall at gmail.com
  *   Armin Rigo - arigo at tunes.org
+ *   Richard Plangger - planrichi at gmail.com
  *
  */
 
@@ -145,6 +146,35 @@
     return 1;
 }
 
+#ifndef RPYTHON_VMPROF
+static PY_THREAD_STATE_T * _get_pystate_for_this_thread(void) {
+    // see issue 116 on github.com/vmprof/vmprof-python.
+    // PyGILState_GetThisThreadState(); can hang forever
+    //
+    PyInterpreterState * istate;
+    PyThreadState * state;
+    long mythread_id;
+
+    istate = PyInterpreterState_Head();
+    if (istate == NULL) {
+        return NULL;
+    }
+    mythread_id = PyThread_get_thread_ident();
+    // fish fish fish, it will NOT lock the keymutex in pythread
+    do {
+        state = PyInterpreterState_ThreadHead(istate);
+        do {
+            if (state->thread_id == mythread_id) {
+                return state;
+            }
+        } while ((state = PyThreadState_Next(state)) != NULL);
+    } while ((istate = PyInterpreterState_Next(istate)) != NULL);
+
+    // uh? not found?
+    return NULL;
+}
+#endif
+
 static void sigprof_handler(int sig_nr, siginfo_t* info, void *ucontext)
 {
     int commit;
@@ -167,7 +197,7 @@
     int fault_code = setjmp(restore_point);
     if (fault_code == 0) {
         pthread_self();
-        tstate = PyGILState_GetThisThreadState();
+        tstate = _get_pystate_for_this_thread();
     } else {
         signal(SIGSEGV, prevhandler);
         __sync_lock_release(&spinlock);
diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_main_win32.c b/rpython/rlib/rvmprof/src/shared/vmprof_main_win32.c
--- a/rpython/rlib/rvmprof/src/shared/vmprof_main_win32.c
+++ b/rpython/rlib/rvmprof/src/shared/vmprof_main_win32.c
@@ -1,4 +1,4 @@
-
+// cannot include this header because it also has definitions
 #include "windows.h"
 #include "compat.h"
 #include "vmp_stack.h"
@@ -12,7 +12,6 @@
     return 0;
 }
 
-#include "vmprof_common.h"
 #include <tlhelp32.h>
 
 int vmp_write_all(const char *buf, size_t bufsize)
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
@@ -48,9 +48,9 @@
         return -1; // possible, e.g. attached debugger or thread alread suspended
     // find the correct thread
     depth = vmp_walk_and_record_stack(tstate->frame, stack->stack,
-                                      MAX_STACK_DEPTH, 0);
+                                      MAX_STACK_DEPTH, 0, 0);
     stack->depth = depth;
-    stack->stack[depth++] = (void*)thread_id;
+    stack->stack[depth++] = (void*)((ULONG_PTR)thread_id);
     stack->count = 1;
     stack->marker = MARKER_STACKTRACE;
     ResumeThread(hThread);
@@ -86,16 +86,14 @@
             continue;
         depth = vmprof_snapshot_thread(tstate->thread_id, tstate, stack);
         if (depth > 0) {
-            // see note in vmprof_common.h on the prof_stacktrace_s struct why
-            // there are two vmpr_write_all calls
-            vmp_write_all((char*)stack + offsetof(prof_stacktrace_s, marker), SIZEOF_PROF_STACKTRACE);
-            vmp_write_all((char*)stack->stack, depth * sizeof(void*));
+            vmp_write_all((char*)stack + offsetof(prof_stacktrace_s, marker),
+                          SIZEOF_PROF_STACKTRACE + depth * sizeof(void*));
         }
     }
 }
 
 RPY_EXTERN
-int vmprof_enable(int memory)
+int vmprof_enable(int memory, int native)
 {
     if (!thread_started) {
         if (!CreateThread(NULL, 0, vmprof_mainloop, NULL, 0, NULL)) {
@@ -121,4 +119,5 @@
 RPY_EXTERN
 void vmprof_ignore_signals(int ignored)
 {
+    enabled = !ignored;
 }


More information about the pypy-commit mailing list