• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef Py_INTERNAL_PYMEM_H
2 #define Py_INTERNAL_PYMEM_H
3 
4 #include "pycore_llist.h"           // struct llist_node
5 #include "pycore_lock.h"            // PyMutex
6 
7 #ifdef __cplusplus
8 extern "C" {
9 #endif
10 
11 #ifndef Py_BUILD_CORE
12 #  error "this header requires Py_BUILD_CORE define"
13 #endif
14 
15 // Try to get the allocators name set by _PyMem_SetupAllocators().
16 // Return NULL if unknown.
17 // Export for '_testinternalcapi' shared extension.
18 PyAPI_FUNC(const char*) _PyMem_GetCurrentAllocatorName(void);
19 
20 // strdup() using PyMem_RawMalloc()
21 extern char* _PyMem_RawStrdup(const char *str);
22 
23 // strdup() using PyMem_Malloc().
24 // Export for '_pickle ' shared extension.
25 PyAPI_FUNC(char*) _PyMem_Strdup(const char *str);
26 
27 // wcsdup() using PyMem_RawMalloc()
28 extern wchar_t* _PyMem_RawWcsdup(const wchar_t *str);
29 
30 typedef struct {
31     /* We tag each block with an API ID in order to tag API violations */
32     char api_id;
33     PyMemAllocatorEx alloc;
34 } debug_alloc_api_t;
35 
36 struct _pymem_allocators {
37     PyMutex mutex;
38     struct {
39         PyMemAllocatorEx raw;
40         PyMemAllocatorEx mem;
41         PyMemAllocatorEx obj;
42     } standard;
43     struct {
44         debug_alloc_api_t raw;
45         debug_alloc_api_t mem;
46         debug_alloc_api_t obj;
47     } debug;
48     int is_debug_enabled;
49     PyObjectArenaAllocator obj_arena;
50 };
51 
52 struct _Py_mem_interp_free_queue {
53     int has_work;   // true if the queue is not empty
54     PyMutex mutex;  // protects the queue
55     struct llist_node head;  // queue of _mem_work_chunk items
56 };
57 
58 /* Set the memory allocator of the specified domain to the default.
59    Save the old allocator into *old_alloc if it's non-NULL.
60    Return on success, or return -1 if the domain is unknown. */
61 extern int _PyMem_SetDefaultAllocator(
62     PyMemAllocatorDomain domain,
63     PyMemAllocatorEx *old_alloc);
64 
65 /* Special bytes broadcast into debug memory blocks at appropriate times.
66    Strings of these are unlikely to be valid addresses, floats, ints or
67    7-bit ASCII.
68 
69    - PYMEM_CLEANBYTE: clean (newly allocated) memory
70    - PYMEM_DEADBYTE dead (newly freed) memory
71    - PYMEM_FORBIDDENBYTE: untouchable bytes at each end of a block
72 
73    Byte patterns 0xCB, 0xDB and 0xFB have been replaced with 0xCD, 0xDD and
74    0xFD to use the same values as Windows CRT debug malloc() and free().
75    If modified, _PyMem_IsPtrFreed() should be updated as well. */
76 #define PYMEM_CLEANBYTE      0xCD
77 #define PYMEM_DEADBYTE       0xDD
78 #define PYMEM_FORBIDDENBYTE  0xFD
79 
80 /* Heuristic checking if a pointer value is newly allocated
81    (uninitialized), newly freed or NULL (is equal to zero).
82 
83    The pointer is not dereferenced, only the pointer value is checked.
84 
85    The heuristic relies on the debug hooks on Python memory allocators which
86    fills newly allocated memory with CLEANBYTE (0xCD) and newly freed memory
87    with DEADBYTE (0xDD). Detect also "untouchable bytes" marked
88    with FORBIDDENBYTE (0xFD). */
_PyMem_IsPtrFreed(const void * ptr)89 static inline int _PyMem_IsPtrFreed(const void *ptr)
90 {
91     uintptr_t value = (uintptr_t)ptr;
92 #if SIZEOF_VOID_P == 8
93     return (value == 0
94             || value == (uintptr_t)0xCDCDCDCDCDCDCDCD
95             || value == (uintptr_t)0xDDDDDDDDDDDDDDDD
96             || value == (uintptr_t)0xFDFDFDFDFDFDFDFD);
97 #elif SIZEOF_VOID_P == 4
98     return (value == 0
99             || value == (uintptr_t)0xCDCDCDCD
100             || value == (uintptr_t)0xDDDDDDDD
101             || value == (uintptr_t)0xFDFDFDFD);
102 #else
103 #  error "unknown pointer size"
104 #endif
105 }
106 
107 extern int _PyMem_GetAllocatorName(
108     const char *name,
109     PyMemAllocatorName *allocator);
110 
111 /* Configure the Python memory allocators.
112    Pass PYMEM_ALLOCATOR_DEFAULT to use default allocators.
113    PYMEM_ALLOCATOR_NOT_SET does nothing. */
114 extern int _PyMem_SetupAllocators(PyMemAllocatorName allocator);
115 
116 /* Is the debug allocator enabled? */
117 extern int _PyMem_DebugEnabled(void);
118 
119 // Enqueue a pointer to be freed possibly after some delay.
120 extern void _PyMem_FreeDelayed(void *ptr);
121 
122 // Enqueue an object to be freed possibly after some delay
123 extern void _PyObject_FreeDelayed(void *ptr);
124 
125 // Periodically process delayed free requests.
126 extern void _PyMem_ProcessDelayed(PyThreadState *tstate);
127 
128 // Abandon all thread-local delayed free requests and push them to the
129 // interpreter's queue.
130 extern void _PyMem_AbandonDelayed(PyThreadState *tstate);
131 
132 // On interpreter shutdown, frees all delayed free requests.
133 extern void _PyMem_FiniDelayed(PyInterpreterState *interp);
134 
135 #ifdef __cplusplus
136 }
137 #endif
138 #endif  // !Py_INTERNAL_PYMEM_H
139