Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b8eccd86 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change 6898

* changes:
  implement Mutex and Condition with pthread instead of calling futex directly.
parents 004f16a5 ec0f1f67
Loading
Loading
Loading
Loading
+0 −60
Original line number Diff line number Diff line
/*
 * Copyright (C) 2008 The Android Open Source 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.
 */

#ifndef _FUTEX_SYNCHRO_H
#define _FUTEX_SYNCHRO_H

#ifndef HAVE_FUTEX
#error "HAVE_FUTEX not defined"
#endif

#define FUTEX_WAIT_INFINITE (0)

typedef struct futex_mutex_t futex_mutex_t;

struct futex_mutex_t 
{
    volatile int value;
};

typedef struct futex_cond_t futex_cond_t;

struct futex_cond_t 
{
    volatile int value;
};


#if __cplusplus
extern "C" {
#endif

void futex_mutex_init(futex_mutex_t *m);
int futex_mutex_lock(futex_mutex_t *m, unsigned msec);
void futex_mutex_unlock(futex_mutex_t *m);
int futex_mutex_trylock(futex_mutex_t *m);

void futex_cond_init(futex_cond_t *c);
int futex_cond_wait(futex_cond_t *c, futex_mutex_t *m, unsigned msec);
void futex_cond_signal(futex_cond_t *c);
void futex_cond_broadcast(futex_cond_t *c);

#if __cplusplus
} // extern "C"
#endif

#endif // _FUTEX_SYNCHRO_H
+86 −4
Original line number Diff line number Diff line
@@ -21,6 +21,10 @@
#include <sys/types.h>
#include <time.h>

#if defined(HAVE_PTHREADS)
# include <pthread.h>
#endif

// ------------------------------------------------------------------
// C API

@@ -176,6 +180,8 @@ inline thread_id_t getThreadId() {
    return androidGetThreadId();
}

/*****************************************************************************/

/*
 * Simple mutex class.  The implementation is system-dependent.
 *
@@ -212,11 +218,38 @@ private:
    // A mutex cannot be copied
                Mutex(const Mutex&);
    Mutex&      operator = (const Mutex&);
    void        _init();
    
#if defined(HAVE_PTHREADS)
    pthread_mutex_t mMutex;
#else
    void    _init();
    void*   mState;
#endif
};

#if defined(HAVE_PTHREADS)

inline Mutex::Mutex() {
    pthread_mutex_init(&mMutex, NULL);
}
inline Mutex::Mutex(const char* name) {
    pthread_mutex_init(&mMutex, NULL);
}
inline Mutex::~Mutex() {
    pthread_mutex_destroy(&mMutex);
}
inline status_t Mutex::lock() {
    return -pthread_mutex_lock(&mMutex);
}
inline void Mutex::unlock() {
    pthread_mutex_unlock(&mMutex);
}
inline status_t Mutex::tryLock() {
    return -pthread_mutex_trylock(&mMutex);
}

#endif // HAVE_PTHREADS

/*
 * Automatic mutex.  Declare one of these at the top of a function.
 * When the function returns, it will go out of scope, and release the
@@ -225,6 +258,7 @@ private:
 
typedef Mutex::Autolock AutoMutex;

/*****************************************************************************/

/*
 * Condition variable class.  The implementation is system-dependent.
@@ -240,9 +274,6 @@ public:
    ~Condition();
    // Wait on the condition variable.  Lock the mutex before calling.
    status_t wait(Mutex& mutex);
    // Wait on the condition variable until the given time.  Lock the mutex
    // before calling.
    status_t wait(Mutex& mutex, nsecs_t abstime);
    // same with relative timeout
    status_t waitRelative(Mutex& mutex, nsecs_t reltime);
    // Signal the condition variable, allowing one thread to continue.
@@ -251,9 +282,60 @@ public:
    void broadcast();

private:
#if defined(HAVE_PTHREADS)
    pthread_cond_t mCond;
#else
    void*   mState;
#endif
};

#if defined(HAVE_PTHREADS)

inline Condition::Condition() {
    pthread_cond_init(&mCond, NULL);
}
inline Condition::~Condition() {
    pthread_cond_destroy(&mCond);
}
inline status_t Condition::wait(Mutex& mutex) {
    return -pthread_cond_wait(&mCond, &mutex.mMutex);
}
inline status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) {
#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
    struct timespec ts;
    ts.tv_sec  = reltime/1000000000;
    ts.tv_nsec = reltime%1000000000;
    return -pthread_cond_timedwait_relative_np(&mCond, &mutex.mMutex, &ts);
#else // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
    struct timespec ts;
#if defined(HAVE_POSIX_CLOCKS)
    clock_gettime(CLOCK_REALTIME, &ts);
#else // HAVE_POSIX_CLOCKS
    // we don't support the clocks here.
    struct timeval t;
    gettimeofday(&t, NULL);
    ts.tv_sec = t.tv_sec;
    ts.tv_nsec= t.tv_usec*1000;
#endif // HAVE_POSIX_CLOCKS
    ts.tv_sec += reltime/1000000000;
    ts.tv_nsec+= reltime%1000000000;
    if (ts.tv_nsec >= 1000000000) {
        ts.tv_nsec -= 1000000000;
        ts.tv_sec  += 1;
    }
    return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
#endif // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
}
inline void Condition::signal() {
    pthread_cond_signal(&mCond);
}
inline void Condition::broadcast() {
    pthread_cond_broadcast(&mCond);
}

#endif // HAVE_PTHREADS

/*****************************************************************************/

/*
 * This is our spiffy thread object!
+4 −1
Original line number Diff line number Diff line
@@ -111,7 +111,10 @@ MessageList::value_type MessageQueue::waitMessage(nsecs_t timeout)
                if (nextEventTime > 0) {
                    // we're about to wait, flush the binder command buffer
                    IPCThreadState::self()->flushCommands();
                    mCondition.wait(mLock, nextEventTime);
                    const nsecs_t reltime = nextEventTime - systemTime();
                    if (reltime > 0) {
                        mCondition.waitRelative(mLock, reltime);
                    }
                }
            } else {
                //LOGD("going to wait");
+2 −12
Original line number Diff line number Diff line
@@ -51,13 +51,6 @@ include $(CLEAR_VARS)

LOCAL_SRC_FILES:= $(commonSources)

ifeq ($(HOST_OS),linux)
# Use the futex based mutex and condition variable
# implementation from android-arm because it's shared mem safe
	LOCAL_SRC_FILES += \
		futex_synchro.c
endif

LOCAL_MODULE:= libutils

LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS)
@@ -87,15 +80,13 @@ LOCAL_SRC_FILES:= \
	BackupHelpers.cpp

ifeq ($(TARGET_OS),linux)
# Use the futex based mutex and condition variable
# implementation from android-arm because it's shared mem safe
LOCAL_SRC_FILES += futex_synchro.c
LOCAL_LDLIBS += -lrt -ldl
endif

LOCAL_C_INCLUDES += \
		external/zlib \
		external/icu4c/common

LOCAL_LDLIBS += -lpthread

LOCAL_SHARED_LIBRARIES := \
@@ -106,8 +97,7 @@ LOCAL_SHARED_LIBRARIES := \
ifneq ($(TARGET_SIMULATOR),true)
ifeq ($(TARGET_OS)-$(TARGET_ARCH),linux-x86)
# This is needed on x86 to bring in dl_iterate_phdr for CallStack.cpp
LOCAL_SHARED_LIBRARIES += \
	libdl
LOCAL_SHARED_LIBRARIES += libdl
endif # linux-x86
endif # sim

+4 −286
Original line number Diff line number Diff line
@@ -38,10 +38,6 @@
# define HAVE_CREATETHREAD  // Cygwin, vs. HAVE__BEGINTHREADEX for MinGW
#endif

#if defined(HAVE_FUTEX)
#include <private/utils/futex_synchro.h>
#endif

#if defined(HAVE_PRCTL)
#include <sys/prctl.h>
#endif
@@ -56,10 +52,6 @@ using namespace android;

// ----------------------------------------------------------------------------
#if defined(HAVE_PTHREADS)
#if 0
#pragma mark -
#pragma mark PTHREAD
#endif
// ----------------------------------------------------------------------------

/*
@@ -163,10 +155,6 @@ android_thread_id_t androidGetThreadId()

// ----------------------------------------------------------------------------
#elif defined(HAVE_WIN32_THREADS)
#if 0
#pragma mark -
#pragma mark WIN32_THREADS
#endif
// ----------------------------------------------------------------------------

/*
@@ -252,11 +240,6 @@ android_thread_id_t androidGetThreadId()

// ----------------------------------------------------------------------------

#if 0
#pragma mark -
#pragma mark Common Thread functions
#endif

int androidCreateThread(android_thread_func_t fn, void* arg)
{
    return createThreadEtc(fn, arg);
@@ -294,109 +277,9 @@ namespace android {
 * ===========================================================================
 */

#if 0
#pragma mark -
#pragma mark Mutex
#endif

#if defined(HAVE_PTHREADS) && !defined(HAVE_FUTEX)
/*
 * Simple pthread wrapper.
 */

Mutex::Mutex()
{
    _init();
}

Mutex::Mutex(const char* name)
{
    // XXX: name not used for now
    _init();
}

void Mutex::_init()
{
    pthread_mutex_t* pMutex = new pthread_mutex_t;
    pthread_mutex_init(pMutex, NULL);
    mState = pMutex;
}

Mutex::~Mutex()
{
    delete (pthread_mutex_t*) mState;
}

status_t Mutex::lock()
{
    int res;
    while ((res=pthread_mutex_lock((pthread_mutex_t*) mState)) == EINTR) ;
    return -res;
}

void Mutex::unlock()
{
    pthread_mutex_unlock((pthread_mutex_t*) mState);
}

status_t Mutex::tryLock()
{
    int res;
    while ((res=pthread_mutex_trylock((pthread_mutex_t*) mState)) == EINTR) ;
    return -res;
}

#elif defined(HAVE_FUTEX)
#if 0
#pragma mark -
#endif

#define STATE ((futex_mutex_t*) (&mState))

Mutex::Mutex()
{
    _init();
}

Mutex::Mutex(const char* name)
{
    _init();
}

void
Mutex::_init()
{
    futex_mutex_init(STATE);
}

Mutex::~Mutex()
{
}

status_t Mutex::lock()
{
    int res;
    while ((res=futex_mutex_lock(STATE, FUTEX_WAIT_INFINITE)) == EINTR) ;
    return -res;
}

void Mutex::unlock()
{
    futex_mutex_unlock(STATE);
}

status_t Mutex::tryLock()
{
    int res;
    while ((res=futex_mutex_trylock(STATE)) == EINTR) ;
    return -res;
}
#undef STATE

#if defined(HAVE_PTHREADS)
// implemented as inlines in threads.h
#elif defined(HAVE_WIN32_THREADS)
#if 0
#pragma mark -
#endif

Mutex::Mutex()
{
@@ -456,161 +339,9 @@ status_t Mutex::tryLock()
 * ===========================================================================
 */

#if 0
#pragma mark -
#pragma mark Condition
#endif

#if defined(HAVE_PTHREADS) && !defined(HAVE_FUTEX)

/*
 * Constructor.  This is a simple pthread wrapper.
 */
Condition::Condition()
{
    pthread_cond_t* pCond = new pthread_cond_t;

    pthread_cond_init(pCond, NULL);
    mState = pCond;
}

/*
 * Destructor.
 */
Condition::~Condition()
{
    pthread_cond_destroy((pthread_cond_t*) mState);
    delete (pthread_cond_t*) mState;
}

/*
 * Wait on a condition variable.  Lock the mutex before calling.
 */

status_t Condition::wait(Mutex& mutex)
{
    assert(mutex.mState != NULL);

    int cc;
    while ((cc = pthread_cond_wait((pthread_cond_t*)mState,
                (pthread_mutex_t*) mutex.mState)) == EINTR) ;
    return -cc;
}

status_t Condition::wait(Mutex& mutex, nsecs_t abstime)
{
    assert(mutex.mState != NULL);

    struct timespec ts;
    ts.tv_sec = abstime/1000000000;
    ts.tv_nsec = abstime-(ts.tv_sec*1000000000);
    
    int cc;
    while ((cc = pthread_cond_timedwait((pthread_cond_t*)mState,
            (pthread_mutex_t*) mutex.mState, &ts)) == EINTR) ;
    return -cc;
}

status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime)
{
    return wait(mutex, systemTime()+reltime);
}

/*
 * Signal the condition variable, allowing one thread to continue.
 */
void Condition::signal()
{
    pthread_cond_signal((pthread_cond_t*) mState);
}

/*
 * Signal the condition variable, allowing all threads to continue.
 */
void Condition::broadcast()
{
    pthread_cond_broadcast((pthread_cond_t*) mState);
}

#elif defined(HAVE_FUTEX)
#if 0
#pragma mark -
#endif

#define STATE ((futex_cond_t*) (&mState))

/*
 * Constructor.  This is a simple pthread wrapper.
 */
Condition::Condition()
{
    futex_cond_init(STATE);
}

/*
 * Destructor.
 */
Condition::~Condition()
{
}

/*
 * Wait on a condition variable.  Lock the mutex before calling.
 */

status_t Condition::wait(Mutex& mutex)
{
    assert(mutex.mState != NULL);

    int res;
    while ((res = futex_cond_wait(STATE,
        (futex_mutex_t*)(&mutex.mState), FUTEX_WAIT_INFINITE)) == -EINTR) ;

    return -res;
}

status_t Condition::wait(Mutex& mutex, nsecs_t abstime)
{
    nsecs_t reltime = abstime - systemTime();
    if (reltime <= 0) return true;
    return waitRelative(mutex, reltime);
}

status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime)
{
    assert(mutex.mState != NULL);
    int res;
    unsigned msec = ns2ms(reltime);
    if(msec == 0)
        return true;
    // This code will not time out at the correct time if interrupted by signals
    while ((res = futex_cond_wait(STATE,
        (futex_mutex_t*)(&mutex.mState), msec)) == -EINTR) ;
    return res;
}

/*
 * Signal the condition variable, allowing one thread to continue.
 */
void Condition::signal()
{
    futex_cond_signal(STATE);
}

/*
 * Signal the condition variable, allowing all threads to continue.
 */
void Condition::broadcast()
{
    futex_cond_broadcast(STATE);
}

#undef STATE

#if defined(HAVE_PTHREADS)
// implemented as inlines in threads.h
#elif defined(HAVE_WIN32_THREADS)
#if 0
#pragma mark -
#endif

/*
 * Windows doesn't have a condition variable solution.  It's possible
@@ -753,14 +484,6 @@ status_t Condition::wait(Mutex& mutex)
    return ((WinCondition*)mState)->wait(condState, hMutex, NULL);
}

status_t Condition::wait(Mutex& mutex, nsecs_t abstime)
{
    WinCondition* condState = (WinCondition*) mState;
    HANDLE hMutex = (HANDLE) mutex.mState;

    return ((WinCondition*)mState)->wait(condState, hMutex, &abstime);
}

status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime)
{
    return wait(mutex, systemTime()+reltime);
@@ -841,11 +564,6 @@ void Condition::broadcast()

// ----------------------------------------------------------------------------

#if 0
#pragma mark -
#pragma mark Thread::Thread
#endif

/*
 * This is our thread object!
 */
Loading