diff options
Diffstat (limited to 'runtime/base')
-rw-r--r-- | runtime/base/mutex-inl.h | 87 | ||||
-rw-r--r-- | runtime/base/mutex.cc | 88 | ||||
-rw-r--r-- | runtime/base/mutex.h | 2 | ||||
-rw-r--r-- | runtime/base/unix_file/fd_file.cc | 16 | ||||
-rw-r--r-- | runtime/base/unix_file/mapped_file.cc | 4 | ||||
-rw-r--r-- | runtime/base/unix_file/mapped_file.h | 5 |
6 files changed, 77 insertions, 125 deletions
diff --git a/runtime/base/mutex-inl.h b/runtime/base/mutex-inl.h index d20eb17a3c..1890181342 100644 --- a/runtime/base/mutex-inl.h +++ b/runtime/base/mutex-inl.h @@ -45,54 +45,6 @@ static inline int futex(volatile int *uaddr, int op, int val, const struct times } #endif // ART_USE_FUTEXES -#if defined(__APPLE__) - -// This works on Mac OS 10.6 but hasn't been tested on older releases. -struct __attribute__((__may_alias__)) darwin_pthread_mutex_t { - long padding0; // NOLINT(runtime/int) exact match to darwin type - int padding1; - uint32_t padding2; - int16_t padding3; - int16_t padding4; - uint32_t padding5; - pthread_t darwin_pthread_mutex_owner; - // ...other stuff we don't care about. -}; - -struct __attribute__((__may_alias__)) darwin_pthread_rwlock_t { - long padding0; // NOLINT(runtime/int) exact match to darwin type - pthread_mutex_t padding1; - int padding2; - pthread_cond_t padding3; - pthread_cond_t padding4; - int padding5; - int padding6; - pthread_t darwin_pthread_rwlock_owner; - // ...other stuff we don't care about. -}; - -#endif // __APPLE__ - -#if defined(__GLIBC__) - -struct __attribute__((__may_alias__)) glibc_pthread_mutex_t { - int32_t padding0[2]; - int owner; - // ...other stuff we don't care about. -}; - -struct __attribute__((__may_alias__)) glibc_pthread_rwlock_t { -#ifdef __LP64__ - int32_t padding0[6]; -#else - int32_t padding0[7]; -#endif - int writer; - // ...other stuff we don't care about. -}; - -#endif // __GLIBC__ - class ScopedContentionRecorder { public: ScopedContentionRecorder(BaseMutex* mutex, uint64_t blocked_tid, uint64_t owner_tid) @@ -219,12 +171,14 @@ inline void ReaderWriterMutex::SharedLock(Thread* self) { #else CHECK_MUTEX_CALL(pthread_rwlock_rdlock, (&rwlock_)); #endif + DCHECK(exclusive_owner_ == 0U || exclusive_owner_ == -1U); RegisterAsLocked(self); AssertSharedHeld(self); } inline void ReaderWriterMutex::SharedUnlock(Thread* self) { DCHECK(self == NULL || self == Thread::Current()); + DCHECK(exclusive_owner_ == 0U || exclusive_owner_ == -1U); AssertSharedHeld(self); RegisterAsUnlocked(self); #if ART_USE_FUTEXES @@ -262,26 +216,7 @@ inline bool Mutex::IsExclusiveHeld(const Thread* self) const { } inline uint64_t Mutex::GetExclusiveOwnerTid() const { -#if ART_USE_FUTEXES return exclusive_owner_; -#elif defined(__BIONIC__) - return static_cast<uint64_t>((mutex_.value >> 16) & 0xffff); -#elif defined(__GLIBC__) - return reinterpret_cast<const glibc_pthread_mutex_t*>(&mutex_)->owner; -#elif defined(__APPLE__) - const darwin_pthread_mutex_t* dpmutex = reinterpret_cast<const darwin_pthread_mutex_t*>(&mutex_); - pthread_t owner = dpmutex->darwin_pthread_mutex_owner; - // 0 for unowned, -1 for PTHREAD_MTX_TID_SWITCHING - // TODO: should we make darwin_pthread_mutex_owner volatile and recheck until not -1? - if ((owner == (pthread_t)0) || (owner == (pthread_t)-1)) { - return 0; - } - uint64_t tid; - CHECK_PTHREAD_CALL(pthread_threadid_np, (owner, &tid), __FUNCTION__); // Requires Mac OS 10.6 - return tid; -#else -#error unsupported C library -#endif } inline bool ReaderWriterMutex::IsExclusiveHeld(const Thread* self) const { @@ -307,23 +242,7 @@ inline uint64_t ReaderWriterMutex::GetExclusiveOwnerTid() const { return exclusive_owner_; } #else -#if defined(__BIONIC__) - return rwlock_.writerThreadId; -#elif defined(__GLIBC__) - return reinterpret_cast<const glibc_pthread_rwlock_t*>(&rwlock_)->writer; -#elif defined(__APPLE__) - const darwin_pthread_rwlock_t* - dprwlock = reinterpret_cast<const darwin_pthread_rwlock_t*>(&rwlock_); - pthread_t owner = dprwlock->darwin_pthread_rwlock_owner; - if (owner == (pthread_t)0) { - return 0; - } - uint64_t tid; - CHECK_PTHREAD_CALL(pthread_threadid_np, (owner, &tid), __FUNCTION__); // Requires Mac OS 10.6 - return tid; -#else -#error unsupported C library -#endif + return exclusive_owner_; #endif } diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc index aeece74687..fd1eb12420 100644 --- a/runtime/base/mutex.cc +++ b/runtime/base/mutex.cc @@ -263,19 +263,11 @@ Mutex::Mutex(const char* name, LockLevel level, bool recursive) : BaseMutex(name, level), recursive_(recursive), recursion_count_(0) { #if ART_USE_FUTEXES state_ = 0; - exclusive_owner_ = 0; DCHECK_EQ(0, num_contenders_.LoadRelaxed()); -#elif defined(__BIONIC__) || defined(__APPLE__) - // Use recursive mutexes for bionic and Apple otherwise the - // non-recursive mutexes don't have TIDs to check lock ownership of. - pthread_mutexattr_t attributes; - CHECK_MUTEX_CALL(pthread_mutexattr_init, (&attributes)); - CHECK_MUTEX_CALL(pthread_mutexattr_settype, (&attributes, PTHREAD_MUTEX_RECURSIVE)); - CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, &attributes)); - CHECK_MUTEX_CALL(pthread_mutexattr_destroy, (&attributes)); #else - CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, NULL)); + CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, nullptr)); #endif + exclusive_owner_ = 0; } Mutex::~Mutex() { @@ -336,10 +328,11 @@ void Mutex::ExclusiveLock(Thread* self) { // TODO: Change state_ to be a art::Atomic and use an intention revealing CAS operation // that exposes the ordering semantics. DCHECK_EQ(state_, 1); - exclusive_owner_ = SafeGetTid(self); #else CHECK_MUTEX_CALL(pthread_mutex_lock, (&mutex_)); #endif + DCHECK_EQ(exclusive_owner_, 0U); + exclusive_owner_ = SafeGetTid(self); RegisterAsLocked(self); } recursion_count_++; @@ -369,7 +362,6 @@ bool Mutex::ExclusiveTryLock(Thread* self) { } while (!done); // We again assert no memory fence is needed. DCHECK_EQ(state_, 1); - exclusive_owner_ = SafeGetTid(self); #else int result = pthread_mutex_trylock(&mutex_); if (result == EBUSY) { @@ -380,6 +372,8 @@ bool Mutex::ExclusiveTryLock(Thread* self) { PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_; } #endif + DCHECK_EQ(exclusive_owner_, 0U); + exclusive_owner_ = SafeGetTid(self); RegisterAsLocked(self); } recursion_count_++; @@ -394,6 +388,7 @@ bool Mutex::ExclusiveTryLock(Thread* self) { void Mutex::ExclusiveUnlock(Thread* self) { DCHECK(self == NULL || self == Thread::Current()); AssertHeld(self); + DCHECK_NE(exclusive_owner_, 0U); recursion_count_--; if (!recursive_ || recursion_count_ == 0) { if (kDebugLocking) { @@ -402,34 +397,35 @@ void Mutex::ExclusiveUnlock(Thread* self) { } RegisterAsUnlocked(self); #if ART_USE_FUTEXES - bool done = false; - do { - int32_t cur_state = state_; - if (LIKELY(cur_state == 1)) { - // The __sync_bool_compare_and_swap enforces the necessary memory ordering. - // We're no longer the owner. - exclusive_owner_ = 0; - // Change state to 0. - done = __sync_bool_compare_and_swap(&state_, cur_state, 0 /* new state */); - if (LIKELY(done)) { // Spurious fail? - // Wake a contender - if (UNLIKELY(num_contenders_.LoadRelaxed() > 0)) { - futex(&state_, FUTEX_WAKE, 1, NULL, NULL, 0); + bool done = false; + do { + int32_t cur_state = state_; + if (LIKELY(cur_state == 1)) { + // The __sync_bool_compare_and_swap enforces the necessary memory ordering. + // We're no longer the owner. + exclusive_owner_ = 0; + // Change state to 0. + done = __sync_bool_compare_and_swap(&state_, cur_state, 0 /* new state */); + if (LIKELY(done)) { // Spurious fail? + // Wake a contender + if (UNLIKELY(num_contenders_.LoadRelaxed() > 0)) { + futex(&state_, FUTEX_WAKE, 1, NULL, NULL, 0); + } } - } - } else { - // Logging acquires the logging lock, avoid infinite recursion in that case. - if (this != Locks::logging_lock_) { - LOG(FATAL) << "Unexpected state_ in unlock " << cur_state << " for " << name_; } else { - LogMessageData data(__FILE__, __LINE__, INTERNAL_FATAL, -1); - LogMessage::LogLine(data, StringPrintf("Unexpected state_ %d in unlock for %s", - cur_state, name_).c_str()); - _exit(1); + // Logging acquires the logging lock, avoid infinite recursion in that case. + if (this != Locks::logging_lock_) { + LOG(FATAL) << "Unexpected state_ in unlock " << cur_state << " for " << name_; + } else { + LogMessageData data(__FILE__, __LINE__, INTERNAL_FATAL, -1); + LogMessage::LogLine(data, StringPrintf("Unexpected state_ %d in unlock for %s", + cur_state, name_).c_str()); + _exit(1); + } } - } - } while (!done); + } while (!done); #else + exclusive_owner_ = 0; CHECK_MUTEX_CALL(pthread_mutex_unlock, (&mutex_)); #endif } @@ -452,12 +448,13 @@ std::ostream& operator<<(std::ostream& os, const Mutex& mu) { ReaderWriterMutex::ReaderWriterMutex(const char* name, LockLevel level) : BaseMutex(name, level) #if ART_USE_FUTEXES - , state_(0), exclusive_owner_(0), num_pending_readers_(0), num_pending_writers_(0) + , state_(0), num_pending_readers_(0), num_pending_writers_(0) #endif { // NOLINT(whitespace/braces) #if !ART_USE_FUTEXES - CHECK_MUTEX_CALL(pthread_rwlock_init, (&rwlock_, NULL)); + CHECK_MUTEX_CALL(pthread_rwlock_init, (&rwlock_, nullptr)); #endif + exclusive_owner_ = 0; } ReaderWriterMutex::~ReaderWriterMutex() { @@ -506,10 +503,11 @@ void ReaderWriterMutex::ExclusiveLock(Thread* self) { } } while (!done); DCHECK_EQ(state_, -1); - exclusive_owner_ = SafeGetTid(self); #else CHECK_MUTEX_CALL(pthread_rwlock_wrlock, (&rwlock_)); #endif + DCHECK_EQ(exclusive_owner_, 0U); + exclusive_owner_ = SafeGetTid(self); RegisterAsLocked(self); AssertExclusiveHeld(self); } @@ -518,6 +516,7 @@ void ReaderWriterMutex::ExclusiveUnlock(Thread* self) { DCHECK(self == NULL || self == Thread::Current()); AssertExclusiveHeld(self); RegisterAsUnlocked(self); + DCHECK_NE(exclusive_owner_, 0U); #if ART_USE_FUTEXES bool done = false; do { @@ -538,6 +537,7 @@ void ReaderWriterMutex::ExclusiveUnlock(Thread* self) { } } while (!done); #else + exclusive_owner_ = 0; CHECK_MUTEX_CALL(pthread_rwlock_unlock, (&rwlock_)); #endif } @@ -578,7 +578,6 @@ bool ReaderWriterMutex::ExclusiveLockWithTimeout(Thread* self, int64_t ms, int32 num_pending_writers_--; } } while (!done); - exclusive_owner_ = SafeGetTid(self); #else timespec ts; InitTimeSpec(true, CLOCK_REALTIME, ms, ns, &ts); @@ -591,6 +590,7 @@ bool ReaderWriterMutex::ExclusiveLockWithTimeout(Thread* self, int64_t ms, int32 PLOG(FATAL) << "pthread_rwlock_timedwrlock failed for " << name_; } #endif + exclusive_owner_ = SafeGetTid(self); RegisterAsLocked(self); AssertSharedHeld(self); return true; @@ -656,7 +656,7 @@ ConditionVariable::ConditionVariable(const char* name, Mutex& guard) num_waiters_ = 0; #else pthread_condattr_t cond_attrs; - CHECK_MUTEX_CALL(pthread_condattr_init(&cond_attrs)); + CHECK_MUTEX_CALL(pthread_condattr_init, (&cond_attrs)); #if !defined(__APPLE__) // Apple doesn't have CLOCK_MONOTONIC or pthread_condattr_setclock. CHECK_MUTEX_CALL(pthread_condattr_setclock(&cond_attrs, CLOCK_MONOTONIC)); @@ -763,8 +763,11 @@ void ConditionVariable::WaitHoldingLocks(Thread* self) { CHECK_GE(guard_.num_contenders_.LoadRelaxed(), 0); guard_.num_contenders_--; #else + uint64_t old_owner = guard_.exclusive_owner_; + guard_.exclusive_owner_ = 0; guard_.recursion_count_ = 0; CHECK_MUTEX_CALL(pthread_cond_wait, (&cond_, &guard_.mutex_)); + guard_.exclusive_owner_ = old_owner; #endif guard_.recursion_count_ = old_recursion_count; } @@ -804,6 +807,8 @@ void ConditionVariable::TimedWait(Thread* self, int64_t ms, int32_t ns) { #else int clock = CLOCK_REALTIME; #endif + uint64_t old_owner = guard_.exclusive_owner_; + guard_.exclusive_owner_ = 0; guard_.recursion_count_ = 0; timespec ts; InitTimeSpec(true, clock, ms, ns, &ts); @@ -812,6 +817,7 @@ void ConditionVariable::TimedWait(Thread* self, int64_t ms, int32_t ns) { errno = rc; PLOG(FATAL) << "TimedWait failed for " << name_; } + guard_.exclusive_owner_ = old_owner; #endif guard_.recursion_count_ = old_recursion_count; } diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h index 68b450a1b9..1ba6180076 100644 --- a/runtime/base/mutex.h +++ b/runtime/base/mutex.h @@ -245,6 +245,7 @@ class LOCKABLE Mutex : public BaseMutex { AtomicInteger num_contenders_; #else pthread_mutex_t mutex_; + volatile uint64_t exclusive_owner_; // Guarded by mutex_. #endif const bool recursive_; // Can the lock be recursively held? unsigned int recursion_count_; @@ -358,6 +359,7 @@ class LOCKABLE ReaderWriterMutex : public BaseMutex { AtomicInteger num_pending_writers_; #else pthread_rwlock_t rwlock_; + volatile uint64_t exclusive_owner_; // Guarded by rwlock_. #endif DISALLOW_COPY_AND_ASSIGN(ReaderWriterMutex); }; diff --git a/runtime/base/unix_file/fd_file.cc b/runtime/base/unix_file/fd_file.cc index 87d1c0655d..6d5b59cbeb 100644 --- a/runtime/base/unix_file/fd_file.cc +++ b/runtime/base/unix_file/fd_file.cc @@ -69,17 +69,29 @@ int FdFile::Close() { } int FdFile::Flush() { +#ifdef __linux__ int rc = TEMP_FAILURE_RETRY(fdatasync(fd_)); +#else + int rc = TEMP_FAILURE_RETRY(fsync(fd_)); +#endif return (rc == -1) ? -errno : rc; } int64_t FdFile::Read(char* buf, int64_t byte_count, int64_t offset) const { +#ifdef __linux__ int rc = TEMP_FAILURE_RETRY(pread64(fd_, buf, byte_count, offset)); +#else + int rc = TEMP_FAILURE_RETRY(pread(fd_, buf, byte_count, offset)); +#endif return (rc == -1) ? -errno : rc; } int FdFile::SetLength(int64_t new_length) { +#ifdef __linux__ int rc = TEMP_FAILURE_RETRY(ftruncate64(fd_, new_length)); +#else + int rc = TEMP_FAILURE_RETRY(ftruncate(fd_, new_length)); +#endif return (rc == -1) ? -errno : rc; } @@ -90,7 +102,11 @@ int64_t FdFile::GetLength() const { } int64_t FdFile::Write(const char* buf, int64_t byte_count, int64_t offset) { +#ifdef __linux__ int rc = TEMP_FAILURE_RETRY(pwrite64(fd_, buf, byte_count, offset)); +#else + int rc = TEMP_FAILURE_RETRY(pwrite(fd_, buf, byte_count, offset)); +#endif return (rc == -1) ? -errno : rc; } diff --git a/runtime/base/unix_file/mapped_file.cc b/runtime/base/unix_file/mapped_file.cc index bc23a745c9..63927b1216 100644 --- a/runtime/base/unix_file/mapped_file.cc +++ b/runtime/base/unix_file/mapped_file.cc @@ -61,7 +61,11 @@ bool MappedFile::MapReadOnly() { bool MappedFile::MapReadWrite(int64_t file_size) { CHECK(IsOpened()); CHECK(!IsMapped()); +#ifdef __linux__ int result = TEMP_FAILURE_RETRY(ftruncate64(Fd(), file_size)); +#else + int result = TEMP_FAILURE_RETRY(ftruncate(Fd(), file_size)); +#endif if (result == -1) { PLOG(ERROR) << "Failed to truncate file '" << GetPath() << "' to size " << file_size; diff --git a/runtime/base/unix_file/mapped_file.h b/runtime/base/unix_file/mapped_file.h index 28cc5514f7..73056e9764 100644 --- a/runtime/base/unix_file/mapped_file.h +++ b/runtime/base/unix_file/mapped_file.h @@ -32,8 +32,13 @@ class MappedFile : public FdFile { public: // File modes used in Open(). enum FileMode { +#ifdef __linux__ kReadOnlyMode = O_RDONLY | O_LARGEFILE, kReadWriteMode = O_CREAT | O_RDWR | O_LARGEFILE, +#else + kReadOnlyMode = O_RDONLY, + kReadWriteMode = O_CREAT | O_RDWR, +#endif }; MappedFile() : FdFile(), file_size_(-1), mapped_file_(NULL) { |