kernel/eka/nkernsmp/nk_irq.cpp
branchRCL_3
changeset 43 c1f20ce4abcf
parent 8 538db54a451d
child 44 3e88ff8f41d5
equal deleted inserted replaced
42:a179b74831c9 43:c1f20ce4abcf
    27 
    27 
    28 NIrq		Irq[NK_MAX_IRQS];
    28 NIrq		Irq[NK_MAX_IRQS];
    29 NIrqHandler	Handlers[NK_MAX_IRQ_HANDLERS];
    29 NIrqHandler	Handlers[NK_MAX_IRQ_HANDLERS];
    30 NIrqHandler* NIrqHandler::FirstFree;
    30 NIrqHandler* NIrqHandler::FirstFree;
    31 
    31 
    32 extern "C" void send_irq_ipi(TSubScheduler*);
    32 extern "C" void send_irq_ipi(TSubScheduler*, TInt);
    33 
    33 
    34 void StepCookie(volatile TUint16& p, TInt n)
    34 void StepCookie(volatile TUint16& p, TInt n)
    35 	{
    35 	{
    36 	TUint32 x = p<<17;
    36 	TUint32 x = p<<17;
    37 	while(n--)
    37 	while(n--)
   250 	{
   250 	{
   251 	TUint32 orig = DoActivate(aCount);
   251 	TUint32 orig = DoActivate(aCount);
   252 	TRACE_IRQ12(17, this, orig, aCount);
   252 	TRACE_IRQ12(17, this, orig, aCount);
   253 	if (orig & (EDisable|EUnbind|EActive))
   253 	if (orig & (EDisable|EUnbind|EActive))
   254 		return;	// disabled or already active
   254 		return;	// disabled or already active
   255 	if (iTied)
   255 	NSchedulable* tied = iTied;
       
   256 	if (tied)
   256 		{
   257 		{
   257 		// we need to enforce mutual exclusion between the event handler
   258 		// we need to enforce mutual exclusion between the event handler
   258 		// and the tied thread or thread group, so the event handler must
   259 		// and the tied thread or thread group, so the event handler must
   259 		// run on the CPU to which the thread or group is currently attached
   260 		// run on the CPU to which the thread or group is currently attached
   260 		// once the event has been attached to that CPU, the thread/group
   261 		// once the event has been attached to that CPU, the thread/group
   261 		// can't be migrated until the event handler completes.
   262 		// can't be migrated until the event handler completes.
   262 		// need a pending event count for the tied thread/group
   263 		// need a pending event count for the tied thread/group
   263 		// so we know when the thread/group can be migrated
   264 		// so we know when the thread/group can be migrated
   264 		TInt tied_cpu = iTied->BeginTiedEvent();
   265 		TInt tied_cpu = tied->BeginTiedEvent();
   265 		TInt this_cpu = NKern::CurrentCpu();
   266 		TInt this_cpu = NKern::CurrentCpu();
   266 		if (tied_cpu != this_cpu)
   267 		if (tied_cpu != this_cpu)
   267 			{
   268 			{
   268 			__e32_atomic_add_acq32(&iIrq->iEventsPending, 1);
   269 			__e32_atomic_add_acq32(&iIrq->iEventsPending, 1);
   269 			TheSubSchedulers[tied_cpu].QueueEventAndKick(this);
   270 			TheSubSchedulers[tied_cpu].QueueEventAndKick(this);
   280 		(*iFn)(iPtr);
   281 		(*iFn)(iPtr);
   281 		orig = EventDone();
   282 		orig = EventDone();
   282 		TRACE_IRQ8(19, this, orig);
   283 		TRACE_IRQ8(19, this, orig);
   283 		if (!(orig & EActive))
   284 		if (!(orig & EActive))
   284 			{
   285 			{
   285 			if (iTied)
   286 			if (tied)
   286 				iTied->EndTiedEvent();
   287 				tied->EndTiedEvent();
   287 			return;	// that was last occurrence or event now disabled
   288 			return;	// that was last occurrence or event now disabled
   288 			}
   289 			}
   289 		}
   290 		}
   290 	__e32_atomic_add_ord32(&iIrq->iEventsPending, 1);
   291 	__e32_atomic_add_ord32(&iIrq->iEventsPending, 1);
   291 //	add event to this cpu
   292 //	add event to this cpu
   454 	iIrqLink.Deque();
   455 	iIrqLink.Deque();
   455 	iIrq = 0;
   456 	iIrq = 0;
   456 	pI->Done();
   457 	pI->Done();
   457 	}
   458 	}
   458 
   459 
   459 TBool TSubScheduler::QueueEvent(NEventHandler* aEvent)
   460 TInt TSubScheduler::QueueEvent(NEventHandler* aEvent)
   460 	{
   461 	{
       
   462 	TInt r = 0;
   461 	TInt irq = __SPIN_LOCK_IRQSAVE(iEventHandlerLock);
   463 	TInt irq = __SPIN_LOCK_IRQSAVE(iEventHandlerLock);
   462 	TBool pending = iEventHandlersPending;
   464 	if (!(iScheduler->iIpiAcceptCpus & iCpuMask))
       
   465 		r = EQueueEvent_WakeUp;
       
   466 	else if (!iEventHandlersPending)
       
   467 		r = EQueueEvent_Kick;
   463 	iEventHandlersPending = TRUE;
   468 	iEventHandlersPending = TRUE;
   464 	iEventHandlers.Add(aEvent);
   469 	iEventHandlers.Add(aEvent);
   465 	__SPIN_UNLOCK_IRQRESTORE(iEventHandlerLock,irq);
   470 	__SPIN_UNLOCK_IRQRESTORE(iEventHandlerLock,irq);
   466 	return !pending;
   471 	return r;
   467 	}
   472 	}
   468 
   473 
   469 void TSubScheduler::QueueEventAndKick(NEventHandler* aEvent)
   474 void TSubScheduler::QueueEventAndKick(NEventHandler* aEvent)
   470 	{
   475 	{
   471 	if (QueueEvent(aEvent))
   476 	TInt kick = QueueEvent(aEvent);
       
   477 	if (kick)
   472 		{
   478 		{
   473 		// extra barrier ?
   479 		// extra barrier ?
   474 		send_irq_ipi(this);
   480 		send_irq_ipi(this, kick);
   475 		}
   481 		}
   476 	}
   482 	}
   477 
   483 
   478 extern "C" void run_event_handlers(TSubScheduler* aS)
   484 extern "C" void run_event_handlers(TSubScheduler* aS)
   479 	{
   485 	{