1d9f0492fSopenharmony_ci/* 2d9f0492fSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License. 5d9f0492fSopenharmony_ci * You may obtain a copy of the License at 6d9f0492fSopenharmony_ci * 7d9f0492fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8d9f0492fSopenharmony_ci * 9d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and 13d9f0492fSopenharmony_ci * limitations under the License. 14d9f0492fSopenharmony_ci */ 15d9f0492fSopenharmony_ci 16d9f0492fSopenharmony_ci#include <errno.h> 17d9f0492fSopenharmony_ci#include <fcntl.h> 18d9f0492fSopenharmony_ci#include <stdlib.h> 19d9f0492fSopenharmony_ci#include <sys/ioctl.h> 20d9f0492fSopenharmony_ci#include <sys/resource.h> 21d9f0492fSopenharmony_ci#include <sys/stat.h> 22d9f0492fSopenharmony_ci#include <unistd.h> 23d9f0492fSopenharmony_ci 24d9f0492fSopenharmony_ci#ifdef LINUX_WATCHDOG 25d9f0492fSopenharmony_ci#include <linux/watchdog.h> 26d9f0492fSopenharmony_ci#else 27d9f0492fSopenharmony_ci#include <linux/types.h> 28d9f0492fSopenharmony_ci#define WDIOC_KEEPALIVE _IO('W', 5) 29d9f0492fSopenharmony_ci#define WDIOC_SETTIMEOUT _IOWR('W', 6, int) 30d9f0492fSopenharmony_ci#define WDIOC_GETTIMEOUT _IOR('W', 7, int) 31d9f0492fSopenharmony_ci#endif 32d9f0492fSopenharmony_ci 33d9f0492fSopenharmony_ci#include "init_log.h" 34d9f0492fSopenharmony_ci 35d9f0492fSopenharmony_ci#define WAIT_MAX_COUNT 20 36d9f0492fSopenharmony_ci#define DEFAULT_INTERVAL 3 37d9f0492fSopenharmony_ci#define DEFAULT_GAP 3 38d9f0492fSopenharmony_ci#define CONVERSION_BASE 1000000U 39d9f0492fSopenharmony_ci 40d9f0492fSopenharmony_ci#define PRETIMEOUT_GAP 5 41d9f0492fSopenharmony_ci#define PRETIMEOUT_DIV 2 42d9f0492fSopenharmony_ci 43d9f0492fSopenharmony_cistatic void WaitAtStartup(const char *source) 44d9f0492fSopenharmony_ci{ 45d9f0492fSopenharmony_ci unsigned int count = 0; 46d9f0492fSopenharmony_ci struct stat sourceInfo; 47d9f0492fSopenharmony_ci const unsigned int waitTime = 500000; 48d9f0492fSopenharmony_ci do { 49d9f0492fSopenharmony_ci usleep(waitTime); 50d9f0492fSopenharmony_ci count++; 51d9f0492fSopenharmony_ci } while ((stat(source, &sourceInfo) < 0) && (errno == ENOENT) && (count < WAIT_MAX_COUNT)); 52d9f0492fSopenharmony_ci if (count == WAIT_MAX_COUNT) { 53d9f0492fSopenharmony_ci INIT_LOGE("wait for file:%s failed after %u seconds.", source, (WAIT_MAX_COUNT * waitTime) / CONVERSION_BASE); 54d9f0492fSopenharmony_ci } 55d9f0492fSopenharmony_ci return; 56d9f0492fSopenharmony_ci} 57d9f0492fSopenharmony_ci 58d9f0492fSopenharmony_ci#ifdef WDIOC_SETPRETIMEOUT 59d9f0492fSopenharmony_ciint GetWatcherDogCfg(int interval, int timeoutGet, int fd) 60d9f0492fSopenharmony_ci{ 61d9f0492fSopenharmony_ci int preTimeout = 0; 62d9f0492fSopenharmony_ci int preTimeoutGet = 0; 63d9f0492fSopenharmony_ci preTimeout = timeoutGet - PRETIMEOUT_GAP; // ensure pretimeout smaller then timeout 64d9f0492fSopenharmony_ci if (preTimeout > 0) { 65d9f0492fSopenharmony_ci int ret = ioctl(fd, WDIOC_SETPRETIMEOUT, &preTimeout); 66d9f0492fSopenharmony_ci if (ret) { 67d9f0492fSopenharmony_ci INIT_LOGE("Failed to set pretimeout to %d\n", preTimeout); 68d9f0492fSopenharmony_ci } 69d9f0492fSopenharmony_ci ret = ioctl(fd, WDIOC_GETPRETIMEOUT, &preTimeoutGet); 70d9f0492fSopenharmony_ci if (ret) { 71d9f0492fSopenharmony_ci INIT_LOGE("Failed to get pretimeout\n"); 72d9f0492fSopenharmony_ci } 73d9f0492fSopenharmony_ci } 74d9f0492fSopenharmony_ci 75d9f0492fSopenharmony_ci if (preTimeoutGet > 0 && preTimeoutGet < interval) { 76d9f0492fSopenharmony_ci interval = preTimeoutGet / PRETIMEOUT_DIV; 77d9f0492fSopenharmony_ci } 78d9f0492fSopenharmony_ci return interval; 79d9f0492fSopenharmony_ci} 80d9f0492fSopenharmony_ci#endif 81d9f0492fSopenharmony_ci 82d9f0492fSopenharmony_ciint main(int argc, const char *argv[]) 83d9f0492fSopenharmony_ci{ 84d9f0492fSopenharmony_ci EnableInitLog(INIT_INFO); 85d9f0492fSopenharmony_ci WaitAtStartup("/dev/watchdog"); 86d9f0492fSopenharmony_ci int fd = open("/dev/watchdog", O_RDWR); 87d9f0492fSopenharmony_ci if (fd == -1) { 88d9f0492fSopenharmony_ci INIT_LOGE("Can't open /dev/watchdog."); 89d9f0492fSopenharmony_ci return 1; 90d9f0492fSopenharmony_ci } 91d9f0492fSopenharmony_ci 92d9f0492fSopenharmony_ci int interval = 0; 93d9f0492fSopenharmony_ci if (argc >= 2) { // Argument nums greater than or equal to 2. 94d9f0492fSopenharmony_ci interval = atoi(argv[1]); 95d9f0492fSopenharmony_ci if (interval < 0 || interval > INT16_MAX) { 96d9f0492fSopenharmony_ci interval = DEFAULT_INTERVAL; 97d9f0492fSopenharmony_ci } 98d9f0492fSopenharmony_ci } 99d9f0492fSopenharmony_ci interval = (interval > 0) ? interval : DEFAULT_INTERVAL; 100d9f0492fSopenharmony_ci 101d9f0492fSopenharmony_ci int gap = 0; 102d9f0492fSopenharmony_ci if (argc >= 3) { // Argument nums greater than or equal to 3. 103d9f0492fSopenharmony_ci gap = atoi(argv[2]); // 2 second parameter. 104d9f0492fSopenharmony_ci } 105d9f0492fSopenharmony_ci gap = (gap > 0) ? gap : DEFAULT_GAP; 106d9f0492fSopenharmony_ci 107d9f0492fSopenharmony_ci INIT_LOGI("Watchdog started (interval %d, margin %d), fd = %d\n", interval, gap, fd); 108d9f0492fSopenharmony_ci#ifdef OHOS_LITE_WATCHDOG 109d9f0492fSopenharmony_ci#ifndef LINUX_WATCHDOG 110d9f0492fSopenharmony_ci if (setpriority(PRIO_PROCESS, 0, 14) != 0) { // 14 is process priority 111d9f0492fSopenharmony_ci INIT_LOGE("setpriority failed err=%d\n", errno); 112d9f0492fSopenharmony_ci } 113d9f0492fSopenharmony_ci#endif 114d9f0492fSopenharmony_ci#endif 115d9f0492fSopenharmony_ci int timeoutSet = interval + gap; 116d9f0492fSopenharmony_ci int timeoutGet = 0; 117d9f0492fSopenharmony_ci 118d9f0492fSopenharmony_ci int ret = ioctl(fd, WDIOC_SETTIMEOUT, &timeoutSet); 119d9f0492fSopenharmony_ci if (ret) { 120d9f0492fSopenharmony_ci INIT_LOGE("Failed to set timeout to %d\n", timeoutSet); 121d9f0492fSopenharmony_ci } 122d9f0492fSopenharmony_ci ret = ioctl(fd, WDIOC_GETTIMEOUT, &timeoutGet); 123d9f0492fSopenharmony_ci if (ret) { 124d9f0492fSopenharmony_ci INIT_LOGE("Failed to get timeout\n"); 125d9f0492fSopenharmony_ci } 126d9f0492fSopenharmony_ci 127d9f0492fSopenharmony_ci if (timeoutGet > 0) { 128d9f0492fSopenharmony_ci interval = (timeoutGet > gap) ? (timeoutGet - gap) : 1; 129d9f0492fSopenharmony_ci } 130d9f0492fSopenharmony_ci 131d9f0492fSopenharmony_ci#ifdef WDIOC_SETPRETIMEOUT 132d9f0492fSopenharmony_ci interval = GetWatcherDogCfg(interval, timeoutGet, fd); 133d9f0492fSopenharmony_ci#endif 134d9f0492fSopenharmony_ci 135d9f0492fSopenharmony_ci while (1) { 136d9f0492fSopenharmony_ci ioctl(fd, WDIOC_KEEPALIVE); 137d9f0492fSopenharmony_ci sleep(interval); 138d9f0492fSopenharmony_ci } 139d9f0492fSopenharmony_ci close(fd); 140d9f0492fSopenharmony_ci return -1; 141d9f0492fSopenharmony_ci} 142