Loading libs/binder/Binder.cpp +44 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <binder/IShellCallback.h> #include <binder/Parcel.h> #include <linux/sched.h> #include <stdio.h> namespace android { Loading Loading @@ -133,6 +134,8 @@ public: // unlocked objects bool mRequestingSid = false; sp<IBinder> mExtension; int mPolicy = SCHED_NORMAL; int mPriority = 0; // for below objects Mutex mLock; Loading Loading @@ -279,6 +282,47 @@ sp<IBinder> BBinder::getExtension() { return e->mExtension; } void BBinder::setMinSchedulerPolicy(int policy, int priority) { switch (policy) { case SCHED_NORMAL: LOG_ALWAYS_FATAL_IF(priority < -20 || priority > 19, "Invalid priority for SCHED_NORMAL: %d", priority); break; case SCHED_RR: case SCHED_FIFO: LOG_ALWAYS_FATAL_IF(priority < 1 || priority > 99, "Invalid priority for sched %d: %d", policy, priority); break; default: LOG_ALWAYS_FATAL("Unrecognized scheduling policy: %d", policy); } Extras* e = mExtras.load(std::memory_order_acquire); if (e == nullptr) { // Avoid allocations if called with default. if (policy == SCHED_NORMAL && priority == 0) { return; } e = getOrCreateExtras(); if (!e) return; // out of memory } e->mPolicy = policy; e->mPriority = priority; } int BBinder::getMinSchedulerPolicy() { Extras* e = mExtras.load(std::memory_order_acquire); if (e == nullptr) return SCHED_NORMAL; return e->mPolicy; } int BBinder::getMinSchedulerPriority() { Extras* e = mExtras.load(std::memory_order_acquire); if (e == nullptr) return 0; return e->mPriority; } pid_t BBinder::getDebugPid() { return getpid(); } Loading libs/binder/Parcel.cpp +18 −6 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <errno.h> #include <fcntl.h> #include <inttypes.h> #include <linux/sched.h> #include <pthread.h> #include <stdint.h> #include <stdio.h> Loading Loading @@ -188,16 +189,18 @@ status_t Parcel::finishUnflattenBinder( return OK; } static constexpr inline int schedPolicyMask(int policy, int priority) { return (priority & FLAT_BINDER_FLAG_PRIORITY_MASK) | ((policy & 3) << FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT); } status_t Parcel::flattenBinder(const sp<IBinder>& binder) { flat_binder_object obj; if (IPCThreadState::self()->backgroundSchedulingDisabled()) { /* minimum priority for all nodes is nice 0 */ obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS; } else { /* minimum priority for all nodes is MAX_NICE(19) */ obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS; int schedBits = 0; if (!IPCThreadState::self()->backgroundSchedulingDisabled()) { schedBits = schedPolicyMask(SCHED_NORMAL, 19); } if (binder != nullptr) { Loading @@ -213,6 +216,13 @@ status_t Parcel::flattenBinder(const sp<IBinder>& binder) obj.handle = handle; obj.cookie = 0; } else { int policy = local->getMinSchedulerPolicy(); int priority = local->getMinSchedulerPriority(); if (policy != 0 || priority != 0) { // override value, since it is set explicitly schedBits = schedPolicyMask(policy, priority); } if (local->isRequestingSid()) { obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX; } Loading @@ -226,6 +236,8 @@ status_t Parcel::flattenBinder(const sp<IBinder>& binder) obj.cookie = 0; } obj.flags |= schedBits; return finishFlattenBinder(binder, obj); } Loading libs/binder/include/binder/Binder.h +19 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,25 @@ public: // This must be called before the object is sent to another process. Not thread safe. void setExtension(const sp<IBinder>& extension); // This must be called before the object is sent to another process. Not thread safe. // // This function will abort if improper parameters are set. This is like // sched_setscheduler. However, it sets the minimum scheduling policy // only for the duration that this specific binder object is handling the // call in a threadpool. By default, this API is set to SCHED_NORMAL/0. In // this case, the scheduling priority will not actually be modified from // binder defaults. See also IPCThreadState::disableBackgroundScheduling. // // Appropriate values are: // SCHED_NORMAL: -20 <= priority <= 19 // SCHED_RR/SCHED_FIFO: 1 <= priority <= 99 __attribute__((weak)) void setMinSchedulerPolicy(int policy, int priority); __attribute__((weak)) int getMinSchedulerPolicy(); __attribute__((weak)) int getMinSchedulerPriority(); pid_t getDebugPid(); protected: Loading libs/binder/tests/binderLibTest.cpp +32 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,9 @@ static char *binderservername; static char *binderserversuffix; static char binderserverarg[] = "--binderserver"; static constexpr int kSchedPolicy = SCHED_RR; static constexpr int kSchedPriority = 7; static String16 binderLibTestServiceName = String16("test.binderLib"); enum BinderLibTestTranscationCode { Loading @@ -75,6 +78,7 @@ enum BinderLibTestTranscationCode { BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION, BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION, BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, BINDER_LIB_TEST_GET_SCHEDULING_POLICY, BINDER_LIB_TEST_ECHO_VECTOR, BINDER_LIB_TEST_REJECT_BUF, }; Loading Loading @@ -1015,6 +1019,22 @@ TEST_F(BinderLibTest, WorkSourcePropagatedForAllFollowingBinderCalls) EXPECT_EQ(NO_ERROR, ret2); } TEST_F(BinderLibTest, SchedPolicySet) { sp<IBinder> server = addServer(); ASSERT_TRUE(server != nullptr); Parcel data, reply; status_t ret = server->transact(BINDER_LIB_TEST_GET_SCHEDULING_POLICY, data, &reply); EXPECT_EQ(NO_ERROR, ret); int policy = reply.readInt32(); int priority = reply.readInt32(); EXPECT_EQ(kSchedPolicy, policy & (~SCHED_RESET_ON_FORK)); EXPECT_EQ(kSchedPriority, priority); } TEST_F(BinderLibTest, VectorSent) { Parcel data, reply; sp<IBinder> server = addServer(); Loading Loading @@ -1332,6 +1352,16 @@ class BinderLibTestService : public BBinder reply->writeInt32(IPCThreadState::self()->getCallingWorkSourceUid()); return NO_ERROR; } case BINDER_LIB_TEST_GET_SCHEDULING_POLICY: { int policy = 0; sched_param param; if (0 != pthread_getschedparam(pthread_self(), &policy, ¶m)) { return UNKNOWN_ERROR; } reply->writeInt32(policy); reply->writeInt32(param.sched_priority); return NO_ERROR; } case BINDER_LIB_TEST_ECHO_VECTOR: { std::vector<uint64_t> vector; auto err = data.readUint64Vector(&vector); Loading Loading @@ -1368,6 +1398,8 @@ int run_server(int index, int readypipefd, bool usePoll) { sp<BinderLibTestService> testService = new BinderLibTestService(index); testService->setMinSchedulerPolicy(kSchedPolicy, kSchedPriority); /* * Normally would also contain functionality as well, but we are only * testing the extension mechanism. Loading Loading
libs/binder/Binder.cpp +44 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <binder/IShellCallback.h> #include <binder/Parcel.h> #include <linux/sched.h> #include <stdio.h> namespace android { Loading Loading @@ -133,6 +134,8 @@ public: // unlocked objects bool mRequestingSid = false; sp<IBinder> mExtension; int mPolicy = SCHED_NORMAL; int mPriority = 0; // for below objects Mutex mLock; Loading Loading @@ -279,6 +282,47 @@ sp<IBinder> BBinder::getExtension() { return e->mExtension; } void BBinder::setMinSchedulerPolicy(int policy, int priority) { switch (policy) { case SCHED_NORMAL: LOG_ALWAYS_FATAL_IF(priority < -20 || priority > 19, "Invalid priority for SCHED_NORMAL: %d", priority); break; case SCHED_RR: case SCHED_FIFO: LOG_ALWAYS_FATAL_IF(priority < 1 || priority > 99, "Invalid priority for sched %d: %d", policy, priority); break; default: LOG_ALWAYS_FATAL("Unrecognized scheduling policy: %d", policy); } Extras* e = mExtras.load(std::memory_order_acquire); if (e == nullptr) { // Avoid allocations if called with default. if (policy == SCHED_NORMAL && priority == 0) { return; } e = getOrCreateExtras(); if (!e) return; // out of memory } e->mPolicy = policy; e->mPriority = priority; } int BBinder::getMinSchedulerPolicy() { Extras* e = mExtras.load(std::memory_order_acquire); if (e == nullptr) return SCHED_NORMAL; return e->mPolicy; } int BBinder::getMinSchedulerPriority() { Extras* e = mExtras.load(std::memory_order_acquire); if (e == nullptr) return 0; return e->mPriority; } pid_t BBinder::getDebugPid() { return getpid(); } Loading
libs/binder/Parcel.cpp +18 −6 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <errno.h> #include <fcntl.h> #include <inttypes.h> #include <linux/sched.h> #include <pthread.h> #include <stdint.h> #include <stdio.h> Loading Loading @@ -188,16 +189,18 @@ status_t Parcel::finishUnflattenBinder( return OK; } static constexpr inline int schedPolicyMask(int policy, int priority) { return (priority & FLAT_BINDER_FLAG_PRIORITY_MASK) | ((policy & 3) << FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT); } status_t Parcel::flattenBinder(const sp<IBinder>& binder) { flat_binder_object obj; if (IPCThreadState::self()->backgroundSchedulingDisabled()) { /* minimum priority for all nodes is nice 0 */ obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS; } else { /* minimum priority for all nodes is MAX_NICE(19) */ obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS; int schedBits = 0; if (!IPCThreadState::self()->backgroundSchedulingDisabled()) { schedBits = schedPolicyMask(SCHED_NORMAL, 19); } if (binder != nullptr) { Loading @@ -213,6 +216,13 @@ status_t Parcel::flattenBinder(const sp<IBinder>& binder) obj.handle = handle; obj.cookie = 0; } else { int policy = local->getMinSchedulerPolicy(); int priority = local->getMinSchedulerPriority(); if (policy != 0 || priority != 0) { // override value, since it is set explicitly schedBits = schedPolicyMask(policy, priority); } if (local->isRequestingSid()) { obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX; } Loading @@ -226,6 +236,8 @@ status_t Parcel::flattenBinder(const sp<IBinder>& binder) obj.cookie = 0; } obj.flags |= schedBits; return finishFlattenBinder(binder, obj); } Loading
libs/binder/include/binder/Binder.h +19 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,25 @@ public: // This must be called before the object is sent to another process. Not thread safe. void setExtension(const sp<IBinder>& extension); // This must be called before the object is sent to another process. Not thread safe. // // This function will abort if improper parameters are set. This is like // sched_setscheduler. However, it sets the minimum scheduling policy // only for the duration that this specific binder object is handling the // call in a threadpool. By default, this API is set to SCHED_NORMAL/0. In // this case, the scheduling priority will not actually be modified from // binder defaults. See also IPCThreadState::disableBackgroundScheduling. // // Appropriate values are: // SCHED_NORMAL: -20 <= priority <= 19 // SCHED_RR/SCHED_FIFO: 1 <= priority <= 99 __attribute__((weak)) void setMinSchedulerPolicy(int policy, int priority); __attribute__((weak)) int getMinSchedulerPolicy(); __attribute__((weak)) int getMinSchedulerPriority(); pid_t getDebugPid(); protected: Loading
libs/binder/tests/binderLibTest.cpp +32 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,9 @@ static char *binderservername; static char *binderserversuffix; static char binderserverarg[] = "--binderserver"; static constexpr int kSchedPolicy = SCHED_RR; static constexpr int kSchedPriority = 7; static String16 binderLibTestServiceName = String16("test.binderLib"); enum BinderLibTestTranscationCode { Loading @@ -75,6 +78,7 @@ enum BinderLibTestTranscationCode { BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION, BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION, BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, BINDER_LIB_TEST_GET_SCHEDULING_POLICY, BINDER_LIB_TEST_ECHO_VECTOR, BINDER_LIB_TEST_REJECT_BUF, }; Loading Loading @@ -1015,6 +1019,22 @@ TEST_F(BinderLibTest, WorkSourcePropagatedForAllFollowingBinderCalls) EXPECT_EQ(NO_ERROR, ret2); } TEST_F(BinderLibTest, SchedPolicySet) { sp<IBinder> server = addServer(); ASSERT_TRUE(server != nullptr); Parcel data, reply; status_t ret = server->transact(BINDER_LIB_TEST_GET_SCHEDULING_POLICY, data, &reply); EXPECT_EQ(NO_ERROR, ret); int policy = reply.readInt32(); int priority = reply.readInt32(); EXPECT_EQ(kSchedPolicy, policy & (~SCHED_RESET_ON_FORK)); EXPECT_EQ(kSchedPriority, priority); } TEST_F(BinderLibTest, VectorSent) { Parcel data, reply; sp<IBinder> server = addServer(); Loading Loading @@ -1332,6 +1352,16 @@ class BinderLibTestService : public BBinder reply->writeInt32(IPCThreadState::self()->getCallingWorkSourceUid()); return NO_ERROR; } case BINDER_LIB_TEST_GET_SCHEDULING_POLICY: { int policy = 0; sched_param param; if (0 != pthread_getschedparam(pthread_self(), &policy, ¶m)) { return UNKNOWN_ERROR; } reply->writeInt32(policy); reply->writeInt32(param.sched_priority); return NO_ERROR; } case BINDER_LIB_TEST_ECHO_VECTOR: { std::vector<uint64_t> vector; auto err = data.readUint64Vector(&vector); Loading Loading @@ -1368,6 +1398,8 @@ int run_server(int index, int readypipefd, bool usePoll) { sp<BinderLibTestService> testService = new BinderLibTestService(index); testService->setMinSchedulerPolicy(kSchedPolicy, kSchedPriority); /* * Normally would also contain functionality as well, but we are only * testing the extension mechanism. Loading