Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-11-19 09:50:49

0001 #ifndef Py_INTERNAL_PYMEM_H
0002 #define Py_INTERNAL_PYMEM_H
0003 
0004 #include "pycore_llist.h"           // struct llist_node
0005 #include "pycore_lock.h"            // PyMutex
0006 
0007 #ifdef __cplusplus
0008 extern "C" {
0009 #endif
0010 
0011 #ifndef Py_BUILD_CORE
0012 #  error "this header requires Py_BUILD_CORE define"
0013 #endif
0014 
0015 // Try to get the allocators name set by _PyMem_SetupAllocators().
0016 // Return NULL if unknown.
0017 // Export for '_testinternalcapi' shared extension.
0018 PyAPI_FUNC(const char*) _PyMem_GetCurrentAllocatorName(void);
0019 
0020 // strdup() using PyMem_RawMalloc()
0021 extern char* _PyMem_RawStrdup(const char *str);
0022 
0023 // strdup() using PyMem_Malloc().
0024 // Export for '_pickle ' shared extension.
0025 PyAPI_FUNC(char*) _PyMem_Strdup(const char *str);
0026 
0027 // wcsdup() using PyMem_RawMalloc()
0028 extern wchar_t* _PyMem_RawWcsdup(const wchar_t *str);
0029 
0030 typedef struct {
0031     /* We tag each block with an API ID in order to tag API violations */
0032     char api_id;
0033     PyMemAllocatorEx alloc;
0034 } debug_alloc_api_t;
0035 
0036 struct _pymem_allocators {
0037     PyMutex mutex;
0038     struct {
0039         PyMemAllocatorEx raw;
0040         PyMemAllocatorEx mem;
0041         PyMemAllocatorEx obj;
0042     } standard;
0043     struct {
0044         debug_alloc_api_t raw;
0045         debug_alloc_api_t mem;
0046         debug_alloc_api_t obj;
0047     } debug;
0048     int is_debug_enabled;
0049     PyObjectArenaAllocator obj_arena;
0050 };
0051 
0052 struct _Py_mem_interp_free_queue {
0053     int has_work;   // true if the queue is not empty
0054     PyMutex mutex;  // protects the queue
0055     struct llist_node head;  // queue of _mem_work_chunk items
0056 };
0057 
0058 /* Set the memory allocator of the specified domain to the default.
0059    Save the old allocator into *old_alloc if it's non-NULL.
0060    Return on success, or return -1 if the domain is unknown. */
0061 extern int _PyMem_SetDefaultAllocator(
0062     PyMemAllocatorDomain domain,
0063     PyMemAllocatorEx *old_alloc);
0064 
0065 /* Special bytes broadcast into debug memory blocks at appropriate times.
0066    Strings of these are unlikely to be valid addresses, floats, ints or
0067    7-bit ASCII.
0068 
0069    - PYMEM_CLEANBYTE: clean (newly allocated) memory
0070    - PYMEM_DEADBYTE dead (newly freed) memory
0071    - PYMEM_FORBIDDENBYTE: untouchable bytes at each end of a block
0072 
0073    Byte patterns 0xCB, 0xDB and 0xFB have been replaced with 0xCD, 0xDD and
0074    0xFD to use the same values as Windows CRT debug malloc() and free().
0075    If modified, _PyMem_IsPtrFreed() should be updated as well. */
0076 #define PYMEM_CLEANBYTE      0xCD
0077 #define PYMEM_DEADBYTE       0xDD
0078 #define PYMEM_FORBIDDENBYTE  0xFD
0079 
0080 /* Heuristic checking if a pointer value is newly allocated
0081    (uninitialized), newly freed or NULL (is equal to zero).
0082 
0083    The pointer is not dereferenced, only the pointer value is checked.
0084 
0085    The heuristic relies on the debug hooks on Python memory allocators which
0086    fills newly allocated memory with CLEANBYTE (0xCD) and newly freed memory
0087    with DEADBYTE (0xDD). Detect also "untouchable bytes" marked
0088    with FORBIDDENBYTE (0xFD). */
0089 static inline int _PyMem_IsPtrFreed(const void *ptr)
0090 {
0091     uintptr_t value = (uintptr_t)ptr;
0092 #if SIZEOF_VOID_P == 8
0093     return (value == 0
0094             || value == (uintptr_t)0xCDCDCDCDCDCDCDCD
0095             || value == (uintptr_t)0xDDDDDDDDDDDDDDDD
0096             || value == (uintptr_t)0xFDFDFDFDFDFDFDFD);
0097 #elif SIZEOF_VOID_P == 4
0098     return (value == 0
0099             || value == (uintptr_t)0xCDCDCDCD
0100             || value == (uintptr_t)0xDDDDDDDD
0101             || value == (uintptr_t)0xFDFDFDFD);
0102 #else
0103 #  error "unknown pointer size"
0104 #endif
0105 }
0106 
0107 extern int _PyMem_GetAllocatorName(
0108     const char *name,
0109     PyMemAllocatorName *allocator);
0110 
0111 /* Configure the Python memory allocators.
0112    Pass PYMEM_ALLOCATOR_DEFAULT to use default allocators.
0113    PYMEM_ALLOCATOR_NOT_SET does nothing. */
0114 extern int _PyMem_SetupAllocators(PyMemAllocatorName allocator);
0115 
0116 /* Is the debug allocator enabled? */
0117 extern int _PyMem_DebugEnabled(void);
0118 
0119 // Enqueue a pointer to be freed possibly after some delay.
0120 extern void _PyMem_FreeDelayed(void *ptr);
0121 
0122 // Enqueue an object to be freed possibly after some delay
0123 extern void _PyObject_FreeDelayed(void *ptr);
0124 
0125 // Periodically process delayed free requests.
0126 extern void _PyMem_ProcessDelayed(PyThreadState *tstate);
0127 
0128 // Abandon all thread-local delayed free requests and push them to the
0129 // interpreter's queue.
0130 extern void _PyMem_AbandonDelayed(PyThreadState *tstate);
0131 
0132 // On interpreter shutdown, frees all delayed free requests.
0133 extern void _PyMem_FiniDelayed(PyInterpreterState *interp);
0134 
0135 #ifdef __cplusplus
0136 }
0137 #endif
0138 #endif  // !Py_INTERNAL_PYMEM_H