void* SmallMemoryAlloc::allocate(size_t size) { size_t idx = ChunkIndex(size); ACCHECK(idx < CST_CHUNK_NUMBER); //锁指定大小的内存池 ThreadGuard guard(&m_vtGuard[idx]); SMemoryList* &temp = m_vtFreeList[idx]; if (!temp) { //内存池空,分配一个新的chunk做内存池 SMemoryList* newChunk=AllocChunk(idx); SChunkList* chunkNode; //此处chunkNode也通过Memory分配器分配内存 if(ChunkIndex(sizeof(SChunkList)) == idx) { chunkNode = reinterpret_cast<SChunkList *>(temp); temp = temp->m_pNext; } else { chunkNode = reinterpret_cast<SChunkList *>(allocate(sizeof(SChunkList))); } ThreadGuard guard(&m_nChunkGuard); //将新分配出来的chunk链接到chunk链表表头 chunkNode->m_pNext = m_pChunkList; chunkNode->m_pData = newChunk; m_pChunkList = chunkNode; } //从内存池中取出一个内存 void* ret = temp; temp = temp->m_pNext; return ret; }
void SmallMemoryAlloc::deallocate(void* p, size_t size) { //得到该对象大小对应的内存池 size_t idx = ChunkIndex(size); ACCHECK(idx < CST_CHUNK_NUMBER); SMemoryList* freeBlock = reinterpret_cast<SMemoryList *>(p); ThreadGuard guard(&m_vtGuard[idx]); //释放的对象的内存链接到内存池链表表头 SMemoryList* &temp = m_vtFreeList[idx]; freeBlock->m_pNext = temp; temp = freeBlock; }
TUint8* DMemModelProcess::DataSectionBase(DMemModelChunk* aChunk) { // this can't be called after $LOCK is deleted Kern::MutexWait(*iProcessLock); TInt pos=0; TInt r=ChunkIndex(aChunk,pos); if (r==0) // Found the chunk { TUint8* answer=((TUint8*)iChunks[pos].iDataSectionBase); __KTRACE_OPT(KPROC,Kern::Printf("DMemModelProcess::DataSectionBase %x",answer)); Kern::MutexSignal(*iProcessLock); return answer; } __KTRACE_OPT(KPROC,Kern::Printf("DMemModelProcess::DataSectionBase chunk %08x not present in %08x",aChunk,this)); Kern::MutexSignal(*iProcessLock); return(NULL); }
void DMemModelProcess::RemoveChunk(DMemModelChunk *aChunk) { // note that this can't be called after the process $LOCK mutex has been deleted // since it can only be called by a thread in this process doing a handle close or // dying, or by the process handles array being deleted due to the process dying, // all of which happen before $LOCK is deleted. __KTRACE_OPT(KPROC,Kern::Printf("DMemModelProcess %O RemoveChunk %O",this,aChunk)); Kern::MutexWait(*iProcessLock); TInt i = ChunkIndex(aChunk); if(i>=0) // Found the chunk { __KTRACE_OPT(KPROC,Kern::Printf("Chunk access count %d",iChunks[i].iAccessCount)); if(--iChunks[i].iAccessCount==0) { DoRemoveChunk(i); } } Kern::MutexSignal(*iProcessLock); }
void DMemModelProcess::RemoveChunk(DMemModelChunk *aChunk) { // note that this can't be called after the process $LOCK mutex has been deleted // since it can only be called by a thread in this process doing a handle close or // dying, or by the process handles array being deleted due to the process dying, // all of which happen before $LOCK is deleted. __KTRACE_OPT(KPROC,Kern::Printf("DMemModelProcess::RemoveChunk %08x from %08x",aChunk,this)); Kern::MutexWait(*iProcessLock); TInt pos=0; TInt r=ChunkIndex(aChunk,pos); __KTRACE_OPT(KPROC,if(r) Kern::Printf("Chunk lookup failed with %d",r)); if (r==0) // Found the chunk { __KTRACE_OPT(KPROC,Kern::Printf("Chunk access count %d",iChunks[pos].iAccessCount)); if (--iChunks[pos].iAccessCount==0) DoRemoveChunk(pos); } Kern::MutexSignal(*iProcessLock); }
TInt DMemModelProcess::AddChunk(DChunk* aChunk,TBool isReadOnly) { DMemModelChunk* pC=(DMemModelChunk*)aChunk; TInt r=WaitProcessLock(); if (r==KErrNone) { TInt pos=0; r=ChunkIndex(pC,pos); TLinAddr dataSectionBase=0; if (r==0) // Found the chunk in this process, just up its count { iChunks[pos].iAccessCount++; __KTRACE_OPT(KPROC,Kern::Printf("DMemModelProcess::AddChunk %08x to %08x (Access count incremented to %d)",aChunk,this,iChunks[pos].iAccessCount)); SignalProcessLock(); return KErrNone; } r=AddChunk(pC,dataSectionBase,isReadOnly); SignalProcessLock(); } __KTRACE_OPT(KPROC,Kern::Printf("DMemModelProcess::AddChunk returns %d",r)); return r; }
TInt DMemModelProcess::AddChunk(DChunk* aChunk, TBool aIsReadOnly) { DMemModelChunk* pC=(DMemModelChunk*)aChunk; if(pC->iOwningProcess && this!=pC->iOwningProcess) return KErrAccessDenied; TInt r = WaitProcessLock(); if(r==KErrNone) { TInt i = ChunkIndex(pC); if(i>=0) // Found the chunk in this process, just up its count { iChunks[i].iAccessCount++; __KTRACE_OPT(KPROC,Kern::Printf("DMemModelProcess::AddChunk %08x to %08x (Access count incremented to %d)",aChunk,this,iChunks[i].iAccessCount)); SignalProcessLock(); return KErrNone; } r = DoAddChunk(pC,aIsReadOnly); SignalProcessLock(); } __KTRACE_OPT(KPROC,Kern::Printf("DMemModelProcess::AddChunk returns %d",r)); return r; }
TInt DMemModelProcess::DoAddChunk(DMemModelChunk* aChunk, TBool aIsReadOnly) { // // Must hold the process $LOCK mutex before calling this. // As the process lock is held it is safe to access iOsAsid without a reference. // __NK_ASSERT_DEBUG(ChunkIndex(aChunk)==KErrNotFound); // shouldn't be adding a chunk which is already added __KTRACE_OPT(KPROC,Kern::Printf("DMemModelProcess::DoAddChunk %O to %O",aChunk,this)); // create mapping for chunk... DMemoryMapping* mapping; TMappingPermissions perm = MM::MappingPermissions ( iOsAsid!=(TInt)KKernelOsAsid, // user? aIsReadOnly==false, // write? aChunk->iAttributes&DMemModelChunk::ECode // execute? ); TInt r; if(aChunk->iFixedBase) // HACK, kernel chunk has a fixed iBase r = MM::MappingNew(mapping,aChunk->iMemoryObject,perm,iOsAsid,EMappingCreateExactVirtual,(TLinAddr)aChunk->iFixedBase); else r = MM::MappingNew(mapping,aChunk->iMemoryObject,perm,iOsAsid); if(r!=KErrNone) return r; if(iOsAsid==0) aChunk->iKernelMapping = mapping; TLinAddr base = MM::MappingBase(mapping); // expand chunk info memory if required... if(iChunkCount==iChunkAlloc) { TInt newAlloc = iChunkAlloc+KChunkGranularity; r = Kern::SafeReAlloc((TAny*&)iChunks,iChunkAlloc*sizeof(SChunkInfo),newAlloc*sizeof(SChunkInfo)); if(r!=KErrNone) { MM::MappingDestroy(mapping); return r; } iChunkAlloc = newAlloc; } // insert new chunk info... TUint i = ChunkInsertIndex(aChunk); SChunkInfo* info = iChunks+i; SChunkInfo* infoEnd = iChunks+iChunkCount; NKern::LockSystem(); ++iChunkCount; for(;;) { // make space for new chunk info by shuffling along // existing infos KMaxChunkInfosInOneGo at a time... SChunkInfo* infoPtr = infoEnd-KMaxChunkInfosInOneGo; if(infoPtr<info) infoPtr = info; memmove(infoPtr+1,infoPtr,(TLinAddr)infoEnd-(TLinAddr)infoPtr); infoEnd = infoPtr; if(infoEnd<=info) break; NKern::FlashSystem(); } info->iChunk = aChunk; info->iMapping = mapping; info->iAccessCount = 1; info->iIsReadOnly = aIsReadOnly; NKern::UnlockSystem(); // add chunk to list of Shared Chunks... if(aChunk->iChunkType==ESharedKernelSingle || aChunk->iChunkType==ESharedKernelMultiple) { if(!iSharedChunks) iSharedChunks = new RAddressedContainer(&TheSharedChunkLock,iProcessLock); if(!iSharedChunks) r = KErrNoMemory; else r = iSharedChunks->Add(base,aChunk); if(r!=KErrNone) { DoRemoveChunk(i); return r; } } // done OK... __DEBUG_EVENT(EEventUpdateProcess, this); return KErrNone; }