kernel/eka/memmodel/emul/win32/mprocess.cpp
changeset 0 a41df078684a
child 21 e7d2d738d3c2
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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