device_google_gs-common/gs_watchdogd/gs_watchdogd.cpp
Woody Lin 0dd653e624 gs_watchdogd: Use timeout defined by platform
Uses timeout value of watchdog device directly, without modifying it
with ioctl. On some platforms, especially these with multiple watchdog
devices, the timeout values can be strictly defined for the watchdogs to
timeout in a certain order. Leaves timeout value as it is and divides
minimal of them by 2 as watchdog kicking period.

Flag: EXEMPT normal/day-to-day bugfix
Bug: 348318712
Change-Id: Icdcce368f1803cd3b38a48f05e2788d881e3ad6f
2024-06-24 11:45:43 +08:00

101 lines
2.8 KiB
C++

/*
* Copyright (C) 2022 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 <android-base/chrono_utils.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
#include <log/log.h>
#include <fcntl.h>
#include <glob.h>
#include <linux/watchdog.h>
#include <stdlib.h>
#include <string.h>
#include <sys/cdefs.h>
#include <unistd.h>
#include <cstdlib>
#include <vector>
#define NSEC_PER_SEC (1000LL * 1000LL * 1000LL)
#define DEV_GLOB "/sys/devices/platform/*.watchdog_cl*/watchdog/watchdog*"
using android::base::Basename;
using android::base::StringPrintf;
int main(int __unused argc, char** argv) {
auto min_timeout_nsecs = std::numeric_limits<typeof(NSEC_PER_SEC)>::max();
android::base::InitLogging(argv, &android::base::KernelLogger);
glob_t globbuf;
int ret = glob(DEV_GLOB, GLOB_MARK, nullptr, &globbuf);
if (ret) {
PLOG(ERROR) << "Failed to lookup glob " << DEV_GLOB << ": " << ret;
return 1;
}
std::vector<android::base::unique_fd> wdt_dev_fds;
for (size_t i = 0; i < globbuf.gl_pathc; i++) {
int timeout_secs;
std::string dev_path = StringPrintf("/dev/%s", Basename(globbuf.gl_pathv[i]).c_str());
int fd = TEMP_FAILURE_RETRY(open(dev_path.c_str(), O_RDWR | O_CLOEXEC));
if (fd == -1) {
PLOG(ERROR) << "Failed to open " << dev_path;
return 1;
}
ret = ioctl(fd, WDIOC_GETTIMEOUT, &timeout_secs);
if (ret) {
PLOG(ERROR) << "Failed to get timeout on " << dev_path;
continue;
} else {
min_timeout_nsecs = std::min(min_timeout_nsecs, NSEC_PER_SEC * timeout_secs);
}
wdt_dev_fds.emplace_back(fd);
}
globfree(&globbuf);
if (wdt_dev_fds.empty()) {
LOG(ERROR) << "no valid wdt dev found";
return 1;
}
timespec ts;
auto result = div(min_timeout_nsecs / 2, NSEC_PER_SEC);
ts.tv_sec = result.quot;
ts.tv_nsec = result.rem;
while (true) {
timespec rem = ts;
for (const auto& fd : wdt_dev_fds) {
TEMP_FAILURE_RETRY(write(fd, "", 1));
}
if (TEMP_FAILURE_RETRY(nanosleep(&rem, &rem))) {
PLOG(ERROR) << "nanosleep failed";
return 1;
}
}
}