event: governor implementation
Signed-off-by: Maciej Szwed <maciej.szwed@intel.com> Change-Id: I9aaa84261144145933d227976a5f89dc89732267 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4028 Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com> Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
This commit is contained in:
parent
2cffc80079
commit
c6adf304bd
@ -175,6 +175,91 @@ void spdk_subsystem_config_json(struct spdk_json_write_ctx *w, struct spdk_subsy
|
||||
void spdk_rpc_initialize(const char *listen_addr);
|
||||
void spdk_rpc_finish(void);
|
||||
|
||||
struct spdk_governor_capabilities {
|
||||
bool freq_change;
|
||||
bool freq_getset;
|
||||
bool freq_up;
|
||||
bool freq_down;
|
||||
bool freq_max;
|
||||
bool freq_min;
|
||||
bool turbo_set;
|
||||
bool turbo_available;
|
||||
bool priority;
|
||||
};
|
||||
|
||||
/** Cores governor */
|
||||
struct spdk_governor {
|
||||
char *name;
|
||||
|
||||
/* freqs - the buffer array to save the frequencies; num - the number of frequencies to get; return - the number of available frequencies */
|
||||
uint32_t (*get_core_freqs)(uint32_t lcore_id, uint32_t *freqs, uint32_t num);
|
||||
|
||||
/* return - current frequency */
|
||||
uint32_t (*get_core_curr_freq)(uint32_t lcore_id);
|
||||
|
||||
/**
|
||||
* freq_index - index of available frequencies returned from get_core_freqs call
|
||||
*
|
||||
* return
|
||||
* - 1 on success with frequency changed.
|
||||
* - 0 on success without frequency changed.
|
||||
* - Negative on error.
|
||||
*/
|
||||
int (*set_core_freq)(uint32_t lcore_id, uint32_t freq_index);
|
||||
int (*core_freq_up)(uint32_t lcore_id);
|
||||
int (*core_freq_down)(uint32_t lcore_id);
|
||||
int (*set_core_freq_max)(uint32_t lcore_id);
|
||||
int (*set_core_freq_min)(uint32_t lcore_id);
|
||||
|
||||
/**
|
||||
* return
|
||||
* - 1 Turbo Boost is enabled for this lcore.
|
||||
* - 0 Turbo Boost is disabled for this lcore.
|
||||
* - Negative on error.
|
||||
*/
|
||||
int (*get_core_turbo_status)(uint32_t lcore_id);
|
||||
|
||||
/* return - 0 on success; negative on error */
|
||||
int (*enable_core_turbo)(uint32_t lcore_id);
|
||||
int (*disable_core_turbo)(uint32_t lcore_id);
|
||||
int (*get_core_capabilities)(uint32_t lcore_id, struct spdk_governor_capabilities *capabilities);
|
||||
int (*init_core)(uint32_t lcore_id);
|
||||
int (*deinit_core)(uint32_t lcore_id);
|
||||
int (*init)(void);
|
||||
int (*deinit)(void);
|
||||
|
||||
TAILQ_ENTRY(spdk_governor) link;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add the given governor to the list of registered governors.
|
||||
* This function should be invoked by referencing the macro
|
||||
* SPDK_GOVERNOR_REGISTER in the governor c file.
|
||||
*
|
||||
* \param governor Governor to be added.
|
||||
*
|
||||
* \return 0 on success or non-zero on failure.
|
||||
*/
|
||||
void _spdk_governor_list_add(struct spdk_governor *governor);
|
||||
|
||||
/**
|
||||
* Change current governor.
|
||||
*
|
||||
* \param name Name of the governor to be used.
|
||||
*
|
||||
* \return 0 on success or non-zero on failure.
|
||||
*/
|
||||
int _spdk_governor_set(char *name);
|
||||
|
||||
/**
|
||||
* Macro used to register new cores governor.
|
||||
*/
|
||||
#define SPDK_GOVERNOR_REGISTER(governor) \
|
||||
static void __attribute__((constructor)) _spdk_governor_register_##name(void) \
|
||||
{ \
|
||||
_spdk_governor_list_add(governor); \
|
||||
} \
|
||||
|
||||
/**
|
||||
* A list of cores and threads which is used for scheduling.
|
||||
*/
|
||||
@ -190,19 +275,20 @@ struct spdk_scheduler_core_info {
|
||||
* Scheduler balance function type.
|
||||
* Accepts array of core_info which is of size 'count' and returns updated array.
|
||||
*/
|
||||
typedef void (*spdk_scheduler_balance_fn)(struct spdk_scheduler_core_info *core_info, int count);
|
||||
typedef void (*spdk_scheduler_balance_fn)(struct spdk_scheduler_core_info *core_info, int count,
|
||||
struct spdk_governor *governor);
|
||||
|
||||
/**
|
||||
* Scheduler init function type.
|
||||
* Called on scheduler module initialization.
|
||||
*/
|
||||
typedef int (*spdk_scheduler_init_fn)(void);
|
||||
typedef int (*spdk_scheduler_init_fn)(struct spdk_governor *governor);
|
||||
|
||||
/**
|
||||
* Scheduler deinitialization function type.
|
||||
* Called on reactor fini.
|
||||
*/
|
||||
typedef int (*spdk_scheduler_deinit_fn)(void);
|
||||
typedef int (*spdk_scheduler_deinit_fn)(struct spdk_governor *governor);
|
||||
|
||||
/** Thread scheduler */
|
||||
struct spdk_scheduler {
|
||||
|
@ -70,6 +70,17 @@ static struct spdk_reactor *g_scheduling_reactor;
|
||||
static uint32_t g_scheduler_period;
|
||||
static struct spdk_scheduler_core_info *g_core_infos = NULL;
|
||||
|
||||
TAILQ_HEAD(, spdk_governor) g_governor_list
|
||||
= TAILQ_HEAD_INITIALIZER(g_governor_list);
|
||||
|
||||
static int _governor_get_capabilities(uint32_t lcore_id,
|
||||
struct spdk_governor_capabilities *capabilities);
|
||||
|
||||
static struct spdk_governor g_governor = {
|
||||
.name = "default",
|
||||
.get_core_capabilities = _governor_get_capabilities,
|
||||
};
|
||||
|
||||
static int reactor_interrupt_init(struct spdk_reactor *reactor);
|
||||
static void reactor_interrupt_fini(struct spdk_reactor *reactor);
|
||||
|
||||
@ -98,8 +109,12 @@ _spdk_scheduler_set(char *name)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (g_scheduler != NULL && g_scheduler->deinit != NULL) {
|
||||
g_scheduler->deinit(&g_governor);
|
||||
}
|
||||
|
||||
if (scheduler->init != NULL) {
|
||||
scheduler->init();
|
||||
scheduler->init(&g_governor);
|
||||
}
|
||||
|
||||
g_scheduler = scheduler;
|
||||
@ -232,7 +247,7 @@ spdk_reactors_fini(void)
|
||||
}
|
||||
|
||||
if (g_scheduler->deinit != NULL) {
|
||||
g_scheduler->deinit();
|
||||
g_scheduler->deinit(&g_governor);
|
||||
}
|
||||
|
||||
spdk_thread_lib_fini();
|
||||
@ -477,7 +492,7 @@ _reactors_scheduler_fini(void *arg1, void *arg2)
|
||||
|
||||
if (g_reactor_state == SPDK_REACTOR_STATE_RUNNING) {
|
||||
last_core = spdk_env_get_last_core();
|
||||
g_scheduler->balance(g_core_infos, last_core + 1);
|
||||
g_scheduler->balance(g_core_infos, last_core + 1, &g_governor);
|
||||
|
||||
/* Reschedule based on the balancing output */
|
||||
_threads_reschedule(g_core_infos);
|
||||
@ -1115,4 +1130,79 @@ _spdk_lw_thread_get_current_stats(struct spdk_lw_thread *thread, struct spdk_thr
|
||||
*stats = thread->current_stats;
|
||||
}
|
||||
|
||||
static int
|
||||
_governor_get_capabilities(uint32_t lcore_id, struct spdk_governor_capabilities *capabilities)
|
||||
{
|
||||
capabilities->freq_change = false;
|
||||
capabilities->freq_getset = false;
|
||||
capabilities->freq_up = false;
|
||||
capabilities->freq_down = false;
|
||||
capabilities->freq_max = false;
|
||||
capabilities->freq_min = false;
|
||||
capabilities->turbo_set = false;
|
||||
capabilities->priority = false;
|
||||
capabilities->turbo_available = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spdk_governor *
|
||||
_governor_find(char *name)
|
||||
{
|
||||
struct spdk_governor *governor, *tmp;
|
||||
|
||||
TAILQ_FOREACH_SAFE(governor, &g_governor_list, link, tmp) {
|
||||
if (strcmp(name, governor->name) == 0) {
|
||||
return governor;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
_spdk_governor_set(char *name)
|
||||
{
|
||||
struct spdk_governor *governor;
|
||||
uint32_t i;
|
||||
int rc;
|
||||
|
||||
governor = _governor_find(name);
|
||||
if (governor == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
g_governor = *governor;
|
||||
|
||||
if (g_governor.init) {
|
||||
rc = g_governor.init();
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
SPDK_ENV_FOREACH_CORE(i) {
|
||||
if (g_governor.init_core) {
|
||||
rc = g_governor.init_core(i);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
_spdk_governor_list_add(struct spdk_governor *governor)
|
||||
{
|
||||
if (_governor_find(governor->name)) {
|
||||
SPDK_ERRLOG("governor named '%s' already registered.\n", governor->name);
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
TAILQ_INSERT_TAIL(&g_governor_list, governor, link);
|
||||
}
|
||||
|
||||
SPDK_LOG_REGISTER_COMPONENT(reactor)
|
||||
|
Loading…
Reference in New Issue
Block a user