From 34964d5660d2c81ddbd9fa7659277e4944f972ce Mon Sep 17 00:00:00 2001
From: divverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Date: Wed, 26 Oct 2011 09:07:21 +0000
Subject: [PATCH] Linux dedicated server: set nice -19 while spawning server
 (can be turned off by -nonice option)

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@11479 d7cf8633-e32d-0410-b094-e92efae38249
---
 host.c       |  6 +++++
 sv_main.c    | 11 +++++++++
 sys.h        |  5 ++++
 sys_shared.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 89 insertions(+)

diff --git a/host.c b/host.c
index 85c07db6..ff250373 100644
--- a/host.c
+++ b/host.c
@@ -94,6 +94,9 @@ aborts the current host frame and goes on with the next one
 */
 void Host_AbortCurrentFrame(void)
 {
+	// in case we were previously nice, make us mean again
+	Sys_MakeProcessMean();
+
 	longjmp (host_abortframe, 1);
 }
 
@@ -1161,6 +1164,9 @@ static void Host_Init (void)
 	dpsnprintf (engineversion, sizeof (engineversion), "%s %s %s", gamename, os, buildstring);
 	Con_Printf("%s\n", engineversion);
 
+	// initialize process nice level
+	Sys_InitProcessNice();
+
 	// initialize ixtable
 	Mathlib_Init();
 
diff --git a/sv_main.c b/sv_main.c
index c99273b1..f36bfe13 100644
--- a/sv_main.c
+++ b/sv_main.c
@@ -3231,6 +3231,9 @@ void SV_SpawnServer (const char *server)
 
 //	SV_LockThreadMutex();
 
+	if(cls.state == ca_dedicated)
+		Sys_MakeProcessNice();
+
 	if (cls.state != ca_dedicated)
 	{
 		SCR_BeginLoadingPlaque();
@@ -3256,7 +3259,12 @@ void SV_SpawnServer (const char *server)
 	if (!worldmodel || !worldmodel->TraceBox)
 	{
 		Con_Printf("Couldn't load map %s\n", modelname);
+
+		if(cls.state == ca_dedicated)
+			Sys_MakeProcessMean();
+
 //		SV_UnlockThreadMutex();
+
 		return;
 	}
 
@@ -3498,6 +3506,9 @@ void SV_SpawnServer (const char *server)
 	Con_DPrint("Server spawned.\n");
 	NetConn_Heartbeat (2);
 
+	if(cls.state == ca_dedicated)
+		Sys_MakeProcessMean();
+
 //	SV_UnlockThreadMutex();
 }
 
diff --git a/sys.h b/sys.h
index 913b3cdb..628c5d61 100644
--- a/sys.h
+++ b/sys.h
@@ -110,5 +110,10 @@ extern qboolean sys_supportsdlgetticks;
 unsigned int Sys_SDL_GetTicks (void); // wrapper to call SDL_GetTicks
 void Sys_SDL_Delay (unsigned int milliseconds); // wrapper to call SDL_Delay
 
+/// called to set process priority for dedicated servers
+void Sys_InitProcessNice (void);
+void Sys_MakeProcessNice (void);
+void Sys_MakeProcessMean (void);
+
 #endif
 
diff --git a/sys_shared.c b/sys_shared.c
index cb826f17..bcbc727d 100644
--- a/sys_shared.c
+++ b/sys_shared.c
@@ -561,3 +561,70 @@ qboolean Sys_HaveSSE2(void)
 	return false;
 }
 #endif
+
+/// called to set process priority for dedicated servers
+#if defined(__linux__)
+#include <sys/resource.h>
+#include <errno.h>
+static int nicelevel;
+static qboolean nicepossible;
+static qboolean isnice;
+void Sys_InitProcessNice (void)
+{
+	struct rlimit lim;
+	nicepossible = false;
+	if(COM_CheckParm("-nonice"))
+		return;
+	errno = 0;
+	nicelevel = getpriority(PRIO_PROCESS, 0);
+	if(errno)
+	{
+		Con_Printf("Kernel does not support reading process priority - cannot use niceness\n");
+		return;
+	}
+	if(getrlimit(RLIMIT_NICE, &lim))
+	{
+		Con_Printf("Kernel does not support lowering nice level again - cannot use niceness\n");
+		return;
+	}
+	if(lim.rlim_cur != RLIM_INFINITY && nicelevel < (int) (20 - lim.rlim_cur))
+	{
+		Con_Printf("Current nice level is below the soft limit - cannot use niceness\n");
+		return;
+	}
+	nicepossible = true;
+	isnice = false;
+}
+void Sys_MakeProcessNice (void)
+{
+	if(!nicepossible)
+		return;
+	if(isnice)
+		return;
+	Con_DPrintf("Process is becoming 'nice'...\n");
+	if(setpriority(PRIO_PROCESS, 0, 19))
+		Con_Printf("Failed to raise nice level to %d\n", 19);
+	isnice = true;
+}
+void Sys_MakeProcessMean (void)
+{
+	if(!nicepossible)
+		return;
+	if(!isnice)
+		return;
+	Con_DPrintf("Process is becoming 'mean'...\n");
+	if(setpriority(PRIO_PROCESS, 0, nicelevel))
+		Con_Printf("Failed to lower nice level to %d\n", nicelevel);
+	isnice = false;
+}
+#else
+void Sys_InitProcessNice (void)
+{
+}
+void Sys_MakeProcessNice (void)
+{
+}
+void Sys_MakeProcessMean (void)
+{
+}
+#endif
-- 
2.39.5