diff --git a/init/Android.mk b/init/Android.mk index 7dae9df89..a1c1e7ae2 100644 --- a/init/Android.mk +++ b/init/Android.mk @@ -15,7 +15,8 @@ LOCAL_SRC_FILES:= \ signal_handler.c \ init_parser.c \ ueventd.c \ - ueventd_parser.c + ueventd_parser.c \ + watchdogd.c ifeq ($(strip $(INIT_BOOTCHART)),true) LOCAL_SRC_FILES += bootchart.c @@ -42,8 +43,11 @@ endif include $(BUILD_EXECUTABLE) -# Make a symlink from /sbin/ueventd to /init -SYMLINKS := $(TARGET_ROOT_OUT)/sbin/ueventd +# Make a symlink from /sbin/ueventd and /sbin/watchdogd to /init +SYMLINKS := \ + $(TARGET_ROOT_OUT)/sbin/ueventd \ + $(TARGET_ROOT_OUT)/sbin/watchdogd + $(SYMLINKS): INIT_BINARY := $(LOCAL_MODULE) $(SYMLINKS): $(LOCAL_INSTALLED_MODULE) $(LOCAL_PATH)/Android.mk @echo "Symlink: $@ -> ../$(INIT_BINARY)" diff --git a/init/init.c b/init/init.c index 4f5714437..48d9c9ae6 100755 --- a/init/init.c +++ b/init/init.c @@ -58,6 +58,7 @@ #include "init_parser.h" #include "util.h" #include "ueventd.h" +#include "watchdogd.h" #ifdef HAVE_SELINUX struct selabel_handle *sehandle; @@ -863,6 +864,9 @@ int main(int argc, char **argv) if (!strcmp(basename(argv[0]), "ueventd")) return ueventd_main(argc, argv); + if (!strcmp(basename(argv[0]), "watchdogd")) + return watchdogd_main(argc, argv); + /* clear the umask */ umask(0); diff --git a/init/watchdogd.c b/init/watchdogd.c new file mode 100644 index 000000000..fb53836e2 --- /dev/null +++ b/init/watchdogd.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include + +#include "log.h" +#include "util.h" + +#define DEV_NAME "/dev/watchdog" + +int watchdogd_main(int argc, char **argv) +{ + int fd; + int ret; + int interval = 10; + int margin = 10; + int timeout; + + open_devnull_stdio(); + klog_init(); + + INFO("Starting watchdogd\n"); + + if (argc >= 2) + interval = atoi(argv[1]); + + if (argc >= 3) + margin = atoi(argv[2]); + + timeout = interval + margin; + + fd = open(DEV_NAME, O_RDWR); + if (fd < 0) { + ERROR("watchdogd: Failed to open %s: %s\n", DEV_NAME, strerror(errno)); + return 1; + } + + ret = ioctl(fd, WDIOC_SETTIMEOUT, &timeout); + if (ret) { + ERROR("watchdogd: Failed to set timeout to %d: %s\n", timeout, strerror(errno)); + ret = ioctl(fd, WDIOC_GETTIMEOUT, &timeout); + if (ret) { + ERROR("watchdogd: Failed to get timeout: %s\n", strerror(errno)); + } else { + if (timeout > margin) + interval = timeout - margin; + else + interval = 1; + ERROR("watchdogd: Adjusted interval to timeout returned by driver: timeout %d, interval %d, margin %d\n", + timeout, interval, margin); + } + } + + while(1) { + write(fd, "", 1); + sleep(interval); + } +} + diff --git a/init/watchdogd.h b/init/watchdogd.h new file mode 100644 index 000000000..8b48ab86b --- /dev/null +++ b/init/watchdogd.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _INIT_WATCHDOGD_H_ +#define _INIT_WATCHDOGD_H_ + +int watchdogd_main(int argc, char **argv); + +#endif