blob: cd4bfbb90104f6a5bae5bbfe4fa0615d7a9c5500 [file] [log] [blame]
Ian Rogersd9c4fc92013-10-01 19:45:43 -07001/*
2 * Copyright (C) 2011 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 ART_RUNTIME_LOCK_WORD_H_
18#define ART_RUNTIME_LOCK_WORD_H_
19
20#include <iosfwd>
21#include <stdint.h>
22
23#include "base/logging.h"
24
25namespace art {
26namespace mirror {
27 class Object;
28} // namespace mirror
29
30class Monitor;
31
32/* The lock value itself as stored in mirror::Object::monitor_. The MSB of the lock encodes its
33 * state. When cleared, the lock is in the "thin" state and its bits are formatted as follows:
34 *
35 * |3|32222222222111|11111110000000000|
36 * |1|09876543210987|65432109876543210|
37 * |0| lock count | thread id |
38 *
39 * When set, the lock is in the "fat" state and its bits are formatted as follows:
40 *
41 * |3|3222222222211111111110000000000|
42 * |1|0987654321098765432109876543210|
43 * |1| Monitor* >> 1 |
44 */
45class LockWord {
46 public:
47 enum {
48 // Number of bits to encode the state, currently just fat or thin/unlocked.
49 kStateSize = 1,
50 // Number of bits to encode the thin lock owner.
51 kThinLockOwnerSize = 16,
52 // Remaining bits are the recursive lock count.
53 kThinLockCountSize = 32 - kThinLockOwnerSize - kStateSize,
54
55 // Thin lock bits. Owner in lowest bits.
56 kThinLockOwnerShift = 0,
57 kThinLockOwnerMask = (1 << kThinLockOwnerSize) - 1,
58 // Count in higher bits.
59 kThinLockCountShift = kThinLockOwnerSize + kThinLockOwnerShift,
60 kThinLockCountMask = (1 << kThinLockCountShift) - 1,
61 kThinLockMaxCount = kThinLockCountMask,
62
63 // State in the highest bits.
64 kStateShift = kThinLockCountSize + kThinLockCountShift,
65 kStateMask = (1 << kStateSize) - 1,
66 kStateThinOrUnlocked = 0,
67 kStateFat = 1,
68 };
69
70 static LockWord FromThinLockId(uint32_t thread_id, uint32_t count) {
71 CHECK_LE(thread_id, static_cast<uint32_t>(kThinLockOwnerMask));
72 return LockWord((thread_id << kThinLockOwnerShift) | (count << kThinLockCountShift));
73 }
74
75 enum LockState {
76 kUnlocked, // No lock owners.
77 kThinLocked, // Single uncontended owner.
78 kFatLocked // See associated monitor.
79 };
80
81 LockState GetState() const {
82 if (value_ == 0) {
83 return kUnlocked;
84 } else if (((value_ >> kStateShift) & kStateMask) == kStateThinOrUnlocked) {
85 return kThinLocked;
86 } else {
87 return kFatLocked;
88 }
89 }
90
91 // Return the owner thin lock thread id.
92 uint32_t ThinLockOwner() const;
93
94 // Return the number of times a lock value has been locked.
95 uint32_t ThinLockCount() const;
96
97 // Return the Monitor encoded in a fat lock.
98 Monitor* FatLockMonitor() const;
99
100 // Default constructor with no lock ownership.
101 LockWord();
102
103 // Constructor a lock word for inflation to use a Monitor.
104 explicit LockWord(Monitor* mon);
105
106 bool operator==(const LockWord& rhs) {
107 return GetValue() == rhs.GetValue();
108 }
109
110 private:
111 explicit LockWord(uint32_t val) : value_(val) {}
112
113 uint32_t GetValue() const {
114 return value_;
115 }
116
117 // Only Object should be converting LockWords to/from uints.
118 friend class mirror::Object;
119
120 // The encoded value holding all the state.
121 uint32_t value_;
122};
123std::ostream& operator<<(std::ostream& os, const LockWord::LockState& code);
124
125} // namespace art
126
127
128#endif // ART_RUNTIME_LOCK_WORD_H_