/* Allocate a region of memory of al least size bytes, at or above minAddress. * If the attempt fails, answer null. If the attempt succeeds, answer the * start of the region and assign its size through allocatedSizePointer. */ void * sqAllocateMemorySegmentOfSizeAboveAllocatedSizeInto(sqInt size, void *minAddress, sqInt *allocatedSizePointer) { void *alloc; long bytes = roundUpToPage(size); if (!pageSize) { pageSize = getpagesize(); pageMask = pageSize - 1; } *allocatedSizePointer = bytes; while ((char *)minAddress + bytes > (char *)minAddress) { alloc = mmap((void *)roundUpToPage((unsigned long)minAddress), bytes, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0); if (alloc == MAP_FAILED) { perror("sqAllocateMemorySegmentOfSizeAboveAllocatedSizeInto mmap"); return 0; } if (alloc >= minAddress) return alloc; if (munmap(alloc, bytes) != 0) perror("sqAllocateMemorySegment... munmap"); minAddress = (void *)((char *)minAddress + bytes); } return 0; }
/* Allocate a region of memory of al least size bytes, at or above minAddress. * If the attempt fails, answer null. If the attempt succeeds, answer the * start of the region and assign its size through allocatedSizePointer. */ void * sqAllocateMemorySegmentOfSizeAboveAllocatedSizeInto(sqInt size, void *minAddress, sqInt *allocatedSizePointer) { void *alloc; long bytes = roundUpToPage(size); *allocatedSizePointer = bytes; #if 0 /* It appears VirtualAlloc answers low memory by default. */ alloc = VirtualAlloc(0, bytes, MEM_COMMIT, PAGE_READWRITE); if (!alloc) { sqMessageBox(MB_OK | MB_ICONSTOP, TEXT("VM Error:"), "Unable to VirtualAlloc committed memory (%d bytes requested)", bytes); return NULL; } if ((unsigned long)alloc >= (unsigned long)minAddress) return alloc; if (!VirtualFree(alloc, bytes, MEM_RELEASE)) sqMessageBox(MB_OK | MB_ICONSTOP, TEXT("VM Warning:"), "Unable to VirtualFree committed memory (%d bytes requested)", bytes); #endif /* 0 */ alloc = VirtualAlloc(0, bytes, MEM_COMMIT+MEM_TOP_DOWN, PAGE_READWRITE); if ((unsigned long)alloc >= (unsigned long)minAddress) return alloc; if (!VirtualFree(alloc, bytes, MEM_RELEASE)) sqMessageBox(MB_OK | MB_ICONSTOP, TEXT("VM Warning:"), "Unable to VirtualFree committed memory (%d bytes requested)", bytes); sqMessageBox(MB_OK | MB_ICONSTOP, TEXT("VM Error:"), "Unable to VirtualAlloc committed memory at desired address (%d bytes requested at or above %p)", bytes, minAddress); return NULL; }
/* Answer the address of minHeapSize rounded up to page size bytes of memory. */ usqInt sqAllocateMemory(usqInt minHeapSize, usqInt desiredHeapSize) { char *hint, *address, *alloc; unsigned long alignment, allocBytes; if (pageSize) { fprintf(stderr, "sqAllocateMemory: already called\n"); exit(1); } pageSize = getpagesize(); pageMask = ~(pageSize - 1); hint = sbrk(0); alignment = mmax(pageSize,1024*1024); address = (char *)(((usqInt)hint + alignment - 1) & ~(alignment - 1)); alloc = sqAllocateMemorySegmentOfSizeAboveAllocatedSizeInto (roundUpToPage(desiredHeapSize), address, &allocBytes); if (!alloc) { fprintf(stderr, "sqAllocateMemory: initial alloc failed!\n"); exit(errno); } return (usqInt)alloc; }
void sqMakeMemoryNotExecutableFromTo(unsigned long startAddr, unsigned long endAddr) { unsigned long firstPage = roundDownToPage(startAddr); if (mprotect((void *)firstPage, roundUpToPage(endAddr - firstPage), PROT_READ | PROT_WRITE) < 0) perror("mprotect(x,y,PROT_READ | PROT_WRITE)"); }