Commits

Mark Shannon committed 0bd811c Draft

Improve bytecode-level tracing to handle threads and processes

Comments (0)

Files changed (6)

Include/ceval_macros.h

         if (oflow)
             snprintf(buf, 9, " O.int");
         else
-            snprintf(buf, 9, " %d", l);
+            snprintf(buf, 9, " %ld", l);
     }
     else
         snprintf(buf, 9, " O.%s", obj->ob_type->tp_name);
     return &buf[0];
 }
 
-extern FILE *_HotPy_InstructionLog;
-
-static void _print_log(char *name, int rec_depth, int depth, PyObject **sp, int op)
+static void _print_log(char *name, PyThreadState *tstate, int depth, PyObject **sp, int op)
 {
     static char buf1[12];
     static char buf2[12];
-    fprintf(_HotPy_InstructionLog, "%s: [%d, %d%s%s] %s",
+    int rec_depth = tstate->recursion_depth;
+    if (tstate->_InstructionLog == NULL) {
+        char filename[100];
+        int pid = getpid();
+        sprintf(filename, "/tmp/hotpy.%lx.%x.log", tstate->thread_id, pid);
+        tstate->_InstructionLog = fopen(filename, "w+");
+        if (tstate->_InstructionLog == NULL)
+            _HotPy_Options.lltrace = 0;
+    }
+    fprintf(tstate->_InstructionLog, "%s: [%d, %d%s%s] %s",
             name, rec_depth, depth,
             depth > 1 ? small_rep(sp[-2], buf1) : "",
             depth ? small_rep(sp[-1], buf2) : "",
 }
 
 static void
-_log_op(char *name, int rec_depth, int depth, PyObject **sp, int op)
+_log_op(char *name, PyThreadState *tstate, int depth, PyObject **sp, int op)
 {
     if (sp == NULL)
         depth = 0;
-    _print_log(name, rec_depth, depth, sp, op);
-    fprintf(_HotPy_InstructionLog, "\n");
-    fflush(_HotPy_InstructionLog);
+    _print_log(name, tstate, depth, sp, op);
+    fprintf(tstate->_InstructionLog, "\n");
+    fflush(tstate->_InstructionLog);
 }
 
 static void
-_log_op_with_arg(char *name, int rec_depth, int depth, PyObject **sp, int op, int oparg)
+_log_op_with_arg(char *name, PyThreadState *tstate, int depth, PyObject **sp, int op, int oparg)
 {
-    _print_log(name, rec_depth, depth, sp, op);
-    fprintf(_HotPy_InstructionLog, " %d\n", oparg);
-    fflush(_HotPy_InstructionLog);
+    _print_log(name, tstate, depth, sp, op);
+    fprintf(tstate->_InstructionLog, " %d\n", oparg);
+    fflush(tstate->_InstructionLog);
 }
 
 #define LOG_OP(op) INC_ON_TRACE \
     if (_HotPy_Options.lltrace) \
-        _log_op(interpreter_name, tstate->recursion_depth, \
+        _log_op(interpreter_name, tstate, \
                 STACK_LEVEL(), f->f_stacktop, op);
 #define LOG_OP_ARG(op, oparg) INC_ON_TRACE \
     if (_HotPy_Options.lltrace) \
-        _log_op_with_arg(interpreter_name, tstate->recursion_depth, \
+        _log_op_with_arg(interpreter_name, tstate, \
                          STACK_LEVEL(), f->f_stacktop, op, oparg);
 
 #define LOG(txt) \
-    if (_HotPy_Options.lltrace) fprintf(_HotPy_InstructionLog, "%s\n", txt)
+    if (_HotPy_Options.lltrace && tstate->_InstructionLog) \
+        fprintf(tstate->_InstructionLog, "%s\n", txt)
 #define LOG_FMT(fmt, what) \
-    if (_HotPy_Options.lltrace) fprintf(_HotPy_InstructionLog, fmt, what)
+    if (_HotPy_Options.lltrace && tstate->_InstructionLog) \
+        fprintf(tstate->_InstructionLog, fmt, what)
 #define FLUSH_LOG() \
-    if (_HotPy_Options.lltrace) fflush(_HotPy_InstructionLog)
+    if (_HotPy_Options.lltrace && tstate->_InstructionLog) \
+        fflush(tstate->_InstructionLog)
 
 #else
 

Include/pystate.h

     long trace_ticks;
     /* XXX signal handlers should also be here */
 
+#ifdef Py_DEBUG
+    FILE *_InstructionLog;
+#endif
+
 } PyThreadState;
 #endif
 
     /* Update the threading module with the new state.
      */
     tstate = PyThreadState_GET();
+#ifdef Py_DEBUG
+    tstate->_InstructionLog = NULL;
+#endif
     threading = PyMapping_GetItemString(tstate->interp->modules,
                                         "threading");
     if (threading == NULL) {
         tstate->optimiser = NULL;
         tstate->execution_context = NULL;
         tstate->trace_recording = 0;
+        tstate->_InstructionLog = NULL;
 
         if (init)
             _PyThreadState_Init(tstate);

Python/trace_D_O_C.c

 
 #ifdef Py_DEBUG
 
-extern FILE *_HotPy_InstructionLog;
-static void log_context(HotPyContext *c) {
+static void log_context(PyThreadState *tstate, HotPyContext *c) {
     char buf[2000];
-    fprintf(_HotPy_InstructionLog, "State materialised:\n");
+    fprintf(tstate->_InstructionLog, "State materialised:\n");
     HotPyContext_Dump(&buf[0], c);
-    fprintf(_HotPy_InstructionLog, "%s", &buf[0]);
-    fflush(_HotPy_InstructionLog);
+    fprintf(tstate->_InstructionLog, "%s", &buf[0]);
+    fflush(tstate->_InstructionLog);
 }
 
-#define LOG_CONTEXT(c) if (_HotPy_Options.lltrace) log_context(c)
+#define LOG_CONTEXT(ts, c) if (_HotPy_Options.lltrace) log_context(ts, c)
 #else
-#define LOG_CONTEXT(c) ((void)0)
+#define LOG_CONTEXT(ts, c) ((void)0)
 #endif
 
 void
     PyFrameObject *next_frame = tstate->real_frame;
     PyFrameObject *stack[HOTPY_CONTEXT_DEPTH];
     int i, frames;
-    LOG_CONTEXT(context);
+    LOG_CONTEXT(tstate, context);
     _HotPy_Stats.materialisations++;
     HOTPY_TICK();
     frames = read_int(&code);

Python/trace_manager.c

      return 1;
 }
 
-#ifdef Py_DEBUG
-FILE *_HotPy_InstructionLog = NULL;
-#endif
-
 void _HotPyOptions_Init(void)
 {
     PyObject *xopts = PySys_GetXOptions();
     _HotPy_Options.show_stats = option(xopts, "stats", 0);
 #ifdef Py_DEBUG
     _HotPy_Options.lltrace = option(xopts, "lltrace", 0);
-    if (_HotPy_Options.lltrace && _HotPy_InstructionLog == NULL) {
-        _HotPy_InstructionLog = fopen("/tmp/hotpy_interpreter.log", "w+");
-        if ( _HotPy_InstructionLog == NULL)
-            _HotPy_Options.lltrace = 0;
-    }
 #endif
     _HotPy_Options.tracing = option(xopts, "tracing", 1);
      /* Turn these off by default for now */
     Py_ssize_t i = 0;
     PyObject *for_deletion;
 #ifdef Py_DEBUG
-    if (_HotPy_InstructionLog) fprintf(_HotPy_InstructionLog, "Decay\n");
+    if (_HotPy_Options.lltrace && tstate->_InstructionLog)
+        fprintf(tstate->_InstructionLog, "Decay\n");
 #endif
     if (tstate->trace_cache != NULL) {
         PyErr_Fetch(&e_ty, &e_ex, &e_tb);
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.