diff options
-rw-r--r-- | projects/hsm/Makefile | 2 | ||||
-rw-r--r-- | projects/hsm/mgmt-task.c | 34 | ||||
-rw-r--r-- | task.c | 48 | ||||
-rw-r--r-- | task.h | 11 |
4 files changed, 94 insertions, 1 deletions
diff --git a/projects/hsm/Makefile b/projects/hsm/Makefile index 927c9f1..ecd1a5d 100644 --- a/projects/hsm/Makefile +++ b/projects/hsm/Makefile @@ -13,6 +13,8 @@ OBJS = mgmt-cli.o \ BOARD_OBJS += $(TOPLEVEL)/task.o +CFLAGS += -DTASK_METRICS + CFLAGS += -DNUM_RPC_TASK=4 CFLAGS += -I$(LIBHAL_SRC) diff --git a/projects/hsm/mgmt-task.c b/projects/hsm/mgmt-task.c index a1ae7e6..12ce2b8 100644 --- a/projects/hsm/mgmt-task.c +++ b/projects/hsm/mgmt-task.c @@ -69,10 +69,42 @@ static int cmd_task_show(struct cli_def *cli, const char *command, char *argv[], return CLI_OK; } +#ifdef TASK_METRICS +static int cmd_task_show_metrics(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + struct task_metrics tm; + + task_get_metrics(&tm); + + cli_print(cli, "avg time between yields: %ld.%06ld sec", tm.avg.tv_sec, tm.avg.tv_usec); + cli_print(cli, "max time between yields: %ld.%06ld sec", tm.max.tv_sec, tm.max.tv_usec); + + return CLI_OK; +} + +static int cmd_task_reset_metrics(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + task_reset_metrics(); + + return CLI_OK; +} +#endif + void configure_cli_task(struct cli_def *cli) { struct cli_command *c = cli_register_command(cli, NULL, "task", NULL, 0, 0, NULL); /* task show */ - cli_register_command(cli, c, "show", cmd_task_show, 0, 0, "Show the active tasks"); + struct cli_command *c_show = cli_register_command(cli, c, "show", cmd_task_show, 0, 0, "Show the active tasks"); + +#ifdef TASK_METRICS + /* task show metrics */ + cli_register_command(cli, c_show, "metrics", cmd_task_show_metrics, 0, 0, "Show task metrics"); + + /* task reset */ + struct cli_command *c_reset = cli_register_command(cli, c, "reset", NULL, 0, 0, NULL); + + /* task reset metrics */ + cli_register_command(cli, c_reset, "metrics", cmd_task_reset_metrics, 0, 0, "Reset task metrics"); +#endif } @@ -81,6 +81,14 @@ static tcb_t *cur_task = NULL; #define STACK_GUARD_WORD 0x55AA5A5A +#ifdef TASK_METRICS +static uint32_t tick_start = 0; +static uint32_t tick_prev = 0; +static uint32_t tick_idle = 0; +static uint32_t tick_max = 0; +static uint32_t nyield = 0; +#endif + /* Add a task. */ tcb_t *task_add(char *name, funcp_t func, void *cookie, void *stack, size_t stack_len) @@ -180,6 +188,10 @@ void task_yield(void) if (tail == NULL) return; +#ifdef TASK_METRICS + uint32_t tick0 = HAL_GetTick(); +#endif + /* Find the next runnable task. Loop if every task is waiting. */ while (1) { next = next_task(); @@ -197,6 +209,20 @@ void task_yield(void) * } while (next == NULL); */ +#ifdef TASK_METRICS + uint32_t tick = HAL_GetTick(); + tick_idle += (tick - tick0); + if (tick_start == 0) + tick_start = tick; + if (tick_prev != 0) { + uint32_t duration = tick0 - tick_prev; + if (duration > tick_max) + tick_max = duration; + } + tick_prev = tick; + ++nyield; +#endif + /* If there are no other runnable tasks (and cur_task is runnable), * we don't need to context-switch. */ @@ -354,3 +380,25 @@ void task_mutex_unlock(task_mutex_t *mutex) if (mutex != NULL) mutex->locked = 0; } + +#ifdef TASK_METRICS +void task_get_metrics(struct task_metrics *tm) +{ + if (tm != NULL) { + tm->avg.tv_sec = 0; + tm->avg.tv_usec = (HAL_GetTick() - tick_start - tick_idle) * 1000 / nyield; + if (tm->avg.tv_usec > 1000000) { + tm->avg.tv_sec = tm->avg.tv_usec / 1000000; + tm->avg.tv_usec = tm->avg.tv_usec % 1000000; + } + tm->max.tv_sec = tick_max / 1000; + tm->max.tv_usec = (tick_max % 1000) * 1000; + } +} + +void task_reset_metrics(void) +{ + tick_start = HAL_GetTick(); + tick_prev = tick_idle = tick_max = nyield = 0; +} +#endif @@ -73,4 +73,15 @@ extern void task_delay(uint32_t delay); extern void task_mutex_lock(task_mutex_t *mutex); extern void task_mutex_unlock(task_mutex_t *mutex); +#ifdef TASK_METRICS +#include <sys/time.h> + +struct task_metrics { + struct timeval avg, max; +}; + +void task_get_metrics(struct task_metrics *tm); +void task_reset_metrics(void); +#endif + #endif /* _TASK_H_ */ |