Updated authors information.
[profile/ivi/dlt-daemon.git] / src / system / dlt-system-watchdog.c
1 /**
2  * @licence app begin@
3  * Copyright (C) 2012-2014  BMW AG
4  *
5  * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
6  *
7  * Contributions are licensed to the GENIVI Alliance under one or more
8  * Contribution License Agreements.
9  *
10  * \copyright
11  * This Source Code Form is subject to the terms of the
12  * Mozilla Public License, v. 2.0. If a  copy of the MPL was not distributed with
13  * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
14  *
15  * \author
16  * Lassi Marttala <lassi.lm.marttala@partner.bmw.de>
17  * Alexander Wenzel <alexander.aw.wenzel@bmw.de>
18  * Markus Klein <Markus.Klein@esk.fraunhofer.de>
19  * Mikko Rapeli <mikko.rapeli@bmw.de>
20  *
21  * \file dlt-system-logfile.c
22  * For further information see http://www.genivi.org/.
23  * @licence end@
24  */
25
26 #if defined(DLT_SYSTEMD_WATCHDOG_ENABLE)
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <pthread.h>
30 #include <sys/timerfd.h>
31 #include "dlt.h"
32 #include "dlt-system.h"
33
34 #include "sd-daemon.h"
35
36
37 DLT_DECLARE_CONTEXT(watchdogContext)
38 DLT_IMPORT_CONTEXT(dltsystem)
39
40 extern DltSystemThreads threads;
41
42 typedef struct
43 {
44     int timer_fd;
45     unsigned long long wakeups_missed;
46 } PeriodicData;
47
48 void wait_period (PeriodicData *info)
49 {
50     unsigned long long missed;
51
52     if(read (info->timer_fd, &missed, sizeof (missed)) < 0)
53     {
54         DLT_LOG(watchdogContext, DLT_LOG_ERROR,
55                 DLT_STRING("Could not read from timer file descriptor in watchdog.\n"));
56     }
57
58     if (missed > 0)
59     {
60         info->wakeups_missed += (missed - 1);
61     }
62 }
63
64 int make_periodic(unsigned int period, PeriodicData *info)
65 {
66     unsigned int ns;
67     unsigned int sec;
68     int fd;
69     struct itimerspec itval;
70
71     if (info==0)
72     {
73         DLT_LOG(watchdogContext, DLT_LOG_ERROR,
74                                                 DLT_STRING("Invalid function parameters used for function make_periodic.\n"));
75         return -1;
76     }
77
78     /* Create the timer */
79     fd = timerfd_create (CLOCK_MONOTONIC, 0);
80
81     info->wakeups_missed = 0;
82     info->timer_fd = fd;
83
84     if (fd == -1)
85     {
86         DLT_LOG(watchdogContext, DLT_LOG_ERROR,
87                                                 DLT_STRING("Can't create timer filedescriptor.\n"));
88         return -1;
89     }
90
91     /* Make the timer periodic */
92     sec = period/1000000;
93     ns = (period - (sec * 1000000)) * 1000;
94     itval.it_interval.tv_sec = sec;
95     itval.it_interval.tv_nsec = ns;
96     itval.it_value.tv_sec = sec;
97     itval.it_value.tv_nsec = ns;
98
99     return timerfd_settime (fd, 0, &itval, NULL);
100 }
101
102
103 void watchdog_thread(void *v_conf)
104 {
105         char str[512];
106         char *watchdogUSec;
107         unsigned int watchdogTimeoutSeconds;
108         unsigned int notifiyPeriodNSec;
109         PeriodicData info;
110
111         DLT_REGISTER_CONTEXT(watchdogContext, "DOG","dlt system watchdog context.");
112
113         sleep(1);
114
115         DLT_LOG(watchdogContext, DLT_LOG_INFO,DLT_STRING("Watchdog thread started.\n"));
116
117         if (v_conf==0)
118         {
119                 DLT_LOG(watchdogContext, DLT_LOG_ERROR,
120                                         DLT_STRING("Invalid function parameters used for function watchdog_thread.\n"));
121                 return;
122         }
123
124
125         watchdogUSec = getenv("WATCHDOG_USEC");
126
127         if(watchdogUSec)
128         {
129                 DLT_LOG(watchdogContext, DLT_LOG_DEBUG,DLT_STRING("watchdogusec: "),DLT_STRING(watchdogUSec));
130
131                 watchdogTimeoutSeconds = atoi(watchdogUSec);
132
133                 if( watchdogTimeoutSeconds > 0 ){
134
135                         // Calculate half of WATCHDOG_USEC in ns for timer tick
136                         notifiyPeriodNSec = watchdogTimeoutSeconds / 2 ;
137
138                         sprintf(str,"systemd watchdog timeout: %u nsec - timer will be initialized: %u nsec\n", watchdogTimeoutSeconds, notifiyPeriodNSec );
139                         DLT_LOG(watchdogContext, DLT_LOG_DEBUG,DLT_STRING(str));
140
141                         if (make_periodic (notifiyPeriodNSec, &info) < 0 )
142                         {
143                                 DLT_LOG(watchdogContext, DLT_LOG_ERROR,DLT_STRING("Could not initialize systemd watchdog timer\n"));
144                                 return;
145                         }
146
147                         while (1)
148                         {
149                                 if(sd_notify(0, "WATCHDOG=1") < 0)
150                                 {
151                                         DLT_LOG(watchdogContext, DLT_LOG_ERROR,DLT_STRING("Could not reset systemd watchdog\n"));
152                                 }
153
154                                 DLT_LOG(watchdogContext, DLT_LOG_DEBUG,DLT_STRING("systemd watchdog waited periodic\n"));
155
156                                 /* Wait for next period */
157                                 wait_period(&info);
158                         }
159                 }
160                 else
161                 {
162                         sprintf(str,"systemd watchdog timeout incorrect: %u\n", watchdogTimeoutSeconds);
163                         DLT_LOG(watchdogContext, DLT_LOG_DEBUG,DLT_STRING(str));
164                 }
165         }
166         else
167         {
168                 DLT_LOG(watchdogContext, DLT_LOG_ERROR,DLT_STRING("systemd watchdog timeout (WATCHDOG_USEC) is null\n"));
169         }
170
171 }
172
173 void start_systemd_watchdog(DltSystemConfiguration *conf)
174 {
175         DLT_LOG(dltsystem, DLT_LOG_DEBUG,DLT_STRING("Creating thread for systemd watchdog\n"));
176
177         static pthread_attr_t t_attr;
178         static pthread_t pt;
179
180         if (pthread_create(&pt, &t_attr, (void *)watchdog_thread, conf) == 0)
181         {
182                 threads.threads[threads.count++] = pt;
183         }
184         else
185         {
186                 DLT_LOG(dltsystem, DLT_LOG_ERROR,DLT_STRING("Could not create thread for systemd watchdog\n"));
187         }
188 }
189 #endif