diff options
43 files changed, 1389 insertions, 30 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f8adbb339..1db0f28e96 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,6 +117,14 @@ set(GRC_BLOCKS_DIR ${GR_PKG_DATA_DIR}/grc/blocks) set(SYSCONFDIR "${CMAKE_INSTALL_PREFIX}/${GR_CONF_DIR}" CACHE PATH "System configuration directory") set(GR_PREFSDIR ${SYSCONFDIR}/${CMAKE_PROJECT_NAME}/conf.d) +OPTION(ENABLE_PERFORMANCE_COUNTERS "Enable block performance counters" OFF) +if(ENABLE_PERFORMANCE_COUNTERS) + message(STATUS "ADDING PERF COUNTERS") + add_definitions(-DGR_PERFORMANCE_COUNTERS) +else(ENABLE_PERFORMANCE_COUNTERS) + message(STATUS "NO PERF COUNTERS") +endif(ENABLE_PERFORMANCE_COUNTERS) + ######################################################################## # Variables replaced when configuring the package config files ######################################################################## diff --git a/cmake/Modules/GrBoost.cmake b/cmake/Modules/GrBoost.cmake index 23bea41add..dfd17fc24c 100644 --- a/cmake/Modules/GrBoost.cmake +++ b/cmake/Modules/GrBoost.cmake @@ -34,9 +34,9 @@ set(BOOST_REQUIRED_COMPONENTS thread ) -if(UNIX AND EXISTS "/usr/lib64") +if(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64") list(APPEND BOOST_LIBRARYDIR "/usr/lib64") #fedora 64-bit fix -endif(UNIX AND EXISTS "/usr/lib64") +endif(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64") if(MSVC) if (NOT DEFINED BOOST_ALL_DYN_LINK) @@ -50,14 +50,38 @@ if(MSVC) endif(BOOST_ALL_DYN_LINK) endif(MSVC) -# Boost 1.52 disabled, see https://svn.boost.org/trac/boost/ticket/7669 +find_package(Boost "1.35" COMPONENTS ${BOOST_REQUIRED_COMPONENTS}) + +# This does not allow us to disable specific versions. It is used +# internally by cmake to know the formation newer versions. As newer +# Boost version beyond what is shown here are produced, we must extend +# this list. To disable Boost versions, see below. set(Boost_ADDITIONAL_VERSIONS "1.35.0" "1.35" "1.36.0" "1.36" "1.37.0" "1.37" "1.38.0" "1.38" "1.39.0" "1.39" "1.40.0" "1.40" "1.41.0" "1.41" "1.42.0" "1.42" "1.43.0" "1.43" "1.44.0" "1.44" "1.45.0" "1.45" "1.46.0" "1.46" "1.47.0" "1.47" "1.48.0" "1.48" "1.49.0" "1.49" - "1.50.0" "1.50" "1.51.0" "1.51" "1.53.0" "1.53" "1.54.0" "1.54" + "1.50.0" "1.50" "1.51.0" "1.51" "1.52.0" "1.52" "1.53.0" "1.53" "1.54.0" "1.54" "1.55.0" "1.55" "1.56.0" "1.56" "1.57.0" "1.57" "1.58.0" "1.58" "1.59.0" "1.59" "1.60.0" "1.60" "1.61.0" "1.61" "1.62.0" "1.62" "1.63.0" "1.63" "1.64.0" "1.64" "1.65.0" "1.65" "1.66.0" "1.66" "1.67.0" "1.67" "1.68.0" "1.68" "1.69.0" "1.69" ) -find_package(Boost "1.35" COMPONENTS ${BOOST_REQUIRED_COMPONENTS}) + +# Boost 1.52 disabled, see https://svn.boost.org/trac/boost/ticket/7669 +# Similar problems with Boost 1.46 and 1.47. + +# For any unsuitable Boost version, add the version number below in +# the following format: XXYYZZ +# Where: +# XX is the major version ('10' for version 1) +# YY is the minor version number ('46' for 1.46) +# ZZ is the patcher version number (typically just '00') +set(Boost_NOGO_VERSIONS + 104600 104700 105200 +) + +foreach(ver ${Boost_NOGO_VERSIONS}) + if(${Boost_VERSION} EQUAL ${ver}) + MESSAGE(STATUS "Found incompatible Boost (version ${Boost_VERSION}). Disabling.") + set(Boost_FOUND FALSE) + endif(${Boost_VERSION} EQUAL ${ver}) +endforeach(ver) diff --git a/cmake/Packaging/Fedora-18.cmake b/cmake/Packaging/Fedora-18.cmake new file mode 100644 index 0000000000..2e9e78ee11 --- /dev/null +++ b/cmake/Packaging/Fedora-18.cmake @@ -0,0 +1,12 @@ +SET(PACKAGE_DEPENDS_GRUEL_RUNTIME "boost-python" "glibc") +SET(PACKAGE_DEPENDS_GRUEL_PYTHON "python") +SET(PACKAGE_DEPENDS_CORE_RUNTIME "fftw-libs") +SET(PACKAGE_DEPENDS_QTGUI_RUNTIME "qt" "qwt") +SET(PACKAGE_DEPENDS_QTGUI_PYTHON "PyQt4" "PyQwt") +SET(PACKAGE_DEPENDS_GRC "python" "numpy" "gtk2" "python-lxml" "python-cheetah") +SET(PACKAGE_DEPENDS_WXGUI "wxGTK" "python" "numpy") +SET(PACKAGE_DEPENDS_VIDEO_SDL_RUNTIME "SDL") +SET(PACKAGE_DEPENDS_UHD_RUNTIME "uhd") +SET(PACKAGE_DEPENDS_AUDIO_RUNTIME "pulseaudio" "alsa-lib" "jack-audio-connection-kit") +SET(PACKAGE_DEPENDS_WAVELET_RUNTIME "gsl") +SET(PACKAGE_DEPENDS_WAVELET_PYTHON "python" "numpy") diff --git a/docs/doxygen/other/thread_affinity.dox b/docs/doxygen/other/thread_affinity.dox new file mode 100644 index 0000000000..fbbc449a4a --- /dev/null +++ b/docs/doxygen/other/thread_affinity.dox @@ -0,0 +1,65 @@ +/*! \page page_affinity Block Thread Affinity + +\section intro Introduction + +In the thread-per-block scheduler, you can set the block's core +affinity. Each block can be pinned to a group cores or be set back +to use the standard kernel scheduler. + +The implementation is done by adding new functions to the GRUEL +library: + +\code + gr_thread_t get_current_thread_id(); + void thread_bind_to_processor(unsigned int n); + void thread_bind_to_processor(const std::vector<unsigned int> &mask); + void thread_bind_to_processor(gr_thread_t thread, unsigned int n); + void thread_bind_to_processor(gr_thread_t thread, const std::vector<unsigned int> &mask); + void thread_unbind(); + void thread_unbind(gr_thread_t thread); +\endcode + +The ability to set a thread's affinity to a core or groups of cores is +not implemented in the Boost thread library, and so we have made our +own portability library. In particular, the gruel::gr_thread_t type is +defined as the thread type for the given system. The other functions +are designed to be portable as well by calling the specific +implementation for the thread affinity for a particular platform. + +There are functions to set a thread to a group of cores. If the thread +is not given, the current thread is used. If a single number is +passed, only that core is set (this is equivalent to a core mask with +just a single value). + +Similarly, there are functions to unset the affinity. This practically +implements the setting of the thread's affinity to all possible +cores. Again, the function that does not take a thread argument unsets +the affinity for the current thread. + + +\section api GNU Radio Block API + +Each block has two new data members: + +- threaded: a boolean value that is true if the block is attached to a + thread. +- thread: a gruel::gr_thread_t handle to the block's thread. + +A block can set and unset it's affinity at any time using the +following member functions: + +- gr_block::set_processor_affinity(const std::vector<unsigned int> &mask) +- gr_block::unset_processor_affinity() + +Where \p mask is a vector of core numbers to set the thread's affinity +to. + +The current core affinity can be retrieved using the member function: + +- gr_block::processor_affinity() + +When set before the flowgraph is started, the scheduler will set the +thread's affinity when it is started. When already running, the +block's affinity will be immediately set. + +*/ diff --git a/gnuradio-core/src/examples/mp-sched/CMakeLists.txt b/gnuradio-core/src/examples/mp-sched/CMakeLists.txt index dc47d17f9e..d2d910ecf2 100644 --- a/gnuradio-core/src/examples/mp-sched/CMakeLists.txt +++ b/gnuradio-core/src/examples/mp-sched/CMakeLists.txt @@ -20,6 +20,7 @@ include(GrPython) GR_PYTHON_INSTALL(PROGRAMS + affinity_set.py plot_flops.py run_synthetic.py synthetic.py diff --git a/gnuradio-core/src/examples/mp-sched/affinity_set.py b/gnuradio-core/src/examples/mp-sched/affinity_set.py new file mode 100755 index 0000000000..6db632e0fa --- /dev/null +++ b/gnuradio-core/src/examples/mp-sched/affinity_set.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python +################################################## +# Gnuradio Python Flow Graph +# Title: Affinity Set Test +################################################## + +from gnuradio import eng_notation +from gnuradio import gr +from gnuradio.eng_option import eng_option +from gnuradio.gr import firdes +from optparse import OptionParser +import sys + +class affinity_set(gr.top_block): + + def __init__(self): + gr.top_block.__init__(self, "Affinity Set Test") + + ################################################## + # Variables + ################################################## + self.samp_rate = samp_rate = 32000 + + ################################################## + # Blocks + ################################################## + vec_len = 1 + self.gr_throttle_0 = gr.throttle(gr.sizeof_gr_complex*vec_len, samp_rate) + self.gr_null_source_0 = gr.null_source(gr.sizeof_gr_complex*vec_len) + self.gr_null_sink_0 = gr.null_sink(gr.sizeof_gr_complex*vec_len) + self.gr_filt_0 = gr.fir_filter_ccc(1, 40000*[0.2+0.3j,]) + self.gr_filt_1 = gr.fir_filter_ccc(1, 40000*[0.2+0.3j,]) + + self.gr_filt_0.set_processor_affinity([0,]) + self.gr_filt_1.set_processor_affinity([0,1]) + + ################################################## + # Connections + ################################################## + self.connect((self.gr_null_source_0, 0), (self.gr_throttle_0, 0)) + self.connect((self.gr_throttle_0, 0), (self.gr_filt_0, 0)) + self.connect((self.gr_filt_0, 0), (self.gr_filt_1, 0)) + self.connect((self.gr_filt_1, 0), (self.gr_null_sink_0, 0)) + + + # QT sink close method reimplementation + + def get_samp_rate(self): + return self.samp_rate + + def set_samp_rate(self, samp_rate): + self.samp_rate = samp_rate + +if __name__ == '__main__': + parser = OptionParser(option_class=eng_option, usage="%prog: [options]") + (options, args) = parser.parse_args() + tb = affinity_set() + tb.start() + + while(1): + ret = raw_input('Press Enter to quit: ') + if(len(ret) == 0): + tb.stop() + sys.exit(0) + elif(ret.lower() == "none"): + tb.gr_filt_0.unset_processor_affinity() + else: + try: + n = int(ret) + except ValueError: + print "Invalid number" + else: + tb.gr_filt_0.set_processor_affinity([n,]) diff --git a/gnuradio-core/src/lib/general/CMakeLists.txt b/gnuradio-core/src/lib/general/CMakeLists.txt index 4c99acfc36..ce9a80f377 100644 --- a/gnuradio-core/src/lib/general/CMakeLists.txt +++ b/gnuradio-core/src/lib/general/CMakeLists.txt @@ -259,6 +259,7 @@ set(gr_core_general_triple_threats gr_pwr_squelch_cc gr_pwr_squelch_ff gr_quadrature_demod_cf + gr_random_pdu gr_rail_ff gr_regenerate_bb gr_remez diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i index 1446088a2c..b727bc8a6f 100644 --- a/gnuradio-core/src/lib/general/general.i +++ b/gnuradio-core/src/lib/general/general.i @@ -70,6 +70,7 @@ #include <gr_agc_cc.h> #include <gr_agc2_ff.h> #include <gr_agc2_cc.h> +#include <gr_random_pdu.h> #include <gr_rms_cf.h> #include <gr_rms_ff.h> #include <gr_nlog10_ff.h> @@ -194,6 +195,7 @@ %include "gr_agc_cc.i" %include "gr_agc2_ff.i" %include "gr_agc2_cc.i" +%include "gr_random_pdu.i" %include "gr_rms_cf.i" %include "gr_rms_ff.i" %include "gr_nlog10_ff.i" diff --git a/gnuradio-core/src/lib/gengen/CMakeLists.txt b/gnuradio-core/src/lib/gengen/CMakeLists.txt index b44a470750..db3103a26a 100644 --- a/gnuradio-core/src/lib/gengen/CMakeLists.txt +++ b/gnuradio-core/src/lib/gengen/CMakeLists.txt @@ -85,6 +85,7 @@ expand_h_cc_i(gr_vector_source_X b s i f c) expand_h_cc_i(gr_vector_insert_X b) expand_h_cc_i(gr_vector_sink_X b s i f c) expand_h_cc_i(gr_noise_source_X s i f c) +expand_h_cc_i(gr_fastnoise_source_X s i f c) expand_h_cc_i(gr_sig_source_X s i f c) expand_h_cc_i(gr_probe_signal_X b s i f c) expand_h_cc_i(gr_probe_signal_vX b s i f c) diff --git a/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.cc.t b/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.cc.t new file mode 100644 index 0000000000..7be7bdde86 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.cc.t @@ -0,0 +1,116 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <@NAME@.h> +#include <gr_io_signature.h> +#include <stdexcept> + + +@NAME@_sptr +gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed, long samples) +{ + return gnuradio::get_initial_sptr(new @NAME@ (type, ampl, seed, samples)); +} + + +@NAME@::@NAME@ (gr_noise_type_t type, float ampl, long seed, long samples) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, sizeof (@TYPE@))), + d_type (type), + d_ampl (ampl), + d_rng (seed) +{ + d_samples.resize(samples); + generate(); +} + +void +@NAME@::generate() +{ + int noutput_items = d_samples.size(); + switch (d_type){ +#if @IS_COMPLEX@ // complex? + + case GR_UNIFORM: + for (int i = 0; i < noutput_items; i++) + d_samples[i] = gr_complex (d_ampl * ((d_rng.ran1 () * 2.0) - 1.0), + d_ampl * ((d_rng.ran1 () * 2.0) - 1.0)); + break; + + case GR_GAUSSIAN: + for (int i = 0; i < noutput_items; i++) + d_samples[i] = d_ampl * d_rng.rayleigh_complex (); + break; + +#else // nope... + + case GR_UNIFORM: + for (int i = 0; i < noutput_items; i++) + d_samples[i] = (@TYPE@)(d_ampl * ((d_rng.ran1 () * 2.0) - 1.0)); + break; + + case GR_GAUSSIAN: + for (int i = 0; i < noutput_items; i++) + d_samples[i] = (@TYPE@)(d_ampl * d_rng.gasdev ()); + break; + + case GR_LAPLACIAN: + for (int i = 0; i < noutput_items; i++) + d_samples[i] = (@TYPE@)(d_ampl * d_rng.laplacian ()); + break; + + case GR_IMPULSE: // FIXME changeable impulse settings + for (int i = 0; i < noutput_items; i++) + d_samples[i] = (@TYPE@)(d_ampl * d_rng.impulse (9)); + break; +#endif + + default: + throw std::runtime_error ("invalid type"); + } + +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @TYPE@ *out = (@TYPE@ *) output_items[0]; + + for(int i=0; i<noutput_items; i++){ +#ifdef __USE_GNU + size_t idx = lrand48() % d_samples.size(); +#else + size_t idx = rand() % d_samples.size(); +#endif + out[i] = d_samples[idx]; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.h.t b/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.h.t new file mode 100644 index 0000000000..007e449759 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.h.t @@ -0,0 +1,87 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_noise_type.h> +#include <gr_random.h> + + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @NAME@_sptr; + +/*! \brief Make a noise source + * \param type the random distribution to use (see gr_noise_type.h) + * \param ampl a scaling factor for the output + * \param seed seed for random generators. Note that for uniform and + * Gaussian distributions, this should be a negative number. + * \param samples number of samples to pre-generate. + */ +GR_CORE_API @NAME@_sptr +gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed = 0, long samples=1024*16); + +/*! + * \brief Random number source + * \ingroup source_blk + * + * \details + * Generate random values from different distributions. + * Currently, only Gaussian and uniform are enabled. + * + * \param type the random distribution to use (see gr_noise_type.h) + * \param ampl a scaling factor for the output + * \param seed seed for random generators. Note that for uniform and + * Gaussian distributions, this should be a negative number. + * \param samples number of samples to pre-generate. + */ +class GR_CORE_API @NAME@ : public gr_sync_block { + friend GR_CORE_API @NAME@_sptr + + gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed, long samples); + + gr_noise_type_t d_type; + float d_ampl; + gr_random d_rng; + std::vector<@TYPE@> d_samples; + + @NAME@ (gr_noise_type_t type, float ampl, long seed = 0, long samples=1024*16); + + public: + void set_type (gr_noise_type_t type) { d_type = type; generate(); } + void set_amplitude (float ampl) { d_ampl = ampl; generate(); } + void generate(); + + gr_noise_type_t type () const { return d_type; } + float amplitude () const { return d_ampl; } + + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif diff --git a/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.i.t b/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.i.t new file mode 100644 index 0000000000..e1f7c775be --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.i.t @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@); + +@NAME@_sptr +gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed = 0, long samples = 1024*16); + +class @NAME@ : public gr_block { + private: + @NAME@ (gr_noise_type_t type, float ampl, long seed = 0, long samples = 1024*16); + + public: + void set_type (gr_noise_type_t type) { d_type = type; } + void set_amplitude (float ampl) { d_ampl = ampl; } + + gr_noise_type_t type () const { return d_type; } + float amplitude () const { return d_ampl; } +}; diff --git a/gnuradio-core/src/lib/hier/gr_channel_model.cc b/gnuradio-core/src/lib/hier/gr_channel_model.cc index bb01972d29..7da3578093 100644 --- a/gnuradio-core/src/lib/hier/gr_channel_model.cc +++ b/gnuradio-core/src/lib/hier/gr_channel_model.cc @@ -59,7 +59,7 @@ gr_channel_model::gr_channel_model(double noise_voltage, d_multipath = gr_make_fir_filter_ccc(1, d_taps); d_noise_adder = gr_make_add_cc(); - d_noise = gr_make_noise_source_c(GR_GAUSSIAN, noise_voltage, noise_seed); + d_noise = gr_make_fastnoise_source_c(GR_GAUSSIAN, noise_voltage, noise_seed, 1024*8); d_freq_offset = gr_make_sig_source_c(1, GR_SIN_WAVE, frequency_offset, 1.0, 0.0); d_mixer_offset = gr_make_multiply_cc(); diff --git a/gnuradio-core/src/lib/hier/gr_channel_model.h b/gnuradio-core/src/lib/hier/gr_channel_model.h index f0b31b1a67..5796a6db24 100644 --- a/gnuradio-core/src/lib/hier/gr_channel_model.h +++ b/gnuradio-core/src/lib/hier/gr_channel_model.h @@ -25,7 +25,7 @@ #include <gr_sig_source_c.h> #include <gr_fir_filter_ccc.h> #include <gr_add_cc.h> -#include <gr_noise_source_c.h> +#include <gr_fastnoise_source_c.h> #include <gr_multiply_cc.h> class gr_channel_model; @@ -61,7 +61,7 @@ class GR_CORE_API gr_channel_model : public gr_hier_block2 gr_sig_source_c_sptr d_freq_offset; gr_fir_filter_ccc_sptr d_multipath; gr_add_cc_sptr d_noise_adder; - gr_noise_source_c_sptr d_noise; + gr_fastnoise_source_c_sptr d_noise; gr_multiply_cc_sptr d_mixer_offset; std::vector<gr_complex> d_taps; diff --git a/gnuradio-core/src/lib/io/gr_file_source.cc b/gnuradio-core/src/lib/io/gr_file_source.cc index 09f3986cd2..f3def0721b 100644 --- a/gnuradio-core/src/lib/io/gr_file_source.cc +++ b/gnuradio-core/src/lib/io/gr_file_source.cc @@ -89,7 +89,7 @@ gr_file_source::work (int noutput_items, if(d_fp == NULL) throw std::runtime_error("work with file not open"); - boost::mutex::scoped_lock lock(fp_mutex); // hold for the rest of this function + gruel::scoped_lock lock(fp_mutex); // hold for the rest of this function while (size) { i = fread(o, d_itemsize, size, (FILE *) d_fp); @@ -129,7 +129,7 @@ bool gr_file_source::seek (long seek_point, int whence) { // obtain exclusive access for duration of this function - boost::mutex::scoped_lock lock(fp_mutex); + gruel::scoped_lock lock(fp_mutex); return fseek((FILE *) d_fp, seek_point * d_itemsize, whence) == 0; } @@ -137,7 +137,7 @@ void gr_file_source::open(const char *filename, bool repeat) { // obtain exclusive access for duration of this function - boost::mutex::scoped_lock lock(fp_mutex); + gruel::scoped_lock lock(fp_mutex); int fd; @@ -166,7 +166,7 @@ void gr_file_source::close() { // obtain exclusive access for duration of this function - boost::mutex::scoped_lock lock(fp_mutex); + gruel::scoped_lock lock(fp_mutex); if(d_new_fp != NULL) { fclose(d_new_fp); @@ -179,7 +179,7 @@ void gr_file_source::do_update() { if(d_updated) { - boost::mutex::scoped_lock lock(fp_mutex); // hold while in scope + gruel::scoped_lock lock(fp_mutex); // hold while in scope if(d_fp) fclose(d_fp); diff --git a/gnuradio-core/src/lib/runtime/gr_block.cc b/gnuradio-core/src/lib/runtime/gr_block.cc index 5ba30955f9..fd82ab580e 100644 --- a/gnuradio-core/src/lib/runtime/gr_block.cc +++ b/gnuradio-core/src/lib/runtime/gr_block.cc @@ -251,6 +251,101 @@ gr_block::is_set_max_noutput_items() return d_max_noutput_items_set; } +void +gr_block::set_processor_affinity(const std::vector<unsigned int> &mask) +{ + d_affinity = mask; + if(d_detail) { + d_detail->set_processor_affinity(d_affinity); + } +} + +void +gr_block::unset_processor_affinity() +{ + d_affinity.clear(); + if(d_detail) { + d_detail->unset_processor_affinity(); + } +} + +float +gr_block::pc_noutput_items() +{ + if(d_detail) { + return d_detail->pc_noutput_items(); + } + else { + return 0; + } +} + +float +gr_block::pc_nproduced() +{ + if(d_detail) { + return d_detail->pc_nproduced(); + } + else { + return 0; + } +} + +float +gr_block::pc_input_buffers_full(int which) +{ + if(d_detail) { + return d_detail->pc_input_buffers_full(static_cast<size_t>(which)); + } + else { + return 0; + } +} + +std::vector<float> +gr_block::pc_input_buffers_full() +{ + if(d_detail) { + return d_detail->pc_input_buffers_full(); + } + else { + return std::vector<float>(1,0); + } +} + +float +gr_block::pc_output_buffers_full(int which) +{ + if(d_detail) { + return d_detail->pc_output_buffers_full(static_cast<size_t>(which)); + } + else { + return 0; + } +} + +std::vector<float> +gr_block::pc_output_buffers_full() +{ + if(d_detail) { + return d_detail->pc_output_buffers_full(); + } + else { + return std::vector<float>(1,0); + } +} + +float +gr_block::pc_work_time() +{ + if(d_detail) { + return d_detail->pc_work_time(); + } + else { + return 0; + } +} + std::ostream& operator << (std::ostream& os, const gr_block *m) { diff --git a/gnuradio-core/src/lib/runtime/gr_block.h b/gnuradio-core/src/lib/runtime/gr_block.h index 7a70bdaf09..c9d2d8f530 100644 --- a/gnuradio-core/src/lib/runtime/gr_block.h +++ b/gnuradio-core/src/lib/runtime/gr_block.h @@ -358,6 +358,64 @@ class GR_CORE_API gr_block : public gr_basic_block { d_min_output_buffer[port] = min_output_buffer; } + // --------------- Performance counter functions ------------- + + /*! + * \brief Gets average noutput_items performance counter. + */ + float pc_noutput_items(); + + /*! + * \brief Gets average num items produced performance counter. + */ + float pc_nproduced(); + + /*! + * \brief Gets average average fullness of \p which input buffer. + */ + float pc_input_buffers_full(int which); + + /*! + * \brief Gets average fullness of all input buffers. + */ + std::vector<float> pc_input_buffers_full(); + + /*! + * \brief Gets average fullness of \p which input buffer. + */ + float pc_output_buffers_full(int which); + + /*! + * \brief Gets average fullness of all output buffers. + */ + std::vector<float> pc_output_buffers_full(); + + /*! + * \brief Gets average clock cycles spent in work. + */ + float pc_work_time(); + + + // ---------------------------------------------------------------------------- + // Functions to handle thread affinity + + /*! + * \brief Set the thread's affinity to processor core \p n. + * + * \param mask a vector of unsigned ints of the core numbers available to this block. + */ + void set_processor_affinity(const std::vector<unsigned int> &mask); + + /*! + * \brief Remove processor affinity to a specific core. + */ + void unset_processor_affinity(); + + /*! + * \brief Get the current processor affinity. + */ + std::vector<unsigned int> processor_affinity() { return d_affinity; } + // ---------------------------------------------------------------------------- private: @@ -373,6 +431,7 @@ class GR_CORE_API gr_block : public gr_basic_block { bool d_max_noutput_items_set; // if d_max_noutput_items is valid int d_max_noutput_items; // value of max_noutput_items for this block tag_propagation_policy_t d_tag_propagation_policy; // policy for moving tags downstream + std::vector<unsigned int> d_affinity; // thread affinity proc. mask protected: gr_block (void){} //allows pure virtual interface sub-classes diff --git a/gnuradio-core/src/lib/runtime/gr_block.i b/gnuradio-core/src/lib/runtime/gr_block.i index db6c1d04a7..c016f2c28e 100644 --- a/gnuradio-core/src/lib/runtime/gr_block.i +++ b/gnuradio-core/src/lib/runtime/gr_block.i @@ -66,6 +66,20 @@ class gr_block : public gr_basic_block { void set_min_output_buffer(long min_output_buffer); void set_min_output_buffer(int port, long min_output_buffer); + // Methods to access performance counters + float pc_noutput_items(); + float pc_nproduced(); + float pc_input_buffers_full(int which); + std::vector<float> pc_input_buffers_full(); + float pc_output_buffers_full(int which); + std::vector<float> pc_output_buffers_full(); + float pc_work_time(); + + // Methods to manage processor affinity. + void set_processor_affinity(const gr_vector_uint &mask); + void unset_processor_affinity(); + gr_vector_uint processor_affinity(); + // internal use gr_block_detail_sptr detail () const { return d_detail; } void set_detail (gr_block_detail_sptr detail) { d_detail = detail; } diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.cc b/gnuradio-core/src/lib/runtime/gr_block_detail.cc index c65493473c..ff20e0e85a 100644 --- a/gnuradio-core/src/lib/runtime/gr_block_detail.cc +++ b/gnuradio-core/src/lib/runtime/gr_block_detail.cc @@ -26,6 +26,7 @@ #include <gr_block_detail.h> #include <gr_buffer.h> +#include <iostream> using namespace pmt; @@ -41,7 +42,11 @@ gr_block_detail::gr_block_detail (unsigned int ninputs, unsigned int noutputs) : d_produce_or(0), d_ninputs (ninputs), d_noutputs (noutputs), d_input (ninputs), d_output (noutputs), - d_done (false) + d_done (false), + d_avg_noutput_items(0), d_avg_nproduced(0), + d_avg_input_buffers_full(ninputs, 0), + d_avg_output_buffers_full(noutputs, 0), + d_avg_work_time(0) { s_ncurrently_allocated++; } @@ -201,3 +206,104 @@ gr_block_detail::get_tags_in_range(std::vector<gr_tag_t> &v, } } } + +void +gr_block_detail::set_processor_affinity(const std::vector<unsigned int> &mask) +{ + if(threaded) { + try { + gruel::thread_bind_to_processor(thread, mask); + } + catch (std::runtime_error e) { + std::cerr << "set_processor_affinity: invalid mask." << std::endl;; + } + } +} + +void +gr_block_detail::unset_processor_affinity() +{ + if(threaded) { + gruel::thread_unbind(thread); + } +} + +void +gr_block_detail::start_perf_counters() +{ + d_start_of_work = gruel::high_res_timer_now(); +} + +void +gr_block_detail::stop_perf_counters(int noutput_items, int nproduced) +{ + float alpha = 0.05; + float beta = 1.0-alpha; + + d_end_of_work = gruel::high_res_timer_now(); + gruel::high_res_timer_type diff = d_end_of_work - d_start_of_work; + d_avg_work_time = beta*d_avg_work_time + alpha*diff; + + d_avg_nproduced = beta*d_avg_nproduced + alpha*nproduced; + d_avg_noutput_items = beta*d_avg_noutput_items + alpha*noutput_items; + + for(size_t i=0; i < d_input.size(); i++) { + float pfull = static_cast<float>(d_input[i]->items_available()) / + static_cast<float>(d_input[i]->max_possible_items_available()); + d_avg_input_buffers_full[i] = beta*d_avg_input_buffers_full[i] + alpha*pfull; + } + + for(size_t i=0; i < d_output.size(); i++) { + float pfull = 1.0f - static_cast<float>(d_output[i]->space_available()) / + static_cast<float>(d_output[i]->bufsize()); + d_avg_output_buffers_full[i] = beta*d_avg_output_buffers_full[i] + alpha*pfull; + } +} + +float +gr_block_detail::pc_noutput_items() +{ + return d_avg_noutput_items; +} + +float +gr_block_detail::pc_nproduced() +{ + return d_avg_nproduced; +} + +float +gr_block_detail::pc_input_buffers_full(size_t which) +{ + if(which < d_avg_input_buffers_full.size()) + return d_avg_input_buffers_full[which]; + else + return 0; +} + +std::vector<float> +gr_block_detail::pc_input_buffers_full() +{ + return d_avg_input_buffers_full; +} + +float +gr_block_detail::pc_output_buffers_full(size_t which) +{ + if(which < d_avg_output_buffers_full.size()) + return d_avg_output_buffers_full[which]; + else + return 0; +} + +std::vector<float> +gr_block_detail::pc_output_buffers_full() +{ + return d_avg_output_buffers_full; +} + +float +gr_block_detail::pc_work_time() +{ + return d_avg_work_time; +} diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.h b/gnuradio-core/src/lib/runtime/gr_block_detail.h index af00ea7c79..a8ed8da908 100644 --- a/gnuradio-core/src/lib/runtime/gr_block_detail.h +++ b/gnuradio-core/src/lib/runtime/gr_block_detail.h @@ -27,6 +27,7 @@ #include <gr_runtime_types.h> #include <gr_tpb_detail.h> #include <gr_tags.h> +#include <gruel/high_res_timer.h> #include <stdexcept> /*! @@ -155,6 +156,33 @@ class GR_CORE_API gr_block_detail { uint64_t abs_end, const pmt::pmt_t &key); + /*! + * \brief Set core affinity of block to the cores in the vector mask. + * + * \param mask a vector of unsigned ints of the core numbers available to this block. + */ + void set_processor_affinity(const std::vector<unsigned int> &mask); + + /*! + * \brief Unset core affinity. + */ + void unset_processor_affinity(); + + bool threaded; // set if thread is currently running. + gruel::gr_thread_t thread; // portable thread handle + + void start_perf_counters(); + void stop_perf_counters(int noutput_items, int nproduced); + + // Calls to get performance counter items + float pc_noutput_items(); + float pc_nproduced(); + float pc_input_buffers_full(size_t which); + std::vector<float> pc_input_buffers_full(); + float pc_output_buffers_full(size_t which); + std::vector<float> pc_output_buffers_full(); + float pc_work_time(); + gr_tpb_detail d_tpb; // used by thread-per-block scheduler int d_produce_or; @@ -167,6 +195,14 @@ class GR_CORE_API gr_block_detail { std::vector<gr_buffer_sptr> d_output; bool d_done; + // Performance counters + float d_avg_noutput_items; + float d_avg_nproduced; + std::vector<float> d_avg_input_buffers_full; + std::vector<float> d_avg_output_buffers_full; + gruel::high_res_timer_type d_start_of_work, d_end_of_work; + float d_avg_work_time; + gr_block_detail (unsigned int ninputs, unsigned int noutputs); friend struct gr_tpb_detail; diff --git a/gnuradio-core/src/lib/runtime/gr_block_executor.cc b/gnuradio-core/src/lib/runtime/gr_block_executor.cc index 375b58f563..ee0ab9e378 100644 --- a/gnuradio-core/src/lib/runtime/gr_block_executor.cc +++ b/gnuradio-core/src/lib/runtime/gr_block_executor.cc @@ -420,9 +420,18 @@ gr_block_executor::run_one_iteration() for (int i = 0; i < d->ninputs(); i++) d_start_nitems_read[i] = d->nitems_read(i); +#ifdef GR_PERFORMANCE_COUNTERS + d->start_perf_counters(); +#endif /* GR_PERFORMANCE_COUNTERS */ + // Do the actual work of the block int n = m->general_work (noutput_items, d_ninput_items, d_input_items, d_output_items); + +#ifdef GR_PERFORMANCE_COUNTERS + d->stop_perf_counters(noutput_items, n); +#endif /* GR_PERFORMANCE_COUNTERS */ + LOG(*d_log << " general_work: noutput_items = " << noutput_items << " result = " << n << std::endl); diff --git a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc index 9f17a48a80..cea374fac7 100644 --- a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc +++ b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc @@ -38,6 +38,13 @@ gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block, int max_noutput_item gr_block_executor::state s; pmt_t msg; + d->threaded = true; + d->thread = gruel::get_current_thread_id(); + + // Set thread affinity if it was set before fg was started. + if(block->processor_affinity().size() > 0) { + gruel::thread_bind_to_processor(d->thread, block->processor_affinity()); + } while (1){ boost::this_thread::interruption_point(); diff --git a/gnuradio-core/src/lib/runtime/gr_types.h b/gnuradio-core/src/lib/runtime/gr_types.h index ad6cee7682..db13e456aa 100644 --- a/gnuradio-core/src/lib/runtime/gr_types.h +++ b/gnuradio-core/src/lib/runtime/gr_types.h @@ -31,6 +31,7 @@ #include <gr_complex.h> typedef std::vector<int> gr_vector_int; +typedef std::vector<unsigned int> gr_vector_uint; typedef std::vector<float> gr_vector_float; typedef std::vector<double> gr_vector_double; typedef std::vector<void *> gr_vector_void_star; diff --git a/gnuradio-core/src/lib/runtime/qa_gr_top_block.cc b/gnuradio-core/src/lib/runtime/qa_gr_top_block.cc index a0b4755a80..1d3dafadf8 100644 --- a/gnuradio-core/src/lib/runtime/qa_gr_top_block.cc +++ b/gnuradio-core/src/lib/runtime/qa_gr_top_block.cc @@ -262,3 +262,24 @@ void qa_gr_top_block::t10_reconfig_max_output_buffer() // Wait for flowgraph to end on its own tb->wait(); } + +void qa_gr_top_block::t11_set_block_affinity() +{ + gr_top_block_sptr tb = gr_make_top_block("top"); + gr_block_sptr src (gr_make_null_source(sizeof(float))); + gr_block_sptr snk (gr_make_null_sink(sizeof(float))); + + std::vector<unsigned int> set(1, 0), ret; + src->set_processor_affinity(set); + + tb->connect(src, 0, snk, 0); + tb->start(); + tb->stop(); + tb->wait(); + + ret = src->processor_affinity(); + + // We only set the core affinity to 0 because we always know at + // least one thread core exists to use. + CPPUNIT_ASSERT_EQUAL(set[0], ret[0]); +} diff --git a/gnuradio-core/src/lib/runtime/qa_gr_top_block.h b/gnuradio-core/src/lib/runtime/qa_gr_top_block.h index bb891abca6..634eeab1f8 100644 --- a/gnuradio-core/src/lib/runtime/qa_gr_top_block.h +++ b/gnuradio-core/src/lib/runtime/qa_gr_top_block.h @@ -38,6 +38,11 @@ class qa_gr_top_block : public CppUnit::TestCase CPPUNIT_TEST(t4_reconfigure); // triggers 'join never returns' bug CPPUNIT_TEST(t5_max_noutputs); CPPUNIT_TEST(t6_reconfig_max_noutputs); + CPPUNIT_TEST(t7_max_noutputs_per_block); + CPPUNIT_TEST(t8_reconfig_max_noutputs_per_block); + CPPUNIT_TEST(t9_max_output_buffer); + CPPUNIT_TEST(t10_reconfig_max_output_buffer); + CPPUNIT_TEST(t11_set_block_affinity); CPPUNIT_TEST_SUITE_END(); @@ -54,6 +59,8 @@ private: void t8_reconfig_max_noutputs_per_block(); void t9_max_output_buffer(); void t10_reconfig_max_output_buffer(); + void t11_set_block_affinity(); + }; #endif /* INCLUDED_QA_GR_TOP_BLOCK_H */ diff --git a/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt index bd78c8fb4a..da22a5f987 100644 --- a/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt +++ b/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt @@ -29,6 +29,7 @@ GR_PYTHON_INSTALL(FILES gr_threading_24.py hier_block2.py prefs.py + tag_utils.py top_block.py pubsub.py DESTINATION ${GR_PYTHON_DIR}/gnuradio/gr diff --git a/gnuradio-core/src/python/gnuradio/gr/__init__.py b/gnuradio-core/src/python/gnuradio/gr/__init__.py index 5d01ea11b1..f1b971e62d 100644 --- a/gnuradio-core/src/python/gnuradio/gr/__init__.py +++ b/gnuradio-core/src/python/gnuradio/gr/__init__.py @@ -29,6 +29,7 @@ from exceptions import * from hier_block2 import * from top_block import * from gateway import basic_block, sync_block, decim_block, interp_block +from tag_utils import tag_to_python, tag_to_pmt # create a couple of aliases serial_to_parallel = stream_to_vector diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_tag_utils.py b/gnuradio-core/src/python/gnuradio/gr/qa_tag_utils.py new file mode 100755 index 0000000000..ca1184979b --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_tag_utils.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# +# Copyright 2007,2010 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import tag_utils + +try: + import pmt_swig as pmt +except ImportError: + import pmt + +class test_tag_utils (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + + def tearDown (self): + self.tb = None + + def test_001(self): + t = gr.gr_tag_t() + t.offset = 10 + t.key = pmt.pmt_string_to_symbol('key') + t.value = pmt.pmt_from_long(23) + t.srcid = pmt.pmt_from_bool(False) + pt = tag_utils.tag_to_python(t) + self.assertEqual(pt.key, 'key') + self.assertEqual(pt.value, 23) + self.assertEqual(pt.offset, 10) + + +if __name__ == '__main__': + print 'hi' + gr_unittest.run(test_tag_utils, "test_tag_utils.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/tag_utils.py b/gnuradio-core/src/python/gnuradio/gr/tag_utils.py new file mode 100644 index 0000000000..923718fc98 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/tag_utils.py @@ -0,0 +1,54 @@ +# +# Copyright 2003-2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# +""" Conversion tools between stream tags and Python objects """ + +try: import pmt +except: from gruel import pmt + +from gnuradio_core import gr_tag_t + +class PythonTag(object): + " Python container for tags " + def __init__(self): + self.offset = None + self.key = None + self.value = None + self.srcid = None + +def tag_to_python(tag): + """ Convert a stream tag to a Python-readable object """ + newtag = PythonTag() + newtag.offset = tag.offset + newtag.key = pmt.to_python(tag.key) + newtag.value = pmt.to_python(tag.value) + newtag.srcid = pmt.to_python(tag.srcid) + return newtag + +def tag_to_pmt(tag): + """ Convert a Python-readable object to a stream tag """ + newtag = gr_tag_t() + newtag.offset = tag.offset + newtag.key = pmt.to_python(tag.key) + newtag.value = pmt.from_python(tag.value) + newtag.srcid = pmt.from_python(tag.srcid) + return newtag + + diff --git a/gr-analog/include/analog/CMakeLists.txt b/gr-analog/include/analog/CMakeLists.txt index 4de94a88b3..b113dacc44 100644 --- a/gr-analog/include/analog/CMakeLists.txt +++ b/gr-analog/include/analog/CMakeLists.txt @@ -75,11 +75,12 @@ add_custom_target(analog_generated_includes DEPENDS # Install header files ######################################################################## install(FILES - ${analog_generated_includes} + ${generated_includes} api.h cpm.h agc.h agc2.h + noise_type.h squelch_base_ff.h agc_cc.h agc_ff.h diff --git a/gr-analog/lib/ctcss_squelch_ff_impl.cc b/gr-analog/lib/ctcss_squelch_ff_impl.cc index db49b4f6ee..60cd94fdb5 100644 --- a/gr-analog/lib/ctcss_squelch_ff_impl.cc +++ b/gr-analog/lib/ctcss_squelch_ff_impl.cc @@ -115,11 +115,12 @@ namespace gr { d_goertzel_c.input(in); d_goertzel_r.input(in); + float rounder = 100000; float d_out_l, d_out_c, d_out_r; if(d_goertzel_c.ready()) { - d_out_l = abs(d_goertzel_l.output()); - d_out_c = abs(d_goertzel_c.output()); - d_out_r = abs(d_goertzel_r.output()); + d_out_l = floor(rounder*abs(d_goertzel_l.output()))/rounder; + d_out_c = floor(rounder*abs(d_goertzel_c.output()))/rounder; + d_out_r = floor(rounder*abs(d_goertzel_r.output()))/rounder; //printf("d_out_l=%f d_out_c=%f d_out_r=%f\n", d_out_l, d_out_c, d_out_r); d_mute = (d_out_c < d_level || d_out_c < d_out_l || d_out_c < d_out_r); diff --git a/gr-analog/swig/CMakeLists.txt b/gr-analog/swig/CMakeLists.txt index 9ed82e2677..4391e5e09a 100644 --- a/gr-analog/swig/CMakeLists.txt +++ b/gr-analog/swig/CMakeLists.txt @@ -33,7 +33,7 @@ set(GR_SWIG_INCLUDE_DIRS set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/analog_swig_doc.i) set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../lib) - +set(GR_SWIG_TARGET_DEPS analog_generated_includes) set(GR_SWIG_LIBRARIES gnuradio-analog gnuradio-filter) GR_SWIG_MAKE(analog_swig analog_swig.i) diff --git a/gr-blocks/lib/file_source_impl.cc b/gr-blocks/lib/file_source_impl.cc index ed1f50c435..a8db31be7a 100644 --- a/gr-blocks/lib/file_source_impl.cc +++ b/gr-blocks/lib/file_source_impl.cc @@ -84,7 +84,7 @@ namespace gr { file_source_impl::open(const char *filename, bool repeat) { // obtain exclusive access for duration of this function - boost::mutex::scoped_lock lock(fp_mutex); + gruel::scoped_lock lock(fp_mutex); int fd; @@ -113,7 +113,7 @@ namespace gr { file_source_impl::close() { // obtain exclusive access for duration of this function - boost::mutex::scoped_lock lock(fp_mutex); + gruel::scoped_lock lock(fp_mutex); if(d_new_fp != NULL) { fclose(d_new_fp); @@ -126,7 +126,7 @@ namespace gr { file_source_impl::do_update() { if(d_updated) { - boost::mutex::scoped_lock lock(fp_mutex); // hold while in scope + gruel::scoped_lock lock(fp_mutex); // hold while in scope if(d_fp) fclose(d_fp); @@ -150,7 +150,7 @@ namespace gr { if(d_fp == NULL) throw std::runtime_error("work with file not open"); - boost::mutex::scoped_lock lock(fp_mutex); // hold for the rest of this function + gruel::scoped_lock lock(fp_mutex); // hold for the rest of this function while(size) { i = fread(o, d_itemsize, size, (FILE*)d_fp); diff --git a/gr-blocks/swig/CMakeLists.txt b/gr-blocks/swig/CMakeLists.txt index aa5c7bf55e..84ab5b660f 100644 --- a/gr-blocks/swig/CMakeLists.txt +++ b/gr-blocks/swig/CMakeLists.txt @@ -33,7 +33,7 @@ set(GR_SWIG_INCLUDE_DIRS set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/blocks_swig_doc.i) set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../lib) - +set(GR_SWIG_TARGET_DEPS blocks_generated_includes) set(GR_SWIG_LIBRARIES gnuradio-blocks) GR_SWIG_MAKE(blocks_swig blocks_swig.i) diff --git a/gr-filter/include/filter/CMakeLists.txt b/gr-filter/include/filter/CMakeLists.txt index c6bf109cde..4c126fcbd3 100644 --- a/gr-filter/include/filter/CMakeLists.txt +++ b/gr-filter/include/filter/CMakeLists.txt @@ -77,6 +77,7 @@ add_custom_target(filter_generated_includes DEPENDS # Install header files ######################################################################## install(FILES + ${generated_includes} api.h firdes.h fir_filter.h @@ -89,7 +90,6 @@ install(FILES pm_remez.h polyphase_filterbank.h single_pole_iir.h - ${generated_includes} adaptive_fir_ccc.h adaptive_fir_ccf.h dc_blocker_cc.h diff --git a/gr-filter/swig/CMakeLists.txt b/gr-filter/swig/CMakeLists.txt index 50c5bca6de..ea8c010e07 100644 --- a/gr-filter/swig/CMakeLists.txt +++ b/gr-filter/swig/CMakeLists.txt @@ -35,7 +35,7 @@ set(GR_SWIG_INCLUDE_DIRS # FIXME: rename to filter_swig_doc.i when gnuradio-core is updated set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/gr_filter_swig_doc.i) set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../lib) - +set(GR_SWIG_TARGET_DEPS filter_generated_includes) set(GR_SWIG_LIBRARIES gnuradio-filter gnuradio-fft) GR_SWIG_MAKE(filter_swig filter_swig.i) diff --git a/gruel/src/include/gruel/thread.h b/gruel/src/include/gruel/thread.h index 63143c8b46..60832675cd 100644 --- a/gruel/src/include/gruel/thread.h +++ b/gruel/src/include/gruel/thread.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2009,2010,2011 Free Software Foundation, Inc. + * Copyright 2009-2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -26,14 +26,114 @@ #include <boost/thread/mutex.hpp> #include <boost/thread/locks.hpp> #include <boost/thread/condition_variable.hpp> +#include <vector> + +#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include <windows.h> + +#endif namespace gruel { typedef boost::thread thread; typedef boost::mutex mutex; - typedef boost::mutex::scoped_lock scoped_lock; + typedef boost::unique_lock<boost::mutex> scoped_lock; typedef boost::condition_variable condition_variable; + /*! \brief a system-dependent typedef for the underlying thread type. + */ +#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + typedef HANDLE gr_thread_t; +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) + typedef pthread_t gr_thread_t; +#else + typedef pthread_t gr_thread_t; +#endif + + /*! \brief Get the current thread's ID as a gr_thread_t + * + * We use this when setting the thread affinity or any other + * low-level thread settings. Can be called withing a GNU Radio + * block to get a reference to its current thread ID. + */ + GRUEL_API gr_thread_t get_current_thread_id(); + + /*! \brief Bind the current thread to a set of cores. + * + * Wrapper for system-dependent calls to set the affinity of the + * current thread to the processor mask. The mask is simply a + * 1-demensional vector containing the processor or core number from + * 0 to N-1 for N cores. + * + * Note: this does not work on OSX; it is a nop call since OSX does + * not support the concept of thread affinity (and what they do + * support in this way since 10.5 is not what we want or can use in + * this fashion). + */ + GRUEL_API void thread_bind_to_processor(const std::vector<unsigned int> &mask); + + /*! \brief Convineince function to bind the current thread to a single core. + * + * Wrapper for system-dependent calls to set the affinity of the + * current thread to a given core from 0 to N-1 for N cores. + * + * Note: this does not work on OSX; it is a nop call since OSX does + * not support the concept of thread affinity (and what they do + * support in this way since 10.5 is not what we want or can use in + * this fashion). + */ + GRUEL_API void thread_bind_to_processor(unsigned int n); + + /*! \brief Bind a thread to a set of cores. + * + * Wrapper for system-dependent calls to set the affinity of the + * given thread ID to the processor mask. The mask is simply a + * 1-demensional vector containing the processor or core number from + * 0 to N-1 for N cores. + * + * Note: this does not work on OSX; it is a nop call since OSX does + * not support the concept of thread affinity (and what they do + * support in this way since 10.5 is not what we want or can use in + * this fashion). + */ + GRUEL_API void thread_bind_to_processor(gr_thread_t thread, const std::vector<unsigned int> &mask); + + + /*! \brief Convineince function to bind the a thread to a single core. + * + * Wrapper for system-dependent calls to set the affinity of the + * given thread ID to a given core from 0 to N-1 for N cores. + * + * Note: this does not work on OSX; it is a nop call since OSX does + * not support the concept of thread affinity (and what they do + * support in this way since 10.5 is not what we want or can use in + * this fashion). + */ + GRUEL_API void thread_bind_to_processor(gr_thread_t thread, unsigned int n); + + /*! \brief Remove any thread-processor affinity for the current thread. + * + * Note: this does not work on OSX; it is a nop call since OSX does + * not support the concept of thread affinity (and what they do + * support in this way since 10.5 is not what we want or can use in + * this fashion). + */ + GRUEL_API void thread_unbind(); + + /*! \brief Remove any thread-processor affinity for a given thread ID. + * + * Note: this does not work on OSX; it is a nop call since OSX does + * not support the concept of thread affinity (and what they do + * support in this way since 10.5 is not what we want or can use in + * this fashion). + */ + GRUEL_API void thread_unbind(gr_thread_t thread); + } /* namespace gruel */ #endif /* INCLUDED_THREAD_H */ diff --git a/gruel/src/lib/CMakeLists.txt b/gruel/src/lib/CMakeLists.txt index e33b80d64d..717d566601 100644 --- a/gruel/src/lib/CMakeLists.txt +++ b/gruel/src/lib/CMakeLists.txt @@ -76,6 +76,7 @@ link_directories(${Boost_LIBRARY_DIRS}) list(APPEND gruel_sources realtime.cc sys_pri.cc + thread.cc thread_body_wrapper.cc thread_group.cc ) diff --git a/gruel/src/lib/thread.cc b/gruel/src/lib/thread.cc new file mode 100644 index 0000000000..8ebe822fbf --- /dev/null +++ b/gruel/src/lib/thread.cc @@ -0,0 +1,226 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gruel/thread.h> + +#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + +#include <Windows.h> + +namespace gruel { + + gr_thread_t + get_current_thread_id() + { + return GetCurrentThread(); + } + + void + thread_bind_to_processor(unsigned int n) + { + std::vector<unsigned int> mask(1, n); + thread_bind_to_processor(get_current_thread_id(), mask); + } + + void + thread_bind_to_processor(const std::vector<unsigned int> &mask) + { + thread_bind_to_processor(get_current_thread_id(), mask); + } + + void + thread_bind_to_processor(gr_thread_t thread, unsigned int n) + { + std::vector<unsigned int> mask(1, n); + thread_bind_to_processor(thread, mask); + } + + void + thread_bind_to_processor(gr_thread_t thread, const std::vector<unsigned int> &mask) + { + //DWORD_PTR mask = (1 << n); + DWORD_PTR dword_mask = 0; + + std::vector<unsigned int> _mask = mask; + std::vector<unsigned int>::iterator itr; + for(itr = _mask.begin(); itr != _mask.end(); itr++) + dword_mask |= (1 << (*itr)); + + DWORD_PTR ret = SetThreadAffinityMask(thread, dword_mask); + if(ret == 0) { + std::stringstream s; + s << "thread_bind_to_processor failed with error: " << GetLastError() << std::endl; + throw std::runtime_error(s.str()); + } + } + + void + thread_unbind() + { + thread_unbind(get_current_thread_id()); + } + + void + thread_unbind(gr_thread_t thread) + { + DWORD_PTR dword_mask = sizeof(DWORD_PTR) - 1; + DWORD_PTR ret = SetThreadAffinityMask(thread, dword_mask); + if(ret == 0) { + std::stringstream s; + s << "thread_unbind failed with error: " << GetLastError() << std::endl; + throw std::runtime_error(s.str()); + } + } +} /* namespace gruel */ + +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) + +namespace gruel { + + gr_thread_t + get_current_thread_id() + { + // Not implemented on OSX + } + + void + thread_bind_to_processor(unsigned int n) + { + // Not implemented on OSX + } + + void + thread_bind_to_processor(gr_thread_t thread, unsigned int n) + { + // Not implemented on OSX + } + + void + thread_bind_to_processor(const std::vector<unsigned int> &mask) + { + // Not implemented on OSX + } + + void + thread_bind_to_processor(gr_thread_t thread, const std::vector<unsigned int> &mask) + { + // Not implemented on OSX + } + + void + thread_unbind() + { + // Not implemented on OSX + } + + void + thread_unbind(gr_thread_t thread) + { + // Not implemented on OSX + } +} /* namespace gruel */ + +#else + +#include <sstream> +#include <stdexcept> +#include <pthread.h> + +namespace gruel { + + gr_thread_t + get_current_thread_id() + { + return pthread_self(); + } + + void + thread_bind_to_processor(unsigned int n) + { + std::vector<unsigned int> mask(1, n); + thread_bind_to_processor(get_current_thread_id(), mask); + } + + void + thread_bind_to_processor(const std::vector<unsigned int> &mask) + { + thread_bind_to_processor(get_current_thread_id(), mask); + } + + void + thread_bind_to_processor(gr_thread_t thread, unsigned int n) + { + std::vector<unsigned int> mask(1, n); + thread_bind_to_processor(thread, mask); + } + + void + thread_bind_to_processor(gr_thread_t thread, const std::vector<unsigned int> &mask) + { + cpu_set_t set; + size_t len = sizeof(cpu_set_t); + std::vector<unsigned int> _mask = mask; + std::vector<unsigned int>::iterator itr; + + CPU_ZERO(&set); + for(itr = _mask.begin(); itr != _mask.end(); itr++) + CPU_SET(*itr, &set); + + int ret = pthread_setaffinity_np(thread, len, &set); + if(ret != 0) { + std::stringstream s; + s << "thread_bind_to_processor failed with error: " << ret << std::endl; + throw std::runtime_error(s.str()); + } + } + + void + thread_unbind() + { + thread_unbind(get_current_thread_id()); + } + + void + thread_unbind(gr_thread_t thread) + { + cpu_set_t set; + size_t len = sizeof(cpu_set_t); + + CPU_ZERO(&set); + long ncpus = sysconf(_SC_NPROCESSORS_ONLN); + for(long n = 0; n < ncpus; n++) { + CPU_SET(n, &set); + } + + int ret = pthread_setaffinity_np(thread, len, &set); + if(ret != 0) { + std::stringstream s; + s << "thread_unbind failed with error: " << ret << std::endl; + throw std::runtime_error(s.str()); + } + } +} /* namespace gruel */ + +#endif diff --git a/gruel/src/python/CMakeLists.txt b/gruel/src/python/CMakeLists.txt index 13f2111ba2..f5c4ac47a6 100644 --- a/gruel/src/python/CMakeLists.txt +++ b/gruel/src/python/CMakeLists.txt @@ -28,8 +28,9 @@ GR_PYTHON_INSTALL( COMPONENT "gruel_python" ) -GR_PYTHON_INSTALL( - FILES pmt/__init__.py +GR_PYTHON_INSTALL(FILES + pmt/__init__.py + pmt/pmt_to_python.py DESTINATION ${GR_PYTHON_DIR}/gruel/pmt COMPONENT "gruel_python" ) diff --git a/gruel/src/python/pmt/__init__.py b/gruel/src/python/pmt/__init__.py index 0862af0ebe..bc933e80a5 100644 --- a/gruel/src/python/pmt/__init__.py +++ b/gruel/src/python/pmt/__init__.py @@ -26,4 +26,6 @@ The GNU Radio Utility Etcetera Library's Polymorphic Types for Python. ''' from pmt_swig import * +from pmt_to_python import pmt_to_python as to_python +from pmt_to_python import python_to_pmt as to_pmt diff --git a/gruel/src/python/pmt/pmt_to_python.py b/gruel/src/python/pmt/pmt_to_python.py new file mode 100644 index 0000000000..030c1c11d0 --- /dev/null +++ b/gruel/src/python/pmt/pmt_to_python.py @@ -0,0 +1,97 @@ +# Copyright 2012,2013 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +try: import pmt_swig as pmt +except: import pmt +import numpy + +#define missing +def pmt_to_tuple(p): + elems = list() + for i in range(pmt.pmt_length(p)): + elem = pmt.pmt_tuple_ref(p, i) + elems.append(pmt_to_python(elem)) + return tuple(elems) + +def pmt_from_tuple(p): + args = map(python_to_pmt, p) + return pmt.pmt_make_tuple(*args) + +def pmt_to_vector(p): + v = list() + for i in range(pmt.pmt_length(p)): + elem = pmt.pmt_vector_ref(p, i) + v.append(pmt_to_python(elem)) + return v + +def pmt_from_vector(p): + v = pmt.pmt_make_vector(len(p), pmt.PMT_NIL) + for i, elem in enumerate(p): + pmt.pmt_vector_set(v, i, python_to_pmt(elem)) + return v + +def pmt_to_dict(p): + d = dict() + items = pmt.pmt_dict_items(p) + for i in range(pmt.pmt_length(items)): + pair = pmt.pmt_nth(i, items) + k = pmt.pmt_car(pair) + v = pmt.pmt_cdr(pair) + d[pmt_to_python(k)] = pmt_to_python(v) + return d + +def pmt_from_dict(p): + d = pmt.pmt_make_dict() + for k, v in p.iteritems(): + #dict is immutable -> therefore pmt_dict_add returns the new dict + d = pmt.pmt_dict_add(d, python_to_pmt(k), python_to_pmt(v)) + return d + +def numpy_to_blob(p): + p = p.view(numpy.uint8) + b = pmt.pmt_make_blob(len(p)) + pmt.pmt_blob_data(b)[:] = p + return b + +THE_TABLE = ( #python type, check pmt type, to python, from python + (None, pmt.pmt_is_null, lambda x: None, lambda x: pmt.PMT_NIL), + (bool, pmt.pmt_is_bool, pmt.pmt_to_bool, pmt.pmt_from_bool), + (str, pmt.pmt_is_symbol, pmt.pmt_symbol_to_string, pmt.pmt_string_to_symbol), + (int, pmt.pmt_is_integer, pmt.pmt_to_long, pmt.pmt_from_long), + (long, pmt.pmt_is_uint64, lambda x: long(pmt.pmt_to_uint64(x)), pmt.pmt_from_uint64), + (float, pmt.pmt_is_real, pmt.pmt_to_double, pmt.pmt_from_double), + (complex, pmt.pmt_is_complex, pmt.pmt_to_complex, pmt.pmt_from_complex), + (tuple, pmt.pmt_is_tuple, pmt_to_tuple, pmt_from_tuple), + (list, pmt.pmt_is_vector, pmt_to_vector, pmt_from_vector), + (dict, pmt.pmt_is_dict, pmt_to_dict, pmt_from_dict), + (numpy.ndarray, pmt.pmt_is_blob, pmt.pmt_blob_data, numpy_to_blob), +) + +def pmt_to_python(p): + for python_type, pmt_check, to_python, from_python in THE_TABLE: + if pmt_check(p): return to_python(p) + return p #give up, we return the same + +def python_to_pmt(p): + for python_type, pmt_check, to_python, from_python in THE_TABLE: + if python_type is None: + if p == None: return from_python(p) + elif isinstance(p, python_type): return from_python(p) + return p #give up, we return the same + diff --git a/gruel/src/python/qa_pmt_to_python.py b/gruel/src/python/qa_pmt_to_python.py new file mode 100755 index 0000000000..c63403a520 --- /dev/null +++ b/gruel/src/python/qa_pmt_to_python.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python +# +# Copyright 2013 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import unittest +import pmt + +class test_gruel_pmt_to_python(unittest.TestCase): + + def test01 (self): + b = pmt.pmt_from_double(123765) + self.assertEqual(pmt.to_python(b), 123765) + t = pmt.to_pmt(range(5)) + +if __name__ == '__main__': + unittest.main() |