20 #include "pedigree/kernel/utilities/RequestQueue.h" 21 #include "pedigree/kernel/LockGuard.h" 22 #include "pedigree/kernel/Log.h" 23 #include "pedigree/kernel/machine/Machine.h" 24 #include "pedigree/kernel/machine/Timer.h" 25 #include "pedigree/kernel/process/Scheduler.h" 26 #include "pedigree/kernel/process/Thread.h" 27 #include "pedigree/kernel/processor/Processor.h" 28 #include "pedigree/kernel/processor/ProcessorInformation.h" 29 #include "pedigree/kernel/time/Time.h" 30 #include "pedigree/kernel/utilities/assert.h" 31 #include "pedigree/kernel/utilities/new" 38 m_RequestQueueMutex(false), m_pThread(0), m_Halted(false),
40 m_nMaxAsyncRequests(256), m_nAsyncRequests(0), m_Name(name)
42 for (
size_t i = 0; i < REQUEST_QUEUE_NUM_PRIORITIES; i++)
46 m_OverrunChecker.queue =
this;
50 RequestQueue::~RequestQueue()
61 WARNING(
"RequestQueue initialised multiple times - don't do this.");
78 t->registerHandler(&m_OverrunChecker);
81 WARNING(
"RequestQueue: This build does not support threads");
93 for (
size_t i = 0; i < REQUEST_QUEUE_NUM_PRIORITIES; ++i)
103 pRequest->bReject =
true;
105 pRequest = pRequest->next;
113 t->unregisterHandler(&m_OverrunChecker);
119 size_t priority, uint64_t p1, uint64_t p2, uint64_t p3, uint64_t p4,
120 uint64_t p5, uint64_t p6, uint64_t p7, uint64_t p8)
123 priority, RequestQueue::Block, p1, p2, p3, p4, p5, p6, p7, p8);
127 size_t priority, ActionOnDuplicate action, uint64_t p1, uint64_t p2,
128 uint64_t p3, uint64_t p4, uint64_t p5, uint64_t p6, uint64_t p7,
143 pReq->bReject =
false;
146 pReq->priority = priority;
149 bool bOwnRequest =
true;
179 else if (bOwnRequest)
185 if (action == ReturnImmediately)
206 pThread->setBlockingThread(m_pThread);
227 pThread->setBlockingThread(0);
237 NOTICE(
"RequestQueue::addRequest - interrupted");
238 if (pReq->bReject && !--pReq->refcnt)
246 uintptr_t ret = pReq->ret;
249 if (bOwnRequest && pReq->pThread)
266 ++(pReq->owner->m_nAsyncRequests);
272 pReq->priority, ReturnImmediately, pReq->p1, pReq->p2, pReq->p3,
273 pReq->p4, pReq->p5, pReq->p6, pReq->p7, pReq->p8);
275 --(pReq->owner->m_nAsyncRequests);
283 size_t priority, uint64_t p1, uint64_t p2, uint64_t p3, uint64_t p4,
284 uint64_t p5, uint64_t p6, uint64_t p7, uint64_t p8)
287 return addRequest(priority, p1, p2, p3, p4, p5, p6, p7, p8);
300 pReq->bReject =
false;
303 pReq->priority = priority;
307 if (m_nAsyncRequests >= m_nMaxAsyncRequests)
310 "RequestQueue: '" << m_Name
311 <<
"' is not keeping up with demand for " 314 " -> priority=" << priority <<
", p1=" <<
Hex << p1 <<
", p2=" << p2
315 <<
", p3=" << p3 <<
", p4=" << p4);
317 " -> p5=" <<
Hex << p5 <<
", p6=" << p6 <<
", p7=" << p7
326 new Thread(pProcess, &
doAsync, reinterpret_cast<void *>(pReq));
384 for (priority = 0; priority < REQUEST_QUEUE_NUM_PRIORITIES - 1; priority++)
439 bool finished =
true;
441 pReq->p1, pReq->p2, pReq->p3, pReq->p4, pReq->p5, pReq->p6,
449 NOTICE(
"RequestQueue::work - caller interrupted");
463 WARNING(
"RequestQueue: unwind state is Exit, request not " 464 "cleaned up. Leak?");
476 pReq->bCompleted =
true;
493 uint64_t delta, InterruptState &)
496 if (delta < Time::Multiplier::Second)
501 m_Tick -= Time::Multiplier::Second;
503 queue->m_RequestQueueMutex.acquire();
504 size_t lastSize = m_LastQueueSize;
505 size_t currentSize = queue->m_nTotalRequests;
506 m_LastQueueSize = currentSize;
507 queue->m_RequestQueueMutex.release();
509 if (lastSize < currentSize)
514 <<
"' is NOT keeping up with incoming requests [1s ago we had " 515 << lastSize <<
" requests, now have " << currentSize <<
"]!");
527 for (
size_t priority = 0; priority < REQUEST_QUEUE_NUM_PRIORITIES - 1;
virtual void timer(uint64_t delta, InterruptState &state)
virtual bool compareRequests(const Request &a, const Request &b)
bool acquire(size_t n=1, size_t timeoutSecs=0, size_t timeoutUsecs=0)
uint64_t addAsyncRequest(size_t priority, uint64_t p1=0, uint64_t p2=0, uint64_t p3=0, uint64_t p4=0, uint64_t p5=0, uint64_t p6=0, uint64_t p7=0, uint64_t p8=0)
virtual Timer * getTimer()=0
bool isRequestValid(const Request *r)
static ProcessorInformation & information()
Request * getNextRequest()
Mutex m_RequestQueueMutex
virtual uint64_t executeRequest(uint64_t p1, uint64_t p2, uint64_t p3, uint64_t p4, uint64_t p5, uint64_t p6, uint64_t p7, uint64_t p8)=0
static Scheduler & instance()
static int trampoline(void *p)
void addRequest(RequestQueue::Request *req)
ConditionVariable m_RequestQueueCondition
void removeRequest(RequestQueue::Request *req)
No unwind necessary, carry on as normal.
virtual void initialise()
MUST_USE_RESULT uint64_t addRequest(size_t priority, uint64_t p1=0, uint64_t p2=0, uint64_t p3=0, uint64_t p4=0, uint64_t p5=0, uint64_t p6=0, uint64_t p7=0, uint64_t p8=0)
Request * m_pRequestQueue[REQUEST_QUEUE_NUM_PRIORITIES]
static int doAsync(void *p)
bool tryAcquire(size_t n=1)
UnwindType getUnwindState()
RequestQueue(const String &name)
WaitResult wait(Mutex &mutex, Time::Timestamp &timeout)