| /**************************************************************************** |
| * apps/examples/watcher/watcher_main.c |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. The |
| * ASF licenses this file to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance with the |
| * License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations |
| * under the License. |
| * |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Included Files |
| ****************************************************************************/ |
| |
| #include <nuttx/config.h> |
| #include <stdio.h> |
| #include <errno.h> |
| #include <stdlib.h> |
| #include <sched.h> |
| #include <fcntl.h> |
| #include <sys/ioctl.h> |
| #include "ramdisk.h" |
| #include "wdt.h" |
| #include "task_mn.h" |
| |
| /**************************************************************************** |
| * Pre-processor Definitions |
| ****************************************************************************/ |
| |
| #define SUBSCRIBE_CMD 1 |
| #define UNSUBSCRIBE_CMD -1 |
| #define FEED_CMD 2 |
| |
| /**************************************************************************** |
| * Private Data |
| ****************************************************************************/ |
| |
| static const char g_info_file_name[] = "/mnt/watcher/info.txt"; |
| |
| /**************************************************************************** |
| * Private Functions |
| ****************************************************************************/ |
| |
| static void feed_sighandler(int signo, FAR siginfo_t * siginfo, |
| FAR void *context) |
| { |
| struct task_node_s *node; |
| request = *(struct request_s *)siginfo->si_value.sival_ptr; |
| |
| switch (request.code) |
| { |
| case FEED_CMD: |
| |
| /* Update the current requester task status */ |
| |
| node = task_mn_is_task_subscribed(request.task_id); |
| if (node != NULL) |
| { |
| node->reset = true; |
| } |
| else |
| { |
| fprintf(stderr, |
| "watcher daemon: task is not subscribed to feed dog.\n"); |
| } |
| |
| /* Verify if all tasks requested to feed the dog */ |
| |
| if (task_mn_all_tasks_fed()) |
| { |
| /* If all tasks required, reset it and reset all tasks' status" */ |
| |
| wdt_feed_the_dog(); |
| task_mn_reset_all(); |
| } |
| |
| break; |
| case SUBSCRIBE_CMD: |
| |
| /* Include the current requester task to the watched tasks list */ |
| |
| task_mn_subscribe(request.task_id); |
| break; |
| case UNSUBSCRIBE_CMD: |
| |
| /* Excludes the current requester task from the watched tasks list */ |
| |
| task_mn_unsubscribe(request.task_id); |
| |
| /* Verify if all tasks has already requested to feed the dog in this |
| * round. Because maybe the watcher was only expecting the task that |
| * was unsubscribed to finally reset the dog. |
| * If this task is no longer being watched and the others have already |
| * sent a feed request, so it's time to feed the dog. |
| */ |
| |
| if (task_mn_all_tasks_fed()) |
| { |
| /* If all tasks required, reset it and reset all tasks' status" */ |
| |
| wdt_feed_the_dog(); |
| task_mn_reset_all(); |
| } |
| break; |
| default: |
| fprintf(stderr, "watcher daemon: Invalid command\n"); |
| } |
| } |
| |
| static void wdt_log(int signo, FAR siginfo_t * siginfo, |
| FAR void *context) |
| { |
| if (watched_tasks.head != NULL) |
| { |
| printf("*** Printing Tasks Status ***\n"); |
| task_mn_print_tasks_status(); |
| task_mn_reset_all(); |
| } |
| } |
| |
| /**************************************************************************** |
| * Name: watcher_daemon |
| ****************************************************************************/ |
| |
| static int watcher_daemon(int argc, FAR char *argv[]) |
| { |
| int ret; |
| struct sigaction act; |
| struct sigaction act_log; |
| pid_t watcher_pid; |
| FILE *fp; |
| |
| printf("Watcher Daemon has started!\n"); |
| |
| /* Initialize and configure the wdt */ |
| |
| wdt_init(); |
| |
| /* Configure signals action */ |
| |
| /* Configure signal to receive the subscribe/unsubscribe |
| * and feed requests |
| */ |
| |
| act.sa_sigaction = feed_sighandler; /* The handler to be triggered when |
| * receiving a signal */ |
| act.sa_flags = SA_SIGINFO; /* Invoke the signal-catching function */ |
| sigfillset(&act.sa_mask); |
| |
| /* Block all other signals less this one */ |
| |
| sigdelset(&act.sa_mask, CONFIG_EXAMPLES_WATCHER_SIGNAL); |
| |
| ret = sigaction(CONFIG_EXAMPLES_WATCHER_SIGNAL, &act, NULL); |
| if (ret != OK) |
| { |
| int errcode = errno; |
| fprintf(stderr, "ERROR: sigaction failed: %d\n", errcode); |
| ret = errcode; |
| goto errout; |
| } |
| |
| /* Configure signal to log the taks at wdt timeout */ |
| |
| act_log.sa_sigaction = wdt_log; /* The handler to be triggered when |
| * receiving a signal */ |
| act_log.sa_flags = SA_SIGINFO; /* Invoke the signal-catching function */ |
| sigfillset(&act_log.sa_mask); |
| |
| /* Block all other signals less this one */ |
| |
| sigdelset(&act_log.sa_mask, CONFIG_EXAMPLES_WATCHER_SIGNAL_LOG); |
| |
| ret = sigaction(CONFIG_EXAMPLES_WATCHER_SIGNAL_LOG, &act_log, NULL); |
| if (ret != OK) |
| { |
| int errcode = errno; |
| fprintf(stderr, "ERROR: sigaction failed: %d\n", errcode); |
| ret = errcode; |
| goto errout; |
| } |
| |
| /* Collecting the necessary information of the current task */ |
| |
| watcher_pid = getpid(); |
| |
| /* Writing PID, SIGNAL NUMBER, and COMMANDS' value to a file */ |
| |
| fp = fopen(g_info_file_name, "w+"); |
| if (fp == NULL) |
| { |
| int errcode = errno; |
| fprintf(stderr, "ERROR: Failed to open %s: %d\n", |
| g_info_file_name, errcode); |
| ret = errcode; |
| goto errout; |
| } |
| |
| fprintf(fp, "%d %d %d %d %d\n", watcher_pid, |
| CONFIG_EXAMPLES_WATCHER_SIGNAL, SUBSCRIBE_CMD, |
| FEED_CMD, UNSUBSCRIBE_CMD); |
| fclose(fp); |
| |
| /* Suspends the calling thread until delivery of a non-blocked signal. */ |
| |
| while (1) |
| { |
| pause(); |
| } |
| |
| errout: |
| return ret; |
| } |
| |
| /**************************************************************************** |
| * Public Functions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * watcher_main |
| ****************************************************************************/ |
| |
| int main(int argc, FAR char *argv[]) |
| { |
| int ret; |
| FILE *fp; |
| |
| /* Check if the watcher has already been initialized */ |
| |
| fp = fopen(g_info_file_name, "r"); |
| if (fp) |
| { |
| fclose(fp); |
| printf("Watcher is already running.\n"); |
| ret = EBUSY; |
| goto errout; |
| } |
| |
| /* Create a RAMDISK device, format it and mount it */ |
| |
| prepare_fs(); |
| |
| /* Start Daemon */ |
| |
| ret = task_create("watcher_daemon", CONFIG_EXAMPLES_WATCHER_PRIORITY, |
| CONFIG_EXAMPLES_WATCHER_STACKSIZE, watcher_daemon, NULL); |
| if (ret < 0) |
| { |
| int errcode = errno; |
| printf("watcher_main: ERROR: Failed to start watcher_daemon: %d\n", |
| errcode); |
| ret = errcode; |
| goto errout; |
| } |
| |
| errout: |
| return ret; |
| |
| return EXIT_SUCCESS; |
| } |