mirror of
https://github.com/saymrwulf/uhd.git
synced 2026-05-16 21:10:10 +00:00
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...
This commit is contained in:
parent
153f2575bb
commit
8ffd7e04c4
4 changed files with 112 additions and 193 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -32,6 +32,82 @@ static const bool fp_verbose = false; //fast-path verbose
|
|||
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
|
||||
**********************************************************************/
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue