1 /* 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 #include "lock_count_data.h" 18 19 #include <algorithm> 20 #include <string> 21 22 #include "android-base/logging.h" 23 #include "mirror/object-inl.h" 24 #include "thread.h" 25 26 namespace art { 27 28 void LockCountData::AddMonitor(Thread* self, mirror::Object* obj) { 29 if (obj == nullptr) { 30 return; 31 } 32 33 // If there's an error during enter, we won't have locked the monitor. So check there's no 34 // exception. 35 if (self->IsExceptionPending()) { 36 return; 37 } 38 39 if (monitors_ == nullptr) { 40 monitors_.reset(new std::vector<mirror::Object*>()); 41 } 42 monitors_->push_back(obj); 43 } 44 45 void LockCountData::RemoveMonitorOrThrow(Thread* self, const mirror::Object* obj) { 46 if (obj == nullptr) { 47 return; 48 } 49 bool found_object = false; 50 if (monitors_ != nullptr) { 51 // We need to remove one pointer to ref, as duplicates are used for counting recursive locks. 52 // We arbitrarily choose the first one. 53 auto it = std::find(monitors_->begin(), monitors_->end(), obj); 54 if (it != monitors_->end()) { 55 monitors_->erase(it); 56 found_object = true; 57 } 58 } 59 if (!found_object) { 60 // The object wasn't found. Time for an IllegalMonitorStateException. 61 // The order here isn't fully clear. Assume that any other pending exception is swallowed. 62 // TODO: Maybe make already pending exception a suppressed exception. 63 self->ClearException(); 64 self->ThrowNewExceptionF("Ljava/lang/IllegalMonitorStateException;", 65 "did not lock monitor on object of type '%s' before unlocking", 66 const_cast<mirror::Object*>(obj)->PrettyTypeOf().c_str()); 67 } 68 } 69 70 // Helper to unlock a monitor. Must be NO_THREAD_SAFETY_ANALYSIS, as we can't statically show 71 // that the object was locked. 72 void MonitorExitHelper(Thread* self, mirror::Object* obj) NO_THREAD_SAFETY_ANALYSIS { 73 DCHECK(self != nullptr); 74 DCHECK(obj != nullptr); 75 obj->MonitorExit(self); 76 } 77 78 bool LockCountData::CheckAllMonitorsReleasedOrThrow(Thread* self) { 79 DCHECK(self != nullptr); 80 if (monitors_ != nullptr) { 81 if (!monitors_->empty()) { 82 // There may be an exception pending, if the method is terminating abruptly. Clear it. 83 // TODO: Should we add this as a suppressed exception? 84 self->ClearException(); 85 86 // OK, there are monitors that are still locked. To enforce structured locking (and avoid 87 // deadlocks) we unlock all of them before we raise the IllegalMonitorState exception. 88 for (mirror::Object* obj : *monitors_) { 89 MonitorExitHelper(self, obj); 90 // If this raised an exception, ignore. TODO: Should we add this as suppressed 91 // exceptions? 92 if (self->IsExceptionPending()) { 93 self->ClearException(); 94 } 95 } 96 // Raise an exception, just give the first object as the sample. 97 mirror::Object* first = (*monitors_)[0]; 98 self->ThrowNewExceptionF("Ljava/lang/IllegalMonitorStateException;", 99 "did not unlock monitor on object of type '%s'", 100 mirror::Object::PrettyTypeOf(first).c_str()); 101 102 // To make sure this path is not triggered again, clean out the monitors. 103 monitors_->clear(); 104 105 return false; 106 } 107 } 108 return true; 109 } 110 111 } // namespace art 112