Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 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; |
Thomas Heller | 579b65c | 2009-04-16 18:37:24 +0000 | [diff] [blame] | 31 | static int _pagesize; |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 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) { |
Georg Brandl | f78e02b | 2008-06-10 17:40:04 +0000 | [diff] [blame] | 47 | #ifdef _SC_PAGESIZE |
| 48 | _pagesize = sysconf(_SC_PAGESIZE); |
| 49 | #else |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 50 | _pagesize = getpagesize(); |
Georg Brandl | f78e02b | 2008-06-10 17:40:04 +0000 | [diff] [blame] | 51 | #endif |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 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 */ |
Thomas Heller | 34596a9 | 2009-04-24 20:50:00 +0000 | [diff] [blame] | 92 | void _ctypes_free_closure(void *p) |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 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 */ |
Thomas Heller | 34596a9 | 2009-04-24 20:50:00 +0000 | [diff] [blame] | 100 | void *_ctypes_alloc_closure(void) |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 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 | return item; |
| 110 | } |