Home | History | Annotate | Download | only in qphelper
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program Helper Library
      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 Watch dog for detecting timeouts
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "qpWatchDog.h"
     25 
     26 #include "deThread.h"
     27 #include "deClock.h"
     28 #include "deMemory.h"
     29 
     30 #include <stdio.h>
     31 
     32 #if 0
     33 #	define DBGPRINT(X) qpPrintf X
     34 #else
     35 #	define DBGPRINT(X)
     36 #endif
     37 
     38 typedef enum Status_e
     39 {
     40 	STATUS_THREAD_RUNNING = 0,
     41 	STATUS_STOP_THREAD,
     42 
     43 	STATUS_LAST
     44 } Status;
     45 
     46 struct qpWatchDog_s
     47 {
     48 	qpWatchDogFunc		timeOutFunc;
     49 	void*				timeOutUserPtr;
     50 	int					totalTimeLimit;			/* Total test case time limit in seconds	*/
     51 	int					intervalTimeLimit;		/* Iteration length limit in seconds		*/
     52 
     53 	volatile deUint64	resetTime;
     54 	volatile deUint64	lastTouchTime;
     55 
     56 	deThread			watchDogThread;
     57 	volatile Status		status;
     58 };
     59 
     60 static void watchDogThreadFunc (void* arg)
     61 {
     62 	qpWatchDog* dog = (qpWatchDog*)arg;
     63 	DE_ASSERT(dog);
     64 
     65 	DBGPRINT(("watchDogThreadFunc(): start\n"));
     66 
     67 	while (dog->status == STATUS_THREAD_RUNNING)
     68 	{
     69 		deUint64	curTime					= deGetMicroseconds();
     70 		int			totalSecondsPassed		= (int)((curTime - dog->resetTime) / 1000000ull);
     71 		int			secondsSinceLastTouch	= (int)((curTime - dog->lastTouchTime) / 1000000ull);
     72 		deBool		overIntervalLimit		= secondsSinceLastTouch > dog->intervalTimeLimit;
     73 		deBool		overTotalLimit			= totalSecondsPassed > dog->totalTimeLimit;
     74 
     75 		if (overIntervalLimit || overTotalLimit)
     76 		{
     77 		    qpTimeoutReason reason = overTotalLimit ? QP_TIMEOUT_REASON_TOTAL_LIMIT : QP_TIMEOUT_REASON_INTERVAL_LIMIT;
     78 			DBGPRINT(("watchDogThreadFunc(): call timeout func\n"));
     79 			dog->timeOutFunc(dog, dog->timeOutUserPtr, reason);
     80 			break;
     81 		}
     82 
     83 		deSleep(100);
     84 	}
     85 
     86 	DBGPRINT(("watchDogThreadFunc(): stop\n"));
     87 }
     88 
     89 qpWatchDog* qpWatchDog_create (qpWatchDogFunc timeOutFunc, void* userPtr, int totalTimeLimitSecs, int intervalTimeLimitSecs)
     90 {
     91 	/* Allocate & initialize. */
     92 	qpWatchDog* dog = (qpWatchDog*)deCalloc(sizeof(qpWatchDog));
     93 	if (!dog)
     94 		return dog;
     95 
     96 	DE_ASSERT(timeOutFunc);
     97 	DE_ASSERT((totalTimeLimitSecs > 0) && (intervalTimeLimitSecs > 0));
     98 
     99 	DBGPRINT(("qpWatchDog::create(%ds, %ds)\n", totalTimeLimitSecs, intervalTimeLimitSecs));
    100 
    101 	dog->timeOutFunc		= timeOutFunc;
    102 	dog->timeOutUserPtr		= userPtr;
    103 	dog->totalTimeLimit		= totalTimeLimitSecs;
    104 	dog->intervalTimeLimit	= intervalTimeLimitSecs;
    105 
    106 	/* Reset (sets time values). */
    107 	qpWatchDog_reset(dog);
    108 
    109 	/* Initialize watchdog thread. */
    110 	dog->status			= STATUS_THREAD_RUNNING;
    111 	dog->watchDogThread = deThread_create(watchDogThreadFunc, dog, DE_NULL);
    112 	if (!dog->watchDogThread)
    113 	{
    114 		deFree(dog);
    115 		return DE_NULL;
    116 	}
    117 
    118 	return dog;
    119 }
    120 
    121 void qpWatchDog_reset (qpWatchDog* dog)
    122 {
    123 	deUint64 curTime = deGetMicroseconds();
    124 
    125 	DE_ASSERT(dog);
    126 	DBGPRINT(("qpWatchDog::reset()\n"));
    127 
    128 	dog->resetTime			= curTime;
    129 	dog->lastTouchTime		= curTime;
    130 }
    131 
    132 void qpWatchDog_destroy (qpWatchDog* dog)
    133 {
    134 	DE_ASSERT(dog);
    135 	DBGPRINT(("qpWatchDog::destroy()\n"));
    136 
    137 	/* Finish the watchdog thread. */
    138 	dog->status = STATUS_STOP_THREAD;
    139 	deThread_join(dog->watchDogThread);
    140 	deThread_destroy(dog->watchDogThread);
    141 
    142 	DBGPRINT(("qpWatchDog::destroy() finished\n"));
    143 	deFree(dog);
    144 }
    145 
    146 void qpWatchDog_touch (qpWatchDog* dog)
    147 {
    148 	DE_ASSERT(dog);
    149 	DBGPRINT(("qpWatchDog::touch()\n"));
    150 	dog->lastTouchTime = deGetMicroseconds();
    151 }
    152