From aa6b36a60fb56965a9d91cc1fd74ac883b8a9cef Mon Sep 17 00:00:00 2001
From: Raphael Defosseux <raphael.defosseux@eurecom.fr>
Date: Tue, 25 May 2021 14:41:30 +0200
Subject: [PATCH] [RHEL8][CONTAINER] Runtime check when creating pThreads

It looks like :
  - when running on a Fedora-host
  - with generic kernel
  - in a container
  - even in privileged mode

That is not enough and priority/schedule settings is not allowed.

So at runtime, we check and in case, we don't set up priorities.

Signed-off-by: Raphael Defosseux <raphael.defosseux@eurecom.fr>
---
 common/utils/system.c        | 86 +++++++++++++++++++++++++++++-------
 common/utils/system.h        |  8 ++++
 targets/RT/USER/lte-ue.c     | 22 ++++++---
 targets/RT/USER/rt_wrapper.c | 49 +++++++++++---------
 4 files changed, 123 insertions(+), 42 deletions(-)

diff --git a/common/utils/system.c b/common/utils/system.c
index 4c6c1a4dc0b..c8de386958a 100644
--- a/common/utils/system.c
+++ b/common/utils/system.c
@@ -96,6 +96,51 @@ static void read_pipe(int p, char *b, int size) {
   }
 }
 
+static int baseRunTimeCommand(char* cmd) {
+  FILE *fp;
+  size_t retSize = 0;
+
+  fp = popen(cmd, "r");
+
+  memset(cmd, 1, 200);
+  retSize = fread(cmd, 1, 200, fp);
+  fclose(fp);
+
+  if (retSize == 0) {
+    return 0;
+  }
+  return atoi(cmd);
+}
+
+int checkIfFedoraDistribution(void) {
+  char cmd[200];
+
+  memset(cmd, 1, 200);
+  sprintf(cmd, "cat /etc/os-release | grep ID_LIKE | grep -ic fedora || true");
+  return baseRunTimeCommand(cmd);
+}
+
+int checkIfGenericKernelOnFedora(void) {
+  char cmd[200];
+
+  memset(cmd, 1, 200);
+  sprintf(cmd, "uname -a | grep -c rt || true");
+  return (1 - baseRunTimeCommand(cmd));
+}
+
+int checkIfInsideContainer(void) {
+  char cmd[200];
+  int res = 0;
+
+  memset(cmd, 1, 200);
+  sprintf(cmd, "cat /proc/self/cgroup | egrep -c 'libpod|podman|kubepods' || true");
+  res = baseRunTimeCommand(cmd);
+  if (res > 0)
+    return 1;
+  else
+    return 0;
+}
+
 /********************************************************************/
 /* background process                                               */
 /********************************************************************/
@@ -200,29 +245,38 @@ void start_background_system(void) {
 void threadCreate(pthread_t* t, void * (*func)(void*), void * param, char* name, int affinity, int priority){
   pthread_attr_t attr;
   int ret;
+  int settingPriority = 1;
   ret=pthread_attr_init(&attr);
   AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno);
   ret=pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
   AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno);
   ret=pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
   AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno);
-  ret=pthread_attr_setschedpolicy(&attr, SCHED_OAI);
-  AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno);
-  if(priority<sched_get_priority_min(SCHED_OAI) || priority>sched_get_priority_max(SCHED_FIFO)) {
-    LOG_E(TMR,"Prio not possible: %d, min is %d, max: %d, forced in the range\n", 
-              priority, 
-              sched_get_priority_min(SCHED_OAI),
-              sched_get_priority_max(SCHED_OAI));
-    if(priority<sched_get_priority_min(SCHED_OAI))
-      priority=sched_get_priority_min(SCHED_OAI);
-    if(priority>sched_get_priority_max(SCHED_OAI))
-      priority=sched_get_priority_max(SCHED_OAI);
+  if (checkIfFedoraDistribution())
+    if (checkIfGenericKernelOnFedora())
+      if (checkIfInsideContainer())
+        settingPriority = 0;
+
+  if (settingPriority) {
+    ret=pthread_attr_setschedpolicy(&attr, SCHED_OAI);
+    AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno);
+    if(priority<sched_get_priority_min(SCHED_OAI) || priority>sched_get_priority_max(SCHED_FIFO)) {
+      LOG_E(TMR,"Prio not possible: %d, min is %d, max: %d, forced in the range\n",
+                priority,
+                sched_get_priority_min(SCHED_OAI),
+                sched_get_priority_max(SCHED_OAI));
+      if(priority<sched_get_priority_min(SCHED_OAI))
+        priority=sched_get_priority_min(SCHED_OAI);
+      if(priority>sched_get_priority_max(SCHED_OAI))
+        priority=sched_get_priority_max(SCHED_OAI);
+    }
+    AssertFatal(priority<=sched_get_priority_max(SCHED_OAI),"");
+    struct sched_param sparam={0};
+    sparam.sched_priority = priority;
+    ret=pthread_attr_setschedparam(&attr, &sparam);
+    AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno);
   }
-  AssertFatal(priority<=sched_get_priority_max(SCHED_OAI),"");
-  struct sched_param sparam={0};
-  sparam.sched_priority = priority;
-  ret=pthread_attr_setschedparam(&attr, &sparam);
-  AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno);
+
   ret=pthread_create(t, &attr, func, param);
   AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno);
 
diff --git a/common/utils/system.h b/common/utils/system.h
index fbfd338a1a7..c76fef9144a 100644
--- a/common/utils/system.h
+++ b/common/utils/system.h
@@ -58,6 +58,14 @@ void thread_top_init(char *thread_name,
                      uint64_t deadline,
                      uint64_t period);
 
+/****************************************************
+ * Functions to check system at runtime.
+ ****************************************************/
+
+int checkIfFedoraDistribution(void);
+int checkIfGenericKernelOnFedora(void);
+int checkIfInsideContainer(void);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c
index cc084d18c5c..6e6c2533b4d 100644
--- a/targets/RT/USER/lte-ue.c
+++ b/targets/RT/USER/lte-ue.c
@@ -32,6 +32,7 @@
 #include "lte-softmodem.h"
 
 #include "rt_wrapper.h"
+#include "system.h"
 
 #include "LAYER2/MAC/mac.h"
 #include "RRC/LTE/rrc_extern.h"
@@ -230,14 +231,23 @@ void init_thread(int sched_runtime,
   }
 
 #else
+  int settingPriority = 1;
 
-  if (CPU_COUNT(cpuset) > 0)
-    AssertFatal( 0 == pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), cpuset), "");
+  if (checkIfFedoraDistribution())
+    if (checkIfGenericKernelOnFedora())
+      if (checkIfInsideContainer())
+        settingPriority = 0;
+
+  if (settingPriority) {
+    if (CPU_COUNT(cpuset) > 0)
+      AssertFatal( 0 == pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), cpuset), "");
+
+    struct sched_param sp;
+    sp.sched_priority = sched_fifo;
+    AssertFatal(pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp)==0,
+                "Can't set thread priority, Are you root?\n");
+  }
 
-  struct sched_param sp;
-  sp.sched_priority = sched_fifo;
-  AssertFatal(pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp)==0,
-              "Can't set thread priority, Are you root?\n");
   /* Check the actual affinity mask assigned to the thread */
   cpu_set_t *cset=CPU_ALLOC(CPU_SETSIZE);
 
diff --git a/targets/RT/USER/rt_wrapper.c b/targets/RT/USER/rt_wrapper.c
index b0518688252..da3a2d3cfe2 100644
--- a/targets/RT/USER/rt_wrapper.c
+++ b/targets/RT/USER/rt_wrapper.c
@@ -43,6 +43,7 @@
 #include <getopt.h>
 #include <sys/sysinfo.h>
 #include "rt_wrapper.h"
+#include "system.h"
 #include <errno.h>
 #include <common/utils/msc/msc.h>
 
@@ -294,6 +295,7 @@ void thread_top_init(char *thread_name,
   struct sched_param sparam;
   char cpu_affinity[1024];
   cpu_set_t cpuset;
+  int settingPriority = 1;
 
   /* Set affinity mask to include CPUs 2 to MAX_CPUS */
   /* CPU 0 is reserved for UHD threads */
@@ -340,30 +342,37 @@ void thread_top_init(char *thread_name,
     }
   }
 
-  memset(&sparam, 0, sizeof(sparam));
-  sparam.sched_priority = sched_get_priority_max(SCHED_FIFO);
-  policy = SCHED_FIFO ; 
+  if (checkIfFedoraDistribution())
+    if (checkIfGenericKernelOnFedora())
+      if (checkIfInsideContainer())
+        settingPriority = 0;
+
+  if (settingPriority) {
+    memset(&sparam, 0, sizeof(sparam));
+    sparam.sched_priority = sched_get_priority_max(SCHED_FIFO);
+    policy = SCHED_FIFO;
   
-  s = pthread_setschedparam(pthread_self(), policy, &sparam);
-  if (s != 0) {
-    perror("pthread_setschedparam : ");
-    exit_fun("Error setting thread priority");
-  }
+    s = pthread_setschedparam(pthread_self(), policy, &sparam);
+    if (s != 0) {
+      perror("pthread_setschedparam : ");
+      exit_fun("Error setting thread priority");
+    }
   
-  s = pthread_getschedparam(pthread_self(), &policy, &sparam);
-  if (s != 0) {
-    perror("pthread_getschedparam : ");
-    exit_fun("Error getting thread priority");
-  }
+    s = pthread_getschedparam(pthread_self(), &policy, &sparam);
+    if (s != 0) {
+      perror("pthread_getschedparam : ");
+      exit_fun("Error getting thread priority");
+    }
 
-  pthread_setname_np(pthread_self(), thread_name);
+    pthread_setname_np(pthread_self(), thread_name);
 
-  LOG_I(HW, "[SCHED][eNB] %s started on CPU %d, sched_policy = %s , priority = %d, CPU Affinity=%s \n",thread_name,sched_getcpu(),
-                   (policy == SCHED_FIFO)  ? "SCHED_FIFO" :
-                   (policy == SCHED_RR)    ? "SCHED_RR" :
-                   (policy == SCHED_OTHER) ? "SCHED_OTHER" :
-                   "???",
-                   sparam.sched_priority, cpu_affinity );
+    LOG_I(HW, "[SCHED][eNB] %s started on CPU %d, sched_policy = %s , priority = %d, CPU Affinity=%s \n",thread_name,sched_getcpu(),
+                     (policy == SCHED_FIFO)  ? "SCHED_FIFO" :
+                     (policy == SCHED_RR)    ? "SCHED_RR" :
+                     (policy == SCHED_OTHER) ? "SCHED_OTHER" :
+                     "???",
+                     sparam.sched_priority, cpu_affinity );
+  }
 
 #endif //LOW_LATENCY
 
-- 
GitLab