1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Helper Library
3 * -------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Watch dog for detecting timeouts
22 *//*--------------------------------------------------------------------*/
24 #include "qpWatchDog.h"
33 # define DBGPRINT(X) qpPrintf X
40 STATUS_THREAD_RUNNING = 0,
48 qpWatchDogFunc timeOutFunc;
50 int totalTimeLimit; /* Total test case time limit in seconds */
51 int intervalTimeLimit; /* Iteration length limit in seconds */
53 Iteration time limit in seconds specified to the constructor. This is stored so that
54 intervalTimeLimit can be restored after qpWatchDog_touchAndDisableIntervalTimeLimit
57 int defaultIntervalTimeLimit;
59 volatile deUint64 resetTime;
60 volatile deUint64 lastTouchTime;
62 deThread watchDogThread;
63 volatile Status status;
66 static void watchDogThreadFunc (void* arg)
68 qpWatchDog* dog = (qpWatchDog*)arg;
71 DBGPRINT(("watchDogThreadFunc(): start\n"));
73 while (dog->status == STATUS_THREAD_RUNNING)
75 deUint64 curTime = deGetMicroseconds();
76 int totalSecondsPassed = (int)((curTime - dog->resetTime) / 1000000ull);
77 int secondsSinceLastTouch = (int)((curTime - dog->lastTouchTime) / 1000000ull);
78 deBool overIntervalLimit = secondsSinceLastTouch > dog->intervalTimeLimit;
79 deBool overTotalLimit = totalSecondsPassed > dog->totalTimeLimit;
81 if (overIntervalLimit || overTotalLimit)
83 qpTimeoutReason reason = overTotalLimit ? QP_TIMEOUT_REASON_TOTAL_LIMIT : QP_TIMEOUT_REASON_INTERVAL_LIMIT;
84 DBGPRINT(("watchDogThreadFunc(): call timeout func\n"));
85 dog->timeOutFunc(dog, dog->timeOutUserPtr, reason);
92 DBGPRINT(("watchDogThreadFunc(): stop\n"));
95 qpWatchDog* qpWatchDog_create (qpWatchDogFunc timeOutFunc, void* userPtr, int totalTimeLimitSecs, int intervalTimeLimitSecs)
97 /* Allocate & initialize. */
98 qpWatchDog* dog = (qpWatchDog*)deCalloc(sizeof(qpWatchDog));
102 DE_ASSERT(timeOutFunc);
103 DE_ASSERT((totalTimeLimitSecs > 0) && (intervalTimeLimitSecs > 0));
105 DBGPRINT(("qpWatchDog::create(%ds, %ds)\n", totalTimeLimitSecs, intervalTimeLimitSecs));
107 dog->timeOutFunc = timeOutFunc;
108 dog->timeOutUserPtr = userPtr;
109 dog->totalTimeLimit = totalTimeLimitSecs;
110 dog->intervalTimeLimit = intervalTimeLimitSecs;
111 dog->defaultIntervalTimeLimit = intervalTimeLimitSecs;
113 /* Reset (sets time values). */
114 qpWatchDog_reset(dog);
116 /* Initialize watchdog thread. */
117 dog->status = STATUS_THREAD_RUNNING;
118 dog->watchDogThread = deThread_create(watchDogThreadFunc, dog, DE_NULL);
119 if (!dog->watchDogThread)
128 void qpWatchDog_reset (qpWatchDog* dog)
130 deUint64 curTime = deGetMicroseconds();
133 DBGPRINT(("qpWatchDog::reset()\n"));
135 dog->resetTime = curTime;
136 dog->lastTouchTime = curTime;
139 void qpWatchDog_destroy (qpWatchDog* dog)
142 DBGPRINT(("qpWatchDog::destroy()\n"));
144 /* Finish the watchdog thread. */
145 dog->status = STATUS_STOP_THREAD;
146 deThread_join(dog->watchDogThread);
147 deThread_destroy(dog->watchDogThread);
149 DBGPRINT(("qpWatchDog::destroy() finished\n"));
153 void qpWatchDog_touch (qpWatchDog* dog)
156 DBGPRINT(("qpWatchDog::touch()\n"));
157 dog->lastTouchTime = deGetMicroseconds();
161 These function exists to allow the interval timer to be disabled for special cases
162 like very long shader compilations. Heavy code can be put between calls
163 to qpWatchDog_touchAndDisableIntervalTimeLimit and qpWatchDog_touchAndEnableIntervalTimeLimit
164 and during that period the interval time limit will become the same as the total
165 time limit. Afterwards, the interval timer is set back to its default.
167 void qpWatchDog_touchAndDisableIntervalTimeLimit(qpWatchDog *dog)
169 dog->intervalTimeLimit = dog->totalTimeLimit;
170 qpWatchDog_touch(dog);
173 void qpWatchDog_touchAndEnableIntervalTimeLimit(qpWatchDog *dog)
175 dog->intervalTimeLimit = dog->defaultIntervalTimeLimit;
176 qpWatchDog_touch(dog);