From 7e99ec812a9a62742d799e12ef487a07bc008dfb Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 27 Feb 2014 11:11:24 -0600 Subject: Should CPU load on each thread in the PS command --- apps/nshlib/Kconfig | 12 ++++ apps/nshlib/nsh_proccmds.c | 147 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 156 insertions(+), 3 deletions(-) (limited to 'apps') 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 * * Redistribution and use in source and binary forms, with or without @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -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. */ @@ -105,6 +116,114 @@ static const char *g_ttypenames[4] = * Private Functions ****************************************************************************/ +/**************************************************************************** + * 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; } -- cgit v1.2.3