iteration for huge reads and writes, async suspend call for polling

develop
Petr Mrázek 2010-01-02 02:25:21 +00:00
parent a597c69915
commit 91f64ac8ba
8 changed files with 140 additions and 36 deletions

@ -1115,6 +1115,11 @@ bool API::Suspend()
{
return d->p->suspend();
}
bool API::AsyncSuspend()
{
return d->p->asyncSuspend();
}
bool API::Resume()
{
return d->p->resume();

@ -57,6 +57,8 @@ namespace DFHack
// stop DF from executing
bool Suspend();
// stop DF from executing, asynchronous, use with polling
bool AsyncSuspend();
// resume DF
bool Resume();
/**

@ -236,7 +236,6 @@ SHMProcess::SHMProcess(vector <memory_info> & known_versions)
gcc_barrier
// at this point, DF is stopped and waiting for commands. make it run again
((shm_cmd *)d->my_shm)->pingpong = DFPP_RUNNING;
fprintf(stderr,"detach: %d",shmdt(d->my_shm));
}
bool SHMProcess::isSuspended()
@ -355,7 +354,6 @@ void SHMProcess::getMemRanges( vector<t_memrange> & ranges )
bool SHMProcess::suspend()
{
int status;
if(!d->attached)
{
return false;
@ -373,6 +371,28 @@ bool SHMProcess::suspend()
return true;
}
bool SHMProcess::asyncSuspend()
{
if(!d->attached)
{
return false;
}
if(d->suspended)
{
return true;
}
if(((shm_cmd *)d->my_shm)->pingpong == DFPP_SUSPENDED)
{
d->suspended = true;
return true;
}
else
{
((shm_cmd *)d->my_shm)->pingpong = DFPP_SUSPEND;
return false;
}
}
bool SHMProcess::forceresume()
{
return resume();
@ -442,17 +462,41 @@ bool SHMProcess::detach()
return false;
}
// FIXME: use recursion
void SHMProcess::read (const uint32_t offset, const uint32_t size, uint8_t *target)
void SHMProcess::read (uint32_t src_address, uint32_t size, uint8_t *target_buffer)
{
assert (size < (SHM_SIZE - sizeof(shm_read)));
((shm_read *)d->my_shm)->address = offset;
((shm_read *)d->my_shm)->length = size;
gcc_barrier
((shm_read *)d->my_shm)->pingpong = DFPP_READ;
d->waitWhile(DFPP_READ);
memcpy (target, d->my_shm + SHM_HEADER,size);
// normal read under 1MB
if(size <= SHM_BODY)
{
((shm_read *)d->my_shm)->address = src_address;
((shm_read *)d->my_shm)->length = size;
gcc_barrier
((shm_read *)d->my_shm)->pingpong = DFPP_READ;
d->waitWhile(DFPP_READ);
memcpy (target_buffer, d->my_shm + SHM_HEADER,size);
}
// a big read, we pull data over the shm in iterations
else
{
// first read equals the size of the SHM window
uint32_t to_read = SHM_BODY;
while (size)
{
// read to_read bytes from src_cursor
((shm_read *)d->my_shm)->address = src_address;
((shm_read *)d->my_shm)->length = to_read;
gcc_barrier
((shm_read *)d->my_shm)->pingpong = DFPP_READ;
d->waitWhile(DFPP_READ);
memcpy (target_buffer, d->my_shm + SHM_HEADER,size);
// decrease size by bytes read
size -= to_read;
// move the cursors
src_address += to_read;
target_buffer += to_read;
// check how much to write in the next iteration
to_read = min(size, (uint32_t) SHM_BODY);
}
}
}
uint8_t SHMProcess::readByte (const uint32_t offset)
@ -540,14 +584,41 @@ void SHMProcess::writeByte (uint32_t offset, uint8_t data)
d->waitWhile(DFPP_WRITE_BYTE);
}
void SHMProcess::write (uint32_t offset, uint32_t size, const uint8_t *source)
void SHMProcess::write (uint32_t dst_address, uint32_t size, uint8_t *source_buffer)
{
((shm_write *)d->my_shm)->address = offset;
((shm_write *)d->my_shm)->length = size;
memcpy(d->my_shm+SHM_HEADER,source, size);
gcc_barrier
((shm_write *)d->my_shm)->pingpong = DFPP_WRITE;
d->waitWhile(DFPP_WRITE);
// normal write under 1MB
if(size <= SHM_BODY)
{
((shm_write *)d->my_shm)->address = dst_address;
((shm_write *)d->my_shm)->length = size;
memcpy(d->my_shm+SHM_HEADER,source_buffer, size);
gcc_barrier
((shm_write *)d->my_shm)->pingpong = DFPP_WRITE;
d->waitWhile(DFPP_WRITE);
}
// a big write, we push this over the shm in iterations
else
{
// first write equals the size of the SHM window
uint32_t to_write = SHM_BODY;
while (size)
{
// write to_write bytes to dst_cursor
((shm_write *)d->my_shm)->address = dst_address;
((shm_write *)d->my_shm)->length = to_write;
memcpy(d->my_shm+SHM_HEADER,source_buffer, to_write);
gcc_barrier
((shm_write *)d->my_shm)->pingpong = DFPP_WRITE;
d->waitWhile(DFPP_WRITE);
// decrease size by bytes written
size -= to_write;
// move the cursors
source_buffer += to_write;
dst_address += to_write;
// check how much to write in the next iteration
to_write = min(size, (uint32_t) SHM_BODY);
}
}
}
// FIXME: butt-fugly

@ -239,6 +239,11 @@ void NormalProcess::getMemRanges( vector<t_memrange> & ranges )
}
}
bool NormalProcess::asyncSuspend()
{
return suspend();
}
bool NormalProcess::suspend()
{
int status;
@ -470,7 +475,7 @@ void NormalProcess::writeByte (uint32_t offset, uint8_t data)
}
// blah. I hate the kernel devs for crippling /proc/PID/mem. THIS IS RIDICULOUS
void NormalProcess::write (uint32_t offset, uint32_t size, const uint8_t *source)
void NormalProcess::write (uint32_t offset, uint32_t size, uint8_t *source)
{
uint32_t indexptr = 0;
while (size > 0)

@ -196,6 +196,11 @@ bool NormalProcess::isIdentified()
return d->identified;
}
bool NormalProcess::asyncSuspend()
{
return suspend();
}
bool NormalProcess::suspend()
{
if(!d->attached)
@ -365,7 +370,7 @@ void NormalProcess::writeByte (uint32_t offset, uint8_t data)
WriteProcessMemory(d->my_handle, (int*) offset, &data, sizeof(uint8_t), NULL);
}
void NormalProcess::write (uint32_t offset, uint32_t size, const uint8_t *source)
void NormalProcess::write (uint32_t offset, uint32_t size, uint8_t *source)
{
WriteProcessMemory(d->my_handle, (int*) offset, source, size, NULL);
}

@ -61,11 +61,20 @@ namespace DFHack
class DFHACK_EXPORT Process
{
public:
// Set up stuff so we can read memory, suspends synchronously
virtual bool attach() = 0;
// detach from DF, resume its execution if it's suspended
virtual bool detach() = 0;
// synchronous suspend
// waits for DF to be actually suspended,
// this might take a while depending on implementation
virtual bool suspend() = 0;
// asynchronous suspend to use together with polling and timers
virtual bool asyncSuspend() = 0;
// resume DF execution
virtual bool resume() = 0;
// force-resume DF execution
virtual bool forceresume() = 0;
virtual uint32_t readDWord(const uint32_t address) = 0;
@ -74,12 +83,12 @@ namespace DFHack
virtual void readWord(const uint32_t address, uint16_t & value) = 0;
virtual uint8_t readByte(const uint32_t address) = 0;
virtual void readByte(const uint32_t address, uint8_t & value) = 0;
virtual void read( const uint32_t address, const uint32_t length, uint8_t* buffer) = 0;
virtual void read( uint32_t address, uint32_t length, uint8_t* buffer) = 0;
virtual void writeDWord(const uint32_t address, const uint32_t value) = 0;
virtual void writeWord(const uint32_t address, const uint16_t value) = 0;
virtual void writeByte(const uint32_t address, const uint8_t value) = 0;
virtual void write(const uint32_t address,const uint32_t length, const uint8_t* buffer) = 0;
virtual void write(uint32_t address, uint32_t length, uint8_t* buffer) = 0;
virtual const std::string readCString (uint32_t offset) = 0;
@ -87,12 +96,18 @@ namespace DFHack
virtual bool isAttached() = 0;
virtual bool isIdentified() = 0;
// find the thread IDs of the process
virtual bool getThreadIDs(vector<uint32_t> & threads ) = 0;
// get virtual memory ranges of the process (what is mapped where)
virtual void getMemRanges( vector<t_memrange> & ranges ) = 0;
// get the flattened Memory.xml entry of this process
virtual memory_info *getDescriptor() = 0;
// get the DataModel for reading stl containers (depends on the version of stl DF was compiled with)
virtual DataModel *getDataModel() = 0;
// get the DF's window (first that can be found ~_~)
virtual DFWindow * getWindow() = 0;
// get the DF Process ID
virtual int getPID() = 0;
};
@ -105,11 +120,11 @@ namespace DFHack
NormalProcess(uint32_t pid, vector <memory_info> & known_versions);
~NormalProcess();
public:
// Set up stuff so we can read memory
bool attach();
bool detach();
bool suspend();
bool asyncSuspend();
bool resume();
bool forceresume();
@ -119,12 +134,12 @@ namespace DFHack
void readWord(const uint32_t address, uint16_t & value);
uint8_t readByte(const uint32_t address);
void readByte(const uint32_t address, uint8_t & value);
void read( const uint32_t address, const uint32_t length, uint8_t* buffer);
void read( uint32_t address, uint32_t length, uint8_t* buffer);
void writeDWord(const uint32_t address, const uint32_t value);
void writeWord(const uint32_t address, const uint16_t value);
void writeByte(const uint32_t address, const uint8_t value);
void write(const uint32_t address,const uint32_t length, const uint8_t* buffer);
void write(uint32_t address, uint32_t length, uint8_t* buffer);
const std::string readCString (uint32_t offset);
@ -154,6 +169,7 @@ namespace DFHack
bool detach();
bool suspend();
bool asyncSuspend();
bool resume();
bool forceresume();
@ -163,12 +179,12 @@ namespace DFHack
void readWord(const uint32_t address, uint16_t & value);
uint8_t readByte(const uint32_t address);
void readByte(const uint32_t address, uint8_t & value);
void read( const uint32_t address, const uint32_t length, uint8_t* buffer);
void read( uint32_t address, uint32_t length, uint8_t* buffer);
void writeDWord(const uint32_t address, const uint32_t value);
void writeWord(const uint32_t address, const uint16_t value);
void writeByte(const uint32_t address, const uint8_t value);
void write(const uint32_t address,const uint32_t length, const uint8_t* buffer);
void write(uint32_t address, uint32_t length, uint8_t* buffer);
const std::string readCString (uint32_t offset);

@ -115,7 +115,7 @@ ProcessEnumerator::ProcessEnumerator( string path_to_xml )
d->meminfo = new MemInfoManager(path_to_xml);
}
ProcessEnumerator::purge()
void ProcessEnumerator::purge()
{
for(uint32_t i = 0;i < d->processes.size();i++)
{

@ -31,13 +31,13 @@ int main (void)
cout << "Suspended, DF should be suspended now" << endl;
getline(cin, blah);
DF.Resume();
cout << "Resumed, testing ForceResume. Suspend using SysInternals Process Explorer" << endl;
getline(cin, blah);
DF.Resume();
cout << "Resumed, testing ForceResume. Suspend using SysInternals Process Explorer" << endl;
getline(cin, blah);
DF.ForceResume();
cout << "ForceResumed. DF should be running." << endl;
getline(cin, blah);
DF.ForceResume();
cout << "ForceResumed. DF should be running." << endl;
getline(cin, blah);
if(!DF.Detach())
{