summaryrefslogtreecommitdiff
path: root/nuttx/fs
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-02-23 10:55:01 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-02-23 10:55:01 -0600
commit7c745cd460ea7361719b9fd18a35491beed92623 (patch)
treeb35642399f2cbe11bbe6c9a57f6cf2d90fea3ffb /nuttx/fs
parent875b32e8389ac6e06bfb328e992c1865445d96c1 (diff)
downloadnuttx-7c745cd460ea7361719b9fd18a35491beed92623.tar.gz
nuttx-7c745cd460ea7361719b9fd18a35491beed92623.tar.bz2
nuttx-7c745cd460ea7361719b9fd18a35491beed92623.zip
CPU load calculations now available for all threads. Available in /proc/pid/loadavg
Diffstat (limited to 'nuttx/fs')
-rw-r--r--nuttx/fs/procfs/fs_procfscpuload.c40
-rw-r--r--nuttx/fs/procfs/fs_procfsproc.c83
2 files changed, 98 insertions, 25 deletions
diff --git a/nuttx/fs/procfs/fs_procfscpuload.c b/nuttx/fs/procfs/fs_procfscpuload.c
index a1f8179bf..75572dee3 100644
--- a/nuttx/fs/procfs/fs_procfscpuload.c
+++ b/nuttx/fs/procfs/fs_procfscpuload.c
@@ -207,9 +207,6 @@ static ssize_t cpuload_read(FAR struct file *filep, FAR char *buffer,
size_t buflen)
{
FAR struct cpuload_file_s *attr;
- uint32_t cpuload;
- uint32_t cpuload_int;
- uint32_t cpuload_frac;
size_t linesize;
off_t offset;
ssize_t ret;
@@ -230,40 +227,37 @@ static ssize_t cpuload_read(FAR struct file *filep, FAR char *buffer,
if (filep->f_pos == 0)
{
- uint32_t idle;
- uint32_t busycnt;
- uint32_t verify;
+ struct cpuload_s cpuload;
+ uint32_t intpart;
+ uint32_t fracpart;
- /* Sample the counts, repeatedly if necessary to assure that they are
- * in sync.
+ /* Sample the counts for the IDLE thread. clock_cpuload should only
+ * fail if the PID is not valid. This, however, should never happen
+ * for the IDLE thread.
*/
- do
- {
- busycnt = g_cpuload.cnt;
- idle = g_cpuload.idle;
- verify = g_cpuload.cnt;
- }
- while (busycnt != verify);
+ DEBUGVERIFY(clock_cpuload(0, &cpuload));
- /* On the simulator, you may hit busycnt == 0, but probably never on
+ /* On the simulator, you may hit cpuload.total == 0, but probably never on
* real hardware.
*/
- if (busycnt > 0)
+ if (cpuload.total > 0)
{
- cpuload = 1000 - (1000 * idle) / busycnt;
- cpuload_int = cpuload / 10;
- cpuload_frac = cpuload - 10 * cpuload_int;
+ uint32_t tmp;
+
+ tmp = 1000 - (1000 * cpuload.active) / cpuload.total;
+ intpart = tmp / 10;
+ fracpart = tmp - 10 * intpart;
}
else
{
- cpuload_int = 0;
- cpuload_frac = 0;
+ intpart = 0;
+ fracpart = 0;
}
linesize = snprintf(attr->line, CPULOAD_LINELEN, "%3d.%01d%%\n",
- cpuload_int, cpuload_frac);
+ intpart, fracpart);
/* Save the linesize in case we are re-entered with f_pos > 0 */
diff --git a/nuttx/fs/procfs/fs_procfsproc.c b/nuttx/fs/procfs/fs_procfsproc.c
index 1fc90b096..a1ec1b898 100644
--- a/nuttx/fs/procfs/fs_procfsproc.c
+++ b/nuttx/fs/procfs/fs_procfsproc.c
@@ -60,6 +60,10 @@
#include <nuttx/fs/procfs.h>
#include <nuttx/fs/dirent.h>
+#ifdef CONFIG_SCHED_CPULOAD
+# include <nuttx/clock.h>
+#endif
+
#include <arch/irq.h>
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_PROCFS)
@@ -86,6 +90,9 @@ enum proc_node_e
PROC_LEVEL0 = 0, /* The top-level directory */
PROC_STATUS, /* Task/thread status */
PROC_CMDLINE, /* Task command line */
+#ifdef CONFIG_SCHED_CPULOAD
+ PROC_LOADAVG, /* Average CPU utilization */
+#endif
PROC_STACK, /* Task stack info */
PROC_GROUP, /* Group directory */
PROC_GROUP_STATUS, /* Task group status */
@@ -136,6 +143,11 @@ static ssize_t proc_status(FAR struct proc_file_s *procfile,
static ssize_t proc_cmdline(FAR struct proc_file_s *procfile,
FAR struct tcb_s *tcb, FAR char *buffer, size_t buflen,
off_t offset);
+#ifdef CONFIG_SCHED_CPULOAD
+static ssize_t proc_loadavg(FAR struct proc_file_s *procfile,
+ FAR struct tcb_s *tcb, FAR char *buffer, size_t buflen,
+ off_t offset);
+#endif
static ssize_t proc_stack(FAR struct proc_file_s *procfile,
FAR struct tcb_s *tcb, FAR char *buffer, size_t buflen,
off_t offset);
@@ -211,6 +223,13 @@ static const struct proc_node_s g_cmdline =
"cmdline", "cmdline", (uint8_t)PROC_CMDLINE, DTYPE_FILE /* Task command line */
};
+#ifdef CONFIG_SCHED_CPULOAD
+static const struct proc_node_s g_loadavg =
+{
+ "loadavg", "loadavg", (uint8_t)PROC_LOADAVG, DTYPE_FILE /* Average CPU utilization */
+};
+#endif
+
static const struct proc_node_s g_stack =
{
"stack", "stack", (uint8_t)PROC_STACK, DTYPE_FILE /* Task stack info */
@@ -237,6 +256,9 @@ static FAR const struct proc_node_s * const g_nodeinfo[] =
{
&g_status, /* Task/thread status */
&g_cmdline, /* Task command line */
+#ifdef CONFIG_SCHED_CPULOAD
+ &g_loadavg, /* Average CPU utilization */
+#endif
&g_stack, /* Task stack info */
&g_group, /* Group directory */
&g_groupstatus, /* Task group status */
@@ -250,6 +272,9 @@ static const struct proc_node_s * const g_level0info[] =
{
&g_status, /* Task/thread status */
&g_cmdline, /* Task command line */
+#ifdef CONFIG_SCHED_CPULOAD
+ &g_loadavg, /* Average CPU utilization */
+#endif
&g_stack, /* Task stack info */
&g_group, /* Group directory */
};
@@ -518,12 +543,61 @@ static ssize_t proc_cmdline(FAR struct proc_file_s *procfile,
}
/****************************************************************************
+ * Name: proc_loadavg
+ ****************************************************************************/
+
+#ifdef CONFIG_SCHED_CPULOAD
+static ssize_t proc_loadavg(FAR struct proc_file_s *procfile,
+ FAR struct tcb_s *tcb, FAR char *buffer,
+ size_t buflen, off_t offset)
+{
+ struct cpuload_s cpuload;
+ uint32_t intpart;
+ uint32_t fracpart;
+ size_t linesize;
+ size_t copysize;
+ ssize_t ret;
+
+ /* Sample the counts for the thread. clock_cpuload should only fail if
+ * the PID is not valid. This could happen if the thread exited sometime
+ * after the procfs entry was opened.
+ */
+
+ ret = (ssize_t)clock_cpuload(procfile->pid, &cpuload);
+
+ /* On the simulator, you may hit cpuload.total == 0, but probably never on
+ * real hardware.
+ */
+
+ if (cpuload.total > 0)
+ {
+ uint32_t tmp;
+
+ tmp = 1000 - (1000 * cpuload.active) / cpuload.total;
+ intpart = tmp / 10;
+ fracpart = tmp - 10 * intpart;
+ }
+ else
+ {
+ intpart = 0;
+ fracpart = 0;
+ }
+
+ linesize = snprintf(procfile->line, STATUS_LINELEN, "%3d.%01d%%\n",
+ intpart, fracpart);
+ copysize = procfs_memcpy(procfile->line, linesize, buffer, buflen, &offset);
+
+ return copysize;
+}
+#endif
+
+/****************************************************************************
* Name: proc_stack
****************************************************************************/
static ssize_t proc_stack(FAR struct proc_file_s *procfile,
- FAR struct tcb_s *tcb, FAR char *buffer, size_t buflen,
- off_t offset)
+ FAR struct tcb_s *tcb, FAR char *buffer,
+ size_t buflen, off_t offset)
{
size_t remaining;
size_t linesize;
@@ -986,6 +1060,11 @@ static ssize_t proc_read(FAR struct file *filep, FAR char *buffer,
ret = proc_cmdline(procfile, tcb, buffer, buflen, filep->f_pos);
break;
+#ifdef CONFIG_SCHED_CPULOAD
+ case PROC_LOADAVG: /* Average CPU utilization */
+ ret = proc_loadavg(procfile, tcb, buffer, buflen, filep->f_pos);
+ break;
+#endif
case PROC_STACK: /* Task stack info */
ret = proc_stack(procfile, tcb, buffer, buflen, filep->f_pos);
break;