14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* 24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * This is the High Performance Python Profiler portion of HotShot. 34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */ 44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "Python.h" 64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "code.h" 74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "eval.h" 84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "frameobject.h" 94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "structmember.h" 104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* 124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * Which timer to use should be made more configurable, but that should not 134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * be difficult. This will do for now. 144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */ 154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef MS_WINDOWS 164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include <windows.h> 174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef HAVE_DIRECT_H 194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include <direct.h> /* for getcwd() */ 204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtypedef __int64 hs_time; 234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define GETTIMEOFDAY(P_HS_TIME) \ 244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm { LARGE_INTEGER _temp; \ 254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm QueryPerformanceCounter(&_temp); \ 264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm *(P_HS_TIME) = _temp.QuadPart; } 274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else 304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifndef HAVE_GETTIMEOFDAY 314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#error "This module requires gettimeofday() on non-Windows platforms!" 324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#if (defined(PYOS_OS2) && defined(PYCC_GCC)) || defined(__QNX__) 344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include <sys/time.h> 354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else 364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include <sys/resource.h> 374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include <sys/times.h> 384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtypedef struct timeval hs_time; 404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#if !defined(__cplusplus) && !defined(inline) 434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef __GNUC__ 444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define inline __inline 454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifndef inline 494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define inline 504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define BUFFERSIZE 10240 534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#if defined(PYOS_OS2) && defined(PYCC_GCC) 554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define PATH_MAX 260 564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#if defined(__sgi) && _COMPILER_VERSION>700 && !defined(PATH_MAX) 594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* fix PATH_MAX not being defined with MIPSPro 7.x 604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if mode is ANSI C (default) */ 614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define PATH_MAX 1024 624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifndef PATH_MAX 654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# ifdef MAX_PATH 664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# define PATH_MAX MAX_PATH 674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# elif defined (_POSIX_PATH_MAX) 684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# define PATH_MAX _POSIX_PATH_MAX 694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# else 704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# error "Need a defn. for PATH_MAX in _hotshot.c" 714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# endif 724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtypedef struct { 754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject_HEAD 764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *filemap; 774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *logfilename; 784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_ssize_t index; 794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unsigned char buffer[BUFFERSIZE]; 804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm FILE *logfp; 814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int lineevents; 824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int linetimings; 834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int frametimings; 844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* size_t filled; */ 854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int active; 864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int next_fileno; 874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm hs_time prev_timeofday; 884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} ProfilerObject; 894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtypedef struct { 914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject_HEAD 924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *info; 934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm FILE *logfp; 944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int linetimings; 954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int frametimings; 964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} LogReaderObject; 974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject * ProfilerError = NULL; 994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifndef MS_WINDOWS 1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef GETTIMEOFDAY_NO_TZ 1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define GETTIMEOFDAY(ptv) gettimeofday((ptv)) 1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else 1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define GETTIMEOFDAY(ptv) gettimeofday((ptv), (struct timezone *)NULL) 1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* The log reader... */ 1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(logreader_close__doc__, 1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"close()\n" 1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"Close the log file, preventing additional records from being read."); 1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject * 1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmlogreader_close(LogReaderObject *self, PyObject *args) 1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->logfp != NULL) { 1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fclose(self->logfp); 1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->logfp = NULL; 1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(Py_None); 1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return Py_None; 1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(logreader_fileno__doc__, 1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"fileno() -> file descriptor\n" 1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"Returns the file descriptor for the log file, if open.\n" 1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"Raises ValueError if the log file is closed."); 1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject * 1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmlogreader_fileno(LogReaderObject *self) 1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->logfp == NULL) { 1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_SetString(PyExc_ValueError, 1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "logreader's file object already closed"); 1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return PyInt_FromLong(fileno(self->logfp)); 1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* Log File Format 1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * --------------- 1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * The log file consists of a sequence of variable-length records. 1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * Each record is identified with a record type identifier in two 1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * bits of the first byte. The two bits are the "least significant" 1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * bits of the byte. 1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * Low bits: Opcode: Meaning: 1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 0x00 ENTER enter a frame 1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 0x01 EXIT exit a frame 1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 0x02 LINENO execution moved onto a different line 1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 0x03 OTHER more bits are needed to deecode 1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * If the type is OTHER, the record is not packed so tightly, and the 1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * remaining bits are used to disambiguate the record type. These 1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * records are not used as frequently so compaction is not an issue. 1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * Each of the first three record types has a highly tailored 1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * structure that allows it to be packed tightly. 1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * The OTHER records have the following identifiers: 1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * First byte: Opcode: Meaning: 1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 0x13 ADD_INFO define a key/value pair 1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 0x23 DEFINE_FILE define an int->filename mapping 1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 0x33 LINE_TIMES indicates if LINENO events have tdeltas 1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 0x43 DEFINE_FUNC define a (fileno,lineno)->funcname mapping 1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 0x53 FRAME_TIMES indicates if ENTER/EXIT events have tdeltas 1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * Packed Integers 1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * "Packed integers" are non-negative integer values encoded as a 1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * sequence of bytes. Each byte is encoded such that the most 1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * significant bit is set if the next byte is also part of the 1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * integer. Each byte provides bits to the least-significant end of 1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * the result; the accumulated value must be shifted up to place the 1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * new bits into the result. 1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * "Modified packed integers" are packed integers where only a portion 1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * of the first byte is used. In the rest of the specification, these 1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * are referred to as "MPI(n,name)", where "n" is the number of bits 1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * discarded from the least-signicant positions of the byte, and 1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * "name" is a name being given to those "discarded" bits, since they 1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * are a field themselves. 1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * ENTER records: 1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * MPI(2,type) fileno -- type is 0x00 1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * PI lineno 1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * PI tdelta -- iff frame times are enabled 1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * EXIT records 1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * MPI(2,type) tdelta -- type is 0x01; tdelta will be 0 1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * if frame times are disabled 2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * LINENO records 2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * MPI(2,type) lineno -- type is 0x02 2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * PI tdelta -- iff LINENO includes it 2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * ADD_INFO records 2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * BYTE type -- always 0x13 2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * PI len1 -- length of first string 2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * BYTE string1[len1] -- len1 bytes of string data 2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * PI len2 -- length of second string 2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * BYTE string2[len2] -- len2 bytes of string data 2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * DEFINE_FILE records 2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * BYTE type -- always 0x23 2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * PI fileno 2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * PI len -- length of filename 2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * BYTE filename[len] -- len bytes of string data 2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * DEFINE_FUNC records 2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * BYTE type -- always 0x43 2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * PI fileno 2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * PI lineno 2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * PI len -- length of funcname 2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * BYTE funcname[len] -- len bytes of string data 2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * LINE_TIMES records 2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * This record can be used only before the start of ENTER/EXIT/LINENO 2324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * records. If have_tdelta is true, LINENO records will include the 2334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * tdelta field, otherwise it will be omitted. If this record is not 2344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * given, LINENO records will not contain the tdelta field. 2354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 2364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * BYTE type -- always 0x33 2374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * BYTE have_tdelta -- 0 if LINENO does *not* have 2384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * timing information 2394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * FRAME_TIMES records 2404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 2414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * This record can be used only before the start of ENTER/EXIT/LINENO 2424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * records. If have_tdelta is true, ENTER and EXIT records will 2434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * include the tdelta field, otherwise it will be omitted. If this 2444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * record is not given, ENTER and EXIT records will contain the tdelta 2454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * field. 2464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 2474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * BYTE type -- always 0x53 2484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * BYTE have_tdelta -- 0 if ENTER/EXIT do *not* have 2494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * timing information 2504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */ 2514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define WHAT_ENTER 0x00 2534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define WHAT_EXIT 0x01 2544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define WHAT_LINENO 0x02 2554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define WHAT_OTHER 0x03 /* only used in decoding */ 2564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define WHAT_ADD_INFO 0x13 2574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define WHAT_DEFINE_FILE 0x23 2584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define WHAT_LINE_TIMES 0x33 2594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define WHAT_DEFINE_FUNC 0x43 2604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define WHAT_FRAME_TIMES 0x53 2614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define ERR_NONE 0 2634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define ERR_EOF -1 2644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define ERR_EXCEPTION -2 2654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define ERR_BAD_RECTYPE -3 2664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define PISIZE (sizeof(int) + 1) 2684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define MPISIZE (PISIZE + 1) 2694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* Maximum size of "normal" events -- nothing that contains string data */ 2714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define MAXEVENTSIZE (MPISIZE + PISIZE*2) 2724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* Unpack a packed integer; if "discard" is non-zero, unpack a modified 2754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * packed integer with "discard" discarded bits. 2764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */ 2774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int 2784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmunpack_packed_int(LogReaderObject *self, int *pvalue, int discard) 2794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 2804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int c; 2814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int accum = 0; 2824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int bits = 0; 2834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int cont; 2844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm do { 2864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* read byte */ 2874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if ((c = fgetc(self->logfp)) == EOF) 2884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return ERR_EOF; 2894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm accum |= ((c & 0x7F) >> discard) << bits; 2904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm bits += (7 - discard); 2914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm cont = c & 0x80; 2924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm discard = 0; 2934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } while (cont); 2944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm *pvalue = accum; 2964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 2984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 2994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* Unpack a string, which is encoded as a packed integer giving the 3014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * length of the string, followed by the string data. 3024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */ 3034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int 3044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmunpack_string(LogReaderObject *self, PyObject **pvalue) 3054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 3064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int i; 3074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int len; 3084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int err; 3094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int ch; 3104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm char *buf; 3114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if ((err = unpack_packed_int(self, &len, 0))) 3134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return err; 3144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm buf = (char *)malloc(len); 3164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!buf) { 3174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_NoMemory(); 3184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return ERR_EXCEPTION; 3194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 3204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for (i=0; i < len; i++) { 3224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ch = fgetc(self->logfp); 3234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm buf[i] = ch; 3244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (ch == EOF) { 3254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm free(buf); 3264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return ERR_EOF; 3274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 3284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 3294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm *pvalue = PyString_FromStringAndSize(buf, len); 3304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm free(buf); 3314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (*pvalue == NULL) { 3324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return ERR_EXCEPTION; 3334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 3344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 3354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 3364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int 3394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmunpack_add_info(LogReaderObject *self) 3404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 3414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *key; 3424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *value = NULL; 3434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int err; 3444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = unpack_string(self, &key); 3464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!err) { 3474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = unpack_string(self, &value); 3484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (err) 3494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(key); 3504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else { 3514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *list = PyDict_GetItem(self->info, key); 3524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (list == NULL) { 3534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm list = PyList_New(0); 3544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (list == NULL) { 3554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = ERR_EXCEPTION; 3564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm goto finally; 3574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 3584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (PyDict_SetItem(self->info, key, list)) { 3594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(list); 3604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = ERR_EXCEPTION; 3614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm goto finally; 3624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 3634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(list); 3644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 3654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (PyList_Append(list, value)) 3664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = ERR_EXCEPTION; 3674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 3684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 3694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 3704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_XDECREF(key); 3714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_XDECREF(value); 3724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return err; 3734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 3744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void 3774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmeof_error(LogReaderObject *self) 3784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 3794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fclose(self->logfp); 3804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->logfp = NULL; 3814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_SetString(PyExc_EOFError, 3824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "end of file with incomplete profile record"); 3834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 3844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject * 3864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmlogreader_tp_iternext(LogReaderObject *self) 3874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 3884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int c; 3894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int what; 3904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int err = ERR_NONE; 3914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int lineno = -1; 3924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int fileno = -1; 3934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int tdelta = -1; 3944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *s1 = NULL, *s2 = NULL; 3954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *result = NULL; 3964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#if 0 3974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unsigned char b0, b1; 3984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 3994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->logfp == NULL) { 4014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_SetString(ProfilerError, 4024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "cannot iterate over closed LogReader object"); 4034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 4044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 4054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmrestart: 4074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* decode the record type */ 4084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if ((c = fgetc(self->logfp)) == EOF) { 4094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fclose(self->logfp); 4104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->logfp = NULL; 4114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 4124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 4134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm what = c & WHAT_OTHER; 4144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (what == WHAT_OTHER) 4154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm what = c; /* need all the bits for type */ 4164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else 4174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ungetc(c, self->logfp); /* type byte includes packed int */ 4184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm switch (what) { 4204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm case WHAT_ENTER: 4214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = unpack_packed_int(self, &fileno, 2); 4224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!err) { 4234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = unpack_packed_int(self, &lineno, 0); 4244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->frametimings && !err) 4254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = unpack_packed_int(self, &tdelta, 0); 4264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 4274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break; 4284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm case WHAT_EXIT: 4294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = unpack_packed_int(self, &tdelta, 2); 4304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break; 4314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm case WHAT_LINENO: 4324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = unpack_packed_int(self, &lineno, 2); 4334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->linetimings && !err) 4344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = unpack_packed_int(self, &tdelta, 0); 4354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break; 4364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm case WHAT_ADD_INFO: 4374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = unpack_add_info(self); 4384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break; 4394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm case WHAT_DEFINE_FILE: 4404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = unpack_packed_int(self, &fileno, 0); 4414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!err) { 4424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = unpack_string(self, &s1); 4434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!err) { 4444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(Py_None); 4454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s2 = Py_None; 4464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 4474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 4484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break; 4494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm case WHAT_DEFINE_FUNC: 4504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = unpack_packed_int(self, &fileno, 0); 4514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!err) { 4524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = unpack_packed_int(self, &lineno, 0); 4534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!err) 4544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = unpack_string(self, &s1); 4554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 4564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break; 4574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm case WHAT_LINE_TIMES: 4584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if ((c = fgetc(self->logfp)) == EOF) 4594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = ERR_EOF; 4604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else { 4614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->linetimings = c ? 1 : 0; 4624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm goto restart; 4634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 4644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break; 4654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm case WHAT_FRAME_TIMES: 4664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if ((c = fgetc(self->logfp)) == EOF) 4674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = ERR_EOF; 4684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else { 4694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->frametimings = c ? 1 : 0; 4704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm goto restart; 4714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 4724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break; 4734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm default: 4744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = ERR_BAD_RECTYPE; 4754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 4764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (err == ERR_BAD_RECTYPE) { 4774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_SetString(PyExc_ValueError, 4784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "unknown record type in log file"); 4794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 4804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else if (err == ERR_EOF) { 4814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eof_error(self); 4824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 4834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else if (!err) { 4844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm result = PyTuple_New(4); 4854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (result == NULL) 4864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 4874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyTuple_SET_ITEM(result, 0, PyInt_FromLong(what)); 4884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyTuple_SET_ITEM(result, 2, PyInt_FromLong(fileno)); 4894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (s1 == NULL) 4904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyTuple_SET_ITEM(result, 1, PyInt_FromLong(tdelta)); 4914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else 4924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyTuple_SET_ITEM(result, 1, s1); 4934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (s2 == NULL) 4944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyTuple_SET_ITEM(result, 3, PyInt_FromLong(lineno)); 4954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else 4964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyTuple_SET_ITEM(result, 3, s2); 4974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 4984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* The only other case is err == ERR_EXCEPTION, in which case the 4994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * exception is already set. 5004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */ 5014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#if 0 5024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm b0 = self->buffer[self->index]; 5034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm b1 = self->buffer[self->index + 1]; 5044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (b0 & 1) { 5054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* This is a line-number event. */ 5064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm what = PyTrace_LINE; 5074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm lineno = ((b0 & ~1) << 7) + b1; 5084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->index += 2; 5094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 5104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else { 5114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm what = (b0 & 0x0E) >> 1; 5124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm tdelta = ((b0 & 0xF0) << 4) + b1; 5134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (what == PyTrace_CALL) { 5144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* we know there's a 2-byte file ID & 2-byte line number */ 5154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fileno = ((self->buffer[self->index + 2] << 8) 5164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm + self->buffer[self->index + 3]); 5174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm lineno = ((self->buffer[self->index + 4] << 8) 5184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm + self->buffer[self->index + 5]); 5194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->index += 6; 5204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 5214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else 5224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->index += 2; 5234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 5244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 5254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return result; 5264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 5274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void 5294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmlogreader_dealloc(LogReaderObject *self) 5304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 5314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->logfp != NULL) { 5324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fclose(self->logfp); 5334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->logfp = NULL; 5344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 5354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_XDECREF(self->info); 5364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject_Del(self); 5374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 5384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject * 5404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmlogreader_sq_item(LogReaderObject *self, Py_ssize_t index) 5414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 5424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *result = logreader_tp_iternext(self); 5434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (result == NULL && !PyErr_Occurred()) { 5444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_SetString(PyExc_IndexError, "no more events in log"); 5454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 5464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 5474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return result; 5484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 5494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void 5514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdo_stop(ProfilerObject *self); 5524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int 5544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmflush_data(ProfilerObject *self) 5554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 5564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* Need to dump data to the log file... */ 5574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm size_t written = fwrite(self->buffer, 1, self->index, self->logfp); 5584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (written == (size_t)self->index) 5594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->index = 0; 5604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else { 5614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm memmove(self->buffer, &self->buffer[written], 5624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->index - written); 5634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->index -= written; 5644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (written == 0) { 5654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm char *s = PyString_AsString(self->logfilename); 5664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_SetFromErrnoWithFilename(PyExc_IOError, s); 5674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm do_stop(self); 5684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 5694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 5704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 5714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (written > 0) { 5724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (fflush(self->logfp)) { 5734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm char *s = PyString_AsString(self->logfilename); 5744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_SetFromErrnoWithFilename(PyExc_IOError, s); 5754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm do_stop(self); 5764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 5774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 5784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 5794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 5804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 5814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic inline int 5834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpack_packed_int(ProfilerObject *self, int value) 5844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 5854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unsigned char partial; 5864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm do { 5884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm partial = value & 0x7F; 5894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm value >>= 7; 5904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (value) 5914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm partial |= 0x80; 5924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->buffer[self->index] = partial; 5934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->index++; 5944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } while (value); 5954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 5964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 5974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* Encode a modified packed integer, with a subfield of modsize bits 5994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * containing the value "subfield". The value of subfield is not 6004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * checked to ensure it actually fits in modsize bits. 6014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */ 6024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic inline int 6034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpack_modified_packed_int(ProfilerObject *self, int value, 6044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int modsize, int subfield) 6054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 6064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm const int maxvalues[] = {-1, 1, 3, 7, 15, 31, 63, 127}; 6074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int bits = 7 - modsize; 6094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int partial = value & maxvalues[bits]; 6104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unsigned char b = subfield | (partial << modsize); 6114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (partial != value) { 6134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm b |= 0x80; 6144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->buffer[self->index] = b; 6154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->index++; 6164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return pack_packed_int(self, value >> bits); 6174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 6184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->buffer[self->index] = b; 6194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->index++; 6204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 6214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 6224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int 6244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpack_string(ProfilerObject *self, const char *s, Py_ssize_t len) 6254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 6264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (len + PISIZE + self->index >= BUFFERSIZE) { 6274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (flush_data(self) < 0) 6284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 6294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 6304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm assert(len < INT_MAX); 6314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (pack_packed_int(self, (int)len) < 0) 6324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 6334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm memcpy(self->buffer + self->index, s, len); 6344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->index += len; 6354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 6364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 6374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int 6394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpack_add_info(ProfilerObject *self, const char *s1, const char *s2) 6404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 6414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_ssize_t len1 = strlen(s1); 6424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_ssize_t len2 = strlen(s2); 6434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (len1 + len2 + PISIZE*2 + 1 + self->index >= BUFFERSIZE) { 6454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (flush_data(self) < 0) 6464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 6474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 6484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->buffer[self->index] = WHAT_ADD_INFO; 6494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->index++; 6504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (pack_string(self, s1, len1) < 0) 6514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 6524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return pack_string(self, s2, len2); 6534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 6544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int 6564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpack_define_file(ProfilerObject *self, int fileno, const char *filename) 6574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 6584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_ssize_t len = strlen(filename); 6594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (len + PISIZE*2 + 1 + self->index >= BUFFERSIZE) { 6614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (flush_data(self) < 0) 6624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 6634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 6644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->buffer[self->index] = WHAT_DEFINE_FILE; 6654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->index++; 6664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (pack_packed_int(self, fileno) < 0) 6674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 6684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return pack_string(self, filename, len); 6694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 6704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int 6724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpack_define_func(ProfilerObject *self, int fileno, int lineno, 6734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm const char *funcname) 6744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 6754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_ssize_t len = strlen(funcname); 6764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (len + PISIZE*3 + 1 + self->index >= BUFFERSIZE) { 6784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (flush_data(self) < 0) 6794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 6804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 6814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->buffer[self->index] = WHAT_DEFINE_FUNC; 6824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->index++; 6834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (pack_packed_int(self, fileno) < 0) 6844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 6854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (pack_packed_int(self, lineno) < 0) 6864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 6874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return pack_string(self, funcname, len); 6884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 6894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int 6914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpack_line_times(ProfilerObject *self) 6924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 6934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (2 + self->index >= BUFFERSIZE) { 6944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (flush_data(self) < 0) 6954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 6964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 6974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->buffer[self->index] = WHAT_LINE_TIMES; 6984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->buffer[self->index + 1] = self->linetimings ? 1 : 0; 6994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->index += 2; 7004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 7014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 7024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int 7044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpack_frame_times(ProfilerObject *self) 7054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 7064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (2 + self->index >= BUFFERSIZE) { 7074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (flush_data(self) < 0) 7084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 7094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 7104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->buffer[self->index] = WHAT_FRAME_TIMES; 7114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->buffer[self->index + 1] = self->frametimings ? 1 : 0; 7124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->index += 2; 7134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 7144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 7154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic inline int 7174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpack_enter(ProfilerObject *self, int fileno, int tdelta, int lineno) 7184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 7194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (MPISIZE + PISIZE*2 + self->index >= BUFFERSIZE) { 7204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (flush_data(self) < 0) 7214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 7224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 7234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pack_modified_packed_int(self, fileno, 2, WHAT_ENTER); 7244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pack_packed_int(self, lineno); 7254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->frametimings) 7264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return pack_packed_int(self, tdelta); 7274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else 7284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 7294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 7304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic inline int 7324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpack_exit(ProfilerObject *self, int tdelta) 7334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 7344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (MPISIZE + self->index >= BUFFERSIZE) { 7354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (flush_data(self) < 0) 7364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 7374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 7384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->frametimings) 7394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return pack_modified_packed_int(self, tdelta, 2, WHAT_EXIT); 7404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->buffer[self->index] = WHAT_EXIT; 7414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->index++; 7424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 7434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 7444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic inline int 7464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpack_lineno(ProfilerObject *self, int lineno) 7474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 7484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (MPISIZE + self->index >= BUFFERSIZE) { 7494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (flush_data(self) < 0) 7504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 7514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 7524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return pack_modified_packed_int(self, lineno, 2, WHAT_LINENO); 7534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 7544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic inline int 7564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpack_lineno_tdelta(ProfilerObject *self, int lineno, int tdelta) 7574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 7584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (MPISIZE + PISIZE + self->index >= BUFFERSIZE) { 7594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (flush_data(self) < 0) 7604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 7614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 7624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (pack_modified_packed_int(self, lineno, 2, WHAT_LINENO) < 0) 7634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 7644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return pack_packed_int(self, tdelta); 7654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 7664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic inline int 7684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmget_fileno(ProfilerObject *self, PyCodeObject *fcode) 7694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 7704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* This is only used for ENTER events. */ 7714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *obj; 7734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *dict; 7744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int fileno; 7754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm obj = PyDict_GetItem(self->filemap, fcode->co_filename); 7774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (obj == NULL) { 7784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* first sighting of this file */ 7794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm dict = PyDict_New(); 7804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (dict == NULL) { 7814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 7824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 7834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fileno = self->next_fileno; 7844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm obj = Py_BuildValue("iN", fileno, dict); 7854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (obj == NULL) { 7864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 7874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 7884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (PyDict_SetItem(self->filemap, fcode->co_filename, obj)) { 7894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(obj); 7904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 7914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 7924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->next_fileno++; 7934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(obj); 7944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (pack_define_file(self, fileno, 7954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyString_AS_STRING(fcode->co_filename)) < 0) 7964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 7974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 7984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else { 7994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* already know this ID */ 8004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fileno = PyInt_AS_LONG(PyTuple_GET_ITEM(obj, 0)); 8014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm dict = PyTuple_GET_ITEM(obj, 1); 8024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 8034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* make sure we save a function name for this (fileno, lineno) */ 8044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm obj = PyInt_FromLong(fcode->co_firstlineno); 8054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (obj == NULL) { 8064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* We just won't have it saved; too bad. */ 8074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_Clear(); 8084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 8094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else { 8104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *name = PyDict_GetItem(dict, obj); 8114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (name == NULL) { 8124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (pack_define_func(self, fileno, fcode->co_firstlineno, 8134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyString_AS_STRING(fcode->co_name)) < 0) { 8144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(obj); 8154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 8164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 8174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (PyDict_SetItem(dict, obj, fcode->co_name)) { 8184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(obj); 8194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 8204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 8214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 8224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(obj); 8234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 8244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return fileno; 8254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 8264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic inline int 8284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmget_tdelta(ProfilerObject *self) 8294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 8304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int tdelta; 8314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef MS_WINDOWS 8324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm hs_time tv; 8334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm hs_time diff; 8344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm GETTIMEOFDAY(&tv); 8364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm diff = tv - self->prev_timeofday; 8374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm tdelta = (int)diff; 8384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else 8394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm struct timeval tv; 8404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm GETTIMEOFDAY(&tv); 8424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm tdelta = tv.tv_usec - self->prev_timeofday.tv_usec; 8444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (tv.tv_sec != self->prev_timeofday.tv_sec) 8454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm tdelta += (tv.tv_sec - self->prev_timeofday.tv_sec) * 1000000; 8464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 8474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* time can go backwards on some multiprocessor systems or by NTP */ 8484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (tdelta < 0) 8494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 8504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->prev_timeofday = tv; 8524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return tdelta; 8534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 8544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* The workhorse: the profiler callback function. */ 8574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int 8594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtracer_callback(ProfilerObject *self, PyFrameObject *frame, int what, 8604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *arg) 8614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 8624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int fileno; 8634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm switch (what) { 8654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm case PyTrace_CALL: 8664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fileno = get_fileno(self, frame->f_code); 8674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (fileno < 0) 8684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 8694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return pack_enter(self, fileno, 8704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->frametimings ? get_tdelta(self) : -1, 8714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm frame->f_code->co_firstlineno); 8724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm case PyTrace_RETURN: 8744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return pack_exit(self, get_tdelta(self)); 8754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm case PyTrace_LINE: /* we only get these events if we asked for them */ 8774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->linetimings) 8784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return pack_lineno_tdelta(self, frame->f_lineno, 8794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm get_tdelta(self)); 8804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else 8814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return pack_lineno(self, frame->f_lineno); 8824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm default: 8844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* ignore PyTrace_EXCEPTION */ 8854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break; 8864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 8874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 8884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 8894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* A couple of useful helper functions. */ 8924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef MS_WINDOWS 8944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic LARGE_INTEGER frequency = {0, 0}; 8954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 8964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic unsigned long timeofday_diff = 0; 8984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic unsigned long rusage_diff = 0; 8994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void 9014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmcalibrate(void) 9024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 9034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm hs_time tv1, tv2; 9044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef MS_WINDOWS 9064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm hs_time diff; 9074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm QueryPerformanceFrequency(&frequency); 9084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 9094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm GETTIMEOFDAY(&tv1); 9114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm while (1) { 9124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm GETTIMEOFDAY(&tv2); 9134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef MS_WINDOWS 9144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm diff = tv2 - tv1; 9154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (diff != 0) { 9164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm timeofday_diff = (unsigned long)diff; 9174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break; 9184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 9194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else 9204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (tv1.tv_sec != tv2.tv_sec || tv1.tv_usec != tv2.tv_usec) { 9214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (tv1.tv_sec == tv2.tv_sec) 9224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm timeofday_diff = tv2.tv_usec - tv1.tv_usec; 9234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else 9244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm timeofday_diff = (1000000 - tv1.tv_usec) + tv2.tv_usec; 9254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break; 9264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 9274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 9284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 9294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#if defined(MS_WINDOWS) || defined(PYOS_OS2) || \ 9304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm defined(__VMS) || defined (__QNX__) 9314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm rusage_diff = -1; 9324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else 9334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm { 9344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm struct rusage ru1, ru2; 9354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm getrusage(RUSAGE_SELF, &ru1); 9374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm while (1) { 9384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm getrusage(RUSAGE_SELF, &ru2); 9394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (ru1.ru_utime.tv_sec != ru2.ru_utime.tv_sec) { 9404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm rusage_diff = ((1000000 - ru1.ru_utime.tv_usec) 9414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm + ru2.ru_utime.tv_usec); 9424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break; 9434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 9444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else if (ru1.ru_utime.tv_usec != ru2.ru_utime.tv_usec) { 9454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm rusage_diff = ru2.ru_utime.tv_usec - ru1.ru_utime.tv_usec; 9464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break; 9474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 9484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else if (ru1.ru_stime.tv_sec != ru2.ru_stime.tv_sec) { 9494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm rusage_diff = ((1000000 - ru1.ru_stime.tv_usec) 9504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm + ru2.ru_stime.tv_usec); 9514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break; 9524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 9534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else if (ru1.ru_stime.tv_usec != ru2.ru_stime.tv_usec) { 9544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm rusage_diff = ru2.ru_stime.tv_usec - ru1.ru_stime.tv_usec; 9554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break; 9564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 9574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 9584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 9594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 9604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 9614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void 9634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdo_start(ProfilerObject *self) 9644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 9654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->active = 1; 9664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm GETTIMEOFDAY(&self->prev_timeofday); 9674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->lineevents) 9684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyEval_SetTrace((Py_tracefunc) tracer_callback, (PyObject *)self); 9694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else 9704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyEval_SetProfile((Py_tracefunc) tracer_callback, (PyObject *)self); 9714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 9724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void 9744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdo_stop(ProfilerObject *self) 9754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 9764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->active) { 9774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->active = 0; 9784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->lineevents) 9794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyEval_SetTrace(NULL, NULL); 9804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else 9814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyEval_SetProfile(NULL, NULL); 9824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 9834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->index > 0) { 9844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* Best effort to dump out any remaining data. */ 9854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm flush_data(self); 9864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 9874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 9884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int 9904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmis_available(ProfilerObject *self) 9914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 9924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->active) { 9934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_SetString(ProfilerError, "profiler already active"); 9944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 9954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 9964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->logfp == NULL) { 9974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_SetString(ProfilerError, "profiler already closed"); 9984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 9994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 10004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 1; 10014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 10024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* Profiler object interface methods. */ 10054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(addinfo__doc__, 10074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"addinfo(key, value)\n" 10084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"Insert an ADD_INFO record into the log."); 10094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject * 10114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_addinfo(ProfilerObject *self, PyObject *args) 10124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 10134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *result = NULL; 10144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm char *key, *value; 10154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (PyArg_ParseTuple(args, "ss:addinfo", &key, &value)) { 10174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->logfp == NULL) 10184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_SetString(ProfilerError, "profiler already closed"); 10194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else { 10204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (pack_add_info(self, key, value) == 0) { 10214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm result = Py_None; 10224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(result); 10234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 10244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 10254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 10264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return result; 10274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 10284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(close__doc__, 10304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"close()\n" 10314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"Shut down this profiler and close the log files, even if its active."); 10324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject * 10344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_close(ProfilerObject *self) 10354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 10364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm do_stop(self); 10374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->logfp != NULL) { 10384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fclose(self->logfp); 10394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->logfp = NULL; 10404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 10414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(Py_None); 10424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return Py_None; 10434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 10444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define fileno__doc__ logreader_fileno__doc__ 10464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject * 10484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_fileno(ProfilerObject *self) 10494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 10504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->logfp == NULL) { 10514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_SetString(PyExc_ValueError, 10524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "profiler's file object already closed"); 10534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 10544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 10554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return PyInt_FromLong(fileno(self->logfp)); 10564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 10574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(runcall__doc__, 10594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"runcall(callable[, args[, kw]]) -> callable()\n" 10604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"Profile a specific function call, returning the result of that call."); 10614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject * 10634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_runcall(ProfilerObject *self, PyObject *args) 10644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 10654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *result = NULL; 10664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *callargs = NULL; 10674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *callkw = NULL; 10684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *callable; 10694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (PyArg_UnpackTuple(args, "runcall", 1, 3, 10714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm &callable, &callargs, &callkw)) { 10724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (is_available(self)) { 10734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm do_start(self); 10744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm result = PyEval_CallObjectWithKeywords(callable, callargs, callkw); 10754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm do_stop(self); 10764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 10774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 10784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return result; 10794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 10804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(runcode__doc__, 10824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"runcode(code, globals[, locals])\n" 10834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"Execute a code object while collecting profile data. If locals is\n" 10844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"omitted, globals is used for the locals as well."); 10854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject * 10874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_runcode(ProfilerObject *self, PyObject *args) 10884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 10894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *result = NULL; 10904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyCodeObject *code; 10914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *globals; 10924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *locals = NULL; 10934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (PyArg_ParseTuple(args, "O!O!|O:runcode", 10954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm &PyCode_Type, &code, 10964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm &PyDict_Type, &globals, 10974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm &locals)) { 10984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (is_available(self)) { 10994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (locals == NULL || locals == Py_None) 11004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm locals = globals; 11014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else if (!PyDict_Check(locals)) { 11024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_SetString(PyExc_TypeError, 11034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "locals must be a dictionary or None"); 11044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 11054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 11064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm do_start(self); 11074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm result = PyEval_EvalCode(code, globals, locals); 11084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm do_stop(self); 11094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#if 0 11104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!PyErr_Occurred()) { 11114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm result = Py_None; 11124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(result); 11134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 11144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 11154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 11164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 11174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return result; 11184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 11194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(start__doc__, 11214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"start()\n" 11224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"Install this profiler for the current thread."); 11234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject * 11254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_start(ProfilerObject *self, PyObject *args) 11264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 11274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *result = NULL; 11284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (is_available(self)) { 11304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm do_start(self); 11314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm result = Py_None; 11324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(result); 11334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 11344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return result; 11354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 11364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(stop__doc__, 11384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"stop()\n" 11394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"Remove this profiler from the current thread."); 11404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject * 11424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_stop(ProfilerObject *self, PyObject *args) 11434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 11444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *result = NULL; 11454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!self->active) 11474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_SetString(ProfilerError, "profiler not active"); 11484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else { 11494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm do_stop(self); 11504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm result = Py_None; 11514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(result); 11524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 11534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return result; 11544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 11554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* Python API support. */ 11584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void 11604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_dealloc(ProfilerObject *self) 11614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 11624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm do_stop(self); 11634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->logfp != NULL) 11644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fclose(self->logfp); 11654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_XDECREF(self->filemap); 11664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_XDECREF(self->logfilename); 11674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject_Del((PyObject *)self); 11684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 11694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyMethodDef profiler_methods[] = { 11714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"addinfo", (PyCFunction)profiler_addinfo, METH_VARARGS, addinfo__doc__}, 11724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"close", (PyCFunction)profiler_close, METH_NOARGS, close__doc__}, 11734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"fileno", (PyCFunction)profiler_fileno, METH_NOARGS, fileno__doc__}, 11744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"runcall", (PyCFunction)profiler_runcall, METH_VARARGS, runcall__doc__}, 11754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"runcode", (PyCFunction)profiler_runcode, METH_VARARGS, runcode__doc__}, 11764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"start", (PyCFunction)profiler_start, METH_NOARGS, start__doc__}, 11774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"stop", (PyCFunction)profiler_stop, METH_NOARGS, stop__doc__}, 11784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {NULL, NULL} 11794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}; 11804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyMemberDef profiler_members[] = { 11824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"frametimings", T_LONG, offsetof(ProfilerObject, linetimings), READONLY}, 11834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"lineevents", T_LONG, offsetof(ProfilerObject, lineevents), READONLY}, 11844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"linetimings", T_LONG, offsetof(ProfilerObject, linetimings), READONLY}, 11854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {NULL} 11864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}; 11874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject * 11894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_get_closed(ProfilerObject *self, void *closure) 11904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 11914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *result = (self->logfp == NULL) ? Py_True : Py_False; 11924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(result); 11934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return result; 11944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 11954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyGetSetDef profiler_getsets[] = { 11974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"closed", (getter)profiler_get_closed, NULL, 11984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyDoc_STR("True if the profiler's output file has already been closed.")}, 11994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {NULL} 12004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}; 12014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(profiler_object__doc__, 12044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"High-performance profiler object.\n" 12054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"\n" 12064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"Methods:\n" 12074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"\n" 12084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"close(): Stop the profiler and close the log files.\n" 12094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"fileno(): Returns the file descriptor of the log file.\n" 12104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"runcall(): Run a single function call with profiling enabled.\n" 12114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"runcode(): Execute a code object with profiling enabled.\n" 12124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"start(): Install the profiler and return.\n" 12134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"stop(): Remove the profiler.\n" 12144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"\n" 12154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"Attributes (read-only):\n" 12164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"\n" 12174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"closed: True if the profiler has already been closed.\n" 12184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"frametimings: True if ENTER/EXIT events collect timing information.\n" 12194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"lineevents: True if line events are reported to the profiler.\n" 12204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"linetimings: True if line events collect timing information."); 12214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyTypeObject ProfilerType = { 12234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyVarObject_HEAD_INIT(NULL, 0) 12244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "_hotshot.ProfilerType", /* tp_name */ 12254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (int) sizeof(ProfilerObject), /* tp_basicsize */ 12264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_itemsize */ 12274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (destructor)profiler_dealloc, /* tp_dealloc */ 12284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_print */ 12294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_getattr */ 12304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_setattr */ 12314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_compare */ 12324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_repr */ 12334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_as_number */ 12344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_as_sequence */ 12354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_as_mapping */ 12364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_hash */ 12374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_call */ 12384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_str */ 12394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject_GenericGetAttr, /* tp_getattro */ 12404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_setattro */ 12414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_as_buffer */ 12424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_TPFLAGS_DEFAULT, /* tp_flags */ 12434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm profiler_object__doc__, /* tp_doc */ 12444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_traverse */ 12454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_clear */ 12464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_richcompare */ 12474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_weaklistoffset */ 12484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_iter */ 12494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_iternext */ 12504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm profiler_methods, /* tp_methods */ 12514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm profiler_members, /* tp_members */ 12524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm profiler_getsets, /* tp_getset */ 12534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_base */ 12544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_dict */ 12554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_descr_get */ 12564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_descr_set */ 12574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}; 12584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyMethodDef logreader_methods[] = { 12614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"close", (PyCFunction)logreader_close, METH_NOARGS, 12624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm logreader_close__doc__}, 12634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"fileno", (PyCFunction)logreader_fileno, METH_NOARGS, 12644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm logreader_fileno__doc__}, 12654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {NULL, NULL} 12664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}; 12674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyMemberDef logreader_members[] = { 12694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"info", T_OBJECT, offsetof(LogReaderObject, info), RO, 12704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyDoc_STR("Dictionary mapping informational keys to lists of values.")}, 12714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {NULL} 12724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}; 12734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(logreader__doc__, 12764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"logreader(filename) --> log-iterator\n\ 12774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmCreate a log-reader for the timing information file."); 12784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PySequenceMethods logreader_as_sequence = { 12804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* sq_length */ 12814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* sq_concat */ 12824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* sq_repeat */ 12834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (ssizeargfunc)logreader_sq_item, /* sq_item */ 12844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* sq_slice */ 12854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* sq_ass_item */ 12864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* sq_ass_slice */ 12874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* sq_contains */ 12884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* sq_inplace_concat */ 12894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* sq_inplace_repeat */ 12904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}; 12914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject * 12934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmlogreader_get_closed(LogReaderObject *self, void *closure) 12944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 12954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *result = (self->logfp == NULL) ? Py_True : Py_False; 12964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(result); 12974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return result; 12984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 12994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 13004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyGetSetDef logreader_getsets[] = { 13014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"closed", (getter)logreader_get_closed, NULL, 13024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyDoc_STR("True if the logreader's input file has already been closed.")}, 13034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {NULL} 13044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}; 13054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 13064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyTypeObject LogReaderType = { 13074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyVarObject_HEAD_INIT(NULL, 0) 13084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "_hotshot.LogReaderType", /* tp_name */ 13094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (int) sizeof(LogReaderObject), /* tp_basicsize */ 13104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_itemsize */ 13114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (destructor)logreader_dealloc, /* tp_dealloc */ 13124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_print */ 13134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_getattr */ 13144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_setattr */ 13154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_compare */ 13164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_repr */ 13174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_as_number */ 13184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm &logreader_as_sequence, /* tp_as_sequence */ 13194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_as_mapping */ 13204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_hash */ 13214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_call */ 13224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_str */ 13234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject_GenericGetAttr, /* tp_getattro */ 13244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_setattro */ 13254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_as_buffer */ 13264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_TPFLAGS_DEFAULT, /* tp_flags */ 13274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm logreader__doc__, /* tp_doc */ 13284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_traverse */ 13294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_clear */ 13304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_richcompare */ 13314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_weaklistoffset */ 13324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject_SelfIter, /* tp_iter */ 13334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (iternextfunc)logreader_tp_iternext,/* tp_iternext */ 13344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm logreader_methods, /* tp_methods */ 13354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm logreader_members, /* tp_members */ 13364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm logreader_getsets, /* tp_getset */ 13374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_base */ 13384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_dict */ 13394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_descr_get */ 13404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_descr_set */ 13414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}; 13424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 13434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject * 13444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmhotshot_logreader(PyObject *unused, PyObject *args) 13454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 13464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm LogReaderObject *self = NULL; 13474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm char *filename; 13484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int c; 13494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int err = 0; 13504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 13514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (PyArg_ParseTuple(args, "s:logreader", &filename)) { 13524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self = PyObject_New(LogReaderObject, &LogReaderType); 13534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self != NULL) { 13544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->frametimings = 1; 13554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->linetimings = 0; 13564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->info = NULL; 13574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->logfp = fopen(filename, "rb"); 13584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->logfp == NULL) { 13594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_SetFromErrnoWithFilename(PyExc_IOError, filename); 13604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm goto error; 13614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 13624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->info = PyDict_New(); 13634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->info == NULL) 13644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm goto error; 13654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* read initial info */ 13664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for (;;) { 13674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if ((c = fgetc(self->logfp)) == EOF) { 13684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eof_error(self); 13694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm goto error; 13704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 13714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (c != WHAT_ADD_INFO) { 13724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ungetc(c, self->logfp); 13734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break; 13744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 13754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = unpack_add_info(self); 13764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (err) { 13774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (err == ERR_EOF) 13784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eof_error(self); 13794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else 13804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_SetString(PyExc_RuntimeError, 13814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "unexpected error"); 13824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm goto error; 13834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 13844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 13854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 13864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 13874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return (PyObject *) self; 13884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm error: 13894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(self); 13904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 13914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 13924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 13934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 13944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* Return a Python string that represents the version number without the 13954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * extra cruft added by revision control, even if the right options were 13964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * given to the "cvs export" command to make it not include the extra 13974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * cruft. 13984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */ 13994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic char * 14004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmget_version_string(void) 14014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 14024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm static char *rcsid = "$Revision$"; 14034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm char *rev = rcsid; 14044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm char *buffer; 14054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int i = 0; 14064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm while (*rev && !isdigit(Py_CHARMASK(*rev))) 14084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ++rev; 14094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm while (rev[i] != ' ' && rev[i] != '\0') 14104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ++i; 14114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm buffer = (char *)malloc(i + 1); 14124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (buffer != NULL) { 14134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm memmove(buffer, rev, i); 14144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm buffer[i] = '\0'; 14154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 14164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return buffer; 14174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 14184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* Write out a RFC 822-style header with various useful bits of 14204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * information to make the output easier to manage. 14214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */ 14224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int 14234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmwrite_header(ProfilerObject *self) 14244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 14254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm char *buffer; 14264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm char cwdbuffer[PATH_MAX]; 14274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *temp; 14284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_ssize_t i, len; 14294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm buffer = get_version_string(); 14314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (buffer == NULL) { 14324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_NoMemory(); 14334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 14344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 14354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pack_add_info(self, "hotshot-version", buffer); 14364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pack_add_info(self, "requested-frame-timings", 14374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (self->frametimings ? "yes" : "no")); 14384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pack_add_info(self, "requested-line-events", 14394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (self->lineevents ? "yes" : "no")); 14404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pack_add_info(self, "requested-line-timings", 14414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (self->linetimings ? "yes" : "no")); 14424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pack_add_info(self, "platform", Py_GetPlatform()); 14434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pack_add_info(self, "executable", Py_GetProgramFullPath()); 14444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm free(buffer); 14454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm buffer = (char *) Py_GetVersion(); 14464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (buffer == NULL) 14474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_Clear(); 14484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else 14494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pack_add_info(self, "executable-version", buffer); 14504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef MS_WINDOWS 14524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyOS_snprintf(cwdbuffer, sizeof(cwdbuffer), "%I64d", frequency.QuadPart); 14534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pack_add_info(self, "reported-performance-frequency", cwdbuffer); 14544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else 14554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyOS_snprintf(cwdbuffer, sizeof(cwdbuffer), "%lu", rusage_diff); 14564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pack_add_info(self, "observed-interval-getrusage", cwdbuffer); 14574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyOS_snprintf(cwdbuffer, sizeof(cwdbuffer), "%lu", timeofday_diff); 14584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pack_add_info(self, "observed-interval-gettimeofday", cwdbuffer); 14594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 14604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pack_add_info(self, "current-directory", 14624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm getcwd(cwdbuffer, sizeof cwdbuffer)); 14634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm temp = PySys_GetObject("path"); 14654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (temp == NULL || !PyList_Check(temp)) { 14664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_SetString(PyExc_RuntimeError, "sys.path must be a list"); 14674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 14684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 14694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm len = PyList_GET_SIZE(temp); 14704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for (i = 0; i < len; ++i) { 14714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *item = PyList_GET_ITEM(temp, i); 14724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm buffer = PyString_AsString(item); 14734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (buffer == NULL) { 14744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pack_add_info(self, "sys-path-entry", "<non-string-path-entry>"); 14754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_Clear(); 14764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 14774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else { 14784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pack_add_info(self, "sys-path-entry", buffer); 14794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 14804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 14814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pack_frame_times(self); 14824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pack_line_times(self); 14834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 14854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 14864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(profiler__doc__, 14884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"profiler(logfilename[, lineevents[, linetimes]]) -> profiler\n\ 14894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmCreate a new profiler object."); 14904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject * 14924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmhotshot_profiler(PyObject *unused, PyObject *args) 14934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 14944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm char *logfilename; 14954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerObject *self = NULL; 14964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int lineevents = 0; 14974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int linetimings = 1; 14984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (PyArg_ParseTuple(args, "s|ii:profiler", &logfilename, 15004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm &lineevents, &linetimings)) { 15014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self = PyObject_New(ProfilerObject, &ProfilerType); 15024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self == NULL) 15034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 15044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->frametimings = 1; 15054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->lineevents = lineevents ? 1 : 0; 15064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->linetimings = (lineevents && linetimings) ? 1 : 0; 15074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->index = 0; 15084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->active = 0; 15094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->next_fileno = 0; 15104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->logfp = NULL; 15114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->logfilename = PyTuple_GET_ITEM(args, 0); 15124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(self->logfilename); 15134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->filemap = PyDict_New(); 15144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->filemap == NULL) { 15154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(self); 15164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 15174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 15184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->logfp = fopen(logfilename, "wb"); 15194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->logfp == NULL) { 15204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(self); 15214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_SetFromErrnoWithFilename(PyExc_IOError, logfilename); 15224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 15234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 15244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (timeofday_diff == 0) { 15254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* Run this several times since sometimes the first 15264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * doesn't give the lowest values, and we're really trying 15274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * to determine the lowest. 15284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */ 15294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm calibrate(); 15304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm calibrate(); 15314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm calibrate(); 15324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 15334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (write_header(self)) { 15344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* some error occurred, exception has been set */ 15354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(self); 15364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self = NULL; 15374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 15384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 15394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return (PyObject *) self; 15404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 15414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(coverage__doc__, 15434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"coverage(logfilename) -> profiler\n\ 15444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmReturns a profiler that doesn't collect any timing information, which is\n\ 15454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmuseful in building a coverage analysis tool."); 15464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject * 15484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmhotshot_coverage(PyObject *unused, PyObject *args) 15494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 15504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm char *logfilename; 15514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *result = NULL; 15524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (PyArg_ParseTuple(args, "s:coverage", &logfilename)) { 15544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm result = hotshot_profiler(unused, args); 15554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (result != NULL) { 15564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerObject *self = (ProfilerObject *) result; 15574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->frametimings = 0; 15584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->linetimings = 0; 15594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->lineevents = 1; 15604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 15614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 15624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return result; 15634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 15644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_VAR(resolution__doc__) = 15664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef MS_WINDOWS 15674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STR( 15684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"resolution() -> (performance-counter-ticks, update-frequency)\n" 15694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"Return the resolution of the timer provided by the QueryPerformanceCounter()\n" 15704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"function. The first value is the smallest observed change, and the second\n" 15714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"is the result of QueryPerformanceFrequency()." 15724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm) 15734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else 15744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STR( 15754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"resolution() -> (gettimeofday-usecs, getrusage-usecs)\n" 15764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"Return the resolution of the timers provided by the gettimeofday() and\n" 15774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"getrusage() system calls, or -1 if the call is not supported." 15784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm) 15794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 15804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm; 15814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject * 15834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmhotshot_resolution(PyObject *self, PyObject *unused) 15844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 15854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (timeofday_diff == 0) { 15864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm calibrate(); 15874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm calibrate(); 15884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm calibrate(); 15894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 15904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef MS_WINDOWS 15914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return Py_BuildValue("ii", timeofday_diff, frequency.LowPart); 15924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else 15934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return Py_BuildValue("ii", timeofday_diff, rusage_diff); 15944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 15954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 15964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyMethodDef functions[] = { 15994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"coverage", hotshot_coverage, METH_VARARGS, coverage__doc__}, 16004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"profiler", hotshot_profiler, METH_VARARGS, profiler__doc__}, 16014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"logreader", hotshot_logreader, METH_VARARGS, logreader__doc__}, 16024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"resolution", hotshot_resolution, METH_NOARGS, resolution__doc__}, 16034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {NULL, NULL} 16044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}; 16054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 16064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 16074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmvoid 16084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylminit_hotshot(void) 16094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 16104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *module; 16114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 16124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_TYPE(&LogReaderType) = &PyType_Type; 16134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_TYPE(&ProfilerType) = &PyType_Type; 16144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm module = Py_InitModule("_hotshot", functions); 16154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (module != NULL) { 16164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm char *s = get_version_string(); 16174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 16184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyModule_AddStringConstant(module, "__version__", s); 16194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm free(s); 16204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(&LogReaderType); 16214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyModule_AddObject(module, "LogReaderType", 16224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (PyObject *)&LogReaderType); 16234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(&ProfilerType); 16244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyModule_AddObject(module, "ProfilerType", 16254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (PyObject *)&ProfilerType); 16264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 16274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (ProfilerError == NULL) 16284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerError = PyErr_NewException("hotshot.ProfilerError", 16294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm NULL, NULL); 16304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (ProfilerError != NULL) { 16314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(ProfilerError); 16324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyModule_AddObject(module, "ProfilerError", ProfilerError); 16334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 16344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyModule_AddIntConstant(module, "WHAT_ENTER", WHAT_ENTER); 16354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyModule_AddIntConstant(module, "WHAT_EXIT", WHAT_EXIT); 16364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyModule_AddIntConstant(module, "WHAT_LINENO", WHAT_LINENO); 16374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyModule_AddIntConstant(module, "WHAT_OTHER", WHAT_OTHER); 16384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyModule_AddIntConstant(module, "WHAT_ADD_INFO", WHAT_ADD_INFO); 16394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyModule_AddIntConstant(module, "WHAT_DEFINE_FILE", WHAT_DEFINE_FILE); 16404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyModule_AddIntConstant(module, "WHAT_DEFINE_FUNC", WHAT_DEFINE_FUNC); 16414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyModule_AddIntConstant(module, "WHAT_LINE_TIMES", WHAT_LINE_TIMES); 16424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 16434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 1644