forked from python/cpython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmalloc_closure.c
More file actions
148 lines (132 loc) · 3.53 KB
/
malloc_closure.c
File metadata and controls
148 lines (132 loc) · 3.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#ifndef Py_BUILD_CORE_BUILTIN
# define Py_BUILD_CORE_MODULE 1
#endif
#include <Python.h>
#include <ffi.h>
#ifdef MS_WIN32
# include <windows.h>
#else
# include <sys/mman.h>
# include <unistd.h> // sysconf()
# if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
# define MAP_ANONYMOUS MAP_ANON
# endif
#endif
#include "ctypes.h"
/* BLOCKSIZE can be adjusted. Larger blocksize will take a larger memory
overhead, but allocate less blocks from the system. It may be that some
systems have a limit of how many mmap'd blocks can be open.
*/
#define BLOCKSIZE _pagesize
/* #define MALLOC_CLOSURE_DEBUG */ /* enable for some debugging output */
/******************************************************************/
typedef union _tagITEM {
ffi_closure closure;
union _tagITEM *next;
} ITEM;
static ITEM *free_list;
static int _pagesize;
static void more_core(void)
{
ITEM *item;
int count, i;
/* determine the pagesize */
#ifdef MS_WIN32
if (!_pagesize) {
SYSTEM_INFO systeminfo;
GetSystemInfo(&systeminfo);
_pagesize = systeminfo.dwPageSize;
}
#else
if (!_pagesize) {
#ifdef _SC_PAGESIZE
_pagesize = sysconf(_SC_PAGESIZE);
#else
_pagesize = getpagesize();
#endif
}
#endif
/* calculate the number of nodes to allocate */
count = BLOCKSIZE / sizeof(ITEM);
/* allocate a memory block */
#ifdef MS_WIN32
item = (ITEM *)VirtualAlloc(NULL,
count * sizeof(ITEM),
MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
if (item == NULL)
return;
#else
item = (ITEM *)mmap(NULL,
count * sizeof(ITEM),
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS,
-1,
0);
if (item == (void *)MAP_FAILED)
return;
#endif
#ifdef MALLOC_CLOSURE_DEBUG
printf("block at %p allocated (%d bytes), %d ITEMs\n",
item, count * (int)sizeof(ITEM), count);
#endif
/* put them into the free list */
for (i = 0; i < count; ++i) {
item->next = free_list;
free_list = item;
++item;
}
}
/******************************************************************/
/* put the item back into the free list */
void Py_ffi_closure_free(void *p)
{
#ifdef HAVE_FFI_CLOSURE_ALLOC
#ifdef USING_APPLE_OS_LIBFFI
# ifdef HAVE_BUILTIN_AVAILABLE
if (__builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)) {
# else
if (ffi_closure_free != NULL) {
# endif
#endif
ffi_closure_free(p);
return;
#ifdef USING_APPLE_OS_LIBFFI
}
#endif
#endif
ITEM *item = (ITEM *)p;
item->next = free_list;
free_list = item;
}
/* return one item from the free list, allocating more if needed */
void *Py_ffi_closure_alloc(size_t size, void** codeloc)
{
#ifdef HAVE_FFI_CLOSURE_ALLOC
#ifdef USING_APPLE_OS_LIBFFI
# ifdef HAVE_BUILTIN_AVAILABLE
if (__builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)) {
# else
if (ffi_closure_alloc != NULL) {
# endif
#endif
return ffi_closure_alloc(size, codeloc);
#ifdef USING_APPLE_OS_LIBFFI
}
#endif
#endif
ITEM *item;
if (!free_list)
more_core();
if (!free_list)
return NULL;
item = free_list;
free_list = item->next;
#ifdef _M_ARM
// set Thumb bit so that blx is called correctly
*codeloc = (ITEM*)((uintptr_t)item | 1);
#else
*codeloc = (void *)item;
#endif
return (void *)item;
}