void *MFObjectPool::Alloc() { MFThread_LockMutex(mutex); void *pAlloc = NULL; if(allocated < maxItems) { pAlloc = ppItems[allocated++]; } else { if(pNext) { pAlloc = pNext->Alloc(); } else if(grow) { MFHeap *pHeap = MFHeap_GetAllocHeap(pMemory); MFHeap *pOld = MFHeap_SetActiveHeap(pHeap); pNext = (MFObjectPool*)MFHeap_Alloc(sizeof(MFObjectPool)); pNext->Init(objectSize, grow, grow); MFHeap_SetActiveHeap(pOld); pAlloc = pNext->Alloc(); } } MFThread_ReleaseMutex(mutex); return pAlloc; }
int MFObjectPool::Free(void *pItem) { MFThread_LockMutex(mutex); int bFreed = 0; if(pItem >= pMemory && pItem < pMemory + bytes) { for(int a=0; a<allocated; ++a) { if(ppItems[a] == pItem) { void *pItem = ppItems[a]; ppItems[a] = ppItems[--allocated]; ppItems[allocated] = pItem; bFreed = 1; break; } } } if(!bFreed && pNext) bFreed = pNext->Free(pItem); MFThread_ReleaseMutex(mutex); return bFreed; }
void *MFObjectPoolGroup::Alloc(size_t bytes, size_t *pAllocated) { MFThread_LockMutex(mutex); void *pAlloc = NULL; for(int a=0; a<numPools; ++a) { if(bytes <= pConfig[a].objectSize) { if(pAllocated) *pAllocated = pConfig[a].objectSize; pAlloc = pPools[a].Alloc(); break; } } if(!pAlloc) { ++overflows; if(pAllocated) *pAllocated = bytes; MFHeap *pHeap = MFHeap_GetAllocHeap(pConfig); pAlloc = MFHeap_Alloc(bytes, pHeap); } MFThread_ReleaseMutex(mutex); return pAlloc; }
int MFInput_Thread(void *) { // poll input at high frequency... uint64 freq = MFSystem_GetRTCFrequency(); uint64 interval = freq / gInputFrequency; uint64 now = MFSystem_ReadRTC(); uint64 nextSample = now + interval; while(!bInputTerminate) { MFThread_LockMutex(gInputMutex); bThreadUpdate = true; MFInput_Update(); bThreadUpdate = false; // build events for(uint32 i=0; i<MFInput_MaxInputID; ++i) { if(!gDeviceStatus[IDD_Gamepad][i] == IDS_Ready) continue; for(uint32 j=0; j<GamepadType_Max; ++j) { if(gNumEvents[IDD_Gamepad][i] >= MaxEvents) break; MFGamepadState &state = gGamepadStates[i]; MFGamepadState &prev = gPrevGamepadStates[i]; if(state.values[j] == prev.values[j]) continue; MFInputEvent &e = gInputEvents[IDD_Gamepad][i][gNumEvents[IDD_Gamepad][i]++]; e.timestamp = now; e.event = MFIE_Change; e.input = j; e.state = state.values[j]; e.prevState = prev.values[j]; } } MFThread_ReleaseMutex(gInputMutex); // uint64 updateTime = MFSystem_ReadRTC(); // MFDebug_Log(0, MFStr("Input update: %dus", (uint32)((updateTime - now) * 1000000LL / MFSystem_GetRTCFrequency()))); uint32 ms = (uint32)((nextSample - now) * 1000LL / freq); MFThread_Sleep(ms); now = MFSystem_ReadRTC(); do nextSample += interval; while(now >= nextSample); } bInputTerminate = false; return 0; }
MF_API void *MFHeap_AllocInternal(size_t bytes, MFHeap *pHeap) { MFCALLSTACK; MFHeap *pAllocHeap = pOverrideHeap ? pOverrideHeap : (pHeap ? pHeap : pActiveHeap); size_t extra; size_t allocBytes = GetAllocSize(bytes, extra); MFThread_LockMutex(gAllocMutex); char *pMemory = (char*)pAllocHeap->pCallbacks->pMalloc(allocBytes, pAllocHeap->pHeapData); if(pMemory) { #if defined(_USE_TRACKING_HASH_TABLE) #if defined(USE_PRE_MUNGWALL) int alignment = (int)(MFALIGN(pMemory + MFHeap_MungwallBytes, heapAlignment) - (uintp)pMemory); #else int alignment = (int)(MFALIGN(pMemory, heapAlignment) - (uintp)pMemory); #endif #else int alignment = (int)(MFALIGN(pMemory + sizeof(MFAllocHeader), heapAlignment) - (uintp)pMemory); #endif pMemory += alignment; #if defined(_USE_TRACKING_HASH_TABLE) MFAllocHeader *pHeader = AddAlloc(pMemory, bytes, NULL); #else MFAllocHeader *pHeader = GetAllocHeader(pMemory); #endif pHeader->alignment = alignment; pHeader->pHeap = pAllocHeap; pHeader->size = bytes; pHeader->pFile = gpMFHeap_TrackerFile; pHeader->line = gMFHeap_TrackerLine; #if defined(USE_PRE_MUNGWALL) MFCopyMemory(pMemory - MFHeap_MungwallBytes, gLlawgnum, MFHeap_MungwallBytes); #endif #if !defined(_RETAIL) MFCopyMemory(pMemory + bytes, gMungwall, MFHeap_MungwallBytes); pAllocHeap->totalAllocated += allocBytes; pAllocHeap->totalWaste += extra; ++pAllocHeap->allocCount; // MFDebug_Log(2, MFStr("Alloc: %p(%p), %d bytes - %s:(%d)", pMemory, pMemory - pHeader->alignment, bytes, gpMFHeap_TrackerFile, gMFHeap_TrackerLine)); #endif } MFThread_ReleaseMutex(gAllocMutex); return (void*)pMemory; }
void MFObjectPoolGroup::Deinit() { MFThread_LockMutex(mutex); for(int a=0; a<numPools; ++a) pPools[a].Deinit(); MFThread_DestroyMutex(mutex); MFHeap_Free(pConfig); }
void MFObjectPoolGroup::Free(void *pItem) { MFThread_LockMutex(mutex); for(int a=0; a<numPools; ++a) { if(pPools[a].Free(pItem)) goto free_done; } --overflows; MFHeap_Free(pItem); free_done: MFThread_ReleaseMutex(mutex); }
void MFObjectPool::Deinit() { if(!pMemory) return; MFThread_LockMutex(mutex); if(pNext) { pNext->Deinit(); MFHeap_Free(pNext); pNext = NULL; } MFThread_DestroyMutex(mutex); if(bOwnMemory) MFHeap_Free(pMemory); pMemory = NULL; }
MF_API void MFHeap_Free(void *pMem) { MFCALLSTACK; if(!pMem) { MFDebug_Warn(3, "Attemptd to Free 'NULL' pointer."); return; } MFThread_LockMutex(gAllocMutex); MFAllocHeader *pHeader = GetAllocHeader(pMem); MFDebug_Assert(MFHeap_ValidateMemory(pMem), MFStr("Memory corruption detected!!\n%s(" MFFMT_SIZE_T ")", pHeader->pFile, pHeader->line)); MFHeap *pHeap = pHeader->pHeap; #if !defined(_RETAIL) size_t extra; size_t allocBytes = GetAllocSize(pHeader->size, extra); pHeap->totalAllocated -= allocBytes; pHeap->totalWaste -= extra; --pHeap->allocCount; // MFDebug_Log(2, MFStr("Free: %p, %d bytes - %s:(%d)", pMem, pHeader->size, pHeader->pFile, (int)pHeader->line)); #endif MFCopyMemory((char*)pMem + pHeader->size, "freefreefreefree", MFHeap_MungwallBytes); #if defined(USE_PRE_MUNGWALL) MFCopyMemory((char*)pMem - MFHeap_MungwallBytes, "eerfeerfeerfeerf", MFHeap_MungwallBytes); #endif MFMemSet(pMem, 0xFE, pHeader->size); pHeap->pCallbacks->pFree((char*)pMem - pHeader->alignment, pHeap->pHeapData); #if defined(_USE_TRACKING_HASH_TABLE) FreeAlloc(pMem); #endif MFThread_ReleaseMutex(gAllocMutex); }
MF_API bool MFHeap_ValidateHeap() { #if defined(_USE_TRACKING_HASH_TABLE) MFThread_LockMutex(gAllocMutex); for(int i=0; i<MFHeap_AllocTableLength; ++i) { MFHeap_AllocItem *pI = gpAllocTable[i]; while(pI) { if(!MFHeap_ValidateMemory(pI->pMemory)) MFDebug_Assert(false, "Corrupt memory allocation!"); pI = pI->pNext; } } MFThread_ReleaseMutex(gAllocMutex); #endif return true; }
MF_API size_t MFInput_GetEvents(int device, int deviceID, MFInputEvent *pEvents, size_t maxEvents, bool bPeek) { MFThread_LockMutex(gInputMutex); uint32 toRead = 0; if(gNumEvents[device][deviceID] != 0) { toRead = MFMin((uint32)maxEvents, gNumEvents[device][deviceID] - gNumEventsRead[device][deviceID]); MFCopyMemory(pEvents, gInputEvents[device][deviceID] + gNumEventsRead[device][deviceID], sizeof(MFInputEvent)*toRead); if(!bPeek) { gNumEventsRead[device][deviceID] += toRead; if(gNumEventsRead[device][deviceID] == gNumEvents[device][deviceID]) gNumEvents[device][deviceID] = gNumEventsRead[device][deviceID] = 0; } } MFThread_ReleaseMutex(gInputMutex); return toRead; }
MF_API bool MFHeap_ValidateHeap() { #if defined(_USE_ALLOC_TRACKER) MFThread_LockMutex(gAllocMutex); if(gPoolInitialised) { int numAllocated = gAllocList.GetNumAllocated(); for(int a=0; a<numAllocated; ++a) { void *pMem = *(void**)gAllocList.GetItem(a); if(!MFHeap_ValidateMemory(pMem)) { MFDebug_Assert(false, "Corrupt memory allocation!"); return false; } } } MFThread_ReleaseMutex(gAllocMutex); #endif return true; }
MF_API void MFHeap_Free(void *pMem) { MFCALLSTACK; if(!pMem) { MFDebug_Warn(3, "Attemptd to Free 'NULL' pointer."); return; } MFAllocHeader *pHeader = &((MFAllocHeader*)pMem)[-1]; MFDebug_Assert(MFHeap_ValidateMemory(pMem), MFStr("Memory corruption detected!!\n%s(%d)", pHeader->pFile, pHeader->line)); MFThread_LockMutex(gAllocMutex); MFHeap *pHeap = pHeader->pHeap; if(pHeap->heapType != MFHT_Debug) { #if defined(_USE_TRACKING_HASH_TABLE) int hash = MFUtil_HashPointer(pMem) % MFHeap_AllocTableLength; MFHeap_AllocItem *pT = gpAllocTable[hash]; if(pT) { if(pT->pMemory == pMem) { gpAllocTable[hash] = pT->pNext; gAllocHeaderPool.Free(pT); } else { while(pT->pNext && pT->pNext->pMemory != pMem) pT = pT->pNext; if(pT->pNext) { MFHeap_AllocItem *pTN = pT->pNext; pT->pNext = pTN->pNext; gAllocHeaderPool.Free(pTN); } } } #endif #if defined(_USE_ALLOC_TRACKER) if(gPoolInitialised) { int numAllocs = gAllocList.GetNumAllocated(); for(int a=0; a<numAllocs; ++a) { void **ppAlloc = (void**)gAllocList.GetItem(a); if(*ppAlloc == pMem) { gAllocList.Free(ppAlloc); break; } } } #endif } #if !defined(_RETAIL) int pad = 0; while(pad < (int)sizeof(MFAllocHeader)) pad += heapAlignment; size_t extra = pad + sizeof(MFAllocHeader) + MFHeap_MungwallBytes; pHeap->totalAllocated -= pHeader->size + extra; pHeap->totalWaste -= extra; --pHeap->allocCount; // MFDebug_Log(2, MFStr("Free: %08X, %d bytes - %s:(%d)", pMem, pHeader->size, pHeader->pFile, (int)pHeader->line)); #endif MFHeap *pAllocHeap = pHeader->pHeap; MFCopyMemory((char*)pMem + pHeader->size, "freefreefreefree", MFHeap_MungwallBytes); MFCopyMemory((char*)pMem - 8, "freefreefreefree", MFHeap_MungwallBytes); MFMemSet(pMem, 0xFE, pHeader->size); pAllocHeap->pCallbacks->pFree((char*)pMem - pHeader->alignment, pAllocHeap->pHeapData); MFThread_ReleaseMutex(gAllocMutex); }
MF_API void *MFHeap_AllocInternal(size_t bytes, MFHeap *pHeap) { MFCALLSTACK; MFHeap *pAllocHeap = pOverrideHeap ? pOverrideHeap : (pHeap ? pHeap : pActiveHeap); int pad = 0; while(pad < (int)sizeof(MFAllocHeader)) pad += heapAlignment; size_t allocExtra = pad + sizeof(MFAllocHeader) + MFHeap_MungwallBytes; size_t allocBytes = bytes + allocExtra; MFThread_LockMutex(gAllocMutex); char *pMemory = (char*)pAllocHeap->pCallbacks->pMalloc(allocBytes, pAllocHeap->pHeapData); MFDebug_Assert(pMemory, "Failed to allocate memory!"); if(pMemory) { int alignment = (int)(MFALIGN(pMemory + sizeof(MFAllocHeader), heapAlignment) - (uintp)pMemory); pMemory += alignment; MFAllocHeader *pHeader = &((MFAllocHeader*)pMemory)[-1]; pHeader->alignment = (uint16)alignment; pHeader->pHeap = pAllocHeap; pHeader->size = (uint32)bytes; pHeader->pFile = gpMFHeap_TrackerFile; pHeader->line = (uint16)gMFHeap_TrackerLine; #if defined(USE_PRE_MUNGWALL) MFCopyMemory(pHeader->llawgnum, gLlawgnum, MFHeap_MungwallBytes); #endif if(pAllocHeap->heapType != MFHT_Debug) { #if defined(_USE_TRACKING_HASH_TABLE) MFHeap_AllocItem *pAlloc = (MFHeap_AllocItem*)gAllocHeaderPool.Alloc(); pAlloc->header.alignment = (uint16)alignment; pAlloc->header.pHeap = pAllocHeap; pAlloc->header.size = (uint32)bytes; pAlloc->header.pFile = gpMFHeap_TrackerFile; pAlloc->header.line = (uint16)gMFHeap_TrackerLine; pAlloc->pMemory = pMemory; int hash = MFUtil_HashPointer(pMemory) % MFHeap_AllocTableLength; pAlloc->pNext = gpAllocTable[hash]; gpAllocTable[hash] = pAlloc; #endif #if defined(_USE_ALLOC_TRACKER) if(gPoolInitialised) *(void**)gAllocList.Alloc() = pMemory; #endif } #if !defined(_RETAIL) MFCopyMemory(pMemory + bytes, gMungwall, MFHeap_MungwallBytes); pAllocHeap->totalAllocated += allocBytes; pAllocHeap->totalWaste += allocExtra; ++pAllocHeap->allocCount; // MFDebug_Log(2, MFStr("Alloc: %08X(%08X), %d bytes - %s:(%d)", pMemory, pMemory - pHeader->alignment, bytes, gpMFHeap_TrackerFile, gMFHeap_TrackerLine)); #endif } MFThread_ReleaseMutex(gAllocMutex); return (void*)pMemory; }