use a socketpair instead of a pipe in BitTube
Bug: 6252830
Change-Id: Ia7a7b08409517214136261c05569dc5959a597ab
diff --git a/libs/gui/BitTube.cpp b/libs/gui/BitTube.cpp
index 55f4178..355a319 100644
--- a/libs/gui/BitTube.cpp
+++ b/libs/gui/BitTube.cpp
@@ -16,9 +16,9 @@
#include <stdint.h>
#include <sys/types.h>
+#include <sys/socket.h>
#include <fcntl.h>
-#include <signal.h>
#include <unistd.h>
#include <utils/Errors.h>
@@ -30,17 +30,25 @@
namespace android {
// ----------------------------------------------------------------------------
+// Socket buffer size. The default is typically about 128KB, which is much larger than
+// we really need. So we make it smaller.
+static const size_t SOCKET_BUFFER_SIZE = 4 * 1024;
+
+
BitTube::BitTube()
: mSendFd(-1), mReceiveFd(-1)
{
- int fds[2];
- if (pipe(fds) == 0) {
- mReceiveFd = fds[0];
- mSendFd = fds[1];
- fcntl(mReceiveFd, F_SETFL, O_NONBLOCK);
- fcntl(mSendFd, F_SETFL, O_NONBLOCK);
- // ignore SIGPIPE, we handle write errors through EPIPE instead
- signal(SIGPIPE, SIG_IGN);
+ int sockets[2];
+ if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
+ int size = SOCKET_BUFFER_SIZE;
+ setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
+ setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
+ setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
+ setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
+ fcntl(sockets[0], F_SETFL, O_NONBLOCK);
+ fcntl(sockets[1], F_SETFL, O_NONBLOCK);
+ mReceiveFd = sockets[0];
+ mSendFd = sockets[1];
} else {
mReceiveFd = -errno;
ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));
@@ -52,6 +60,9 @@
{
mReceiveFd = dup(data.readFileDescriptor());
if (mReceiveFd >= 0) {
+ int size = SOCKET_BUFFER_SIZE;
+ setsockopt(mReceiveFd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
+ setsockopt(mReceiveFd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
fcntl(mReceiveFd, F_SETFL, O_NONBLOCK);
} else {
mReceiveFd = -errno;
@@ -86,7 +97,7 @@
{
ssize_t err, len;
do {
- len = ::write(mSendFd, vaddr, size);
+ len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);
err = len < 0 ? errno : 0;
} while (err == EINTR);
return err == 0 ? len : -err;
@@ -97,7 +108,7 @@
{
ssize_t err, len;
do {
- len = ::read(mReceiveFd, vaddr, size);
+ len = ::recv(mReceiveFd, vaddr, size, MSG_DONTWAIT);
err = len < 0 ? errno : 0;
} while (err == EINTR);
if (err == EAGAIN || err == EWOULDBLOCK) {
@@ -119,5 +130,46 @@
return result;
}
+
+ssize_t BitTube::sendObjects(const sp<BitTube>& tube,
+ void const* events, size_t count, size_t objSize)
+{
+ ssize_t numObjects = 0;
+ for (size_t i=0 ; i<count ; i++) {
+ const char* vaddr = reinterpret_cast<const char*>(events) + objSize * i;
+ ssize_t size = tube->write(vaddr, objSize);
+ if (size < 0) {
+ // error occurred
+ numObjects = -size;
+ break;
+ } else if (size == 0) {
+ // no more space
+ break;
+ }
+ numObjects++;
+ }
+ return numObjects;
+}
+
+ssize_t BitTube::recvObjects(const sp<BitTube>& tube,
+ void* events, size_t count, size_t objSize)
+{
+ ssize_t numObjects = 0;
+ for (size_t i=0 ; i<count ; i++) {
+ char* vaddr = reinterpret_cast<char*>(events) + objSize * i;
+ ssize_t size = tube->read(vaddr, objSize);
+ if (size < 0) {
+ // error occurred
+ numObjects = -size;
+ break;
+ } else if (size == 0) {
+ // no more messages
+ break;
+ }
+ numObjects++;
+ }
+ return numObjects;
+}
+
// ----------------------------------------------------------------------------
}; // namespace android