pm: move stats code into its own file

Stats are an optional feature, moving it into a separate source file
improves code readability.

Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
This commit is contained in:
Gerard Marull-Paretas 2021-11-22 19:08:35 +01:00 committed by Carles Cufí
commit 7baed3dd3e
4 changed files with 105 additions and 74 deletions

View file

@ -1,7 +1,10 @@
# SPDX-License-Identifier: Apache-2.0
zephyr_sources_ifdef(CONFIG_PM power.c)
zephyr_sources_ifdef(CONFIG_PM pm_ctrl.c)
if(CONFIG_PM)
zephyr_sources(power.c pm_ctrl.c)
zephyr_sources_ifdef(CONFIG_PM_STATS pm_stats.c)
endif()
zephyr_sources_ifdef(CONFIG_PM_DEVICE device.c)
zephyr_sources_ifdef(CONFIG_PM_DEVICE_RUNTIME device_runtime.c)
add_subdirectory(policy)

75
subsys/pm/pm_stats.c Normal file
View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2018 Intel Corporation.
* Copyright (c) 2021 Nordic Semiconductor ASA.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "pm_stats.h"
#include <autoconf.h>
#include <init.h>
#include <kernel_structs.h>
#include <stats/stats.h>
#include <sys/printk.h>
struct pm_cpu_timing {
uint32_t timer_start;
uint32_t timer_end;
};
static struct pm_cpu_timing pm_cpu_timings[CONFIG_MP_NUM_CPUS];
STATS_SECT_START(pm_cpu_stats)
STATS_SECT_ENTRY32(state_count)
STATS_SECT_ENTRY32(state_last_cycles)
STATS_SECT_ENTRY32(state_total_cycles)
STATS_SECT_END;
STATS_NAME_START(pm_cpu_stats)
STATS_NAME(pm_cpu_stats, state_count)
STATS_NAME(pm_cpu_stats, state_last_cycles)
STATS_NAME(pm_cpu_stats, state_total_cycles)
STATS_NAME_END(pm_cpu_stats);
#define PM_STAT_NAME_LEN sizeof("pm_cpu_XXX_state_X_stats")
static char pm_cpu_stat_names[CONFIG_MP_NUM_CPUS][PM_STATE_COUNT][PM_STAT_NAME_LEN];
static struct stats_pm_cpu_stats pm_cpu_stats[CONFIG_MP_NUM_CPUS][PM_STATE_COUNT];
static int pm_stats_init(const struct device *unused)
{
for (int i = 0; i < CONFIG_MP_NUM_CPUS; i++) {
for (int j = 0; j < PM_STATE_COUNT; j++) {
snprintk(pm_cpu_stat_names[i][j], PM_STAT_NAME_LEN,
"pm_cpu_%03d_state_%1d_stats", i, j);
stats_init(&(pm_cpu_stats[i][j].s_hdr), STATS_SIZE_32, 3,
STATS_NAME_INIT_PARMS(pm_cpu_stats));
stats_register(pm_cpu_stat_names[i][j], &(pm_cpu_stats[i][j].s_hdr));
}
}
return 0;
}
SYS_INIT(pm_stats_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
void pm_start_timer(void)
{
pm_cpu_timings[_current_cpu->id].timer_start = k_cycle_get_32();
}
void pm_stop_timer(void)
{
pm_cpu_timings[_current_cpu->id].timer_end = k_cycle_get_32();
}
void pm_stats_update(enum pm_state state)
{
uint8_t cpu = _current_cpu->id;
uint32_t time_total =
pm_cpu_timings[cpu].timer_end -
pm_cpu_timings[cpu].timer_start;
STATS_INC(pm_cpu_stats[cpu][state], state_count);
STATS_INCN(pm_cpu_stats[cpu][state], state_total_cycles, time_total);
STATS_SET(pm_cpu_stats[cpu][state], state_last_cycles, time_total);
}

23
subsys/pm/pm_stats.h Normal file
View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2018 Intel Corporation.
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_SUBSYS_PM_PM_STATS_H_
#define ZEPHYR_SUBSYS_PM_PM_STATS_H_
#include <pm/state.h>
#ifdef CONFIG_PM_STATS
void pm_start_timer(void);
void pm_stop_timer(void);
void pm_stats_update(enum pm_state state);
#else
static inline void pm_start_timer(void) {}
static inline void pm_stop_timer(void) {}
static inline void pm_stats_update(enum pm_state state) {}
#endif /* CONFIG_PM_STATS */
#endif /* ZEPHYR_SUBSYS_PM_PM_STATS_H_ */

View file

@ -17,6 +17,8 @@
#include <pm/policy.h>
#include <tracing/tracing.h>
#include "pm_stats.h"
#include <logging/log.h>
LOG_MODULE_REGISTER(pm, CONFIG_PM_LOG_LEVEL);
@ -30,79 +32,7 @@ static atomic_t z_cpus_active = ATOMIC_INIT(CONFIG_MP_NUM_CPUS);
#endif
static struct k_spinlock pm_notifier_lock;
#ifdef CONFIG_PM_STATS
#include <stats/stats.h>
#include <sys/util_macro.h>
struct pm_cpu_timing {
uint32_t timer_start;
uint32_t timer_end;
};
static struct pm_cpu_timing pm_cpu_timings[CONFIG_MP_NUM_CPUS];
static inline void pm_start_timer(void)
{
pm_cpu_timings[_current_cpu->id].timer_start = k_cycle_get_32();
}
static inline void pm_stop_timer(void)
{
pm_cpu_timings[_current_cpu->id].timer_end = k_cycle_get_32();
}
STATS_SECT_START(pm_cpu_stats)
STATS_SECT_ENTRY32(state_count)
STATS_SECT_ENTRY32(state_last_cycles)
STATS_SECT_ENTRY32(state_total_cycles)
STATS_SECT_END;
STATS_NAME_START(pm_cpu_stats)
STATS_NAME(pm_cpu_stats, state_count)
STATS_NAME(pm_cpu_stats, state_last_cycles)
STATS_NAME(pm_cpu_stats, state_total_cycles)
STATS_NAME_END(pm_cpu_stats);
#define PM_STAT_NAME_LEN sizeof("pm_cpu_XXX_state_X_stats")
static char pm_cpu_stat_names[CONFIG_MP_NUM_CPUS][PM_STATE_COUNT][PM_STAT_NAME_LEN];
static struct stats_pm_cpu_stats pm_cpu_stats[CONFIG_MP_NUM_CPUS][PM_STATE_COUNT];
static int pm_stats_init(const struct device *unused)
{
for (int i = 0; i < CONFIG_MP_NUM_CPUS; i++) {
for (int j = 0; j < PM_STATE_COUNT; j++) {
snprintk(pm_cpu_stat_names[i][j], PM_STAT_NAME_LEN,
"pm_cpu_%03d_state_%1d_stats", i, j);
stats_init(&(pm_cpu_stats[i][j].s_hdr), STATS_SIZE_32, 3,
STATS_NAME_INIT_PARMS(pm_cpu_stats));
stats_register(pm_cpu_stat_names[i][j], &(pm_cpu_stats[i][j].s_hdr));
}
}
return 0;
}
SYS_INIT(pm_stats_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
static void pm_stats_update(enum pm_state state)
{
uint8_t cpu = _current_cpu->id;
uint32_t time_total =
pm_cpu_timings[cpu].timer_end -
pm_cpu_timings[cpu].timer_start;
STATS_INC(pm_cpu_stats[cpu][state], state_count);
STATS_INCN(pm_cpu_stats[cpu][state], state_total_cycles, time_total);
STATS_SET(pm_cpu_stats[cpu][state], state_last_cycles, time_total);
}
#else
static inline void pm_start_timer(void) {}
static inline void pm_stop_timer(void) {}
static void pm_stats_update(enum pm_state state) {}
#endif
#ifdef CONFIG_PM_DEVICE
extern const struct device *__pm_device_slots_start[];