⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cdb.c

📁 This a framework to test new ideas in transmission technology. Actual development is a LDPC-coder in
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************         spm.c  -  RTLinux kernel module for storing         information about available SPM types.                             -------------------     begin                :  2002    authors              :  Silvio Boehler    emails               :  sboehler@student.ethz.ch ***************************************************************************//***************************************************************************                                 Changes                                 ------- date - name - description09.09.2002 - silvio - begin work  **************************************************************************//*************************************************************************** *                                                                         * *   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.                                   * *                                                                         * ***************************************************************************//** * Debugging stuff */#include "debugging.h"#ifdef DBG_LVL#undef DBG_LVL#endif#define DBG_LVL 0/** * The interface for this module */#include "cdb.h"/** * We use statistics and configuration parameters */#include "system.h"#include "parameter_types.h"#include "parameters.h"#include "ports.h"#include "cdb.h"#include "memory.h"//-------------------------------------------------------------------// TYPES//-------------------------------------------------------------------/** * This is an entry in the SPM database. Reference counting is used * for  */typedef struct {  int refs;  // we do reference counting,  char name[SWR_CDB_MAX_NAME_LENGTH];  const swr_spc_desc_t *desc;}database_entry_t;typedef struct {  int nbr_spms;  pthread_mutex_t mutex;  int last_id;  database_entry_t **entries;}database_t;//-------------------------------------------------------------------// GLOBAL VARIABLES//-------------------------------------------------------------------database_t *database;//-------------------------------------------------------------------// MACROS//-------------------------------------------------------------------#define INDEX(id) ( (id) & (DB_SIZE - 1) )#define TURN(id) ( (id) >> SWR_CDB_SIZE_LOG_2 )#define DB_SIZE (1 << SWR_CDB_SIZE_LOG_2)//-------------------------------------------------------------------//// PRIVATE FUNCTIONS////-------------------------------------------------------------------//-------------------------------------------------------------------// Initializing and destroying SPM descriptions//-------------------------------------------------------------------/** * Create and initialize SPM description.  * * @param nbr_inputs The number of inputs * * @param nbr_outputs The number of outputs * * @param nbr_config_params The number of configuration parameters * * @param nbr_stats_params The number of statistics parameters * * @return A pointer to the newly allocated SPM description. In case * of an error, NULL is returned. * */swr_spc_desc_t *create_spc_desc(int nbr_inputs,                                int nbr_outputs,                                int nbr_config_params,                                int nbr_stats_params) {  swr_spc_desc_t *desc = swr_malloc(sizeof(swr_spc_desc_t));  if (!desc) {    PR_DBG(0, "Couldn't create SPM description\n");    return NULL;  }  init_parameters_desc(&desc->stats, nbr_stats_params);  init_parameters_desc(&desc->config, nbr_config_params);  init_ports_desc(&desc->inputs, nbr_inputs);  init_ports_desc(&desc->outputs, nbr_outputs);  desc->fn_init = NULL;  desc->fn_process_data = NULL;  desc->fn_reconfigure = NULL;  desc->fn_configure_inputs = NULL;  desc->fn_configure_outputs = NULL;  desc->fn_custom_msg = NULL;  desc->fn_finalize = NULL;  return desc;}/** * Free a SPM description.  * * @param desc A pointer to the SPM description which is to free. * * @return 0 if success, a negative number in case of an error. */int free_spc_desc(swr_spc_desc_t *desc) {  int error = 0;  if (!desc) {    PR_DBG(0, "desc == NULL\n");    return -1;  }  error |= finalize_parameters_desc(&desc->config);  error |= finalize_parameters_desc(&desc->stats);  error |= finalize_ports_desc(&desc->inputs);  error |= finalize_ports_desc(&desc->outputs);  error |= swr_free(desc);  if (error) {    PR_DBG(0, "freeing failed\n");    return error;  }  return 0;}/** * Check whether a SPM description is complete. *  * @param desc The SPM description to be checked. * * @return 0 if the description is not complete, !0 if it is complete. */inline int description_complete(const swr_spc_desc_t *desc) {  if (desc)    return parameters_desc_complete(desc->config)           &&   parameters_desc_complete(desc->stats)           &&   ports_desc_complete(desc->inputs)           &&   ports_desc_complete(desc->outputs);  PR_DBG(0, "desc == NULL");  return -1;}//-------------------------------------------------------------------// Initializing and destroying of the database//-------------------------------------------------------------------/** * Create the database. * * @return 0 if success, a negative number if error. */int create_database(void) {  database = (database_t *)swr_malloc(sizeof(database_t));  if (!database) {    PR_DBG(0, "couldn't allocate database\n");    return -1;  }  database->nbr_spms = 0;  database->last_id = -1;  PR_DBG(1, "Database created\n");  return 0;}/** * Destroy the database. * * @return 0 if success, a negative number if error. */int destroy_database(void) {  int error = swr_free(database);  if (error) {    PR_DBG(0, "Error freeing the database\n");    return -1;  }  PR_DBG(1, "Database destroyed\n");  return 0;}/** * Create array of pointers to entries * * @return 0 if success, a negative number if error. */int create_entries_array(void) {  int i;  database->entries = (database_entry_t **)swr_malloc(sizeof(database_entry_t *[DB_SIZE]));  if (!database->entries) {    PR_DBG(0, "Couldn't allocate array\n");    return -1;  }  for (i = 0; i < DB_SIZE; i++)    database->entries[i] = 0;  PR_DBG(1, "Created and initialized array\n");  return 0;}/** * Destroy array of pointers to entries *  * @return 0 if success, a negative number if error. */int destroy_entries_array(void) {  if (swr_free(database->entries)) {    PR_DBG(0, "Couldn't free database entries array\n");    return -1;  }  PR_DBG(1, "Freed array\n");  return 0;}/** * Initialize the database * * @return 0 if success, a negative number if error. */int initialize(void) {  int error;  error = create_database();  if (error)    goto create_database_failed;  error = create_entries_array();  if (error)    goto create_entries_array_failed;  error = pthread_mutex_init(&database->mutex, 0);  if (error)    goto init_mutex_failed;  return 0;init_mutex_failed:  destroy_entries_array();create_entries_array_failed:  destroy_database();create_database_failed:  return -1;}/** * Finalize the database */void finalize(void) {  pthread_mutex_lock(&database->mutex);  destroy_entries_array();  destroy_database();  pthread_mutex_unlock(&database->mutex);  pthread_mutex_destroy(&database->mutex);}//-------------------------------------------------------------------// Basic database functions//-------------------------------------------------------------------/** * Get the next free id. * * @param id A pointer to swr_spc_id_t where the id will be written. * * @return 0 if success, a negative number if error */int get_new_id(swr_spc_id_t *id) {  int i;  for (i = 1;  i  <= DB_SIZE; i++) {    if (!database->entries[INDEX(database->last_id + i)]) {      database->last_id += i;      *id = database->last_id;      return 0;    }  }  PR_DBG(0, "Database full, can't create new entry\n");  return -1;}/** * Check if the ID is valid and the corresponding SPM exists in the * database. * * @param id The ID which is to check. * * @return !0 if valid, 0 if not valid. */int validate_id(swr_spc_id_t id) {  if (id < 0) {    PR_DBG(0, "id invalid (id < 0)\n");    return 0;  }  if (!database->entries[INDEX(id)]) {    PR_DBG(0, "id invalid (entry doesn't exist)\n");    return 0;  }  if (database->entries[INDEX(id)]->desc->id != id) {    PR_DBG(0, "id invalid (SPM exists but other id)\n" );    return 0;  }  // ID is valid:  return 1;}/** * Look up if an SPM for a given name exists in the database. * * @param name The name of the SPM to look for. * * @return The ID of the SPM if success, SWR_SPM_INVALID_ID if error or not found. */swr_spc_id_t get_id(const char *name) {  swr_spc_id_t id = SWR_SPM_INVALID_ID;  database_entry_t **entry;  database_entry_t **first = &database->entries[0];  database_entry_t **beyond = &database->entries[DB_SIZE];  if (!name) {    PR_DBG(0, "name == NULL\n");    return SWR_SPM_INVALID_ID;  }  for (entry = first; entry < beyond && id == SWR_SPM_INVALID_ID; entry++) {    if (*entry && !strncmp((*entry)->name, name, SWR_CDB_MAX_NAME_LENGTH)) {      id = (*entry)->desc->id;      return id;    }  }  return SWR_SPM_INVALID_ID;}int cdb_get_name(swr_spc_id_t id, char *buffer) {#ifndef FAST  if (!validate_id(id)) {    PR_DBG(0, "ID not valid\n");    return -1;  }  if (!buffer) {    PR_DBG(0, "buffer for name is NULL\n");    return -2;  }#endif  strncpy(buffer, database->entries[INDEX(id)]->name, SWR_CDB_MAX_NAME_LENGTH);  return 0;}/** * Get all IDs from the CDB * * @param buffer The buffer where the IDs will be written. * * @return nbr The number of IDs which fit in the buffer. * * @return The number of IDs which has been written, or a negative * number in case of an error. */int get_all_ids(swr_spc_id_t *buffer, int nbr) {  database_entry_t **cur_entry, **beyond_entry = database->entries + DB_SIZE;  swr_spc_id_t *cur_id = buffer, *beyond_id = buffer + nbr;  if (!buffer) {    PR_DBG(0, "buffer == NULL\n");    return -1;  }  for (cur_entry = database->entries; cur_entry < beyond_entry && cur_id < beyond_id; cur_entry++) {    if (*cur_entry) {      *cur_id++ = (*cur_entry)->desc->id;    }  }  return cur_id - buffer;}/** * Create database entry * * @return A pointer to the newly created database entry. */database_entry_t *create_database_entry(void) {  return (database_entry_t *)swr_malloc(sizeof(database_entry_t));}/** * Add database entry * * @param desc A pointer to the SPM description which should be added * to the database. * * */swr_spc_id_t add_database_entry(swr_spc_desc_t **desc, const char *name) {  database_entry_t *entry;  if (!desc) {    PR_DBG(0, "desc == NULL -> give me the address of your pointer!\n");    return SWR_SPM_INVALID_ID;  }  if (!*desc) {    PR_DBG(0, "*desc == NULL -> nothing to register\n");    return SWR_SPM_INVALID_ID;  }  // If now an error occurs, desc has to be cleaned up  if (!description_complete(*desc)) {    PR_DBG(0, "The description is not complete yet, I do not take it.\n");    goto cleanup_desc;  }  if (!name) {    PR_DBG(0, "name == NULL\n");    goto cleanup_desc;  }  if (get_id(name) != SWR_SPM_INVALID_ID) {    PR_DBG(0, "A module named '%s' does already exist, registration failed\n",           name );    goto cleanup_desc;  }  if (get_new_id(&(*desc)->id)) {    PR_DBG(0, "Couldn't get new ID\n");    goto cleanup_desc;  }  entry = create_database_entry();  if (!entry) {    PR_DBG(0, "Couldn't create entry\n");    goto cleanup_desc;  }  entry->desc = *desc;  entry->refs = 0;  strncpy(entry->name, name, SWR_CDB_MAX_NAME_LENGTH);  database->entries[INDEX(entry->desc->id)] = entry;  database->nbr_spms++;  return (*desc)->id;cleanup_desc:  free_spc_desc(*desc);  *desc = NULL;  return SWR_SPM_INVALID_ID;}/** * Remove database entry * * @param id The ID of the database entry which should be removed. * * @return 0 if success, a negative number if error. */int remove_database_entry(swr_spc_id_t id) {  database_entry_t *entry;  if (!validate_id(id)) {    PR_DBG(0, "ID not valid\n");    return -1;  }  entry = database->entries[INDEX(id)];  if (entry->refs != 0) {    PR_DBG(0, "still active references, not removing SPM %s\n",           entry->name );    return -3;  }  if (free_spc_desc((swr_spc_desc_t *)entry->desc)) {    PR_DBG(0, "fatal error while freeing desc\n");    return -4;  }  if (swr_free(entry)) {    PR_DBG(0, "Fatal error while freeing entry\n");    return -5;  }  database->entries[INDEX(id)] = NULL;  database->nbr_spms--;  return 0;}/** * Get a reference to a SPM */int cdb_get_reference(const swr_spc_desc_t **ref, swr_spc_id_t id) {  if (!validate_id(id)) {    PR_DBG(0, "the specified ID is not valid\n");    return -1;  }  // id is valid  database->entries[INDEX(id)]->refs++;  *ref = database->entries[INDEX(id)]->desc;  return 0;}/** * Free a reference to a SPM */int cdb_free_reference(const swr_spc_desc_t **ref) {  swr_spc_id_t id;  if (!ref) {    PR_DBG(0, "ref points to NULL\n");    return -1;  }  if (!*ref) {    PR_DBG(0, "*ref points to NULL\n");    return -2;  }  // ref is not NULL, so take the ID:  id = ((swr_spc_desc_t *)*ref)->id;  if (!validate_id(id)) {    PR_DBG(0, "ID of returned reference not valid!\n");    return -3;  }  if (database->entries[INDEX(id)]->refs == 0) {    PR_DBG(0, "Can't free reference 'cause refs already == 0\n");    return -4;  }  database->entries[INDEX(id)]->refs--;  *ref = NULL;  return 0;}//-------------------------------------------------------------------//// INTERFACE FUNCTIONS////-------------------------------------------------------------------/** * Get an empty SPM description. Space for all arrays is already * allocated, but the actual values have still to be filled out. */swr_spc_desc_t *swr_spc_get_new_desc(int nbr_inputs,                                     int nbr_outputs,                                     int nbr_config_params,                                     int nbr_stats_params) {  return create_spc_desc(nbr_inputs,                         nbr_outputs,                         nbr_config_params,                         nbr_stats_params);}/** * Free an SPM description. This should only be used with unregistered * descriptions which have been explicitely allocated with * swr_get_new_spc_desc(). */int swr_spc_free_desc(swr_spc_desc_t *desc) {  return free_spc_desc(desc);}/** * Register a SPM in the database. The description has to be filled * out.  */swr_spc_id_t swr_cdb_register_spc(swr_spc_desc_t** desc, const char *name) {  swr_spc_id_t id;  pthread_mutex_lock(&database->mutex);  id = add_database_entry(desc, name);  pthread_mutex_unlock(&database->mutex);  if (id == SWR_SPM_INVALID_ID)    PR_DBG(0, "module not registered\n");  return id;}/** * Unregister a SPM from the database. */int swr_cdb_unregister_spc(swr_spc_id_t id) {  int error;  pthread_mutex_lock(&database->mutex);  error = remove_database_entry(id);  pthread_mutex_unlock(&database->mutex);  if (error) {    PR_DBG(0, "Couldn't unregister SPM\n");    return -1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -