diff options
| -rw-r--r-- | host/include/uhd/utils/log.hpp | 2 | ||||
| -rw-r--r-- | host/lib/usrp/usrp_e100/usrp_e100_impl.cpp | 70 | ||||
| -rw-r--r-- | host/lib/utils/log.cpp | 116 | ||||
| -rw-r--r-- | host/lib/utils/msg.cpp | 32 | ||||
| -rw-r--r-- | host/usrp_e_utils/usrp-e-utility.cpp | 3 | 
5 files changed, 116 insertions, 107 deletions
| diff --git a/host/include/uhd/utils/log.hpp b/host/include/uhd/utils/log.hpp index 8d8f42fd0..7f83fd2a9 100644 --- a/host/include/uhd/utils/log.hpp +++ b/host/include/uhd/utils/log.hpp @@ -38,7 +38,7 @@   * (in other words, as often or less often than the current log level)   * are recorded into the log file. All other messages are sent to null.   * - * The default log level is "regular", but can be overridden: + * The default log level is "never", but can be overridden:   *  - at compile time by setting the pre-processor define UHD_LOG_LEVEL.   *  - at runtime by setting the environment variable UHD_LOG_LEVEL.   * diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp index 5fba0c153..e9e9b6e20 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp @@ -76,6 +76,15 @@ static device_addrs_t usrp_e100_find(const device_addr_t &hint){  /***********************************************************************   * Make   **********************************************************************/ +static size_t hash_fpga_file(const std::string &file_path){ +    size_t hash = 0; +    std::ifstream file(file_path.c_str()); +    if (not file.good()) throw uhd::io_error("cannot open fpga file for read: " + file_path); +    while (file.good()) boost::hash_combine(hash, file.get()); +    file.close(); +    return hash; +} +  static device::sptr usrp_e100_make(const device_addr_t &device_addr){      //setup the main interface into fpga @@ -83,55 +92,44 @@ static device::sptr usrp_e100_make(const device_addr_t &device_addr){      UHD_MSG(status) << boost::format("Opening USRP-E on %s") % node << std::endl;      usrp_e100_iface::sptr iface = usrp_e100_iface::make(node); -    //------------------------------------------------------------------ -    //-- Handle the FPGA loading... -    //-- The image can be confimed as already loaded when: -    //--   1) The compatibility number matches. -    //--   2) The hash in the hash-file matches. -    //------------------------------------------------------------------ -    static const char *hash_file_path = "/tmp/usrp_e100_hash"; -      //extract the fpga path for usrp-e -    std::string usrp_e100_fpga_image = find_image_path( -        device_addr.has_key("fpga")? device_addr["fpga"] : "usrp_e100_fpga.bin" -    ); - -    //calculate a hash of the fpga file -    size_t fpga_hash = 0; -    { -        std::ifstream file(usrp_e100_fpga_image.c_str()); -        if (not file.good()) throw uhd::io_error( -            "cannot open fpga file for read: " + usrp_e100_fpga_image -        ); -        do{ -            boost::hash_combine(fpga_hash, file.get()); -        } while (file.good()); -        file.close(); -    } +    std::string usrp_e100_fpga_image = find_image_path(device_addr.get("fpga", "usrp_e100_fpga.bin")); -    //read the compatibility number -    boost::uint16_t fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT); +    //compute a hash of the fpga file +    const boost::uint32_t file_hash = boost::uint32_t(hash_fpga_file(usrp_e100_fpga_image)); -    //read the hash in the hash-file -    size_t loaded_hash = 0; -    try{std::ifstream(hash_file_path) >> loaded_hash;}catch(...){} - -    //if not loaded: load the fpga image and write the hash-file -    if (fpga_compat_num != USRP_E_FPGA_COMPAT_NUM or loaded_hash != fpga_hash){ +    //When the hash does not match: +    // - unload the iface to free the node +    // - load the fpga configuration file +    // - re-open the iface on the node +    if (iface->peek32(UE_REG_RB_MISC_TEST32) != file_hash){          iface.reset();          usrp_e100_load_fpga(usrp_e100_fpga_image);          sleep(1); ///\todo do this better one day.          UHD_MSG(status) << boost::format("re-Opening USRP-E on %s") % node << std::endl;          iface = usrp_e100_iface::make(node); -        try{std::ofstream(hash_file_path) << fpga_hash;}catch(...){} +    } + +    //store the hash into the FPGA register +    iface->poke32(UE_REG_SR_MISC_TEST32, file_hash); + +    //check that the hash can be readback correctly +    if (iface->peek32(UE_REG_RB_MISC_TEST32) != file_hash){ +        UHD_MSG(error) << boost::format( +            "The FPGA hash readback failed!\n" +            "The FPGA is either clocked improperly\n" +            "or the FPGA build is not compatible.\n" +        );      }      //check that the compatibility is correct -    fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT); +    const boost::uint16_t fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT);      if (fpga_compat_num != USRP_E_FPGA_COMPAT_NUM){          throw uhd::runtime_error(str(boost::format( -            "Expected fpga compatibility number 0x%x, but got 0x%x:\n" -            "The fpga build is not compatible with the host code build." +            "\nPlease update the FPGA image for your device.\n" +            "See the application notes for USRP E-Series for instructions.\n" +            "Expected FPGA compatibility number 0x%x, but got 0x%x:\n" +            "The FPGA build is not compatible with the host code build."          ) % USRP_E_FPGA_COMPAT_NUM % fpga_compat_num));      } diff --git a/host/lib/utils/log.cpp b/host/lib/utils/log.cpp index 5e8039fda..7d11877a1 100644 --- a/host/lib/utils/log.cpp +++ b/host/lib/utils/log.cpp @@ -16,6 +16,7 @@  //  #include <uhd/utils/log.hpp> +#include <uhd/utils/msg.hpp>  #include <uhd/utils/static.hpp>  #include <boost/filesystem.hpp>  #include <boost/format.hpp> @@ -41,6 +42,7 @@ namespace boost{ namespace interprocess{  #include <stdio.h> //P_tmpdir  #include <cstdlib> //getenv  #include <fstream> +#include <sstream>  #include <cctype>  namespace fs = boost::filesystem; @@ -84,22 +86,21 @@ static fs::path get_temp_path(void){  }  /*********************************************************************** - * The library's streamer resource (static initialization) + * Global resources for the logger   **********************************************************************/ -class null_streambuf_class : public std::streambuf{ -    int overflow(int c) { return c; } -}; -UHD_SINGLETON_FCN(null_streambuf_class, null_streambuf); - -class uhd_logger_stream_resource_class{ +class log_resource_type{  public: -    uhd_logger_stream_resource_class(void) : _null_stream(&null_streambuf()){ -        const std::string log_path = (get_temp_path() / "uhd.log").string(); -        _file_stream.open(log_path.c_str(), std::fstream::out | std::fstream::app); -        _file_lock = new ip::file_lock(log_path.c_str()); +    boost::mutex mutex; +    std::ostringstream ss; +    uhd::_log::verbosity_t verbosity, level; + +    log_resource_type(void){ + +        //file lock pointer must be null +        _file_lock = NULL;          //set the default log level -        _log_level = uhd::_log::regularly; +        level = uhd::_log::never;          //allow override from macro definition          #ifdef UHD_LOG_LEVEL @@ -109,42 +110,34 @@ public:          //allow override from environment variable          const char * log_level_env = std::getenv("UHD_LOG_LEVEL");          if (log_level_env != NULL) _set_log_level(log_level_env); -      } -    ~uhd_logger_stream_resource_class(void){ +    ~log_resource_type(void){          _file_stream.close(); -        delete _file_lock; -    } - -    std::ostream &get(void){ -        if (_verbosity >= _log_level) return _file_stream; -        return _null_stream; +        if (_file_lock != NULL) delete _file_lock;      } -    void aquire(bool lock){ -        if (lock){ -            _mutex.lock(); -            _file_lock->lock(); +    void log_to_file(void){ +        if (verbosity < level) return; +        if (_file_lock == NULL){ +            const std::string log_path = (get_temp_path() / "uhd.log").string(); +            _file_stream.open(log_path.c_str(), std::fstream::out | std::fstream::app); +            _file_lock = new ip::file_lock(log_path.c_str());          } -        else{ -            _file_lock->unlock(); -            _mutex.unlock(); -        } -    } - -    void set_verbosity(uhd::_log::verbosity_t verbosity){ -        _verbosity = verbosity; +        _file_lock->lock(); +        _file_stream << ss.str() << std::flush; +        _file_lock->unlock();      }  private:      //! set the log level from a string that is either a digit or an enum name      void _set_log_level(const std::string &log_level_str){ -        const uhd::_log::verbosity_t log_level = uhd::_log::verbosity_t(log_level_str[0]-'0'); -        if (std::isdigit(log_level_str[0]) and log_level >= uhd::_log::always and log_level <= uhd::_log::never){ -            _log_level = log_level; +        const uhd::_log::verbosity_t log_level_num = uhd::_log::verbosity_t(log_level_str[0]-'0'); +        if (std::isdigit(log_level_str[0]) and log_level_num >= uhd::_log::always and log_level_num <= uhd::_log::never){ +            this->level = log_level_num; +            return;          } -        #define if_lls_equal(name) else if(log_level_str == #name) _log_level = uhd::_log::name +        #define if_lls_equal(name) else if(log_level_str == #name) this->level = uhd::_log::name          if_lls_equal(always);          if_lls_equal(often);          if_lls_equal(regularly); @@ -153,20 +146,12 @@ private:          if_lls_equal(never);      } -    //available stream objects +    //file stream and lock:      std::ofstream _file_stream; -    std::ostream _null_stream; - -    //synchronization mechanisms -    boost::mutex _mutex; //process-level -    ip::file_lock *_file_lock; //system-level - -    //log-level settings -    uhd::_log::verbosity_t _verbosity; -    uhd::_log::verbosity_t _log_level; +    ip::file_lock *_file_lock;  }; -UHD_SINGLETON_FCN(uhd_logger_stream_resource_class, uhd_logger_stream_resource); +UHD_SINGLETON_FCN(log_resource_type, log_rs);  /***********************************************************************   * The logger object implementation @@ -188,14 +173,14 @@ uhd::_log::log::log(      const unsigned int line,      const std::string &function  ){ -    uhd_logger_stream_resource().aquire(true); -    uhd_logger_stream_resource().set_verbosity(verbosity); +    log_rs().mutex.lock(); +    log_rs().verbosity = verbosity;      const std::string time = pt::to_simple_string(pt::microsec_clock::local_time());      const std::string header1 = str(boost::format("-- %s - level %d") % time % int(verbosity));      const std::string header2 = str(boost::format("-- %s") % function).substr(0, 80);      const std::string header3 = str(boost::format("-- %s:%u") % get_rel_file_path(file) % line);      const std::string border = std::string(std::max(std::max(header1.size(), header2.size()), header3.size()), '-'); -    uhd_logger_stream_resource().get() +    log_rs().ss          << std::endl          << border << std::endl          << header1 << std::endl @@ -206,10 +191,35 @@ uhd::_log::log::log(  }  uhd::_log::log::~log(void){ -    uhd_logger_stream_resource().get() << std::endl; -    uhd_logger_stream_resource().aquire(false); +    log_rs().ss << std::endl; +    try{ +        log_rs().log_to_file(); +    } +    catch(const std::exception &e){ +        /*! +         * Critical behavior below. +         * The following steps must happen in order to avoid a lock-up condition. +         * This is because the message facility will call into the logging facility. +         * Therefore we must disable the logger (level = never) and unlock the mutex. +         * +         * 1) Set logging level to never. +         * 2) Unlock the mutex. +         * 3) Send the error message. +         * 4) Return. +         */ +        log_rs().level = never; +        log_rs().ss.str(""); //clear for next call +        log_rs().mutex.unlock(); +        UHD_MSG(error) +            << "Logging failed: " << e.what() << std::endl +            << "Logging has been disabled for this process" << std::endl +        ; +        return; +    } +    log_rs().ss.str(""); //clear for next call +    log_rs().mutex.unlock();  }  std::ostream & uhd::_log::log::operator()(void){ -    return uhd_logger_stream_resource().get(); +    return log_rs().ss;  } diff --git a/host/lib/utils/msg.cpp b/host/lib/utils/msg.cpp index e850b5a6d..0fd62bfc1 100644 --- a/host/lib/utils/msg.cpp +++ b/host/lib/utils/msg.cpp @@ -61,20 +61,24 @@ static void msg_to_cerr(const std::string &title, const std::string &msg){  }  /*********************************************************************** - * Global settings for the messenger + * Global resources for the messenger   **********************************************************************/ -static boost::mutex msg_mutex; -static std::ostringstream msg_ss; -static uhd::msg::type_t msg_type; -static uhd::msg::handler_t msg_handler; +struct msg_resource_type{ +    boost::mutex mutex; +    std::ostringstream ss; +    uhd::msg::type_t type; +    uhd::msg::handler_t handler; +}; + +UHD_SINGLETON_FCN(msg_resource_type, msg_rs);  /***********************************************************************   * Setup the message handlers   **********************************************************************/  void uhd::msg::register_handler(const handler_t &handler){ -    msg_mutex.lock(); -    msg_handler = handler; -    msg_mutex.unlock(); +    msg_rs().mutex.lock(); +    msg_rs().handler = handler; +    msg_rs().mutex.unlock();  }  static void default_msg_handler(uhd::msg::type_t type, const std::string &msg){ @@ -108,16 +112,16 @@ UHD_STATIC_BLOCK(msg_register_default_handler){   * The message object implementation   **********************************************************************/  uhd::msg::_msg::_msg(const type_t type){ -    msg_mutex.lock(); -    msg_type = type; +    msg_rs().mutex.lock(); +    msg_rs().type = type;  }  uhd::msg::_msg::~_msg(void){ -    msg_handler(msg_type, msg_ss.str()); -    msg_ss.str(""); //clear for next call -    msg_mutex.unlock(); +    msg_rs().handler(msg_rs().type, msg_rs().ss.str()); +    msg_rs().ss.str(""); //clear for next call +    msg_rs().mutex.unlock();  }  std::ostream & uhd::msg::_msg::operator()(void){ -    return msg_ss; +    return msg_rs().ss;  } diff --git a/host/usrp_e_utils/usrp-e-utility.cpp b/host/usrp_e_utils/usrp-e-utility.cpp index b926cf49d..47a2c0900 100644 --- a/host/usrp_e_utils/usrp-e-utility.cpp +++ b/host/usrp_e_utils/usrp-e-utility.cpp @@ -64,9 +64,6 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){              "  usrp-e-utility --reclk --fpga=/usr/share/uhd/images/usrp_e1xx_pt_fpga.bin"          );          clock_genconfig_main(); -        if (std::system("rm /tmp/usrp*hash") != 0){ //clear hash so driver must reload -            std::cerr << "No hash to remove! Don't worry, its not a problem." << std::endl; -        }      }      std::cout << "Done!" << std::endl; | 
