[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