[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