Sync.cpp revision 953a0ed4e507fd6e756aa3e5c671bee80d7e9b3e
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
36f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro#include <fcntl.h>
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <unistd.h>
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <pthread.h>
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <time.h>
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/time.h>
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <errno.h>
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define LOG_THIN    LOGV
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION     /* fwd */
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic const char* kStartBanner =
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#";
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic const char* kEndBanner =
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#->";
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unsorted, expanding list of objects.
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is very similar to PointerSet (which came into existence after this),
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * but these are unsorted, uniqueness is not enforced by the "add" function,
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and the base object isn't allocated on the heap.
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct ExpandingObjectList {
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u2          alloc;
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u2          count;
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object**    list;
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} ExpandingObjectList;
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* fwd */
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void updateDeadlockPrediction(Thread* self, Object* obj);
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void removeCollectedObject(Object* obj);
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void expandObjClear(ExpandingObjectList* pList);
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Every Object has a monitor associated with it, but not every Object is
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * actually locked.  Even the ones that are locked do not need a
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * full-fledged monitor until a) there is actual contention or b) wait()
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is called on the Object.
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For Dalvik, we have implemented a scheme similar to the one described
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in Bacon et al.'s "Thin locks: featherweight synchronization for Java"
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (ACM 1998).  Things are even easier for us, though, because we have
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a full 32 bits to work with.
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * The two states of an Object's lock are referred to as "thin" and
8394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * "fat".  A lock may transition from the "thin" state to the "fat"
8494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * state and this transition is referred to as inflation.  Once a lock
8594338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * has been inflated it remains in the "fat" state indefinitely.
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * The lock value itself is stored in Object.lock.  The LSB of the
8877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * lock encodes its state.  When cleared, the lock is in the "thin"
8977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * state and its bits are formatted as follows:
9071938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro *
9194338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro *    [31 ---- 19] [18 ---- 3] [2 ---- 1] [0]
9294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro *     lock count   thread id  hash state  0
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
9477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * When set, the lock is in the "fat" state and its bits are formatted
9594338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * as follows:
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
9794338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro *    [31 ---- 3] [2 ---- 1] [0]
9894338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro *      pointer   hash state  1
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For an in-depth description of the mechanics of thin-vs-fat locking,
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * read the paper referred to above.
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Monitors provide:
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - mutually exclusive access to resources
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - a way for multiple threads to wait for notification
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In effect, they fill the role of both mutexes and condition variables.
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Only one thread can own the monitor at any time.  There may be several
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * threads waiting on it (the wait call unlocks it).  One or more waiting
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * threads may be getting interrupted or notified at any given time.
114fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro *
115fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro * TODO: the various members of monitor are not SMP-safe.
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstruct Monitor {
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread*     owner;          /* which thread currently owns the lock? */
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int         lockCount;      /* owner's recursive lock depth */
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object*     obj;            /* what object are we part of [debug only] */
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
12277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    Thread*     waitSet;	/* threads currently waiting on this monitor */
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pthread_mutex_t lock;
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor*    next;
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
128fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    /*
129fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro     * Who last acquired this monitor, when lock sampling is enabled.
130fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro     * Even when enabled, ownerFileName may be NULL.
131fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro     */
132fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    char*       ownerFileName;
133fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    u4          ownerLineNumber;
134fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Objects that have been locked immediately after this one in the
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * past.  We use an expanding flat array, allocated on first use, to
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * minimize allocations.  Deletions from the list, expected to be
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * infrequent, are crunched down.
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandingObjectList historyChildren;
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We also track parents.  This isn't strictly necessary, but it makes
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the cleanup at GC time significantly faster.
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandingObjectList historyParents;
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* used during cycle detection */
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool        historyMark;
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* stack trace, established the first time we locked the object */
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int         historyStackDepth;
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int*        historyRawStackTrace;
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project};
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create and initialize a monitor.
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectMonitor* dvmCreateMonitor(Object* obj)
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon = (Monitor*) calloc(1, sizeof(Monitor));
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon == NULL) {
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Unable to allocate monitor\n");
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
17294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    if (((u4)mon & 7) != 0) {
17394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        LOGE("Misaligned monitor: %p\n", mon);
17494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        dvmAbort();
17594338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    }
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->obj = obj;
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmInitMutex(&mon->lock);
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* replace the head of the list with the new monitor */
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    do {
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->next = gDvm.monitorList;
1826e10b9aaa72425a4825a25f0043533d0c6fdbba4Andy McFadden    } while (android_atomic_release_cas((int32_t)mon->next, (int32_t)mon,
1836e10b9aaa72425a4825a25f0043533d0c6fdbba4Andy McFadden            (int32_t*)(void*)&gDvm.monitorList) != 0);
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return mon;
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free the monitor list.  Only used when shutting the VM down.
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmFreeMonitorList(void)
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* nextMon;
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon = gDvm.monitorList;
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (mon != NULL) {
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        nextMon = mon->next;
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        expandObjClear(&mon->historyChildren);
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        expandObjClear(&mon->historyParents);
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(mon->historyRawStackTrace);
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(mon);
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon = nextMon;
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Log some info about our monitors.
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpMonitorInfo(const char* msg)
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if QUIET_ZYGOTE_MONITOR
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.zygote) {
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int totalCount;
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int liveCount;
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    totalCount = liveCount = 0;
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon = gDvm.monitorList;
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (mon != NULL) {
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        totalCount++;
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (mon->obj != NULL)
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            liveCount++;
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon = mon->next;
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGD("%s: monitor list has %d entries (%d live)\n",
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        msg, totalCount, liveCount);
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the object that a monitor is part of.
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectObject* dvmGetMonitorObject(Monitor* mon)
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon == NULL)
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return mon->obj;
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
24930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * Returns the thread id of the thread owning the given lock.
25030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */
25130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapirostatic u4 lockOwner(Object* obj)
25230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro{
25330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    Thread *owner;
25430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    u4 lock;
25530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro
25630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    assert(obj != NULL);
25730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    /*
25830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro     * Since we're reading the lock value multiple times, latch it so
25930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro     * that it doesn't change out from under us if we get preempted.
26030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro     */
26130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    lock = obj->lock;
26230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    if (LW_SHAPE(lock) == LW_SHAPE_THIN) {
26330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        return LW_LOCK_OWNER(lock);
26430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    } else {
26530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        owner = LW_MONITOR(lock)->owner;
26630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        return owner ? owner->threadId : 0;
26730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    }
26830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro}
26930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro
27030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro/*
271fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * Get the thread that holds the lock on the specified object.  The
272fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * object may be unlocked, thin-locked, or fat-locked.
273fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden *
274fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * The caller must lock the thread list before calling here.
275fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden */
276fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFaddenThread* dvmGetObjectLockHolder(Object* obj)
277fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden{
278fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    u4 threadId = lockOwner(obj);
279fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden
280fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    if (threadId == 0)
281fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden        return NULL;
282fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    return dvmGetThreadByThreadId(threadId);
283fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden}
284fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden
285fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden/*
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Checks whether the given thread holds the given
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * objects's lock.
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmHoldsLock(Thread* thread, Object* obj)
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (thread == NULL || obj == NULL) {
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
29430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        return thread->threadId == lockOwner(obj);
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free the monitor associated with an object and make the object's lock
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * thin again.  This is called during garbage collection.
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3025a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapirostatic void freeObjectMonitor(Object* obj)
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor *mon;
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3065a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    assert(LW_SHAPE(obj->lock) == LW_SHAPE_FAT);
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.deadlockPredictMode != kDPOff)
3105a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro        removeCollectedObject(obj);
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3135a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    mon = LW_MONITOR(obj->lock);
3145a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    obj->lock = DVM_LOCK_INITIAL_THIN_VALUE;
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* This lock is associated with an object
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that's being swept.  The only possible way
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * anyone could be holding this lock would be
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * if some JNI code locked but didn't unlock
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the object, in which case we've got some bad
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * native code somewhere.
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3231ff876da3c8316ebe4a39e29b5db697953421511Carl Shapiro    assert(pthread_mutex_trylock(&mon->lock) == 0);
3241ff876da3c8316ebe4a39e29b5db697953421511Carl Shapiro    assert(pthread_mutex_unlock(&mon->lock) == 0);
325980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro    dvmDestroyMutex(&mon->lock);
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
3275a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    expandObjClear(&mon->historyChildren);
3285a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    expandObjClear(&mon->historyParents);
3295a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    free(mon->historyRawStackTrace);
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
3315a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    free(mon);
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3345a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro/*
3355a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro * Frees monitor objects belonging to unmarked objects.
3365a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro */
3375a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapirovoid dvmSweepMonitorList(Monitor** mon, int (*isUnmarkedObject)(void*))
3385a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro{
3395a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    Monitor handle;
3405a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    Monitor *prev, *curr;
3415a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    Object *obj;
3425a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro
3435a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    assert(mon != NULL);
3445a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    assert(isUnmarkedObject != NULL);
3458881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro#ifdef WITH_DEADLOCK_PREDICTION
3468881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro    dvmDumpMonitorInfo("before monitor sweep");
3478881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro#endif
3485a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    prev = &handle;
3495a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    prev->next = curr = *mon;
3505a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    while (curr != NULL) {
3515a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro        obj = curr->obj;
3525a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro        if (obj != NULL && (*isUnmarkedObject)(obj) != 0) {
3535a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro            prev->next = curr = curr->next;
3545a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro            freeObjectMonitor(obj);
3555a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro        } else {
3565a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro            prev = curr;
3575a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro            curr = curr->next;
3585a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro        }
3595a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    }
3605a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    *mon = handle.next;
3618881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro#ifdef WITH_DEADLOCK_PREDICTION
3628881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro    dvmDumpMonitorInfo("after monitor sweep");
3638881a8098e259a1faf392d20c1fefc1ee4a63b20Carl Shapiro#endif
3645a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro}
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
366f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapirostatic char *logWriteInt(char *dst, int value)
367f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro{
368f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    *dst++ = EVENT_TYPE_INT;
369f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    set4LE((u1 *)dst, value);
370f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    return dst + 4;
371f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro}
372f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
373f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapirostatic char *logWriteString(char *dst, const char *value, size_t len)
374f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro{
375f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    *dst++ = EVENT_TYPE_STRING;
376af69cf8d062a42300852ddee6bcb9f189f5a1b83Carl Shapiro    len = len < 32 ? len : 32;
377f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    set4LE((u1 *)dst, len);
378f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    dst += 4;
379f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    memcpy(dst, value, len);
380f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    return dst + len;
381f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro}
382f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
383af69cf8d062a42300852ddee6bcb9f189f5a1b83Carl Shapiro#define EVENT_LOG_TAG_dvm_lock_sample 20003
384f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
385fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapirostatic void logContentionEvent(Thread *self, u4 waitMs, u4 samplePercent,
386fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro                               const char *ownerFileName, u4 ownerLineNumber)
387f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro{
388f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    const StackSaveArea *saveArea;
389f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    const Method *meth;
390f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    u4 relativePc;
391fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    char eventBuffer[174];
392f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    const char *fileName;
393e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro    char procName[33], *selfName;
394f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    char *cp;
395af69cf8d062a42300852ddee6bcb9f189f5a1b83Carl Shapiro    size_t len;
396af69cf8d062a42300852ddee6bcb9f189f5a1b83Carl Shapiro    int fd;
397f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
398f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    saveArea = SAVEAREA_FROM_FP(self->curFrame);
399f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    meth = saveArea->method;
400f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    cp = eventBuffer;
401f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
402f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    /* Emit the event list length, 1 byte. */
403fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    *cp++ = 9;
404f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
405f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    /* Emit the process name, <= 37 bytes. */
406f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    fd = open("/proc/self/cmdline", O_RDONLY);
407af69cf8d062a42300852ddee6bcb9f189f5a1b83Carl Shapiro    memset(procName, 0, sizeof(procName));
408af69cf8d062a42300852ddee6bcb9f189f5a1b83Carl Shapiro    read(fd, procName, sizeof(procName) - 1);
409f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    close(fd);
410af69cf8d062a42300852ddee6bcb9f189f5a1b83Carl Shapiro    len = strlen(procName);
411af69cf8d062a42300852ddee6bcb9f189f5a1b83Carl Shapiro    cp = logWriteString(cp, procName, len);
412f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
413f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    /* Emit the main thread status, 5 bytes. */
414f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    bool isMainThread = (self->systemTid == getpid());
415f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    cp = logWriteInt(cp, isMainThread);
416f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
417f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    /* Emit self thread name string, <= 37 bytes. */
418f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    selfName = dvmGetThreadName(self);
419f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    cp = logWriteString(cp, selfName, strlen(selfName));
420f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    free(selfName);
421f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
422f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    /* Emit the wait time, 5 bytes. */
423f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    cp = logWriteInt(cp, waitMs);
424f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
425f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    /* Emit the source code file name, <= 37 bytes. */
426f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    fileName = dvmGetMethodSourceFile(meth);
427f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    if (fileName == NULL) fileName = "";
428f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    cp = logWriteString(cp, fileName, strlen(fileName));
429f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
430f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    /* Emit the source code line number, 5 bytes. */
431f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    relativePc = saveArea->xtra.currentPc - saveArea->method->insns;
432f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    cp = logWriteInt(cp, dvmLineNumFromPC(meth, relativePc));
433f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
434fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    /* Emit the lock owner source code file name, <= 37 bytes. */
435fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    if (ownerFileName == NULL) {
436fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro      ownerFileName = "";
437fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    } else if (strcmp(fileName, ownerFileName) == 0) {
438fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro      /* Common case, so save on log space. */
439fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro      ownerFileName = "-";
440fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    }
441fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    cp = logWriteString(cp, ownerFileName, strlen(ownerFileName));
442fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro
443fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    /* Emit the source code line number, 5 bytes. */
444fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    cp = logWriteInt(cp, ownerLineNumber);
445fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro
446f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    /* Emit the sample percentage, 5 bytes. */
447f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    cp = logWriteInt(cp, samplePercent);
448f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
449f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    assert((size_t)(cp - eventBuffer) <= sizeof(eventBuffer));
450af69cf8d062a42300852ddee6bcb9f189f5a1b83Carl Shapiro    android_btWriteLog(EVENT_LOG_TAG_dvm_lock_sample,
451f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro                       EVENT_TYPE_LIST,
452f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro                       eventBuffer,
453f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro                       (size_t)(cp - eventBuffer));
454f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro}
455f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Lock a monitor.
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void lockMonitor(Thread* self, Monitor* mon)
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
461f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    ThreadStatus oldStatus;
462f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    u4 waitThreshold, samplePercent;
463f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    u8 waitStart, waitEnd, waitMs;
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon->owner == self) {
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->lockCount++;
467f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro        return;
468f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    }
469045fdc99f7c0dfde95002da66cb85ace19aee069Carl Shapiro    if (dvmTryLockMutex(&mon->lock) != 0) {
470f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro        oldStatus = dvmChangeStatus(self, THREAD_MONITOR);
471f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro        waitThreshold = gDvm.lockProfThreshold;
472f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro        if (waitThreshold) {
473f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro            waitStart = dvmGetRelativeTimeUsec();
474f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro        }
475fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro        const char* currentOwnerFileName = mon->ownerFileName;
476fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro        u4 currentOwnerLineNumber = mon->ownerLineNumber;
477fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro
478f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro        dvmLockMutex(&mon->lock);
479f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro        if (waitThreshold) {
480f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro            waitEnd = dvmGetRelativeTimeUsec();
481f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro        }
482f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro        dvmChangeStatus(self, oldStatus);
483f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro        if (waitThreshold) {
484f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro            waitMs = (waitEnd - waitStart) / 1000;
485f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro            if (waitMs >= waitThreshold) {
486f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro                samplePercent = 100;
487f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro            } else {
488af69cf8d062a42300852ddee6bcb9f189f5a1b83Carl Shapiro                samplePercent = 100 * waitMs / waitThreshold;
489f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro            }
490b8fcf57f13b4d37950cfbd72a6af401941d7bdd8Carl Shapiro            if (samplePercent != 0 && ((u4)rand() % 100 < samplePercent)) {
491fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro                logContentionEvent(self, waitMs, samplePercent,
492fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro                                   currentOwnerFileName, currentOwnerLineNumber);
493f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro            }
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
496f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    mon->owner = self;
497f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    assert(mon->lockCount == 0);
498fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro
499fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    // When debugging, save the current monitor holder for future
500fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    // acquisition failures to use in sampled logging.
501fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    if (gDvm.lockProfThreshold > 0) {
502fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro        const StackSaveArea *saveArea;
503fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro        const Method *meth;
504fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro        mon->ownerLineNumber = 0;
505fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro        if (self->curFrame == NULL) {
506fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro            mon->ownerFileName = "no_frame";
507fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro        } else if ((saveArea = SAVEAREA_FROM_FP(self->curFrame)) == NULL) {
508fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro            mon->ownerFileName = "no_save_area";
509fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro        } else if ((meth = saveArea->method) == NULL) {
510fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro            mon->ownerFileName = "no_method";
511fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro        } else {
512fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro            u4 relativePc = saveArea->xtra.currentPc - saveArea->method->insns;
513fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro            mon->ownerFileName = (char*) dvmGetMethodSourceFile(meth);
514fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro            if (mon->ownerFileName == NULL) {
515fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro                mon->ownerFileName = "no_method_file";
516fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro            } else {
517fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro                mon->ownerLineNumber = dvmLineNumFromPC(meth, relativePc);
518fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro            }
519fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro        }
520fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    }
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Try to lock a monitor.
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" on success.
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
528b31b30131bbf58280a515c40027aa958b81b5cd6Carl Shapiro#ifdef WITH_COPYING_GC
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool tryLockMonitor(Thread* self, Monitor* mon)
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon->owner == self) {
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->lockCount++;
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
535980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro        if (dvmTryLockMutex(&mon->lock) == 0) {
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mon->owner = self;
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(mon->lockCount == 0);
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
544b31b30131bbf58280a515c40027aa958b81b5cd6Carl Shapiro#endif
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unlock a monitor.
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns true if the unlock succeeded.
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the unlock failed, an exception will be pending.
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool unlockMonitor(Thread* self, Monitor* mon)
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
55477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(self != NULL);
5559227708d5de03fd72c8a99e3dd2747934591ba5bCarl Shapiro    assert(mon != NULL);
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon->owner == self) {
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We own the monitor, so nobody else can be in here.
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (mon->lockCount == 0) {
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mon->owner = NULL;
562fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro            mon->ownerFileName = "unlocked";
563fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro            mon->ownerLineNumber = 0;
564980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro            dvmUnlockMutex(&mon->lock);
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mon->lockCount--;
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We don't own this, so we're not allowed to unlock it.
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The JNI spec says that we should throw IllegalMonitorStateException
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * in this case.
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
5748782d7ca2bce5ad097557afc3886c52bf85eb99fCarl Shapiro        dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
5758782d7ca2bce5ad097557afc3886c52bf85eb99fCarl Shapiro                          "unlock of unowned monitor");
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
58277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * Checks the wait set for circular structure.  Returns 0 if the list
583b453919fee9bf10ccd576d389d8b3584061bba8bCarl Shapiro * is not circular.  Otherwise, returns 1.  Used only by asserts.
58477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro */
585b31b30131bbf58280a515c40027aa958b81b5cd6Carl Shapiro#ifndef NDEBUG
58677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapirostatic int waitSetCheck(Monitor *mon)
58777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro{
58877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    Thread *fast, *slow;
58977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    size_t n;
59077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
59177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(mon != NULL);
59277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    fast = slow = mon->waitSet;
59377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    n = 0;
59477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    for (;;) {
59577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        if (fast == NULL) return 0;
59677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        if (fast->waitNext == NULL) return 0;
5975f56e67999c67861872c27097803d2126142fed4Carl Shapiro        if (fast == slow && n > 0) return 1;
59877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        n += 2;
59977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        fast = fast->waitNext->waitNext;
60077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        slow = slow->waitNext;
60177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
60277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro}
603b31b30131bbf58280a515c40027aa958b81b5cd6Carl Shapiro#endif
60477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
60577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro/*
60630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * Links a thread into a monitor's wait set.  The monitor lock must be
60730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * held by the caller of this routine.
60877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro */
60977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapirostatic void waitSetAppend(Monitor *mon, Thread *thread)
61077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro{
61177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    Thread *elt;
61277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
61377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(mon != NULL);
61430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    assert(mon->owner == dvmThreadSelf());
61577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(thread != NULL);
61677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(thread->waitNext == NULL);
61777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(waitSetCheck(mon) == 0);
61877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (mon->waitSet == NULL) {
61977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        mon->waitSet = thread;
62077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        return;
62177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
62277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    elt = mon->waitSet;
62377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    while (elt->waitNext != NULL) {
62477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        elt = elt->waitNext;
62577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
62677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    elt->waitNext = thread;
62777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro}
62877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
62977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro/*
63030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * Unlinks a thread from a monitor's wait set.  The monitor lock must
63130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * be held by the caller of this routine.
63277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro */
63377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapirostatic void waitSetRemove(Monitor *mon, Thread *thread)
63477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro{
63577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    Thread *elt;
63677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
63777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(mon != NULL);
63830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    assert(mon->owner == dvmThreadSelf());
63977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(thread != NULL);
64077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(waitSetCheck(mon) == 0);
64177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (mon->waitSet == NULL) {
64277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        return;
64377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
64477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (mon->waitSet == thread) {
64577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        mon->waitSet = thread->waitNext;
64677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        thread->waitNext = NULL;
64777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        return;
64877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
64977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    elt = mon->waitSet;
65077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    while (elt->waitNext != NULL) {
65177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        if (elt->waitNext == thread) {
65277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro            elt->waitNext = thread->waitNext;
65377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro            thread->waitNext = NULL;
65477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro            return;
65577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        }
65677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        elt = elt->waitNext;
65777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
65877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro}
65977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
660b453919fee9bf10ccd576d389d8b3584061bba8bCarl Shapiro/*
661b453919fee9bf10ccd576d389d8b3584061bba8bCarl Shapiro * Converts the given relative waiting time into an absolute time.
662b453919fee9bf10ccd576d389d8b3584061bba8bCarl Shapiro */
663953a0ed4e507fd6e756aa3e5c671bee80d7e9b3eAndy McFaddenstatic void absoluteTime(s8 msec, s4 nsec, struct timespec *ts)
66477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro{
66577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    s8 endSec;
66677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
66777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro#ifdef HAVE_TIMEDWAIT_MONOTONIC
66877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    clock_gettime(CLOCK_MONOTONIC, ts);
66977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro#else
67077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    {
67177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        struct timeval tv;
67277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        gettimeofday(&tv, NULL);
67377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        ts->tv_sec = tv.tv_sec;
67477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        ts->tv_nsec = tv.tv_usec * 1000;
67577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
67677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro#endif
67777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    endSec = ts->tv_sec + msec / 1000;
67877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (endSec >= 0x7fffffff) {
67977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        LOGV("NOTE: end time exceeds epoch\n");
68077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        endSec = 0x7ffffffe;
68177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
68277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    ts->tv_sec = endSec;
68377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    ts->tv_nsec = (ts->tv_nsec + (msec % 1000) * 1000000) + nsec;
68477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
68577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    /* catch rollover */
68677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (ts->tv_nsec >= 1000000000L) {
68777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        ts->tv_sec++;
68877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        ts->tv_nsec -= 1000000000L;
68977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
69077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro}
69177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
692fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbeeint dvmRelativeCondWait(pthread_cond_t* cond, pthread_mutex_t* mutex,
693fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee                        s8 msec, s4 nsec)
694fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee{
695fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee    int ret;
696fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee    struct timespec ts;
697fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee    absoluteTime(msec, nsec, &ts);
698fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee#if defined(HAVE_TIMEDWAIT_MONOTONIC)
699fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee    ret = pthread_cond_timedwait_monotonic(cond, mutex, &ts);
700fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee#else
701fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee    ret = pthread_cond_timedwait(cond, mutex, &ts);
702fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee#endif
703fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee    assert(ret == 0 || ret == ETIMEDOUT);
704fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee    return ret;
705fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee}
706fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee
70777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro/*
708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Wait on a monitor until timeout, interrupt, or notification.  Used for
709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.wait() and (somewhat indirectly) Thread.sleep() and Thread.join().
710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If another thread calls Thread.interrupt(), we throw InterruptedException
712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and return immediately if one of the following are true:
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - blocked in wait(), wait(long), or wait(long, int) methods of Object
714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - blocked in join(), join(long), or join(long, int) methods of Thread
715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - blocked in sleep(long), or sleep(long, int) methods of Thread
716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Otherwise, we set the "interrupted" flag.
717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Checks to make sure that "nsec" is in the range 0-999999
719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (i.e. fractions of a millisecond) and throws the appropriate
720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exception if it isn't.
721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The spec allows "spurious wakeups", and recommends that all code using
723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.wait() do so in a loop.  This appears to derive from concerns
724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * about pthread_cond_wait() on multiprocessor systems.  Some commentary
725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on the web casts doubt on whether these can/should occur.
726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Since we're allowed to wake up "early", we clamp extremely long durations
728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to return at the end of the 32-bit time epoch.
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void waitMonitor(Thread* self, Monitor* mon, s8 msec, s4 nsec,
731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool interruptShouldThrow)
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct timespec ts;
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool wasInterrupted = false;
735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool timed;
73677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    int ret;
737fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    char *savedFileName;
738fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    u4 savedLineNumber;
739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
74071938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(self != NULL);
74171938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(mon != NULL);
74271938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro
74394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    /* Make sure that we hold the lock. */
74471938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    if (mon->owner != self) {
745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "object not locked by thread before wait()");
747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Enforce the timeout range.
752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (msec < 0 || nsec < 0 || nsec > 999999) {
754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/IllegalArgumentException;",
755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "timeout arguments out of range");
756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Compute absolute wakeup time, if necessary.
761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (msec == 0 && nsec == 0) {
763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        timed = false;
764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
765fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee        absoluteTime(msec, nsec, &ts);
766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        timed = true;
767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Add ourselves to the set of threads waiting on this monitor, and
771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * release our hold.  We need to let it go even if we're a few levels
772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * deep in a recursive lock, and we need to restore that later.
773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
774142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro     * We append to the wait set ahead of clearing the count and owner
775142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro     * fields so the subroutine can check that the calling thread owns
776142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro     * the monitor.  Aside from that, the order of member updates is
777142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro     * not order sensitive as we hold the pthread mutex.
778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
779142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro    waitSetAppend(mon, self);
780142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro    int prevLockCount = mon->lockCount;
781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->lockCount = 0;
782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->owner = NULL;
783fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    savedFileName = mon->ownerFileName;
784fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    mon->ownerFileName = NULL;
785fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    savedLineNumber = mon->ownerLineNumber;
786fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    mon->ownerLineNumber = 0;
787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Update thread status.  If the GC wakes up, it'll ignore us, knowing
790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that we won't touch any references in this state, and we'll check
791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * our suspend mode before we transition out.
792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (timed)
794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmChangeStatus(self, THREAD_TIMED_WAIT);
795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmChangeStatus(self, THREAD_WAIT);
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
798980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro    dvmLockMutex(&self->waitMutex);
79977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
80177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     * Set waitMonitor to the monitor object we will be waiting on.
80277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     * When waitMonitor is non-NULL a notifying or interrupting thread
80377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     * must signal the thread's waitCond to wake it up.
804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
80577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(self->waitMonitor == NULL);
806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->waitMonitor = mon;
807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Handle the case where the thread was interrupted before we called
810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * wait().
811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self->interrupted) {
813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        wasInterrupted = true;
81477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        self->waitMonitor = NULL;
815980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro        dvmUnlockMutex(&self->waitMutex);
816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto done;
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
81977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    /*
82077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     * Release the monitor lock and wait for a notification or
82177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     * a timeout to occur.
82277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     */
823980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro    dvmUnlockMutex(&mon->lock);
82477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
82577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (!timed) {
82677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        ret = pthread_cond_wait(&self->waitCond, &self->waitMutex);
82777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        assert(ret == 0);
82877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    } else {
829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef HAVE_TIMEDWAIT_MONOTONIC
83077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        ret = pthread_cond_timedwait_monotonic(&self->waitCond, &self->waitMutex, &ts);
831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
83277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        ret = pthread_cond_timedwait(&self->waitCond, &self->waitMutex, &ts);
833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
83477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        assert(ret == 0 || ret == ETIMEDOUT);
83577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
83677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (self->interrupted) {
83777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        wasInterrupted = true;
838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
84077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    self->interrupted = false;
84177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    self->waitMonitor = NULL;
84277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
843980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro    dvmUnlockMutex(&self->waitMutex);
84477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
84530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    /* Reacquire the monitor lock. */
84677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    lockMonitor(self, mon);
847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
848142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapirodone:
849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
85007b359273a838a15accafefcbe861be15caaac3aCarl Shapiro     * We remove our thread from wait set after restoring the count
85107b359273a838a15accafefcbe861be15caaac3aCarl Shapiro     * and owner fields so the subroutine can check that the calling
85207b359273a838a15accafefcbe861be15caaac3aCarl Shapiro     * thread owns the monitor. Aside from that, the order of member
85307b359273a838a15accafefcbe861be15caaac3aCarl Shapiro     * updates is not order sensitive as we hold the pthread mutex.
854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->owner = self;
856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->lockCount = prevLockCount;
857fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    mon->ownerFileName = savedFileName;
858fa903b348ea1ba0ba121ccc3b34927f88e4353b1Carl Shapiro    mon->ownerLineNumber = savedLineNumber;
85907b359273a838a15accafefcbe861be15caaac3aCarl Shapiro    waitSetRemove(mon, self);
860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* set self->status back to THREAD_RUNNING, and self-suspend if needed */
862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmChangeStatus(self, THREAD_RUNNING);
863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (wasInterrupted) {
865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We were interrupted while waiting, or somebody interrupted an
86730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * un-interruptible thread earlier and we're bailing out immediately.
868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The doc sayeth: "The interrupted status of the current thread is
870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * cleared when this exception is thrown."
871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self->interrupted = false;
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (interruptShouldThrow)
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/InterruptedException;", NULL);
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Notify one thread waiting on this monitor.
880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void notifyMonitor(Thread* self, Monitor* mon)
882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
88377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    Thread* thread;
88477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
88571938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(self != NULL);
88671938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(mon != NULL);
88771938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro
88894338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    /* Make sure that we hold the lock. */
88971938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    if (mon->owner != self) {
890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "object not locked by thread before notify()");
892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
89430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    /* Signal the first waiting thread in the wait set. */
89530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    while (mon->waitSet != NULL) {
89677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        thread = mon->waitSet;
89777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        mon->waitSet = thread->waitNext;
89877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        thread->waitNext = NULL;
899980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro        dvmLockMutex(&thread->waitMutex);
90077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        /* Check to see if the thread is still waiting. */
90177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        if (thread->waitMonitor != NULL) {
90277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro            pthread_cond_signal(&thread->waitCond);
903980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro            dvmUnlockMutex(&thread->waitMutex);
90430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            return;
90577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        }
906980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro        dvmUnlockMutex(&thread->waitMutex);
907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Notify all threads waiting on this monitor.
912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void notifyAllMonitor(Thread* self, Monitor* mon)
914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
91577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    Thread* thread;
91677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
91771938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(self != NULL);
91871938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(mon != NULL);
91971938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro
92094338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    /* Make sure that we hold the lock. */
92171938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    if (mon->owner != self) {
922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "object not locked by thread before notifyAll()");
924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
92677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    /* Signal all threads in the wait set. */
92777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    while (mon->waitSet != NULL) {
92877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        thread = mon->waitSet;
92977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        mon->waitSet = thread->waitNext;
93077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        thread->waitNext = NULL;
931980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro        dvmLockMutex(&thread->waitMutex);
93277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        /* Check to see if the thread is still waiting. */
93377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        if (thread->waitMonitor != NULL) {
93477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro            pthread_cond_signal(&thread->waitCond);
93577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        }
936980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro        dvmUnlockMutex(&thread->waitMutex);
937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
94166bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro * Changes the shape of a monitor from thin to fat, preserving the
94266bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro * internal lock state.  The calling thread must own the lock.
94366bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro */
94466bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapirostatic void inflateMonitor(Thread *self, Object *obj)
94566bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro{
94666bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    Monitor *mon;
94766bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    u4 thin;
94866bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro
94966bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    assert(self != NULL);
95066bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    assert(obj != NULL);
95166bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    assert(LW_SHAPE(obj->lock) == LW_SHAPE_THIN);
95266bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    assert(LW_LOCK_OWNER(obj->lock) == self->threadId);
95366bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    /* Allocate and acquire a new monitor. */
95466bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    mon = dvmCreateMonitor(obj);
95566bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    lockMonitor(self, mon);
95666bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    /* Propagate the lock state. */
95766bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    thin = obj->lock;
95866bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    mon->lockCount = LW_LOCK_COUNT(thin);
95966bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    thin &= LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT;
96066bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    thin |= (u4)mon | LW_SHAPE_FAT;
96166bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    /* Publish the updated lock word. */
9624ba5672a3d33ff8aaf45e2ae8371e18fe30d469bCarl Shapiro    android_atomic_release_store(thin, (int32_t *)&obj->lock);
96366bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro}
96466bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro
96566bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro/*
966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Implements monitorenter for "synchronized" stuff.
967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This does not fail or throw an exception (unless deadlock prediction
969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is enabled and set to "err" mode).
970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmLockObject(Thread* self, Object *obj)
972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
973147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    volatile u4 *thinp;
974147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    ThreadStatus oldStatus;
975147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    useconds_t sleepDelay;
976147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    const useconds_t maxSleepDelay = 1 << 20;
977147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    u4 thin, newThin, threadId;
978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
979147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    assert(self != NULL);
980147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    assert(obj != NULL);
981147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    threadId = self->threadId;
982147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    thinp = &obj->lock;
983147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiroretry:
984147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    thin = *thinp;
985147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
986147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro        /*
987147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro         * The lock is a thin lock.  The owner field is used to
988147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro         * determine the acquire method, ordered by cost.
989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
990147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro        if (LW_LOCK_OWNER(thin) == threadId) {
991147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            /*
992147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * The calling thread owns the lock.  Increment the
993147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * value of the recursion count field.
994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
995147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            obj->lock += 1 << LW_LOCK_COUNT_SHIFT;
996f3cfbbf80364d4d15b722afb48637dffba73fb3cCarl Shapiro            if (LW_LOCK_COUNT(obj->lock) == LW_LOCK_COUNT_MASK) {
997f3cfbbf80364d4d15b722afb48637dffba73fb3cCarl Shapiro                /*
998f3cfbbf80364d4d15b722afb48637dffba73fb3cCarl Shapiro                 * The reacquisition limit has been reached.  Inflate
999f3cfbbf80364d4d15b722afb48637dffba73fb3cCarl Shapiro                 * the lock so the next acquire will not overflow the
1000f3cfbbf80364d4d15b722afb48637dffba73fb3cCarl Shapiro                 * recursion count field.
1001f3cfbbf80364d4d15b722afb48637dffba73fb3cCarl Shapiro                 */
1002f3cfbbf80364d4d15b722afb48637dffba73fb3cCarl Shapiro                inflateMonitor(self, obj);
1003f3cfbbf80364d4d15b722afb48637dffba73fb3cCarl Shapiro            }
1004147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro        } else if (LW_LOCK_OWNER(thin) == 0) {
1005147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            /*
1006147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * The lock is unowned.  Install the thread id of the
1007147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * calling thread into the owner field.  This is the
1008147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * common case.  In performance critical code the JIT
1009147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * will have tried this before calling out to the VM.
1010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1011147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            newThin = thin | (threadId << LW_LOCK_OWNER_SHIFT);
10123ba10c9932db4c7c9546081ea070c73d5001c168Carl Shapiro            if (android_atomic_acquire_cas(thin, newThin,
10136e10b9aaa72425a4825a25f0043533d0c6fdbba4Andy McFadden                    (int32_t*)thinp) != 0) {
1014147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                /*
1015147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                 * The acquire failed.  Try again.
1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
1017147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                goto retry;
1018147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            }
1019147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro        } else {
1020147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            LOG_THIN("(%d) spin on lock %p: %#x (%#x) %#x",
1021147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                     threadId, &obj->lock, 0, *thinp, thin);
1022147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            /*
1023147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * The lock is owned by another thread.  Notify the VM
1024147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * that we are about to wait.
1025147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             */
1026147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            oldStatus = dvmChangeStatus(self, THREAD_MONITOR);
1027147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            /*
1028147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * Spin until the thin lock is released or inflated.
1029147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             */
1030147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            sleepDelay = 0;
1031147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            for (;;) {
1032147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                thin = *thinp;
1033147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                /*
1034147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                 * Check the shape of the lock word.  Another thread
1035147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                 * may have inflated the lock while we were waiting.
1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
1037147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
1038147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                    if (LW_LOCK_OWNER(thin) == 0) {
1039147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                        /*
1040147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                         * The lock has been released.  Install the
1041147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                         * thread id of the calling thread into the
1042147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                         * owner field.
1043147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                         */
1044147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                        newThin = thin | (threadId << LW_LOCK_OWNER_SHIFT);
10453ba10c9932db4c7c9546081ea070c73d5001c168Carl Shapiro                        if (android_atomic_acquire_cas(thin, newThin,
10466e10b9aaa72425a4825a25f0043533d0c6fdbba4Andy McFadden                                (int32_t *)thinp) == 0) {
1047147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                            /*
1048147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                             * The acquire succeed.  Break out of the
1049147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                             * loop and proceed to inflate the lock.
1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                             */
1051147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                            break;
1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
1053147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                    } else {
1054147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                        /*
1055147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                         * The lock has not been released.  Yield so
1056147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                         * the owning thread can run.
1057147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                         */
1058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        if (sleepDelay == 0) {
1059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            sched_yield();
1060147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                            sleepDelay = 1000;
1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        } else {
1062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            usleep(sleepDelay);
1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            if (sleepDelay < maxSleepDelay / 2) {
1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                sleepDelay *= 2;
1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            }
1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
1068147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                } else {
1069147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                    /*
1070147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                     * The thin lock was inflated by another thread.
1071147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                     * Let the VM know we are no longer waiting and
1072147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                     * try again.
1073147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                     */
1074147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                    LOG_THIN("(%d) lock %p surprise-fattened",
1075147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                             threadId, &obj->lock);
1076147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                    dvmChangeStatus(self, oldStatus);
1077147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                    goto retry;
1078147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                }
1079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1080147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            LOG_THIN("(%d) spin on lock done %p: %#x (%#x) %#x",
1081147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                     threadId, &obj->lock, 0, *thinp, thin);
1082147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            /*
1083147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * We have acquired the thin lock.  Let the VM know that
1084147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * we are no longer waiting.
1085147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             */
1086147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            dvmChangeStatus(self, oldStatus);
1087147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            /*
1088147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * Fatten the lock.
1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
109066bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro            inflateMonitor(self, obj);
1091147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            LOG_THIN("(%d) lock %p fattened", threadId, &obj->lock);
1092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1093147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    } else {
1094147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro        /*
1095147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro         * The lock is a fat lock.
1096147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro         */
1097147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro        assert(LW_MONITOR(obj->lock) != NULL);
1098147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro        lockMonitor(self, LW_MONITOR(obj->lock));
1099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
1101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * See if we were allowed to grab the lock at this time.  We do it
1103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * *after* acquiring the lock, rather than before, so that we can
1104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * freely update the Monitor struct.  This seems counter-intuitive,
1105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * but our goal is deadlock *prediction* not deadlock *prevention*.
1106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (If we actually deadlock, the situation is easy to diagnose from
1107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * a thread dump, so there's no point making a special effort to do
1108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the checks before the lock is held.)
1109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * This needs to happen before we add the object to the thread's
1111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * monitor list, so we can tell the difference between first-lock and
1112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * re-lock.
1113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * It's also important that we do this while in THREAD_RUNNING, so
1115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that we don't interfere with cleanup operations in the GC.
1116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.deadlockPredictMode != kDPOff) {
1118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (self->status != THREAD_RUNNING) {
1119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Bad thread status (%d) in DP\n", self->status);
1120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmDumpThread(self, false);
1121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
1122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!dvmCheckException(self));
1124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        updateDeadlockPrediction(self, obj);
1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmCheckException(self)) {
1126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * If we're throwing an exception here, we need to free the
1128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * lock.  We add the object to the thread's monitor list so the
1129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * "unlock" code can remove it.
1130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAddToMonitorList(self, obj, false);
1132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmUnlockObject(self, obj);
1133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGV("--- unlocked, pending is '%s'\n",
1134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmGetException(self)->clazz->descriptor);
1135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Add the locked object, and the current stack trace, to the list
1140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * held by the Thread object.  If deadlock prediction isn't on,
1141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * don't capture the stack trace.
1142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmAddToMonitorList(self, obj, gDvm.deadlockPredictMode != kDPOff);
1144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#elif defined(WITH_MONITOR_TRACKING)
1145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Add the locked object to the list held by the Thread object.
1147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmAddToMonitorList(self, obj, false);
1149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Implements monitorexit for "synchronized" stuff.
1154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On failure, throws an exception and returns "false".
1156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmUnlockObject(Thread* self, Object *obj)
1158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
115994338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    u4 thin;
1160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1161ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro    assert(self != NULL);
1162ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro    assert(self->status == THREAD_RUNNING);
1163ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro    assert(obj != NULL);
1164ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro    /*
1165ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro     * Cache the lock word as its value can change while we are
1166ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro     * examining its state.
1167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1168147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    thin = obj->lock;
1169ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro    if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
1170ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro        /*
1171ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro         * The lock is thin.  We must ensure that the lock is owned
1172ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro         * by the given thread before unlocking it.
1173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1174ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro        if (LW_LOCK_OWNER(thin) == self->threadId) {
1175ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro            /*
1176ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro             * We are the lock owner.  It is safe to update the lock
1177ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro             * without CAS as lock ownership guards the lock itself.
1178ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro             */
1179ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro            if (LW_LOCK_COUNT(thin) == 0) {
1180ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                /*
1181ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                 * The lock was not recursively acquired, the common
1182ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                 * case.  Unlock by clearing all bits except for the
1183ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                 * hash state.
1184ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                 */
1185147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                obj->lock &= (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT);
1186ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro            } else {
1187ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                /*
1188ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                 * The object was recursively acquired.  Decrement the
1189ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                 * lock recursion count field.
1190ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                 */
1191147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                obj->lock -= 1 << LW_LOCK_COUNT_SHIFT;
1192ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro            }
1193ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro        } else {
1194ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro            /*
1195ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro             * We do not own the lock.  The JVM spec requires that we
1196ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro             * throw an exception in this case.
1197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1199ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                              "unlock of unowned monitor");
1200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
1201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1203ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro        /*
1204ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro         * The lock is fat.  We must check to see if unlockMonitor has
1205ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro         * raised any exceptions before continuing.
1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
12078d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        assert(LW_MONITOR(obj->lock) != NULL);
12088d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        if (!unlockMonitor(self, LW_MONITOR(obj->lock))) {
1209ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro            /*
1210ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro             * An exception has been raised.  Do not fall through.
1211ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro             */
1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_MONITOR_TRACKING
1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Remove the object from the Thread's list.
1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmRemoveFromMonitorList(self, obj);
1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.wait().  Also called for class init.
1228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmObjectWait(Thread* self, Object *obj, s8 msec, s4 nsec,
1230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool interruptShouldThrow)
1231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
123266bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    Monitor* mon;
12338d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    u4 thin = obj->lock;
1234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the lock is still thin, we need to fatten it.
1236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
123794338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
1238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Make sure that 'self' holds the lock.
1239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
124094338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        if (LW_LOCK_OWNER(thin) != self->threadId) {
1241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "object not locked by thread before wait()");
1243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
1244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* This thread holds the lock.  We need to fatten the lock
1247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * so 'self' can block on it.  Don't update the object lock
1248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * field yet, because 'self' needs to acquire the lock before
1249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * any other thread gets a chance.
1250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
125166bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro        inflateMonitor(self, obj);
125266bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro        LOG_THIN("(%d) lock %p fattened by wait() to count %d",
125366bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro                 self->threadId, &obj->lock, mon->lockCount);
1254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
125566bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    mon = LW_MONITOR(obj->lock);
1256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    waitMonitor(self, mon, msec, nsec, interruptShouldThrow);
1257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.notify().
1261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmObjectNotify(Thread* self, Object *obj)
1263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
12648d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    u4 thin = obj->lock;
1265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the lock is still thin, there aren't any waiters;
1267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * waiting on an object forces lock fattening.
1268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
126994338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
1270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Make sure that 'self' holds the lock.
1271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
127294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        if (LW_LOCK_OWNER(thin) != self->threadId) {
1273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "object not locked by thread before notify()");
1275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
1276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* no-op;  there are no waiters to notify.
1279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* It's a fat lock.
1282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
128394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        notifyMonitor(self, LW_MONITOR(thin));
1284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.notifyAll().
1289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmObjectNotifyAll(Thread* self, Object *obj)
1291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
12928d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    u4 thin = obj->lock;
1293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the lock is still thin, there aren't any waiters;
1295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * waiting on an object forces lock fattening.
1296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
129794338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
1298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Make sure that 'self' holds the lock.
1299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
130094338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        if (LW_LOCK_OWNER(thin) != self->threadId) {
1301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "object not locked by thread before notifyAll()");
1303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
1304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* no-op;  there are no waiters to notify.
1307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* It's a fat lock.
1310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
131194338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        notifyAllMonitor(self, LW_MONITOR(thin));
1312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This implements java.lang.Thread.sleep(long msec, int nsec).
1317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The sleep is interruptible by other threads, which means we can't just
1319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * plop into an OS sleep call.  (We probably could if we wanted to send
1320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * signals around and rely on EINTR, but that's inefficient and relies
1321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on native code respecting our signal mask.)
1322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We have to do all of this stuff for Object.wait() as well, so it's
1324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * easiest to just sleep on a private Monitor.
1325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It appears that we want sleep(0,0) to go through the motions of sleeping
1327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for a very short duration, rather than just returning.
1328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmThreadSleep(u8 msec, u4 nsec)
1330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
1332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon = gDvm.threadSleepMon;
1333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* sleep(0,0) wakes up immediately, wait(0,0) means wait forever; adjust */
1335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (msec == 0 && nsec == 0)
1336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        nsec++;
1337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    lockMonitor(self, mon);
1339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    waitMonitor(self, mon, msec, nsec, true);
1340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unlockMonitor(self, mon);
1341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Implement java.lang.Thread.interrupt().
1345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
134677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapirovoid dvmThreadInterrupt(Thread* thread)
1347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
134877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(thread != NULL);
134977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
1350980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro    dvmLockMutex(&thread->waitMutex);
135177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
135277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    /*
135377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     * If the interrupted flag is already set no additional action is
135477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     * required.
135577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     */
135677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (thread->interrupted == true) {
1357980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro        dvmUnlockMutex(&thread->waitMutex);
135877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        return;
135977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
136077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
1361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Raise the "interrupted" flag.  This will cause it to bail early out
1363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * of the next wait() attempt, if it's not currently waiting on
1364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * something.
1365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    thread->interrupted = true;
1367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Is the thread waiting?
1370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Note that fat vs. thin doesn't matter here;  waitMonitor
1372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is only set when a thread actually waits on a monitor,
1373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * which implies that the monitor has already been fattened.
1374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
137577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (thread->waitMonitor != NULL) {
137677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        pthread_cond_signal(&thread->waitCond);
1377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1379980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro    dvmUnlockMutex(&thread->waitMutex);
1380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
138230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro#ifndef WITH_COPYING_GC
138394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapirou4 dvmIdentityHashCode(Object *obj)
138494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro{
138594338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    return (u4)obj;
138694338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro}
138730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro#else
138830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro/*
138930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * Returns the identity hash code of the given object.
139030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */
139130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapirou4 dvmIdentityHashCode(Object *obj)
139230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro{
139330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    Thread *self, *thread;
139430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    volatile u4 *lw;
1395bfe4dcc3bd3d4d85a07fd3d63da537b51342b6ebCarl Shapiro    size_t size;
139630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    u4 lock, owner, hashState;
139730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro
139830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    if (obj == NULL) {
139930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
140030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * Null is defined to have an identity hash code of 0.
140130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
140230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        return 0;
140330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    }
140430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    lw = &obj->lock;
140530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiroretry:
140630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    hashState = LW_HASH_STATE(*lw);
140730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    if (hashState == LW_HASH_STATE_HASHED) {
140830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
140930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * The object has been hashed but has not had its hash code
141030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * relocated by the garbage collector.  Use the raw object
141130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * address.
141230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
141330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        return (u4)obj >> 3;
141430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    } else if (hashState == LW_HASH_STATE_HASHED_AND_MOVED) {
141530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
141630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * The object has been hashed and its hash code has been
141730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * relocated by the collector.  Use the value of the naturally
141830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * aligned word following the instance data.
141930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
1420c48b6d0dc6b8c01c65977a9d18203c8510687267Carl Shapiro        assert(obj->clazz != gDvm.classJavaLangClass);
142130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISARRAY)) {
1422bfe4dcc3bd3d4d85a07fd3d63da537b51342b6ebCarl Shapiro            size = dvmArrayObjectSize((ArrayObject *)obj);
1423c48b6d0dc6b8c01c65977a9d18203c8510687267Carl Shapiro            size = (size + 2) & ~2;
142430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        } else {
1425bfe4dcc3bd3d4d85a07fd3d63da537b51342b6ebCarl Shapiro            size = obj->clazz->objectSize;
142630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        }
1427bfe4dcc3bd3d4d85a07fd3d63da537b51342b6ebCarl Shapiro        return *(u4 *)(((char *)obj) + size);
142830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    } else if (hashState == LW_HASH_STATE_UNHASHED) {
142930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
143030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * The object has never been hashed.  Change the hash state to
143130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * hashed and use the raw object address.
143230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
143330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        self = dvmThreadSelf();
143430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        if (self->threadId == lockOwner(obj)) {
143530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            /*
143630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * We already own the lock so we can update the hash state
143730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * directly.
143830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             */
143930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            *lw |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
144030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            return (u4)obj >> 3;
144130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        }
144230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
144330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * We do not own the lock.  Try acquiring the lock.  Should
144430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * this fail, we must suspend the owning thread.
144530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
144630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        if (LW_SHAPE(*lw) == LW_SHAPE_THIN) {
144730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            /*
144830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * If the lock is thin assume it is unowned.  We simulate
144930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * an acquire, update, and release with a single CAS.
145030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             */
145130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            lock = DVM_LOCK_INITIAL_THIN_VALUE;
145230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            lock |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
14533ba10c9932db4c7c9546081ea070c73d5001c168Carl Shapiro            if (android_atomic_acquire_cas(
145430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                                (int32_t)DVM_LOCK_INITIAL_THIN_VALUE,
14556e10b9aaa72425a4825a25f0043533d0c6fdbba4Andy McFadden                                (int32_t)lock,
14566e10b9aaa72425a4825a25f0043533d0c6fdbba4Andy McFadden                                (int32_t *)lw) == 0) {
145730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                /*
145830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                 * A new lockword has been installed with a hash state
145930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                 * of hashed.  Use the raw object address.
146030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                 */
146130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                return (u4)obj >> 3;
146230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            }
146330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        } else {
146430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            if (tryLockMonitor(self, LW_MONITOR(*lw))) {
146530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                /*
146630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                 * The monitor lock has been acquired.  Change the
146730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                 * hash state to hashed and use the raw object
146830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                 * address.
146930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                 */
147030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                *lw |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
147130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                unlockMonitor(self, LW_MONITOR(*lw));
147230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                return (u4)obj >> 3;
147330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            }
147430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        }
147530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
147630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * At this point we have failed to acquire the lock.  We must
147730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * identify the owning thread and suspend it.
147830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
147930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        dvmLockThreadList(self);
148030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
148130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * Cache the lock word as its value can change between
148230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * determining its shape and retrieving its owner.
148330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
148430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        lock = *lw;
148530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        if (LW_SHAPE(lock) == LW_SHAPE_THIN) {
148630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            /*
148730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * Find the thread with the corresponding thread id.
148830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             */
148930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            owner = LW_LOCK_OWNER(lock);
149030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            assert(owner != self->threadId);
149130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            /*
149230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * If the lock has no owner do not bother scanning the
149330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * thread list and fall through to the failure handler.
149430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             */
149530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            thread = owner ? gDvm.threadList : NULL;
149630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            while (thread != NULL) {
149730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                if (thread->threadId == owner) {
149830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                    break;
149930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                }
150030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                thread = thread->next;
150130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            }
150230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        } else {
150330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            thread = LW_MONITOR(lock)->owner;
150430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        }
150530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
150630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * If thread is NULL the object has been released since the
150730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * thread list lock was acquired.  Try again.
150830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
150930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        if (thread == NULL) {
151030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            dvmUnlockThreadList();
151130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            goto retry;
151230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        }
151330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
151430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * Wait for the owning thread to suspend.
151530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
151630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        dvmSuspendThread(thread);
151730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        if (dvmHoldsLock(thread, obj)) {
151830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            /*
151930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * The owning thread has been suspended.  We can safely
152030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * change the hash state to hashed.
152130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             */
152230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            *lw |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
152330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            dvmResumeThread(thread);
152430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            dvmUnlockThreadList();
152530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            return (u4)obj >> 3;
152630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        }
152730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
152830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * The wrong thread has been suspended.  Try again.
152930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
153030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        dvmResumeThread(thread);
153130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        dvmUnlockThreadList();
153230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        goto retry;
153330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    }
153430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    LOGE("object %p has an unknown hash state %#x", obj, hashState);
153530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    dvmDumpThread(dvmThreadSelf(), false);
153630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    dvmAbort();
153730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    return 0;  /* Quiet the compiler. */
153830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro}
153930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro#endif  /* WITH_COPYING_GC */
1540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
1542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
1544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Deadlock prediction
1545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
1546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe idea is to predict the possibility of deadlock by recording the order
1549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectin which monitors are acquired.  If we see an attempt to acquire a lock
1550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectout of order, we can identify the locks and offending code.
1551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectTo make this work, we need to keep track of the locks held by each thread,
1553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectand create history trees for each lock.  When a thread tries to acquire
1554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecta new lock, we walk through the "history children" of the lock, looking
1555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfor a match with locks the thread already holds.  If we find a match,
1556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectit means the thread has made a request that could result in a deadlock.
1557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectTo support recursive locks, we always allow re-locking a currently-held
1559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectlock, and maintain a recursion depth count.
1560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectAn ASCII-art example, where letters represent Objects:
1562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        A
1564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project       /|\
1565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project      / | \
1566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     B  |  D
1567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project      \ |
1568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project       \|
1569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        C
1570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe above is the tree we'd have after handling Object synchronization
1572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsequences "ABC", "AC", "AD".  A has three children, {B, C, D}.  C is also
1573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecta child of B.  (The lines represent pointers between parent and child.
1574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectEvery node can have multiple parents and multiple children.)
1575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectIf we hold AC, and want to lock B, we recursively search through B's
1577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchildren to see if A or C appears.  It does, so we reject the attempt.
1578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project(A straightforward way to implement it: add a link from C to B, then
1579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectdetermine whether the graph starting at B contains a cycle.)
1580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectIf we hold AC and want to lock D, we would succeed, creating a new link
1582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfrom C to D.
1583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe lock history and a stack trace is attached to the Object's Monitor
1585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstruct, which means we need to fatten every Object we lock (thin locking
1586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectis effectively disabled).  If we don't need the stack trace we can
1587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectavoid fattening the leaf nodes, only fattening objects that need to hold
1588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecthistory trees.
1589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectUpdates to Monitor structs are only allowed for the thread that holds
1591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe Monitor, so we actually do most of our deadlock prediction work after
1592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe lock has been acquired.
1593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectWhen an object with a monitor is GCed, we need to remove it from the
1595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecthistory trees.  There are two basic approaches:
1596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (1) For through the entire set of known monitors, search all child
1597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     lists for the object in question.  This is rather slow, resulting
1598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     in GC passes that take upwards of 10 seconds to complete.
1599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (2) Maintain "parent" pointers in each node.  Remove the entries as
1600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     required.  This requires additional storage and maintenance for
1601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     every operation, but is significantly faster at GC time.
1602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectFor each GCed object, we merge all of the object's children into each of
1603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe object's parents.
1604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/
1605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(WITH_MONITOR_TRACKING)
1607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# error "WITH_DEADLOCK_PREDICTION requires WITH_MONITOR_TRACKING"
1608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clear out the contents of an ExpandingObjectList, freeing any
1612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * dynamic allocations.
1613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void expandObjClear(ExpandingObjectList* pList)
1615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pList->list != NULL) {
1617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(pList->list);
1618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pList->list = NULL;
1619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList->alloc = pList->count = 0;
1621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the number of objects currently stored in the list.
1625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline int expandBufGetCount(const ExpandingObjectList* pList)
1627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return pList->count;
1629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the Nth entry from the list.
1633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline Object* expandBufGetEntry(const ExpandingObjectList* pList,
1635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i)
1636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return pList->list[i];
1638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add a new entry to the list.
1642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We don't check for or try to enforce uniqueness.  It's expected that
1644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the higher-level code does this for us.
1645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void expandObjAddEntry(ExpandingObjectList* pList, Object* obj)
1647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pList->count == pList->alloc) {
1649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* time to expand */
1650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object** newList;
1651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pList->alloc == 0)
1653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pList->alloc = 4;
1654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
1655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pList->alloc *= 2;
1656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("expanding %p to %d\n", pList, pList->alloc);
1657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newList = realloc(pList->list, pList->alloc * sizeof(Object*));
1658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (newList == NULL) {
1659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Failed expanding DP object list (alloc=%d)\n", pList->alloc);
1660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
1661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pList->list = newList;
1663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList->list[pList->count++] = obj;
1666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if the element was successfully removed.
1670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool expandObjRemoveEntry(ExpandingObjectList* pList, Object* obj)
1672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = pList->count-1; i >= 0; i--) {
1676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pList->list[i] == obj)
1677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (i < 0)
1680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
1681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (i != pList->count-1) {
1683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The order of elements is not important, so we just copy the
1685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * last entry into the new slot.
1686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //memmove(&pList->list[i], &pList->list[i+1],
1688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    (pList->count-1 - i) * sizeof(pList->list[0]));
1689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pList->list[i] = pList->list[pList->count-1];
1690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList->count--;
1693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList->list[pList->count] = (Object*) 0xdecadead;
1694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
1695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if "obj" appears in the list.
1699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool expandObjHas(const ExpandingObjectList* pList, Object* obj)
1701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < pList->count; i++) {
1705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pList->list[i] == obj)
1706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
1707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return false;
1709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the list contents to stdout.  For debugging.
1713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void expandObjDump(const ExpandingObjectList* pList)
1715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < pList->count; i++)
1718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(" %p", pList->list[i]);
1719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Check for duplicate entries.  Returns the index of the first instance
1723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of the duplicated value, or -1 if no duplicates were found.
1724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int expandObjCheckForDuplicates(const ExpandingObjectList* pList)
1726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i, j;
1728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < pList->count-1; i++) {
1729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (j = i + 1; j < pList->count; j++) {
1730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (pList->list[i] == pList->list[j]) {
1731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return i;
1732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return -1;
1737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine whether "child" appears in the list of objects associated
1742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * with the Monitor in "parent".  If "parent" is a thin lock, we return
1743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * false immediately.
1744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool objectInChildList(const Object* parent, Object* child)
1746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
17478d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    u4 lock = parent->lock;
1748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!IS_LOCK_FAT(&lock)) {
1749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //LOGI("on thin\n");
1750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
1751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17538d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    return expandObjHas(&LW_MONITOR(lock)->historyChildren, child);
1754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the child list.
1758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void dumpKids(Object* parent)
1760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
17618d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    Monitor* mon = LW_MONITOR(parent->lock);
1762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("Children of %p:", parent);
1764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    expandObjDump(&mon->historyChildren);
1765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("\n");
1766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add "child" to the list of children in "parent", and add "parent" to
1770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the list of parents in "child".
1771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void linkParentToChild(Object* parent, Object* child)
1773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
17748d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    //assert(LW_MONITOR(parent->lock)->owner == dvmThreadSelf());   // !owned for merge
1775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&parent->lock));
1776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&child->lock));
1777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(parent != child);
1778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
1779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17808d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(parent->lock);
1781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!expandObjHas(&mon->historyChildren, child));
1782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    expandObjAddEntry(&mon->historyChildren, child);
1783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17848d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(child->lock);
1785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!expandObjHas(&mon->historyParents, parent));
1786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    expandObjAddEntry(&mon->historyParents, parent);
1787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Remove "child" from the list of children in "parent".
1792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void unlinkParentFromChild(Object* parent, Object* child)
1794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
17958d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    //assert(LW_MONITOR(parent->lock)->owner == dvmThreadSelf());   // !owned for GC
1796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&parent->lock));
1797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&child->lock));
1798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(parent != child);
1799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
1800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
18018d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(parent->lock);
1802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!expandObjRemoveEntry(&mon->historyChildren, child)) {
1803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("WARNING: child %p not found in parent %p\n", child, parent);
1804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!expandObjHas(&mon->historyChildren, child));
1806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(expandObjCheckForDuplicates(&mon->historyChildren) < 0);
1807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
18088d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(child->lock);
1809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!expandObjRemoveEntry(&mon->historyParents, parent)) {
1810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("WARNING: parent %p not found in child %p\n", parent, child);
1811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!expandObjHas(&mon->historyParents, parent));
1813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(expandObjCheckForDuplicates(&mon->historyParents) < 0);
1814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Log the monitors held by the current thread.  This is done as part of
1819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * flagging an error.
1820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void logHeldMonitors(Thread* self)
1822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* name = NULL;
1824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    name = dvmGetThreadName(self);
1826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGW("Monitors currently held by thread (threadid=%d '%s')\n",
1827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self->threadId, name);
1828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGW("(most-recently-acquired on top):\n");
1829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(name);
1830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LockedObjectData* lod = self->pLockedObjects;
1832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (lod != NULL) {
1833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("--- object %p[%d] (%s)\n",
1834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lod->obj, lod->recursionCount, lod->obj->clazz->descriptor);
1835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLogRawStackTrace(lod->rawStackTrace, lod->stackDepth);
1836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        lod = lod->next;
1838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Recursively traverse the object hierarchy starting at "obj".  We mark
1843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ourselves on entry and clear the mark on exit.  If we ever encounter
1844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a marked object, we have a cycle.
1845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if all is well, "false" if we found a cycle.
1847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool traverseTree(Thread* self, const Object* obj)
1849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&obj->lock));
18518d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    Monitor* mon = LW_MONITOR(obj->lock);
1852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Have we been here before?
1855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon->historyMark) {
1857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int* rawStackTrace;
1858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int stackDepth;
1859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("%s\n", kStartBanner);
1861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Illegal lock attempt:\n");
1862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("--- object %p (%s)\n", obj, obj->clazz->descriptor);
1863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        rawStackTrace = dvmFillInStackTraceRaw(self, &stackDepth);
1865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLogRawStackTrace(rawStackTrace, stackDepth);
1866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(rawStackTrace);
1867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW(" ");
1869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        logHeldMonitors(self);
1870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW(" ");
1872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Earlier, the following lock order (from last to first) was\n");
1873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("established -- stack trace is from first successful lock):\n");
1874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
1875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->historyMark = true;
1877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Examine the children.  We do NOT hold these locks, so they might
1880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * very well transition from thin to fat or change ownership while
1881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we work.
1882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * NOTE: we rely on the fact that they cannot revert from fat to thin
1884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * while we work.  This is currently a safe assumption.
1885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We can safely ignore thin-locked children, because by definition
1887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * they have no history and are leaf nodes.  In the current
1888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * implementation we always fatten the locks to provide a place to
1889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * hang the stack trace.
1890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandingObjectList* pList = &mon->historyChildren;
1892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
1894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Object* child = expandBufGetEntry(pList, i);
18958d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        u4 lock = child->lock;
1896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!IS_LOCK_FAT(&lock))
1897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
1898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!traverseTree(self, child)) {
1899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("--- object %p (%s)\n", obj, obj->clazz->descriptor);
1900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLogRawStackTrace(mon->historyRawStackTrace,
1901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                mon->historyStackDepth);
1902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mon->historyMark = false;
1903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
1904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->historyMark = false;
1908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
1910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Update the deadlock prediction tree, based on the current thread
1914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * acquiring "acqObj".  This must be called before the object is added to
1915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the thread's list of held monitors.
1916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the thread already holds the lock (recursion), or this is a known
1918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * lock configuration, we return without doing anything.  Otherwise, we add
1919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a link from the most-recently-acquired lock in this thread to "acqObj"
1920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * after ensuring that the parent lock is "fat".
1921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This MUST NOT be called while a GC is in progress in another thread,
1923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because we assume exclusive access to history trees in owned monitors.
1924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void updateDeadlockPrediction(Thread* self, Object* acqObj)
1926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LockedObjectData* lod;
1928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LockedObjectData* mrl;
1929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Quick check for recursive access.
1932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    lod = dvmFindInMonitorList(self, acqObj);
1934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (lod != NULL) {
1935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("+++ DP: recursive %p\n", acqObj);
1936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Make the newly-acquired object's monitor "fat".  In some ways this
1941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * isn't strictly necessary, but we need the GC to tell us when
1942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "interesting" objects go away, and right now the only way to make
1943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * an object look interesting is to give it a monitor.
1944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * This also gives us a place to hang a stack trace.
1946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Our thread holds the lock, so we're allowed to rewrite the lock
1948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * without worrying that something will change out from under us.
1949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!IS_LOCK_FAT(&acqObj->lock)) {
1951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("fattening lockee %p (recur=%d)\n",
195294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro            acqObj, LW_LOCK_COUNT(acqObj->lock.thin));
195366bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro        inflateMonitor(self, acqObj);
1954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* if we don't have a stack trace for this monitor, establish one */
19578d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    if (LW_MONITOR(acqObj->lock)->historyRawStackTrace == NULL) {
19588d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        Monitor* mon = LW_MONITOR(acqObj->lock);
1959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->historyRawStackTrace = dvmFillInStackTraceRaw(self,
1960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            &mon->historyStackDepth);
1961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We need to examine and perhaps modify the most-recently-locked
1965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * monitor.  We own that, so there's no risk of another thread
1966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * stepping on us.
1967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Retrieve the most-recently-locked entry from our thread.
1969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mrl = self->pLockedObjects;
1971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mrl == NULL)
1972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;         /* no other locks held */
1973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Do a quick check to see if "acqObj" is a direct descendant.  We can do
1976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * this without holding the global lock because of our assertion that
1977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * a GC is not running in parallel -- nobody except the GC can
1978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * modify a history list in a Monitor they don't own, and we own "mrl".
1979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (There might be concurrent *reads*, but no concurrent *writes.)
1980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we find it, this is a known good configuration, and we're done.
1982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (objectInChildList(mrl->obj, acqObj))
1984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "mrl" is going to need to have a history tree.  If it's currently
1988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * a thin lock, we make it fat now.  The thin lock might have a
1989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * nonzero recursive lock count, which we need to carry over.
1990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Our thread holds the lock, so we're allowed to rewrite the lock
1992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * without worrying that something will change out from under us.
1993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!IS_LOCK_FAT(&mrl->obj->lock)) {
1995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("fattening parent %p f/b/o child %p (recur=%d)\n",
19968d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro            mrl->obj, acqObj, LW_LOCK_COUNT(mrl->obj->lock));
199766bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro        inflateMonitor(self, mrl->obj);
1998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We haven't seen this configuration before.  We need to scan down
2002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * acqObj's tree to see if any of the monitors in self->pLockedObjects
2003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * appear.  We grab a global lock before traversing or updating the
2004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * history list.
2005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we find a match for any of our held locks, we know that the lock
2007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * has previously been acquired *after* acqObj, and we throw an error.
2008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The easiest way to do this is to create a link from "mrl" to "acqObj"
2010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and do a recursive traversal, marking nodes as we cross them.  If
2011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we cross one a second time, we have a cycle and can throw an error.
2012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (We do the flag-clearing traversal before adding the new link, so
2013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that we're guaranteed to terminate.)
2014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If "acqObj" is a thin lock, it has no history, and we can create a
2016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * link to it without additional checks.  [ We now guarantee that it's
2017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * always fat. ]
2018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool failed = false;
2020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLockMutex(&gDvm.deadlockHistoryLock);
2021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    linkParentToChild(mrl->obj, acqObj);
2022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!traverseTree(self, acqObj)) {
2023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("%s\n", kEndBanner);
2024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        failed = true;
2025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* remove the entry so we're still okay when in "warning" mode */
2027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unlinkParentFromChild(mrl->obj, acqObj);
2028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockMutex(&gDvm.deadlockHistoryLock);
2030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (failed) {
2032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (gDvm.deadlockPredictMode) {
2033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kDPErr:
2034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ldalvik/system/PotentialDeadlockError;", NULL);
2035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
2036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kDPAbort:
2037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Aborting due to potential deadlock\n");
2038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
2039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
2040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:
2041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* warn only */
2042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
2043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're removing "child" from existence.  We want to pull all of
2049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * child's children into "parent", filtering out duplicates.  This is
2050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * called during the GC.
2051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This does not modify "child", which might have multiple parents.
2053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void mergeChildren(Object* parent, const Object* child)
2055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
2057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
2058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&child->lock));
20608d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(child->lock);
2061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandingObjectList* pList = &mon->historyChildren;
2062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
2064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* grandChild = expandBufGetEntry(pList, i);
2065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!objectInChildList(parent, grandChild)) {
2067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("+++  migrating %p link to %p\n", grandChild, parent);
2068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            linkParentToChild(parent, grandChild);
2069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
2070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("+++  parent %p already links to %p\n", parent, grandChild);
2071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * An object with a fat lock is being collected during a GC pass.  We
2077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * want to remove it from any lock history trees that it is a part of.
2078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This may require updating the history trees in several monitors.  The
2080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * monitor semantics guarantee that no other thread will be accessing
2081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the history trees at the same time.
2082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void removeCollectedObject(Object* obj)
2084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
2086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("+++ collecting %p\n", obj);
2088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * For every parent of this object:
2091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  - merge all of our children into the parent's child list (creates
2092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *    a two-way link between parent and child)
2093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  - remove ourselves from the parent's child list
2094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandingObjectList* pList;
2096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
2097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&obj->lock));
20998d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(obj->lock);
2100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList = &mon->historyParents;
2101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
2102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* parent = expandBufGetEntry(pList, i);
21038d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        Monitor* parentMon = LW_MONITOR(parent->lock);
2104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!expandObjRemoveEntry(&parentMon->historyChildren, obj)) {
2106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("WARNING: child %p not found in parent %p\n", obj, parent);
2107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!expandObjHas(&parentMon->historyChildren, obj));
2109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mergeChildren(parent, obj);
2111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * For every child of this object:
2115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  - remove ourselves from the child's parent list
2116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList = &mon->historyChildren;
2118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
2119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* child = expandBufGetEntry(pList, i);
21208d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        Monitor* childMon = LW_MONITOR(child->lock);
2121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!expandObjRemoveEntry(&childMon->historyParents, obj)) {
2123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("WARNING: parent %p not found in child %p\n", obj, child);
2124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!expandObjHas(&childMon->historyParents, obj));
2126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif /*WITH_DEADLOCK_PREDICTION*/
2130