|
From: <jmk...@us...> - 2003-08-15 20:47:53
|
Update of /cvsroot/emc/rtapi/examples/watchdog
In directory sc8-pr-cvs1:/tmp/cvs-serv2354/examples/watchdog
Added Files:
Makefile watchdog.c
Log Message:
Finished converting rtai_rtapi.c, added watchdog example.
--- NEW FILE: Makefile ---
# Makefile for watchdog example
# get the defs for CC, CFLAGS, LIB_DIR, etc.
include ../../Makefile.inc
SRCS = watchdog.c
OBJS = $(RTLIB_DIR)/watchdog.o
HEADERS =
BINS =
all : $(OBJS)
$(RTLIB_DIR)/%.o : %.c
$(CC) -c $(RTFLAGS) $< -o $@
headers :
depend :
makedepend -Y -I$(INC_DIR) -p$(RTLIB_DIR)/ $(SRCS) 2> /dev/null
indent :
indent $(SRCS)
clean :
- \rm -f *.bak *~
- \rm -f $(OBJS)
.PHONY: all headers depend indent install clean clean_install
# DO NOT DELETE
/home/John/emcdev/rtapi/rtlib/watchdog.o: /home/John/emcdev/rtapi/include/rtapi.h
/home/John/emcdev/rtapi/rtlib/watchdog.o: /home/John/emcdev/rtapi/include/rtapi_app.h
--- NEW FILE: watchdog.c ---
/*
watchdog.c
A crude but effective watchdog to prevent lockups if realtime tasks
get stuck in infinite loops or otherwise start hogging the CPU.
Theory of operation:
On init, watchdog sets up two periodic tasks. One operates at the
lowest priority, runs once per second, and resets a global variable
to zero. The other operates at the highest priority, runs once
per second, and increments the global variable. If the global
ever reaches 5, the high priority task concludes that some mis-
behaving task(s) are keeping the low priority task from running.
In that case, it takes action. The action is pretty brutal, it
simply pauses ALL tasks, except for the watchdog tasks. That
should be enough to get the user a prompt. Note that the watchdog
cannot protect against a mis-behaving task at the highest or lowest
priority. A highest priority task could prempt the watchdog itself,
and a lowest priority task could time-share with the low priority
watchdog task while blocking all user (Linux) activity. DON'T
run untrusted code at the highest or lowest priority!.
This could be improved - possible features:
User specified delay instead of 5 seconds.
Variable priority for the hi task, so that trusted, time-critical
tasks wouldn't be interrupted by the watchdog hi task.
If it were incorporated directly into the rtapi, the range of
priority permitted by other tasks could be reduced by 1 at
each end, allowing the watchdog tasks to protect all priorities.
A user mode program could be used to "pet" the watchdog, to
provide even more protection against locking Linux out of the
CPU.
Maybe later....
*/
/** Copyright (C) 2003 John Kasunich *
* <jmkasunich AT users DOT sourceforge DOT net> */
/* This program is free software; you can redistribute it and/or *
* modify it under the terms of version 2 of the GNU General Public *
* License as published by the Free Software Foundation. *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA */
#include "rtapi.h"
#include "rtapi_app.h" /* rtapi_app_main,exit() */
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
static int hi_task; /* the high priority task ID */
static int lo_task; /* the low priority task ID */
static int watchdog = 0; /* the counter variable */
enum { TIMER_PERIOD_NSEC = 10000000 }; /* timer period, in nanoseconds */
enum { TASK_PERIOD_NSEC = 1000000000 }; /* task period, in nanoseconds */
enum { STACKSIZE = 1024 }; /* how big the stack is */
static void hi_code( int arg )
{
int n;
watchdog = 0;
while (1) {
/* check the dog, loop as long as somebody's petting him */
while ( watchdog++ < 6 ) {
rtapi_wait();
}
/* oops - nobody's petting the dog, and he's getting angry! */
rtapi_print_msg( RTAPI_MSG_ERR, "WATCHDOG: WOOF - pausing all tasks!\n" );
/* loop, deleting tasks (we don't know how many, just try them all */
for ( n = 0 ; n < 256 ; n++ ) {
/* don't want to kill the watchdog tasks */
if ((n != hi_task) && (n != lo_task)) {
rtapi_task_pause ( n );
}
}
/* put the dog back to sleep */
watchdog = 0;
}
return;
}
static void lo_code( int arg )
{
while ( 1 ) {
/* pet the dog. "Nice dog, don't bite me." */
watchdog = 0;
/* wait and do it again. */
rtapi_wait();
}
return;
}
/* part of the Linux kernel module that kicks off the tasks */
int rtapi_app_main(void)
{
int retval;
int prio;
rtapi_print_msg(RTAPI_MSG_INFO, "WATCHDOG: Installing watchdog\n");
if (rtapi_init() != RTAPI_SUCCESS ) {
return -1;
}
/* set the base timer period */
retval = rtapi_clock_set_period(TIMER_PERIOD_NSEC);
if ( retval < 0 ) {
/* See rtapi.h for the error codes returned */
rtapi_print_msg( RTAPI_MSG_ERR,
"watchdog init: rtapi_clock_set_period returned %d\n", retval );
return -1;
}
/* low priority task first */
prio = rtapi_prio_lowest();
lo_task = rtapi_task_new(lo_code, 0 /* arg */, prio, STACKSIZE, RTAPI_NO_FP );
if ( lo_task < 0 ) {
/* See rtapi.h for the error codes returned */
rtapi_print_msg( RTAPI_MSG_ERR,
"watchdog init: rtapi_task_new(lo) returned %d\n", lo_task );
return -1;
}
/* now the high priority task */
prio = rtapi_prio_highest();
hi_task = rtapi_task_new(hi_code, 0 /* arg */, prio, STACKSIZE, RTAPI_NO_FP );
if ( hi_task < 0 ) {
rtapi_print_msg( RTAPI_MSG_ERR,
"watchdog init: rtapi_task_new(hi) returned %d\n", hi_task );
return -1;
}
/* start both tasks running */
retval = rtapi_task_start( lo_task, TASK_PERIOD_NSEC, RTAPI_NOW );
if ( retval != RTAPI_SUCCESS ) {
rtapi_print_msg( RTAPI_MSG_ERR,
"watchdog init: rtapi_task_start(lo) returned %d\n", retval );
return -1;
}
retval = rtapi_task_start( hi_task, TASK_PERIOD_NSEC, RTAPI_NOW );
if ( retval != RTAPI_SUCCESS ) {
rtapi_print_msg( RTAPI_MSG_ERR,
"watchdog init: rtapi_task_start(hi) returned %d\n", retval );
return -1;
}
rtapi_print_msg( RTAPI_MSG_INFO, "WATCHDOG: The watchdog is on duty.\n" );
return 0;
}
/* part of the Linux kernel module that stops the tasks */
void rtapi_app_exit(void)
{
int retval;
rtapi_print_msg( RTAPI_MSG_INFO, "WATCHDOG: The watchdog is going to sleep.\n" );
/* Stop the tasks */
retval = rtapi_task_pause(hi_task);
if ( retval != RTAPI_SUCCESS ) {
rtapi_print_msg( RTAPI_MSG_ERR,
"watchdog exit: rtapi_task_pause(hi) returned %d\n", retval );
}
retval = rtapi_task_pause(lo_task);
if ( retval != RTAPI_SUCCESS ) {
rtapi_print_msg( RTAPI_MSG_ERR,
"watchdog exit: rtapi_task_pause(lo) returned %d\n", retval );
}
/* delete the tasks */
retval = rtapi_task_delete(hi_task);
if ( retval != RTAPI_SUCCESS ) {
rtapi_print_msg( RTAPI_MSG_ERR,
"watchdog exit: rtapi_task_delete(hi) returned %d\n", retval );
}
retval = rtapi_task_delete(lo_task);
if ( retval != RTAPI_SUCCESS ) {
rtapi_print_msg( RTAPI_MSG_ERR,
"watchdog exit: rtapi_task_delete(lo) returned %d\n", retval );
}
rtapi_exit();
rtapi_print_msg(RTAPI_MSG_INFO, "WATCHDOG: Watchdog removed.\n");
}
|