<p>pespin has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/libosmocore/+/19442">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">WIP: vty: Introduce support to set cpu-affinity and scheduler policy<br><br>Process willing to support this kind of configuration through VTY simply<br>need to call "osmo_sched_vty_init(tall_ctx);" during startup to register<br>the commands.<br>For multithreaded processes, new threads willing to get their<br>cpu-affinity mask according to VTY config should call<br>osmo_sched_vty_apply_localthread() (potentially after<br>setting the thread name through pthread_setname_np()).<br><br>Related: SYS#4986<br>Change-Id: If76a4bd2cc7b3c7adf5d84790a944d78be70e10a<br>---<br>M include/Makefile.am<br>M include/osmocom/vty/command.h<br>A include/osmocom/vty/sched_vty.h<br>M src/vty/Makefile.am<br>A src/vty/sched_vty.c<br>5 files changed, 600 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/42/19442/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/Makefile.am b/include/Makefile.am</span><br><span>index 7af7e01..097f34d 100644</span><br><span>--- a/include/Makefile.am</span><br><span>+++ b/include/Makefile.am</span><br><span>@@ -164,6 +164,7 @@</span><br><span>                           osmocom/vty/vector.h \</span><br><span>                           osmocom/vty/vty.h \</span><br><span>                           osmocom/vty/ports.h \</span><br><span style="color: hsl(120, 100%, 40%);">+                          osmocom/vty/sched_vty.h \</span><br><span>                           osmocom/vty/tdef_vty.h \</span><br><span>                           osmocom/ctrl/control_vty.h</span><br><span> endif</span><br><span>diff --git a/include/osmocom/vty/command.h b/include/osmocom/vty/command.h</span><br><span>index 29206ce..338400f 100644</span><br><span>--- a/include/osmocom/vty/command.h</span><br><span>+++ b/include/osmocom/vty/command.h</span><br><span>@@ -97,6 +97,7 @@</span><br><span>         L_CS7_SCCPADDR_NODE,    /*!< SS7 SCCP Address */</span><br><span>  L_CS7_SCCPADDR_GT_NODE, /*!< SS7 SCCP Global Title */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+  L_SCHED_NODE,           /*!< CPU Sched related options node */</span><br><span>    /*</span><br><span>    * When adding new nodes to the libosmocore project, these nodes can be</span><br><span>       * used to avoid ABI changes for unrelated projects.</span><br><span>diff --git a/include/osmocom/vty/sched_vty.h b/include/osmocom/vty/sched_vty.h</span><br><span>new file mode 100644</span><br><span>index 0000000..6de2914</span><br><span>--- /dev/null</span><br><span>+++ b/include/osmocom/vty/sched_vty.h</span><br><span>@@ -0,0 +1,37 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \file sched_vty.h</span><br><span style="color: hsl(120, 100%, 40%);">+ * API to CPU / Threading / Scheduler properties from VTY configuration.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+/* (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Author: Pau Espin Pedrol <pespin@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: GPL-2.0+</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/vty/command.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \defgroup sched_VTY Configuration</span><br><span style="color: hsl(120, 100%, 40%);">+ * @{</span><br><span style="color: hsl(120, 100%, 40%);">+ * \file sched_vty.h</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_sched_vty_init(void *tall_ctx);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_sched_vty_apply_localthread(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! @} */</span><br><span>diff --git a/src/vty/Makefile.am b/src/vty/Makefile.am</span><br><span>index 35350cc..5527449 100644</span><br><span>--- a/src/vty/Makefile.am</span><br><span>+++ b/src/vty/Makefile.am</span><br><span>@@ -12,7 +12,7 @@</span><br><span> libosmovty_la_SOURCES = buffer.c command.c vty.c vector.c utils.c \</span><br><span>                    telnet_interface.c logging_vty.c stats_vty.c \</span><br><span>                       fsm_vty.c talloc_ctx_vty.c \</span><br><span style="color: hsl(0, 100%, 40%);">-                    tdef_vty.c</span><br><span style="color: hsl(120, 100%, 40%);">+                    sched_vty.c tdef_vty.c</span><br><span> libosmovty_la_LDFLAGS = -version-info $(LIBVERSION) -no-undefined</span><br><span> libosmovty_la_LIBADD = $(top_builddir)/src/libosmocore.la $(TALLOC_LIBS)</span><br><span> endif</span><br><span>diff --git a/src/vty/sched_vty.c b/src/vty/sched_vty.c</span><br><span>new file mode 100644</span><br><span>index 0000000..54d7f2a</span><br><span>--- /dev/null</span><br><span>+++ b/src/vty/sched_vty.c</span><br><span>@@ -0,0 +1,560 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \file sched_vty.c</span><br><span style="color: hsl(120, 100%, 40%);">+ * Implementation to CPU / Threading / Scheduler properties from VTY configuration.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+/* (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Author: Pau Espin Pedrol <pespin@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: GPLv2+</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define _GNU_SOURCE</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <limits.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <unistd.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <sched.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <ctype.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/types.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/stat.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <fcntl.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <dirent.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <pthread.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <inttypes.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/vty/vty.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/vty/command.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/vty/tdef_vty.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/tdef.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/fsm.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/linuxlist.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \addtogroup Tdef_VTY</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * CPU Scheduling related VTY API.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @{</span><br><span style="color: hsl(120, 100%, 40%);">+ * \file sched_vty.c</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum sched_vty_thread_id {</span><br><span style="color: hsl(120, 100%, 40%);">+        SCHED_VTY_THREAD_SELF,</span><br><span style="color: hsl(120, 100%, 40%);">+        SCHED_VTY_THREAD_ALL,</span><br><span style="color: hsl(120, 100%, 40%);">+ SCHED_VTY_THREAD_ID,</span><br><span style="color: hsl(120, 100%, 40%);">+  SCHED_VTY_THREAD_NAME,</span><br><span style="color: hsl(120, 100%, 40%);">+        SCHED_VTY_THREAD_UNKNOWN,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct cpu_affinity_it {</span><br><span style="color: hsl(120, 100%, 40%);">+     struct llist_head entry;</span><br><span style="color: hsl(120, 100%, 40%);">+      enum sched_vty_thread_id tid_type;</span><br><span style="color: hsl(120, 100%, 40%);">+    char bufname[64];</span><br><span style="color: hsl(120, 100%, 40%);">+     unsigned long mask;</span><br><span style="color: hsl(120, 100%, 40%);">+   bool delay;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct sched_vty_opts {</span><br><span style="color: hsl(120, 100%, 40%);">+    void *tall_ctx;</span><br><span style="color: hsl(120, 100%, 40%);">+       int sched_rr_prio;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct llist_head cpu_affinity_li;</span><br><span style="color: hsl(120, 100%, 40%);">+    pthread_mutex_t cpu_affinity_li_mutex;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct sched_vty_opts *sched_vty_opts;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct cmd_node sched_node = {</span><br><span style="color: hsl(120, 100%, 40%);">+        L_SCHED_NODE,</span><br><span style="color: hsl(120, 100%, 40%);">+ "%s(config-sched)# ",</span><br><span style="color: hsl(120, 100%, 40%);">+       1,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static bool proc_tid_exists(pid_t tid)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   DIR *proc_dir;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct dirent *entry;</span><br><span style="color: hsl(120, 100%, 40%);">+ char dirname[100];</span><br><span style="color: hsl(120, 100%, 40%);">+    int tid_it;</span><br><span style="color: hsl(120, 100%, 40%);">+   bool found = false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(dirname, sizeof(dirname), "/proc/%ld/task", (long int)getpid());</span><br><span style="color: hsl(120, 100%, 40%);">+   proc_dir = opendir(dirname);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!proc_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+                return false; /*FIXME; print error */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       while ((entry = readdir(proc_dir)))</span><br><span style="color: hsl(120, 100%, 40%);">+   {</span><br><span style="color: hsl(120, 100%, 40%);">+             if(entry->d_name[0] == '.')</span><br><span style="color: hsl(120, 100%, 40%);">+                        continue;</span><br><span style="color: hsl(120, 100%, 40%);">+             tid_it = atoi(entry->d_name);</span><br><span style="color: hsl(120, 100%, 40%);">+              if (tid_it == tid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  found = true;</span><br><span style="color: hsl(120, 100%, 40%);">+                 break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   closedir(proc_dir);</span><br><span style="color: hsl(120, 100%, 40%);">+   return found;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static bool proc_name_exists(const char *name, pid_t *res_pid)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ DIR *proc_dir;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct dirent *entry;</span><br><span style="color: hsl(120, 100%, 40%);">+ char path[100];</span><br><span style="color: hsl(120, 100%, 40%);">+       char buf[17]; /* 15 + \n + \0 */</span><br><span style="color: hsl(120, 100%, 40%);">+      int tid_it;</span><br><span style="color: hsl(120, 100%, 40%);">+   int fd;</span><br><span style="color: hsl(120, 100%, 40%);">+       pid_t mypid = getpid();</span><br><span style="color: hsl(120, 100%, 40%);">+       bool found = false;</span><br><span style="color: hsl(120, 100%, 40%);">+   int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     *res_pid = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       snprintf(path, sizeof(path), "/proc/%ld/task", (long int)mypid);</span><br><span style="color: hsl(120, 100%, 40%);">+    proc_dir = opendir(path);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!proc_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+                return false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       while ((entry = readdir(proc_dir)))</span><br><span style="color: hsl(120, 100%, 40%);">+   {</span><br><span style="color: hsl(120, 100%, 40%);">+             if(entry->d_name[0] == '.')</span><br><span style="color: hsl(120, 100%, 40%);">+                        continue;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           tid_it = atoi(entry->d_name);</span><br><span style="color: hsl(120, 100%, 40%);">+              snprintf(path, sizeof(path), "/proc/%ld/task/%ld/comm", (long int)mypid, (long int) tid_it);</span><br><span style="color: hsl(120, 100%, 40%);">+                if ((fd = open(path, O_RDONLY)) == -1)</span><br><span style="color: hsl(120, 100%, 40%);">+                        continue;</span><br><span style="color: hsl(120, 100%, 40%);">+             rc = read(fd, buf, sizeof(buf));</span><br><span style="color: hsl(120, 100%, 40%);">+              if (rc >= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     /* Last char contain a '\n', get rid of it */</span><br><span style="color: hsl(120, 100%, 40%);">+                 buf[rc-1] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+                     buf[rc] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+                       if (strcmp(name, buf) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         *res_pid = tid_it;</span><br><span style="color: hsl(120, 100%, 40%);">+                            found = true;</span><br><span style="color: hsl(120, 100%, 40%);">+                 }</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+             close(fd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          if (found)</span><br><span style="color: hsl(120, 100%, 40%);">+                    break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   closedir(proc_dir);</span><br><span style="color: hsl(120, 100%, 40%);">+   return found;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static enum sched_vty_thread_id procname2pid(pid_t *res_pid, const char *str, bool applynow)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   size_t i, len;</span><br><span style="color: hsl(120, 100%, 40%);">+        char *end;</span><br><span style="color: hsl(120, 100%, 40%);">+    bool is_pid = true;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strcmp(str, "all") == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              *res_pid = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+         return SCHED_VTY_THREAD_ALL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (strcmp(str, "self") == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+             *res_pid = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+         return SCHED_VTY_THREAD_SELF;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   len = strlen(str);</span><br><span style="color: hsl(120, 100%, 40%);">+    for (i = 0; i < len; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                if (!isdigit(str[i])) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       is_pid = false;</span><br><span style="color: hsl(120, 100%, 40%);">+                       break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (is_pid) {</span><br><span style="color: hsl(120, 100%, 40%);">+         errno = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+            *res_pid = strtoul(str, &end, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+         if ((errno == ERANGE && *res_pid == ULONG_MAX) || (errno && !*res_pid) ||</span><br><span style="color: hsl(120, 100%, 40%);">+                 str == end) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     return SCHED_VTY_THREAD_UNKNOWN;</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+             if (!applynow || proc_tid_exists(*res_pid))</span><br><span style="color: hsl(120, 100%, 40%);">+                   return SCHED_VTY_THREAD_ID;</span><br><span style="color: hsl(120, 100%, 40%);">+           else</span><br><span style="color: hsl(120, 100%, 40%);">+                  return SCHED_VTY_THREAD_UNKNOWN;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (len > 15) {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* Thread names only allow up to 15+1 null chars, see man pthread_setname_np */</span><br><span style="color: hsl(120, 100%, 40%);">+               return SCHED_VTY_THREAD_UNKNOWN;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (applynow) {</span><br><span style="color: hsl(120, 100%, 40%);">+               if (proc_name_exists(str, res_pid))</span><br><span style="color: hsl(120, 100%, 40%);">+                   return SCHED_VTY_THREAD_NAME;</span><br><span style="color: hsl(120, 100%, 40%);">+         else</span><br><span style="color: hsl(120, 100%, 40%);">+                  return SCHED_VTY_THREAD_UNKNOWN;</span><br><span style="color: hsl(120, 100%, 40%);">+      } else  {</span><br><span style="color: hsl(120, 100%, 40%);">+             /* assume a thread will be named after it */</span><br><span style="color: hsl(120, 100%, 40%);">+          *res_pid = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+         return SCHED_VTY_THREAD_NAME;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int my_sched_setaffinity(enum sched_vty_thread_id tid_type, pid_t pid, unsigned long mask)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ DIR *proc_dir;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct dirent *entry;</span><br><span style="color: hsl(120, 100%, 40%);">+ char dirname[100];</span><br><span style="color: hsl(120, 100%, 40%);">+    int tid_it;</span><br><span style="color: hsl(120, 100%, 40%);">+   int rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   unsigned long mask_tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+       cpu_set_t *cpuset;</span><br><span style="color: hsl(120, 100%, 40%);">+    size_t cpuset_size;</span><br><span style="color: hsl(120, 100%, 40%);">+   unsigned int cpu_i = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     cpuset = CPU_ALLOC(64);</span><br><span style="color: hsl(120, 100%, 40%);">+       cpuset_size = CPU_ALLOC_SIZE(64);</span><br><span style="color: hsl(120, 100%, 40%);">+     CPU_ZERO_S(cpuset_size, cpuset);</span><br><span style="color: hsl(120, 100%, 40%);">+      mask_tmp = mask;</span><br><span style="color: hsl(120, 100%, 40%);">+      while (mask_tmp) {</span><br><span style="color: hsl(120, 100%, 40%);">+            if (mask_tmp & 0x01)</span><br><span style="color: hsl(120, 100%, 40%);">+                      CPU_SET_S(cpu_i, cpuset_size, cpuset);</span><br><span style="color: hsl(120, 100%, 40%);">+                mask_tmp >>= 1;</span><br><span style="color: hsl(120, 100%, 40%);">+         cpu_i++;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (tid_type != SCHED_VTY_THREAD_ALL) {</span><br><span style="color: hsl(120, 100%, 40%);">+               LOGP(DLGLOBAL, LOGL_NOTICE, "Setting CPU affinity mask for tid %lu to: 0x%lx\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                 (unsigned long) pid, mask);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            rc = sched_setaffinity(pid, sizeof(cpu_set_t), cpuset);</span><br><span style="color: hsl(120, 100%, 40%);">+               CPU_FREE(cpuset);</span><br><span style="color: hsl(120, 100%, 40%);">+             return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   snprintf(dirname, sizeof(dirname), "/proc/%ld/task", (long int)getpid());</span><br><span style="color: hsl(120, 100%, 40%);">+   proc_dir = opendir(dirname);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!proc_dir) {</span><br><span style="color: hsl(120, 100%, 40%);">+              CPU_FREE(cpuset);</span><br><span style="color: hsl(120, 100%, 40%);">+             return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   while ((entry = readdir(proc_dir)))</span><br><span style="color: hsl(120, 100%, 40%);">+   {</span><br><span style="color: hsl(120, 100%, 40%);">+             if(entry->d_name[0] == '.')</span><br><span style="color: hsl(120, 100%, 40%);">+                        continue;</span><br><span style="color: hsl(120, 100%, 40%);">+             tid_it = atoi(entry->d_name);</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGP(DLGLOBAL, LOGL_NOTICE, "Setting CPU affinity mask for tid %lu to: 0x%lx\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                 (unsigned long) tid_it, mask);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         rc = sched_setaffinity(tid_it, sizeof(cpu_set_t), cpuset);</span><br><span style="color: hsl(120, 100%, 40%);">+            if (rc == -1)</span><br><span style="color: hsl(120, 100%, 40%);">+                 break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   closedir(proc_dir);</span><br><span style="color: hsl(120, 100%, 40%);">+   CPU_FREE(cpuset);</span><br><span style="color: hsl(120, 100%, 40%);">+     return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+DEFUN(cfg_sched_cpu_affinity, cfg_sched_cpu_affinity_cmd,</span><br><span style="color: hsl(120, 100%, 40%);">+  "cpu-affinity (self|all|<0-4294967295>|THREADNAME) <0x00-0xffffffffffffffff> [delay]", /* Allow up to 64 CPUs */</span><br><span style="color: hsl(120, 100%, 40%);">+        "Set Target thread to apply the CPU affinty mask\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ "Set CPU affinity mask of the thread\n"</span><br><span style="color: hsl(120, 100%, 40%);">+     "CPU affinity mask\n"</span><br><span style="color: hsl(120, 100%, 40%);">+       "If set, delay applying the affinity mask now and let the app handle it at a later point\n")</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     unsigned long mask;</span><br><span style="color: hsl(120, 100%, 40%);">+   const char* str_who = argv[0];</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *str_mask = argv[1];</span><br><span style="color: hsl(120, 100%, 40%);">+       bool applynow = (argc != 3);</span><br><span style="color: hsl(120, 100%, 40%);">+  char *end;</span><br><span style="color: hsl(120, 100%, 40%);">+    int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       pid_t pid;</span><br><span style="color: hsl(120, 100%, 40%);">+    enum sched_vty_thread_id tid_type;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct cpu_affinity_it *it, *it_next;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       tid_type = procname2pid(&pid, str_who, applynow);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tid_type == SCHED_VTY_THREAD_UNKNOWN) {</span><br><span style="color: hsl(120, 100%, 40%);">+           vty_out(vty, "%% Failed parsing target thread %s%s",</span><br><span style="color: hsl(120, 100%, 40%);">+                        str_who, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+                return CMD_WARNING;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (tid_type == SCHED_VTY_THREAD_ID && !applynow)  {</span><br><span style="color: hsl(120, 100%, 40%);">+          vty_out(vty, "%% It makes no sense to delay applying cpu-affinity on tid %lu%s",</span><br><span style="color: hsl(120, 100%, 40%);">+                    (unsigned long)pid, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+             return CMD_WARNING;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (tid_type == SCHED_VTY_THREAD_ALL && !applynow)  {</span><br><span style="color: hsl(120, 100%, 40%);">+         vty_out(vty, "%% It makes no sense to delay applying cpu-affinity on all threads%s",</span><br><span style="color: hsl(120, 100%, 40%);">+                        VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+         return CMD_WARNING;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   errno = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    mask = strtoul(str_mask, &end, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        if ((errno == ERANGE && mask == ULONG_MAX) || (errno && !mask) ||</span><br><span style="color: hsl(120, 100%, 40%);">+         str_mask == end) {</span><br><span style="color: hsl(120, 100%, 40%);">+                vty_out(vty, "%% Failed parsing CPU Affinity Mask %s%s",</span><br><span style="color: hsl(120, 100%, 40%);">+                    str_mask, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+               return CMD_WARNING;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (applynow) {</span><br><span style="color: hsl(120, 100%, 40%);">+               rc = my_sched_setaffinity(tid_type, pid, mask);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (rc == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       vty_out(vty, "%% Failed setting sched CPU Affinity Mask 0x%lx: %s%s",</span><br><span style="color: hsl(120, 100%, 40%);">+                               mask, strerror(errno), VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+                  return CMD_WARNING;</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Keep history of cmds applied to be able to rewrite config. If PID was passed</span><br><span style="color: hsl(120, 100%, 40%);">+          directly it makes no sense to store it since PIDs are temporary */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tid_type == SCHED_VTY_THREAD_SELF ||</span><br><span style="color: hsl(120, 100%, 40%);">+          tid_type == SCHED_VTY_THREAD_ALL ||</span><br><span style="color: hsl(120, 100%, 40%);">+           tid_type == SCHED_VTY_THREAD_NAME) {</span><br><span style="color: hsl(120, 100%, 40%);">+              pthread_mutex_lock(&sched_vty_opts->cpu_affinity_li_mutex);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          /* Drop previous entries matching, since they will be overwritten */</span><br><span style="color: hsl(120, 100%, 40%);">+          llist_for_each_entry_safe(it, it_next, &sched_vty_opts->cpu_affinity_li, entry) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      if (strcmp(it->bufname, str_who) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                           llist_del(&it->entry);</span><br><span style="color: hsl(120, 100%, 40%);">+                         talloc_free(it);</span><br><span style="color: hsl(120, 100%, 40%);">+                              break;</span><br><span style="color: hsl(120, 100%, 40%);">+                        }</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+             it = talloc_zero(sched_vty_opts->tall_ctx, struct cpu_affinity_it);</span><br><span style="color: hsl(120, 100%, 40%);">+                OSMO_STRLCPY_ARRAY(it->bufname, str_who);</span><br><span style="color: hsl(120, 100%, 40%);">+          it->tid_type = tid_type;</span><br><span style="color: hsl(120, 100%, 40%);">+           it->mask = mask;</span><br><span style="color: hsl(120, 100%, 40%);">+           it->delay = !applynow;</span><br><span style="color: hsl(120, 100%, 40%);">+             llist_add_tail(&it->entry, &sched_vty_opts->cpu_affinity_li);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         pthread_mutex_unlock(&sched_vty_opts->cpu_affinity_li_mutex);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return CMD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int set_sched_rr(unsigned int prio)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct sched_param param;</span><br><span style="color: hsl(120, 100%, 40%);">+     int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       memset(&param, 0, sizeof(param));</span><br><span style="color: hsl(120, 100%, 40%);">+ param.sched_priority = prio;</span><br><span style="color: hsl(120, 100%, 40%);">+  LOGP(DLGLOBAL, LOGL_NOTICE, "Setting SCHED_RR priority %d\n", param.sched_priority);</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = sched_setscheduler(getpid(), SCHED_RR, &param);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (rc == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+               LOGP(DLGLOBAL, LOGL_FATAL, "Setting SCHED_RR priority %d failed: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                  param.sched_priority, strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+          return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+DEFUN(cfg_sched_policy, cfg_sched_policy_cmd,</span><br><span style="color: hsl(120, 100%, 40%);">+ "policy rr <1-32>",</span><br><span style="color: hsl(120, 100%, 40%);">+   "Set the scheduling policy to use for the process\n"</span><br><span style="color: hsl(120, 100%, 40%);">+        "Use the SCHED_RR real-time scheduling algorithm\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ "Use the SCHED_RR real-time priority\n"</span><br><span style="color: hsl(120, 100%, 40%);">+     "Real time priority\n")</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  sched_vty_opts->sched_rr_prio = atoi(argv[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (set_sched_rr(sched_vty_opts->sched_rr_prio) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+          vty_out(vty, "%% Failed setting SCHED_RR priority %d%s",</span><br><span style="color: hsl(120, 100%, 40%);">+                    sched_vty_opts->sched_rr_prio, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+               return CMD_WARNING;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return CMD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+DEFUN(cfg_sched,</span><br><span style="color: hsl(120, 100%, 40%);">+      cfg_sched_cmd,</span><br><span style="color: hsl(120, 100%, 40%);">+      "sched", "Configure CPU Scheduler related settings")</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   vty->index = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ vty->node = L_SCHED_NODE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        return CMD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+DEFUN(show_sched_threads, show_sched_threads_cmd,</span><br><span style="color: hsl(120, 100%, 40%);">+   "show sched threads",</span><br><span style="color: hsl(120, 100%, 40%);">+       SHOW_STR</span><br><span style="color: hsl(120, 100%, 40%);">+      "Show Sched section information\n"</span><br><span style="color: hsl(120, 100%, 40%);">+  "Show information about running threads)\n")</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     DIR *proc_dir;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct dirent *entry;</span><br><span style="color: hsl(120, 100%, 40%);">+ char path[100];</span><br><span style="color: hsl(120, 100%, 40%);">+       char buf[16];</span><br><span style="color: hsl(120, 100%, 40%);">+ int tid_it;</span><br><span style="color: hsl(120, 100%, 40%);">+   int fd;</span><br><span style="color: hsl(120, 100%, 40%);">+       pid_t mypid = getpid();</span><br><span style="color: hsl(120, 100%, 40%);">+       int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       uint64_t mask;</span><br><span style="color: hsl(120, 100%, 40%);">+        cpu_set_t *cpuset;</span><br><span style="color: hsl(120, 100%, 40%);">+    unsigned int cpu_i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, "Thread list for PID %lu:%s", (unsigned long) mypid, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   snprintf(path, sizeof(path), "/proc/%ld/task", (long int)mypid);</span><br><span style="color: hsl(120, 100%, 40%);">+    proc_dir = opendir(path);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!proc_dir) {</span><br><span style="color: hsl(120, 100%, 40%);">+              vty_out(vty, "%% Failed opening dir%s%s", buf, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+                return CMD_WARNING;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   while ((entry = readdir(proc_dir)))</span><br><span style="color: hsl(120, 100%, 40%);">+   {</span><br><span style="color: hsl(120, 100%, 40%);">+             if(entry->d_name[0] == '.')</span><br><span style="color: hsl(120, 100%, 40%);">+                        continue;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           tid_it = atoi(entry->d_name);</span><br><span style="color: hsl(120, 100%, 40%);">+              snprintf(path, sizeof(path), "/proc/%ld/task/%ld/comm", (long int)mypid, (long int) tid_it);</span><br><span style="color: hsl(120, 100%, 40%);">+                if ((fd = open(path, O_RDONLY)) != -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      rc = read(fd, buf, sizeof(buf));</span><br><span style="color: hsl(120, 100%, 40%);">+                      if (rc >= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                             /* Last char contain a '\n', get rid of it */</span><br><span style="color: hsl(120, 100%, 40%);">+                         buf[rc-1] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+                     }</span><br><span style="color: hsl(120, 100%, 40%);">+                     close(fd);</span><br><span style="color: hsl(120, 100%, 40%);">+            } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      buf[0] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           mask = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+             cpuset = CPU_ALLOC(64);</span><br><span style="color: hsl(120, 100%, 40%);">+               CPU_ZERO_S(CPU_ALLOC_SIZE(64), cpuset);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (sched_getaffinity(tid_it, CPU_ALLOC_SIZE(64), cpuset) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     for (cpu_i = 0; cpu_i < 64; cpu_i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                             if (CPU_ISSET(cpu_i, cpuset))</span><br><span style="color: hsl(120, 100%, 40%);">+                                 mask |= (1 << cpu_i);</span><br><span style="color: hsl(120, 100%, 40%);">+                   }</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+             CPU_FREE(cpuset);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           vty_out(vty, " TID: %lu, NAME: '%s', cpu-affinity: 0x%" PRIx64 "%s", (unsigned long) tid_it, buf, mask, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   closedir(proc_dir);</span><br><span style="color: hsl(120, 100%, 40%);">+   return CMD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int config_write_sched(struct vty *vty)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct cpu_affinity_it *it;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Only add the node if there's something to write under it */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (sched_vty_opts->sched_rr_prio || !llist_empty(&sched_vty_opts->cpu_affinity_li))</span><br><span style="color: hsl(120, 100%, 40%);">+                vty_out(vty, "sched%s", VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (sched_vty_opts->sched_rr_prio)</span><br><span style="color: hsl(120, 100%, 40%);">+         vty_out(vty, " policy rr %d%s", sched_vty_opts->sched_rr_prio, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   llist_for_each_entry(it, &sched_vty_opts->cpu_affinity_li, entry) {</span><br><span style="color: hsl(120, 100%, 40%);">+            vty_out(vty, " cpu-affinity %s 0x%lx%s%s", it->bufname, it->mask,</span><br><span style="color: hsl(120, 100%, 40%);">+                     it->delay ? " delay" : "", VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return CMD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Initialize sched VTY nodes</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] vty  VTY context for vty_out() of error messages.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] tdefs  Array of timer definitions to look up T timer.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] T_str  Argument string. It is not validated, expected to be checked by VTY input.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 on success, non-zero on error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_sched_vty_init(void *tall_ctx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(!sched_vty_opts); /* assert only called once */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ sched_vty_opts = talloc_zero(tall_ctx, struct sched_vty_opts);</span><br><span style="color: hsl(120, 100%, 40%);">+        sched_vty_opts->tall_ctx = tall_ctx;</span><br><span style="color: hsl(120, 100%, 40%);">+       INIT_LLIST_HEAD(&sched_vty_opts->cpu_affinity_li);</span><br><span style="color: hsl(120, 100%, 40%);">+     pthread_mutex_init(&sched_vty_opts->cpu_affinity_li_mutex, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    install_element(CONFIG_NODE, &cfg_sched_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+     install_node(&sched_node, config_write_sched);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  install_element(L_SCHED_NODE, &cfg_sched_policy_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+     install_element(L_SCHED_NODE, &cfg_sched_cpu_affinity_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     install_element_ve(&show_sched_threads_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+      return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Apply cpu-affinity on calling thread based on VTY configuration</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 on success, non-zero on error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_sched_vty_apply_localthread(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct cpu_affinity_it *it;</span><br><span style="color: hsl(120, 100%, 40%);">+   char name[17];  /* 15 + \n + \0 */</span><br><span style="color: hsl(120, 100%, 40%);">+    bool has_name = false;</span><br><span style="color: hsl(120, 100%, 40%);">+        bool mask_found = false;</span><br><span style="color: hsl(120, 100%, 40%);">+      unsigned long mask;</span><br><span style="color: hsl(120, 100%, 40%);">+   int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Assert subsystem was inited and structs are preset */</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sched_vty_opts);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (pthread_getname_np(pthread_self(), name, sizeof(name)) == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+              has_name = true;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Get latest matching mask for the thread */</span><br><span style="color: hsl(120, 100%, 40%);">+ pthread_mutex_lock(&sched_vty_opts->cpu_affinity_li_mutex);</span><br><span style="color: hsl(120, 100%, 40%);">+    llist_for_each_entry(it, &sched_vty_opts->cpu_affinity_li, entry) {</span><br><span style="color: hsl(120, 100%, 40%);">+            switch (it->tid_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+            case SCHED_VTY_THREAD_SELF:</span><br><span style="color: hsl(120, 100%, 40%);">+                   continue; /* self to the VTY thread, not us */</span><br><span style="color: hsl(120, 100%, 40%);">+                case SCHED_VTY_THREAD_ALL:</span><br><span style="color: hsl(120, 100%, 40%);">+                    mask_found = true;</span><br><span style="color: hsl(120, 100%, 40%);">+                    mask = it->mask;</span><br><span style="color: hsl(120, 100%, 40%);">+                   break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case SCHED_VTY_THREAD_NAME:</span><br><span style="color: hsl(120, 100%, 40%);">+                   if (!has_name)</span><br><span style="color: hsl(120, 100%, 40%);">+                                continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (strcmp(name, it->bufname) != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                                continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                     mask_found = true;</span><br><span style="color: hsl(120, 100%, 40%);">+                    mask = it->mask;</span><br><span style="color: hsl(120, 100%, 40%);">+                   break;</span><br><span style="color: hsl(120, 100%, 40%);">+                default:</span><br><span style="color: hsl(120, 100%, 40%);">+                      OSMO_ASSERT(0);</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     pthread_mutex_unlock(&sched_vty_opts->cpu_affinity_li_mutex);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!mask_found)</span><br><span style="color: hsl(120, 100%, 40%);">+              return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   rc = my_sched_setaffinity(SCHED_VTY_THREAD_SELF, 0, mask);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (rc == -1)</span><br><span style="color: hsl(120, 100%, 40%);">+         LOGP(DLGLOBAL, LOGL_FATAL, "Setting cpu-affinity mask 0x%lx failed: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+               mask, strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+  return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! @} */</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/19442">change 19442</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/libosmocore/+/19442"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: If76a4bd2cc7b3c7adf5d84790a944d78be70e10a </div>
<div style="display:none"> Gerrit-Change-Number: 19442 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>