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