summaryrefslogtreecommitdiff
path: root/win32
diff options
context:
space:
mode:
authorSteve Hay <SteveHay@planit.com>2004-07-16 12:16:05 +0000
committerNick Ing-Simmons <nik@tiuk.ti.com>2004-07-16 12:16:05 +0000
commitb2d41e21b21c57718b8e506bc104adc20f931613 (patch)
treec76e9c806fa21db4d66c55ec9e0e26397af894ba /win32
parent69e39a9aeaf661e41da7db0001d9c91f3c2c89c7 (diff)
downloadperl-b2d41e21b21c57718b8e506bc104adc20f931613.tar.gz
Use VirtualAlloc() more flexibly when using it to mimic UNIX's sbrk().
CC: perl-win32-porters@listserv.ActiveState.com Message-ID: <40F6B295.8010804@uk.radan.com> Assumes perl's malloc can now handle non-contiguous memory (believed to be true). Does not address threading issues. "The attached patch (against blead) makes sbrk() initially try to extend the existing block of memory exactly as it currently does, but to not fail immediately if it can't -- it now frees up that part of whatever it had previously reserved+committed which hadn't actually been used yet, resets all its static variables and basically starts anew." p4raw-id: //depot/perl@23128
Diffstat (limited to 'win32')
-rw-r--r--win32/win32.c41
1 files changed, 30 insertions, 11 deletions
diff --git a/win32/win32.c b/win32/win32.c
index bead78a8a8..2e5db2c94a 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -4155,7 +4155,6 @@ static char *base = NULL; /* XXX threadead */
static char *reserved = NULL; /* XXX threadead */
static char *brk = NULL; /* XXX threadead */
static DWORD pagesize = 0; /* XXX threadead */
-static DWORD allocsize = 0; /* XXX threadead */
void *
sbrk(ptrdiff_t need)
@@ -4168,28 +4167,34 @@ sbrk(ptrdiff_t need)
* call the OS to commit just one page ...
*/
pagesize = info.dwPageSize << 3;
- allocsize = info.dwAllocationGranularity;
}
- /* This scheme fails eventually if request for contiguous
- * block is denied so reserve big blocks - this is only
- * address space not memory ...
- */
if (brk+need >= reserved)
{
- DWORD size = 64*1024*1024;
+ DWORD size = brk+need-reserved;
char *addr;
+ char *prev_committed = NULL;
if (committed && reserved && committed < reserved)
{
/* Commit last of previous chunk cannot span allocations */
addr = (char *) VirtualAlloc(committed,reserved-committed,MEM_COMMIT,PAGE_READWRITE);
if (addr)
+ {
+ /* Remember where we committed from in case we want to decommit later */
+ prev_committed = committed;
committed = reserved;
+ }
}
/* Reserve some (more) space
+ * Contiguous blocks give us greater efficiency, so reserve big blocks -
+ * this is only address space not memory...
* Note this is a little sneaky, 1st call passes NULL as reserved
* so lets system choose where we start, subsequent calls pass
* the old end address so ask for a contiguous block
*/
+sbrk_reserve:
+ if (size < 64*1024*1024)
+ size = 64*1024*1024;
+ size = ((size + pagesize - 1) / pagesize) * pagesize;
addr = (char *) VirtualAlloc(reserved,size,MEM_RESERVE,PAGE_NOACCESS);
if (addr)
{
@@ -4201,6 +4206,19 @@ sbrk(ptrdiff_t need)
if (!brk)
brk = committed;
}
+ else if (reserved)
+ {
+ /* The existing block could not be extended far enough, so decommit
+ * anything that was just committed above and start anew */
+ if (prev_committed)
+ {
+ if (!VirtualFree(prev_committed,reserved-prev_committed,MEM_DECOMMIT))
+ return (void *) -1;
+ }
+ reserved = base = committed = brk = NULL;
+ size = need;
+ goto sbrk_reserve;
+ }
else
{
return (void *) -1;
@@ -4211,11 +4229,12 @@ sbrk(ptrdiff_t need)
if (brk > committed)
{
DWORD size = ((brk-committed + pagesize -1)/pagesize) * pagesize;
- char *addr = (char *) VirtualAlloc(committed,size,MEM_COMMIT,PAGE_READWRITE);
+ char *addr;
+ if (committed+size > reserved)
+ size = reserved-committed;
+ addr = (char *) VirtualAlloc(committed,size,MEM_COMMIT,PAGE_READWRITE);
if (addr)
- {
- committed += size;
- }
+ committed += size;
else
return (void *) -1;
}