Use sched_yield depending on CPU affinity

develop
Petr Mrázek 2010-03-04 04:40:06 +01:00
parent 0192520d43
commit 6e69dcdeed
5 changed files with 188 additions and 178 deletions

@ -28,6 +28,7 @@ distribution.
#include <sys/ipc.h> #include <sys/ipc.h>
#include <time.h> #include <time.h>
#include "../shmserver/shms.h" #include "../shmserver/shms.h"
#include "../shmserver/shms-core.h"
#include <sys/time.h> #include <sys/time.h>
#include <time.h> #include <time.h>
#include <sched.h> #include <sched.h>
@ -68,22 +69,27 @@ class Process::Private
bool waitWhile (CORE_COMMAND state); bool waitWhile (CORE_COMMAND state);
bool DF_TestBridgeVersion(bool & ret); bool DF_TestBridgeVersion(bool & ret);
bool DF_GetPID(pid_t & ret); bool DF_GetPID(pid_t & ret);
void DF_SyncAffinity(void);
}; };
// some helpful macros to keep the code bloat in check // some helpful macros to keep the code bloat in check
#define SHMCMD ((shm_cmd *)my_shm)->pingpong #define SHMCMD ((shm_cmd *)my_shm)->pingpong
#define D_SHMCMD ((shm_cmd *)d->my_shm)->pingpong #define D_SHMCMD ((shm_cmd *)d->my_shm)->pingpong
#define SHMHDR ((shm_header *)my_shm) #define SHMHDR ((shm_core_hdr *)my_shm)
#define D_SHMHDR ((shm_header *)d->my_shm) #define D_SHMHDR ((shm_core_hdr *)d->my_shm)
/*
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 (CORE_COMMAND state)
{ {
uint32_t cnt = 0; uint32_t cnt = 0;
struct shmid_ds descriptor; struct shmid_ds descriptor;
while (SHMCMD == state) while (SHMCMD == state)
{ {
if(cnt == 10000) if(cnt == 10000)// check if the other process is still there
{ {
shmctl(my_shmid, IPC_STAT, &descriptor); shmctl(my_shmid, IPC_STAT, &descriptor);
@ -98,7 +104,10 @@ bool Process::Private::waitWhile (CORE_COMMAND state)
cnt = 0; cnt = 0;
} }
} }
SCHED_YIELD if(useYield)
{
SCHED_YIELD
}
cnt++; cnt++;
} }
if(SHMCMD == CORE_SV_ERROR) if(SHMCMD == CORE_SV_ERROR)
@ -136,6 +145,31 @@ bool Process::Private::DF_GetPID(pid_t & ret)
return true; return true;
} }
uint32_t OS_getAffinity()
{
cpu_set_t mask;
sched_getaffinity(0,sizeof(cpu_set_t),&mask);
// FIXME: truncation
uint32_t affinity = *(uint32_t *) &mask;
return affinity;
}
void Process::Private::DF_SyncAffinity( void )
{
SHMHDR->value = OS_getAffinity();
gcc_barrier
SHMCMD = CORE_SYNC_YIELD;
gcc_barrier
if(!waitWhile(CORE_SYNC_YIELD))
return;
gcc_barrier
SHMCMD = CORE_SUSPENDED;
useYield = SHMHDR->value;
#ifdef DEBUG
if(useYield) cerr << "Using Yield!" << endl;
#endif
}
Process::Process(vector <memory_info *> & known_versions) Process::Process(vector <memory_info *> & known_versions)
: d(new Private()) : d(new Private())
{ {
@ -204,6 +238,7 @@ Process::Process(vector <memory_info *> & known_versions)
// try to identify the DF version // try to identify the DF version
d->validate(target_name, d->my_pid, known_versions); d->validate(target_name, d->my_pid, known_versions);
d->DF_SyncAffinity();
d->my_window = new DFWindow(this); d->my_window = new DFWindow(this);
} }
gcc_barrier gcc_barrier

@ -23,6 +23,7 @@ distribution.
*/ */
#include "DFCommonInternal.h" #include "DFCommonInternal.h"
#include "../shmserver/shms.h" #include "../shmserver/shms.h"
#include "../shmserver/shms-core.h"
using namespace DFHack; using namespace DFHack;
// a full memory barrier! better be safe than sorry. // a full memory barrier! better be safe than sorry.
@ -38,6 +39,7 @@ class Process::Private
attached = false; attached = false;
suspended = false; suspended = false;
identified = false; identified = false;
useYield = 0;
DFSVMutex = 0; DFSVMutex = 0;
DFCLMutex = 0; DFCLMutex = 0;
}; };
@ -52,13 +54,22 @@ class Process::Private
bool attached; bool attached;
bool suspended; bool suspended;
bool identified; bool identified;
bool useYield;
bool waitWhile (CORE_COMMAND state); bool waitWhile (CORE_COMMAND state);
bool isValidSV(); bool isValidSV();
bool DF_TestBridgeVersion(bool & ret); bool DF_TestBridgeVersion(bool & ret);
bool DF_GetPID(uint32_t & ret); bool DF_GetPID(uint32_t & ret);
void DF_SyncAffinity(void);
}; };
// some helpful macros to keep the code bloat in check
#define SHMCMD ((shm_cmd *)my_shm)->pingpong
#define D_SHMCMD ((shm_cmd *)d->my_shm)->pingpong
#define SHMHDR ((shm_core_hdr *)my_shm)
#define D_SHMHDR ((shm_core_hdr *)d->my_shm)
// is the other side still there? // is the other side still there?
bool Process::Private::isValidSV() bool Process::Private::isValidSV()
{ {
@ -90,14 +101,17 @@ bool Process::Private::isValidSV()
bool Process::Private::waitWhile (CORE_COMMAND state) bool Process::Private::waitWhile (CORE_COMMAND state)
{ {
uint32_t cnt = 0; uint32_t cnt = 0;
SCHED_YIELD // yield the CPU, valid only on single-core CPUs
while (((shm_cmd *)my_shm)->pingpong == state) while (((shm_cmd *)my_shm)->pingpong == state)
{ {
// yield the CPU, only on single-core CPUs
if(useYield)
{
SCHED_YIELD
}
if(cnt == 10000) if(cnt == 10000)
{ {
if(!isValidSV())// DF not there anymore? if(!isValidSV())// DF not there anymore?
{ {
full_barrier
((shm_cmd *)my_shm)->pingpong = CORE_RUNNING; ((shm_cmd *)my_shm)->pingpong = CORE_RUNNING;
attached = suspended = false; attached = suspended = false;
ReleaseMutex(DFCLMutex); ReleaseMutex(DFCLMutex);
@ -115,7 +129,6 @@ bool Process::Private::waitWhile (CORE_COMMAND state)
((shm_cmd *)my_shm)->pingpong = CORE_RUNNING; ((shm_cmd *)my_shm)->pingpong = CORE_RUNNING;
attached = suspended = false; attached = suspended = false;
cerr << "shm server error!" << endl; cerr << "shm server error!" << endl;
assert (false);
return false; return false;
} }
return true; return true;
@ -145,6 +158,34 @@ bool Process::Private::DF_GetPID(uint32_t & ret)
return true; return true;
} }
void Process::Private::DF_SyncAffinity(void)
{
}
uint32_t OS_getAffinity()
{
HANDLE hProcess = GetCurrentProcess();
DWORD dwProcessAffinityMask, dwSystemAffinityMask;
GetProcessAffinityMask( hProcess, &dwProcessAffinityMask, &dwSystemAffinityMask );
return dwProcessAffinityMask;
}
void Process::Private::DF_SyncAffinity( void )
{
SHMHDR->value = OS_getAffinity();
full_barrier
SHMCMD = CORE_SYNC_YIELD;
full_barrier
if(!waitWhile(CORE_SYNC_YIELD))
return;
full_barrier
SHMCMD = CORE_SUSPENDED;
useYield = SHMHDR->value;
if(useYield) cerr << "Using Yield!" << endl;
}
Process::Process(vector <memory_info *> & known_versions) Process::Process(vector <memory_info *> & known_versions)
: d(new Private()) : d(new Private())
{ {
@ -255,12 +296,13 @@ Process::Process(vector <memory_info *> & known_versions)
if(d->identified) if(d->identified)
{ {
d->my_window = new DFWindow(this); d->my_window = new DFWindow(this);
d->DF_SyncAffinity();
} }
else else
{ {
((shm_cmd *)d->my_shm)->pingpong = CORE_RUNNING; ((shm_cmd *)d->my_shm)->pingpong = CORE_RUNNING;
UnmapViewOfFile(d->my_shm); UnmapViewOfFile(d->my_shm);
d->my_shm = 0; d->my_shm = 0;
ReleaseMutex(d->DFCLMutex); ReleaseMutex(d->DFCLMutex);
CloseHandle(d->DFSVMutex); CloseHandle(d->DFSVMutex);
d->DFSVMutex = 0; d->DFSVMutex = 0;

@ -33,50 +33,7 @@ distribution.
#include <string> #include <string>
#include <vector> #include <vector>
#include "shms.h" #include "shms.h"
#include "shms-core.h"
enum DFPP_CmdType
{
CANCELLATION, // we should jump out of the Act()
CLIENT_WAIT, // we are waiting for the client
FUNCTION, // we call a function as a result of the command
};
struct DFPP_command
{
DFPP_CmdType type:32; // force the enum to 32 bits for compatibility reasons
std::string name;
void (*_function)(void);
};
struct DFPP_module
{
inline void push_command(DFPP_CmdType type, const char * name, void (*_function)(void))
{
DFPP_command cmd;
cmd.type = type;
cmd.name = name;
cmd._function = _function;
commands.push_back(cmd);
}
inline void set_command(unsigned int index, DFPP_CmdType type, const char * name, void (*_function)(void))
{
DFPP_command cmd;
cmd.type = type;
cmd.name = name;
cmd._function = _function;
commands[index] = cmd;
}
inline void reserve (unsigned int numcommands)
{
commands.clear();
DFPP_command cmd = {CANCELLATION,"",0};
commands.resize(numcommands,cmd);
}
std::string name;
uint32_t version; // version
std::vector <DFPP_command> commands;
void * modulestate;
};
std::vector <DFPP_module> module_registry; std::vector <DFPP_module> module_registry;
@ -84,78 +41,59 @@ std::vector <DFPP_module> module_registry;
extern int errorstate; extern int errorstate;
extern char *shm; extern char *shm;
extern int shmid; extern int shmid;
bool useYield = 0;
#define SHMHDR ((shm_header *)shm) #define SHMHDR ((shm_core_hdr *)shm)
#define SHMCMD ((shm_cmd *)shm)->pingpong #define SHMCMD ((shm_cmd *)shm)->pingpong
void GetCoreVersion (void) void GetCoreVersion (void)
{ {
SHMHDR->value = module_registry[0].version; SHMHDR->value = module_registry[0].version;
full_barrier
SHMCMD = CORE_RET_VERSION;
} }
void GetPID (void) void GetPID (void)
{ {
SHMHDR->value = OS_getPID(); SHMHDR->value = OS_getPID();
full_barrier
SHMCMD = CORE_RET_PID;
} }
void ReadRaw (void) void ReadRaw (void)
{ {
memcpy(shm + SHM_HEADER, (void *) SHMHDR->address,SHMHDR->length); memcpy(shm + SHM_HEADER, (void *) SHMHDR->address,SHMHDR->length);
full_barrier
SHMCMD = CORE_RET_DATA;
} }
void ReadDWord (void) void ReadDWord (void)
{ {
SHMHDR->value = *((uint32_t*) SHMHDR->address); SHMHDR->value = *((uint32_t*) SHMHDR->address);
full_barrier
SHMCMD = CORE_RET_DWORD;
} }
void ReadWord (void) void ReadWord (void)
{ {
SHMHDR->value = *((uint16_t*) SHMHDR->address); SHMHDR->value = *((uint16_t*) SHMHDR->address);
full_barrier
SHMCMD = CORE_RET_WORD;
} }
void ReadByte (void) void ReadByte (void)
{ {
SHMHDR->value = *((uint8_t*) SHMHDR->address); SHMHDR->value = *((uint8_t*) SHMHDR->address);
full_barrier
SHMCMD = CORE_RET_BYTE;
} }
void WriteRaw (void) void WriteRaw (void)
{ {
memcpy((void *)SHMHDR->address, shm + SHM_HEADER,SHMHDR->length); memcpy((void *)SHMHDR->address, shm + SHM_HEADER,SHMHDR->length);
full_barrier
SHMCMD = CORE_SUSPENDED;
} }
void WriteDWord (void) void WriteDWord (void)
{ {
(*(uint32_t*)SHMHDR->address) = SHMHDR->value; (*(uint32_t*)SHMHDR->address) = SHMHDR->value;
full_barrier
SHMCMD = CORE_SUSPENDED;
} }
void WriteWord (void) void WriteWord (void)
{ {
(*(uint16_t*)SHMHDR->address) = SHMHDR->value; (*(uint16_t*)SHMHDR->address) = SHMHDR->value;
full_barrier
SHMCMD = CORE_SUSPENDED;
} }
void WriteByte (void) void WriteByte (void)
{ {
(*(uint8_t*)SHMHDR->address) = SHMHDR->value; (*(uint8_t*)SHMHDR->address) = SHMHDR->value;
full_barrier
SHMCMD = CORE_SUSPENDED;
} }
void ReadSTLString (void) void ReadSTLString (void)
@ -163,10 +101,8 @@ void ReadSTLString (void)
std::string * myStringPtr = (std::string *) SHMHDR->address; std::string * myStringPtr = (std::string *) SHMHDR->address;
unsigned int l = myStringPtr->length(); unsigned int l = myStringPtr->length();
SHMHDR->value = l; SHMHDR->value = l;
// there doesn't have to be a null terminator! // FIXME: there doesn't have to be a null terminator!
strncpy(shm+SHM_HEADER,myStringPtr->c_str(),l+1); strncpy(shm+SHM_HEADER,myStringPtr->c_str(),l+1);
full_barrier
SHMCMD = CORE_RET_STRING;
} }
void WriteSTLString (void) void WriteSTLString (void)
@ -174,13 +110,31 @@ void WriteSTLString (void)
std::string * myStringPtr = (std::string *) SHMHDR->address; std::string * myStringPtr = (std::string *) SHMHDR->address;
// here we DO expect a 0 terminator // here we DO expect a 0 terminator
myStringPtr->assign((const char *) (shm + SHM_HEADER)); myStringPtr->assign((const char *) (shm + SHM_HEADER));
full_barrier
SHMCMD = CORE_SUSPENDED;
} }
void Suspend (void) // MIT HAKMEM bitcount
int bitcount(uint32_t n)
{ {
SHMCMD = CORE_SUSPENDED; register uint32_t tmp;
tmp = n - ((n >> 1) & 033333333333) - ((n >> 2) & 011111111111);
return ((tmp + (tmp >> 3)) & 030707070707) % 63;
}
// get local and remote affinity, set up yield if required (single core available)
void SyncYield (void)
{
uint32_t local = OS_getAffinity();
uint32_t remote = SHMHDR->value;
uint32_t pool = local | remote;
if(bitcount(pool) == 1)
{
SHMHDR->value = useYield = 1;
}
else
{
SHMHDR->value = useYield = 0;
}
} }
void InitCore(void) void InitCore(void)
@ -191,41 +145,42 @@ void InitCore(void)
core.modulestate = 0; // this one is dumb and has no real state core.modulestate = 0; // this one is dumb and has no real state
core.reserve(NUM_CORE_CMDS); core.reserve(NUM_CORE_CMDS);
core.set_command(CORE_RUNNING, CANCELLATION, "Running", NULL); core.set_command(CORE_RUNNING, CANCELLATION, "Running");
core.set_command(CORE_GET_VERSION, FUNCTION,"Get core version",GetCoreVersion); core.set_command(CORE_GET_VERSION, FUNCTION,"Get core version",GetCoreVersion, CORE_RET_VERSION);
core.set_command(CORE_RET_VERSION, CLIENT_WAIT,"Core version return",0); core.set_command(CORE_RET_VERSION, CLIENT_WAIT,"Core version return");
core.set_command(CORE_GET_PID, FUNCTION, "Get PID", GetPID); core.set_command(CORE_GET_PID, FUNCTION, "Get PID", GetPID, CORE_RET_PID);
core.set_command(CORE_RET_PID, CLIENT_WAIT, "PID return", 0); core.set_command(CORE_RET_PID, CLIENT_WAIT, "PID return");
core.set_command(CORE_DFPP_READ, FUNCTION,"Raw read",ReadRaw); core.set_command(CORE_DFPP_READ, FUNCTION,"Raw read",ReadRaw, CORE_RET_DATA);
core.set_command(CORE_RET_DATA, CLIENT_WAIT,"Raw read return",0); core.set_command(CORE_RET_DATA, CLIENT_WAIT,"Raw read return");
core.set_command(CORE_READ_DWORD, FUNCTION,"Read DWORD",ReadDWord); core.set_command(CORE_READ_DWORD, FUNCTION,"Read DWORD",ReadDWord, CORE_RET_DWORD);
core.set_command(CORE_RET_DWORD, CLIENT_WAIT,"Read DWORD return",0); core.set_command(CORE_RET_DWORD, CLIENT_WAIT,"Read DWORD return");
core.set_command(CORE_READ_WORD, FUNCTION,"Read WORD",ReadWord); core.set_command(CORE_READ_WORD, FUNCTION,"Read WORD",ReadWord, CORE_RET_WORD);
core.set_command(CORE_RET_WORD, CLIENT_WAIT,"Read WORD return",0); core.set_command(CORE_RET_WORD, CLIENT_WAIT,"Read WORD return");
core.set_command(CORE_READ_BYTE, FUNCTION,"Read BYTE",ReadByte); core.set_command(CORE_READ_BYTE, FUNCTION,"Read BYTE",ReadByte, CORE_RET_BYTE);
core.set_command(CORE_RET_BYTE, CLIENT_WAIT,"Read BYTE return",0); core.set_command(CORE_RET_BYTE, CLIENT_WAIT,"Read BYTE return");
core.set_command(CORE_SV_ERROR, CANCELLATION, "Server error", 0); core.set_command(CORE_SV_ERROR, CANCELLATION, "Server error");
core.set_command(CORE_CL_ERROR, CANCELLATION, "Client error", 0); core.set_command(CORE_CL_ERROR, CANCELLATION, "Client error");
core.set_command(CORE_WRITE, FUNCTION, "Raw write", WriteRaw); core.set_command(CORE_WRITE, FUNCTION, "Raw write", WriteRaw, CORE_SUSPENDED);
core.set_command(CORE_WRITE_DWORD, FUNCTION, "Write DWORD", WriteDWord); core.set_command(CORE_WRITE_DWORD, FUNCTION, "Write DWORD", WriteDWord, CORE_SUSPENDED);
core.set_command(CORE_WRITE_WORD, FUNCTION, "Write WORD", WriteWord); core.set_command(CORE_WRITE_WORD, FUNCTION, "Write WORD", WriteWord, CORE_SUSPENDED);
core.set_command(CORE_WRITE_BYTE, FUNCTION, "Write BYTE", WriteByte); core.set_command(CORE_WRITE_BYTE, FUNCTION, "Write BYTE", WriteByte, CORE_SUSPENDED);
core.set_command(CORE_SUSPEND, FUNCTION, "Suspend", Suspend); core.set_command(CORE_SUSPEND, CLIENT_WAIT, "Suspend", 0 , CORE_SUSPENDED);
core.set_command(CORE_SUSPENDED, CLIENT_WAIT, "Suspended", 0); core.set_command(CORE_SUSPENDED, CLIENT_WAIT, "Suspended");
core.set_command(CORE_READ_STL_STRING, FUNCTION, "Read STL string", ReadSTLString); core.set_command(CORE_READ_STL_STRING, FUNCTION, "Read STL string", ReadSTLString, CORE_RET_STRING);
core.set_command(CORE_READ_C_STRING, CLIENT_WAIT, "RESERVED", 0); core.set_command(CORE_READ_C_STRING, CLIENT_WAIT, "RESERVED");
core.set_command(CORE_RET_STRING, CLIENT_WAIT, "Return string", 0); core.set_command(CORE_RET_STRING, CLIENT_WAIT, "Return string");
core.set_command(CORE_WRITE_STL_STRING, FUNCTION, "Write STL string", WriteSTLString); 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); module_registry.push_back(core);
} }
@ -233,6 +188,7 @@ void InitModules (void)
{ {
// create the core module // create the core module
InitCore(); InitCore();
// TODO: dynamic module init
} }
void SHM_Act (void) void SHM_Act (void)
@ -252,7 +208,7 @@ void SHM_Act (void)
} }
else else
{ {
full_barrier // full_barrier
SHMCMD = CORE_RUNNING; SHMCMD = CORE_RUNNING;
fprintf(stderr,"dfhack: Broke out of loop, other process disappeared.\n"); fprintf(stderr,"dfhack: Broke out of loop, other process disappeared.\n");
} }
@ -264,9 +220,16 @@ void SHM_Act (void)
{ {
cmd._function(); cmd._function();
} }
if(cmd.nextState != -1)
{
SHMCMD = cmd.nextState;
}
if(cmd.type != CANCELLATION) if(cmd.type != CANCELLATION)
{ {
SCHED_YIELD if(useYield)
{
SCHED_YIELD
}
numwaits ++; // watchdog timeout numwaits ++; // watchdog timeout
goto check_again; goto check_again;
} }

@ -37,11 +37,8 @@ distribution.
#include <vector> #include <vector>
#include <string> #include <string>
#include "shms.h" #include "shms.h"
#include <sys/time.h> #include "shms-core.h"
#include <time.h> #include <sched.h>
#include <linux/futex.h>
#include <sys/syscall.h>
#include <signal.h>
#define DFhackCExport extern "C" __attribute__ ((visibility("default"))) #define DFhackCExport extern "C" __attribute__ ((visibility("default")))
@ -69,6 +66,15 @@ uint32_t OS_getPID()
return getpid(); return getpid();
} }
uint32_t OS_getAffinity()
{
cpu_set_t mask;
sched_getaffinity(0,sizeof(cpu_set_t),&mask);
// FIXME: truncation
uint32_t affinity = *(uint32_t *) &mask;
return affinity;
}
void SHM_Init ( void ) void SHM_Init ( void )
{ {
// check that we do this only once per process // check that we do this only once per process

@ -1,7 +1,6 @@
#ifndef DFCONNECT_H #ifndef DFCONNECT_H
#define DFCONNECT_H #define DFCONNECT_H
#define CORE_VERSION 3
#define SHM_KEY 123466 #define SHM_KEY 123466
#define SHM_HEADER 1024 // 1kB reserved for a header #define SHM_HEADER 1024 // 1kB reserved for a header
#define SHM_BODY 1024*1024 // 1MB reserved for bulk data transfer #define SHM_BODY 1024*1024 // 1MB reserved for bulk data transfer
@ -12,16 +11,14 @@
#ifdef LINUX_BUILD #ifdef LINUX_BUILD
// a full memory barrier! better be safe than sorry. // a full memory barrier! better be safe than sorry.
#define full_barrier asm volatile("" ::: "memory"); __sync_synchronize(); #define full_barrier asm volatile("" ::: "memory"); __sync_synchronize();
#define SCHED_YIELD sched_yield(); // slow but allows the SHM to work on single-core #define SCHED_YIELD sched_yield(); // a requirement for single-core
// #define SCHED_YIELD usleep(0); // extremely slow
// #define SCHED_YIELD // works only on multi-core
#else #else
// we need windows.h for Sleep() // we need windows.h for Sleep()
#define _WIN32_WINNT 0x0501 // needed for INPUT struct #define _WIN32_WINNT 0x0501 // needed for INPUT struct
#define WINVER 0x0501 // OpenThread(), PSAPI, Toolhelp32 #define WINVER 0x0501 // OpenThread(), PSAPI, Toolhelp32
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
#define SCHED_YIELD Sleep(0); // slow on single-core, but avoids infinite lockup #define SCHED_YIELD Sleep(0); // avoids infinite lockup on single core
// FIXME: detect MSVC here and use the right barrier magic // FIXME: detect MSVC here and use the right barrier magic
#ifdef __MINGW32__ #ifdef __MINGW32__
#define full_barrier asm volatile("" ::: "memory"); #define full_barrier asm volatile("" ::: "memory");
@ -32,66 +29,40 @@
#endif #endif
#endif #endif
enum DF_SHM_ERRORSTATE enum DFPP_CmdType
{ {
SHM_OK, // all OK CANCELLATION, // we should jump out of the Act()
SHM_CANT_GET_SHM, // getting the SHM ID failed for some reason CLIENT_WAIT, // we are waiting for the client
SHM_CANT_ATTACH, // we can't attach the shm for some reason FUNCTION, // we call a function as a result of the command
SHM_SECOND_DF // we are a second DF process, can't use SHM at all
}; };
enum CORE_COMMAND struct DFPP_command
{ {
CORE_RUNNING = 0, // no command, normal server execution void (*_function)(void);
DFPP_CmdType type:32; // force the enum to 32 bits for compatibility reasons
CORE_GET_VERSION, // protocol version query std::string name;
CORE_RET_VERSION, // return the protocol version uint32_t nextState;
CORE_GET_PID, // query for the process ID
CORE_RET_PID, // return process ID
// version 1 stuff below
CORE_DFPP_READ, // cl -> sv, read some data
CORE_RET_DATA, // sv -> cl, returned data
CORE_READ_DWORD, // cl -> sv, read a dword
CORE_RET_DWORD, // sv -> cl, returned dword
CORE_READ_WORD, // cl -> sv, read a word
CORE_RET_WORD, // sv -> cl, returned word
CORE_READ_BYTE, // cl -> sv, read a byte
CORE_RET_BYTE, // sv -> cl, returned byte
CORE_SV_ERROR, // there was a server error
CORE_CL_ERROR, // there was a client error
CORE_WRITE,// client writes to server
CORE_WRITE_DWORD,// client writes a DWORD to server
CORE_WRITE_WORD,// client writes a WORD to server
CORE_WRITE_BYTE,// client writes a BYTE to server
CORE_SUSPEND, // client notifies server to wait for commands (server is stalled in busy wait)
CORE_SUSPENDED, // response to WAIT, server is stalled in busy wait
// all strings capped at 1MB
CORE_READ_STL_STRING,// client requests contents of STL string at address
CORE_READ_C_STRING,// client requests contents of a C string at address, max length (0 means zero terminated)
CORE_RET_STRING, // sv -> cl length + string contents
CORE_WRITE_STL_STRING,// client wants to set STL string at address to something
// compare affinity and determine if using yield is required
CORE_SYNC_YIELD,// cl sends affinity to sv, sv sets yield
CORE_SYNC_YIELD_RET,// sv returns yield bool
NUM_CORE_CMDS
}; };
struct DFPP_module
enum DF_ERROR
{ {
DFEE_INVALID_COMMAND, inline void set_command(const unsigned int index, const DFPP_CmdType type, const char * name, void (*_function)(void) = 0,uint32_t nextState = -1)
DFEE_BUFFER_OVERFLOW {
commands[index].type = type;
commands[index].name = name;
commands[index]._function = _function;
commands[index].nextState = nextState;
}
inline void reserve (unsigned int numcommands)
{
commands.clear();
DFPP_command cmd = {0,CANCELLATION,"",0};
commands.resize(numcommands,cmd);
}
std::string name;
uint32_t version; // version
std::vector <DFPP_command> commands;
void * modulestate;
}; };
typedef union typedef union
@ -108,17 +79,10 @@ typedef union
} }
} shm_cmd; } shm_cmd;
typedef struct
{
shm_cmd cmd;
uint32_t address;
uint32_t value;
uint32_t length;
} shm_header;
void SHM_Act (void); void SHM_Act (void);
void InitModules (void); void InitModules (void);
bool isValidSHM(); bool isValidSHM();
uint32_t OS_getPID(); uint32_t OS_getPID();
uint32_t OS_getAffinity(); // limited to 32 processors. Silly, eh?
#endif #endif