Skip to content

Commit

Permalink
platform/linux: implement debug timers and cl_maxframetime to catch v…
Browse files Browse the repository at this point in the history
…ery long frames on debugger
  • Loading branch information
mittorn authored and a1batross committed Dec 25, 2023
1 parent a488f79 commit b4a7c26
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 0 deletions.
4 changes: 4 additions & 0 deletions engine/client/cl_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)" );
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions engine/client/cl_view.c
Original file line number Diff line number Diff line change
Expand Up @@ -549,5 +549,6 @@ void V_PostRender( void )

SCR_MakeScreenShot();
ref.dllFuncs.R_AllowFog( true );
Platform_SetTimer( 0.0f );
ref.dllFuncs.R_EndFrame();
}
45 changes: 45 additions & 0 deletions engine/platform/linux/sys_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 );
}
}
8 changes: 8 additions & 0 deletions engine/platform/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,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 )
Expand Down Expand Up @@ -181,6 +182,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
}

/*
==============================================================================
Expand Down

0 comments on commit b4a7c26

Please sign in to comment.