First public contribution.
1 // Copyright (c) 1997-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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\euser\cbase\ub_bma.cpp
20 const TInt KBitsPerInt=32;
21 const TInt KBitsPerIntMask=(KBitsPerInt-1);
22 const TInt KBitsPerIntShift=5;
25 inline TInt FindLeastSignificantZero(register TUint n)
29 if (n<<16==0) n>>=16, i+=16;
30 if (n<<24==0) n>>=8, i+=8;
31 if (n<<28==0) n>>=4, i+=4;
32 if (n<<30==0) n>>=2, i+=2;
33 if (n<<31==0) n>>=1, i+=1;
37 inline TInt FindLeastSignificantZero(register TUint n, TUint aFrom)
40 return FindLeastSignificantZero(n);
43 inline TInt FindLeastSignificantOne(register TUint n)
46 if (n<<16==0) n>>=16, i+=16;
47 if (n<<24==0) n>>=8, i+=8;
48 if (n<<28==0) n>>=4, i+=4;
49 if (n<<30==0) n>>=2, i+=2;
50 if (n<<31==0) n>>=1, i+=1;
54 inline TInt FindMostSignificantZero(register TUint n)
58 if (n<0x00010000) n<<=16, i-=16;
59 if (n<0x01000000) n<<=8, i-=8;
60 if (n<0x10000000) n<<=4, i-=4;
61 if (n<0x40000000) n<<=2, i-=2;
62 if (n<0x80000000) n<<=1, i-=1;
66 EXPORT_C CBitMapAllocator::CBitMapAllocator(TInt aSize,TInt aLength)
70 : iAvail(aSize),iSize(aSize),iLength(aLength)
72 TInt rem=aSize&KBitsPerIntMask;
75 TInt last=(aSize-1)>>KBitsPerIntShift;
76 iMap[last]=0xFFFFFFFFu<<rem;
80 EXPORT_C CBitMapAllocator::~CBitMapAllocator()
87 EXPORT_C CBitMapAllocator *CBitMapAllocator::New(TInt aSize)
89 // Create a new bit map allocator.
92 __ASSERT_ALWAYS(aSize>0,Panic(EBmaSizeLessOrEqualToZero));
93 TInt sz=((aSize+KBitsPerIntMask)>>KBitsPerIntShift)-1;
94 return(new(sz*sizeof(TUint)) CBitMapAllocator(aSize,sz+1));
97 EXPORT_C CBitMapAllocator *CBitMapAllocator::NewL(TInt aSize)
99 // Create a new bit map allocator. Leave on any error.
102 CBitMapAllocator *pA=New(aSize);
103 User::LeaveIfNull(pA);
107 EXPORT_C TInt CBitMapAllocator::Alloc()
109 // Allocate the next position.
115 TUint *pE=pS+iLength;
117 register TUint n=*pS++;
121 TInt bit=FindLeastSignificantZero(n);
123 return((TInt(pS-iMap)<<KBitsPerIntShift)+bit);
126 Panic(EBmaInconsistentState);
128 return(KErrNoMemory);
131 EXPORT_C TInt CBitMapAllocator::AllocFrom(TInt aPos)
133 // Allocate the next position after aPos.
136 __ASSERT_ALWAYS((aPos>=0 && aPos<iSize),Panic(EBmaAllocFromOutOfRange));
139 TUint *pS=iMap+(aPos>>KBitsPerIntShift);
140 TUint *pE=iMap+iLength;
141 TInt start=aPos&KBitsPerIntMask;
145 n=*pS++ | ~(0xFFFFFFFFu<<start);
156 TInt bit=FindLeastSignificantZero(n);
158 return((TInt(pS-iMap)<<KBitsPerIntShift)+bit);
162 return(KErrNoMemory);
165 EXPORT_C TInt CBitMapAllocator::AllocFromTop()
167 // Allocate the next position.
173 TUint *pE=pS+iLength;
175 register TUint n=*--pE;
179 TInt bit=FindMostSignificantZero(n);
181 return((TInt(pE-pS)<<KBitsPerIntShift)+bit);
184 Panic(EBmaInconsistentState);
186 return(KErrNoMemory);
189 EXPORT_C TInt CBitMapAllocator::AllocFromTopFrom(TInt aPos)
191 // Allocate the next position after aPos.
194 __ASSERT_ALWAYS((aPos>=0 && aPos<iSize),Panic(EBmaAllocFromTopFromOutOfRange));
198 TUint *pE=pS+((aPos+1)>>KBitsPerIntShift);
199 TInt start=(aPos+1)&KBitsPerIntMask;
203 n=*pE | (0xFFFFFFFFu<<start);
214 TInt bit=FindMostSignificantZero(n);
216 return((TInt(pE-pS)<<KBitsPerIntShift)+bit);
220 return(KErrNoMemory);
223 EXPORT_C TInt CBitMapAllocator::Alloc(TInt aCount, TInt& aConsecutive)
225 __ASSERT_ALWAYS((aCount>0),Panic(EBmaAllocCountNegative));
230 TUint *pE=pS+iLength;
237 Panic(EBmaInconsistentState);
241 TInt bit=FindLeastSignificantZero(n);
242 initPos=(TInt(pS-iMap)<<KBitsPerIntShift)+bit;
246 c=FindLeastSignificantOne(n);
247 if (aCount<c) c=aCount;
248 *pS |= ~(0xFFFFFFFFu<<c)<<bit;
258 *pS |= ~(0xFFFFFFFFu<<c)<<bit;
260 *pS |= 0xFFFFFFFFu<<bit;
267 while(++pS<pE && (n=*pS)==0 && c>=KBitsPerInt)
268 *pS=0xFFFFFFFFu, c-=KBitsPerInt;
269 if (c && pS<pE && n!=0xFFFFFFFFu)
271 bit=n?FindLeastSignificantOne(n):KBitsPerInt;
273 *pS |= ~(0xFFFFFFFFu<<bit);
276 aConsecutive=aCount-c;
277 iAvail-=aConsecutive;
284 LOCAL_D const TUint AlignedSearchMask[] =
285 {0x00000000,0xAAAAAAAA,0xEEEEEEEE,0xFEFEFEFE,0xFFFEFFFE};
287 EXPORT_C TInt CBitMapAllocator::AllocAligned(TInt anAlignment)
289 __ASSERT_ALWAYS((anAlignment>=0 && anAlignment<32),Panic(EBmaAllAlgnOutOfRange));
294 if (anAlignment>=KBitsPerIntShift)
297 step=1<<(anAlignment-KBitsPerIntShift);
301 mask=AlignedSearchMask[anAlignment];
305 TUint *pE=pM+iLength;
307 register TUint n=*pM | mask;
311 TInt bit=(mask==0xFFFFFFFEu)?0:FindLeastSignificantZero(n);
313 return((TInt(pM-iMap)<<KBitsPerIntShift)+bit);
320 EXPORT_C TInt CBitMapAllocator::AllocAlignedBlock(TInt anAlignment)
322 __ASSERT_ALWAYS((anAlignment>=0 && anAlignment<32),Panic(EBmaAllAlgnBOutOfRange));
325 TInt blocksz=1<<anAlignment;
329 if (anAlignment>=KBitsPerIntShift)
332 step=1<<(anAlignment-KBitsPerIntShift);
337 mask=AlignedSearchMask[anAlignment];
339 block=~(0xFFFFFFFFu<<blocksz);
342 TUint *pE=pM+iLength;
344 register TUint n=*pM | mask;
347 if (blocksz>=KBitsPerInt)
353 do n|=*pM++; while(pM<pS);
358 do *pM++=0xFFFFFFFFu; while(pM<pS);
360 return (TInt(pM-iMap)<<KBitsPerIntShift);
366 TInt bit=FindLeastSignificantZero(n);
374 return((TInt(pM-iMap)<<KBitsPerIntShift)+bit);
386 EXPORT_C void CBitMapAllocator::AllocAt(TInt aPos)
388 // Allocate a required position.
391 __ASSERT_ALWAYS(aPos>=0 && aPos<iSize,Panic(EBmaAllocOutOfRange));
392 TUint *pM=iMap+(aPos>>KBitsPerIntShift);
393 TUint mask=1<<(aPos&KBitsPerIntMask);
394 __ASSERT_ALWAYS(!(*pM&mask),Panic(EBmaAllocAtAlreadyAllocated));
399 EXPORT_C void CBitMapAllocator::AllocAt(TInt aPos, TInt aCount)
401 __ASSERT_ALWAYS((aPos>=0 && (aPos+aCount)<=iSize),Panic(EBmaAllocBlkOutOfRange));
402 TUint *pM=iMap+(aPos>>KBitsPerIntShift);
403 TInt c=aPos&KBitsPerIntMask;
405 if (aCount<(KBitsPerInt-c))
407 m=~(0xFFFFFFFFu<<aCount)<<c;
409 Panic(EBmaAllocBlkNotFree);
416 Panic(EBmaAllocBlkNotFree);
418 c=aCount-KBitsPerInt+c;
419 while(c>=KBitsPerInt)
422 Panic(EBmaAllocBlkNotFree);
428 m=0xFFFFFFFFu>>(KBitsPerInt-c);
430 Panic(EBmaAllocBlkNotFree);
436 EXPORT_C TInt CBitMapAllocator::ExtractRamPages(TInt aConsecutive,TInt& aPageNo)
438 if(iAvail<aConsecutive)
442 TUint *pE=pS+iLength;
445 register TUint n=*pS++;
451 TInt bit=FindLeastSignificantZero(n,x);
452 TInt pos=(TInt((pS-1)-iMap)<<KBitsPerIntShift)+bit;
453 if(pos+aConsecutive > iSize)
455 if(IsFree(pos,aConsecutive))
457 AllocAt(pos,aConsecutive);
466 while (x < KBitsPerInt);
472 EXPORT_C TBool CBitMapAllocator::IsFree(TInt aPos)
474 // Check a required position is available
477 __ASSERT_ALWAYS(aPos>=0 && aPos<iSize,Panic(EBmaFreeOutOfRange));
478 TUint n=iMap[aPos>>KBitsPerIntShift];
479 return !(n>>(aPos&KBitsPerIntMask)&1);
482 EXPORT_C TBool CBitMapAllocator::IsFree(TInt aPos, TInt aCount)
484 __ASSERT_ALWAYS((aPos>=0 && (aPos+aCount)<=iSize),Panic(EBmaChkBlkOutOfRange));
485 TUint *pM=iMap+(aPos>>KBitsPerIntShift);
487 TInt c=aPos&KBitsPerIntMask;
489 if (aCount<(KBitsPerInt-c))
491 return !(m&~(0xFFFFFFFFu<<aCount));
493 aCount-=(KBitsPerInt-c);
494 while(aCount>=KBitsPerInt)
501 m|=(*pM<<(KBitsPerInt-aCount));
506 EXPORT_C void CBitMapAllocator::Free(TInt aPos)
511 __ASSERT_ALWAYS(aPos>=0 && aPos<iSize,Panic(EBmaFreeOutOfRange));
512 TUint *pM=iMap+(aPos>>KBitsPerIntShift);
513 TUint mask=1<<(aPos&KBitsPerIntMask);
514 __ASSERT_ALWAYS((*pM&mask),Panic(EBmaFreeNotAllocated));
519 EXPORT_C void CBitMapAllocator::Free(TInt aPos, TInt aCount)
521 __ASSERT_ALWAYS((aPos>=0 && (aPos+aCount)<=iSize),Panic(EBmaFreeBlkOutOfRange));
522 TUint *pM=iMap+(aPos>>KBitsPerIntShift);
523 TInt c=aPos&KBitsPerIntMask;
525 if (aCount<(KBitsPerInt-c))
527 m=~(0xFFFFFFFFu<<aCount)<<c;
529 Panic(EBmaFreeBlkNotAllocated);
536 Panic(EBmaFreeBlkNotAllocated);
538 c=aCount-KBitsPerInt+c;
539 while(c>=KBitsPerInt)
542 Panic(EBmaFreeBlkNotAllocated);
548 m=0xFFFFFFFFu>>(KBitsPerInt-c);
550 Panic(EBmaFreeBlkNotAllocated);
556 EXPORT_C TInt CBitMapAllocator::Avail()
558 // Get the available blocks count.
564 EXPORT_C TInt CBitMapAllocator::Size()
566 // Get the size of all available blocks.