1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/memmodel/emul/win32/mprocess.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,469 @@
1.4 +// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32\memmodel\emul\win32\mprocess.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#include "memmodel.h"
1.22 +#include <property.h>
1.23 +#include <emulator.h>
1.24 +#include <wchar.h>
1.25 +
1.26 +#define iMState iWaitLink.iSpare1
1.27 +
1.28 +extern const char* JustInTime;
1.29 +extern TBool DisableWSDWarning;
1.30 +const TInt KMaxWsdDllsPerProcess = 256;
1.31 +
1.32 +/********************************************
1.33 + * Process
1.34 + ********************************************/
1.35 +DWin32Process::DWin32Process()
1.36 +: iDllData(KMaxWsdDllsPerProcess, _FOFF(SProcessDllDataBlock,iCodeSeg))
1.37 + {
1.38 + // Set process JustInTime flag from the emulator property. This is not set
1.39 + // for the process containing supervisor thread.
1.40 + if (JustInTime && !_stricmp(JustInTime, "none"))
1.41 + {
1.42 + iFlags &= !KProcessFlagJustInTime;
1.43 + }
1.44 + }
1.45 +
1.46 +DWin32Process::~DWin32Process()
1.47 + {
1.48 + __KTRACE_OPT(KMMU,Kern::Printf("DWin32Process destruct"));
1.49 + Destruct();
1.50 + RemoveDllData();
1.51 + iDllData.Close();
1.52 + }
1.53 +
1.54 +TInt DWin32Process::NewChunk(DChunk*& aChunk, SChunkCreateInfo& aInfo, TLinAddr& aRunAddr)
1.55 + {
1.56 + aChunk=NULL;
1.57 + DWin32Chunk* pC=new DWin32Chunk;
1.58 + if (!pC)
1.59 + return KErrNoMemory;
1.60 + pC->iChunkType=aInfo.iType;
1.61 + if (!aInfo.iGlobal && (iAttributes & DWin32Process::EPrivate)!=0)
1.62 + pC->iAttributes |= DWin32Chunk::EPrivate;
1.63 + pC->iOwningProcess=(aInfo.iGlobal)?NULL:this;
1.64 + TInt r=pC->Create(aInfo);
1.65 + if (r==KErrNone && (aInfo.iOperations & SChunkCreateInfo::EAdjust))
1.66 + {
1.67 + __ASSERT_ALWAYS(aInfo.iRunAddress==0,MM::Panic(MM::EInvalidChunkCreate));
1.68 + if (aInfo.iPreallocated==0)
1.69 + {
1.70 + if (pC->iAttributes & DChunk::EDisconnected)
1.71 + {
1.72 + r=pC->Commit(aInfo.iInitialBottom,aInfo.iInitialTop-aInfo.iInitialBottom);
1.73 + }
1.74 + else if (pC->iAttributes & DChunk::EDoubleEnded)
1.75 + {
1.76 + r=pC->AdjustDoubleEnded(aInfo.iInitialBottom,aInfo.iInitialTop);
1.77 + }
1.78 + else
1.79 + {
1.80 + r=pC->Adjust(aInfo.iInitialTop);
1.81 + }
1.82 + }
1.83 + if (r==KErrNone)
1.84 + {
1.85 + aRunAddr=(TLinAddr)pC->Base();
1.86 + }
1.87 + }
1.88 + if (r==KErrNone)
1.89 + {
1.90 + pC->iDestroyedDfc = aInfo.iDestroyedDfc;
1.91 + aChunk=(DChunk*)pC;
1.92 + }
1.93 + else
1.94 + pC->Close(NULL); // NULL since chunk can't have been added to process
1.95 + return r;
1.96 + }
1.97 +
1.98 +TInt DWin32Process::DoCreate(TBool aKernelProcess, TProcessCreateInfo& /*aInfo*/)
1.99 + {
1.100 + __KTRACE_OPT(KPROC,Kern::Printf("DWin32Process::DoCreate %O",this))
1.101 + iAttributes=aKernelProcess ? ESupervisor|EPrivate : 0;
1.102 + // force iDllData to reserve KMaxWsdDllsPerProcess. The Append will
1.103 + // create the space, the Remove will not free it.
1.104 + SProcessDllDataBlock data = {0,0,0};
1.105 + TInt err = iDllData.Append(data);
1.106 + if(err==KErrNone)
1.107 + {
1.108 + __ASSERT_ALWAYS(iDllData.Count()==1,MM::Panic(MM::EWsdBadReserve));
1.109 + iDllData.Remove(0);
1.110 + }
1.111 + return err;
1.112 + }
1.113 +
1.114 +TInt DWin32Process::CreateDataBssStackArea(TProcessCreateInfo& /*aInfo*/)
1.115 +//
1.116 +// This is managed for us by win32
1.117 +//
1.118 + {
1.119 + __KTRACE_OPT(KPROC,Kern::Printf("DWin32Process::CreateDataBssStackArea %O",this));
1.120 + return KErrNone;
1.121 + }
1.122 +
1.123 +TInt DWin32Process::AddChunk(DChunk* /*aChunk*/,TBool /*isReadOnly*/)
1.124 + {
1.125 + return KErrNone;
1.126 + }
1.127 +
1.128 +
1.129 +TInt DWin32Process::NewShPool(DShPool*& aPool, TShPoolCreateInfo& aInfo)
1.130 + {
1.131 + aPool = NULL;
1.132 + DWin32ShPool* pC = NULL;
1.133 +
1.134 + if (aInfo.iInfo.iFlags & TShPoolCreateInfo::EPageAlignedBuffer)
1.135 + {
1.136 + pC = new DWin32AlignedShPool();
1.137 + }
1.138 + else
1.139 + {
1.140 + pC = new DWin32NonAlignedShPool();
1.141 + }
1.142 +
1.143 + if (pC == NULL)
1.144 + {
1.145 + return KErrNoMemory;
1.146 + }
1.147 +
1.148 + TInt r = pC->Create(this, aInfo);
1.149 +
1.150 + if (r == KErrNone)
1.151 + {
1.152 + aPool = pC;
1.153 + }
1.154 + else
1.155 + {
1.156 + pC->Close(NULL);
1.157 + }
1.158 +
1.159 + return r;
1.160 + } // DWin32Process::NewShPool
1.161 +
1.162 +
1.163 +void DWin32Process::Release()
1.164 + {
1.165 + CallRuntimeHook(EWin32RuntimeProcessDetach);
1.166 + DProcess::Release();
1.167 + }
1.168 +
1.169 +void DWin32Process::FinalRelease()
1.170 + {
1.171 + }
1.172 +
1.173 +TInt DWin32Process::MapCodeSeg(DCodeSeg* aSeg)
1.174 + {
1.175 +
1.176 + __KTRACE_OPT(KDLL,Kern::Printf("Process %O MapCodeSeg(%C)", this, aSeg));
1.177 + if (!aSeg || !aSeg->IsDll())
1.178 + return KErrNone;
1.179 +
1.180 + DWin32CodeSeg* seg = (DWin32CodeSeg*)aSeg;
1.181 + if (seg->iRealDataSize == 0 && seg->iRealBssSize == 0)
1.182 + return KErrNone;
1.183 +
1.184 + if (!DisableWSDWarning && this!=K::TheKernelProcess)
1.185 + Kern::Printf("WARNING!!: WSD Lib Loaded- Process %O, has loaded Lib %C"
1.186 + " which has %d bytes of WSD",this,aSeg,
1.187 + seg->iRealDataSize + seg->iRealBssSize);
1.188 +
1.189 + // remove any existing copy of this code seg (should never happen)
1.190 + UnmapCodeSeg(aSeg);
1.191 +
1.192 + SProcessDllDataBlock data;
1.193 + data.iCodeSeg = seg;
1.194 +
1.195 + TInt count=0;
1.196 + TInt err = KErrNone;
1.197 + data.iDataCopy = Kern::Alloc(seg->iRealDataSize);
1.198 + data.iBssCopy = Kern::Alloc(seg->iRealBssSize);
1.199 + if (!data.iDataCopy || !data.iBssCopy)
1.200 + {
1.201 + err = KErrNoMemory;
1.202 + goto failed;
1.203 + }
1.204 +
1.205 + memcpy(data.iDataCopy, seg->iDataCopy, seg->iRealDataSize); // start with init data
1.206 + memclr(data.iBssCopy, seg->iRealBssSize); // initialized to zeros
1.207 +
1.208 + NKern::Lock();
1.209 + count = iDllData.Count();
1.210 + if (count == KMaxWsdDllsPerProcess)
1.211 + err = KErrOverflow;
1.212 + if (!err)
1.213 + err = iDllData.InsertInUnsignedKeyOrder(data);
1.214 + NKern::Unlock();
1.215 + if (err)
1.216 + goto failed;
1.217 +
1.218 + return KErrNone;
1.219 +
1.220 +failed:
1.221 + Kern::Free(data.iDataCopy);
1.222 + Kern::Free(data.iBssCopy);
1.223 +
1.224 + return err;
1.225 + }
1.226 +
1.227 +void DWin32Process::UnmapCodeSeg(DCodeSeg* aSeg)
1.228 + {
1.229 + if (!aSeg || !aSeg->IsDll())
1.230 + return;
1.231 +
1.232 + DWin32CodeSeg* seg = (DWin32CodeSeg*)aSeg;
1.233 + if (seg->iRealDataSize == 0 && seg->iRealBssSize == 0)
1.234 + return;
1.235 +
1.236 + SProcessDllDataBlock data;
1.237 + data.iCodeSeg = seg;
1.238 + NKern::Lock();
1.239 + if (seg->iLiveProcess == this)
1.240 + seg->iLiveProcess = NULL;
1.241 + TInt ix = iDllData.FindInUnsignedKeyOrder(data);
1.242 + if (ix >= 0)
1.243 + {
1.244 + data = iDllData[ix];
1.245 + iDllData.Remove(ix);
1.246 + }
1.247 + NKern::Unlock();
1.248 +
1.249 + if (ix < 0)
1.250 + return;
1.251 +
1.252 + Kern::Free(data.iDataCopy);
1.253 + Kern::Free(data.iBssCopy);
1.254 + __KTRACE_OPT(KDLL,Kern::Printf("Process %O UnmapCodeSeg(%C)", this, aSeg));
1.255 + }
1.256 +
1.257 +void DWin32Process::RemoveDllData()
1.258 + {
1.259 + // unmap all DLL data with kernel locked
1.260 + TInt count = iDllData.Count();
1.261 + for (TInt ii=count-1; ii>=0; ii--)
1.262 + {
1.263 + SProcessDllDataBlock data = iDllData[ii];
1.264 + NKern::Lock();
1.265 + if (data.iCodeSeg->iLiveProcess == this)
1.266 + data.iCodeSeg->iLiveProcess = NULL;
1.267 + NKern::Unlock();
1.268 + iDllData.Remove(ii);
1.269 + Kern::Free(data.iDataCopy);
1.270 + Kern::Free(data.iBssCopy);
1.271 + }
1.272 + }
1.273 +
1.274 +TInt DWin32Process::AttachExistingCodeSeg(TProcessCreateInfo& /*aInfo*/)
1.275 + {
1.276 + return KErrNotSupported; // never allowed
1.277 + }
1.278 +
1.279 +void DWin32Process::CallRuntimeHook(TWin32RuntimeReason aReason)
1.280 + {
1.281 + if (iWin32RuntimeHook)
1.282 + {
1.283 + SchedulerLock();
1.284 + TBool ok = iWin32RuntimeHook(aReason);
1.285 + SchedulerUnlock();
1.286 + if (!ok && aReason != EWin32RuntimeProcessDetach)
1.287 + Kern::PanicCurrentThread(_L("MemModel"), MM::EWin32RuntimeError);
1.288 + }
1.289 + }
1.290 +
1.291 +
1.292 +void DThread::IpcExcHandler(TExcTrap* aTrap, DThread* aThread, TAny* aContext)
1.293 + {
1.294 + aThread->iIpcClient = 0;
1.295 + TIpcExcTrap& xt=*(TIpcExcTrap*)aTrap;
1.296 + TWin32ExcInfo& info=*(TWin32ExcInfo*)aContext;
1.297 + TLinAddr va=(TLinAddr)info.iExcDataAddress;
1.298 + if (va>=xt.iRemoteBase && (va-xt.iRemoteBase)<xt.iSize)
1.299 + xt.Exception(KErrBadDescriptor); // problem accessing remote address - 'leave' so an error code will be returned
1.300 + if (xt.iLocalBase && va>=xt.iLocalBase && (va-xt.iLocalBase)<xt.iSize)
1.301 + NKern::UnlockSystem(); // problem accessing local address - return and panic current thread as usual
1.302 + // otherwise return and fault kernel
1.303 + }
1.304 +
1.305 +TInt DThread::RawRead(const TAny* aSrc, TAny* aDest, TInt aLength, TInt /*aFlags*/, TIpcExcTrap* /*aExcTrap*/)
1.306 +//
1.307 +// Read from the thread's process.
1.308 +// aSrc is run address of memory to read
1.309 +// aDest is current address of destination
1.310 +// Enter and leave with system locked
1.311 +//
1.312 + {
1.313 + if (iMState==EDead)
1.314 + return KErrDied;
1.315 + const TUint8* pS=(const TUint8*)aSrc;
1.316 + TUint8* pD=(TUint8*)aDest;
1.317 + TBool kernelLocked = EFalse;
1.318 + const TUint8* pC=(const TUint8*)MM::CurrentAddress(this,pS,aLength,EFalse,kernelLocked);
1.319 + if (kernelLocked)
1.320 + {
1.321 + // kernel locked because of DLL WSD IPC, do it all in one big block
1.322 + TInt r = KErrNone;
1.323 + __KTRACE_OPT(KTHREAD2,Kern::Printf("DThread::RawRead %08x",pC));
1.324 + if (!pC)
1.325 + r = KErrBadDescriptor;
1.326 + else
1.327 + memcpy(pD,pC,aLength);
1.328 + NKern::Unlock();
1.329 + return r;
1.330 + }
1.331 + TBool check=ETrue;
1.332 + while (aLength)
1.333 + {
1.334 + if (check)
1.335 + {
1.336 + if (iMState==EDead)
1.337 + return KErrDied;
1.338 + __KTRACE_OPT(KTHREAD2,Kern::Printf("DThread::Read %08x",pS));
1.339 + }
1.340 + TInt l=Min(aLength,K::MaxMemCopyInOneGo);
1.341 + memcpy(pD,pS,l);
1.342 + pD+=l;
1.343 + pS+=l;
1.344 + aLength-=l;
1.345 + if (aLength)
1.346 + check=NKern::FlashSystem();
1.347 + }
1.348 + return KErrNone;
1.349 + }
1.350 +
1.351 +TInt DThread::RawWrite(const TAny* aDest, const TAny* aSrc, TInt aLength, TInt /*aFlags*/, DThread* /*anOriginatingThread*/, TIpcExcTrap* /*aExcTrap*/)
1.352 +//
1.353 +// Write to the thread's process.
1.354 +// aDest is run address of memory to write
1.355 +// aSrc is current address of destination
1.356 +// anOriginatingThread is the thread on behalf of which this operation is performed (eg client of device driver).
1.357 +// Enter and leave with system locked
1.358 +//
1.359 + {
1.360 + if (iMState==EDead)
1.361 + return KErrDied;
1.362 + TUint8* pD=(TUint8*)aDest;
1.363 + const TUint8* pS=(const TUint8*)aSrc;
1.364 + TBool kernelLocked = EFalse;
1.365 + TUint8* pC=(TUint8*)MM::CurrentAddress(this,pD,aLength,ETrue,kernelLocked);
1.366 + if (kernelLocked)
1.367 + {
1.368 + // kernel locked because of DLL WSD IPC, do it all in one big block
1.369 + TInt r = KErrNone;
1.370 + __KTRACE_OPT(KTHREAD2,Kern::Printf("DThread::RawWrite %08x",pC));
1.371 + if (!pC)
1.372 + r = KErrBadDescriptor;
1.373 + else
1.374 + memcpy(pC,pS,aLength);
1.375 + NKern::Unlock();
1.376 + return r;
1.377 + }
1.378 + TBool check=ETrue;
1.379 + while (aLength)
1.380 + {
1.381 + if (check)
1.382 + {
1.383 + if (iMState==EDead)
1.384 + return KErrDied;
1.385 + __KTRACE_OPT(KTHREAD2,Kern::Printf("DThread::Write %08x",pD));
1.386 + }
1.387 + TInt l=Min(aLength,K::MaxMemCopyInOneGo);
1.388 + memcpy(pD,pS,l);
1.389 + pD+=l;
1.390 + pS+=l;
1.391 + aLength-=l;
1.392 + if (aLength)
1.393 + check=NKern::FlashSystem();
1.394 + }
1.395 + return KErrNone;
1.396 + }
1.397 +
1.398 +TInt DThread::ReadAndParseDesHeader(const TAny* aSrc, TDesHeader& aDest)
1.399 +//
1.400 +// Read and parse the header of a remote descriptor.
1.401 +// Enter and leave with system locked.
1.402 +//
1.403 + {
1.404 + __ASSERT_SYSTEM_LOCK;
1.405 + static const TUint8 LengthLookup[16]={4,8,12,8,12,0,0,0,0,0,0,0,0,0,0,0};
1.406 + if (iMState == EDead)
1.407 + return KErrDied;
1.408 + TBool kernelLocked = EFalse;
1.409 + const TUint32* pS=(const TUint32*)MM::CurrentAddress(this,aSrc,sizeof(TDesC8),EFalse,kernelLocked);
1.410 + if (!pS || (TInt(pS)&3)!=0)
1.411 + {
1.412 + if (kernelLocked)
1.413 + NKern::Unlock();
1.414 + return KErrBadDescriptor;
1.415 + }
1.416 + TInt type=0;
1.417 + XTRAPD(r, XT_DEFAULT, \
1.418 + type=*pS>>KShiftDesType8; \
1.419 + TInt l=LengthLookup[type]; \
1.420 + if (l==0) \
1.421 + r=KErrBadDescriptor; \
1.422 + else \
1.423 + wordmove(&aDest,pS,l); \
1.424 + );
1.425 + if (kernelLocked)
1.426 + NKern::Unlock();
1.427 + if (r!=KErrNone)
1.428 + return r;
1.429 + return K::ParseDesHeader(aSrc, (TRawDesHeader&)aDest, aDest);
1.430 + }
1.431 +
1.432 +DChunk* DThread::OpenSharedChunk(const TAny* aAddress, TBool /*aWrite*/, TInt& aOffset)
1.433 + {
1.434 + DWin32Chunk* chunk=0;
1.435 + DObjectCon& chunks=*K::Containers[EChunk];
1.436 + chunks.Wait();
1.437 + TInt count=chunks.Count();
1.438 + TInt i;
1.439 + TUint offset=0;
1.440 + for(i=0;i<count;i++)
1.441 + {
1.442 + DWin32Chunk* pC=(DWin32Chunk*)chunks[i];
1.443 + offset = (TUint)aAddress-(TUint)pC->Base();
1.444 + if(offset<TUint(pC->iMaxSize))
1.445 + {
1.446 + chunk = pC;
1.447 + break;
1.448 + }
1.449 + }
1.450 + chunks.Signal();
1.451 +
1.452 + if(!chunk)
1.453 + return 0;
1.454 +
1.455 + if((chunk->iChunkType!=ESharedKernelSingle && chunk->iChunkType!=ESharedKernelMultiple))
1.456 + return 0;
1.457 + if(chunk->Open()!=KErrNone)
1.458 + return 0;
1.459 + aOffset = offset;
1.460 + return chunk;
1.461 + }
1.462 +
1.463 +TInt DThread::PrepareMemoryForDMA(const TAny* /*aLinAddr*/, TInt /*aSize*/, TPhysAddr* /*aPhysicalPageList*/)
1.464 + {
1.465 + return KErrNotSupported;
1.466 + }
1.467 +
1.468 +TInt DThread::ReleaseMemoryFromDMA(const TAny* /*aLinAddr*/, TInt /*aSize*/, TPhysAddr* /*aPhysicalPageList*/)
1.469 + {
1.470 + return KErrNotSupported;
1.471 + }
1.472 +