| author | Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> | 
| Tue, 25 May 2010 14:09:55 +0300 | |
| branch | RCL_3 | 
| changeset 28 | 5b5d147c7838 | 
| parent 26 | c734af59ce98 | 
| permissions | -rw-r--r-- | 
| 0 | 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\klib\bma.cpp | |
| 15 | // This file is directly included in the test harness t_tbma | |
| 16 | // | |
| 17 | // | |
| 18 | ||
| 19 | #include <kernel/kbma.h> | |
| 20 | ||
| 21 | #ifdef TBMA_TEST_CODE | |
| 22 | ||
| 23 | #ifdef __MARM__ | |
| 24 | #define __TBMA_MACHINE_CODED__ | |
| 25 | #endif | |
| 26 | ||
| 27 | #include <e32std.h> | |
| 28 | #include <e32std_private.h> | |
| 29 | #include <e32atomics.h> | |
| 30 | ||
| 31 | #define __ALLOC(x) User::Alloc(x) | |
| 32 | ||
| 33 | void TBmaFault(TInt aLine) | |
| 34 | 	{
 | |
| 35 | 	User::Panic(_L("TBMA"),aLine);
 | |
| 36 | } | |
| 37 | ||
| 38 | #else | |
| 39 | ||
| 40 | #include <kernel/kern_priv.h> | |
| 41 | ||
| 42 | #define __ALLOC(x) Kern::Alloc(x) | |
| 43 | ||
| 44 | void TBmaFault(TInt aLine) | |
| 45 | 	{
 | |
| 46 | 	Kern::Fault("TBMA",aLine);
 | |
| 47 | } | |
| 48 | ||
| 49 | #endif | |
| 50 | ||
| 51 | #define TBMA_FAULT() TBmaFault(__LINE__) | |
| 52 | ||
| 53 | /** Creates a new TBitMapAllocator object. | |
| 54 | ||
| 55 | @param aSize The number of bit positions required, must be >0. | |
| 56 | @param aState TRUE if all bit positions initially free | |
| 57 | FALSE if all bit positions initially allocated. | |
| 58 | ||
| 59 | @return Pointer to new object, NULL if out of memory. | |
| 60 | ||
| 61 | @pre Calling thread must be in a critical section. | |
| 62 | @pre No fast mutex can be held. | |
| 63 | @pre Call in a thread context. | |
| 64 | @pre Interrupts must be enabled. | |
| 65 | @pre Kernel must be unlocked. | |
| 66 | */ | |
| 67 | EXPORT_C TBitMapAllocator* TBitMapAllocator::New(TInt aSize, TBool aState) | |
| 68 | 	{
 | |
| 69 | #ifndef TBMA_TEST_CODE | |
| 70 | CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"TBitMapAllocator::New"); | |
| 71 | #endif | |
| 72 | TInt nmapw=(aSize+31)>>5; | |
| 73 | TInt memsz=sizeof(TBitMapAllocator)+(nmapw-1)*sizeof(TUint32); | |
| 74 | TBitMapAllocator* pA=(TBitMapAllocator*)__ALLOC(memsz); | |
| 75 | if (pA) | |
| 76 | new(pA) TBitMapAllocator(aSize, aState); | |
| 77 | return pA; | |
| 78 | } | |
| 79 | ||
| 80 | ||
| 81 | /** Finds a set of consecutive bit positions with specified alignment, with | |
| 82 | support for chaining multiple allocators. | |
| 83 | ||
| 84 | Note that this function does not mark the positions as allocated. | |
| 85 | ||
| 86 | In first fit mode: | |
| 87 | 1. Any initial run is added to the carry in | |
| 88 | 2. If all bits free, if BMA size+carry<=request length return 0 and leave carry alone | |
| 89 | else add size to carry and return KErrOverflow | |
| 90 | 3. If request satisfied by initial run + carry return 0 and leave carry alone | |
| 91 | 4. If request satisfied by an intermediate or final run, return start pos of run and set carry=0 | |
| 92 | 5. Otherwise carry = length of any final run and return KErrNotFound | |
| 93 | ||
| 94 | With a single allocator set aCarry (and usually aBase) to zero and ignore | |
| 95 | aRunLength. The return value then indicates the required position (after | |
| 96 | being aligned up as necessary) or KErrNotFound. | |
| 97 | ||
| 98 | With multiple allocators, this function should be called on each allocator in | |
| 99 | increasing logical bit number order. The carry should be set to zero initially | |
| 100 | and if there is a gap in the logical bit number between two allocators, otherwise | |
| 101 | it should be left alone. The first call which returns a nonnegative value indicates | |
| 102 | success and the required logical bit position is given by aligning up | |
| 103 | logical bit number of first bit of allocator + return value - carry | |
| 104 | ||
| 105 | In best fit mode: | |
| 106 | 1. Any initial run is added to the carry in | |
| 107 | 2. If all bits free, add bma length to carry and return KErrOverflow | |
| 108 | 3. If any run including initial+carry but not final has length >= request length | |
| 109 | return start pos and length of smallest such, also set carry = length of final run | |
| 110 | unless exact match found, when carry is either unchanged or set to 0 | |
| 111 | 4. If only final run large enough, return KErrNotFound and set carry = length of final run | |
| 112 | carry=0 if no final run | |
| 113 | ||
| 114 | Here is an example of how to use this for multiple allocators: | |
| 115 | @code | |
| 116 | // aLength = run length required, aAlign = alignment constraint | |
| 117 | TInt bmalen=0; | |
| 118 | TInt carry=0; | |
| 119 | TInt minrun=KMaxTInt; // this will track the length of the shortest useful run | |
| 120 | TInt minrunpos=KErrNotFound; // this will track the start position of the shortest useful run | |
| 121 | TUint32 alignsize=1<<aAlign; | |
| 122 | TUint32 alignmask=alignsize-1; | |
| 123 | TBitMapAllocator** ppA=iBmaList; // pointer to list of TBitMapAllocator* | |
| 124 | TBitMapAllocator** pE=ppA+iNumBmas; // pointer to end of list | |
| 125 | TInt* pB=iBaseList; // pointer to list of initial logical bit numbers | |
| 126 | TInt base=*pB; | |
| 127 | for (; ppA<pE; ++ppA, ++pB) | |
| 128 | 		{
 | |
| 129 | TBitMapAllocator* pA=*ppA; | |
| 130 | if (*pB!=base+bmalen) | |
| 131 | 			{
 | |
| 132 | // this BMA is not contiguous with previous one | |
| 133 | // check final run of previous BMA | |
| 134 | if (carry<minrun) | |
| 135 | 				{
 | |
| 136 | TInt fpos=base+bmalen-carry; | |
| 137 | TInt lost=((fpos+base+alignmask)&~alignmask)-base-fpos; | |
| 138 | if (carry-lost>=aLength) | |
| 139 | 					{
 | |
| 140 | minrun=carry; | |
| 141 | minrunpos=fpos; | |
| 142 | } | |
| 143 | } | |
| 144 | carry=0; | |
| 145 | } | |
| 146 | base=*pB; | |
| 147 | bmalen=pA->iSize; | |
| 148 | TInt l=KMaxTInt; | |
| 149 | TInt oldc=carry; // need to save this for the case where the best run is the initial one | |
| 150 | TInt r=pA->AllocAligned(aLength,aAlign,base,ETrue,carry,l); | |
| 151 | if (r>=0) | |
| 152 | 			{
 | |
| 153 | // check shortest run in this BMA | |
| 154 | if (l<minrun) | |
| 155 | 				{
 | |
| 156 | minrun=l; | |
| 157 | minrunpos=r ? (base+r) : (base-oldc); | |
| 158 | if (minrun==aLength) | |
| 159 | break; // exact match so finish | |
| 160 | } | |
| 161 | } | |
| 162 | } | |
| 163 | // check final run of last BMA (unless exact match already found) | |
| 164 | if (ppA==pE && carry<minrun) | |
| 165 | 		{
 | |
| 166 | TInt fpos=base+bmalen-carry; | |
| 167 | TInt lost=((fpos+alignmask)&~alignmask)-fpos; | |
| 168 | if (carry-lost>=aLength) | |
| 169 | 			{
 | |
| 170 | minrun=carry; | |
| 171 | minrunpos=fpos; | |
| 172 | } | |
| 173 | } | |
| 174 | result = (minrunpos<0) ? minrunpos : ((minrunpos+alignmask)&~alignmask); | |
| 175 | ||
| 176 | @endcode | |
| 177 | ||
| 178 | ||
| 179 | @param aLength number of consecutive bit positions to allocate. | |
| 180 | @param aAlign logarithm to base 2 of the alignment required. | |
| 181 | @param aBase the alignment of the first bit of this allocator - only significant modulo 2^aAlign. | |
| 182 | @param aBestFit TRUE for best fit allocation strategy, FALSE for first fit. | |
| 183 | @param aCarry carry in/carry out. | |
| 184 | @param aRunLength Holds best run length found so far. This will be set to KMaxTInt when no | |
| 185 | suitable run length has been found. In best fit mode aCarry should also be | |
| 186 | checked as aRunLength will not be set if aCarry is the only suitable run length | |
| 187 | found. | |
| 188 | ||
| 189 | @return Start position, if a suitable run was found; | |
| 190 | KErrNotFound, if no suitable run was found; | |
| 191 | KErrOverflow, if all positions free and best fit mode, or if all positions free | |
| 192 | in first fit mode and length requested > number of positions available. | |
| 193 | ||
| 194 | @see TBitMapAllocator::AllocConsecutive(TInt aLength, TBool aBestFit) | |
| 195 | @see TBitMapAllocator::AllocAligned(TInt aLength, TInt aAlign, TInt aBase, TBool aBestFit) | |
| 196 | */ | |
| 197 | EXPORT_C TInt TBitMapAllocator::AllocAligned(TInt aLength, TInt aAlign, TInt aBase, TBool aBestFit, TInt& aCarry, TInt& aRunLength) const | |
| 198 | 	{
 | |
| 199 | return AllocAligned(aLength, aAlign, aBase, aBestFit, aCarry, aRunLength, 0); | |
| 200 | } | |
| 201 | ||
| 202 | ||
| 203 | /** Allocates the next available bit position starting from the specified offset. | |
| 204 | ||
| 205 | Note - If no free bit positions can be found after aOffset this method will | |
| 206 | wrap around and continue the search from the start of the bit map. | |
| 207 | ||
| 208 | @param aOffset The offset from the start of the bit map. | |
| 209 | @return The number of the bit position allocated, -1 if all positions are occupied. | |
| 210 | */ | |
| 211 | EXPORT_C TInt TBitMapAllocator::AllocFrom(TUint aOffset) | |
| 212 | 	{
 | |
| 213 | __ASSERT_ALWAYS(aOffset < (TUint)iSize, TBMA_FAULT()); | |
| 214 | ||
| 215 | if (!iAvail) | |
| 216 | return -1; | |
| 217 | --iAvail; | |
| 218 | const TUint32* pEnd = iMap + ((iSize+31)>>5); | |
| 219 | TUint32* pW = iMap + (aOffset >> 5); | |
| 220 | // Only check the bits after aOffset in this word. | |
| 221 | TUint wordMask = 0xffffffffu >> (aOffset & 0x1f); | |
| 222 | #ifdef _DEBUG | |
| 223 | if(!((aOffset&0x1f)==0 || (wordMask&0x80000000u)==0)) // check compiler has done unsigned >> | |
| 224 | TBMA_FAULT(); | |
| 225 | #endif | |
| 226 | TUint word = *pW & wordMask; | |
| 227 | // No free bit positions in this word so search through the rest of the words. | |
| 228 | while (!word) | |
| 229 | 		{
 | |
| 230 | ++pW; | |
| 231 | if (pW >= pEnd) | |
| 232 | pW = iMap; | |
| 233 | word = *pW; | |
| 234 | } | |
| 235 | TInt n = __e32_find_ms1_32(word); | |
| 236 | *pW &= ~(1 << n); | |
| 237 | n = (31 - n) + ((pW - iMap) << 5); | |
| 238 | return n; | |
| 239 | } | |
| 240 | ||
| 241 | ||
| 242 | #if !defined( __TBMA_MACHINE_CODED__) | defined(__EABI_CTORS__) | |
| 243 | /** Constructs a new TBitMapAllocator object. | |
| 244 | ||
| 245 | @param aSize The number of bit positions required. | |
| 246 | @param aState TRUE if all bit positions initially free; | |
| 247 | FALSE if all bit positions initially allocated. | |
| 248 | */ | |
| 249 | EXPORT_C TBitMapAllocator::TBitMapAllocator(TInt aSize, TBool aState) | |
| 250 | 	{
 | |
| 251 | __ASSERT_ALWAYS(aSize>0, TBMA_FAULT()); | |
| 252 | iSize=aSize; | |
| 253 | if (aState) | |
| 254 | 		{
 | |
| 255 | iCheckFirst=iMap; | |
| 256 | iAvail=aSize; | |
| 257 | TUint32* pW=iMap; | |
| 258 | for (; aSize>=32; aSize-=32) | |
| 259 | *pW++=0xffffffff; | |
| 260 | if (aSize) | |
| 261 | *pW=((0xffffffffu)<<(32-aSize)); | |
| 262 | } | |
| 263 | else | |
| 264 | 		{
 | |
| 265 | TInt nmapw=(aSize+31)>>5; | |
| 266 | iAvail=0; | |
| 267 | iCheckFirst=iMap+nmapw-1; | |
| 268 | memclr(iMap, nmapw*sizeof(TUint32)); | |
| 269 | } | |
| 270 | } | |
| 271 | #endif | |
| 272 | ||
| 273 | ||
| 274 | #if !defined( __TBMA_MACHINE_CODED__) | |
| 275 | /** Allocates the next available bit position. | |
| 276 | ||
| 277 | @return Number of position allocated, -1 if all positions occupied. | |
| 278 | */ | |
| 279 | EXPORT_C TInt TBitMapAllocator::Alloc() | |
| 280 | 	{
 | |
| 281 | if (!iAvail) | |
| 282 | return -1; | |
| 283 | --iAvail; | |
| 284 | TUint32* pW=iCheckFirst; | |
| 285 | while (!*pW) | |
| 286 | ++pW; | |
| 287 | iCheckFirst=pW; | |
| 288 | TInt n=__e32_find_ms1_32(*pW); | |
| 289 | *pW &= ~(1<<n); | |
| 290 | n=(31-n)+((pW-iMap)<<5); | |
| 291 | return n; | |
| 292 | } | |
| 293 | ||
| 294 | ||
| 295 | /** Frees the specified bit position. | |
| 296 | ||
| 297 | @param aPos Number of bit position to be freed; must be currently allocated. | |
| 298 | */ | |
| 299 | EXPORT_C void TBitMapAllocator::Free(TInt aPos) | |
| 300 | 	{
 | |
| 301 | __ASSERT_ALWAYS(TUint(aPos)<TUint(iSize), TBMA_FAULT()); | |
| 302 | TUint32* pW=iMap+(aPos>>5); | |
| 303 | TUint32 b=0x80000000u>>(aPos&31); | |
| 304 | __ASSERT_ALWAYS(!(*pW & b), TBMA_FAULT()); | |
| 305 | *pW |= b; | |
| 306 | ++iAvail; | |
| 307 | if (pW<iCheckFirst) | |
| 308 | iCheckFirst=pW; | |
| 309 | } | |
| 310 | ||
| 311 | ||
| 312 | /** Allocates a specific range of bit positions. | |
| 313 | ||
| 314 | The specified range must lie within the total range for this allocator and all | |
| 315 | the positions must currently be free. | |
| 316 | ||
| 317 | @param aStart First position to allocate. | |
| 318 | @param aLength Number of consecutive positions to allocate, must be >0. | |
| 319 | */ | |
| 320 | EXPORT_C void TBitMapAllocator::Alloc(TInt aStart, TInt aLength) | |
| 321 | 	{
 | |
| 322 | __ASSERT_ALWAYS(TUint(aStart)<TUint(iSize), TBMA_FAULT()); | |
| 323 | __ASSERT_ALWAYS(TUint(aStart+aLength)>=TUint(aStart), TBMA_FAULT()); | |
| 324 | __ASSERT_ALWAYS(TUint(aStart+aLength)<=TUint(iSize), TBMA_FAULT()); | |
| 325 | TInt wix=aStart>>5; | |
| 326 | TInt sbit=aStart&31; | |
| 327 | TUint32* pW=iMap+wix; | |
| 328 | iAvail-=aLength; | |
| 329 | TInt ebit=sbit+aLength; | |
| 330 | if (ebit<32) | |
| 331 | 		{
 | |
| 332 | TUint32 b=(~(0xffffffffu>>aLength)>>sbit); | |
| 333 | TUint32 w=*pW; | |
| 334 | __ASSERT_ALWAYS((w|b)==w, TBMA_FAULT()); | |
| 335 | *pW=w&~b; | |
| 336 | return; | |
| 337 | } | |
| 338 | TUint32 b=(0xffffffffu>>sbit); | |
| 339 | while (ebit>0) | |
| 340 | 		{
 | |
| 341 | TUint32 w=*pW; | |
| 342 | __ASSERT_ALWAYS((w|b)==w, TBMA_FAULT()); | |
| 343 | *pW++=w&~b; | |
| 344 | b=0xffffffffu; | |
| 345 | ebit-=32; | |
| 346 | if (ebit<32) | |
| 347 | b=~(b>>ebit); | |
| 348 | } | |
| 349 | } | |
| 350 | ||
| 351 | ||
| 352 | /** Frees a specific range of bit positions. | |
| 353 | ||
| 354 | The specified range must lie within the total range for this allocator and all | |
| 355 | the positions must currently be allocated. | |
| 356 | ||
| 357 | @param aStart First position to free. | |
| 358 | @param aLength Number of consecutive positions to free, must be >0. | |
| 359 | */ | |
| 360 | EXPORT_C void TBitMapAllocator::Free(TInt aStart, TInt aLength) | |
| 361 | 	{
 | |
| 362 | __ASSERT_ALWAYS(TUint(aStart)<TUint(iSize), TBMA_FAULT()); | |
| 363 | __ASSERT_ALWAYS(TUint(aStart+aLength)>=TUint(aStart), TBMA_FAULT()); | |
| 364 | __ASSERT_ALWAYS(TUint(aStart+aLength)<=TUint(iSize), TBMA_FAULT()); | |
| 365 | TInt wix=aStart>>5; | |
| 366 | TInt sbit=aStart&31; | |
| 367 | TUint32* pW=iMap+wix; | |
| 368 | if (!iAvail || pW<iCheckFirst) | |
| 369 | iCheckFirst=pW; | |
| 370 | iAvail+=aLength; | |
| 371 | TInt ebit=sbit+aLength; | |
| 372 | if (ebit<32) | |
| 373 | 		{
 | |
| 374 | TUint32 b=(~(0xffffffffu>>aLength)>>sbit); | |
| 375 | TUint32 w=*pW; | |
| 376 | __ASSERT_ALWAYS((w&b)==0, TBMA_FAULT()); | |
| 377 | *pW=w|b; | |
| 378 | return; | |
| 379 | } | |
| 380 | TUint32 b=(0xffffffffu>>sbit); | |
| 381 | while (ebit>0) | |
| 382 | 		{
 | |
| 383 | TUint32 w=*pW; | |
| 384 | __ASSERT_ALWAYS((w&b)==0, TBMA_FAULT()); | |
| 385 | *pW++=w|b; | |
| 386 | b=0xffffffffu; | |
| 387 | ebit-=32; | |
| 388 | if (ebit<32) | |
| 389 | b=~(b>>ebit); | |
| 390 | } | |
| 391 | } | |
| 392 | ||
| 393 | ||
| 394 | /** Frees a specific range of bit positions. | |
| 395 | ||
| 396 | The specified range must lie within the total range for this allocator but it is | |
| 397 | not necessary that all the positions are currently allocated. | |
| 398 | ||
| 399 | @param aStart First position to free. | |
| 400 | @param aLength Number of consecutive positions to free, must be >0. | |
| 401 | */ | |
| 402 | EXPORT_C void TBitMapAllocator::SelectiveFree(TInt aStart, TInt aLength) | |
| 403 | 	{
 | |
| 404 | __ASSERT_ALWAYS(TUint(aStart)<TUint(iSize), TBMA_FAULT()); | |
| 405 | __ASSERT_ALWAYS(TUint(aStart+aLength)>=TUint(aStart), TBMA_FAULT()); | |
| 406 | __ASSERT_ALWAYS(TUint(aStart+aLength)<=TUint(iSize), TBMA_FAULT()); | |
| 407 | TInt wix=aStart>>5; | |
| 408 | TInt sbit=aStart&31; | |
| 409 | TUint32* pW=iMap+wix; | |
| 410 | if (!iAvail || pW<iCheckFirst) | |
| 411 | iCheckFirst=pW; | |
| 412 | iAvail+=aLength; // update free count assuming no positions already free | |
| 413 | TInt ebit=sbit+aLength; | |
| 414 | if (ebit<32) | |
| 415 | 		{
 | |
| 416 | TUint32 b=(~(0xffffffffu>>aLength)>>sbit); | |
| 417 | TUint32 w=*pW; | |
| 418 | *pW=w|b; // mark all positions free | |
| 419 | iAvail-=__e32_bit_count_32(w&b); // reduce free count by number of positions already free | |
| 420 | return; | |
| 421 | } | |
| 422 | TUint32 b=(0xffffffffu>>sbit); | |
| 423 | while (ebit>0) | |
| 424 | 		{
 | |
| 425 | TUint32 w=*pW; | |
| 426 | *pW++=w|b; // mark all positions free | |
| 427 | iAvail-=__e32_bit_count_32(w&b); // reduce free count by number of positions already free | |
| 428 | b=0xffffffffu; | |
| 429 | ebit-=32; | |
| 430 | if (ebit<32) | |
| 431 | b=~(b>>ebit); | |
| 432 | } | |
| 433 | } | |
| 434 | ||
| 435 | ||
| 28 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 436 | /** Allocates a specific range of bit positions. | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 437 | |
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 438 | The specified range must lie within the total range for this allocator but it is | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 439 | not necessary that all the positions are currently free. | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 440 | |
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 441 | @param aStart First position to allocate. | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 442 | @param aLength Number of consecutive positions to allocate, must be >0. | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 443 | @return The number of previously free positions that were allocated. | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 444 | */ | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 445 | EXPORT_C TUint TBitMapAllocator::SelectiveAlloc(TInt aStart, TInt aLength) | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 446 | 	{
 | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 447 | __ASSERT_ALWAYS(TUint(aStart) < TUint(iSize), TBMA_FAULT()); | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 448 | __ASSERT_ALWAYS(TUint(aStart + aLength) >= TUint(aStart), TBMA_FAULT()); | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 449 | __ASSERT_ALWAYS(TUint(aStart + aLength) <= TUint(iSize), TBMA_FAULT()); | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 450 | TInt wix = aStart >> 5; | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 451 | TInt sbit = aStart & 31; | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 452 | TUint32* pW = iMap + wix; | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 453 | iAvail -= aLength; // update free count assuming no positions already allocated | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 454 | TInt ebit = sbit + aLength; | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 455 | if (ebit < 32) | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 456 | 		{
 | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 457 | TUint32 b = ((0xffffffffu >> aLength) >> sbit) | ~(0xffffffffu >> sbit); | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 458 | TUint32 w = *pW; | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 459 | *pW = w & b; // mark all positions allocated | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 460 | TUint allocated = __e32_bit_count_32(~w & ~b); | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 461 | iAvail += allocated; // increase free count by number of positions already allocated | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 462 | return aLength - allocated; | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 463 | } | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 464 | TUint32 b = ~(0xffffffffu >> sbit); | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 465 | while (ebit > 0) | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 466 | 		{
 | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 467 | TUint32 w = *pW; | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 468 | *pW++ = w & b; // mark all positions allocated | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 469 | TUint allocated = __e32_bit_count_32(~w & ~b); | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 470 | iAvail += allocated; // increase free count by number of positions already allocated | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 471 | aLength -= allocated; | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 472 | ebit -= 32; | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 473 | b = (ebit >= 32)? 0 : 0xffffffff >> ebit; | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 474 | } | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 475 | return aLength; | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 476 | } | 
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 477 | |
| 
5b5d147c7838
Revision: 201021
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
26diff
changeset | 478 | |
| 0 | 479 | /** Tests whether a specific range of bit positions are all free. | 
| 480 | ||
| 481 | The specified range must lie within the total range for this allocator. | |
| 482 | ||
| 483 | @param aStart First position to check. | |
| 484 | @param aLength Number of consecutive positions to check, must be >0. | |
| 485 | ||
| 486 | @return FALSE if all positions free, TRUE if at least one is occupied. | |
| 487 | */ | |
| 488 | EXPORT_C TBool TBitMapAllocator::NotFree(TInt aStart, TInt aLength) const | |
| 489 | 	{
 | |
| 490 | // Inverse logic - returns 0 if all positions free, nonzero otherwise | |
| 491 | __ASSERT_ALWAYS(TUint(aStart)<TUint(iSize), TBMA_FAULT()); | |
| 492 | __ASSERT_ALWAYS(TUint(aStart+aLength)>=TUint(aStart), TBMA_FAULT()); | |
| 493 | __ASSERT_ALWAYS(TUint(aStart+aLength)<=TUint(iSize), TBMA_FAULT()); | |
| 494 | TInt wix=aStart>>5; | |
| 495 | TInt sbit=aStart&31; | |
| 496 | const TUint32* pW=iMap+wix; | |
| 497 | TInt ebit=sbit+aLength; | |
| 498 | if (ebit<32) | |
| 499 | 		{
 | |
| 500 | TUint32 b=(~(0xffffffffu>>aLength)>>sbit); | |
| 501 | return (*pW^b)&b; | |
| 502 | } | |
| 503 | TUint32 b=(0xffffffffu>>sbit); | |
| 504 | TUint32 r=0; | |
| 505 | while (ebit>0) | |
| 506 | 		{
 | |
| 507 | r|=((*pW++^b)&b); | |
| 508 | b=0xffffffffu; | |
| 509 | ebit-=32; | |
| 510 | if (ebit<32) | |
| 511 | b=~(b>>ebit); | |
| 512 | } | |
| 513 | return r; | |
| 514 | } | |
| 515 | ||
| 516 | ||
| 517 | /** Tests whether a specific range of bit positions are all occupied. | |
| 518 | ||
| 519 | The specified range must lie within the total range for this allocator. | |
| 520 | ||
| 521 | @param aStart First position to check. | |
| 522 | @param aLength Number of consecutive positions to check, must be >0. | |
| 523 | ||
| 524 | @return FALSE if all positions occupied, TRUE if at least one is free. | |
| 525 | */ | |
| 526 | EXPORT_C TBool TBitMapAllocator::NotAllocated(TInt aStart, TInt aLength) const | |
| 527 | 	{
 | |
| 528 | // Inverse logic - returns 0 if all positions allocated, nonzero otherwise | |
| 529 | __ASSERT_ALWAYS(TUint(aStart)<TUint(iSize), TBMA_FAULT()); | |
| 530 | __ASSERT_ALWAYS(TUint(aStart+aLength)>=TUint(aStart), TBMA_FAULT()); | |
| 531 | __ASSERT_ALWAYS(TUint(aStart+aLength)<=TUint(iSize), TBMA_FAULT()); | |
| 532 | TInt wix=aStart>>5; | |
| 533 | TInt sbit=aStart&31; | |
| 534 | const TUint32* pW=iMap+wix; | |
| 535 | TInt ebit=sbit+aLength; | |
| 536 | if (ebit<32) | |
| 537 | 		{
 | |
| 538 | TUint32 b=(~(0xffffffffu>>aLength)>>sbit); | |
| 539 | return *pW&b; | |
| 540 | } | |
| 541 | TUint32 b=(0xffffffffu>>sbit); | |
| 542 | TUint32 r=0; | |
| 543 | while (ebit>0) | |
| 544 | 		{
 | |
| 545 | r|=(*pW++&b); | |
| 546 | b=0xffffffffu; | |
| 547 | ebit-=32; | |
| 548 | if (ebit<32) | |
| 549 | b=~(b>>ebit); | |
| 550 | } | |
| 551 | return r; | |
| 552 | } | |
| 553 | ||
| 554 | ||
| 555 | /** Allocates up to a specified number of available bit positions. | |
| 556 | ||
| 557 | The allocated positions are not required to bear any relationship to | |
| 558 | each other. | |
| 559 | If the number of free positions is less than the number requested, | |
| 560 | allocate all currently free positions. | |
| 561 | ||
| 562 | @param aLength Maximum number of positions to allocate. | |
| 563 | @param aList Pointer to memory area where allocated bit numbers should be stored. | |
| 564 | ||
| 565 | @return The number of positions allocated. | |
| 566 | */ | |
| 567 | EXPORT_C TInt TBitMapAllocator::AllocList(TInt aLength, TInt* aList) | |
| 568 | 	{
 | |
| 569 | __ASSERT_ALWAYS(aLength>0, TBMA_FAULT()); | |
| 570 | if (aLength>iAvail) | |
| 571 | aLength=iAvail; | |
| 572 | TInt c=aLength; | |
| 573 | while (c--) | |
| 574 | *aList++=Alloc(); | |
| 575 | return aLength; | |
| 576 | } | |
| 577 | ||
| 578 | ||
| 579 | /** Finds a set of consecutive bit positions with specified alignment starting the | |
| 580 | search from the specfied bit position offset, with support for chaining | |
| 581 | multiple allocators. | |
| 582 | ||
| 583 | For further details see: | |
| 584 | TBitMapAllocator::AllocAligned(TInt aLength, TInt aAlign, TInt aBase, TBool aBestFit, TInt& aCarry, TInt& aRunLength) | |
| 585 | ||
| 586 | @param aLength number of consecutive bit positions to allocate. | |
| 587 | @param aAlign logarithm to base 2 of the alignment required. | |
| 588 | @param aBase the alignment of the first bit of this allocator - only significant modulo 2^aAlign. | |
| 589 | @param aBestFit TRUE for best fit allocation strategy, FALSE for first fit. | |
| 590 | @param aCarry carry in/carry out. | |
| 591 | @param aRunLength Holds best run length found so far. This will be set to KMaxTInt when no | |
| 592 | suitable run length has been found. In best fit mode aCarry should also be | |
| 593 | checked as aRunLength will not be set if aCarry is the only suitable run length | |
| 594 | found. | |
| 595 | @param aOffset The bit position to start the search from, set to 0 to search all bit positions. | |
| 596 | aOffset will be aligned so all bits before an aligned aOffset will be | |
| 597 | ignored. This can only be non-zero if aCarry is zero as any carry in bits will be | |
| 598 | ignored if aOffset is non-zero. | |
| 599 | ||
| 600 | @return Start position, if a suitable run was found; | |
| 601 | KErrNotFound, if no suitable run was found; | |
| 602 | KErrOverflow, if all positions free and best fit mode, or if all positions free | |
| 603 | in first fit mode and length requested > number of positions available. | |
| 604 | ||
| 605 | @see TBitMapAllocator::AllocAligned(TInt aLength, TInt aAlign, TInt aBase, TBool aBestFit, TInt& aCarry, TInt& aRunLength) | |
| 606 | */ | |
| 607 | EXPORT_C TInt TBitMapAllocator::AllocAligned(TInt aLength, TInt aAlign, TInt aBase, TBool aBestFit, TInt& aCarry, TInt& aRunLength, TUint aOffset) const | |
| 608 | 	{
 | |
| 609 | TInt minrl=KMaxTInt; | |
| 610 | __ASSERT_ALWAYS(aLength>0, TBMA_FAULT()); | |
| 611 | __ASSERT_ALWAYS(TUint(aAlign)<31, TBMA_FAULT()); | |
| 612 | __ASSERT_ALWAYS(aOffset < (TUint)iSize, TBMA_FAULT()); | |
| 613 | __ASSERT_ALWAYS(!aCarry || !aOffset, TBMA_FAULT()); | |
| 614 | TUint32 alignsize=1<<aAlign; | |
| 615 | TUint32 alignmask=alignsize-1; | |
| 616 | aBase&=alignmask; | |
| 617 | if (iAvail==iSize) | |
| 618 | 		{
 | |
| 619 | // Align aOffset if it is set so we ignore all bits before the aligned offset. | |
| 620 | aOffset = (!aOffset)? aOffset : ((aOffset + aBase + alignmask) & ~alignmask) - aBase; | |
| 621 | TInt runLength = (aOffset < (TUint)iSize)? iSize - aOffset : 0; | |
| 622 | if (!aBestFit) | |
| 623 | 			{
 | |
| 624 | TInt alignedStartPos = ((aOffset - aCarry + aBase + alignmask) & ~alignmask) - aBase; | |
| 625 | TInt lost = alignedStartPos - (aOffset - aCarry); | |
| 626 | if (runLength + aCarry - lost >= aLength) | |
| 627 | 				{
 | |
| 628 | aRunLength = runLength; | |
| 629 | if (alignedStartPos >= 0) | |
| 630 | 					{
 | |
| 631 | aCarry=0; // clear carry if not initial run | |
| 632 | } | |
| 633 | return (alignedStartPos >= 0)? alignedStartPos : 0; // return start pos of exact run | |
| 634 | } | |
| 635 | } | |
| 636 | if (aOffset) | |
| 637 | aCarry = runLength; | |
| 638 | else | |
| 639 | aCarry += iAvail; | |
| 640 | aRunLength = KMaxTInt; | |
| 641 | return KErrOverflow; | |
| 642 | } | |
| 643 | const TUint32* pW=aCarry?iMap:iCheckFirst; | |
| 644 | const TUint32* pE=iMap+((iSize+31)>>5); | |
| 645 | TInt n=((pW-iMap)<<5); | |
| 646 | TInt p=-1; | |
| 647 | TInt q=-aCarry; | |
| 648 | TUint32 s=aCarry?~0:0; // 0 when searching for 1's, FFFFFFFF when searching for 0's | |
| 649 | ||
| 650 | TUint32 offsetMask = 0; | |
| 651 | if (aOffset) | |
| 652 | 		{// Start search from aOffset.  Only align aOffset if aOffset is to
 | |
| 653 | // be used otherwise the best fit mode may fail as aligning aOffset | |
| 654 | // may cause the search to skip past parts of the bit map. | |
| 655 | aOffset = ((aOffset + aBase + alignmask) & ~alignmask) - aBase; | |
| 656 | const TUint32* offsetWord = iMap + (aOffset >> 5); | |
| 657 | if (offsetWord >= pW) | |
| 658 | 			{
 | |
| 659 | pW = offsetWord; | |
| 660 | n = aOffset & 0xffffffe0; | |
| 661 | offsetMask = 0xffffffff >> (aOffset & 31); | |
| 662 | __ASSERT_ALWAYS(offsetMask, TBMA_FAULT()); | |
| 663 | } | |
| 664 | } | |
| 665 | while (pW<pE) | |
| 666 | 		{
 | |
| 667 | TUint32 word = *pW++; | |
| 668 | if (offsetMask) | |
| 669 | 			{// Start search after bit aOffset.
 | |
| 670 | word &= offsetMask; // Mask off any bits before the aOffset | |
| 671 | offsetMask = 0; // Reset so future iterations use whole of next word. | |
| 672 | } | |
| 673 | if (word==s) // check if any of required bit present | |
| 674 | 			{
 | |
| 675 | n+=32; // if not, step bit number on by 32 | |
| 676 | continue; | |
| 677 | } | |
| 678 | TInt rl=-1; | |
| 679 | for (TUint32 b=0x80000000; b; ++n, b>>=1) | |
| 680 | 			{
 | |
| 681 | if ((word ^ s) & b) | |
| 682 | 				{
 | |
| 683 | if (s && n==iSize) | |
| 684 | break; // reached end | |
| 685 | // bit found - invert search bit | |
| 686 | s=~s; | |
| 687 | if (s) | |
| 688 | q=n; // 1 found so save position | |
| 689 | else | |
| 690 | 					{
 | |
| 691 | rl=n-q; // 0 found, calculate run length of 1's | |
| 692 | TInt alignedStartPos = ((q + aBase + alignmask) & ~alignmask) - aBase; | |
| 693 | TInt lost = alignedStartPos - q; | |
| 694 | if (rl-lost>=aLength) | |
| 695 | 						{
 | |
| 696 | if (!aBestFit || rl==aLength) | |
| 697 | 							{
 | |
| 698 | // first fit or exact match - we're finished | |
| 699 | if (alignedStartPos >= 0) | |
| 700 | 								{
 | |
| 701 | aCarry=0; // clear carry if not initial run | |
| 702 | } | |
| 703 | aRunLength=rl; | |
| 704 | return (alignedStartPos >= 0)? alignedStartPos : 0; | |
| 705 | } | |
| 706 | if (rl<minrl) | |
| 707 | 							{
 | |
| 708 | // best fit and this run is smallest so far, so record its position and length | |
| 709 | minrl=rl; | |
| 710 | p = (alignedStartPos >= 0)? alignedStartPos : 0; | |
| 711 | } | |
| 712 | } | |
| 713 | } | |
| 714 | } | |
| 715 | } | |
| 716 | } | |
| 717 | if (minrl!=aLength) | |
| 718 | 		{
 | |
| 719 | // exact match not found or first fit and no match found | |
| 720 | TInt rl=0; | |
| 721 | if (s) | |
| 722 | 			{
 | |
| 723 | // we were looking for 0, so this counts as a run | |
| 724 | // get run length | |
| 725 | rl=n-q; | |
| 726 | if (!aBestFit) | |
| 727 | 				{
 | |
| 728 | TInt alignedStartPos = ((q + aBase + alignmask) & ~alignmask) - aBase; | |
| 729 | TInt lost = alignedStartPos - q; | |
| 730 | if (rl-lost>=aLength) | |
| 731 | 					{// BMA is not totally empty so this can't be the initial run
 | |
| 732 | // and the final run. Therefore the start pos must be within | |
| 733 | // this bma so clear carry and return start pos. | |
| 734 | aCarry=0; | |
| 735 | aRunLength=rl; | |
| 736 | return alignedStartPos; | |
| 737 | } | |
| 738 | } | |
| 739 | } | |
| 740 | aCarry=rl; // set carry to length of final run or 0 if none | |
| 741 | } | |
| 742 | aRunLength=minrl; // return best run length found | |
| 743 | return p; // return start position of run or -1 if run not found | |
| 744 | } | |
| 745 | #endif | |
| 746 | ||
| 747 | ||
| 748 | /** Finds a set of consecutive free positions on a single bit map allocator. | |
| 749 | ||
| 750 | @param aLength number of consecutive bit positions to allocate. | |
| 751 | @param aBestFit TRUE for best fit allocation strategy, FALSE for first fit. | |
| 752 | ||
| 753 | @return Start position, if a suitable run was found; | |
| 754 | KErrNotFound, if no suitable run was found. | |
| 755 | */ | |
| 756 | EXPORT_C TInt TBitMapAllocator::AllocConsecutive(TInt aLength, TBool aBestFit) const | |
| 757 | 	{
 | |
| 758 | TInt carry=0; | |
| 759 | TInt l=KMaxTInt; | |
| 760 | TInt r=AllocAligned(aLength,0,0,aBestFit,carry,l); | |
| 761 | if (aBestFit) | |
| 762 | 		{
 | |
| 763 | // must check final run if any | |
| 764 | if (carry>=aLength && carry<l) | |
| 765 | r=iSize-carry; | |
| 766 | } | |
| 767 | if (r<0) | |
| 768 | r=KErrNotFound; | |
| 769 | return r; | |
| 770 | } | |
| 771 | ||
| 772 | ||
| 773 | /** Finds a set of consecutive free positions on a single bit map allocator with | |
| 774 | specified alignment. | |
| 775 | ||
| 776 | @param aLength number of consecutive bit positions to allocate. | |
| 777 | @param aAlign logarithm to base 2 of the alignment required. | |
| 778 | @param aBase the alignment of the first bit of this allocator - only significant modulo 2^aAlign. | |
| 779 | @param aBestFit TRUE for best fit allocation strategy, FALSE for first fit. | |
| 780 | ||
| 781 | @return Start position, if a suitable run was found; | |
| 782 | KErrNotFound, if no suitable run was found. | |
| 783 | */ | |
| 784 | EXPORT_C TInt TBitMapAllocator::AllocAligned(TInt aLength, TInt aAlign, TInt aBase, TBool aBestFit) const | |
| 785 | 	{
 | |
| 786 | TInt carry=0; | |
| 787 | TInt l=KMaxTInt; | |
| 788 | TUint32 alignsize=1<<aAlign; | |
| 789 | TUint32 alignmask=alignsize-1; | |
| 790 | aBase&=alignmask; | |
| 791 | TInt r=AllocAligned(aLength,aAlign,aBase,aBestFit,carry,l); | |
| 792 | if (aBestFit) | |
| 793 | 		{
 | |
| 794 | // must check final run if any | |
| 795 | TInt fpos=iSize-carry; | |
| 796 | TInt lost=((fpos+aBase+alignmask)&~alignmask)-aBase-fpos; | |
| 797 | if (carry-lost>=aLength && carry<l) | |
| 798 | r=fpos+lost; | |
| 799 | } | |
| 800 | if (r<0) | |
| 801 | r=KErrNotFound; | |
| 802 | else | |
| 803 | r=((r+aBase+alignmask)&~alignmask)-aBase; | |
| 804 | return r; | |
| 805 | } | |
| 806 | ||
| 807 | ||
| 808 | /** Copies a range from another allocator, mark remainder as occupied. | |
| 809 | ||
| 810 | Values of bit positions from aFirst to aFirst+aLen-1 inclusive in allocator | |
| 811 | aA are copied to bit positions in this allocator starting with aFirst mod 32. | |
| 812 | Remaining bit positions in this allocator are marked as occupied. | |
| 813 | ||
| 814 | @param aA Pointer to source allocator. | |
| 815 | @param aFirst Number in source allocator of first bit to copy. | |
| 816 | @param aLen Number of bits to copy from source allocator. | |
| 817 | */ | |
| 818 | EXPORT_C void TBitMapAllocator::CopyAlignedRange(const TBitMapAllocator* aA, TInt aFirst, TInt aLen) | |
| 819 | 	{
 | |
| 820 | const TUint32* srcptr = aA->iMap + (aFirst>>5); | |
| 821 | TInt last = aFirst + aLen - 1; | |
| 822 | TInt len = (((last+32)&~31)-(aFirst&~31))>>3; // bytes | |
| 823 | __ASSERT_ALWAYS(len<=iSize, TBMA_FAULT()); | |
| 824 | TInt remain = ((iSize+31)&~31)-(len<<3); | |
| 825 | wordmove(iMap, srcptr, len); | |
| 826 | memclr(iMap+(len>>2), remain>>3); | |
| 827 | TUint32* p = iMap; | |
| 828 | TUint32* pE = p + (len>>2); | |
| 829 | *p &= (0xffffffffu >> (aFirst&31)); | |
| 830 | pE[-1] &= (0xffffffffu << (31-(last&31))); | |
| 831 | iCheckFirst = pE-1; | |
| 832 | iAvail = 0; | |
| 833 | for (; p<pE; ++p) | |
| 834 | 		{
 | |
| 835 | TUint32 x = *p; | |
| 836 | if (x) | |
| 837 | 			{
 | |
| 838 | if (p<iCheckFirst) | |
| 839 | iCheckFirst = p; | |
| 840 | iAvail += __e32_bit_count_32(x); | |
| 841 | } | |
| 842 | } | |
| 843 | } |