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