Project

General

Profile

Using Watchdog » watchdog.cpp

Jonathan Cormier, 10/14/2014 03:43 PM

 
#include "watchdog.h"
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <linux/watchdog.h>

using namespace MityDSP;

/**
* Constructor for the watchdog abstraction
*
* \param apDevice filename of device (defaults to /dev/watchdog)
*/
tcWatchdog::tcWatchdog(const char* apDevice)
: mnMask(0)
, mnSet(0)
, mnFd(-1)
{
sem_init(&mhSem, 0, 1);
mpFileName = new char[strlen(apDevice)+1];
strcpy(mpFileName, apDevice);
}

/**
* Destructor. Shuts down running watchdog. cleans up resources.
*/
tcWatchdog::~tcWatchdog(void)
{
const char *no_reboot = "V\n";
if (mnFd >= 0)
{
printf("shutting down watchdog\n");
write(mnFd,no_reboot,strlen(no_reboot));
close(mnFd);
}
delete [] mpFileName;
sem_destroy(&mhSem);
}

/**
* Enable the watchdog. This should typically be
* called after at least 1 checkpoint has been registered
* and the application is ready for the watchdog operation
* to begin.
*
* \param TimeoutSecs number of seconds before watchdog timeout
* \return non-zero on error.
*/
int tcWatchdog::StartWatchDog(int TimeoutSecs)
{
mnFd = open(mpFileName, O_RDWR);
if (mnFd < 0)
{
perror("open watchdog:");
return mnFd;
}
// NOTE: L138 watchdog driver doesn't support WDIOC_SETTIMEOUT.
// Timeout defaults to 60 seconds
ioctl(mnFd,WDIOC_SETTIMEOUT,&TimeoutSecs);
return 0;
}

/**
* Register a checkpoint. The tcWatchdog class supports multiple
* checkpoints (or threads, etc.) that must Checkin() prior to the
* watchdog being tagged. This routine generates a handle for a
* newly registered checkpoint.
*
* \return handle to use for Checkin() or -1 on failure.
*/
int tcWatchdog::RegisterCheckpoint(void)
{
int i, mask;
int rv = -1;
sem_wait(&mhSem);
/* find next available slot in mask */
for (i = 0, mask=1; i < 31; i++, mask<<=1)
{
if (!(mask & mnMask))
{
mnMask |= mask;
rv = mask;
break;
}
}
sem_post(&mhSem);
return rv;
}

/**
* Remove a registered checkpoint from the monitor list.
* \param handle the checkpoint previously from RegisterCheckpoint
* \return non-zero on error.
*/
int tcWatchdog::UnRegisterCheckpoint(int handle)
{
int rv = -1;
sem_wait(&mhSem);
if (handle & mnMask)
{
mnMask &= ~handle;
rv = 0;
}
sem_post(&mhSem);
return rv;
}

/**
* Check in for the watchdog update. When all registered
* methods have checked in, the watchdog timer will be
* tagged/reset.
*
* \param Checkpoint checkpoint handle from RegisterCheckpoint
*
* \return non-zero on error.
*/
int tcWatchdog::Checkin(int Checkpoint)
{
if (mnFd < 0)
return -1;

sem_wait(&mhSem);
mnSet |= Checkpoint;
if (mnSet == mnMask)
{
/* tag watchdog */
mnSet = 0;
ioctl(mnFd, WDIOC_KEEPALIVE, 0);
}
sem_post(&mhSem);

return 0;
}

#ifdef WATCHDOG_MAIN
int main()
{
tcWatchdog watch;
int watchHandle;

printf("Starting watchdog! Timeout interval 60s.\n");
watch.StartWatchDog(60000);
watchHandle = watch.RegisterCheckpoint();

while (1 == 1)
{
printf(".");
fflush(stdout);

// Tickle watchdog
watch.Checkin(watchHandle);
// Sleep 1 second
sleep(1);
}

return 0;
}
#endif
(5-5/7)