diff options
author | Jari Vetoniemi <mailroxas@gmail.com> | 2018-07-30 15:58:23 +0300 |
---|---|---|
committer | Jari Vetoniemi <mailroxas@gmail.com> | 2018-07-30 15:58:23 +0300 |
commit | 055295943756cf3cc8238dba741777b1e45fe948 (patch) | |
tree | e0b125ba30694c7bfb4a8e409b35f41b37f2cd4d /src | |
parent | 2a39d7b28a0deda9333afa87ea8eb6e38d629427 (diff) |
pthread: Implement implicit sem init
This should be undefined behaviour, but some android apps rely on
default initialized semaphores. (Hearthstone)
Diffstat (limited to 'src')
-rw-r--r-- | src/libpthread.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/src/libpthread.c b/src/libpthread.c index 515b7df..f001c47 100644 --- a/src/libpthread.c +++ b/src/libpthread.c @@ -132,6 +132,15 @@ bionic_sem_destroy(bionic_sem_t *sem) return ret; } +static void +default_sem_init(bionic_sem_t *sem) +{ + // Apparently some android apps (hearthstone) do not call sem_init() + assert(sem); + sem->glibc = mmap(NULL, sizeof(*sem->glibc), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0); + memset(sem->glibc, 0, sizeof(*sem->glibc)); +} + int bionic_sem_init(bionic_sem_t *sem, int pshared, unsigned int value) { @@ -146,28 +155,32 @@ bionic_sem_init(bionic_sem_t *sem, int pshared, unsigned int value) int bionic_sem_post(bionic_sem_t *sem) { - assert(sem && IS_MAPPED(sem)); + assert(sem); + INIT_IF_NOT_MAPPED(sem, default_sem_init); return sem_post(sem->glibc); } int bionic_sem_wait(bionic_sem_t *sem) { - assert(sem && IS_MAPPED(sem)); + assert(sem); + INIT_IF_NOT_MAPPED(sem, default_sem_init); return sem_wait(sem->glibc); } int bionic_sem_trywait(bionic_sem_t *sem) { - assert(sem && IS_MAPPED(sem)); + assert(sem); + INIT_IF_NOT_MAPPED(sem, default_sem_init); return sem_trywait(sem->glibc); } int bionic_sem_timedwait(bionic_sem_t *sem, const struct timespec *abs_timeout) { - assert(sem && IS_MAPPED(sem) && abs_timeout); + assert(sem && abs_timeout); + INIT_IF_NOT_MAPPED(sem, default_sem_init); return sem_timedwait(sem->glibc, abs_timeout); } |