event: define scheduler API

Add structures and function for new scheduler API.

Change-Id: I8e379db62189eb7c36092265c137f07368650e9b
Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Signed-off-by: Maciej Szwed <maciej.szwed@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4053
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Maciej Szwed 2020-09-22 13:47:11 +02:00 committed by Tomasz Zawadzki
parent 9e89645b61
commit 2a146cd936
2 changed files with 132 additions and 2 deletions

View File

@ -62,8 +62,11 @@ enum spdk_reactor_state {
struct spdk_lw_thread { struct spdk_lw_thread {
TAILQ_ENTRY(spdk_lw_thread) link; TAILQ_ENTRY(spdk_lw_thread) link;
bool resched;
uint64_t tsc_start; uint64_t tsc_start;
uint32_t lcore;
uint32_t new_lcore;
bool resched;
struct spdk_thread_stats current_stats;
}; };
struct spdk_reactor { struct spdk_reactor {
@ -76,7 +79,8 @@ struct spdk_reactor {
struct { struct {
uint32_t is_valid : 1; uint32_t is_valid : 1;
uint32_t reserved : 31; uint32_t is_scheduling : 1;
uint32_t reserved : 30;
} flags; } flags;
uint64_t tsc_last; uint64_t tsc_last;
@ -171,6 +175,79 @@ 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_initialize(const char *listen_addr);
void spdk_rpc_finish(void); void spdk_rpc_finish(void);
/**
* A list of cores and threads which is used for scheduling.
*/
struct spdk_scheduler_core_info {
uint64_t core_idle_tsc;
uint64_t core_busy_tsc;
uint32_t lcore;
uint32_t threads_count;
struct spdk_lw_thread **threads;
};
/**
* 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);
/**
* Scheduler init function type.
* Called on scheduler module initialization.
*/
typedef int (*spdk_scheduler_init_fn)(void);
/**
* Scheduler deinitialization function type.
* Called on reactor fini.
*/
typedef int (*spdk_scheduler_deinit_fn)(void);
/** Thread scheduler */
struct spdk_scheduler {
char *name;
spdk_scheduler_init_fn init;
spdk_scheduler_deinit_fn deinit;
spdk_scheduler_balance_fn balance;
TAILQ_ENTRY(spdk_scheduler) link;
};
/**
* 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_list_add(struct spdk_scheduler *scheduler);
/**
* Change current scheduler.
*
* \param name Name of the scheduler to be used.
*
* \return 0 on success or non-zero on failure.
*/
int _spdk_scheduler_set(char *name);
/**
* Change current scheduling period.
*
* \param period New period (ticks).
* Use spdk_get_ticks_hz() to translate seconds to ticks.
*/
void _spdk_scheduler_period_set(uint32_t period);
/*
* Macro used to register new reactor balancer.
*/
#define SPDK_SCHEDULER_REGISTER(scheduler) \
static void __attribute__((constructor)) _spdk_scheduler_register_##name(void) \
{ \
spdk_scheduler_list_add(scheduler); \
} \
/** /**
* \brief Register a new subsystem * \brief Register a new subsystem
*/ */

View File

@ -62,9 +62,61 @@ static bool g_framework_context_switch_monitor_enabled = true;
static struct spdk_mempool *g_spdk_event_mempool = NULL; static struct spdk_mempool *g_spdk_event_mempool = NULL;
TAILQ_HEAD(, spdk_scheduler) g_scheduler_list
= TAILQ_HEAD_INITIALIZER(g_scheduler_list);
static struct spdk_scheduler *g_scheduler;
static uint32_t g_scheduler_period;
static int reactor_interrupt_init(struct spdk_reactor *reactor); static int reactor_interrupt_init(struct spdk_reactor *reactor);
static void reactor_interrupt_fini(struct spdk_reactor *reactor); static void reactor_interrupt_fini(struct spdk_reactor *reactor);
static struct spdk_scheduler *
_scheduler_find(char *name)
{
struct spdk_scheduler *tmp;
TAILQ_FOREACH(tmp, &g_scheduler_list, link) {
if (strcmp(name, tmp->name) == 0) {
return tmp;
}
}
return NULL;
}
int
_spdk_scheduler_set(char *name)
{
struct spdk_scheduler *scheduler;
scheduler = _scheduler_find(name);
if (scheduler == NULL) {
return -ENOENT;
}
g_scheduler = scheduler;
return 0;
}
void
_spdk_scheduler_period_set(uint32_t period)
{
g_scheduler_period = period;
}
void
_spdk_scheduler_list_add(struct spdk_scheduler *scheduler)
{
if (_scheduler_find(scheduler->name)) {
SPDK_ERRLOG("scheduler named '%s' already registered.\n", scheduler->name);
assert(false);
return;
}
TAILQ_INSERT_TAIL(&g_scheduler_list, scheduler, link);
}
static void static void
reactor_construct(struct spdk_reactor *reactor, uint32_t lcore) reactor_construct(struct spdk_reactor *reactor, uint32_t lcore)
{ {
@ -689,6 +741,7 @@ _reactor_request_thread_reschedule(struct spdk_thread *thread)
assert(lw_thread != NULL); assert(lw_thread != NULL);
lw_thread->resched = true; lw_thread->resched = true;
lw_thread->lcore = SPDK_ENV_LCORE_ID_ANY;
current_core = spdk_env_get_current_core(); current_core = spdk_env_get_current_core();
reactor = spdk_reactor_get(current_core); reactor = spdk_reactor_get(current_core);