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