You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by st...@apache.org on 2015/11/17 19:39:22 UTC

incubator-mynewt-larva git commit: add task info display. re-arrange the task structure a little, removing enum on task state and making it a uint8

Repository: incubator-mynewt-larva
Updated Branches:
  refs/heads/master 55082ce6c -> e96c2c3c6


add task info display.  re-arrange the task structure a little, removing enum on task state and making it a uint8


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/commit/e96c2c3c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/e96c2c3c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/e96c2c3c

Branch: refs/heads/master
Commit: e96c2c3c6377452d9f7b40915f741116c8209eb3
Parents: 55082ce
Author: Sterling Hughes <st...@apache.org>
Authored: Tue Nov 17 10:39:01 2015 -0800
Committer: Sterling Hughes <st...@apache.org>
Committed: Tue Nov 17 10:39:12 2015 -0800

----------------------------------------------------------------------
 libs/os/egg.yml                          |   5 +
 libs/os/include/os/os.h                  |   3 +
 libs/os/include/os/os_sched.h            |   4 +
 libs/os/include/os/os_task.h             |   7 +-
 libs/os/src/arch/cortex_m4/os_arch_arm.c |   4 +
 libs/os/src/arch/sim/os_arch_sim.c       |   4 +
 libs/os/src/os.c                         |   3 +
 libs/os/src/os_info.c                    | 167 ++++++++++++++++++++++++++
 libs/os/src/os_sched.c                   |  56 ++++++++-
 libs/os/src/os_task.c                    |   6 +
 libs/os/src/os_time.c                    |   2 +-
 libs/util/src/stats.c                    |   9 ++
 12 files changed, 266 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/egg.yml
----------------------------------------------------------------------
diff --git a/libs/os/egg.yml b/libs/os/egg.yml
index f9cddee..dd2657f 100644
--- a/libs/os/egg.yml
+++ b/libs/os/egg.yml
@@ -4,3 +4,8 @@ egg.deps:
     - libs/testutil
 egg.req_caps:
     - console
+
+egg.deps.SHELL:
+    - libs/console/full 
+    - libs/shell 
+egg.cflags.SHELL: -DSHELL_PRESENT 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/include/os/os.h
----------------------------------------------------------------------
diff --git a/libs/os/include/os/os.h b/libs/os/include/os/os.h
index 62b4c11..938f8b7 100644
--- a/libs/os/include/os/os.h
+++ b/libs/os/include/os/os.h
@@ -43,6 +43,8 @@
  */
 extern int g_os_started; 
 
+int os_info_init(void);
+
 /**
  * Returns 1 if the OS has been started, 0 if it has not yet been 
  * been started.
@@ -84,6 +86,7 @@ void os_init_idle_task(void);
 #include "os/os_sched.h"
 #include "os/os_eventq.h"
 #include "os/os_callout.h" 
+#include "os/os_heap.h"
 #include "os/os_mutex.h"
 #include "os/os_sem.h"
 #include "os/os_mempool.h"

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/include/os/os_sched.h
----------------------------------------------------------------------
diff --git a/libs/os/include/os/os_sched.h b/libs/os/include/os/os_sched.h
index ee84f76..a34c5e3 100644
--- a/libs/os/include/os/os_sched.h
+++ b/libs/os/include/os/os_sched.h
@@ -19,6 +19,10 @@
 
 #include "os/os_task.h"
 
+typedef int (*os_sched_walk_func_t)(struct os_task *, void *arg);
+
+int os_sched_walk(os_sched_walk_func_t walk_func, void *arg);
+void os_sched_ctx_sw_hook(struct os_task *);
 struct os_task *os_sched_get_current_task(void);
 void os_sched_set_current_task(struct os_task *);
 struct os_task *os_sched_next_task(void);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/include/os/os_task.h
----------------------------------------------------------------------
diff --git a/libs/os/include/os/os_task.h b/libs/os/include/os/os_task.h
index 8f7c746..3f75432 100644
--- a/libs/os/include/os/os_task.h
+++ b/libs/os/include/os/os_task.h
@@ -47,7 +47,8 @@ struct os_task {
 
     uint8_t t_taskid;
     uint8_t t_prio;
-    uint8_t t_pad[2];
+    uint8_t t_state;
+    uint8_t t_pad;
 
     char *t_name;
     os_task_func_t t_func;
@@ -57,8 +58,9 @@ struct os_task {
 
     struct os_sanity_check t_sanity_check; 
 
-    os_task_state_t t_state;
     os_time_t t_next_wakeup;
+    os_time_t t_run_time;
+    uint32_t t_ctx_sw_cnt;
     
     /* Used to chain task to either the run or sleep list */ 
     TAILQ_ENTRY(os_task) t_os_list;
@@ -71,6 +73,7 @@ int os_task_init(struct os_task *, char *, os_task_func_t, void *, uint8_t,
         os_time_t, os_stack_t *, uint16_t);
 
 int os_task_sanity_checkin(struct os_task *);
+uint8_t os_task_count(void);
 
 
 #endif /* _OS_TASK_H */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/src/arch/cortex_m4/os_arch_arm.c
----------------------------------------------------------------------
diff --git a/libs/os/src/arch/cortex_m4/os_arch_arm.c b/libs/os/src/arch/cortex_m4/os_arch_arm.c
index 3cc7ca1..d941809 100755
--- a/libs/os/src/arch/cortex_m4/os_arch_arm.c
+++ b/libs/os/src/arch/cortex_m4/os_arch_arm.c
@@ -99,6 +99,8 @@ timer_handler(void)
 void
 os_arch_ctx_sw(struct os_task *t)
 {
+    os_sched_ctx_sw_hook(t);
+
     /* Set PendSV interrupt pending bit to force context switch */
     SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
 }
@@ -106,6 +108,8 @@ os_arch_ctx_sw(struct os_task *t)
 void
 os_arch_ctx_sw_isr(struct os_task *t)
 {
+    os_sched_ctx_sw_hook(t);
+
     /* Set PendSV interrupt pending bit to force context switch */
     SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/src/arch/sim/os_arch_sim.c
----------------------------------------------------------------------
diff --git a/libs/os/src/arch/sim/os_arch_sim.c b/libs/os/src/arch/sim/os_arch_sim.c
index f2d57e3..2a1d585 100644
--- a/libs/os/src/arch/sim/os_arch_sim.c
+++ b/libs/os/src/arch/sim/os_arch_sim.c
@@ -152,6 +152,8 @@ os_arch_ctx_sw(struct os_task *next_t)
         }
     }
 
+    os_sched_ctx_sw_hook(next_t);
+
     os_sched_set_current_task(next_t);
 
     sf = (struct stack_frame *) next_t->t_stackptr;
@@ -196,6 +198,8 @@ os_arch_ctx_sw_isr(struct os_task *next_t)
 
     isr_state(&block_isr_off, NULL);
 
+    os_sched_ctx_sw_hook(next_t);
+
     os_sched_set_current_task(next_t);
     
     sf = (struct stack_frame *) next_t->t_stackptr;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/src/os.c
----------------------------------------------------------------------
diff --git a/libs/os/src/os.c b/libs/os/src/os.c
index 3ca3177..581db1d 100644
--- a/libs/os/src/os.c
+++ b/libs/os/src/os.c
@@ -59,6 +59,9 @@ os_init(void)
 
     err = os_arch_os_init();
     assert(err == OS_OK);
+
+    err = os_info_init();
+    assert(err == OS_OK);
 }
 
 void

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/src/os_info.c
----------------------------------------------------------------------
diff --git a/libs/os/src/os_info.c b/libs/os/src/os_info.c
new file mode 100644
index 0000000..dde779d
--- /dev/null
+++ b/libs/os/src/os_info.c
@@ -0,0 +1,167 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "os/os.h"
+
+#include "os/queue.h"
+
+#include "console/console.h"
+#include "shell/shell.h" 
+
+#include <string.h>
+
+struct os_task_info_walk {
+    struct os_task_info *info;
+    int info_cnt;
+};
+
+#define OS_TASK_INFO_NAME_SIZE (32)
+struct os_task_info {
+    uint8_t oti_tid;
+    uint8_t oti_prio;
+    uint8_t oti_state;
+    uint8_t oti_pad1;
+    uint16_t oti_flags;
+    uint16_t oti_stack_size;
+    uint32_t oti_csw_cnt;
+    os_time_t oti_next_wakeup;
+    os_time_t oti_run_time;
+    char oti_name[OS_TASK_INFO_NAME_SIZE];
+};
+
+int os_task_info_get(struct os_task_info *info, int info_cnt);
+
+#ifdef SHELL_PRESENT
+struct shell_cmd shell_os_tasks_display_cmd;
+#endif
+
+
+#ifdef SHELL_PRESENT
+/* Code to register with shell, and display the results of os_getinfo() 
+ */
+
+
+int 
+shell_os_tasks_display(int argc, char **argv)
+{
+    struct os_task_info *info; 
+    char *name;
+    int i;
+    int found;
+    int rc;
+    uint8_t tcount;
+
+    name = NULL;
+    found = 0;
+
+    if (argv[1] != NULL && strcmp(argv[1], "")) {
+        name = argv[1];
+    }   
+
+    tcount = os_task_count();
+
+    info = (struct os_task_info *) os_malloc(
+            sizeof(struct os_task_info) * tcount);
+    if (!info) {
+        rc = -1;
+        goto err;
+    }
+
+    rc = os_task_info_get(info, tcount);
+
+    console_printf("%d tasks: \n", rc);
+    for (i = 0; i < rc; i++) {
+        if (name) {
+            if (strcmp(name, info[i].oti_name)) {
+                continue;
+            } else {
+                found = 1;
+            }
+        }
+
+        console_printf("  %s (prio: %u, nw: %u, flags: 0x%x, "
+                "ssize: %u, cswcnt: %lu, tot_run_time: %ums)", 
+                info[i].oti_name, 
+                info[i].oti_prio, info[i].oti_next_wakeup, info[i].oti_flags, 
+                info[i].oti_stack_size,
+                info[i].oti_csw_cnt, info[i].oti_run_time);
+
+    }
+
+    if (name && !found) {
+        console_printf("Couldn't find task with name %s\n", name);
+    }
+
+    os_free(info);
+
+    return (0);
+err:
+    return (rc);
+}
+    
+
+#endif 
+
+static int
+_os_task_copy_info(struct os_task *t, void *arg)
+{
+    struct os_task_info_walk *walk;
+
+    walk = (struct os_task_info_walk *) arg;
+
+    if (walk->info_cnt == 0) {
+        /* Stored all the elements we can fit, exit out */
+        return (1);
+    }
+
+    walk->info->oti_tid = t->t_taskid;
+    walk->info->oti_prio = t->t_prio;
+    strlcpy(walk->info->oti_name, t->t_name, OS_TASK_INFO_NAME_SIZE);
+    walk->info->oti_state = (uint8_t) t->t_state;
+    walk->info->oti_next_wakeup = t->t_next_wakeup;
+    walk->info->oti_flags = t->t_flags;
+    walk->info->oti_stack_size = t->t_stacksize;
+    walk->info->oti_csw_cnt = t->t_ctx_sw_cnt;
+    walk->info->oti_run_time = t->t_run_time;
+
+    walk->info += 1;
+    walk->info_cnt--;
+
+    return (0);
+}
+
+int
+os_task_info_get(struct os_task_info *info, int info_cnt)
+{
+    struct os_task_info_walk walk;
+
+    walk.info = info;
+    walk.info_cnt = info_cnt;
+
+    os_sched_walk(_os_task_copy_info, (void *) &walk);
+    return (info_cnt - walk.info_cnt);
+}
+
+
+int 
+os_info_init(void)
+{
+#ifdef SHELL_PRESENT 
+    shell_cmd_register(&shell_os_tasks_display_cmd, "tasks", 
+            shell_os_tasks_display);
+#endif
+    return (0);
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/src/os_sched.c
----------------------------------------------------------------------
diff --git a/libs/os/src/os_sched.c b/libs/os/src/os_sched.c
index 240bc62..0589e81 100644
--- a/libs/os/src/os_sched.c
+++ b/libs/os/src/os_sched.c
@@ -25,6 +25,9 @@ TAILQ_HEAD(, os_task) g_os_sleep_list = TAILQ_HEAD_INITIALIZER(g_os_sleep_list);
 
 struct os_task *g_current_task; 
 
+extern os_time_t g_os_time;
+os_time_t g_os_last_ctx_sw_time;
+
 /**
  * os sched insert
  *  
@@ -68,6 +71,57 @@ err:
 }
 
 /**
+ * Walk all the active tasks currently being scheduled.
+ *
+ * @param walk_func The walk function to call for each task
+ * @param arg       The argument to pass the walk function
+ *
+ * @return 0 on success, < 0 on abort.
+ */
+int
+os_sched_walk(os_sched_walk_func_t walk_func, void *arg)
+{
+    struct os_task *t;
+    os_sr_t sr;
+    int rc;
+
+    /* Go through tasks and fill out the info blocks
+     */
+    OS_ENTER_CRITICAL(sr);
+    TAILQ_FOREACH(t, &g_os_run_list, t_os_list) {
+        rc = walk_func(t, arg);
+        if (rc != 0) {
+            goto done;
+        }
+    }
+
+    TAILQ_FOREACH(t, &g_os_sleep_list, t_os_list) {
+        rc = walk_func(t, arg);
+        if (rc != 0) {
+            goto done;
+        }
+    }
+
+done:
+    OS_EXIT_CRITICAL(sr);
+
+    return (rc);
+}
+
+void
+os_sched_ctx_sw_hook(struct os_task *next_t)
+{
+    if (g_current_task == next_t) {
+        return;
+    }
+
+    next_t->t_ctx_sw_cnt++;
+    next_t->t_run_time += g_os_time - g_os_last_ctx_sw_time;
+    g_os_last_ctx_sw_time = g_os_time;
+}
+
+
+/**
  * os sched get current task 
  *  
  * Returns the currently running task. Note that this task may or may not be 
@@ -118,7 +172,7 @@ os_sched(struct os_task *next_t, int isr)
         next_t = os_sched_next_task();
     }
 
-    if (next_t != os_sched_get_current_task()) {
+    if (next_t != g_current_task) {
         OS_EXIT_CRITICAL(sr);
         if (isr) {
             os_arch_ctx_sw_isr(next_t);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/src/os_task.c
----------------------------------------------------------------------
diff --git a/libs/os/src/os_task.c b/libs/os/src/os_task.c
index f9da560..950d54f 100644
--- a/libs/os/src/os_task.c
+++ b/libs/os/src/os_task.c
@@ -45,6 +45,12 @@ os_task_next_id(void)
     return (rc);
 }
 
+uint8_t 
+os_task_count(void)
+{
+    return (g_task_id);
+}
+
 int 
 os_task_sanity_checkin(struct os_task *t)
 {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/src/os_time.c
----------------------------------------------------------------------
diff --git a/libs/os/src/os_time.c b/libs/os/src/os_time.c
index cc2e819..9613159 100644
--- a/libs/os/src/os_time.c
+++ b/libs/os/src/os_time.c
@@ -17,7 +17,7 @@
 #include "os/os.h"
 #include "os/queue.h"
 
-static os_time_t g_os_time = 0;
+os_time_t g_os_time = 0;
 
 os_time_t  
 os_time_get(void)

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/util/src/stats.c
----------------------------------------------------------------------
diff --git a/libs/util/src/stats.c b/libs/util/src/stats.c
index 2ecc073..0d2eb36 100644
--- a/libs/util/src/stats.c
+++ b/libs/util/src/stats.c
@@ -101,6 +101,15 @@ shell_stats_display(int argc, char **argv)
     uint8_t *end;
 
     name = argv[1];
+    if (name == NULL || !strcmp(name, "")) {
+        console_printf("Must specify a statistic name to dump, "
+                "possible names are:\n");
+        STAILQ_FOREACH(hdr, &g_stats_registry, s_next) {
+            console_printf("\t%s\n", hdr->s_name);
+        }
+        goto done;
+    }
+
 
     hdr = stats_find(name);
     if (!hdr) {


Re: incubator-mynewt-larva git commit: add task info display. re-arrange the task structure a little, removing enum on task state and making it a uint8

Posted by Sterling Hughes <st...@apache.org>.
Hey,

Two things with this commit I wanted to see how people felt about.

1- I've done some re-arrangement of the task structure.

Specifically:

-    uint8_t t_pad[2];
+    uint8_t t_state;
+    uint8_t t_pad;

     char *t_name;
     os_task_func_t t_func;
@@ -57,8 +58,9 @@ struct os_task {

     struct os_sanity_check t_sanity_check;

-    os_task_state_t t_state;
     os_time_t t_next_wakeup;
+    os_time_t t_run_time;
+    uint32_t t_ctx_sw_cnt;


Prior to these changes task state (SLEEP, RDY) was an enum, taking up
4-bytes!  Bad!  (I think I may have done it this way originally :-)

If you look at this section of the structure, you now have:

  uint16_t t_stacksize;
  uint16_t t_flags;

  uint8_t t_taskid;
  uint8_t t_prio;
  uint8_t t_state;
  uint8_t t_pad;

With only 2-bits of flags being used.  I wonder if we should compress
this further, we could, for example:

- Make stack size a multiple of 8, and use 13 bits for it.  Take 2 of
those bits and make that the flags, and 1 bit to indicate Sleep or
ready.

- Eliminate state & pad.

Talking with Will, we decided this wasn't worth it.  We'd rather just
burn the 4-bytes in this structure.

2- In adding task profiling, I've made the structure a further 8-bytes
bigger, by adding context switch count and total run time.  In other
OS's, I've seen these two variable's #ifdef'd out, depending on
profiling level.

Some notes here:

- I've added them in os_arch_ctx_sw(), not within the ISR context.
This means that I could spuriously count a context switch, where the
OS wants to switch context, but before the PEND_SV (Cortex M* series)
interrupt actually swaps in the task, another, higher priority
interrupt executes and switches context to a new task.

I thought this was fine, because even if PEND_SV does switch context,
the interrupt could come before the task executed a single
instruction: there will always be some opportunity for jitter here.
I'd rather not do task accounting within an interrupt context, and
live with this.

- Total run time only increments at the granularity of the OS timer
(currently 1ms on ARM), which means that if you have smaller runtimes,
they won't be counted.  We have a more granular timer in the HAL, but
I decided it wasn't worth bringing in that dependency.  Therefore some
tasks, which execute very quickly, will show 0 runtime.

- Context switch count and total run time are very similar metrics.
However, because CSW count provides an indication of whether a task is
actually being scheduled, and runtime gives you an idea of how long
its been running, I think both are useful.

- There is one more statistic I want to add by default, which is total
stack usage.  This should be the maximum amount of stack used, as
opposed to what the current stack usage is.  I wonder if the task
should also record the bottom of the stack, so we can get the current
amount of stack usage?

Are there any other statistics we should be keeping?  Do folks think
that we should #ifdef these elements out?   I'm somewhat against it,
because I just think its useful enough to always know this, that the
slight efficiency gains you get aren't really worth it.  However, I
could be swayed.

Sterling











On Tue, Nov 17, 2015 at 10:39 AM,  <st...@apache.org> wrote:
> Repository: incubator-mynewt-larva
> Updated Branches:
>   refs/heads/master 55082ce6c -> e96c2c3c6
>
>
> add task info display.  re-arrange the task structure a little, removing enum on task state and making it a uint8
>
>
> Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/repo
> Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/commit/e96c2c3c
> Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/e96c2c3c
> Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/e96c2c3c
>
> Branch: refs/heads/master
> Commit: e96c2c3c6377452d9f7b40915f741116c8209eb3
> Parents: 55082ce
> Author: Sterling Hughes <st...@apache.org>
> Authored: Tue Nov 17 10:39:01 2015 -0800
> Committer: Sterling Hughes <st...@apache.org>
> Committed: Tue Nov 17 10:39:12 2015 -0800
>
> ----------------------------------------------------------------------
>  libs/os/egg.yml                          |   5 +
>  libs/os/include/os/os.h                  |   3 +
>  libs/os/include/os/os_sched.h            |   4 +
>  libs/os/include/os/os_task.h             |   7 +-
>  libs/os/src/arch/cortex_m4/os_arch_arm.c |   4 +
>  libs/os/src/arch/sim/os_arch_sim.c       |   4 +
>  libs/os/src/os.c                         |   3 +
>  libs/os/src/os_info.c                    | 167 ++++++++++++++++++++++++++
>  libs/os/src/os_sched.c                   |  56 ++++++++-
>  libs/os/src/os_task.c                    |   6 +
>  libs/os/src/os_time.c                    |   2 +-
>  libs/util/src/stats.c                    |   9 ++
>  12 files changed, 266 insertions(+), 4 deletions(-)
> ----------------------------------------------------------------------
>
>
> http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/egg.yml
> ----------------------------------------------------------------------
> diff --git a/libs/os/egg.yml b/libs/os/egg.yml
> index f9cddee..dd2657f 100644
> --- a/libs/os/egg.yml
> +++ b/libs/os/egg.yml
> @@ -4,3 +4,8 @@ egg.deps:
>      - libs/testutil
>  egg.req_caps:
>      - console
> +
> +egg.deps.SHELL:
> +    - libs/console/full
> +    - libs/shell
> +egg.cflags.SHELL: -DSHELL_PRESENT
>
> http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/include/os/os.h
> ----------------------------------------------------------------------
> diff --git a/libs/os/include/os/os.h b/libs/os/include/os/os.h
> index 62b4c11..938f8b7 100644
> --- a/libs/os/include/os/os.h
> +++ b/libs/os/include/os/os.h
> @@ -43,6 +43,8 @@
>   */
>  extern int g_os_started;
>
> +int os_info_init(void);
> +
>  /**
>   * Returns 1 if the OS has been started, 0 if it has not yet been
>   * been started.
> @@ -84,6 +86,7 @@ void os_init_idle_task(void);
>  #include "os/os_sched.h"
>  #include "os/os_eventq.h"
>  #include "os/os_callout.h"
> +#include "os/os_heap.h"
>  #include "os/os_mutex.h"
>  #include "os/os_sem.h"
>  #include "os/os_mempool.h"
>
> http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/include/os/os_sched.h
> ----------------------------------------------------------------------
> diff --git a/libs/os/include/os/os_sched.h b/libs/os/include/os/os_sched.h
> index ee84f76..a34c5e3 100644
> --- a/libs/os/include/os/os_sched.h
> +++ b/libs/os/include/os/os_sched.h
> @@ -19,6 +19,10 @@
>
>  #include "os/os_task.h"
>
> +typedef int (*os_sched_walk_func_t)(struct os_task *, void *arg);
> +
> +int os_sched_walk(os_sched_walk_func_t walk_func, void *arg);
> +void os_sched_ctx_sw_hook(struct os_task *);
>  struct os_task *os_sched_get_current_task(void);
>  void os_sched_set_current_task(struct os_task *);
>  struct os_task *os_sched_next_task(void);
>
> http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/include/os/os_task.h
> ----------------------------------------------------------------------
> diff --git a/libs/os/include/os/os_task.h b/libs/os/include/os/os_task.h
> index 8f7c746..3f75432 100644
> --- a/libs/os/include/os/os_task.h
> +++ b/libs/os/include/os/os_task.h
> @@ -47,7 +47,8 @@ struct os_task {
>
>      uint8_t t_taskid;
>      uint8_t t_prio;
> -    uint8_t t_pad[2];
> +    uint8_t t_state;
> +    uint8_t t_pad;
>
>      char *t_name;
>      os_task_func_t t_func;
> @@ -57,8 +58,9 @@ struct os_task {
>
>      struct os_sanity_check t_sanity_check;
>
> -    os_task_state_t t_state;
>      os_time_t t_next_wakeup;
> +    os_time_t t_run_time;
> +    uint32_t t_ctx_sw_cnt;
>
>      /* Used to chain task to either the run or sleep list */
>      TAILQ_ENTRY(os_task) t_os_list;
> @@ -71,6 +73,7 @@ int os_task_init(struct os_task *, char *, os_task_func_t, void *, uint8_t,
>          os_time_t, os_stack_t *, uint16_t);
>
>  int os_task_sanity_checkin(struct os_task *);
> +uint8_t os_task_count(void);
>
>
>  #endif /* _OS_TASK_H */
>
> http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/src/arch/cortex_m4/os_arch_arm.c
> ----------------------------------------------------------------------
> diff --git a/libs/os/src/arch/cortex_m4/os_arch_arm.c b/libs/os/src/arch/cortex_m4/os_arch_arm.c
> index 3cc7ca1..d941809 100755
> --- a/libs/os/src/arch/cortex_m4/os_arch_arm.c
> +++ b/libs/os/src/arch/cortex_m4/os_arch_arm.c
> @@ -99,6 +99,8 @@ timer_handler(void)
>  void
>  os_arch_ctx_sw(struct os_task *t)
>  {
> +    os_sched_ctx_sw_hook(t);
> +
>      /* Set PendSV interrupt pending bit to force context switch */
>      SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
>  }
> @@ -106,6 +108,8 @@ os_arch_ctx_sw(struct os_task *t)
>  void
>  os_arch_ctx_sw_isr(struct os_task *t)
>  {
> +    os_sched_ctx_sw_hook(t);
> +
>      /* Set PendSV interrupt pending bit to force context switch */
>      SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
>  }
>
> http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/src/arch/sim/os_arch_sim.c
> ----------------------------------------------------------------------
> diff --git a/libs/os/src/arch/sim/os_arch_sim.c b/libs/os/src/arch/sim/os_arch_sim.c
> index f2d57e3..2a1d585 100644
> --- a/libs/os/src/arch/sim/os_arch_sim.c
> +++ b/libs/os/src/arch/sim/os_arch_sim.c
> @@ -152,6 +152,8 @@ os_arch_ctx_sw(struct os_task *next_t)
>          }
>      }
>
> +    os_sched_ctx_sw_hook(next_t);
> +
>      os_sched_set_current_task(next_t);
>
>      sf = (struct stack_frame *) next_t->t_stackptr;
> @@ -196,6 +198,8 @@ os_arch_ctx_sw_isr(struct os_task *next_t)
>
>      isr_state(&block_isr_off, NULL);
>
> +    os_sched_ctx_sw_hook(next_t);
> +
>      os_sched_set_current_task(next_t);
>
>      sf = (struct stack_frame *) next_t->t_stackptr;
>
> http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/src/os.c
> ----------------------------------------------------------------------
> diff --git a/libs/os/src/os.c b/libs/os/src/os.c
> index 3ca3177..581db1d 100644
> --- a/libs/os/src/os.c
> +++ b/libs/os/src/os.c
> @@ -59,6 +59,9 @@ os_init(void)
>
>      err = os_arch_os_init();
>      assert(err == OS_OK);
> +
> +    err = os_info_init();
> +    assert(err == OS_OK);
>  }
>
>  void
>
> http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/src/os_info.c
> ----------------------------------------------------------------------
> diff --git a/libs/os/src/os_info.c b/libs/os/src/os_info.c
> new file mode 100644
> index 0000000..dde779d
> --- /dev/null
> +++ b/libs/os/src/os_info.c
> @@ -0,0 +1,167 @@
> +/**
> + * Copyright (c) 2015 Runtime Inc.
> + *
> + * Licensed under the Apache License, Version 2.0 (the "License");
> + * you may not use this file except in compliance with the License.
> + * You may obtain a copy of the License at
> + *
> + *   http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +
> +#include "os/os.h"
> +
> +#include "os/queue.h"
> +
> +#include "console/console.h"
> +#include "shell/shell.h"
> +
> +#include <string.h>
> +
> +struct os_task_info_walk {
> +    struct os_task_info *info;
> +    int info_cnt;
> +};
> +
> +#define OS_TASK_INFO_NAME_SIZE (32)
> +struct os_task_info {
> +    uint8_t oti_tid;
> +    uint8_t oti_prio;
> +    uint8_t oti_state;
> +    uint8_t oti_pad1;
> +    uint16_t oti_flags;
> +    uint16_t oti_stack_size;
> +    uint32_t oti_csw_cnt;
> +    os_time_t oti_next_wakeup;
> +    os_time_t oti_run_time;
> +    char oti_name[OS_TASK_INFO_NAME_SIZE];
> +};
> +
> +int os_task_info_get(struct os_task_info *info, int info_cnt);
> +
> +#ifdef SHELL_PRESENT
> +struct shell_cmd shell_os_tasks_display_cmd;
> +#endif
> +
> +
> +#ifdef SHELL_PRESENT
> +/* Code to register with shell, and display the results of os_getinfo()
> + */
> +
> +
> +int
> +shell_os_tasks_display(int argc, char **argv)
> +{
> +    struct os_task_info *info;
> +    char *name;
> +    int i;
> +    int found;
> +    int rc;
> +    uint8_t tcount;
> +
> +    name = NULL;
> +    found = 0;
> +
> +    if (argv[1] != NULL && strcmp(argv[1], "")) {
> +        name = argv[1];
> +    }
> +
> +    tcount = os_task_count();
> +
> +    info = (struct os_task_info *) os_malloc(
> +            sizeof(struct os_task_info) * tcount);
> +    if (!info) {
> +        rc = -1;
> +        goto err;
> +    }
> +
> +    rc = os_task_info_get(info, tcount);
> +
> +    console_printf("%d tasks: \n", rc);
> +    for (i = 0; i < rc; i++) {
> +        if (name) {
> +            if (strcmp(name, info[i].oti_name)) {
> +                continue;
> +            } else {
> +                found = 1;
> +            }
> +        }
> +
> +        console_printf("  %s (prio: %u, nw: %u, flags: 0x%x, "
> +                "ssize: %u, cswcnt: %lu, tot_run_time: %ums)",
> +                info[i].oti_name,
> +                info[i].oti_prio, info[i].oti_next_wakeup, info[i].oti_flags,
> +                info[i].oti_stack_size,
> +                info[i].oti_csw_cnt, info[i].oti_run_time);
> +
> +    }
> +
> +    if (name && !found) {
> +        console_printf("Couldn't find task with name %s\n", name);
> +    }
> +
> +    os_free(info);
> +
> +    return (0);
> +err:
> +    return (rc);
> +}
> +
> +
> +#endif
> +
> +static int
> +_os_task_copy_info(struct os_task *t, void *arg)
> +{
> +    struct os_task_info_walk *walk;
> +
> +    walk = (struct os_task_info_walk *) arg;
> +
> +    if (walk->info_cnt == 0) {
> +        /* Stored all the elements we can fit, exit out */
> +        return (1);
> +    }
> +
> +    walk->info->oti_tid = t->t_taskid;
> +    walk->info->oti_prio = t->t_prio;
> +    strlcpy(walk->info->oti_name, t->t_name, OS_TASK_INFO_NAME_SIZE);
> +    walk->info->oti_state = (uint8_t) t->t_state;
> +    walk->info->oti_next_wakeup = t->t_next_wakeup;
> +    walk->info->oti_flags = t->t_flags;
> +    walk->info->oti_stack_size = t->t_stacksize;
> +    walk->info->oti_csw_cnt = t->t_ctx_sw_cnt;
> +    walk->info->oti_run_time = t->t_run_time;
> +
> +    walk->info += 1;
> +    walk->info_cnt--;
> +
> +    return (0);
> +}
> +
> +int
> +os_task_info_get(struct os_task_info *info, int info_cnt)
> +{
> +    struct os_task_info_walk walk;
> +
> +    walk.info = info;
> +    walk.info_cnt = info_cnt;
> +
> +    os_sched_walk(_os_task_copy_info, (void *) &walk);
> +    return (info_cnt - walk.info_cnt);
> +}
> +
> +
> +int
> +os_info_init(void)
> +{
> +#ifdef SHELL_PRESENT
> +    shell_cmd_register(&shell_os_tasks_display_cmd, "tasks",
> +            shell_os_tasks_display);
> +#endif
> +    return (0);
> +}
>
> http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/src/os_sched.c
> ----------------------------------------------------------------------
> diff --git a/libs/os/src/os_sched.c b/libs/os/src/os_sched.c
> index 240bc62..0589e81 100644
> --- a/libs/os/src/os_sched.c
> +++ b/libs/os/src/os_sched.c
> @@ -25,6 +25,9 @@ TAILQ_HEAD(, os_task) g_os_sleep_list = TAILQ_HEAD_INITIALIZER(g_os_sleep_list);
>
>  struct os_task *g_current_task;
>
> +extern os_time_t g_os_time;
> +os_time_t g_os_last_ctx_sw_time;
> +
>  /**
>   * os sched insert
>   *
> @@ -68,6 +71,57 @@ err:
>  }
>
>  /**
> + * Walk all the active tasks currently being scheduled.
> + *
> + * @param walk_func The walk function to call for each task
> + * @param arg       The argument to pass the walk function
> + *
> + * @return 0 on success, < 0 on abort.
> + */
> +int
> +os_sched_walk(os_sched_walk_func_t walk_func, void *arg)
> +{
> +    struct os_task *t;
> +    os_sr_t sr;
> +    int rc;
> +
> +    /* Go through tasks and fill out the info blocks
> +     */
> +    OS_ENTER_CRITICAL(sr);
> +    TAILQ_FOREACH(t, &g_os_run_list, t_os_list) {
> +        rc = walk_func(t, arg);
> +        if (rc != 0) {
> +            goto done;
> +        }
> +    }
> +
> +    TAILQ_FOREACH(t, &g_os_sleep_list, t_os_list) {
> +        rc = walk_func(t, arg);
> +        if (rc != 0) {
> +            goto done;
> +        }
> +    }
> +
> +done:
> +    OS_EXIT_CRITICAL(sr);
> +
> +    return (rc);
> +}
> +
> +void
> +os_sched_ctx_sw_hook(struct os_task *next_t)
> +{
> +    if (g_current_task == next_t) {
> +        return;
> +    }
> +
> +    next_t->t_ctx_sw_cnt++;
> +    next_t->t_run_time += g_os_time - g_os_last_ctx_sw_time;
> +    g_os_last_ctx_sw_time = g_os_time;
> +}
> +
> +
> +/**
>   * os sched get current task
>   *
>   * Returns the currently running task. Note that this task may or may not be
> @@ -118,7 +172,7 @@ os_sched(struct os_task *next_t, int isr)
>          next_t = os_sched_next_task();
>      }
>
> -    if (next_t != os_sched_get_current_task()) {
> +    if (next_t != g_current_task) {
>          OS_EXIT_CRITICAL(sr);
>          if (isr) {
>              os_arch_ctx_sw_isr(next_t);
>
> http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/src/os_task.c
> ----------------------------------------------------------------------
> diff --git a/libs/os/src/os_task.c b/libs/os/src/os_task.c
> index f9da560..950d54f 100644
> --- a/libs/os/src/os_task.c
> +++ b/libs/os/src/os_task.c
> @@ -45,6 +45,12 @@ os_task_next_id(void)
>      return (rc);
>  }
>
> +uint8_t
> +os_task_count(void)
> +{
> +    return (g_task_id);
> +}
> +
>  int
>  os_task_sanity_checkin(struct os_task *t)
>  {
>
> http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/os/src/os_time.c
> ----------------------------------------------------------------------
> diff --git a/libs/os/src/os_time.c b/libs/os/src/os_time.c
> index cc2e819..9613159 100644
> --- a/libs/os/src/os_time.c
> +++ b/libs/os/src/os_time.c
> @@ -17,7 +17,7 @@
>  #include "os/os.h"
>  #include "os/queue.h"
>
> -static os_time_t g_os_time = 0;
> +os_time_t g_os_time = 0;
>
>  os_time_t
>  os_time_get(void)
>
> http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e96c2c3c/libs/util/src/stats.c
> ----------------------------------------------------------------------
> diff --git a/libs/util/src/stats.c b/libs/util/src/stats.c
> index 2ecc073..0d2eb36 100644
> --- a/libs/util/src/stats.c
> +++ b/libs/util/src/stats.c
> @@ -101,6 +101,15 @@ shell_stats_display(int argc, char **argv)
>      uint8_t *end;
>
>      name = argv[1];
> +    if (name == NULL || !strcmp(name, "")) {
> +        console_printf("Must specify a statistic name to dump, "
> +                "possible names are:\n");
> +        STAILQ_FOREACH(hdr, &g_stats_registry, s_next) {
> +            console_printf("\t%s\n", hdr->s_name);
> +        }
> +        goto done;
> +    }
> +
>
>      hdr = stats_find(name);
>      if (!hdr) {
>