Commit 2a146cd9 authored by Maciej Szwed's avatar Maciej Szwed Committed by Tomasz Zawadzki
Browse files

event: define scheduler API



Add structures and function for new scheduler API.

Change-Id: I8e379db62189eb7c36092265c137f07368650e9b
Signed-off-by: default avatarVitaliy Mysak <vitaliy.mysak@intel.com>
Signed-off-by: default avatarMaciej Szwed <maciej.szwed@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4053


Reviewed-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarAleksey Marchuk <alexeymar@mellanox.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent 9e89645b
Loading
Loading
Loading
Loading
+79 −2
Original line number Diff line number Diff line
@@ -62,8 +62,11 @@ enum spdk_reactor_state {

struct spdk_lw_thread {
	TAILQ_ENTRY(spdk_lw_thread)	link;
	bool				resched;
	uint64_t			tsc_start;
	uint32_t                        lcore;
	uint32_t                        new_lcore;
	bool				resched;
	struct spdk_thread_stats        current_stats;
};

struct spdk_reactor {
@@ -76,7 +79,8 @@ struct spdk_reactor {

	struct {
		uint32_t				is_valid : 1;
		uint32_t				reserved : 31;
		uint32_t				is_scheduling : 1;
		uint32_t				reserved : 30;
	} flags;

	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_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
 */
+53 −0
Original line number Diff line number Diff line
@@ -62,9 +62,61 @@ static bool g_framework_context_switch_monitor_enabled = true;

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 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
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);

	lw_thread->resched = true;
	lw_thread->lcore = SPDK_ENV_LCORE_ID_ANY;

	current_core = spdk_env_get_current_core();
	reactor = spdk_reactor_get(current_core);