sl@0: // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32\euser\cbase\ub_bma.cpp sl@0: // sl@0: // sl@0: sl@0: #include "ub_std.h" sl@0: sl@0: const TInt KBitsPerInt=32; sl@0: const TInt KBitsPerIntMask=(KBitsPerInt-1); sl@0: const TInt KBitsPerIntShift=5; sl@0: sl@0: sl@0: inline TInt FindLeastSignificantZero(register TUint n) sl@0: { sl@0: register TInt i=0; sl@0: n=~n; sl@0: if (n<<16==0) n>>=16, i+=16; sl@0: if (n<<24==0) n>>=8, i+=8; sl@0: if (n<<28==0) n>>=4, i+=4; sl@0: if (n<<30==0) n>>=2, i+=2; sl@0: if (n<<31==0) n>>=1, i+=1; sl@0: return i; sl@0: } sl@0: sl@0: inline TInt FindLeastSignificantZero(register TUint n, TUint aFrom) sl@0: { sl@0: n |= ((1<>=16, i+=16; sl@0: if (n<<24==0) n>>=8, i+=8; sl@0: if (n<<28==0) n>>=4, i+=4; sl@0: if (n<<30==0) n>>=2, i+=2; sl@0: if (n<<31==0) n>>=1, i+=1; sl@0: return i; sl@0: } sl@0: sl@0: inline TInt FindMostSignificantZero(register TUint n) sl@0: { sl@0: register TInt i=31; sl@0: n=~n; sl@0: if (n<0x00010000) n<<=16, i-=16; sl@0: if (n<0x01000000) n<<=8, i-=8; sl@0: if (n<0x10000000) n<<=4, i-=4; sl@0: if (n<0x40000000) n<<=2, i-=2; sl@0: if (n<0x80000000) n<<=1, i-=1; sl@0: return i; sl@0: } sl@0: sl@0: EXPORT_C CBitMapAllocator::CBitMapAllocator(TInt aSize,TInt aLength) sl@0: // sl@0: // Constructor sl@0: // sl@0: : iAvail(aSize),iSize(aSize),iLength(aLength) sl@0: { sl@0: TInt rem=aSize&KBitsPerIntMask; sl@0: if (rem) sl@0: { sl@0: TInt last=(aSize-1)>>KBitsPerIntShift; sl@0: iMap[last]=0xFFFFFFFFu<0,Panic(EBmaSizeLessOrEqualToZero)); sl@0: TInt sz=((aSize+KBitsPerIntMask)>>KBitsPerIntShift)-1; sl@0: return(new(sz*sizeof(TUint)) CBitMapAllocator(aSize,sz+1)); sl@0: } sl@0: sl@0: EXPORT_C CBitMapAllocator *CBitMapAllocator::NewL(TInt aSize) sl@0: // sl@0: // Create a new bit map allocator. Leave on any error. sl@0: // sl@0: { sl@0: CBitMapAllocator *pA=New(aSize); sl@0: User::LeaveIfNull(pA); sl@0: return(pA); sl@0: } sl@0: sl@0: EXPORT_C TInt CBitMapAllocator::Alloc() sl@0: // sl@0: // Allocate the next position. sl@0: // sl@0: { sl@0: if (iAvail) sl@0: { sl@0: TUint *pS=iMap; sl@0: TUint *pE=pS+iLength; sl@0: do { sl@0: register TUint n=*pS++; sl@0: if (n!=0xFFFFFFFFu) sl@0: { sl@0: iAvail--; sl@0: TInt bit=FindLeastSignificantZero(n); sl@0: *--pS=n|(1<=0 && aPos>KBitsPerIntShift); sl@0: TUint *pE=iMap+iLength; sl@0: TInt start=aPos&KBitsPerIntMask; sl@0: register TUint n; sl@0: if (start) sl@0: { sl@0: n=*pS++ | ~(0xFFFFFFFFu<pS); sl@0: Panic(EBmaInconsistentState); sl@0: } sl@0: return(KErrNoMemory); sl@0: } sl@0: sl@0: EXPORT_C TInt CBitMapAllocator::AllocFromTopFrom(TInt aPos) sl@0: // sl@0: // Allocate the next position after aPos. sl@0: // sl@0: { sl@0: __ASSERT_ALWAYS((aPos>=0 && aPos>KBitsPerIntShift); sl@0: TInt start=(aPos+1)&KBitsPerIntMask; sl@0: register TUint n; sl@0: if (start) sl@0: { sl@0: n=*pE | (0xFFFFFFFFu<pS) sl@0: { sl@0: n=*--pE; sl@0: if (n!=0xFFFFFFFFu) sl@0: { sl@0: found: sl@0: iAvail--; sl@0: TInt bit=FindMostSignificantZero(n); sl@0: *pE|=(1<0),Panic(EBmaAllocCountNegative)); sl@0: TInt initPos; sl@0: if (iAvail) sl@0: { sl@0: TUint *pS=iMap; sl@0: TUint *pE=pS+iLength; sl@0: register TUint n; sl@0: do { sl@0: n=*pS++; sl@0: if (n!=0xFFFFFFFFu) sl@0: goto found; sl@0: } while(pS>=bit; sl@0: if (n) sl@0: { sl@0: c=FindLeastSignificantOne(n); sl@0: if (aCount=aCount) sl@0: { sl@0: c=aCount; sl@0: if (c=KBitsPerInt) sl@0: *pS=0xFFFFFFFFu, c-=KBitsPerInt; sl@0: if (c && pSc) bit=c; sl@0: *pS |= ~(0xFFFFFFFFu<=0 && anAlignment<32),Panic(EBmaAllAlgnOutOfRange)); sl@0: if (iAvail==0) sl@0: return KErrNoMemory; sl@0: TUint mask; sl@0: TInt step; sl@0: if (anAlignment>=KBitsPerIntShift) sl@0: { sl@0: mask=0xFFFFFFFEu; sl@0: step=1<<(anAlignment-KBitsPerIntShift); sl@0: } sl@0: else sl@0: { sl@0: mask=AlignedSearchMask[anAlignment]; sl@0: step=1; sl@0: } sl@0: TUint *pM=iMap; sl@0: TUint *pE=pM+iLength; sl@0: do { sl@0: register TUint n=*pM | mask; sl@0: if (n!=0xFFFFFFFFu) sl@0: { sl@0: iAvail--; sl@0: TInt bit=(mask==0xFFFFFFFEu)?0:FindLeastSignificantZero(n); sl@0: *pM |= (1<=0 && anAlignment<32),Panic(EBmaAllAlgnBOutOfRange)); sl@0: if (iAvail==0) sl@0: return KErrNoMemory; sl@0: TInt blocksz=1<=KBitsPerIntShift) sl@0: { sl@0: mask=0xFFFFFFFEu; sl@0: step=1<<(anAlignment-KBitsPerIntShift); sl@0: block=0xFFFFFFFFu; sl@0: } sl@0: else sl@0: { sl@0: mask=AlignedSearchMask[anAlignment]; sl@0: step=1; sl@0: block=~(0xFFFFFFFFu<=KBitsPerInt) sl@0: { sl@0: n=0; sl@0: TUint *pS=pM+step; sl@0: if (pS<=pE) sl@0: { sl@0: do n|=*pM++; while(pM=0 && aPos>KBitsPerIntShift); sl@0: TUint mask=1<<(aPos&KBitsPerIntMask); sl@0: __ASSERT_ALWAYS(!(*pM&mask),Panic(EBmaAllocAtAlreadyAllocated)); sl@0: *pM |= mask; sl@0: iAvail--; sl@0: } sl@0: sl@0: EXPORT_C void CBitMapAllocator::AllocAt(TInt aPos, TInt aCount) sl@0: { sl@0: __ASSERT_ALWAYS((aPos>=0 && (aPos+aCount)<=iSize),Panic(EBmaAllocBlkOutOfRange)); sl@0: TUint *pM=iMap+(aPos>>KBitsPerIntShift); sl@0: TInt c=aPos&KBitsPerIntMask; sl@0: TUint m; sl@0: if (aCount<(KBitsPerInt-c)) sl@0: { sl@0: m=~(0xFFFFFFFFu<=KBitsPerInt) sl@0: { sl@0: if (*pM) sl@0: Panic(EBmaAllocBlkNotFree); sl@0: *pM++=0xFFFFFFFFu; sl@0: c-=KBitsPerInt; sl@0: } sl@0: if (c) sl@0: { sl@0: m=0xFFFFFFFFu>>(KBitsPerInt-c); sl@0: if (*pM & m) sl@0: Panic(EBmaAllocBlkNotFree); sl@0: *pM++ |= m; sl@0: } sl@0: iAvail-=aCount; sl@0: } sl@0: sl@0: EXPORT_C TInt CBitMapAllocator::ExtractRamPages(TInt aConsecutive,TInt& aPageNo) sl@0: { sl@0: if(iAvail iSize) sl@0: return KErrNoMemory; sl@0: if(IsFree(pos,aConsecutive)) sl@0: { sl@0: AllocAt(pos,aConsecutive); sl@0: aPageNo=pos; sl@0: return KErrNone; sl@0: } sl@0: else sl@0: { sl@0: x = bit+2; sl@0: } sl@0: } sl@0: while (x < KBitsPerInt); sl@0: } sl@0: } while(pS=0 && aPos>KBitsPerIntShift]; sl@0: return !(n>>(aPos&KBitsPerIntMask)&1); sl@0: } sl@0: sl@0: EXPORT_C TBool CBitMapAllocator::IsFree(TInt aPos, TInt aCount) sl@0: { sl@0: __ASSERT_ALWAYS((aPos>=0 && (aPos+aCount)<=iSize),Panic(EBmaChkBlkOutOfRange)); sl@0: TUint *pM=iMap+(aPos>>KBitsPerIntShift); sl@0: TUint m=*pM++; sl@0: TInt c=aPos&KBitsPerIntMask; sl@0: m>>=c; sl@0: if (aCount<(KBitsPerInt-c)) sl@0: { sl@0: return !(m&~(0xFFFFFFFFu<=KBitsPerInt) sl@0: { sl@0: m |= *pM++; sl@0: aCount-=KBitsPerInt; sl@0: } sl@0: if (aCount) sl@0: { sl@0: m|=(*pM<<(KBitsPerInt-aCount)); sl@0: } sl@0: return(!m); sl@0: } sl@0: sl@0: EXPORT_C void CBitMapAllocator::Free(TInt aPos) sl@0: // sl@0: // Free a position. sl@0: // sl@0: { sl@0: __ASSERT_ALWAYS(aPos>=0 && aPos>KBitsPerIntShift); sl@0: TUint mask=1<<(aPos&KBitsPerIntMask); sl@0: __ASSERT_ALWAYS((*pM&mask),Panic(EBmaFreeNotAllocated)); sl@0: *pM &= ~mask; sl@0: iAvail++; sl@0: } sl@0: sl@0: EXPORT_C void CBitMapAllocator::Free(TInt aPos, TInt aCount) sl@0: { sl@0: __ASSERT_ALWAYS((aPos>=0 && (aPos+aCount)<=iSize),Panic(EBmaFreeBlkOutOfRange)); sl@0: TUint *pM=iMap+(aPos>>KBitsPerIntShift); sl@0: TInt c=aPos&KBitsPerIntMask; sl@0: TUint m; sl@0: if (aCount<(KBitsPerInt-c)) sl@0: { sl@0: m=~(0xFFFFFFFFu<=KBitsPerInt) sl@0: { sl@0: if (*pM!=0xFFFFFFFF) sl@0: Panic(EBmaFreeBlkNotAllocated); sl@0: *pM++=0; sl@0: c-=KBitsPerInt; sl@0: } sl@0: if (c) sl@0: { sl@0: m=0xFFFFFFFFu>>(KBitsPerInt-c); sl@0: if ((*pM & m)!=m) sl@0: Panic(EBmaFreeBlkNotAllocated); sl@0: *pM++ &= ~m; sl@0: } sl@0: iAvail+=aCount; sl@0: } sl@0: sl@0: EXPORT_C TInt CBitMapAllocator::Avail() sl@0: // sl@0: // Get the available blocks count. sl@0: // sl@0: { sl@0: return(iAvail); sl@0: } sl@0: sl@0: EXPORT_C TInt CBitMapAllocator::Size() sl@0: // sl@0: // Get the size of all available blocks. sl@0: // sl@0: { sl@0: return(iSize); sl@0: } sl@0: