Home | History | Annotate | Download | only in common
      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 
     36 Event::Event (void)
     37 	: m_result		(RESULT_NOT_READY)
     38 	, m_waiterCount	(0)
     39 	, m_waiters		(0, 0)
     40 {
     41 }
     42 
     43 Event::~Event (void)
     44 {
     45 }
     46 
     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 
     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 
     77 Object::Object (const char* type, SharedPtr<Event> e)
     78 	: m_type	(type)
     79 	, m_modify	(e)
     80 {
     81 }
     82 
     83 Object::~Object	(void)
     84 {
     85 }
     86 
     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 
     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 
    112 Operation::Operation (const char* name)
    113 	: m_name	(name)
    114 	, m_event	(new Event)
    115 {
    116 }
    117 
    118 Operation::~Operation (void)
    119 {
    120 }
    121 
    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 
    160 void MessageBuilder::operator<< (const EndToken&)
    161 {
    162 	m_thread.pushMessage(m_stream.str());
    163 }
    164 
    165 Thread::Thread (int seed)
    166 	: m_random	(seed)
    167 	, m_status	(THREADSTATUS_NOT_STARTED)
    168 {
    169 }
    170 
    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 
    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 
    189 void Thread::addOperation (Operation* operation)
    190 {
    191 	m_operations.push_back(operation);
    192 }
    193 
    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 
    237 void Thread::exec (void)
    238 {
    239 	start();
    240 }
    241 
    242 void Thread::pushMessage (const std::string& str)
    243 {
    244 	m_messages.push_back(Message(deGetMicroseconds(), str.c_str()));
    245 }
    246 
    247 DataBlock::DataBlock (SharedPtr<Event> event)
    248 	: Object("DataBlock", event)
    249 {
    250 }
    251 
    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 
    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 
    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