Wiley.Symbian.OS.Internals.Real.time.Kernel.Programming.Dec.2005.eBook-DDU (779891), страница 64
Текст из файла (страница 64)
Behind every call to the new and delete300MEMORY MODELSoperators in C++, or to the malloc() and free() functions in C, is anallocator. This object is concerned with taking the memory provided bythe OS, usually in multi-page sized blocks, and dividing it up so that anapplication can use smaller pieces of it in an efficient manner.7.5.2.1 Allocator APIsThe essential allocation support required for C++ and C is very similar,and in particular an allocator that supports standard C programs is goodenough to implement support for C++. The key services of an allocatorare just these three functions:malloc()operator new()Allocate and return a block of memory of at least therequested size in bytes, otherwise return NULL if therequest cannot be satisfied.
The allocator must ensurethat it meets the alignment requirements of all objecttypes. For example, the ABI for the ARM Architecturerequires 8-byte alignment.free()operator delete()Release a block of memory previously allocated usingmalloc() or realloc(). Following this call thememory block should not be used by the programagain.realloc()Grow or shrink a memory block previously allocatedusing malloc() or realloc(), preserving thecontents and return the newly reallocated block.
Notethat this could trivially be implemented usingmalloc(), memcpy() and free(), but someallocation schemes may be able to satisfy this request‘‘in place’’, thus avoiding the potentially expensivememory copy.The last of these functions is clearly optional, and has no parallel in theC++ allocation operators. Of course, C++ also allows the programmerto provide specialized allocation services for a class by over-ridingthe default implementation of operator new – perhaps to improveperformance, meet a strict alignment constraint, or to use a specific typeor part of the physical memory.This simple API does not describe the behavior of a free store allocatorwith multiple threads. The language standards do not define the behaviorin this situation because there would be a performance penalty to using athread-safe allocator in a single-threaded program.
Thus the question ofthread-safety is left to the implementation to determine. I will come backto how Symbian OS tackles this problem a little later.PROGRAMMER APIs3017.5.2.2 Allocator strategiesIf we examine the basic problem of dividing up pages of RAM intodifferent sized pieces, we find that there are several different techniquesfor structuring and dividing the memory for allocation, and differentalgorithms for selecting exactly which portion of memory will be used tosatisfy a particular allocation request.Different allocation techniques have different ways of organizing theirmemory and acquiring and releasing it from the operating system. InSymbian OS an allocator is most likely going to use a chunk to providethe lower-level allocation, and will pick the type of chunk that best fitsthe allocation strategy and usage pattern.
Here are some examples:• Many free store allocators – that is, those supporting operatornew() in C++ or malloc() and free() in C – assume that thestorage is a single contiguous address range, and that requests foradditional pages of memory extend the current committed memoryat the ‘‘top’’. We can implement these using a standard chunk.
Thestandard ‘‘heap’’ allocator in Symbian OS is one such allocator• Some memory managers for non-native programming systems, suchas Java, implement a handle/body system for objects – and effectivelyrequire two dynamically re-sizable contiguous memory regions. Wecan manage these two memory regions in a double-ended chunk,with one region growing upwards and the other downwards• More advanced allocators may not require fully contiguous memoryregions, and may also be able to release pages of memory back tothe OS when no longer used by the program. This may result inbetter overall memory use in the OS.
We use a disconnected chunkto support these.Why should we bother with so many possible choices of data structureand algorithm for allocators? The simple answer is that there is no ‘‘idealallocator’’. All allocator designs will favor some attributes over others.For example, some provide fast, real-time allocation but have a highmemory overhead; others have a minimal memory overhead, but havepoor worst-case performance.
Different applications may need differentallocators to meet their requirements.7.5.2.3 Allocators in Symbian OSWe realized that Symbian OS has to achieve two aims with the allocatorthat it provides:1. A good, general purpose allocator provided by default for all programs3022.MEMORY MODELSThe ability to customize or replace the default allocator for applications that have special requirements.EKA1 met the first of these needs with the RHeap allocator class. EKA2provides the same choice of default allocator, but now also meets thesecond need by providing an abstract allocator class. This is the definitionof MAllocator in e32cmn.h:class MAllocator{public:virtual TAny* Alloc(TInt)=0;virtual void Free(TAny*)=0;virtual TAny* ReAlloc(TAny*, TInt, TInt =0)=0;virtual TInt AllocLen(const TAny*) const =0;virtual TInt Compress()=0;virtual void Reset()=0;virtual TInt AllocSize(TInt&) const =0;virtual TInt Available(TInt&) const =0;virtual TInt DebugFunction(TInt, TAny*, TAny*)=0;};The first three members are the basic allocator API that I describedearlier.
The OS expects several other services from the allocator, as Idescribe in the following table:Alloc()Basic allocation function, foundation for malloc() andsimilar allocator functions.Free()Basic de-allocation function, basis for free(), etc.ReAlloc()Reallocation function, basis for realloc().There is an optional third parameter, to control allocatorbehavior in certain situations. This enables an allocator toprovide compatibility with programs that may incorrectlyassume that all allocators behave like the originalRHeap::ReAlloc() function.AllocLen()Return the allocated length for the memory block.
This isalways at least as much as the memory requested, but issometimes significantly larger.Compress()Release any unused pages of memory back to the OS, ifpossible.This function is deprecated, but retained for EKA1compatibility. Allocators for EKA2 are expected to do thisautomatically as a side effect of Free() rather than waitfor an explicit request.PROGRAMMER APIs303Reset()Release all allocated memory – effectively equivalent toFree() on all allocated blocks.AllocSize()Returns the number of blocks and the number of bytescurrently allocated in this allocator.Available()Returns the number of bytes in this allocator that areunused and the largest allocation that would succeedwithout requesting more pages of memory from the OS.DebugFunction()Provide support for additional diagnostics, instrumentationand forced failure of the allocator, typically implementedonly in a debug build of Symbian OS.In practice, however, a concrete allocator will derive from the RAllocator class.
This is the class that defines the full behavior expected by thefree store API in Symbian OS. It provides commonly used additional functionality to the allocator, such as support for calling User::Leave() onallocation failure, rather than returning NULL. It also defines the forcedfailure support expected by Symbian OS.Here is the RAllocator class as defined in e32cmn.h:class RAllocator : public MAllocator{public:enum TAllocFail{ERandom,ETrueRandom,ENone,EFailNext,EReset};enum TDbgHeapType { EUser, EKernel };enum TAllocDebugOp {ECount, EMarkStart, EMarkEnd,ECheck, ESetFail, ECopyDebugInfo};enum TReAllocMode{ENeverMove=1,EAllowMoveOnShrink=2};enum TFlags {ESingleThreaded=1, EFixedSize=2};enum {EMaxHandles=32};public:inline RAllocator();TInt Open();void Close();TAny* AllocZ(TInt);TAny* AllocZL(TInt);TAny* AllocL(TInt);TAny* AllocLC(TInt);304MEMORY MODELSvoid FreeZ(TAny*&);TAny* ReAllocL(TAny*, TInt, TInt=0);TInt Count() const;TInt Count(TInt&) const;void Check() const;void __DbgMarkStart();TUint32 __DbgMarkEnd(TInt);TInt __DbgMarkCheck(TBool, TInt, const TDesC8&, TInt);void __DbgMarkCheck(TBool, TInt, const TUint8*, TInt);void __DbgSetAllocFail(TAllocFail, TInt);protected:virtual void DoClose();protected:TInt iAccessCount;TInt iHandleCount;TInt* iHandles;TUint32 iFlags;TInt iCellCount;TInt iTotalAllocSize;};We are still a step or two away from the APIs that programmerstypically use to allocate memory.
Symbian OS implements the standardC and C++ allocation functions using static members of the User class:malloc()operator new()User::Alloc()free()User::Free()operator delete()realloc()User::ReAlloc()These User functions need to identify an allocator object to pass onthe requests. The User::Allocator() function provides this service,returning a reference to the RAllocator object that is designated as thecalling thread’s current allocator.The User class provides more functions related to manipulating andaccessing the current allocator.