[2/n] Improvements to AddressSpaceStream protocol
- Add a new state that represents the emulator rendering for sure.
- Avoid excessive notification spam.
- Add writeFullyAsync, writeFully that doesn't wait for finish.
This should be compatible with older hosts, but will notify old hosts
a bit more.
Bug: 177241396
Change-Id: Icfb00757a419f0b1328ff66eca39e51c566d8e11
diff --git a/system/OpenglSystemCommon/AddressSpaceStream.cpp b/system/OpenglSystemCommon/AddressSpaceStream.cpp
index 8c30afd..53b5285 100644
--- a/system/OpenglSystemCommon/AddressSpaceStream.cpp
+++ b/system/OpenglSystemCommon/AddressSpaceStream.cpp
@@ -15,6 +15,8 @@
*/
#include "AddressSpaceStream.h"
+#include "android/base/Tracing.h"
+
#if PLATFORM_SDK_VERSION < 26
#include <cutils/log.h>
#else
@@ -321,6 +323,9 @@
}
void *AddressSpaceStream::allocBuffer(size_t minSize) {
+ AEMU_SCOPED_TRACE("allocBuffer");
+ ensureType3Finished();
+
if (!m_readBuf) {
m_readBuf = (unsigned char*)malloc(kReadSize);
}
@@ -465,7 +470,7 @@
int AddressSpaceStream::writeFully(const void *buf, size_t size)
{
- ensureConsumerFinishing();
+ AEMU_SCOPED_TRACE("writeFully");
ensureType3Finished();
ensureType1Finished();
@@ -473,10 +478,77 @@
m_context.ring_config->transfer_mode = 3;
size_t sent = 0;
- size_t quarterRingSize = m_writeBufferSize / 4;
- size_t chunkSize = size < quarterRingSize ? size : quarterRingSize;
+ size_t preferredChunkSize = m_writeBufferSize / 4;
+ size_t chunkSize = size < preferredChunkSize ? size : preferredChunkSize;
const uint8_t* bufferBytes = (const uint8_t*)buf;
+ bool hostPinged = false;
+ while (sent < size) {
+ size_t remaining = size - sent;
+ size_t sendThisTime = remaining < chunkSize ? remaining : chunkSize;
+
+ long sentChunks =
+ ring_buffer_view_write(
+ m_context.to_host_large_xfer.ring,
+ &m_context.to_host_large_xfer.view,
+ bufferBytes + sent, sendThisTime, 1);
+
+ if (!hostPinged && *(m_context.host_state) != ASG_HOST_STATE_CAN_CONSUME &&
+ *(m_context.host_state) != ASG_HOST_STATE_RENDERING) {
+ notifyAvailable();
+ hostPinged = true;
+ }
+
+ if (sentChunks == 0) {
+ ring_buffer_yield();
+ backoff();
+ }
+
+ sent += sentChunks * sendThisTime;
+
+ if (isInError()) {
+ return -1;
+ }
+ }
+
+ bool isRenderingAfter = ASG_HOST_STATE_RENDERING == __atomic_load_n(m_context.host_state, __ATOMIC_ACQUIRE);
+
+ if (!isRenderingAfter) {
+ notifyAvailable();
+ }
+
+ ensureType3Finished();
+
+ resetBackoff();
+ m_context.ring_config->transfer_mode = 1;
+ m_written += size;
+
+ float mb = (float)m_written / 1048576.0f;
+ if (mb > 100.0f) {
+ ALOGD("%s: %f mb in %d notifs. %f mb/notif\n", __func__,
+ mb, m_notifs, m_notifs ? mb / (float)m_notifs : 0.0f);
+ m_notifs = 0;
+ m_written = 0;
+ }
+ return 0;
+}
+
+int AddressSpaceStream::writeFullyAsync(const void *buf, size_t size)
+{
+ AEMU_SCOPED_TRACE("writeFullyAsync");
+ ensureType3Finished();
+ ensureType1Finished();
+
+ __atomic_store_n(&m_context.ring_config->transfer_size, size, __ATOMIC_RELEASE);
+ m_context.ring_config->transfer_mode = 3;
+
+ size_t sent = 0;
+ size_t preferredChunkSize = m_writeBufferSize / 2;
+ size_t chunkSize = size < preferredChunkSize ? size : preferredChunkSize;
+ const uint8_t* bufferBytes = (const uint8_t*)buf;
+
+ bool pingedHost = false;
+
while (sent < size) {
size_t remaining = size - sent;
size_t sendThisTime = remaining < chunkSize ? remaining : chunkSize;
@@ -487,7 +559,12 @@
&m_context.to_host_large_xfer.view,
bufferBytes + sent, sendThisTime, 1);
- if (*(m_context.host_state) != ASG_HOST_STATE_CAN_CONSUME) {
+ uint32_t hostState = __atomic_load_n(m_context.host_state, __ATOMIC_ACQUIRE);
+
+ if (!pingedHost &&
+ hostState != ASG_HOST_STATE_CAN_CONSUME &&
+ hostState != ASG_HOST_STATE_RENDERING) {
+ pingedHost = true;
notifyAvailable();
}
@@ -503,10 +580,24 @@
}
}
- ensureType3Finished();
+
+ bool isRenderingAfter = ASG_HOST_STATE_RENDERING == __atomic_load_n(m_context.host_state, __ATOMIC_ACQUIRE);
+
+ if (!isRenderingAfter) {
+ notifyAvailable();
+ }
+
resetBackoff();
m_context.ring_config->transfer_mode = 1;
m_written += size;
+
+ float mb = (float)m_written / 1048576.0f;
+ if (mb > 100.0f) {
+ ALOGD("%s: %f mb in %d notifs. %f mb/notif\n", __func__,
+ mb, m_notifs, m_notifs ? mb / (float)m_notifs : 0.0f);
+ m_notifs = 0;
+ m_written = 0;
+ }
return 0;
}
@@ -529,7 +620,6 @@
}
ssize_t AddressSpaceStream::speculativeRead(unsigned char* readBuffer, size_t trySize) {
- ensureConsumerFinishing();
ensureType3Finished();
ensureType1Finished();
@@ -568,6 +658,7 @@
}
void AddressSpaceStream::notifyAvailable() {
+ AEMU_SCOPED_TRACE("PING");
struct address_space_ping request;
request.metadata = ASG_NOTIFY_AVAILABLE;
m_ops.ping(m_handle, &request);
@@ -597,7 +688,8 @@
break;
}
- if (*(m_context.host_state) != ASG_HOST_STATE_CAN_CONSUME) {
+ if (*(m_context.host_state) != ASG_HOST_STATE_CAN_CONSUME &&
+ *(m_context.host_state) != ASG_HOST_STATE_RENDERING) {
notifyAvailable();
break;
}
@@ -607,7 +699,7 @@
}
void AddressSpaceStream::ensureType1Finished() {
- ensureConsumerFinishing();
+ AEMU_SCOPED_TRACE("ensureType1Finished");
uint32_t currAvailRead =
ring_buffer_available_read(m_context.to_host, 0);
@@ -623,6 +715,7 @@
}
void AddressSpaceStream::ensureType3Finished() {
+ AEMU_SCOPED_TRACE("ensureType3Finished");
uint32_t availReadLarge =
ring_buffer_available_read(
m_context.to_host_large_xfer.ring,
@@ -634,7 +727,8 @@
ring_buffer_available_read(
m_context.to_host_large_xfer.ring,
&m_context.to_host_large_xfer.view);
- if (*(m_context.host_state) != ASG_HOST_STATE_CAN_CONSUME) {
+ if (*(m_context.host_state) != ASG_HOST_STATE_CAN_CONSUME &&
+ *(m_context.host_state) != ASG_HOST_STATE_RENDERING) {
notifyAvailable();
}
if (isInError()) {
@@ -644,6 +738,11 @@
}
int AddressSpaceStream::type1Write(uint32_t bufferOffset, size_t size) {
+
+ AEMU_SCOPED_TRACE("type1Write");
+
+ ensureType3Finished();
+
size_t sent = 0;
size_t sizeForRing = sizeof(struct asg_type1_xfer);
@@ -663,10 +762,10 @@
uint32_t ringAvailReadNow = ring_buffer_available_read(m_context.to_host, 0);
while (ringAvailReadNow >= maxOutstanding * sizeForRing) {
- ensureConsumerFinishing();
ringAvailReadNow = ring_buffer_available_read(m_context.to_host, 0);
}
+ bool hostPinged = false;
while (sent < sizeForRing) {
long sentChunks = ring_buffer_write(
@@ -674,8 +773,11 @@
writeBufferBytes + sent,
sizeForRing - sent, 1);
- if (*(m_context.host_state) != ASG_HOST_STATE_CAN_CONSUME) {
+ if (!hostPinged &&
+ *(m_context.host_state) != ASG_HOST_STATE_CAN_CONSUME &&
+ *(m_context.host_state) != ASG_HOST_STATE_RENDERING) {
notifyAvailable();
+ hostPinged = true;
}
if (sentChunks == 0) {
@@ -690,7 +792,12 @@
}
}
- ensureConsumerFinishing();
+ bool isRenderingAfter = ASG_HOST_STATE_RENDERING == __atomic_load_n(m_context.host_state, __ATOMIC_ACQUIRE);
+
+ if (!isRenderingAfter) {
+ notifyAvailable();
+ }
+
m_written += size;
float mb = (float)m_written / 1048576.0f;
@@ -706,7 +813,7 @@
}
void AddressSpaceStream::backoff() {
-#if defined(__APPLE__) || defined(__MACOSX) || defined(__Fuchsia__)
+#if defined(HOST_BUILD) || defined(__APPLE__) || defined(__MACOSX) || defined(__Fuchsia__)
static const uint32_t kBackoffItersThreshold = 50000000;
static const uint32_t kBackoffFactorDoublingIncrement = 50000000;
#else
diff --git a/system/OpenglSystemCommon/AddressSpaceStream.h b/system/OpenglSystemCommon/AddressSpaceStream.h
index 9e81120..62f235e 100644
--- a/system/OpenglSystemCommon/AddressSpaceStream.h
+++ b/system/OpenglSystemCommon/AddressSpaceStream.h
@@ -44,6 +44,7 @@
virtual const unsigned char *readFully( void *buf, size_t len);
virtual const unsigned char *read( void *buf, size_t *inout_len);
virtual int writeFully(const void *buf, size_t len);
+ virtual int writeFullyAsync(const void *buf, size_t len);
virtual const unsigned char *commitBufferAndReadFully(size_t size, void *buf, size_t len);
int getRendernodeFd() const {
@@ -97,8 +98,8 @@
uint32_t m_notifs;
uint32_t m_written;
- uint32_t m_backoffIters;
- uint32_t m_backoffFactor;
+ uint64_t m_backoffIters;
+ uint64_t m_backoffFactor;
};
#endif
diff --git a/system/OpenglSystemCommon/address_space_graphics_types.h b/system/OpenglSystemCommon/address_space_graphics_types.h
index 753644b..42c00f6 100644
--- a/system/OpenglSystemCommon/address_space_graphics_types.h
+++ b/system/OpenglSystemCommon/address_space_graphics_types.h
@@ -102,6 +102,9 @@
// Error: Something weird happened and we need to exit.
ASG_HOST_STATE_ERROR = 3,
+
+ // Host is rendering
+ ASG_HOST_STATE_RENDERING = 4,
};
struct asg_ring_config;