diff options
author | Ian Lynagh <igloo@earth.li> | 2010-08-13 17:04:02 +0000 |
---|---|---|
committer | Ian Lynagh <igloo@earth.li> | 2010-08-13 17:04:02 +0000 |
commit | 3fb074b5fcfd91fe0d37af83f221450ac4734908 (patch) | |
tree | ce49021f2f6411643cfc261b79bbb73e4ea1ff1c /rts/win32/OSMem.c | |
parent | 429dc9a048f5533143fb5c9908b09d3155496e9b (diff) | |
download | haskell-3fb074b5fcfd91fe0d37af83f221450ac4734908.tar.gz |
Return memory to the OS; trac #698
Diffstat (limited to 'rts/win32/OSMem.c')
-rw-r--r-- | rts/win32/OSMem.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/rts/win32/OSMem.c b/rts/win32/OSMem.c index f61aadc762..44286d2562 100644 --- a/rts/win32/OSMem.c +++ b/rts/win32/OSMem.c @@ -203,6 +203,42 @@ osGetMBlocks(nat n) { return ret; } +void osFreeMBlocks(char *addr, nat n) +{ + alloc_rec *p; + lnat nBytes = (lnat)n * MBLOCK_SIZE; + + insertFree(addr, nBytes); + + p = allocs; + while ((p != NULL) && (addr >= (p->base + p->size))) { + p = p->next; + } + while (nBytes > 0) { + if ((p == NULL) || (p->base > addr)) { + errorBelch("Memory to be freed isn't allocated\n"); + stg_exit(EXIT_FAILURE); + } + if (p->base + p->size >= addr + nBytes) { + if (!VirtualFree(addr, nBytes, MEM_DECOMMIT)) { + sysErrorBelch("osFreeMBlocks: VirtualFree MEM_DECOMMIT failed"); + stg_exit(EXIT_FAILURE); + } + nBytes = 0; + } + else { + lnat bytesToFree = p->base + p->size - addr; + if (!VirtualFree(addr, bytesToFree, MEM_DECOMMIT)) { + sysErrorBelch("osFreeMBlocks: VirtualFree MEM_DECOMMIT failed"); + stg_exit(EXIT_FAILURE); + } + addr += bytesToFree; + nBytes -= bytesToFree; + p = p->next; + } + } +} + void osFreeAllMBlocks(void) { |