aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2011-02-15 17:07:34 -0800
committerJosh Blum <josh@joshknows.com>2011-02-15 17:07:34 -0800
commit8ffd7e04c4cf5089b3adbe211ce2c80f4e76ebd7 (patch)
tree7443157ce121e933ddba4dcc3dd9a5ed6a25c151
parent153f2575bb077c66f7ce5ba5d7911eea6fc37b98 (diff)
downloaduhd-8ffd7e04c4cf5089b3adbe211ce2c80f4e76ebd7.tar.gz
uhd-8ffd7e04c4cf5089b3adbe211ce2c80f4e76ebd7.tar.bz2
uhd-8ffd7e04c4cf5089b3adbe211ce2c80f4e76ebd7.zip
usrp-e100: replaced safe managed buffers in usrp-e100 mmap with custom ones
the buffers are reusable and the overhead is reduced (nothing to malloc) also removed the zero_copy.cpp (not needed anymore) need to test on device...
-rw-r--r--host/include/uhd/transport/zero_copy.hpp30
-rw-r--r--host/lib/transport/CMakeLists.txt1
-rw-r--r--host/lib/transport/zero_copy.cpp114
-rw-r--r--host/lib/usrp/usrp_e100/usrp_e100_mmap_zero_copy.cpp160
4 files changed, 112 insertions, 193 deletions
diff --git a/host/include/uhd/transport/zero_copy.hpp b/host/include/uhd/transport/zero_copy.hpp
index 18eb3fb6d..092028d09 100644
--- a/host/include/uhd/transport/zero_copy.hpp
+++ b/host/include/uhd/transport/zero_copy.hpp
@@ -21,7 +21,6 @@
#include <uhd/config.hpp>
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
-#include <boost/function.hpp>
namespace uhd{ namespace transport{
@@ -33,20 +32,6 @@ namespace uhd{ namespace transport{
class UHD_API managed_recv_buffer{
public:
typedef boost::shared_ptr<managed_recv_buffer> sptr;
- typedef boost::function<void(void)> release_fcn_t;
-
- /*!
- * Make a safe managed receive buffer:
- * A safe managed buffer ensures that release is called once,
- * either by the user or automatically upon deconstruction.
- * \param buff a pointer into read-only memory
- * \param size the length of the buffer in bytes
- * \param release_fcn callback to release the memory
- * \return a new managed receive buffer
- */
- static sptr make_safe(
- const void *buff, size_t size, const release_fcn_t &release_fcn
- );
/*!
* Signal to the transport that we are done with the buffer.
@@ -84,21 +69,6 @@ namespace uhd{ namespace transport{
class UHD_API managed_send_buffer{
public:
typedef boost::shared_ptr<managed_send_buffer> sptr;
- typedef boost::function<void(size_t)> commit_fcn_t;
-
- /*!
- * Make a safe managed send buffer:
- * A safe managed buffer ensures that commit is called once,
- * either by the user or automatically upon deconstruction.
- * In the later case, the deconstructor will call commit(0).
- * \param buff a pointer into writable memory
- * \param size the length of the buffer in bytes
- * \param commit_fcn callback to commit the memory
- * \return a new managed send buffer
- */
- static sptr make_safe(
- void *buff, size_t size, const commit_fcn_t &commit_fcn
- );
/*!
* Signal to the transport that we are done with the buffer.
diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt
index 8765c6703..a66a58d32 100644
--- a/host/lib/transport/CMakeLists.txt
+++ b/host/lib/transport/CMakeLists.txt
@@ -77,5 +77,4 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/udp_simple.cpp
${CMAKE_CURRENT_SOURCE_DIR}/udp_zero_copy_asio.cpp
${CMAKE_CURRENT_SOURCE_DIR}/vrt_packet_handler.hpp
- ${CMAKE_CURRENT_SOURCE_DIR}/zero_copy.cpp
)
diff --git a/host/lib/transport/zero_copy.cpp b/host/lib/transport/zero_copy.cpp
deleted file mode 100644
index b91eaae1d..000000000
--- a/host/lib/transport/zero_copy.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-//
-// Copyright 2010-2011 Ettus Research LLC
-//
-// 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/>.
-//
-
-#include <uhd/transport/zero_copy.hpp>
-
-using namespace uhd::transport;
-
-/***********************************************************************
- * Safe managed receive buffer
- **********************************************************************/
-static void release_nop(void){
- /* NOP */
-}
-
-class safe_managed_receive_buffer : public managed_recv_buffer{
-public:
- safe_managed_receive_buffer(
- const void *buff, size_t size, const release_fcn_t &release_fcn
- ):
- _buff(buff), _size(size), _release_fcn(release_fcn)
- {
- /* NOP */
- }
-
- ~safe_managed_receive_buffer(void){
- _release_fcn();
- }
-
- void release(void){
- release_fcn_t release_fcn = _release_fcn;
- _release_fcn = &release_nop;
- return release_fcn();
- }
-
-private:
- const void *get_buff(void) const{
- return _buff;
- }
-
- size_t get_size(void) const{
- return _size;
- }
-
- const void *_buff;
- size_t _size;
- release_fcn_t _release_fcn;
-};
-
-managed_recv_buffer::sptr managed_recv_buffer::make_safe(
- const void *buff, size_t size, const release_fcn_t &release_fcn
-){
- return sptr(new safe_managed_receive_buffer(buff, size, release_fcn));
-}
-
-/***********************************************************************
- * Safe managed send buffer
- **********************************************************************/
-static void commit_nop(size_t){
- /* NOP */
-}
-
-class safe_managed_send_buffer : public managed_send_buffer{
-public:
- safe_managed_send_buffer(
- void *buff, size_t size, const commit_fcn_t &commit_fcn
- ):
- _buff(buff), _size(size), _commit_fcn(commit_fcn)
- {
- /* NOP */
- }
-
- ~safe_managed_send_buffer(void){
- _commit_fcn(0);
- }
-
- void commit(size_t num_bytes){
- commit_fcn_t commit_fcn = _commit_fcn;
- _commit_fcn = &commit_nop;
- return commit_fcn(num_bytes);
- }
-
-private:
- void *get_buff(void) const{
- return _buff;
- }
-
- size_t get_size(void) const{
- return _size;
- }
-
- void *_buff;
- size_t _size;
- commit_fcn_t _commit_fcn;
-};
-
-safe_managed_send_buffer::sptr managed_send_buffer::make_safe(
- void *buff, size_t size, const commit_fcn_t &commit_fcn
-){
- return sptr(new safe_managed_send_buffer(buff, size, commit_fcn));
-}
diff --git a/host/lib/usrp/usrp_e100/usrp_e100_mmap_zero_copy.cpp b/host/lib/usrp/usrp_e100/usrp_e100_mmap_zero_copy.cpp
index 4e0137fdb..c155d426a 100644
--- a/host/lib/usrp/usrp_e100/usrp_e100_mmap_zero_copy.cpp
+++ b/host/lib/usrp/usrp_e100/usrp_e100_mmap_zero_copy.cpp
@@ -22,7 +22,7 @@
#include <sys/mman.h> //mmap
#include <unistd.h> //getpagesize
#include <poll.h> //poll
-#include <boost/bind.hpp>
+#include <vector>
#include <iostream>
using namespace uhd;
@@ -33,6 +33,82 @@ static const bool sp_verbose = false; //slow-path verbose
static const size_t poll_breakout = 10; //how many poll timeouts constitute a full timeout
/***********************************************************************
+ * Reusable managed receiver buffer:
+ * - The buffer knows how to claim and release a frame.
+ **********************************************************************/
+class usrp_e100_mmap_zero_copy_mrb : public managed_recv_buffer{
+public:
+ usrp_e100_mmap_zero_copy_mrb(void *mem, ring_buffer_info *info):
+ _mem(mem), _info(info) { /* NOP */ }
+
+ void release(void){
+ if (_info->flags != RB_USER_PROCESS) return;
+ if (fp_verbose) std::cout << "recv buff: release" << std::endl;
+ _info->flags = RB_KERNEL; //release the frame
+ }
+
+ bool ready(void){return _info->flags & RB_USER;}
+
+ sptr get_new(void){
+ if (fp_verbose) std::cout << " make_recv_buff: " << get_size() << std::endl;
+ _info->flags = RB_USER_PROCESS; //claim the frame
+ return sptr(this, &usrp_e100_mmap_zero_copy_mrb::fake_deleter);
+ }
+
+private:
+ static void fake_deleter(void *obj){
+ static_cast<usrp_e100_mmap_zero_copy_mrb *>(obj)->release();
+ }
+
+ const void *get_buff(void) const{return _mem;}
+ size_t get_size(void) const{return _info->len;}
+
+ void *_mem;
+ ring_buffer_info *_info;
+};
+
+/***********************************************************************
+ * Reusable managed send buffer:
+ * - The buffer knows how to claim and release a frame.
+ **********************************************************************/
+class usrp_e100_mmap_zero_copy_msb : public managed_send_buffer{
+public:
+ usrp_e100_mmap_zero_copy_msb(void *mem, ring_buffer_info *info, size_t len, int fd):
+ _mem(mem), _info(info), _len(len), _fd(fd) { /* NOP */ }
+
+ void commit(size_t len){
+ if (_info->flags != RB_USER_PROCESS) return;
+ if (fp_verbose) std::cout << "send buff: commit " << len << std::endl;
+ _info->len = len;
+ _info->flags = RB_USER; //release the frame
+ if (::write(_fd, NULL, 0) < 0){ //notifies the kernel
+ std::cerr << UHD_THROW_SITE_INFO("write error") << std::endl;
+ }
+ }
+
+ bool ready(void){return _info->flags & RB_KERNEL;}
+
+ sptr get_new(void){
+ if (fp_verbose) std::cout << " make_send_buff: " << get_size() << std::endl;
+ _info->flags = RB_USER_PROCESS; //claim the frame
+ return sptr(this, &usrp_e100_mmap_zero_copy_msb::fake_deleter);
+ }
+
+private:
+ static void fake_deleter(void *obj){
+ static_cast<usrp_e100_mmap_zero_copy_msb *>(obj)->commit(0);
+ }
+
+ void *get_buff(void) const{return _mem;}
+ size_t get_size(void) const{return _len;}
+
+ void *_mem;
+ ring_buffer_info *_info;
+ size_t _len;
+ int _fd;
+};
+
+/***********************************************************************
* The zero copy interface implementation
**********************************************************************/
class usrp_e100_mmap_zero_copy_impl : public zero_copy_if{
@@ -81,13 +157,32 @@ public:
std::cout << "send_buff_off: " << send_buff_off << std::endl;
}
+ //pointers to sections in the mapped memory
+ ring_buffer_info (*recv_info)[], (*send_info)[];
+ char *recv_buff, *send_buff;
+
//set the internal pointers for info and buffers
typedef ring_buffer_info (*rbi_pta)[];
char *rb_ptr = reinterpret_cast<char *>(_mapped_mem);
- _recv_info = reinterpret_cast<rbi_pta>(rb_ptr + recv_info_off);
- _recv_buff = rb_ptr + recv_buff_off;
- _send_info = reinterpret_cast<rbi_pta>(rb_ptr + send_info_off);
- _send_buff = rb_ptr + send_buff_off;
+ recv_info = reinterpret_cast<rbi_pta>(rb_ptr + recv_info_off);
+ recv_buff = rb_ptr + recv_buff_off;
+ send_info = reinterpret_cast<rbi_pta>(rb_ptr + send_info_off);
+ send_buff = rb_ptr + send_buff_off;
+
+ //initialize the managed receive buffers
+ for (size_t i = 0; i < get_num_recv_frames(); i++){
+ _mrb_pool.push_back(usrp_e100_mmap_zero_copy_mrb(
+ recv_buff + get_recv_frame_size()*i, (*recv_info) + i
+ ));
+ }
+
+ //initialize the managed send buffers
+ for (size_t i = 0; i < get_num_recv_frames(); i++){
+ _msb_pool.push_back(usrp_e100_mmap_zero_copy_msb(
+ send_buff + get_send_frame_size()*i, (*send_info) + i,
+ get_send_frame_size(), _fd
+ ));
+ }
}
~usrp_e100_mmap_zero_copy_impl(void){
@@ -97,13 +192,10 @@ public:
managed_recv_buffer::sptr get_recv_buff(double timeout){
if (fp_verbose) std::cout << "get_recv_buff: " << _recv_index << std::endl;
-
- //grab pointers to the info and buffer
- ring_buffer_info *info = (*_recv_info) + _recv_index;
- void *mem = _recv_buff + _frame_size*_recv_index;
+ usrp_e100_mmap_zero_copy_mrb &mrb = _mrb_pool[_recv_index];
//poll/wait for a ready frame
- if (not (info->flags & RB_USER)){
+ if (not mrb.ready()){
for (size_t i = 0; i < poll_breakout; i++){
pollfd pfd;
pfd.fd = _fd;
@@ -115,18 +207,11 @@ public:
return managed_recv_buffer::sptr(); //timed-out for real
} found_user_frame:
- //the process has claimed the frame
- info->flags = RB_USER_PROCESS;
-
//increment the index for the next call
- if (++_recv_index == size_t(_rb_size.num_rx_frames)) _recv_index = 0;
+ if (++_recv_index == get_num_recv_frames()) _recv_index = 0;
//return the managed buffer for this frame
- if (fp_verbose) std::cout << " make_recv_buff: " << info->len << std::endl;
- return managed_recv_buffer::make_safe(
- mem, info->len,
- boost::bind(&usrp_e100_mmap_zero_copy_impl::release, this, info)
- );
+ return mrb.get_new();
}
size_t get_num_recv_frames(void) const{
@@ -139,13 +224,10 @@ public:
managed_send_buffer::sptr get_send_buff(double timeout){
if (fp_verbose) std::cout << "get_send_buff: " << _send_index << std::endl;
-
- //grab pointers to the info and buffer
- ring_buffer_info *info = (*_send_info) + _send_index;
- void *mem = _send_buff + _frame_size*_send_index;
+ usrp_e100_mmap_zero_copy_msb &msb = _msb_pool[_send_index];
//poll/wait for a ready frame
- if (not (info->flags & RB_KERNEL)){
+ if (not msb.ready()){
pollfd pfd;
pfd.fd = _fd;
pfd.events = POLLOUT;
@@ -155,14 +237,10 @@ public:
}
//increment the index for the next call
- if (++_send_index == size_t(_rb_size.num_tx_frames)) _send_index = 0;
+ if (++_send_index == get_num_send_frames()) _send_index = 0;
//return the managed buffer for this frame
- if (fp_verbose) std::cout << " make_send_buff: " << _frame_size << std::endl;
- return managed_send_buffer::make_safe(
- mem, _frame_size,
- boost::bind(&usrp_e100_mmap_zero_copy_impl::commit, this, info, _1)
- );
+ return msb.get_new();
}
size_t get_num_send_frames(void) const{
@@ -174,21 +252,7 @@ public:
}
private:
-
- void release(ring_buffer_info *info){
- if (fp_verbose) std::cout << "recv buff: release" << std::endl;
- info->flags = RB_KERNEL;
- }
-
- void commit(ring_buffer_info *info, size_t len){
- if (fp_verbose) std::cout << "send buff: commit " << len << std::endl;
- info->len = len;
- info->flags = RB_USER;
- if (::write(_fd, NULL, 0) < 0){
- std::cerr << UHD_THROW_SITE_INFO("write error") << std::endl;
- }
- }
-
+ //file descriptor for mmap
int _fd;
//the mapped memory itself
@@ -198,9 +262,9 @@ private:
usrp_e_ring_buffer_size_t _rb_size;
size_t _frame_size, _map_size;
- //pointers to sections in the mapped memory
- ring_buffer_info (*_recv_info)[], (*_send_info)[];
- char *_recv_buff, *_send_buff;
+ //re-usable managed buffers
+ std::vector<usrp_e100_mmap_zero_copy_mrb> _mrb_pool;
+ std::vector<usrp_e100_mmap_zero_copy_msb> _msb_pool;
//indexes into sub-sections of mapped memory
size_t _recv_index, _send_index;