From 242bf471439c2c4d235064f81eedc53baa30092d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Mon, 4 Jan 2010 05:20:28 +0000 Subject: [PATCH] some rearrangement of the shm server part, preparing for the windows port --- CMakeLists.txt | 6 +- library/CMakeLists.txt | 2 +- library/DFProcess-linux-SHM.cpp | 2 +- library/DFProcessEnumerator-linux.cpp | 2 +- shmserver/CMakeLists.txt | 47 +++++ {library/shmserver => shmserver}/df-hacked | 0 {library/shmserver => shmserver}/dfconnect.so | Bin {library/shmserver => shmserver}/readme.txt | 0 .../dfconnect.c => shmserver/shms-linux.cpp | 139 +------------- shmserver/shms-proto.cpp | 170 ++++++++++++++++++ shmserver/shms-windows.cpp | 31 ++++ .../shmserver/dfconnect.h => shmserver/shms.h | 16 ++ 12 files changed, 279 insertions(+), 136 deletions(-) create mode 100644 shmserver/CMakeLists.txt rename {library/shmserver => shmserver}/df-hacked (100%) rename {library/shmserver => shmserver}/dfconnect.so (100%) rename {library/shmserver => shmserver}/readme.txt (100%) rename library/shmserver/dfconnect.c => shmserver/shms-linux.cpp (56%) create mode 100644 shmserver/shms-proto.cpp create mode 100644 shmserver/shms-windows.cpp rename library/shmserver/dfconnect.h => shmserver/shms.h (86%) diff --git a/CMakeLists.txt b/CMakeLists.txt index ab8f95695..ea6b29e8a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # main project file. use it from a build sub-folder, see COMPILE for details -PROJECT (dfhack) +PROJECT (dfhack) cmake_minimum_required(VERSION 2.6) # disable warning, autosearch @@ -25,6 +25,8 @@ SET( LIBRARY_OUTPUT_PATH ${dfhack_SOURCE_DIR}/output CACHE PATH "Output director SET( EXECUTABLE_OUTPUT_PATH ${dfhack_SOURCE_DIR}/output CACHE PATH "Output directory for the dfhack tools" ) include_directories (${CMAKE_SOURCE_DIR}/library/) +include_directories (${CMAKE_SOURCE_DIR}/shmserver/) add_subdirectory (library) -add_subdirectory (tools) \ No newline at end of file +add_subdirectory (tools) +add_subdirectory (shmserver) \ No newline at end of file diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index f6eb29e12..77b340bf6 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -20,7 +20,7 @@ md5/md5wrapper.h tinyxml/tinystr.h tinyxml/tinyxml.h -shmserver/dfconnect.h +../shmserver/shms.h ) SET(PROJECT_SRCS diff --git a/library/DFProcess-linux-SHM.cpp b/library/DFProcess-linux-SHM.cpp index 48e8816e3..d8bb9a46a 100644 --- a/library/DFProcess-linux-SHM.cpp +++ b/library/DFProcess-linux-SHM.cpp @@ -27,7 +27,7 @@ distribution. #include #include #include -#include "shmserver/dfconnect.h" +#include "../shmserver/shms.h" #include #include #include diff --git a/library/DFProcessEnumerator-linux.cpp b/library/DFProcessEnumerator-linux.cpp index 6755bf9e7..c9e20da70 100644 --- a/library/DFProcessEnumerator-linux.cpp +++ b/library/DFProcessEnumerator-linux.cpp @@ -27,7 +27,7 @@ distribution. #include #include #include -#include "shmserver/dfconnect.h" +#include "../shmserver/shms.h" using namespace DFHack; diff --git a/shmserver/CMakeLists.txt b/shmserver/CMakeLists.txt new file mode 100644 index 000000000..bd650e472 --- /dev/null +++ b/shmserver/CMakeLists.txt @@ -0,0 +1,47 @@ +# don't use this file directly. use the one in the root folder of the project + +SET(PROJECT_HDRS +shms.h +) + +SET(PROJECT_SRCS +shms-proto.cpp +) + +SET(PROJECT_HDRS_LINUX +) + +SET(PROJECT_HDRS_WINDOWS +) + +SET(PROJECT_SRCS_LINUX +shms-linux.cpp +) + +SET(PROJECT_SRCS_WINDOWS +shms-windows.cpp +) + +IF(UNIX) + LIST(APPEND PROJECT_HDRS ${PROJECT_HDRS_LINUX}) + LIST(APPEND PROJECT_SRCS ${PROJECT_SRCS_LINUX}) +ELSE(UNIX) + LIST(APPEND PROJECT_HDRS ${PROJECT_HDRS_WINDOWS}) + LIST(APPEND PROJECT_SRCS ${PROJECT_SRCS_WINDOWS}) +ENDIF(UNIX) + + +SET_SOURCE_FILES_PROPERTIES( ${PROJECT_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE ) + +LIST(APPEND PROJECT_SRCS ${PROJECT_HDRS}) + +IF(UNIX) + add_definitions(-DLINUX_BUILD) + SET(PROJECT_LIBS rt) +ELSE(UNIX) +# SET(PROJECT_LIBS psapi) +ENDIF(UNIX) + +ADD_LIBRARY(dfconnect SHARED ${PROJECT_SRCS}) +TARGET_LINK_LIBRARIES(dfconnect ${PROJECT_LIBS}) + diff --git a/library/shmserver/df-hacked b/shmserver/df-hacked similarity index 100% rename from library/shmserver/df-hacked rename to shmserver/df-hacked diff --git a/library/shmserver/dfconnect.so b/shmserver/dfconnect.so similarity index 100% rename from library/shmserver/dfconnect.so rename to shmserver/dfconnect.so diff --git a/library/shmserver/readme.txt b/shmserver/readme.txt similarity index 100% rename from library/shmserver/readme.txt rename to shmserver/readme.txt diff --git a/library/shmserver/dfconnect.c b/shmserver/shms-linux.cpp similarity index 56% rename from library/shmserver/dfconnect.c rename to shmserver/shms-linux.cpp index 50f9e0e5b..1d8fc03df 100644 --- a/library/shmserver/dfconnect.c +++ b/shmserver/shms-linux.cpp @@ -34,7 +34,7 @@ distribution. #include #include #include -#include "dfconnect.h" +#include "shms.h" #include #include #include @@ -137,136 +137,6 @@ void SHM_Destroy ( void ) fprintf(stderr,"dfhack: destroyed shared segment.\n"); } -void SHM_Act (void) -{ - if(errorstate) - { - return; - } - shmid_ds descriptor; - uint32_t numwaits = 0; - uint32_t length; - uint32_t address; - check_again: // goto target!!! - if(numwaits == 10000) - { - shmctl(shmid, IPC_STAT, &descriptor); - if(descriptor.shm_nattch == 1)// other guy crashed - { - gcc_barrier - ((shm_cmd *)shm)->pingpong = DFPP_RUNNING; - fprintf(stderr,"dfhack: Broke out of loop, other process disappeared.\n"); - return; - } - else - { - numwaits = 0; - } - } - switch (((shm_cmd *)shm)->pingpong) - { - case DFPP_RET_VERSION: - case DFPP_RET_DATA: - case DFPP_RET_DWORD: - case DFPP_RET_WORD: - case DFPP_RET_BYTE: - case DFPP_SUSPENDED: - case DFPP_RET_PID: - case DFPP_SV_ERROR: - numwaits++; - goto check_again; - case DFPP_SUSPEND: - gcc_barrier - ((shm_cmd *)shm)->pingpong = DFPP_SUSPENDED; - goto check_again; - /* - case DFPP_BOUNCE: - length = ((shm_bounce *)shm)->length; - memcpy(BigFat,shm + SHM_HEADER,length); - memcpy(shm + SHM_HEADER,BigFat,length); - ((shm_cmd *)shm)->pingpong = DFPP_RET_DATA; - goto check_again; - */ - case DFPP_PID: - ((shm_retval *)shm)->value = getpid(); - gcc_barrier - ((shm_retval *)shm)->pingpong = DFPP_RET_PID; - goto check_again; - - case DFPP_VERSION: - ((shm_retval *)shm)->value = PINGPONG_VERSION; - gcc_barrier - ((shm_retval *)shm)->pingpong = DFPP_RET_VERSION; - goto check_again; - - case DFPP_READ: - length = ((shm_read *)shm)->length; - address = ((shm_read *)shm)->address; - memcpy(shm + SHM_HEADER, (void *) address,length); - gcc_barrier - ((shm_cmd *)shm)->pingpong = DFPP_RET_DATA; - goto check_again; - - case DFPP_READ_DWORD: - address = ((shm_read_small *)shm)->address; - ((shm_retval *)shm)->value = *((uint32_t*) address); - gcc_barrier - ((shm_retval *)shm)->pingpong = DFPP_RET_DWORD; - goto check_again; - - case DFPP_READ_WORD: - address = ((shm_read_small *)shm)->address; - ((shm_retval *)shm)->value = *((uint16_t*) address); - gcc_barrier - ((shm_retval *)shm)->pingpong = DFPP_RET_WORD; - goto check_again; - - case DFPP_READ_BYTE: - address = ((shm_read_small *)shm)->address; - ((shm_retval *)shm)->value = *((uint8_t*) address); - gcc_barrier - ((shm_retval *)shm)->pingpong = DFPP_RET_BYTE; - goto check_again; - - case DFPP_WRITE: - address = ((shm_write *)shm)->address; - length = ((shm_write *)shm)->length; - memcpy((void *)address, shm + SHM_HEADER,length); - gcc_barrier - ((shm_cmd *)shm)->pingpong = DFPP_SUSPENDED; - goto check_again; - - case DFPP_WRITE_DWORD: - (*(uint32_t*)((shm_write_small *)shm)->address) = ((shm_write_small *)shm)->value; - gcc_barrier - ((shm_cmd *)shm)->pingpong = DFPP_SUSPENDED; - goto check_again; - - case DFPP_WRITE_WORD: - (*(uint16_t*)((shm_write_small *)shm)->address) = ((shm_write_small *)shm)->value; - gcc_barrier - ((shm_cmd *)shm)->pingpong = DFPP_SUSPENDED; - goto check_again; - - case DFPP_WRITE_BYTE: - (*(uint8_t*)((shm_write_small *)shm)->address) = ((shm_write_small *)shm)->value; - gcc_barrier - ((shm_cmd *)shm)->pingpong = DFPP_SUSPENDED; - goto check_again; - - case DFPP_CL_ERROR: - case DFPP_RUNNING: - fprintf(stderr, "no. of waits: %d\n", numwaits); - break; - - default: - ((shm_retval *)shm)->value = DFEE_INVALID_COMMAND; - gcc_barrier - ((shm_retval *)shm)->pingpong = DFPP_SV_ERROR; - break; - } -} - // hook - called every tick in OpenGL mode of DF extern "C" void SDL_GL_SwapBuffers(void) { @@ -331,3 +201,10 @@ extern "C" int SDL_Init(uint32_t flags) return _SDL_Init(flags); } +// FIXME: add error checking? +bool isValidSHM() +{ + shmid_ds descriptor; + shmctl(shmid, IPC_STAT, &descriptor); + return descriptor.shm_nattch == 1; +} \ No newline at end of file diff --git a/shmserver/shms-proto.cpp b/shmserver/shms-proto.cpp new file mode 100644 index 000000000..36d7930a7 --- /dev/null +++ b/shmserver/shms-proto.cpp @@ -0,0 +1,170 @@ +/* +www.sourceforge.net/projects/dfhack +Copyright (c) 2009 Petr Mrázek (peterix) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +/** + * This is the source for the DF <-> dfhack shm bridge, server protocol part + */ +#include +#include +#include +#include +#include +#include "shms.h" + +// various crud +extern int errorstate; +extern char *shm; +extern int shmid; + +void SHM_Act (void) +{ + if(errorstate) + { + return; + } + uint32_t numwaits = 0; + uint32_t length; + uint32_t address; + check_again: // goto target!!! + if(numwaits == 10000) + { + // this tests if there's a process on the other side + if(isValidSHM()) + { + numwaits = 0; + } + else + { + full_barrier + ((shm_cmd *)shm)->pingpong = DFPP_RUNNING; + fprintf(stderr,"dfhack: Broke out of loop, other process disappeared.\n"); + } + } + switch (((shm_cmd *)shm)->pingpong) + { + case DFPP_RET_VERSION: + case DFPP_RET_DATA: + case DFPP_RET_DWORD: + case DFPP_RET_WORD: + case DFPP_RET_BYTE: + case DFPP_SUSPENDED: + case DFPP_RET_PID: + case DFPP_SV_ERROR: + numwaits++; + goto check_again; + case DFPP_SUSPEND: + full_barrier + ((shm_cmd *)shm)->pingpong = DFPP_SUSPENDED; + goto check_again; + /* + case DFPP_BOUNCE: + length = ((shm_bounce *)shm)->length; + memcpy(BigFat,shm + SHM_HEADER,length); + memcpy(shm + SHM_HEADER,BigFat,length); + ((shm_cmd *)shm)->pingpong = DFPP_RET_DATA; + goto check_again; + */ + case DFPP_PID: + #ifdef LINUX_BUILD + ((shm_retval *)shm)->value = getpid(); + #else + ((shm_retval *)shm)->value = GetCurrentProcessId(void); + #endif + full_barrier + ((shm_retval *)shm)->pingpong = DFPP_RET_PID; + goto check_again; + + case DFPP_VERSION: + ((shm_retval *)shm)->value = PINGPONG_VERSION; + full_barrier + ((shm_retval *)shm)->pingpong = DFPP_RET_VERSION; + goto check_again; + + case DFPP_READ: + length = ((shm_read *)shm)->length; + address = ((shm_read *)shm)->address; + memcpy(shm + SHM_HEADER, (void *) address,length); + full_barrier + ((shm_cmd *)shm)->pingpong = DFPP_RET_DATA; + goto check_again; + + case DFPP_READ_DWORD: + address = ((shm_read_small *)shm)->address; + ((shm_retval *)shm)->value = *((uint32_t*) address); + full_barrier + ((shm_retval *)shm)->pingpong = DFPP_RET_DWORD; + goto check_again; + + case DFPP_READ_WORD: + address = ((shm_read_small *)shm)->address; + ((shm_retval *)shm)->value = *((uint16_t*) address); + full_barrier + ((shm_retval *)shm)->pingpong = DFPP_RET_WORD; + goto check_again; + + case DFPP_READ_BYTE: + address = ((shm_read_small *)shm)->address; + ((shm_retval *)shm)->value = *((uint8_t*) address); + full_barrier + ((shm_retval *)shm)->pingpong = DFPP_RET_BYTE; + goto check_again; + + case DFPP_WRITE: + address = ((shm_write *)shm)->address; + length = ((shm_write *)shm)->length; + memcpy((void *)address, shm + SHM_HEADER,length); + full_barrier + ((shm_cmd *)shm)->pingpong = DFPP_SUSPENDED; + goto check_again; + + case DFPP_WRITE_DWORD: + (*(uint32_t*)((shm_write_small *)shm)->address) = ((shm_write_small *)shm)->value; + full_barrier + ((shm_cmd *)shm)->pingpong = DFPP_SUSPENDED; + goto check_again; + + case DFPP_WRITE_WORD: + (*(uint16_t*)((shm_write_small *)shm)->address) = ((shm_write_small *)shm)->value; + full_barrier + ((shm_cmd *)shm)->pingpong = DFPP_SUSPENDED; + goto check_again; + + case DFPP_WRITE_BYTE: + (*(uint8_t*)((shm_write_small *)shm)->address) = ((shm_write_small *)shm)->value; + full_barrier + ((shm_cmd *)shm)->pingpong = DFPP_SUSPENDED; + goto check_again; + + case DFPP_CL_ERROR: + case DFPP_RUNNING: + fprintf(stderr, "no. of waits: %d\n", numwaits); + break; + + default: + ((shm_retval *)shm)->value = DFEE_INVALID_COMMAND; + full_barrier + ((shm_retval *)shm)->pingpong = DFPP_SV_ERROR; + break; + } +} \ No newline at end of file diff --git a/shmserver/shms-windows.cpp b/shmserver/shms-windows.cpp new file mode 100644 index 000000000..b083ff69e --- /dev/null +++ b/shmserver/shms-windows.cpp @@ -0,0 +1,31 @@ +/* +www.sourceforge.net/projects/dfhack +Copyright (c) 2009 Petr Mrázek (peterix) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +/** + * This is the source for the DF <-> dfhack shm bridge + */ +#include "shms.h" +extern char *shm; + +// TO BE DONE \ No newline at end of file diff --git a/library/shmserver/dfconnect.h b/shmserver/shms.h similarity index 86% rename from library/shmserver/dfconnect.h rename to shmserver/shms.h index aa51742da..df04f4fb6 100644 --- a/library/shmserver/dfconnect.h +++ b/shmserver/shms.h @@ -7,6 +7,19 @@ #define SHM_BODY 1024*1024 #define SHM_SIZE SHM_HEADER+SHM_BODY +// a full memory barrier! better be safe than sorry. +#ifdef LINUX_BUILD + #define full_barrier asm volatile("" ::: "memory"); __sync_synchronize(); +#else + // FIXME: detect MSVC here and use the right barrier magic + #define full_barrier ; +/* + #pragma intrinsic(_ReadWriteBarrier) + #define full_barrier MFENCE; _ReadWriteBarrier(); + */ +#endif + + /* * read - parameters are address and length * write - parameters are address, length and the actual data to write @@ -109,4 +122,7 @@ typedef struct uint32_t value; } shm_retval; +void SHM_Act (void); +bool isValidSHM(); + #endif \ No newline at end of file