diff options
-rw-r--r-- | config/grc_usrp2.m4 | 5 | ||||
-rw-r--r-- | gruel/src/include/gruel/thread.h | 10 | ||||
-rw-r--r-- | gruel/src/lib/Makefile.am | 3 | ||||
-rw-r--r-- | gruel/src/lib/thread.cc | 35 | ||||
-rw-r--r-- | usrp2/host/apps/Makefile.am | 5 | ||||
-rw-r--r-- | usrp2/host/lib/Makefile.am | 9 | ||||
-rw-r--r-- | usrp2/host/lib/control.cc | 23 | ||||
-rw-r--r-- | usrp2/host/lib/control.h | 8 | ||||
-rw-r--r-- | usrp2/host/lib/ring.cc | 14 | ||||
-rw-r--r-- | usrp2/host/lib/ring.h | 8 | ||||
-rw-r--r-- | usrp2/host/lib/usrp2_impl.cc | 41 | ||||
-rw-r--r-- | usrp2/host/lib/usrp2_impl.h | 24 | ||||
-rw-r--r-- | usrp2/host/lib/usrp2_thread.cc | 64 | ||||
-rw-r--r-- | usrp2/host/lib/usrp2_thread.h | 47 |
14 files changed, 117 insertions, 179 deletions
diff --git a/config/grc_usrp2.m4 b/config/grc_usrp2.m4 index f7064c916..701b100ad 100644 --- a/config/grc_usrp2.m4 +++ b/config/grc_usrp2.m4 @@ -1,4 +1,4 @@ -dnl Copyright 2008 Free Software Foundation, Inc. +dnl Copyright 2008,2010 Free Software Foundation, Inc. dnl dnl This file is part of GNU Radio dnl @@ -23,9 +23,8 @@ AC_DEFUN([GRC_USRP2],[ dnl firmware uses a subsidiary configure.ac AC_CONFIG_SUBDIRS([usrp2/firmware]) - dnl Don't do usrp if omnithread or gruel is skipped + dnl Don't do usrp if gruel is skipped GRC_CHECK_DEPENDENCY(usrp2, gruel) - GRC_CHECK_DEPENDENCY(usrp2, omnithread) dnl USRP2 host code only works on Linux at the moment AC_MSG_CHECKING([whether host_os is linux*]) diff --git a/gruel/src/include/gruel/thread.h b/gruel/src/include/gruel/thread.h index 0e7acaa85..d72e5520c 100644 --- a/gruel/src/include/gruel/thread.h +++ b/gruel/src/include/gruel/thread.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2009 Free Software Foundation, Inc. + * Copyright 2009,2010 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -22,12 +22,20 @@ #define INCLUDED_THREAD_H #include <boost/thread.hpp> +#include <boost/date_time/posix_time/posix_time.hpp> namespace gruel { + typedef boost::thread thread; typedef boost::mutex mutex; typedef boost::unique_lock<boost::mutex> scoped_lock; typedef boost::condition_variable condition_variable; + typedef boost::posix_time::time_duration duration; + + /*! + * Returns absolute time 'secs' into the future + */ + boost::system_time get_new_timeout(double secs); } /* namespace gruel */ diff --git a/gruel/src/lib/Makefile.am b/gruel/src/lib/Makefile.am index b21f8023c..6bde9ee27 100644 --- a/gruel/src/lib/Makefile.am +++ b/gruel/src/lib/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2008,2009 Free Software Foundation, Inc. +# Copyright 2008,2009,2010 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -45,6 +45,7 @@ MSG_LIB = msg/libmsg.la libgruel_la_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 000000000..d8f77b506 --- /dev/null +++ b/gruel/src/lib/thread.cc @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 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> + +namespace gruel { + + boost::system_time + get_new_timeout(double secs) + { + return boost::get_system_time() + boost::posix_time::milliseconds(long(secs*1e3)); + } + +} diff --git a/usrp2/host/apps/Makefile.am b/usrp2/host/apps/Makefile.am index db7660196..4a26898fa 100644 --- a/usrp2/host/apps/Makefile.am +++ b/usrp2/host/apps/Makefile.am @@ -24,9 +24,8 @@ AM_CPPFLAGS = \ $(GRUEL_INCLUDES) LDADD = \ - $(USRP2_LA) \ - $(GRUEL_LA) \ - $(OMNITHREAD_LA) + $(USRP2_LA) \ + $(GRUEL_LA) bin_PROGRAMS = \ find_usrps \ diff --git a/usrp2/host/lib/Makefile.am b/usrp2/host/lib/Makefile.am index 772cf1446..cda051bb0 100644 --- a/usrp2/host/lib/Makefile.am +++ b/usrp2/host/lib/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2007,2008 Free Software Foundation, Inc. +# Copyright 2007,2008,2010 Free Software Foundation, Inc. # # 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 @@ -45,11 +45,9 @@ libusrp2_la_SOURCES = \ rx_sample_handler.cc \ strtod_si.c \ usrp2.cc \ - usrp2_impl.cc \ - usrp2_thread.cc + usrp2_impl.cc libusrp2_la_LIBADD = \ - $(OMNITHREAD_LA) \ $(GRUEL_LA) \ $(BOOST_LDFLAGS) $(BOOST_THREAD_LIB) @@ -63,5 +61,4 @@ noinst_HEADERS = \ pktfilter.h \ ring.h \ usrp2_bytesex.h \ - usrp2_impl.h \ - usrp2_thread.h + usrp2_impl.h
\ No newline at end of file diff --git a/usrp2/host/lib/control.cc b/usrp2/host/lib/control.cc index bb71f79c2..33a95c078 100644 --- a/usrp2/host/lib/control.cc +++ b/usrp2/host/lib/control.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008 Free Software Foundation, Inc. + * Copyright 2008,2009,2010 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -23,14 +23,14 @@ #include <config.h> #endif -#include <gnuradio/omni_time.h> #include "control.h" #include <iostream> +#include <gruel/thread.h> namespace usrp2 { pending_reply::pending_reply(unsigned int rid, void *buffer, size_t len) - : d_rid(rid), d_buffer(buffer), d_len(len), d_mutex(), d_cond(&d_mutex), + : d_rid(rid), d_buffer(buffer), d_len(len), d_mutex(), d_cond(), d_complete(false) { } @@ -43,22 +43,23 @@ namespace usrp2 { int pending_reply::wait_for_completion(double secs) { - omni_time abs_timeout = omni_time::time(omni_time(secs)); - omni_mutex_lock l(d_mutex); - while (!d_complete){ - int r = d_cond.timedwait(abs_timeout.d_secs, abs_timeout.d_nsecs); - if (r == 0) // timed out - return 0; + gruel::scoped_lock l(d_mutex); + boost::system_time to(gruel::get_new_timeout(secs)); + + while (!d_complete) { + if (!d_cond.timed_wait(l, to)) + return 0; // timed out } + return 1; } void pending_reply::notify_completion() { - omni_mutex_lock l(d_mutex); + gruel::scoped_lock l(d_mutex); d_complete = true; - d_cond.signal(); + d_cond.notify_one(); } } // namespace usrp2 diff --git a/usrp2/host/lib/control.h b/usrp2/host/lib/control.h index 46ce791ea..3515ba10f 100644 --- a/usrp2/host/lib/control.h +++ b/usrp2/host/lib/control.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008,2009 Free Software Foundation, Inc. + * Copyright 2008,2009,2010 Free Software Foundation, Inc. * * 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 @@ -19,7 +19,7 @@ #ifndef INCLUDED_CONTROL_H #define INCLUDED_CONTROL_H -#include <gnuradio/omnithread.h> +#include <gruel/thread.h> #include <usrp2_eth_packet.h> namespace usrp2 { @@ -130,8 +130,8 @@ namespace usrp2 { size_t d_len; // d_mutex is used with d_cond and also protects d_complete - omni_mutex d_mutex; - omni_condition d_cond; + gruel::mutex d_mutex; + gruel::condition_variable d_cond; bool d_complete; public: diff --git a/usrp2/host/lib/ring.cc b/usrp2/host/lib/ring.cc index 3c45821f8..d0048418c 100644 --- a/usrp2/host/lib/ring.cc +++ b/usrp2/host/lib/ring.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008 Free Software Foundation, Inc. + * Copyright 2008,2010 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -29,7 +29,7 @@ namespace usrp2 { ring::ring(unsigned int entries) : d_max(entries), d_read_ind(0), d_write_ind(0), d_ring(entries), - d_mutex(), d_not_empty(&d_mutex) + d_mutex(), d_not_empty() { for (unsigned int i = 0; i < entries; i++) { d_ring[i].d_base = 0; @@ -40,15 +40,15 @@ namespace usrp2 { void ring::wait_for_not_empty() { - omni_mutex_lock l(d_mutex); + gruel::scoped_lock l(d_mutex); while (empty()) - d_not_empty.wait(); + d_not_empty.wait(l); } bool ring::enqueue(void *p, size_t len) { - omni_mutex_lock l(d_mutex); + gruel::scoped_lock l(d_mutex); if (full()) return false; @@ -56,14 +56,14 @@ namespace usrp2 { d_ring[d_write_ind].d_base = p; inc_write_ind(); - d_not_empty.signal(); + d_not_empty.notify_one(); return true; } bool ring::dequeue(void **p, size_t *len) { - omni_mutex_lock l(d_mutex); + gruel::scoped_lock l(d_mutex); if (empty()) return false; diff --git a/usrp2/host/lib/ring.h b/usrp2/host/lib/ring.h index 19ae9ae97..fd0ad0a9f 100644 --- a/usrp2/host/lib/ring.h +++ b/usrp2/host/lib/ring.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008 Free Software Foundation, Inc. + * Copyright 2008,2010 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -21,10 +21,10 @@ #ifndef INCLUDED_RING_H #define INCLUDED_RING_H -#include <gnuradio/omnithread.h> #include <stddef.h> #include <vector> #include <boost/shared_ptr.hpp> +#include <gruel/thread.h> namespace usrp2 { @@ -46,8 +46,8 @@ namespace usrp2 { }; std::vector<ring_desc> d_ring; - omni_mutex d_mutex; - omni_condition d_not_empty; + gruel::mutex d_mutex; + gruel::condition_variable d_not_empty; void inc_read_ind() { diff --git a/usrp2/host/lib/usrp2_impl.cc b/usrp2/host/lib/usrp2_impl.cc index d4f29baf0..5592c76ea 100644 --- a/usrp2/host/lib/usrp2_impl.cc +++ b/usrp2/host/lib/usrp2_impl.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008,2009 Free Software Foundation, Inc. + * Copyright 2008,2009,2010 Free Software Foundation, Inc. * * 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 @@ -24,9 +24,9 @@ #include <usrp2/tune_result.h> #include <usrp2/copiers.h> #include <gruel/inet.h> +#include <gruel/realtime.h> #include <usrp2_types.h> #include "usrp2_impl.h" -#include "usrp2_thread.h" #include "eth_buffer.h" #include "pktfilter.h" #include "control.h" @@ -129,10 +129,10 @@ namespace usrp2 { usrp2::impl::impl(const std::string &ifc, props *p, size_t rx_bufsize) - : d_eth_buf(new eth_buffer(rx_bufsize)), d_interface_name(ifc), d_pf(0), d_bg_thread(0), + : d_eth_buf(new eth_buffer(rx_bufsize)), d_interface_name(ifc), d_pf(0), d_bg_running(false), d_rx_seqno(-1), d_tx_seqno(0), d_next_rid(0), d_num_rx_frames(0), d_num_rx_missing(0), d_num_rx_overruns(0), d_num_rx_bytes(0), - d_num_enqueued(0), d_enqueued_mutex(), d_bg_pending_cond(&d_enqueued_mutex), + d_num_enqueued(0), d_enqueued_mutex(), d_bg_pending_cond(), d_channel_rings(NCHANS), d_tx_interp(0), d_rx_decim(0), d_dont_enqueue(true) { if (!d_eth_buf->open(ifc, htons(U2_ETHERTYPE))) @@ -152,8 +152,8 @@ namespace usrp2 { memset(d_pending_replies, 0, sizeof(d_pending_replies)); - d_bg_thread = new usrp2_thread(this); - d_bg_thread->start(); + // Kick off receive thread + start_bg(); // In case the USRP2 was left streaming RX // FIXME: only one channel right now @@ -208,7 +208,6 @@ namespace usrp2 { usrp2::impl::~impl() { stop_bg(); - d_bg_thread = 0; // thread class deletes itself delete d_pf; d_eth_buf->close(); delete d_eth_buf; @@ -336,18 +335,24 @@ namespace usrp2 { // ---------------------------------------------------------------- void + usrp2::impl::start_bg() + { + d_rx_tg.create_thread(boost::bind(&usrp2::impl::bg_loop, this)); + } + + void usrp2::impl::stop_bg() { d_bg_running = false; - d_bg_pending_cond.signal(); - - void *dummy_status; - d_bg_thread->join(&dummy_status); + d_bg_pending_cond.notify_one(); // FIXME: check if needed + d_rx_tg.join_all(); } void usrp2::impl::bg_loop() { + gruel::enable_realtime_scheduling(); + d_bg_running = true; while(d_bg_running) { DEBUG_LOG(":"); @@ -362,9 +367,9 @@ namespace usrp2 { // The channel ring thread that decrements d_num_enqueued to zero // will signal this thread to continue. { - omni_mutex_lock l(d_enqueued_mutex); + gruel::scoped_lock l(d_enqueued_mutex); while(d_num_enqueued > 0 && d_bg_running) - d_bg_pending_cond.wait(); + d_bg_pending_cond.wait(l); } } d_bg_running = false; @@ -463,7 +468,7 @@ namespace usrp2 { unsigned int chan = u2p_chan(&pkt->hdrs.fixed); { - omni_mutex_lock l(d_channel_rings_mutex); + gruel::scoped_lock l(d_channel_rings_mutex); if (!d_channel_rings[chan]) { DEBUG_LOG("!"); @@ -650,7 +655,7 @@ namespace usrp2 { } { - omni_mutex_lock l(d_channel_rings_mutex); + gruel::scoped_lock l(d_channel_rings_mutex); if (d_channel_rings[channel]) { std::cerr << "usrp2: channel " << channel << " already streaming" << std::endl; @@ -704,7 +709,7 @@ namespace usrp2 { } { - omni_mutex_lock l(d_channel_rings_mutex); + gruel::scoped_lock guard(d_channel_rings_mutex); if (d_channel_rings[channel]) { std::cerr << "usrp2: channel " << channel << " already streaming" << std::endl; @@ -758,7 +763,7 @@ namespace usrp2 { } { - omni_mutex_lock l(d_channel_rings_mutex); + gruel::scoped_lock guard(d_channel_rings_mutex); if (d_channel_rings[channel]) { std::cerr << "usrp2: channel " << channel << " already streaming" << std::endl; @@ -820,7 +825,7 @@ namespace usrp2 { op_generic_t reply; { - omni_mutex_lock l(d_channel_rings_mutex); + gruel::scoped_lock l(d_channel_rings_mutex); memset(&cmd, 0, sizeof(cmd)); init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1); diff --git a/usrp2/host/lib/usrp2_impl.h b/usrp2/host/lib/usrp2_impl.h index a75947922..eee26358e 100644 --- a/usrp2/host/lib/usrp2_impl.h +++ b/usrp2/host/lib/usrp2_impl.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008,2009 Free Software Foundation, Inc. + * Copyright 2008,2009,2010 Free Software Foundation, Inc. * * 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 @@ -22,6 +22,7 @@ #include <usrp2/usrp2.h> #include <usrp2/data_handler.h> #include <usrp2_eth_packet.h> +#include <gruel/thread.h> #include <boost/scoped_ptr.hpp> #include "control.h" #include "ring.h" @@ -60,7 +61,8 @@ namespace usrp2 { std::string d_interface_name; pktfilter *d_pf; std::string d_addr; // FIXME: use u2_mac_addr_t instead - usrp2_thread *d_bg_thread; + + boost::thread_group d_rx_tg; volatile bool d_bg_running; // TODO: multistate if needed int d_rx_seqno; @@ -72,14 +74,14 @@ namespace usrp2 { unsigned int d_num_rx_bytes; unsigned int d_num_enqueued; - omni_mutex d_enqueued_mutex; - omni_condition d_bg_pending_cond; + gruel::mutex d_enqueued_mutex; + gruel::condition_variable d_bg_pending_cond; // all pending_replies are stack allocated, thus no possibility of leaking these pending_reply *d_pending_replies[NRIDS]; // indexed by 8-bit reply id std::vector<ring_sptr> d_channel_rings; // indexed by 5-bit channel number - omni_mutex d_channel_rings_mutex; + gruel::mutex d_channel_rings_mutex; db_info d_tx_db_info; db_info d_rx_db_info; @@ -90,20 +92,21 @@ namespace usrp2 { bool d_dont_enqueue; void inc_enqueued() { - omni_mutex_lock l(d_enqueued_mutex); + gruel::scoped_lock l(d_enqueued_mutex); d_num_enqueued++; } void dec_enqueued() { - omni_mutex_lock l(d_enqueued_mutex); + gruel::scoped_lock l(d_enqueued_mutex); if (--d_num_enqueued == 0) - d_bg_pending_cond.signal(); + d_bg_pending_cond.notify_one(); } static bool parse_mac_addr(const std::string &s, u2_mac_addr_t *p); void init_et_hdrs(u2_eth_packet_t *p, const std::string &dst); void init_etf_hdrs(u2_eth_packet_t *p, const std::string &dst, int word0_flags, int chan, uint32_t timestamp); + void start_bg(); void stop_bg(); void init_config_rx_v2_cmd(op_config_rx_v2_cmd *cmd); void init_config_tx_v2_cmd(op_config_tx_v2_cmd *cmd); @@ -119,8 +122,6 @@ namespace usrp2 { impl(const std::string &ifc, props *p, size_t rx_bufsize); ~impl(); - void bg_loop(); - std::string mac_addr() const { return d_addr; } // FIXME: convert from u2_mac_addr_t std::string interface_name() const { return d_interface_name; } @@ -199,6 +200,9 @@ namespace usrp2 { bool sync_every_pps(bool enable); std::vector<uint32_t> peek32(uint32_t addr, uint32_t words); bool poke32(uint32_t addr, const std::vector<uint32_t> &data); + + // Receive thread, need to be public for boost::bind + void bg_loop(); }; } // namespace usrp2 diff --git a/usrp2/host/lib/usrp2_thread.cc b/usrp2/host/lib/usrp2_thread.cc deleted file mode 100644 index d14770395..000000000 --- a/usrp2/host/lib/usrp2_thread.cc +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 Free Software Foundation, Inc. - * - * 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 3 of the License, or - * (at your option) any later version. - * - * This program 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, see <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "usrp2_thread.h" -#include "usrp2_impl.h" -#include <gruel/realtime.h> -#include <gruel/sys_pri.h> -#include <iostream> - -#define USRP2_THREAD_DEBUG 1 - -namespace usrp2 { - - usrp2_thread::usrp2_thread(usrp2::impl *u2) : - omni_thread(NULL, PRIORITY_HIGH), - d_u2(u2) - { - } - - usrp2_thread::~usrp2_thread() - { - // we don't own this, just forget it - d_u2 = 0; - } - - void - usrp2_thread::start() - { - start_undetached(); - } - - void * - usrp2_thread::run_undetached(void *arg) - { - if (gruel::enable_realtime_scheduling(gruel::sys_pri::usrp2_backend()) != gruel::RT_OK) - std::cerr << "usrp2: failed to enable realtime scheduling" << std::endl; - - // This is the first code to run in the new thread context. - d_u2->bg_loop(); - - return 0; - } - -} // namespace usrp2 - diff --git a/usrp2/host/lib/usrp2_thread.h b/usrp2/host/lib/usrp2_thread.h deleted file mode 100644 index 12723e947..000000000 --- a/usrp2/host/lib/usrp2_thread.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 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. - */ - -#ifndef INCLUDED_USRP2_THREAD_H -#define INCLUDED_USRP2_THREAD_H - -#include <gnuradio/omnithread.h> -#include <usrp2_impl.h> - -namespace usrp2 { - - class usrp2_thread : public omni_thread - { - private: - usrp2::impl *d_u2; - - public: - usrp2_thread(usrp2::impl *u2); - ~usrp2_thread(); - - void start(); - - virtual void *run_undetached(void *arg); - }; - -} // namespace usrp2 - -#endif /* INCLUDED_USRP2_THREAD_H */ |