cpython/Python/tracemalloc.c

#include "Python.h"
#include "pycore_fileutils.h"     // _Py_write_noraise()
#include "pycore_gc.h"            // PyGC_Head
#include "pycore_hashtable.h"     // _Py_hashtable_t
#include "pycore_object.h"        // _PyType_PreHeaderSize()
#include "pycore_pymem.h"         // _Py_tracemalloc_config
#include "pycore_runtime.h"       // _Py_ID()
#include "pycore_traceback.h"     // _Py_DumpASCII()
#include <pycore_frame.h>

#include "frameobject.h"          // _PyInterpreterFrame_GetLine

#include <stdlib.h>               // malloc()

#define tracemalloc_config

_Py_DECLARE_STR(anon_unknown, "<unknown>");

/* Forward declaration */
static void* raw_malloc(size_t size);
static void raw_free(void *ptr);

#ifdef Py_DEBUG
#define TRACE_DEBUG
#endif

#define TO_PTR(key)
#define FROM_PTR(key)

#define allocators


#if defined(TRACE_RAW_MALLOC)
/* This lock is needed because tracemalloc_free() is called without
   the GIL held from PyMem_RawFree(). It cannot acquire the lock because it
   would introduce a deadlock in _PyThreadState_DeleteCurrent(). */
#define tables_lock
#define TABLES_LOCK()
#define TABLES_UNLOCK()
#else
   /* variables are protected by the GIL */
#define TABLES_LOCK
#define TABLES_UNLOCK
#endif


#define DEFAULT_DOMAIN

frame_t;
traceback_t;

#define TRACEBACK_SIZE(NFRAME)

/* The maximum number of frames is either:
 - The maximum number of frames we can store in `traceback_t.nframe`
 - The maximum memory size_t we can allocate */
static const unsigned long MAX_NFRAME =;


#define tracemalloc_empty_traceback


/* Trace of a memory block */
trace_t;


#define tracemalloc_traced_memory
#define tracemalloc_peak_traced_memory
#define tracemalloc_filenames
#define tracemalloc_traceback
#define tracemalloc_tracebacks
#define tracemalloc_traces
#define tracemalloc_domains


#ifdef TRACE_DEBUG
static void
tracemalloc_error(const char *format, ...)
{
    va_list ap;
    fprintf(stderr, "tracemalloc: ");
    va_start(ap, format);
    vfprintf(stderr, format, ap);
    va_end(ap);
    fprintf(stderr, "\n");
    fflush(stderr);
}
#endif


#if defined(TRACE_RAW_MALLOC)
#define REENTRANT_THREADLOCAL

#define tracemalloc_reentrant_key

/* Any non-NULL pointer can be used */
#define REENTRANT

static int
get_reentrant(void)
{}

static void
set_reentrant(int reentrant)
{}

#else

/* TRACE_RAW_MALLOC not defined: variable protected by the GIL */
static int tracemalloc_reentrant = 0;

static int
get_reentrant(void)
{
    return tracemalloc_reentrant;
}

static void
set_reentrant(int reentrant)
{
    assert(reentrant != tracemalloc_reentrant);
    tracemalloc_reentrant = reentrant;
}
#endif


static Py_uhash_t
hashtable_hash_pyobject(const void *key)
{}


static int
hashtable_compare_unicode(const void *key1, const void *key2)
{}


static Py_uhash_t
hashtable_hash_uint(const void *key_raw)
{}


static _Py_hashtable_t *
hashtable_new(_Py_hashtable_hash_func hash_func,
              _Py_hashtable_compare_func compare_func,
              _Py_hashtable_destroy_func key_destroy_func,
              _Py_hashtable_destroy_func value_destroy_func)
{}


static void*
raw_malloc(size_t size)
{}

static void
raw_free(void *ptr)
{}


static Py_uhash_t
hashtable_hash_traceback(const void *key)
{}


static int
hashtable_compare_traceback(const void *key1, const void *key2)
{}


static void
tracemalloc_get_frame(_PyInterpreterFrame *pyframe, frame_t *frame)
{}


static Py_uhash_t
traceback_hash(traceback_t *traceback)
{}


static void
traceback_get_frames(traceback_t *traceback)
{}


static traceback_t *
traceback_new(void)
{}


static _Py_hashtable_t*
tracemalloc_create_traces_table(void)
{}


static _Py_hashtable_t*
tracemalloc_create_domains_table(void)
{}


static _Py_hashtable_t*
tracemalloc_get_traces_table(unsigned int domain)
{}


static void
tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr)
{}

#define REMOVE_TRACE(ptr)


static int
tracemalloc_add_trace(unsigned int domain, uintptr_t ptr,
                      size_t size)
{}

#define ADD_TRACE(ptr, size)


static void*
tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
{}


static void*
tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
{}


static void
tracemalloc_free(void *ctx, void *ptr)
{}


static void*
tracemalloc_alloc_gil(int use_calloc, void *ctx, size_t nelem, size_t elsize)
{}


static void*
tracemalloc_malloc_gil(void *ctx, size_t size)
{}


static void*
tracemalloc_calloc_gil(void *ctx, size_t nelem, size_t elsize)
{}


static void*
tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
{}


#ifdef TRACE_RAW_MALLOC
static void*
tracemalloc_raw_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
{}


static void*
tracemalloc_raw_malloc(void *ctx, size_t size)
{}


static void*
tracemalloc_raw_calloc(void *ctx, size_t nelem, size_t elsize)
{}


static void*
tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
{}
#endif   /* TRACE_RAW_MALLOC */


static void
tracemalloc_clear_filename(void *value)
{}


/* reentrant flag must be set to call this function and GIL must be held */
static void
tracemalloc_clear_traces(void)
{}


int
_PyTraceMalloc_Init(void)
{}


static void
tracemalloc_deinit(void)
{}


int
_PyTraceMalloc_Start(int max_nframe)
{}


void
_PyTraceMalloc_Stop(void)
{}



static PyObject*
frame_to_pyobject(frame_t *frame)
{}


static PyObject*
traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table)
{}


static PyObject*
trace_to_pyobject(unsigned int domain, const trace_t *trace,
                  _Py_hashtable_t *intern_tracebacks)
{}


get_traces_t;


static int
tracemalloc_copy_trace(_Py_hashtable_t *traces,
                       const void *key, const void *value,
                       void *user_data)
{}


static _Py_hashtable_t*
tracemalloc_copy_traces(_Py_hashtable_t *traces)
{}


static int
tracemalloc_copy_domain(_Py_hashtable_t *domains,
                        const void *key, const void *value,
                        void *user_data)
{}


static _Py_hashtable_t*
tracemalloc_copy_domains(_Py_hashtable_t *domains)
{}


static int
tracemalloc_get_traces_fill(_Py_hashtable_t *traces,
                            const void *key, const void *value,
                            void *user_data)
{}


static int
tracemalloc_get_traces_domain(_Py_hashtable_t *domains,
                              const void *key, const void *value,
                              void *user_data)
{}


static void
tracemalloc_pyobject_decref(void *value)
{}


static traceback_t*
tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr)
{}


#define PUTS

static void
_PyMem_DumpFrame(int fd, frame_t * frame)
{}

/* Dump the traceback where a memory block was allocated into file descriptor
   fd. The function may block on TABLES_LOCK() but it is unlikely. */
void
_PyMem_DumpTraceback(int fd, const void *ptr)
{}

#undef PUTS


static int
tracemalloc_get_tracemalloc_memory_cb(_Py_hashtable_t *domains,
                                      const void *key, const void *value,
                                      void *user_data)
{}

int
PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
                    size_t size)
{}


int
PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
{}


void
_PyTraceMalloc_Fini(void)
{}


/* If the object memory block is already traced, update its trace
   with the current Python traceback.

   Do nothing if tracemalloc is not tracing memory allocations
   or if the object memory block is not already traced. */
int
_PyTraceMalloc_TraceRef(PyObject *op, PyRefTracerEvent event, void* Py_UNUSED(ignore))
{}


PyObject*
_PyTraceMalloc_GetTraceback(unsigned int domain, uintptr_t ptr)
{}

int
_PyTraceMalloc_IsTracing(void)
{}

void
_PyTraceMalloc_ClearTraces(void)
{}

PyObject *
_PyTraceMalloc_GetTraces(void)
{}

PyObject *
_PyTraceMalloc_GetObjectTraceback(PyObject *obj)
/*[clinic end generated code: output=41ee0553a658b0aa input=29495f1b21c53212]*/
{}

int _PyTraceMalloc_GetTracebackLimit(void) {}

size_t
_PyTraceMalloc_GetMemory(void) {}


PyObject *
_PyTraceMalloc_GetTracedMemory(void)
{}

void
_PyTraceMalloc_ResetPeak(void)
{}