kernel/eka/nkernsmp/nk_irq.cpp
changeset 90 947f0dc9f7a8
parent 36 538db54a451d
child 257 3e88ff8f41d5
--- a/kernel/eka/nkernsmp/nk_irq.cpp	Tue Feb 02 01:24:03 2010 +0200
+++ b/kernel/eka/nkernsmp/nk_irq.cpp	Fri Apr 16 16:24:37 2010 +0300
@@ -29,7 +29,7 @@
 NIrqHandler	Handlers[NK_MAX_IRQ_HANDLERS];
 NIrqHandler* NIrqHandler::FirstFree;
 
-extern "C" void send_irq_ipi(TSubScheduler*);
+extern "C" void send_irq_ipi(TSubScheduler*, TInt);
 
 void StepCookie(volatile TUint16& p, TInt n)
 	{
@@ -252,7 +252,8 @@
 	TRACE_IRQ12(17, this, orig, aCount);
 	if (orig & (EDisable|EUnbind|EActive))
 		return;	// disabled or already active
-	if (iTied)
+	NSchedulable* tied = iTied;
+	if (tied)
 		{
 		// we need to enforce mutual exclusion between the event handler
 		// and the tied thread or thread group, so the event handler must
@@ -261,7 +262,7 @@
 		// can't be migrated until the event handler completes.
 		// need a pending event count for the tied thread/group
 		// so we know when the thread/group can be migrated
-		TInt tied_cpu = iTied->BeginTiedEvent();
+		TInt tied_cpu = tied->BeginTiedEvent();
 		TInt this_cpu = NKern::CurrentCpu();
 		if (tied_cpu != this_cpu)
 			{
@@ -282,8 +283,8 @@
 		TRACE_IRQ8(19, this, orig);
 		if (!(orig & EActive))
 			{
-			if (iTied)
-				iTied->EndTiedEvent();
+			if (tied)
+				tied->EndTiedEvent();
 			return;	// that was last occurrence or event now disabled
 			}
 		}
@@ -456,22 +457,27 @@
 	pI->Done();
 	}
 
-TBool TSubScheduler::QueueEvent(NEventHandler* aEvent)
+TInt TSubScheduler::QueueEvent(NEventHandler* aEvent)
 	{
+	TInt r = 0;
 	TInt irq = __SPIN_LOCK_IRQSAVE(iEventHandlerLock);
-	TBool pending = iEventHandlersPending;
+	if (!(iScheduler->iIpiAcceptCpus & iCpuMask))
+		r = EQueueEvent_WakeUp;
+	else if (!iEventHandlersPending)
+		r = EQueueEvent_Kick;
 	iEventHandlersPending = TRUE;
 	iEventHandlers.Add(aEvent);
 	__SPIN_UNLOCK_IRQRESTORE(iEventHandlerLock,irq);
-	return !pending;
+	return r;
 	}
 
 void TSubScheduler::QueueEventAndKick(NEventHandler* aEvent)
 	{
-	if (QueueEvent(aEvent))
+	TInt kick = QueueEvent(aEvent);
+	if (kick)
 		{
 		// extra barrier ?
-		send_irq_ipi(this);
+		send_irq_ipi(this, kick);
 		}
 	}