Home | History | Annotate | Download | only in _ctypes
      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