1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef _LIBS_UTILS_MUTEX_H 18 #define _LIBS_UTILS_MUTEX_H 19 20 #include <stdint.h> 21 #include <sys/types.h> 22 #include <time.h> 23 24 #if !defined(_WIN32) 25 # include <pthread.h> 26 #endif 27 28 #include <utils/Errors.h> 29 #include <utils/Timers.h> 30 31 // --------------------------------------------------------------------------- 32 namespace android { 33 // --------------------------------------------------------------------------- 34 35 class Condition; 36 37 /* 38 * NOTE: This class is for code that builds on Win32. Its usage is 39 * deprecated for code which doesn't build for Win32. New code which 40 * doesn't build for Win32 should use std::mutex and std::lock_guard instead. 41 * 42 * Simple mutex class. The implementation is system-dependent. 43 * 44 * The mutex must be unlocked by the thread that locked it. They are not 45 * recursive, i.e. the same thread can't lock it multiple times. 46 */ 47 class Mutex { 48 public: 49 enum { 50 PRIVATE = 0, 51 SHARED = 1 52 }; 53 54 Mutex(); 55 Mutex(const char* name); 56 Mutex(int type, const char* name = NULL); 57 ~Mutex(); 58 59 // lock or unlock the mutex 60 status_t lock(); 61 void unlock(); 62 63 // lock if possible; returns 0 on success, error otherwise 64 status_t tryLock(); 65 66 #if defined(__ANDROID__) 67 // Lock the mutex, but don't wait longer than timeoutNs (relative time). 68 // Returns 0 on success, TIMED_OUT for failure due to timeout expiration. 69 // 70 // OSX doesn't have pthread_mutex_timedlock() or equivalent. To keep 71 // capabilities consistent across host OSes, this method is only available 72 // when building Android binaries. 73 // 74 // FIXME?: pthread_mutex_timedlock is based on CLOCK_REALTIME, 75 // which is subject to NTP adjustments, and includes time during suspend, 76 // so a timeout may occur even though no processes could run. 77 // Not holding a partial wakelock may lead to a system suspend. 78 status_t timedLock(nsecs_t timeoutNs); 79 #endif 80 81 // Manages the mutex automatically. It'll be locked when Autolock is 82 // constructed and released when Autolock goes out of scope. 83 class Autolock { 84 public: 85 inline Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); } 86 inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); } 87 inline ~Autolock() { mLock.unlock(); } 88 private: 89 Mutex& mLock; 90 }; 91 92 private: 93 friend class Condition; 94 95 // A mutex cannot be copied 96 Mutex(const Mutex&); 97 Mutex& operator = (const Mutex&); 98 99 #if !defined(_WIN32) 100 pthread_mutex_t mMutex; 101 #else 102 void _init(); 103 void* mState; 104 #endif 105 }; 106 107 // --------------------------------------------------------------------------- 108 109 #if !defined(_WIN32) 110 111 inline Mutex::Mutex() { 112 pthread_mutex_init(&mMutex, NULL); 113 } 114 inline Mutex::Mutex(__attribute__((unused)) const char* name) { 115 pthread_mutex_init(&mMutex, NULL); 116 } 117 inline Mutex::Mutex(int type, __attribute__((unused)) const char* name) { 118 if (type == SHARED) { 119 pthread_mutexattr_t attr; 120 pthread_mutexattr_init(&attr); 121 pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); 122 pthread_mutex_init(&mMutex, &attr); 123 pthread_mutexattr_destroy(&attr); 124 } else { 125 pthread_mutex_init(&mMutex, NULL); 126 } 127 } 128 inline Mutex::~Mutex() { 129 pthread_mutex_destroy(&mMutex); 130 } 131 inline status_t Mutex::lock() { 132 return -pthread_mutex_lock(&mMutex); 133 } 134 inline void Mutex::unlock() { 135 pthread_mutex_unlock(&mMutex); 136 } 137 inline status_t Mutex::tryLock() { 138 return -pthread_mutex_trylock(&mMutex); 139 } 140 #if defined(__ANDROID__) 141 inline status_t Mutex::timedLock(nsecs_t timeoutNs) { 142 timeoutNs += systemTime(SYSTEM_TIME_REALTIME); 143 const struct timespec ts = { 144 /* .tv_sec = */ static_cast<time_t>(timeoutNs / 1000000000), 145 /* .tv_nsec = */ static_cast<long>(timeoutNs % 1000000000), 146 }; 147 return -pthread_mutex_timedlock(&mMutex, &ts); 148 } 149 #endif 150 151 #endif // !defined(_WIN32) 152 153 // --------------------------------------------------------------------------- 154 155 /* 156 * Automatic mutex. Declare one of these at the top of a function. 157 * When the function returns, it will go out of scope, and release the 158 * mutex. 159 */ 160 161 typedef Mutex::Autolock AutoMutex; 162 163 // --------------------------------------------------------------------------- 164 }; // namespace android 165 // --------------------------------------------------------------------------- 166 167 #endif // _LIBS_UTILS_MUTEX_H 168