Fix #2591 spinlock issue. (#2637)

* Fix #2591 spinlock issue.
Add basic_test, for few integration test.
Add thread_local_storage support in cmake
Fix thread.c for linux and fix small typo
This commit is contained in:
lighta 2017-11-26 22:30:17 -04:00 committed by GitHub
parent cfb8b42d84
commit 618b9356fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 527 additions and 14 deletions

6
3rdparty/cmake/tests/HAVE_TLS.c vendored Normal file
View File

@ -0,0 +1,6 @@
__thread int tls;
int main(int argc, char** argv)
{
return 0;
}

View File

@ -79,5 +79,5 @@ set( YAML_DEFINITIONS
"-std=c++11"
CACHE INTERNAL "yaml definitions" )
include_directories(${YAML_INCLUDE_DIRS} ${YAML_SOURCE_DIR})
message(STATUS "YAML_INCLUDE_DIRS : ${YAML_INCLUDE_DIRS}, YAML_SOURCE_DIR=${YAML_SOURCE_DIR}")
#message(STATUS "YAML_INCLUDE_DIRS : ${YAML_INCLUDE_DIRS}, YAML_SOURCE_DIR=${YAML_SOURCE_DIR}")
ADD_LIBRARY(${this_target} STATIC ${YAML_SOURCES} )

View File

@ -107,6 +107,7 @@ include( CheckFunctionExists )
include( FindFunctionLibrary )
include( TestBigEndian )
#
# PACKETVER
#
@ -149,6 +150,16 @@ if( CMAKE_THREAD_LIBS_INIT )
endif()
message( STATUS "Detecting threads library - done" )
message( STATUS "Check if supporting Thread local storage (TLS)" )
file( READ "${CMAKE_SOURCE_DIR}/3rdparty/cmake/tests/HAVE_TLS.c" _SOURCE )
CHECK_C_SOURCE_RUNS( "${_SOURCE}" HAVE_TLS )
if( HAVE_TLS )
message( STATUS "Check for TLS- yes" )
set_property( CACHE GLOBAL_DEFINITIONS PROPERTY VALUE "${GLOBAL_DEFINITIONS} -DHAVE_TLS" )
else()
message( STATUS "Check for TLS - no" )
endif()
#
# math library (FreeBSD/Linux/Solaris)

View File

@ -62,6 +62,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "map-cache", "src\tool\map-c
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yaml-cpp", "3rdparty\yaml-cpp\yaml-cpp.vcxproj", "{61D6A599-6BED-4154-A9FC-40553BD972E0}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic_test", "src\test\basic_test.vcxproj", "{99B4DF6A-6180-4E7F-9227-F812FF30414A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@ -142,6 +144,14 @@ Global
{61D6A599-6BED-4154-A9FC-40553BD972E0}.Release|Win32.Build.0 = Release|Win32
{61D6A599-6BED-4154-A9FC-40553BD972E0}.Release|x64.ActiveCfg = Release|x64
{61D6A599-6BED-4154-A9FC-40553BD972E0}.Release|x64.Build.0 = Release|x64
{99B4DF6A-6180-4E7F-9227-F812FF30414A}.Debug|Win32.ActiveCfg = Debug|Win32
{99B4DF6A-6180-4E7F-9227-F812FF30414A}.Debug|Win32.Build.0 = Debug|Win32
{99B4DF6A-6180-4E7F-9227-F812FF30414A}.Debug|x64.ActiveCfg = Debug|x64
{99B4DF6A-6180-4E7F-9227-F812FF30414A}.Debug|x64.Build.0 = Debug|x64
{99B4DF6A-6180-4E7F-9227-F812FF30414A}.Release|Win32.ActiveCfg = Release|Win32
{99B4DF6A-6180-4E7F-9227-F812FF30414A}.Release|Win32.Build.0 = Release|Win32
{99B4DF6A-6180-4E7F-9227-F812FF30414A}.Release|x64.ActiveCfg = Release|x64
{99B4DF6A-6180-4E7F-9227-F812FF30414A}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -157,5 +167,9 @@ Global
{352B45B3-FE88-4431-9D89-48CF811446DB} = {C0A6FC9A-3A5C-48F8-A4B6-8D463C61C021}
{FC4C071B-2C26-4B03-948A-335C94A88B5E} = {9F328FE9-129D-4C0C-820B-BE4AA5996652}
{61D6A599-6BED-4154-A9FC-40553BD972E0} = {6ABA1767-6242-4CA0-BA22-A30972DC8918}
{99B4DF6A-6180-4E7F-9227-F812FF30414A} = {9F328FE9-129D-4C0C-820B-BE4AA5996652}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {026DA20F-820C-40AA-983E-0E231EA90AD5}
EndGlobalSection
EndGlobal

View File

@ -16,4 +16,6 @@ endif()
add_subdirectory( login )
add_subdirectory( char )
add_subdirectory( map )
add_subdirectory( test )
add_subdirectory( tool )

View File

@ -22,7 +22,9 @@ source_group( common FILES ${COMMON_BASE_HEADERS} ${COMMON_HEADERS} )
source_group( char FILES ${CHAR_HEADERS} ${CHAR_SOURCES} )
include_directories( ${INCLUDE_DIRS} )
#message( STATUS "char-server SOURCE_FILES=${SOURCE_FILES}")
add_executable( char-server ${SOURCE_FILES} )
#message( STATUS "char-server LIBRARIES=${LIBRARIES}, DEPENDENCIES=${DEPENDENCIES} DEFINITIONS=${DEFINITIONS}")
add_dependencies( char-server ${DEPENDENCIES} )
target_link_libraries( char-server ${LIBRARIES} ${DEPENDENCIES} )
set_target_properties( char-server PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" )

View File

@ -139,6 +139,7 @@ source_group( mt19937ar FILES ${MT19937AR_HEADERS} ${MT19937AR_SOURCES} )
source_group( common FILES ${COMMON_BASE_HEADERS} ${COMMON_BASE_SOURCES} )
add_library( common_base ${SOURCE_FILES} )
#message( STATUS "common_base LIBRARIES=${LIBRARIES}, DEFINITIONS=${DEFINITIONS}")
target_link_libraries( common_base ${LIBRARIES} )
set_target_properties( common_base PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" )
include_directories( ${INCLUDE_DIRS} )
@ -172,6 +173,7 @@ set( SOURCE_FILES ${COMMON_HEADERS} ${COMMON_SOURCES} )
source_group( common FILES ${COMMON_HEADERS} ${COMMON_SOURCES} )
add_library( common ${SOURCE_FILES} )
#message( STATUS "common LIBRARIES=${LIBRARIES}, DEPENDENCIES=${DEPENDENCIES} DEFINITIONS=${DEFINITIONS}")
add_dependencies( common ${DEPENDENCIES} )
target_link_libraries( common ${LIBRARIES} ${DEPENDENCIES} )
set_target_properties( common PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" )

View File

@ -71,14 +71,11 @@ static forceinline void EnterSpinLock(PSPIN_LOCK lck){
// Spin until we've got it !
while(1){
if(InterlockedCompareExchange(&lck->lock, tid, 0) == 0){
while(1){
if(InterlockedCompareExchange(&lck->lock, tid, RA_INVALID_THID) == RA_INVALID_THID){
InterlockedIncrement(&lck->nest);
return; // Got Lock
}
rathread_yield(); // Force ctxswitch to another thread.
}
@ -92,13 +89,14 @@ static forceinline void LeaveSpinLock(PSPIN_LOCK lck){
if(InterlockedCompareExchange(&lck->lock, tid, tid) == tid){ // this thread owns the lock.
if(InterlockedDecrement(&lck->nest) == 0)
InterlockedExchange(&lck->lock, 0); // Unlock!
InterlockedExchange(&lck->lock, RA_INVALID_THID); // Unlock!
}
dropsynclock(&lck->sync_lock);
}
#undef getsynclock
#undef dropsynclock
#endif

View File

@ -25,7 +25,7 @@
#include "thread.h"
// When Compiling using MSC (on win32..) we know we have support in any case!
#ifdef _MSC_VER
#if defined(_MSC_VER ) && !defined(HAS_TLS)
#define HAS_TLS
#endif
@ -48,7 +48,7 @@ struct rAthread {
#ifdef HAS_TLS
__thread int g_rathread_ID = -1;
__thread int g_rathread_ID = RA_INVALID_THID;
#endif
@ -57,6 +57,12 @@ __thread int g_rathread_ID = -1;
///
static struct rAthread l_threads[RA_THREADS_MAX];
prAthread rathenat_getThread( int idx ) {
if(idx < RA_THREADS_MAX)
return &l_threads[idx];
return NULL;
}
void rathread_init(){
register unsigned int i;
memset(&l_threads, 0x00, RA_THREADS_MAX * sizeof(struct rAthread) );
@ -70,7 +76,11 @@ void rathread_init(){
g_rathread_ID = 0;
#endif
l_threads[0].prio = RAT_PRIO_NORMAL;
l_threads[0].proc = (rAthreadProc)0xDEADCAFE;
#if defined(_WIN64) || defined(__x86_64__) || defined(__ppc64__)
l_threads[0].proc = (rAthreadProc)0xDEADCAFEDEADCAFE;
#else
l_threads[0].proc = (rAthreadProc)0xDEADCAFE;
#endif
}//end: rathread_init()
@ -221,7 +231,7 @@ void rathread_destroy ( prAthread handle ){
rat_thread_terminated(handle);
}
#else
if( pthread_cancel( handle->hThread ) == 0){
if(handle->hThread && pthread_cancel( handle->hThread ) == 0){
// We have to join it, otherwise pthread wont re-cycle its internal ressources assoc. with this thread.
//

View File

@ -20,6 +20,15 @@ typedef enum RATHREAD_PRIO {
RAT_PRIO_HIGH
} RATHREAD_PRIO;
#define RA_INVALID_THID -1
/**
* Get the handle of a specific thread
*
* @param idx - The index of the thread
* @return not NULL if success
*/
prAthread rathenat_getThread( int idx );
/**
* Creates a new Thread

View File

@ -12,7 +12,7 @@ message( STATUS "Creating target map-server" )
file(GLOB MAP_HEADERS ${MAP_SOURCE_DIR}/*.hpp)
file(GLOB MAP_SOURCES ${MAP_SOURCE_DIR}/*.cpp)
set( DEPENDENCIES common yaml-cpp)
set( LIBRARIES ${GLOBAL_LIBRARIES} yaml-cpp)
set( LIBRARIES ${GLOBAL_LIBRARIES})
set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ${COMMON_BASE_INCLUDE_DIRS} )
set( DEFINITIONS "${GLOBAL_DEFINITIONS} ${COMMON_BASE_DEFINITIONS}" )
if( WITH_PCRE )
@ -28,7 +28,9 @@ source_group( common FILES ${COMMON_BASE_HEADERS} ${COMMON_HEADERS} )
source_group( map FILES ${MAP_HEADERS} ${MAP_SOURCES} )
include_directories( ${INCLUDE_DIRS} )
#message( STATUS "map-server SOURCE_FILES=${SOURCE_FILES}")
add_executable( map-server ${SOURCE_FILES} )
#message( STATUS "map-server LIBRARIES=${LIBRARIES}, DEPENDENCIES=${DEPENDENCIES} DEFINITIONS=${DEFINITIONS}")
add_dependencies( map-server ${DEPENDENCIES} )
target_link_libraries( map-server ${LIBRARIES} ${DEPENDENCIES} )
set_target_properties( map-server PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" )

41
src/test/CMakeLists.txt Normal file
View File

@ -0,0 +1,41 @@
#
# basic_test
#
option( BUILD_TESTS "build basic_test executable" ON )
if( BUILD_TESTS )
set( TESTS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "" )
message( STATUS "Creating target basic_test" )
file(GLOB TESTS_HEADERS ${TESTS_SOURCE_DIR}/*.hpp)
file(GLOB TESTS_SOURCES ${TESTS_SOURCE_DIR}/*.cpp)
set( DEPENDENCIES common)
set( LIBRARIES ${GLOBAL_LIBRARIES})
set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ${COMMON_BASE_INCLUDE_DIRS} )
set( DEFINITIONS "${GLOBAL_DEFINITIONS} ${COMMON_BASE_DEFINITIONS} -DCMAKE" )
set( SOURCE_FILES ${COMMON_BASE_HEADERS} ${COMMON_HEADERS} ${TESTS_HEADERS} ${TESTS_SOURCES} )
source_group( common FILES ${COMMON_BASE_HEADERS} ${COMMON_HEADERS} )
source_group( test FILES ${TESTS_HEADERS} ${TESTS_SOURCES} )
include_directories( ${INCLUDE_DIRS} )
#message( STATUS "basic_test SOURCE_FILES=${SOURCE_FILES}")
add_executable( basic_test ${SOURCE_FILES} )
#message( STATUS "basic_test LIBRARIES=${LIBRARIES}, DEPENDENCIES=${DEPENDENCIES} DEFINITIONS=${DEFINITIONS}")
add_dependencies( basic_test ${DEPENDENCIES} )
target_link_libraries( basic_test ${LIBRARIES} ${DEPENDENCIES} )
set_target_properties( basic_test PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" )
if( INSTALL_COMPONENT_RUNTIME )
cpack_add_component( Runtime_tests DESCRIPTION "basic integration test" DISPLAY_NAME "basic_test" GROUP Runtime )
install( TARGETS basic_test
DESTINATION "."
COMPONENT Runtime_tests )
endif( INSTALL_COMPONENT_RUNTIME )
set( TARGET_LIST ${TARGET_LIST} basic_test CACHE INTERNAL "" )
message( STATUS "Creating target basic_test - done" )
endif( BUILD_TESTS )

171
src/test/basic_test.vcxproj Normal file
View File

@ -0,0 +1,171 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{99B4DF6A-6180-4E7F-9227-F812FF30414A}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>basic_test</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)</OutDir>
<IntDir>$(SolutionDir).vs\build\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)</OutDir>
<IntDir>$(SolutionDir).vs\build\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)</OutDir>
<IntDir>$(SolutionDir).vs\build\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)</OutDir>
<IntDir>$(SolutionDir).vs\build\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;$(SolutionDir).vs\build\common.lib;$(SolutionDir).vs\build\libconfig.lib;$(SolutionDir).vs\build\mt19937ar.lib;$(SolutionDir)3rdparty\zlib\lib\$(Platform)\zlib.lib;$(SolutionDir)3rdparty\pcre\lib\$(Platform)\pcre8.lib;$(SolutionDir)3rdparty\mysql\lib\$(Platform)\libmysql.lib;$(SolutionDir).vs\build\yaml-cpp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;$(SolutionDir).vs\build\common.lib;$(SolutionDir).vs\build\libconfig.lib;$(SolutionDir).vs\build\mt19937ar.lib;$(SolutionDir)3rdparty\zlib\lib\$(Platform)\zlib.lib;$(SolutionDir)3rdparty\pcre\lib\$(Platform)\pcre8.lib;$(SolutionDir)3rdparty\mysql\lib\$(Platform)\libmysql.lib;$(SolutionDir).vs\build\yaml-cpp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;$(SolutionDir).vs\build\common.lib;$(SolutionDir).vs\build\libconfig.lib;$(SolutionDir).vs\build\mt19937ar.lib;$(SolutionDir)3rdparty\zlib\lib\$(Platform)\zlib.lib;$(SolutionDir)3rdparty\pcre\lib\$(Platform)\pcre8.lib;$(SolutionDir)3rdparty\mysql\lib\$(Platform)\libmysql.lib;$(SolutionDir).vs\build\yaml-cpp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;$(SolutionDir).vs\build\common.lib;$(SolutionDir).vs\build\libconfig.lib;$(SolutionDir).vs\build\mt19937ar.lib;$(SolutionDir)3rdparty\zlib\lib\$(Platform)\zlib.lib;$(SolutionDir)3rdparty\pcre\lib\$(Platform)\pcre8.lib;$(SolutionDir)3rdparty\mysql\lib\$(Platform)\libmysql.lib;$(SolutionDir).vs\build\yaml-cpp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="basictest.cpp" />
<ClCompile Include="test_spinlock.cpp" />
<ClCompile Include="test_thread.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="test_spinlock.hpp" />
<ClInclude Include="test_thread.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="basictest.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="test_thread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="test_spinlock.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="test_spinlock.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="test_thread.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

39
src/test/basictest.cpp Normal file
View File

@ -0,0 +1,39 @@
// basictest.cpp : Sets the entry point for the console application.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef _WIN32
#include <unistd.h>
#endif
#include "../common/core.h"
#include "test_thread.hpp"
#include "test_spinlock.hpp"
using namespace ra::unit_tests;
int do_init( int, char** )
{
test_thread_creation_and_wait();
test_thread_spinlock();
return 0;
}
//just some empty function to comply link
void do_abort(void) {}
void do_final(void) {}
void set_server_type(void) {}
//tmp tp avoid link issue in cmake
#if defined(CMAKE)
#ifdef __cplusplus
extern "C" {
#endif
void Sql_Init(void) {}
#ifdef __cplusplus
}
#endif
#endif

102
src/test/test_spinlock.cpp Normal file
View File

@ -0,0 +1,102 @@
#include "test_spinlock.hpp"
#include <chrono>
#include <thread>
#include "../common/thread.h"
#include "../common/spinlock.h"
#include "../common/showmsg.h"
#include "test_thread.hpp"
namespace ra
{
namespace unit_tests
{
static SPIN_LOCK lSpinLock;
void* thread_test_critical( void *x )
{
size_t count = 0;
while ( count++ < 10 )
{
EnterSpinLock( &lSpinLock );
ShowStatus( "TH Entering critical_section recursion_count=%d iteration_count=%d\n", lSpinLock.nest,count );
std::this_thread::sleep_for(std::chrono::milliseconds( 100 )); //a simple test with critical section
ShowStatus( "TH Leaving critical_section recursion_count=%d\n iteration_count=%d", lSpinLock.nest,count );
LeaveSpinLock( &lSpinLock );
rathread_yield();
std::this_thread::sleep_for(std::chrono::milliseconds( 200 )); //let try to lose the lock here
}
return nullptr;
}
void test_thread_spinlock()
{
ShowStatus( "Testing test_thread_spinlock\n" );
InitializeSpinLock( &lSpinLock );
EnterSpinLock( &lSpinLock ); //fake critical section (we take it before creation to ensure we have the lock)
ShowStatus( "Main Entering critical_section recursion_count=%d\n", lSpinLock.nest );
prAthread lnd2th = rathread_create( &thread_test_critical, nullptr );
int lMainID = rathread_get_tid();
ShowStatus( "Continuing main th id=%d\n", lMainID );
rathread_yield();
std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); //fake doing stuff
ShowStatus( "Main Leaving critical_section recursion_count=%d\n", lSpinLock.nest );
LeaveSpinLock( &lSpinLock );
std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); //fake doing stuff
EnterSpinLock( &lSpinLock ); //now we should be waiting
ShowStatus( "Main Entering critical_section recursion_count=%d\n", lSpinLock.nest );
EnterSpinLock( &lSpinLock ); //testing with a recursion
ShowStatus( "Main Entering critical_section recursion_count=%d\n", lSpinLock.nest );
std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); //fake doing stuff
ShowStatus( "Main Leaving critical_section recursion_count=%d\n", lSpinLock.nest );
LeaveSpinLock( &lSpinLock );
ShowStatus( "Main Leaving critical_section recursion_count=%d\n", lSpinLock.nest );
LeaveSpinLock( &lSpinLock );
while ( !rathread_wait( lnd2th, nullptr ) )
{
ShowStatus( "Waiting 2nd thread\n" );
std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
}
rathread_destroy( lnd2th );
FinalizeSpinLock( &lSpinLock );
}
}
}
/* Expected result
[Status]: Testing test_thread_spinlock
[Status]: Main Entering critical_section recursion_count=1
[Status]: Continuing main th id=0
[Status]: Main Leaving critical_section recursion_count=1
[Status]: TH Entering critical_section recursion_count=1 iteration_count=1
[Status]: TH Leaving critical_section recursion_count=1 iteration_count=1
[Status]: Main Entering critical_section recursion_count=1
[Status]: Main Entering critical_section recursion_count=2
[Status]: Main Leaving critical_section recursion_count=2
[Status]: Main Leaving critical_section recursion_count=1
[Status]: TH Entering critical_section recursion_count=1 iteration_count=2
[Status]: TH Leaving critical_section recursion_count=1 iteration_count=2
[Status]: TH Entering critical_section recursion_count=1 iteration_count=3
[Status]: TH Leaving critical_section recursion_count=1 iteration_count=3
[Status]: TH Entering critical_section recursion_count=1 iteration_count=4
[Status]: TH Leaving critical_section recursion_count=1 iteration_count=4
[Status]: TH Entering critical_section recursion_count=1 iteration_count=5
[Status]: TH Leaving critical_section recursion_count=1 iteration_count=5
[Status]: TH Entering critical_section recursion_count=1 iteration_count=6
[Status]: TH Leaving critical_section recursion_count=1 iteration_count=6
[Status]: TH Entering critical_section recursion_count=1 iteration_count=7
[Status]: TH Leaving critical_section recursion_count=1 iteration_count=7
[Status]: TH Entering critical_section recursion_count=1 iteration_count=8
[Status]: TH Leaving critical_section recursion_count=1 iteration_count=8
[Status]: TH Entering critical_section recursion_count=1 iteration_count=9
[Status]: TH Leaving critical_section recursion_count=1 iteration_count=9
[Status]: TH Entering critical_section recursion_count=1 iteration_count=10
[Status]: TH Leaving critical_section recursion_count=1 iteration_count=10
*/

View File

@ -0,0 +1,12 @@
#pragma once
namespace ra
{
namespace unit_tests
{
//main
void test_thread_spinlock();
//subs
void* thread_test_critical( void *x ); //must match rAthreadProc signature
}
}

48
src/test/test_thread.cpp Normal file
View File

@ -0,0 +1,48 @@
#include "test_thread.hpp"
#include <chrono>
#include <thread>
#include "../common/thread.h"
#include "../common/showmsg.h"
namespace ra
{
namespace unit_tests
{
void* thread_test(void *x)
{
ShowStatus( "Entering thread_test\n" );
int lTHID = rathread_get_tid();
ShowStatus( "test th id=%d\n",lTHID);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
ShowStatus( "Leaving thread_test\n" );
return nullptr;
}
void test_thread_creation_and_wait()
{
ShowStatus( "Testing thread_creation_and_wait\n" );
prAthread lnd2th = rathread_create(&thread_test,nullptr);
//rathread_yield();
std::this_thread::sleep_for(std::chrono::milliseconds(100)); //fake doing stuff
int lMainID = rathread_get_tid();
ShowStatus( "Continuing main th id=%d\n",lMainID);
while ( !rathread_wait( lnd2th, nullptr ) )
{
ShowStatus( "Waiting 2nd thread\n" );
std::this_thread::sleep_for(std::chrono::seconds(1));
}
rathread_destroy(lnd2th); //will be destroy anyway by manager if not
}
}
}
/* Expected result
[Status]: Testing thread_creation_and_wait
[Status]: Entering thread_test
[Status]: test th id=1
[Status]: Continuing main th id=0
[Status]: Leaving thread_test
*/

12
src/test/test_thread.hpp Normal file
View File

@ -0,0 +1,12 @@
#pragma once
namespace ra
{
namespace unit_tests
{
//main
void test_thread_creation_and_wait();
//sub
void* thread_test( void *x ); //must match rAthreadProc signature
}
}

View File

@ -101,7 +101,7 @@ sub Main {
CHAR_PORT => "6121",
LOGIN_PORT => "6900",
MD5_ENABLE => "yes",
PINCODE_ENABLE => "no",
PINCODE_ENABLE => "yes",
SQL_HOST => "localhost",
SQL_PORT => "3306",
SQL_UID => "ragnarok",