summaryrefslogtreecommitdiffstats
path: root/src/seastar/include/seastar/core/scheduling.hh
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/seastar/include/seastar/core/scheduling.hh366
1 files changed, 366 insertions, 0 deletions
diff --git a/src/seastar/include/seastar/core/scheduling.hh b/src/seastar/include/seastar/core/scheduling.hh
new file mode 100644
index 000000000..fb4c59e5a
--- /dev/null
+++ b/src/seastar/include/seastar/core/scheduling.hh
@@ -0,0 +1,366 @@
+/*
+ * This file is open source software, licensed to you under the terms
+ * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
+ * distributed with this work for additional information regarding copyright
+ * ownership. You may not use this file except in compliance with the License.
+ *
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/*
+ * Copyright (C) 2016 Scylla DB Ltd
+ */
+
+#pragma once
+
+#include <typeindex>
+#include <seastar/core/sstring.hh>
+#include <seastar/core/function_traits.hh>
+#include <seastar/util/concepts.hh>
+
+/// \file
+
+namespace seastar {
+
+constexpr unsigned max_scheduling_groups() { return 16; }
+
+#if SEASTAR_API_LEVEL < 6
+#define SEASTAR_ELLIPSIS ...
+template <typename SEASTAR_ELLIPSIS T>
+#else
+#define SEASTAR_ELLIPSIS
+template <typename T = void>
+#endif
+class future;
+
+class reactor;
+
+class scheduling_group;
+class scheduling_group_key;
+
+namespace internal {
+
+// Returns an index between 0 and max_scheduling_groups()
+unsigned scheduling_group_index(scheduling_group sg) noexcept;
+scheduling_group scheduling_group_from_index(unsigned index) noexcept;
+
+unsigned long scheduling_group_key_id(scheduling_group_key) noexcept;
+
+template<typename T>
+T* scheduling_group_get_specific_ptr(scheduling_group sg, scheduling_group_key key) noexcept;
+
+}
+
+
+/// Creates a scheduling group with a specified number of shares.
+///
+/// The operation is global and affects all shards. The returned scheduling
+/// group can then be used in any shard.
+///
+/// \param name A name that identifiers the group; will be used as a label
+/// in the group's metrics
+/// \param shares number of shares of the CPU time allotted to the group;
+/// Use numbers in the 1-1000 range (but can go above).
+/// \return a scheduling group that can be used on any shard
+future<scheduling_group> create_scheduling_group(sstring name, float shares) noexcept;
+
+/// Destroys a scheduling group.
+///
+/// Destroys a \ref scheduling_group previously created with create_scheduling_group().
+/// The destroyed group must not be currently in use and must not be used later.
+///
+/// The operation is global and affects all shards.
+///
+/// \param sg The scheduling group to be destroyed
+/// \return a future that is ready when the scheduling group has been torn down
+future<> destroy_scheduling_group(scheduling_group sg) noexcept;
+
+/// Rename scheduling group.
+///
+/// Renames a \ref scheduling_group previously created with create_scheduling_group().
+///
+/// The operation is global and affects all shards.
+/// The operation affects the exported statistics labels.
+///
+/// \param sg The scheduling group to be renamed
+/// \param new_name The new name for the scheduling group.
+/// \return a future that is ready when the scheduling group has been renamed
+future<> rename_scheduling_group(scheduling_group sg, sstring new_name) noexcept;
+
+
+/**
+ * Represents a configuration for a specific scheduling group value,
+ * it contains all that is needed to maintain a scheduling group specific
+ * value when it needs to be created, due to, for example, a new
+ * \ref scheduling_group being created.
+ *
+ * @note is is recomended to use @ref make_scheduling_group_key_config in order to
+ * create and configure this syructure. The only reason that one might want to not use
+ * this method is because of a need for specific intervention in the construction or
+ * destruction of the value. Even then, it is recommended to first create the configuration
+ * with @ref make_scheduling_group_key_config and only the change it.
+ *
+ */
+struct scheduling_group_key_config {
+ /**
+ * Constructs a default configuration
+ */
+ scheduling_group_key_config() :
+ scheduling_group_key_config(typeid(void)) {}
+ /**
+ * Creates a configuration that is made for a specific type.
+ * It does not contain the right alignment and allocation sizes
+ * neither the correct construction or destruction logic, but only
+ * the indication for the intended type which is used in debug mode
+ * to make sure that the correct type is reffered to when accessing
+ * the value.
+ * @param type_info - the type information class (create with typeid(T)).
+ */
+ scheduling_group_key_config(const std::type_info& type_info) :
+ type_index(type_info) {}
+ /// The allocation size for the value (usually: sizeof(T))
+ size_t allocation_size;
+ /// The required alignment of the value (usually: alignof(T))
+ size_t alignment;
+ /// Holds the type information for debug mode runtime validation
+ std::type_index type_index;
+ /// A function that will be called for each newly allocated value
+ std::function<void (void*)> constructor;
+ /// A function that will be called for each element that is about
+ /// to be dealocated.
+ std::function<void (void*)> destructor;
+
+};
+
+
+/**
+ * A class that is intended to encapsulate the scheduling group specific
+ * key and "hide" it implementation concerns and details.
+ *
+ * @note this object can be copied accross shards and scheduling groups.
+ */
+class scheduling_group_key {
+public:
+ /// The only user allowed operation on a key is copying.
+ scheduling_group_key(const scheduling_group_key&) noexcept = default;
+ scheduling_group_key(scheduling_group_key&&) noexcept = default;
+private:
+ scheduling_group_key(unsigned long id) noexcept :
+ _id(id) {}
+ unsigned long _id;
+ unsigned long id() const noexcept {
+ return _id;
+ }
+ friend class reactor;
+ friend future<scheduling_group_key> scheduling_group_key_create(scheduling_group_key_config cfg) noexcept;
+ template<typename T>
+ friend T* internal::scheduling_group_get_specific_ptr(scheduling_group sg, scheduling_group_key key) noexcept;
+ template<typename T>
+ friend T& scheduling_group_get_specific(scheduling_group_key key) noexcept;
+
+ friend unsigned long internal::scheduling_group_key_id(scheduling_group_key key) noexcept;
+};
+
+namespace internal {
+
+inline unsigned long scheduling_group_key_id(scheduling_group_key key) noexcept {
+ return key.id();
+}
+
+/**
+ * @brief A function in the spirit of Cpp17 apply, but specifically for constructors.
+ * This function is used in order to preserve support in Cpp14.
+
+ * @tparam ConstructorType - the constructor type or in other words the type to be constructed
+ * @tparam Tuple - T params tuple type (should be deduced)
+ * @tparam size_t...Idx - a sequence of indexes in order to access the typpels members in compile time.
+ * (should be deduced)
+ *
+ * @param pre_alocated_mem - a pointer to the pre allocated memory chunk that will hold the
+ * the initialized object.
+ * @param args - A tupple that holds the prarameters for the constructor
+ * @param idx_seq - An index sequence that will be used to access the members of the tuple in compile
+ * time.
+ *
+ * @note this function was not intended to be called by users and it is only a utility function
+ * for suporting \ref make_scheduling_group_key_config
+ */
+template<typename ConstructorType, typename Tuple, size_t...Idx>
+void apply_constructor(void* pre_alocated_mem, Tuple args, std::index_sequence<Idx...> idx_seq) {
+ new (pre_alocated_mem) ConstructorType(std::get<Idx>(args)...);
+}
+}
+
+/**
+ * A template function that builds a scheduling group specific value configuration.
+ * This configuration is used by the infrastructure to allocate memory for the values
+ * and initialize or deinitialize them when they are created or destroyed.
+ *
+ * @tparam T - the type for the newly created value.
+ * @tparam ...ConstructorArgs - the types for the constructor parameters (should be deduced)
+ * @param args - The parameters for the constructor.
+ * @return a fully initialized \ref scheduling_group_key_config object.
+ */
+template <typename T, typename... ConstructorArgs>
+scheduling_group_key_config
+make_scheduling_group_key_config(ConstructorArgs... args) {
+ scheduling_group_key_config sgkc(typeid(T));
+ sgkc.allocation_size = sizeof(T);
+ sgkc.alignment = alignof(T);
+ sgkc.constructor = [args = std::make_tuple(args...)] (void* p) {
+ internal::apply_constructor<T>(p, args, std::make_index_sequence<sizeof...(ConstructorArgs)>());
+ };
+ sgkc.destructor = [] (void* p) {
+ static_cast<T*>(p)->~T();
+ };
+ return sgkc;
+}
+
+/**
+ * Returns a future that holds a scheduling key and resolves when this key can be used
+ * to access the scheduling group specific value it represents.
+ * @param cfg - A \ref scheduling_group_key_config object (by recomendation: initialized with
+ * \ref make_scheduling_group_key_config )
+ * @return A future containing \ref scheduling_group_key for the newly created specific value.
+ */
+future<scheduling_group_key> scheduling_group_key_create(scheduling_group_key_config cfg) noexcept;
+
+/**
+ * Returnes a reference to the given scheduling group specific value
+ * @tparam T - the type of the scheduling specific type (cannot be deduced)
+ * @param sg - the scheduling group which it's specific value to retrieve
+ * @param key - the key of the value to retrieve.
+ * @return A reference to the scheduling specific value.
+ */
+template<typename T>
+T& scheduling_group_get_specific(scheduling_group sg, scheduling_group_key key);
+
+
+/// \brief Identifies function calls that are accounted as a group
+///
+/// A `scheduling_group` is a tag that can be used to mark a function call.
+/// Executions of such tagged calls are accounted as a group.
+class scheduling_group {
+ unsigned _id;
+private:
+ explicit scheduling_group(unsigned id) noexcept : _id(id) {}
+public:
+ /// Creates a `scheduling_group` object denoting the default group
+ constexpr scheduling_group() noexcept : _id(0) {} // must be constexpr for current_scheduling_group_holder
+ bool active() const noexcept;
+ const sstring& name() const noexcept;
+ bool operator==(scheduling_group x) const noexcept { return _id == x._id; }
+ bool operator!=(scheduling_group x) const noexcept { return _id != x._id; }
+ bool is_main() const noexcept { return _id == 0; }
+ template<typename T>
+ /**
+ * Returnes a reference to this scheduling group specific value
+ * @tparam T - the type of the scheduling specific type (cannot be deduced)
+ * @param key - the key of the value to retrieve.
+ * @return A reference to this scheduling specific value.
+ */
+ T& get_specific(scheduling_group_key key) noexcept {
+ return *internal::scheduling_group_get_specific_ptr<T>(*this, key);
+ }
+ /// Adjusts the number of shares allotted to the group.
+ ///
+ /// Dynamically adjust the number of shares allotted to the group, increasing or
+ /// decreasing the amount of CPU bandwidth it gets. The adjustment is local to
+ /// the shard.
+ ///
+ /// This can be used to reduce a background job's interference with a foreground
+ /// load: the shares can be started at a low value, increased when the background
+ /// job's backlog increases, and reduced again when the backlog decreases.
+ ///
+ /// \param shares number of shares allotted to the group. Use numbers
+ /// in the 1-1000 range.
+ void set_shares(float shares) noexcept;
+ friend future<scheduling_group> create_scheduling_group(sstring name, float shares) noexcept;
+ friend future<> destroy_scheduling_group(scheduling_group sg) noexcept;
+ friend future<> rename_scheduling_group(scheduling_group sg, sstring new_name) noexcept;
+ friend class reactor;
+ friend unsigned internal::scheduling_group_index(scheduling_group sg) noexcept;
+ friend scheduling_group internal::scheduling_group_from_index(unsigned index) noexcept;
+
+ template<typename SpecificValType, typename Mapper, typename Reducer, typename Initial>
+ SEASTAR_CONCEPT( requires requires(SpecificValType specific_val, Mapper mapper, Reducer reducer, Initial initial) {
+ {reducer(initial, mapper(specific_val))} -> std::convertible_to<Initial>;
+ })
+ friend future<typename function_traits<Reducer>::return_type>
+ map_reduce_scheduling_group_specific(Mapper mapper, Reducer reducer, Initial initial_val, scheduling_group_key key);
+
+ template<typename SpecificValType, typename Reducer, typename Initial>
+ SEASTAR_CONCEPT( requires requires(SpecificValType specific_val, Reducer reducer, Initial initial) {
+ {reducer(initial, specific_val)} -> std::convertible_to<Initial>;
+ })
+ friend future<typename function_traits<Reducer>::return_type>
+ reduce_scheduling_group_specific(Reducer reducer, Initial initial_val, scheduling_group_key key);
+
+
+};
+
+/// \cond internal
+namespace internal {
+
+inline
+unsigned
+scheduling_group_index(scheduling_group sg) noexcept {
+ return sg._id;
+}
+
+inline
+scheduling_group
+scheduling_group_from_index(unsigned index) noexcept {
+ return scheduling_group(index);
+}
+
+inline
+scheduling_group*
+current_scheduling_group_ptr() noexcept {
+ // Slow unless constructor is constexpr
+ static thread_local scheduling_group sg;
+ return &sg;
+}
+
+}
+/// \endcond
+
+/// Returns the current scheduling group
+inline
+scheduling_group
+current_scheduling_group() noexcept {
+ return *internal::current_scheduling_group_ptr();
+}
+
+inline
+scheduling_group
+default_scheduling_group() noexcept {
+ return scheduling_group();
+}
+
+inline
+bool
+scheduling_group::active() const noexcept {
+ return *this == current_scheduling_group();
+}
+
+}
+
+namespace std {
+
+template <>
+struct hash<seastar::scheduling_group> {
+ size_t operator()(seastar::scheduling_group sg) const noexcept {
+ return seastar::internal::scheduling_group_index(sg);
+ }
+};
+
+}