From ed0614c80bbea861bf922a63c08e1eb2ad9ce814 Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Wed, 3 Aug 2016 10:41:54 -0700 Subject: [PATCH] libcutils: add sched_policy test Bug: 30597190 Change-Id: I51950e82235fa19bc92b3f7e8d190766d71af7df Signed-off-by: Greg Hackmann --- libcutils/tests/Android.bp | 1 + libcutils/tests/sched_policy_test.cpp | 98 +++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 libcutils/tests/sched_policy_test.cpp diff --git a/libcutils/tests/Android.bp b/libcutils/tests/Android.bp index 530c74716..ada7d5f06 100644 --- a/libcutils/tests/Android.bp +++ b/libcutils/tests/Android.bp @@ -21,6 +21,7 @@ cc_defaults { srcs: [ "MemsetTest.cpp", "PropertiesTest.cpp", + "sched_policy_test.cpp", "trace-dev_test.cpp", ], }, diff --git a/libcutils/tests/sched_policy_test.cpp b/libcutils/tests/sched_policy_test.cpp new file mode 100644 index 000000000..173174a1a --- /dev/null +++ b/libcutils/tests/sched_policy_test.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * 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. + */ + +#include +#include +#include +#include + +#include + +#include + +#include + +bool hasCapSysNice() { + __user_cap_header_struct header; + memset(&header, 0, sizeof(header)); + header.version = _LINUX_CAPABILITY_VERSION_3; + + __user_cap_data_struct caps[_LINUX_CAPABILITY_U32S_3]; + if (capget(&header, &caps[0])) { + GTEST_LOG_(WARNING) << "failed to get process capabilities"; + return false; + } + + auto nice_idx = CAP_TO_INDEX(CAP_SYS_NICE); + auto nice_mask = CAP_TO_MASK(CAP_SYS_NICE); + return caps[nice_idx].effective & nice_mask; +} + +long long medianSleepTime() { + std::vector sleepTimes; + constexpr size_t numSamples = 100; + + for (size_t i = 0; i < numSamples; i++) { + auto start = std::chrono::steady_clock::now(); + std::this_thread::sleep_for(std::chrono::nanoseconds(1)); + auto end = std::chrono::steady_clock::now(); + + auto diff = end - start; + sleepTimes.push_back(diff.count()); + } + + constexpr auto median = numSamples / 2; + std::nth_element(sleepTimes.begin(), sleepTimes.begin() + median, + sleepTimes.end()); + return sleepTimes[median]; +} + +TEST(SchedPolicy, set_sched_policy) { + if (!hasCapSysNice()) { + GTEST_LOG_(INFO) << "skipping test that requires CAP_SYS_NICE"; + return; + } + + // A measureable effect of scheduling policy is that the kernel has 800x + // greater slack time in waking up a sleeping background thread. + // + // Look for 100x difference in how long FB and BG threads actually sleep + // when trying to sleep for 1 ns. This difference is large enough not + // to happen by chance, but small enough (compared to 800x) to keep inherent + // fuzziness in scheduler behavior from causing false negatives. + const unsigned int BG_FG_SLACK_FACTOR = 100; + + ASSERT_EQ(0, set_sched_policy(0, SP_BACKGROUND)); + auto bgSleepTime = medianSleepTime(); + + ASSERT_EQ(0, set_sched_policy(0, SP_FOREGROUND)); + auto fgSleepTime = medianSleepTime(); + ASSERT_GT(bgSleepTime, fgSleepTime * BG_FG_SLACK_FACTOR); +} + +TEST(SchedPolicy, get_sched_policy) { + SchedPolicy policy; + ASSERT_EQ(0, get_sched_policy(0, &policy)); + + const char *policyName = get_sched_policy_name(policy); + EXPECT_NE(nullptr, policyName); + EXPECT_STRNE("error", policyName); + + ASSERT_EQ(0, set_sched_policy(0, SP_BACKGROUND)); + SchedPolicy newPolicy; + ASSERT_EQ(0, get_sched_policy(0, &newPolicy)); + EXPECT_EQ(SP_BACKGROUND, newPolicy); +}