LCOV - code coverage report
Current view: top level - nnstreamer-2.4.2/gst/nnstreamer - nnstreamer_watchdog.c (source / functions) Coverage Total Hit
Test: nnstreamer 2.4.2-0 nnstreamer/nnstreamer#eca68b8d050408568af95d831a8eef62aaee7784 Lines: 84.5 % 84 71
Test Date: 2025-03-13 05:38:21 Functions: 100.0 % 6 6

            Line data    Source code
       1              : /* SPDX-License-Identifier: LGPL-2.1-only */
       2              : /**
       3              :  * NNStreamer watchdog
       4              :  * Copyright (C) 2024 Gichan Jang <gichan2.jang@samsung.com>
       5              :  */
       6              : /**
       7              :  * @file        nnstreamer_watchdog.c
       8              :  * @date        30 Oct 2024
       9              :  * @brief       NNStreamer watchdog to manage the schedule in the element.
      10              :  * @see         https://github.com/nnstreamer/nnstreamer
      11              :  * @author      Gichan Jang <gichan2.jang@samsung.com>
      12              :  * @bug         No known bugs except for NYI items
      13              :  */
      14              : 
      15              : #include <nnstreamer_log.h>
      16              : #include "nnstreamer_watchdog.h"
      17              : 
      18              : /**
      19              :  * @brief Structure for NNStreamer watchdog.
      20              :  */
      21              : typedef struct _NnstWatchdog
      22              : {
      23              :   GMainContext *context;
      24              :   GMainLoop *loop;
      25              :   GThread *thread;
      26              :   GSource *source;
      27              :   GMutex lock;
      28              :   GCond cond;
      29              : } NnstWatchdog;
      30              : 
      31              : /**
      32              :  * @brief Called when loop is running
      33              :  */
      34              : static gboolean
      35            5 : _loop_running_cb (NnstWatchdog * watchdog)
      36              : {
      37            5 :   g_mutex_lock (&watchdog->lock);
      38            5 :   g_cond_signal (&watchdog->cond);
      39            5 :   g_mutex_unlock (&watchdog->lock);
      40              : 
      41            5 :   return G_SOURCE_REMOVE;
      42              : }
      43              : 
      44              : /**
      45              :  * @brief Watchdog thread.
      46              :  */
      47              : static gpointer
      48            5 : _nnstreamer_watchdog_thread (gpointer ptr)
      49              : {
      50            5 :   NnstWatchdog *watchdog = (NnstWatchdog *) ptr;
      51              :   GSource *idle_source;
      52              : 
      53            5 :   g_main_context_push_thread_default (watchdog->context);
      54              : 
      55            5 :   idle_source = g_idle_source_new ();
      56            5 :   g_source_set_callback (idle_source,
      57              :       (GSourceFunc) _loop_running_cb, watchdog, NULL);
      58            5 :   g_source_attach (idle_source, watchdog->context);
      59            5 :   g_source_unref (idle_source);
      60              : 
      61            5 :   g_main_loop_run (watchdog->loop);
      62              : 
      63            5 :   g_main_context_pop_thread_default (watchdog->context);
      64              : 
      65            5 :   return NULL;
      66              : }
      67              : 
      68              : /**
      69              :  * @brief Create nnstreamer watchdog. Recommended using watchdog handle with proper lock (e.g., GST_OBJECT_LOCK())
      70              :  */
      71              : gboolean
      72            6 : nnstreamer_watchdog_create (nns_watchdog_h * watchdog_h)
      73              : {
      74              :   gint64 end_time;
      75            6 :   gboolean ret = TRUE;
      76            6 :   GError *error = NULL;
      77              :   NnstWatchdog *watchdog;
      78              : 
      79            6 :   if (!watchdog_h) {
      80            1 :     ml_loge ("Invalid parameter: watchdog handle is NULL.");
      81            6 :     return FALSE;
      82              :   }
      83              : 
      84            5 :   watchdog = g_try_new0 (NnstWatchdog, 1);
      85            5 :   if (!watchdog) {
      86            0 :     ml_loge ("Failed to allocate memory for watchdog.");
      87            0 :     return FALSE;
      88              :   }
      89              : 
      90            5 :   watchdog->context = g_main_context_new ();
      91            5 :   watchdog->loop = g_main_loop_new (watchdog->context, FALSE);
      92              : 
      93            5 :   g_mutex_init (&watchdog->lock);
      94            5 :   g_cond_init (&watchdog->cond);
      95            5 :   g_mutex_lock (&watchdog->lock);
      96            5 :   watchdog->thread =
      97            5 :       g_thread_try_new ("suspend_watchdog", _nnstreamer_watchdog_thread,
      98              :       watchdog, &error);
      99              : 
     100            5 :   if (!watchdog->thread) {
     101            0 :     ml_loge ("Failed to create watchdog thread: %s", error->message);
     102            0 :     g_clear_error (&error);
     103            0 :     ret = FALSE;
     104            0 :     goto done;
     105              :   }
     106              : 
     107            5 :   end_time = g_get_monotonic_time () + 5 * G_TIME_SPAN_SECOND;
     108           10 :   while (!g_main_loop_is_running (watchdog->loop)) {
     109            5 :     if (!g_cond_wait_until (&watchdog->cond, &watchdog->lock, end_time)) {
     110            0 :       ml_loge ("Failed to wait main loop running.");
     111            0 :       ret = FALSE;
     112            0 :       goto done;
     113              :     }
     114              :   }
     115              : 
     116            5 : done:
     117            5 :   g_mutex_unlock (&watchdog->lock);
     118            5 :   g_mutex_clear (&watchdog->lock);
     119            5 :   g_cond_clear (&watchdog->cond);
     120            5 :   if (!ret) {
     121            0 :     nnstreamer_watchdog_destroy (watchdog);
     122            0 :     watchdog = NULL;
     123              :   }
     124            5 :   *watchdog_h = watchdog;
     125              : 
     126            5 :   return ret;
     127              : }
     128              : 
     129              : /**
     130              :  * @brief Destroy watchdog source. Recommended using watchdog handle with proper lock (e.g., GST_OBJECT_LOCK())
     131              :  */
     132              : void
     133            6 : nnstreamer_watchdog_destroy (nns_watchdog_h watchdog_h)
     134              : {
     135            6 :   NnstWatchdog *watchdog = (NnstWatchdog *) watchdog_h;
     136            6 :   nnstreamer_watchdog_release (watchdog);
     137              : 
     138            6 :   if (watchdog && watchdog->context) {
     139            5 :     g_main_loop_quit (watchdog->loop);
     140            5 :     g_thread_join (watchdog->thread);
     141            5 :     watchdog->thread = NULL;
     142              : 
     143            5 :     g_main_loop_unref (watchdog->loop);
     144            5 :     watchdog->loop = NULL;
     145              : 
     146            5 :     g_main_context_unref (watchdog->context);
     147            5 :     watchdog->context = NULL;
     148              : 
     149            5 :     g_free (watchdog_h);
     150              :   }
     151            6 : }
     152              : 
     153              : /**
     154              :  * @brief Release watchdog source. Recommended using watchdog handle with proper lock (e.g., GST_OBJECT_LOCK())
     155              :  */
     156              : void
     157            8 : nnstreamer_watchdog_release (nns_watchdog_h watchdog_h)
     158              : {
     159            8 :   NnstWatchdog *watchdog = (NnstWatchdog *) watchdog_h;
     160            8 :   if (watchdog && watchdog->source) {
     161            4 :     g_source_destroy (watchdog->source);
     162            4 :     g_source_unref (watchdog->source);
     163            4 :     watchdog->source = NULL;
     164              :   }
     165            8 : }
     166              : 
     167              : /**
     168              :  * @brief Set watchdog timeout. Recommended using watchdog handle with proper lock (e.g., GST_OBJECT_LOCK())
     169              :  */
     170              : gboolean
     171            6 : nnstreamer_watchdog_feed (nns_watchdog_h watchdog_h, GSourceFunc func,
     172              :     guint interval, void *user_data)
     173              : {
     174            6 :   NnstWatchdog *watchdog = (NnstWatchdog *) watchdog_h;
     175              : 
     176            6 :   if (!watchdog || !func) {
     177            2 :     ml_loge ("Invalid parameter: watchdog handle or func is NULL.");
     178            2 :     return FALSE;
     179              :   }
     180              : 
     181            4 :   if (watchdog->context) {
     182            4 :     watchdog->source = g_timeout_source_new (interval);
     183            4 :     g_source_set_callback (watchdog->source, func, user_data, NULL);
     184            4 :     g_source_attach (watchdog->source, watchdog->context);
     185              :   } else {
     186            0 :     ml_loge
     187              :         ("Failed to feed to watchdog. Watchdog is not created or context is invalid.");
     188            0 :     return FALSE;
     189              :   }
     190              : 
     191            4 :   return TRUE;
     192              : }
        

Generated by: LCOV version 2.0-1