• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <gtest/gtest.h>
18 
19 #include <errno.h>
20 #include <sched.h>
21 #include <sys/types.h>
22 #include <sys/wait.h>
23 
child_fn(void * i_ptr)24 static int child_fn(void* i_ptr) {
25   *reinterpret_cast<int*>(i_ptr) = 42;
26   return 123;
27 }
28 
29 #if defined(__BIONIC__)
TEST(sched,clone)30 TEST(sched, clone) {
31   void* child_stack[1024];
32 
33   int i = 0;
34   pid_t tid = clone(child_fn, &child_stack[1024], CLONE_VM, &i);
35 
36   int status;
37   ASSERT_EQ(tid, TEMP_FAILURE_RETRY(waitpid(tid, &status, __WCLONE)));
38 
39   ASSERT_EQ(42, i);
40 
41   ASSERT_TRUE(WIFEXITED(status));
42   ASSERT_EQ(123, WEXITSTATUS(status));
43 }
44 #else
45 // For glibc, any call to clone with CLONE_VM set will cause later pthread
46 // calls in the same process to misbehave.
47 // See https://sourceware.org/bugzilla/show_bug.cgi?id=10311 for more details.
TEST(sched,clone)48 TEST(sched, clone) {
49   // In order to enumerate all possible tests for CTS, create an empty test.
50   GTEST_SKIP() << "glibc is broken";
51 }
52 #endif
53 
TEST(sched,clone_errno)54 TEST(sched, clone_errno) {
55   // Check that our hand-written clone assembler sets errno correctly on failure.
56   uintptr_t fake_child_stack[16];
57   errno = 0;
58   // If CLONE_THREAD is set, CLONE_SIGHAND must be set too.
59   ASSERT_EQ(-1, clone(child_fn, &fake_child_stack[16], CLONE_THREAD, nullptr));
60   ASSERT_EQ(EINVAL, errno);
61 }
62 
TEST(sched,clone_null_child_stack)63 TEST(sched, clone_null_child_stack) {
64   int i = 0;
65   errno = 0;
66   ASSERT_EQ(-1, clone(child_fn, nullptr, CLONE_VM, &i));
67   ASSERT_EQ(EINVAL, errno);
68 }
69 
TEST(sched,cpu_set)70 TEST(sched, cpu_set) {
71   cpu_set_t set;
72 
73   CPU_ZERO(&set);
74   CPU_SET(0, &set);
75   CPU_SET(17, &set);
76   for (int i = 0; i < CPU_SETSIZE; i++) {
77     ASSERT_EQ(i == 0 || i == 17, CPU_ISSET(i, &set));
78   }
79 
80   // We should fail silently if we try to set/test outside the range.
81   CPU_SET(CPU_SETSIZE, &set);
82   ASSERT_FALSE(CPU_ISSET(CPU_SETSIZE, &set));
83 }
84 
TEST(sched,cpu_count)85 TEST(sched, cpu_count) {
86   cpu_set_t set;
87 
88   CPU_ZERO(&set);
89   ASSERT_EQ(0, CPU_COUNT(&set));
90   CPU_SET(2, &set);
91   CPU_SET(10, &set);
92   ASSERT_EQ(2, CPU_COUNT(&set));
93   CPU_CLR(10, &set);
94   ASSERT_EQ(1, CPU_COUNT(&set));
95 }
96 
TEST(sched,cpu_zero)97 TEST(sched, cpu_zero) {
98   cpu_set_t set;
99 
100   CPU_ZERO(&set);
101   ASSERT_EQ(0, CPU_COUNT(&set));
102   for (int i = 0; i < CPU_SETSIZE; i++) {
103     ASSERT_FALSE(CPU_ISSET(i, &set));
104   }
105 }
106 
TEST(sched,cpu_clr)107 TEST(sched, cpu_clr) {
108   cpu_set_t set;
109 
110   CPU_ZERO(&set);
111   CPU_SET(0, &set);
112   CPU_SET(1, &set);
113   for (int i = 0; i < CPU_SETSIZE; i++) {
114     ASSERT_EQ(i == 0 || i == 1, CPU_ISSET(i, &set));
115   }
116   CPU_CLR(1, &set);
117   for (int i = 0; i < CPU_SETSIZE; i++) {
118     ASSERT_EQ(i == 0, CPU_ISSET(i, &set));
119   }
120 
121   // We should fail silently if we try to clear/test outside the range.
122   CPU_CLR(CPU_SETSIZE, &set);
123   ASSERT_FALSE(CPU_ISSET(CPU_SETSIZE, &set));
124 }
125 
TEST(sched,cpu_equal)126 TEST(sched, cpu_equal) {
127   cpu_set_t set1;
128   cpu_set_t set2;
129 
130   CPU_ZERO(&set1);
131   CPU_ZERO(&set2);
132   CPU_SET(1, &set1);
133   ASSERT_FALSE(CPU_EQUAL(&set1, &set2));
134   CPU_SET(1, &set2);
135   ASSERT_TRUE(CPU_EQUAL(&set1, &set2));
136 }
137 
TEST(sched,cpu_op)138 TEST(sched, cpu_op) {
139   cpu_set_t set1;
140   cpu_set_t set2;
141   cpu_set_t set3;
142 
143   CPU_ZERO(&set1);
144   CPU_ZERO(&set2);
145   CPU_ZERO(&set3);
146   CPU_SET(0, &set1);
147   CPU_SET(0, &set2);
148   CPU_SET(1, &set2);
149 
150   CPU_AND(&set3, &set1, &set2);
151   for (int i = 0; i < CPU_SETSIZE; i++) {
152     ASSERT_EQ(i == 0, CPU_ISSET(i, &set3));
153   }
154 
155   CPU_XOR(&set3, &set1, &set2);
156   for (int i = 0; i < CPU_SETSIZE; i++) {
157     ASSERT_EQ(i == 1, CPU_ISSET(i, &set3));
158   }
159 
160   CPU_OR(&set3, &set1, &set2);
161   for (int i = 0; i < CPU_SETSIZE; i++) {
162     ASSERT_EQ(i == 0 || i == 1, CPU_ISSET(i, &set3));
163   }
164 }
165 
166 
TEST(sched,cpu_alloc_small)167 TEST(sched, cpu_alloc_small) {
168   cpu_set_t* set = CPU_ALLOC(17);
169   size_t size = CPU_ALLOC_SIZE(17);
170 
171   CPU_ZERO_S(size, set);
172   ASSERT_EQ(0, CPU_COUNT_S(size, set));
173   CPU_SET_S(16, size, set);
174   ASSERT_TRUE(CPU_ISSET_S(16, size, set));
175 
176   CPU_FREE(set);
177 }
178 
TEST(sched,cpu_alloc_big)179 TEST(sched, cpu_alloc_big) {
180   cpu_set_t* set = CPU_ALLOC(10 * CPU_SETSIZE);
181   size_t size = CPU_ALLOC_SIZE(10 * CPU_SETSIZE);
182 
183   CPU_ZERO_S(size, set);
184   ASSERT_EQ(0, CPU_COUNT_S(size, set));
185   CPU_SET_S(CPU_SETSIZE, size, set);
186   ASSERT_TRUE(CPU_ISSET_S(CPU_SETSIZE, size, set));
187 
188   CPU_FREE(set);
189 }
190 
TEST(sched,cpu_s_macros)191 TEST(sched, cpu_s_macros) {
192   int set_size = 64;
193   size_t size = CPU_ALLOC_SIZE(set_size);
194   cpu_set_t* set = CPU_ALLOC(set_size);
195 
196   CPU_ZERO_S(size, set);
197   for (int i = 0; i < set_size; i++) {
198     ASSERT_FALSE(CPU_ISSET_S(i, size, set));
199     CPU_SET_S(i, size, set);
200     ASSERT_TRUE(CPU_ISSET_S(i, size, set));
201     ASSERT_EQ(i + 1, CPU_COUNT_S(size, set));
202   }
203 
204   for (int i = 0; i < set_size; i++) {
205     CPU_CLR_S(i, size, set);
206     ASSERT_FALSE(CPU_ISSET_S(i, size, set));
207     ASSERT_EQ(set_size - i - 1, CPU_COUNT_S(size, set));
208   }
209 
210   CPU_FREE(set);
211 }
212 
TEST(sched,cpu_op_s_macros)213 TEST(sched, cpu_op_s_macros) {
214   int set_size1 = 64;
215   int set_size2 = set_size1 * 2;
216   int set_size3 = set_size1 * 3;
217   size_t size1 = CPU_ALLOC_SIZE(set_size1);
218   size_t size2 = CPU_ALLOC_SIZE(set_size2);
219   size_t size3 = CPU_ALLOC_SIZE(set_size3);
220 
221   cpu_set_t* set1 = CPU_ALLOC(set_size1);
222   cpu_set_t* set2 = CPU_ALLOC(set_size2);
223   cpu_set_t* set3 = CPU_ALLOC(set_size3);
224   CPU_ZERO_S(size1, set1);
225   CPU_ZERO_S(size2, set2);
226   CPU_ZERO_S(size3, set3);
227 
228   CPU_SET_S(0, size1, set1);
229   CPU_SET_S(0, size2, set2);
230   CPU_SET_S(1, size3, set2);
231 
232   CPU_AND_S(size1, set3, set1, set2);
233   for (int i = 0; i < set_size3; i++) {
234     ASSERT_EQ(i == 0, CPU_ISSET_S(i, size3, set3));
235   }
236 
237   CPU_OR_S(size1, set3, set1, set2);
238   for (int i = 0; i < set_size3; i++) {
239     ASSERT_EQ(i == 0 || i == 1, CPU_ISSET_S(i, size3, set3));
240   }
241 
242   CPU_XOR_S(size1, set3, set1, set2);
243   for (int i = 0; i < set_size3; i++) {
244     ASSERT_EQ(i == 1, CPU_ISSET_S(i, size3, set3));
245   }
246 
247   CPU_FREE(set1);
248   CPU_FREE(set2);
249   CPU_FREE(set3);
250 }
251 
TEST(sched,cpu_equal_s)252 TEST(sched, cpu_equal_s) {
253   int set_size1 = 64;
254   int set_size2 = set_size1 * 2;
255   size_t size1 = CPU_ALLOC_SIZE(set_size1);
256   size_t size2 = CPU_ALLOC_SIZE(set_size2);
257 
258   cpu_set_t* set1 = CPU_ALLOC(set_size1);
259   cpu_set_t* set2 = CPU_ALLOC(set_size2);
260 
261   CPU_ZERO_S(size1, set1);
262   CPU_ZERO_S(size2, set2);
263 
264   CPU_SET_S(0, size1, set1);
265   ASSERT_TRUE(CPU_EQUAL_S(size1, set1, set1));
266   ASSERT_FALSE(CPU_EQUAL_S(size1, set1, set2));
267   CPU_SET_S(0, size2, set2);
268   ASSERT_TRUE(CPU_EQUAL_S(size1, set1, set2));
269 
270   CPU_FREE(set1);
271   CPU_FREE(set2);
272 }
273 
TEST(sched,sched_get_priority_min_sched_get_priority_max)274 TEST(sched, sched_get_priority_min_sched_get_priority_max) {
275   EXPECT_LE(sched_get_priority_min(SCHED_BATCH), sched_get_priority_max(SCHED_BATCH));
276   EXPECT_LE(sched_get_priority_min(SCHED_FIFO), sched_get_priority_max(SCHED_FIFO));
277   EXPECT_LE(sched_get_priority_min(SCHED_IDLE), sched_get_priority_max(SCHED_IDLE));
278   EXPECT_LE(sched_get_priority_min(SCHED_OTHER), sched_get_priority_max(SCHED_OTHER));
279   EXPECT_LE(sched_get_priority_min(SCHED_RR), sched_get_priority_max(SCHED_RR));
280 }
281 
TEST(sched,sched_getscheduler_sched_setscheduler)282 TEST(sched, sched_getscheduler_sched_setscheduler) {
283   // POSIX: "If pid is zero, the scheduling policy shall be returned for the
284   // calling process".
285   ASSERT_EQ(sched_getscheduler(getpid()), sched_getscheduler(0));
286 
287   const int original_policy = sched_getscheduler(getpid());
288   sched_param p = {};
289   p.sched_priority = sched_get_priority_min(original_policy);
290   errno = 0;
291   ASSERT_EQ(-1, sched_setscheduler(getpid(), INT_MAX, &p));
292   ASSERT_EQ(EINVAL, errno);
293 
294   ASSERT_EQ(0, sched_getparam(getpid(), &p));
295   ASSERT_EQ(original_policy, sched_setscheduler(getpid(), SCHED_BATCH, &p));
296   // POSIX says this should return the previous policy (here SCHED_BATCH),
297   // but the Linux system call doesn't, and the glibc wrapper doesn't correct
298   // this (the "returns 0" behavior is even documented on the man page in
299   // the BUGS section). This was our historical behavior too, so in the
300   // absence of reasons to break compatibility with ourselves and glibc, we
301   // don't behave as POSIX specifies. http://b/26203902.
302   ASSERT_EQ(0, sched_setscheduler(getpid(), original_policy, &p));
303 }
304