/** * Unlocks a memory object. * @param pMemNode Node of the memory object */ void MemoryUnlock(MEM_NODE *pMemNode) { // make sure memory object is already locked assert(pMemNode->flags & DWM_LOCKED); // clear the lock flag pMemNode->flags &= ~DWM_LOCKED; #ifdef DEBUG MemoryStats(); #endif // update the LRU time pMemNode->lruTime = DwGetCurrentTime(); }
/** * Allocates the specified number of bytes from the heap. * @param flags Allocation attributes * @param size Number of bytes to allocate */ static MEM_NODE *MemoryAlloc(long size) { MEM_NODE *pHeap = &heapSentinel; #ifdef SCUMM_NEED_ALIGNMENT const int alignPadding = sizeof(void*) - 1; size = (size + alignPadding) & ~alignPadding; //round up to nearest multiple of sizeof(void*), this ensures the addresses that are returned are alignment-safe. #endif // compact the heap to make up room for 'size' bytes, if necessary if (!HeapCompact(size)) return 0; // success! we may allocate a new node of the right size // Allocate a node. MEM_NODE *pNode = AllocMemNode(); // Allocate memory for the node. pNode->pBaseAddr = (byte *)malloc(size); // Verify that we got the memory. // TODO: If this fails, we should first try to compact the heap some further. assert(pNode->pBaseAddr); // Subtract size of new block from total heapSentinel.size -= size; #ifdef DEBUG MemoryStats(); #endif // Set flags, LRU time and size pNode->flags = DWM_USED; pNode->lruTime = DwGetCurrentTime() + 1; pNode->size = size; // set mnode at the end of the list pNode->pPrev = pHeap->pPrev; pNode->pNext = pHeap; // fix links to this mnode pHeap->pPrev->pNext = pNode; pHeap->pPrev = pNode; return pNode; }
/** * Locks a memory object and returns a pointer to the first byte * of the objects memory block. * @param pMemNode Node of the memory object */ void *MemoryLock(MEM_NODE *pMemNode) { // make sure memory object is not already locked assert((pMemNode->flags & DWM_LOCKED) == 0); // check for a discarded or null memory object if ((pMemNode->flags & DWM_DISCARDED) || pMemNode->size == 0) return NULL; // set the lock flag pMemNode->flags |= DWM_LOCKED; #ifdef DEBUG MemoryStats(); #endif // return memory objects base address return pMemNode->pBaseAddr; }
/** * Discards the specified memory object. * @param pMemNode Node of the memory object */ void MemoryDiscard(MEM_NODE *pMemNode) { // validate mnode pointer assert(pMemNode >= mnodeList && pMemNode <= mnodeList + NUM_MNODES - 1); // object must be in use and locked assert((pMemNode->flags & (DWM_USED | DWM_LOCKED)) == DWM_USED); // discard it if it isn't already if ((pMemNode->flags & DWM_DISCARDED) == 0) { // free memory free(pMemNode->pBaseAddr); heapSentinel.size += pMemNode->size; #ifdef DEBUG MemoryStats(); #endif // mark the node as discarded pMemNode->flags |= DWM_DISCARDED; pMemNode->pBaseAddr = NULL; pMemNode->size = 0; } }
FORCEINLINE DWORDLONG GetWinTotalRam() { // SYSTEM_INFO sys_info; MEMORYSTATUSEX mem_info; mem_info.dwLength = sizeof(MEMORYSTATUSEX); GlobalMemoryStatusEx(&mem_info); return mem_info.ullTotalPhys; } FORCEINLINE DWORDLONG GetWinPageSize() { SYSTEM_INFO sys_info; // MEMORYSTATUSEX mem_info; GetSystemInfo(&sys_info); /*TODO: �������� ����� ������� �������������(dwAllocationGranularity)*/ return sys_info.dwPageSize; } /*FIXIT: �������� � ������, � ������� ������ ������ �� �����������*/ fpPlatformMemory::MemoryStats fpPlatformMemory::Stats = MemoryStats(GetWinTotalRam(), 1024, GetWinPageSize()); void* fpWindowsPlatformMemory::SystemAlloc(SIZE_T size) { fpGenericMemory::Stats.IncrementSystemAllocCallCounter(); void* ptr = VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); memset(ptr, 0, size); //FIXIT: implement function fpPlatformMemory::Stats.OsMemory += size; return ptr; } void fpWindowsPlatformMemory::SystemFree(void* ptr,SIZE_T size) { fpPlatformMemory::Stats.IncrementSystemFreeCallCounter(); VirtualFree(ptr, 0, MEM_RELEASE); fpPlatformMemory::Stats.OsMemory -= size; }