📄 sdb.c
字号:
/*************************************************************************** sdb.c - RTLinux kernel module for the subsystem data base ------------------- begin : 2002 authors : Linus Gasser emails : linus.gasser@epfl.ch ***************************************************************************//*************************************************************************** Changes ------- date - name - description 02-09-11 - ineiti - begin 02/10/31 - ineiti - take out messages 03/04/01 - ineiti - move swr_sdb_set* and swr_sdb_get* to values.c 03/04/04 - ineiti - added profiling 03/04/04 - ineiti - added indexes to config/struct 03/12/15 - ineiti - reconfiguration happens asynchronously now 04/03/31 - ineiti - swr_sdb_send_msg can return a non-zero value **************************************************************************//*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/#define DBG_LVL 0#include "system.h"#include "debugging.h"#include "sdb.h"#include "subsystem.h"#include "memory.h"#include "parameters.h"#include "dbg.h"/** * The maximal number of concurrently available subsystems */#define MAX_SYS_POTWO 10#define MAX_SUBSYSTEMS ( 1 << MAX_SYS_POTWO )typedef struct { swr_sdb_t context; pthread_mutex_t mutex_config; pthread_mutex_t mutex_stats; void *config_data; void *stats_data;}sdb_t;/** * All data for every subsystem is stored in here */sdb_t *sdb_table;pthread_mutex_t mutex_table;/** * The id of the next subsystem, if created */int curr_sdb_id;/** * Takes an id to a subsystem and returns the corresponding entry in the * table */#define ENTRY(i) sdb_table[ (i) & ( MAX_SUBSYSTEMS - 1 ) ]#define CHECK_ID(id) if ( ( id < 0 ) || ( ENTRY(id).context.id != id ) ){ \ PR_DBG( 0, "ID not valid\n" ); return -1; }char swr_profile_name[][16] = { "Messages", "Data ", "Total " };struct swr_stats_track_t swr_stats_track[ MAX_TRACKS ][ 2 ];/** * @short Returns the spc-id of a subsystem * * Checks for a given subsystem the correct spm-id * * @param id the subsytem to search for * * @return the spm-id or a negative error: * <ul> * <li>ERROR_NO_SUBSYS no such subsystem</li> * <li>ERROR_NO_SPM no corresponding spm-id found</li> * </ul> */swr_spc_id_t swr_sdb_spm( swr_sdb_id id ) { if ( id < 0 ) return ERROR_NO_SUBSYS; if ( ENTRY( id ).context.id != id ) return ERROR_NO_SUBSYS; return ENTRY( id ).context.cdb_desc->id;}/** * @short Sends a 'message' to a subsystem * * Calls the message-handler of the given subsystem and gives * it the appropriate options * * @param id the subsystems id * @param m_id The message. swr_sdb_send_msg doesn't care about this * value, it just passes it along. * @param d The data to pass along. This can be anything * @param ret_id Where eventual replies shall be sent to. Putting * a -1 here is a valid option. * * @return 0 or a negative error: * <ul> * <li>ERROR_NO_SUBSYS no such subsystem</li> * </ul> */int swr_sdb_send_msg( swr_sdb_id id, int m_id, void *d, swr_sdb_id ret_id ) { PR_DBG( 4, "Sending msg %i from %i to %i\n", m_id, ret_id, id ); return subsys_handler( swr_sdb_get_struct( id ), m_id, d, ret_id );}/** * @short instantiate by name * * Perhaps the most important function. It takes a spm-id and * tries to generate a subsystem out of it. The spm-structure * is generated and initialised by the spm-init function. * Everything is set up and ready to be connected to other * spm-modules. * * After calling this function and if no error occured, the * return-value points to a waiting subsystem, ready to go. * * @param name a string pointing to the name of the sdb * * @return subsys-id if all went well or a negative error: * <ul> * <li>ERROR_NO_SPM no such spm</li> * <li>ERROR_NO_MEMORY not enough memory</li> * <li>ERROR_OTHER undefined error</li> * </ul> */swr_sdb_id swr_sdb_instantiate_name( char *name ) { return swr_sdb_instantiate_id( swr_cdb_get_id( name ) );}/** * @short Creates an instance of a subsystem * * Perhaps the most important function. It takes a spm-id and * tries to generate a subsystem out of it. The spm-structure * is generated and initialised by the spm-init function. * Everything is set up and ready to be connected to other * spm-modules. * * After calling this function and if no error occured, the * return-value points to a waiting subsystem, ready to go. * * @param id the spm-id * * @return subsys-id if all went well or a negative error: * <ul> * <li>ERROR_NO_SPM no such spm</li> * <li>ERROR_NO_MEMORY not enough memory</li> * <li>ERROR_OTHER undefined error</li> * </ul> */swr_sdb_id swr_sdb_instantiate_id( swr_spc_id_t id ) { int i, new_id; const swr_spc_desc_t *cdb_struct; sdb_t entry; pthread_mutex_lock( &mutex_table ); if ( id < 0 ) goto swr_sdb_inst_err; PR_DBG( 3, "Initialising dummy-entry\n" ); // First we do some checking whether the id exists, and if there // is place left if ( swr_cdb_get_reference( &cdb_struct, id ) < 0 ) goto swr_sdb_inst_err; for ( new_id=curr_sdb_id; new_id < MAX_SUBSYSTEMS + curr_sdb_id; new_id++ ) { if ( ENTRY(new_id).context.id == -1 ) break; } if ( ENTRY(new_id).context.id != -1 ) goto swr_sdb_inst_err_ref; // Then we begin putting in new values in our local entry entry.context.id = new_id; entry.context.cdb_desc = cdb_struct; entry.context.status = 0; entry.context.rec_count = 0; // Get the output-ports, or initialise to NULL if there aren't any if ( cdb_struct->outputs.nbr_ports ) { if ( !( entry.context.port_out = (swr_port_t*)swr_malloc( sizeof( swr_port_t ) * cdb_struct->outputs.nbr_ports ) ) ) { goto swr_sdb_inst_err_outports; } } else { entry.context.port_out = NULL; } // Get the input-ports, or initialise to NULL if there aren't any if ( cdb_struct->inputs.nbr_ports ) { if ( !( entry.context.port_in = (swr_port_t*)swr_malloc( sizeof( swr_port_t ) * cdb_struct->inputs.nbr_ports ) ) ) { goto swr_sdb_inst_err_inports; } } else { entry.context.port_in = NULL; } // Setting up the configuration-memory, if any. if ( ( i = swr_spc_get_config_memory_size( entry.context.cdb_desc ) ) ) { if ( !(entry.config_data = swr_malloc( i ) ) ) goto swr_sdb_inst_err_malloc_config; } else { entry.config_data = NULL; } // Setting up the stats-memory, if any. if ( ( i = swr_spc_get_stats_memory_size( entry.context.cdb_desc ) ) ) { if ( !( entry.stats_data = swr_malloc( i ) ) ) goto swr_sdb_inst_err_malloc_stats; } else { entry.stats_data = NULL; } PR_DBG( 3, "Preparing module\n" ); // Create the mutex and cond-var for the subsystem and initialise the // message-queue pthread_mutex_init( &entry.context.mutex, NULL ); pthread_cond_init( &entry.context.cond, NULL ); // The mutexes have to be initialised: // preparing a mutex protection for config and stats pthread_mutex_init( &entry.mutex_config, NULL ); pthread_mutex_init( &entry.mutex_stats, NULL ); ENTRY(new_id) = entry; if ( subsys_init( &ENTRY(new_id).context ) < 0 ) { PR_DBG( 0, "Failed to initialise subsys. What now?\n" ); } curr_sdb_id = new_id + 1; PR_DBG( 4, "Finished\n" ); pthread_mutex_unlock( &mutex_table ); return new_id; // ERROR-handlingswr_sdb_inst_err_malloc_stats: PR_DBG_CL( 0, "Freeing stats and config, " ); swr_cdb_free_reference( &entry.context.cdb_desc ); swr_free( entry.context.port_in );swr_sdb_inst_err_malloc_config:swr_sdb_inst_err_inports: PR_DBG_CL( 0, "Freeing the connections, " ); swr_free( entry.context.port_out );swr_sdb_inst_err_outports:swr_sdb_inst_err_ref: PR_DBG_CL( 0, "Freeing reference " ); swr_cdb_free_reference( &cdb_struct );swr_sdb_inst_err: PR_DBG( 0, "and exiting with error\n"); pthread_mutex_unlock( &mutex_table ); return -1;}/** * @short Destroys an instance of a subsystem */int swr_sdb_destroy( swr_sdb_id id ) { sdb_t *entry; if ( id < 0 ) goto swr_sdb_destroy_error; entry = &ENTRY( id ); if ( entry->context.id < 0 ){ PR_DBG( 0, "Trying to free an already freed sdb: %i\n", id ); return -1; } subsys_handler( &entry->context, SUBS_MSG_EXIT, NULL, -1 ); pthread_mutex_lock( &mutex_table ); if ( entry->context.id != id ) goto swr_sdb_destroy_error; swr_conn_sdb_remove( id ); pthread_mutex_destroy( &entry->mutex_config ); pthread_mutex_destroy( &entry->mutex_stats ); pthread_mutex_destroy( &entry->context.mutex ); pthread_cond_destroy( &entry->context.cond ); // Cleaning up our structures entry->context.id = -1; if ( entry->context.port_in ) { swr_free( entry->context.port_in ); } if ( entry->context.port_out ) { swr_free( entry->context.port_out ); } if ( entry->config_data ) { swr_free( entry->config_data ); } if ( entry->stats_data ) { swr_free( entry->stats_data ); } swr_cdb_free_reference( &entry->context.cdb_desc ); pthread_mutex_unlock( &mutex_table ); return 0;swr_sdb_destroy_error: PR_DBG( 0, "uncool id %i\n", id ); pthread_mutex_unlock( &mutex_table ); return -1;}/** * @short returns the corresponding structure */swr_sdb_t *swr_sdb_get_struct( swr_sdb_id id ) { if ( id < 0 ) return NULL; if ( ENTRY( id ).context.id != id ) return NULL; return &ENTRY( id ).context;}/** * @short activate inputs and call a module * * This function can be used to call a module out-of order. * It is mostly for debugging purposes. * First the desired input-ports are activated (if they have * a valid data-part) and then a SUBS_SWR_MSG_DATA message is * sent to the module. * * @param id The id of the module * @param act A bit-mask for the input-ports to activate * * @return 0 on success, -1 on failure */int swr_sdb_call_module( swr_sdb_id id, int act ){ swr_sdb_t *s; swr_port_t *port; int i; s = swr_sdb_get_struct( id ); if ( !s ){ PR_DBG( 0, "Module %i doesn't exist\n", id ); return -1; } for ( i=0; i<s->cdb_desc->inputs.nbr_ports; i++ ){ if ( ( 1 << i ) & act ){ port = s->port_in + i; if ( port->data ){ PR_DBG( 4, "Setting port %i with data\n", i ); port->flags |= SWR_PORT_DATA; } } } swr_sdb_send_msg( id, SUBS_MSG_DATA, NULL, -1 ); return 0;}/** * @short Writes maximum size subsys-ids in ids and * returns the total number of ids. */int swr_sdb_list( swr_sdb_id *ids, int size ) { int i, tot=0; pthread_mutex_lock( &mutex_table ); for ( i=0; i<MAX_SUBSYSTEMS; i++ ) { if ( ENTRY(i).context.id != -1 ) { if ( tot < size ) { ids[tot] = ENTRY(i).context.id; } tot++; } } pthread_mutex_unlock( &mutex_table ); return tot;}/** * @short Returns the number of a certain parameter */int swr_sdb_get_config_parameter_nbr( swr_sdb_id id, char *name ) { sdb_t *entry; int ret = -1; // if id < -1, then it might be a call to set_config with a negative // id, which means not to reconfigure, so do allow it. if ( id < 0 ){ if ( id < -1 ){ id = -id; } else { // Well, this is used as an invalid id soo often return -1; } } entry = &ENTRY(id); pthread_mutex_lock( &entry->mutex_config ); if ( entry->context.id != id ) goto swr_sdb_get_config_param_error; ret = swr_spc_get_config_parameter_nbr( entry->context.cdb_desc, name );swr_sdb_get_config_param_error: pthread_mutex_unlock( &entry->mutex_config ); return ret;}/** * @short Writes a new value to the config-structure */int swr_sdb_set_config_parameter_value( swr_sdb_id id, int param, void *data ) { sdb_t *entry; int ret = -1; int call_reconf = 1; // If id < 0, then only set the value, without reconfiguration // Nevertheless, keep the error on id -1, as this is used in many // places to design an invalid module if ( id < 0 ){ if ( id < -1 ){ id = -id; call_reconf = 0; } else { return -1; } } entry = &ENTRY(id); pthread_mutex_lock( &entry->mutex_config ); if ( entry->context.id != id ) goto swr_sdb_set_config_error; if ( swr_spc_set_config_parameter_value( entry->context.cdb_desc, entry->config_data, param, data ) ) { ret = 0; PR_DBG( 4, "Setting status_reconf\n" );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -