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 25 typedef union _tagITEM { 26 ffi_closure closure; 27 union _tagITEM *next; 28 } ITEM; 29 30 static ITEM *free_list; 31 static int _pagesize; 32 33 static 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 */ 92 void 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 */ 100 void *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