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 { |