44 size_t occurrenceEpoch;
53 enum class UnregisterResult {
70 : mutationGeneration(0),
72 mode(LineMode::Empty),
73 policyConfigured(
false),
74 trigger(IrqTrigger::Edge),
75 controllerAck(IrqControllerAck::None),
76 lineRelease(IrqLineRelease::AfterHardStage) {}
78 size_t mutationGeneration;
81 bool policyConfigured;
90 bool registerThreadedHandler(uint8_t irq,
IrqHandler* handler);
113 UnregisterResult unregisterHandler(uint8_t irq,
IrqHandlerBase* handler);
121 UnregisterResult unregisterHandler(uint8_t irq,
IrqHandlerBase* handler,
122 LineMode& removedDelivery);
131 bool dispatchHard(uint8_t irq, InterruptState& state,
HardIrqDisposition& disposition,
132 HardIrqHandler* onlyHandler =
nullptr,
size_t dispatchGeneration = 0,
133 irq_id_t callbackId = 0);
134 bool dispatchHard(uint8_t irq, InterruptState& state,
HardIrqDisposition& disposition,
139 bool hardLineQuarantined(uint8_t irq)
const;
151 bool publishThreadedDispatch(uint8_t irq,
size_t dispatchGeneration);
152 bool publishThreadedDispatch(uint8_t irq,
size_t dispatchGeneration,
174 void invalidateThreadedLine(uint8_t irq,
size_t throughGeneration);
183 void invalidateThreadedGenerationFromInterrupt(uint8_t irq,
size_t throughGeneration);
196 IrqHandler* onlyHandler =
nullptr, irq_id_t callbackId = 0);
198 size_t handlerCount(uint8_t irq);
204 LineMode lineMode(uint8_t irq);
213 bool snapshotLineConfiguration(uint8_t irq,
LineConfiguration& configuration)
const;
222 size_t hardDispatchState(uint8_t irq,
size_t& exactGeneration)
const;
232 size_t threadedDispatchState(uint8_t irq, uintptr_t& exactHandlerIdentity)
const;
234#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
235 enum class HandlerHazardStage {
240 RetirementBoundaryPublished,
241 BeforeClaimFinalization,
242 FinalizationContended,
243 BeforeActionMutationPin,
245 BeforePendingExchange,
247 BeforeQuiescedExchange,
251 enum class OccurrenceCaptureStage {
260 using HandlerHazardHook = void (*)(
IrqHandlerBase*, HandlerHazardStage);
261 using DispatchAbandonHook = void (*)(
void*, bool);
262 using MutationLockHook = void (*)();
263 using OccurrenceCaptureHook = void (*)(
IrqHandlerRegistry*, uint8_t, OccurrenceCaptureStage,
266 void setHandlerPinHook(HandlerPinHook hook);
267 void setHandlerPrePinHook(HandlerPrePinHook hook);
268 void setHandlerHazardHook(HandlerHazardHook hook);
269 void setDispatchAbandonHook(DispatchAbandonHook hook);
270 void setOccurrenceCaptureHookForTest(OccurrenceCaptureHook hook);
271 void withMutationLockForTest(MutationLockHook hook);
272 void withMutationEpochForTest(MutationLockHook hook);
274 size_t claimedDispatchCountForOwnerForTest(
void* owner);
275 bool containsHandlerForTest(uint8_t irq,
IrqHandlerBase* handler);
276 size_t tombstoneCountForTest(uint8_t irq)
const;
277 size_t threadedActionMutationWriterCountForTest()
const;
278 bool setThreadedActionLanesForTest(
IrqHandlerBase* handler,
size_t pendingGeneration,
279 size_t claimedGeneration,
size_t quiescedGeneration);
280 bool consumeThreadedQuiescedForTest(
IrqHandlerBase* handler,
size_t generation);
281 bool publishControllerQuiescedForTest(
IrqHandlerBase* handler, uint8_t irq,
size_t generation);
285 enum class Delivery :
size_t {
290 static constexpr size_t MaxHandlerSlots = 64;
291 static constexpr size_t MaxActiveDispatches = 64;
292 static constexpr size_t IrqCount = 256;
294 static constexpr size_t GraceBucketCount = 16;
295 static constexpr uint8_t InvalidIrq = 0xFF;
297 enum class SlotMode :
size_t {
307 enum class QuiescedLane :
size_t {
314 static constexpr size_t QuiescedLaneCount =
static_cast<size_t>(QuiescedLane::Count);
316 static constexpr size_t ModeBits = 3;
317 static constexpr size_t ModeMask = (1 << ModeBits) - 1;
318 static constexpr size_t DeliveryBits = 1;
319 static constexpr size_t DeliveryShift = ModeBits;
320 static constexpr size_t DeliveryMask = ((1 << DeliveryBits) - 1) << DeliveryShift;
321 static constexpr size_t IrqShift = DeliveryShift + DeliveryBits;
322 static constexpr size_t IrqMask = 0xFF << IrqShift;
323 static constexpr size_t GenerationShift = IrqShift + 8;
324 static constexpr size_t MaximumPublicationGeneration = ~static_cast<size_t>(0) >> GenerationShift;
326 static constexpr size_t PolicyValid = 1U << 0;
327 static constexpr size_t PolicyTriggerShift = 1;
328 static constexpr size_t PolicyControllerAckShift = 3;
329 static constexpr size_t PolicyLineReleaseShift = 5;
330 static constexpr size_t PolicyTriggerMask = 3U << PolicyTriggerShift;
331 static constexpr size_t PolicyControllerAckMask = 3U << PolicyControllerAckShift;
332 static constexpr size_t PolicyLineReleaseMask = 1U << PolicyLineReleaseShift;
333 static constexpr size_t PolicyMixedCompatibilityMask =
334 PolicyTriggerMask | PolicyControllerAckMask;
335 static constexpr size_t LineSnapshotAttempts = 2;
344 admittedPublication(0),
345 controllerGeneration(0),
352 size_t admittedPublication;
353 size_t controllerGeneration;
364 pendingThreadedGeneration(0),
365 claimedThreadedGeneration(0),
366 quiescedThreadedGenerations(),
369 finalizationGate(0) {}
374 size_t admissionEpoch;
375 size_t pendingThreadedGeneration;
376 size_t claimedThreadedGeneration;
377 size_t quiescedThreadedGenerations[QuiescedLaneCount];
378 size_t retirementEpoch;
381 size_t finalizationGate;
386 size_t admittedPublication,
bool isCallback =
true)
387 : registry(registry),
389 owner(dispatchOwner),
390 publication(admittedPublication),
391 callback(isCallback),
392 activeDispatch(
nullptr),
393 previousDeviceHardIrqDepth(0),
394 restoreDeviceHardIrqDepth(
false),
395 previousInterruptState(
false),
396 restoreInterruptState(
false),
405 size_t previousDeviceHardIrqDepth;
406 bool restoreDeviceHardIrqDepth;
407 bool previousInterruptState;
408 bool restoreInterruptState;
414 : registry(owner), cutoff(admissionCutoff), thread(
nullptr), ownsCutoff(
false), cleanup() {}
425 : registry(owner), thread(
nullptr), cleanup() {}
432 static size_t makePublication(
size_t generation, uint8_t irq, SlotMode mode, Delivery delivery);
433 static size_t generationOf(
size_t publication);
434 static uint8_t irqOf(
size_t publication);
435 static SlotMode modeOf(
size_t publication);
436 static Delivery deliveryOf(
size_t publication);
437 static bool generationReached(
size_t current,
size_t target);
438 static size_t encodePolicy(
const IrqPolicy* policy);
440 static bool mixedPoliciesCompatible(
size_t first,
size_t second);
441 static size_t effectiveMixedPolicy(
size_t hard,
size_t threaded);
442 static LineMode lineModeForDelivery(Delivery delivery);
444 bool registerHandler(uint8_t irq,
IrqHandlerBase* handler, Delivery delivery,
size_t policy);
446 bool acquireOccurrenceReaderLeases(uint8_t irq,
size_t readerBank,
size_t count);
447 void releaseOccurrenceReaderLeases(uint8_t irq,
size_t readerBank,
size_t count);
450 static void abandonAdmissionCutoff(
void* context);
452 void beginMutation();
453 void finishMutation();
456 void completeThreadedActionMutation();
457 static void abandonThreadedActionMutation(
void* context);
460 bool retireSlotOrObserveClosed(
HandlerSlot& slot,
size_t expectedPublication,
462 bool closeSlotAdmission(
HandlerSlot& slot,
size_t expectedPublication,
size_t& closedPublication);
463 void tryReclaimTombstones(uint8_t irq);
465 bool publishDispatch(
DispatchCleanup& cleanup,
size_t controllerGeneration);
467 static void abandonDispatch(
void* context);
469 static bool canWaitForActionFinalization();
470 bool acquireFinalizationGate(
HandlerSlot& slot,
bool canWait);
471 static void releaseFinalizationGate(
HandlerSlot& slot);
475 bool hasActiveDispatch(
HandlerSlot& slot,
size_t admittedPublication)
const;
476 bool findCurrentDispatch(
void* owner,
HandlerSlot* target,
size_t targetPublication,
477 bool& callbackContext)
const;
478 static void* currentDispatchOwner();
479 bool threadedGenerationValid(uint8_t irq,
size_t generation)
const;
480 void publishSlotQuiesced(
HandlerSlot& slot, uint8_t irq,
size_t dispatchGeneration,
482 void publishSlotQuiescedValue(
HandlerSlot& slot, uint8_t irq,
size_t dispatchGeneration,
484 static size_t* quiescedLane(
HandlerSlot& slot, QuiescedLane lane);
485 static const size_t* quiescedLane(
const HandlerSlot& slot, QuiescedLane lane);
486 static bool hasQuiescedGeneration(
const HandlerSlot& slot);
491 size_t m_HardHandoffEpochs[GraceBucketCount];
492 size_t m_ThreadedInvalidationGenerations[IrqCount];
493 size_t m_ThreadedActionMutationGeneration;
494 size_t m_ThreadedActionMutationWriters;
495 size_t m_OccurrenceEpochs[GraceBucketCount];
496 size_t m_OccurrenceReaders[GraceBucketCount][2];
497 size_t m_OccurrenceBoundaryLocks[GraceBucketCount];
499 size_t m_AdmissionEpoch;
500 size_t m_MutationGeneration;
501 size_t m_MutationWriters;
503#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
504 void observeOccurrenceCaptureForTest(uint8_t irq, OccurrenceCaptureStage stage,
505 size_t occurrenceEpoch);
506 HandlerPinHook m_HandlerPinHook;
507 HandlerPrePinHook m_HandlerPrePinHook;
508 HandlerHazardHook m_HandlerHazardHook;
509 DispatchAbandonHook m_DispatchAbandonHook;
510 OccurrenceCaptureHook m_OccurrenceCaptureHook;