xref: /aosp_15_r20/external/deqp/framework/common/tcuThreadUtil.hpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker #ifndef _TCUTHREADUTIL_HPP
2*35238bceSAndroid Build Coastguard Worker #define _TCUTHREADUTIL_HPP
3*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program Tester Core
5*35238bceSAndroid Build Coastguard Worker  * ----------------------------------------
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
8*35238bceSAndroid Build Coastguard Worker  *
9*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
10*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
11*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
14*35238bceSAndroid Build Coastguard Worker  *
15*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
16*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
17*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
19*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
20*35238bceSAndroid Build Coastguard Worker  *
21*35238bceSAndroid Build Coastguard Worker  *//*!
22*35238bceSAndroid Build Coastguard Worker  * \file
23*35238bceSAndroid Build Coastguard Worker  * \brief Thread test utilities
24*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
25*35238bceSAndroid Build Coastguard Worker 
26*35238bceSAndroid Build Coastguard Worker #include "tcuDefs.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "deSharedPtr.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "deMutex.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "deSemaphore.hpp"
30*35238bceSAndroid Build Coastguard Worker #include "deThread.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "deRandom.hpp"
32*35238bceSAndroid Build Coastguard Worker 
33*35238bceSAndroid Build Coastguard Worker #include <vector>
34*35238bceSAndroid Build Coastguard Worker #include <sstream>
35*35238bceSAndroid Build Coastguard Worker 
36*35238bceSAndroid Build Coastguard Worker namespace tcu
37*35238bceSAndroid Build Coastguard Worker {
38*35238bceSAndroid Build Coastguard Worker namespace ThreadUtil
39*35238bceSAndroid Build Coastguard Worker {
40*35238bceSAndroid Build Coastguard Worker // Event object for synchronizing threads
41*35238bceSAndroid Build Coastguard Worker class Event
42*35238bceSAndroid Build Coastguard Worker {
43*35238bceSAndroid Build Coastguard Worker public:
44*35238bceSAndroid Build Coastguard Worker     enum Result
45*35238bceSAndroid Build Coastguard Worker     {
46*35238bceSAndroid Build Coastguard Worker         RESULT_NOT_READY = 0,
47*35238bceSAndroid Build Coastguard Worker         RESULT_OK,
48*35238bceSAndroid Build Coastguard Worker         RESULT_FAILED
49*35238bceSAndroid Build Coastguard Worker     };
50*35238bceSAndroid Build Coastguard Worker 
51*35238bceSAndroid Build Coastguard Worker     Event(void);
52*35238bceSAndroid Build Coastguard Worker     ~Event(void);
53*35238bceSAndroid Build Coastguard Worker     void setResult(Result result);
54*35238bceSAndroid Build Coastguard Worker     Result waitReady(void);
getResult(void) const55*35238bceSAndroid Build Coastguard Worker     Result getResult(void) const
56*35238bceSAndroid Build Coastguard Worker     {
57*35238bceSAndroid Build Coastguard Worker         return m_result;
58*35238bceSAndroid Build Coastguard Worker     }
59*35238bceSAndroid Build Coastguard Worker 
60*35238bceSAndroid Build Coastguard Worker private:
61*35238bceSAndroid Build Coastguard Worker     volatile Result m_result;
62*35238bceSAndroid Build Coastguard Worker     volatile int m_waiterCount;
63*35238bceSAndroid Build Coastguard Worker     de::Semaphore m_waiters;
64*35238bceSAndroid Build Coastguard Worker     de::Mutex m_lock;
65*35238bceSAndroid Build Coastguard Worker 
66*35238bceSAndroid Build Coastguard Worker     // Disabled
67*35238bceSAndroid Build Coastguard Worker     Event(const Event &);
68*35238bceSAndroid Build Coastguard Worker     Event &operator=(const Event &);
69*35238bceSAndroid Build Coastguard Worker };
70*35238bceSAndroid Build Coastguard Worker 
71*35238bceSAndroid Build Coastguard Worker // Base class for objects which modifications should be tracked between threads
72*35238bceSAndroid Build Coastguard Worker class Object
73*35238bceSAndroid Build Coastguard Worker {
74*35238bceSAndroid Build Coastguard Worker public:
75*35238bceSAndroid Build Coastguard Worker     Object(const char *type, de::SharedPtr<Event> createEvent);
76*35238bceSAndroid Build Coastguard Worker     virtual ~Object(void);
getType(void) const77*35238bceSAndroid Build Coastguard Worker     const char *getType(void) const
78*35238bceSAndroid Build Coastguard Worker     {
79*35238bceSAndroid Build Coastguard Worker         return m_type;
80*35238bceSAndroid Build Coastguard Worker     }
81*35238bceSAndroid Build Coastguard Worker 
82*35238bceSAndroid Build Coastguard Worker     // Used by class Operation only
83*35238bceSAndroid Build Coastguard Worker     void read(de::SharedPtr<Event> event, std::vector<de::SharedPtr<Event>> &deps);
84*35238bceSAndroid Build Coastguard Worker     void modify(de::SharedPtr<Event> event, std::vector<de::SharedPtr<Event>> &deps);
85*35238bceSAndroid Build Coastguard Worker 
86*35238bceSAndroid Build Coastguard Worker private:
87*35238bceSAndroid Build Coastguard Worker     const char *m_type;
88*35238bceSAndroid Build Coastguard Worker     de::SharedPtr<Event> m_modify;
89*35238bceSAndroid Build Coastguard Worker     std::vector<de::SharedPtr<Event>> m_reads;
90*35238bceSAndroid Build Coastguard Worker 
91*35238bceSAndroid Build Coastguard Worker     // Disabled
92*35238bceSAndroid Build Coastguard Worker     Object(const Object &);
93*35238bceSAndroid Build Coastguard Worker     Object &operator=(const Object &);
94*35238bceSAndroid Build Coastguard Worker };
95*35238bceSAndroid Build Coastguard Worker 
96*35238bceSAndroid Build Coastguard Worker class Thread;
97*35238bceSAndroid Build Coastguard Worker 
98*35238bceSAndroid Build Coastguard Worker class MessageBuilder
99*35238bceSAndroid Build Coastguard Worker {
100*35238bceSAndroid Build Coastguard Worker public:
MessageBuilder(Thread & thread)101*35238bceSAndroid Build Coastguard Worker     MessageBuilder(Thread &thread) : m_thread(thread)
102*35238bceSAndroid Build Coastguard Worker     {
103*35238bceSAndroid Build Coastguard Worker     }
MessageBuilder(const MessageBuilder & other)104*35238bceSAndroid Build Coastguard Worker     MessageBuilder(const MessageBuilder &other) : m_thread(other.m_thread), m_stream(other.m_stream.str())
105*35238bceSAndroid Build Coastguard Worker     {
106*35238bceSAndroid Build Coastguard Worker     }
107*35238bceSAndroid Build Coastguard Worker     template <class T>
operator <<(const T & t)108*35238bceSAndroid Build Coastguard Worker     MessageBuilder &operator<<(const T &t)
109*35238bceSAndroid Build Coastguard Worker     {
110*35238bceSAndroid Build Coastguard Worker         m_stream << t;
111*35238bceSAndroid Build Coastguard Worker         return *this;
112*35238bceSAndroid Build Coastguard Worker     }
113*35238bceSAndroid Build Coastguard Worker 
114*35238bceSAndroid Build Coastguard Worker     class EndToken
115*35238bceSAndroid Build Coastguard Worker     {
116*35238bceSAndroid Build Coastguard Worker     public:
EndToken(void)117*35238bceSAndroid Build Coastguard Worker         EndToken(void)
118*35238bceSAndroid Build Coastguard Worker         {
119*35238bceSAndroid Build Coastguard Worker         }
120*35238bceSAndroid Build Coastguard Worker     };
121*35238bceSAndroid Build Coastguard Worker 
122*35238bceSAndroid Build Coastguard Worker     void operator<<(const EndToken &);
123*35238bceSAndroid Build Coastguard Worker 
124*35238bceSAndroid Build Coastguard Worker private:
125*35238bceSAndroid Build Coastguard Worker     Thread &m_thread;
126*35238bceSAndroid Build Coastguard Worker     std::stringstream m_stream;
127*35238bceSAndroid Build Coastguard Worker };
128*35238bceSAndroid Build Coastguard Worker 
129*35238bceSAndroid Build Coastguard Worker class Message
130*35238bceSAndroid Build Coastguard Worker {
131*35238bceSAndroid Build Coastguard Worker public:
Message(uint64_t time,const char * message)132*35238bceSAndroid Build Coastguard Worker     Message(uint64_t time, const char *message) : m_time(time), m_message(message)
133*35238bceSAndroid Build Coastguard Worker     {
134*35238bceSAndroid Build Coastguard Worker     }
135*35238bceSAndroid Build Coastguard Worker 
getTime(void) const136*35238bceSAndroid Build Coastguard Worker     uint64_t getTime(void) const
137*35238bceSAndroid Build Coastguard Worker     {
138*35238bceSAndroid Build Coastguard Worker         return m_time;
139*35238bceSAndroid Build Coastguard Worker     }
getMessage(void) const140*35238bceSAndroid Build Coastguard Worker     const std::string &getMessage(void) const
141*35238bceSAndroid Build Coastguard Worker     {
142*35238bceSAndroid Build Coastguard Worker         return m_message;
143*35238bceSAndroid Build Coastguard Worker     }
144*35238bceSAndroid Build Coastguard Worker 
145*35238bceSAndroid Build Coastguard Worker     static const MessageBuilder::EndToken End;
146*35238bceSAndroid Build Coastguard Worker 
147*35238bceSAndroid Build Coastguard Worker private:
148*35238bceSAndroid Build Coastguard Worker     uint64_t m_time;
149*35238bceSAndroid Build Coastguard Worker     std::string m_message;
150*35238bceSAndroid Build Coastguard Worker };
151*35238bceSAndroid Build Coastguard Worker 
152*35238bceSAndroid Build Coastguard Worker // Base class for operations executed by threads
153*35238bceSAndroid Build Coastguard Worker class Operation
154*35238bceSAndroid Build Coastguard Worker {
155*35238bceSAndroid Build Coastguard Worker public:
156*35238bceSAndroid Build Coastguard Worker     Operation(const char *name);
157*35238bceSAndroid Build Coastguard Worker     virtual ~Operation(void);
158*35238bceSAndroid Build Coastguard Worker 
getName(void) const159*35238bceSAndroid Build Coastguard Worker     const char *getName(void) const
160*35238bceSAndroid Build Coastguard Worker     {
161*35238bceSAndroid Build Coastguard Worker         return m_name;
162*35238bceSAndroid Build Coastguard Worker     }
getEvent(void)163*35238bceSAndroid Build Coastguard Worker     de::SharedPtr<Event> getEvent(void)
164*35238bceSAndroid Build Coastguard Worker     {
165*35238bceSAndroid Build Coastguard Worker         return m_event;
166*35238bceSAndroid Build Coastguard Worker     }
167*35238bceSAndroid Build Coastguard Worker 
readObject(de::SharedPtr<Object> object)168*35238bceSAndroid Build Coastguard Worker     void readObject(de::SharedPtr<Object> object)
169*35238bceSAndroid Build Coastguard Worker     {
170*35238bceSAndroid Build Coastguard Worker         object->read(m_event, m_deps);
171*35238bceSAndroid Build Coastguard Worker     }
modifyObject(de::SharedPtr<Object> object)172*35238bceSAndroid Build Coastguard Worker     void modifyObject(de::SharedPtr<Object> object)
173*35238bceSAndroid Build Coastguard Worker     {
174*35238bceSAndroid Build Coastguard Worker         object->modify(m_event, m_deps);
175*35238bceSAndroid Build Coastguard Worker     }
176*35238bceSAndroid Build Coastguard Worker 
177*35238bceSAndroid Build Coastguard Worker     virtual void exec(Thread &thread) = 0; //!< Overwritten by inherited class to perform actual operation
178*35238bceSAndroid Build Coastguard Worker     virtual void execute(
179*35238bceSAndroid Build Coastguard Worker         Thread &thread); //!< May Be overwritten by inherited class to change how syncronization is done
180*35238bceSAndroid Build Coastguard Worker 
181*35238bceSAndroid Build Coastguard Worker protected:
182*35238bceSAndroid Build Coastguard Worker     const char *m_name;
183*35238bceSAndroid Build Coastguard Worker     std::vector<de::SharedPtr<Event>> m_deps;
184*35238bceSAndroid Build Coastguard Worker     de::SharedPtr<Event> m_event;
185*35238bceSAndroid Build Coastguard Worker 
186*35238bceSAndroid Build Coastguard Worker     Operation(const Operation &);
187*35238bceSAndroid Build Coastguard Worker     Operation &operator=(const Operation &);
188*35238bceSAndroid Build Coastguard Worker };
189*35238bceSAndroid Build Coastguard Worker 
190*35238bceSAndroid Build Coastguard Worker class Thread : public de::Thread
191*35238bceSAndroid Build Coastguard Worker {
192*35238bceSAndroid Build Coastguard Worker public:
193*35238bceSAndroid Build Coastguard Worker     enum ThreadStatus
194*35238bceSAndroid Build Coastguard Worker     {
195*35238bceSAndroid Build Coastguard Worker         THREADSTATUS_NOT_STARTED = 0,
196*35238bceSAndroid Build Coastguard Worker         THREADSTATUS_INIT_FAILED,
197*35238bceSAndroid Build Coastguard Worker         THREADSTATUS_RUNNING,
198*35238bceSAndroid Build Coastguard Worker         THREADSTATUS_READY,
199*35238bceSAndroid Build Coastguard Worker         THREADSTATUS_FAILED,
200*35238bceSAndroid Build Coastguard Worker         THREADSTATUS_NOT_SUPPORTED
201*35238bceSAndroid Build Coastguard Worker     };
202*35238bceSAndroid Build Coastguard Worker     Thread(uint32_t seed);
203*35238bceSAndroid Build Coastguard Worker     ~Thread(void);
204*35238bceSAndroid Build Coastguard Worker 
init(void)205*35238bceSAndroid Build Coastguard Worker     virtual void init(void)
206*35238bceSAndroid Build Coastguard Worker     {
207*35238bceSAndroid Build Coastguard Worker     } //!< Called first before any Operation
208*35238bceSAndroid Build Coastguard Worker 
209*35238bceSAndroid Build Coastguard Worker     // \todo [mika] Should the result of execution be passed to deinit?
deinit(void)210*35238bceSAndroid Build Coastguard Worker     virtual void deinit(void)
211*35238bceSAndroid Build Coastguard Worker     {
212*35238bceSAndroid Build Coastguard Worker     } //!< Called after after operation
213*35238bceSAndroid Build Coastguard Worker 
214*35238bceSAndroid Build Coastguard Worker     void addOperation(Operation *operation);
215*35238bceSAndroid Build Coastguard Worker 
216*35238bceSAndroid Build Coastguard Worker     void exec(void);
217*35238bceSAndroid Build Coastguard Worker 
218*35238bceSAndroid Build Coastguard Worker     uint8_t *getUnusedData(
219*35238bceSAndroid Build Coastguard Worker         size_t size); //!< Return data pointer that contains at least size bytes. Valid until next call
220*35238bceSAndroid Build Coastguard Worker 
getStatus(void) const221*35238bceSAndroid Build Coastguard Worker     ThreadStatus getStatus(void) const
222*35238bceSAndroid Build Coastguard Worker     {
223*35238bceSAndroid Build Coastguard Worker         de::ScopedLock lock(m_statusLock);
224*35238bceSAndroid Build Coastguard Worker         return m_status;
225*35238bceSAndroid Build Coastguard Worker     }
setStatus(ThreadStatus status)226*35238bceSAndroid Build Coastguard Worker     void setStatus(ThreadStatus status)
227*35238bceSAndroid Build Coastguard Worker     {
228*35238bceSAndroid Build Coastguard Worker         de::ScopedLock lock(m_statusLock);
229*35238bceSAndroid Build Coastguard Worker         m_status = status;
230*35238bceSAndroid Build Coastguard Worker     }
231*35238bceSAndroid Build Coastguard Worker 
newMessage(void)232*35238bceSAndroid Build Coastguard Worker     MessageBuilder newMessage(void)
233*35238bceSAndroid Build Coastguard Worker     {
234*35238bceSAndroid Build Coastguard Worker         return MessageBuilder(*this);
235*35238bceSAndroid Build Coastguard Worker     }
getRandom(void)236*35238bceSAndroid Build Coastguard Worker     de::Random &getRandom(void)
237*35238bceSAndroid Build Coastguard Worker     {
238*35238bceSAndroid Build Coastguard Worker         return m_random;
239*35238bceSAndroid Build Coastguard Worker     }
240*35238bceSAndroid Build Coastguard Worker 
241*35238bceSAndroid Build Coastguard Worker     // Used to by test case to read log messages
242*35238bceSAndroid Build Coastguard Worker     int getMessageCount(void) const;
243*35238bceSAndroid Build Coastguard Worker     Message getMessage(int index) const;
244*35238bceSAndroid Build Coastguard Worker 
245*35238bceSAndroid Build Coastguard Worker     // Used by message builder
246*35238bceSAndroid Build Coastguard Worker     void pushMessage(const std::string &str);
247*35238bceSAndroid Build Coastguard Worker 
248*35238bceSAndroid Build Coastguard Worker private:
249*35238bceSAndroid Build Coastguard Worker     virtual void run(void);
250*35238bceSAndroid Build Coastguard Worker 
251*35238bceSAndroid Build Coastguard Worker     std::vector<Operation *> m_operations;
252*35238bceSAndroid Build Coastguard Worker     de::Random m_random;
253*35238bceSAndroid Build Coastguard Worker 
254*35238bceSAndroid Build Coastguard Worker     mutable de::Mutex m_messageLock;
255*35238bceSAndroid Build Coastguard Worker     std::vector<Message> m_messages;
256*35238bceSAndroid Build Coastguard Worker     mutable de::Mutex m_statusLock;
257*35238bceSAndroid Build Coastguard Worker     ThreadStatus m_status;
258*35238bceSAndroid Build Coastguard Worker     std::vector<uint8_t> m_unusedData;
259*35238bceSAndroid Build Coastguard Worker 
260*35238bceSAndroid Build Coastguard Worker     // Disabled
261*35238bceSAndroid Build Coastguard Worker     Thread(const Thread &);
262*35238bceSAndroid Build Coastguard Worker     Thread operator=(const Thread &);
263*35238bceSAndroid Build Coastguard Worker };
264*35238bceSAndroid Build Coastguard Worker 
265*35238bceSAndroid Build Coastguard Worker class DataBlock : public Object
266*35238bceSAndroid Build Coastguard Worker {
267*35238bceSAndroid Build Coastguard Worker public:
268*35238bceSAndroid Build Coastguard Worker     DataBlock(de::SharedPtr<Event> event);
269*35238bceSAndroid Build Coastguard Worker 
270*35238bceSAndroid Build Coastguard Worker     void setData(size_t size, const void *data);
getData(void) const271*35238bceSAndroid Build Coastguard Worker     const uint8_t *getData(void) const
272*35238bceSAndroid Build Coastguard Worker     {
273*35238bceSAndroid Build Coastguard Worker         return &(m_data[0]);
274*35238bceSAndroid Build Coastguard Worker     }
getSize(void) const275*35238bceSAndroid Build Coastguard Worker     size_t getSize(void) const
276*35238bceSAndroid Build Coastguard Worker     {
277*35238bceSAndroid Build Coastguard Worker         return m_data.size();
278*35238bceSAndroid Build Coastguard Worker     }
279*35238bceSAndroid Build Coastguard Worker 
280*35238bceSAndroid Build Coastguard Worker private:
281*35238bceSAndroid Build Coastguard Worker     std::vector<uint8_t> m_data;
282*35238bceSAndroid Build Coastguard Worker };
283*35238bceSAndroid Build Coastguard Worker 
284*35238bceSAndroid Build Coastguard Worker class CompareData : public Operation
285*35238bceSAndroid Build Coastguard Worker {
286*35238bceSAndroid Build Coastguard Worker public:
287*35238bceSAndroid Build Coastguard Worker     CompareData(de::SharedPtr<DataBlock> a, de::SharedPtr<DataBlock> b);
288*35238bceSAndroid Build Coastguard Worker     void exec(Thread &thread);
289*35238bceSAndroid Build Coastguard Worker 
290*35238bceSAndroid Build Coastguard Worker private:
291*35238bceSAndroid Build Coastguard Worker     de::SharedPtr<DataBlock> m_a;
292*35238bceSAndroid Build Coastguard Worker     de::SharedPtr<DataBlock> m_b;
293*35238bceSAndroid Build Coastguard Worker };
294*35238bceSAndroid Build Coastguard Worker 
295*35238bceSAndroid Build Coastguard Worker } // namespace ThreadUtil
296*35238bceSAndroid Build Coastguard Worker } // namespace tcu
297*35238bceSAndroid Build Coastguard Worker 
298*35238bceSAndroid Build Coastguard Worker #endif // _TCUTHREADUTIL_HPP
299