summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJari Vetoniemi <mailroxas@gmail.com>2018-07-30 15:58:23 +0300
committerJari Vetoniemi <mailroxas@gmail.com>2018-07-30 15:58:23 +0300
commit055295943756cf3cc8238dba741777b1e45fe948 (patch)
treee0b125ba30694c7bfb4a8e409b35f41b37f2cd4d
parent2a39d7b28a0deda9333afa87ea8eb6e38d629427 (diff)
pthread: Implement implicit sem init
This should be undefined behaviour, but some android apps rely on default initialized semaphores. (Hearthstone)
-rw-r--r--src/libpthread.c21
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);
}