xref: /aosp_15_r20/external/deqp/executor/xeCallQueue.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program Test Executor
3*35238bceSAndroid Build Coastguard Worker  * ------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief Cross-thread function call dispatcher.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "xeCallQueue.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "deInt32.h"
26*35238bceSAndroid Build Coastguard Worker #include "deMemory.h"
27*35238bceSAndroid Build Coastguard Worker 
28*35238bceSAndroid Build Coastguard Worker using std::vector;
29*35238bceSAndroid Build Coastguard Worker 
getNextQueueSize(int curSize,int minNewSize)30*35238bceSAndroid Build Coastguard Worker static inline int getNextQueueSize(int curSize, int minNewSize)
31*35238bceSAndroid Build Coastguard Worker {
32*35238bceSAndroid Build Coastguard Worker     return de::max(curSize * 2, 1 << deLog2Ceil32(minNewSize));
33*35238bceSAndroid Build Coastguard Worker }
34*35238bceSAndroid Build Coastguard Worker 
35*35238bceSAndroid Build Coastguard Worker namespace xe
36*35238bceSAndroid Build Coastguard Worker {
37*35238bceSAndroid Build Coastguard Worker 
38*35238bceSAndroid Build Coastguard Worker // CallQueue
39*35238bceSAndroid Build Coastguard Worker 
CallQueue(void)40*35238bceSAndroid Build Coastguard Worker CallQueue::CallQueue(void) : m_canceled(false), m_callSem(0), m_callQueue(64)
41*35238bceSAndroid Build Coastguard Worker {
42*35238bceSAndroid Build Coastguard Worker }
43*35238bceSAndroid Build Coastguard Worker 
~CallQueue(void)44*35238bceSAndroid Build Coastguard Worker CallQueue::~CallQueue(void)
45*35238bceSAndroid Build Coastguard Worker {
46*35238bceSAndroid Build Coastguard Worker     // Destroy all calls.
47*35238bceSAndroid Build Coastguard Worker     for (vector<Call *>::iterator i = m_calls.begin(); i != m_calls.end(); i++)
48*35238bceSAndroid Build Coastguard Worker         delete *i;
49*35238bceSAndroid Build Coastguard Worker }
50*35238bceSAndroid Build Coastguard Worker 
cancel(void)51*35238bceSAndroid Build Coastguard Worker void CallQueue::cancel(void)
52*35238bceSAndroid Build Coastguard Worker {
53*35238bceSAndroid Build Coastguard Worker     m_canceled = true;
54*35238bceSAndroid Build Coastguard Worker     m_callSem.increment();
55*35238bceSAndroid Build Coastguard Worker }
56*35238bceSAndroid Build Coastguard Worker 
callNext(void)57*35238bceSAndroid Build Coastguard Worker void CallQueue::callNext(void)
58*35238bceSAndroid Build Coastguard Worker {
59*35238bceSAndroid Build Coastguard Worker     Call *call = DE_NULL;
60*35238bceSAndroid Build Coastguard Worker 
61*35238bceSAndroid Build Coastguard Worker     // Wait for a call.
62*35238bceSAndroid Build Coastguard Worker     m_callSem.decrement();
63*35238bceSAndroid Build Coastguard Worker 
64*35238bceSAndroid Build Coastguard Worker     if (m_canceled)
65*35238bceSAndroid Build Coastguard Worker         return;
66*35238bceSAndroid Build Coastguard Worker 
67*35238bceSAndroid Build Coastguard Worker     // Acquire call from buffer.
68*35238bceSAndroid Build Coastguard Worker     {
69*35238bceSAndroid Build Coastguard Worker         de::ScopedLock lock(m_lock);
70*35238bceSAndroid Build Coastguard Worker         call = m_callQueue.popBack();
71*35238bceSAndroid Build Coastguard Worker     }
72*35238bceSAndroid Build Coastguard Worker 
73*35238bceSAndroid Build Coastguard Worker     try
74*35238bceSAndroid Build Coastguard Worker     {
75*35238bceSAndroid Build Coastguard Worker         // \note Enqueue lock is not held during call so it is possible to enqueue more work from dispatched call.
76*35238bceSAndroid Build Coastguard Worker         CallReader reader(call);
77*35238bceSAndroid Build Coastguard Worker 
78*35238bceSAndroid Build Coastguard Worker         call->getFunction()(reader);
79*35238bceSAndroid Build Coastguard Worker 
80*35238bceSAndroid Build Coastguard Worker         // check callee consumed all
81*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(reader.isDataConsumed());
82*35238bceSAndroid Build Coastguard Worker         call->clear();
83*35238bceSAndroid Build Coastguard Worker     }
84*35238bceSAndroid Build Coastguard Worker     catch (const std::exception &)
85*35238bceSAndroid Build Coastguard Worker     {
86*35238bceSAndroid Build Coastguard Worker         try
87*35238bceSAndroid Build Coastguard Worker         {
88*35238bceSAndroid Build Coastguard Worker             // Try to push call into free calls list.
89*35238bceSAndroid Build Coastguard Worker             de::ScopedLock lock(m_lock);
90*35238bceSAndroid Build Coastguard Worker             m_freeCalls.push_back(call);
91*35238bceSAndroid Build Coastguard Worker         }
92*35238bceSAndroid Build Coastguard Worker         catch (const std::exception &)
93*35238bceSAndroid Build Coastguard Worker         {
94*35238bceSAndroid Build Coastguard Worker             // We can't do anything but ignore this.
95*35238bceSAndroid Build Coastguard Worker         }
96*35238bceSAndroid Build Coastguard Worker 
97*35238bceSAndroid Build Coastguard Worker         throw;
98*35238bceSAndroid Build Coastguard Worker     }
99*35238bceSAndroid Build Coastguard Worker 
100*35238bceSAndroid Build Coastguard Worker     // Push back to free calls list.
101*35238bceSAndroid Build Coastguard Worker     {
102*35238bceSAndroid Build Coastguard Worker         de::ScopedLock lock(m_lock);
103*35238bceSAndroid Build Coastguard Worker         m_freeCalls.push_back(call);
104*35238bceSAndroid Build Coastguard Worker     }
105*35238bceSAndroid Build Coastguard Worker }
106*35238bceSAndroid Build Coastguard Worker 
getEmptyCall(void)107*35238bceSAndroid Build Coastguard Worker Call *CallQueue::getEmptyCall(void)
108*35238bceSAndroid Build Coastguard Worker {
109*35238bceSAndroid Build Coastguard Worker     de::ScopedLock lock(m_lock);
110*35238bceSAndroid Build Coastguard Worker     Call *call = DE_NULL;
111*35238bceSAndroid Build Coastguard Worker 
112*35238bceSAndroid Build Coastguard Worker     // Try to get from free calls list.
113*35238bceSAndroid Build Coastguard Worker     if (!m_freeCalls.empty())
114*35238bceSAndroid Build Coastguard Worker     {
115*35238bceSAndroid Build Coastguard Worker         call = m_freeCalls.back();
116*35238bceSAndroid Build Coastguard Worker         m_freeCalls.pop_back();
117*35238bceSAndroid Build Coastguard Worker     }
118*35238bceSAndroid Build Coastguard Worker 
119*35238bceSAndroid Build Coastguard Worker     // If no free calls were available, create a new.
120*35238bceSAndroid Build Coastguard Worker     if (!call)
121*35238bceSAndroid Build Coastguard Worker     {
122*35238bceSAndroid Build Coastguard Worker         m_calls.reserve(m_calls.size() + 1);
123*35238bceSAndroid Build Coastguard Worker         call = new Call();
124*35238bceSAndroid Build Coastguard Worker         m_calls.push_back(call);
125*35238bceSAndroid Build Coastguard Worker     }
126*35238bceSAndroid Build Coastguard Worker 
127*35238bceSAndroid Build Coastguard Worker     return call;
128*35238bceSAndroid Build Coastguard Worker }
129*35238bceSAndroid Build Coastguard Worker 
enqueue(Call * call)130*35238bceSAndroid Build Coastguard Worker void CallQueue::enqueue(Call *call)
131*35238bceSAndroid Build Coastguard Worker {
132*35238bceSAndroid Build Coastguard Worker     de::ScopedLock lock(m_lock);
133*35238bceSAndroid Build Coastguard Worker 
134*35238bceSAndroid Build Coastguard Worker     if (m_callQueue.getNumFree() == 0)
135*35238bceSAndroid Build Coastguard Worker     {
136*35238bceSAndroid Build Coastguard Worker         // Call queue must be grown.
137*35238bceSAndroid Build Coastguard Worker         m_callQueue.resize(getNextQueueSize(m_callQueue.getSize(), m_callQueue.getSize() + 1));
138*35238bceSAndroid Build Coastguard Worker     }
139*35238bceSAndroid Build Coastguard Worker 
140*35238bceSAndroid Build Coastguard Worker     m_callQueue.pushFront(call);
141*35238bceSAndroid Build Coastguard Worker     m_callSem.increment();
142*35238bceSAndroid Build Coastguard Worker }
143*35238bceSAndroid Build Coastguard Worker 
freeCall(Call * call)144*35238bceSAndroid Build Coastguard Worker void CallQueue::freeCall(Call *call)
145*35238bceSAndroid Build Coastguard Worker {
146*35238bceSAndroid Build Coastguard Worker     de::ScopedLock lock(m_lock);
147*35238bceSAndroid Build Coastguard Worker     m_freeCalls.push_back(call);
148*35238bceSAndroid Build Coastguard Worker }
149*35238bceSAndroid Build Coastguard Worker 
150*35238bceSAndroid Build Coastguard Worker // Call
151*35238bceSAndroid Build Coastguard Worker 
Call(void)152*35238bceSAndroid Build Coastguard Worker Call::Call(void) : m_func(DE_NULL)
153*35238bceSAndroid Build Coastguard Worker {
154*35238bceSAndroid Build Coastguard Worker }
155*35238bceSAndroid Build Coastguard Worker 
~Call(void)156*35238bceSAndroid Build Coastguard Worker Call::~Call(void)
157*35238bceSAndroid Build Coastguard Worker {
158*35238bceSAndroid Build Coastguard Worker }
159*35238bceSAndroid Build Coastguard Worker 
clear(void)160*35238bceSAndroid Build Coastguard Worker void Call::clear(void)
161*35238bceSAndroid Build Coastguard Worker {
162*35238bceSAndroid Build Coastguard Worker     m_func = DE_NULL;
163*35238bceSAndroid Build Coastguard Worker     m_data.clear();
164*35238bceSAndroid Build Coastguard Worker }
165*35238bceSAndroid Build Coastguard Worker 
166*35238bceSAndroid Build Coastguard Worker // CallReader
167*35238bceSAndroid Build Coastguard Worker 
CallReader(Call * call)168*35238bceSAndroid Build Coastguard Worker CallReader::CallReader(Call *call) : m_call(call), m_curPos(0)
169*35238bceSAndroid Build Coastguard Worker {
170*35238bceSAndroid Build Coastguard Worker }
171*35238bceSAndroid Build Coastguard Worker 
read(uint8_t * bytes,size_t numBytes)172*35238bceSAndroid Build Coastguard Worker void CallReader::read(uint8_t *bytes, size_t numBytes)
173*35238bceSAndroid Build Coastguard Worker {
174*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(m_curPos + numBytes <= m_call->getDataSize());
175*35238bceSAndroid Build Coastguard Worker     deMemcpy(bytes, m_call->getData() + m_curPos, numBytes);
176*35238bceSAndroid Build Coastguard Worker     m_curPos += numBytes;
177*35238bceSAndroid Build Coastguard Worker }
178*35238bceSAndroid Build Coastguard Worker 
getDataBlock(size_t numBytes)179*35238bceSAndroid Build Coastguard Worker const uint8_t *CallReader::getDataBlock(size_t numBytes)
180*35238bceSAndroid Build Coastguard Worker {
181*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(m_curPos + numBytes <= m_call->getDataSize());
182*35238bceSAndroid Build Coastguard Worker 
183*35238bceSAndroid Build Coastguard Worker     const uint8_t *ptr = m_call->getData() + m_curPos;
184*35238bceSAndroid Build Coastguard Worker     m_curPos += numBytes;
185*35238bceSAndroid Build Coastguard Worker 
186*35238bceSAndroid Build Coastguard Worker     return ptr;
187*35238bceSAndroid Build Coastguard Worker }
188*35238bceSAndroid Build Coastguard Worker 
isDataConsumed(void) const189*35238bceSAndroid Build Coastguard Worker bool CallReader::isDataConsumed(void) const
190*35238bceSAndroid Build Coastguard Worker {
191*35238bceSAndroid Build Coastguard Worker     return m_curPos == m_call->getDataSize();
192*35238bceSAndroid Build Coastguard Worker }
193*35238bceSAndroid Build Coastguard Worker 
operator >>(CallReader & reader,std::string & value)194*35238bceSAndroid Build Coastguard Worker CallReader &operator>>(CallReader &reader, std::string &value)
195*35238bceSAndroid Build Coastguard Worker {
196*35238bceSAndroid Build Coastguard Worker     value.clear();
197*35238bceSAndroid Build Coastguard Worker     for (;;)
198*35238bceSAndroid Build Coastguard Worker     {
199*35238bceSAndroid Build Coastguard Worker         char c;
200*35238bceSAndroid Build Coastguard Worker         reader.read((uint8_t *)&c, sizeof(char));
201*35238bceSAndroid Build Coastguard Worker         if (c != 0)
202*35238bceSAndroid Build Coastguard Worker             value.push_back(c);
203*35238bceSAndroid Build Coastguard Worker         else
204*35238bceSAndroid Build Coastguard Worker             break;
205*35238bceSAndroid Build Coastguard Worker     }
206*35238bceSAndroid Build Coastguard Worker 
207*35238bceSAndroid Build Coastguard Worker     return reader;
208*35238bceSAndroid Build Coastguard Worker }
209*35238bceSAndroid Build Coastguard Worker 
210*35238bceSAndroid Build Coastguard Worker // CallWriter
211*35238bceSAndroid Build Coastguard Worker 
CallWriter(CallQueue * queue,Call::Function function)212*35238bceSAndroid Build Coastguard Worker CallWriter::CallWriter(CallQueue *queue, Call::Function function)
213*35238bceSAndroid Build Coastguard Worker     : m_queue(queue)
214*35238bceSAndroid Build Coastguard Worker     , m_call(queue->getEmptyCall())
215*35238bceSAndroid Build Coastguard Worker     , m_enqueued(false)
216*35238bceSAndroid Build Coastguard Worker {
217*35238bceSAndroid Build Coastguard Worker     m_call->setFunction(function);
218*35238bceSAndroid Build Coastguard Worker }
219*35238bceSAndroid Build Coastguard Worker 
~CallWriter(void)220*35238bceSAndroid Build Coastguard Worker CallWriter::~CallWriter(void)
221*35238bceSAndroid Build Coastguard Worker {
222*35238bceSAndroid Build Coastguard Worker     if (!m_enqueued)
223*35238bceSAndroid Build Coastguard Worker         m_queue->freeCall(m_call);
224*35238bceSAndroid Build Coastguard Worker }
225*35238bceSAndroid Build Coastguard Worker 
write(const uint8_t * bytes,size_t numBytes)226*35238bceSAndroid Build Coastguard Worker void CallWriter::write(const uint8_t *bytes, size_t numBytes)
227*35238bceSAndroid Build Coastguard Worker {
228*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!m_enqueued);
229*35238bceSAndroid Build Coastguard Worker     size_t curPos = m_call->getDataSize();
230*35238bceSAndroid Build Coastguard Worker     m_call->setDataSize(curPos + numBytes);
231*35238bceSAndroid Build Coastguard Worker     deMemcpy(m_call->getData() + curPos, bytes, numBytes);
232*35238bceSAndroid Build Coastguard Worker }
233*35238bceSAndroid Build Coastguard Worker 
enqueue(void)234*35238bceSAndroid Build Coastguard Worker void CallWriter::enqueue(void)
235*35238bceSAndroid Build Coastguard Worker {
236*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!m_enqueued);
237*35238bceSAndroid Build Coastguard Worker     m_queue->enqueue(m_call);
238*35238bceSAndroid Build Coastguard Worker     m_enqueued = true;
239*35238bceSAndroid Build Coastguard Worker }
240*35238bceSAndroid Build Coastguard Worker 
operator <<(CallWriter & writer,const char * str)241*35238bceSAndroid Build Coastguard Worker CallWriter &operator<<(CallWriter &writer, const char *str)
242*35238bceSAndroid Build Coastguard Worker {
243*35238bceSAndroid Build Coastguard Worker     int pos = 0;
244*35238bceSAndroid Build Coastguard Worker     for (;;)
245*35238bceSAndroid Build Coastguard Worker     {
246*35238bceSAndroid Build Coastguard Worker         writer.write((const uint8_t *)str + pos, sizeof(char));
247*35238bceSAndroid Build Coastguard Worker         if (str[pos] == 0)
248*35238bceSAndroid Build Coastguard Worker             break;
249*35238bceSAndroid Build Coastguard Worker         pos += 1;
250*35238bceSAndroid Build Coastguard Worker     }
251*35238bceSAndroid Build Coastguard Worker 
252*35238bceSAndroid Build Coastguard Worker     return writer;
253*35238bceSAndroid Build Coastguard Worker }
254*35238bceSAndroid Build Coastguard Worker 
255*35238bceSAndroid Build Coastguard Worker } // namespace xe
256