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:
parent
9e89645b61
commit
2a146cd936
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user