Commit 949dd995 authored by Sebastien Petitdemange's avatar Sebastien Petitdemange
Browse files

Use mmap to avoid memcpy

parent f4d3a9d1
......@@ -25,6 +25,7 @@
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/types.h>
#include <sys/mman.h>
#include "Debug.h"
#include "PilatusInterface.h"
......@@ -372,6 +373,65 @@ void SyncCtrlObj::prepareAcq()
m_cam.setNbImagesInSequence(nb_frames);
}
/*****************************************************************************
Memory map manager
*****************************************************************************/
class _MmapManager : public HwBufferCtrlObj::Callback
{
DEB_CLASS(DebModCamera, "Pilatus::_MmapManager");
typedef std::pair<void*,long> AddressNSize;
typedef std::map<void*,AddressNSize> Data2BaseNSize;
typedef std::multiset<void *> BufferList;
public:
_MmapManager() : HwBufferCtrlObj::Callback() {}
virtual void map(void* address)
{
DEB_MEMBER_FUNCT();
AutoMutex lock(m_mutex);
m_buffer_in_use.insert(address);
}
virtual void release(void* address)
{
DEB_MEMBER_FUNCT();
AutoMutex lock(m_mutex);
BufferList::iterator it = m_buffer_in_use.find(address);
if(it == m_buffer_in_use.end())
THROW_HW_ERROR(Error) << "Internal error: releasing buffer not in used list";
m_buffer_in_use.erase(it++);
if(it == m_buffer_in_use.end() || *it != address)
{
Data2BaseNSize::iterator mmap_info = m_data_2_base_n_size.find(address);
munmap(mmap_info->second.first,mmap_info->second.second);
m_data_2_base_n_size.erase(mmap_info);
}
}
virtual void releaseAll()
{
DEB_MEMBER_FUNCT();
AutoMutex lock(m_mutex);
for(Data2BaseNSize::iterator mmap_info = m_data_2_base_n_size.begin();
mmap_info != m_data_2_base_n_size.end();++mmap_info)
munmap(mmap_info->second.first,mmap_info->second.second);
m_data_2_base_n_size.clear();
m_buffer_in_use.clear();
}
void register_new_mmap(void *mmap_mem_base,
void *aDataBuffer,long length)
{
AutoMutex lock(m_mutex);
m_data_2_base_n_size[aDataBuffer] = AddressNSize(mmap_mem_base,length);
}
private:
Mutex m_mutex;
Data2BaseNSize m_data_2_base_n_size;
BufferList m_buffer_in_use;
};
/*******************************************************************
* \brief Interface::_BufferCallback
......@@ -398,15 +458,11 @@ public:
FrameDim anImageDim;
getFrameDim(anImageDim);
void *aDataBuffer;
if(posix_memalign(&aDataBuffer,16,anImageDim.getMemSize()))
THROW_HW_ERROR(Error) << "Can't allocate memory";
long memSize = anImageDim.getMemSize();
int fd = open(full_path,O_RDONLY);
if(fd < 0)
{
free(aDataBuffer);
if(from == HwFileEventCallbackHelper::OnDemand)
THROW_HW_ERROR(Error) << "Image is no more available";
else
......@@ -415,20 +471,23 @@ public:
THROW_HW_ERROR(Error) << "Can't open file:" << DEB_VAR1(full_path);
}
}
lseek(fd,DECTRIS_EDF_OFFSET,SEEK_SET);
ssize_t aReadSize = read(fd,aDataBuffer,anImageDim.getMemSize());
if(aReadSize != anImageDim.getMemSize())
void* mmap_mem_base = mmap(NULL,DECTRIS_EDF_OFFSET + memSize,
PROT_READ,MAP_SHARED,fd,0);
close(fd);
if(mmap_mem_base == MAP_FAILED)
{
close(fd),free(aDataBuffer);
m_interface.m_cam.errorStopAcquisition();
THROW_HW_ERROR(Error) << "Problem to read image:" << DEB_VAR1(full_path);
}
close(fd);
void* aDataBuffer = (char*)mmap_mem_base + DECTRIS_EDF_OFFSET;
frame_info = HwFrameInfoType(image_number,aDataBuffer,&anImageDim,
Timestamp(),0,
HwFrameInfoType::Shared);
HwFrameInfoType::Managed);
m_mmap_manager.register_new_mmap(mmap_mem_base,
aDataBuffer,DECTRIS_EDF_OFFSET + memSize);
bool aReturnFlag = true;
if(m_interface.m_buffer.getNbOfFramePending() > 32)
{
......@@ -452,8 +511,13 @@ public:
frame_dim.setSize(current_size);
frame_dim.setImageType(current_image_type);
}
virtual HwBufferCtrlObj::Callback* getBufferCallback()
{
return &m_mmap_manager;
}
private:
Interface& m_interface;
_MmapManager m_mmap_manager;
};
/*******************************************************************
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment