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 
     73 		if ((secondsSinceLastTouch > dog->intervalTimeLimit) || (totalSecondsPassed > dog->totalTimeLimit))
     74 		{
     75 			DBGPRINT(("watchDogThreadFunc(): call timeout func\n"));
     76 			dog->timeOutFunc(dog, dog->timeOutUserPtr);
     77 			break;
     78 		}
     79 
     80 		deSleep(100);
     81 	}
     82 
     83 	DBGPRINT(("watchDogThreadFunc(): stop\n"));
     84 }
     85 
     86 qpWatchDog* qpWatchDog_create (qpWatchDogFunc timeOutFunc, void* userPtr, int totalTimeLimitSecs, int intervalTimeLimitSecs)
     87 {
     88 	/* Allocate & initialize. */
     89 	qpWatchDog* dog = (qpWatchDog*)deCalloc(sizeof(qpWatchDog));
     90 	if (!dog)
     91 		return dog;
     92 
     93 	DE_ASSERT(timeOutFunc);
     94 	DE_ASSERT((totalTimeLimitSecs > 0) && (intervalTimeLimitSecs > 0));
     95 
     96 	DBGPRINT(("qpWatchDog::create(%ds, %ds)\n", totalTimeLimitSecs, intervalTimeLimitSecs));
     97 
     98 	dog->timeOutFunc		= timeOutFunc;
     99 	dog->timeOutUserPtr		= userPtr;
    100 	dog->totalTimeLimit		= totalTimeLimitSecs;
    101 	dog->intervalTimeLimit	= intervalTimeLimitSecs;
    102 
    103 	/* Reset (sets time values). */
    104 	qpWatchDog_reset(dog);
    105 
    106 	/* Initialize watchdog thread. */
    107 	dog->status			= STATUS_THREAD_RUNNING;
    108 	dog->watchDogThread = deThread_create(watchDogThreadFunc, dog, DE_NULL);
    109 	if (!dog->watchDogThread)
    110 	{
    111 		deFree(dog);
    112 		return DE_NULL;
    113 	}
    114 
    115 	return dog;
    116 }
    117 
    118 void qpWatchDog_reset (qpWatchDog* dog)
    119 {
    120 	deUint64 curTime = deGetMicroseconds();
    121 
    122 	DE_ASSERT(dog);
    123 	DBGPRINT(("qpWatchDog::reset()\n"));
    124 
    125 	dog->resetTime			= curTime;
    126 	dog->lastTouchTime		= curTime;
    127 }
    128 
    129 void qpWatchDog_destroy (qpWatchDog* dog)
    130 {
    131 	DE_ASSERT(dog);
    132 	DBGPRINT(("qpWatchDog::destroy()\n"));
    133 
    134 	/* Finish the watchdog thread. */
    135 	dog->status = STATUS_STOP_THREAD;
    136 	deThread_join(dog->watchDogThread);
    137 	deThread_destroy(dog->watchDogThread);
    138 
    139 	DBGPRINT(("qpWatchDog::destroy() finished\n"));
    140 	deFree(dog);
    141 }
    142 
    143 void qpWatchDog_touch (qpWatchDog* dog)
    144 {
    145 	DE_ASSERT(dog);
    146 	DBGPRINT(("qpWatchDog::touch()\n"));
    147 	dog->lastTouchTime = deGetMicroseconds();
    148 }
    149