/* * @licence app begin@ * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of GENIVI Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.genivi.org/. * @licence end@ */ /*! * \author * Lassi Marttala * Alexander Wenzel * Markus Klein * Mikko Rapeli * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-system-watchdog.c */ #if defined(DLT_SYSTEMD_WATCHDOG_ENABLE) #include #include #include #include #include "dlt.h" #include "dlt-system.h" #include "sd-daemon.h" DLT_DECLARE_CONTEXT(watchdogContext) DLT_IMPORT_CONTEXT(dltsystem) extern DltSystemThreads threads; typedef struct { int timer_fd; unsigned long long wakeups_missed; } PeriodicData; void wait_period (PeriodicData *info) { unsigned long long missed; if (read (info->timer_fd, &missed, sizeof (missed)) < 0) DLT_LOG(watchdogContext, DLT_LOG_ERROR, DLT_STRING("Could not read from timer file descriptor in watchdog.\n")); if (missed > 0) info->wakeups_missed += (missed - 1); } int make_periodic(unsigned int period, PeriodicData *info) { unsigned int ns; unsigned int sec; int fd; struct itimerspec itval; if (info == 0) { DLT_LOG(watchdogContext, DLT_LOG_ERROR, DLT_STRING("Invalid function parameters used for function make_periodic.\n")); return -1; } /* Create the timer */ fd = timerfd_create (CLOCK_MONOTONIC, 0); info->wakeups_missed = 0; info->timer_fd = fd; if (fd == -1) { DLT_LOG(watchdogContext, DLT_LOG_ERROR, DLT_STRING("Can't create timer filedescriptor.\n")); return -1; } /* Make the timer periodic */ sec = period / 1000000; ns = (period - (sec * 1000000)) * 1000; itval.it_interval.tv_sec = sec; itval.it_interval.tv_nsec = ns; itval.it_value.tv_sec = sec; itval.it_value.tv_nsec = ns; return timerfd_settime (fd, 0, &itval, NULL); } void watchdog_thread(void *v_conf) { char str[512]; char *watchdogUSec; unsigned int watchdogTimeoutSeconds; unsigned int notifiyPeriodNSec; PeriodicData info; DLT_REGISTER_CONTEXT(watchdogContext, "DOG", "dlt system watchdog context."); sleep(1); DLT_LOG(watchdogContext, DLT_LOG_INFO, DLT_STRING("Watchdog thread started.\n")); if (v_conf == 0) { DLT_LOG(watchdogContext, DLT_LOG_ERROR, DLT_STRING("Invalid function parameters used for function watchdog_thread.\n")); return; } watchdogUSec = getenv("WATCHDOG_USEC"); if (watchdogUSec) { DLT_LOG(watchdogContext, DLT_LOG_DEBUG, DLT_STRING("watchdogusec: "), DLT_STRING(watchdogUSec)); watchdogTimeoutSeconds = atoi(watchdogUSec); if (watchdogTimeoutSeconds > 0) { /* Calculate half of WATCHDOG_USEC in ns for timer tick */ notifiyPeriodNSec = watchdogTimeoutSeconds / 2; snprintf(str, 512, "systemd watchdog timeout: %u nsec - timer will be initialized: %u nsec\n", watchdogTimeoutSeconds, notifiyPeriodNSec); DLT_LOG(watchdogContext, DLT_LOG_DEBUG, DLT_STRING(str)); if (make_periodic (notifiyPeriodNSec, &info) < 0) { DLT_LOG(watchdogContext, DLT_LOG_ERROR, DLT_STRING("Could not initialize systemd watchdog timer\n")); return; } while (1) { if (sd_notify(0, "WATCHDOG=1") < 0) DLT_LOG(watchdogContext, DLT_LOG_ERROR, DLT_STRING("Could not reset systemd watchdog\n")); DLT_LOG(watchdogContext, DLT_LOG_DEBUG, DLT_STRING("systemd watchdog waited periodic\n")); /* Wait for next period */ wait_period(&info); } } else { snprintf(str, 512, "systemd watchdog timeout incorrect: %u\n", watchdogTimeoutSeconds); DLT_LOG(watchdogContext, DLT_LOG_DEBUG, DLT_STRING(str)); } } else { DLT_LOG(watchdogContext, DLT_LOG_ERROR, DLT_STRING("systemd watchdog timeout (WATCHDOG_USEC) is null\n")); } } void start_systemd_watchdog(DltSystemConfiguration *conf) { DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("Creating thread for systemd watchdog\n")); static pthread_attr_t t_attr; static pthread_t pt; if (pthread_create(&pt, &t_attr, (void *)watchdog_thread, conf) == 0) threads.threads[threads.count++] = pt; else DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("Could not create thread for systemd watchdog\n")); } #endif