1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker * drawElements Quality Program Tester Core
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 Thread test utilities
22*35238bceSAndroid Build Coastguard Worker *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker
24*35238bceSAndroid Build Coastguard Worker #include "tcuThreadUtil.hpp"
25*35238bceSAndroid Build Coastguard Worker
26*35238bceSAndroid Build Coastguard Worker #include "deClock.h"
27*35238bceSAndroid Build Coastguard Worker #include "deMemory.h"
28*35238bceSAndroid Build Coastguard Worker
29*35238bceSAndroid Build Coastguard Worker using de::SharedPtr;
30*35238bceSAndroid Build Coastguard Worker using std::vector;
31*35238bceSAndroid Build Coastguard Worker
32*35238bceSAndroid Build Coastguard Worker namespace tcu
33*35238bceSAndroid Build Coastguard Worker {
34*35238bceSAndroid Build Coastguard Worker namespace ThreadUtil
35*35238bceSAndroid Build Coastguard Worker {
36*35238bceSAndroid Build Coastguard Worker
Event(void)37*35238bceSAndroid Build Coastguard Worker Event::Event(void) : m_result(RESULT_NOT_READY), m_waiterCount(0), m_waiters(0, 0)
38*35238bceSAndroid Build Coastguard Worker {
39*35238bceSAndroid Build Coastguard Worker }
40*35238bceSAndroid Build Coastguard Worker
~Event(void)41*35238bceSAndroid Build Coastguard Worker Event::~Event(void)
42*35238bceSAndroid Build Coastguard Worker {
43*35238bceSAndroid Build Coastguard Worker }
44*35238bceSAndroid Build Coastguard Worker
setResult(Result result)45*35238bceSAndroid Build Coastguard Worker void Event::setResult(Result result)
46*35238bceSAndroid Build Coastguard Worker {
47*35238bceSAndroid Build Coastguard Worker m_lock.lock();
48*35238bceSAndroid Build Coastguard Worker DE_ASSERT(m_result == RESULT_NOT_READY);
49*35238bceSAndroid Build Coastguard Worker m_result = result;
50*35238bceSAndroid Build Coastguard Worker m_lock.unlock();
51*35238bceSAndroid Build Coastguard Worker
52*35238bceSAndroid Build Coastguard Worker for (int i = 0; i < m_waiterCount; i++)
53*35238bceSAndroid Build Coastguard Worker m_waiters.increment();
54*35238bceSAndroid Build Coastguard Worker }
55*35238bceSAndroid Build Coastguard Worker
waitReady(void)56*35238bceSAndroid Build Coastguard Worker Event::Result Event::waitReady(void)
57*35238bceSAndroid Build Coastguard Worker {
58*35238bceSAndroid Build Coastguard Worker m_lock.lock();
59*35238bceSAndroid Build Coastguard Worker
60*35238bceSAndroid Build Coastguard Worker if (m_result == RESULT_NOT_READY)
61*35238bceSAndroid Build Coastguard Worker m_waiterCount = m_waiterCount + 1;
62*35238bceSAndroid Build Coastguard Worker else
63*35238bceSAndroid Build Coastguard Worker {
64*35238bceSAndroid Build Coastguard Worker m_lock.unlock();
65*35238bceSAndroid Build Coastguard Worker return m_result;
66*35238bceSAndroid Build Coastguard Worker }
67*35238bceSAndroid Build Coastguard Worker
68*35238bceSAndroid Build Coastguard Worker m_lock.unlock();
69*35238bceSAndroid Build Coastguard Worker
70*35238bceSAndroid Build Coastguard Worker m_waiters.decrement();
71*35238bceSAndroid Build Coastguard Worker
72*35238bceSAndroid Build Coastguard Worker return m_result;
73*35238bceSAndroid Build Coastguard Worker }
74*35238bceSAndroid Build Coastguard Worker
Object(const char * type,SharedPtr<Event> e)75*35238bceSAndroid Build Coastguard Worker Object::Object(const char *type, SharedPtr<Event> e) : m_type(type), m_modify(e)
76*35238bceSAndroid Build Coastguard Worker {
77*35238bceSAndroid Build Coastguard Worker }
78*35238bceSAndroid Build Coastguard Worker
~Object(void)79*35238bceSAndroid Build Coastguard Worker Object::~Object(void)
80*35238bceSAndroid Build Coastguard Worker {
81*35238bceSAndroid Build Coastguard Worker }
82*35238bceSAndroid Build Coastguard Worker
read(SharedPtr<Event> event,std::vector<SharedPtr<Event>> & deps)83*35238bceSAndroid Build Coastguard Worker void Object::read(SharedPtr<Event> event, std::vector<SharedPtr<Event>> &deps)
84*35238bceSAndroid Build Coastguard Worker {
85*35238bceSAndroid Build Coastguard Worker // Make call depend on last modifying call
86*35238bceSAndroid Build Coastguard Worker deps.push_back(m_modify);
87*35238bceSAndroid Build Coastguard Worker
88*35238bceSAndroid Build Coastguard Worker // Add read dependency
89*35238bceSAndroid Build Coastguard Worker m_reads.push_back(event);
90*35238bceSAndroid Build Coastguard Worker }
91*35238bceSAndroid Build Coastguard Worker
modify(SharedPtr<Event> event,std::vector<SharedPtr<Event>> & deps)92*35238bceSAndroid Build Coastguard Worker void Object::modify(SharedPtr<Event> event, std::vector<SharedPtr<Event>> &deps)
93*35238bceSAndroid Build Coastguard Worker {
94*35238bceSAndroid Build Coastguard Worker // Make call depend on all reads
95*35238bceSAndroid Build Coastguard Worker for (int readNdx = 0; readNdx < (int)m_reads.size(); readNdx++)
96*35238bceSAndroid Build Coastguard Worker {
97*35238bceSAndroid Build Coastguard Worker deps.push_back(m_reads[readNdx]);
98*35238bceSAndroid Build Coastguard Worker }
99*35238bceSAndroid Build Coastguard Worker deps.push_back(m_modify);
100*35238bceSAndroid Build Coastguard Worker
101*35238bceSAndroid Build Coastguard Worker // Update last modifying call
102*35238bceSAndroid Build Coastguard Worker m_modify = event;
103*35238bceSAndroid Build Coastguard Worker
104*35238bceSAndroid Build Coastguard Worker // Clear read dependencies of last "version" of this object
105*35238bceSAndroid Build Coastguard Worker m_reads.clear();
106*35238bceSAndroid Build Coastguard Worker }
107*35238bceSAndroid Build Coastguard Worker
Operation(const char * name)108*35238bceSAndroid Build Coastguard Worker Operation::Operation(const char *name) : m_name(name), m_event(new Event)
109*35238bceSAndroid Build Coastguard Worker {
110*35238bceSAndroid Build Coastguard Worker }
111*35238bceSAndroid Build Coastguard Worker
~Operation(void)112*35238bceSAndroid Build Coastguard Worker Operation::~Operation(void)
113*35238bceSAndroid Build Coastguard Worker {
114*35238bceSAndroid Build Coastguard Worker }
115*35238bceSAndroid Build Coastguard Worker
execute(Thread & thread)116*35238bceSAndroid Build Coastguard Worker void Operation::execute(Thread &thread)
117*35238bceSAndroid Build Coastguard Worker {
118*35238bceSAndroid Build Coastguard Worker bool success = true;
119*35238bceSAndroid Build Coastguard Worker
120*35238bceSAndroid Build Coastguard Worker // Wait for dependencies and check that they succeeded
121*35238bceSAndroid Build Coastguard Worker for (int depNdx = 0; depNdx < (int)m_deps.size(); depNdx++)
122*35238bceSAndroid Build Coastguard Worker {
123*35238bceSAndroid Build Coastguard Worker if (m_deps[depNdx]->waitReady() != Event::RESULT_OK)
124*35238bceSAndroid Build Coastguard Worker success = false;
125*35238bceSAndroid Build Coastguard Worker }
126*35238bceSAndroid Build Coastguard Worker
127*35238bceSAndroid Build Coastguard Worker // Try execute operation
128*35238bceSAndroid Build Coastguard Worker if (success)
129*35238bceSAndroid Build Coastguard Worker {
130*35238bceSAndroid Build Coastguard Worker try
131*35238bceSAndroid Build Coastguard Worker {
132*35238bceSAndroid Build Coastguard Worker exec(thread);
133*35238bceSAndroid Build Coastguard Worker }
134*35238bceSAndroid Build Coastguard Worker catch (...)
135*35238bceSAndroid Build Coastguard Worker {
136*35238bceSAndroid Build Coastguard Worker // Got exception event failed
137*35238bceSAndroid Build Coastguard Worker m_event->setResult(Event::RESULT_FAILED);
138*35238bceSAndroid Build Coastguard Worker throw;
139*35238bceSAndroid Build Coastguard Worker }
140*35238bceSAndroid Build Coastguard Worker
141*35238bceSAndroid Build Coastguard Worker m_event->setResult(Event::RESULT_OK);
142*35238bceSAndroid Build Coastguard Worker }
143*35238bceSAndroid Build Coastguard Worker else
144*35238bceSAndroid Build Coastguard Worker // Some dependencies failed
145*35238bceSAndroid Build Coastguard Worker m_event->setResult(Event::RESULT_FAILED);
146*35238bceSAndroid Build Coastguard Worker
147*35238bceSAndroid Build Coastguard Worker // Release resources
148*35238bceSAndroid Build Coastguard Worker m_deps.clear();
149*35238bceSAndroid Build Coastguard Worker m_event = SharedPtr<Event>();
150*35238bceSAndroid Build Coastguard Worker }
151*35238bceSAndroid Build Coastguard Worker
152*35238bceSAndroid Build Coastguard Worker const MessageBuilder::EndToken Message::End = MessageBuilder::EndToken();
153*35238bceSAndroid Build Coastguard Worker
operator <<(const EndToken &)154*35238bceSAndroid Build Coastguard Worker void MessageBuilder::operator<<(const EndToken &)
155*35238bceSAndroid Build Coastguard Worker {
156*35238bceSAndroid Build Coastguard Worker m_thread.pushMessage(m_stream.str());
157*35238bceSAndroid Build Coastguard Worker }
158*35238bceSAndroid Build Coastguard Worker
Thread(uint32_t seed)159*35238bceSAndroid Build Coastguard Worker Thread::Thread(uint32_t seed) : m_random(seed), m_status(THREADSTATUS_NOT_STARTED)
160*35238bceSAndroid Build Coastguard Worker {
161*35238bceSAndroid Build Coastguard Worker }
162*35238bceSAndroid Build Coastguard Worker
~Thread(void)163*35238bceSAndroid Build Coastguard Worker Thread::~Thread(void)
164*35238bceSAndroid Build Coastguard Worker {
165*35238bceSAndroid Build Coastguard Worker for (int operationNdx = 0; operationNdx < (int)m_operations.size(); operationNdx++)
166*35238bceSAndroid Build Coastguard Worker delete m_operations[operationNdx];
167*35238bceSAndroid Build Coastguard Worker
168*35238bceSAndroid Build Coastguard Worker m_operations.clear();
169*35238bceSAndroid Build Coastguard Worker }
170*35238bceSAndroid Build Coastguard Worker
getUnusedData(size_t size)171*35238bceSAndroid Build Coastguard Worker uint8_t *Thread::getUnusedData(size_t size)
172*35238bceSAndroid Build Coastguard Worker {
173*35238bceSAndroid Build Coastguard Worker if (m_unusedData.size() < size)
174*35238bceSAndroid Build Coastguard Worker {
175*35238bceSAndroid Build Coastguard Worker m_unusedData.resize(size);
176*35238bceSAndroid Build Coastguard Worker }
177*35238bceSAndroid Build Coastguard Worker
178*35238bceSAndroid Build Coastguard Worker return &(m_unusedData[0]);
179*35238bceSAndroid Build Coastguard Worker }
180*35238bceSAndroid Build Coastguard Worker
addOperation(Operation * operation)181*35238bceSAndroid Build Coastguard Worker void Thread::addOperation(Operation *operation)
182*35238bceSAndroid Build Coastguard Worker {
183*35238bceSAndroid Build Coastguard Worker m_operations.push_back(operation);
184*35238bceSAndroid Build Coastguard Worker }
185*35238bceSAndroid Build Coastguard Worker
run(void)186*35238bceSAndroid Build Coastguard Worker void Thread::run(void)
187*35238bceSAndroid Build Coastguard Worker {
188*35238bceSAndroid Build Coastguard Worker setStatus(THREADSTATUS_RUNNING);
189*35238bceSAndroid Build Coastguard Worker bool initOk = false;
190*35238bceSAndroid Build Coastguard Worker
191*35238bceSAndroid Build Coastguard Worker // Reserve at least two messages for each operation
192*35238bceSAndroid Build Coastguard Worker m_messages.reserve(m_operations.size() * 2);
193*35238bceSAndroid Build Coastguard Worker try
194*35238bceSAndroid Build Coastguard Worker {
195*35238bceSAndroid Build Coastguard Worker init();
196*35238bceSAndroid Build Coastguard Worker initOk = true;
197*35238bceSAndroid Build Coastguard Worker for (int operationNdx = 0; operationNdx < (int)m_operations.size(); operationNdx++)
198*35238bceSAndroid Build Coastguard Worker m_operations[operationNdx]->execute(*this);
199*35238bceSAndroid Build Coastguard Worker
200*35238bceSAndroid Build Coastguard Worker deinit();
201*35238bceSAndroid Build Coastguard Worker setStatus(THREADSTATUS_READY);
202*35238bceSAndroid Build Coastguard Worker }
203*35238bceSAndroid Build Coastguard Worker catch (const tcu::NotSupportedError &e)
204*35238bceSAndroid Build Coastguard Worker {
205*35238bceSAndroid Build Coastguard Worker newMessage() << "tcu::NotSupportedError '" << e.what() << "'" << Message::End;
206*35238bceSAndroid Build Coastguard Worker deinit();
207*35238bceSAndroid Build Coastguard Worker setStatus(initOk ? THREADSTATUS_NOT_SUPPORTED : THREADSTATUS_INIT_FAILED);
208*35238bceSAndroid Build Coastguard Worker }
209*35238bceSAndroid Build Coastguard Worker catch (const tcu::Exception &e)
210*35238bceSAndroid Build Coastguard Worker {
211*35238bceSAndroid Build Coastguard Worker newMessage() << "tcu::Exception '" << e.what() << "'" << Message::End;
212*35238bceSAndroid Build Coastguard Worker deinit();
213*35238bceSAndroid Build Coastguard Worker setStatus(initOk ? THREADSTATUS_FAILED : THREADSTATUS_INIT_FAILED);
214*35238bceSAndroid Build Coastguard Worker }
215*35238bceSAndroid Build Coastguard Worker catch (const std::exception &error)
216*35238bceSAndroid Build Coastguard Worker {
217*35238bceSAndroid Build Coastguard Worker newMessage() << "std::exception '" << error.what() << "'" << Message::End;
218*35238bceSAndroid Build Coastguard Worker deinit();
219*35238bceSAndroid Build Coastguard Worker setStatus(initOk ? THREADSTATUS_FAILED : THREADSTATUS_INIT_FAILED);
220*35238bceSAndroid Build Coastguard Worker }
221*35238bceSAndroid Build Coastguard Worker catch (...)
222*35238bceSAndroid Build Coastguard Worker {
223*35238bceSAndroid Build Coastguard Worker newMessage() << "Unkown exception" << Message::End;
224*35238bceSAndroid Build Coastguard Worker deinit();
225*35238bceSAndroid Build Coastguard Worker setStatus(initOk ? THREADSTATUS_FAILED : THREADSTATUS_INIT_FAILED);
226*35238bceSAndroid Build Coastguard Worker }
227*35238bceSAndroid Build Coastguard Worker }
228*35238bceSAndroid Build Coastguard Worker
exec(void)229*35238bceSAndroid Build Coastguard Worker void Thread::exec(void)
230*35238bceSAndroid Build Coastguard Worker {
231*35238bceSAndroid Build Coastguard Worker start();
232*35238bceSAndroid Build Coastguard Worker }
233*35238bceSAndroid Build Coastguard Worker
pushMessage(const std::string & str)234*35238bceSAndroid Build Coastguard Worker void Thread::pushMessage(const std::string &str)
235*35238bceSAndroid Build Coastguard Worker {
236*35238bceSAndroid Build Coastguard Worker de::ScopedLock lock(m_messageLock);
237*35238bceSAndroid Build Coastguard Worker m_messages.push_back(Message(deGetMicroseconds(), str.c_str()));
238*35238bceSAndroid Build Coastguard Worker }
239*35238bceSAndroid Build Coastguard Worker
getMessageCount(void) const240*35238bceSAndroid Build Coastguard Worker int Thread::getMessageCount(void) const
241*35238bceSAndroid Build Coastguard Worker {
242*35238bceSAndroid Build Coastguard Worker de::ScopedLock lock(m_messageLock);
243*35238bceSAndroid Build Coastguard Worker return (int)(m_messages.size());
244*35238bceSAndroid Build Coastguard Worker }
245*35238bceSAndroid Build Coastguard Worker
getMessage(int index) const246*35238bceSAndroid Build Coastguard Worker Message Thread::getMessage(int index) const
247*35238bceSAndroid Build Coastguard Worker {
248*35238bceSAndroid Build Coastguard Worker de::ScopedLock lock(m_messageLock);
249*35238bceSAndroid Build Coastguard Worker return m_messages[index];
250*35238bceSAndroid Build Coastguard Worker }
251*35238bceSAndroid Build Coastguard Worker
DataBlock(SharedPtr<Event> event)252*35238bceSAndroid Build Coastguard Worker DataBlock::DataBlock(SharedPtr<Event> event) : Object("DataBlock", event)
253*35238bceSAndroid Build Coastguard Worker {
254*35238bceSAndroid Build Coastguard Worker }
255*35238bceSAndroid Build Coastguard Worker
setData(size_t size,const void * data)256*35238bceSAndroid Build Coastguard Worker void DataBlock::setData(size_t size, const void *data)
257*35238bceSAndroid Build Coastguard Worker {
258*35238bceSAndroid Build Coastguard Worker m_data = std::vector<uint8_t>(size);
259*35238bceSAndroid Build Coastguard Worker deMemcpy(&(m_data[0]), data, size);
260*35238bceSAndroid Build Coastguard Worker }
261*35238bceSAndroid Build Coastguard Worker
CompareData(SharedPtr<DataBlock> a,SharedPtr<DataBlock> b)262*35238bceSAndroid Build Coastguard Worker CompareData::CompareData(SharedPtr<DataBlock> a, SharedPtr<DataBlock> b) : Operation("CompareData"), m_a(a), m_b(b)
263*35238bceSAndroid Build Coastguard Worker {
264*35238bceSAndroid Build Coastguard Worker readObject(SharedPtr<Object>(a));
265*35238bceSAndroid Build Coastguard Worker readObject(SharedPtr<Object>(b));
266*35238bceSAndroid Build Coastguard Worker }
267*35238bceSAndroid Build Coastguard Worker
exec(Thread & thread)268*35238bceSAndroid Build Coastguard Worker void CompareData::exec(Thread &thread)
269*35238bceSAndroid Build Coastguard Worker {
270*35238bceSAndroid Build Coastguard Worker bool result = true;
271*35238bceSAndroid Build Coastguard Worker DE_ASSERT(m_a->getSize() == m_b->getSize());
272*35238bceSAndroid Build Coastguard Worker
273*35238bceSAndroid Build Coastguard Worker thread.newMessage() << "Begin -- CompareData" << Message::End;
274*35238bceSAndroid Build Coastguard Worker
275*35238bceSAndroid Build Coastguard Worker for (int byteNdx = 0; byteNdx < (int)m_a->getSize(); byteNdx++)
276*35238bceSAndroid Build Coastguard Worker {
277*35238bceSAndroid Build Coastguard Worker if (m_a->getData()[byteNdx] != m_b->getData()[byteNdx])
278*35238bceSAndroid Build Coastguard Worker {
279*35238bceSAndroid Build Coastguard Worker result = false;
280*35238bceSAndroid Build Coastguard Worker thread.newMessage() << "CompareData failed at offset :" << byteNdx << Message::End;
281*35238bceSAndroid Build Coastguard Worker break;
282*35238bceSAndroid Build Coastguard Worker }
283*35238bceSAndroid Build Coastguard Worker }
284*35238bceSAndroid Build Coastguard Worker
285*35238bceSAndroid Build Coastguard Worker if (result)
286*35238bceSAndroid Build Coastguard Worker thread.newMessage() << "CompareData passed" << Message::End;
287*35238bceSAndroid Build Coastguard Worker else
288*35238bceSAndroid Build Coastguard Worker TCU_FAIL("Data comparision failed");
289*35238bceSAndroid Build Coastguard Worker
290*35238bceSAndroid Build Coastguard Worker thread.newMessage() << "End -- CompareData" << Message::End;
291*35238bceSAndroid Build Coastguard Worker }
292*35238bceSAndroid Build Coastguard Worker
293*35238bceSAndroid Build Coastguard Worker } // namespace ThreadUtil
294*35238bceSAndroid Build Coastguard Worker } // namespace tcu
295