]>
Commit | Line | Data |
---|---|---|
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 | |
38 | using namespace std::chrono_literals; | |
39 | ||
40 | using namespace seastar; | |
41 | ||
42 | /** | |
43 | * Test setting primitive and object as a value after all groups are created | |
44 | */ | |
45 | SEASTAR_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 | */ | |
103 | SEASTAR_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 | */ | |
161 | SEASTAR_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 | */ | |
221 | SEASTAR_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 | ||
241 | SEASTAR_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 | } |