1b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#include <Python.h>
2b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#include <ffi.h>
3b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#ifdef MS_WIN32
4b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#include <windows.h>
5b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#else
6b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#include <sys/mman.h>
7b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#include <unistd.h>
8b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller# if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
9b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#  define MAP_ANONYMOUS MAP_ANON
10b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller# endif
11b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#endif
12b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#include "ctypes.h"
13b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller
14b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller/* BLOCKSIZE can be adjusted.  Larger blocksize will take a larger memory
15b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller   overhead, but allocate less blocks from the system.  It may be that some
16b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller   systems have a limit of how many mmap'd blocks can be open.
17b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller*/
18b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller
19b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#define BLOCKSIZE _pagesize
20b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller
21b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller/* #define MALLOC_CLOSURE_DEBUG */ /* enable for some debugging output */
22b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller
23b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller/******************************************************************/
24b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller
25b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Hellertypedef union _tagITEM {
26c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    ffi_closure closure;
27c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    union _tagITEM *next;
28b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller} ITEM;
29b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller
30b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Hellerstatic ITEM *free_list;
31b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Hellerstatic int _pagesize;
32b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller
33b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Hellerstatic void more_core(void)
34b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller{
35c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    ITEM *item;
36c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    int count, i;
37b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller
38b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller/* determine the pagesize */
39b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#ifdef MS_WIN32
40c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    if (!_pagesize) {
41c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        SYSTEM_INFO systeminfo;
42c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        GetSystemInfo(&systeminfo);
43c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        _pagesize = systeminfo.dwPageSize;
44c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    }
45b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#else
46c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    if (!_pagesize) {
47b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#ifdef _SC_PAGESIZE
48c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        _pagesize = sysconf(_SC_PAGESIZE);
49b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#else
50c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        _pagesize = getpagesize();
51b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#endif
52c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    }
53b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#endif
54b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller
55c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    /* calculate the number of nodes to allocate */
56c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    count = BLOCKSIZE / sizeof(ITEM);
57b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller
58c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    /* allocate a memory block */
59b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#ifdef MS_WIN32
60c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    item = (ITEM *)VirtualAlloc(NULL,
61c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou                                           count * sizeof(ITEM),
62c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou                                           MEM_COMMIT,
63c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou                                           PAGE_EXECUTE_READWRITE);
64c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    if (item == NULL)
65c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        return;
66b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#else
67c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    item = (ITEM *)mmap(NULL,
68c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou                        count * sizeof(ITEM),
69c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou                        PROT_READ | PROT_WRITE | PROT_EXEC,
70c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou                        MAP_PRIVATE | MAP_ANONYMOUS,
71c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou                        -1,
72c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou                        0);
73c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    if (item == (void *)MAP_FAILED)
74c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        return;
75b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#endif
76b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller
77b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#ifdef MALLOC_CLOSURE_DEBUG
78c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    printf("block at %p allocated (%d bytes), %d ITEMs\n",
79c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou           item, count * sizeof(ITEM), count);
80b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller#endif
81c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    /* put them into the free list */
82c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    for (i = 0; i < count; ++i) {
83c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        item->next = free_list;
84c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        free_list = item;
85c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        ++item;
86c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    }
87b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller}
88b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller
89b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller/******************************************************************/
90b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller
91b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller/* put the item back into the free list */
92001d3a1d8ac9b5a057a585950182880f5733c608Thomas Hellervoid ffi_closure_free(void *p)
93b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller{
94c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    ITEM *item = (ITEM *)p;
95c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    item->next = free_list;
96c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    free_list = item;
97b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller}
98b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller
99b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller/* return one item from the free list, allocating more if needed */
100001d3a1d8ac9b5a057a585950182880f5733c608Thomas Hellervoid *ffi_closure_alloc(size_t ignored, void** codeloc)
101b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller{
102c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    ITEM *item;
103c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    if (!free_list)
104c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        more_core();
105c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    if (!free_list)
106c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        return NULL;
107c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    item = free_list;
108c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    free_list = item->next;
10930a171fcb6ae70a98a6366c401e494ecc44ee2d8Ronald Oussoren    *codeloc = (void *)item;
110001d3a1d8ac9b5a057a585950182880f5733c608Thomas Heller    return (void *)item;
111b102ddadcbcaaf8fc50e5060e45b89a4d3a3a492Thomas Heller}
112