~a1batross/xash3d-fwgs

platform/linux: implement debug timers and cl_maxframetime to catch very long frames on debugger v1 APPLIED

mittorn: 1
 platform/linux: implement debug timers and cl_maxframetime to catch very long frames on debugger

 4 files changed, 58 insertions(+), 0 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~a1batross/xash3d-fwgs/patches/47999/mbox | git am -3
Learn more about email & git

[PATCH] platform/linux: implement debug timers and cl_maxframetime to catch very long frames on debugger Export this patch

---
 engine/client/cl_main.c           |  4 +++
 engine/client/cl_view.c           |  1 +
 engine/platform/linux/sys_linux.c | 45 +++++++++++++++++++++++++++++++
 engine/platform/platform.h        |  8 ++++++
 4 files changed, 58 insertions(+)

diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c
index 182a8354..8950f9bf 100644
--- a/engine/client/cl_main.c
+++ b/engine/client/cl_main.c
@@ -87,6 +87,7 @@ static CVAR_DEFINE_AUTO( model, "", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABL
static CVAR_DEFINE_AUTO( topcolor, "0", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player top color" );
static CVAR_DEFINE_AUTO( bottomcolor, "0", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player bottom color" );
CVAR_DEFINE_AUTO( rate, "3500", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player network rate" );
static CVAR_DEFINE_AUTO( cl_maxframetime, "0", 0, "set deadline timer for client rendering to catch freezes" );

client_t		cl;
client_static_t	cls;
@@ -2917,6 +2918,7 @@ void CL_InitLocal( void )
	Cvar_RegisterVariable( &cl_showevents );
	Cvar_Get( "lastdemo", "", FCVAR_ARCHIVE, "last played demo" );
	Cvar_RegisterVariable( &ui_renderworld );
	Cvar_RegisterVariable( &cl_maxframetime );

	// these two added to shut up CS 1.5 about 'unknown' commands
	Cvar_Get( "lightgamma", "1", FCVAR_ARCHIVE, "ambient lighting level (legacy, unused)" );
@@ -3057,6 +3059,8 @@ void Host_ClientFrame( void )
{
	// if client is not active, do nothing
	if( !cls.initialized ) return;
	if( cls.key_dest == key_game && cls.state == ca_active && !Con_Visible() )
		Platform_SetTimer( cl_maxframetime.value );

	// if running the server remotely, send intentions now after
	// the incoming messages have been read
diff --git a/engine/client/cl_view.c b/engine/client/cl_view.c
index 477b5be4..f3fa4ca3 100644
--- a/engine/client/cl_view.c
+++ b/engine/client/cl_view.c
@@ -549,5 +549,6 @@ void V_PostRender( void )

	SCR_MakeScreenShot();
	ref.dllFuncs.R_AllowFog( true );
	Platform_SetTimer( 0.0f );
	ref.dllFuncs.R_EndFrame();
}
diff --git a/engine/platform/linux/sys_linux.c b/engine/platform/linux/sys_linux.c
index 0734dbc3..860cd7d4 100644
--- a/engine/platform/linux/sys_linux.c
+++ b/engine/platform/linux/sys_linux.c
@@ -17,6 +17,10 @@ GNU General Public License for more details.
#include <stdlib.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <signal.h>
#include <ucontext.h>
#include <time.h>
#include <unistd.h>
#include "platform/platform.h"

static void *g_hsystemd;
@@ -103,3 +107,44 @@ void Linux_Shutdown( void )
		g_hsystemd = NULL;
	}
}

static void Linux_TimerHandler( int sig, siginfo_t *si, void *uc )
{
	timer_t  *tidp = si->si_value.sival_ptr;
	int overrun = timer_getoverrun( *tidp );
	Con_Printf( "Frame too long (overrun %d)!\n", overrun );
}

#define DEBUG_TIMER_SIGNAL SIGRTMIN

void Linux_SetTimer( float tm )
{
	static timer_t timerid;

	if( !timerid && tm )
	{
		struct sigevent    sev = { 0 };
		struct sigaction   sa = { 0 };

		sa.sa_flags = SA_SIGINFO;
		sa.sa_sigaction = Linux_TimerHandler;
		sigaction( DEBUG_TIMER_SIGNAL, &sa, NULL );
		// this path availiable in POSIX, but may signal wrong thread...
		// sev.sigev_notify = SIGEV_SIGNAL;
		sev.sigev_notify = SIGEV_THREAD_ID;
		sev._sigev_un._tid  = gettid();
		sev.sigev_signo = DEBUG_TIMER_SIGNAL;
		sev.sigev_value.sival_ptr = &timerid;
		timer_create( CLOCK_REALTIME, &sev, &timerid );
	}

	if( timerid )
	{
		struct itimerspec  its = {0};
		its.it_value.tv_sec = tm;
		its.it_value.tv_nsec = 1000000000ULL * fmod( tm, 1.0f );
		its.it_interval.tv_sec = 0;
		its.it_interval.tv_nsec = 0;
		timer_settime( timerid, 0, &its, NULL );
	}
}
diff --git a/engine/platform/platform.h b/engine/platform/platform.h
index 44415512..dd5379f7 100644
--- a/engine/platform/platform.h
+++ b/engine/platform/platform.h
@@ -93,6 +93,7 @@ void DOS_Shutdown( void );
#if XASH_LINUX
void Linux_Init( void );
void Linux_Shutdown( void );
void Linux_SetTimer( float time );
#endif

static inline void Platform_Init( void )
@@ -185,6 +186,13 @@ void Platform_SetClipboardText( const char *buffer );
#define SDL_VERSION_ATLEAST( x, y, z ) 0
#endif

static void Platform_SetTimer( float time )
{
#if XASH_LINUX
	Linux_SetTimer( time );
#endif
}

/*
==============================================================================

-- 
2.39.2