os/kernelhwsrv/userlibandfileserver/fileserver/sfile/sf_memory_client.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2008-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 // f32\sfile\sf_memory_client.cpp
    15 // 
    16 //
    17 
    18 /**
    19  @file
    20  @internalTechnology
    21 */
    22 
    23 #include <e32std.h>
    24 #include <e32std_private.h>
    25 #include "sf_std.h"
    26 #include <e32uid.h>
    27 #include <e32wins.h>
    28 #include <f32file.h>
    29 #include "sf_memory_man.h"
    30 #include "sf_memory_client.h"
    31 
    32 
    33 CCacheMemoryClient::~CCacheMemoryClient()
    34 	{
    35 	const TUint32 segCnt = iTouchedRegionFlag <= iReservedRegionMarkInSegs ? 
    36 										iReservedRegionMarkInSegs : iTouchedRegionFlag;
    37 	TInt r = DecommitSegments(iBase, segCnt);
    38 	if (r != KErrNone)  // this 'if() {}' is to remove build warnings
    39 	{
    40 	ASSERT(0);
    41 	}
    42 	iReusablePagePool.Close();
    43 	delete iName;
    44 	}
    45 
    46 /**
    47 Static factory function for CCacheMemoryClient
    48 @param	aManager	reference of CCacheMemoryManager that this client register with
    49 @param	aClientName	the unique identification of CCacheMemoryClient
    50 @param	aOffsetInBytes	the offset to the base position of CCacheMemoryManager it registered
    51 @param	aMinSizeInSegs	the minimum client size in segments, equals to the number of reserved segments
    52 @param	aMaxSizeInSegs	the maximum client size in segments
    53 */
    54 CCacheMemoryClient* CCacheMemoryClient::NewL(CCacheMemoryManager& aManager, const TDesC& aClientName, TUint32 aOffsetInBytes, TUint32 aMinSizeInSegs, TUint32 aMaxSizeInSegs)
    55 	{
    56 	// only create clients when sensible parameters are provided, otherwise will cause fatal error to file server 
    57 	if (aMinSizeInSegs > 0 && aMaxSizeInSegs >= aMinSizeInSegs && aClientName.Length() > 0)
    58 		{
    59 		CCacheMemoryClient* self = new(ELeave) CCacheMemoryClient(aManager, aMinSizeInSegs, aMaxSizeInSegs);
    60 		CleanupStack::PushL(self);
    61 		self->ConstructL(aClientName, aOffsetInBytes);
    62 		CleanupStack::Pop(1, self);
    63 		return self;
    64 		}
    65 	return NULL;
    66 	}
    67 
    68 /**
    69 Constructor of CCacheMemoryClient
    70 @param	aManager	reference of CCacheMemoryManager that this client register with
    71 @param	aMinSizeInSegs	the minimum client size in segments, equals to the number of reserved segments
    72 @param	aMaxSizeInSegs	the maximum client size in segments
    73 */
    74 CCacheMemoryClient::CCacheMemoryClient(CCacheMemoryManager& aManager, TUint32 aMinSizeInSegs, TUint32 aMaxSizeInSegs)
    75 :iManager(aManager),
    76 iMinSizeInSegs(aMinSizeInSegs),
    77 iMaxSizeInSegs(aMaxSizeInSegs)
    78 	{
    79 	}
    80 
    81 /**
    82 Second phase constructor of CCacheMemoryClient
    83 @param	aClientName	the unique identification of CCacheMemoryClient
    84 @param	aOffsetInBytes	the offset to the base position of CCacheMemoryManager it registered
    85 */
    86 void CCacheMemoryClient::ConstructL(const TDesC& aClientName, TUint32 aOffsetInBytes)
    87 	{
    88     __PRINT4(_L("CCacheMemoryClient::ConstructL(%S, min=%d, max=%d, base=0x%X)"), &aClientName, iMinSizeInSegs, iMaxSizeInSegs, iBase);
    89 	iName = HBufC::NewMaxL(aClientName.Length());
    90 	*iName = aClientName;
    91 	iSegSizeInBytesLog2 = iManager.SegmentSizeInBytesLog2();
    92 	iSegSizeInBytes = 1 << iSegSizeInBytesLog2;
    93 	iReusablePagePool.Close();
    94 	iReusablePagePool.ReserveL(iMinSizeInSegs);
    95 	iBase = iManager.Base() + aOffsetInBytes;
    96 	iReservedRegionMarkInSegs = iMinSizeInSegs;
    97 	TInt r = iManager.AllocateAndLockSegments(iBase, iReservedRegionMarkInSegs);
    98 	ASSERT(r==KErrNone);
    99 	User::LeaveIfError(r);
   100 	iTouchedRegionFlag = 0;
   101 	__PRINT(_L("CCacheMemoryClient::ConstructL() return 0"));
   102 	}
   103 
   104 /**
   105 Reset the client state, this is normally issued from the cache it connected with.
   106 For exmaple, a FAT volume is dismounted so the directory cache needs to be reset.
   107 Although the cache is reset, the CCacheMemoryClient object should not be destroyed and the reserved region should still 
   108 be hold to make sure when the cache re-connect with the CCacheMemoryClient, it will not fail due to OOM conditions.
   109 
   110 @internalTechnology
   111 @released
   112 */
   113 EXPORT_C void CCacheMemoryClient::Reset()
   114 	{
   115 	__PRINT3(_L("CCacheMemoryClient::Reset(%S, reserved=%d, touched=%d)"), iName, iReservedRegionMarkInSegs, iTouchedRegionFlag);
   116 	
   117 	// reset the cache memeory client to initial states: 
   118 	//     1. all memory that have been 'touched' should be decommitted
   119 	//     2. the reserved region of memory should be re-locked
   120 
   121 	// if we have touched more than reserved region of memory, we shall decommit all of them 
   122 	if (iTouchedRegionFlag > iReservedRegionMarkInSegs)
   123 	    {
   124 	    TInt r = DecommitSegments(iBase, iTouchedRegionFlag);
   125 	    if (r != KErrNone)  // this 'if() {}' is to remove build warnings in debug mode, same is below
   126 	        {
   127 	        ASSERT(0);
   128 	        }
   129 	    }
   130 	else   // otherwise we decommit the reserved region of memory only.
   131 	    {
   132 	    TInt r = DecommitSegments(iBase, iReservedRegionMarkInSegs);
   133 	    if (r != KErrNone)  // this 'if() {}' is to remove build warnings in debug mode, same is below
   134 	        {
   135 	        ASSERT(0);
   136 	        }
   137 	    }
   138 
   139     // re-lock the reserved region of memory
   140 	TInt r = iManager.AllocateAndLockSegments(iBase, iReservedRegionMarkInSegs);
   141     if (r != KErrNone)
   142         {
   143         ASSERT(0);
   144         }
   145 
   146 	iTouchedRegionFlag = 0;
   147 	iReusablePagePool.Close();
   148 	iReusablePagePool.Reserve(iReservedRegionMarkInSegs);
   149 	}
   150 
   151 /**
   152 Commit an unused set of contiguous segments. 
   153 @param	aSegmentCount	the segment number to be commited.
   154 @return	TUint8*	the starting ram address of the commited segments.
   155 
   156 @internalTechnology
   157 @released
   158 */
   159 EXPORT_C TUint8* CCacheMemoryClient::AllocateAndLockSegments(TUint32 aSegmentCount)
   160 	{
   161 	__PRINT4(_L("CCacheMemoryClient::AllocateAndLockSegments(%S, segs=%d, reserved=%d, touched=%d)"), iName, aSegmentCount, iReservedRegionMarkInSegs, iTouchedRegionFlag);
   162 //	__PRINT2(_L("iBase = 0x%x, segcnt = %d"), iBase, aSegmentCount);
   163     TUint8* addr = NULL;
   164     // if we are walking through the reserved region first time, we should
   165     // make assumption that this area is locked already
   166     if (iTouchedRegionFlag + aSegmentCount <= iReservedRegionMarkInSegs)
   167        	{
   168        	addr = iBase + (iTouchedRegionFlag << iSegSizeInBytesLog2);
   169        	iTouchedRegionFlag += aSegmentCount;
   170 //       	__PRINT3(_L("!! USED RESERVED SEGS: addr=0x%x, touched=%d, reserved=%d"), addr, iTouchedRegionFlag, iReservedRegionMarkInSegs);
   171        	return addr;
   172        	}
   173     
   174 	// if we have used up reserved region, get new pages from reusable pool first
   175     if (iReusablePagePool.Count())
   176     	{
   177 		addr = iReusablePagePool[0];
   178 		iReusablePagePool.Remove(0);
   179 //       	__PRINT2(_L("!! USED REUSABLE POOL SEGS: addr=0x%x, reusable.Count()=%d"), addr, iReusablePagePool.Count());
   180     	}
   181     // or we grow the touched region flag
   182     else
   183     	{
   184     	addr = iBase + (iTouchedRegionFlag << iSegSizeInBytesLog2);
   185     	iTouchedRegionFlag += aSegmentCount;
   186 //       	__PRINT2(_L("!! GROW TOUCHED SEGS: addr=0x%x, touched=%d"), addr, iTouchedRegionFlag);
   187     	}
   188 	
   189     // parameter validation
   190     ASSERT(((addr - iBase) >> iSegSizeInBytesLog2) + aSegmentCount <= iMaxSizeInSegs);
   191     if(((addr - iBase) >> iSegSizeInBytesLog2) + aSegmentCount > iMaxSizeInSegs)
   192     	{
   193     	ASSERT(0);
   194     	return NULL;
   195     	}
   196 
   197     TInt r = iManager.AllocateAndLockSegments(addr, aSegmentCount);
   198 	if (r != KErrNone)
   199 		return NULL;
   200 
   201 	return addr;
   202 	}
   203 
   204 /**
   205 Decommit a set of contiguous segments. 
   206 @param	aStartRamAddr	the start ram address of the region to be decommitted.
   207 @param	aSegmentCount	the segment number to be decommited.
   208 @return		KErrNone if succeed, otherwise a system-wide error code.
   209 
   210 @internalTechnology
   211 @released
   212 */
   213 EXPORT_C TInt CCacheMemoryClient::DecommitSegments(TUint8* aStartRamAddr, TUint32 aSegmentCount)
   214 	{
   215 	__PRINT4(_L("CCacheMemoryClient::DecommitSegments(%S, reserved=%d, touched=%d, segNo=%d)"), iName, iReservedRegionMarkInSegs, iTouchedRegionFlag, aSegmentCount);
   216 	// parameter validation
   217 	if(aStartRamAddr < iBase || 
   218 			(((aStartRamAddr - iBase) >> iSegSizeInBytesLog2) + aSegmentCount > iMaxSizeInSegs))
   219 		{
   220 		ASSERT(0);
   221 		return KErrArgument;
   222 		}
   223 	
   224 	TInt err = iManager.DecommitSegments(aStartRamAddr, aSegmentCount);
   225 	ASSERT(err == KErrNone);
   226 	if (err != KErrNone)
   227 		return err;
   228 	iReusablePagePool.Append(aStartRamAddr);
   229 	return KErrNone;
   230 	}
   231 
   232 /**
   233 Lock a set of contiguous segments. 
   234 @param	aStartRamAddr	the start ram address of the region to be locked.
   235 @param	aSegmentCount	the segment number to be locked.
   236 @return		KErrNone if succeed, otherwise a system-wide error code.
   237 
   238 @internalTechnology
   239 @released
   240 */
   241 EXPORT_C TInt CCacheMemoryClient::LockSegments(TUint8* aStartRamAddr, TUint32 aSegmentCount)
   242 	{
   243 	__PRINT4(_L("CCacheMemoryClient::LockSegments(%S, reserved=%d, touched=%d, segNo=%d)"), iName, iReservedRegionMarkInSegs, iTouchedRegionFlag, (aStartRamAddr - iBase) >> iSegSizeInBytesLog2);
   244 	// parameter validation
   245 	if(aStartRamAddr < iBase || 
   246 			(((aStartRamAddr - iBase) >> iSegSizeInBytesLog2) + aSegmentCount > iMaxSizeInSegs))
   247 		{
   248 		ASSERT(0);
   249 		return KErrArgument;
   250 		}
   251 	return iManager.LockSegments(aStartRamAddr, aSegmentCount);
   252 	}
   253 
   254 /**
   255 Unlock a set of contiguous segments. 
   256 @param	aStartRamAddr	the start ram address of the region to be unlocked.
   257 @param	aSegmentCount	the segment number to be unlocked.
   258 @return		KErrNone if succeed, otherwise a system-wide error code.
   259 
   260 @internalTechnology
   261 @released
   262 */
   263 EXPORT_C TInt CCacheMemoryClient::UnlockSegments(TUint8* aStartRamAddr, TUint32 aSegmentCount)
   264 	{
   265 	__PRINT4(_L("CCacheMemoryClient::UnlockSegments(%S, reserved=%d, touched=%d, segNo=%d)"), iName, iReservedRegionMarkInSegs, iTouchedRegionFlag, (aStartRamAddr - iBase) >> iSegSizeInBytesLog2);
   266 	// validate parameters
   267 	if(aStartRamAddr < iBase || 
   268 			(((aStartRamAddr - iBase) >> iSegSizeInBytesLog2) + aSegmentCount > iMaxSizeInSegs))
   269 		{
   270 		ASSERT(0);
   271 		return KErrArgument;
   272 		}
   273 	return iManager.UnlockSegments(aStartRamAddr, aSegmentCount);
   274 	}
   275 
   276 //////////////////////////// auxiliary functions /////////////////////////
   277 TUint32 CCacheMemoryClient::MaxSizeInBytes()
   278 	{
   279 	return iMaxSizeInSegs  << iSegSizeInBytesLog2;
   280 	}
   281 
   282 const TDesC& CCacheMemoryClient::Name() const
   283 	{
   284 	return *iName;
   285 	}
   286