scheduler: create public API and subsystem for scheduler/governor

This patch moves schedueler and governor related API from
the internal event.h to public scheduler.h.

With this it is possible to create subsystem responsible
for handling the schedulers.
Three schedulers and a governor were moved to scheduler modules
from event framework.

This will allow next patch to add JSON RPC configuration
to the whole subsystem.
Along with easier addition of other schedulers.

Removed debug logs from gscheduler, as they serve little purpose.

Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: I98ca1ea4fb281beb71941656444267842a8875b7
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6995
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Community-CI: Mellanox Build Bot
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
Tomasz Zawadzki 2021-08-06 05:17:16 -04:00
parent b518cbe2d4
commit a86e40f320
24 changed files with 672 additions and 295 deletions

286
include/spdk/scheduler.h Normal file
View File

@ -0,0 +1,286 @@
/*-
* BSD LICENSE
*
* Copyright (c) Intel Corporation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SPDK_SCHEDULER_H
#define SPDK_SCHEDULER_H
#include "spdk/stdinc.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "spdk/event.h"
#include "spdk/json.h"
#include "spdk/thread.h"
#include "spdk/util.h"
struct spdk_governor_capabilities {
bool priority; /* Core with higher base frequency */
};
/**
* Cores governor
* Implements core frequency control for schedulers. Functions from this structure
* are invoked from scheduling reactor.
*/
struct spdk_governor {
const char *name;
/**
* Get current frequency of a given core.
*
* \param lcore_id Core number.
*
* \return Currently set core frequency.
*/
uint32_t (*get_core_curr_freq)(uint32_t lcore_id);
/**
* Increase core frequency to next available one.
*
* \param lcore_id Core number.
*
* \return 1 on success, 0 already at max frequency, negative on error.
*/
int (*core_freq_up)(uint32_t lcore_id);
/**
* Decrease core frequency to next available one.
*
* \param lcore_id Core number.
*
* \return 1 on success, 0 already at min frequency, negative on error.
*/
int (*core_freq_down)(uint32_t lcore_id);
/**
* Set core frequency to maximum available.
*
* \param lcore_id Core number.
*
* \return 1 on success, 0 already at max frequency, negative on error.
*/
int (*set_core_freq_max)(uint32_t lcore_id);
/**
* Set core frequency to minimum available.
*
* \param lcore_id Core number.
*
* \return 1 on success, 0 already at min frequency, negative on error.
*/
int (*set_core_freq_min)(uint32_t lcore_id);
/**
* Get capabilities of a given core.
*
* \param lcore_id Core number.
* \param capabilities Structure to fill with capabilities data.
*
* \return 0 on success, negative on error.
*/
int (*get_core_capabilities)(uint32_t lcore_id, struct spdk_governor_capabilities *capabilities);
/**
* Initialize a governor.
*
* \return 0 on success, non-zero on error.
*/
int (*init)(void);
/**
* Deinitialize a governor.
*/
void (*deinit)(void);
TAILQ_ENTRY(spdk_governor) link;
};
/**
* Set the current governor.
*
* Always deinitalizes previously set governor.
* No governor will be set if name parameter is NULL.
* This function should be invoked on scheduling reactor.
*
* \param name Name of the governor to be used.
*
* \return 0 on success or non-zero on failure.
*/
int spdk_governor_set(const char *name);
/**
* Get currently set governor.
*
* \return a pointer to spdk governor or NULL if none is set.
*/
struct spdk_governor *spdk_governor_get(void);
/**
* 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_register(struct spdk_governor *governor);
/**
* Macro used to register new governors.
*/
#define SPDK_GOVERNOR_REGISTER(governor) \
static void __attribute__((constructor)) _spdk_governor_register_ ## governor(void) \
{ \
spdk_governor_register(&governor); \
} \
/**
* Structure representing thread used for scheduling.
*/
struct spdk_scheduler_thread_info {
uint32_t lcore;
uint64_t thread_id;
/* stats over a lifetime of a thread */
struct spdk_thread_stats total_stats;
/* stats during the last scheduling period */
struct spdk_thread_stats current_stats;
};
/**
* A list of cores and threads which is used for scheduling.
*/
struct spdk_scheduler_core_info {
/* stats over a lifetime of a core */
uint64_t total_idle_tsc;
uint64_t total_busy_tsc;
/* stats during the last scheduling period */
uint64_t current_idle_tsc;
uint64_t current_busy_tsc;
uint32_t lcore;
uint32_t threads_count;
bool interrupt_mode;
struct spdk_scheduler_thread_info *thread_infos;
};
/**
* Thread scheduler.
* Functions from this structure are invoked from scheduling reactor.
*/
struct spdk_scheduler {
const char *name;
/**
* This function is called to initialize a scheduler.
*
* \return 0 on success or non-zero on failure.
*/
int (*init)(void);
/**
* This function is called to deinitialize a scheduler.
*/
void (*deinit)(void);
/**
* Function to balance threads across cores by modifying
* the value of their lcore field.
*
* \param core_info Structure describing cores and threads on them.
* \param count Size of the core_info array.
*/
void (*balance)(struct spdk_scheduler_core_info *core_info, uint32_t count);
TAILQ_ENTRY(spdk_scheduler) link;
};
/**
* Change current scheduler. If another scheduler was used prior,
* it will be deinitalized. No scheduler will be set if name parameter
* is NULL.
* This function should be invoked from scheduling reactor.
*
* \param name Name of the scheduler to be used.
*
* \return 0 on success or non-zero on failure.
*/
int spdk_scheduler_set(const char *name);
/**
* Get currently set scheduler.
*
* \return a pointer to spdk scheduler or NULL if none is set.
*/
struct spdk_scheduler *spdk_scheduler_get(void);
/**
* Change current scheduling period.
* Setting period to 0 disables scheduling.
*
* \param period Period to set in microseconds.
*/
void spdk_scheduler_set_period(uint64_t period);
/**
* Get scheduling period of currently set scheduler.
*
* \return Scheduling period in microseconds.
*/
uint64_t spdk_scheduler_get_period(void);
/**
* Add the given scheduler to the list of registered schedulers.
* This function should be invoked by referencing the macro
* SPDK_SCHEDULER_REGISTER in the scheduler c file.
*
* \param scheduler Scheduler to be added.
*/
void spdk_scheduler_register(struct spdk_scheduler *scheduler);
/*
* Macro used to register new scheduler.
*/
#define SPDK_SCHEDULER_REGISTER(scheduler) \
static void __attribute__((constructor)) _spdk_scheduler_register_ ## scheduler (void) \
{ \
spdk_scheduler_register(&scheduler); \
} \
#ifdef __cplusplus
}
#endif
#endif /* SPDK_SCHEDULER_H */

View File

@ -163,240 +163,6 @@ int spdk_reactor_set_interrupt_mode(uint32_t lcore, bool new_in_interrupt,
*/
struct spdk_thread *_spdk_get_app_thread(void);
struct spdk_governor_capabilities {
bool priority; /* Core with higher base frequency */
};
/**
* Cores governor
* Implements core frequency control for schedulers. Functions from this structure
* are invoked from scheduling reactor.
*/
struct spdk_governor {
const char *name;
/**
* Get current frequency of a given core.
*
* \param lcore_id Core number.
*
* \return Currently set core frequency.
*/
uint32_t (*get_core_curr_freq)(uint32_t lcore_id);
/**
* Increase core frequency to next available one.
*
* \param lcore_id Core number.
*
* \return 1 on success, 0 already at max frequency, negative on error.
*/
int (*core_freq_up)(uint32_t lcore_id);
/**
* Decrease core frequency to next available one.
*
* \param lcore_id Core number.
*
* \return 1 on success, 0 already at min frequency, negative on error.
*/
int (*core_freq_down)(uint32_t lcore_id);
/**
* Set core frequency to maximum available.
*
* \param lcore_id Core number.
*
* \return 1 on success, 0 already at max frequency, negative on error.
*/
int (*set_core_freq_max)(uint32_t lcore_id);
/**
* Set core frequency to minimum available.
*
* \param lcore_id Core number.
*
* \return 1 on success, 0 already at min frequency, negative on error.
*/
int (*set_core_freq_min)(uint32_t lcore_id);
/**
* Get capabilities of a given core.
*
* \param lcore_id Core number.
* \param capabilities Structure to fill with capabilities data.
*
* \return 0 on success, negative on error.
*/
int (*get_core_capabilities)(uint32_t lcore_id, struct spdk_governor_capabilities *capabilities);
/**
* Initialize a governor.
*
* \return 0 on success, non-zero on error.
*/
int (*init)(void);
/**
* Deinitialize a governor.
*/
void (*deinit)(void);
TAILQ_ENTRY(spdk_governor) link;
};
/**
* Set the current governor.
*
* Always deinitalizes previously set governor.
* No governor will be set if name parameter is NULL.
* This function should be invoked on scheduling reactor.
*
* \param name Name of the governor to be used.
*
* \return 0 on success or non-zero on failure.
*/
int _spdk_governor_set(const char *name);
/**
* Get currently set governor.
*
* \return a pointer to spdk governor or NULL if none is set.
*/
struct spdk_governor *_spdk_governor_get(void);
/**
* 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_register(struct spdk_governor *governor);
/**
* Macro used to register new governors.
*/
#define SPDK_GOVERNOR_REGISTER(governor) \
static void __attribute__((constructor)) _spdk_governor_register_ ## governor(void) \
{ \
_spdk_governor_register(&governor); \
} \
/**
* Structure representing thread used for scheduling.
*/
struct spdk_scheduler_thread_info {
uint32_t lcore;
uint64_t thread_id;
/* stats over a lifetime of a thread */
struct spdk_thread_stats total_stats;
/* stats during the last scheduling period */
struct spdk_thread_stats current_stats;
};
/**
* A list of cores and threads which is used for scheduling.
*/
struct spdk_scheduler_core_info {
/* stats over a lifetime of a core */
uint64_t total_idle_tsc;
uint64_t total_busy_tsc;
/* stats during the last scheduling period */
uint64_t current_idle_tsc;
uint64_t current_busy_tsc;
uint32_t lcore;
uint32_t threads_count;
bool interrupt_mode;
struct spdk_scheduler_thread_info *thread_infos;
};
/**
* Thread scheduler.
* Functions from this structure are invoked from scheduling reactor.
*/
struct spdk_scheduler {
const char *name;
/**
* This function is called to initialize a scheduler.
*
* \return 0 on success or non-zero on failure.
*/
int (*init)(void);
/**
* This function is called to deinitialize a scheduler.
*/
void (*deinit)(void);
/**
* Function to balance threads across cores by modifying
* the value of their lcore field.
*
* \param core_info Structure describing cores and threads on them.
* \param count Size of the core_info array.
*/
void (*balance)(struct spdk_scheduler_core_info *core_info, uint32_t count);
TAILQ_ENTRY(spdk_scheduler) link;
};
/**
* Change current scheduler. If another scheduler was used prior,
* it will be deinitalized. No scheduler will be set if name parameter
* is NULL.
* This function should be invoked from scheduling reactor.
*
* \param name Name of the scheduler to be used.
*
* \return 0 on success or non-zero on failure.
*/
int _spdk_scheduler_set(const char *name);
/**
* Get currently set scheduler.
*
* \return a pointer to spdk scheduler or NULL if none is set.
*/
struct spdk_scheduler *_spdk_scheduler_get(void);
/**
* Change current scheduling period.
* Setting period to 0 disables scheduling.
*
* \param period Period to set in microseconds.
*/
void _spdk_scheduler_set_period(uint64_t period);
/**
* Get scheduling period of currently set scheduler.
*
* \return Scheduling period in microseconds.
*/
uint64_t _spdk_scheduler_get_period(void);
/**
* Add the given scheduler to the list of registered schedulers.
* This function should be invoked by referencing the macro
* SPDK_SCHEDULER_REGISTER in the scheduler c file.
*
* \param scheduler Scheduler to be added.
*/
void _spdk_scheduler_register(struct spdk_scheduler *scheduler);
/*
* Macro used to register new scheduler.
*/
#define SPDK_SCHEDULER_REGISTER(scheduler) \
static void __attribute__((constructor)) _spdk_scheduler_register_ ## scheduler (void) \
{ \
_spdk_scheduler_register(&scheduler); \
} \
#ifdef __cplusplus
}
#endif

View File

@ -35,7 +35,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
SO_VER := 9
SO_MINOR := 0
SO_MINOR := 1
CFLAGS += $(ENV_CFLAGS)
@ -43,15 +43,6 @@ LIBNAME = event
C_SRCS = app.c reactor.c log_rpc.c \
app_rpc.c scheduler_static.c
# Do not compile schedulers and governors based on DPDK env
# if non-DPDK env is used.
ENV_NAME := $(notdir $(CONFIG_ENV))
ifeq ($(ENV_NAME),env_dpdk)
ifeq ($(OS),Linux)
C_SRCS += gscheduler.c dpdk_governor.c scheduler_dynamic.c
endif
endif
SPDK_MAP_FILE = $(abspath $(CURDIR)/spdk_event.map)
include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk

View File

@ -44,6 +44,7 @@
#include "spdk/thread.h"
#include "spdk/trace.h"
#include "spdk/string.h"
#include "spdk/scheduler.h"
#include "spdk/rpc.h"
#include "spdk/util.h"
@ -620,7 +621,6 @@ app_stop(void *arg1)
spdk_rpc_finish();
g_spdk_app.stopped = true;
_spdk_scheduler_set_period(0);
_start_subsystem_fini(NULL);
}

View File

@ -38,6 +38,7 @@
#include "spdk/string.h"
#include "spdk/util.h"
#include "spdk/env.h"
#include "spdk/scheduler.h"
#include "spdk/thread.h"
#include "spdk/log.h"
@ -399,7 +400,8 @@ _rpc_framework_get_reactors(void *arg1, void *arg2)
spdk_json_write_named_uint64(ctx->w, "busy", reactor->busy_tsc);
spdk_json_write_named_uint64(ctx->w, "idle", reactor->idle_tsc);
spdk_json_write_named_bool(ctx->w, "in_interrupt", reactor->in_interrupt);
governor = _spdk_governor_get();
governor = spdk_governor_get();
if (governor != NULL) {
/* Governor returns core freqs in kHz, we want MHz. */
curr_core_freq = governor->get_core_curr_freq(current_core) / 1000;
@ -491,10 +493,10 @@ rpc_framework_set_scheduler(struct spdk_jsonrpc_request *request,
}
if (req.period != 0) {
_spdk_scheduler_set_period(req.period);
spdk_scheduler_set_period(req.period);
}
ret = _spdk_scheduler_set(req.name);
ret = spdk_scheduler_set(req.name);
if (ret) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
spdk_strerror(ret));
@ -513,9 +515,9 @@ rpc_framework_get_scheduler(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct spdk_json_write_ctx *w;
struct spdk_scheduler *scheduler = _spdk_scheduler_get();
uint64_t scheduler_period = _spdk_scheduler_get_period();
struct spdk_governor *governor = _spdk_governor_get();
struct spdk_scheduler *scheduler = spdk_scheduler_get();
uint64_t scheduler_period = spdk_scheduler_get_period();
struct spdk_governor *governor = spdk_governor_get();
if (params) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,

View File

@ -40,6 +40,7 @@
#include "spdk/thread.h"
#include "spdk/env.h"
#include "spdk/util.h"
#include "spdk/scheduler.h"
#include "spdk/string.h"
#include "spdk/fd_group.h"
@ -69,7 +70,7 @@ TAILQ_HEAD(, spdk_scheduler) g_scheduler_list
static struct spdk_scheduler *g_scheduler = NULL;
static struct spdk_reactor *g_scheduling_reactor;
bool g_scheduling_in_progress = false;
static uint64_t g_scheduler_period;
static uint64_t g_scheduler_period = 0;
static uint32_t g_scheduler_core_number;
static struct spdk_scheduler_core_info *g_core_infos = NULL;
@ -96,7 +97,7 @@ _scheduler_find(const char *name)
}
int
_spdk_scheduler_set(const char *name)
spdk_scheduler_set(const char *name)
{
struct spdk_scheduler *scheduler;
int rc = 0;
@ -132,27 +133,27 @@ _spdk_scheduler_set(const char *name)
}
struct spdk_scheduler *
_spdk_scheduler_get(void)
spdk_scheduler_get(void)
{
return g_scheduler;
}
uint64_t
_spdk_scheduler_get_period(void)
spdk_scheduler_get_period(void)
{
/* Convert from ticks to microseconds */
return (g_scheduler_period * SPDK_SEC_TO_USEC / spdk_get_ticks_hz());
}
void
_spdk_scheduler_set_period(uint64_t period)
spdk_scheduler_set_period(uint64_t period)
{
/* Convert microseconds to ticks */
g_scheduler_period = period * spdk_get_ticks_hz() / SPDK_SEC_TO_USEC;
}
void
_spdk_scheduler_register(struct spdk_scheduler *scheduler)
spdk_scheduler_register(struct spdk_scheduler *scheduler)
{
if (_scheduler_find(scheduler->name)) {
SPDK_ERRLOG("scheduler named '%s' already registered.\n", scheduler->name);
@ -281,12 +282,6 @@ spdk_reactors_init(void)
assert(reactor != NULL);
g_scheduling_reactor = reactor;
/* set default scheduling period to one second */
g_scheduler_period = spdk_get_ticks_hz();
rc = _spdk_scheduler_set("static");
assert(rc == 0);
g_reactor_state = SPDK_REACTOR_STATE_INITIALIZED;
return 0;
@ -302,8 +297,6 @@ spdk_reactors_fini(void)
return;
}
_spdk_scheduler_set(NULL);
spdk_thread_lib_fini();
SPDK_ENV_FOREACH_CORE(i) {
@ -767,7 +760,7 @@ _reactors_scheduler_cancel(void *arg1, void *arg2)
static void
_reactors_scheduler_balance(void *arg1, void *arg2)
{
struct spdk_scheduler *scheduler = _spdk_scheduler_get();
struct spdk_scheduler *scheduler = spdk_scheduler_get();
if (g_reactor_state != SPDK_REACTOR_STATE_RUNNING || scheduler == NULL) {
_reactors_scheduler_cancel(NULL, NULL);
@ -1493,7 +1486,7 @@ _governor_find(const char *name)
}
int
_spdk_governor_set(const char *name)
spdk_governor_set(const char *name)
{
struct spdk_governor *governor;
int rc = 0;
@ -1528,13 +1521,13 @@ _spdk_governor_set(const char *name)
}
struct spdk_governor *
_spdk_governor_get(void)
spdk_governor_get(void)
{
return g_governor;
}
void
_spdk_governor_register(struct spdk_governor *governor)
spdk_governor_register(struct spdk_governor *governor)
{
if (_governor_find(governor->name)) {
SPDK_ERRLOG("governor named '%s' already registered.\n", governor->name);

View File

@ -36,6 +36,7 @@
#include "spdk/event.h"
#include "spdk/log.h"
#include "spdk/env.h"
#include "spdk/scheduler.h"
#include "spdk_internal/event.h"

View File

@ -17,6 +17,16 @@
spdk_framework_enable_context_switch_monitor;
spdk_framework_context_switch_monitor_enabled;
# Public scheduler functions
spdk_scheduler_set;
spdk_scheduler_get;
spdk_scheduler_register;
spdk_scheduler_set_period;
spdk_scheduler_get_period;
spdk_governor_set;
spdk_governor_get;
spdk_governor_register;
# Functions used by other SPDK libraries
spdk_reactors_init;
spdk_reactors_fini;

View File

@ -88,6 +88,7 @@ endif
MODULES-bdev = spdk_bdev_modules
MODULES-sock = spdk_sock_modules
MODULES-accel = spdk_accel_modules
MODULES-scheduler = spdk_scheduler_modules
ifeq ($(SPDK_ROOT_DIR)/lib/env_dpdk,$(CONFIG_ENV))
MODULES-event = spdk_env_dpdk_rpc
endif

View File

@ -127,6 +127,15 @@ DEPDIRS-env_dpdk_rpc := log $(JSON_LIBS)
DEPDIRS-sock_posix := log sock util
DEPDIRS-sock_uring := log sock util
# module/scheduler
DEPDIRS-scheduler_dynamic := event log thread util
ifeq ($(SPDK_ROOT_DIR)/lib/env_dpdk,$(CONFIG_ENV))
ifeq ($(OS),Linux)
DEPDIRS-scheduler_dpdk_governor := event log
DEPDIRS-scheduler_gscheduler := event log
endif
endif
# module/bdev
DEPDIRS-bdev_gpt := bdev json log thread util
@ -166,10 +175,12 @@ DEPDIRS-event_vmd := init vmd $(JSON_LIBS) log thread
DEPDIRS-event_bdev := init bdev event_accel event_vmd event_sock
DEPDIRS-event_scheduler := event init
DEPDIRS-event_nbd := init nbd event_bdev
DEPDIRS-event_nvmf := init nvmf event_bdev event_sock thread log bdev util $(JSON_LIBS)
DEPDIRS-event_nvmf := init nvmf event_bdev event_scheduler event_sock thread log bdev util $(JSON_LIBS)
DEPDIRS-event_scsi := init scsi event_bdev
DEPDIRS-event_iscsi := init iscsi event_scsi event_sock
DEPDIRS-event_vhost := init vhost event_scsi
DEPDIRS-event_iscsi := init iscsi event_scheduler event_scsi event_sock
DEPDIRS-event_vhost := init vhost event_scheduler event_scsi
DEPDIRS-event_sock := init sock

View File

@ -118,7 +118,14 @@ ifeq ($(CONFIG_IDXD),y)
ACCEL_MODULES_LIST += accel_idxd idxd
endif
SCHEDULER_MODULES_LIST = scheduler_dynamic
ifeq ($(SPDK_ROOT_DIR)/lib/env_dpdk,$(CONFIG_ENV))
ifeq ($(OS),Linux)
SCHEDULER_MODULES_LIST += env_dpdk scheduler_dpdk_governor scheduler_gscheduler
endif
endif
EVENT_BDEV_SUBSYSTEM = event_bdev event_accel event_vmd event_sock
ALL_MODULES_LIST = $(BLOCKDEV_MODULES_LIST) $(ACCEL_MODULES_LIST) $(SOCK_MODULES_LIST)
ALL_MODULES_LIST = $(BLOCKDEV_MODULES_LIST) $(ACCEL_MODULES_LIST) $(SCHEDULER_MODULES_LIST) $(SOCK_MODULES_LIST)
SYS_LIBS += $(BLOCKDEV_MODULES_PRIVATE_LIBS)

View File

@ -35,7 +35,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
include $(SPDK_ROOT_DIR)/mk/spdk.modules.mk
DIRS-y = bdev blob blobfs accel event sock
DIRS-y = bdev blob blobfs accel event sock scheduler
ifeq ($(SPDK_ROOT_DIR)/lib/env_dpdk,$(CONFIG_ENV))
DIRS-y += env_dpdk
endif
@ -44,6 +44,7 @@ DEPDIRS-blob :=
DEPDIRS-accel :=
DEPDIRS-env_dpdk :=
DEPDIRS-sock :=
DEPDIRS-scheduler :=
DEPDIRS-bdev := blob
DEPDIRS-blobfs := blob
DEPDIRS-event := bdev blob
@ -53,6 +54,7 @@ DEPDIRS-event := bdev blob
BDEV_MODULES_PKGCONFIG = $(call pkgconfig_filename,spdk_bdev_modules)
ACCEL_MODULES_PKGCONFIG = $(call pkgconfig_filename,spdk_accel_modules)
SOCK_MODULES_PKGCONFIG = $(call pkgconfig_filename,spdk_sock_modules)
SCHEDULER_MODULES_PKGCONFIG = $(call pkgconfig_filename,spdk_scheduler_modules)
SYSLIBS_PKGCONFIG = $(call pkgconfig_filename,spdk_syslibs)
PRIVATE_SYSLIBS = $(SYS_LIBS)
@ -62,6 +64,7 @@ endif
MODULES_PKGCONFIG = $(BDEV_MODULES_PKGCONFIG) $(ACCEL_MODULES_PKGCONFIG)
MODULES_PKGCONFIG += $(SOCK_MODULES_PKGCONFIG) $(SYSLIBS_PKGCONFIG)
MODULES_PKGCONFIG += $(SCHEDULER_MODULES_PKGCONFIG)
$(BDEV_MODULES_PKGCONFIG):
$(Q)$(SPDK_ROOT_DIR)/scripts/pc_modules.sh bdev "$(BLOCKDEV_MODULES_LIST:%=spdk_%)" > $@
@ -72,6 +75,9 @@ $(ACCEL_MODULES_PKGCONFIG):
$(SOCK_MODULES_PKGCONFIG):
$(Q)$(SPDK_ROOT_DIR)/scripts/pc_modules.sh sock "$(SOCK_MODULES_LIST:%=spdk_%)" > $@
$(SCHEDULER_MODULES_PKGCONFIG):
$(Q)$(SPDK_ROOT_DIR)/scripts/pc_modules.sh scheduler "$(SCHEDULER_MODULES_LIST:%=spdk_%)" > $@
$(SYSLIBS_PKGCONFIG):
$(Q)$(SPDK_ROOT_DIR)/scripts/pc_libs.sh "" "$(PRIVATE_SYSLIBS)" System spdk_syslibs > $@

View File

@ -34,7 +34,7 @@
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
DIRS-y += bdev accel iscsi nvmf scsi vmd sock
DIRS-y += bdev accel iscsi nvmf scsi vmd scheduler sock
ifeq ($(OS),Linux)
DIRS-y += nbd

View File

@ -0,0 +1,45 @@
#
# BSD LICENSE
#
# Copyright (c) Intel Corporation.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
SO_VER := 1
SO_MINOR := 0
C_SRCS = scheduler.c
LIBNAME = event_scheduler
SPDK_MAP_FILE = $(SPDK_ROOT_DIR)/mk/spdk_blank.map
include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk

View File

@ -0,0 +1,72 @@
/*-
* BSD LICENSE
*
* Copyright (c) Intel Corporation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "spdk/stdinc.h"
#include "spdk/env.h"
#include "spdk/scheduler.h"
#include "spdk_internal/event.h"
#include "spdk_internal/init.h"
static void
scheduler_subsystem_init(void)
{
int rc = 0;
/* Set the defaults */
if (spdk_scheduler_get() == NULL) {
rc = spdk_scheduler_set("static");
}
if (spdk_scheduler_get_period() == 0) {
spdk_scheduler_set_period(SPDK_SEC_TO_USEC);
}
spdk_subsystem_init_next(rc);
}
static void
scheduler_subsystem_fini(void)
{
spdk_scheduler_set_period(0);
spdk_scheduler_set(NULL);
spdk_subsystem_fini_next();
}
static struct spdk_subsystem g_spdk_subsystem_scheduler = {
.name = "scheduler",
.init = scheduler_subsystem_init,
.fini = scheduler_subsystem_fini,
};
SPDK_SUBSYSTEM_REGISTER(g_spdk_subsystem_scheduler);

53
module/scheduler/Makefile Normal file
View File

@ -0,0 +1,53 @@
#
# BSD LICENSE
#
# Copyright (c) Intel Corporation.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
DIRS-y = scheduler_dynamic
# Do not compile schedulers and governors based on DPDK env
# if non-DPDK env is used.
ENV_NAME := $(notdir $(CONFIG_ENV))
ifeq ($(ENV_NAME),env_dpdk)
ifeq ($(OS),Linux)
DIRS-y += dpdk_governor gscheduler
endif
endif
.PHONY: all clean $(DIRS-y)
all: $(DIRS-y)
clean: $(DIRS-y)
include $(SPDK_ROOT_DIR)/mk/spdk.subdirs.mk

View File

@ -0,0 +1,47 @@
#
# BSD LICENSE
#
# Copyright (c) Intel Corporation.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
SO_VER := 1
SO_MINOR := 0
CFLAGS += $(ENV_CFLAGS)
LIBNAME = scheduler_dpdk_governor
C_SRCS = dpdk_governor.c
SPDK_MAP_FILE = $(SPDK_ROOT_DIR)/mk/spdk_blank.map
include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk

View File

@ -35,6 +35,7 @@
#include "spdk/log.h"
#include "spdk/env.h"
#include "spdk/event.h"
#include "spdk/scheduler.h"
#include "spdk_internal/event.h"

View File

@ -0,0 +1,45 @@
#
# BSD LICENSE
#
# Copyright (c) Intel Corporation.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
SO_VER := 1
SO_MINOR := 0
LIBNAME = scheduler_gscheduler
C_SRCS = gscheduler.c
SPDK_MAP_FILE = $(SPDK_ROOT_DIR)/mk/spdk_blank.map
include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk

View File

@ -39,17 +39,18 @@
#include "spdk/log.h"
#include "spdk/env.h"
#include "spdk/scheduler.h"
static int
init(void)
{
return _spdk_governor_set("dpdk_governor");
return spdk_governor_set("dpdk_governor");
}
static void
deinit(void)
{
_spdk_governor_set(NULL);
spdk_governor_set(NULL);
}
static void
@ -61,7 +62,7 @@ balance(struct spdk_scheduler_core_info *cores, uint32_t core_count)
uint32_t i;
int rc;
governor = _spdk_governor_get();
governor = spdk_governor_get();
assert(governor != NULL);
/* Gather active/idle statistics */
@ -79,29 +80,21 @@ balance(struct spdk_scheduler_core_info *cores, uint32_t core_count)
if (rc < 0) {
SPDK_ERRLOG("setting to minimal frequency for core %u failed\n", core->lcore);
}
SPDK_DEBUGLOG(reactor, "setting to minimal frequency for core: %u\n", core->lcore);
} else if (core->total_idle_tsc > core->total_busy_tsc) {
rc = governor->core_freq_down(core->lcore);
if (rc < 0) {
SPDK_ERRLOG("lowering frequency for core %u failed\n", core->lcore);
}
SPDK_DEBUGLOG(reactor, "lowering frequency for core: %u\n", core->lcore);
} else if (core->total_idle_tsc < (core->total_busy_tsc / 1000)) {
rc = governor->set_core_freq_max(core->lcore);
if (rc < 0) {
SPDK_ERRLOG("setting to maximal frequency for core %u failed\n", core->lcore);
}
SPDK_DEBUGLOG(reactor, "setting to maximum frequency for core: %u\n", core->lcore);
} else {
rc = governor->core_freq_up(core->lcore);
if (rc < 0) {
SPDK_ERRLOG("increasing frequency for core %u failed\n", core->lcore);
}
SPDK_DEBUGLOG(reactor, "increasing frequency for core: %u\n", core->lcore);
}
}
}

View File

@ -0,0 +1,45 @@
#
# BSD LICENSE
#
# Copyright (c) Intel Corporation.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
SO_VER := 1
SO_MINOR := 0
LIBNAME = scheduler_dynamic
C_SRCS = scheduler_dynamic.c
SPDK_MAP_FILE = $(SPDK_ROOT_DIR)/mk/spdk_blank.map
include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk

View File

@ -39,6 +39,7 @@
#include "spdk/thread.h"
#include "spdk_internal/event.h"
#include "spdk/scheduler.h"
static uint32_t g_main_lcore;
@ -224,7 +225,7 @@ init(void)
{
g_main_lcore = spdk_env_get_current_core();
if (_spdk_governor_set("dpdk_governor") != 0) {
if (spdk_governor_set("dpdk_governor") != 0) {
SPDK_NOTICELOG("Unable to initialize dpdk governor\n");
}
@ -242,8 +243,7 @@ deinit(void)
{
free(g_cores);
g_cores = NULL;
_spdk_governor_set(NULL);
spdk_governor_set(NULL);
}
static void
@ -312,7 +312,7 @@ balance(struct spdk_scheduler_core_info *cores_info, uint32_t cores_count)
}
}
governor = _spdk_governor_get();
governor = spdk_governor_get();
if (governor == NULL) {
return;
}

View File

@ -38,6 +38,6 @@ include $(SPDK_ROOT_DIR)/mk/spdk.modules.mk
APP = scheduler
C_SRCS := scheduler.c
SPDK_LIB_LIST = $(ALL_MODULES_LIST) event event_bdev conf
SPDK_LIB_LIST = $(ALL_MODULES_LIST) event event_bdev conf event_scheduler
include $(SPDK_ROOT_DIR)/mk/spdk.app.mk

View File

@ -37,8 +37,9 @@
#include "common/lib/test_env.c"
#include "event/reactor.c"
#include "spdk/thread.h"
#include "spdk_internal/thread.h"
#include "event/scheduler_static.c"
#include "event/scheduler_dynamic.c"
#include "../module/scheduler/scheduler_dynamic/scheduler_dynamic.c"
struct spdk_thread *
_spdk_get_app_thread(void)
@ -576,7 +577,7 @@ test_scheduler(void)
CU_ASSERT(spdk_reactors_init() == 0);
_spdk_scheduler_set("dynamic");
spdk_scheduler_set("dynamic");
for (i = 0; i < 3; i++) {
spdk_cpuset_set_cpu(&g_reactor_core_mask, i, true);
@ -794,13 +795,14 @@ test_governor(void)
MOCK_SET(spdk_env_get_current_core, 0);
g_curr_freq = last_freq;
_spdk_governor_register(&governor);
spdk_governor_register(&governor);
allocate_cores(2);
CU_ASSERT(spdk_reactors_init() == 0);
_spdk_scheduler_set("dynamic");
spdk_scheduler_set("dynamic");
spdk_governor_set("dpdk_governor");
for (i = 0; i < 2; i++) {
spdk_cpuset_set_cpu(&g_reactor_core_mask, i, true);