wd_keeper.c
来自「OTP是开放电信平台的简称」· C语言 代码 · 共 205 行
C
205 行
/* ``The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' * * $Id$ *//* * File: wd_keeper.c * Purpose: Hardware watchdog handler for Solaris on FORCE 5TE * * DESCRIPTION * * This program enables the hardware watchdog of the CPU board, * and then keeps the little puppy happy as long as it receives * periodical signals from the outside. If there is too long a * gap between these signals, the wd_keeper stops resetting the * watchdog, which resets the system in a few seconds. * * Once successfully started, SIGUSR1 signals are expected from * the outside within the interval specified at startup. The hardware * watchdog itself wannot be disabled once enabled, but by sending * wd_keeper a SIGFREEZE, it keeps the dog happy even if no SIGUSR1 * signals arrive. Normal operation is resumed upon reception of a * SIGTHAW signal. * * SYNOPSIS * * wd_keeper [timeout [nice_value]] * * timeout is the maximum time in seconds between consecutive * SIGUSR1 signals. Defaults to 60 seconds. * nice_value is passed to nice(2) to lower or (sooner) raise * the priority of the wd_keeper process. * * When the program has started, it prints an 'A' on stdout to * indicate the successful start of the hardware watchdog, and * otherwise an 'X' to indicate a failure. */#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <sys/types.h>#include <sys/mman.h>#include <fcntl.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <errno.h>/* #include <sys/vme.h> */#include "sys_vme.h" /* This file is really the sys/vme.h file if the FORCEvme package is installed on the system */#define WD_RESET_INTERVAL 400 /* 400 msec (the HW watchdog requires a pat at least every 830 ms, and we want some margins) */extern int usleep(unsigned int useconds);int main(int argc, char **argv);void pet_dog(int vme);void arm_wd(int sig);void disarm_wd(int sig);void pet_wd_wd(int sig);/* Make these two volatile sig_atomic_t, thereby avoiding aggressive optimizations, as they will be modified from within the interrupt handler. It might be even better to have a special variable indicating that wd_wd_pet has been called, and only change wd_count from within the main loop. */volatile sig_atomic_t wd_disarmed = 0; /* Armed */volatile sig_atomic_t wd_count;int wd_count_startval;intmain(int argc, char **argv){ int vme, res; unsigned int timeout = 0; if (argc >= 2) { timeout = (unsigned int)atoi(argv[1]); } if (!timeout) { timeout = 60; /* Default */ } wd_count_startval = (int)((1000 * timeout) / WD_RESET_INTERVAL); wd_count = wd_count_startval; if (sigset(SIGFREEZE, disarm_wd) != 0) { fprintf(stderr, "Error installing interrupt handler for SIGFREEZE: %d\n", errno); printf("X"); fflush(stdout); return 1; } if (sigset(SIGTHAW, arm_wd) != 0) { fprintf(stderr, "Error installing interrupt handler for SIGTHAW: %d\n", errno); printf("X"); fflush(stdout); return 1; } if (sigset(SIGUSR1, pet_wd_wd) != 0) { fprintf(stderr, "Error installing interrupt handler for SIGUSR1: %d\n", errno); printf("X"); fflush(stdout); return 1; } if (argc >= 3) { int niceval = atoi(argv[2]); if (niceval) { if ((res = nice(niceval)) == -1) { perror("Error setting process priority"); printf("X"); fflush(stdout); return 1; } } } if ((vme=open("/dev/vme32d32", O_RDWR)) < 0) { perror("Error opening /dev/vme32d32"); printf("X"); fflush(stdout); return 1; } /* fprintf(stderr, "HW watchdog started (about to send ACK)\n"); */ printf("A"); /* Indicate everything is OK */ fflush(stdout); /* Watchdog is armed by petting it once */ while ((wd_count > 0) || wd_disarmed) { pet_dog(vme); usleep(WD_RESET_INTERVAL*1000); if (!wd_disarmed) wd_count--; } /* When we get here, reboot is just a few seconds away */ fprintf(stderr, "Watchdog timeout.\r\nSystem is about to be rebooted\r\n"); return 1;} voidpet_dog(int vme){ struct vme_ioctl vmeioctl; vmeioctl.reg_no = VME_A32MAP_REG; ioctl(vme, VME_GET_REG, &vmeioctl); /* * now (re-)enable watchdog timer (can not be disabled) * must be retriggered in a 600ms intervall or it will cause a NMI * at least then it must be retriggered or it will cause * a RESET after ... ms */ vmeioctl.reg_data |= VME_WATCHDOG_ENA; ioctl(vme, VME_SET_REG, &vmeioctl);}/* NOTE: We'll have to manage w/o the fprintf()s, as I/O isn't allowed in signal handlers. Actually, it would probably work, especially of we used write(2) instead, but... */voidarm_wd(int sig){ /* fprintf(stderr, "Hardware watchdog armed.\r\n"); */ wd_disarmed = 0; wd_count = wd_count_startval;}voiddisarm_wd(int sig){ /* fprintf(stderr, "Hardware watchdog disarmed.\r\n"); */ wd_disarmed = 1;}voidpet_wd_wd(int sig){ wd_count = wd_count_startval;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?