mutex.h revision 00f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abac
18daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes/*
28daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * Copyright (C) 2011 The Android Open Source Project
38daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes *
48daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
58daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * you may not use this file except in compliance with the License.
68daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * You may obtain a copy of the License at
78daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes *
88daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
98daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes *
108daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * Unless required by applicable law or agreed to in writing, software
118daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
128daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * See the License for the specific language governing permissions and
148daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * limitations under the License.
158daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes */
168daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
178daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#ifndef ART_SRC_MUTEX_H_
188daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#define ART_SRC_MUTEX_H_
198daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
208daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include <pthread.h>
21cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom#include <stdint.h>
22ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes
23ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes#include <iosfwd>
248daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include <string>
258daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
2600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "globals.h"
273efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes#include "gtest/gtest.h"
288daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include "logging.h"
298daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include "macros.h"
308daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
318daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughesnamespace art {
328daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
3300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE Mutex;
3400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE ReaderWriterMutex;
3500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
3600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// MutexLevel is used to impose a lock hierarchy [1] where acquisition of a Mutex at a higher or
3700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// equal level to a lock a thread holds is invalid. The lock hierarchy achieves a cycle free
3800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// partial ordering and thereby cause deadlock situations to fail checks.
3900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//
4000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// [1] http://www.drdobbs.com/parallel/use-lock-hierarchies-to-avoid-deadlock/204801163
4100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersenum MutexLevel {
4200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  kLoggingLock = 0,
4300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  kUnexpectedSignalLock = 1,
44ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes  kThreadSuspendCountLock = 2,
4500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  kAbortLock = 3,
4600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  kDefaultMutexLevel = 4,
4700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  kLoadLibraryLock = 5,
4800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  kClassLinkerClassesLock = 6,
4900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  kThreadListLock = 7,
5000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  kHeapBitmapLock = 8,
5100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  kZygoteCreationLock = 9,
5200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  kMonitorLock = 10,
5300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  kMutatorLock = 11,
5400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  kMaxMutexLevel = kMutatorLock,
55ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes};
5600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstd::ostream& operator<<(std::ostream& os, const MutexLevel& rhs);
57ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes
5800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Global mutexes corresponding to the levels above.
5900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass GlobalSynchronization {
608daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes public:
6100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static void Init();
628daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
6300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // The mutator_lock_ is used to allow mutators to execute in a shared (reader) mode or to block
6400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // mutators by having an exclusive (writer) owner. In normal execution each mutator thread holds
6500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // a share on the mutator_lock_. The garbage collector may also execute with shared access but
6600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // at times requires exclusive access to the heap (not to be confused with the heap meta-data
6700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // guarded by the heap_lock_ below). When the garbage collector requires exclusive access it asks
6800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // the mutators to suspend themselves which also involves usage of the thread_suspend_count_lock_
6900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // to cover weaknesses in using ReaderWriterMutexes with ConditionVariables. We use a condition
7000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // variable to wait upon in the suspension logic as releasing and then re-acquiring a share on
7100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // the mutator lock doesn't necessarily allow the exclusive user (e.g the garbage collector)
7200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // chance to acquire the lock.
7300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //
7400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Thread suspension:
7500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Shared users                                  | Exclusive user
7600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // (holding mutator lock and in kRunnable state) |   .. running ..
7700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. running ..                               | Request thread suspension by:
7800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. running ..                               |   - acquiring thread_suspend_count_lock_
7900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. running ..                               |   - incrementing Thread::suspend_count_ on
8000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. running ..                               |     all mutator threads
8100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. running ..                               |   - releasing thread_suspend_count_lock_
8200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. running ..                               | Block trying to acquire exclusive mutator lock
8300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Poll Thread::suspend_count_ and enter full    |   .. blocked ..
8400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // suspend code.                                 |   .. blocked ..
8500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Change state to kSuspended                    |   .. blocked ..
8600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // x: Release share on mutator_lock_             | Carry out exclusive access
8700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Acquire thread_suspend_count_lock_            |   .. exclusive ..
8800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // while Thread::suspend_count_ > 0              |   .. exclusive ..
8900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   - wait on Thread::resume_cond_              |   .. exclusive ..
9000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //     (releases thread_suspend_count_lock_)     |   .. exclusive ..
9100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. waiting ..                               | Release mutator_lock_
9200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. waiting ..                               | Request thread resumption by:
9300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. waiting ..                               |   - acquiring thread_suspend_count_lock_
9400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. waiting ..                               |   - decrementing Thread::suspend_count_ on
9500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. waiting ..                               |     all mutator threads
9600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. waiting ..                               |   - notifying on Thread::resume_cond_
9700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    - re-acquire thread_suspend_count_lock_    |   - releasing thread_suspend_count_lock_
9800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release thread_suspend_count_lock_            |  .. running ..
9900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Acquire share on mutator_lock_                |  .. running ..
10000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //  - This could block but the thread still      |  .. running ..
10100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    has a state of kSuspended and so this      |  .. running ..
10200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    isn't an issue.                            |  .. running ..
10300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Acquire thread_suspend_count_lock_            |  .. running ..
10400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //  - we poll here as we're transitioning into   |  .. running ..
10500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    kRunnable and an individual thread suspend |  .. running ..
10600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    request (e.g for debugging) won't try      |  .. running ..
10700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    to acquire the mutator lock (which would   |  .. running ..
10800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    block as we hold the mutator lock). This   |  .. running ..
10900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    poll ensures that if the suspender thought |  .. running ..
11000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    we were suspended by incrementing our      |  .. running ..
11100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    Thread::suspend_count_ and then reading    |  .. running ..
11200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    our state we go back to waiting on         |  .. running ..
11300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    Thread::resume_cond_.                      |  .. running ..
11400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // can_go_runnable = Thread::suspend_count_ == 0 |  .. running ..
11500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release thread_suspend_count_lock_            |  .. running ..
11600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // if can_go_runnable                            |  .. running ..
11700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   Change state to kRunnable                   |  .. running ..
11800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // else                                          |  .. running ..
11900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   Goto x                                      |  .. running ..
12000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //  .. running ..                                |  .. running ..
12100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static ReaderWriterMutex* mutator_lock_;
1228daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
12300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Allow reader-writer mutual exclusion on the mark and live bitmaps of the heap.
12400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static ReaderWriterMutex* heap_bitmap_lock_ ACQUIRED_AFTER(mutator_lock_);
1258daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
12600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // The thread_list_lock_ guards ThreadList::list_. It is also commonly held to stop threads
12700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // attaching and detaching.
12800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static Mutex* thread_list_lock_ ACQUIRED_AFTER(heap_bitmap_lock_);
1298daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
13000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Guards lists of classes within the class linker.
13100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static Mutex* classlinker_classes_lock_ ACQUIRED_AFTER(thread_list_lock_);
1328daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
13300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // When declaring any Mutex add DEFAULT_MUTEX_ACQUIRED_AFTER to use annotalysis to check the code
13400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // doesn't try to hold a higher level Mutex.
13500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  #define DEFAULT_MUTEX_ACQUIRED_AFTER ACQUIRED_AFTER(classlinker_classes_lock_)
136accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes
13700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Have an exclusive aborting thread.
13800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static Mutex* abort_lock_ ACQUIRED_AFTER(classlinker_classes_lock_);
139cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom
14000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Allow mutual exclusion when manipulating Thread::suspend_count_.
14100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // TODO: Does the trade-off of a per-thread lock make sense?
14200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static Mutex* thread_suspend_count_lock_ ACQUIRED_AFTER(abort_lock_);
14300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
14400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // One unexpected signal at a time lock.
14500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static Mutex* unexpected_signal_lock_ ACQUIRED_AFTER(thread_suspend_count_lock_);
14600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
14700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Have an exclusive logging thread.
14800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static Mutex* logging_lock_ ACQUIRED_AFTER(unexpected_signal_lock_);
14900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
15000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
15100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Base class for all Mutex implementations
15200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass BaseMutex {
15300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
15400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  const std::string& GetName() const {
15500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return name_;
15600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
15700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
15800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsMutex() const { return false; }
15900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsReaderWriterMutex() const { return false; }
16000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
16100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers protected:
16200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  friend class ConditionVariable;
16300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
16400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  BaseMutex(const char* name, MutexLevel level);
16500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual ~BaseMutex() {}
16600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void RegisterAsLockedWithCurrentThread();
16700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void RegisterAsUnlockedWithCurrentThread();
16800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void CheckSafeToWait();
16900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
17000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  const MutexLevel level_;  // Support for lock hierarchy.
1710a1038b0a30a52dff1a449a989825e808a83df80Elliott Hughes  const std::string name_;
17200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
17300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
17400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// A Mutex is used to achieve mutual exclusion between threads. A Mutex can be used to gain
17500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// exclusive access to what it guards. A Mutex can be in one of two states:
17600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Free - not owned by any thread,
17700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Exclusive - owned by a single thread.
17800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//
17900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// The effect of locking and unlocking operations on the state is:
18000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// State     | ExclusiveLock | ExclusiveUnlock
18100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// -------------------------------------------
18200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Free      | Exclusive     | error
18300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Exclusive | Block*        | Free
18400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// * Mutex is not reentrant and so an attempt to ExclusiveLock on the same thread will result in
18500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//   an error. Being non-reentrant simplifies Waiting on ConditionVariables.
18600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE Mutex : public BaseMutex {
18700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
18800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  explicit Mutex(const char* name, MutexLevel level = kDefaultMutexLevel, bool recursive = false);
18900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~Mutex();
19000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
19100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsMutex() const { return true; }
19200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
19300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until mutex is free then acquire exclusive access.
19400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void ExclusiveLock() EXCLUSIVE_LOCK_FUNCTION();
19500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void Lock() EXCLUSIVE_LOCK_FUNCTION() {  ExclusiveLock(); }
19600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
19700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Returns true if acquires exclusive access, false otherwise.
19800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  bool ExclusiveTryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true);
19900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true) { return ExclusiveTryLock(); }
20000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
20100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release exclusive access.
20200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void ExclusiveUnlock() UNLOCK_FUNCTION();
20300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void Unlock() UNLOCK_FUNCTION() {  ExclusiveUnlock(); }
20400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
20500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Is the current thread the exclusive holder of the Mutex.
20600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  bool IsExclusiveHeld() const;
2078daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
20800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert that the Mutex is exclusively held by the current thread.
20900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertExclusiveHeld() {
21000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    if (kIsDebugBuild) {
21100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      CHECK(IsExclusiveHeld());
21200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
21300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
21400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertHeld() { AssertExclusiveHeld(); }
21500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
21600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert that the Mutex is not held by the current thread.
21700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertNotHeldExclusive() {
21800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    if (kIsDebugBuild) {
21900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      CHECK(!IsExclusiveHeld());
22000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
22100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
22200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertNotHeld() { AssertNotHeldExclusive(); }
22300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
22400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Id associated with exclusive owner.
22500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  uint64_t GetExclusiveOwnerTid() const;
22600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
22700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Returns how many times this Mutex has been locked, it is better to use AssertHeld/NotHeld.
22800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  unsigned int GetDepth() const {
22900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return recursion_count_;
23000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
23100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
23200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
23300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  pthread_mutex_t mutex_;
23400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  const bool recursive_;  // Can the lock be recursively held?
23500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  unsigned int recursion_count_;
236f1498437b0d6beb9f4f91980b98cbeb0b5c773ceElliott Hughes  friend class ConditionVariable;
2373efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes  friend class MutexTester;
2388daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  DISALLOW_COPY_AND_ASSIGN(Mutex);
2398daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes};
2408daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
24100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// A ReaderWriterMutex is used to achieve mutual exclusion between threads, similar to a Mutex.
24200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Unlike a Mutex a ReaderWriterMutex can be used to gain exclusive (writer) or shared (reader)
24300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// access to what it guards. A flaw in relation to a Mutex is that it cannot be used with a
24400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// condition variable. A ReaderWriterMutex can be in one of three states:
24500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Free - not owned by any thread,
24600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Exclusive - owned by a single thread,
24700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Shared(n) - shared amongst n threads.
24800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//
24900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// The effect of locking and unlocking operations on the state is:
25000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//
25100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// State     | ExclusiveLock | ExclusiveUnlock | SharedLock       | SharedUnlock
25200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// ----------------------------------------------------------------------------
25300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Free      | Exclusive     | error           | SharedLock(1)    | error
25400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Exclusive | Block         | Free            | Block            | error
25500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Shared(n) | Block         | error           | SharedLock(n+1)* | Shared(n-1) or Free
25600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// * for large values of n the SharedLock may block.
25700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE ReaderWriterMutex : public BaseMutex {
2588daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes public:
25900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  explicit ReaderWriterMutex(const char* name, MutexLevel level = kDefaultMutexLevel);
26000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~ReaderWriterMutex();
26100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
26200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsReaderWriterMutex() const { return true; }
26300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
26400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until ReaderWriterMutex is free then acquire exclusive access.
26500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void ExclusiveLock() EXCLUSIVE_LOCK_FUNCTION();
26600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void WriterLock() EXCLUSIVE_LOCK_FUNCTION() {  ExclusiveLock(); }
26700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
26800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release exclusive access.
26900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void ExclusiveUnlock() UNLOCK_FUNCTION();
27000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void WriterUnlock() UNLOCK_FUNCTION() {  ExclusiveUnlock(); }
27100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
27200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until ReaderWriterMutex is free and acquire exclusive access. Returns true on success
27300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // or false if timeout is reached.
27400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  bool ExclusiveLockWithTimeout(const timespec& abs_timeout) EXCLUSIVE_TRYLOCK_FUNCTION(true);
27500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
27600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until ReaderWriterMutex is shared or free then acquire a share on the access.
27700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void SharedLock() SHARED_LOCK_FUNCTION();
27800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void ReaderLock() SHARED_LOCK_FUNCTION() { SharedLock(); }
27900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
28000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Try to acquire share of ReaderWriterMutex.
28100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  bool SharedTryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true);
28200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
28300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release a share of the access.
28400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void SharedUnlock() UNLOCK_FUNCTION();
28500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void ReaderUnlock() UNLOCK_FUNCTION() { SharedUnlock(); }
28600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
28700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Is the current thread the exclusive holder of the ReaderWriterMutex.
28800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  bool IsExclusiveHeld() const;
28900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
29000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread has exclusive access to the ReaderWriterMutex.
29100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertExclusiveHeld() {
29200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    if (kIsDebugBuild) {
29300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      CHECK(IsExclusiveHeld());
29400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
2958daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  }
29600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertWriterHeld() { AssertExclusiveHeld(); }
2978daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
29800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread doesn't have exclusive access to the ReaderWriterMutex.
29900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertNotExclusiveHeld() {
30000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    if (kIsDebugBuild) {
30100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      CHECK(!IsExclusiveHeld());
30200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
30300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
30400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertNotWriterHeld() { AssertNotExclusiveHeld(); }
30500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
30600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Is the current thread a shared holder of the ReaderWriterMutex.
30700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  bool IsSharedHeld() const;
30800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
30900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread has shared access to the ReaderWriterMutex.
31000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertSharedHeld() {
31100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    if (kIsDebugBuild) {
31200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      CHECK(IsSharedHeld());
31300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
3148daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  }
31500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertReaderHeld() { AssertSharedHeld(); }
3168daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
31700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread doesn't hold this ReaderWriterMutex either in shared or exclusive
31800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // mode.
31900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertNotHeld() {
32000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    if (kIsDebugBuild) {
32100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      CHECK(!IsSharedHeld());
32200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
32300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
32400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
32500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Id associated with exclusive owner.
32600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  uint64_t GetExclusiveOwnerTid() const;
3278daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes private:
32800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  pthread_rwlock_t rwlock_;
32900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
33000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  friend class MutexTester;
33100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(ReaderWriterMutex);
3328daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes};
3338daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
33400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// ConditionVariables allow threads to queue and sleep. Threads may then be resumed individually
33500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// (Signal) or all at once (Broadcast).
3365f79133a435ebcb20000370d56046fe01201dd80Elliott Hughesclass ConditionVariable {
3375f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes public:
338a51a3dd5603daf3d368b7735067e1d9eb54c4c40Elliott Hughes  explicit ConditionVariable(const std::string& name);
3395f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  ~ConditionVariable();
3405f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
3415f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  void Broadcast();
3425f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  void Signal();
3435f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  void Wait(Mutex& mutex);
3445f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  void TimedWait(Mutex& mutex, const timespec& ts);
3455f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
3465f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes private:
3475f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  pthread_cond_t cond_;
3485f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  std::string name_;
3495f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  DISALLOW_COPY_AND_ASSIGN(ConditionVariable);
3505f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes};
3515f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
35200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a regular Mutex that acquires mu upon construction and releases it
35300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// upon destruction.
35400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE MutexLock {
35500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
35600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  explicit MutexLock(Mutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) {
35700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    mu_.ExclusiveLock();
35800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
35900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
36000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~MutexLock() UNLOCK_FUNCTION() {
36100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    mu_.ExclusiveUnlock();
36200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
36300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
36400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
36500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  Mutex& mu_;
36600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(MutexLock);
36700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
36800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "MutexLock (lock);" instead of "MutexLock mu(lock)".
36900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_declaration_missing_variable_name)
37000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
37100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a ReaderWriterMutex that acquires read access to mu upon
37200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// construction and releases it upon destruction.
37300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE ReaderMutexLock {
37400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
37500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  explicit ReaderMutexLock(ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) {
37600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    mu_.SharedLock();
37700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
37800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
37900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~ReaderMutexLock() UNLOCK_FUNCTION() {
38000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    mu_.SharedUnlock();
38100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
38200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
38300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
38400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ReaderWriterMutex& mu_;
38500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(ReaderMutexLock);
38600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
38700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "ReaderMutexLock (lock);" instead of
38800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// "ReaderMutexLock mu(lock)".
38900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define ReaderMutexLock(x) COMPILE_ASSERT(0, reader_mutex_lock_declaration_missing_variable_name)
39000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
39100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a ReaderWriterMutex that acquires write access to mu upon
39200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// construction and releases it upon destruction.
39300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE WriterMutexLock {
39400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
39500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  explicit WriterMutexLock(ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) {
39600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    mu_.ExclusiveLock();
39700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
39800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
39900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~WriterMutexLock() UNLOCK_FUNCTION() {
40000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    mu_.ExclusiveUnlock();
40100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
40200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
40300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
40400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ReaderWriterMutex& mu_;
40500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(WriterMutexLock);
40600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
40700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "WriterMutexLock (lock);" instead of
40800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// "WriterMutexLock mu(lock)".
40900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define WriterMutexLock(x) COMPILE_ASSERT(0, writer_mutex_lock_declaration_missing_variable_name)
41000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
41100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped unlocker/locker for a ReaderWriterMutex that releases read access to mu upon
41200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// construction and acquires it again upon destruction.
41300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass ReaderMutexUnlock {
41400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
41500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  explicit ReaderMutexUnlock(ReaderWriterMutex& mu) UNLOCK_FUNCTION(mu) : mu_(mu) {
41600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    mu_.SharedUnlock();
41700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
41800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
41900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~ReaderMutexUnlock() SHARED_LOCK_FUNCTION(mu_) {
42000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    mu_.SharedLock();
42100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
42200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
42300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
42400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ReaderWriterMutex& mu_;
42500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(ReaderMutexUnlock);
42600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
42700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "ReaderMutexUnlock (lock);" instead of
42800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// "ReaderMutexUnlock mu(lock)".
42900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define ReaderMutexUnlock(x) \
43000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    COMPILE_ASSERT(0, reader_mutex_unlock_declaration_missing_variable_name)
43100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
4328daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}  // namespace art
4338daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
4348daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#endif  // ART_SRC_MUTEX_H_
435