void FixedAlloc::FreeChunk(FixedBlock* b) { if ( ((b->prevFree && (b->prevFree->nextFree!=b))) || ((b->nextFree && (b->nextFree->prevFree!=b))) ) VMPI_abort(); m_numBlocks--; // Unlink the block from the list if (b == m_firstBlock) m_firstBlock = b->next; else b->prev->next = b->next; if (b == m_lastBlock) m_lastBlock = b->prev; else b->next->prev = b->prev; // If this is the first free block, pick a new one... if ( m_firstFree == b ) m_firstFree = b->nextFree; else if (b->prevFree) b->prevFree->nextFree = b->nextFree; if (b->nextFree) b->nextFree->prevFree = b->prevFree; // Any lock can't be held across the call to FreeNoProfile, so if there // is a lock obtain it, release it, and then reacquire it. This works // because Destroy caches no state across the call to FreeChunk. vmpi_spin_lock_t *lock = NULL; if(m_isFixedAllocSafe) { lock = &((FixedAllocSafe*)this)->m_spinlock; VMPI_lockRelease(lock); } // Free the memory m_heap->FreeNoProfile(b); if(lock != NULL) VMPI_lockAcquire(lock); VALGRIND_MEMPOOL_FREE(b, b); VALGRIND_DESTROY_MEMPOOL(b); }
void *AVMPI_allocateCodeMemory(size_t nbytes) { MMgc::GCHeap* heap = MMgc::GCHeap::GetGCHeap(); size_t pagesize = VMPI_getVMPageSize(); if (nbytes % pagesize != 0) { #ifdef DEBUG char buf[256]; VMPI_snprintf(buf, sizeof(buf), "AVMPI_allocateCodeMemory invariants violated: request=%lu pagesize=%lu\nAborting.\n", (unsigned long)nbytes, (unsigned long)pagesize); VMPI_log(buf); #endif VMPI_abort(); } size_t nblocks = nbytes / MMgc::GCHeap::kBlockSize; heap->SignalCodeMemoryAllocation(nblocks, true); return heap->Alloc(nblocks, MMgc::GCHeap::flags_Alloc, pagesize/MMgc::GCHeap::kBlockSize); }
void AVMPI_makeCodeMemoryExecutable(void *address, size_t nbytes, bool makeItSo) { size_t pagesize = VMPI_getVMPageSize(); if ((uintptr_t)address % pagesize != 0 || nbytes % pagesize != 0) { #ifdef DEBUG char buf[256]; VMPI_snprintf(buf, sizeof(buf), "AVMPI_makeCodeMemoryExecutable invariants violated: address=%llu size=%llu pagesize=%llu\nAborting.\n", (unsigned long long)(uintptr_t)address, (unsigned long long)nbytes, (unsigned long long)pagesize); VMPI_log(buf); #endif VMPI_abort(); } DWORD oldProtectFlags = 0; DWORD newProtectFlags = 0; if ( makeItSo ) newProtectFlags = PAGE_EXECUTE_READ; else newProtectFlags = PAGE_READWRITE; BOOL retval; do { MEMORY_BASIC_INFORMATION mbi; VirtualQuery(address, &mbi, sizeof(MEMORY_BASIC_INFORMATION)); size_t markSize = nbytes > mbi.RegionSize ? mbi.RegionSize : nbytes; // handle multiple adjoining regions retval = VirtualProtect(address, markSize, newProtectFlags, &oldProtectFlags); AvmAssert(retval != 0); address = (char*) address + markSize; nbytes -= markSize; } while(nbytes != 0 && retval != 0); }
void AVMPI_makeCodeMemoryExecutable(void *address, size_t nbytes, bool makeItSo) { size_t pagesize = VMPI_getVMPageSize(); if ((uintptr_t)address % pagesize != 0 || nbytes % pagesize != 0) { #ifdef DEBUG char buf[256]; VMPI_snprintf(buf, sizeof(buf), "AVMPI_makeCodeMemoryExecutable invariants violated: address=%lu size=%lu pagesize=%lu\nAborting.\n", (unsigned long)address, (unsigned long)nbytes, (unsigned long)pagesize); VMPI_log(buf); #endif VMPI_abort(); } int flags = makeItSo ? PROT_EXEC|PROT_READ : PROT_WRITE|PROT_READ; int retval = mprotect((maddr_ptr)address, (unsigned int)nbytes, flags); AvmAssert(retval == 0); (void)retval; }
void AVMPI_freeCodeMemory(void* address, size_t nbytes) { MMgc::GCHeap* heap = MMgc::GCHeap::GetGCHeap(); size_t pagesize = VMPI_getVMPageSize(); size_t nblocks = heap->Size(address); size_t actualBytes = nblocks * MMgc::GCHeap::kBlockSize; if ((uintptr_t)address % pagesize != 0 || nbytes % pagesize != 0 || nbytes != actualBytes) { #ifdef DEBUG char buf[256]; VMPI_snprintf(buf, sizeof(buf), "AVMPI_freeCodeMemory invariants violated: address=%lu provided=%lu actual=%lu\nAborting.\n", (unsigned long)address, (unsigned long)nbytes, (unsigned long)actualBytes); VMPI_log(buf); #endif VMPI_abort(); } heap->Free(address); heap->SignalCodeMemoryDeallocated(nblocks, true); }