libcutils: ashmem: Avoid doing fd checks for ashmem calls

Callers already verify that they are calling ashmem API on a valid fd by
calling ashmem_valid first. Lets make the fstat syscall only if the
ioctl returns -ENOTTY. This means in the regular case, only 1 syscall is
needed (ioctl) vs the current 2 (fstat+ioctl).

Some data to show improvements in reduction of vfs_getattr calls in the
kernel by 10x when doing a camera.

Test: Boot and camera CTS
Bug: 111418894
Change-Id: I992620bbe44355e54ba19eeac81da586c5e5a6e0
Signed-off-by: Joel Fernandes <joelaf@google.com>
This commit is contained in:
Joel Fernandes 2018-07-17 13:00:17 -07:00
parent a73ea65c5a
commit 56cd651e7a

View file

@ -90,7 +90,7 @@ static int __ashmem_is_ashmem(int fd, int fatal)
dev_t rdev;
struct stat st;
if (TEMP_FAILURE_RETRY(fstat(fd, &st)) < 0) {
if (fstat(fd, &st) < 0) {
return -1;
}
@ -135,6 +135,12 @@ static int __ashmem_is_ashmem(int fd, int fatal)
return -1;
}
static int __ashmem_check_failure(int fd, int result)
{
if (result == -1 && errno == ENOTTY) __ashmem_is_ashmem(fd, 1);
return result;
}
int ashmem_valid(int fd)
{
return __ashmem_is_ashmem(fd, 0) >= 0;
@ -182,12 +188,7 @@ error:
int ashmem_set_prot_region(int fd, int prot)
{
int ret = __ashmem_is_ashmem(fd, 1);
if (ret < 0) {
return ret;
}
return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_SET_PROT_MASK, prot));
return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_SET_PROT_MASK, prot)));
}
int ashmem_pin_region(int fd, size_t offset, size_t len)
@ -195,12 +196,7 @@ int ashmem_pin_region(int fd, size_t offset, size_t len)
// TODO: should LP64 reject too-large offset/len?
ashmem_pin pin = { static_cast<uint32_t>(offset), static_cast<uint32_t>(len) };
int ret = __ashmem_is_ashmem(fd, 1);
if (ret < 0) {
return ret;
}
return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_PIN, &pin));
return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_PIN, &pin)));
}
int ashmem_unpin_region(int fd, size_t offset, size_t len)
@ -208,20 +204,10 @@ int ashmem_unpin_region(int fd, size_t offset, size_t len)
// TODO: should LP64 reject too-large offset/len?
ashmem_pin pin = { static_cast<uint32_t>(offset), static_cast<uint32_t>(len) };
int ret = __ashmem_is_ashmem(fd, 1);
if (ret < 0) {
return ret;
}
return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_UNPIN, &pin));
return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_UNPIN, &pin)));
}
int ashmem_get_size_region(int fd)
{
int ret = __ashmem_is_ashmem(fd, 1);
if (ret < 0) {
return ret;
}
return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_GET_SIZE, NULL));
return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_GET_SIZE, NULL)));
}