/* * Copyright (c) 2021 NVIDIA Corporation. All rights reserved. * * NVIDIA Corporation and its licensors retain all intellectual property * and proprietary rights in and to this software, related documentation * and any modifications thereto. Any use, reproduction, disclosure or * distribution of this software and related documentation without an express * license agreement from NVIDIA Corporation is strictly prohibited. */ #ifndef NVS_SCHED_H #define NVS_SCHED_H /** * @page NV Scheduler * * Overview * ======== * * An nvs_sched object defines a _scheduler_, this is an object that contains * information about the domains and contexts to manage, and some operations * to interact with the underlying HW. The scheduler is split up into three * distinct parts: * * 1. The implementation operations that allow the scheduler to interact * with a given piece of hardware. This serves as a hardware abstraction * since the conceptual framework here is not tied to a specific piece of * HW such as a GPU. * 2. Algorithm implementations that pick the next context to actually run. * 3. A core component that defines the data structures which define the * domains/contexts. The core component is responsible for linking the * scheduling algorithm outputs to hardware operations. * * Implementation Operations * ========================= * * Each concrete implementation of nvsched must provide, at a minimum some * operations that allow the scheduling logic to interact with the managed * HW. The two primary operations are preemption and recovery. * * Algorithms * ========== * * nvsched splits the data structures from the algorithms. This allows * multiple algorithms to be supported: for example one implementation could * use a round-robin approach for picking next domains, but another may wish * to use a priority based approach. * * Core Scheduler * ============== * * The responsibility for the core scheduler is to provide data structures * that model a two level scheduling model: first there's domains and then * there's contexts within a domain. An implementation built on top of * nvsched will need to instantiate domains and contexts and then execute * some top level operations to trigger scheduling work. * * The data structure nesting looks like this: * * struct nvs_sched * +-------------------------+ +---------->+-----------+ * | | | | preempt() | * | struct nvs_sched_ops +-----+ | recover() | * | | +-----------+ * | // List of: | * | struct nvs_domain +---------------->+-----------------+ * | | | Domain 1 | * | struct nvs_domain_algo +-------+ | Domain Params | * | | | | Context list +-----+ * +-------------------------+ | +-----------------+ | * | | Domain ... | | * +-------------+ | | Domain Params | | * | Context 1 |<---------+ | | Context list +---+ | * +-------------+ | | +-----------------+ | | * | Context 2 |<---------+ | | Domain N | | | * +-------------+ | | | Domain Params | | | * | Context ... |<-----+ | | | Context list +-+ | | * +-------------+ | | | +-----------------+ | | | * | Context ... |<-----+ | | | | | * +-------------+ | | +-------->+-----------------+ | | | * | Context M |<-+ | | | next_domain() | | | | * +-------------+ | | | | schedule() | | | | * | | | | init() | | | | * | | | +-----------------+ | | | * +---|---|-----------------------------------+ | | * +---|-------------------------------------+ | * +---------------------------------------+ */ #include #include struct nvs_sched; struct nvs_domain; struct nvs_domain_algo; struct nvs_domain_list; struct nvs_log_buffer; /** * @brief Base scheduling operations an implementation will need to provide * to the scheduling core. */ struct nvs_sched_ops { /** * @brief Preempt the running context on the device \a sched * is managing. * * @param sched The scheduler. */ int (*preempt)(struct nvs_sched *sched); /** * @brief Recover the running context in \a sched. */ int (*recover)(struct nvs_sched *sched); }; /** * @brief Define a top level scheduler object. */ struct nvs_sched { /** * Ops that let the scheduler interface with the underlying * hardware. */ struct nvs_sched_ops *ops; /** * List of domains. Internally stored as a singly linked * list. * * @sa struct nvs_domain_list */ struct nvs_domain_list *domain_list; /** * Algorithm instance; invoked after a schedule() call. */ struct nvs_domain_algo *algorithm; /** * Log buffer with log entries. */ struct nvs_log_buffer *log; /** * Implementation private data. */ void *priv; }; /** * @brief Create a scheduler and assign the \a ops and \a priv pointers. * * @param sched Pointer to an uninitialized struct sched. * @param ops Ops defining HW interactions. * @param priv Private pointer for implementation use. * * Build a sched struct in the passed memory \a sched. This pointer should * have at least sizeof(struct nvs_sched) bytes. nvsched cannot do this allocation * since the nvs_malloc() function relies on the sched object (some APIs require * an API token of some sort which they may choose to embed in sched->priv. * * The ops struct should be in memory that will not be reclaimed until after the * \a sched memory is reclaimed. * * \a priv may be used by implementations where needed. The priv pointer contents * will never be touched by nvsched. */ int nvs_sched_create(struct nvs_sched *sched, struct nvs_sched_ops *ops, void *priv); void nvs_sched_close(struct nvs_sched *sched); #endif