Sync.cpp revision 07b359273a838a15accafefcbe861be15caaac3a
1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16581bed77d3596b9d7242da10867c8d4cfd382239Andy McFadden 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Fundamental synchronization mechanisms. 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The top part of the file has operations on "monitor" structs; the 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * next part has the native calls on objects. 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The current implementation uses "thin locking" to avoid allocating 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an Object's full Monitor struct until absolutely necessary (i.e., 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * during contention or a call to wait()). 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: make improvements to thin locking 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We may be able to improve performance and reduce memory requirements by: 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - reverting to a thin lock once the Monitor is no longer necessary 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - using a pool of monitor objects, with some sort of recycling scheme 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: recycle native-level monitors when objects are garbage collected. 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h" 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h> 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <unistd.h> 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <pthread.h> 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <time.h> 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/time.h> 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <errno.h> 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define LOG_THIN LOGV 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION /* fwd */ 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic const char* kStartBanner = 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "<-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#"; 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic const char* kEndBanner = 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#->"; 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unsorted, expanding list of objects. 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is very similar to PointerSet (which came into existence after this), 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * but these are unsorted, uniqueness is not enforced by the "add" function, 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and the base object isn't allocated on the heap. 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct ExpandingObjectList { 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u2 alloc; 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u2 count; 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object** list; 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} ExpandingObjectList; 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* fwd */ 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void updateDeadlockPrediction(Thread* self, Object* obj); 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void removeCollectedObject(Object* obj); 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void expandObjClear(ExpandingObjectList* pList); 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Every Object has a monitor associated with it, but not every Object is 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * actually locked. Even the ones that are locked do not need a 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * full-fledged monitor until a) there is actual contention or b) wait() 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is called on the Object. 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For Dalvik, we have implemented a scheme similar to the one described 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in Bacon et al.'s "Thin locks: featherweight synchronization for Java" 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (ACM 1998). Things are even easier for us, though, because we have 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a full 32 bits to work with. 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8194338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * The two states of an Object's lock are referred to as "thin" and 8294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * "fat". A lock may transition from the "thin" state to the "fat" 8394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * state and this transition is referred to as inflation. Once a lock 8494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * has been inflated it remains in the "fat" state indefinitely. 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * The lock value itself is stored in Object.lock. The LSB of the 8777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * lock encodes its state. When cleared, the lock is in the "thin" 8877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * state and its bits are formatted as follows: 8971938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro * 9094338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * [31 ---- 19] [18 ---- 3] [2 ---- 1] [0] 9194338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * lock count thread id hash state 0 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 9377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * When set, the lock is in the "fat" state and its bits are formatted 9494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * as follows: 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 9694338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * [31 ---- 3] [2 ---- 1] [0] 9794338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * pointer hash state 1 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For an in-depth description of the mechanics of thin-vs-fat locking, 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * read the paper referred to above. 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Monitors provide: 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - mutually exclusive access to resources 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - a way for multiple threads to wait for notification 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In effect, they fill the role of both mutexes and condition variables. 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Only one thread can own the monitor at any time. There may be several 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * threads waiting on it (the wait call unlocks it). One or more waiting 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * threads may be getting interrupted or notified at any given time. 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstruct Monitor { 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* owner; /* which thread currently owns the lock? */ 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int lockCount; /* owner's recursive lock depth */ 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* obj; /* what object are we part of [debug only] */ 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 11977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro Thread* waitSet; /* threads currently waiting on this monitor */ 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pthread_mutex_t lock; 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Monitor* next; 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Objects that have been locked immediately after this one in the 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * past. We use an expanding flat array, allocated on first use, to 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * minimize allocations. Deletions from the list, expected to be 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * infrequent, are crunched down. 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ExpandingObjectList historyChildren; 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We also track parents. This isn't strictly necessary, but it makes 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the cleanup at GC time significantly faster. 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ExpandingObjectList historyParents; 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* used during cycle detection */ 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool historyMark; 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* stack trace, established the first time we locked the object */ 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int historyStackDepth; 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int* historyRawStackTrace; 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}; 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create and initialize a monitor. 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectMonitor* dvmCreateMonitor(Object* obj) 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Monitor* mon; 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon = (Monitor*) calloc(1, sizeof(Monitor)); 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (mon == NULL) { 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Unable to allocate monitor\n"); 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 16294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro if (((u4)mon & 7) != 0) { 16394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro LOGE("Misaligned monitor: %p\n", mon); 16494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro dvmAbort(); 16594338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro } 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon->obj = obj; 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmInitMutex(&mon->lock); 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* replace the head of the list with the new monitor */ 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project do { 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon->next = gDvm.monitorList; 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } while (!ATOMIC_CMP_SWAP((int32_t*)(void*)&gDvm.monitorList, 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (int32_t)mon->next, (int32_t)mon)); 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return mon; 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free the monitor list. Only used when shutting the VM down. 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmFreeMonitorList(void) 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Monitor* mon; 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Monitor* nextMon; 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon = gDvm.monitorList; 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (mon != NULL) { 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project nextMon = mon->next; 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project expandObjClear(&mon->historyChildren); 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project expandObjClear(&mon->historyParents); 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(mon->historyRawStackTrace); 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(mon); 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon = nextMon; 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Log some info about our monitors. 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpMonitorInfo(const char* msg) 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if QUIET_ZYGOTE_MONITOR 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.zygote) { 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int totalCount; 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int liveCount; 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project totalCount = liveCount = 0; 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Monitor* mon = gDvm.monitorList; 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (mon != NULL) { 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project totalCount++; 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (mon->obj != NULL) 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project liveCount++; 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon = mon->next; 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD("%s: monitor list has %d entries (%d live)\n", 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project msg, totalCount, liveCount); 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the object that a monitor is part of. 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectObject* dvmGetMonitorObject(Monitor* mon) 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (mon == NULL) 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return mon->obj; 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 23930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * Returns the thread id of the thread owning the given lock. 24030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */ 24130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapirostatic u4 lockOwner(Object* obj) 24230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro{ 24330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro Thread *owner; 24430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro u4 lock; 24530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro 24630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro assert(obj != NULL); 24730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro /* 24830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * Since we're reading the lock value multiple times, latch it so 24930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * that it doesn't change out from under us if we get preempted. 25030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */ 25130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro lock = obj->lock; 25230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro if (LW_SHAPE(lock) == LW_SHAPE_THIN) { 25330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro return LW_LOCK_OWNER(lock); 25430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } else { 25530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro owner = LW_MONITOR(lock)->owner; 25630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro return owner ? owner->threadId : 0; 25730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } 25830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro} 25930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro 26030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro/* 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Checks whether the given thread holds the given 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * objects's lock. 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmHoldsLock(Thread* thread, Object* obj) 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (thread == NULL || obj == NULL) { 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 26930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro return thread->threadId == lockOwner(obj); 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free the monitor associated with an object and make the object's lock 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * thin again. This is called during garbage collection. 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 2775a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapirostatic void freeObjectMonitor(Object* obj) 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Monitor *mon; 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 2815a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro assert(LW_SHAPE(obj->lock) == LW_SHAPE_FAT); 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.deadlockPredictMode != kDPOff) 2855a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro removeCollectedObject(obj); 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 2885a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro mon = LW_MONITOR(obj->lock); 2895a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro obj->lock = DVM_LOCK_INITIAL_THIN_VALUE; 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* This lock is associated with an object 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that's being swept. The only possible way 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * anyone could be holding this lock would be 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if some JNI code locked but didn't unlock 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the object, in which case we've got some bad 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * native code somewhere. 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(pthread_mutex_trylock(&mon->lock) == 0); 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pthread_mutex_destroy(&mon->lock); 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION 3015a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro expandObjClear(&mon->historyChildren); 3025a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro expandObjClear(&mon->historyParents); 3035a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro free(mon->historyRawStackTrace); 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 3055a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro free(mon); 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 3085a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro/* 3095a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro * Frees monitor objects belonging to unmarked objects. 3105a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro */ 3115a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapirovoid dvmSweepMonitorList(Monitor** mon, int (*isUnmarkedObject)(void*)) 3125a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro{ 3135a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro Monitor handle; 3145a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro Monitor *prev, *curr; 3155a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro Object *obj; 3165a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro 3175a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro assert(mon != NULL); 3185a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro assert(*mon != NULL); 3195a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro assert(isUnmarkedObject != NULL); 3205a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro prev = &handle; 3215a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro prev->next = curr = *mon; 3225a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro while (curr != NULL) { 3235a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro obj = curr->obj; 3245a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro if (obj != NULL && (*isUnmarkedObject)(obj) != 0) { 3255a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro prev->next = curr = curr->next; 3265a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro freeObjectMonitor(obj); 3275a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro } else { 3285a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro prev = curr; 3295a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro curr = curr->next; 3305a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro } 3315a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro } 3325a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro *mon = handle.next; 3335a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro} 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Lock a monitor. 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void lockMonitor(Thread* self, Monitor* mon) 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int cc; 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (mon->owner == self) { 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon->lockCount++; 344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ThreadStatus oldStatus; 346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pthread_mutex_trylock(&mon->lock) != 0) { 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* mutex is locked, switch to wait status and sleep on it */ 349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oldStatus = dvmChangeStatus(self, THREAD_MONITOR); 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cc = pthread_mutex_lock(&mon->lock); 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(cc == 0); 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmChangeStatus(self, oldStatus); 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon->owner = self; 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(mon->lockCount == 0); 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Try to lock a monitor. 362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" on success. 364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool tryLockMonitor(Thread* self, Monitor* mon) 366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int cc; 368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (mon->owner == self) { 370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon->lockCount++; 371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cc = pthread_mutex_trylock(&mon->lock); 374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (cc == 0) { 375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon->owner = self; 376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(mon->lockCount == 0); 377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unlock a monitor. 387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns true if the unlock succeeded. 389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the unlock failed, an exception will be pending. 390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool unlockMonitor(Thread* self, Monitor* mon) 392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 39377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro assert(self != NULL); 394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(mon != NULL); // can this happen? 395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (mon->owner == self) { 397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We own the monitor, so nobody else can be in here. 399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (mon->lockCount == 0) { 401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int cc; 402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon->owner = NULL; 403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cc = pthread_mutex_unlock(&mon->lock); 404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(cc == 0); 405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon->lockCount--; 407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We don't own this, so we're not allowed to unlock it. 411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The JNI spec says that we should throw IllegalMonitorStateException 412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in this case. 413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (mon->owner == NULL) { 415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //LOGW("Unlock fat %p: not owned\n", mon->obj); 416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //LOGW("Unlock fat %p: id %d vs %d\n", 418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // mon->obj, mon->owner->threadId, self->threadId); 419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ljava/lang/IllegalMonitorStateException;", 421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "unlock of unowned monitor"); 422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 42877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * Checks the wait set for circular structure. Returns 0 if the list 429b453919fee9bf10ccd576d389d8b3584061bba8bCarl Shapiro * is not circular. Otherwise, returns 1. Used only by asserts. 43077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro */ 43177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapirostatic int waitSetCheck(Monitor *mon) 43277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro{ 43377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro Thread *fast, *slow; 43477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro size_t n; 43577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro 43677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro assert(mon != NULL); 43777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro fast = slow = mon->waitSet; 43877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro n = 0; 43977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro for (;;) { 44077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro if (fast == NULL) return 0; 44177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro if (fast->waitNext == NULL) return 0; 4425f56e67999c67861872c27097803d2126142fed4Carl Shapiro if (fast == slow && n > 0) return 1; 44377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro n += 2; 44477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro fast = fast->waitNext->waitNext; 44577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro slow = slow->waitNext; 44677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro } 44777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro} 44877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro 44977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro/* 45030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * Links a thread into a monitor's wait set. The monitor lock must be 45130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * held by the caller of this routine. 45277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro */ 45377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapirostatic void waitSetAppend(Monitor *mon, Thread *thread) 45477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro{ 45577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro Thread *elt; 45677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro 45777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro assert(mon != NULL); 45830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro assert(mon->owner == dvmThreadSelf()); 45977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro assert(thread != NULL); 46077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro assert(thread->waitNext == NULL); 46177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro assert(waitSetCheck(mon) == 0); 46277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro if (mon->waitSet == NULL) { 46377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro mon->waitSet = thread; 46477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro return; 46577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro } 46677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro elt = mon->waitSet; 46777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro while (elt->waitNext != NULL) { 46877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro elt = elt->waitNext; 46977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro } 47077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro elt->waitNext = thread; 47177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro} 47277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro 47377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro/* 47430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * Unlinks a thread from a monitor's wait set. The monitor lock must 47530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * be held by the caller of this routine. 47677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro */ 47777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapirostatic void waitSetRemove(Monitor *mon, Thread *thread) 47877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro{ 47977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro Thread *elt; 48077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro 48177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro assert(mon != NULL); 48230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro assert(mon->owner == dvmThreadSelf()); 48377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro assert(thread != NULL); 48477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro assert(waitSetCheck(mon) == 0); 48577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro if (mon->waitSet == NULL) { 48677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro return; 48777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro } 48877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro if (mon->waitSet == thread) { 48977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro mon->waitSet = thread->waitNext; 49077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro thread->waitNext = NULL; 49177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro return; 49277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro } 49377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro elt = mon->waitSet; 49477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro while (elt->waitNext != NULL) { 49577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro if (elt->waitNext == thread) { 49677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro elt->waitNext = thread->waitNext; 49777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro thread->waitNext = NULL; 49877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro return; 49977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro } 50077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro elt = elt->waitNext; 50177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro } 50277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro} 50377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro 504b453919fee9bf10ccd576d389d8b3584061bba8bCarl Shapiro/* 505b453919fee9bf10ccd576d389d8b3584061bba8bCarl Shapiro * Converts the given relative waiting time into an absolute time. 506b453919fee9bf10ccd576d389d8b3584061bba8bCarl Shapiro */ 50777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapirostatic void absoluteTime(s8 msec, s4 nsec, struct timespec *ts) 50877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro{ 50977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro s8 endSec; 51077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro 51177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro#ifdef HAVE_TIMEDWAIT_MONOTONIC 51277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro clock_gettime(CLOCK_MONOTONIC, ts); 51377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro#else 51477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro { 51577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro struct timeval tv; 51677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro gettimeofday(&tv, NULL); 51777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro ts->tv_sec = tv.tv_sec; 51877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro ts->tv_nsec = tv.tv_usec * 1000; 51977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro } 52077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro#endif 52177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro endSec = ts->tv_sec + msec / 1000; 52277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro if (endSec >= 0x7fffffff) { 52377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro LOGV("NOTE: end time exceeds epoch\n"); 52477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro endSec = 0x7ffffffe; 52577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro } 52677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro ts->tv_sec = endSec; 52777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro ts->tv_nsec = (ts->tv_nsec + (msec % 1000) * 1000000) + nsec; 52877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro 52977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro /* catch rollover */ 53077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro if (ts->tv_nsec >= 1000000000L) { 53177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro ts->tv_sec++; 53277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro ts->tv_nsec -= 1000000000L; 53377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro } 53477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro} 53577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro 53677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro/* 537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Wait on a monitor until timeout, interrupt, or notification. Used for 538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.wait() and (somewhat indirectly) Thread.sleep() and Thread.join(). 539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If another thread calls Thread.interrupt(), we throw InterruptedException 541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and return immediately if one of the following are true: 542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - blocked in wait(), wait(long), or wait(long, int) methods of Object 543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - blocked in join(), join(long), or join(long, int) methods of Thread 544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - blocked in sleep(long), or sleep(long, int) methods of Thread 545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Otherwise, we set the "interrupted" flag. 546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Checks to make sure that "nsec" is in the range 0-999999 548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (i.e. fractions of a millisecond) and throws the appropriate 549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exception if it isn't. 550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The spec allows "spurious wakeups", and recommends that all code using 552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.wait() do so in a loop. This appears to derive from concerns 553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * about pthread_cond_wait() on multiprocessor systems. Some commentary 554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on the web casts doubt on whether these can/should occur. 555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Since we're allowed to wake up "early", we clamp extremely long durations 557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to return at the end of the 32-bit time epoch. 558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void waitMonitor(Thread* self, Monitor* mon, s8 msec, s4 nsec, 560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool interruptShouldThrow) 561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project struct timespec ts; 563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool wasInterrupted = false; 564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool timed; 56577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro int ret; 566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 56771938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro assert(self != NULL); 56871938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro assert(mon != NULL); 56971938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro 57094338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro /* Make sure that we hold the lock. */ 57171938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro if (mon->owner != self) { 572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ljava/lang/IllegalMonitorStateException;", 573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "object not locked by thread before wait()"); 574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Enforce the timeout range. 579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (msec < 0 || nsec < 0 || nsec > 999999) { 581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ljava/lang/IllegalArgumentException;", 582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "timeout arguments out of range"); 583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute absolute wakeup time, if necessary. 588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (msec == 0 && nsec == 0) { 590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project timed = false; 591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 59277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro absoluteTime(msec, nsec, &ts); 593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project timed = true; 594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add ourselves to the set of threads waiting on this monitor, and 598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * release our hold. We need to let it go even if we're a few levels 599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * deep in a recursive lock, and we need to restore that later. 600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 601142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro * We append to the wait set ahead of clearing the count and owner 602142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro * fields so the subroutine can check that the calling thread owns 603142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro * the monitor. Aside from that, the order of member updates is 604142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro * not order sensitive as we hold the pthread mutex. 605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 606142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro waitSetAppend(mon, self); 607142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro int prevLockCount = mon->lockCount; 608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon->lockCount = 0; 609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon->owner = NULL; 610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Update thread status. If the GC wakes up, it'll ignore us, knowing 613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that we won't touch any references in this state, and we'll check 614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * our suspend mode before we transition out. 615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (timed) 617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmChangeStatus(self, THREAD_TIMED_WAIT); 618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmChangeStatus(self, THREAD_WAIT); 620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 62177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro ret = pthread_mutex_lock(&self->waitMutex); 62277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro assert(ret == 0); 62377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro 624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 62577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * Set waitMonitor to the monitor object we will be waiting on. 62677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * When waitMonitor is non-NULL a notifying or interrupting thread 62777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * must signal the thread's waitCond to wake it up. 628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 62977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro assert(self->waitMonitor == NULL); 630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->waitMonitor = mon; 631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Handle the case where the thread was interrupted before we called 634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * wait(). 635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->interrupted) { 637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project wasInterrupted = true; 63877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro self->waitMonitor = NULL; 63977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro pthread_mutex_unlock(&self->waitMutex); 640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto done; 641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 64377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro /* 64477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * Release the monitor lock and wait for a notification or 64577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * a timeout to occur. 64677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro */ 64777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro pthread_mutex_unlock(&mon->lock); 64877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro 64977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro if (!timed) { 65077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro ret = pthread_cond_wait(&self->waitCond, &self->waitMutex); 65177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro assert(ret == 0); 65277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro } else { 653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef HAVE_TIMEDWAIT_MONOTONIC 65477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro ret = pthread_cond_timedwait_monotonic(&self->waitCond, &self->waitMutex, &ts); 655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else 65677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro ret = pthread_cond_timedwait(&self->waitCond, &self->waitMutex, &ts); 657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 65877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro assert(ret == 0 || ret == ETIMEDOUT); 65977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro } 66077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro if (self->interrupted) { 66177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro wasInterrupted = true; 662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 66477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro self->interrupted = false; 66577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro self->waitMonitor = NULL; 66677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro 66777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro pthread_mutex_unlock(&self->waitMutex); 66877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro 66930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro /* Reacquire the monitor lock. */ 67077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro lockMonitor(self, mon); 671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 672142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapirodone: 673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 67407b359273a838a15accafefcbe861be15caaac3aCarl Shapiro * We remove our thread from wait set after restoring the count 67507b359273a838a15accafefcbe861be15caaac3aCarl Shapiro * and owner fields so the subroutine can check that the calling 67607b359273a838a15accafefcbe861be15caaac3aCarl Shapiro * thread owns the monitor. Aside from that, the order of member 67707b359273a838a15accafefcbe861be15caaac3aCarl Shapiro * updates is not order sensitive as we hold the pthread mutex. 678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon->owner = self; 680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon->lockCount = prevLockCount; 68107b359273a838a15accafefcbe861be15caaac3aCarl Shapiro waitSetRemove(mon, self); 682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* set self->status back to THREAD_RUNNING, and self-suspend if needed */ 684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmChangeStatus(self, THREAD_RUNNING); 685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (wasInterrupted) { 687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We were interrupted while waiting, or somebody interrupted an 68930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * un-interruptible thread earlier and we're bailing out immediately. 690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The doc sayeth: "The interrupted status of the current thread is 692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * cleared when this exception is thrown." 693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interrupted = false; 695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (interruptShouldThrow) 696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ljava/lang/InterruptedException;", NULL); 697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Notify one thread waiting on this monitor. 702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void notifyMonitor(Thread* self, Monitor* mon) 704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 70577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro Thread* thread; 70677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro 70771938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro assert(self != NULL); 70871938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro assert(mon != NULL); 70971938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro 71094338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro /* Make sure that we hold the lock. */ 71171938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro if (mon->owner != self) { 712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ljava/lang/IllegalMonitorStateException;", 713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "object not locked by thread before notify()"); 714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 71630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro /* Signal the first waiting thread in the wait set. */ 71730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro while (mon->waitSet != NULL) { 71877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro thread = mon->waitSet; 71977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro mon->waitSet = thread->waitNext; 72077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro thread->waitNext = NULL; 72177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro pthread_mutex_lock(&thread->waitMutex); 72277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro /* Check to see if the thread is still waiting. */ 72377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro if (thread->waitMonitor != NULL) { 72477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro pthread_cond_signal(&thread->waitCond); 72530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro pthread_mutex_unlock(&thread->waitMutex); 72630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro return; 72777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro } 72877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro pthread_mutex_unlock(&thread->waitMutex); 729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Notify all threads waiting on this monitor. 734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void notifyAllMonitor(Thread* self, Monitor* mon) 736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 73777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro Thread* thread; 73877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro 73971938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro assert(self != NULL); 74071938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro assert(mon != NULL); 74171938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro 74294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro /* Make sure that we hold the lock. */ 74371938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro if (mon->owner != self) { 744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ljava/lang/IllegalMonitorStateException;", 745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "object not locked by thread before notifyAll()"); 746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 74877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro /* Signal all threads in the wait set. */ 74977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro while (mon->waitSet != NULL) { 75077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro thread = mon->waitSet; 75177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro mon->waitSet = thread->waitNext; 75277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro thread->waitNext = NULL; 75377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro pthread_mutex_lock(&thread->waitMutex); 75477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro /* Check to see if the thread is still waiting. */ 75577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro if (thread->waitMonitor != NULL) { 75677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro pthread_cond_signal(&thread->waitCond); 75777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro } 75877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro pthread_mutex_unlock(&thread->waitMutex); 759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Implements monitorenter for "synchronized" stuff. 764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This does not fail or throw an exception (unless deadlock prediction 766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is enabled and set to "err" mode). 767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmLockObject(Thread* self, Object *obj) 769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 7708d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro volatile u4 *thinp = &obj->lock; 7718d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro u4 hashState; 77294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro u4 thin; 773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 threadId = self->threadId; 77494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro Monitor *mon; 775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* First, try to grab the lock as if it's thin; 777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this is the common case and will usually succeed. 778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 77930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro hashState = LW_HASH_STATE(*thinp) << LW_HASH_STATE_SHIFT; 78094338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro thin = threadId << LW_LOCK_OWNER_SHIFT; 78130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro thin |= hashState; 782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!ATOMIC_CMP_SWAP((int32_t *)thinp, 78330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro hashState, 78494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro (int32_t)thin)) { 785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The lock is either a thin lock held by someone (possibly 'self'), 786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * or a fat lock. 787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 78894338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro if (LW_LOCK_OWNER(*thinp) == threadId) { 789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 'self' is already holding the thin lock; we can just 790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * bump the count. Atomic operations are not necessary 791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because only the thread holding the lock is allowed 792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to modify the Lock field. 793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 79494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro *thinp += 1 << LW_LOCK_COUNT_SHIFT; 795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* If this is a thin lock we need to spin on it, if it's fat 797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we need to acquire the monitor. 798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 79994338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro if (LW_SHAPE(*thinp) == LW_SHAPE_THIN) { 800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ThreadStatus oldStatus; 801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project static const unsigned long maxSleepDelay = 1 * 1024 * 1024; 802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project unsigned long sleepDelay; 803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOG_THIN("(%d) spin on lock 0x%08x: 0x%08x (0x%08x) 0x%08x\n", 805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project threadId, (uint)&obj->lock, 80630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro hashState, *thinp, thin); 807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The lock is still thin, but some other thread is 809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * holding it. Let the VM know that we're about 810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to wait on another thread. 811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oldStatus = dvmChangeStatus(self, THREAD_MONITOR); 813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Spin until the other thread lets go. 815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sleepDelay = 0; 817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project do { 818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* In addition to looking for an unlock, 819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we need to watch out for some other thread 820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * fattening the lock behind our back. 821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 82294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro while (LW_LOCK_OWNER(*thinp) != 0) { 82394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro if (LW_SHAPE(*thinp) == LW_SHAPE_FAT) { 824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The lock has been fattened already. 825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOG_THIN("(%d) lock 0x%08x surprise-fattened\n", 827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project threadId, (uint)&obj->lock); 828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmChangeStatus(self, oldStatus); 829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto fat_lock; 830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (sleepDelay == 0) { 833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sched_yield(); 834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sleepDelay = 1 * 1000; 835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project usleep(sleepDelay); 837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (sleepDelay < maxSleepDelay / 2) { 838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sleepDelay *= 2; 839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 84230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro hashState = LW_HASH_STATE(*thinp) << LW_HASH_STATE_SHIFT; 84394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro thin = threadId << LW_LOCK_OWNER_SHIFT; 84430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro thin |= hashState; 845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } while (!ATOMIC_CMP_SWAP((int32_t *)thinp, 84630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro (int32_t)hashState, 84794338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro (int32_t)thin)); 848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOG_THIN("(%d) spin on lock done 0x%08x: " 849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "0x%08x (0x%08x) 0x%08x\n", 850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project threadId, (uint)&obj->lock, 85130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro hashState, *thinp, thin); 852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* We've got the thin lock; let the VM know that we're 854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * done waiting. 855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmChangeStatus(self, oldStatus); 857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Fatten the lock. Note this relinquishes ownership. 859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We could also create the monitor in an "owned" state 860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to avoid "re-locking" it in fat_lock. 861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 86294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro mon = dvmCreateMonitor(obj); 8638d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro hashState = LW_HASH_STATE(*thinp) << LW_HASH_STATE_SHIFT; 8648d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro obj->lock = (u4)mon | hashState | LW_SHAPE_FAT; 865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOG_THIN("(%d) lock 0x%08x fattened\n", 866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project threadId, (uint)&obj->lock); 867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Fall through to acquire the newly fat lock. 869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The lock is already fat, which means 8738d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro * that obj->lock is a regular (Monitor *). 874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fat_lock: 8768d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro assert(LW_MONITOR(obj->lock) != NULL); 8778d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro lockMonitor(self, LW_MONITOR(obj->lock)); 878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // else, the lock was acquired with the ATOMIC_CMP_SWAP(). 881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION 883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See if we were allowed to grab the lock at this time. We do it 885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * *after* acquiring the lock, rather than before, so that we can 886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * freely update the Monitor struct. This seems counter-intuitive, 887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * but our goal is deadlock *prediction* not deadlock *prevention*. 888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (If we actually deadlock, the situation is easy to diagnose from 889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a thread dump, so there's no point making a special effort to do 890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the checks before the lock is held.) 891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This needs to happen before we add the object to the thread's 893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * monitor list, so we can tell the difference between first-lock and 894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * re-lock. 895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It's also important that we do this while in THREAD_RUNNING, so 897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that we don't interfere with cleanup operations in the GC. 898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.deadlockPredictMode != kDPOff) { 900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->status != THREAD_RUNNING) { 901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Bad thread status (%d) in DP\n", self->status); 902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDumpThread(self, false); 903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!dvmCheckException(self)); 906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project updateDeadlockPrediction(self, obj); 907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmCheckException(self)) { 908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we're throwing an exception here, we need to free the 910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * lock. We add the object to the thread's monitor list so the 911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "unlock" code can remove it. 912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAddToMonitorList(self, obj, false); 914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmUnlockObject(self, obj); 915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("--- unlocked, pending is '%s'\n", 916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmGetException(self)->clazz->descriptor); 917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add the locked object, and the current stack trace, to the list 922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * held by the Thread object. If deadlock prediction isn't on, 923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * don't capture the stack trace. 924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAddToMonitorList(self, obj, gDvm.deadlockPredictMode != kDPOff); 926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#elif defined(WITH_MONITOR_TRACKING) 927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add the locked object to the list held by the Thread object. 929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAddToMonitorList(self, obj, false); 931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Implements monitorexit for "synchronized" stuff. 936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On failure, throws an exception and returns "false". 938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmUnlockObject(Thread* self, Object *obj) 940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 9418d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro volatile u4 *thinp = &obj->lock; 942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 threadId = self->threadId; 94394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro u4 thin; 944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Check the common case, where 'self' has locked 'obj' once, first. 946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 94794338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro thin = *thinp; 94894338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro if (LW_LOCK_OWNER(thin) == threadId && LW_LOCK_COUNT(thin) == 0) { 949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Unlock 'obj' by clearing our threadId from 'thin'. 950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The lock protects the lock field itself, so it's 951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * safe to update non-atomically. 952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 95394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro *thinp &= (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT); 95494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro } else if (LW_SHAPE(*thinp) == LW_SHAPE_THIN) { 955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* If the object is locked, it had better be locked by us. 956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 95794338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro if (LW_LOCK_OWNER(*thinp) != threadId) { 958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* The JNI spec says that we should throw an exception 959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in this case. 960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //LOGW("Unlock thin %p: id %d vs %d\n", 962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // obj, (*thinp & 0xfff), threadId); 963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ljava/lang/IllegalMonitorStateException;", 964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "unlock of unowned monitor"); 965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* It's a thin lock, but 'self' has locked 'obj' 969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * more than once. Decrement the count. 970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 97194338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro *thinp -= 1 << LW_LOCK_COUNT_SHIFT; 972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* It's a fat lock. 974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 9758d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro assert(LW_MONITOR(obj->lock) != NULL); 9768d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro if (!unlockMonitor(self, LW_MONITOR(obj->lock))) { 977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* exception has been raised */ 978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_MONITOR_TRACKING 983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Remove the object from the Thread's list. 985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmRemoveFromMonitorList(self, obj); 987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.wait(). Also called for class init. 994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmObjectWait(Thread* self, Object *obj, s8 msec, s4 nsec, 996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool interruptShouldThrow) 997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 9988d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro Monitor* mon = LW_MONITOR(obj->lock); 9998d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro u4 hashState; 10008d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro u4 thin = obj->lock; 1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* If the lock is still thin, we need to fatten it. 1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 100494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro if (LW_SHAPE(thin) == LW_SHAPE_THIN) { 1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Make sure that 'self' holds the lock. 1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 100794338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro if (LW_LOCK_OWNER(thin) != self->threadId) { 1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ljava/lang/IllegalMonitorStateException;", 1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "object not locked by thread before wait()"); 1010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* This thread holds the lock. We need to fatten the lock 1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * so 'self' can block on it. Don't update the object lock 1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * field yet, because 'self' needs to acquire the lock before 1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * any other thread gets a chance. 1017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon = dvmCreateMonitor(obj); 1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 'self' has actually locked the object one or more times; 1021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * make sure that the monitor reflects this. 1022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lockMonitor(self, mon); 102494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro mon->lockCount = LW_LOCK_COUNT(thin); 1025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOG_THIN("(%d) lock 0x%08x fattened by wait() to count %d\n", 1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->threadId, (uint)&obj->lock, mon->lockCount); 1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1028581bed77d3596b9d7242da10867c8d4cfd382239Andy McFadden 1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Make the monitor public now that it's in the right state. 1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1031581bed77d3596b9d7242da10867c8d4cfd382239Andy McFadden MEM_BARRIER(); 10328d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro hashState = LW_HASH_STATE(thin) << LW_HASH_STATE_SHIFT; 10338d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro obj->lock = (u4)mon | hashState | LW_SHAPE_FAT; 1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project waitMonitor(self, mon, msec, nsec, interruptShouldThrow); 1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.notify(). 1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmObjectNotify(Thread* self, Object *obj) 1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 10448d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro u4 thin = obj->lock; 1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* If the lock is still thin, there aren't any waiters; 1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * waiting on an object forces lock fattening. 1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 104994338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro if (LW_SHAPE(thin) == LW_SHAPE_THIN) { 1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Make sure that 'self' holds the lock. 1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 105294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro if (LW_LOCK_OWNER(thin) != self->threadId) { 1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ljava/lang/IllegalMonitorStateException;", 1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "object not locked by thread before notify()"); 1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* no-op; there are no waiters to notify. 1059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* It's a fat lock. 1062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 106394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro notifyMonitor(self, LW_MONITOR(thin)); 1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.notifyAll(). 1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmObjectNotifyAll(Thread* self, Object *obj) 1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 10728d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro u4 thin = obj->lock; 1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* If the lock is still thin, there aren't any waiters; 1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * waiting on an object forces lock fattening. 1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 107794338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro if (LW_SHAPE(thin) == LW_SHAPE_THIN) { 1078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Make sure that 'self' holds the lock. 1079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 108094338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro if (LW_LOCK_OWNER(thin) != self->threadId) { 1081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ljava/lang/IllegalMonitorStateException;", 1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "object not locked by thread before notifyAll()"); 1083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 1084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* no-op; there are no waiters to notify. 1087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* It's a fat lock. 1090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 109194338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro notifyAllMonitor(self, LW_MONITOR(thin)); 1092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This implements java.lang.Thread.sleep(long msec, int nsec). 1097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The sleep is interruptible by other threads, which means we can't just 1099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * plop into an OS sleep call. (We probably could if we wanted to send 1100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * signals around and rely on EINTR, but that's inefficient and relies 1101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on native code respecting our signal mask.) 1102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We have to do all of this stuff for Object.wait() as well, so it's 1104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * easiest to just sleep on a private Monitor. 1105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It appears that we want sleep(0,0) to go through the motions of sleeping 1107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for a very short duration, rather than just returning. 1108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmThreadSleep(u8 msec, u4 nsec) 1110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self = dvmThreadSelf(); 1112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Monitor* mon = gDvm.threadSleepMon; 1113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* sleep(0,0) wakes up immediately, wait(0,0) means wait forever; adjust */ 1115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (msec == 0 && nsec == 0) 1116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project nsec++; 1117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lockMonitor(self, mon); 1119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project waitMonitor(self, mon, msec, nsec, true); 1120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project unlockMonitor(self, mon); 1121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Implement java.lang.Thread.interrupt(). 1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 112677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapirovoid dvmThreadInterrupt(Thread* thread) 1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 112877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro assert(thread != NULL); 112977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro 113077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro pthread_mutex_lock(&thread->waitMutex); 113177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro 113277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro /* 113377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * If the interrupted flag is already set no additional action is 113477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * required. 113577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro */ 113677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro if (thread->interrupted == true) { 113777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro pthread_mutex_unlock(&thread->waitMutex); 113877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro return; 113977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro } 114077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro 1141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Raise the "interrupted" flag. This will cause it to bail early out 1143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of the next wait() attempt, if it's not currently waiting on 1144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * something. 1145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project thread->interrupted = true; 1147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project MEM_BARRIER(); 1148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Is the thread waiting? 1151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note that fat vs. thin doesn't matter here; waitMonitor 1153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is only set when a thread actually waits on a monitor, 1154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * which implies that the monitor has already been fattened. 1155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 115677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro if (thread->waitMonitor != NULL) { 115777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro pthread_cond_signal(&thread->waitCond); 1158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 116077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro pthread_mutex_unlock(&thread->waitMutex); 1161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 116330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro#ifndef WITH_COPYING_GC 116494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapirou4 dvmIdentityHashCode(Object *obj) 116594338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro{ 116694338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro return (u4)obj; 116794338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro} 116830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro#else 116930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapirostatic size_t arrayElementWidth(const ArrayObject *array) 117030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro{ 117130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro const char *descriptor; 117230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro 117330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro if (dvmIsObjectArray(array)) { 117430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro return sizeof(Object *); 117530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } else { 117630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro descriptor = array->obj.clazz->descriptor; 117730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro switch (descriptor[1]) { 117830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro case 'B': return 1; /* byte */ 117930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro case 'C': return 2; /* char */ 118030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro case 'D': return 8; /* double */ 118130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro case 'F': return 4; /* float */ 118230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro case 'I': return 4; /* int */ 118330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro case 'J': return 8; /* long */ 118430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro case 'S': return 2; /* short */ 118530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro case 'Z': return 1; /* boolean */ 118630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } 118730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } 118830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro LOGE("object %p has an unhandled descriptor '%s'", array, descriptor); 118930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro dvmDumpThread(dvmThreadSelf(), false); 119030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro dvmAbort(); 119130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro return 0; /* Quiet the compiler. */ 119230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro} 119330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro 119430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapirostatic size_t arrayObjectLength(const ArrayObject *array) 119530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro{ 119630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro size_t length; 119730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro 119830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro length = offsetof(ArrayObject, contents); 119930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro length += array->length * arrayElementWidth(array); 120030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro return length; 120130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro} 120230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro 120330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro/* 120430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * Returns the identity hash code of the given object. 120530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */ 120630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapirou4 dvmIdentityHashCode(Object *obj) 120730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro{ 120830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro Thread *self, *thread; 120930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro volatile u4 *lw; 121030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro size_t length; 121130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro u4 lock, owner, hashState; 121230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro 121330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro if (obj == NULL) { 121430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro /* 121530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * Null is defined to have an identity hash code of 0. 121630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */ 121730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro return 0; 121830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } 121930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro lw = &obj->lock; 122030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiroretry: 122130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro hashState = LW_HASH_STATE(*lw); 122230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro if (hashState == LW_HASH_STATE_HASHED) { 122330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro /* 122430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * The object has been hashed but has not had its hash code 122530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * relocated by the garbage collector. Use the raw object 122630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * address. 122730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */ 122830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro return (u4)obj >> 3; 122930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } else if (hashState == LW_HASH_STATE_HASHED_AND_MOVED) { 123030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro /* 123130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * The object has been hashed and its hash code has been 123230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * relocated by the collector. Use the value of the naturally 123330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * aligned word following the instance data. 123430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */ 123530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISARRAY)) { 123630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro length = arrayObjectLength((ArrayObject *)obj); 123730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro length = (length + 3) & ~3; 123830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } else { 123930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro length = obj->clazz->objectSize; 124030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } 124130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro return *(u4 *)(((char *)obj) + length); 124230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } else if (hashState == LW_HASH_STATE_UNHASHED) { 124330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro /* 124430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * The object has never been hashed. Change the hash state to 124530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * hashed and use the raw object address. 124630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */ 124730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro self = dvmThreadSelf(); 124830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro if (self->threadId == lockOwner(obj)) { 124930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro /* 125030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * We already own the lock so we can update the hash state 125130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * directly. 125230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */ 125330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro *lw |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT); 125430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro return (u4)obj >> 3; 125530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } 125630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro /* 125730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * We do not own the lock. Try acquiring the lock. Should 125830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * this fail, we must suspend the owning thread. 125930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */ 126030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro if (LW_SHAPE(*lw) == LW_SHAPE_THIN) { 126130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro /* 126230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * If the lock is thin assume it is unowned. We simulate 126330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * an acquire, update, and release with a single CAS. 126430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */ 126530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro lock = DVM_LOCK_INITIAL_THIN_VALUE; 126630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro lock |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT); 126730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro if (ATOMIC_CMP_SWAP((int32_t *)lw, 126830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro (int32_t)DVM_LOCK_INITIAL_THIN_VALUE, 126930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro (int32_t)lock)) { 127030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro /* 127130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * A new lockword has been installed with a hash state 127230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * of hashed. Use the raw object address. 127330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */ 127430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro return (u4)obj >> 3; 127530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } 127630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } else { 127730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro if (tryLockMonitor(self, LW_MONITOR(*lw))) { 127830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro /* 127930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * The monitor lock has been acquired. Change the 128030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * hash state to hashed and use the raw object 128130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * address. 128230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */ 128330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro *lw |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT); 128430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro unlockMonitor(self, LW_MONITOR(*lw)); 128530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro return (u4)obj >> 3; 128630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } 128730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } 128830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro /* 128930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * At this point we have failed to acquire the lock. We must 129030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * identify the owning thread and suspend it. 129130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */ 129230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro dvmLockThreadList(self); 129330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro /* 129430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * Cache the lock word as its value can change between 129530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * determining its shape and retrieving its owner. 129630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */ 129730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro lock = *lw; 129830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro if (LW_SHAPE(lock) == LW_SHAPE_THIN) { 129930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro /* 130030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * Find the thread with the corresponding thread id. 130130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */ 130230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro owner = LW_LOCK_OWNER(lock); 130330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro assert(owner != self->threadId); 130430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro /* 130530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * If the lock has no owner do not bother scanning the 130630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * thread list and fall through to the failure handler. 130730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */ 130830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro thread = owner ? gDvm.threadList : NULL; 130930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro while (thread != NULL) { 131030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro if (thread->threadId == owner) { 131130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro break; 131230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } 131330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro thread = thread->next; 131430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } 131530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } else { 131630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro thread = LW_MONITOR(lock)->owner; 131730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } 131830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro /* 131930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * If thread is NULL the object has been released since the 132030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * thread list lock was acquired. Try again. 132130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */ 132230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro if (thread == NULL) { 132330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro dvmUnlockThreadList(); 132430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro goto retry; 132530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } 132630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro /* 132730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * Wait for the owning thread to suspend. 132830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */ 132930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro dvmSuspendThread(thread); 133030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro if (dvmHoldsLock(thread, obj)) { 133130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro /* 133230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * The owning thread has been suspended. We can safely 133330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * change the hash state to hashed. 133430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */ 133530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro *lw |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT); 133630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro dvmResumeThread(thread); 133730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro dvmUnlockThreadList(); 133830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro return (u4)obj >> 3; 133930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } 134030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro /* 134130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * The wrong thread has been suspended. Try again. 134230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */ 134330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro dvmResumeThread(thread); 134430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro dvmUnlockThreadList(); 134530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro goto retry; 134630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro } 134730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro LOGE("object %p has an unknown hash state %#x", obj, hashState); 134830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro dvmDumpThread(dvmThreadSelf(), false); 134930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro dvmAbort(); 135030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro return 0; /* Quiet the compiler. */ 135130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro} 135230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro#endif /* WITH_COPYING_GC */ 1353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION 1355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * =========================================================================== 1357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Deadlock prediction 1358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * =========================================================================== 1359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe idea is to predict the possibility of deadlock by recording the order 1362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectin which monitors are acquired. If we see an attempt to acquire a lock 1363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectout of order, we can identify the locks and offending code. 1364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectTo make this work, we need to keep track of the locks held by each thread, 1366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectand create history trees for each lock. When a thread tries to acquire 1367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecta new lock, we walk through the "history children" of the lock, looking 1368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfor a match with locks the thread already holds. If we find a match, 1369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectit means the thread has made a request that could result in a deadlock. 1370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectTo support recursive locks, we always allow re-locking a currently-held 1372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectlock, and maintain a recursion depth count. 1373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectAn ASCII-art example, where letters represent Objects: 1375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project A 1377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /|\ 1378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project / | \ 1379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project B | D 1380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project \ | 1381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project \| 1382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project C 1383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe above is the tree we'd have after handling Object synchronization 1385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsequences "ABC", "AC", "AD". A has three children, {B, C, D}. C is also 1386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecta child of B. (The lines represent pointers between parent and child. 1387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectEvery node can have multiple parents and multiple children.) 1388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectIf we hold AC, and want to lock B, we recursively search through B's 1390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchildren to see if A or C appears. It does, so we reject the attempt. 1391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project(A straightforward way to implement it: add a link from C to B, then 1392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectdetermine whether the graph starting at B contains a cycle.) 1393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectIf we hold AC and want to lock D, we would succeed, creating a new link 1395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfrom C to D. 1396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe lock history and a stack trace is attached to the Object's Monitor 1398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstruct, which means we need to fatten every Object we lock (thin locking 1399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectis effectively disabled). If we don't need the stack trace we can 1400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectavoid fattening the leaf nodes, only fattening objects that need to hold 1401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecthistory trees. 1402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectUpdates to Monitor structs are only allowed for the thread that holds 1404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe Monitor, so we actually do most of our deadlock prediction work after 1405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe lock has been acquired. 1406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectWhen an object with a monitor is GCed, we need to remove it from the 1408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecthistory trees. There are two basic approaches: 1409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (1) For through the entire set of known monitors, search all child 1410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lists for the object in question. This is rather slow, resulting 1411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project in GC passes that take upwards of 10 seconds to complete. 1412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (2) Maintain "parent" pointers in each node. Remove the entries as 1413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project required. This requires additional storage and maintenance for 1414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project every operation, but is significantly faster at GC time. 1415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectFor each GCed object, we merge all of the object's children into each of 1416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe object's parents. 1417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/ 1418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(WITH_MONITOR_TRACKING) 1420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# error "WITH_DEADLOCK_PREDICTION requires WITH_MONITOR_TRACKING" 1421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 1422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clear out the contents of an ExpandingObjectList, freeing any 1425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * dynamic allocations. 1426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void expandObjClear(ExpandingObjectList* pList) 1428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pList->list != NULL) { 1430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pList->list); 1431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pList->list = NULL; 1432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pList->alloc = pList->count = 0; 1434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the number of objects currently stored in the list. 1438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline int expandBufGetCount(const ExpandingObjectList* pList) 1440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return pList->count; 1442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the Nth entry from the list. 1446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline Object* expandBufGetEntry(const ExpandingObjectList* pList, 1448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i) 1449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return pList->list[i]; 1451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add a new entry to the list. 1455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We don't check for or try to enforce uniqueness. It's expected that 1457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the higher-level code does this for us. 1458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void expandObjAddEntry(ExpandingObjectList* pList, Object* obj) 1460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pList->count == pList->alloc) { 1462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* time to expand */ 1463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object** newList; 1464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pList->alloc == 0) 1466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pList->alloc = 4; 1467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 1468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pList->alloc *= 2; 1469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("expanding %p to %d\n", pList, pList->alloc); 1470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newList = realloc(pList->list, pList->alloc * sizeof(Object*)); 1471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (newList == NULL) { 1472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Failed expanding DP object list (alloc=%d)\n", pList->alloc); 1473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 1474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pList->list = newList; 1476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pList->list[pList->count++] = obj; 1479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if the element was successfully removed. 1483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool expandObjRemoveEntry(ExpandingObjectList* pList, Object* obj) 1485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i; 1487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = pList->count-1; i >= 0; i--) { 1489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pList->list[i] == obj) 1490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (i < 0) 1493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 1494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (i != pList->count-1) { 1496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The order of elements is not important, so we just copy the 1498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * last entry into the new slot. 1499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //memmove(&pList->list[i], &pList->list[i+1], 1501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // (pList->count-1 - i) * sizeof(pList->list[0])); 1502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pList->list[i] = pList->list[pList->count-1]; 1503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pList->count--; 1506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pList->list[pList->count] = (Object*) 0xdecadead; 1507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 1508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if "obj" appears in the list. 1512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool expandObjHas(const ExpandingObjectList* pList, Object* obj) 1514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i; 1516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0; i < pList->count; i++) { 1518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pList->list[i] == obj) 1519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 1520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 1522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the list contents to stdout. For debugging. 1526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void expandObjDump(const ExpandingObjectList* pList) 1528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i; 1530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0; i < pList->count; i++) 1531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project printf(" %p", pList->list[i]); 1532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Check for duplicate entries. Returns the index of the first instance 1536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of the duplicated value, or -1 if no duplicates were found. 1537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int expandObjCheckForDuplicates(const ExpandingObjectList* pList) 1539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i, j; 1541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0; i < pList->count-1; i++) { 1542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (j = i + 1; j < pList->count; j++) { 1543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pList->list[i] == pList->list[j]) { 1544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return i; 1545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -1; 1550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine whether "child" appears in the list of objects associated 1555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * with the Monitor in "parent". If "parent" is a thin lock, we return 1556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * false immediately. 1557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool objectInChildList(const Object* parent, Object* child) 1559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 15608d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro u4 lock = parent->lock; 1561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!IS_LOCK_FAT(&lock)) { 1562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //LOGI("on thin\n"); 1563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 1564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 15668d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro return expandObjHas(&LW_MONITOR(lock)->historyChildren, child); 1567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the child list. 1571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void dumpKids(Object* parent) 1573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 15748d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro Monitor* mon = LW_MONITOR(parent->lock); 1575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project printf("Children of %p:", parent); 1577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project expandObjDump(&mon->historyChildren); 1578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project printf("\n"); 1579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add "child" to the list of children in "parent", and add "parent" to 1583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the list of parents in "child". 1584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void linkParentToChild(Object* parent, Object* child) 1586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 15878d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro //assert(LW_MONITOR(parent->lock)->owner == dvmThreadSelf()); // !owned for merge 1588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(IS_LOCK_FAT(&parent->lock)); 1589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(IS_LOCK_FAT(&child->lock)); 1590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(parent != child); 1591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Monitor* mon; 1592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 15938d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro mon = LW_MONITOR(parent->lock); 1594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!expandObjHas(&mon->historyChildren, child)); 1595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project expandObjAddEntry(&mon->historyChildren, child); 1596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 15978d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro mon = LW_MONITOR(child->lock); 1598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!expandObjHas(&mon->historyParents, parent)); 1599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project expandObjAddEntry(&mon->historyParents, parent); 1600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Remove "child" from the list of children in "parent". 1605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void unlinkParentFromChild(Object* parent, Object* child) 1607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 16088d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro //assert(LW_MONITOR(parent->lock)->owner == dvmThreadSelf()); // !owned for GC 1609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(IS_LOCK_FAT(&parent->lock)); 1610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(IS_LOCK_FAT(&child->lock)); 1611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(parent != child); 1612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Monitor* mon; 1613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 16148d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro mon = LW_MONITOR(parent->lock); 1615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!expandObjRemoveEntry(&mon->historyChildren, child)) { 1616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("WARNING: child %p not found in parent %p\n", child, parent); 1617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!expandObjHas(&mon->historyChildren, child)); 1619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(expandObjCheckForDuplicates(&mon->historyChildren) < 0); 1620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 16218d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro mon = LW_MONITOR(child->lock); 1622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!expandObjRemoveEntry(&mon->historyParents, parent)) { 1623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("WARNING: parent %p not found in child %p\n", parent, child); 1624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!expandObjHas(&mon->historyParents, parent)); 1626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(expandObjCheckForDuplicates(&mon->historyParents) < 0); 1627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Log the monitors held by the current thread. This is done as part of 1632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * flagging an error. 1633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void logHeldMonitors(Thread* self) 1635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* name = NULL; 1637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project name = dvmGetThreadName(self); 1639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("Monitors currently held by thread (threadid=%d '%s')\n", 1640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->threadId, name); 1641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("(most-recently-acquired on top):\n"); 1642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(name); 1643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LockedObjectData* lod = self->pLockedObjects; 1645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (lod != NULL) { 1646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("--- object %p[%d] (%s)\n", 1647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lod->obj, lod->recursionCount, lod->obj->clazz->descriptor); 1648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLogRawStackTrace(lod->rawStackTrace, lod->stackDepth); 1649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lod = lod->next; 1651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Recursively traverse the object hierarchy starting at "obj". We mark 1656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ourselves on entry and clear the mark on exit. If we ever encounter 1657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a marked object, we have a cycle. 1658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if all is well, "false" if we found a cycle. 1660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool traverseTree(Thread* self, const Object* obj) 1662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(IS_LOCK_FAT(&obj->lock)); 16648d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro Monitor* mon = LW_MONITOR(obj->lock); 1665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Have we been here before? 1668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (mon->historyMark) { 1670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int* rawStackTrace; 1671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int stackDepth; 1672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("%s\n", kStartBanner); 1674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("Illegal lock attempt:\n"); 1675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("--- object %p (%s)\n", obj, obj->clazz->descriptor); 1676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project rawStackTrace = dvmFillInStackTraceRaw(self, &stackDepth); 1678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLogRawStackTrace(rawStackTrace, stackDepth); 1679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(rawStackTrace); 1680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW(" "); 1682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project logHeldMonitors(self); 1683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW(" "); 1685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("Earlier, the following lock order (from last to first) was\n"); 1686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("established -- stack trace is from first successful lock):\n"); 1687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 1688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon->historyMark = true; 1690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Examine the children. We do NOT hold these locks, so they might 1693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * very well transition from thin to fat or change ownership while 1694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we work. 1695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: we rely on the fact that they cannot revert from fat to thin 1697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * while we work. This is currently a safe assumption. 1698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We can safely ignore thin-locked children, because by definition 1700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * they have no history and are leaf nodes. In the current 1701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * implementation we always fatten the locks to provide a place to 1702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * hang the stack trace. 1703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ExpandingObjectList* pList = &mon->historyChildren; 1705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i; 1706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = expandBufGetCount(pList)-1; i >= 0; i--) { 1707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const Object* child = expandBufGetEntry(pList, i); 17088d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro u4 lock = child->lock; 1709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!IS_LOCK_FAT(&lock)) 1710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project continue; 1711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!traverseTree(self, child)) { 1712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("--- object %p (%s)\n", obj, obj->clazz->descriptor); 1713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLogRawStackTrace(mon->historyRawStackTrace, 1714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon->historyStackDepth); 1715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon->historyMark = false; 1716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 1717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon->historyMark = false; 1721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 1723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Update the deadlock prediction tree, based on the current thread 1727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * acquiring "acqObj". This must be called before the object is added to 1728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the thread's list of held monitors. 1729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the thread already holds the lock (recursion), or this is a known 1731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * lock configuration, we return without doing anything. Otherwise, we add 1732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a link from the most-recently-acquired lock in this thread to "acqObj" 1733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * after ensuring that the parent lock is "fat". 1734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This MUST NOT be called while a GC is in progress in another thread, 1736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because we assume exclusive access to history trees in owned monitors. 1737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void updateDeadlockPrediction(Thread* self, Object* acqObj) 1739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LockedObjectData* lod; 1741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LockedObjectData* mrl; 1742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Quick check for recursive access. 1745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lod = dvmFindInMonitorList(self, acqObj); 1747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (lod != NULL) { 1748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("+++ DP: recursive %p\n", acqObj); 1749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 1750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Make the newly-acquired object's monitor "fat". In some ways this 1754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * isn't strictly necessary, but we need the GC to tell us when 1755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "interesting" objects go away, and right now the only way to make 1756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an object look interesting is to give it a monitor. 1757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This also gives us a place to hang a stack trace. 1759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Our thread holds the lock, so we're allowed to rewrite the lock 1761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * without worrying that something will change out from under us. 1762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!IS_LOCK_FAT(&acqObj->lock)) { 1764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("fattening lockee %p (recur=%d)\n", 176594338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro acqObj, LW_LOCK_COUNT(acqObj->lock.thin)); 1766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Monitor* newMon = dvmCreateMonitor(acqObj); 1767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lockMonitor(self, newMon); // can't stall, don't need VMWAIT 17688d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro newMon->lockCount += LW_LOCK_COUNT(acqObj->lock); 17698d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro u4 hashState = LW_HASH_STATE(acqObj->lock) << LW_HASH_STATE_SHIFT; 17708d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro acqObj->lock = (u4)newMon | hashState | LW_SHAPE_FAT; 1771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* if we don't have a stack trace for this monitor, establish one */ 17748d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro if (LW_MONITOR(acqObj->lock)->historyRawStackTrace == NULL) { 17758d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro Monitor* mon = LW_MONITOR(acqObj->lock); 1776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon->historyRawStackTrace = dvmFillInStackTraceRaw(self, 1777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project &mon->historyStackDepth); 1778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We need to examine and perhaps modify the most-recently-locked 1782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * monitor. We own that, so there's no risk of another thread 1783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * stepping on us. 1784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Retrieve the most-recently-locked entry from our thread. 1786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mrl = self->pLockedObjects; 1788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (mrl == NULL) 1789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; /* no other locks held */ 1790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Do a quick check to see if "acqObj" is a direct descendant. We can do 1793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this without holding the global lock because of our assertion that 1794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a GC is not running in parallel -- nobody except the GC can 1795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * modify a history list in a Monitor they don't own, and we own "mrl". 1796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (There might be concurrent *reads*, but no concurrent *writes.) 1797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we find it, this is a known good configuration, and we're done. 1799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (objectInChildList(mrl->obj, acqObj)) 1801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 1802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "mrl" is going to need to have a history tree. If it's currently 1805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a thin lock, we make it fat now. The thin lock might have a 1806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * nonzero recursive lock count, which we need to carry over. 1807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Our thread holds the lock, so we're allowed to rewrite the lock 1809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * without worrying that something will change out from under us. 1810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!IS_LOCK_FAT(&mrl->obj->lock)) { 1812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("fattening parent %p f/b/o child %p (recur=%d)\n", 18138d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro mrl->obj, acqObj, LW_LOCK_COUNT(mrl->obj->lock)); 1814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Monitor* newMon = dvmCreateMonitor(mrl->obj); 1815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lockMonitor(self, newMon); // can't stall, don't need VMWAIT 18168d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro newMon->lockCount += LW_LOCK_COUNT(mrl->obj->lock); 18178d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro u4 hashState = LW_HASH_STATE(mrl->obj->lock) << LW_HASH_STATE_SHIFT; 18188d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro mrl->obj->lock = (u4)newMon | hashState | LW_SHAPE_FAT; 1819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We haven't seen this configuration before. We need to scan down 1823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * acqObj's tree to see if any of the monitors in self->pLockedObjects 1824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * appear. We grab a global lock before traversing or updating the 1825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * history list. 1826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we find a match for any of our held locks, we know that the lock 1828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * has previously been acquired *after* acqObj, and we throw an error. 1829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The easiest way to do this is to create a link from "mrl" to "acqObj" 1831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and do a recursive traversal, marking nodes as we cross them. If 1832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we cross one a second time, we have a cycle and can throw an error. 1833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (We do the flag-clearing traversal before adding the new link, so 1834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that we're guaranteed to terminate.) 1835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "acqObj" is a thin lock, it has no history, and we can create a 1837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * link to it without additional checks. [ We now guarantee that it's 1838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * always fat. ] 1839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool failed = false; 1841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLockMutex(&gDvm.deadlockHistoryLock); 1842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project linkParentToChild(mrl->obj, acqObj); 1843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!traverseTree(self, acqObj)) { 1844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("%s\n", kEndBanner); 1845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project failed = true; 1846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* remove the entry so we're still okay when in "warning" mode */ 1848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project unlinkParentFromChild(mrl->obj, acqObj); 1849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmUnlockMutex(&gDvm.deadlockHistoryLock); 1851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (failed) { 1853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (gDvm.deadlockPredictMode) { 1854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case kDPErr: 1855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ldalvik/system/PotentialDeadlockError;", NULL); 1856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case kDPAbort: 1858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Aborting due to potential deadlock\n"); 1859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 1860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project default: 1862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* warn only */ 1863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're removing "child" from existence. We want to pull all of 1870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * child's children into "parent", filtering out duplicates. This is 1871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * called during the GC. 1872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This does not modify "child", which might have multiple parents. 1874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void mergeChildren(Object* parent, const Object* child) 1876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Monitor* mon; 1878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i; 1879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(IS_LOCK_FAT(&child->lock)); 18818d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro mon = LW_MONITOR(child->lock); 1882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ExpandingObjectList* pList = &mon->historyChildren; 1883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = expandBufGetCount(pList)-1; i >= 0; i--) { 1885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* grandChild = expandBufGetEntry(pList, i); 1886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!objectInChildList(parent, grandChild)) { 1888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("+++ migrating %p link to %p\n", grandChild, parent); 1889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project linkParentToChild(parent, grandChild); 1890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("+++ parent %p already links to %p\n", parent, grandChild); 1892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * An object with a fat lock is being collected during a GC pass. We 1898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * want to remove it from any lock history trees that it is a part of. 1899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This may require updating the history trees in several monitors. The 1901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * monitor semantics guarantee that no other thread will be accessing 1902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the history trees at the same time. 1903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void removeCollectedObject(Object* obj) 1905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Monitor* mon; 1907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("+++ collecting %p\n", obj); 1909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0 1911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're currently running through the entire set of known monitors. 1913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This can be somewhat slow. We may want to keep lists of parents 1914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in each child to speed up GC. 1915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon = gDvm.monitorList; 1917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (mon != NULL) { 1918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* parent = mon->obj; 1919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (parent != NULL) { /* value nulled for deleted entries */ 1920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (objectInChildList(parent, obj)) { 1921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("removing child %p from parent %p\n", obj, parent); 1922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project unlinkParentFromChild(parent, obj); 1923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mergeChildren(parent, obj); 1924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mon = mon->next; 1927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 1929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For every parent of this object: 1932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - merge all of our children into the parent's child list (creates 1933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a two-way link between parent and child) 1934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - remove ourselves from the parent's child list 1935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ExpandingObjectList* pList; 1937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i; 1938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(IS_LOCK_FAT(&obj->lock)); 19408d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro mon = LW_MONITOR(obj->lock); 1941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pList = &mon->historyParents; 1942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = expandBufGetCount(pList)-1; i >= 0; i--) { 1943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* parent = expandBufGetEntry(pList, i); 19448d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro Monitor* parentMon = LW_MONITOR(parent->lock); 1945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!expandObjRemoveEntry(&parentMon->historyChildren, obj)) { 1947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("WARNING: child %p not found in parent %p\n", obj, parent); 1948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!expandObjHas(&parentMon->historyChildren, obj)); 1950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mergeChildren(parent, obj); 1952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For every child of this object: 1956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - remove ourselves from the child's parent list 1957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pList = &mon->historyChildren; 1959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = expandBufGetCount(pList)-1; i >= 0; i--) { 1960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* child = expandBufGetEntry(pList, i); 19618d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro Monitor* childMon = LW_MONITOR(child->lock); 1962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!expandObjRemoveEntry(&childMon->historyParents, obj)) { 1964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("WARNING: parent %p not found in child %p\n", obj, child); 1965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!expandObjHas(&childMon->historyParents, obj)); 1967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif /*WITH_DEADLOCK_PREDICTION*/ 1971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1972