56 enum class OverrunStatus {
63#if THREADS && HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
65 OverrunStatus sampleOverrunForTest();
67 using HostedSmokeHook = void (*)(
void*);
69 void setAfterPreallocatedAdmissionHookForTest(HostedSmokeHook hook,
void* context) {
70 m_AfterPreallocatedAdmissionHook = hook;
71 m_AfterPreallocatedAdmissionContext = context;
74 void setAfterIntakeExchangeHookForTest(HostedSmokeHook hook,
void* context) {
75 m_AfterIntakeExchangeHook = hook;
76 m_AfterIntakeExchangeContext = context;
79 size_t workerTransientRetriesForTest() {
80 return m_WorkerTransientRetries.value();
83 size_t guardedTransientRetriesForTest() {
84 return m_GuardedTransientRetries.value();
87 size_t publisherDrainRetriesForTest() {
88 return m_PublisherDrainRetries.value();
92#if THREADS && PEDIGREE_CONCURRENCY_SMOKE_TESTS
93 using ConcurrencySmokeHook = void (*)(
void*);
95 void setAfterPreallocatedClaimHookForTest(ConcurrencySmokeHook hook,
void* context) {
96 m_AfterPreallocatedClaimHook = hook;
97 m_AfterPreallocatedClaimContext = context;
108 : m_LastQueueSize(0),
109 m_LastProgressGeneration(0),
111 m_HasBacklogBaseline(
false),
115 virtual void timer(uint64_t delta);
116 OverrunStatus sample(
size_t& lastSize,
size_t& currentSize);
117 void resetBaselineLocked();
119 size_t m_LastQueueSize;
120 size_t m_LastProgressGeneration;
122 bool m_HasBacklogBaseline;
132 explicit IntakeNode(
Request* request =
nullptr) : next(
nullptr), owner(request) {}
141 Request(
size_t requestPriority,
bool asynchronous, uint64_t requestP1, uint64_t requestP2,
142 uint64_t requestP3, uint64_t requestP4, uint64_t requestP5, uint64_t requestP6,
143 uint64_t requestP7, uint64_t requestP8,
156 m_References(asynchronous ? 1 : 2),
160 m_Priority(requestPriority),
161 m_Asynchronous(asynchronous),
164 m_pPreallocatedOwner(preallocatedOwner) {
167 uint64_t p1, p2, p3, p4, p5, p6, p7, p8;
175 uint64_t m_ReturnValue;
189 void operator=(
const Request&);
226 using ReleaseCallback = void (*)(
void*);
232 bool isAvailable()
const;
248 ReleaseCallback m_ReleaseCallback;
249 void* m_ReleaseContext;
252 enum class PreallocatedPublishResult {
269 enum ActionOnDuplicate {
278 enum class LifecycleState {
286 virtual void initialise();
296 virtual void destroy();
308 MUST_USE_RESULT uint64_t addRequest(
size_t priority, uint64_t p1 = 0, uint64_t p2 = 0,
309 uint64_t p3 = 0, uint64_t p4 = 0, uint64_t p5 = 0,
310 uint64_t p6 = 0, uint64_t p7 = 0, uint64_t p8 = 0);
314 MUST_USE_RESULT uint64_t addRequest(
size_t priority, ActionOnDuplicate action, uint64_t p1 = 0,
315 uint64_t p2 = 0, uint64_t p3 = 0, uint64_t p4 = 0,
316 uint64_t p5 = 0, uint64_t p6 = 0, uint64_t p7 = 0,
328 uint64_t addAsyncRequest(
size_t priority, uint64_t p1 = 0, uint64_t p2 = 0, uint64_t p3 = 0,
329 uint64_t p4 = 0, uint64_t p5 = 0, uint64_t p6 = 0, uint64_t p7 = 0,
339 MUST_USE_RESULT bool publishAsyncRequest(
size_t priority, uint64_t p1 = 0, uint64_t p2 = 0,
340 uint64_t p3 = 0, uint64_t p4 = 0, uint64_t p5 = 0,
341 uint64_t p6 = 0, uint64_t p7 = 0, uint64_t p8 = 0);
344 bool canWaitForCompletion();
348 MUST_USE_RESULT bool waitForPreallocated(PreallocatedRequest& request);
366 MUST_USE_RESULT PreallocatedPublishResult publishPreallocated(PreallocatedRequest& request,
367 size_t priority, uint64_t p1 = 0,
368 uint64_t p2 = 0, uint64_t p3 = 0,
369 uint64_t p4 = 0, uint64_t p5 = 0,
370 uint64_t p6 = 0, uint64_t p7 = 0,
380 MUST_USE_RESULT PreallocatedPublishResult republishPreallocatedWhileReleasing(
381 PreallocatedRequest& request,
size_t priority, uint64_t p1 = 0, uint64_t p2 = 0,
382 uint64_t p3 = 0, uint64_t p4 = 0, uint64_t p5 = 0, uint64_t p6 = 0, uint64_t p7 = 0,
399 LifecycleState getLifecycleState();
416 virtual uint64_t
executeRequest(uint64_t p1, uint64_t p2, uint64_t p3, uint64_t p4, uint64_t p5,
417 uint64_t p6, uint64_t p7, uint64_t p8) = 0;
447 static int trampoline(
void* p);
452 enum class NextRequestResult {
459 NextRequestResult getNextRequest(Request*& request);
462 bool drainIntakeLocked(
size_t priority);
465 void publishRequest(Request* request);
468 Request* findDuplicate(
const Request& request);
471 static void completeRequest(Request* request, uint64_t returnValue,
bool rejected);
474 void discardRequest(Request* request);
476 uint64_t addAsyncRequestInternal(
size_t priority, uint64_t p1, uint64_t p2, uint64_t p3,
477 uint64_t p4, uint64_t p5, uint64_t p6, uint64_t p7, uint64_t p8);
479 PreallocatedPublishResult publishPreallocatedRequest(PreallocatedRequest& request,
480 PreallocatedRequest::State availableState,
481 size_t priority, uint64_t p1, uint64_t p2,
482 uint64_t p3, uint64_t p4, uint64_t p5,
483 uint64_t p6, uint64_t p7, uint64_t p8);
486 void releasePreallocatedRequest(Request* request);
489 void invokeCancelRequest(
const Request& request);
492 bool callbackActiveOnCurrentThread()
const;
496 static void retainRequest(Request* request);
497 void releaseRequest(Request* request);
498 uint64_t waitForRequest(Request* request);
504 void closePreallocatedAdmission();
505 void waitForPreallocatedPublishers();
508 static constexpr size_t PublicationClosed =
static_cast<size_t>(1) << ((
sizeof(
size_t) * 8) - 1);
509 static constexpr size_t PublicationCountMask = ~PublicationClosed;
515 Request* m_pRequestQueue[REQUEST_QUEUE_NUM_PRIORITIES];
516 Request* m_pRequestQueueTail[REQUEST_QUEUE_NUM_PRIORITIES];
548 Timer* m_pOverrunTimer;
553#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
554 HostedSmokeHook m_AfterPreallocatedAdmissionHook;
555 void* m_AfterPreallocatedAdmissionContext;
556 HostedSmokeHook m_AfterIntakeExchangeHook;
557 void* m_AfterIntakeExchangeContext;
562#if PEDIGREE_CONCURRENCY_SMOKE_TESTS
563 ConcurrencySmokeHook m_AfterPreallocatedClaimHook;
564 void* m_AfterPreallocatedClaimContext;