This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git


The following commit(s) were added to refs/heads/master by this push:
     new afc652243 examples/thttpd: use procfs for tasks CGI
afc652243 is described below

commit afc652243efd77f6050ef1c8c3a0c1a2755f4195
Author: Nightt <[email protected]>
AuthorDate: Fri Jun 12 15:56:07 2026 +0800

    examples/thttpd: use procfs for tasks CGI
    
    The tasks CGI used nxsched_foreach() to walk scheduler internals and read
    fields directly from struct tcb_s. That exposes an application example to
    non-standard OS internals.
    
    Read task information from /proc/<pid>/status instead, matching the public
    procfs interface used by other task listing tools.
    
    Signed-off-by: Nightt <[email protected]>
---
 examples/thttpd/content/tasks/tasks.c | 290 ++++++++++++++++++++++++++--------
 1 file changed, 226 insertions(+), 64 deletions(-)

diff --git a/examples/thttpd/content/tasks/tasks.c 
b/examples/thttpd/content/tasks/tasks.c
index da7347678..089a751b6 100644
--- a/examples/thttpd/content/tasks/tasks.c
+++ b/examples/thttpd/content/tasks/tasks.c
@@ -26,48 +26,36 @@
 
 #include <nuttx/config.h>
 
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
 #include <stdio.h>
-#include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
-#include <sched.h>
-
-#include <nuttx/sched.h>
 
 /****************************************************************************
- * Private Data
+ * Pre-processor Definitions
  ****************************************************************************/
 
-static const char *g_statenames[] =
-{
-  "INVALID ",
-  "PENDING ",
-  "READY   ",
-  "RUNNING ",
-  "INACTIVE",
-  "WAITSEM ",
-#ifndef CONFIG_DISABLE_MQUEUE
-  "WAITSIG ",
-#endif
-#ifndef CONFIG_DISABLE_MQUEUE
-  "MQNEMPTY",
-  "MQNFULL "
+#ifndef THTTPD_PROCFS_MOUNTPOINT
+#  define THTTPD_PROCFS_MOUNTPOINT "/proc"
 #endif
-};
 
-static const char *g_ttypenames[4] =
-{
-  "TASK   ",
-  "PTHREAD",
-  "KTHREAD",
-  "--?--  "
-};
+#define THTTPD_STATUS_SIZE 512
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
 
-static FAR const char *g_policynames[4] =
+struct thttpd_task_status_s
 {
-  "FIFO",
-  "RR  ",
-  "SPOR",
-  "OTHR"
+  FAR const char *name;
+  FAR const char *type;
+  FAR const char *state;
+  FAR const char *priority;
+  FAR const char *policy;
 };
 
 /****************************************************************************
@@ -78,38 +66,210 @@ static FAR const char *g_policynames[4] =
  * Private Functions
  ****************************************************************************/
 
-/* NOTEs:
- *
- * 1. One limitation in the use of NXFLAT is that functions that are
- *    referenced as a pointer-to-a-function must have global scope.
- *    Otherwise ARM GCC will generate some bad logic.
- * 2. In general, when called back, there is no guarantee to that PIC
- *    registers will be valid and, unless you take special precautions, it
- *    could be dangerous to reference global variables in the callback
- *    function.
- */
-
-void show_task(FAR struct tcb_s *tcb, FAR void *arg)
+/****************************************************************************
+ * Name: tasks_trim_value
+ ****************************************************************************/
+
+static FAR char *tasks_trim_value(FAR char *line)
 {
-  FAR const char *policy;
+  FAR char *end;
 
-  /* Show task/thread status */
+  while (isblank((unsigned char)*line) && *line != '\0')
+    {
+      line++;
+    }
 
-  policy = g_policynames[(tcb->flags & TCB_FLAG_POLICY_MASK) >>
-                         TCB_FLAG_POLICY_SHIFT];
-#if CONFIG_TASK_NAME_SIZE > 0
-  printf("%5d %3d %4s %7s %8s %s\n",
-#else
-  printf("%5d %3d %4s %7s %8s\n",
-#endif
-         tcb->pid, tcb->sched_priority, policy,
-         g_ttypenames[(tcb->flags & TCB_FLAG_TTYPE_MASK) >>
-                      TCB_FLAG_TTYPE_SHIFT],
-         g_statenames[tcb->task_state]
-#if CONFIG_TASK_NAME_SIZE > 0
-         , tcb->name
-#endif
-         );
+  end = line + strlen(line);
+  while (end > line &&
+         (*(end - 1) == '\n' || *(end - 1) == '\r' ||
+          isblank((unsigned char)*(end - 1))))
+    {
+      end--;
+    }
+
+  *end = '\0';
+  return line;
+}
+
+/****************************************************************************
+ * Name: tasks_is_pid_dir
+ ****************************************************************************/
+
+static bool tasks_is_pid_dir(FAR const struct dirent *entryp)
+{
+  FAR const char *name = entryp->d_name;
+
+  if (!DIRENT_ISDIRECTORY(entryp->d_type) || *name == '\0')
+    {
+      return false;
+    }
+
+  for (; *name != '\0'; name++)
+    {
+      if (!isdigit((unsigned char)*name))
+        {
+          return false;
+        }
+    }
+
+  return true;
+}
+
+/****************************************************************************
+ * Name: tasks_parse_status_line
+ ****************************************************************************/
+
+static void tasks_parse_status_line(FAR char *line,
+                                    FAR struct thttpd_task_status_s *status)
+{
+  if (strncmp(line, "Name:", 5) == 0)
+    {
+      status->name = tasks_trim_value(&line[5]);
+    }
+  else if (strncmp(line, "Type:", 5) == 0)
+    {
+      status->type = tasks_trim_value(&line[5]);
+    }
+  else if (strncmp(line, "State:", 6) == 0)
+    {
+      status->state = tasks_trim_value(&line[6]);
+    }
+  else if (strncmp(line, "Priority:", 9) == 0)
+    {
+      status->priority = tasks_trim_value(&line[9]);
+    }
+  else if (strncmp(line, "Scheduler:", 10) == 0)
+    {
+      status->policy = tasks_trim_value(&line[10]);
+    }
+}
+
+/****************************************************************************
+ * Name: tasks_parse_status
+ ****************************************************************************/
+
+static void tasks_parse_status(FAR char *buffer,
+                               FAR struct thttpd_task_status_s *status)
+{
+  FAR char *line = buffer;
+
+  while (line != NULL && *line != '\0')
+    {
+      FAR char *next = strchr(line, '\n');
+      if (next != NULL)
+        {
+          *next++ = '\0';
+        }
+
+      tasks_parse_status_line(line, status);
+      line = next;
+    }
+}
+
+/****************************************************************************
+ * Name: tasks_read_status
+ ****************************************************************************/
+
+static int tasks_read_status(FAR const char *pid, FAR char *buffer,
+                             size_t buflen,
+                             FAR struct thttpd_task_status_s *status)
+{
+  char filepath[sizeof(THTTPD_PROCFS_MOUNTPOINT) + NAME_MAX +
+                sizeof("/status") + 1];
+  ssize_t nread;
+  size_t total = 0;
+  int ret;
+  int fd;
+
+  ret = snprintf(filepath, sizeof(filepath), "%s/%s/status",
+                 THTTPD_PROCFS_MOUNTPOINT, pid);
+  if (ret < 0 || ret >= sizeof(filepath))
+    {
+      return -ENAMETOOLONG;
+    }
+
+  fd = open(filepath, O_RDONLY);
+  if (fd < 0)
+    {
+      return -errno;
+    }
+
+  while (total < buflen - 1)
+    {
+      nread = read(fd, &buffer[total], buflen - 1 - total);
+      if (nread < 0)
+        {
+          ret = -errno;
+          close(fd);
+          return ret;
+        }
+      else if (nread == 0)
+        {
+          break;
+        }
+
+      total += nread;
+    }
+
+  close(fd);
+  buffer[total] = '\0';
+  tasks_parse_status(buffer, status);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: show_task
+ ****************************************************************************/
+
+static void show_task(FAR const char *pid,
+                      FAR const struct thttpd_task_status_s *status)
+{
+  printf("%5s %-12s %-14s %-7s %-18s %s\n",
+         pid, status->priority, status->policy, status->type,
+         status->state, status->name);
+}
+
+/****************************************************************************
+ * Name: show_tasks
+ ****************************************************************************/
+
+static int show_tasks(void)
+{
+  FAR struct dirent *entryp;
+  DIR *dirp;
+
+  dirp = opendir(THTTPD_PROCFS_MOUNTPOINT);
+  if (dirp == NULL)
+    {
+      printf("Unable to open %s (is procfs mounted?): %d\n",
+             THTTPD_PROCFS_MOUNTPOINT, errno);
+      return -errno;
+    }
+
+  while ((entryp = readdir(dirp)) != NULL)
+    {
+      char buffer[THTTPD_STATUS_SIZE];
+      struct thttpd_task_status_s status =
+      {
+        "", "", "", "", ""
+      };
+
+      if (!tasks_is_pid_dir(entryp))
+        {
+          continue;
+        }
+
+      if (tasks_read_status(entryp->d_name, buffer, sizeof(buffer),
+                            &status) < 0)
+        {
+          continue;
+        }
+
+      show_task(entryp->d_name, &status);
+    }
+
+  closedir(dirp);
+  return OK;
 }
 
 /****************************************************************************
@@ -139,10 +299,12 @@ int main(int argc, char *argv[])
     "<br>\r\n"
     "</div>\r\n"
     "<div class=\"contentblock\">\r\n"
-    "<pre>\r\n"
-    "PID   PRI SCHD TYPE   NP STATE    NAME\r\n");
+    "<pre>\r\n");
+
+  printf("%5s %-12s %-14s %-7s %-18s %s\n",
+         "PID", "PRI", "SCHEDULER", "TYPE", "STATE", "NAME");
 
-  nxsched_foreach(show_task, NULL);
+  show_tasks();
 
   puts(
     "</pre>\r\n"

Reply via email to