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