[Android] [PATCH] Add pthread_once function from AOSP
Edward Wang
edward.c.wang at compdigitec.com
Thu Jun 28 12:37:53 CEST 2012
On 12-06-28 04:55 AM, Rafaël Carré <funman at videolan.org> wrote:
> Le 28/06/2012 00:09, Edward Wang a écrit :
>> See:
>> http://www.compdigitec.com/labs/2012/06/25/fclose-freezes-when-run-inside-pthread-on-android-2-1/
>> http://code.google.com/p/android/issues/detail?id=5116
>>
>> Summary:
>> Android 2.1/2.2's pthread implementation has a bug where fclose() hangs inside pthread. This commit imports a working version of pthread_once that makes VLC for Android work on Android 2.1 and 2.2.
>> ---
>> Updated version, please discard previous version.
>>
>> vlc-android/jni/Android.mk | 3 +-
>> vlc-android/jni/pthread-once.c | 91 ++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 93 insertions(+), 1 deletions(-)
>> create mode 100644 vlc-android/jni/pthread-once.c
>>
>> diff --git a/vlc-android/jni/Android.mk b/vlc-android/jni/Android.mk
>> index 7c05cb5..b2647d4 100644
>> --- a/vlc-android/jni/Android.mk
>> +++ b/vlc-android/jni/Android.mk
>> @@ -3,7 +3,7 @@ include $(CLEAR_VARS)
>>
>> LOCAL_MODULE := libvlcjni
>>
>> -LOCAL_SRC_FILES := libvlcjni.c aout.c thumbnailer.c pthread-condattr.c pthread-rwlocks.c eventfd.c sem.c
>> +LOCAL_SRC_FILES := libvlcjni.c aout.c thumbnailer.c pthread-condattr.c pthread-rwlocks.c pthread-once.c eventfd.c sem.c
>>
>> LOCAL_C_INCLUDES := $(VLC_SRC_DIR)/include
>>
>> @@ -11,6 +11,7 @@ ARCH=$(ANDROID_ABI)
>>
>> CPP_STATIC=$(ANDROID_NDK)/sources/cxx-stl/gnu-libstdc++/libs/$(ARCH)/libgnustl_static.a
>>
>> +LOCAL_ARM_MODE := arm
> not related?
It is related, please see below:
>> LOCAL_CFLAGS := -std=gnu99
>> ifeq ($(ARCH), "armeabi")
>> LOCAL_CFLAGS += -DHAVE_ARMEABI
>> diff --git a/vlc-android/jni/pthread-once.c b/vlc-android/jni/pthread-once.c
>> new file mode 100644
>> index 0000000..0fae403
>> --- /dev/null
>> +++ b/vlc-android/jni/pthread-once.c
>> @@ -0,0 +1,91 @@
>> +/*
>> + * Copyright (C) 2008 The Android Open Source Project
>> + * All rights reserved.
>> + *
>> + * Redistribution and use in source and binary forms, with or without
>> + * modification, are permitted provided that the following conditions
>> + * are met:
>> + * * Redistributions of source code must retain the above copyright
>> + * notice, this list of conditions and the following disclaimer.
>> + * * Redistributions in binary form must reproduce the above copyright
>> + * notice, this list of conditions and the following disclaimer in
>> + * the documentation and/or other materials provided with the
>> + * distribution.
>> + *
>> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
>> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
>> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
>> + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
>> + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
>> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
>> + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
>> + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
>> + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
>> + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
>> + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
>> + * SUCH DAMAGE.
>> + */
>> +#include<errno.h>
>> +#include<pthread.h>
>> +#include<unistd.h>
>> +
>> +#include<machine/cpu-features.h>
>> +
>> +/* Adapted from bionic_atomic_inline.h */
>> +void ANDROID_MEMBAR_FULL() {
>> + if(sysconf(_SC_NPROCESSORS_CONF)> 1) { /* SMP */
> no need to detect SMP at runtime, just use the same code everywhere and
> asm ("" : : : "memory") as fallback
OK
>
>> +#ifdef __arm__
>> + #if __ARM_ARCH__>= 7
>> + do { __asm__ __volatile__ ("dmb" ::: "memory"); } while (0);
>> + #elif __ARM_ARCH__ == 6
>> + /*
>> + * For ARMv6 we need to issue a specific MCR instead of the DMB, since
>> + * that wasn't added until v7.
>> + */
>> + do { __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" :: "r" (0) : "memory"); } while (0);
> Is the system control coprocessor present on all ARMv6 ?
It is present in ARMv6 base in _ARM_ mode, that's why I had
LOCAL_MODE_ARM set above to ensure it runs on all ARMv6 devices.
>> + #elif __ARM_ARCH__< 6
>> + /*
>> + * For anything older, SMP isn't relevant.
>> + */
>> + #endif
>> +#elif defined(__i386__) || defined(__x86_64__)
>> + /*
>> + * For recent x86, we can use the SSE2 mfence instruction.
>> + */
>> + do { __asm__ __volatile__ ("mfence" ::: "memory"); } while (0);
> This should use __SSE2__ define
OK
>
>> +#else
>> + /*
>> + * Implementation not defined for this platform. Hopefully we're building
>> + * in uniprocessor mode.
>> + *
>> + * For example: MIPS, PowerPC, etc
>> + */
>> +#endif
>> + } else {
>> + do { __asm__ __volatile__ ("" ::: "memory"); } while (0);
>> + }
>> +}
>> +
>> +/* NOTE: this implementation doesn't support a init function that throws a C++ exception
>> + * or calls fork()
>> + */
>> +int pthread_once( pthread_once_t* once_control, void (*init_routine)(void) )
>> +{
>> + if( once_control == NULL || init_routine == NULL )
>> + return EINVAL;
>> + static pthread_mutex_t once_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
>> + volatile pthread_once_t* ocptr = once_control;
>> +
>> + pthread_once_t tmp = *ocptr;
>> + ANDROID_MEMBAR_FULL();
>> + if (tmp == PTHREAD_ONCE_INIT) {
>> + pthread_mutex_lock(&once_lock );
>> + if (*ocptr == PTHREAD_ONCE_INIT) {
>> + (*init_routine)();
>> + ANDROID_MEMBAR_FULL();
>> + *ocptr = ~PTHREAD_ONCE_INIT;
>> + }
>> + pthread_mutex_unlock(&once_lock );
>> + }
>> + return 0;
>> +}
>>
>>
Regards,
Edward Wang
More information about the Android
mailing list