diff options
author | 2021-09-29 14:54:48 +0000 | |
---|---|---|
committer | 2021-09-29 14:54:48 +0000 | |
commit | b37acedb7fcc4c89b191548ad0e605e33d2cc4dc (patch) | |
tree | 385f4a96a367df74fda106e9716c5ef65765dbb0 /libs/binder/RpcState.cpp | |
parent | a7e51752c22427dc918281ea739f391aab35bf9f (diff) | |
parent | 43921d5d92d6e27bf1ec00de062746f032268717 (diff) |
Merge changes from topic "libbinder-rpc-perf-poll"
* changes:
libbinder: RPC handle builtup refcounts
libbinder: RPC avoid poll
libbinder: RPC simpl transactAddressInternal
Diffstat (limited to 'libs/binder/RpcState.cpp')
-rw-r--r-- | libs/binder/RpcState.cpp | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp index 3ff13bcd9b..86cc91c03e 100644 --- a/libs/binder/RpcState.cpp +++ b/libs/binder/RpcState.cpp @@ -307,7 +307,7 @@ RpcState::CommandData::CommandData(size_t size) : mSize(size) { status_t RpcState::rpcSend(const sp<RpcSession::RpcConnection>& connection, const sp<RpcSession>& session, const char* what, const void* data, - size_t size) { + size_t size, const std::function<status_t()>& altPoll) { LOG_RPC_DETAIL("Sending %s on RpcTransport %p: %s", what, connection->rpcTransport.get(), android::base::HexString(data, size).c_str()); @@ -319,7 +319,7 @@ status_t RpcState::rpcSend(const sp<RpcSession::RpcConnection>& connection, if (status_t status = connection->rpcTransport->interruptableWriteFully(session->mShutdownTrigger.get(), - data, size); + data, size, altPoll); status != OK) { LOG_RPC_DETAIL("Failed to write %s (%zu bytes) on RpcTransport %p, error: %s", what, size, connection->rpcTransport.get(), statusToString(status).c_str()); @@ -341,7 +341,7 @@ status_t RpcState::rpcRec(const sp<RpcSession::RpcConnection>& connection, if (status_t status = connection->rpcTransport->interruptableReadFully(session->mShutdownTrigger.get(), - data, size); + data, size, {}); status != OK) { LOG_RPC_DETAIL("Failed to read %s (%zu bytes) on RpcTransport %p, error: %s", what, size, connection->rpcTransport.get(), statusToString(status).c_str()); @@ -523,21 +523,44 @@ status_t RpcState::transactAddress(const sp<RpcSession::RpcConnection>& connecti memcpy(transactionData.data() + sizeof(RpcWireHeader) + sizeof(RpcWireTransaction), data.data(), data.dataSize()); + constexpr size_t kWaitMaxUs = 1000000; + constexpr size_t kWaitLogUs = 10000; + size_t waitUs = 0; + + // Oneway calls have no sync point, so if many are sent before, whether this + // is a twoway or oneway transaction, they may have filled up the socket. + // So, make sure we drain them before polling. + std::function<status_t()> drainRefs = [&] { + if (waitUs > kWaitLogUs) { + ALOGE("Cannot send command, trying to process pending refcounts. Waiting %zuus. Too " + "many oneway calls?", + waitUs); + } + + if (waitUs > 0) { + usleep(waitUs); + waitUs = std::min(kWaitMaxUs, waitUs * 2); + } else { + waitUs = 1; + } + + return drainCommands(connection, session, CommandType::CONTROL_ONLY); + }; + if (status_t status = rpcSend(connection, session, "transaction", transactionData.data(), - transactionData.size()); - status != OK) + transactionData.size(), drainRefs); + status != OK) { // TODO(b/167966510): need to undo onBinderLeaving - we know the // refcount isn't successfully transferred. return status; + } if (flags & IBinder::FLAG_ONEWAY) { LOG_RPC_DETAIL("Oneway command, so no longer waiting on RpcTransport %p", connection->rpcTransport.get()); // Do not wait on result. - // However, too many oneway calls may cause refcounts to build up and fill up the socket, - // so process those. - return drainCommands(connection, session, CommandType::CONTROL_ONLY); + return OK; } LOG_ALWAYS_FATAL_IF(reply == nullptr, "Reply parcel must be used for synchronous transaction."); @@ -723,7 +746,7 @@ status_t RpcState::processTransactInternal(const sp<RpcSession::RpcConnection>& // for 'recursive' calls to this, we have already read and processed the // binder from the transaction data and taken reference counts into account, // so it is cached here. - sp<IBinder> targetRef; + sp<IBinder> target; processTransactInternalTailCall: if (transactionData.size() < sizeof(RpcWireTransaction)) { @@ -738,12 +761,9 @@ processTransactInternalTailCall: bool oneway = transaction->flags & IBinder::FLAG_ONEWAY; status_t replyStatus = OK; - sp<IBinder> target; if (addr != 0) { - if (!targetRef) { + if (!target) { replyStatus = onBinderEntering(session, addr, &target); - } else { - target = targetRef; } if (replyStatus != OK) { @@ -910,7 +930,8 @@ processTransactInternalTailCall: // reset up arguments transactionData = std::move(todo.data); - targetRef = std::move(todo.ref); + LOG_ALWAYS_FATAL_IF(target != todo.ref, + "async list should be associated with a binder"); it->second.asyncTodo.pop(); goto processTransactInternalTailCall; |