[Android] [PATCH] Add pthread_once function from AOSP
Rafaël Carré
funman at videolan.org
Thu Jun 28 10:55:19 CEST 2012
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?
> 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
> +#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 ?
> + #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
> +#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;
> +}
>
More information about the Android
mailing list