SHM rework, stage 2

develop
Petr Mrázek 2010-03-05 00:05:01 +01:00
parent 088028cc5f
commit c86464502c
15 changed files with 396 additions and 146 deletions

@ -47,9 +47,7 @@ int main (int numargs, char** args)
uint32_t x_max,y_max,z_max;
uint32_t num_blocks = 0;
uint64_t bytes_read = 0;
uint16_t tiletypes[16][16];
DFHack::t_designation designations[16][16];
DFHack::t_occupancy occupancies[16][16];
DFHack::mapblock40d Block;
DFHack::API DF("Memory.xml");
if(!DF.Attach())
@ -76,11 +74,9 @@ int main (int numargs, char** args)
{
if(DF.isValidBlock(x,y,z))
{
DF.ReadTileTypes(x,y,z, (uint16_t *) tiletypes);
DF.ReadDesignations(x,y,z, (uint32_t *) designations);
DF.ReadOccupancy(x,y,z, (uint32_t *) occupancies);
DF.ReadBlock40d(x, y, z, &Block);
num_blocks ++;
bytes_read += sizeof(tiletypes) + sizeof(designations) + sizeof(occupancies);
bytes_read += sizeof(DFHack::mapblock40d);
}
}
}

@ -144,8 +144,6 @@ void clrscr()
GRASS2,
GRASS_DEAD,
GRASS_DRY,
#include <DFProcess.h>
#include <DFProcess.h>
DRIFTWOOD,
HFS,
MAGMA,
@ -272,9 +270,12 @@ main(int argc, char *argv[])
int x_max,y_max,z_max;
uint32_t x_max_a,y_max_a,z_max_a;
/*
uint16_t tiletypes[16][16];
DFHack::t_designation designations[16][16];
uint8_t regionoffsets[16];
*/
mapblock40d Block;
map <int16_t, uint32_t> materials;
materials.clear();
vector<DFHack::t_matgloss> stonetypes;
@ -300,7 +301,6 @@ main(int argc, char *argv[])
error = "Can't find a map to look at.";
pDF = 0;
finish(0);
#include <DFMemInfo.h>
}
DF.getSize(x_max_a,y_max_a,z_max_a);
@ -401,30 +401,34 @@ main(int argc, char *argv[])
if(DF.isValidBlock(cursorX+i,cursorY+j,cursorZ))
{
// read data
DF.ReadBlock40d(cursorX+i,cursorY+j,cursorZ, &Block);
/*
DF.ReadTileTypes(cursorX+i,cursorY+j,cursorZ, (uint16_t *) tiletypes);
DF.ReadDesignations(cursorX+i,cursorY+j,cursorZ, (uint32_t *) designations);
*/
for(int x = 0; x < 16; x++)
{
for(int y = 0; y < 16; y++)
{
if(dig)
{
if(tileTypeTable[tiletypes[x][y]].c == WALL && tileTypeTable[tiletypes[x][y]].m == VEIN
|| tileTypeTable[tiletypes[x][y]].c == TREE_OK || tileTypeTable[tiletypes[x][y]].c == TREE_DEAD)
TileClass tc = tileTypeTable[Block.tiletypes[x][y]].c;
TileMaterial tm = tileTypeTable[Block.tiletypes[x][y]].m;
if( tc == WALL && tm == VEIN || tc == TREE_OK || tc == TREE_DEAD)
{
designations[x][y].bits.dig = designation_default;
Block.designaton[x][y].bits.dig = designation_default;
}
}
int color = COLOR_BLACK;
color = pickColor(tiletypes[x][y]);
if(designations[x][y].bits.hidden)
color = pickColor(Block.tiletypes[x][y]);
if(Block.designaton[x][y].bits.hidden)
{
puttile(x+(i+1)*16,y+(j+1)*16,tiletypes[x][y], color);
puttile(x+(i+1)*16,y+(j+1)*16,Block.tiletypes[x][y], color);
}
else
{
attron(A_STANDOUT);
puttile(x+(i+1)*16,y+(j+1)*16,tiletypes[x][y], color);
puttile(x+(i+1)*16,y+(j+1)*16,Block.tiletypes[x][y], color);
attroff(A_STANDOUT);
}
}
@ -439,7 +443,7 @@ main(int argc, char *argv[])
filenum++;
}
if(dig)
DF.WriteDesignations(cursorX+i,cursorY+j,cursorZ, (uint32_t *) designations);
DF.WriteDesignations(cursorX+i,cursorY+j,cursorZ, (uint32_t *) Block.designaton);
DF.ReadDirtyBit(cursorX+i,cursorY+j,cursorZ,dirtybit);
if(digbit)
{

@ -23,6 +23,9 @@ distribution.
*/
#include "DFCommonInternal.h"
#include "../shmserver/shms.h"
#include "../shmserver/mod-core.h"
#include "../shmserver/mod-maps.h"
using namespace DFHack;
/*
@ -106,6 +109,7 @@ public:
ProcessEnumerator* pm;
Process* p;
char * shm_start;
memory_info* offset_descriptor;
vector<uint16_t> v_geology[eBiomeCount];
string xml;
@ -122,6 +126,8 @@ public:
bool settlementsInited;
bool nameTablesInited;
uint32_t maps_module;
uint32_t tree_offset;
DfVector *p_cre;
DfVector *p_cons;
@ -149,6 +155,8 @@ API::API (const string path_to_xml)
d->notesInited = false;
d->hotkeyInited = false;
d->pm = NULL;
d->shm_start = 0;
d->maps_module = 0;
}
API::~API()
@ -156,6 +164,11 @@ API::~API()
delete d;
}
#define SHMCMD ((shm_cmd *)d->shm_start)->pingpong
#define SHMHDR ((shm_core_hdr *)d->shm_start)
#define SHMMAPSHDR ((Maps::shm_maps_hdr *)d->shm_start)
#define SHMDATA(type) ((type *)(d->shm_start + SHM_HEADER))
/*-----------------------------------*
* Init the mapblock pointer array *
*-----------------------------------*/
@ -182,18 +195,42 @@ bool API::InitMap()
d->vein_mineral_vptr = 0;
d->offset_descriptor->resolveClassnameToVPtr("block_square_event_mineral",d->vein_mineral_vptr);
/*
* --> SHM initialization (if possible) <--
*/
g_pProcess->getModuleIndex("Maps",1,d->maps_module);
if(d->maps_module)
{
// supply the module with offsets so it can work with them
Maps::maps_offsets *off = SHMDATA(Maps::maps_offsets);
off->biome_stuffs = d->biome_stuffs;
off->designation_offset = d->designation_offset;
off->map_offset = map_offset;
off->occupancy_offset = d->occupancy_offset;
off->tile_type_offset = d->tile_type_offset;
off->vein_ice_vptr = d->vein_ice_vptr; // FIXME: not necessarily true, the shm server side needs a class lookup >_<
off->vein_mineral_vptr = d->vein_mineral_vptr; // FIXME: not necessarily true, the shm server side needs a class lookup >_<
off->veinvector = d->veinvector;
off->x_count_offset = x_count_offset;
off->y_count_offset = y_count_offset;
off->z_count_offset = z_count_offset;
full_barrier
const uint32_t cmd = Maps::MAP_INIT + d->maps_module << 16;
SHMCMD = cmd;
g_pProcess->waitWhile(cmd);
//cerr << "Map acceleration enabled!" << endl;
}
// get the map pointer
uint32_t x_array_loc = g_pProcess->readDWord (map_offset);
//FIXME: very inadequate
if (!x_array_loc)
{
throw Error::NoMapLoaded();
// bad stuffz happend
//return false;
}
uint32_t mx, my, mz;
// get the size
uint32_t mx, my, mz;
mx = d->x_block_count = g_pProcess->readDWord (x_count_offset);
my = d->y_block_count = g_pProcess->readDWord (y_count_offset);
mz = d->z_block_count = g_pProcess->readDWord (z_count_offset);
@ -253,6 +290,41 @@ uint32_t API::getBlockPtr (uint32_t x, uint32_t y, uint32_t z)
return d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z];
}
bool API::ReadBlock40d(uint32_t x, uint32_t y, uint32_t z, mapblock40d * buffer)
{
if(d->shm_start && d->maps_module) // ACCELERATE!
{
SHMMAPSHDR->x = x;
SHMMAPSHDR->y = y;
SHMMAPSHDR->z = z;
const uint32_t cmd = Maps::MAP_READ_BLOCK_BY_COORDS + (d->maps_module << 16);
full_barrier
SHMCMD = cmd;
if(!g_pProcess->waitWhile(cmd))
{
return false;
}
memcpy(buffer,SHMDATA(mapblock40d),sizeof(mapblock40d));
return true;
}
else // plain old block read
{
uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z];
if (addr)
{
g_pProcess->read (addr + d->tile_type_offset, sizeof (buffer->tiletypes), (uint8_t *) buffer->tiletypes);
g_pProcess->read (addr + d->occupancy_offset, sizeof (buffer->occupancy), (uint8_t *) buffer->occupancy);
g_pProcess->read (addr + d->designation_offset, sizeof (buffer->designaton), (uint8_t *) buffer->designaton);
g_pProcess->read (addr + d->biome_stuffs, sizeof (buffer->biome_indices), (uint8_t *) buffer->biome_indices);
uint32_t addr_of_struct = g_pProcess->readDWord(addr);
buffer->dirty_dword = g_pProcess->readDWord(addr_of_struct);
return true;
}
return false;
}
}
// 256 * sizeof(uint16_t)
bool API::ReadTileTypes (uint32_t x, uint32_t y, uint32_t z, uint16_t *buffer)
{
@ -713,7 +785,7 @@ bool API::ReadGeology (vector < vector <uint16_t> >& assign)
}
assign.clear();
assign.reserve (eBiomeCount);
// TODO: clean this up
// // TODO: clean this up
for (int i = 0; i < eBiomeCount;i++)
{
assign.push_back (d->v_geology[i]);
@ -1341,6 +1413,7 @@ bool API::Attach()
//cerr << "couldn't attach to process" << endl;
//return false; // couldn't attach to process, no go
}
d->shm_start = d->p->getSHMStart();
d->offset_descriptor = d->p->getDescriptor();
// process is attached, everything went just fine... hopefully
return true;
@ -1359,6 +1432,7 @@ bool API::Detach()
}
d->pm = NULL;
d->p = NULL;
d->shm_start = 0;
d->offset_descriptor = NULL;
return true;
}

@ -135,6 +135,8 @@ namespace DFHack
*/
uint32_t getBlockPtr (uint32_t blockx, uint32_t blocky, uint32_t blockz);
bool ReadBlock40d(uint32_t blockx, uint32_t blocky, uint32_t blockz, mapblock40d * buffer);
bool ReadTileTypes(uint32_t blockx, uint32_t blocky, uint32_t blockz, uint16_t *buffer); // 256 * sizeof(uint16_t)
bool WriteTileTypes(uint32_t blockx, uint32_t blocky, uint32_t blockz, uint16_t *buffer); // 256 * sizeof(uint16_t)

@ -28,7 +28,7 @@ distribution.
#include <sys/ipc.h>
#include <time.h>
#include "../shmserver/shms.h"
#include "../shmserver/shms-core.h"
#include "../shmserver/mod-core.h"
#include <sys/time.h>
#include <time.h>
#include <sched.h>
@ -59,6 +59,7 @@ class Process::Private
pid_t my_pid;
char *my_shm;
int my_shmid;
Process* q;
bool attached;
bool suspended;
@ -66,10 +67,10 @@ class Process::Private
bool useYield;
bool validate(char* exe_file, uint32_t pid, std::vector< memory_info* >& known_versions);
bool waitWhile (CORE_COMMAND state);
bool DF_TestBridgeVersion(bool & ret);
bool DF_GetPID(pid_t & ret);
void DF_SyncAffinity(void);
bool waitWhile (uint32_t state);
};
// some helpful macros to keep the code bloat in check
@ -83,7 +84,7 @@ class Process::Private
Yeah. with no way to synchronize things (locks are slow, the OS doesn't give us enough control over scheduling)
we end up with this silly thing
*/
bool Process::Private::waitWhile (CORE_COMMAND state)
bool Process::Private::waitWhile (uint32_t state)
{
uint32_t cnt = 0;
struct shmid_ds descriptor;
@ -121,6 +122,48 @@ bool Process::Private::waitWhile (CORE_COMMAND state)
return true;
}
/*
Yeah. with no way to synchronize things (locks are slow, the OS doesn't give us enough control over scheduling)
we end up with this silly thing
*/
bool Process::waitWhile (uint32_t state)
{
uint32_t cnt = 0;
struct shmid_ds descriptor;
while (D_SHMCMD == state)
{
if(cnt == 10000)// check if the other process is still there
{
shmctl(d->my_shmid, IPC_STAT, &descriptor);
if(descriptor.shm_nattch == 1)// DF crashed?
{
D_SHMCMD = CORE_RUNNING;
d->attached = d->suspended = false;
return false;
}
else
{
cnt = 0;
}
}
if(d->useYield)
{
SCHED_YIELD
}
cnt++;
}
if(D_SHMCMD == CORE_SV_ERROR)
{
D_SHMCMD = CORE_RUNNING;
d->attached = d->suspended = false;
cerr << "shm server error!" << endl;
assert (false);
return false;
}
return true;
}
bool Process::Private::DF_TestBridgeVersion(bool & ret)
{
SHMCMD = CORE_GET_VERSION;
@ -363,7 +406,7 @@ bool Process::suspend()
return true;
}
D_SHMCMD = CORE_SUSPEND;
if(!d->waitWhile(CORE_SUSPEND))
if(!waitWhile(CORE_SUSPEND))
{
return false;
}
@ -472,7 +515,7 @@ void Process::read (uint32_t src_address, uint32_t size, uint8_t *target_buffer)
D_SHMHDR->length = size;
gcc_barrier
D_SHMCMD = CORE_DFPP_READ;
d->waitWhile(CORE_DFPP_READ);
waitWhile(CORE_DFPP_READ);
memcpy (target_buffer, d->my_shm + SHM_HEADER,size);
}
// a big read, we pull data over the shm in iterations
@ -487,7 +530,7 @@ void Process::read (uint32_t src_address, uint32_t size, uint8_t *target_buffer)
D_SHMHDR->length = to_read;
gcc_barrier
D_SHMCMD = CORE_DFPP_READ;
d->waitWhile(CORE_DFPP_READ);
waitWhile(CORE_DFPP_READ);
memcpy (target_buffer, d->my_shm + SHM_HEADER,size);
// decrease size by bytes read
size -= to_read;
@ -505,7 +548,7 @@ uint8_t Process::readByte (const uint32_t offset)
D_SHMHDR->address = offset;
gcc_barrier
D_SHMCMD = CORE_READ_BYTE;
d->waitWhile(CORE_READ_BYTE);
waitWhile(CORE_READ_BYTE);
return D_SHMHDR->value;
}
@ -514,7 +557,7 @@ void Process::readByte (const uint32_t offset, uint8_t &val )
D_SHMHDR->address = offset;
gcc_barrier
D_SHMCMD = CORE_READ_BYTE;
d->waitWhile(CORE_READ_BYTE);
waitWhile(CORE_READ_BYTE);
val = D_SHMHDR->value;
}
@ -523,7 +566,7 @@ uint16_t Process::readWord (const uint32_t offset)
D_SHMHDR->address = offset;
gcc_barrier
D_SHMCMD = CORE_READ_WORD;
d->waitWhile(CORE_READ_WORD);
waitWhile(CORE_READ_WORD);
return D_SHMHDR->value;
}
@ -532,7 +575,7 @@ void Process::readWord (const uint32_t offset, uint16_t &val)
D_SHMHDR->address = offset;
gcc_barrier
D_SHMCMD = CORE_READ_WORD;
d->waitWhile(CORE_READ_WORD);
waitWhile(CORE_READ_WORD);
val = D_SHMHDR->value;
}
@ -541,7 +584,7 @@ uint32_t Process::readDWord (const uint32_t offset)
D_SHMHDR->address = offset;
gcc_barrier
D_SHMCMD = CORE_READ_DWORD;
d->waitWhile(CORE_READ_DWORD);
waitWhile(CORE_READ_DWORD);
return D_SHMHDR->value;
}
void Process::readDWord (const uint32_t offset, uint32_t &val)
@ -549,7 +592,7 @@ void Process::readDWord (const uint32_t offset, uint32_t &val)
D_SHMHDR->address = offset;
gcc_barrier
D_SHMCMD = CORE_READ_DWORD;
d->waitWhile(CORE_READ_DWORD);
waitWhile(CORE_READ_DWORD);
val = D_SHMHDR->value;
}
@ -563,7 +606,7 @@ void Process::writeDWord (uint32_t offset, uint32_t data)
D_SHMHDR->value = data;
gcc_barrier
D_SHMCMD = CORE_WRITE_DWORD;
d->waitWhile(CORE_WRITE_DWORD);
waitWhile(CORE_WRITE_DWORD);
}
// using these is expensive.
@ -573,7 +616,7 @@ void Process::writeWord (uint32_t offset, uint16_t data)
D_SHMHDR->value = data;
gcc_barrier
D_SHMCMD = CORE_WRITE_WORD;
d->waitWhile(CORE_WRITE_WORD);
waitWhile(CORE_WRITE_WORD);
}
void Process::writeByte (uint32_t offset, uint8_t data)
@ -582,7 +625,7 @@ void Process::writeByte (uint32_t offset, uint8_t data)
D_SHMHDR->value = data;
gcc_barrier
D_SHMCMD = CORE_WRITE_BYTE;
d->waitWhile(CORE_WRITE_BYTE);
waitWhile(CORE_WRITE_BYTE);
}
void Process::write (uint32_t dst_address, uint32_t size, uint8_t *source_buffer)
@ -595,7 +638,7 @@ void Process::write (uint32_t dst_address, uint32_t size, uint8_t *source_buffer
memcpy(d->my_shm+SHM_HEADER,source_buffer, size);
gcc_barrier
D_SHMCMD = CORE_WRITE;
d->waitWhile(CORE_WRITE);
waitWhile(CORE_WRITE);
}
// a big write, we push this over the shm in iterations
else
@ -610,7 +653,7 @@ void Process::write (uint32_t dst_address, uint32_t size, uint8_t *source_buffer
memcpy(d->my_shm+SHM_HEADER,source_buffer, to_write);
gcc_barrier
D_SHMCMD = CORE_WRITE;
d->waitWhile(CORE_WRITE);
waitWhile(CORE_WRITE);
// decrease size by bytes written
size -= to_write;
// move the cursors
@ -661,7 +704,7 @@ const std::string Process::readSTLString(uint32_t offset)
D_SHMHDR->address = offset;
full_barrier
D_SHMCMD = CORE_READ_STL_STRING;
d->waitWhile(CORE_READ_STL_STRING);
waitWhile(CORE_READ_STL_STRING);
//int length = ((shm_retval *)d->my_shm)->value;
return(string( (char *)d->my_shm+SHM_HEADER));
}
@ -671,7 +714,7 @@ size_t Process::readSTLString (uint32_t offset, char * buffer, size_t bufcapacit
D_SHMHDR->address = offset;
full_barrier
D_SHMCMD = CORE_READ_STL_STRING;
d->waitWhile(CORE_READ_STL_STRING);
waitWhile(CORE_READ_STL_STRING);
size_t length = D_SHMHDR->value;
size_t fit = min(bufcapacity - 1, length);
strncpy(buffer,(char *)d->my_shm+SHM_HEADER,fit);
@ -685,7 +728,7 @@ void Process::writeSTLString(const uint32_t address, const std::string writeStri
strncpy(d->my_shm+SHM_HEADER,writeString.c_str(),writeString.length()+1); // length + 1 for the null terminator
full_barrier
D_SHMCMD = CORE_WRITE_STL_STRING;
d->waitWhile(CORE_WRITE_STL_STRING);
waitWhile(CORE_WRITE_STL_STRING);
}
string Process::readClassName (uint32_t vptr)
@ -697,3 +740,22 @@ string Process::readClassName (uint32_t vptr)
size_t end = raw.length();
return raw.substr(start,end-start - 2); // trim the 'st' from the end
}
// get module index by name and version. bool 1 = error
bool Process::getModuleIndex (const char * name, const uint32_t version, uint32_t & OUTPUT)
{
modulelookup * payload = (modulelookup *) (d->my_shm + SHM_HEADER);
payload->version = version;
strcpy(payload->name,name);
full_barrier
D_SHMCMD = CORE_ACQUIRE_MODULE;
waitWhile(CORE_ACQUIRE_MODULE);
if(D_SHMHDR->error) return false;
OUTPUT = D_SHMHDR->value;
return true;
}
char * Process::getSHMStart (void)
{
return d->my_shm;
}

@ -23,7 +23,7 @@ distribution.
*/
#include "DFCommonInternal.h"
#include "../shmserver/shms.h"
#include "../shmserver/shms-core.h"
#include "../shmserver/mod-core.h"
using namespace DFHack;
// a full memory barrier! better be safe than sorry.
@ -56,7 +56,7 @@ class Process::Private
bool identified;
bool useYield;
bool waitWhile (CORE_COMMAND state);
bool waitWhile (uint32_t state);
bool isValidSV();
bool DF_TestBridgeVersion(bool & ret);
bool DF_GetPID(uint32_t & ret);
@ -98,10 +98,15 @@ bool Process::Private::isValidSV()
}
}
bool Process::Private::waitWhile (CORE_COMMAND state)
bool Process::waitWhile (uint32_t state)
{
return d->waitWhile(state);
}
bool Process::Private::waitWhile (uint32_t state)
{
uint32_t cnt = 0;
while (((shm_cmd *)my_shm)->pingpong == state)
while (SHMCMD == state)
{
// yield the CPU, only on single-core CPUs
if(useYield)
@ -112,7 +117,7 @@ bool Process::Private::waitWhile (CORE_COMMAND state)
{
if(!isValidSV())// DF not there anymore?
{
((shm_cmd *)my_shm)->pingpong = CORE_RUNNING;
SHMCMD = CORE_RUNNING;
attached = suspended = false;
ReleaseMutex(DFCLMutex);
return false;
@ -124,9 +129,9 @@ bool Process::Private::waitWhile (CORE_COMMAND state)
}
cnt++;
}
if(((shm_cmd *)my_shm)->pingpong == CORE_SV_ERROR)
if(SHMCMD == CORE_SV_ERROR)
{
((shm_cmd *)my_shm)->pingpong = CORE_RUNNING;
SHMCMD = CORE_RUNNING;
attached = suspended = false;
cerr << "shm server error!" << endl;
return false;
@ -136,33 +141,28 @@ bool Process::Private::waitWhile (CORE_COMMAND state)
bool Process::Private::DF_TestBridgeVersion(bool & ret)
{
((shm_cmd *)my_shm)->pingpong = CORE_GET_VERSION;
SHMCMD = CORE_GET_VERSION;
full_barrier
if(!waitWhile(CORE_GET_VERSION))
return false;
full_barrier
((shm_cmd *)my_shm)->pingpong = CORE_SUSPENDED;
ret =( ((shm_val *)my_shm)->value == CORE_VERSION );
SHMCMD = CORE_SUSPENDED;
ret =( SHMHDR->value == CORE_VERSION );
return true;
}
bool Process::Private::DF_GetPID(uint32_t & ret)
{
((shm_cmd *)my_shm)->pingpong = CORE_GET_PID;
SHMCMD = CORE_GET_PID;
full_barrier
if(!waitWhile(CORE_GET_PID))
return false;
full_barrier
((shm_cmd *)my_shm)->pingpong = CORE_SUSPENDED;
ret = ((shm_val *)my_shm)->value;
SHMCMD = CORE_SUSPENDED;
ret = SHMHDR->value;
return true;
}
void Process::Private::DF_SyncAffinity(void)
{
}
uint32_t OS_getAffinity()
{
HANDLE hProcess = GetCurrentProcess();
@ -223,7 +223,7 @@ Process::Process(vector <memory_info *> & known_versions)
if(!bridgeOK)
{
fprintf(stderr,"SHM bridge version mismatch\n");
((shm_cmd *)d->my_shm)->pingpong = CORE_RUNNING;
D_SHMCMD = CORE_RUNNING;
UnmapViewOfFile(d->my_shm);
ReleaseMutex(d->DFCLMutex);
CloseHandle(d->DFSVMutex);
@ -300,7 +300,7 @@ Process::Process(vector <memory_info *> & known_versions)
}
else
{
((shm_cmd *)d->my_shm)->pingpong = CORE_RUNNING;
D_SHMCMD = CORE_RUNNING;
UnmapViewOfFile(d->my_shm);
d->my_shm = 0;
ReleaseMutex(d->DFCLMutex);
@ -417,7 +417,7 @@ bool Process::suspend()
cerr << "couldn't suspend, already suspended" << endl;
return true;
}
((shm_cmd *)d->my_shm)->pingpong = CORE_SUSPEND;
D_SHMCMD = CORE_SUSPEND;
if(!d->waitWhile(CORE_SUSPEND))
{
cerr << "couldn't suspend, DF not responding to commands" << endl;
@ -437,14 +437,14 @@ bool Process::asyncSuspend()
{
return true;
}
if(((shm_cmd *)d->my_shm)->pingpong == CORE_SUSPENDED)
if(D_SHMCMD == CORE_SUSPENDED)
{
d->suspended = true;
return true;
}
else
{
((shm_cmd *)d->my_shm)->pingpong = CORE_SUSPEND;
D_SHMCMD = CORE_SUSPEND;
return false;
}
}
@ -466,7 +466,7 @@ bool Process::resume()
cerr << "couldn't resume because of not being suspended" << endl;
return true;
}
((shm_cmd *)d->my_shm)->pingpong = CORE_RUNNING;
D_SHMCMD = CORE_RUNNING;
d->suspended = false;
return true;
}
@ -541,10 +541,10 @@ void Process::read (uint32_t src_address, uint32_t size, uint8_t *target_buffer)
// normal read under 1MB
if(size <= SHM_BODY)
{
((shm_addrlen *)d->my_shm)->address = src_address;
((shm_addrlen *)d->my_shm)->length = size;
D_SHMHDR->address = src_address;
D_SHMHDR->length = size;
full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_DFPP_READ;
D_SHMCMD = CORE_DFPP_READ;
d->waitWhile(CORE_DFPP_READ);
memcpy (target_buffer, d->my_shm + SHM_HEADER,size);
}
@ -556,10 +556,10 @@ void Process::read (uint32_t src_address, uint32_t size, uint8_t *target_buffer)
while (size)
{
// read to_read bytes from src_cursor
((shm_addrlen *)d->my_shm)->address = src_address;
((shm_addrlen *)d->my_shm)->length = to_read;
D_SHMHDR->address = src_address;
D_SHMHDR->length = to_read;
full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_DFPP_READ;
D_SHMCMD = CORE_DFPP_READ;
d->waitWhile(CORE_DFPP_READ);
memcpy (target_buffer, d->my_shm + SHM_HEADER,size);
// decrease size by bytes read
@ -575,55 +575,55 @@ void Process::read (uint32_t src_address, uint32_t size, uint8_t *target_buffer)
uint8_t Process::readByte (const uint32_t offset)
{
((shm_addr *)d->my_shm)->address = offset;
D_SHMHDR->address = offset;
full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_READ_BYTE;
D_SHMCMD = CORE_READ_BYTE;
d->waitWhile(CORE_READ_BYTE);
return ((shm_val *)d->my_shm)->value;
return D_SHMHDR->value;
}
void Process::readByte (const uint32_t offset, uint8_t &val )
{
((shm_addr *)d->my_shm)->address = offset;
D_SHMHDR->address = offset;
full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_READ_BYTE;
D_SHMCMD = CORE_READ_BYTE;
d->waitWhile(CORE_READ_BYTE);
val = ((shm_val *)d->my_shm)->value;
val = D_SHMHDR->value;
}
uint16_t Process::readWord (const uint32_t offset)
{
((shm_addr *)d->my_shm)->address = offset;
D_SHMHDR->address = offset;
full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_READ_WORD;
D_SHMCMD = CORE_READ_WORD;
d->waitWhile(CORE_READ_WORD);
return ((shm_val *)d->my_shm)->value;
return D_SHMHDR->value;
}
void Process::readWord (const uint32_t offset, uint16_t &val)
{
((shm_addr *)d->my_shm)->address = offset;
D_SHMHDR->address = offset;
full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_READ_WORD;
D_SHMCMD = CORE_READ_WORD;
d->waitWhile(CORE_READ_WORD);
val = ((shm_val *)d->my_shm)->value;
val = D_SHMHDR->value;
}
uint32_t Process::readDWord (const uint32_t offset)
{
((shm_addr *)d->my_shm)->address = offset;
D_SHMHDR->address = offset;
full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_READ_DWORD;
D_SHMCMD = CORE_READ_DWORD;
d->waitWhile(CORE_READ_DWORD);
return ((shm_val *)d->my_shm)->value;
return D_SHMHDR->value;
}
void Process::readDWord (const uint32_t offset, uint32_t &val)
{
((shm_addr *)d->my_shm)->address = offset;
D_SHMHDR->address = offset;
full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_READ_DWORD;
D_SHMCMD = CORE_READ_DWORD;
d->waitWhile(CORE_READ_DWORD);
val = ((shm_val *)d->my_shm)->value;
val = D_SHMHDR->value;
}
/*
@ -632,29 +632,29 @@ void Process::readDWord (const uint32_t offset, uint32_t &val)
void Process::writeDWord (uint32_t offset, uint32_t data)
{
((shm_addrval *)d->my_shm)->address = offset;
((shm_addrval *)d->my_shm)->value = data;
D_SHMHDR->address = offset;
D_SHMHDR->value = data;
full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_WRITE_DWORD;
D_SHMCMD = CORE_WRITE_DWORD;
d->waitWhile(CORE_WRITE_DWORD);
}
// using these is expensive.
void Process::writeWord (uint32_t offset, uint16_t data)
{
((shm_addrval *)d->my_shm)->address = offset;
((shm_addrval *)d->my_shm)->value = data;
D_SHMHDR->address = offset;
D_SHMHDR->value = data;
full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_WRITE_WORD;
D_SHMCMD = CORE_WRITE_WORD;
d->waitWhile(CORE_WRITE_WORD);
}
void Process::writeByte (uint32_t offset, uint8_t data)
{
((shm_addrval *)d->my_shm)->address = offset;
((shm_addrval *)d->my_shm)->value = data;
D_SHMHDR->address = offset;
D_SHMHDR->value = data;
full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_WRITE_BYTE;
D_SHMCMD = CORE_WRITE_BYTE;
d->waitWhile(CORE_WRITE_BYTE);
}
@ -663,11 +663,11 @@ void Process::write (uint32_t dst_address, uint32_t size, uint8_t *source_buffer
// normal write under 1MB
if(size <= SHM_BODY)
{
((shm_addrlen *)d->my_shm)->address = dst_address;
((shm_addrlen *)d->my_shm)->length = size;
D_SHMHDR->address = dst_address;
D_SHMHDR->length = size;
memcpy(d->my_shm+SHM_HEADER,source_buffer, size);
full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_WRITE;
D_SHMCMD = CORE_WRITE;
d->waitWhile(CORE_WRITE);
}
// a big write, we push this over the shm in iterations
@ -678,11 +678,11 @@ void Process::write (uint32_t dst_address, uint32_t size, uint8_t *source_buffer
while (size)
{
// write to_write bytes to dst_cursor
((shm_addrlen *)d->my_shm)->address = dst_address;
((shm_addrlen *)d->my_shm)->length = to_write;
D_SHMHDR->address = dst_address;
D_SHMHDR->length = to_write;
memcpy(d->my_shm+SHM_HEADER,source_buffer, to_write);
full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_WRITE;
D_SHMCMD = CORE_WRITE;
d->waitWhile(CORE_WRITE);
// decrease size by bytes written
size -= to_write;
@ -734,11 +734,11 @@ DfVector Process::readVector (uint32_t offset, uint32_t item_size)
const std::string Process::readSTLString(uint32_t offset)
{
//offset -= 4; //msvc std::string pointers are 8 bytes ahead of their data, not 4
((shm_addr *)d->my_shm)->address = offset;
D_SHMHDR->address = offset;
full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_READ_STL_STRING;
D_SHMCMD = CORE_READ_STL_STRING;
d->waitWhile(CORE_READ_STL_STRING);
int length = ((shm_val *)d->my_shm)->value;
int length = D_SHMHDR->value;
// char temp_c[256];
// strncpy(temp_c, d->my_shm+SHM_HEADER,length+1); // length + 1 for the null terminator
return(string(d->my_shm+SHM_HEADER));
@ -747,11 +747,11 @@ const std::string Process::readSTLString(uint32_t offset)
size_t Process::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity)
{
//offset -= 4; //msvc std::string pointers are 8 bytes ahead of their data, not 4
((shm_addr *)d->my_shm)->address = offset;
D_SHMHDR->address = offset;
full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_READ_STL_STRING;
D_SHMCMD = CORE_READ_STL_STRING;
d->waitWhile(CORE_READ_STL_STRING);
size_t length = ((shm_val *)d->my_shm)->value;
size_t length = D_SHMHDR->value;
size_t real = min(length, bufcapacity - 1);
strncpy(buffer, d->my_shm+SHM_HEADER,real); // length + 1 for the null terminator
buffer[real] = 0;
@ -760,10 +760,10 @@ size_t Process::readSTLString (uint32_t offset, char * buffer, size_t bufcapacit
void Process::writeSTLString(const uint32_t address, const std::string writeString)
{
((shm_addr *)d->my_shm)->address = address/*-4*/;
D_SHMHDR->address = address/*-4*/;
strncpy(d->my_shm+SHM_HEADER,writeString.c_str(),writeString.length()+1); // length + 1 for the null terminator
full_barrier
((shm_cmd *)d->my_shm)->pingpong = CORE_WRITE_STL_STRING;
D_SHMCMD = CORE_WRITE_STL_STRING;
d->waitWhile(CORE_WRITE_STL_STRING);
}
@ -775,3 +775,22 @@ string Process::readClassName (uint32_t vptr)
raw.resize(raw.length() - 4);// trim st@@ from end
return raw;
}
// get module index by name and version. bool 1 = error
bool Process::getModuleIndex (const char * name, const uint32_t version, uint32_t & OUTPUT)
{
modulelookup * payload = (modulelookup *) (d->my_shm + SHM_HEADER);
payload->version = version;
strcpy(payload->name,name);
full_barrier
D_SHMCMD = CORE_ACQUIRE_MODULE;
d->waitWhile(CORE_ACQUIRE_MODULE);
if(D_SHMHDR->error) return false;
OUTPUT = D_SHMHDR->value;
return true;
}
char * Process::getSHMStart (void)
{
return d->my_shm;
}

@ -121,6 +121,12 @@ namespace DFHack
DFWindow * getWindow();
// get the DF Process ID
int getPID();
// get module index by name and version. bool 1 = error
bool getModuleIndex (const char * name, const uint32_t version, uint32_t & OUTPUT);
// get the SHM start if available
char * getSHMStart (void);
// wait for a SHM state. returns 0 without the SHM
bool waitWhile (uint32_t state);
};
}
#endif

@ -764,6 +764,15 @@ union t_occupancy
naked_occupancy_grouped unibits;
};
typedef struct
{
int16_t tiletypes [16][16];
DFHack::t_designation designaton [16][16];
DFHack::t_occupancy occupancy [16][16];
uint8_t biome_indices [7];
uint32_t dirty_dword; // bit 1 set means that the block is to be included in job checks
} mapblock40d;
struct t_viewscreen
{
int32_t type;

@ -2,10 +2,13 @@
SET(PROJECT_HDRS
shms.h
mod-core.h
mod-maps.h
)
SET(PROJECT_SRCS
shms-core.cpp
mod-core.cpp
mod-maps.cpp
)
SET(PROJECT_HDRS_LINUX

@ -32,8 +32,12 @@ distribution.
#include <string.h>
#include <string>
#include <vector>
#define SHM_INTERNAL // for things only visible to the SHM
#include "shms.h"
#include "shms-core.h"
#include "mod-core.h"
#include "mod-maps.h"
std::vector <DFPP_module> module_registry;
@ -46,57 +50,57 @@ bool useYield = 0;
#define SHMHDR ((shm_core_hdr *)shm)
#define SHMCMD ((shm_cmd *)shm)->pingpong
void GetCoreVersion (void)
void GetCoreVersion (void * data)
{
SHMHDR->value = module_registry[0].version;
}
void GetPID (void)
void GetPID (void * data)
{
SHMHDR->value = OS_getPID();
}
void ReadRaw (void)
void ReadRaw (void * data)
{
memcpy(shm + SHM_HEADER, (void *) SHMHDR->address,SHMHDR->length);
}
void ReadDWord (void)
void ReadDWord (void * data)
{
SHMHDR->value = *((uint32_t*) SHMHDR->address);
}
void ReadWord (void)
void ReadWord (void * data)
{
SHMHDR->value = *((uint16_t*) SHMHDR->address);
}
void ReadByte (void)
void ReadByte (void * data)
{
SHMHDR->value = *((uint8_t*) SHMHDR->address);
}
void WriteRaw (void)
void WriteRaw (void * data)
{
memcpy((void *)SHMHDR->address, shm + SHM_HEADER,SHMHDR->length);
}
void WriteDWord (void)
void WriteDWord (void * data)
{
(*(uint32_t*)SHMHDR->address) = SHMHDR->value;
}
void WriteWord (void)
void WriteWord (void * data)
{
(*(uint16_t*)SHMHDR->address) = SHMHDR->value;
}
void WriteByte (void)
void WriteByte (void * data)
{
(*(uint8_t*)SHMHDR->address) = SHMHDR->value;
}
void ReadSTLString (void)
void ReadSTLString (void * data)
{
std::string * myStringPtr = (std::string *) SHMHDR->address;
unsigned int l = myStringPtr->length();
@ -105,7 +109,7 @@ void ReadSTLString (void)
strncpy(shm+SHM_HEADER,myStringPtr->c_str(),l+1);
}
void WriteSTLString (void)
void WriteSTLString (void * data)
{
std::string * myStringPtr = (std::string *) SHMHDR->address;
// here we DO expect a 0 terminator
@ -122,7 +126,7 @@ int bitcount(uint32_t n)
}
// get local and remote affinity, set up yield if required (single core available)
void SyncYield (void)
void SyncYield (void * data)
{
uint32_t local = OS_getAffinity();
uint32_t remote = SHMHDR->value;
@ -137,7 +141,33 @@ void SyncYield (void)
}
}
void InitCore(void)
void FindModule (void * data)
{
bool found = false;
modulelookup * payload = (modulelookup *) (shm + SHM_HEADER);
std::string test = payload->name;
uint32_t version = payload->version;
for(unsigned int i = 0; i < module_registry.size();i++)
{
if(module_registry[i].name == test && module_registry[i].version == version)
{
// gotcha
SHMHDR->value = i;
found = true;
break;
}
}
if(found)
{
SHMHDR->error = false;
}
else
{
SHMHDR->error = true;
}
}
DFPP_module InitCore(void)
{
DFPP_module core;
core.name = "Core";
@ -181,16 +211,31 @@ void InitCore(void)
core.set_command(CORE_RET_STRING, CLIENT_WAIT, "Return string");
core.set_command(CORE_WRITE_STL_STRING, FUNCTION, "Write STL string", WriteSTLString, CORE_SUSPENDED);
core.set_command(CORE_SYNC_YIELD, FUNCTION, "Synchronize affinity/yield", SyncYield, CORE_SYNC_YIELD_RET);
module_registry.push_back(core);
core.set_command(CORE_SYNC_YIELD_RET, CLIENT_WAIT, "Synchronize affinity/yield return");
core.set_command(CORE_ACQUIRE_MODULE, FUNCTION, "Module lookup", FindModule, CORE_RET_MODULE);
core.set_command(CORE_RET_MODULE, CLIENT_WAIT, "Return module index or error");
return core;
}
void InitModules (void)
{
// create the core module
InitCore();
module_registry.push_back(InitCore());
module_registry.push_back(InitMaps());
// TODO: dynamic module init
}
void KillModules (void)
{
for(unsigned int i = 0; i < module_registry.size();i++)
{
if(module_registry[i].modulestate)
free(module_registry[i].modulestate);
}
module_registry.clear();
}
void SHM_Act (void)
{
if(errorstate)
@ -215,10 +260,12 @@ void SHM_Act (void)
}
DFPP_module & mod = module_registry[((shm_cmd *)shm)->parts.module];
DFPP_command & cmd = mod.commands[((shm_cmd *)shm)->parts.command];
//fprintf(stderr, "Client invoked %s\n", cmd.name.c_str() );
//fprintf(stderr, "Client invoked %d:%d = ",((shm_cmd *)shm)->parts.module,((shm_cmd *)shm)->parts.command);
//fprintf(stderr, "%s\n",cmd.name.c_str());
if(cmd._function)
{
cmd._function();
cmd._function(mod.modulestate);
}
if(cmd.nextState != -1)
{

@ -3,7 +3,7 @@
#include <integers.h>
#include "shms.h"
#include "shms-core.h"
#include "mod-core.h"
#include "mod-maps.h"
#include <DFTypes.h>
using namespace DFHack;
@ -69,7 +69,7 @@ void ReadBlockByCoords (void * data)
*/
mblock * *** mapArray = *(mblock * ****)offsets.map_offset;
mblock * block = mapArray[SHMHDR->x][SHMHDR->y][SHMHDR->z];
fprintf(stderr, "Readblock: %d %d %d 0x%x\n", SHMHDR->x,SHMHDR->y,SHMHDR->z, block);
//fprintf(stderr, "Readblock: %d %d %d 0x%x\n", SHMHDR->x,SHMHDR->y,SHMHDR->z, block);
if(block)
{
memcpy(&(SHMBLOCK->tiletypes), block + offsets.tile_type_offset, sizeof(SHMBLOCK->tiletypes));
@ -85,7 +85,7 @@ void ReadBlockByCoords (void * data)
}
}
DFPP_module InitMaps(std::vector <DFPP_module>* module_registry)
DFPP_module InitMaps( void )
{
DFPP_module maps;
maps.name = "Maps";
@ -104,10 +104,8 @@ DFPP_module InitMaps(std::vector <DFPP_module>* module_registry)
// will it fit into 1MB? We shouldn't assume this is the case
maps.set_command(MAP_READ_BLOCKTREE, FUNCTION,"Get the tree of block pointers as a single structure", NullCommand, CORE_SUSPENDED);
// really doesn't fit into 1MB, there should be a streaming variant to better utilize context switches
maps.set_command(MAP_READ_BLOCKS_3D, FUNCTION, "Read a range of blocks between two sets of coords", NullCommand, CORE_SUSPENDED);
module_registry->push_back(maps);
return maps;
}

@ -37,7 +37,7 @@ distribution.
#include <vector>
#include <string>
#include "shms.h"
#include "shms-core.h"
#include "mod-core.h"
#include <sched.h>
#define DFhackCExport extern "C" __attribute__ ((visibility("default")))
@ -125,6 +125,7 @@ void SHM_Destroy ( void )
{
if(inited && !errorstate)
{
KillModules();
shmid_ds descriptor;
shmctl(shmid, IPC_STAT, &descriptor);
shmdt(shm);

@ -37,6 +37,7 @@ distribution.
#include <vector>
#include <string>
#include "shms.h"
#include "mod-core.h"
#include <cstdio>
int errorstate = 0;
char *shm = 0;
@ -150,6 +151,7 @@ void SHM_Destroy ( void )
{
if(errorstate)
return;
KillModules();
ReleaseMutex(DFSVMutex);
CloseHandle(DFSVMutex);
CloseHandle(DFCLMutex);
@ -160,6 +162,17 @@ uint32_t OS_getPID()
return GetCurrentProcessId();
}
// TODO: move to some utils file
uint32_t OS_getAffinity()
{
HANDLE hProcess = GetCurrentProcess();
DWORD dwProcessAffinityMask, dwSystemAffinityMask;
GetProcessAffinityMask( hProcess, &dwProcessAffinityMask, &dwSystemAffinityMask );
return dwProcessAffinityMask;
}
// is the other side still there?
bool isValidSHM()
{

@ -38,7 +38,7 @@ enum DFPP_CmdType
struct DFPP_command
{
void (*_function)(void);
void (*_function)(void *);
DFPP_CmdType type:32; // force the enum to 32 bits for compatibility reasons
std::string name;
uint32_t nextState;
@ -46,7 +46,21 @@ struct DFPP_command
struct DFPP_module
{
inline void set_command(const unsigned int index, const DFPP_CmdType type, const char * name, void (*_function)(void) = 0,uint32_t nextState = -1)
DFPP_module()
{
name = "Uninitialized module";
version = 0;
modulestate = 0;
}
// ALERT: the structures share state
DFPP_module(const DFPP_module & orig)
{
commands = orig.commands;
name = orig.name;
modulestate = orig.modulestate;
version = orig.version;
}
inline void set_command(const unsigned int index, const DFPP_CmdType type, const char * name, void (*_function)(void *) = 0,uint32_t nextState = -1)
{
commands[index].type = type;
commands[index].name = name;
@ -81,8 +95,10 @@ typedef union
void SHM_Act (void);
void InitModules (void);
void KillModules (void);
bool isValidSHM();
uint32_t OS_getPID();
DFPP_module InitMaps(void);
uint32_t OS_getAffinity(); // limited to 32 processors. Silly, eh?
#endif