/* * Return the address of the base of the newly committed memory, or 0 * if committing failed. */ void * sysCommitMem(void *requestedAddr, size_t requestedSize, size_t *committedSize) { void *committedAddr; char *ret; *committedSize = roundUpToGrain(requestedSize); committedAddr = (void *) roundDownToGrain((long) requestedAddr); #ifdef USE_MALLOC #ifdef __linux__ ret = committedAddr; #else ret = requestedAddr; #endif #else ret = mapChunkReserve(committedAddr, *committedSize); #endif if (ret) { committedAddr = ret; Log4(2, "sysCommitMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n", *committedSize, committedAddr, requestedSize, requestedAddr); } else { committedAddr = 0; Log2(2, "sysCommitMem failed: (request: 0x%x bytes at 0x%x)\n", requestedSize, requestedAddr); } return committedAddr; }
/* Purpose: Decommits a range of memory which was previously committed using CVMmemCommit(). The memory range may be a subset of the range returned by CVMmemCommit(). The range to decommit is specified by addr as the starting address of the range, and requestedSize as the size of the range in units of bytes. Returns: The starting address of the decommitted range is returned. The actual size of the decommitted range is set in *decommittedSize in units of bytes. Else, if failed to decommit, NULL is returned and *decommittedSize is set to 0. Note: memory sizes must be in increments of the page size as returned by CVMmemPageSize() in units of bytes. Committed memory must be uncommitted using CVMmemDecommit() before it is unmmapped with CVMmemUnmap(). If this order is not adhered to, then the state of the committed memory will be undefined. */ void *CVMmemDecommit(void *requestedAddr, size_t requestedSize, size_t *decommittedSize) { void *decommittedAddr = NULL; CVMBool success = CVM_FALSE; CVMassert(requestedSize == roundDownToGrain(requestedSize)); CVMassert(requestedAddr == (void *)roundUpToGrain((CVMAddr)requestedAddr)); if (requestedSize != 0) { success = VirtualFree(requestedAddr, requestedSize, MEM_DECOMMIT); #ifdef WINCE if (!success && ((DWORD)requestedAddr + requestedSize) >= ROUND_UP_32MB(requestedAddr)) { /* crossing 32MB boundary, need to break up the decommit */ size_t origSize = requestedSize; void *newAddr = requestedAddr; while(((DWORD)newAddr + origSize) >= ROUND_UP_32MB(newAddr)) { size_t newSize = ROUND_UP_32MB(newAddr) - (DWORD)newAddr; success = VirtualFree(newAddr, newSize, MEM_DECOMMIT); if (!success) { break; } newAddr = (void*)((DWORD)newAddr + newSize); origSize -= newSize; } if (success && origSize > 0) { /* Some residual pages to decommit */ success = VirtualFree(newAddr, origSize, MEM_DECOMMIT); } } #endif } if (success) { decommittedAddr = requestedAddr; *decommittedSize = requestedSize; } else { *decommittedSize = 0; } #ifdef DEBUG_MMAP if (success) { CVMconsolePrintf( "CVMmemDecommit: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n", *decommittedSize, decommittedAddr, requestedSize, requestedAddr); } else { CVMconsolePrintf( "CVMmemDecommit failed: (request: 0x%x bytes at 0x%x)\n", requestedSize, requestedAddr); } #endif return decommittedAddr; }
/* * Return the address of the base of the newly decommitted memory, or 0 * if decommitting failed. */ void * sysDecommitMem(void *requestedAddr, size_t requestedSize, size_t *decommittedSize) { void *decommittedAddr; char *ret; *decommittedSize = roundDownToGrain(requestedSize); decommittedAddr = (void *) roundUpToGrain((long) requestedAddr); #ifdef USE_MALLOC ret = 0; #else ret = mapChunkNoreserve(decommittedAddr, *decommittedSize); #endif Log4(2, "sysDecommitMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n", *decommittedSize, decommittedAddr, requestedSize, requestedAddr); return ret; }
/* Purpose: Commits a range of memory which was previously reserved using CVMmemMap(). The memory range may be a subset of the range returned by CVMmemMap(). The range to commit is specified by addr as the starting address of the range, and requestedSize as the size of the range in units of bytes. Returns: The starting address of the committed range is returned. The actual size of the committed range is set in *committedSize in units of bytes. Else, if failed to commit, NULL is returned and *committedSize is set to 0. Note: memory sizes must be in increments of the page size as returned by CVMmemPageSize() in units of bytes. Committed memory must be uncommitted using CVMmemDecommit() before it is unmmapped with CVMmemUnmap(). If this order is not adhered to, then the state of the committed memory will be undefined. */ void *CVMmemCommit(void *requestedAddr, size_t requestedSize, size_t *committedSize) { void *committedAddr = NULL; MEMORY_BASIC_INFORMATION mb; CVMassert(requestedSize == roundUpToGrain(requestedSize)); CVMassert(requestedAddr == (void *)roundDownToGrain((CVMAddr)requestedAddr)); if (requestedSize != 0) { committedAddr = VirtualAlloc(requestedAddr, requestedSize, MEM_COMMIT, PAGE_READWRITE); #ifdef WINCE if (committedAddr == NULL && ((DWORD)requestedAddr + requestedSize) >= ROUND_UP_32MB(requestedAddr)) { /* hitting/crossing 32MB boundary, need to break up the commit */ size_t origSize = requestedSize; void *newAddr = requestedAddr; size_t pageSize = CVMmemPageSize(); while(((DWORD)newAddr + origSize) >= ROUND_UP_32MB(newAddr)) { size_t newSize = ROUND_UP_32MB(newAddr) - (DWORD)newAddr; if (newSize >= pageSize * 2) { /* Sometimes, for whatever reason, if you * allocate right up to the 32MB boundary it returns * INVALID PARAMETER error. So, back off a page */ newSize -= pageSize; } committedAddr = VirtualAlloc(newAddr, newSize, MEM_COMMIT, PAGE_READWRITE); if (committedAddr == NULL) { break; } newAddr = (void*)((DWORD)newAddr + newSize); origSize -= newSize; } #if _WIN32_WCE < 600 while(committedAddr != NULL && origSize > 0) { /* Some residual pages to commit */ /* WinCE < 6.0 fails on commits that are too big, where too big * is some unknown value I can't seem to pin down. So just do * it a page at a time. */ committedAddr = VirtualAlloc(newAddr, pageSize, MEM_COMMIT, PAGE_READWRITE); origSize -= pageSize; newAddr = (void *)((DWORD)newAddr + pageSize); } #else if (committedAddr != NULL) { committedAddr = VirtualAlloc(newAddr, origSize, MEM_COMMIT, PAGE_READWRITE); } #endif if (committedAddr != NULL) { committedAddr = requestedAddr; } } #endif } *committedSize = (committedAddr != NULL) ? (CVMassert(committedAddr == requestedAddr), requestedSize) : 0; #ifdef WINCE if (committedAddr == NULL) { /* Must have had an error committing, attempt to decommit anything we * committed */ size_t decommittedSize; CVMmemDecommit(requestedAddr, requestedSize, &decommittedSize); } #endif #ifdef DEBUG_MMAP if (committedAddr != NULL) { CVMconsolePrintf( "CVMmemCommit: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n", *committedSize, committedAddr, requestedSize, requestedAddr); } else { CVMconsolePrintf( "CVMmemCommit failed: Error %d, (request: 0x%x bytes at 0x%x)\n", GetLastError(), requestedSize, requestedAddr); CVMconsolePrintf("CVMmemCommit: State:\n"); VirtualQuery(requestedAddr, &mb, sizeof(mb)); CVMconsolePrintf(" Base: 0x%x\n AllocBase: 0x%x\n AllocProtect: 0x%x\n Size: 0x%x\n State: 0x%x\n Protect: 0x%x\n Type: 0x%x\n", (int)mb.BaseAddress, mb.AllocationBase, mb.AllocationProtect, mb.RegionSize, mb.State, mb.Protect, mb.Type); } #endif return committedAddr; }