iso9660fs fix
[minix3.git] / kernel / watchdog.c
blob69e72f159bf7d0378024eea213b2442142f5a473
1 /*
2 * This is arch independent NMI watchdog implementation part. It is used to
3 * detect kernel lockups and help debugging. each architecture must add its own
4 * low level code that triggers periodic checks
5 */
7 #include "watchdog.h"
8 #include "arch/i386/glo.h"
9 #include "profile.h"
11 unsigned watchdog_local_timer_ticks = 0U;
12 struct arch_watchdog *watchdog;
13 int watchdog_enabled;
15 static void lockup_check(struct nmi_frame * frame)
17 /* FIXME this should be CPU local */
18 static unsigned no_ticks;
19 static unsigned last_tick_count = (unsigned) -1;
22 * when debugging on serial console, printing takes a lot of time some
23 * times while the kernel is certainly not locked up. We don't want to
24 * report a lockup in such situation
26 if (serial_debug_active)
27 return;
29 if (last_tick_count != watchdog_local_timer_ticks) {
30 if (no_ticks == 1) {
31 printf("watchdog : kernel unlocked\n");
32 no_ticks = 0;
34 /* we are still ticking, everything seems good */
35 last_tick_count = watchdog_local_timer_ticks;
36 return;
40 * if watchdog_local_timer_ticks didn't changed since last time, give it
41 * some more time and only if it still dead, trigger the watchdog alarm
43 if (++no_ticks < 10) {
44 if (no_ticks == 1)
45 printf("WARNING watchdog : possible kernel lockup\n");
46 return;
49 /* if we get this far, the kernel is locked up */
50 arch_watchdog_lockup(frame);
53 void nmi_watchdog_handler(struct nmi_frame * frame)
55 #if SPROFILE
57 * Do not check for lockups while profiling, it is extremely likely that
58 * a false positive is detected if the frequency is high
60 if (watchdog_enabled && !sprofiling)
61 lockup_check(frame);
62 if (sprofiling)
63 nmi_sprofile_handler(frame);
65 if ((watchdog_enabled || sprofiling) && watchdog->reinit)
66 watchdog->reinit(cpuid);
67 #else
68 if (watchdog_enabled) {
69 lockup_check(frame);
70 if (watchdog->reinit)
71 watchdog->reinit(cpuid);
73 #endif
76 int nmi_watchdog_start_profiling(const unsigned freq)
78 int err;
80 /* if watchdog hasn't been enabled, we must enable it now */
81 if (!watchdog_enabled) {
82 if (arch_watchdog_init())
83 return ENODEV;
86 if (!watchdog->profile_init) {
87 printf("WARNING NMI watchdog profiling not supported\n");
88 nmi_watchdog_stop_profiling();
89 return ENODEV;
92 err = watchdog->profile_init(freq);
93 if (err != OK)
94 return err;
96 watchdog->resetval = watchdog->profile_resetval;
98 return OK;
101 void nmi_watchdog_stop_profiling(void)
104 * if we do not rearm the NMI source, we are done, if we want to keep
105 * the watchdog running, we reset is to its normal value
108 if (watchdog)
109 watchdog->resetval = watchdog->watchdog_resetval;
111 if (!watchdog_enabled)
112 arch_watchdog_stop();