From ca9d3d8cbc29233c21894c46cd1ad9e49313d395 Mon Sep 17 00:00:00 2001 From: bones_was_here Date: Sun, 25 Aug 2024 04:22:08 +1000 Subject: [PATCH] sys: make TimeString thread-safe Also avoids copying to an intermediate buffer in the warmer paths. Signed-off-by: bones_was_here --- cl_demo.c | 3 ++- cl_main.c | 5 ++++- cl_parse.c | 3 ++- cl_screen.c | 15 ++++++++++----- console.c | 6 ++---- sbar.c | 4 ++-- sv_main.c | 5 ++++- sys.h | 2 +- sys_shared.c | 13 ++++++++----- 9 files changed, 35 insertions(+), 21 deletions(-) diff --git a/cl_demo.c b/cl_demo.c index a2ee5f92..0f42a7d0 100644 --- a/cl_demo.c +++ b/cl_demo.c @@ -520,7 +520,8 @@ static void CL_FinishTimeDemo (void) fpsmax = cls.td_onesecondmaxfps; // LadyHavoc: timedemo now prints out 7 digits of fraction, and min/avg/max Con_Printf("%i frames %5.7f seconds %5.7f fps, one-second fps min/avg/max: %.0f %.0f %.0f (%i seconds)\n", frames, time, totalfpsavg, fpsmin, fpsavg, fpsmax, cls.td_onesecondavgcount); - Log_Printf("benchmark.log", "date %s | enginedate %s | demo %s | commandline %s | run %d | result %i frames %5.7f seconds %5.7f fps, one-second fps min/avg/max: %.0f %.0f %.0f (%i seconds)\n", Sys_TimeString("%Y-%m-%d %H:%M:%S"), engineversion, cls.demoname, cmdline.string, benchmark_runs + 1, frames, time, totalfpsavg, fpsmin, fpsavg, fpsmax, cls.td_onesecondavgcount); + Sys_TimeString(vabuf, sizeof(vabuf), "%Y-%m-%d %H:%M:%S"); + Log_Printf("benchmark.log", "date %s | enginedate %s | demo %s | commandline %s | run %d | result %i frames %5.7f seconds %5.7f fps, one-second fps min/avg/max: %.0f %.0f %.0f (%i seconds)\n", vabuf, engineversion, cls.demoname, cmdline.string, benchmark_runs + 1, frames, time, totalfpsavg, fpsmin, fpsavg, fpsmax, cls.td_onesecondavgcount); if (Sys_CheckParm("-benchmark")) { ++benchmark_runs; diff --git a/cl_main.c b/cl_main.c index 71443f14..17921410 100644 --- a/cl_main.c +++ b/cl_main.c @@ -2310,6 +2310,8 @@ static void CL_Locs_Save_f(cmd_state_t *cmd) cl_locnode_t *loc; qfile_t *outfile; char locfilename[MAX_QPATH]; + char timestring[128]; + if (!cl.locnodes) { Con_Printf("No loc points/boxes exist!\n"); @@ -2332,7 +2334,8 @@ static void CL_Locs_Save_f(cmd_state_t *cmd) break; if (loc) { - FS_Printf(outfile, "// %s %s saved by %s\n// x,y,z,x,y,z,\"name\"\n\n", locfilename, Sys_TimeString("%Y-%m-%d"), engineversion); + Sys_TimeString(timestring, sizeof(timestring), "%Y-%m-%d"); + FS_Printf(outfile, "// %s %s saved by %s\n// x,y,z,x,y,z,\"name\"\n\n", locfilename, timestring, engineversion); for (loc = cl.locnodes;loc;loc = loc->next) if (VectorCompare(loc->mins, loc->maxs)) break; diff --git a/cl_parse.c b/cl_parse.c index b5d0cd4f..30c455f5 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -1930,7 +1930,8 @@ static void CL_ParseServerInfo (void) } // start a new demo file - dpsnprintf (demofile, sizeof(demofile), "%s_%s.dem", Sys_TimeString (cl_autodemo_nameformat.string), cl.worldbasename); + Sys_TimeString(vabuf, sizeof(vabuf), cl_autodemo_nameformat.string); + dpsnprintf (demofile, sizeof(demofile), "%s_%s.dem", vabuf, cl.worldbasename); Con_Printf ("Auto-recording to %s.\n", demofile); diff --git a/cl_screen.c b/cl_screen.c index 7604fda6..bf4c3d19 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -959,10 +959,11 @@ void SCR_ScreenShot_f(cmd_state_t *cmd) int shotnumber100; // TODO maybe make capturevideo and screenshot use similar name patterns? + Sys_TimeString(vabuf, sizeof(vabuf), "%Y%m%d%H%M%S"); if (scr_screenshot_name_in_mapdir.integer && cl.worldbasename[0]) - dpsnprintf(prefix_name, sizeof(prefix_name), "%s/%s%s", cl.worldbasename, scr_screenshot_name.string, Sys_TimeString("%Y%m%d%H%M%S")); + dpsnprintf(prefix_name, sizeof(prefix_name), "%s/%s%s", cl.worldbasename, scr_screenshot_name.string, vabuf); else - dpsnprintf(prefix_name, sizeof(prefix_name), "%s%s", scr_screenshot_name.string, Sys_TimeString("%Y%m%d%H%M%S")); + dpsnprintf(prefix_name, sizeof(prefix_name), "%s%s", scr_screenshot_name.string, vabuf); // find a file name to save it to for (shotnumber100 = 0;shotnumber100 < 100;shotnumber100++) @@ -981,10 +982,11 @@ void SCR_ScreenShot_f(cmd_state_t *cmd) else { // TODO maybe make capturevideo and screenshot use similar name patterns? + Sys_TimeString(vabuf, sizeof(vabuf), scr_screenshot_name.string); if (scr_screenshot_name_in_mapdir.integer && cl.worldbasename[0]) - dpsnprintf(prefix_name, sizeof(prefix_name), "%s/%s", cl.worldbasename, Sys_TimeString(scr_screenshot_name.string)); + dpsnprintf(prefix_name, sizeof(prefix_name), "%s/%s", cl.worldbasename, vabuf); else - dpsnprintf(prefix_name, sizeof(prefix_name), "%s", Sys_TimeString(scr_screenshot_name.string)); + dpsnprintf(prefix_name, sizeof(prefix_name), "%s", vabuf); // if prefix changed, gamedir or map changed, reset the shotnumber so // we scan again @@ -1040,6 +1042,8 @@ static void SCR_CaptureVideo_BeginVideo(void) double r, g, b; unsigned int i; int width = cl_capturevideo_width.integer, height = cl_capturevideo_height.integer; + char timestring[128]; + if (cls.capturevideo.active) return; memset(&cls.capturevideo, 0, sizeof(cls.capturevideo)); @@ -1075,7 +1079,8 @@ static void SCR_CaptureVideo_BeginVideo(void) cls.capturevideo.realtime = cl_capturevideo_realtime.integer != 0; cls.capturevideo.screenbuffer = (unsigned char *)Mem_Alloc(tempmempool, vid.mode.width * vid.mode.height * 4); cls.capturevideo.outbuffer = (unsigned char *)Mem_Alloc(tempmempool, width * height * (4+4) + 18); - dpsnprintf(cls.capturevideo.basename, sizeof(cls.capturevideo.basename), "video/%s%03i", Sys_TimeString(cl_capturevideo_nameformat.string), cl_capturevideo_number.integer); + Sys_TimeString(timestring, sizeof(timestring), cl_capturevideo_nameformat.string); + dpsnprintf(cls.capturevideo.basename, sizeof(cls.capturevideo.basename), "video/%s%03i", timestring, cl_capturevideo_number.integer); Cvar_SetValueQuick(&cl_capturevideo_number, cl_capturevideo_number.integer + 1); /* diff --git a/console.c b/console.c index c1c3f2f1..f46eddb5 100644 --- a/console.c +++ b/console.c @@ -1166,7 +1166,6 @@ void Con_MaskPrint(unsigned additionalmask, const char *msg) // if this is the beginning of a new line, print timestamp if (index == 0) { - const char *timestamp = timestamps.integer ? Sys_TimeString(timeformat.string) : ""; // reset the color // FIXME: 1. perhaps we should use a terminal system 2. use a constant instead of 7! line[index++] = STRING_COLOR_TAG; @@ -1198,9 +1197,8 @@ void Con_MaskPrint(unsigned additionalmask, const char *msg) Con_Rcon_AddChar(*msg); } // store timestamp - for (;*timestamp;index++, timestamp++) - if (index < (int)sizeof(line) - 2) - line[index] = *timestamp; + if (timestamps.integer) + index += Sys_TimeString(&line[index], sizeof(line) - index, timeformat.string); // add the mask mask |= additionalmask; } diff --git a/sbar.c b/sbar.c index 43b64b9e..8c0f0cf5 100644 --- a/sbar.c +++ b/sbar.c @@ -1142,12 +1142,12 @@ void Sbar_ShowFPS(void) } if (cl_showtime.integer) { - dp_strlcpy(timestring, Sys_TimeString(cl_showtime_format.string), sizeof(timestring)); + Sys_TimeString(timestring, sizeof(timestring), cl_showtime_format.string); fps_strings++; } if (cl_showdate.integer) { - dp_strlcpy(datestring, Sys_TimeString(cl_showdate_format.string), sizeof(datestring)); + Sys_TimeString(datestring, sizeof(datestring), cl_showdate_format.string); fps_strings++; } if (cl_showblur.integer) diff --git a/sv_main.c b/sv_main.c index 7d5c45ad..7778f117 100644 --- a/sv_main.c +++ b/sv_main.c @@ -812,6 +812,7 @@ void SV_SendServerinfo (client_t *client) { char demofile[MAX_OSPATH]; char ipaddress[MAX_QPATH]; + char timestring[128]; size_t j; // start a new demo file @@ -819,7 +820,9 @@ void SV_SendServerinfo (client_t *client) for(j = 0; ipaddress[j]; ++j) if(!isalnum(ipaddress[j])) ipaddress[j] = '-'; - dpsnprintf (demofile, sizeof(demofile), "%s_%s_%d_%s.dem", Sys_TimeString (sv_autodemo_perclient_nameformat.string), sv.worldbasename, PRVM_NUM_FOR_EDICT(client->edict), ipaddress); + Sys_TimeString(timestring, sizeof(timestring), sv_autodemo_perclient_nameformat.string); + dpsnprintf(demofile, sizeof(demofile), "%s_%s_%d_%s.dem", timestring, + sv.worldbasename, PRVM_NUM_FOR_EDICT(client->edict), ipaddress); SV_StartDemoRecording(client, demofile, -1); } diff --git a/sys.h b/sys.h index c2f238e2..4c46754f 100644 --- a/sys.h +++ b/sys.h @@ -202,7 +202,7 @@ void Sys_Init_Commands (void); /// \returns current timestamp -char *Sys_TimeString(const char *timeformat); +size_t Sys_TimeString(char buf[], size_t bufsize, const char *timeformat); // // system IO interface (these are the sys functions that need to be implemented in a new driver atm) diff --git a/sys_shared.c b/sys_shared.c index 0d6cf410..ddf905df 100644 --- a/sys_shared.c +++ b/sys_shared.c @@ -41,18 +41,21 @@ sys_t sys; -static char sys_timestring[128]; -char *Sys_TimeString(const char *timeformat) + +size_t Sys_TimeString(char buf[], size_t bufsize, const char *timeformat) { time_t mytime = time(NULL); + size_t strlen; #if _MSC_VER >= 1400 struct tm mytm; localtime_s(&mytm, &mytime); - strftime(sys_timestring, sizeof(sys_timestring), timeformat, &mytm); + strlen = strftime(buf, bufsize, timeformat, &mytm); #else - strftime(sys_timestring, sizeof(sys_timestring), timeformat, localtime(&mytime)); + strlen = strftime(buf, bufsize, timeformat, localtime(&mytime)); #endif - return sys_timestring; + if (!strlen) // means the array contents are undefined (but it's not always an error) + buf[0] = '\0'; // better fix it + return strlen; } -- 2.39.2