diff --git a/libc_shim/Android.mk b/libc_shim/Android.mk new file mode 100644 index 0000000..1558b6b --- /dev/null +++ b/libc_shim/Android.mk @@ -0,0 +1,31 @@ +# +# Copyright (C) 2017 The LineageOS Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + bionic/bionic_time_conversions.cpp \ + bionic/pthread_cond.cpp + +LOCAL_SHARED_LIBRARIES := libc + +LOCAL_MODULE := libc_shim +LOCAL_MODULE_TAGS := optional + +LOCAL_32_BIT_ONLY := true + +include $(BUILD_SHARED_LIBRARY) diff --git a/libc_shim/bionic/bionic_time_conversions.cpp b/libc_shim/bionic/bionic_time_conversions.cpp new file mode 100644 index 0000000..0fbf15c --- /dev/null +++ b/libc_shim/bionic/bionic_time_conversions.cpp @@ -0,0 +1,17 @@ +#include "private/bionic_time_conversions.h" + +#define NS_PER_S 1000000000 + +bool timespec_from_absolute_timespec(timespec& ts, const timespec& abs_ts, clockid_t clock) { + clock_gettime(clock, &ts); + ts.tv_sec = abs_ts.tv_sec - ts.tv_sec; + ts.tv_nsec = abs_ts.tv_nsec - ts.tv_nsec; + if (ts.tv_nsec < 0) { + ts.tv_sec--; + ts.tv_nsec += NS_PER_S; + } + if (ts.tv_nsec < 0 || ts.tv_sec < 0) { + return false; + } + return true; +} diff --git a/libc_shim/bionic/pthread_cond.cpp b/libc_shim/bionic/pthread_cond.cpp new file mode 100644 index 0000000..0bde504 --- /dev/null +++ b/libc_shim/bionic/pthread_cond.cpp @@ -0,0 +1,79 @@ +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "private/bionic_futex.h" +#include "private/bionic_time_conversions.h" + +#define COND_SHARED_MASK 0x0001 +#define COND_CLOCK_MASK 0x0002 + +#define COND_IS_SHARED(c) (((c) & COND_SHARED_MASK) != 0) +#define COND_GET_CLOCK(c) (((c) & COND_CLOCK_MASK) >> 1) + +struct pthread_cond_internal_t { + atomic_uint state; + + bool process_shared() { + return COND_IS_SHARED(atomic_load_explicit(&state, memory_order_relaxed)); + } + + int get_clock() { + return COND_GET_CLOCK(atomic_load_explicit(&state, memory_order_relaxed)); + } + +#if defined(__LP64__) + char __reserved[44]; +#endif +}; + +static pthread_cond_internal_t* __get_internal_cond(pthread_cond_t* cond_interface) { + return reinterpret_cast(cond_interface); +} + +static int __pthread_cond_timedwait_relative(pthread_cond_internal_t* cond, pthread_mutex_t* mutex, + const timespec* rel_timeout_or_null) { + unsigned int old_state = atomic_load_explicit(&cond->state, memory_order_relaxed); + + pthread_mutex_unlock(mutex); + int status = __futex_wait_ex(&cond->state, cond->process_shared(), old_state, rel_timeout_or_null); + pthread_mutex_lock(mutex); + + if (status == -ETIMEDOUT) { + return ETIMEDOUT; + } + return 0; +} + +static int __pthread_cond_timedwait(pthread_cond_internal_t* cond, pthread_mutex_t* mutex, + const timespec* abs_timeout_or_null, clockid_t clock) { + timespec ts; + timespec* rel_timeout = NULL; + + if (abs_timeout_or_null != NULL) { + rel_timeout = &ts; + if (!timespec_from_absolute_timespec(*rel_timeout, *abs_timeout_or_null, clock)) { + return ETIMEDOUT; + } + } + + return __pthread_cond_timedwait_relative(cond, mutex, rel_timeout); +} + +int pthread_cond_timedwait(pthread_cond_t *cond_interface, pthread_mutex_t * mutex, + const timespec *abstime) { + + pthread_cond_internal_t* cond = __get_internal_cond(cond_interface); + return __pthread_cond_timedwait(cond, mutex, abstime, cond->get_clock()); +} + +int pthread_cond_wait(pthread_cond_t* cond_interface, pthread_mutex_t* mutex) { + pthread_cond_internal_t* cond = __get_internal_cond(cond_interface); + return __pthread_cond_timedwait(cond, mutex, NULL, cond->get_clock()); +} diff --git a/libc_shim/private/bionic_futex.h b/libc_shim/private/bionic_futex.h new file mode 100644 index 0000000..0a8f4b0 --- /dev/null +++ b/libc_shim/private/bionic_futex.h @@ -0,0 +1,14 @@ +static inline __always_inline int __futex(volatile void* ftx, int op, int value, const struct timespec* timeout) { + // Our generated syscall assembler sets errno, but our callers (pthread functions) don't want to. + int saved_errno = errno; + int result = syscall(__NR_futex, ftx, op, value, timeout); + if (__predict_false(result == -1)) { + result = -errno; + errno = saved_errno; + } + return result; +} + +static inline int __futex_wait_ex(volatile void* ftx, bool shared, int value, const struct timespec* timeout) { + return __futex(ftx, shared ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE, value, timeout); +} diff --git a/libc_shim/private/bionic_time_conversions.h b/libc_shim/private/bionic_time_conversions.h new file mode 100644 index 0000000..3010e87 --- /dev/null +++ b/libc_shim/private/bionic_time_conversions.h @@ -0,0 +1,3 @@ +#include + +bool timespec_from_absolute_timespec(timespec& ts, const timespec& abs_ts, clockid_t clock); diff --git a/msm8976.mk b/msm8976.mk index d448df1..66e9260 100644 --- a/msm8976.mk +++ b/msm8976.mk @@ -105,8 +105,8 @@ PRODUCT_PACKAGES += \ Gello # Camera -PRODUCT_COPY_FILES += \ - $(LOCAL_PATH)/prebuilt/libc_shim.so:system/lib/libc_shim.so +PRODUCT_PACKAGES += \ + libc_shim # Display PRODUCT_PACKAGES += \ diff --git a/prebuilt/libc_shim.so b/prebuilt/libc_shim.so deleted file mode 100644 index a48a4a4..0000000 Binary files a/prebuilt/libc_shim.so and /dev/null differ