12bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian/*
22bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * Copyright (C) 2007 The Android Open Source Project
32bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian *
42bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * Licensed under the Apache License, Version 2.0 (the "License");
52bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * you may not use this file except in compliance with the License.
62bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * You may obtain a copy of the License at
72bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian *
82bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian *      http://www.apache.org/licenses/LICENSE-2.0
92bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian *
102bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * Unless required by applicable law or agreed to in writing, software
112bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * distributed under the License is distributed on an "AS IS" BASIS,
122bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * See the License for the specific language governing permissions and
142bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * limitations under the License.
152bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian */
162bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
172bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#ifndef _LIBS_UTILS_MUTEX_H
182bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#define _LIBS_UTILS_MUTEX_H
192bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
202bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#include <stdint.h>
212bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#include <sys/types.h>
222bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#include <time.h>
232bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
244a6e5a3b641dd99b658c4c336490371a3a5ae180Yabin Cui#if !defined(_WIN32)
252bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian# include <pthread.h>
262bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#endif
272bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
282bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#include <utils/Errors.h>
29601424a84fdf626c32de8baa045e58b40c856f83Jesse Hall#include <utils/Timers.h>
302bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
312bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian// ---------------------------------------------------------------------------
322bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopiannamespace android {
332bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian// ---------------------------------------------------------------------------
342bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
352bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianclass Condition;
362bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
372bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian/*
38d62698d4a3399ccdf27150a1701c6b1e3ba66ee7Greg Kaiser * NOTE: This class is for code that builds on Win32.  Its usage is
39d62698d4a3399ccdf27150a1701c6b1e3ba66ee7Greg Kaiser * deprecated for code which doesn't build for Win32.  New code which
40d62698d4a3399ccdf27150a1701c6b1e3ba66ee7Greg Kaiser * doesn't build for Win32 should use std::mutex and std::lock_guard instead.
41d62698d4a3399ccdf27150a1701c6b1e3ba66ee7Greg Kaiser *
422bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * Simple mutex class.  The implementation is system-dependent.
432bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian *
442bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * The mutex must be unlocked by the thread that locked it.  They are not
452bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * recursive, i.e. the same thread can't lock it multiple times.
462bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian */
472bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianclass Mutex {
482bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianpublic:
492bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    enum {
502bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        PRIVATE = 0,
512bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        SHARED = 1
522bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    };
53601424a84fdf626c32de8baa045e58b40c856f83Jesse Hall
542bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian                Mutex();
552a929968e1038d1940bab08a678263db3c2655eaChih-Hung Hsieh    explicit    Mutex(const char* name);
562a929968e1038d1940bab08a678263db3c2655eaChih-Hung Hsieh    explicit    Mutex(int type, const char* name = NULL);
572bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian                ~Mutex();
582bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
592bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    // lock or unlock the mutex
602bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    status_t    lock();
612bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    void        unlock();
622bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
632bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    // lock if possible; returns 0 on success, error otherwise
642bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    status_t    tryLock();
652bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
669b828adfad09200f3f1bd3602187fe3dd5335774Elliott Hughes#if defined(__ANDROID__)
67604ba48220357b9e3f3607c0e19f5790f5074e2bAndy Hung    // Lock the mutex, but don't wait longer than timeoutNs (relative time).
68601424a84fdf626c32de8baa045e58b40c856f83Jesse Hall    // Returns 0 on success, TIMED_OUT for failure due to timeout expiration.
69601424a84fdf626c32de8baa045e58b40c856f83Jesse Hall    //
70601424a84fdf626c32de8baa045e58b40c856f83Jesse Hall    // OSX doesn't have pthread_mutex_timedlock() or equivalent. To keep
71601424a84fdf626c32de8baa045e58b40c856f83Jesse Hall    // capabilities consistent across host OSes, this method is only available
72601424a84fdf626c32de8baa045e58b40c856f83Jesse Hall    // when building Android binaries.
73604ba48220357b9e3f3607c0e19f5790f5074e2bAndy Hung    //
74604ba48220357b9e3f3607c0e19f5790f5074e2bAndy Hung    // FIXME?: pthread_mutex_timedlock is based on CLOCK_REALTIME,
75604ba48220357b9e3f3607c0e19f5790f5074e2bAndy Hung    // which is subject to NTP adjustments, and includes time during suspend,
76604ba48220357b9e3f3607c0e19f5790f5074e2bAndy Hung    // so a timeout may occur even though no processes could run.
77604ba48220357b9e3f3607c0e19f5790f5074e2bAndy Hung    // Not holding a partial wakelock may lead to a system suspend.
78604ba48220357b9e3f3607c0e19f5790f5074e2bAndy Hung    status_t    timedLock(nsecs_t timeoutNs);
79601424a84fdf626c32de8baa045e58b40c856f83Jesse Hall#endif
80601424a84fdf626c32de8baa045e58b40c856f83Jesse Hall
812bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    // Manages the mutex automatically. It'll be locked when Autolock is
822bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    // constructed and released when Autolock goes out of scope.
832bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    class Autolock {
842bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    public:
852a929968e1038d1940bab08a678263db3c2655eaChih-Hung Hsieh        inline explicit Autolock(Mutex& mutex) : mLock(mutex)  { mLock.lock(); }
862a929968e1038d1940bab08a678263db3c2655eaChih-Hung Hsieh        inline explicit Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
872bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        inline ~Autolock() { mLock.unlock(); }
882bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    private:
892bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        Mutex& mLock;
902bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    };
912bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
922bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianprivate:
932bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    friend class Condition;
94601424a84fdf626c32de8baa045e58b40c856f83Jesse Hall
952bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    // A mutex cannot be copied
962bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian                Mutex(const Mutex&);
972bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    Mutex&      operator = (const Mutex&);
98601424a84fdf626c32de8baa045e58b40c856f83Jesse Hall
994a6e5a3b641dd99b658c4c336490371a3a5ae180Yabin Cui#if !defined(_WIN32)
1002bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    pthread_mutex_t mMutex;
1012bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#else
1022bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    void    _init();
1032bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    void*   mState;
1042bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#endif
1052bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian};
1062bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
1072bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian// ---------------------------------------------------------------------------
1082bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
1094a6e5a3b641dd99b658c4c336490371a3a5ae180Yabin Cui#if !defined(_WIN32)
1102bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
1112bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianinline Mutex::Mutex() {
1122bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    pthread_mutex_init(&mMutex, NULL);
1132bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}
114a27c1e08396aa2969511dad1f661d10c2b835ac1Igor Murashkininline Mutex::Mutex(__attribute__((unused)) const char* name) {
1152bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    pthread_mutex_init(&mMutex, NULL);
1162bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}
117a27c1e08396aa2969511dad1f661d10c2b835ac1Igor Murashkininline Mutex::Mutex(int type, __attribute__((unused)) const char* name) {
1182bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    if (type == SHARED) {
1192bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        pthread_mutexattr_t attr;
1202bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        pthread_mutexattr_init(&attr);
1212bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
1222bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        pthread_mutex_init(&mMutex, &attr);
1232bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        pthread_mutexattr_destroy(&attr);
1242bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    } else {
1252bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        pthread_mutex_init(&mMutex, NULL);
1262bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    }
1272bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}
1282bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianinline Mutex::~Mutex() {
1292bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    pthread_mutex_destroy(&mMutex);
1302bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}
1312bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianinline status_t Mutex::lock() {
1322bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    return -pthread_mutex_lock(&mMutex);
1332bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}
1342bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianinline void Mutex::unlock() {
1352bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    pthread_mutex_unlock(&mMutex);
1362bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}
1372bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianinline status_t Mutex::tryLock() {
1382bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    return -pthread_mutex_trylock(&mMutex);
1392bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}
1409b828adfad09200f3f1bd3602187fe3dd5335774Elliott Hughes#if defined(__ANDROID__)
141601424a84fdf626c32de8baa045e58b40c856f83Jesse Hallinline status_t Mutex::timedLock(nsecs_t timeoutNs) {
142604ba48220357b9e3f3607c0e19f5790f5074e2bAndy Hung    timeoutNs += systemTime(SYSTEM_TIME_REALTIME);
143601424a84fdf626c32de8baa045e58b40c856f83Jesse Hall    const struct timespec ts = {
144ba8cdf99a4be85eae26fb9e94c017ba85ca6c211Chih-Hung Hsieh        /* .tv_sec = */ static_cast<time_t>(timeoutNs / 1000000000),
145ba8cdf99a4be85eae26fb9e94c017ba85ca6c211Chih-Hung Hsieh        /* .tv_nsec = */ static_cast<long>(timeoutNs % 1000000000),
146601424a84fdf626c32de8baa045e58b40c856f83Jesse Hall    };
147601424a84fdf626c32de8baa045e58b40c856f83Jesse Hall    return -pthread_mutex_timedlock(&mMutex, &ts);
148601424a84fdf626c32de8baa045e58b40c856f83Jesse Hall}
149601424a84fdf626c32de8baa045e58b40c856f83Jesse Hall#endif
1502bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
1514a6e5a3b641dd99b658c4c336490371a3a5ae180Yabin Cui#endif // !defined(_WIN32)
1522bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
1532bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian// ---------------------------------------------------------------------------
1542bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
1552bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian/*
1562bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * Automatic mutex.  Declare one of these at the top of a function.
1572bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * When the function returns, it will go out of scope, and release the
1582bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * mutex.
1592bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian */
160601424a84fdf626c32de8baa045e58b40c856f83Jesse Hall
1612bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopiantypedef Mutex::Autolock AutoMutex;
1622bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
1632bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian// ---------------------------------------------------------------------------
1642bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}; // namespace android
1652bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian// ---------------------------------------------------------------------------
1662bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
1672bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#endif // _LIBS_UTILS_MUTEX_H
168