248 lines
7.1 KiB
C
248 lines
7.1 KiB
C
//
|
|
// Copyright (c) 2014 Wind River Systems, Inc.
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
#include "sm_watchdog_module.h"
|
|
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <glib.h>
|
|
#include <gmodule.h>
|
|
|
|
#include "sm_types.h"
|
|
#include "sm_list.h"
|
|
#include "sm_timer.h"
|
|
#include "sm_debug.h"
|
|
|
|
#define SM_WATCHDOG_MODULE_FILENAME_MAX_SIZE 128
|
|
#define SM_WATCHDOG_MODULE_PATH "/var/lib/sm/watchdog/modules"
|
|
#define SM_WATCHDOG_MODULE_DO_CHECK_FUNC "sm_watchdog_module_do_check"
|
|
#define SM_WATCHDOG_MODULE_INITIALIZE_FUNC "sm_watchdog_module_initialize"
|
|
#define SM_WATCHDOG_MODULE_FINALIZE_FUNC "sm_watchdog_module_finalize"
|
|
|
|
typedef void (*SmWatchdogModuleDoCheckT) (void);
|
|
typedef bool (*SmWatchdogModuleInitializeT) (int* do_check_in_ms);
|
|
typedef bool (*SmWatchdogModuleFinalizeT) (void);
|
|
|
|
typedef struct
|
|
{
|
|
gchar filename[SM_WATCHDOG_MODULE_FILENAME_MAX_SIZE];
|
|
GModule* glibmod;
|
|
int do_check_in_ms;
|
|
SmTimerIdT do_check_timer_id;
|
|
SmWatchdogModuleDoCheckT do_check;
|
|
SmWatchdogModuleInitializeT initialize;
|
|
SmWatchdogModuleFinalizeT finalize;
|
|
} SmWatchdogModuleT;
|
|
|
|
static SmListT* _modules = NULL;
|
|
|
|
// ****************************************************************************
|
|
// Watchdog Module - Do Check Timer
|
|
// ================================
|
|
static bool sm_watchdog_module_do_check_timer( SmTimerIdT timer_id,
|
|
int64_t user_data )
|
|
{
|
|
SmListT* entry = NULL;
|
|
SmListEntryDataPtrT entry_data;
|
|
SmWatchdogModuleT* module = NULL;
|
|
|
|
SM_LIST_FOREACH( _modules, entry, entry_data )
|
|
{
|
|
module = (SmWatchdogModuleT*) entry_data;
|
|
if( NULL == module )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if( timer_id == module->do_check_timer_id )
|
|
{
|
|
DPRINTFD( "Found do-check timer for module (%s).",
|
|
g_module_name(module->glibmod) );
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( NULL != module )
|
|
{
|
|
if( NULL != module->do_check )
|
|
{
|
|
DPRINTFD( "Calling do-check for module (%s).",
|
|
g_module_name(module->glibmod) );
|
|
module->do_check();
|
|
return( true );
|
|
}
|
|
} else {
|
|
DPRINTFE( "Module not found for do-check timer." );
|
|
}
|
|
|
|
return( false );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ***************************************************************************
|
|
// Watchdog Module - Load
|
|
// ======================
|
|
static SmErrorT sm_watchdog_module_load( const gchar* filename )
|
|
{
|
|
gchar* filepath;
|
|
SmWatchdogModuleT* module;
|
|
|
|
module = (SmWatchdogModuleT*) malloc( sizeof(SmWatchdogModuleT) );
|
|
if( NULL == module )
|
|
{
|
|
DPRINTFE( "Failed to allocate watchdog module." );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
memset( module, 0, sizeof(SmWatchdogModuleT) );
|
|
|
|
g_snprintf(module->filename, SM_WATCHDOG_MODULE_FILENAME_MAX_SIZE,
|
|
"%s", filename);
|
|
|
|
filepath = g_module_build_path( SM_WATCHDOG_MODULE_PATH, filename );
|
|
|
|
module->glibmod = g_module_open( filepath, G_MODULE_BIND_LAZY );
|
|
if( NULL == module->glibmod )
|
|
{
|
|
DPRINTFE( "Failed to open module (%s).", filepath );
|
|
free( module );
|
|
g_free( filepath );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
g_free( filepath );
|
|
|
|
g_module_symbol( module->glibmod, SM_WATCHDOG_MODULE_INITIALIZE_FUNC,
|
|
(gpointer*) &(module->initialize) );
|
|
|
|
g_module_symbol( module->glibmod, SM_WATCHDOG_MODULE_FINALIZE_FUNC,
|
|
(gpointer*) &(module->finalize) );
|
|
|
|
g_module_symbol( module->glibmod, SM_WATCHDOG_MODULE_DO_CHECK_FUNC,
|
|
(gpointer*) &(module->do_check) );
|
|
|
|
SM_LIST_PREPEND( _modules, (SmListEntryDataPtrT) module );
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ***************************************************************************
|
|
|
|
// ***************************************************************************
|
|
// Watchdog Module - Load All
|
|
// ==========================
|
|
SmErrorT sm_watchdog_module_load_all( void )
|
|
{
|
|
const gchar* file;
|
|
GDir* directory;
|
|
GError* g_error;
|
|
SmListT* entry = NULL;
|
|
SmListEntryDataPtrT entry_data;
|
|
SmWatchdogModuleT* module;
|
|
SmErrorT error;
|
|
|
|
directory = g_dir_open( SM_WATCHDOG_MODULE_PATH, 0, &g_error );
|
|
if( NULL == directory )
|
|
{
|
|
DPRINTFE( "Failed to open directory( %s), error=%s",
|
|
SM_WATCHDOG_MODULE_PATH, g_error->message );
|
|
g_error_free( g_error );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
file = g_dir_read_name( directory );
|
|
while( NULL != file )
|
|
{
|
|
DPRINTFI( "Loading module (%s).", file );
|
|
|
|
error = sm_watchdog_module_load( file );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to load module (%s), error=%s.",
|
|
file, sm_error_str(error) );
|
|
}
|
|
|
|
file = g_dir_read_name( directory );
|
|
}
|
|
|
|
g_dir_close( directory );
|
|
|
|
SM_LIST_FOREACH( _modules, entry, entry_data )
|
|
{
|
|
module = (SmWatchdogModuleT*) entry_data;
|
|
if( NULL == module )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if( NULL != module->initialize )
|
|
{
|
|
DPRINTFI( "Initializing module (%s).",
|
|
g_module_name(module->glibmod) );
|
|
|
|
if( !(module->initialize( &(module->do_check_in_ms) )) )
|
|
{
|
|
DPRINTFE( "Failed to initialize %s.",
|
|
g_module_name(module->glibmod) );
|
|
return( SM_FAILED );
|
|
}
|
|
|
|
error = sm_timer_register( module->filename,
|
|
module->do_check_in_ms,
|
|
sm_watchdog_module_do_check_timer,
|
|
0, &(module->do_check_timer_id) );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to create module (%s) do-check timer, "
|
|
"error=%s.", g_module_name(module->glibmod),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
}
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ***************************************************************************
|
|
|
|
// ***************************************************************************
|
|
// Watchdog Module - Unload All
|
|
// ============================
|
|
SmErrorT sm_watchdog_module_unload_all( void )
|
|
{
|
|
SmListT* entry = NULL;
|
|
SmListEntryDataPtrT entry_data;
|
|
SmWatchdogModuleT* module;
|
|
|
|
SM_LIST_FOREACH( _modules, entry, entry_data )
|
|
{
|
|
module = (SmWatchdogModuleT*) entry_data;
|
|
if( NULL == module )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if( NULL != module->finalize )
|
|
{
|
|
DPRINTFI( "Finalizing module (%s).",
|
|
g_module_name(module->glibmod) );
|
|
|
|
if( !(module->finalize()) )
|
|
{
|
|
DPRINTFE( "Failed to finalize %s.",
|
|
g_module_name(module->glibmod) );
|
|
}
|
|
}
|
|
|
|
g_module_close( module->glibmod );
|
|
}
|
|
|
|
SM_LIST_CLEANUP_ALL( _modules );
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ***************************************************************************
|