summaryrefslogtreecommitdiff
path: root/apps/nshlib
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-02-27 11:11:24 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-02-27 11:11:24 -0600
commit7e99ec812a9a62742d799e12ef487a07bc008dfb (patch)
treee052355b416a87dd4e80768a7541ab02e0f83e81 /apps/nshlib
parent4f7347955eb8b544d1c7910e4141b4a9865b3d85 (diff)
downloadnuttx-7e99ec812a9a62742d799e12ef487a07bc008dfb.tar.gz
nuttx-7e99ec812a9a62742d799e12ef487a07bc008dfb.tar.bz2
nuttx-7e99ec812a9a62742d799e12ef487a07bc008dfb.zip
Should CPU load on each thread in the PS command
Diffstat (limited to 'apps/nshlib')
-rw-r--r--apps/nshlib/Kconfig12
-rw-r--r--apps/nshlib/nsh_proccmds.c147
2 files changed, 156 insertions, 3 deletions
diff --git a/apps/nshlib/Kconfig b/apps/nshlib/Kconfig
index 74d25a59e..1de11376a 100644
--- a/apps/nshlib/Kconfig
+++ b/apps/nshlib/Kconfig
@@ -98,6 +98,11 @@ config NSH_DISABLE_DD
default y if DEFAULT_SMALL
default n if !DEFAULT_SMALL
+config NSH_DISABLE_DF
+ bool "Disable df"
+ default y if DEFAULT_SMALL
+ default n if !DEFAULT_SMALL
+
config NSH_DISABLE_DELROUTE
bool "Disable delroute"
default y if DEFAULT_SMALL
@@ -284,6 +289,7 @@ config NSH_CMDOPT_DF_H
bool "df: Enable [-h] man-readable format"
default n if DEFAULT_SMALL
default y if !DEFAULT_SMALL
+ depends on !NSH_DISABLE_DF
config NSH_CODECS_BUFSIZE
int "File buffer size used by CODEC commands"
@@ -293,6 +299,12 @@ config NSH_CMDOPT_HEXDUMP
bool "hexdump: Enable 'skip' and 'count' parameters"
default n if DEFAULT_SMALL
default y if !DEFAULT_SMALL
+ depends on !NSH_DISABLE_HEXDUMP
+
+config NSH_PROC_MOUNTPOUNT
+ string "procfs mountpoint"
+ default "/proc"
+ depends on FS_PROCFS
endmenu
diff --git a/apps/nshlib/nsh_proccmds.c b/apps/nshlib/nsh_proccmds.c
index 29daec0cd..4b92abf9b 100644
--- a/apps/nshlib/nsh_proccmds.c
+++ b/apps/nshlib/nsh_proccmds.c
@@ -1,7 +1,7 @@
/****************************************************************************
* apps/nshlib/nsh_proccmds.c
*
- * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011-2012, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -42,6 +42,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <fcntl.h>
#include <sched.h>
#include <errno.h>
@@ -49,14 +50,24 @@
#include "nsh_console.h"
/****************************************************************************
- * Definitions
+ * Pre-processor Definitions
****************************************************************************/
+#ifndef CONFIG_NSH_PROC_MOUNTPOUNT
+# define CONFIG_NSH_PROC_MOUNTPOUNT "/proc"
+#endif
+
+#undef HAVE_CPULOAD
+#if defined(CONFIG_SCHED_CPULOAD) && defined(CONFIG_FS_PROCFS) && \
+ !defined(CONFIG_FS_PROCFS_EXCLUDE_CPULOAD)
+# define HAVE_CPULOAD 1
+#endif
+
/****************************************************************************
* Private Types
****************************************************************************/
-/* The returned value should be zero for sucess or TRUE or non zero for
+/* The returned value should be zero for success or TRUE or non zero for
* failure or FALSE.
*/
@@ -106,6 +117,114 @@ static const char *g_ttypenames[4] =
****************************************************************************/
/****************************************************************************
+ * Name: loadavg
+ ****************************************************************************/
+
+#ifdef HAVE_CPULOAD
+static int readfile(FAR const char *filename, FAR char *buffer, size_t buflen)
+{
+ FAR char *bufptr;
+ size_t remaining;
+ ssize_t nread;
+ ssize_t ntotal;
+ int fd;
+ int ret;
+
+ /* Open the file */
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ {
+ int errcode = errno;
+ DEBUGASSERT(errcode > 0);
+ return -errcode;
+ }
+
+ /* Read until we hit the end of the file, until we have exhausted the
+ * buffer space, or until some irrecoverable error occurs
+ */
+
+ ntotal = 0; /* No bytes read yet */
+ *buffer = '\0'; /* NUL terminate the empty buffer */
+ bufptr = buffer; /* Working pointer */
+ remaining = buflen - 1; /* Reserve one byte for a NUL terminator */
+ ret = -E2BIG; /* Assume result will not fit in the buffer */
+
+ do
+ {
+ nread = read(fd, bufptr, remaining);
+ if (nread < 0)
+ {
+ /* Read error */
+
+ int errcode = errno;
+ DEBUGASSERT(errcode > 0);
+
+ /* EINTR is not a read error. It simply means that a signal was
+ * received while waiting for the read to complete.
+ */
+
+ if (errcode != EINTR)
+ {
+ /* Fatal error */
+
+ ret = -errcode;
+ break;
+ }
+ }
+ else if (nread == 0)
+ {
+ /* End of file */
+
+ ret = OK;
+ break;
+ }
+ else
+ {
+ /* Successful read. Make sure that the buffer is null terminated */
+
+ DEBUGASSERT(nread <= remaining);
+ ntotal += nread;
+ buffer[ntotal] = '\0';
+
+ /* Bump up the read count and continuing reading to the end of
+ * file.
+ */
+
+ bufptr += nread;
+ remaining -= nread;
+ }
+ }
+ while (buflen > 0);
+
+ /* Close the file and return. */
+
+ close(fd);
+ return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: loadavg
+ ****************************************************************************/
+
+#ifdef HAVE_CPULOAD
+static int loadavg(pid_t pid, FAR char *buffer, size_t buflen)
+{
+ char path[24];
+
+ /* Form the full path to the 'loadavg' pseudo-file */
+
+ snprintf(path, sizeof(path), CONFIG_NSH_PROC_MOUNTPOUNT "/%d/loadavg",
+ (int)pid);
+
+ /* Read the 'loadavg' pseudo-file into the user buffer */
+
+ return readfile(path, buffer, buflen);
+}
+#endif
+
+/****************************************************************************
* Name: ps_task
****************************************************************************/
@@ -113,6 +232,10 @@ static const char *g_ttypenames[4] =
static void ps_task(FAR struct tcb_s *tcb, FAR void *arg)
{
struct nsh_vtbl_s *vtbl = (struct nsh_vtbl_s*)arg;
+#ifdef HAVE_CPULOAD
+ char buffer[8];
+ int ret;
+#endif
#if CONFIG_MAX_TASK_ARGS > 2
int i;
#endif
@@ -127,6 +250,20 @@ static void ps_task(FAR struct tcb_s *tcb, FAR void *arg)
tcb->flags & TCB_FLAG_CANCEL_PENDING ? 'P' : ' ',
g_statenames[tcb->task_state]);
+#ifdef HAVE_CPULOAD
+ /* Get the CPU load */
+
+ ret = loadavg(tcb->pid, buffer, sizeof(buffer));
+ if (ret < 0)
+ {
+ /* Make the buffer into an empty string */
+
+ buffer[0] = '\0';
+ }
+
+ nsh_output(vtbl, "%-6s ", buffer);
+#endif
+
/* Show task name and arguments */
#if CONFIG_TASK_NAME_SIZE > 0
@@ -202,7 +339,11 @@ int cmd_exec(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
#ifndef CONFIG_NSH_DISABLE_PS
int cmd_ps(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
+#ifdef HAVE_CPULOAD
+ nsh_output(vtbl, "PID PRI SCHD TYPE NP STATE CPU NAME\n");
+#else
nsh_output(vtbl, "PID PRI SCHD TYPE NP STATE NAME\n");
+#endif
sched_foreach(ps_task, vtbl);
return OK;
}