From 1104ae8cfc0e5144e7d796cf29ee124d05401cbf Mon Sep 17 00:00:00 2001 From: Mathieu Chartier Date: Tue, 3 Jun 2014 10:24:21 -0700 Subject: Make host ashmem_create_region seed only once. Not seeding this each call should help reduce collisions when multiple threads are calling ashmem_create_region. Also cleaned up code by deleting gotos, and making formatting consistent. Bug: 15394258 Change-Id: Iafdaea57b2317e0eb7c40d7b5595c523814fd88c --- libcutils/ashmem-host.c | 124 ++++++++++++++++++++++++------------------------ 1 file changed, 63 insertions(+), 61 deletions(-) (limited to 'libcutils') diff --git a/libcutils/ashmem-host.c b/libcutils/ashmem-host.c index 7873964..4ac4f57 100644 --- a/libcutils/ashmem-host.c +++ b/libcutils/ashmem-host.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include #include @@ -36,83 +38,83 @@ #define __unused __attribute__((__unused__)) #endif +static pthread_once_t seed_initialized = PTHREAD_ONCE_INIT; +static void initialize_random() { + srand(time(NULL) + getpid()); +} + int ashmem_create_region(const char *ignored __unused, size_t size) { - static const char txt[] = "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - char name[64]; - unsigned int retries = 0; - pid_t pid = getpid(); - int fd; - - srand(time(NULL) + pid); - -retry: - /* not beautiful, its just wolf-like loop unrolling */ - snprintf(name, sizeof(name), "/tmp/android-ashmem-%d-%c%c%c%c%c%c%c%c", - pid, - txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))], - txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))], - txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))], - txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))], - txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))], - txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))], - txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))], - txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))]); - - /* open O_EXCL & O_CREAT: we are either the sole owner or we fail */ - fd = open(name, O_RDWR | O_CREAT | O_EXCL, 0600); - if (fd == -1) { - /* unlikely, but if we failed because `name' exists, retry */ - if (errno == EEXIST && ++retries < 6) - goto retry; - return -1; - } - - /* truncate the file to `len' bytes */ - if (ftruncate(fd, size) == -1) - goto error; - - if (unlink(name) == -1) - goto error; - - return fd; -error: - close(fd); - return -1; + static const char txt[] = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + char name[64]; + unsigned int retries = 0; + pid_t pid = getpid(); + int fd; + if (pthread_once(&seed_initialized, &initialize_random) != 0) { + return -1; + } + do { + /* not beautiful, its just wolf-like loop unrolling */ + snprintf(name, sizeof(name), "/tmp/android-ashmem-%d-%c%c%c%c%c%c%c%c", + pid, + txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))], + txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))], + txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))], + txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))], + txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))], + txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))], + txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))], + txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))]); + + /* open O_EXCL & O_CREAT: we are either the sole owner or we fail */ + fd = open(name, O_RDWR | O_CREAT | O_EXCL, 0600); + if (fd == -1) { + /* unlikely, but if we failed because `name' exists, retry */ + if (errno != EEXIST || ++retries >= 6) { + return -1; + } + } + } while (fd == -1); + /* truncate the file to `len' bytes */ + if (ftruncate(fd, size) != -1 && unlink(name) != -1) { + return fd; + } + close(fd); + return -1; } int ashmem_set_prot_region(int fd __unused, int prot __unused) { - return 0; + return 0; } int ashmem_pin_region(int fd __unused, size_t offset __unused, size_t len __unused) { - return ASHMEM_NOT_PURGED; + return ASHMEM_NOT_PURGED; } int ashmem_unpin_region(int fd __unused, size_t offset __unused, size_t len __unused) { - return ASHMEM_IS_UNPINNED; + return ASHMEM_IS_UNPINNED; } int ashmem_get_size_region(int fd) { - struct stat buf; - int result; - - result = fstat(fd, &buf); - if (result == -1) { - return -1; - } - - // Check if this is an "ashmem" region. - // TODO: This is very hacky, and can easily break. We need some reliable indicator. - if (!(buf.st_nlink == 0 && S_ISREG(buf.st_mode))) { - errno = ENOTTY; - return -1; - } - - return (int)buf.st_size; // TODO: care about overflow (> 2GB file)? + struct stat buf; + int result; + + result = fstat(fd, &buf); + if (result == -1) { + return -1; + } + + // Check if this is an "ashmem" region. + // TODO: This is very hacky, and can easily break. We need some reliable indicator. + if (!(buf.st_nlink == 0 && S_ISREG(buf.st_mode))) { + errno = ENOTTY; + return -1; + } + + return (int)buf.st_size; // TODO: care about overflow (> 2GB file)? } -- cgit v1.1