os/kernelhwsrv/kernel/eka/memmodel/emul/win32/mprocess.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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\memmodel\emul\win32\mprocess.cpp
    15 // 
    16 //
    17 
    18 #include "memmodel.h"
    19 #include <property.h>
    20 #include <emulator.h>
    21 #include <wchar.h>
    22 
    23 #define iMState		iWaitLink.iSpare1
    24 
    25 extern const char* JustInTime;
    26 extern TBool DisableWSDWarning;
    27 const TInt KMaxWsdDllsPerProcess = 256;
    28 
    29 /********************************************
    30  * Process
    31  ********************************************/
    32 DWin32Process::DWin32Process()
    33 : iDllData(KMaxWsdDllsPerProcess, _FOFF(SProcessDllDataBlock,iCodeSeg))
    34 	{
    35 	// Set process JustInTime flag from the emulator property.  This is not set
    36 	// for the process containing supervisor thread.
    37 	if (JustInTime && !_stricmp(JustInTime, "none"))
    38 			{
    39 			iFlags &= !KProcessFlagJustInTime;
    40 			}
    41 	}
    42 
    43 DWin32Process::~DWin32Process()
    44 	{
    45 	__KTRACE_OPT(KMMU,Kern::Printf("DWin32Process destruct"));
    46 	Destruct();
    47 	RemoveDllData();
    48 	iDllData.Close();
    49 	}
    50 
    51 TInt DWin32Process::NewChunk(DChunk*& aChunk, SChunkCreateInfo& aInfo, TLinAddr& aRunAddr)
    52 	{
    53 	aChunk=NULL;
    54 	DWin32Chunk* pC=new DWin32Chunk;
    55 	if (!pC)
    56 		return KErrNoMemory;
    57 	pC->iChunkType=aInfo.iType;
    58 	if (!aInfo.iGlobal && (iAttributes & DWin32Process::EPrivate)!=0)
    59 		pC->iAttributes |= DWin32Chunk::EPrivate;
    60 	pC->iOwningProcess=(aInfo.iGlobal)?NULL:this;
    61 	TInt r=pC->Create(aInfo);
    62 	if (r==KErrNone && (aInfo.iOperations & SChunkCreateInfo::EAdjust))
    63 		{
    64 		__ASSERT_ALWAYS(aInfo.iRunAddress==0,MM::Panic(MM::EInvalidChunkCreate));
    65 		if (aInfo.iPreallocated==0)
    66 			{
    67 			if (pC->iAttributes & DChunk::EDisconnected)
    68 				{
    69 				r=pC->Commit(aInfo.iInitialBottom,aInfo.iInitialTop-aInfo.iInitialBottom);
    70 				}
    71 			else if (pC->iAttributes & DChunk::EDoubleEnded)
    72 				{
    73 				r=pC->AdjustDoubleEnded(aInfo.iInitialBottom,aInfo.iInitialTop);
    74 				}
    75 			else
    76 				{
    77 				r=pC->Adjust(aInfo.iInitialTop);
    78 				}
    79 			}
    80 		if (r==KErrNone)
    81 			{
    82 			aRunAddr=(TLinAddr)pC->Base();
    83 			}
    84 		}
    85 	if (r==KErrNone)
    86 		{
    87 		pC->iDestroyedDfc = aInfo.iDestroyedDfc;
    88 		aChunk=(DChunk*)pC;
    89 		}
    90 	else
    91 		pC->Close(NULL);	// NULL since chunk can't have been added to process
    92 	return r;
    93 	}
    94 
    95 TInt DWin32Process::DoCreate(TBool aKernelProcess, TProcessCreateInfo& /*aInfo*/)
    96 	{
    97 	__KTRACE_OPT(KPROC,Kern::Printf("DWin32Process::DoCreate %O",this))
    98 	iAttributes=aKernelProcess ? ESupervisor|EPrivate : 0;
    99 	// force iDllData to reserve KMaxWsdDllsPerProcess. The Append will
   100 	// create the space, the Remove will not free it.
   101 	SProcessDllDataBlock data = {0,0,0};
   102 	TInt err = iDllData.Append(data);
   103 	if(err==KErrNone) 
   104 		{
   105 			__ASSERT_ALWAYS(iDllData.Count()==1,MM::Panic(MM::EWsdBadReserve));
   106 			iDllData.Remove(0);
   107 		}
   108 	return err;
   109 	}
   110 
   111 TInt DWin32Process::CreateDataBssStackArea(TProcessCreateInfo& /*aInfo*/)
   112 //
   113 // This is managed for us by win32
   114 //
   115 	{
   116 	__KTRACE_OPT(KPROC,Kern::Printf("DWin32Process::CreateDataBssStackArea %O",this));
   117 	return KErrNone;
   118 	}
   119 
   120 TInt DWin32Process::AddChunk(DChunk* /*aChunk*/,TBool /*isReadOnly*/)
   121 	{
   122 	return KErrNone;
   123 	}
   124 
   125 
   126 TInt DWin32Process::NewShPool(DShPool*& aPool, TShPoolCreateInfo& aInfo)
   127 	{
   128 	aPool = NULL;
   129 	DWin32ShPool* pC = NULL;
   130 
   131 	if (aInfo.iInfo.iFlags & TShPoolCreateInfo::EPageAlignedBuffer)
   132 		{
   133 		pC = new DWin32AlignedShPool();
   134 		}
   135 	else
   136 		{
   137 		pC = new DWin32NonAlignedShPool();
   138 		}
   139 
   140 	if (pC == NULL)
   141 		{
   142 		return KErrNoMemory;
   143 		}
   144 
   145 	TInt r = pC->Create(this, aInfo);
   146 
   147 	if (r == KErrNone)
   148 		{
   149 		aPool = pC;
   150 		}
   151 	else
   152 		{
   153 		pC->Close(NULL);
   154 		}
   155 
   156 	return r;
   157 	} // DWin32Process::NewShPool
   158 
   159 
   160 void DWin32Process::Release()
   161 	{
   162 	CallRuntimeHook(EWin32RuntimeProcessDetach);
   163 	DProcess::Release();
   164 	}
   165 
   166 void DWin32Process::FinalRelease()
   167 	{
   168 	}
   169 
   170 TInt DWin32Process::MapCodeSeg(DCodeSeg* aSeg)
   171 	{
   172 	
   173 	__KTRACE_OPT(KDLL,Kern::Printf("Process %O MapCodeSeg(%C)", this, aSeg));
   174 	if (!aSeg || !aSeg->IsDll())
   175 		return KErrNone;
   176 	
   177 	DWin32CodeSeg* seg = (DWin32CodeSeg*)aSeg;
   178 	if (seg->iRealDataSize == 0 && seg->iRealBssSize == 0)
   179 		return KErrNone;
   180 	
   181 	if (!DisableWSDWarning && this!=K::TheKernelProcess) 
   182         Kern::Printf("WARNING!!: WSD Lib Loaded- Process %O, has loaded Lib %C"
   183                      " which has %d bytes of WSD",this,aSeg,
   184                      seg->iRealDataSize + seg->iRealBssSize);
   185 	
   186 	// remove any existing copy of this code seg (should never happen)
   187 	UnmapCodeSeg(aSeg);
   188 	
   189 	SProcessDllDataBlock data;
   190 	data.iCodeSeg = seg;
   191 	
   192 	TInt count=0;
   193 	TInt err = KErrNone;
   194 	data.iDataCopy = Kern::Alloc(seg->iRealDataSize);
   195 	data.iBssCopy = Kern::Alloc(seg->iRealBssSize);
   196 	if (!data.iDataCopy || !data.iBssCopy)
   197 		{
   198 		err = KErrNoMemory;
   199 		goto failed;
   200 		}
   201 		
   202 	memcpy(data.iDataCopy, seg->iDataCopy, seg->iRealDataSize);	// start with init data
   203 	memclr(data.iBssCopy, seg->iRealBssSize);					// initialized to zeros
   204 
   205 	NKern::Lock();
   206 	count = iDllData.Count();
   207 	if (count == KMaxWsdDllsPerProcess)
   208 		err = KErrOverflow;
   209 	if (!err)
   210 		err = iDllData.InsertInUnsignedKeyOrder(data);
   211 	NKern::Unlock();
   212 	if (err)
   213 		goto failed;
   214 			
   215 	return KErrNone;	
   216 
   217 failed:
   218 	Kern::Free(data.iDataCopy);
   219 	Kern::Free(data.iBssCopy);
   220 
   221 	return err;
   222 	}
   223 
   224 void DWin32Process::UnmapCodeSeg(DCodeSeg* aSeg)
   225 	{
   226 	if (!aSeg || !aSeg->IsDll())
   227 		return;
   228 	
   229 	DWin32CodeSeg* seg = (DWin32CodeSeg*)aSeg;
   230 	if (seg->iRealDataSize == 0 && seg->iRealBssSize == 0)
   231 		return;
   232 		
   233 	SProcessDllDataBlock data;
   234 	data.iCodeSeg = seg;
   235 	NKern::Lock();
   236 	if (seg->iLiveProcess == this)
   237 		seg->iLiveProcess = NULL;
   238 	TInt ix = iDllData.FindInUnsignedKeyOrder(data);
   239 	if (ix >= 0)
   240 		{
   241 		data = iDllData[ix];
   242 		iDllData.Remove(ix);
   243 		}
   244 	NKern::Unlock();
   245 	
   246 	if (ix < 0)
   247 		return;
   248 	
   249 	Kern::Free(data.iDataCopy);
   250 	Kern::Free(data.iBssCopy);
   251 	__KTRACE_OPT(KDLL,Kern::Printf("Process %O UnmapCodeSeg(%C)", this, aSeg));
   252 	}
   253 
   254 void DWin32Process::RemoveDllData()
   255 	{
   256 	// unmap all DLL data with kernel locked
   257 	TInt count = iDllData.Count();
   258 	for (TInt ii=count-1; ii>=0; ii--)
   259 		{
   260 		SProcessDllDataBlock data = iDllData[ii];
   261 		NKern::Lock();
   262 		if (data.iCodeSeg->iLiveProcess == this)
   263 			data.iCodeSeg->iLiveProcess = NULL;
   264 		NKern::Unlock();
   265 		iDllData.Remove(ii);
   266 		Kern::Free(data.iDataCopy);
   267 		Kern::Free(data.iBssCopy);
   268 		}
   269 	}
   270 
   271 TInt DWin32Process::AttachExistingCodeSeg(TProcessCreateInfo& /*aInfo*/)
   272 	{
   273 	return KErrNotSupported;	// never allowed
   274 	}
   275 
   276 void DWin32Process::CallRuntimeHook(TWin32RuntimeReason aReason)
   277 	{
   278 	if (iWin32RuntimeHook)
   279 		{
   280 		SchedulerLock();
   281 		TBool ok = iWin32RuntimeHook(aReason);
   282 		SchedulerUnlock();
   283 		if (!ok && aReason != EWin32RuntimeProcessDetach)
   284 			Kern::PanicCurrentThread(_L("MemModel"), MM::EWin32RuntimeError);
   285 		}
   286 	}
   287 
   288 
   289 void DThread::IpcExcHandler(TExcTrap* aTrap, DThread* aThread, TAny* aContext)
   290 	{
   291 	aThread->iIpcClient = 0;
   292 	TIpcExcTrap& xt=*(TIpcExcTrap*)aTrap;
   293 	TWin32ExcInfo& info=*(TWin32ExcInfo*)aContext;
   294 	TLinAddr va=(TLinAddr)info.iExcDataAddress;
   295 	if (va>=xt.iRemoteBase && (va-xt.iRemoteBase)<xt.iSize)
   296 		xt.Exception(KErrBadDescriptor);	// problem accessing remote address - 'leave' so an error code will be returned
   297 	if (xt.iLocalBase && va>=xt.iLocalBase && (va-xt.iLocalBase)<xt.iSize)
   298 		NKern::UnlockSystem();		// problem accessing local address - return and panic current thread as usual
   299 	// otherwise return and fault kernel
   300 	}
   301 
   302 TInt DThread::RawRead(const TAny* aSrc, TAny* aDest, TInt aLength, TInt /*aFlags*/, TIpcExcTrap* /*aExcTrap*/)
   303 //
   304 // Read from the thread's process.
   305 // aSrc is run address of memory to read
   306 // aDest is current address of destination
   307 // Enter and leave with system locked
   308 //
   309 	{
   310 	if (iMState==EDead)
   311 		return KErrDied;
   312 	const TUint8* pS=(const TUint8*)aSrc;
   313 	TUint8* pD=(TUint8*)aDest;
   314 	TBool kernelLocked = EFalse;
   315 	const TUint8* pC=(const TUint8*)MM::CurrentAddress(this,pS,aLength,EFalse,kernelLocked);
   316 	if (kernelLocked)
   317 		{
   318 		// kernel locked because of DLL WSD IPC, do it all in one big block
   319 		TInt r = KErrNone;
   320 		__KTRACE_OPT(KTHREAD2,Kern::Printf("DThread::RawRead %08x",pC));
   321 		if (!pC)
   322 			r = KErrBadDescriptor;
   323 		else
   324 			memcpy(pD,pC,aLength);
   325 		NKern::Unlock();
   326 		return r;
   327 		}
   328 	TBool check=ETrue;
   329 	while (aLength)
   330 		{
   331 		if (check)
   332 			{
   333 			if (iMState==EDead)
   334 				return KErrDied;
   335 			__KTRACE_OPT(KTHREAD2,Kern::Printf("DThread::Read %08x",pS));
   336 			}
   337 		TInt l=Min(aLength,K::MaxMemCopyInOneGo);
   338 		memcpy(pD,pS,l);
   339 		pD+=l;
   340 		pS+=l;
   341 		aLength-=l;
   342 		if (aLength)
   343 			check=NKern::FlashSystem();
   344 		}
   345 	return KErrNone;
   346 	}
   347 
   348 TInt DThread::RawWrite(const TAny* aDest, const TAny* aSrc, TInt aLength, TInt /*aFlags*/, DThread* /*anOriginatingThread*/, TIpcExcTrap* /*aExcTrap*/)
   349 //
   350 // Write to the thread's process.
   351 // aDest is run address of memory to write
   352 // aSrc is current address of destination
   353 // anOriginatingThread is the thread on behalf of which this operation is performed (eg client of device driver).
   354 // Enter and leave with system locked
   355 //
   356 	{
   357 	if (iMState==EDead)
   358 		return KErrDied;
   359 	TUint8* pD=(TUint8*)aDest;
   360 	const TUint8* pS=(const TUint8*)aSrc;
   361 	TBool kernelLocked = EFalse;
   362 	TUint8* pC=(TUint8*)MM::CurrentAddress(this,pD,aLength,ETrue,kernelLocked);
   363 	if (kernelLocked)
   364 		{
   365 		// kernel locked because of DLL WSD IPC, do it all in one big block
   366 		TInt r = KErrNone;
   367 		__KTRACE_OPT(KTHREAD2,Kern::Printf("DThread::RawWrite %08x",pC));
   368 		if (!pC)
   369 			r = KErrBadDescriptor;
   370 		else
   371 			memcpy(pC,pS,aLength);
   372 		NKern::Unlock();
   373 		return r;
   374 		}
   375 	TBool check=ETrue;
   376 	while (aLength)
   377 		{
   378 		if (check)
   379 			{
   380 			if (iMState==EDead)
   381 				return KErrDied;
   382 			__KTRACE_OPT(KTHREAD2,Kern::Printf("DThread::Write %08x",pD));
   383 			}
   384 		TInt l=Min(aLength,K::MaxMemCopyInOneGo);
   385 		memcpy(pD,pS,l);
   386 		pD+=l;
   387 		pS+=l;
   388 		aLength-=l;
   389 		if (aLength)
   390 			check=NKern::FlashSystem();
   391 		}
   392 	return KErrNone;
   393 	}
   394 
   395 TInt DThread::ReadAndParseDesHeader(const TAny* aSrc, TDesHeader& aDest)
   396 //
   397 // Read and parse the header of a remote descriptor.
   398 // Enter and leave with system locked.
   399 //
   400 	{
   401 	__ASSERT_SYSTEM_LOCK;
   402 	static const TUint8 LengthLookup[16]={4,8,12,8,12,0,0,0,0,0,0,0,0,0,0,0};
   403 	if (iMState == EDead)
   404 		return KErrDied;
   405 	TBool kernelLocked = EFalse;
   406 	const TUint32* pS=(const TUint32*)MM::CurrentAddress(this,aSrc,sizeof(TDesC8),EFalse,kernelLocked);
   407 	if (!pS || (TInt(pS)&3)!=0)
   408 		{
   409 		if (kernelLocked)
   410 			NKern::Unlock();
   411 		return KErrBadDescriptor;
   412 		}
   413 	TInt type=0;
   414 	XTRAPD(r, XT_DEFAULT,					\
   415 		type=*pS>>KShiftDesType8;			\
   416 		TInt l=LengthLookup[type];			\
   417 		if (l==0)							\
   418 			r=KErrBadDescriptor;			\
   419 		else								\
   420 			wordmove(&aDest,pS,l);			\
   421 		);
   422 	if (kernelLocked)
   423 		NKern::Unlock();
   424 	if (r!=KErrNone)
   425 		return r;
   426 	return K::ParseDesHeader(aSrc, (TRawDesHeader&)aDest, aDest);
   427 	}
   428 
   429 DChunk* DThread::OpenSharedChunk(const TAny* aAddress, TBool /*aWrite*/, TInt& aOffset)
   430 	{
   431 	DWin32Chunk* chunk=0;
   432 	DObjectCon& chunks=*K::Containers[EChunk];
   433 	chunks.Wait();
   434 	TInt count=chunks.Count();
   435 	TInt i;
   436 	TUint offset=0;
   437 	for(i=0;i<count;i++)
   438 		{
   439 		DWin32Chunk* pC=(DWin32Chunk*)chunks[i];
   440 		offset = (TUint)aAddress-(TUint)pC->Base();
   441 		if(offset<TUint(pC->iMaxSize))
   442 			{
   443 			chunk = pC;
   444 			break;
   445 			}
   446 		}
   447 	chunks.Signal();
   448 
   449 	if(!chunk)
   450 		return 0;
   451 
   452 	if((chunk->iChunkType!=ESharedKernelSingle && chunk->iChunkType!=ESharedKernelMultiple))
   453 		return 0;
   454 	if(chunk->Open()!=KErrNone)
   455 		return 0;
   456 	aOffset = offset;
   457 	return chunk;
   458 	}
   459 
   460 TInt DThread::PrepareMemoryForDMA(const TAny* /*aLinAddr*/, TInt /*aSize*/, TPhysAddr* /*aPhysicalPageList*/)
   461 	{
   462 	return KErrNotSupported;
   463 	}
   464 
   465 TInt DThread::ReleaseMemoryFromDMA(const TAny* /*aLinAddr*/, TInt /*aSize*/, TPhysAddr* /*aPhysicalPageList*/)
   466 	{
   467 	return KErrNotSupported;
   468 	}
   469