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