kernel/eka/kernel/sprocess.cpp
changeset 0 a41df078684a
child 42 a179b74831c9
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\kernel\sprocess.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <kernel/kern_priv.h>
       
    19 #include <e32uid.h>
       
    20 
       
    21 #define iMState		iWaitLink.iSpare1
       
    22 
       
    23 _LIT(KDollarLock,"$LOCK");
       
    24 _LIT(KDllDollarLock,"DLL$LOCK");
       
    25 _LIT(KLitMain,"Main");
       
    26 _LIT(KLitKill,"Kill");
       
    27 _LIT(KLitTerminate,"Terminate");
       
    28 
       
    29 /********************************************
       
    30  * Process
       
    31  ********************************************/
       
    32 DProcess::DProcess()
       
    33 	: iPriority(EProcPriorityForeground),
       
    34 	  iExitType((TUint8)EExitPending), iGeneration(1), iFlags(KProcessFlagJustInTime),
       
    35 	  iDynamicCode(8, _FOFF(SCodeSegEntry, iSeg), 2*256)
       
    36 	{
       
    37 	//reserve slot 0 for later use for the command line
       
    38 	iEnvironmentData[0] = EBinaryData;
       
    39 	}
       
    40 
       
    41 DProcess::~DProcess()
       
    42 	{
       
    43 	delete iCommandLine;
       
    44 	//delete any process parameters given to this process when it was created
       
    45 	TInt i;
       
    46 	for (i = 0; i < KArgIndex; ++i)
       
    47 		{
       
    48 		//if the value is a pointer to a buffer, delete it
       
    49 		//if its a pointer to an object, close it
       
    50 		TInt data = iEnvironmentData[i]&~3;
       
    51 
       
    52 		if (iEnvironmentData[i] & EBinaryData)
       
    53 			{
       
    54 			delete (HBuf8*)(data);
       
    55 			}
       
    56 		else if (iEnvironmentData[i] & EHandle)
       
    57 			{
       
    58 			((DObject*)data)->Close(NULL);
       
    59 			}
       
    60 		}
       
    61 
       
    62 	}
       
    63 
       
    64 void DProcess::Destruct()
       
    65 	{
       
    66 	}
       
    67 
       
    68 void DProcess::DoAppendName(TDes& aName)
       
    69 	{
       
    70 	DObject::DoAppendName(aName);
       
    71 	aName.Append('[');
       
    72 	aName.AppendNumFixedWidth(iUids.iUid[2].iUid,EHex,8);
       
    73 	aName.Append(']');
       
    74 	aName.AppendNumFixedWidth(iGeneration,EDecimal,4);
       
    75 	}
       
    76 
       
    77 TInt NextGeneration(const TDesC& aName, TUid aUid)
       
    78 //
       
    79 // Return the next generation number for the process
       
    80 //
       
    81 	{
       
    82 
       
    83 	const TInt KNameSuffixLen = 14;  // Number of chars after root name, see DoAppendName
       
    84 
       
    85 	__KTRACE_OPT(KPROC,Kern::Printf("DProcess::NextGeneration %S 0x%08x", &aName, aUid.iUid));
       
    86 	TInt gen=0;
       
    87 	DObjectCon& processes=*K::Containers[EProcess];
       
    88 	TKName name;
       
    89 	processes.Wait();
       
    90 	for (TInt i = 0 ; i < processes.Count() ; ++i)
       
    91 		{
       
    92 		DProcess* pP=(DProcess*)processes[i];
       
    93 		if (pP->iAccessCount > 0 && aUid.iUid == pP->iUids.iUid[2].iUid && pP->NameBuf())
       
    94 			{
       
    95 			pP->Name(name);
       
    96 			if (name.Length() > KNameSuffixLen)
       
    97 				{
       
    98 				TPtrC rootName = name.Left(name.Length() - KNameSuffixLen);
       
    99 				if (aName.CompareF(rootName) == 0 && pP->iAccessCount > 0)
       
   100 					{
       
   101 					if (pP->iGeneration>gen)
       
   102 						gen=pP->iGeneration;
       
   103 					}
       
   104 				}
       
   105 			}
       
   106 		}
       
   107 	processes.Signal();
       
   108 	__KTRACE_OPT(KPROC,Kern::Printf("DProcess generation %d",gen+1));
       
   109 	return(gen+1);
       
   110 	}
       
   111 
       
   112 __ASSERT_COMPILE(ECapability_Limit<=32);  // Kernel's iCaps caps below assumes this
       
   113 
       
   114 
       
   115 TInt DProcess::SetPaging(const TProcessCreateInfo& aInfo)
       
   116 	{// Default implementation that only verifies flags, this virtual method 
       
   117 	// is overridden in memory models that support paging.
       
   118 	if (aInfo.iFlags & TProcessCreateInfo::EDataPagingMask == 
       
   119 		TProcessCreateInfo::EDataPagingMask)
       
   120 		{
       
   121 		return KErrCorrupt;	
       
   122 		}
       
   123 	return KErrNone;
       
   124 	}
       
   125 
       
   126 
       
   127 TInt DProcess::Create(TBool aKernelProcess, TProcessCreateInfo& aInfo, HBuf* aCommandLine)
       
   128 	{
       
   129 	__KTRACE_OPT(KBOOT,Kern::Printf("DProcess::Create"));
       
   130 
       
   131 	TInt r=KErrNone;
       
   132 	iCommandLine=aCommandLine;	// do this first to prevent memory leak if error occurs
       
   133 	TPtrC f=aInfo.iFileName.Mid(aInfo.iRootNameOffset,aInfo.iRootNameLength);
       
   134 	r=SetName(&f);
       
   135 	if (r!=KErrNone)
       
   136 		return r;
       
   137 
       
   138 	// Verify and save any data paging attributes.
       
   139 	SetPaging(aInfo);
       
   140 
       
   141 	iUids=aInfo.iUids;
       
   142 	iS=aInfo.iS;
       
   143 	iDebugAttributes = (TUint8)aInfo.iDebugAttributes;
       
   144 	if (!aKernelProcess)
       
   145 		{
       
   146 		iPriority=0;
       
   147 		TInt p=ConvertPriority(aInfo.iPriority);
       
   148 		if (p<0)
       
   149 			return KErrArgument;
       
   150 		iPriority=p;
       
   151 		iGeneration=NextGeneration(f,iUids.iUid[2]);
       
   152 		}
       
   153 	else
       
   154 		{
       
   155 		iPriority = EProcPrioritySystemServer3;
       
   156 		iFlags |= KProcessFlagSystemPermanent|KProcessFlagSystemCritical;
       
   157 		}
       
   158 #ifdef BTRACE_THREAD_PRIORITY
       
   159 	BTrace8(BTrace::EThreadPriority,BTrace::EProcessPriority,this,iPriority);
       
   160 #endif
       
   161 	iId = K::NewId();
       
   162 	iCreatorId = iId;  // Initialise as self for safety because creator has special capabilities
       
   163 	if(TheSuperPage().KernelConfigFlags() & EKernelConfigPlatSecProcessIsolation)
       
   164 		{
       
   165 		if(aInfo.iSecurityZone==KSecurityZoneUnique)
       
   166 			iSecurityZone=iId;
       
   167 		else
       
   168 			iSecurityZone=aInfo.iSecurityZone;
       
   169 		}
       
   170 	else
       
   171 		iSecurityZone=KSecurityZoneLegacyCode;
       
   172 
       
   173 	r=K::MutexCreate((DMutex*&)iProcessLock, KDollarLock, this, EFalse, KMutexOrdProcessLock);
       
   174 	__KTRACE_OPT(KPROC,Kern::Printf("Lock mutex created, %d",r));
       
   175 	if (r!=KErrNone)
       
   176 		return r;
       
   177 	if (!aKernelProcess)
       
   178 		{
       
   179 		r=K::MutexCreate((DMutex*&)iDllLock, KDllDollarLock, this, EFalse, KMutexOrdUser);
       
   180 		if (r!=KErrNone)
       
   181 			return r;
       
   182 		}
       
   183 	r=DoCreate(aKernelProcess,aInfo);
       
   184 	if (r!=KErrNone)
       
   185 		return r;
       
   186 	__KTRACE_OPT(KPROC,Kern::Printf("Process attributes %08x",iAttributes));
       
   187 	iAttributes |= EBeingLoaded;
       
   188 
       
   189 #ifdef __DEBUGGER_SUPPORT__
       
   190 	// Send new process notification.  Note that the creator thread can not always 
       
   191 	// be figured out.  It could have been killed atfer requesting the loader to
       
   192 	// create the process or the process could be created by a kernel thread.
       
   193 	NKern::LockSystem();
       
   194 
       
   195 	DThread* creator = (DThread*)TheCurrentThread->ObjectFromHandle(aInfo.iClientHandle,EThread);
       
   196 
       
   197 	if (creator && (creator->Open() != KErrNone))
       
   198 		creator = NULL;
       
   199 
       
   200 	NKern::UnlockSystem();
       
   201 
       
   202 	__DEBUG_EVENT2(EEventAddProcess, this, creator);
       
   203 
       
   204 	if (creator)
       
   205 		creator->Close(NULL);
       
   206 #endif
       
   207 
       
   208 #ifdef BTRACE_THREAD_IDENTIFICATION
       
   209 	BTrace4(BTrace::EThreadIdentification,BTrace::EProcessCreate,this);
       
   210 #endif
       
   211 
       
   212 	iTempCodeSeg=(DCodeSeg*)aInfo.iHandle;
       
   213 	if (iTempCodeSeg)
       
   214 		{
       
   215 		if (iTempCodeSeg->iExeCodeSeg!=iTempCodeSeg)
       
   216 			return KErrNotSupported;
       
   217 		iTempCodeSeg->WaitCheckedOpen();
       
   218 		r=AttachExistingCodeSeg(aInfo);		// doesn't map the code in - Loaded() does this
       
   219 		if (r!=KErrNone)
       
   220 			return r;
       
   221 		}
       
   222 	else
       
   223 		{
       
   224 		iTempCodeSeg=M::NewCodeSeg(aInfo);
       
   225 		if (!iTempCodeSeg)
       
   226 			return KErrNoMemory;
       
   227 		iTempCodeSeg->iExeCodeSeg=iTempCodeSeg;
       
   228 		r=iTempCodeSeg->Create(aInfo,this);
       
   229 		if (r!=KErrNone)
       
   230 			return r;
       
   231 		iTempCodeSeg->WaitCheckedOpen();
       
   232 		aInfo.iHandle=iTempCodeSeg;
       
   233 		}
       
   234 	if (!aKernelProcess)
       
   235 		{
       
   236 		DThread* pT=NULL;
       
   237 		SStdEpocThreadCreateInfo t;
       
   238 		t.iType=EThreadUser;
       
   239 		t.iFunction=(TThreadFunction)aInfo.iFileEntryPoint;	// kernel will call veneer, veneer will call this
       
   240 		t.iPtr=NULL;
       
   241 		t.iSupervisorStack=NULL;
       
   242 		t.iSupervisorStackSize=0;	// zero means use default value
       
   243 		t.iUserStack=NULL;
       
   244 		t.iUserStackSize=aInfo.iStackSize;
       
   245 		t.iInitialThreadPriority=EThrdPriorityNormal;
       
   246 		t.iName.Set(KLitMain);
       
   247 		t.iAllocator=NULL;
       
   248 		t.iHeapInitialSize=aInfo.iHeapSizeMin;
       
   249 		t.iHeapMaxSize=aInfo.iHeapSizeMax;
       
   250 		t.iTotalSize = sizeof(t);
       
   251 		r=NewThread((DThread*&)pT, t, NULL, EOwnerProcess);
       
   252 		if (r==KErrNone)
       
   253 			pT->iFlags |= KThreadFlagProcessPermanent|KThreadFlagOriginal;
       
   254 		iUserThreadsRunning=1;
       
   255 		}
       
   256 	if (r!=KErrNone)
       
   257 		return r;
       
   258 	if (!aKernelProcess)
       
   259 		r=K::AddObject(this,EProcess);
       
   260 	return r;
       
   261 	}
       
   262 
       
   263 DCodeSeg* DProcess::CodeSeg()
       
   264 	{
       
   265 	return iCodeSeg ? iCodeSeg : iTempCodeSeg;
       
   266 	}
       
   267 
       
   268 TInt DProcess::SetPriority(TProcessPriority aPriority)
       
   269 	{
       
   270 	TInt p=ConvertPriority(aPriority);
       
   271 	if (p<0)
       
   272 		return KErrArgument;
       
   273 	if (iExitType!=EExitPending)
       
   274 		return KErrDied;
       
   275 
       
   276 	__KTRACE_OPT(KPROC,Kern::Printf("Process %O SetPriority(%d)",this,p));
       
   277 	TInt r=WaitProcessLock();
       
   278 	__KTRACE_FAIL(r,Kern::Printf("PSP: %d",r));
       
   279 	if (r!=KErrNone)
       
   280 		return KErrDied;
       
   281 #ifdef BTRACE_THREAD_PRIORITY
       
   282 	BTrace8(BTrace::EThreadPriority,BTrace::EProcessPriority,this,p);
       
   283 #endif
       
   284 	NKern::LockSystem();
       
   285 	iPriority=p;
       
   286 	SDblQueLink* pLink=iThreadQ.First();
       
   287 	while (pLink!=&iThreadQ.iA)
       
   288 		{
       
   289 		DThread* pT=_LOFF(pLink,DThread,iProcessLink);
       
   290 		pT->SetThreadPriority(pT->iThreadPriority);
       
   291 		pLink=pLink->iNext;
       
   292 		NKern::FlashSystem();
       
   293 		}
       
   294 	NKern::UnlockSystem();
       
   295 	SignalProcessLock();
       
   296 	return KErrNone;
       
   297 	}
       
   298 
       
   299 TInt DProcess::ConvertPriority(TProcessPriority aPriority)
       
   300 	{
       
   301 	TInt p=-1;
       
   302 	switch(aPriority)
       
   303 		{
       
   304 		case EPriorityLow: p=EProcPriorityLow; break;
       
   305 		case EPriorityBackground: p=EProcPriorityBackground; break;
       
   306 		case EPriorityForeground: p=EProcPriorityForeground; break;
       
   307 		case EPriorityHigh: p=EProcPriorityHigh; break;
       
   308 		case EPriorityWindowServer: p=EProcPrioritySystemServer1; break;
       
   309 		case EPriorityFileServer: p=EProcPrioritySystemServer2; break;
       
   310 		case EPriorityRealTimeServer: p=EProcPriorityRealTimeServer; break;
       
   311 		case EPrioritySupervisor: p=EProcPrioritySystemServer3; break;
       
   312 		}
       
   313 	return p;
       
   314 	}
       
   315 
       
   316 TInt DProcess::Rename(const TDesC& aName)
       
   317 	{
       
   318 	if (aName.Length()>KMaxKernelName-KMaxUidName-4)
       
   319 		return KErrBadName;
       
   320 	TKName n;
       
   321 	DObject::BaseName(n); // get current name, without UID and generation number
       
   322 	if (n.MatchF(aName)==0)
       
   323 		return KErrNone;		// new name is the same so nothing to do
       
   324 
       
   325 	iGeneration = NextGeneration(aName, iUids.iUid[2]);
       
   326 
       
   327 	__KTRACE_OPT(KTHREAD,Kern::Printf("DProcess::Rename %O to %lS",this,&aName));
       
   328 	TInt r = SetName(&aName);
       
   329 #ifdef BTRACE_THREAD_IDENTIFICATION
       
   330 	Name(n);
       
   331 	BTraceN(BTrace::EThreadIdentification,BTrace::EProcessName,0,this,n.Ptr(),n.Size());
       
   332 #endif
       
   333 
       
   334 	__COND_DEBUG_EVENT(r==KErrNone, EEventUpdateProcess, this);
       
   335 	return(r);
       
   336 	}
       
   337 
       
   338 void DProcess::Release()
       
   339 	{
       
   340 #ifdef __SMP__
       
   341 	// delete thread group
       
   342 	if (iSMPUnsafeGroup)
       
   343 		{
       
   344 		NKern::GroupDestroy(iSMPUnsafeGroup);
       
   345 		Kern::Free(iSMPUnsafeGroup);
       
   346 		}
       
   347 #endif
       
   348 
       
   349 	// delete handles with lock mutex free
       
   350 	__KTRACE_OPT(KPROC,Kern::Printf("Process %O Release()",this));
       
   351 	__KTRACE_OPT(KPROC,Kern::Printf("Deleting handles"));
       
   352 	iHandles.Close(this);
       
   353 
       
   354 	// Notify process unloading before code segs are released
       
   355 	__DEBUG_EVENT(EEventUnloadingProcess, this);
       
   356 
       
   357 	__NK_ASSERT_DEBUG(iGarbageList.IsEmpty());
       
   358 
       
   359 	if (iCodeSeg || iTempCodeSeg)
       
   360 		{
       
   361 		DCodeSeg::Wait();
       
   362 		if (iCodeSeg)
       
   363 			RemoveCodeSeg(iCodeSeg, NULL);
       
   364 		DCodeSeg* pS = (DCodeSeg*)__e32_atomic_swp_ord_ptr(&iTempCodeSeg, 0);
       
   365 		if (pS)
       
   366 			pS->CheckedClose();
       
   367 		RemoveDllData();
       
   368 		DCodeSeg::Signal();
       
   369 		}
       
   370 
       
   371 	__ASSERT_ALWAYS(iDynamicCode.Count()==0, K::Fault(K::ECodeStillMapped));
       
   372 	iDynamicCode.Close();
       
   373 
       
   374 	__KTRACE_OPT(KPROC,Kern::Printf("Closing DLL$LOCK mutex"));
       
   375 	Kern::SafeClose((DObject*&)iDllLock,this);
       
   376 
       
   377 	__KTRACE_OPT(KPROC,Kern::Printf("Closing owning process"));
       
   378 	Kern::SafeClose((DObject*&)iOwningProcess,NULL);
       
   379 
       
   380 	__KTRACE_OPT(KPROC,Kern::Printf("Closing DataBssStack chunk"));
       
   381 	Kern::SafeClose((DObject*&)iDataBssStackChunk,this);
       
   382 
       
   383 	NKern::LockSystem();
       
   384 	iFinalReleaseFlag = ETrue;
       
   385 	if (iProcessLock)
       
   386 		iProcessLock->Wait();			// this will get released when the lock mutex is deleted
       
   387 	NKern::UnlockSystem();
       
   388 
       
   389 	__KTRACE_OPT(KPROC,Kern::Printf("Calling FinalRelease()"));
       
   390 	// Call FinalRelease() with process $LOCK mutex held (if it exists)
       
   391 	// and don't ever release the mutex afterwards.
       
   392 	FinalRelease();
       
   393 
       
   394 	__KTRACE_OPT(KPROC,Kern::Printf("Closing $LOCK mutex"));
       
   395 	Kern::SafeClose((DObject*&)iProcessLock,this);
       
   396 
       
   397 	// Notify process removal before closing process
       
   398 	__DEBUG_EVENT(EEventRemoveProcess, this);
       
   399 
       
   400 #ifdef BTRACE_THREAD_IDENTIFICATION
       
   401 	BTrace4(BTrace::EThreadIdentification,BTrace::EProcessDestroy,this);
       
   402 #endif
       
   403 
       
   404 	// Kill any processes which we created but have not resumed
       
   405 	NKern::LockSystem();	// In case we died in the middle of DProcess::Resume()
       
   406 	NKern::UnlockSystem();
       
   407 	for(;;)
       
   408 		{
       
   409 		DObjectCon& processes=*K::Containers[EProcess];
       
   410 		processes.Wait();
       
   411 		DProcess* zombie=NULL;
       
   412 		TInt c=processes.Count();
       
   413 		for (TInt i=0; i<c; i++)
       
   414 			{
       
   415 			DProcess* pP=(DProcess*)processes[i];
       
   416 			if (pP->iCreatorId==iId && pP!=this && pP->Open()==KErrNone)
       
   417 				{
       
   418 				zombie = pP;
       
   419 				break;
       
   420 				}
       
   421 			}
       
   422 		processes.Signal();
       
   423 		if(!zombie)
       
   424 			break;
       
   425 		__KTRACE_OPT(KPROC,Kern::Printf("Killing zombie process %O",zombie));
       
   426 		zombie->iCreatorId=zombie->iId;
       
   427 		zombie->Die(EExitPanic,EZombieProcessKilled,KLitKernExec());
       
   428 		zombie->Close(0);
       
   429 		}
       
   430 
       
   431 	__KTRACE_OPT(KPROC,Kern::Printf("Closing process"));
       
   432 	Close(this);
       
   433 	}
       
   434 
       
   435 TInt DProcess::WaitProcessLock()
       
   436 	{
       
   437 	TInt r=KErrGeneral;
       
   438 	NKern::LockSystem();
       
   439 	if (iProcessLock && !iFinalReleaseFlag)				// iProcessLock is deleted during process death
       
   440 		{
       
   441 		r=iProcessLock->Wait();							// mutex may be resetting just before deletion
       
   442 		__KTRACE_FAIL(r,Kern::Printf("PLW: %d",r));		// will return KErrGeneral if mutex is reset
       
   443 		}
       
   444 	NKern::UnlockSystem();
       
   445 	__KTRACE_FAIL(r,Kern::Printf("WPL: %d",r));
       
   446 	return r;
       
   447 	}
       
   448 
       
   449 TInt DProcess::SignalProcessLock()
       
   450 	{
       
   451 	TInt r=KErrDied;
       
   452 	NKern::LockSystem();
       
   453 	if (iProcessLock)
       
   454 		{
       
   455 		iProcessLock->Signal();
       
   456 		r=KErrNone;
       
   457 		}
       
   458 	else
       
   459 		NKern::UnlockSystem();
       
   460 	__KTRACE_FAIL(r,Kern::Printf("SPL: %d",r));
       
   461 	return r;
       
   462 	}
       
   463 
       
   464 TInt DProcess::Loaded(TProcessCreateInfo& aInfo)
       
   465 //
       
   466 // Confirm that the process has been loaded O.K.
       
   467 //
       
   468 	{
       
   469 	__KTRACE_OPT(KPROC,Kern::Printf("DProcess::Loaded"));
       
   470 
       
   471 	//
       
   472 	// Update our code segment and dependents
       
   473 	//
       
   474 	DCodeSeg::Wait();
       
   475 
       
   476 	TInt r = KErrNone;
       
   477 
       
   478 	if (!(iTempCodeSeg->iMark & DCodeSeg::EMarkLoaded))
       
   479 		{
       
   480 		// newly loaded code segment, not another instance of same
       
   481 		r = iTempCodeSeg->Loaded(aInfo);
       
   482 		}
       
   483 
       
   484 	if (r == KErrNone)
       
   485 		r = OpenDeps();
       
   486 
       
   487 	DCodeSeg::Signal();
       
   488 
       
   489 	if (r != KErrNone)
       
   490 		return r;
       
   491 
       
   492 	if (iCodeSeg->iAttr & ECodeSegAttSMPSafe)
       
   493 		iSMPUnsafeCount = 0;
       
   494 	else
       
   495 		{
       
   496 		iSMPUnsafeCount = 1;
       
   497 #ifdef __SMP__
       
   498 		r = UpdateSMPSafe();
       
   499 		if (r != KErrNone)
       
   500 			return r;
       
   501 #endif
       
   502 		}
       
   503 	FirstThread()->iMState=DThread::EReady;
       
   504 	SetProtection(DObject::EGlobal);
       
   505 	iAttributes &= ~EBeingLoaded;
       
   506 	iReentryPoint = iCodeSeg->iEntryPtVeneer;
       
   507 
       
   508 	// Send loaded process notification.
       
   509 	__DEBUG_EVENT(EEventLoadedProcess, this);
       
   510 
       
   511 	return KErrNone;
       
   512 	}
       
   513 
       
   514 void DProcess::Resume()
       
   515 //
       
   516 // Resume a newly created process. Idempotent. Enter and return with system locked.
       
   517 //
       
   518 	{
       
   519 	if (iAttributes&EBeingLoaded)
       
   520 		K::PanicCurrentThread(EProcessNotLoaded);
       
   521 	if (!(iAttributes&EResumed))
       
   522 		{
       
   523 		iAttributes|=EResumed;
       
   524 		iCreatorId = iId;	// Creator loses control over process once it has been resumed
       
   525 		FirstThread()->Resume();
       
   526 		}
       
   527 	}
       
   528 
       
   529 void DProcess::Die(TExitType aType, TInt aReason, const TDesC &aCategory)
       
   530 //
       
   531 // Kill a process. Enter and return with system unlocked and calling thread in critical section.
       
   532 //
       
   533 	{
       
   534 	__KTRACE_OPT(KPROC,Kern::Printf("Process %O Die: %d %d %lS",this,aType,aReason,&aCategory));
       
   535 
       
   536 	TInt r=WaitProcessLock();
       
   537 	if (r!=KErrNone)
       
   538 		return;			// process already exiting
       
   539 	NKern::LockSystem();
       
   540 	if (iAttributes&EBeingLoaded)
       
   541 		{
       
   542 		// Load failed before UserSvr::ProcessLoaded() was called.
       
   543 		// The thread is still runnable however, since UserSvr::ProcessCreate() must have succeeded.
       
   544 		// We just need to set the thread state so it can be resumed.
       
   545 		FirstThread()->iMState=DThread::EReady;
       
   546 		}
       
   547 	if (iExitType==EExitPending)
       
   548 		{
       
   549 		iExitType = (TUint8)aType;
       
   550 		iExitReason=aReason;
       
   551 		if (iExitType==EExitKill)
       
   552 			iExitCategory=KLitKill;
       
   553 		else if (iExitType==EExitTerminate)
       
   554 			iExitCategory=KLitTerminate;
       
   555 		else
       
   556 			iExitCategory=aCategory;
       
   557 
       
   558 		if (iExitType!=EExitKill && (iFlags & (KProcessFlagSystemPermanent|KProcessFlagSystemCritical)))
       
   559 			K::Fault(K::ESystemProcessPanic);
       
   560 		if (iFlags & KProcessFlagSystemPermanent)
       
   561 			K::Fault(K::EPermanentProcessExit);
       
   562 
       
   563 		// Kill all threads; when the last one exits the process will be cleaned up.
       
   564 		TBool killMe = KillAllThreads(aType, aReason, aCategory);
       
   565 		if (killMe)
       
   566 			{
       
   567 			DThread* pC=TheCurrentThread;
       
   568 			pC->iExitType=(TUint8)iExitType;
       
   569 			pC->iExitReason=iExitReason;
       
   570 			pC->iExitCategory=iExitCategory;
       
   571 			NKern::DeferredExit();
       
   572 			}
       
   573 		}
       
   574 	NKern::UnlockSystem();
       
   575 	SignalProcessLock();
       
   576 	}
       
   577 
       
   578 TBool DProcess::KillAllThreads(TExitType aType, TInt aReason, const TDesC &aCategory)
       
   579 //
       
   580 // Kill all threads in a process.  Enter and return with system locked, the process lock held and
       
   581 // calling thread in a critical section.  Returns whether the current thread needs to exit too.
       
   582 //
       
   583 	{
       
   584 	TBool killMe=EFalse;
       
   585 	DThread* pC=TheCurrentThread;
       
   586 	SDblQueLink* pLink=iThreadQ.First();
       
   587 	while (pLink!=&iThreadQ.iA)
       
   588 		{
       
   589 		DThread* pT=_LOFF(pLink,DThread,iProcessLink);
       
   590 		pLink=pLink->iNext;
       
   591 		if (pT!=pC)
       
   592 			{
       
   593 			// Need to stop the current thread being killed as a consequence of killing pT
       
   594 			pT->iFlags &= ~(KThreadFlagProcessPermanent|KThreadFlagProcessCritical);
       
   595 			pT->Die(aType, aReason, aCategory);
       
   596 			}
       
   597 		else
       
   598 			{
       
   599 			killMe=ETrue;
       
   600 			NKern::UnlockSystem();
       
   601 			}
       
   602 		NKern::LockSystem();
       
   603 		}
       
   604 	return killMe;
       
   605 	}
       
   606 
       
   607 void DProcess::AddThread(DThread &aThread)
       
   608 	{
       
   609 	__KTRACE_OPT(KPROC,Kern::Printf("AddThread %O to %O",&aThread,this));
       
   610 	iThreadQ.Add(&aThread.iProcessLink);
       
   611 	}
       
   612 
       
   613 TInt DProcess::NewThread(DThread*& aThread, SThreadCreateInfo& anInfo, TInt* aHandle, TOwnerType aType)
       
   614 	{
       
   615 	__KTRACE_OPT(KTHREAD,Kern::Printf("NewThread proc %O, func %08x ptr %08x",this,anInfo.iFunction,anInfo.iPtr));
       
   616 	__KTRACE_OPT(KTHREAD,Kern::Printf("type %d name %lS pri %d",anInfo.iType,&anInfo.iName,anInfo.iInitialThreadPriority));
       
   617 	if (aHandle)
       
   618 		*aHandle=0;
       
   619 	TInt r=GetNewThread(aThread,anInfo);
       
   620 	__KTRACE_FAIL(r,Kern::Printf("GNT: %d",r));
       
   621 	DThread* pT=aThread;
       
   622 	if (r==KErrNone)
       
   623 		{
       
   624 		r=pT->Create(anInfo);
       
   625 		__KTRACE_FAIL(r,Kern::Printf("NTC: %d",r));
       
   626 		if (r==KErrNone && aHandle)
       
   627 			{
       
   628 			r=K::MakeHandleAndOpen(aType,pT,*aHandle);
       
   629 			__KTRACE_FAIL(r,Kern::Printf("NT MHO: %d",r));
       
   630 			}
       
   631 		if (r==KErrNone)
       
   632 			{
       
   633 			r=WaitProcessLock();
       
   634 			if (r==KErrNone)
       
   635 				{
       
   636 				NKern::LockSystem();
       
   637 				if (iExitType==EExitPending)
       
   638 					{
       
   639 					AddThread(*pT);
       
   640 					pT->iMState=DThread::EReady;
       
   641 					// set fully constructed flag here
       
   642 					}
       
   643 				else
       
   644 					r=KErrDied;
       
   645 				NKern::UnlockSystem();
       
   646 				SignalProcessLock();
       
   647 				__KTRACE_FAIL(r,Kern::Printf("NT ADD: %d",r));
       
   648 				}
       
   649 			else
       
   650 				r=KErrDied;
       
   651 			}
       
   652 		}
       
   653 	if (r==KErrNone)
       
   654 		{
       
   655 		if (anInfo.iType == EThreadUser)
       
   656 			{
       
   657 			pT->iUserThreadState = DThread::EUserThreadCreated;
       
   658 			__e32_atomic_tas_ord32(&iUserThreadsRunning, 1, 1, 0);
       
   659 			}	
       
   660 #ifdef BTRACE_THREAD_IDENTIFICATION
       
   661 		if(BTrace::Filter(BTrace::EThreadIdentification))
       
   662 			{
       
   663 			DObjectCon* threads=Kern::Containers()[EThread];
       
   664 			threads->Wait(); // hold mutex so traces below don't get mixed up with other thread creation traces
       
   665 			TKName nameBuf;
       
   666 			Name(nameBuf);
       
   667 			BTraceN(BTrace::EThreadIdentification,BTrace::EProcessName,&pT->iNThread,this,nameBuf.Ptr(),nameBuf.Size());
       
   668 			pT->Name(nameBuf);
       
   669 			BTraceN(BTrace::EThreadIdentification,BTrace::EThreadCreate,&pT->iNThread,this,nameBuf.Ptr(),nameBuf.Size());
       
   670 			BTrace12(BTrace::EThreadIdentification,BTrace::EThreadId,&pT->iNThread,this,pT->iId);
       
   671 			threads->Signal();
       
   672 			}
       
   673 #endif
       
   674 		__DEBUG_EVENT2(EEventAddThread, pT, TheCurrentThread);
       
   675 		}
       
   676 	else if (pT)
       
   677 		{
       
   678 		if (aHandle && *aHandle)
       
   679 			{
       
   680 			K::HandleClose(*aHandle);
       
   681 			*aHandle=0;
       
   682 			}
       
   683 		pT->Stillborn();
       
   684 		aThread=NULL;
       
   685 		}
       
   686 	__KTRACE_FAIL(r,Kern::Printf("NT: %d",r));
       
   687 	return r;
       
   688 	}
       
   689 
       
   690 void DProcess::Rendezvous(TInt aReason)
       
   691 //
       
   692 // Enter and return with system unlocked and calling thread in critical section.
       
   693 //
       
   694 	{
       
   695 	TLogon::CompleteAll(iTargetLogons, TLogon::ETargetRendezvous, aReason);
       
   696 	}
       
   697 
       
   698 TInt DProcess::Logon(TRequestStatus* aStatus, TBool aRendezvous)
       
   699 	{
       
   700 	TInt r = KErrNoMemory;
       
   701 	DThread* pC = TheCurrentThread;
       
   702 	__KTRACE_OPT(KTHREAD, Kern::Printf("Thread %O Logon to process %O, status at %08x rdv=%x",
       
   703 		     pC, this, aStatus, aRendezvous));
       
   704 
       
   705 	TLogon* pL = new TLogon;
       
   706 	if (pL)
       
   707 		{
       
   708 		TUint32 type = TLogon::ETargetProcess;
       
   709 		if (aRendezvous)
       
   710 			type |= TLogon::ERendezvous;
       
   711 		r = pL->Attach(iTargetLogons, pC, this, aStatus, type);
       
   712 		if (r != KErrNone)
       
   713 			pL->Close();
       
   714 		}
       
   715 
       
   716 	__KTRACE_OPT(KTHREAD, Kern::Printf("DProcess::Logon ret %d", r));
       
   717 	return r;
       
   718 	}
       
   719 
       
   720 void DProcess::BTracePrime(TInt aCategory)
       
   721 	{
       
   722 #ifdef BTRACE_THREAD_IDENTIFICATION
       
   723 	if(aCategory==BTrace::EThreadIdentification || aCategory==-1)
       
   724 		BTrace4(BTrace::EThreadIdentification,BTrace::EProcessCreate,this);
       
   725 #endif
       
   726 	}
       
   727 
       
   728 #ifdef __SMP__
       
   729 TInt DProcess::UpdateSMPSafe()
       
   730 	{
       
   731 	TUint32 config = TheSuperPage().KernelConfigFlags();
       
   732 	if (!(config & (EKernelConfigSMPUnsafeCompat|EKernelConfigSMPUnsafeCPU0)) || this == K::TheKernelProcess)
       
   733 		return KErrNone;
       
   734 	__KTRACE_OPT(KPROC,Kern::Printf("Process %O UpdateSMPSafe count=%d",this,iSMPUnsafeCount));
       
   735 	TInt r=WaitProcessLock();
       
   736 	(void)r;
       
   737 	__NK_ASSERT_DEBUG(r==KErrNone);
       
   738 	if ((config & EKernelConfigSMPUnsafeCompat) && !iSMPUnsafeGroup)
       
   739 		{
       
   740 		SNThreadGroupCreateInfo info;
       
   741 		info.iCpuAffinity = KCpuAffinityAny;
       
   742 		iSMPUnsafeGroup = (NThreadGroup*)Kern::Alloc(sizeof(NThreadGroup));
       
   743 		r = KErrNoMemory;
       
   744 		if (iSMPUnsafeGroup)
       
   745 			r = NKern::GroupCreate(iSMPUnsafeGroup, info);
       
   746 		}
       
   747 	if (r==KErrNone)
       
   748 		{
       
   749 		SDblQueLink* pLink=iThreadQ.First();
       
   750 		while (pLink!=&iThreadQ.iA)
       
   751 			{
       
   752 			DThread* pT=_LOFF(pLink,DThread,iProcessLink);
       
   753 			NKern::QueueUserModeCallback(&pT->iNThread, &pT->iSMPSafeCallback);
       
   754 			pLink=pLink->iNext;
       
   755 			}
       
   756 		}
       
   757 	SignalProcessLock();
       
   758 	return r;
       
   759 	}
       
   760 #endif
       
   761