Back to index

plt-scheme  4.2.1
vm_win.c
Go to the documentation of this file.
00001 /* 
00002    Provides:
00003       allocator
00004       determine_max_heap_size()
00005    Requires:
00006    Optional:
00007       DONT_NEED_MAX_HEAP_SIZE --- to disable a provide
00008 */
00009 
00010 /* Cache doesn't seem to help in Windows: */
00011 #define CACHE_SLOTS 0
00012 
00013 #if CACHE_SLOTS
00014 typedef struct {
00015   size_t len;
00016   void *page;
00017 } alloc_cache_entry;
00018 
00019 /* First dimension is age: */
00020 static alloc_cache_entry cache[2][CACHE_SLOTS];
00021 #endif
00022 
00023 static void *vm_malloc_pages(VM *vm, size_t len, size_t alignment, int dirty_ok)
00024 {
00025 #if CACHE_SLOTS
00026   {
00027     int i, j;
00028 
00029     for (j = 0; j < 2; j++) {
00030       for (i = 0; i < CACHE_SLOTS; i++) {
00031         if (cache[j][i].len == len) {
00032           if (cache[j][i].page) {
00033             void *result = cache[j][i].page;
00034             cache[j][i].page = *(void **)result;
00035             memset(result, 0, len);
00036             return result;
00037           }
00038           break;
00039         }
00040       }
00041     }
00042   }
00043 #endif
00044 
00045   vm_memory_allocated_inc(vm, len);
00046 
00047   /* VirtualAlloc MEM_COMMIT always zeros memory */
00048   return (void *)VirtualAlloc(NULL, len, 
00049       MEM_COMMIT | MEM_RESERVE, 
00050       PAGE_READWRITE);
00051 }
00052 
00053 static void vm_free_pages(VM *vm, void *p, size_t len)
00054 {
00055 
00056 #if CACHE_SLOTS
00057   {
00058     int i;
00059 
00060     for (i = 0; i < CACHE_SLOTS; i++) {
00061       if (!cache[0][i].len)
00062         cache[0][i].len = len;
00063       if (cache[0][i].len == len) {
00064         *(void **)p = cache[0][i].page;
00065         cache[0][i].page = p;
00066         return;
00067       }
00068     }
00069   }
00070 #endif
00071 
00072   vm_memory_allocated_dec(vm, len);
00073   VirtualFree(p, 0, MEM_RELEASE);
00074 }
00075 
00076 static void vm_flush_freed_pages(VM *vm)
00077 {
00078 #if CACHE_SLOTS
00079   int i;
00080   void *p, *next;
00081 
00082   for (i = 0; i < CACHE_SLOTS; i++) {
00083     if (cache[1][i].len) {
00084       for (p = cache[1][i].page; p; p = next) {
00085         next = *(void **)p;
00086         vm_memory_allocated_dec(vm, cache[i].len);
00087         VirtualFree(p, 0, MEM_RELEASE);
00088       }
00089     }
00090     cache[1][i].len = cache[0][i].len;
00091     cache[1][i].page = cache[0][i].page;
00092     cache[0][i].len = 0;
00093     cache[0][i].page = NULL;
00094   }
00095 #endif
00096 }
00097 
00098 static void vm_protect_pages(void *p, size_t len, int writeable)
00099 {
00100   DWORD old;
00101   VirtualProtect(p, len, (writeable ? PAGE_READWRITE : PAGE_READONLY), &old);
00102 }
00103 
00104 #ifndef DONT_NEED_MAX_HEAP_SIZE
00105 typedef unsigned long size_type;
00106 
00107 typedef BOOL (WINAPI * QueryInformationJobObject_Proc)(HANDLE hJob,
00108     JOBOBJECTINFOCLASS JobObjectInfoClass,
00109     LPVOID lpJobObjectInfo,
00110     DWORD cbJobObjectInfoLength,
00111     LPDWORD lpReturnLength);
00112 
00113 static size_type determine_max_heap_size(void)
00114 {
00115   JOBOBJECT_EXTENDED_LIMIT_INFORMATION info;
00116   HMODULE hm;
00117   SYSTEM_INFO si;
00118 
00119   hm = LoadLibrary("kernel32.dll");
00120   if (hm) {
00121     DWORD size;
00122     QueryInformationJobObject_Proc qijo = NULL;
00123     qijo = (QueryInformationJobObject_Proc)GetProcAddress(hm, "QueryInformationJobObject");
00124     if (qijo) {
00125       if (qijo(NULL, JobObjectExtendedLimitInformation, &info, sizeof(info), &size)) {
00126         if (info.BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_PROCESS_MEMORY) {
00127           return info.ProcessMemoryLimit;
00128         }
00129       }
00130     }
00131   }
00132 
00133   GetSystemInfo(&si);
00134   return (size_type)si.lpMaximumApplicationAddress - (size_type)si.lpMinimumApplicationAddress;
00135 }
00136 #endif