]> git.proxmox.com Git - ceph.git/blame - ceph/src/seastar/tests/unit/scheduling_group_test.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / seastar / tests / unit / scheduling_group_test.cc
CommitLineData
9f95a23c
TL
1/*
2 * This file is open source software, licensed to you under the terms
3 * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4 * distributed with this work for additional information regarding copyright
5 * ownership. You may not use this file except in compliance with the License.
6 *
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied. See the License for the
15 * specific language governing permissions and limitations
16 * under the License.
17 */
18/*
19 * Copyright (C) 2017 ScyllaDB Ltd.
20 */
21
22#include <algorithm>
23#include <vector>
24#include <chrono>
25
26#include <seastar/core/thread.hh>
27#include <seastar/testing/test_case.hh>
28#include <seastar/testing/thread_test_case.hh>
29#include <seastar/testing/test_runner.hh>
30#include <seastar/core/execution_stage.hh>
31#include <seastar/core/sleep.hh>
32#include <seastar/core/print.hh>
33#include <seastar/core/scheduling_specific.hh>
f67539c2
TL
34#include <seastar/core/smp.hh>
35#include <seastar/core/with_scheduling_group.hh>
36#include <seastar/util/later.hh>
9f95a23c
TL
37
38using namespace std::chrono_literals;
39
40using namespace seastar;
41
42/**
43 * Test setting primitive and object as a value after all groups are created
44 */
45SEASTAR_THREAD_TEST_CASE(sg_specific_values_define_after_sg_create) {
46 using ivec = std::vector<int>;
47 const int num_scheduling_groups = 4;
48 std::vector<scheduling_group> sgs;
49 for (int i = 0; i < num_scheduling_groups; i++) {
50 sgs.push_back(create_scheduling_group(format("sg{}", i).c_str(), 100).get0());
51 }
52
53 const auto destroy_scheduling_groups = defer([&sgs] () {
54 for (scheduling_group sg : sgs) {
55 destroy_scheduling_group(sg).get();
56 }
57 });
58 scheduling_group_key_config key1_conf = make_scheduling_group_key_config<int>();
59 scheduling_group_key key1 = scheduling_group_key_create(key1_conf).get0();
60
61 scheduling_group_key_config key2_conf = make_scheduling_group_key_config<ivec>();
62 scheduling_group_key key2 = scheduling_group_key_create(key2_conf).get0();
63
64 smp::invoke_on_all([key1, key2, &sgs] () {
f67539c2 65 int factor = this_shard_id() + 1;
9f95a23c
TL
66 for (int i=0; i < num_scheduling_groups; i++) {
67 sgs[i].get_specific<int>(key1) = (i + 1) * factor;
68 sgs[i].get_specific<ivec>(key2).push_back((i + 1) * factor);
69 }
70
71 for (int i=0; i < num_scheduling_groups; i++) {
72 BOOST_REQUIRE_EQUAL(sgs[i].get_specific<int>(key1) = (i + 1) * factor, (i + 1) * factor);
73 BOOST_REQUIRE_EQUAL(sgs[i].get_specific<ivec>(key2)[0], (i + 1) * factor);
74 }
75
76 }).get();
77
78 smp::invoke_on_all([key1, key2] () {
79 return reduce_scheduling_group_specific<int>(std::plus<int>(), int(0), key1).then([] (int sum) {
f67539c2 80 int factor = this_shard_id() + 1;
9f95a23c
TL
81 int expected_sum = ((1 + num_scheduling_groups)*num_scheduling_groups) * factor /2;
82 BOOST_REQUIRE_EQUAL(expected_sum, sum);
83 }). then([key2] {
84 auto ivec_to_int = [] (ivec& v) {
85 return v.size() ? v[0] : 0;
86 };
87
88 return map_reduce_scheduling_group_specific<ivec>(ivec_to_int, std::plus<int>(), int(0), key2).then([] (int sum) {
f67539c2 89 int factor = this_shard_id() + 1;
9f95a23c
TL
90 int expected_sum = ((1 + num_scheduling_groups)*num_scheduling_groups) * factor /2;
91 BOOST_REQUIRE_EQUAL(expected_sum, sum);
92 });
93
94 });
95 }).get();
96
97
98}
99
100/**
101 * Test setting primitive and object as a value before all groups are created
102 */
103SEASTAR_THREAD_TEST_CASE(sg_specific_values_define_before_sg_create) {
104 using ivec = std::vector<int>;
105 const int num_scheduling_groups = 4;
106 std::vector<scheduling_group> sgs;
107 const auto destroy_scheduling_groups = defer([&sgs] () {
108 for (scheduling_group sg : sgs) {
109 destroy_scheduling_group(sg).get();
110 }
111 });
112 scheduling_group_key_config key1_conf = make_scheduling_group_key_config<int>();
113 scheduling_group_key key1 = scheduling_group_key_create(key1_conf).get0();
114
115 scheduling_group_key_config key2_conf = make_scheduling_group_key_config<ivec>();
116 scheduling_group_key key2 = scheduling_group_key_create(key2_conf).get0();
117
118 for (int i = 0; i < num_scheduling_groups; i++) {
119 sgs.push_back(create_scheduling_group(format("sg{}", i).c_str(), 100).get0());
120 }
121
122 smp::invoke_on_all([key1, key2, &sgs] () {
f67539c2 123 int factor = this_shard_id() + 1;
9f95a23c
TL
124 for (int i=0; i < num_scheduling_groups; i++) {
125 sgs[i].get_specific<int>(key1) = (i + 1) * factor;
126 sgs[i].get_specific<ivec>(key2).push_back((i + 1) * factor);
127 }
128
129 for (int i=0; i < num_scheduling_groups; i++) {
130 BOOST_REQUIRE_EQUAL(sgs[i].get_specific<int>(key1) = (i + 1) * factor, (i + 1) * factor);
131 BOOST_REQUIRE_EQUAL(sgs[i].get_specific<ivec>(key2)[0], (i + 1) * factor);
132 }
133
134 }).get();
135
136 smp::invoke_on_all([key1, key2] () {
137 return reduce_scheduling_group_specific<int>(std::plus<int>(), int(0), key1).then([] (int sum) {
f67539c2 138 int factor = this_shard_id() + 1;
9f95a23c
TL
139 int expected_sum = ((1 + num_scheduling_groups)*num_scheduling_groups) * factor /2;
140 BOOST_REQUIRE_EQUAL(expected_sum, sum);
141 }). then([key2] {
142 auto ivec_to_int = [] (ivec& v) {
143 return v.size() ? v[0] : 0;
144 };
145
146 return map_reduce_scheduling_group_specific<ivec>(ivec_to_int, std::plus<int>(), int(0), key2).then([] (int sum) {
f67539c2 147 int factor = this_shard_id() + 1;
9f95a23c
TL
148 int expected_sum = ((1 + num_scheduling_groups)*num_scheduling_groups) * factor /2;
149 BOOST_REQUIRE_EQUAL(expected_sum, sum);
150 });
151
152 });
153 }).get();
154
155}
156
157/**
158 * Test setting primitive and an object as a value before some groups are created
159 * and after some of the groups are created.
160 */
161SEASTAR_THREAD_TEST_CASE(sg_specific_values_define_before_and_after_sg_create) {
162 using ivec = std::vector<int>;
163 const int num_scheduling_groups = 4;
164 std::vector<scheduling_group> sgs;
165 const auto destroy_scheduling_groups = defer([&sgs] () {
166 for (scheduling_group sg : sgs) {
167 destroy_scheduling_group(sg).get();
168 }
169 });
170
171 for (int i = 0; i < num_scheduling_groups/2; i++) {
172 sgs.push_back(create_scheduling_group(format("sg{}", i).c_str(), 100).get0());
173 }
174 scheduling_group_key_config key1_conf = make_scheduling_group_key_config<int>();
175 scheduling_group_key key1 = scheduling_group_key_create(key1_conf).get0();
176
177 scheduling_group_key_config key2_conf = make_scheduling_group_key_config<ivec>();
178 scheduling_group_key key2 = scheduling_group_key_create(key2_conf).get0();
179
180 for (int i = num_scheduling_groups/2; i < num_scheduling_groups; i++) {
181 sgs.push_back(create_scheduling_group(format("sg{}", i).c_str(), 100).get0());
182 }
183
184 smp::invoke_on_all([key1, key2, &sgs] () {
f67539c2 185 int factor = this_shard_id() + 1;
9f95a23c
TL
186 for (int i=0; i < num_scheduling_groups; i++) {
187 sgs[i].get_specific<int>(key1) = (i + 1) * factor;
188 sgs[i].get_specific<ivec>(key2).push_back((i + 1) * factor);
189 }
190
191 for (int i=0; i < num_scheduling_groups; i++) {
192 BOOST_REQUIRE_EQUAL(sgs[i].get_specific<int>(key1) = (i + 1) * factor, (i + 1) * factor);
193 BOOST_REQUIRE_EQUAL(sgs[i].get_specific<ivec>(key2)[0], (i + 1) * factor);
194 }
195
196 }).get();
197
198 smp::invoke_on_all([key1, key2] () {
199 return reduce_scheduling_group_specific<int>(std::plus<int>(), int(0), key1).then([] (int sum) {
f67539c2 200 int factor = this_shard_id() + 1;
9f95a23c
TL
201 int expected_sum = ((1 + num_scheduling_groups)*num_scheduling_groups) * factor /2;
202 BOOST_REQUIRE_EQUAL(expected_sum, sum);
203 }). then([key2] {
204 auto ivec_to_int = [] (ivec& v) {
205 return v.size() ? v[0] : 0;
206 };
207
208 return map_reduce_scheduling_group_specific<ivec>(ivec_to_int, std::plus<int>(), int(0), key2).then([] (int sum) {
f67539c2 209 int factor = this_shard_id() + 1;
9f95a23c
TL
210 int expected_sum = ((1 + num_scheduling_groups)*num_scheduling_groups) * factor /2;
211 BOOST_REQUIRE_EQUAL(expected_sum, sum);
212 });
213
214 });
215 }).get();
216}
217
218/*
219 * Test that current scheduling group is inherited by seastar::async()
220 */
221SEASTAR_THREAD_TEST_CASE(sg_scheduling_group_inheritance_in_seastar_async_test) {
222 scheduling_group sg = create_scheduling_group("sg0", 100).get0();
223 thread_attributes attr = {};
224 attr.sched_group = sg;
225 seastar::async(attr, [attr] {
226 BOOST_REQUIRE_EQUAL(internal::scheduling_group_index(current_scheduling_group()),
227 internal::scheduling_group_index(*(attr.sched_group)));
228
229 seastar::async([attr] {
230 BOOST_REQUIRE_EQUAL(internal::scheduling_group_index(current_scheduling_group()),
231 internal::scheduling_group_index(*(attr.sched_group)));
232
233 smp::invoke_on_all([sched_group_idx = internal::scheduling_group_index(*(attr.sched_group))] () {
234 BOOST_REQUIRE_EQUAL(internal::scheduling_group_index(current_scheduling_group()), sched_group_idx);
235 }).get();
236 }).get();
237 }).get();
238}
f67539c2
TL
239
240
241SEASTAR_THREAD_TEST_CASE(later_preserves_sg) {
242 scheduling_group sg = create_scheduling_group("sg", 100).get0();
243 auto cleanup = defer([&] { destroy_scheduling_group(sg).get(); });
244 with_scheduling_group(sg, [&] {
245 return later().then([&] {
246 BOOST_REQUIRE_EQUAL(
247 internal::scheduling_group_index(current_scheduling_group()),
248 internal::scheduling_group_index(sg));
249 });
250 }).get();
251}