--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/kernel/sprocess.cpp Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,761 @@
+// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\kernel\sprocess.cpp
+//
+//
+
+#include <kernel/kern_priv.h>
+#include <e32uid.h>
+
+#define iMState iWaitLink.iSpare1
+
+_LIT(KDollarLock,"$LOCK");
+_LIT(KDllDollarLock,"DLL$LOCK");
+_LIT(KLitMain,"Main");
+_LIT(KLitKill,"Kill");
+_LIT(KLitTerminate,"Terminate");
+
+/********************************************
+ * Process
+ ********************************************/
+DProcess::DProcess()
+ : iPriority(EProcPriorityForeground),
+ iExitType((TUint8)EExitPending), iGeneration(1), iFlags(KProcessFlagJustInTime),
+ iDynamicCode(8, _FOFF(SCodeSegEntry, iSeg), 2*256)
+ {
+ //reserve slot 0 for later use for the command line
+ iEnvironmentData[0] = EBinaryData;
+ }
+
+DProcess::~DProcess()
+ {
+ delete iCommandLine;
+ //delete any process parameters given to this process when it was created
+ TInt i;
+ for (i = 0; i < KArgIndex; ++i)
+ {
+ //if the value is a pointer to a buffer, delete it
+ //if its a pointer to an object, close it
+ TInt data = iEnvironmentData[i]&~3;
+
+ if (iEnvironmentData[i] & EBinaryData)
+ {
+ delete (HBuf8*)(data);
+ }
+ else if (iEnvironmentData[i] & EHandle)
+ {
+ ((DObject*)data)->Close(NULL);
+ }
+ }
+
+ }
+
+void DProcess::Destruct()
+ {
+ }
+
+void DProcess::DoAppendName(TDes& aName)
+ {
+ DObject::DoAppendName(aName);
+ aName.Append('[');
+ aName.AppendNumFixedWidth(iUids.iUid[2].iUid,EHex,8);
+ aName.Append(']');
+ aName.AppendNumFixedWidth(iGeneration,EDecimal,4);
+ }
+
+TInt NextGeneration(const TDesC& aName, TUid aUid)
+//
+// Return the next generation number for the process
+//
+ {
+
+ const TInt KNameSuffixLen = 14; // Number of chars after root name, see DoAppendName
+
+ __KTRACE_OPT(KPROC,Kern::Printf("DProcess::NextGeneration %S 0x%08x", &aName, aUid.iUid));
+ TInt gen=0;
+ DObjectCon& processes=*K::Containers[EProcess];
+ TKName name;
+ processes.Wait();
+ for (TInt i = 0 ; i < processes.Count() ; ++i)
+ {
+ DProcess* pP=(DProcess*)processes[i];
+ if (pP->iAccessCount > 0 && aUid.iUid == pP->iUids.iUid[2].iUid && pP->NameBuf())
+ {
+ pP->Name(name);
+ if (name.Length() > KNameSuffixLen)
+ {
+ TPtrC rootName = name.Left(name.Length() - KNameSuffixLen);
+ if (aName.CompareF(rootName) == 0 && pP->iAccessCount > 0)
+ {
+ if (pP->iGeneration>gen)
+ gen=pP->iGeneration;
+ }
+ }
+ }
+ }
+ processes.Signal();
+ __KTRACE_OPT(KPROC,Kern::Printf("DProcess generation %d",gen+1));
+ return(gen+1);
+ }
+
+__ASSERT_COMPILE(ECapability_Limit<=32); // Kernel's iCaps caps below assumes this
+
+
+TInt DProcess::SetPaging(const TProcessCreateInfo& aInfo)
+ {// Default implementation that only verifies flags, this virtual method
+ // is overridden in memory models that support paging.
+ if (aInfo.iFlags & TProcessCreateInfo::EDataPagingMask ==
+ TProcessCreateInfo::EDataPagingMask)
+ {
+ return KErrCorrupt;
+ }
+ return KErrNone;
+ }
+
+
+TInt DProcess::Create(TBool aKernelProcess, TProcessCreateInfo& aInfo, HBuf* aCommandLine)
+ {
+ __KTRACE_OPT(KBOOT,Kern::Printf("DProcess::Create"));
+
+ TInt r=KErrNone;
+ iCommandLine=aCommandLine; // do this first to prevent memory leak if error occurs
+ TPtrC f=aInfo.iFileName.Mid(aInfo.iRootNameOffset,aInfo.iRootNameLength);
+ r=SetName(&f);
+ if (r!=KErrNone)
+ return r;
+
+ // Verify and save any data paging attributes.
+ SetPaging(aInfo);
+
+ iUids=aInfo.iUids;
+ iS=aInfo.iS;
+ iDebugAttributes = (TUint8)aInfo.iDebugAttributes;
+ if (!aKernelProcess)
+ {
+ iPriority=0;
+ TInt p=ConvertPriority(aInfo.iPriority);
+ if (p<0)
+ return KErrArgument;
+ iPriority=p;
+ iGeneration=NextGeneration(f,iUids.iUid[2]);
+ }
+ else
+ {
+ iPriority = EProcPrioritySystemServer3;
+ iFlags |= KProcessFlagSystemPermanent|KProcessFlagSystemCritical;
+ }
+#ifdef BTRACE_THREAD_PRIORITY
+ BTrace8(BTrace::EThreadPriority,BTrace::EProcessPriority,this,iPriority);
+#endif
+ iId = K::NewId();
+ iCreatorId = iId; // Initialise as self for safety because creator has special capabilities
+ if(TheSuperPage().KernelConfigFlags() & EKernelConfigPlatSecProcessIsolation)
+ {
+ if(aInfo.iSecurityZone==KSecurityZoneUnique)
+ iSecurityZone=iId;
+ else
+ iSecurityZone=aInfo.iSecurityZone;
+ }
+ else
+ iSecurityZone=KSecurityZoneLegacyCode;
+
+ r=K::MutexCreate((DMutex*&)iProcessLock, KDollarLock, this, EFalse, KMutexOrdProcessLock);
+ __KTRACE_OPT(KPROC,Kern::Printf("Lock mutex created, %d",r));
+ if (r!=KErrNone)
+ return r;
+ if (!aKernelProcess)
+ {
+ r=K::MutexCreate((DMutex*&)iDllLock, KDllDollarLock, this, EFalse, KMutexOrdUser);
+ if (r!=KErrNone)
+ return r;
+ }
+ r=DoCreate(aKernelProcess,aInfo);
+ if (r!=KErrNone)
+ return r;
+ __KTRACE_OPT(KPROC,Kern::Printf("Process attributes %08x",iAttributes));
+ iAttributes |= EBeingLoaded;
+
+#ifdef __DEBUGGER_SUPPORT__
+ // Send new process notification. Note that the creator thread can not always
+ // be figured out. It could have been killed atfer requesting the loader to
+ // create the process or the process could be created by a kernel thread.
+ NKern::LockSystem();
+
+ DThread* creator = (DThread*)TheCurrentThread->ObjectFromHandle(aInfo.iClientHandle,EThread);
+
+ if (creator && (creator->Open() != KErrNone))
+ creator = NULL;
+
+ NKern::UnlockSystem();
+
+ __DEBUG_EVENT2(EEventAddProcess, this, creator);
+
+ if (creator)
+ creator->Close(NULL);
+#endif
+
+#ifdef BTRACE_THREAD_IDENTIFICATION
+ BTrace4(BTrace::EThreadIdentification,BTrace::EProcessCreate,this);
+#endif
+
+ iTempCodeSeg=(DCodeSeg*)aInfo.iHandle;
+ if (iTempCodeSeg)
+ {
+ if (iTempCodeSeg->iExeCodeSeg!=iTempCodeSeg)
+ return KErrNotSupported;
+ iTempCodeSeg->WaitCheckedOpen();
+ r=AttachExistingCodeSeg(aInfo); // doesn't map the code in - Loaded() does this
+ if (r!=KErrNone)
+ return r;
+ }
+ else
+ {
+ iTempCodeSeg=M::NewCodeSeg(aInfo);
+ if (!iTempCodeSeg)
+ return KErrNoMemory;
+ iTempCodeSeg->iExeCodeSeg=iTempCodeSeg;
+ r=iTempCodeSeg->Create(aInfo,this);
+ if (r!=KErrNone)
+ return r;
+ iTempCodeSeg->WaitCheckedOpen();
+ aInfo.iHandle=iTempCodeSeg;
+ }
+ if (!aKernelProcess)
+ {
+ DThread* pT=NULL;
+ SStdEpocThreadCreateInfo t;
+ t.iType=EThreadUser;
+ t.iFunction=(TThreadFunction)aInfo.iFileEntryPoint; // kernel will call veneer, veneer will call this
+ t.iPtr=NULL;
+ t.iSupervisorStack=NULL;
+ t.iSupervisorStackSize=0; // zero means use default value
+ t.iUserStack=NULL;
+ t.iUserStackSize=aInfo.iStackSize;
+ t.iInitialThreadPriority=EThrdPriorityNormal;
+ t.iName.Set(KLitMain);
+ t.iAllocator=NULL;
+ t.iHeapInitialSize=aInfo.iHeapSizeMin;
+ t.iHeapMaxSize=aInfo.iHeapSizeMax;
+ t.iTotalSize = sizeof(t);
+ r=NewThread((DThread*&)pT, t, NULL, EOwnerProcess);
+ if (r==KErrNone)
+ pT->iFlags |= KThreadFlagProcessPermanent|KThreadFlagOriginal;
+ iUserThreadsRunning=1;
+ }
+ if (r!=KErrNone)
+ return r;
+ if (!aKernelProcess)
+ r=K::AddObject(this,EProcess);
+ return r;
+ }
+
+DCodeSeg* DProcess::CodeSeg()
+ {
+ return iCodeSeg ? iCodeSeg : iTempCodeSeg;
+ }
+
+TInt DProcess::SetPriority(TProcessPriority aPriority)
+ {
+ TInt p=ConvertPriority(aPriority);
+ if (p<0)
+ return KErrArgument;
+ if (iExitType!=EExitPending)
+ return KErrDied;
+
+ __KTRACE_OPT(KPROC,Kern::Printf("Process %O SetPriority(%d)",this,p));
+ TInt r=WaitProcessLock();
+ __KTRACE_FAIL(r,Kern::Printf("PSP: %d",r));
+ if (r!=KErrNone)
+ return KErrDied;
+#ifdef BTRACE_THREAD_PRIORITY
+ BTrace8(BTrace::EThreadPriority,BTrace::EProcessPriority,this,p);
+#endif
+ NKern::LockSystem();
+ iPriority=p;
+ SDblQueLink* pLink=iThreadQ.First();
+ while (pLink!=&iThreadQ.iA)
+ {
+ DThread* pT=_LOFF(pLink,DThread,iProcessLink);
+ pT->SetThreadPriority(pT->iThreadPriority);
+ pLink=pLink->iNext;
+ NKern::FlashSystem();
+ }
+ NKern::UnlockSystem();
+ SignalProcessLock();
+ return KErrNone;
+ }
+
+TInt DProcess::ConvertPriority(TProcessPriority aPriority)
+ {
+ TInt p=-1;
+ switch(aPriority)
+ {
+ case EPriorityLow: p=EProcPriorityLow; break;
+ case EPriorityBackground: p=EProcPriorityBackground; break;
+ case EPriorityForeground: p=EProcPriorityForeground; break;
+ case EPriorityHigh: p=EProcPriorityHigh; break;
+ case EPriorityWindowServer: p=EProcPrioritySystemServer1; break;
+ case EPriorityFileServer: p=EProcPrioritySystemServer2; break;
+ case EPriorityRealTimeServer: p=EProcPriorityRealTimeServer; break;
+ case EPrioritySupervisor: p=EProcPrioritySystemServer3; break;
+ }
+ return p;
+ }
+
+TInt DProcess::Rename(const TDesC& aName)
+ {
+ if (aName.Length()>KMaxKernelName-KMaxUidName-4)
+ return KErrBadName;
+ TKName n;
+ DObject::BaseName(n); // get current name, without UID and generation number
+ if (n.MatchF(aName)==0)
+ return KErrNone; // new name is the same so nothing to do
+
+ iGeneration = NextGeneration(aName, iUids.iUid[2]);
+
+ __KTRACE_OPT(KTHREAD,Kern::Printf("DProcess::Rename %O to %lS",this,&aName));
+ TInt r = SetName(&aName);
+#ifdef BTRACE_THREAD_IDENTIFICATION
+ Name(n);
+ BTraceN(BTrace::EThreadIdentification,BTrace::EProcessName,0,this,n.Ptr(),n.Size());
+#endif
+
+ __COND_DEBUG_EVENT(r==KErrNone, EEventUpdateProcess, this);
+ return(r);
+ }
+
+void DProcess::Release()
+ {
+#ifdef __SMP__
+ // delete thread group
+ if (iSMPUnsafeGroup)
+ {
+ NKern::GroupDestroy(iSMPUnsafeGroup);
+ Kern::Free(iSMPUnsafeGroup);
+ }
+#endif
+
+ // delete handles with lock mutex free
+ __KTRACE_OPT(KPROC,Kern::Printf("Process %O Release()",this));
+ __KTRACE_OPT(KPROC,Kern::Printf("Deleting handles"));
+ iHandles.Close(this);
+
+ // Notify process unloading before code segs are released
+ __DEBUG_EVENT(EEventUnloadingProcess, this);
+
+ __NK_ASSERT_DEBUG(iGarbageList.IsEmpty());
+
+ if (iCodeSeg || iTempCodeSeg)
+ {
+ DCodeSeg::Wait();
+ if (iCodeSeg)
+ RemoveCodeSeg(iCodeSeg, NULL);
+ DCodeSeg* pS = (DCodeSeg*)__e32_atomic_swp_ord_ptr(&iTempCodeSeg, 0);
+ if (pS)
+ pS->CheckedClose();
+ RemoveDllData();
+ DCodeSeg::Signal();
+ }
+
+ __ASSERT_ALWAYS(iDynamicCode.Count()==0, K::Fault(K::ECodeStillMapped));
+ iDynamicCode.Close();
+
+ __KTRACE_OPT(KPROC,Kern::Printf("Closing DLL$LOCK mutex"));
+ Kern::SafeClose((DObject*&)iDllLock,this);
+
+ __KTRACE_OPT(KPROC,Kern::Printf("Closing owning process"));
+ Kern::SafeClose((DObject*&)iOwningProcess,NULL);
+
+ __KTRACE_OPT(KPROC,Kern::Printf("Closing DataBssStack chunk"));
+ Kern::SafeClose((DObject*&)iDataBssStackChunk,this);
+
+ NKern::LockSystem();
+ iFinalReleaseFlag = ETrue;
+ if (iProcessLock)
+ iProcessLock->Wait(); // this will get released when the lock mutex is deleted
+ NKern::UnlockSystem();
+
+ __KTRACE_OPT(KPROC,Kern::Printf("Calling FinalRelease()"));
+ // Call FinalRelease() with process $LOCK mutex held (if it exists)
+ // and don't ever release the mutex afterwards.
+ FinalRelease();
+
+ __KTRACE_OPT(KPROC,Kern::Printf("Closing $LOCK mutex"));
+ Kern::SafeClose((DObject*&)iProcessLock,this);
+
+ // Notify process removal before closing process
+ __DEBUG_EVENT(EEventRemoveProcess, this);
+
+#ifdef BTRACE_THREAD_IDENTIFICATION
+ BTrace4(BTrace::EThreadIdentification,BTrace::EProcessDestroy,this);
+#endif
+
+ // Kill any processes which we created but have not resumed
+ NKern::LockSystem(); // In case we died in the middle of DProcess::Resume()
+ NKern::UnlockSystem();
+ for(;;)
+ {
+ DObjectCon& processes=*K::Containers[EProcess];
+ processes.Wait();
+ DProcess* zombie=NULL;
+ TInt c=processes.Count();
+ for (TInt i=0; i<c; i++)
+ {
+ DProcess* pP=(DProcess*)processes[i];
+ if (pP->iCreatorId==iId && pP!=this && pP->Open()==KErrNone)
+ {
+ zombie = pP;
+ break;
+ }
+ }
+ processes.Signal();
+ if(!zombie)
+ break;
+ __KTRACE_OPT(KPROC,Kern::Printf("Killing zombie process %O",zombie));
+ zombie->iCreatorId=zombie->iId;
+ zombie->Die(EExitPanic,EZombieProcessKilled,KLitKernExec());
+ zombie->Close(0);
+ }
+
+ __KTRACE_OPT(KPROC,Kern::Printf("Closing process"));
+ Close(this);
+ }
+
+TInt DProcess::WaitProcessLock()
+ {
+ TInt r=KErrGeneral;
+ NKern::LockSystem();
+ if (iProcessLock && !iFinalReleaseFlag) // iProcessLock is deleted during process death
+ {
+ r=iProcessLock->Wait(); // mutex may be resetting just before deletion
+ __KTRACE_FAIL(r,Kern::Printf("PLW: %d",r)); // will return KErrGeneral if mutex is reset
+ }
+ NKern::UnlockSystem();
+ __KTRACE_FAIL(r,Kern::Printf("WPL: %d",r));
+ return r;
+ }
+
+TInt DProcess::SignalProcessLock()
+ {
+ TInt r=KErrDied;
+ NKern::LockSystem();
+ if (iProcessLock)
+ {
+ iProcessLock->Signal();
+ r=KErrNone;
+ }
+ else
+ NKern::UnlockSystem();
+ __KTRACE_FAIL(r,Kern::Printf("SPL: %d",r));
+ return r;
+ }
+
+TInt DProcess::Loaded(TProcessCreateInfo& aInfo)
+//
+// Confirm that the process has been loaded O.K.
+//
+ {
+ __KTRACE_OPT(KPROC,Kern::Printf("DProcess::Loaded"));
+
+ //
+ // Update our code segment and dependents
+ //
+ DCodeSeg::Wait();
+
+ TInt r = KErrNone;
+
+ if (!(iTempCodeSeg->iMark & DCodeSeg::EMarkLoaded))
+ {
+ // newly loaded code segment, not another instance of same
+ r = iTempCodeSeg->Loaded(aInfo);
+ }
+
+ if (r == KErrNone)
+ r = OpenDeps();
+
+ DCodeSeg::Signal();
+
+ if (r != KErrNone)
+ return r;
+
+ if (iCodeSeg->iAttr & ECodeSegAttSMPSafe)
+ iSMPUnsafeCount = 0;
+ else
+ {
+ iSMPUnsafeCount = 1;
+#ifdef __SMP__
+ r = UpdateSMPSafe();
+ if (r != KErrNone)
+ return r;
+#endif
+ }
+ FirstThread()->iMState=DThread::EReady;
+ SetProtection(DObject::EGlobal);
+ iAttributes &= ~EBeingLoaded;
+ iReentryPoint = iCodeSeg->iEntryPtVeneer;
+
+ // Send loaded process notification.
+ __DEBUG_EVENT(EEventLoadedProcess, this);
+
+ return KErrNone;
+ }
+
+void DProcess::Resume()
+//
+// Resume a newly created process. Idempotent. Enter and return with system locked.
+//
+ {
+ if (iAttributes&EBeingLoaded)
+ K::PanicCurrentThread(EProcessNotLoaded);
+ if (!(iAttributes&EResumed))
+ {
+ iAttributes|=EResumed;
+ iCreatorId = iId; // Creator loses control over process once it has been resumed
+ FirstThread()->Resume();
+ }
+ }
+
+void DProcess::Die(TExitType aType, TInt aReason, const TDesC &aCategory)
+//
+// Kill a process. Enter and return with system unlocked and calling thread in critical section.
+//
+ {
+ __KTRACE_OPT(KPROC,Kern::Printf("Process %O Die: %d %d %lS",this,aType,aReason,&aCategory));
+
+ TInt r=WaitProcessLock();
+ if (r!=KErrNone)
+ return; // process already exiting
+ NKern::LockSystem();
+ if (iAttributes&EBeingLoaded)
+ {
+ // Load failed before UserSvr::ProcessLoaded() was called.
+ // The thread is still runnable however, since UserSvr::ProcessCreate() must have succeeded.
+ // We just need to set the thread state so it can be resumed.
+ FirstThread()->iMState=DThread::EReady;
+ }
+ if (iExitType==EExitPending)
+ {
+ iExitType = (TUint8)aType;
+ iExitReason=aReason;
+ if (iExitType==EExitKill)
+ iExitCategory=KLitKill;
+ else if (iExitType==EExitTerminate)
+ iExitCategory=KLitTerminate;
+ else
+ iExitCategory=aCategory;
+
+ if (iExitType!=EExitKill && (iFlags & (KProcessFlagSystemPermanent|KProcessFlagSystemCritical)))
+ K::Fault(K::ESystemProcessPanic);
+ if (iFlags & KProcessFlagSystemPermanent)
+ K::Fault(K::EPermanentProcessExit);
+
+ // Kill all threads; when the last one exits the process will be cleaned up.
+ TBool killMe = KillAllThreads(aType, aReason, aCategory);
+ if (killMe)
+ {
+ DThread* pC=TheCurrentThread;
+ pC->iExitType=(TUint8)iExitType;
+ pC->iExitReason=iExitReason;
+ pC->iExitCategory=iExitCategory;
+ NKern::DeferredExit();
+ }
+ }
+ NKern::UnlockSystem();
+ SignalProcessLock();
+ }
+
+TBool DProcess::KillAllThreads(TExitType aType, TInt aReason, const TDesC &aCategory)
+//
+// Kill all threads in a process. Enter and return with system locked, the process lock held and
+// calling thread in a critical section. Returns whether the current thread needs to exit too.
+//
+ {
+ TBool killMe=EFalse;
+ DThread* pC=TheCurrentThread;
+ SDblQueLink* pLink=iThreadQ.First();
+ while (pLink!=&iThreadQ.iA)
+ {
+ DThread* pT=_LOFF(pLink,DThread,iProcessLink);
+ pLink=pLink->iNext;
+ if (pT!=pC)
+ {
+ // Need to stop the current thread being killed as a consequence of killing pT
+ pT->iFlags &= ~(KThreadFlagProcessPermanent|KThreadFlagProcessCritical);
+ pT->Die(aType, aReason, aCategory);
+ }
+ else
+ {
+ killMe=ETrue;
+ NKern::UnlockSystem();
+ }
+ NKern::LockSystem();
+ }
+ return killMe;
+ }
+
+void DProcess::AddThread(DThread &aThread)
+ {
+ __KTRACE_OPT(KPROC,Kern::Printf("AddThread %O to %O",&aThread,this));
+ iThreadQ.Add(&aThread.iProcessLink);
+ }
+
+TInt DProcess::NewThread(DThread*& aThread, SThreadCreateInfo& anInfo, TInt* aHandle, TOwnerType aType)
+ {
+ __KTRACE_OPT(KTHREAD,Kern::Printf("NewThread proc %O, func %08x ptr %08x",this,anInfo.iFunction,anInfo.iPtr));
+ __KTRACE_OPT(KTHREAD,Kern::Printf("type %d name %lS pri %d",anInfo.iType,&anInfo.iName,anInfo.iInitialThreadPriority));
+ if (aHandle)
+ *aHandle=0;
+ TInt r=GetNewThread(aThread,anInfo);
+ __KTRACE_FAIL(r,Kern::Printf("GNT: %d",r));
+ DThread* pT=aThread;
+ if (r==KErrNone)
+ {
+ r=pT->Create(anInfo);
+ __KTRACE_FAIL(r,Kern::Printf("NTC: %d",r));
+ if (r==KErrNone && aHandle)
+ {
+ r=K::MakeHandleAndOpen(aType,pT,*aHandle);
+ __KTRACE_FAIL(r,Kern::Printf("NT MHO: %d",r));
+ }
+ if (r==KErrNone)
+ {
+ r=WaitProcessLock();
+ if (r==KErrNone)
+ {
+ NKern::LockSystem();
+ if (iExitType==EExitPending)
+ {
+ AddThread(*pT);
+ pT->iMState=DThread::EReady;
+ // set fully constructed flag here
+ }
+ else
+ r=KErrDied;
+ NKern::UnlockSystem();
+ SignalProcessLock();
+ __KTRACE_FAIL(r,Kern::Printf("NT ADD: %d",r));
+ }
+ else
+ r=KErrDied;
+ }
+ }
+ if (r==KErrNone)
+ {
+ if (anInfo.iType == EThreadUser)
+ {
+ pT->iUserThreadState = DThread::EUserThreadCreated;
+ __e32_atomic_tas_ord32(&iUserThreadsRunning, 1, 1, 0);
+ }
+#ifdef BTRACE_THREAD_IDENTIFICATION
+ if(BTrace::Filter(BTrace::EThreadIdentification))
+ {
+ DObjectCon* threads=Kern::Containers()[EThread];
+ threads->Wait(); // hold mutex so traces below don't get mixed up with other thread creation traces
+ TKName nameBuf;
+ Name(nameBuf);
+ BTraceN(BTrace::EThreadIdentification,BTrace::EProcessName,&pT->iNThread,this,nameBuf.Ptr(),nameBuf.Size());
+ pT->Name(nameBuf);
+ BTraceN(BTrace::EThreadIdentification,BTrace::EThreadCreate,&pT->iNThread,this,nameBuf.Ptr(),nameBuf.Size());
+ BTrace12(BTrace::EThreadIdentification,BTrace::EThreadId,&pT->iNThread,this,pT->iId);
+ threads->Signal();
+ }
+#endif
+ __DEBUG_EVENT2(EEventAddThread, pT, TheCurrentThread);
+ }
+ else if (pT)
+ {
+ if (aHandle && *aHandle)
+ {
+ K::HandleClose(*aHandle);
+ *aHandle=0;
+ }
+ pT->Stillborn();
+ aThread=NULL;
+ }
+ __KTRACE_FAIL(r,Kern::Printf("NT: %d",r));
+ return r;
+ }
+
+void DProcess::Rendezvous(TInt aReason)
+//
+// Enter and return with system unlocked and calling thread in critical section.
+//
+ {
+ TLogon::CompleteAll(iTargetLogons, TLogon::ETargetRendezvous, aReason);
+ }
+
+TInt DProcess::Logon(TRequestStatus* aStatus, TBool aRendezvous)
+ {
+ TInt r = KErrNoMemory;
+ DThread* pC = TheCurrentThread;
+ __KTRACE_OPT(KTHREAD, Kern::Printf("Thread %O Logon to process %O, status at %08x rdv=%x",
+ pC, this, aStatus, aRendezvous));
+
+ TLogon* pL = new TLogon;
+ if (pL)
+ {
+ TUint32 type = TLogon::ETargetProcess;
+ if (aRendezvous)
+ type |= TLogon::ERendezvous;
+ r = pL->Attach(iTargetLogons, pC, this, aStatus, type);
+ if (r != KErrNone)
+ pL->Close();
+ }
+
+ __KTRACE_OPT(KTHREAD, Kern::Printf("DProcess::Logon ret %d", r));
+ return r;
+ }
+
+void DProcess::BTracePrime(TInt aCategory)
+ {
+#ifdef BTRACE_THREAD_IDENTIFICATION
+ if(aCategory==BTrace::EThreadIdentification || aCategory==-1)
+ BTrace4(BTrace::EThreadIdentification,BTrace::EProcessCreate,this);
+#endif
+ }
+
+#ifdef __SMP__
+TInt DProcess::UpdateSMPSafe()
+ {
+ TUint32 config = TheSuperPage().KernelConfigFlags();
+ if (!(config & (EKernelConfigSMPUnsafeCompat|EKernelConfigSMPUnsafeCPU0)) || this == K::TheKernelProcess)
+ return KErrNone;
+ __KTRACE_OPT(KPROC,Kern::Printf("Process %O UpdateSMPSafe count=%d",this,iSMPUnsafeCount));
+ TInt r=WaitProcessLock();
+ (void)r;
+ __NK_ASSERT_DEBUG(r==KErrNone);
+ if ((config & EKernelConfigSMPUnsafeCompat) && !iSMPUnsafeGroup)
+ {
+ SNThreadGroupCreateInfo info;
+ info.iCpuAffinity = KCpuAffinityAny;
+ iSMPUnsafeGroup = (NThreadGroup*)Kern::Alloc(sizeof(NThreadGroup));
+ r = KErrNoMemory;
+ if (iSMPUnsafeGroup)
+ r = NKern::GroupCreate(iSMPUnsafeGroup, info);
+ }
+ if (r==KErrNone)
+ {
+ SDblQueLink* pLink=iThreadQ.First();
+ while (pLink!=&iThreadQ.iA)
+ {
+ DThread* pT=_LOFF(pLink,DThread,iProcessLink);
+ NKern::QueueUserModeCallback(&pT->iNThread, &pT->iSMPSafeCallback);
+ pLink=pLink->iNext;
+ }
+ }
+ SignalProcessLock();
+ return r;
+ }
+#endif
+