diff options
author | Mathieu Chartier <mathieuc@google.com> | 2014-06-03 10:24:21 -0700 |
---|---|---|
committer | Mathieu Chartier <mathieuc@google.com> | 2014-06-03 11:47:58 -0700 |
commit | 1104ae8cfc0e5144e7d796cf29ee124d05401cbf (patch) | |
tree | df0388ab009f75821efe35e707805308ec78be7d /libcutils/ashmem-host.c | |
parent | 252b0e2b46e3d5e71a8b5c55928dc9ca62811f0a (diff) | |
download | system_core-1104ae8cfc0e5144e7d796cf29ee124d05401cbf.tar.gz system_core-1104ae8cfc0e5144e7d796cf29ee124d05401cbf.tar.bz2 system_core-1104ae8cfc0e5144e7d796cf29ee124d05401cbf.zip |
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
Diffstat (limited to 'libcutils/ashmem-host.c')
-rw-r--r-- | libcutils/ashmem-host.c | 124 |
1 files changed, 63 insertions, 61 deletions
diff --git a/libcutils/ashmem-host.c b/libcutils/ashmem-host.c index 787396435..4ac4f5782 100644 --- a/libcutils/ashmem-host.c +++ b/libcutils/ashmem-host.c @@ -22,6 +22,8 @@ #include <errno.h> #include <fcntl.h> #include <limits.h> +#include <pthread.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -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)? } |