kernel/eka/common/alloc.cpp
changeset 0 a41df078684a
child 43 c1f20ce4abcf
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32\common\alloc.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "common.h"
       
    19 #include <e32atomics.h>
       
    20 
       
    21 
       
    22 
       
    23 #ifndef __KERNEL_MODE__
       
    24 /**
       
    25 Opens this heap for shared access.
       
    26 
       
    27 Opening the heap increases the heap's access count by one.
       
    28 
       
    29 @return KErrNone if successful;
       
    30         KErrGeneral, if the original valeu of the access count
       
    31         was not positive.
       
    32 */
       
    33 EXPORT_C TInt RAllocator::Open()
       
    34 	{
       
    35 	TInt c = __e32_atomic_tas_ord32(&iAccessCount, 1, 1, 0);
       
    36 	return (c>0) ? KErrNone : KErrGeneral;
       
    37 	}
       
    38 
       
    39 
       
    40 
       
    41 
       
    42 /**
       
    43 Closes this shared heap.
       
    44 
       
    45 Closing the heap decreases the heap's access count by one.
       
    46 
       
    47 @panic USER 57 if the access count has already reached zero.
       
    48 */
       
    49 EXPORT_C void RAllocator::Close()
       
    50 	{
       
    51 	TInt count = __e32_atomic_tas_ord32(&iAccessCount, 1, -1, 0);
       
    52 	__ASSERT_ALWAYS(count>0, Panic(EAllocatorClosedTooManyTimes));
       
    53 	if (count==1)
       
    54 		DoClose();
       
    55 	}
       
    56 
       
    57 
       
    58 
       
    59 /**
       
    60 @internalComponent
       
    61 */
       
    62 EXPORT_C void RAllocator::DoClose()
       
    63 	{
       
    64 	__ASSERT_ALWAYS(TUint32(iHandleCount)<=TUint32(EMaxHandles), Panic(EAllocatorBadHandleCount));
       
    65 	TInt handle[EMaxHandles];
       
    66 	TInt c = iHandleCount;
       
    67 	wordmove(handle, iHandles, c*sizeof(TInt));
       
    68 	memclr(iHandles, c*sizeof(TInt));
       
    69 	TInt* pH = handle;
       
    70 	TInt* pE = pH + c;
       
    71 	while (pH<pE)
       
    72 		{
       
    73 		RHandleBase h;
       
    74 		h.SetHandle(*pH++);
       
    75 		h.Close();
       
    76 		}
       
    77 	}
       
    78 
       
    79 
       
    80 
       
    81 
       
    82 /**
       
    83 Allocates a cell of specified size from the heap, and clears
       
    84 it to binary zeroes.
       
    85 
       
    86 If there is insufficient memory available on the heap from which to
       
    87 allocate a cell of the required size, the function returns NULL.
       
    88 
       
    89 The resulting size of the allocated cell may be rounded up to a value greater 
       
    90 than aSize, but is guaranteed to be not less than aSize.
       
    91 
       
    92 @param aSize The size of the cell to be allocated from the current thread's 
       
    93              heap.
       
    94              
       
    95 @return A pointer to the allocated cell. NULL, if there is insufficient memory 
       
    96         available.
       
    97         
       
    98 @panic USER 47  if the maximum unsigned value of aSize is greater
       
    99                 than or equal to KMaxTInt/2. For example,
       
   100                 calling Alloc(-1) raises this panic.
       
   101 */
       
   102 EXPORT_C TAny* RAllocator::AllocZ(TInt aSize)
       
   103 	{
       
   104 	TAny* p = Alloc(aSize);
       
   105 	if (p)
       
   106 		Mem::FillZ(p, aSize);
       
   107 	return p;
       
   108 	}
       
   109 
       
   110 
       
   111 
       
   112 
       
   113 /**
       
   114 Allocates a cell of specified size from the heap, clears it to
       
   115 binary zeroes, and leaves if there is insufficient memory in the heap.
       
   116 
       
   117 The resulting size of the allocated cell may be rounded up to a value greater 
       
   118 than aSize, but is guaranteed to be not less than aSize.
       
   119 
       
   120 @param aSize The size of the cell to be allocated from the heap.
       
   121 
       
   122 @return A pointer to the allocated cell.
       
   123  
       
   124 @panic USER 47  if the maximum unsigned value of aSize is greater
       
   125                 than or equal to KMaxTInt/2. For example,
       
   126                 calling Alloc(-1) raises this panic.
       
   127 */
       
   128 EXPORT_C TAny* RAllocator::AllocZL(TInt aSize)
       
   129 	{
       
   130 	TAny* p = AllocL(aSize);
       
   131 	Mem::FillZ(p, aSize);
       
   132 	return p;
       
   133 	}
       
   134 
       
   135 
       
   136 
       
   137 
       
   138 /**
       
   139 Allocates a cell of specified size from the heap, and leaves 
       
   140 if there is insufficient memory in the heap.
       
   141 
       
   142 The resulting size of the allocated cell may be rounded up to a value greater 
       
   143 than aSize, but is guaranteed to be not less than aSize.
       
   144 
       
   145 @param aSize The size of the cell to be allocated from the heap.
       
   146 
       
   147 @return A pointer to the allocated cell.
       
   148 
       
   149 @panic USER 47  if the maximum unsigned value of aSize is greater
       
   150                 than or equal to KMaxTInt/2. For example,
       
   151                 calling Alloc(-1) raises this panic.
       
   152 */
       
   153 EXPORT_C TAny* RAllocator::AllocL(TInt aSize)
       
   154 	{
       
   155 	TAny* p = Alloc(aSize);
       
   156 	if (!p)
       
   157 		User::LeaveNoMemory();
       
   158 	return p;
       
   159 	}
       
   160 
       
   161 
       
   162 
       
   163 
       
   164 /**
       
   165 Allocates a cell of specified size from the heap, and,
       
   166 if successful, places a pointer to the cell onto the cleanup stack.
       
   167 
       
   168 The function leaves if there is insufficient memory in the heap.
       
   169 
       
   170 The resulting size of the allocated cell may be rounded up to a value greater 
       
   171 than aSize, but is guaranteed to be not less than aSize.
       
   172 
       
   173 @param aSize The size of the cell to be allocated from the heap.
       
   174              
       
   175 @return A pointer to the allocated cell.
       
   176 
       
   177 @panic USER 47  if the maximum unsigned value of aSize is greater
       
   178                 than or equal to KMaxTInt/2. For example,
       
   179                 calling Alloc(-1) raises this panic.
       
   180 */
       
   181 EXPORT_C TAny* RAllocator::AllocLC(TInt aSize)
       
   182 	{
       
   183 	TAny* p = AllocL(aSize);
       
   184 	CleanupStack::PushL(p);
       
   185 	return p;
       
   186 	}
       
   187 
       
   188 
       
   189 
       
   190 
       
   191 /**
       
   192 Frees the specified cell, returns it to the heap, and resets 
       
   193 the pointer to NULL.
       
   194 
       
   195 @param aCell A reference to a pointer to a valid cell to be freed. If NULL 
       
   196              this function call will be ignored.
       
   197              
       
   198 @panic USER 42  if aCell is not NULL and does not point to a valid cell.             
       
   199 */
       
   200 EXPORT_C void RAllocator::FreeZ(TAny*& aCell)
       
   201 	{
       
   202 	Free(aCell);
       
   203 	aCell = NULL;
       
   204 	}
       
   205 
       
   206 
       
   207 
       
   208 
       
   209 /**
       
   210 Increases or decreases the size of an existing cell, and leaves 
       
   211 if there is insufficient memory in the heap.
       
   212 
       
   213 If the cell is being decreased in size, then it is guaranteed not to move,
       
   214 and the function returns the pointer originally passed in aCell. Note that the
       
   215 length of the cell will be the same if the difference between the old size
       
   216 and the new size is smaller than the minimum cell size.
       
   217 
       
   218 If the cell is being increased in size, i.e. aSize is bigger than its
       
   219 current size, then the function tries to grow the cell in place.
       
   220 If successful, then the function returns the pointer originally
       
   221 passed in aCell. If unsuccessful, then:
       
   222 
       
   223 1. if the cell cannot be moved, i.e. aMode has the ENeverMove bit set, then
       
   224    the function leaves.
       
   225 2. if the cell can be moved, i.e. aMode does not have the ENeverMove bit set,
       
   226    then the function tries to allocate a new replacement cell, and, if
       
   227    successful, returns a pointer to the new cell; if unsuccessful, it
       
   228    leaves.
       
   229 
       
   230 Note that in debug mode, the function leaves if the cell cannot be grown
       
   231 in place, regardless of whether the ENeverMove bit is set.
       
   232 
       
   233 If the reallocated cell is at a different location from the original cell, then
       
   234 the content of the original cell is copied to the reallocated cell.
       
   235 
       
   236 Note the following general points:
       
   237 
       
   238 1. If reallocation fails, the content of the original cell is preserved.
       
   239 
       
   240 2. The resulting size of the re-allocated cell may be rounded up to a value
       
   241    greater than aSize, but is guaranteed to be not less than aSize.
       
   242 
       
   243 @param aCell A pointer to the cell to be reallocated. This may be NULL.
       
   244 
       
   245 @param aSize The new size of the cell. This may be bigger or smaller than the
       
   246              size of the original cell.
       
   247              
       
   248 @param aMode Flags controlling the reallocation. The only bit which has any
       
   249              effect on this function is that defined by the enumeration
       
   250              ENeverMove of the enum RAllocator::TReAllocMode.
       
   251              If this is set, then any successful reallocation guarantees not
       
   252              to have changed the start address of the cell.
       
   253              By default, this parameter is zero.
       
   254 
       
   255 @return A pointer to the reallocated cell. This may be the same as the original
       
   256         pointer supplied through aCell.
       
   257 
       
   258 @panic USER 42, if aCell is not NULL, and does not point to a valid cell.
       
   259 @panic USER 47, if the maximum unsigned value of aSize is greater
       
   260                 than or equal to KMaxTInt/2. For example,
       
   261                 calling ReAlloc(someptr,-1) raises this panic.
       
   262 
       
   263 @see RAllocator::TReAllocMode
       
   264 */
       
   265 EXPORT_C TAny* RAllocator::ReAllocL(TAny* aCell, TInt aSize, TInt aMode)
       
   266 	{
       
   267 	TAny* p = ReAlloc(aCell, aSize, aMode);
       
   268 	if (!p)
       
   269 		User::LeaveNoMemory();
       
   270 	return p;
       
   271 	}
       
   272 
       
   273 
       
   274 
       
   275 
       
   276 /**
       
   277 Gets the total number of cells allocated on the heap.
       
   278 
       
   279 @return The number of cells allocated on the heap.
       
   280 */
       
   281 EXPORT_C TInt RAllocator::Count() const
       
   282 	{
       
   283 	return iCellCount;
       
   284 	}
       
   285 
       
   286 
       
   287 
       
   288 
       
   289 /**
       
   290 Gets the the total number of cells allocated, and the number of free cells, 
       
   291 on the heap.
       
   292 
       
   293 @param aFreeCount On return, contains the number of free cells 
       
   294                   on the heap.
       
   295 
       
   296 @return The number of cells allocated on the heap.
       
   297 */
       
   298 EXPORT_C TInt RAllocator::Count(TInt& aFreeCount) const
       
   299 	{
       
   300 	return ((RAllocator*)this)->DebugFunction(ECount, &aFreeCount);
       
   301 	}
       
   302 #endif
       
   303 
       
   304 
       
   305 
       
   306 
       
   307 /**
       
   308 Checks the validity of the heap.
       
   309 
       
   310 The function walks through the list of allocated cells and the list of
       
   311 free cells checking that this heap is consistent and complete.
       
   312 
       
   313 @panic USER 47 if any corruption is found, specifically	a bad allocated
       
   314                heap cell size.
       
   315 @panic USER 48 if any corruption is found, specifically a bad allocated
       
   316                heap cell address.
       
   317 @panic USER 49 if any corruption is found, specifically a bad free heap
       
   318                cell address.
       
   319 */
       
   320 UEXPORT_C void RAllocator::Check() const
       
   321 	{
       
   322 	((RAllocator*)this)->DebugFunction(ECheck);
       
   323 	}
       
   324 
       
   325 
       
   326 
       
   327 
       
   328 /**
       
   329 Marks the start of heap cell checking for this heap.
       
   330 
       
   331 If earlier calls to __DbgMarkStart() have been made, then this call
       
   332 to __DbgMarkStart() marks the start of a new nested level of
       
   333 heap cell checking.
       
   334 
       
   335 Every call to __DbgMarkStart() should be matched by a later call
       
   336 to __DbgMarkEnd() to verify that the number of heap cells allocated,
       
   337 at the current nested level, is as expected. This expected number of heap cells
       
   338 is passed to __DbgMarkEnd() as a parameter; however, the most common expected
       
   339 number is zero, reflecting the fact that most developers check that all memory
       
   340 allocated since a previous call to __DbgMarkStart() has been freed.
       
   341 
       
   342 @see RAllocator::__DbgMarkEnd()
       
   343 */
       
   344 UEXPORT_C void RAllocator::__DbgMarkStart()
       
   345 	{
       
   346 	DebugFunction(EMarkStart);
       
   347 	}
       
   348 
       
   349 
       
   350 
       
   351 
       
   352 /**
       
   353 Marks the end of heap cell checking at the current nested level for this heap.
       
   354 
       
   355 A call to this function should match an earlier call to __DbgMarkStart().
       
   356 If there are more calls to this function than calls to __DbgMarkStart(),
       
   357 then this function raises a USER 51 panic.
       
   358 
       
   359 The function checks that the number of heap cells allocated, at the current
       
   360 nested level, is aCount. The most common value for aCount is zero, reflecting
       
   361 the fact that most developers check that all memory allocated since a previous
       
   362 call to __DbgMarkStart() has been freed.
       
   363 
       
   364 If the check fails, the function returns a pointer to the first orphaned
       
   365 heap cell.
       
   366 
       
   367 @param aCount The number of allocated heap cells expected.
       
   368 
       
   369 @return A pointer to the first orphaned heap cell, if verification fails;
       
   370         zero otherwise.
       
   371 
       
   372 @see RAllocator::__DbgMarkStart()
       
   373 */
       
   374 UEXPORT_C TUint32 RAllocator::__DbgMarkEnd(TInt aCount)
       
   375 	{
       
   376 	return DebugFunction(EMarkEnd, (TAny*)aCount);
       
   377 	}
       
   378 
       
   379 
       
   380 
       
   381 
       
   382 /**
       
   383 Checks the current number of allocated heap cells for this heap.
       
   384 
       
   385 If aCountAll is true, the function checks that the total number of allocated
       
   386 cells on this heap is the same as aCount. If aCountAll is false, then
       
   387 the function checks that the number of allocated cells at the current nested
       
   388 level is the same as aCount.
       
   389 
       
   390 If checking fails, the function raises a panic;
       
   391 information about the failure is put into the panic category;
       
   392 this takes the form:
       
   393 
       
   394 ALLOC COUNT\\rExpected aaa\\rAllocated bbb\\rLn: ccc ddddd
       
   395 
       
   396 where
       
   397 
       
   398 1. aaaa is the value aCount
       
   399 
       
   400 2. bbbb is the number of allocated heap cells
       
   401 
       
   402 3. ccc is a line number, copied from aLineNum
       
   403 
       
   404 4. ddddd is a file name, copied from the descriptor aFileName
       
   405 
       
   406 Note that the panic number is 1.
       
   407 
       
   408 @param aCountAll If true, the function checks that the total number of
       
   409                  allocated cells on this heap is the same as aCount.
       
   410                  If false, the function checks that the number of allocated
       
   411                  cells at the current nested level is the same as aCount.
       
   412 @param aCount    The expected number of allocated cells.
       
   413 @param aFileName A filename; this is displayed as part of the panic
       
   414                  category if the check fails.
       
   415 @param aLineNum  A line number; this is displayed as part of the panic category 
       
   416                  if the check fails.
       
   417 
       
   418 @return KErrNone, if successful; otherwise one of the other system wide error codes.
       
   419 */
       
   420 UEXPORT_C TInt RAllocator::__DbgMarkCheck(TBool aCountAll, TInt aCount, const TDesC8& aFileName, TInt aLineNum)
       
   421 	{
       
   422 	SCheckInfo info;
       
   423 	info.iAll = aCountAll;
       
   424 	info.iCount = aCount;
       
   425 	info.iFileName = &aFileName;
       
   426 	info.iLineNum = aLineNum;
       
   427 	return DebugFunction(ECheck, &info);
       
   428 	}
       
   429 
       
   430 
       
   431 
       
   432 
       
   433 /**
       
   434 Simulates a heap allocation failure for this heap.
       
   435 
       
   436 The failure occurs on subsequent calls to new or any of the functions which
       
   437 allocate memory from this heap.
       
   438 
       
   439 The timing of the allocation failure depends on the type of 
       
   440 allocation failure requested, i.e. on the value of aType.
       
   441 
       
   442 The simulation of heap allocation failure is cancelled
       
   443 if aType is given the value RAllocator::ENone.
       
   444 
       
   445 Notes:
       
   446 
       
   447 1. If the failure type is RAllocator::EFailNext, the next attempt to allocate from
       
   448    this heap fails; however, no further failures will occur.
       
   449 
       
   450 2. For failure types RAllocator::EFailNext and RAllocator::ENone, set aRate to 1.
       
   451 
       
   452 @param aType  An enumeration which indicates how to simulate heap
       
   453               allocation failure.
       
   454 @param aRate The rate of failure; when aType is RAllocator::EDeterministic,
       
   455               heap allocation fails every aRate attempts
       
   456 */
       
   457 UEXPORT_C void RAllocator::__DbgSetAllocFail(TAllocFail aType, TInt aRate)
       
   458 	{
       
   459 	DebugFunction(ESetFail, (TAny*)aType, (TAny*)aRate);
       
   460 	}
       
   461 
       
   462 
       
   463 /**
       
   464 Simulates a burst of heap allocation failures for this heap.
       
   465 
       
   466 The failure occurs for aBurst allocations attempt via subsequent calls 
       
   467 to new or any of the functions which allocate memory from this heap.
       
   468 
       
   469 The timing of the allocation failure depends on the type of 
       
   470 allocation failure requested, i.e. on the value of aType.
       
   471 
       
   472 The simulation of heap allocation failure is cancelled
       
   473 if aType is given the value RAllocator::ENone.
       
   474 
       
   475 Notes:
       
   476 
       
   477 1. If the failure type is RAllocator::EFailNext or RAllocator::EBurstFailNext, 
       
   478 the next one or aBurst attempts to allocate from this heap will fail; 
       
   479 however, no further failures will occur.
       
   480 
       
   481 2. For failure types RAllocator::EFailNext and RAllocator::ENone, set aRate to 1.
       
   482 
       
   483 @param aType  An enumeration which indicates how to simulate heap
       
   484               allocation failure.
       
   485 @param aRate The rate of failure; when aType is RAllocator::EDeterministic,
       
   486               heap allocation fails every aRate attempts.
       
   487 @param aBurst The number of consecutive heap allocations that will fail each
       
   488 time the allocations should fail.
       
   489 
       
   490 @see RAllocator::TAllocFail
       
   491 */
       
   492 UEXPORT_C void RAllocator::__DbgSetBurstAllocFail(TAllocFail aType, TUint aRate, TUint aBurst)
       
   493 	{
       
   494 	SRAllocatorBurstFail burstFail;
       
   495 	burstFail.iRate = aRate;
       
   496 	burstFail.iBurst = aBurst;
       
   497 	DebugFunction(ESetBurstFail, (TAny*)aType, (TAny*)&burstFail);
       
   498 	}
       
   499 
       
   500 /**
       
   501 Returns the number of heap allocation failures the current debug allocator fail
       
   502 function has caused so far.
       
   503 
       
   504 This is intended to only be used with fail types RAllocator::EFailNext,
       
   505 RAllocator::EBurstFailNext, RAllocator::EDeterministic and
       
   506 RAllocator::EBurstDeterministic.  The return value is unreliable for 
       
   507 all other fail types.
       
   508 
       
   509 @return The number of heap allocation failures the current debug fail 
       
   510 function has caused.
       
   511 
       
   512 @see RAllocator::TAllocFail
       
   513 */
       
   514 UEXPORT_C TUint RAllocator::__DbgCheckFailure()
       
   515 	{
       
   516 	return DebugFunction(ECheckFailure);
       
   517 	}
       
   518 
       
   519 
       
   520 UEXPORT_C TInt RAllocator::Extension_(TUint, TAny*& a0, TAny*)
       
   521 	{
       
   522 	a0 = NULL;
       
   523 	return KErrExtensionNotSupported;
       
   524 	}