[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