Stop synchronous suspend from eating CPU cycles.

Untested on windows.
Breaks the SHM protocol. New SHM server library is required.
develop
Petr Mrázek 2010-03-18 19:55:01 +01:00
parent e18828e466
commit d2afd21318
5 changed files with 96 additions and 63 deletions

@ -26,7 +26,7 @@ int main (void)
cerr << e.what() << endl; cerr << e.what() << endl;
return 1; return 1;
} }
/*
// attach/detach test // attach/detach test
cout << "Testing attach/detach" << endl; cout << "Testing attach/detach" << endl;
time(&start); time(&start);
@ -62,7 +62,7 @@ int main (void)
time_diff = difftime(end, start); time_diff = difftime(end, start);
cout << "attach tests done in " << time_diff << " seconds." << endl; cout << "attach tests done in " << time_diff << " seconds." << endl;
*/
cout << "Testing suspend/resume" << endl; cout << "Testing suspend/resume" << endl;
DF.Attach(); DF.Attach();
time(&start); time(&start);

@ -275,9 +275,9 @@ main(int argc, char *argv[])
DFHack::t_designation designations[16][16]; DFHack::t_designation designations[16][16];
uint8_t regionoffsets[16]; uint8_t regionoffsets[16];
*/ */
mapblock40d Block;
map <int16_t, uint32_t> materials; map <int16_t, uint32_t> materials;
materials.clear(); materials.clear();
mapblock40d blocks[3][3];
vector<DFHack::t_matgloss> stonetypes; vector<DFHack::t_matgloss> stonetypes;
vector< vector <uint16_t> > layerassign; vector< vector <uint16_t> > layerassign;
vector<t_vein> veinVector; vector<t_vein> veinVector;
@ -338,13 +338,16 @@ main(int argc, char *argv[])
bool dirtybit = false; bool dirtybit = false;
uint32_t blockaddr = 0; uint32_t blockaddr = 0;
uint32_t blockaddr2 = 0; uint32_t blockaddr2 = 0;
// walk the map!
// resume so we don't block DF while we wait for input
DF.Resume();
for (;;) for (;;)
{ {
dig = false; dig = false;
dump = false; dump = false;
digbit = false; digbit = false;
DF.Resume();
int c = getch(); /* refresh, accept single keystroke of input */ int c = getch(); /* refresh, accept single keystroke of input */
clrscr(); clrscr();
/* process the command keystroke */ /* process the command keystroke */
@ -392,76 +395,85 @@ main(int argc, char *argv[])
cursorX = min(cursorX, x_max - 1); cursorX = min(cursorX, x_max - 1);
cursorY = min(cursorY, y_max - 1); cursorY = min(cursorY, y_max - 1);
cursorZ = min(cursorZ, z_max - 1); cursorZ = min(cursorZ, z_max - 1);
// clear data before we suspend
memset(blocks,0,sizeof(blocks));
veinVector.clear();
IceVeinVector.clear();
dirtybit = 0;
// Supend, read/write data
DF.Suspend(); DF.Suspend();
for(int i = -1; i <= 1; i++) for(int i = -1; i <= 1; i++) for(int j = -1; j <= 1; j++)
{ {
for(int j = -1; j <= 1; j++) mapblock40d * Block = &blocks[i+1][j+1];
if(DF.isValidBlock(cursorX+i,cursorY+j,cursorZ))
{ {
if(DF.isValidBlock(cursorX+i,cursorY+j,cursorZ)) DF.ReadBlock40d(cursorX+i,cursorY+j,cursorZ, Block);
// extra processing of the block in the middle
if(i == 0 && j == 0)
{ {
// read data // read veins
DF.ReadBlock40d(cursorX+i,cursorY+j,cursorZ, &Block); DF.ReadVeins(cursorX+i,cursorY+j,cursorZ,veinVector,IceVeinVector);
/*
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++) // get pointer to block
blockaddr = DF.getBlockPtr(cursorX+i,cursorY+j,cursorZ);
blockaddr2 = Block->origin;
// dig all veins and trees
if(dig)
{ {
for(int y = 0; y < 16; y++) for(int x = 0; x < 16; x++) for(int y = 0; y < 16; y++)
{ {
if(dig) TileClass tc = tileTypeTable[Block->tiletypes[x][y]].c;
{ TileMaterial tm = tileTypeTable[Block->tiletypes[x][y]].m;
TileClass tc = tileTypeTable[Block.tiletypes[x][y]].c; if( tc == WALL && tm == VEIN || tc == TREE_OK || tc == TREE_DEAD)
TileMaterial tm = tileTypeTable[Block.tiletypes[x][y]].m;
if( tc == WALL && tm == VEIN || tc == TREE_OK || tc == TREE_DEAD)
{
Block.designaton[x][y].bits.dig = designation_default;
}
}
int color = COLOR_BLACK;
color = pickColor(Block.tiletypes[x][y]);
if(Block.designaton[x][y].bits.hidden)
{ {
puttile(x+(i+1)*16,y+(j+1)*16,Block.tiletypes[x][y], color); Block->designaton[x][y].bits.dig = designation_default;
}
else
{
attron(A_STANDOUT);
puttile(x+(i+1)*16,y+(j+1)*16,Block.tiletypes[x][y], color);
attroff(A_STANDOUT);
} }
} }
DF.WriteDesignations(cursorX+i,cursorY+j,cursorZ, (uint32_t *) Block->designaton);
} }
// do a dump of the block data
if(i == 0 && j == 0) if(dump)
{ {
blockaddr = DF.getBlockPtr(cursorX+i,cursorY+j,cursorZ); hexdump(DF,blockaddr,0x1E00,filenum);
blockaddr2 = Block.origin; filenum++;
if(dump) }
{ // read/write dirty bit of the block
hexdump(DF,blockaddr,0x1E00,filenum); DF.ReadDirtyBit(cursorX+i,cursorY+j,cursorZ,dirtybit);
filenum++; if(digbit)
} {
dirtybit = !dirtybit;
if(dig) DF.WriteDirtyBit(cursorX+i,cursorY+j,cursorZ,dirtybit);
DF.WriteDesignations(cursorX+i,cursorY+j,cursorZ, (uint32_t *) Block.designaton);
DF.ReadDirtyBit(cursorX+i,cursorY+j,cursorZ,dirtybit);
if(digbit)
{
dirtybit = !dirtybit;
DF.WriteDirtyBit(cursorX+i,cursorY+j,cursorZ,dirtybit);
}
veinVector.clear();
IceVeinVector.clear();
DF.ReadVeins(cursorX+i,cursorY+j,cursorZ,veinVector,IceVeinVector);
} }
} }
} }
} }
// Resume, print stuff to the terminal
DF.Resume();
for(int i = -1; i <= 1; i++) for(int j = -1; j <= 1; j++)
{
mapblock40d * Block = &blocks[i+1][j+1];
for(int x = 0; x < 16; x++) for(int y = 0; y < 16; y++)
{
int color = COLOR_BLACK;
color = pickColor(Block->tiletypes[x][y]);
if(Block->designaton[x][y].bits.hidden)
{
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,Block->tiletypes[x][y], color);
attroff(A_STANDOUT);
}
}
}
gotoxy(0,48); gotoxy(0,48);
cprintf("arrow keys, PGUP, PGDN = navigate"); cprintf("arrow keys, PGUP, PGDN = navigate");
gotoxy(0,49); gotoxy(0,49);

@ -429,20 +429,26 @@ bool SHMProcess::suspend()
if(D_SHMCMD == CORE_RUN) if(D_SHMCMD == CORE_RUN)
{ {
//fprintf(stderr,"%d invokes step\n",d->attachmentIdx); //fprintf(stderr,"%d invokes step\n",d->attachmentIdx);
/*
// wait for the next window // wait for the next window
if(!d->SetAndWait(CORE_STEP)) if(!d->SetAndWait(CORE_STEP))
{ {
throw Error::SHMLockingError("if(!d->SetAndWait(CORE_STEP))"); throw Error::SHMLockingError("if(!d->SetAndWait(CORE_STEP))");
} }
*/
D_SHMCMD = CORE_STEP;
} }
else else
{ {
//fprintf(stderr,"%d invokes suspend\n",d->attachmentIdx); //fprintf(stderr,"%d invokes suspend\n",d->attachmentIdx);
// lock now // lock now
/*
if(!d->SetAndWait(CORE_SUSPEND)) if(!d->SetAndWait(CORE_SUSPEND))
{ {
throw Error::SHMLockingError("if(!d->SetAndWait(CORE_SUSPEND))"); throw Error::SHMLockingError("if(!d->SetAndWait(CORE_SUSPEND))");
} }
*/
D_SHMCMD = CORE_SUSPEND;
} }
//fprintf(stderr,"waiting for lock\n"); //fprintf(stderr,"waiting for lock\n");
// we wait for the server to give up our suspend lock (held by default) // we wait for the server to give up our suspend lock (held by default)

@ -202,7 +202,7 @@ DFPP_module InitCore(void)
//core.set_command(CORE_RUN, FUNCTION, "Run!",AcquireSuspendLock,CORE_RUNNING); //core.set_command(CORE_RUN, FUNCTION, "Run!",AcquireSuspendLock,CORE_RUNNING);
core.set_command(CORE_RUN, CANCELLATION, "Run!",0,CORE_RUNNING); core.set_command(CORE_RUN, CANCELLATION, "Run!",0,CORE_RUNNING);
core.set_command(CORE_STEP, CANCELLATION, "Suspend on next step",0,CORE_SUSPEND);// set command to CORE_SUSPEND, check next client core.set_command(CORE_STEP, CANCELLATION, "Suspend on next step",0,CORE_SUSPEND);// set command to CORE_SUSPEND, check next client
core.set_command(CORE_SUSPEND, FUNCTION, "Suspend", ReleaseSuspendLock , CORE_SUSPENDED); core.set_command(CORE_SUSPEND, FUNCTION, "Suspend", ReleaseSuspendLock , CORE_SUSPENDED, LOCKING_LOCKS);
core.set_command(CORE_SUSPENDED, CLIENT_WAIT, "Suspended"); core.set_command(CORE_SUSPENDED, CLIENT_WAIT, "Suspended");
core.set_command(CORE_ERROR, CANCELLATION, "Error"); core.set_command(CORE_ERROR, CANCELLATION, "Error");
@ -298,13 +298,20 @@ void SHM_Act (void)
} }
full_barrier full_barrier
*/ */
// set next state BEFORE we act on the command - good for locks
if(cmd.locking == LOCKING_LOCKS)
{
if(cmd.nextState != -1) SHMCMD = cmd.nextState;
}
if(cmd._function) if(cmd._function)
{ {
cmd._function(mod.modulestate); cmd._function(mod.modulestate);
} }
full_barrier full_barrier
if(cmd.nextState != -1) // set next state AFTER we act on the command - good for busy waits
if(cmd.locking == LOCKING_BUSY)
{ {
/* /*
char text [512]; char text [512];
@ -313,7 +320,7 @@ void SHM_Act (void)
sprintf(text2, "Server set %d\n",cmd.nextState); sprintf(text2, "Server set %d\n",cmd.nextState);
*/ */
// FIXME: WHAT HAPPENS WHEN A 'NEXTSTATE' IS FROM A DIFFERENT MODULE THAN 'CORE'? Yeah. It doesn't work. // FIXME: WHAT HAPPENS WHEN A 'NEXTSTATE' IS FROM A DIFFERENT MODULE THAN 'CORE'? Yeah. It doesn't work.
SHMCMD = cmd.nextState; if(cmd.nextState != -1) SHMCMD = cmd.nextState;
//MessageBox(0,text,text2, MB_OK); //MessageBox(0,text,text2, MB_OK);
//fflush(stderr); // make sure this finds its way to the terminal! //fflush(stderr); // make sure this finds its way to the terminal!

@ -31,6 +31,12 @@
#endif #endif
#endif #endif
enum DFPP_Locking
{
LOCKING_BUSY = 0,
LOCKING_LOCKS = 1
};
enum DFPP_CmdType enum DFPP_CmdType
{ {
CANCELLATION, // we should jump out of the Act() CANCELLATION, // we should jump out of the Act()
@ -44,6 +50,7 @@ struct DFPP_command
DFPP_CmdType type:32; // force the enum to 32 bits for compatibility reasons DFPP_CmdType type:32; // force the enum to 32 bits for compatibility reasons
std::string name; std::string name;
uint32_t nextState; uint32_t nextState;
DFPP_Locking locking;
}; };
struct DFPP_module struct DFPP_module
@ -62,12 +69,13 @@ struct DFPP_module
modulestate = orig.modulestate; modulestate = orig.modulestate;
version = orig.version; 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) inline void set_command(const unsigned int index, const DFPP_CmdType type, const char * name, void (*_function)(void *) = 0,uint32_t nextState = -1, DFPP_Locking locking = LOCKING_BUSY)
{ {
commands[index].type = type; commands[index].type = type;
commands[index].name = name; commands[index].name = name;
commands[index]._function = _function; commands[index]._function = _function;
commands[index].nextState = nextState; commands[index].nextState = nextState;
commands[index].locking = locking;
} }
inline void reserve (unsigned int numcommands) inline void reserve (unsigned int numcommands)
{ {