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 bool dispatchHard(uint8_t irq, InterruptState& state,
HardIrqDisposition& disposition,
138 bool hardLineQuarantined(uint8_t irq)
const;
150 bool publishThreadedDispatch(uint8_t irq,
size_t dispatchGeneration);
151 bool publishThreadedDispatch(uint8_t irq,
size_t dispatchGeneration,
173 void invalidateThreadedLine(uint8_t irq,
size_t throughGeneration);
182 void invalidateThreadedGenerationFromInterrupt(uint8_t irq,
size_t throughGeneration);
197 size_t handlerCount(uint8_t irq);
200 LineMode lineMode(uint8_t irq);
209 bool snapshotLineConfiguration(uint8_t irq,
LineConfiguration& configuration)
const;
218 size_t hardDispatchState(uint8_t irq,
size_t& exactGeneration)
const;
228 size_t threadedDispatchState(uint8_t irq, uintptr_t& exactHandlerIdentity)
const;
230#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
231 enum class HandlerHazardStage {
236 RetirementBoundaryPublished,
237 BeforeClaimFinalization,
238 FinalizationContended,
239 BeforeActionMutationPin,
241 BeforePendingExchange,
243 BeforeQuiescedExchange,
247 enum class OccurrenceCaptureStage {
256 using HandlerHazardHook = void (*)(
IrqHandlerBase*, HandlerHazardStage);
257 using DispatchAbandonHook = void (*)(
void*, bool);
258 using MutationLockHook = void (*)();
259 using OccurrenceCaptureHook = void (*)(
IrqHandlerRegistry*, uint8_t, OccurrenceCaptureStage,
262 void setHandlerPinHook(HandlerPinHook hook);
263 void setHandlerPrePinHook(HandlerPrePinHook hook);
264 void setHandlerHazardHook(HandlerHazardHook hook);
265 void setDispatchAbandonHook(DispatchAbandonHook hook);
266 void setOccurrenceCaptureHookForTest(OccurrenceCaptureHook hook);
267 void withMutationLockForTest(MutationLockHook hook);
268 void withMutationEpochForTest(MutationLockHook hook);
270 size_t claimedDispatchCountForOwnerForTest(
void* owner);
271 bool containsHandlerForTest(uint8_t irq,
IrqHandlerBase* handler);
272 size_t tombstoneCountForTest(uint8_t irq)
const;
273 size_t threadedActionMutationWriterCountForTest()
const;
274 bool setThreadedActionLanesForTest(
IrqHandlerBase* handler,
size_t pendingGeneration,
275 size_t claimedGeneration,
size_t quiescedGeneration);
276 bool consumeThreadedQuiescedForTest(
IrqHandlerBase* handler,
size_t generation);
277 bool publishControllerQuiescedForTest(
IrqHandlerBase* handler, uint8_t irq,
size_t generation);
281 enum class Delivery :
size_t {
286 static constexpr size_t MaxHandlerSlots = 64;
287 static constexpr size_t MaxActiveDispatches = 64;
288 static constexpr size_t IrqCount = 256;
290 static constexpr size_t GraceBucketCount = 16;
291 static constexpr uint8_t InvalidIrq = 0xFF;
293 enum class SlotMode :
size_t {
303 enum class QuiescedLane :
size_t {
310 static constexpr size_t QuiescedLaneCount =
static_cast<size_t>(QuiescedLane::Count);
312 static constexpr size_t ModeBits = 3;
313 static constexpr size_t ModeMask = (1 << ModeBits) - 1;
314 static constexpr size_t DeliveryBits = 1;
315 static constexpr size_t DeliveryShift = ModeBits;
316 static constexpr size_t DeliveryMask = ((1 << DeliveryBits) - 1) << DeliveryShift;
317 static constexpr size_t IrqShift = DeliveryShift + DeliveryBits;
318 static constexpr size_t IrqMask = 0xFF << IrqShift;
319 static constexpr size_t GenerationShift = IrqShift + 8;
320 static constexpr size_t MaximumPublicationGeneration = ~static_cast<size_t>(0) >> GenerationShift;
322 static constexpr size_t PolicyValid = 1U << 0;
323 static constexpr size_t PolicyTriggerShift = 1;
324 static constexpr size_t PolicyControllerAckShift = 3;
325 static constexpr size_t PolicyLineReleaseShift = 5;
326 static constexpr size_t PolicyTriggerMask = 3U << PolicyTriggerShift;
327 static constexpr size_t PolicyControllerAckMask = 3U << PolicyControllerAckShift;
328 static constexpr size_t PolicyLineReleaseMask = 1U << PolicyLineReleaseShift;
329 static constexpr size_t PolicyMixedCompatibilityMask =
330 PolicyTriggerMask | PolicyControllerAckMask;
331 static constexpr size_t LineSnapshotAttempts = 2;
340 admittedPublication(0),
341 controllerGeneration(0),
348 size_t admittedPublication;
349 size_t controllerGeneration;
360 pendingThreadedGeneration(0),
361 claimedThreadedGeneration(0),
362 quiescedThreadedGenerations(),
365 finalizationGate(0) {}
370 size_t admissionEpoch;
371 size_t pendingThreadedGeneration;
372 size_t claimedThreadedGeneration;
373 size_t quiescedThreadedGenerations[QuiescedLaneCount];
374 size_t retirementEpoch;
377 size_t finalizationGate;
382 size_t admittedPublication,
bool isCallback =
true)
383 : registry(registry),
385 owner(dispatchOwner),
386 publication(admittedPublication),
387 callback(isCallback),
388 previousDeviceHardIrqDepth(0),
389 restoreDeviceHardIrqDepth(
false),
390 previousInterruptState(
false),
391 restoreInterruptState(
false),
399 size_t previousDeviceHardIrqDepth;
400 bool restoreDeviceHardIrqDepth;
401 bool previousInterruptState;
402 bool restoreInterruptState;
408 : registry(owner), cutoff(admissionCutoff), thread(
nullptr), ownsCutoff(
false), cleanup() {}
419 : registry(owner), thread(
nullptr), cleanup() {}
426 static size_t makePublication(
size_t generation, uint8_t irq, SlotMode mode, Delivery delivery);
427 static size_t generationOf(
size_t publication);
428 static uint8_t irqOf(
size_t publication);
429 static SlotMode modeOf(
size_t publication);
430 static Delivery deliveryOf(
size_t publication);
431 static bool generationReached(
size_t current,
size_t target);
432 static size_t encodePolicy(
const IrqPolicy* policy);
434 static bool mixedPoliciesCompatible(
size_t first,
size_t second);
435 static size_t effectiveMixedPolicy(
size_t hard,
size_t threaded);
436 static LineMode lineModeForDelivery(Delivery delivery);
438 bool registerHandler(uint8_t irq,
IrqHandlerBase* handler, Delivery delivery,
size_t policy);
440 bool acquireOccurrenceReaderLeases(uint8_t irq,
size_t readerBank,
size_t count);
441 void releaseOccurrenceReaderLeases(uint8_t irq,
size_t readerBank,
size_t count);
444 static void abandonAdmissionCutoff(
void* context);
446 void beginMutation();
447 void finishMutation();
450 void completeThreadedActionMutation();
451 static void abandonThreadedActionMutation(
void* context);
454 bool retireSlotOrObserveClosed(
HandlerSlot& slot,
size_t expectedPublication,
456 bool closeSlotAdmission(
HandlerSlot& slot,
size_t expectedPublication,
size_t& closedPublication);
457 void tryReclaimTombstones(uint8_t irq);
460 size_t admittedPublication,
size_t controllerGeneration,
461 bool callback =
true);
462 bool unpublishDispatch(
void* token,
HandlerSlot& slot,
size_t admittedPublication,
bool required);
463 static void abandonDispatch(
void* context);
465 static bool canWaitForActionFinalization();
466 bool acquireFinalizationGate(
HandlerSlot& slot,
bool canWait);
467 static void releaseFinalizationGate(
HandlerSlot& slot);
472 bool hasActiveDispatch(
HandlerSlot& slot,
size_t admittedPublication)
const;
473 bool findCurrentDispatch(
void* owner,
HandlerSlot* target,
size_t targetPublication,
474 bool& callbackContext)
const;
475 static void* currentDispatchOwner();
476 bool threadedGenerationValid(uint8_t irq,
size_t generation)
const;
477 void publishSlotQuiesced(
HandlerSlot& slot, uint8_t irq,
size_t dispatchGeneration,
479 void publishSlotQuiescedValue(
HandlerSlot& slot, uint8_t irq,
size_t dispatchGeneration,
481 static size_t* quiescedLane(
HandlerSlot& slot, QuiescedLane lane);
482 static const size_t* quiescedLane(
const HandlerSlot& slot, QuiescedLane lane);
483 static bool hasQuiescedGeneration(
const HandlerSlot& slot);
488 size_t m_HardHandoffEpochs[GraceBucketCount];
489 size_t m_ThreadedInvalidationGenerations[IrqCount];
490 size_t m_ThreadedActionMutationGeneration;
491 size_t m_ThreadedActionMutationWriters;
492 size_t m_OccurrenceEpochs[GraceBucketCount];
493 size_t m_OccurrenceReaders[GraceBucketCount][2];
494 size_t m_OccurrenceBoundaryLocks[GraceBucketCount];
496 size_t m_AdmissionEpoch;
497 size_t m_MutationGeneration;
498 size_t m_MutationWriters;
500#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
501 void observeOccurrenceCaptureForTest(uint8_t irq, OccurrenceCaptureStage stage,
502 size_t occurrenceEpoch);
503 HandlerPinHook m_HandlerPinHook;
504 HandlerPrePinHook m_HandlerPrePinHook;
505 HandlerHazardHook m_HandlerHazardHook;
506 DispatchAbandonHook m_DispatchAbandonHook;
507 OccurrenceCaptureHook m_OccurrenceCaptureHook;