13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program Helper Library
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * -------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Watch dog for detecting timeouts
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "qpWatchDog.h"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deThread.h"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deClock.h"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemory.h"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <stdio.h>
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if 0
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	define DBGPRINT(X) qpPrintf X
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#else
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	define DBGPRINT(X)
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef enum Status_e
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	STATUS_THREAD_RUNNING = 0,
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	STATUS_STOP_THREAD,
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	STATUS_LAST
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} Status;
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct qpWatchDog_s
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	qpWatchDogFunc		timeOutFunc;
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void*				timeOutUserPtr;
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					totalTimeLimit;			/* Total test case time limit in seconds 	*/
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					intervalTimeLimit;		/* Iteration length limit in seconds 		*/
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	volatile deUint64	resetTime;
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	volatile deUint64	lastTouchTime;
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deThread			watchDogThread;
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	volatile Status		status;
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void watchDogThreadFunc (void* arg)
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	qpWatchDog* dog = (qpWatchDog*)arg;
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(dog);
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DBGPRINT(("watchDogThreadFunc(): start\n"));
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	while (dog->status == STATUS_THREAD_RUNNING)
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint64	curTime					= deGetMicroseconds();
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int			totalSecondsPassed		= (int)((curTime - dog->resetTime) / 1000000ull);
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int			secondsSinceLastTouch	= (int)((curTime - dog->lastTouchTime) / 1000000ull);
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if ((secondsSinceLastTouch > dog->intervalTimeLimit) || (totalSecondsPassed > dog->totalTimeLimit))
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DBGPRINT(("watchDogThreadFunc(): call timeout func\n"));
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dog->timeOutFunc(dog, dog->timeOutUserPtr);
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deSleep(100);
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DBGPRINT(("watchDogThreadFunc(): stop\n"));
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
863c827367444ee418f129b2c238299f49d3264554Jarkko PoyryqpWatchDog* qpWatchDog_create (qpWatchDogFunc timeOutFunc, void* userPtr, int totalTimeLimitSecs, int intervalTimeLimitSecs)
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Allocate & initialize. */
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	qpWatchDog* dog = (qpWatchDog*)deCalloc(sizeof(qpWatchDog));
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!dog)
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return dog;
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(timeOutFunc);
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((totalTimeLimitSecs > 0) && (intervalTimeLimitSecs > 0));
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DBGPRINT(("qpWatchDog::create(%ds, %ds)\n", totalTimeLimitSecs, intervalTimeLimitSecs));
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dog->timeOutFunc		= timeOutFunc;
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dog->timeOutUserPtr		= userPtr;
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dog->totalTimeLimit		= totalTimeLimitSecs;
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dog->intervalTimeLimit	= intervalTimeLimitSecs;
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Reset (sets time values). */
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	qpWatchDog_reset(dog);
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Initialize watchdog thread. */
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dog->status			= STATUS_THREAD_RUNNING;
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dog->watchDogThread = deThread_create(watchDogThreadFunc, dog, DE_NULL);
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!dog->watchDogThread)
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deFree(dog);
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_NULL;
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return dog;
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid qpWatchDog_reset (qpWatchDog* dog)
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint64 curTime = deGetMicroseconds();
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(dog);
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DBGPRINT(("qpWatchDog::reset()\n"));
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dog->resetTime			= curTime;
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dog->lastTouchTime		= curTime;
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid qpWatchDog_destroy (qpWatchDog* dog)
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(dog);
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DBGPRINT(("qpWatchDog::destroy()\n"));
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Finish the watchdog thread. */
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dog->status = STATUS_STOP_THREAD;
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deThread_join(dog->watchDogThread);
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deThread_destroy(dog->watchDogThread);
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DBGPRINT(("qpWatchDog::destroy() finished\n"));
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deFree(dog);
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid qpWatchDog_touch (qpWatchDog* dog)
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(dog);
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DBGPRINT(("qpWatchDog::touch()\n"));
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dog->lastTouchTime = deGetMicroseconds();
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
149